From 43a3991ddf449ac0d7610687037b7aed07cb6fe3 Mon Sep 17 00:00:00 2001 From: byuu Date: Mon, 29 Mar 2010 17:41:11 +0000 Subject: [PATCH] Update to bsnes v063r01 release. I've had enough of idiots incapable of finding fullscreen settings. The menubar is enabled in fullscreen mode by default. A new option in settings->configuration->video will let you hide it as with v063 official. I don't want to hear about how I shouldn't allow any settings to be configured differently in fullscreen mode, or how it should be in a GUI panel, or whatever. I will ignore you if you bring it up. I've also added the strpos / qstrpos function->class code, as mentioned in the programming section. --- bsnes.exe | Bin 0 -> 674816 bytes pixelshaders/Curvature/fragment | 17 - pixelshaders/HDRTV/fragment | 14 - pixelshaders/HDRTV/vertex | 9 - pixelshaders/HLSL/sepia.fx | 25 - pixelshaders/HQ2x/fragment | 49 - pixelshaders/HQ2x/vertex | 26 - pixelshaders/Pixellate/fragment | 36 - pixelshaders/Pixellate/vertex | 8 - pixelshaders/Scale2x/fragment | 28 - pixelshaders/Scale2x/vertex | 28 - snesfilter/2xsai/2xsai.cpp | 132 - snesfilter/2xsai/2xsai.hpp | 35 - snesfilter/2xsai/implementation.cpp | 1171 ----- snesfilter/Makefile | 89 - snesfilter/cc.bat | 2 - snesfilter/clean.bat | 1 - snesfilter/direct/direct.cpp | 32 - snesfilter/direct/direct.hpp | 5 - snesfilter/hq2x/hq2x.cpp | 203 - snesfilter/hq2x/hq2x.hpp | 30 - snesfilter/lq2x/lq2x.cpp | 61 - snesfilter/lq2x/lq2x.hpp | 5 - snesfilter/nall/Makefile | 107 - snesfilter/nall/algorithm.hpp | 23 - snesfilter/nall/any.hpp | 74 - snesfilter/nall/array.hpp | 120 - snesfilter/nall/base64.hpp | 90 - snesfilter/nall/bit.hpp | 51 - snesfilter/nall/concept.hpp | 15 - snesfilter/nall/config.hpp | 124 - snesfilter/nall/crc32.hpp | 66 - snesfilter/nall/detect.hpp | 30 - snesfilter/nall/dictionary.hpp | 76 - snesfilter/nall/dl.hpp | 119 - snesfilter/nall/endian.hpp | 38 - snesfilter/nall/file.hpp | 259 -- snesfilter/nall/filemap.hpp | 190 - snesfilter/nall/foreach.hpp | 31 - snesfilter/nall/function.hpp | 102 - snesfilter/nall/input.hpp | 386 -- snesfilter/nall/lzss.hpp | 81 - snesfilter/nall/moduloarray.hpp | 40 - snesfilter/nall/platform.hpp | 80 - snesfilter/nall/priorityqueue.hpp | 109 - snesfilter/nall/property.hpp | 91 - snesfilter/nall/qt/Makefile | 55 - snesfilter/nall/qt/check-action.moc.hpp | 41 - snesfilter/nall/qt/concept.hpp | 10 - snesfilter/nall/qt/file-dialog.moc.hpp | 392 -- snesfilter/nall/qt/hex-editor.moc.hpp | 173 - snesfilter/nall/qt/radio-action.moc.hpp | 41 - snesfilter/nall/qt/window.moc.hpp | 105 - snesfilter/nall/serial.hpp | 80 - snesfilter/nall/serializer.hpp | 145 - snesfilter/nall/sha256.hpp | 143 - snesfilter/nall/sort.hpp | 62 - snesfilter/nall/static.hpp | 20 - snesfilter/nall/stdint.hpp | 44 - snesfilter/nall/string.hpp | 26 - snesfilter/nall/string/base.hpp | 137 - snesfilter/nall/string/cast.hpp | 32 - snesfilter/nall/string/compare.hpp | 104 - snesfilter/nall/string/convert.hpp | 153 - snesfilter/nall/string/core.hpp | 133 - snesfilter/nall/string/filename.hpp | 61 - snesfilter/nall/string/match.hpp | 76 - snesfilter/nall/string/math.hpp | 164 - snesfilter/nall/string/replace.hpp | 103 - snesfilter/nall/string/split.hpp | 56 - snesfilter/nall/string/strl.hpp | 52 - snesfilter/nall/string/trim.hpp | 54 - snesfilter/nall/string/utility.hpp | 169 - snesfilter/nall/string/variadic.hpp | 27 - snesfilter/nall/string/xml.hpp | 257 -- snesfilter/nall/ups.hpp | 190 - snesfilter/nall/utf8.hpp | 72 - snesfilter/nall/utility.hpp | 30 - snesfilter/nall/varint.hpp | 92 - snesfilter/nall/vector.hpp | 240 - snesfilter/ntsc/ntsc.cpp | 396 -- snesfilter/ntsc/ntsc.moc.hpp | 91 - snesfilter/ntsc/snes_ntsc/snes_ntsc.c | 251 -- snesfilter/ntsc/snes_ntsc/snes_ntsc.h | 228 - snesfilter/ntsc/snes_ntsc/snes_ntsc_config.h | 26 - snesfilter/ntsc/snes_ntsc/snes_ntsc_impl.h | 439 -- snesfilter/pixellate2x/pixellate2x.cpp | 39 - snesfilter/pixellate2x/pixellate2x.hpp | 5 - snesfilter/scale2x/scale2x.cpp | 61 - snesfilter/scale2x/scale2x.hpp | 5 - snesfilter/snesfilter.cpp | 84 - snesfilter/snesfilter.hpp | 16 - snesfilter/sync.sh | 2 - snesreader/7z_C/7zAlloc.c | 77 - snesreader/7z_C/7zAlloc.h | 23 - snesreader/7z_C/7zBuf.c | 36 - snesreader/7z_C/7zBuf.h | 31 - snesreader/7z_C/7zC.txt | 194 - snesreader/7z_C/7zCrc.c | 35 - snesreader/7z_C/7zCrc.h | 32 - snesreader/7z_C/7zDecode.c | 257 -- snesreader/7z_C/7zDecode.h | 13 - snesreader/7z_C/7zExtract.c | 93 - snesreader/7z_C/7zExtract.h | 49 - snesreader/7z_C/7zHeader.c | 6 - snesreader/7z_C/7zHeader.h | 57 - snesreader/7z_C/7zIn.c | 1204 ------ snesreader/7z_C/7zIn.h | 49 - snesreader/7z_C/7zItem.c | 129 - snesreader/7z_C/7zItem.h | 83 - snesreader/7z_C/7zStream.c | 184 - snesreader/7z_C/Bcj2.c | 132 - snesreader/7z_C/Bcj2.h | 30 - snesreader/7z_C/Bra.h | 60 - snesreader/7z_C/Bra86.c | 85 - snesreader/7z_C/CpuArch.h | 69 - snesreader/7z_C/LzmaDec.c | 1010 ----- snesreader/7z_C/LzmaDec.h | 223 - snesreader/7z_C/Types.h | 206 - snesreader/7z_C/lzma.txt | 594 --- snesreader/7z_C/readme.txt | 19 - snesreader/Makefile | 187 - snesreader/cc.bat | 2 - snesreader/clean.bat | 1 - snesreader/fex/Binary_Extractor.cpp | 77 - snesreader/fex/Binary_Extractor.h | 26 - snesreader/fex/Data_Reader.cpp | 551 --- snesreader/fex/Data_Reader.h | 264 -- snesreader/fex/File_Extractor.cpp | 341 -- snesreader/fex/File_Extractor.h | 191 - snesreader/fex/Gzip_Extractor.cpp | 98 - snesreader/fex/Gzip_Extractor.h | 34 - snesreader/fex/Gzip_Reader.cpp | 85 - snesreader/fex/Gzip_Reader.h | 46 - snesreader/fex/Rar_Extractor.cpp | 197 - snesreader/fex/Rar_Extractor.h | 43 - snesreader/fex/Zip7_Extractor.cpp | 252 -- snesreader/fex/Zip7_Extractor.h | 34 - snesreader/fex/Zip_Extractor.cpp | 390 -- snesreader/fex/Zip_Extractor.h | 45 - snesreader/fex/Zlib_Inflater.cpp | 257 -- snesreader/fex/Zlib_Inflater.h | 70 - snesreader/fex/blargg_common.cpp | 51 - snesreader/fex/blargg_common.h | 206 - snesreader/fex/blargg_config.h | 34 - snesreader/fex/blargg_endian.h | 185 - snesreader/fex/blargg_errors.cpp | 113 - snesreader/fex/blargg_errors.h | 80 - snesreader/fex/blargg_source.h | 125 - snesreader/fex/fex.cpp | 323 -- snesreader/fex/fex.h | 206 - snesreader/filechooser.cpp | 57 - snesreader/filechooser.moc.hpp | 20 - snesreader/libjma/7z.h | 28 - snesreader/libjma/7zlzma.cpp | 50 - snesreader/libjma/aribitcd.h | 73 - snesreader/libjma/ariconst.h | 29 - snesreader/libjma/ariprice.h | 12 - snesreader/libjma/btreecd.h | 126 - snesreader/libjma/crc32.h | 26 - snesreader/libjma/iiostrm.cpp | 132 - snesreader/libjma/iiostrm.h | 210 - snesreader/libjma/inbyte.cpp | 60 - snesreader/libjma/inbyte.h | 76 - snesreader/libjma/jcrc32.cpp | 80 - snesreader/libjma/jma.cpp | 550 --- snesreader/libjma/jma.h | 88 - snesreader/libjma/lencoder.h | 93 - snesreader/libjma/litcoder.h | 122 - snesreader/libjma/lzma.cpp | 41 - snesreader/libjma/lzma.h | 124 - snesreader/libjma/lzmadec.h | 82 - snesreader/libjma/lzmadecode.cpp | 298 -- snesreader/libjma/portable.h | 83 - snesreader/libjma/rcdefs.h | 60 - snesreader/libjma/rngcoder.h | 143 - snesreader/libjma/winout.cpp | 89 - snesreader/libjma/winout.h | 90 - snesreader/micro-bunzip/micro-bunzip.c | 515 --- snesreader/nall/Makefile | 107 - snesreader/nall/algorithm.hpp | 23 - snesreader/nall/any.hpp | 74 - snesreader/nall/array.hpp | 120 - snesreader/nall/base64.hpp | 90 - snesreader/nall/bit.hpp | 51 - snesreader/nall/concept.hpp | 15 - snesreader/nall/config.hpp | 124 - snesreader/nall/crc32.hpp | 66 - snesreader/nall/detect.hpp | 30 - snesreader/nall/dictionary.hpp | 76 - snesreader/nall/dl.hpp | 119 - snesreader/nall/endian.hpp | 38 - snesreader/nall/file.hpp | 259 -- snesreader/nall/filemap.hpp | 190 - snesreader/nall/foreach.hpp | 31 - snesreader/nall/function.hpp | 102 - snesreader/nall/input.hpp | 386 -- snesreader/nall/lzss.hpp | 81 - snesreader/nall/moduloarray.hpp | 40 - snesreader/nall/platform.hpp | 80 - snesreader/nall/priorityqueue.hpp | 109 - snesreader/nall/property.hpp | 91 - snesreader/nall/qt/Makefile | 55 - snesreader/nall/qt/check-action.moc.hpp | 41 - snesreader/nall/qt/concept.hpp | 10 - snesreader/nall/qt/file-dialog.moc.hpp | 392 -- snesreader/nall/qt/hex-editor.moc.hpp | 173 - snesreader/nall/qt/radio-action.moc.hpp | 41 - snesreader/nall/qt/window.moc.hpp | 105 - snesreader/nall/serial.hpp | 80 - snesreader/nall/serializer.hpp | 145 - snesreader/nall/sha256.hpp | 143 - snesreader/nall/sort.hpp | 62 - snesreader/nall/static.hpp | 20 - snesreader/nall/stdint.hpp | 44 - snesreader/nall/string.hpp | 26 - snesreader/nall/string/base.hpp | 137 - snesreader/nall/string/cast.hpp | 32 - snesreader/nall/string/compare.hpp | 104 - snesreader/nall/string/convert.hpp | 153 - snesreader/nall/string/core.hpp | 133 - snesreader/nall/string/filename.hpp | 61 - snesreader/nall/string/match.hpp | 76 - snesreader/nall/string/math.hpp | 164 - snesreader/nall/string/replace.hpp | 103 - snesreader/nall/string/split.hpp | 56 - snesreader/nall/string/strl.hpp | 52 - snesreader/nall/string/trim.hpp | 54 - snesreader/nall/string/utility.hpp | 169 - snesreader/nall/string/variadic.hpp | 27 - snesreader/nall/string/xml.hpp | 257 -- snesreader/nall/ups.hpp | 190 - snesreader/nall/utf8.hpp | 72 - snesreader/nall/utility.hpp | 30 - snesreader/nall/varint.hpp | 92 - snesreader/nall/vector.hpp | 240 - snesreader/snesreader.cpp | 235 - snesreader/snesreader.hpp | 8 - snesreader/sync.sh | 2 - snesreader/unrar/archive.cpp | 97 - snesreader/unrar/archive.hpp | 45 - snesreader/unrar/arcread.cpp | 314 -- snesreader/unrar/array.hpp | 135 - snesreader/unrar/changes.txt | 141 - snesreader/unrar/coder.cpp | 49 - snesreader/unrar/coder.hpp | 24 - snesreader/unrar/compress.hpp | 36 - snesreader/unrar/crc.cpp | 69 - snesreader/unrar/encname.cpp | 57 - snesreader/unrar/encname.hpp | 20 - snesreader/unrar/extract.cpp | 110 - snesreader/unrar/getbits.cpp | 34 - snesreader/unrar/getbits.hpp | 40 - snesreader/unrar/headers.hpp | 145 - snesreader/unrar/license.txt | 40 - snesreader/unrar/model.cpp | 612 --- snesreader/unrar/model.hpp | 133 - snesreader/unrar/rar.hpp | 209 - snesreader/unrar/rarvm.cpp | 1158 ----- snesreader/unrar/rarvm.hpp | 112 - snesreader/unrar/rarvmtbl.cpp | 57 - snesreader/unrar/rawread.cpp | 86 - snesreader/unrar/rawread.hpp | 25 - snesreader/unrar/readme.txt | 63 - snesreader/unrar/suballoc.cpp | 261 -- snesreader/unrar/suballoc.hpp | 88 - snesreader/unrar/technote.txt | 275 -- snesreader/unrar/unicode.cpp | 106 - snesreader/unrar/unicode.hpp | 10 - snesreader/unrar/unpack.cpp | 1065 ----- snesreader/unrar/unpack.hpp | 227 - snesreader/unrar/unpack15.cpp | 532 --- snesreader/unrar/unpack20.cpp | 394 -- snesreader/unrar/unrar.cpp | 350 -- snesreader/unrar/unrar.h | 164 - snesreader/unrar/unrar_misc.cpp | 170 - snesreader/unrar/unrar_open.cpp | 45 - snesreader/unrar/whatsnew.txt | 267 -- snesreader/xml.cpp | 752 ---- snesreader/xml.hpp | 103 - snesreader/zlib/adler32.c | 149 - snesreader/zlib/crc32.c | 423 -- snesreader/zlib/crc32.h | 441 -- snesreader/zlib/inffast.c | 318 -- snesreader/zlib/inffast.h | 11 - snesreader/zlib/inffixed.h | 94 - snesreader/zlib/inflate.c | 1368 ------ snesreader/zlib/inflate.h | 115 - snesreader/zlib/inftrees.c | 329 -- snesreader/zlib/inftrees.h | 55 - snesreader/zlib/readme.txt | 10 - snesreader/zlib/zconf.h | 335 -- snesreader/zlib/zlib.h | 1357 ------ snesreader/zlib/zlib.txt | 125 - snesreader/zlib/zutil.c | 318 -- snesreader/zlib/zutil.h | 269 -- src/base.hpp | 2 +- src/lib/nall/config.hpp | 5 +- src/lib/nall/dictionary.hpp | 5 +- src/lib/nall/input.hpp | 18 +- src/lib/nall/qt/file-dialog.moc.hpp | 2 +- src/lib/nall/string.hpp | 1 + src/lib/nall/string/base.hpp | 7 +- src/lib/nall/string/compare.hpp | 32 - src/lib/nall/string/core.hpp | 28 +- src/lib/nall/string/strpos.hpp | 60 + src/lib/nall/string/xml.hpp | 66 +- src/ui_qt/base/main.cpp | 5 + src/ui_qt/base/main.moc.hpp | 1 + src/ui_qt/config.cpp | 2 + src/ui_qt/config.hpp | 3 + src/ui_qt/settings/video.cpp | 13 + src/ui_qt/settings/video.moc.hpp | 3 + src/ui_qt/tools/cheateditor.cpp | 10 +- src/ui_qt/utility/window.cpp | 4 +- supergameboy/Makefile | 126 - supergameboy/cc.bat | 2 - supergameboy/clean.bat | 1 - supergameboy/common/adaptivesleep.cpp | 56 - supergameboy/common/adaptivesleep.h | 34 - supergameboy/common/array.h | 40 - supergameboy/common/rateest.cpp | 96 - supergameboy/common/rateest.h | 73 - supergameboy/common/resample/blackmansinc.h | 100 - .../common/resample/chainresampler.cpp | 118 - supergameboy/common/resample/chainresampler.h | 189 - supergameboy/common/resample/cic2.h | 198 - supergameboy/common/resample/cic3.h | 382 -- supergameboy/common/resample/cic4.h | 237 - supergameboy/common/resample/convoluter.h | 156 - supergameboy/common/resample/hammingsinc.h | 100 - supergameboy/common/resample/linint.h | 129 - supergameboy/common/resample/makesinckernel.h | 152 - supergameboy/common/resample/rectsinc.h | 99 - supergameboy/common/resample/resampler.h | 43 - .../common/resample/resamplerinfo.cpp | 61 - supergameboy/common/resample/resamplerinfo.h | 36 - supergameboy/common/resample/subresampler.h | 33 - supergameboy/common/resample/u48div.cpp | 54 - supergameboy/common/resample/u48div.h | 24 - supergameboy/common/resample/upsampler.h | 51 - supergameboy/common/ringbuffer.h | 112 - supergameboy/common/usec.h | 31 - supergameboy/interface/interface.cpp | 373 -- supergameboy/interface/interface.hpp | 80 - supergameboy/libgambatte/SConstruct | 64 - supergameboy/libgambatte/include/filterinfo.h | 32 - supergameboy/libgambatte/include/gambatte.h | 82 - supergameboy/libgambatte/include/inputstate.h | 30 - .../libgambatte/include/inputstategetter.h | 30 - supergameboy/libgambatte/include/int.h | 29 - .../libgambatte/include/videoblitter.h | 44 - supergameboy/libgambatte/src/bitmap_font.cpp | 328 -- supergameboy/libgambatte/src/bitmap_font.h | 87 - .../libgambatte/src/colorconversion.cpp | 96 - .../libgambatte/src/colorconversion.h | 46 - supergameboy/libgambatte/src/cpu.cpp | 2842 ------------ supergameboy/libgambatte/src/cpu.h | 115 - supergameboy/libgambatte/src/event_queue.h | 160 - supergameboy/libgambatte/src/file/file.cpp | 73 - supergameboy/libgambatte/src/file/file.h | 42 - .../libgambatte/src/file/file_zip.cpp | 167 - .../libgambatte/src/file/unzip/crypt.h | 132 - .../libgambatte/src/file/unzip/ioapi.c | 177 - .../libgambatte/src/file/unzip/ioapi.h | 75 - .../libgambatte/src/file/unzip/unzip.c | 1605 ------- .../libgambatte/src/file/unzip/unzip.h | 354 -- supergameboy/libgambatte/src/gambatte.cpp | 184 - supergameboy/libgambatte/src/initstate.cpp | 281 -- supergameboy/libgambatte/src/initstate.h | 26 - supergameboy/libgambatte/src/insertion_sort.h | 51 - supergameboy/libgambatte/src/interrupter.cpp | 44 - supergameboy/libgambatte/src/interrupter.h | 38 - supergameboy/libgambatte/src/memory.cpp | 1867 -------- supergameboy/libgambatte/src/memory.h | 238 - supergameboy/libgambatte/src/osd_element.h | 65 - supergameboy/libgambatte/src/rtc.cpp | 157 - supergameboy/libgambatte/src/rtc.h | 97 - supergameboy/libgambatte/src/savestate.h | 184 - supergameboy/libgambatte/src/sound.cpp | 155 - supergameboy/libgambatte/src/sound.h | 95 - .../libgambatte/src/sound/channel1.cpp | 257 -- supergameboy/libgambatte/src/sound/channel1.h | 91 - .../libgambatte/src/sound/channel2.cpp | 161 - supergameboy/libgambatte/src/sound/channel2.h | 70 - .../libgambatte/src/sound/channel3.cpp | 207 - supergameboy/libgambatte/src/sound/channel3.h | 100 - .../libgambatte/src/sound/channel4.cpp | 300 -- supergameboy/libgambatte/src/sound/channel4.h | 99 - .../libgambatte/src/sound/duty_unit.cpp | 148 - .../libgambatte/src/sound/duty_unit.h | 64 - .../libgambatte/src/sound/envelope_unit.cpp | 101 - .../libgambatte/src/sound/envelope_unit.h | 50 - .../libgambatte/src/sound/length_counter.cpp | 87 - .../libgambatte/src/sound/length_counter.h | 44 - .../libgambatte/src/sound/master_disabler.h | 31 - .../libgambatte/src/sound/sound_unit.h | 35 - .../src/sound/static_output_tester.h | 41 - .../libgambatte/src/state_osd_elements.cpp | 169 - .../libgambatte/src/state_osd_elements.h | 29 - supergameboy/libgambatte/src/statesaver.cpp | 407 -- supergameboy/libgambatte/src/statesaver.h | 37 - supergameboy/libgambatte/src/video.cpp | 1474 ------- supergameboy/libgambatte/src/video.h | 293 -- .../libgambatte/src/video/basic_add_event.cpp | 75 - .../libgambatte/src/video/basic_add_event.h | 56 - .../libgambatte/src/video/break_event.cpp | 35 - .../libgambatte/src/video/break_event.h | 59 - .../src/video/filters/catrom2x.cpp | 194 - .../libgambatte/src/video/filters/catrom2x.h | 40 - .../src/video/filters/catrom3x.cpp | 360 -- .../libgambatte/src/video/filters/catrom3x.h | 40 - .../libgambatte/src/video/filters/filter.h | 39 - .../src/video/filters/kreed2xsai.cpp | 243 -- .../src/video/filters/kreed2xsai.h | 40 - .../src/video/filters/maxsthq2x.cpp | 2875 ------------ .../libgambatte/src/video/filters/maxsthq2x.h | 41 - .../src/video/filters/maxsthq3x.cpp | 3845 ----------------- .../libgambatte/src/video/filters/maxsthq3x.h | 40 - .../libgambatte/src/video/irq_event.cpp | 36 - .../libgambatte/src/video/irq_event.h | 52 - .../libgambatte/src/video/ly_counter.cpp | 62 - .../libgambatte/src/video/ly_counter.h | 69 - .../libgambatte/src/video/lyc_irq.cpp | 42 - supergameboy/libgambatte/src/video/lyc_irq.h | 67 - .../libgambatte/src/video/m3_extra_cycles.cpp | 101 - .../libgambatte/src/video/m3_extra_cycles.h | 56 - .../libgambatte/src/video/mode0_irq.cpp | 95 - .../libgambatte/src/video/mode0_irq.h | 42 - .../libgambatte/src/video/mode1_irq.cpp | 33 - .../libgambatte/src/video/mode1_irq.h | 56 - .../libgambatte/src/video/mode2_irq.cpp | 63 - .../libgambatte/src/video/mode2_irq.h | 40 - .../libgambatte/src/video/mode3_event.cpp | 62 - .../libgambatte/src/video/mode3_event.h | 47 - .../libgambatte/src/video/sc_reader.cpp | 62 - .../libgambatte/src/video/sc_reader.h | 77 - .../libgambatte/src/video/scx_reader.cpp | 71 - .../libgambatte/src/video/scx_reader.h | 85 - .../libgambatte/src/video/sprite_mapper.cpp | 187 - .../libgambatte/src/video/sprite_mapper.h | 148 - .../libgambatte/src/video/video_event.h | 50 - .../src/video/video_event_comparer.h | 31 - supergameboy/libgambatte/src/video/we.cpp | 59 - supergameboy/libgambatte/src/video/we.h | 118 - .../src/video/we_master_checker.cpp | 58 - .../libgambatte/src/video/we_master_checker.h | 73 - supergameboy/libgambatte/src/video/window.h | 47 - .../libgambatte/src/video/wx_reader.cpp | 65 - .../libgambatte/src/video/wx_reader.h | 83 - supergameboy/libgambatte/src/video/wy.cpp | 105 - supergameboy/libgambatte/src/video/wy.h | 187 - supergameboy/nall/Makefile | 107 - supergameboy/nall/algorithm.hpp | 23 - supergameboy/nall/any.hpp | 74 - supergameboy/nall/array.hpp | 120 - supergameboy/nall/base64.hpp | 90 - supergameboy/nall/bit.hpp | 51 - supergameboy/nall/concept.hpp | 15 - supergameboy/nall/config.hpp | 124 - supergameboy/nall/crc32.hpp | 66 - supergameboy/nall/detect.hpp | 30 - supergameboy/nall/dictionary.hpp | 76 - supergameboy/nall/dl.hpp | 119 - supergameboy/nall/endian.hpp | 38 - supergameboy/nall/file.hpp | 259 -- supergameboy/nall/filemap.hpp | 190 - supergameboy/nall/foreach.hpp | 31 - supergameboy/nall/function.hpp | 102 - supergameboy/nall/input.hpp | 386 -- supergameboy/nall/lzss.hpp | 81 - supergameboy/nall/moduloarray.hpp | 40 - supergameboy/nall/platform.hpp | 80 - supergameboy/nall/priorityqueue.hpp | 109 - supergameboy/nall/property.hpp | 91 - supergameboy/nall/qt/Makefile | 55 - supergameboy/nall/qt/check-action.moc.hpp | 41 - supergameboy/nall/qt/concept.hpp | 10 - supergameboy/nall/qt/file-dialog.moc.hpp | 392 -- supergameboy/nall/qt/hex-editor.moc.hpp | 173 - supergameboy/nall/qt/radio-action.moc.hpp | 41 - supergameboy/nall/qt/window.moc.hpp | 105 - supergameboy/nall/serial.hpp | 80 - supergameboy/nall/serializer.hpp | 145 - supergameboy/nall/sha256.hpp | 143 - supergameboy/nall/sort.hpp | 62 - supergameboy/nall/static.hpp | 20 - supergameboy/nall/stdint.hpp | 44 - supergameboy/nall/string.hpp | 26 - supergameboy/nall/string/base.hpp | 137 - supergameboy/nall/string/cast.hpp | 32 - supergameboy/nall/string/compare.hpp | 104 - supergameboy/nall/string/convert.hpp | 153 - supergameboy/nall/string/core.hpp | 133 - supergameboy/nall/string/filename.hpp | 61 - supergameboy/nall/string/match.hpp | 76 - supergameboy/nall/string/math.hpp | 164 - supergameboy/nall/string/replace.hpp | 103 - supergameboy/nall/string/split.hpp | 56 - supergameboy/nall/string/strl.hpp | 52 - supergameboy/nall/string/trim.hpp | 54 - supergameboy/nall/string/utility.hpp | 169 - supergameboy/nall/string/variadic.hpp | 27 - supergameboy/nall/string/xml.hpp | 257 -- supergameboy/nall/ups.hpp | 190 - supergameboy/nall/utf8.hpp | 72 - supergameboy/nall/utility.hpp | 30 - supergameboy/nall/varint.hpp | 92 - supergameboy/nall/vector.hpp | 240 - supergameboy/supergameboy.cpp | 68 - supergameboy/supergameboy.hpp | 32 - supergameboy/sync.sh | 2 - 512 files changed, 163 insertions(+), 76795 deletions(-) create mode 100644 bsnes.exe delete mode 100644 pixelshaders/Curvature/fragment delete mode 100644 pixelshaders/HDRTV/fragment delete mode 100644 pixelshaders/HDRTV/vertex delete mode 100644 pixelshaders/HLSL/sepia.fx delete mode 100644 pixelshaders/HQ2x/fragment delete mode 100644 pixelshaders/HQ2x/vertex delete mode 100644 pixelshaders/Pixellate/fragment delete mode 100644 pixelshaders/Pixellate/vertex delete mode 100644 pixelshaders/Scale2x/fragment delete mode 100644 pixelshaders/Scale2x/vertex delete mode 100644 snesfilter/2xsai/2xsai.cpp delete mode 100644 snesfilter/2xsai/2xsai.hpp delete mode 100644 snesfilter/2xsai/implementation.cpp delete mode 100644 snesfilter/Makefile delete mode 100644 snesfilter/cc.bat delete mode 100644 snesfilter/clean.bat delete mode 100644 snesfilter/direct/direct.cpp delete mode 100644 snesfilter/direct/direct.hpp delete mode 100644 snesfilter/hq2x/hq2x.cpp delete mode 100644 snesfilter/hq2x/hq2x.hpp delete mode 100644 snesfilter/lq2x/lq2x.cpp delete mode 100644 snesfilter/lq2x/lq2x.hpp delete mode 100644 snesfilter/nall/Makefile delete mode 100644 snesfilter/nall/algorithm.hpp delete mode 100644 snesfilter/nall/any.hpp delete mode 100644 snesfilter/nall/array.hpp delete mode 100644 snesfilter/nall/base64.hpp delete mode 100644 snesfilter/nall/bit.hpp delete mode 100644 snesfilter/nall/concept.hpp delete mode 100644 snesfilter/nall/config.hpp delete mode 100644 snesfilter/nall/crc32.hpp delete mode 100644 snesfilter/nall/detect.hpp delete mode 100644 snesfilter/nall/dictionary.hpp delete mode 100644 snesfilter/nall/dl.hpp delete mode 100644 snesfilter/nall/endian.hpp delete mode 100644 snesfilter/nall/file.hpp delete mode 100644 snesfilter/nall/filemap.hpp delete mode 100644 snesfilter/nall/foreach.hpp delete mode 100644 snesfilter/nall/function.hpp delete mode 100644 snesfilter/nall/input.hpp delete mode 100644 snesfilter/nall/lzss.hpp delete mode 100644 snesfilter/nall/moduloarray.hpp delete mode 100644 snesfilter/nall/platform.hpp delete mode 100644 snesfilter/nall/priorityqueue.hpp delete mode 100644 snesfilter/nall/property.hpp delete mode 100644 snesfilter/nall/qt/Makefile delete mode 100644 snesfilter/nall/qt/check-action.moc.hpp delete mode 100644 snesfilter/nall/qt/concept.hpp delete mode 100644 snesfilter/nall/qt/file-dialog.moc.hpp delete mode 100644 snesfilter/nall/qt/hex-editor.moc.hpp delete mode 100644 snesfilter/nall/qt/radio-action.moc.hpp delete mode 100644 snesfilter/nall/qt/window.moc.hpp delete mode 100644 snesfilter/nall/serial.hpp delete mode 100644 snesfilter/nall/serializer.hpp delete mode 100644 snesfilter/nall/sha256.hpp delete mode 100644 snesfilter/nall/sort.hpp delete mode 100644 snesfilter/nall/static.hpp delete mode 100644 snesfilter/nall/stdint.hpp delete mode 100644 snesfilter/nall/string.hpp delete mode 100644 snesfilter/nall/string/base.hpp delete mode 100644 snesfilter/nall/string/cast.hpp delete mode 100644 snesfilter/nall/string/compare.hpp delete mode 100644 snesfilter/nall/string/convert.hpp delete mode 100644 snesfilter/nall/string/core.hpp delete mode 100644 snesfilter/nall/string/filename.hpp delete mode 100644 snesfilter/nall/string/match.hpp delete mode 100644 snesfilter/nall/string/math.hpp delete mode 100644 snesfilter/nall/string/replace.hpp delete mode 100644 snesfilter/nall/string/split.hpp delete mode 100644 snesfilter/nall/string/strl.hpp delete mode 100644 snesfilter/nall/string/trim.hpp delete mode 100644 snesfilter/nall/string/utility.hpp delete mode 100644 snesfilter/nall/string/variadic.hpp delete mode 100644 snesfilter/nall/string/xml.hpp delete mode 100644 snesfilter/nall/ups.hpp delete mode 100644 snesfilter/nall/utf8.hpp delete mode 100644 snesfilter/nall/utility.hpp delete mode 100644 snesfilter/nall/varint.hpp delete mode 100644 snesfilter/nall/vector.hpp delete mode 100644 snesfilter/ntsc/ntsc.cpp delete mode 100644 snesfilter/ntsc/ntsc.moc.hpp delete mode 100644 snesfilter/ntsc/snes_ntsc/snes_ntsc.c delete mode 100644 snesfilter/ntsc/snes_ntsc/snes_ntsc.h delete mode 100644 snesfilter/ntsc/snes_ntsc/snes_ntsc_config.h delete mode 100644 snesfilter/ntsc/snes_ntsc/snes_ntsc_impl.h delete mode 100644 snesfilter/pixellate2x/pixellate2x.cpp delete mode 100644 snesfilter/pixellate2x/pixellate2x.hpp delete mode 100644 snesfilter/scale2x/scale2x.cpp delete mode 100644 snesfilter/scale2x/scale2x.hpp delete mode 100644 snesfilter/snesfilter.cpp delete mode 100644 snesfilter/snesfilter.hpp delete mode 100644 snesfilter/sync.sh delete mode 100644 snesreader/7z_C/7zAlloc.c delete mode 100644 snesreader/7z_C/7zAlloc.h delete mode 100644 snesreader/7z_C/7zBuf.c delete mode 100644 snesreader/7z_C/7zBuf.h delete mode 100644 snesreader/7z_C/7zC.txt delete mode 100644 snesreader/7z_C/7zCrc.c delete mode 100644 snesreader/7z_C/7zCrc.h delete mode 100644 snesreader/7z_C/7zDecode.c delete mode 100644 snesreader/7z_C/7zDecode.h delete mode 100644 snesreader/7z_C/7zExtract.c delete mode 100644 snesreader/7z_C/7zExtract.h delete mode 100644 snesreader/7z_C/7zHeader.c delete mode 100644 snesreader/7z_C/7zHeader.h delete mode 100644 snesreader/7z_C/7zIn.c delete mode 100644 snesreader/7z_C/7zIn.h delete mode 100644 snesreader/7z_C/7zItem.c delete mode 100644 snesreader/7z_C/7zItem.h delete mode 100644 snesreader/7z_C/7zStream.c delete mode 100644 snesreader/7z_C/Bcj2.c delete mode 100644 snesreader/7z_C/Bcj2.h delete mode 100644 snesreader/7z_C/Bra.h delete mode 100644 snesreader/7z_C/Bra86.c delete mode 100644 snesreader/7z_C/CpuArch.h delete mode 100644 snesreader/7z_C/LzmaDec.c delete mode 100644 snesreader/7z_C/LzmaDec.h delete mode 100644 snesreader/7z_C/Types.h delete mode 100644 snesreader/7z_C/lzma.txt delete mode 100644 snesreader/7z_C/readme.txt delete mode 100644 snesreader/Makefile delete mode 100644 snesreader/cc.bat delete mode 100644 snesreader/clean.bat delete mode 100644 snesreader/fex/Binary_Extractor.cpp delete mode 100644 snesreader/fex/Binary_Extractor.h delete mode 100644 snesreader/fex/Data_Reader.cpp delete mode 100644 snesreader/fex/Data_Reader.h delete mode 100644 snesreader/fex/File_Extractor.cpp delete mode 100644 snesreader/fex/File_Extractor.h delete mode 100644 snesreader/fex/Gzip_Extractor.cpp delete mode 100644 snesreader/fex/Gzip_Extractor.h delete mode 100644 snesreader/fex/Gzip_Reader.cpp delete mode 100644 snesreader/fex/Gzip_Reader.h delete mode 100644 snesreader/fex/Rar_Extractor.cpp delete mode 100644 snesreader/fex/Rar_Extractor.h delete mode 100644 snesreader/fex/Zip7_Extractor.cpp delete mode 100644 snesreader/fex/Zip7_Extractor.h delete mode 100644 snesreader/fex/Zip_Extractor.cpp delete mode 100644 snesreader/fex/Zip_Extractor.h delete mode 100644 snesreader/fex/Zlib_Inflater.cpp delete mode 100644 snesreader/fex/Zlib_Inflater.h delete mode 100644 snesreader/fex/blargg_common.cpp delete mode 100644 snesreader/fex/blargg_common.h delete mode 100644 snesreader/fex/blargg_config.h delete mode 100644 snesreader/fex/blargg_endian.h delete mode 100644 snesreader/fex/blargg_errors.cpp delete mode 100644 snesreader/fex/blargg_errors.h delete mode 100644 snesreader/fex/blargg_source.h delete mode 100644 snesreader/fex/fex.cpp delete mode 100644 snesreader/fex/fex.h delete mode 100644 snesreader/filechooser.cpp delete mode 100644 snesreader/filechooser.moc.hpp delete mode 100644 snesreader/libjma/7z.h delete mode 100644 snesreader/libjma/7zlzma.cpp delete mode 100644 snesreader/libjma/aribitcd.h delete mode 100644 snesreader/libjma/ariconst.h delete mode 100644 snesreader/libjma/ariprice.h delete mode 100644 snesreader/libjma/btreecd.h delete mode 100644 snesreader/libjma/crc32.h delete mode 100644 snesreader/libjma/iiostrm.cpp delete mode 100644 snesreader/libjma/iiostrm.h delete mode 100644 snesreader/libjma/inbyte.cpp delete mode 100644 snesreader/libjma/inbyte.h delete mode 100644 snesreader/libjma/jcrc32.cpp delete mode 100644 snesreader/libjma/jma.cpp delete mode 100644 snesreader/libjma/jma.h delete mode 100644 snesreader/libjma/lencoder.h delete mode 100644 snesreader/libjma/litcoder.h delete mode 100644 snesreader/libjma/lzma.cpp delete mode 100644 snesreader/libjma/lzma.h delete mode 100644 snesreader/libjma/lzmadec.h delete mode 100644 snesreader/libjma/lzmadecode.cpp delete mode 100644 snesreader/libjma/portable.h delete mode 100644 snesreader/libjma/rcdefs.h delete mode 100644 snesreader/libjma/rngcoder.h delete mode 100644 snesreader/libjma/winout.cpp delete mode 100644 snesreader/libjma/winout.h delete mode 100644 snesreader/micro-bunzip/micro-bunzip.c delete mode 100644 snesreader/nall/Makefile delete mode 100644 snesreader/nall/algorithm.hpp delete mode 100644 snesreader/nall/any.hpp delete mode 100644 snesreader/nall/array.hpp delete mode 100644 snesreader/nall/base64.hpp delete mode 100644 snesreader/nall/bit.hpp delete mode 100644 snesreader/nall/concept.hpp delete mode 100644 snesreader/nall/config.hpp delete mode 100644 snesreader/nall/crc32.hpp delete mode 100644 snesreader/nall/detect.hpp delete mode 100644 snesreader/nall/dictionary.hpp delete mode 100644 snesreader/nall/dl.hpp delete mode 100644 snesreader/nall/endian.hpp delete mode 100644 snesreader/nall/file.hpp delete mode 100644 snesreader/nall/filemap.hpp delete mode 100644 snesreader/nall/foreach.hpp delete mode 100644 snesreader/nall/function.hpp delete mode 100644 snesreader/nall/input.hpp delete mode 100644 snesreader/nall/lzss.hpp delete mode 100644 snesreader/nall/moduloarray.hpp delete mode 100644 snesreader/nall/platform.hpp delete mode 100644 snesreader/nall/priorityqueue.hpp delete mode 100644 snesreader/nall/property.hpp delete mode 100644 snesreader/nall/qt/Makefile delete mode 100644 snesreader/nall/qt/check-action.moc.hpp delete mode 100644 snesreader/nall/qt/concept.hpp delete mode 100644 snesreader/nall/qt/file-dialog.moc.hpp delete mode 100644 snesreader/nall/qt/hex-editor.moc.hpp delete mode 100644 snesreader/nall/qt/radio-action.moc.hpp delete mode 100644 snesreader/nall/qt/window.moc.hpp delete mode 100644 snesreader/nall/serial.hpp delete mode 100644 snesreader/nall/serializer.hpp delete mode 100644 snesreader/nall/sha256.hpp delete mode 100644 snesreader/nall/sort.hpp delete mode 100644 snesreader/nall/static.hpp delete mode 100644 snesreader/nall/stdint.hpp delete mode 100644 snesreader/nall/string.hpp delete mode 100644 snesreader/nall/string/base.hpp delete mode 100644 snesreader/nall/string/cast.hpp delete mode 100644 snesreader/nall/string/compare.hpp delete mode 100644 snesreader/nall/string/convert.hpp delete mode 100644 snesreader/nall/string/core.hpp delete mode 100644 snesreader/nall/string/filename.hpp delete mode 100644 snesreader/nall/string/match.hpp delete mode 100644 snesreader/nall/string/math.hpp delete mode 100644 snesreader/nall/string/replace.hpp delete mode 100644 snesreader/nall/string/split.hpp delete mode 100644 snesreader/nall/string/strl.hpp delete mode 100644 snesreader/nall/string/trim.hpp delete mode 100644 snesreader/nall/string/utility.hpp delete mode 100644 snesreader/nall/string/variadic.hpp delete mode 100644 snesreader/nall/string/xml.hpp delete mode 100644 snesreader/nall/ups.hpp delete mode 100644 snesreader/nall/utf8.hpp delete mode 100644 snesreader/nall/utility.hpp delete mode 100644 snesreader/nall/varint.hpp delete mode 100644 snesreader/nall/vector.hpp delete mode 100644 snesreader/snesreader.cpp delete mode 100644 snesreader/snesreader.hpp delete mode 100644 snesreader/sync.sh delete mode 100644 snesreader/unrar/archive.cpp delete mode 100644 snesreader/unrar/archive.hpp delete mode 100644 snesreader/unrar/arcread.cpp delete mode 100644 snesreader/unrar/array.hpp delete mode 100644 snesreader/unrar/changes.txt delete mode 100644 snesreader/unrar/coder.cpp delete mode 100644 snesreader/unrar/coder.hpp delete mode 100644 snesreader/unrar/compress.hpp delete mode 100644 snesreader/unrar/crc.cpp delete mode 100644 snesreader/unrar/encname.cpp delete mode 100644 snesreader/unrar/encname.hpp delete mode 100644 snesreader/unrar/extract.cpp delete mode 100644 snesreader/unrar/getbits.cpp delete mode 100644 snesreader/unrar/getbits.hpp delete mode 100644 snesreader/unrar/headers.hpp delete mode 100644 snesreader/unrar/license.txt delete mode 100644 snesreader/unrar/model.cpp delete mode 100644 snesreader/unrar/model.hpp delete mode 100644 snesreader/unrar/rar.hpp delete mode 100644 snesreader/unrar/rarvm.cpp delete mode 100644 snesreader/unrar/rarvm.hpp delete mode 100644 snesreader/unrar/rarvmtbl.cpp delete mode 100644 snesreader/unrar/rawread.cpp delete mode 100644 snesreader/unrar/rawread.hpp delete mode 100644 snesreader/unrar/readme.txt delete mode 100644 snesreader/unrar/suballoc.cpp delete mode 100644 snesreader/unrar/suballoc.hpp delete mode 100644 snesreader/unrar/technote.txt delete mode 100644 snesreader/unrar/unicode.cpp delete mode 100644 snesreader/unrar/unicode.hpp delete mode 100644 snesreader/unrar/unpack.cpp delete mode 100644 snesreader/unrar/unpack.hpp delete mode 100644 snesreader/unrar/unpack15.cpp delete mode 100644 snesreader/unrar/unpack20.cpp delete mode 100644 snesreader/unrar/unrar.cpp delete mode 100644 snesreader/unrar/unrar.h delete mode 100644 snesreader/unrar/unrar_misc.cpp delete mode 100644 snesreader/unrar/unrar_open.cpp delete mode 100644 snesreader/unrar/whatsnew.txt delete mode 100644 snesreader/xml.cpp delete mode 100644 snesreader/xml.hpp delete mode 100644 snesreader/zlib/adler32.c delete mode 100644 snesreader/zlib/crc32.c delete mode 100644 snesreader/zlib/crc32.h delete mode 100644 snesreader/zlib/inffast.c delete mode 100644 snesreader/zlib/inffast.h delete mode 100644 snesreader/zlib/inffixed.h delete mode 100644 snesreader/zlib/inflate.c delete mode 100644 snesreader/zlib/inflate.h delete mode 100644 snesreader/zlib/inftrees.c delete mode 100644 snesreader/zlib/inftrees.h delete mode 100644 snesreader/zlib/readme.txt delete mode 100644 snesreader/zlib/zconf.h delete mode 100644 snesreader/zlib/zlib.h delete mode 100644 snesreader/zlib/zlib.txt delete mode 100644 snesreader/zlib/zutil.c delete mode 100644 snesreader/zlib/zutil.h create mode 100644 src/lib/nall/string/strpos.hpp delete mode 100644 supergameboy/Makefile delete mode 100644 supergameboy/cc.bat delete mode 100644 supergameboy/clean.bat delete mode 100644 supergameboy/common/adaptivesleep.cpp delete mode 100644 supergameboy/common/adaptivesleep.h delete mode 100644 supergameboy/common/array.h delete mode 100644 supergameboy/common/rateest.cpp delete mode 100644 supergameboy/common/rateest.h delete mode 100644 supergameboy/common/resample/blackmansinc.h delete mode 100644 supergameboy/common/resample/chainresampler.cpp delete mode 100644 supergameboy/common/resample/chainresampler.h delete mode 100644 supergameboy/common/resample/cic2.h delete mode 100644 supergameboy/common/resample/cic3.h delete mode 100644 supergameboy/common/resample/cic4.h delete mode 100644 supergameboy/common/resample/convoluter.h delete mode 100644 supergameboy/common/resample/hammingsinc.h delete mode 100644 supergameboy/common/resample/linint.h delete mode 100644 supergameboy/common/resample/makesinckernel.h delete mode 100644 supergameboy/common/resample/rectsinc.h delete mode 100644 supergameboy/common/resample/resampler.h delete mode 100644 supergameboy/common/resample/resamplerinfo.cpp delete mode 100644 supergameboy/common/resample/resamplerinfo.h delete mode 100644 supergameboy/common/resample/subresampler.h delete mode 100644 supergameboy/common/resample/u48div.cpp delete mode 100644 supergameboy/common/resample/u48div.h delete mode 100644 supergameboy/common/resample/upsampler.h delete mode 100644 supergameboy/common/ringbuffer.h delete mode 100644 supergameboy/common/usec.h delete mode 100644 supergameboy/interface/interface.cpp delete mode 100644 supergameboy/interface/interface.hpp delete mode 100644 supergameboy/libgambatte/SConstruct delete mode 100644 supergameboy/libgambatte/include/filterinfo.h delete mode 100644 supergameboy/libgambatte/include/gambatte.h delete mode 100644 supergameboy/libgambatte/include/inputstate.h delete mode 100644 supergameboy/libgambatte/include/inputstategetter.h delete mode 100644 supergameboy/libgambatte/include/int.h delete mode 100644 supergameboy/libgambatte/include/videoblitter.h delete mode 100644 supergameboy/libgambatte/src/bitmap_font.cpp delete mode 100644 supergameboy/libgambatte/src/bitmap_font.h delete mode 100644 supergameboy/libgambatte/src/colorconversion.cpp delete mode 100644 supergameboy/libgambatte/src/colorconversion.h delete mode 100644 supergameboy/libgambatte/src/cpu.cpp delete mode 100644 supergameboy/libgambatte/src/cpu.h delete mode 100644 supergameboy/libgambatte/src/event_queue.h delete mode 100644 supergameboy/libgambatte/src/file/file.cpp delete mode 100644 supergameboy/libgambatte/src/file/file.h delete mode 100644 supergameboy/libgambatte/src/file/file_zip.cpp delete mode 100644 supergameboy/libgambatte/src/file/unzip/crypt.h delete mode 100644 supergameboy/libgambatte/src/file/unzip/ioapi.c delete mode 100644 supergameboy/libgambatte/src/file/unzip/ioapi.h delete mode 100644 supergameboy/libgambatte/src/file/unzip/unzip.c delete mode 100644 supergameboy/libgambatte/src/file/unzip/unzip.h delete mode 100644 supergameboy/libgambatte/src/gambatte.cpp delete mode 100644 supergameboy/libgambatte/src/initstate.cpp delete mode 100644 supergameboy/libgambatte/src/initstate.h delete mode 100644 supergameboy/libgambatte/src/insertion_sort.h delete mode 100644 supergameboy/libgambatte/src/interrupter.cpp delete mode 100644 supergameboy/libgambatte/src/interrupter.h delete mode 100644 supergameboy/libgambatte/src/memory.cpp delete mode 100644 supergameboy/libgambatte/src/memory.h delete mode 100644 supergameboy/libgambatte/src/osd_element.h delete mode 100644 supergameboy/libgambatte/src/rtc.cpp delete mode 100644 supergameboy/libgambatte/src/rtc.h delete mode 100644 supergameboy/libgambatte/src/savestate.h delete mode 100644 supergameboy/libgambatte/src/sound.cpp delete mode 100644 supergameboy/libgambatte/src/sound.h delete mode 100644 supergameboy/libgambatte/src/sound/channel1.cpp delete mode 100644 supergameboy/libgambatte/src/sound/channel1.h delete mode 100644 supergameboy/libgambatte/src/sound/channel2.cpp delete mode 100644 supergameboy/libgambatte/src/sound/channel2.h delete mode 100644 supergameboy/libgambatte/src/sound/channel3.cpp delete mode 100644 supergameboy/libgambatte/src/sound/channel3.h delete mode 100644 supergameboy/libgambatte/src/sound/channel4.cpp delete mode 100644 supergameboy/libgambatte/src/sound/channel4.h delete mode 100644 supergameboy/libgambatte/src/sound/duty_unit.cpp delete mode 100644 supergameboy/libgambatte/src/sound/duty_unit.h delete mode 100644 supergameboy/libgambatte/src/sound/envelope_unit.cpp delete mode 100644 supergameboy/libgambatte/src/sound/envelope_unit.h delete mode 100644 supergameboy/libgambatte/src/sound/length_counter.cpp delete mode 100644 supergameboy/libgambatte/src/sound/length_counter.h delete mode 100644 supergameboy/libgambatte/src/sound/master_disabler.h delete mode 100644 supergameboy/libgambatte/src/sound/sound_unit.h delete mode 100644 supergameboy/libgambatte/src/sound/static_output_tester.h delete mode 100644 supergameboy/libgambatte/src/state_osd_elements.cpp delete mode 100644 supergameboy/libgambatte/src/state_osd_elements.h delete mode 100644 supergameboy/libgambatte/src/statesaver.cpp delete mode 100644 supergameboy/libgambatte/src/statesaver.h delete mode 100644 supergameboy/libgambatte/src/video.cpp delete mode 100644 supergameboy/libgambatte/src/video.h delete mode 100644 supergameboy/libgambatte/src/video/basic_add_event.cpp delete mode 100644 supergameboy/libgambatte/src/video/basic_add_event.h delete mode 100644 supergameboy/libgambatte/src/video/break_event.cpp delete mode 100644 supergameboy/libgambatte/src/video/break_event.h delete mode 100644 supergameboy/libgambatte/src/video/filters/catrom2x.cpp delete mode 100644 supergameboy/libgambatte/src/video/filters/catrom2x.h delete mode 100644 supergameboy/libgambatte/src/video/filters/catrom3x.cpp delete mode 100644 supergameboy/libgambatte/src/video/filters/catrom3x.h delete mode 100644 supergameboy/libgambatte/src/video/filters/filter.h delete mode 100644 supergameboy/libgambatte/src/video/filters/kreed2xsai.cpp delete mode 100644 supergameboy/libgambatte/src/video/filters/kreed2xsai.h delete mode 100644 supergameboy/libgambatte/src/video/filters/maxsthq2x.cpp delete mode 100644 supergameboy/libgambatte/src/video/filters/maxsthq2x.h delete mode 100644 supergameboy/libgambatte/src/video/filters/maxsthq3x.cpp delete mode 100644 supergameboy/libgambatte/src/video/filters/maxsthq3x.h delete mode 100644 supergameboy/libgambatte/src/video/irq_event.cpp delete mode 100644 supergameboy/libgambatte/src/video/irq_event.h delete mode 100644 supergameboy/libgambatte/src/video/ly_counter.cpp delete mode 100644 supergameboy/libgambatte/src/video/ly_counter.h delete mode 100644 supergameboy/libgambatte/src/video/lyc_irq.cpp delete mode 100644 supergameboy/libgambatte/src/video/lyc_irq.h delete mode 100644 supergameboy/libgambatte/src/video/m3_extra_cycles.cpp delete mode 100644 supergameboy/libgambatte/src/video/m3_extra_cycles.h delete mode 100644 supergameboy/libgambatte/src/video/mode0_irq.cpp delete mode 100644 supergameboy/libgambatte/src/video/mode0_irq.h delete mode 100644 supergameboy/libgambatte/src/video/mode1_irq.cpp delete mode 100644 supergameboy/libgambatte/src/video/mode1_irq.h delete mode 100644 supergameboy/libgambatte/src/video/mode2_irq.cpp delete mode 100644 supergameboy/libgambatte/src/video/mode2_irq.h delete mode 100644 supergameboy/libgambatte/src/video/mode3_event.cpp delete mode 100644 supergameboy/libgambatte/src/video/mode3_event.h delete mode 100644 supergameboy/libgambatte/src/video/sc_reader.cpp delete mode 100644 supergameboy/libgambatte/src/video/sc_reader.h delete mode 100644 supergameboy/libgambatte/src/video/scx_reader.cpp delete mode 100644 supergameboy/libgambatte/src/video/scx_reader.h delete mode 100644 supergameboy/libgambatte/src/video/sprite_mapper.cpp delete mode 100644 supergameboy/libgambatte/src/video/sprite_mapper.h delete mode 100644 supergameboy/libgambatte/src/video/video_event.h delete mode 100644 supergameboy/libgambatte/src/video/video_event_comparer.h delete mode 100644 supergameboy/libgambatte/src/video/we.cpp delete mode 100644 supergameboy/libgambatte/src/video/we.h delete mode 100644 supergameboy/libgambatte/src/video/we_master_checker.cpp delete mode 100644 supergameboy/libgambatte/src/video/we_master_checker.h delete mode 100644 supergameboy/libgambatte/src/video/window.h delete mode 100644 supergameboy/libgambatte/src/video/wx_reader.cpp delete mode 100644 supergameboy/libgambatte/src/video/wx_reader.h delete mode 100644 supergameboy/libgambatte/src/video/wy.cpp delete mode 100644 supergameboy/libgambatte/src/video/wy.h delete mode 100644 supergameboy/nall/Makefile delete mode 100644 supergameboy/nall/algorithm.hpp delete mode 100644 supergameboy/nall/any.hpp delete mode 100644 supergameboy/nall/array.hpp delete mode 100644 supergameboy/nall/base64.hpp delete mode 100644 supergameboy/nall/bit.hpp delete mode 100644 supergameboy/nall/concept.hpp delete mode 100644 supergameboy/nall/config.hpp delete mode 100644 supergameboy/nall/crc32.hpp delete mode 100644 supergameboy/nall/detect.hpp delete mode 100644 supergameboy/nall/dictionary.hpp delete mode 100644 supergameboy/nall/dl.hpp delete mode 100644 supergameboy/nall/endian.hpp delete mode 100644 supergameboy/nall/file.hpp delete mode 100644 supergameboy/nall/filemap.hpp delete mode 100644 supergameboy/nall/foreach.hpp delete mode 100644 supergameboy/nall/function.hpp delete mode 100644 supergameboy/nall/input.hpp delete mode 100644 supergameboy/nall/lzss.hpp delete mode 100644 supergameboy/nall/moduloarray.hpp delete mode 100644 supergameboy/nall/platform.hpp delete mode 100644 supergameboy/nall/priorityqueue.hpp delete mode 100644 supergameboy/nall/property.hpp delete mode 100644 supergameboy/nall/qt/Makefile delete mode 100644 supergameboy/nall/qt/check-action.moc.hpp delete mode 100644 supergameboy/nall/qt/concept.hpp delete mode 100644 supergameboy/nall/qt/file-dialog.moc.hpp delete mode 100644 supergameboy/nall/qt/hex-editor.moc.hpp delete mode 100644 supergameboy/nall/qt/radio-action.moc.hpp delete mode 100644 supergameboy/nall/qt/window.moc.hpp delete mode 100644 supergameboy/nall/serial.hpp delete mode 100644 supergameboy/nall/serializer.hpp delete mode 100644 supergameboy/nall/sha256.hpp delete mode 100644 supergameboy/nall/sort.hpp delete mode 100644 supergameboy/nall/static.hpp delete mode 100644 supergameboy/nall/stdint.hpp delete mode 100644 supergameboy/nall/string.hpp delete mode 100644 supergameboy/nall/string/base.hpp delete mode 100644 supergameboy/nall/string/cast.hpp delete mode 100644 supergameboy/nall/string/compare.hpp delete mode 100644 supergameboy/nall/string/convert.hpp delete mode 100644 supergameboy/nall/string/core.hpp delete mode 100644 supergameboy/nall/string/filename.hpp delete mode 100644 supergameboy/nall/string/match.hpp delete mode 100644 supergameboy/nall/string/math.hpp delete mode 100644 supergameboy/nall/string/replace.hpp delete mode 100644 supergameboy/nall/string/split.hpp delete mode 100644 supergameboy/nall/string/strl.hpp delete mode 100644 supergameboy/nall/string/trim.hpp delete mode 100644 supergameboy/nall/string/utility.hpp delete mode 100644 supergameboy/nall/string/variadic.hpp delete mode 100644 supergameboy/nall/string/xml.hpp delete mode 100644 supergameboy/nall/ups.hpp delete mode 100644 supergameboy/nall/utf8.hpp delete mode 100644 supergameboy/nall/utility.hpp delete mode 100644 supergameboy/nall/varint.hpp delete mode 100644 supergameboy/nall/vector.hpp delete mode 100644 supergameboy/supergameboy.cpp delete mode 100644 supergameboy/supergameboy.hpp delete mode 100644 supergameboy/sync.sh diff --git a/bsnes.exe b/bsnes.exe new file mode 100644 index 0000000000000000000000000000000000000000..ae11e59a2af57acc6de4ce8ee548774a53402dda GIT binary patch literal 674816 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%0AEHr@-I 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%0D*h>mVpz|b*-P-$@W{q|q3n;} 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

D(o-)WGk7b93Eg#)0f~X3v51vQdK0WSBUW$NM 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 z zh_N7h>%}In8{$38NfAQarCG!OgQI<82ljkf8rwNH(%=6s`XXZ`)BDop70q&A^G;sb z@19v(S>R|fciEb7!+#?`yaPPEeyGObY}X#SX*PaUjyaoiJ1K!g)j!%nP}H$vh9T+&F#dWxA)z@`_0+exf3V8b7u9FzZ;Q@Jpdabfa+h7(&ME7w4pV^ zaNb9$=eARXBy1*UEqTa4LkYz!XDG~eVcbnDKbZ9Vo&HK3BNL)OFBU;Rih)D0PG0YU zuaMq(JawaUs`t=zXJm}0 zV~)$zXG=>cMnqy?$a2t5-}-cnbB)Ie6oEUS%6UA4+ z^X<^=$-lP~8cXHHxBk~HcEcQTs)ERv10CT14@4yU_u#TEWBRu5Dl%n7g|s~{4J@r* zOsMLP4nISMv_p0u|CGb1sxwm7*$O{WRXpz`6#iXAE=LQe9=>5}0M|;<6pUueN}!!n z5J3u6ny)e(t4X~*v@Lu;nzQbu(_zS6uXr^Ma*7Id_CRZ6nXsGj@Jm+c;@Jm($G^n5>?M2n&GQJ@3x^e_%`{1MV z%}0f48!N~(m^*G26Rq6m@e}uNTVnGH??$K&ORlWpqXK9i6+MHTWyLCbN5Pop@#Mak zBJoalGM6CMh{JjCeZcf!rlF#-HJQ(}-H=FvSyUy%sdUPlj+A!%bbi-2K8!CbFNg;x z4O`iR&0|%ZymN0RM0t1Kbb{{jsKCPyAJgo7IxNT@Q%pv#8K&o(p7fz)w+@c<-yPe3 zUHyi5Z{%(ji)x(i89>7F1ydZyg{q0U)v|0qrSV1>mX=pcf;*Rh`e*7l?<&BD9+J_Ch`=0e< zh}V(@-U)fE(hFxcy-(i&sbaz4LnLqvdCVRv&+)Q7v#^?I)3@~&ZX-E5a}PbWMcvqk z$UFjUtFx|s)9D>$Ekn}_XqKitemaUoDptqj)br0hfwqUl#v@wAdYzAu$Idfbz0Ft? z?}ol}i#d*V{S$A2H(%eTU!xy&PQ6s6NaTz@ggDZcZ6`3+`K`~Y=dX4C>ayn^IdPwx zdAUgFJ77qx=>xDGt6!xKX&HDj=8xA3r1$;3NPaF!&P^SoZ)8Ch$`Tr$R4H}3Yb#<9 zxYz5!XS{H?u;wnaMp3H!)L3z_P^W#ezua<}Y@#onm7?Q! zM!MP8C-?mr`jvrHhTYuhs*~E1SGJ$F^D!2euBm?M>#H8V&*VD;h)I&K;*7^kMCIOI zNph#$+42qBucLsi$2FvFs-xox{v|ra;42Z~uG}K?%Pb{7F26d+HdR<@6akR-aJwy80B{r6hOPv~& zlCNn^DrAKd1OV&~)9DCf$U>&_*4~Rd?Z>BW$g9Fb=+reWaJR8R&Kr~85?)3ZI#)1W zP*(FrywvNq@3bf+4|RkZV``5Z2I8gE`Rd4OgV`FbvBozjtIKYOPGvHeAskR4uQ&>V z16(VEF9&}{kOEVvk^LvSbq4}-wS>SLYsbttC#S>z^4g*j8cqN275ty zOk9#l*kk{G1s=@*wYs!{nkA=Jzdvj6y<;U>KG?d=7Cel-{gw2dFU8MJ>-Ye<1Ozk@ zzBuY+TA9r%F%oPmGu1a3SHD+;ap{=i`naG+2CQ1%ftT?JBxY>|w`P$CB2E238T1~4 zI)VTKH)@?j_2n-JUQcqaQBzf@mY$O;a`o)*_u|AWc+_JsjsasmVp-OWgZum? zW)5+b{4tO^9y5?EYkN>Lu_NC&`(C;^V|O7@XooB=;V*H`LKL3 z8RfHfJj4Cy(8nKntJQ5#%&h09vCxFu+lp!dI~N;|W6#1L?}j(#vweI_rL`|=j-k4H z%7VMQeB^f&N+J)6?yP%Pfdq{G zC14Y0r#X?XV4=(h z6Z*-y^>^C--NmJW&IV<1#RHd#OV-s`!z%VP-#I3LD+^Z^wI+{7X1-H zeeNO#1@EfLp$Znt6;U9+#^N$o^50dgLQ%KihCBo1lmM7 z>W=lpc2KR~VhIb~u*=rr+B6|M5Ig~|s4VAlsu@`S>hJPe%9n$B86*JZ64^{@y;=y# zb5en`q+OW&z&o*wNni=u4O$^`S1vk|dx`*;R-2x&&S@(??)P`eF5!8?!usVd%`#xn z76ZPCP8U&GDM;P2{&VhPpMOG+L_y<`G9xFeknqN|rt zr*94|XbWt8IPwWO@w%g0JY=q^|OJnK~Ho zFXbGGmUCWb9`fPLm05{uv@>k#RR=io&5SeV8%{;AYJ3QZ)KuqC!M`EInN(_tu7P-} zhcPS6SgpCx+D+l0v=asr&|~PCzqHh9<|!5>w|5IV*TGsCN%THM!hWo>(@w&T&Afl> zGLcy1rN!iZ$F-AZ9SMEWAbe-;-SiqnI~!uO&BM{4a`QIXD#u+94<^F?{!&2kPqD%w474`fFgng^v5%7-%0GdpvngBibg)3o1V$}|R z?l#y5rO~_(S6^_gXHevr2%(t%r}5YBQaT7`Yz6Fj0VXb)oWq|i9{sfD)HJ=5>G-vv z7)oJ&bZkml*ZD_rdGS`?C}JSmKwI;Q^?j3x6Lo-43_Kz^dnu< zpR)5*213J9v=;$yItKNKSV3X}Fr)Vzr0aC($orALhj56@_7&y2Of@dT#)y6wCFsas zxapA->>cXWD?zWXTWkmTJ2ck$Y`84jovvRdy{}w>NZSA>-3|erz+{oK-(~)sLio zGB4{%XRo17HK(a|yiQt3D!cZup^D&b&Ll0fGwcv?)J|-b!pjG*%JO?g3O*S<;^Z6A3HE+4WGI=GVvFA(fp#1Qqm3Mn3SAp z?3PGj-wo{y^}yPx)Rwcgo)tgchW|;hhi22qDY9t8ejj(o-=*x!P>ceXq*+MH)Wubl zwn{u(-o+rBg$R7%M;UF^a|_iI5>3$a0@xyXlofrT(4blx`}MM4O)@t33H$P}w8R5E z+QF(BSbc-=i$MiZ4qUNj?qBN$n#~wYDVq6)(hA_I-gEIlF{Ua^R2GwH&PJmL13B@* zV@LdR70&4%#*__*&SH0o>+qaD{Y;g&6 zO5hx5d9NT$$_k&lTX@L-{k6TWQCtwoY!KL(^~`F)p2QTM^xr6zdrSrSAph9e5<#<| zY)dUZ)F7gtM@u)x#gIF1aw+t5M%wipgC$#A!-#bj(;4IZWOxpAmS(NXFYK&$O#ah4 zHg#@fB+d6$T|b)mBi;b}7MvELov!90f{&Lib~#gpjb5CBOKwYS9g@hwJQ84Ny-}pH z#599~z`X2a*OW$F@FlD`49D8M>DwtU> z1$Th3>R9bRo*%5G%A!a1oq7=*Z{WT2@BQA!C%75Zz&h1aBJO|BCCr`CbTAqqAs`U2 zMBht`Ur+e3{d=ukgT?PVq&!dDIaEGC*M$}HIkbuYA95gOG>mq7Ay8HNFkz2KiJ>lE z>F<0a_pa6-3)MOv3Fhe$V4DB#OvL;v^)^MITrVGE${%5Q+Ut3>{pwRUKLuI{zZ|V$ z7UDSd^9VTO0f@af!}G86%ccH>f?IpF-uj;Y^a8UN@r;v=4^!hxp#o2#z?3`2cQd|Ca7oOC*v+*qqd+(GP~fReZm1R+N8jyMi#LynnQfcoYbn(D35CZh;G4th%wH6_l&$SPShV~*mB z<%_6+i>0?iq#&NtAEG{gXA=FE0_qt1CU;kj78+EieX2LDhdMncckKU~Q~QXf?n@=8 zi5%3jTW;?AU|W}m!sGDMXVp9y^-;cp>4?Ji>t21)5{sgNeIKmbMuJ-{CyFKh9VA); zH23pYIWr>j-1pxQG^*8T-Vi*(k>QL-0#PWYu+C%VmSwvpYU&!Myo|&Vk z)P?{6$jj@GT3!_W_m3Zn$+acp z#Ok~zCldTANJ~`w`iY-e)}ATVG1Kg49(V9~3y0@(DNta*!VrF^nTplUMF+Au^_JS61ED7tEqLqImUXq+(k{Tvl^02TcBhNK8Q$d1jDE*e1LexXSB z=rIP=2ai+H8s!5wh`{H;D5ixPyzmPpA7s%>cZb%N@4|G_WM`mrlo1hebRx`(*K|k| zmYM^X7Bh(jJLnB)rkbpXW6A-G{QkQ4M9}s#;Qe-=Y79Cb8Q00XJ6`N zfTV_IL0|2SDNOrx1L(A8RGnC)YLO6d$J^?>n@5uKO=fHS1MUg{@#k4!Jxb;gCRnl~ zU_&)oeD2nv?HW$lS5A>ZWN)c+-vmBk_#n<#4+l;%pSr6+2&8XZm<5-1r8X{;p{)WJ~~-(g!-{?3F}BO$o-P( zIrROZ20XZrA=nE3Tk*oA;?OD_tX~QGGW3AF^%lCmVqAX9IcR_XYde>Iyrr;d)D|L6 zLoPL#^cDxzE^h0)zdu;P(7IVqC+~-d%R)QShCP0sFp)%!j^>j|xqJl?0onqGI z_YZwG3*JyhJqxYuBI5$usKUH?`!M})wC2ObFc%zq$ErZ%v$z*H8oS#J5vFnG`18XJ zlE`3RWJItwG3(sx^;OsayezZD`R+L;2_hLb`X4A@2qF+CCtcJ5crtbOH=|L!(XFsk~k5rzH^J(S>U z|BP*B`H8CYZ=3N}EWEoyFghgi`YIvSged;Shj|fYw&8OJjLnF}GRRZ`ZU|WIV5h^P z<2+S!$zZa`#!}lq`m?qWSjT`Re*ixNc$V2Q;e=OD!HxcJyOdl~Pi|9o1 z$XssYFtOdqLGFu=0TZSRC5=bUS5-xWhd+v#VANdRO0)=4f;KJ}3&0$yvc=kSw z3J+HHFF>bCp4V~y2CK`WgeH!4R8o#X=Nas=bZG z%BvFAcoUeD5>jAtzvdR~2+$J3E6cq_AVS}o8S-WJCP6Iv@SftnPrF9c-*I(kaOw^~ zZKOYoM|7`<+GZY$^Ez$0zqM;1lF&_lwK={X8h**s6Q^z7>de_RQ zosVzGEym-8gw5Es&3ArZLfv&4ZWa?~u$%9+cQY#EW z0y~UuA-cb_Ec2;g>RZFjIj7ii=r?|9-la6q>vW}j9`{e86KTD`EC_!+u#g|k_s*VI zPRjiSdgq#ahb|6YZHk06G5JH{iDb4oHFcH{9uXW^4NWAz{8`(wv{U@y*jrcLlf~5Q zX;nNLo~dlO<}|61LXb&&k&pm`CP-tR1RiA~T1P8cSj*}#0y=0@D^&Xmx!KoMfIn_YW)+7vN@ znZOt>b3+Hmm8sg-iV*Pf4x!UcXYJ$-Vy46^wNf&EwsiuX7x6_6V&{a57xa8Ogck_p zZ)@7IK`~lWhH`a*#n#2~(=p?P~zt^}6!k9_D9AU_u zvBt<#V^j8r`^!iIzJHxPr7*9s8bAE`@q>b&r65G;1ri9CK1qs|)h=(3Z+{Wrq&j(Y zy80|k!hj=>9AHk4gEP)%)CCN~8RH6kfpqu1zmcOBCNy45r9}?mSqfwAR!RNQ&U*CS zbQIk>_Xjf*<#A*kdF-k$O%=1C6Anqq=4rrD4-teck~yGVLIdMqxCCwh|CuLZJRIk+1R~NKsz@1QzitSC81BryU2hzmo1Rd)OsiO^+E~iRTST_;6_4k1G zkF(Etc$jx{DaCWTBpjG&o!()cSgO@+meHO{rVH@2`=b-0i2JP?Vnr$yAzCJrs`R1PnjJ(~aY}#xI1r zwgViD#Bbqk2BU^@<9<-*N=ZYi zElwzc6BThu35_d-Vtc;IRWITOvBV)4uf^wXDYH9Fzvd|zE@X6325jk`#b^M*TFT4$ z+AKhzQ(u+IqBGq3?h#?gM$QNhSFQs8The5N=tyyZGq(8Mo#EN*Jc5urNTBJy@K%Svs$eg|r+S4iZT}F0T=E$K zi2(&pk}OKNuYpyIVuFtd6JunhZ(0goW%-vdg+6@^wC+#f_RVfRLWF1c>Ys^4n8@Ik zQZ+qJQtxS46Uy1N4sLUgMudE1g6T5q6hja3cd-r*kikcF4*Z$BB!L4zhp6#ZWa+uL zFXqxv^>mGzM?qbOx37Q9`4Qh>(MUd8l6q@~fjpaYz7)ICj&0jfXK<#J5o1$*i$Aeu#6<4u*a|wbQO{E**cjYVL{=+SOPXtHo zWG5_oGx78`i78Zz!3NW(AGyoe-`Urh6h2gX;J#N2L^N?ER(5@ZgUz|v4P%J+&xH3& zt({SPQdZJyaS~@5xb?68fv~y^bA@))vz;7*TKjYorY%JAKbWwXKRS;buXe)zQ2&kj z``e5e%+4(;8t@P8;M>-#6IyZjp7ie=UfS8w)9TFIeSvO&TUFPw+WmiaEWbfLeh$Lq z#Df(H;LC?6kbX?)q`B)Do(c@>xzzjv$3ghAfQCvFs*C4bmP&n^ZzFbhP>6E$w4lc% z@EIsI7`eoSMduGfUPl*g*W|O;wQcz6JNyV~vLQeI2gy}*t_bBbtx8A=OvIlSaS<{q5ms23O7IeONU87VzB()+LP>D7} z@Tt2|7}p#g_l2er7IuAf>Q$LuSDdzP&8^pM^1p~%83+es5Ehzs4nzTd-7FRe^`a+q zlt8YOgA;z872#qLX5y0nZuEm79pWw~=E2>mb_jskpCrEW9pPTDmkU;k4HH=gg}LfX z-1%mKr9LO9&Y2Nw=bFKv<()Dq? z*Pi;Ul(BRGB;(z#mbU;Vz`C=UEk*jfDNVM2dlI9r@(stipkV{-asO zoPAf@V^kP<+miU77_`PJoFG*+tnWz0)&4{oUnd0`9+VIdZgL2VelRz|m4p&viG~tW zIBUJYXHC3d=l?XICBdrgz*h4ld=w{{s^oANv((L5OV9DJXw0K>&Iy1#ni|2*3L8lY z(BgQh_SQMM`V5B$@hGYWY>jj`bP}Y!L$os;dY$7lvv3-MsRt*6iN^EDoO6Iw5%fqi zjV=+!iizXa((kl*{&Q_-pTf~NE|ec(|8WtR9vIIfqGh5M2oBsR52?V=o!fm2YcDi5Qb=TqO83w?#P1YdaqMpTZ z;Hto*Y?Hg@W8W3#e(w=+UXx-)1D@chL{YMYrKkZ|bgaLQ)$ND)X1toS@Te*<1XLKU z_{S`a+nWdzXL6LqG6mWwPB|=`zSEgqe5Iyt?E!QQ(*Syj8KFE*pMVNqhsc=`xoCY= zLg-uTc+6fUh8rQ+l~*WjnyD%tk%`1euhH&+K5V_F{fqu0ER&z z(e6JcY6Wxd(@70}d->yWX5sxohM9uKCV(bp0tuM$&IlB{FqcV|aqG){YO_N@W_o)D z#t;lB0EicbyGWV+GJQ5O$CWOVZss!UCOA)~jD&2^IkaYKXAQ+*rHS{?)ob!k-DfL3!Me$~pWVOJmVmgPg>^bQ!_hMOHhH&Lv-Jx(;x zObIf5Hs)RnjzLdRfl6SVch3;3F~vW4nMqXo`HZi~pZ7wpa3kbvw|%;zpSv*vl6xnd zDweWKT#z*AXeS>TyTMkS8}c8l)Lz>2rj45ozw)|SjicReQ7O|J2{yRDBu!01C6^SU z|4bUs)fXPfRDbJbdmhe{=Y79rcc@(Qd1Z@y(*}xJ@}v9$`^!EZ!^A{bed~Q4lIzDz zB3ANj{YGcug{Kmb=HUd0tW@i+FPDU1Rm!bj4C%~fD{uE{^AWQfzpWlv0WGjc*M}Ib z{j_CXWothx?QFUf^X^v_N_PLwW3C2&Lt|_JH%F{hhqWghZpdE~BobN}BYbgk*u6{` zVU(^v2%LZ5p!1<_dDsv{ z0-N~95}OS6vmvhT{ytVwY2BQ5_i)sth@)fR`vK+fTpf?P#CN`)rWdAc7Ia^PTG|gQ z1fC_0d7zacqHoNusLoGdfg9#m>5}%(-hxMbkX^-rK6DTwn_7Tp@iO=VyPaQAc1Geo+WzA*CC}9)Z<H1)wh0LH8@~kwvb=fy9?>0~OgdW!&)F1& z1wAM;ryIr&nu=1mrb`^jyRmIAGGG{^!A?X5*M$g?=GG`PRb~zAZ-bL>`vp1~7&Jf^ zEkEXDlFGzi!t~br*2?a!`dMvI*{HA$>PNBJGHEot^O+JH)+U})((qf4Ljyz8klEw= zv&(k^r(%){gx+@;wPwt zUkk_k=9A?eR}Y1*b$aoc%tr&BAMlPDBBaMLh8`R3pqQ1hmky(YSI;7-xG3vx?9D&p zjLStcj`PU<2Auau;h-TH0Nz>>)-o){e2I;PYxb8ea+Kb$yY)bW5Q{v4WVR;UL@4ID zeO-}ZgwkZFQD~#sCgfAfPD={MKhMl!3(3XS6vJ?+vpCb&fhUAI6PahpcLm*DEF$5F zgzSc1kpH0T|F@7=zRii69;-g?ae*@xv>u2wW%NgbRej-A-6*FRP=F>ia_N>fjaHkl z;H>1{ol8=4w7mT??Ac-*PW1^So&!qK;&P%RwYy5fvE^lVX>#ur$i0@bhTkauAK^A$m}2>92$6rN$pvzt}oG z+)0#oiH6qTysk#lCs=ZeARQjK`4kfpmS1_kS7T#=WUVUf@;^AeKsK)b-WMPBu;&u6I<=-A7ez8L0PSrrRu z@V-s`G0s(d$`CTBADgPfv%Xq878-K}#k{HwV)8qW4`x2Er213!qz1UE7axw8@nR@6 z!Uw_#@k23qaiW9qEr02Oyn5^ z`!0-ZQ;9DR+QZIDi|bLroQ2-&({s_{^EWgaw%Ym^@3sc4uD!mNfz{|hm)~w0=iRH5 zdaVN&!Ma%D)!st%l^9_gxDFVwngEmcFSAvoj}8&kpPTOe_8eO~IAn!EFJfC-*=B}A z)NXOx8z$4unOB5xlg@Oa&tS%R$0jqbptQ7r(y9R6mCm_CWVX)h#iaw|)j+_v#iD}fz+vm)l%xog^2qR{JmS^>au-_gkrh*8x$be) zsw~~l6tOz=7bEz%%1;%!k7iWsuhH+yPhM6>ZbB5m@I9a-t(af!sl~EuMl<7UIfOB? zlOv{YqJ126E&Ear%`Qp7yzgJt@!NmXn9^n%-kW-OY$cFq(O5Ir4z>nkE6M!ZS<(xm zsC9L5n>%jT=T9R-0$NmK#^cWwyT~rkJIeay^z>YDyJ}~DXw|t+8$1~d8N%4NbP#8N zersUKz^Q$NZZ3v%FgUA(I2ZDgDs#j3)hu}92ggf+9&~MUt?Z+8@;|NH2ugYj>E@-x zP;lCMOS1(nAcA~4j`FDwD|8*+4{ahr6`E#47V78>Ykznkew^ zIcDbm`9rl9AHfi7!)fz)5z2A)MElv(BGzJNwhp*5!3+prOy4iX;`SW5I7afKcq(@{ zBLjpM2`3DD)e25niXWldnbwY9oAeZCx|V_>D+8B+9F2ruz$ z-VF6n69ONvD&&h(>@#>QXLxI=aqBz{mX#J4_YEoAPKbGZ2J#KejA{WdJTv22EYra!YE+;KW* zHZfp$?f3dPPY6!R`t?>ZUaRF?ENL;w)6Lp_xAGV9gN+wyPr^hPV98o$1Uq5k+4!{g z>x@f>itY#XO;fU%5&(yn2_36Fzm_3C5X*ymb?Lj`D8h#%q>mbx$6jQm>z!e%advrDLx(#?K z8c&|`pX~&C=c(-@C?_H_R6t1u0B0l|QA#6<`uIF6De3r;!UaT zi6uA@*2IeqV)8iKNON}HEjLMy$zsvhY?>3pK9kR&eW}%^Eqi+j)qo&OO_VG|Hv*B1 z27UBrR*rrvf@n2;1K$jezr|VI^!k8h-GH5~!RIro+F%tl)~14Rn+jiLBqn~ylF z(9S@RI*{vEc)eKDT~72E;F&6wz5j8E<{oat6!TV;azg22fZ+gpJ15hRKiG!nRJq=j zr)`M0%p8Y3><1a={>~g2Pi+`o|5_WL6X!kd!6Fdw%Z$w|47Dql%1nhHu7(ARwTHp` zB4J(YNPaPq{(@7sk+sgVzGKkp>*%duD!^8!8ud9WtNCT z-;0V2HSns;ykhznswJymTV-PgmVairZ@+Yp#Bi^HDahvDDK(?^Wo0MBA90JrjMuW4 zjsl`Ldhx+N6SDzBEe|9l>?1YUZ{!glVzxd#$5jaCHhtD7^8lYah3DYQe;pa4XxE6? zKs@Y>F1VI|sHLXQmWwZcR0{wRp4ukE?Sh8`x;^%ZHWms+85CW7q(gjxTL7^=-0$9# zO6<8~eTrq;b`w?(ew03dJ0%3!fo=hgnC`PpFxXz?0?*a&w)xdJy6M3Lr3PCgI_((w zB6rfdt#SnLFlFoU+|Psoo|N5ms2nL%XBNbWk~~2fB+Ais3+Eu)8=Tpz*YF`( zB$MtuwyqrX=Ky>B3=S}_l0Wrn!Dw_xe>bZhY^cVFlM}h%yS@7ze&|YYL-T}MD|NIs z>FMMJq*`JU|Grv>%+=`mUsJdjb9Nx`OSGTU<{bhi?z1zVm9#nQBsf2BvWC}_O(MhF zi?g9U0dMeFBUDp+U#T&SXQux-geqCBi&f--z1Szof+GqM0!@l9On;c=s!>!i}5AvW*j$5~$=_`xErFK2gTm6FRO= zjI;JycZ#MhENpm2rjb9Gdi|tO%(mLGcjNA`eWXUKNB2|w`z-Ac;)TAdx9iS`>_SHM zFSKC(*vK}=sh{ZOm8`Mdel8dagLF4oTTmXT(fUR&@I|WZ+};_OXKDpfYKh&NfI2e} zdZ|*Devvb!dOt26!&ti8NVz?^kWJmG)@vpvznN(~Z-$MBN&7PU{ACA3w|R=35W&93 z_$g7~+=me0-D}Z3AWGVD+|o)#1+~nlOKoztcm#M9%P=%$u54J^eGQ8hc`QD0y5XH7 z1z3>~hJ|VuNBFQKBT9a}RU{0zgvg zEo9IO-+|F;pozm(V>9G{^Uqs{H;smki$5|RXuY8rUY>p5@@^hul(2`JKRs*vuk_~L zioPSAX>n7Q-Tj^Y89a}G=|-dK*)?O`GEcYF@{=oMWA00nW)+gDl{Ip38~?Rb+tK9b zWUIH&Sxp)aFVU7zI|I$jK^pw+?%m<3;qz^CUm)$vmL&#>m(io?^Wj8s=Q^N*xTiwF z43}&Z#~A&sL;_Yr^4#S~Evd)g!Zsy; zn3F6bXi5QJjMKQDsWhJ$e0t)i0f~MS9GiKHP`C)^7_YLqOwjIY{Y9*NedP5TuC%Vm zc1By!>JcmgMcg`>^S3X|o>&Ujkz|p4LFNO0(Puq4&=|S#H@GTAX;1!}9atm7nYwoQ ztUAe-WK9ay{!_P*1bRLgHNrpr?M3ottwO|7drs|!_3|2xmDVNt3?ee=FNM$Y2e0$h zo0oa%>vtINt!sAUhdr|M%^jg%w1>Rxz=w@*_)z{1j6KwYh zmU1EddV!!1w(fH!3z&BQcY1omnSXA{>B0r@HcYlsgj-F8=4@|K~*G?H%VPOy11F z=O<9_0VFL~j%hEA?2G&0EA#Lamq(JkkgY{O&=pduVnVeN4o>}3?y>9%+zekL0#VcJ z;eO4p*fNa72WMD>Lgqk7%8QiDt1e8!`;!FzQ_ci9 zn|n#6sxMh$UB4Un(I6F-h~%f~JL>iYSBNM_r@GXWB@T*tjJ#(mRxz=>5P6-+sYlc5 zTJ6}HhuwZH>w!s}De?bJ!2o?h-JleIYbO;4`xu^{Li8cMSXXq)sikJ1B^Q>xC^=LP zE2(nC=#44%AthD;6IVpdJNy@a3>MrV$qxRf%|r=MeO-MSl=vr!#7F$<)pb)UMkFv*v&-sW6T?GZ2vkU30avfXnzcEr z7xFjCW4k5v+PuC+erJ-zN_-b`Oqdv6JxWWJzo8f#jIGtvzLv?1k{zn2%*IznZz8N; zcRoBiL84jtZw?q^K}?{-C-vj!E|f3B}*zG56$CX>XO4KJ3#EmbHO9Dq(;<4=nCyRDI>~WJ zy8V!4*ft&(xo#v4xoD`+wQ4AMG2z!t{LLc(8JDVWT5k-q1cgc0r;E{*$xx64)6!xb zg$pg0DCo-?({F(8u-6rSxDi5_bgOSr-Yf_DdTJqikj{ZG>D*(F%8$?G=k>`Lg3wh- z5}3cAxwPlmC{>gc-59q3$v&WlY#02cXO+m*N0>BCMwY_VYz)JV;%Es!-kx!SY#nj{ zLYAIQu_$=h&O}g96PvB#93kW@ETtLt4pwrmmi;XNcu1s6V!SMUZ99I|WO6tB`CDfL zQRni*X;0oEsCI^^WoagVe_(NQePm8~=IqFHfEsAPRAjm{?Xo-M?z~R0Pqv+dQH5u< z`1Fw`bdjh(5bzd(X5;g}VpCpxcSGJN{!F48h|p^0#oBRyZe_nANk4wv1}YYDLyZP8 z95^zY1-FvBzfHgJjvnV1MEyVSNN+n3qk}>|5t;l>7Ji@K{^+udPZZQ$>i+w8`*B)d ztRiUD3YA42xSY+P+KtAN>|hhBcD@0}tYohzy0mH0%f{9RqeVMM3Ku8I%wj%EjA1j-gF|LnrJeSEFWiK1DWSyr0i)dZGc~u#S7_J!64UtxI`l+c zZPDH&OF4e?CbG6F=@@w{YY#q*c@_Niqx@RhZ!0DJ)nnoAQ|y6&EoHn^SDD}7ts}r| zUnwkxqK!jsV$Ox0h26H0QYS{{XzNuu&`AqcqWW6*u#=%?{VH+T&Y0i6M$z)NIwcHO z{#$x>LLF^X9LRwKYETNoCz+e z5eXbHpmX z!O@z2Yc9i2Q>^dsTwe+Cvb2m6LQ58yLHfX<{ z+$d|tpj96+Nl$ZdW#eL46!8{z2FjOg$d1(Lt;q_`|F2Y$(N-9I@ZQzNQpF^=k#@LXBtO8&?1 zrC6k)1(mSzI^AWd?Azy5KWeH3wfN!WC~CRCj&BPi?0X4F^uh|jj9O5myGgmy?rXG& z3uKl2tA0LPvFOMQM|`i;2I)1qQsfbdOjC(B&K2s2vwsZUIYWg~4Z$^)*CoGFyn^}* zzdBZsEQ}}|-bKDbaQIqwAl=93OdSV`;XF|wQlngC!*Tp5VYE&=M}t{>7?#j}M_;%p zhg2!~|F)e}j!{~QF%pPZ<(y`rKtJn6$**E4e>isfRJJW{1YIaq&xsu?CNF;xiKl>v zk!c?#73<|09b=_oS|&*9ArP)q7Koxa;Z2Hj;=h3-t-K!&xd&J=pFGT#Xnq>I8-<2Y zp)iWyA@xs!vPw!;QEH|=^{Qj|>RcO{2!&cX?+it+K4)tpf%>JCSW#ZW%U63sjttSl zgCfSQ!ikQMd0{`U|EKLoUd($6y@!UwU3OM&ukk`ZN&JDroff&w$*!W&rsq=V7rTBj z88ucFlsIl9#LVh>)8drcfzP#b$7^Axo19GSyb3`K2X-w!tu$w{xyfE6%-?3Gbcnx*c^$fPtsOIPG%yi zujugAA-?c(fw=*Tz_}7yXaeRW-QM?8yKD}l-MPj;lMbT*n*ZKazHhyy+4)%hFyPh=JqGSV)I%(p;E$)ONullF^=#t5@UoiOIGu15#=T~z-OShxZk9y=i~V;!j-+-C>|xsvGTovu zv6oY&c(5Gk&Kwq?HWqzj#2oug#fd+W!uVJ8%JY$>X3?k|* z@7}eo=D$UGM+|BTo%Hh5CVS*Ycqa^DY)T3rS$J?c#&E@1%N8v_OI%V6tvBPnpDD70 z9x?lyx5nDzpos+ui9e|QgDoXO?@55faQ!xHEOD3M{rOIv>S=BZie^gE_nIwop%cA zss@M8KgvZ(ay1yk=}S-~b9?@5%j{W1OY>nuDb&FsmCd|2?f zA>tFCl_MEhc=EeDCHN!`*TeA_FGKmtuTtr zcE!*3O=2iARe~^}V|Th%#(GbQkN1#}apgnu@H36%7Y1s=+BEa}2plI}e@GDQ#wVeN zpiM#?5Ab75MD+w2@>zNl8J|V&NhHYk=c~BXRl?+cN@sE0=`Y#Cb4D5iFj4jQXw607 zHsqiB#hrt9O?k-T(7sUwjHV?puZueAu)61rX7_pa{#^uJMh->7g7-M$I-I#m5jT0v z!gHUYu?9wM0JK*Nn zD*7hes2yr10ZvA9Sqp?^K6`h4F}7`${}xLE7t16i<+q}`VyopmL!n+OPs*JfV-pOu zjBxon&wip=@wt^Gdl!^lwkrTa{0H5j%w~B_Vr=xG;4-$S<@i37cpn@qHrV|vTG*{j z`0QG)xLD@Fgct~x>c=0FQb6Tt^G>tB#2I}-GVXsScr5H5PB>e6{!)#r)pj6?kqKBaw?ulbB7l=QsN3rp&m(514I$L=K?RWX?>J zOWuWox*$t9@~D}KW#E=pBs{<89Fp)oP^DI>F;;Ydb63c?s^AR3v~1hjRz}#Ailx=J zW$9@TKaP3<7DUne{v+wA1EPAGfOJW>2na~Gv~)>#NQZQ%AaFEDi!?|#(kXRxBi+&= z-6i$Dcfarcyq%eix4V-&W2{q~XBPYS!C!A-4y{;Cb?HtT#_qIQdDg#;+d}1ihI>~2 ztTOp7!x4HXtvRNp&*pg*apr>I@Th1jO*vD zkXDMqGD~!t3If?|w9L==Dpd)v6&Pp!AjZ`CGk^VRa>#LGyFsn4R-}}*SoeL4e~R(g zjuQ;#8(+(1*|#lmx^vk$the;EnY6*8KGvuuotOunw>hereYO76>TMID;`Xi6aF*hb zlyiV072Yp_HDq)3{vWeR1H^Su9tl)!!7TRJ{mPyFb4+q$oj10V4a-_c4DZqKTq<9` zdH+E4MnMG@3_x{Px?$Ii#~;w3V8862YgKS3V_$bs_5%(P#+qrx3UI0V(bgppoq4#| zsjNC*pyi~&qX;BRfjem#E)ORtlc>5Fe|dUOj3W>)7Cqh;F;yie#5~st`h>urPU;+Q z5{Ni48W1e^ng(uiRQj!Z(iHr4y;-OXC^tfS-=F`>^24BT>-fo4A52s4KqjB^3%hpv zKcPT1oZ9U;VDLqCEyhOYKac%n@$F<@_78?(GcMhoo+_>2=&<@*ZTXJpcc(@iQ&A}6 z8B#wPnS6foQWNR_K<+@W@pa=%0_|07ALw=lBoooaBaJobtgY3`l_@rd663{^yGd8F zv%t;7e4P@ElW*`yGV!s#?4b*%5-2S>!D1byP5X zmCKfe$1#baF80x$;?&fftwzb-H#3t5f_Xu4;*i8m z!s)i&F{T}=nYry&6VmcMt(`NK59d1ndNnzmFFvHOXfj^CIivLz@i|s)ci_Ol)FS2_ z9D9lOF>l!CtcY}H%7g09&cbGqD3_;&Bk!ZQVJXb(!YorXM~AZ%!jx{qCVb3GSJ>9% zVkP_az%2*X`8y$V_?IDBaU^!CRqFwrP5#iUM|B&i7jyH8u0oAv7Y2jpAoHU0To?E)G{Lox?%L#}>yg3xp7aK2HWr}3 zjNm}a8Nx=J_t0Wv#HBaYW;P3F`hpY}u>qCL{i~^OB;7mECt&%q1RYv!^pnvbdb@8i zejkrIKaGlaB*+T`+iN`%$ij6wDOkh0-`geHSv#UTFntE?+$Hd;?G2H~GFn=q?#Bne zeM|(&d9Aa-{#v7Nno~BVdAD-$kvw)VszMe#^`vpV{^aC*+Bwg728g-?YnW5+JbOdi zEj-l{P&0JYc9K28tyRlEQ@P~9?0%0IxBWt2%c(;7#xzL_`s4&0`7!@AWVRF|a?ti_ z?+cMG6Jj&FK+4#D2318+1haCf9n3}wD}E)H2|079=5chDNpCOSDvi7Ocgz#r14?PY z&pK3liiBIQgh2iq$cfmX=8Lbvz@NZ7jU@nD`}}OnTx<8YH4-<-;gdDdW6oPcr9Uvr zdcGI#pV_1GMUY$KEYbSig6>hpOO;gxYjP+hRQ2DMV3@4dzsF%yd27v2fOrj4jOmGH z#8J}^5yv9@T{WxVEQg-=p=j(oO-uKo?=Yx9*$S81^9=<=O?kAkNdyGPv>U0nM}>-z|;m|x5y-5V{YrN=&j-} z_V;_60fR|=61-CFbGgORL^?<%XTWMae0Ms0Tm%%Kw@|KKN=(C)-EOch%7l&-2In5_ z_1U!F$*__C>aQ2Vg$L$963w&kjk(zNz#rQB*?~)l!(K@oKtp=P%q$( zBkVqmMM1~cogrb?q5ILZT#~K%WzMX1v7Wiy(o6%~@&HeU<@URLW3vE1Fh@iZB9*ADyP|MQMVw?UEIY<5pJecP_zM;0BC%se3)-E)NRUe zFx2PsF_NYZ;B%9RhHHxCJppT;f$0_#LU0(uxZSv-NdQkc&$@rPC;>3PEKs{sLfTws zC&sch7Rj2{Na&XQYlCHMtns_^4qE^^G6VRD0dAjx9}0#eANdb;8f`sfdxeL0ZUppK zQhIxTfHy{tvp~m)S?<%XMTKW8n$^Z~*&9KwU5%kT3=p;H0SC`V147ux5DUKS;s&$rxn8rdAue*ZcI#-jn~H}ZmM%0=IAPyFce@s-}v;$uAjA|81b zOu%t@XzKrSpSvipvX#`UuC!MRj>qXj{S#ZhP*ODCaaen@N2W?iT7~Y}7Y7}GbAd~c zAn4^AiF42&b=1?a{xyS}5X+w$5S=u#5)f)+I4Gjt#@0Rn!sIx=SuRfe9zdjQIIqUK zsCzJ2`BZyzJax^)25PO4HnYaR9ESY|f3tBJ%O{0pXo5t>e^$f9LMW|hVfJ&8>?N-C z*|rAl2fQrN(m#;Voq_L7%Hh^>egGH}R6p*YIdHJ`4?5>Y&uG+VyEVi^K;5#aKN-i$ z(F7gr1_~G0l)QVhbEEgGPZhrr6sE(5E!pkVBe`oRa_C}@{p2klZGJJ*EGT#IK~Vf? z#EAUnz!dzDyeU|JxUb5c5hO8+#W75*pLwjo*%)KAd$TB3# zc&1}u79&BCm+sSY1-V0yQ#&n$Fa+4wOo-mDZjg|=DX+QHW|k9%A#OasdTH8_7e6FL zs-R%q=Uj{@i99m*x%wxerO1!kgACZ4(zU&ULC)2|-<^*WBc;_M3sah}<2szAwmJUe zyxvwQZn8!rWJ&nK|3ndh_Ec16CqbhUp&o@#ITy-cei!g3=5v8uh-q&wh$1yAZW6-& zo?QUA{fXBJmG|$9nsgh2-N4cgAsuxT5&;Ih{P>iqLq~7TuELHkQ3fQs0qmta6NN?d ze^RzJ`QO@g$(A8VNRQ2JpUxf%6^^lpBHCdK`2M+eo5VDjNX%7vrTP-q=t7 zboe=Ozn_qBlRt22;Ns&kLbu4_6WAP=R~9vCyKWbf<-qzJKoZe%mH!i5!79B16;ja2 zBgZR4l7E?hOaHa#iVcbNQ1Ac+9V?D@U~k9-QWqwF~(}9ZcH$SGoaz%34(5Tzkfs>CSMzW1omdk-O<0u z7I%0ZZKyO9yP$x=NtgW3uL+@=gcdnLNGwdK7)o3qj#*e?JwbI|x9{*f{E~PvwF-hc ztyqIEK1Dar;DGYd#;8Y$h_f53*}CEl{BLQJS7f1H?B>B^UkzxSj)4qxoSUO&sK-Ob zoAB`qArJ$Qb&}OLDj0YFd5fFKwRD*0Aiw;)sGY$wTHMo7mFEd+TV9Xq#7kO<%mrlG z{z_&>+~3x}MZ9oI^Z2~q2YS=jp67V5WMrbLmGMbM!Z4qdEfz?)&V;_@nhy@1N`={^ z@7i#@5C$f;7w&-aEJRN;-2x&+K6De0M#;4}B5vMhoR!P|d(f8u~xWmFnS} z&lQ|P`e#slMn{RoR&CpvBjx)ayh*`xp=4_ zC=255ykV$rL4g8#dIar^`ueI5&GReYxNC>@7KjlxP#&h0+M7T_2y~0(o?eDMer0py z9k!q;g-S&Lq#=RdwVi+`8Ajpj*lvdU;4KyIrH{@%1t1lZv%&SLx&yWQW!oex$F zL8;{T(E|2wBxK2eiu8+SjhLD=Qz!Jt`feJ$b8^#XA|l+EZ`i=7D6As}Kjm~n7PdCk z)#i{CO~rus-a)V~yzWg-+dF<9PftLqq9j|taP*tGxrc%2JgWJ+jl}3Uia66OuT3c9uy53Izub`!6 zdB2Vo-pUBoHhMP_cc%Y{g|FG#!X9e$O8bVka^BE_8S3t*EjuWd@oSGH+nYu zH{Oi7BBCayGMhdEAF`WU9Y&hmCiY?+5Ug}t-ofT|s5bWy+<;}!4>gsVVZXg_jG_RPX)WIY^uTv>F1@*@*MUStcVM8 zx(A>pk5auD?#9Q~oiDIfB;O^Fd@1Yqc`*F~UVUK5VakhJ&B*T2dkg26G0lS?7*AVne^==pgzMew#(2h3iOR zOMq#jIn&))wdUf8^hCkB~Nb`9kSr7 zQICIAuMq*GA9|*(ieX0-O2zR(wu{P4bxm6ISkr$?29CF8h9zu4#jLK<6+br#QV@~#=F+A#LTRF#^r_m-bH|$!?Z|{C1Y+u6}opn@W z%hl)o%bfSHzO?dqf^X{Zvvb-{O7T>nS7;vcZFnSiUmun=P$cTw{}UT4uMn@T9)o6< z1-{U%SNt2T|8ie6zVIy1-q7fTa}{?BGBCgr>52{F-z(^O^X-=IE>yNYP?Peeg9_6B z_yo3^0ym8C7vUXmx-TD2b>ywvC~;OD9~rdSXQw}_!$e2oli|Bk!5{nj!WhDT@7q;v z_*^b9pJFmfh=(29z;@tHd^K=Etw7n<`H_~jttTY^E|Yoi{D8C0i^2cqABh=^b+Bvx z{oI$PyXMg`bgx|+8|P(tgY4O{?^EdLX3qrKY`&2{>l$+XL);|$lkfqH0R%)ES zf4u@vVF8-Kzy##S+xr^^pR5g2_)y^_aNi-AlnDx?MB6qwfT6v>@@~=AZ_Jp|D_=I{ z*UIxrT{i>9VHmieCJo>O(6YhhrzQzosf%e{1fi9nQ4x0GX%aG%aEXG=#wQX4xtgfI zF;X!Kn4GmEOm58+8-cMZ#IBZS;fYoDdjLR*q(hjp+78YwRu<6hkf4#{{*{TYumqL6RWeba^nxNFk_j`w zjDj%Lyt1JeJbB>V6%ur`taPz_eik<{%v`?f(0Ex!d<Ymz^|8S zYIQM%HsHDjfl?d*BuuCq^KZO%fE1-f-SW=vrkr{n=e`5N)Xzvj3A-!rtnwpXvUid$ zx$%BTl{yn#=Xcex&@|D(|IBm_?y9XqejIuEF*oE5UN5a0q{_=_>_5Lq`_aWYtH^)` zn=nQaegLzsoV*`G7PQ-Ap{*2xm@r!%|p^}o27y$5EZ5hoc}`tVOTz*XhNH^-%|6+id+ zN>ud}oWP@{C#X%6?vu~z;iO=^SL4gI1JTuA;NgIaKO=*`#8R^Us^%Pz5s}EEX444k zCAUCeb1Joyz&e0%D3ps#4K-ANqeX*Tf_W4vfrVIV8pi1_=_}=kC(YVpkH0rE{L+yT z8J2s2D>_SWEq6&{U7)yCUq*x)weXp|<3IOD-MHMwXFC>_OO)FRPL)_T zbBL*aio{xJTEwWs&J-yTY|J~nM2p!$(ze=Nr$08rC0iS)3>DWRlK7tdkA8+svl~ML z;hvAA^&Op0FK~YCU>YR0!my4s&*v4cBnfVJ;t*<;>JXO`vUSo$mg2JPzczRB#%g*< zCI#vs+{^(sFh*lcW`{cZKE#wU`^_+z<$;q^J!7X|A~f=&Rq38L2HzZ&f&V!G^Ex*eLiuS;;zh$dg>bHN=I@K4^R1Fbnw{1Q#YN>jL;B^ItTQOab z=Zh=)&Yy?-c_~NpTYH6fAeN1wTcJhj9q9Zy0K8Q1UbT>74t(A`UHSN)kWynf|~MQmvDZ%?1kLS5z;O)A|pWPnIjKr?VQ>DfX*ES8uKdjqGG# z-OZ~RF3}Zbp`e83cRt=Uu=3X&&-Fx+rO!wP@t1 zUEl9tCvo~cQwcvp4_pyuLE{RL9pkg?bnH@lqy0Ko(DBQXON_9gs(o|j?|}ubHO6zLMJD~!m-NwJ+_o(k%YDhs?@Rk*s+}0X zuA%khv%+j4Up#Fxof8bw4U;RAT@vud9X}D1WbtZTBNH4SUvEc}`dIJJaLya%!EPvT+5CV^I0p zFD?@zTeY-HWm99T6Dv*)Y-1n%$ai4Z`P(h`W!{@;vJv-u5f3e<3SWb&HL@wY_IJZv z>M-67bQJqL;b#lJ6CCxOinPzx?zK5n%+A9u$w)xGeID%mPuHNH=9FC?VoXK8xfpI* zu3}^1^)q?++p|7wAy@pyfl>t_8qB=I?D7WgchvFu1(lG)=6=c69%whs6YBULO(Np7 ziqh)jbH2z_8wz3t7r9S(g1L`Bu;VqvjzCiJu_kJB*(L zi_DA%jwQq0F$>t9PST@WCE?>+1!}SCm=@^q(>~5xke<`K2c84eCE@v>C=ZiD@%Hao zDny<%K-9{#&DbR?6M%46a*)ntq;AM<+f-Dszpc+d74qc)K=jOi;_x=fKMo&~dxILk zY~Dsm>QVoM>{$CcDCSOv;eugc>E*MS z@U>9-SGt^a>R4%@}$uB+*0cLJ`n(}X!!N<^~3y{$04}UJ~FDSehUVi6vs(DQx zxMF=pxv&g5Vy3=4m7NxN^a7_ z;UmSN*6C%P06*+`p5)))>%#z~q9)9?Zjm*r5igqi}nXHzph}az^-jU6I9fi1`$) z;M^PBz}Dp+dy*3bMN2pWw$47p&g|uwj%%FS&l`(K_cTkL-XKpy!;I#2eniN}%53kn zeu2WyL0gKk4PqMeLF!ZV8gFk159%ggmv+g+m2wb?b#H7Vt}#!*0zv@t1`+<(OkWA( z@Flu&NKS`p2pa|R-8!-3ezh(RpI!Zg!5olhez3rK;ySH*6H8he{hep;=0F00*K6T% zwE5NVQTZECAX0gK4;RWQ^!}Yt5Zkk7{Y$;Di>);AN0`HDO*I?0|0mNm5!ve_joPOg z2Kzor{rIsviJQ__prnjPzNqA}C{2~o_*F=pYrBVp>+5X<4J;s@+tNQ`@!J3JthJ(W zaiL`W@*!Q4>i*w^_`?(UFna=7fHa-~tZ7NkAfd*e*r6h`dGPKVUgk{E;H1{(NkhLsC^&g}u(AJ>7tCM= zk!+9Ey!35woa@D)GuKBc!xUaf zQSl9zVR;d^5HZMJbiUST{f3nVett!VNIMW^VC)0PIBJKs*u2UdWkx=k2vcQRh@Xei zadE7IqJlDUv${Q|Tmv_Cc*N z&a*(1YcNnoNLY@*Hl83%BBtUyVlRLMB}hgQN>;H}+5dP#6HZ$jXDrbLeU?kp)TSUhL!Pi_f!hMXzIl7=yE-P8Q$aVdW52A9xOJOC&I^bg|VLsQ<)5T~DiLMvpyZTZ^roZO%!66pr& z(|OBb{4O=Ej$$pk8zc#R<;Ld#6JGN+=k9(|TqD(r-bM@ZnQqf>upaUg#10%cbyRyYz+EbW&qkf^KoisDl{manl*$z zNd`}@f(bP00t~q_dBbjH7KKcVu33`tc71Bp9*pCN0lHGKen;3ar+;8&vm~=oIiNtl z{A4Z0=FOY=(MkL%IpWZgR{>qU5CKl80R8pEF%g! zhw-aYHbH9z&_Hd>a-Tp}-{;Qr#Xmgpq{oV8 ztaU{MRVE&yB39vt1B<1*qyzDMK896Ff8XmDfYTjtS5dL;dlTM!9Lh?3E?l{Ox0%l) zF;hif!wMUKxsZ?-4tH&{fk!rLXqwmfRN|R*;FT5ib+@YPKBeO+42D=7-M9D{p`P5~ zlby3qF6mm5NOJ76L6hAlV8(%hJD(Wj;(g=jVrv!@8XrxAz6FuMiDRIu4V9>48{m|{ zD7aOIOts{wm*NpJycJMK>SM7A*bd1g9}opD9C4rQ+vH~;^K4JeROb#JKdvhsM4%Dj`=#lF!j$p@ESM-PJgss$n^x%^I(8h0b(@mKMlZy(pCSQX2Z>X z%j(Q;>qJmqAkUre?8fjb9EEFoAKFms;A~=H@E4T6p!?!bJg%$o-`Jc{NgTr4J7UsH zeg-~B(H(SO!4GvMbC!EV-}UAW_3Y^`9@kfU|90!eKB~m1fH=$oCVUhWvp8AmhB8^r z%o~Q|&bG+KK#iliOB?bQ=Rdp9g`!9P9Llopq`FUnqT?<05=uC+L$}4E-&I{X+ZpMb zIdCaLqEBz1P-DJHFaoh5{Snk#rT(H4=DqPQ=HORU3K7YCiVfK&kr+V>2^%{~h>t`y zLRbHfF$n*~l$UqQax)QXAkAn&NU&xoT(8fYTG+-Rl&}`l{Ez9OR{drl@PDSecUB!+ z(p~&I=5c9_<>SNUS^De4l?}nZWG^C+V4h02eu(j7rAecBZE+FBc6qL*zvv~~*gN#>F!Qnsd~iwg?0}hqVciT}ZT7P$ za`K+~M>z?`p#vG49S*nmi_!Iy>AYWVFJE9?X?Knm7HS*gM(V=@}w3ShhI3(me5>4R-bK&j@v-=;VFW920yWefgt17BUJ{lQ2L zcuN4%f04QnJYIdO@*sJwG-#Oeo!^-^E%@BEQ6GZ$6;>~qRe{@&riF$-yyb5DXdylR zd)l7Is(+ePPzbnYzyk4c$XDIeuc;mEo{iEsw0IWx9Sh`t*QC3(EPCR>twXh~yoUEs zp)CZYanRmfv7W0NU8Ct#Ky^ET)u0bdoh(;tQ?7$pXJkDtGQN5SQWW77TGDWlU@B593V4v0>BdI){1A_h zM#g59?uQ?zl9G7=qLFX*+){-mhX&MINO38JB61AWCJIm`qSF;1*G7RXhynelW+3Nx zDq=dZU;ohW)%;&eb^@L+)z|htuF7q1JYPTkx5rNAJ|+GsADg=my1nN0sX`a()W3)) z@-shU)9btYVLaLjURo5=PA8tWUyO+xEk<)!JigH{v)>rWE+{Gnvd?R72g z&A)L9zKP3%UNPmI)QjBv}@epKX?9uvl5&6*FvrFh`&9XG>g7$n|Hc&Br{; z82=#Yv)B^(kk5z1P7YKxID0Ys$}ykJ>%A=o`Q5~`ul>o4BclDnB-{0UrN{($I7>`l zWG_Q0XT*k1v3ZVk*GOM^w`sgccm+Tg5$Yit`tPb^^v<|j`A=e`=7I8O;6-5RQF>M(;AvV<7cAsZ=zrLJBV z4hL*rJxgE17VU!%B0@V!b0Nvp&N2*{w1aI}b|kn6R;q<8Fc^uP=t*h@#EG1#PHI&d zo3FDLv|DgDDy@+>&C7>-V_@u6ACQCngjMG8&$z`pMA$uY`zpVoBI2W#PjN=z8Azdp z7hl&?-foStLXPjov8k3&x4$Kp)Tj?mogHQg#$fUZ`Ab6SuA6;vmJ_^0I2s@zKR-;G z?4f$u4K_Pb_4uTQp}d+KwvWXUF3C^XP?NPjq7^6GE&uVx;Y`F5R~TbUvyxU{IzJE8k|IHrO~eGz63&xWXATqhqQYHy;pyoNylQz}j` zGp#^Ze?2IB07K(FD`Swdy|-E^Enh`W4m|vwH7p*+oJ3(~6wtVu-*sCdxHkFVm&|4p z{p%_cCp%s_RA@A=;^pmc5^oqxka=dVowUDWCmBOmVi7_=M+QgP>gWNUYU_oqCE3eE z7*`hmL#KGuV6c1bd_>{pkiFeBi?eI{j_|U5)tJ%&3bTN;+CNiiT{}WJvdaSJiH4ZM z5WNf6{1jw&`Yrz3kSDV(_v~huX5uC&fB$%XAkMuRekCHCk9>UD8Py!%>EFLtJl=@QoR* zVK6n7gI!%NMT=9~$g~>$|GKD=Gaq;e>P4`AO}&rmA=Zb%xGE$ar?tze@| z+fm$CduM(4Z6V5m8OP!B1E@X$?N0vuQnFiphcc%>4OQ3P9UB~HItBzmkWWm_M0-4kLIsD{Z4}yR~w0de|Z_^K= zMjn_Wj2#(1wuZ8sCYF;5fhv|5O~LXZ329lGuS}F4lm8YJ_-5G`>ro4es8UpkfBtmN z!a%3}+ui&vgg_lHdLN7_i(y9_RtGacp#EZDRyrf#W?b{!56!eT7trBwU&@Zw%tDHB4o5PDUPN=dZ0)Pk21M?unAzM z9zH}B(Z1)haOY8|!X`thy#upPtR3WO+bxrnOiVgPFa41@A3gn%2T6h*OeeEziyGWO z9IC=z1HuBFvf&yAhHWHPB)Uu*se&BvdH}T8m=vu`(e-r{@%pId(I?ty(zA{ic`Y#- z*1%)g?ol3Vs3tDdevm@J_c5ET!mDdPu|%>~nFMG$242oUSG}^%1D^etm_@tIp zT_DhliohBQ`UwFR=2GccrjT4sOkzYWc^!!)9CbQU0hR{ays-(;Eby}IpQ+Ob!{J|= z;WsI`WEoy_-@pM^+7jrX9A3;@%Dy&yr%wDiZE1ZAPjLiE!lgVPY zxxNWvSc-RkCbAbHswA5BHM#2PHgb(XOpp;L_l}Ln09sj<>A2<7FhT_KYuAA_BL_w1 zAnPu{i1qYDb%js$U@;w(r91GFI$>_t2+vn}_LJYX$CVuSQN!=nW$2#=$yYtbA{j1E z^G5ggeC(7>cquv0wL0khKA?hyb1Zd1>1W4N2j7*$0XLh4%F!_ z`-F-M3+HKylb~0WUe*nC!1gy3WDixK*qW&-xZ;zmETgl;;g^0?K$3KgWnl4lT9Se1 z*-l5t@VUvFoHGE61FdxzU7duqS_4g}mWtJlx z=OhDqGI*Cvpmn0NyfP3fBo965)ZYur=rQy9<||w^VMh9VG%&` zRrINSm;3a47|bs(c%-!My1;ghoye8ofB6j~*KPcB193m`&9V%+r(hy5uv%8>&|WG_ z>8CGDF4#UDzSrR?8<;Afwm${+A`SDVh7R2WB1iH%rW_RU8F426W2XpA(>y74Yv0)t?iRd;A@NiKUisq(b)o?DGpoXc0 ze3)JNv6_~4N37WY!#IHWu_~`a|M75;Tl0HbI$S#Mk`HWD4(5(P-s>VY_;O9ff(s2h z5L;9pXZ!{0s~pQ$1hT%^XHn z^5JzFr~0){TGBuk20M0hU@L5QF!q^mCHm2oMdTNI{#eBH(dNou+gZOvV$sclhvqgI z%$>_3ptS9AE8x;Q)UFVa0l!SOvjZ===+`D_@^F3-0IbbkAIn1Fxwtt}c9gMX!*H|p${Zpi1m4~#&31|rd!lvHwLA?d8a-MkulO7IF#hTS1G}8z#-6-FeZ$Qse-!MdoY=`O)msDu# z=0U4YAzGegTCNmT|hU zXzPzjT6FPJ{k9_wypT$pwEG`PFbY>ddsARa(`r~pgfESGzO9?^N<|=Por7q*=NtwL zFLI8{n`ni8^J?p^O27%ZKY;aZzP=-j*IdBdJfp;Gn8{~>{dur-Zs4& zym?Z(uWW=0zjOCkb7tR6gblA4-(<3s(l|~OVHz`Ofa<#S&cnp9MWvGY#$MaPipK^5 z0N$wXI-07#Bab58yY#;OdXYxZf^AjzD&!fUQJA-@+8>;e3?qr^*U%>!dRS9Bj3@o} z+fs@$-iVv#rCb#S$maly!RWykToy9h@T6RCE&?#qBBQh8E6%xgF%UU~ei7?%wJWoS&HQXhCc= zd^u7~+I$H5&QZ3fFe6@ESR?ns3-G+y40uet5<3}%4kI8cH;PfjbK~RIULoD>D}{@m zPp}2X2s~zt-?AQ1JX=$wyY`NSLjrritOpsQog3NfXF|B)Rq8p2nN)1w5(pSj)xZ$| zbhK=)NIW>Ye+|y^BoIFsa5B^JbC%9vIhljO|cX1P?+5jI$`LBOb*xr{sb-gslyu69_W>3cy!-wD5h9$oNfOd_`RxQ0M72iMJ6mu_d#rEMc@L50BqZFkHcbF?HLALgNfN`=SYUrT#9f8H$R#SpkWFhp|bFr{*;lG~ndQ z{L@45D^I4={A<-=7*^W3h?=4tQ;+%WO9vFvpW17oU8zVkrGu4PBBY)qHZXY#IK(4K z8*6?0QWa+~HDvB93vOva5h0?1iQNFLE5153QD;K90@fQQR5(tTH>Xik?ZYbJ0GWl}@^Y%4RwM#3 zP~d_hU|1^<22hy)j5LtQ5i_zia7{}oVadS(+ra3skJ{?z2sF{mbSBi&-i`VJrqXT$~CP&G_@K&QUpk;$vy(tn3SyJNrm=}@pPY1VSYPd>}7!@&}3sv=Y7wmuF$Rc3T8g4To5(YBu@d{muPA2%*>>F>VaTC*=FO zu_*sP!dWjYEjvds-rFrt;e*Y9yQ$bym@lOp;A&iTZ7%x$P3E6C??Bck*YhNo+iyQ$ zBmj!4BQ`=|L6^GO3YC{cLajY>f0rn;)@aj!k_xj{Czvb>+*l`l(r?MYWl#I|!vEUt zcc`7m%t>s3cD$8;;ikX3HVj6OCyShxo4oh*X7k;N65iWO5%lqEfw)$A!liyB&Gsl` ztOI~I?)+prc)pOp}xg5xR}OCPk~z$hEdwOl5=ygitx%EN7a(dZ_j zy=i7p_>hbSk(}Z0Ea8H|XczY4$Z4IG@yr!5@E4Z^Y2vEOTekhB5bGk`U4Lm=OZ78EGl|QG<(t02+>Q2qbnw zErs9K)@nI6-~c*bpL2LLBHxwBGl@uq4WoZgkVkl@whN=&scIc1m~(LSeqBhbH>#(r zLlwH8Nm66_I^U}SVfH=>R=miEL$J$J)MvV0=*z90WpW4viBwk!bu6BycoU4eWYEd% z4$85NK$ni6skcbv4jBzY5TIUXwm!2clKo%<+yEK&>8b{S>Tk}Dc^++hIR(1`CCFEz z9jle+Q{F3zSfS%1_MgqOlAHu@#HB&&0E9SM`h5H*9_rL2_$>L}{pEzni9J%Nm#rww zQCdCAc&2Iis=!Y)l4b>G4GX&_*xVmC9NTg75wzrV(fu^RiF(kJV-LHTe?9%0)kGkI zj^5-6oT(0~VcbnC(9xFO%(0osL92^~n9PgNSsp~tiHZ%J7KB{RFv=IW7h=%ytA>09 z6#}r}4028o;&KpiVe(pLLIabXzS=+II3I}qUTu{n^-gJeI@~i5%1SgjU+cU}LRuAk zKB5C2Drh8=WiNZVxi1xA5M2X@|Blb`{+idZdaS;=p^PXLq|2PQcyX2H6=7pee@$&$ z&-UQI5#DIH)33ri_H*%0#19>9u#7#S7`j!G^@o)Z&V)Y|$10 zuV?gyQB-*H?N|L*2m7kTx^5f^ikrJYD%PMIUxq*<~u~~uzel-E4N>@(x_c$p=JAj)L z7dEcMyfEb@R__aNzRzoT_h%=){Rt5hTDPOV`MIctGKIWfp2o|IV3QKY_82{mPYWh| z*=L(0tcpTUAtgmZ^X>lUK|}41qrVmm#><0KiV?%5Xlyr5dotXi-7R^tE&#{5YPrk_ z9w0$O1uK06lJJ&q;MEv9UuMhDY^p{;qY-Iy;fQH%VED$Ou~HUY+UF~BQj`d|YReSX z$3N?ACZ`Cz_5O@oTi1iHuYjFSoK&Vy6BWrXB)3}{W!%e<`Sh?O1e(vp3><4<4*@CS zCGn{RwD5D6Sy9~IeYWeE!fly#75f^j6$?6O$s%V_N8l^ewM`@bSPPhtZ7Qz$+(34o z)`##&S1d6ROmNYif9?c)V(9(W(d5MYU=)HtVZ%kzS)&|Ou_@G~`vn-fyB8D(Ed0BDz!GSWPn z8cC#$M~LO#_5>!SlYpwMTp0T)7~01n{(1i28BR3AEv$QHtLlV24x79Kqu9fX0l=u*S6&dScbrm z2Jdd09KrRw(YIg>?A{$BupTaio(DJES3u0MiK2PSC_trym@13N>!0Y@^c|@)dpFLn zNmm>Wk~gPrIKRN&B|FidnS@8g6=Qe4FIRIKT@HFe?dvFdw>xpo_}|D!hX>3LXxjQc$%yL?_zfO0!zj#iY@7xW93tnG1M2MX5at@@^i59Cl2?T zaK$Hcvgm)3dvdtng#4DtIrXVS`be-6eTT3nLm~y5Yp>0DoWp2Ike-7O$Ypc0L!Ajm z2Sx20JYh$t5buY~EBmH8)4^$mVDT~rCus8pbivm2yp3|ypjRLK$ZJ=xZ;Y3I*kv-J z$F!D;%&=g^w0s`)sxSnKAd^~uv02b!?ELR9dm3%5|FC;-3y;APNC}_u0FN8_7+4|F z52YqA%RH%uS+43kVEb}el;Cz!y*%bca>7KlmQKY!hps{7MfG5Nv}&u;A@$S4`4;Y;ji7nH~j)mI>@8uSKy=z%yl;vgz zH$K$#uhlu(=`B+r$Z>E9;$}nfC+7k#mfh!tRQx(mH1X96YcfaavGG;F7!%bUjyK8F zlr_^+;QKxeOC7i(>%SX+P)gASsy!5=1y_?|V(8aDC<$RM0epte3qnbn`>Ur6&JbI< zJyu~%%pL^TNW8}TXLbHQBz)2x6!Nggw!5`NFr{u4GzoUgK%(4xIG6>EWzGmO211`r zn4dnK6;iUhN0xQAXsUZXlKab%ZpRZ7cDkUMD3=SflVau}I>T(5dM;+l==~UZRO92u z2M!M2HQ}f$S8}KORqe3%dYSOnqrJl-forepnU1%77D6le{|0eaVPr;OG=d8A=d%sZ zVM+4~Q$;c|4Qz8Z0vf?PBox?{R%mj^D1s)^+B1#u)+xW$rzy+R)4EM=IsmZ@LL30e zn#jplRhj&a7$T z?6MfTG;hslzwUD!eNfc+%zJtE_-6p@4k1HEUr6>LhkBGAS}l#HJP%lHh^vnl;Nq2CjQ{1)Guws@BzA4=&H1uO7qdZ`t3SC=xh#06av3G&K+>O9FLVEMnWp;RUcjp>K^qoqr>u z<3KhAGNvdZCaFw3D7r6uJ#$L2QASlXDvJX+FeseSvxV|)SF-CtWO4n#%Id3CQw;OZ z|7O7h19U=cjM`{-#Dl|f;onZJV+tRKNVe}Qc*eq(1Za@9o<8(A4bK-t3Y5a7l8aRc z(5lR#O-Pc{`7|V@r3uULhQN6#TUbJcoR=3$K*n6jq)CWG!Gd0(m77n32O1_OmmK$- z3{C3<4!*uc9Rh8`(4|%3m0QWA)CKgO)PgFdv4J=R1k3%tI7Xm~sPHKAHRFj07clXP zRZJPQ34uO-%bJ{=5>-vJ5E~?Z0x|B`s7!?z=J?>+-fA;VxZMBF7oD?FjZ>8UQ+KG*kLDmE* z7*y!aTA0K*GVraAdYSb*d}YvTXR|K7^KVn50sw(0ihLE&fxJB4%1buSe>s*rPO<+7 z{QG& zE{uGzwt9fO>YD7&cn<5(T=8q28?ESn+WGb5)utJf`(m2t9o?mg;HMYaC`4`VkN^y{ zr=Dt8O5p{9-@*H~WEoT5&yWXz!_dK8gZE|8;V-S0OvU3#dhS3$x^JmyGmMc$KnAcz z&~luZCibHnbsX^^QKsB*lR?1>!DA@j9+sj=EDl?LGk`Oib5IkJIl*m_^O<<+$%31skAz;C`zdO01==U`@6sQ z_vE)iNH4uz&iz=nZp@Q?#xCr_Jd-ncr?lv!S0+9wUgcSVuud#4l?KG3??3GJZG9?v z%jDVe)7ZO2nKYAC3Ulw^;~kh1#(0NE(gu_2`T*(X!v9oi_{Y=%4G=|}%h6Rrj7u4Y z`btu&B?2S`401@_kc&>Pu4ID8RP8c$I5xgOf2?-ev_Sq|{#V+ByoGT}|TyXU010&pTPGB%OX3$2ZV#R?yWU4)zub0;?`nCr z361)^$Jv_pER5-Z=@<|RKA6B2Ar;jP_qJAG_*tjvV_qiZfz2~VI`19B5N_fST(_Sw(~DX4lF2u z2&~tel;{V*9O}yU5s2yj6ufb=w3Q$Xp^?zlB|LNL zdVhvd!jN%a0qYy8k#>q8G;VPEFLTSvacmtlF|N0SZ7N0_mZq$DuHMu5o#nT=+dp+_ z;)XZc?%IWdOx|P^>tobi>%1%6?9dC2WVGqeVq>lokHG|=CL%a{h2zSNF;mx4ld*Ns z4RwLZgvd>dMyhfdgTpS0-}h~KzS%M+AzwjVJ^Y*0}+0{eqk_Bn2`sX$zB3Te3Ms z%|;u$8;L>PU^4P@O6F~J(1>Uc(N;M#xC36PdW+bc)%V2Cp_jkdJJO7nE%`;Z;vcvc z_knm}@we+{%j)Y+hC4;ghEvi~m*o`QfVno1wPCTKyKJP}w+{JS!hfTlZn4#33yL9YmC9{Uf_JA)lv&syhV23CM}W=QCLRB z_3I@2m=TBpnI=H=p~~XCtY=LrYHh*LjlcQUWinJr#ngzzS%&>o)FcZ0cH&nd_wJv* zaK6)ze4hU1ZDNDe+M=E0p6jdyqAq}nt*MXLklYVbN@w(cdP%s~(dqcOu0LpGT>wMT zXXu6pMIQJFm*8KRP}WXsF|ERCa{znIW#gISich(>L*JK#8h^jf+|TUY1RGq5Z`KWt~qLym6!0<3D2JT6pm)Bd-Ld-*>UaxW9k1Z!`Fbszw)qw-l&M|Z8S=e`4# z0xFZMUORO+KEcy7&_z@Qeb=`%Qu2~#AHBi6Y*lcswqmIQEJSl?aCE6=uOiL-5G1p%){SGYq2u(eVaZ40t z(jm(x9!s3Z@R(2~)aP+*Q8%vI#p}g~Zcqv2Qgt)%?T#;>gJFJ;0?z?sl91k&^R>QjWX@h0c_=;{Z|hPKBlhcRLA8PLxLD`BnMZBx*) zw~EwT{j)E9?c-4Dl=%1-%T1?0O}H{EegU(HZm3M--@?or|JI>|$1{yagvT9XiDBMu z#=|QE(4t;xP3Zc?a1a$~OKFiTB!7@dw`}A>I76A63*|ZD+CHZ?@0CgMpE`t`cIhk< z6Vqlr!kmPPa*u*|hZen=U^-XrC5KDMVHwXbXxenyoW?4N`Q(bc`K~Igj@tqCezDfG z#MAy%MB+_BD$uox$~dd3FHzk(aIhz`h>3H;^=IH``7PLO5N==vYUPi#OKz;*ai#bj z4$W{Z%)TJxOeo%Lt>yh{;Lm-qe{&$LxN~jtye&{ zdorne_h+@{afea*-2{7g0PKi*Vg$?b(sFb0N>zCWE#w>JwN91SV(lSYvz5kS%6?0H zfM>=M+Oxkrq=Kx~BZW=f%lhQg*}MS(4d2w+7pL$kfgAbLmtr5q!9{x{2+cpQA6(S~ z@awr96cT+F>`r^;_}S%FF@&lEag*czd78j1!Zn}&(MBn`#XIOd>j?x+o3G_B#W~zv zC(6vQ3n4;d+|bX|6Vp|~@W^3nV5cKfLK1mI9ybIB^Ud}uMLnW4q=5Sm#E%x|Uq3BBzgWpJ6TE*SJsGc+ zt9roDCB85!{PyI51|m>kKR=}IW6*|ZfEQ@=FdKP&{e_+{xUd|Ovg^}&VP1v)25epp z=u)EgPs~h*(DCW^jmCBXjM=Ls! z!JvY>+8#ik1-M+C_Zk$Xs>VIzbm$wtd{Jo3*oBN8!6c*64jC;azeUDl$Av0ojxf>L zfrnD>G5@Txjbu{=X+t4We={8z@4Vzx4dPD%-}b2&ng0ooSqfN1Wmn z$YuEJryN0eZeC8#gqzkmR)}9*>!vLnt866Ac~5_x<&jUj;q*2(rY1yrjgvC(g%3W; z4m+cV3~4yq)1u|c?3>kRfDgo`$<-octW)dL8iuQ^kLuH~ZGg}O$lG^JzsW$`@DEKb z9x^E&9ZvNVUV6JglopufUh0PozBC1_yv?nch5NhH{C0+6^{&K?pKv70B+bxa7d&1A zo>=ev{Iw8m_iMCZL+@a|wnWvn^n}f_iHIG*U=Bk>V6n+6Um%N7N7e?)YEoKa=jkyj zrj;|tykje5Et_nIJZ}ahs^`rPr5@5AZ7z<(1>zvC^3&V!O4Tfc-k_$|Ne;_7C}<8<`q`nnw=x040Wk_4Xu z!`)qvWP^RY=ec?r*1@S~xc?u{hx=&+ZYc0OZ@nB~7ct0J;|6k%t+y7mBpd33+fX?; z?QK0D%+hhtD$(`RoPbL>-(!KkW-XXpe*W0;>reO(i{5X@C-WxM%;YF$j)AfI)^fUulir4wMESo1fO7-XWpU6A z%y>Qj7bNlIfM2ieb%W+J;BRLqI#OCWTYRi@d24tL6j$D5VXW(>-)3K_X;d3K6gwEP z!L|2>g1l*}yqNZ)#dWBHT~jOa6J>Q5p=d|0f>Fl6!k>(@d~7B)5p<_-G7g#E1Ii{Y zY&=K*ACa60YZW9vBd(eKlxeoDp4Y^iv^XfBgN37Uv5R086NUM=%arghB*M&wf63KQERXkp@PEemZF~lYAMe z_W*lS0Y&d*ZD}{Zf3;^+%KJo;Rxe$z`UpJx-tmLCBFaVV;Tt~6F}tLqhjA%>>5@NR ztyqV4EJ1t$0Ji^y1^Lae|CqQU=8v8iwraRLK z-c;|#WB1u^?tTb3cpz+0JGc=>C_Z_#i^J%+rUE{0elPb1?|pKixfX}~)o zV6fpYYyJ8hU;6#t%=m?3#z#TYD5cNN>y5t45Mxp;H`>1zV?k$o@;NB7(WZ-kLWRKe zKp~zX1q84FDw~hTS#^Z6=}_mNSzF0ReN6Aq2SNYgFLCcntytF7plr zQ?ivlb%D*b?5pbvh&B_Ir~cJhc@XA_yTPAWM#Lp_vOHxLr*7NKaAf0!Hk;7~oCGE^ z(aF&nyr^;qp?Wt3Mk^^HEjb@MI7q+Oc@v_AZ;ug~Z91)ZCeey0UeO~VvUB7;?%*O( zQpo+1ia2e4k$6ezHAb&bQ16w8R&(*{Cr>Fb7Kl~}N zWih|hOX-=H6o9Qdina&omv!0~Q{8sY21^Ssy9pMqZ5p-?7RY|&fBtw_EO%IQD6Rig zbGBM`*(At*yg)cVE?{8sKXiePOvueg00@Ym)XZ`g;A9C>L{iVqXQKL9Kv`fRDB&Y7;*CN|1YQ9i@XtHFQ?n#Pb5@xfiSjE z{vayU!M{aJ3><};ad%kzQ9R6Pe32y6@z}qLFxI^Vr z8(ck)d~QdC)6#+SFp>9Lt#y>Dsy%$#54J~EJGi}4HEo1Rzh<+(- zl&=;M1rhBZv@e=wTDw3Pw4E?o=jhPaq6&9vpV`(g?mypR0F@8z8OI(C)dMoi!Y zrf8+w_XGv}Ht(TA!ox+0C#537MB`~%5kp1A+`yO_m`Z^H2jAo5N{dKu6jSvsCpRQr z^<9z6#g%UJf__(&C^wK10c10cM;cJJuz1DIUm%Bvm{=;%VH!w21K7hYid?kuu31Jh zwEKck3muBAPavj8kxca?^Efd?qbdP0Tw>+89`W0b9s{o7`WN3K0gcVLQsi15+IZW* z$8Uo3V2{ZvCX1ZXwm&{1Fa3JB${#uJ1mS0t#&%V_yRxBga9pcZSy!D`SW-qtJZV>u zdJ~+Gb)ML>jwN7@7!D7x1wZkD2{HE5L!Z9E$uwFwpfKkKb16?GA(!T%Cb}Mi6D)%% zXN29=s|XZC7Q54dS5x^*mP85Nfa?}c$9KBk>A?%X>WmbkB)D==`fLu5@*@IVf)2_EmwY=a6{ zZsX&T4g*oS-+DcWCjE>@EiLP8os&VBQ8m<0)8I=U@lJ$xUvrvvaMIk%7s&gEVLo>~ znDgj`{v^fWN3#(|6D;p29HItDf9W{q0-UNyy?^Mwg z_|7xnT~$;X$P5P?d61bDf`~2&KOWmYA@2{`TjHrjZI7<2&rYfy|5Rm5Pw#gLFM9W^ z|38O1FEW&=GiTZq5H z(BW{(RJS{dGN!VMfXokzn7>{0WNIdv)dyow$|liDTgWj>xs-k@{r@cNCZ#HMH_*rw z3DI)ygdc5HK0fGpJ!*nIZ$lWWBBM@$Jf%geD04KcdXHo=&pcmmK+8EcrTO6?=Og_T zDL8T92|lggNZ^UMhp=P{h0gxz*1xgAx0Cy$djPhTzTwAZXpjcFvr_-f2T?iP1l+jM zZ9_Jb_#oS{usc$uX8;*7L0*-TMSCkhSbf+9&I~~DFR{x*MyZ<@;JMN>3Nc3tf+IG9 z;D}mym6d-VvMc1c%VXcGuQl&S=dvEP8_XXuLe%*FZ_Z=QpyEx3YbTS8rZy^9b7to= z!gbatPyaAi%rp;#X4g1ZuQ4wuUy8NXTG_j8_-?xdo1sE-Ooi{1_Cv5>2>^<5Nve_< zn?OIEjvx6h?Q^+ZzFQaQbmyGU>IL5I!Nd}we{-DR)`e|}J8tDH?)Y;4wFwzAp7sz&^KBv?0d0Je*OdH1__@Nrw9L#Q{V<8aC?d48P#S?MdSaQ7$=Sld ztHd$u#Ak}8@9(djTG&4LN~%USzMC0$ru<7;xe528NW_-&Lv6Y~W_1dvU>p^=x#q~( zs%;S@ouh7rbI5&-UXgUbANY9>v=3z80!`y{esI%UgY4d|EUR8uw0Y>GJK1~FUu@Ul zP}UPG{J0APLL9RDg6nDYKNmA2ypmWWOKRuB#F3^%?ttJA*%(%4h$)jqS&~?K3LQKh ze(OOuayAMif(=*{*ij*y7C%>dnAe{aZ_xLEfoQ&;?x!pb9|cUWq^=+|I3yVu2`LSx%DqV(O(YDWeh zDip{8>A8$eI4f{`L@~q_^u-EbUo>7A z{3^h2JiUjLhK6X+-lO$a!e*8ENTF}6M}r6LBT$8cP>vspyg9>`vja=)Y2S;~9`G2-RAO1MvP2#N5*4i1bxTSEZ})G7GMpFR?fM zlw_`?I%&YCIE%?z1CzNyPeQYxP27wi)^Y@gh3=W}_qUZN`K#pz9mV z$ls^!xrmUXX5R>8njbNMW<;-I*TNzh!c4Hd26WgfHbkEm-CG9=fq7x=0hHQ{R(1aY zvJZdY=x5T^4ZNb1$|w234oX0#uZcQ(yURxF{ZeGXPfTb#y<09cqr%+t76^xPtJD_h zUwJh#oh$RpB)9KzDy(sw;Ju@7gE|_fN1lMK@VvS5N-nUo;F|a~7SfrJFx|cA&=9I4t z>yV{;2-_c5^FQG0dc?L@b5-drY6BMq?=@pCb-!q-^u6XD5;RU?O;q0<7u+jcNjQYV zrG-c>uE#*N%U_ugNfhFHlJBP05Sr&D@;hH&m5Q6M?&#O6tA|zH zg0_AA$$LA2tT!sCN(%?zY;;zMK6Ytkycl^%z6@J1Mc1>oH4cGeyHI~H+^2L)3B0^m z_178eo%nhB$r29+aK9PmaPyW{y^9h1FsEb6eRonIn$hI+5o$X0qxtXw% zxZ9$~{+3!86*cd)XG$#oC$a9g&oqd=pe#K~jFGkiM2Av~h9?*!Y=0Qi+ZVq+uD_mL z`%~QH4YB(Dwbduh7hm>!0gdJ^i$h1Pd&c=Bb&_zkBh^PwV zcc;%Kx=9Ao$V(>=$Z;pf?Wb{+%$Jf&Sl2JENk9FZbNC+da_%NA|!Juj8&@?_|4pWIK#nUZxry69gq+mHkC z%kNmGfmGDa`I28B>4KJjHL072=?FKfzNsU++TIM9&IkVTo&Dx85Zg4JkNRn+QPnYA~l`MWfP{%}H?iZiDfNg#>}NNhZ(@=gNEg#aIM$(kJn z=*t257BO_PJZw*CH<{H5ZjjjkOHA{8@Q$Up$qMOn(mM2MqCTN~NI&xFnJHx+mT zoRGPX*;!hy#~8RbufsdlJM?~Yrlr)TeeG-29LVQ4Il`TNHN1cqn>cdf&?tUn)#RjV ztUGI>4lObOt4&vw*!|_7Vl`jskA&Gm{zPaDK)V24CzZ-Ar3XOXUWb&Fy&R(3SwBdK)%e?9FxupK_1OLfhj8UyPV@e@e0l?HlVp-2wLFk2+iginz4 ziJF-}x3n9BAA_DMQwX^Eu|GS$15WF74GR?zDGz?M2lENYE=N#LwF9c-epdEJJ&iB< zo|n$P!IDtXeGqKsRO*xo^(5@6XFxr6@8Zj0qJ;6!_MYF@sC?i-GqU#BBjwat-*(pQ ze`?Ztc2V51VyLGGhJ*n?27grG!;{yvb`>HOjI|oBBvVB`bJ@l~H?{h2=+e~xlZIh5 z7qqmQ+4GoXn0~=!;?i;Nw@jTp-_*YncQ}%m&J9BNOdcI;oZI-OIjWt67kq9WP&`$1 zzP6Zc*FWvcvDjYQ1Whwwr*-+G5Q)}K7VW4jn%8$In3mq|&a|;0G59zxRY$OTG{}9z zs0cZTQqx?EQy2v%PS7)Tn~jhK!hiMty@iGg&45F^N!QJ`g^m*iAJK%ZV&50iO0;^D34JL_;2t!u!mWtT(|+adYJ1(Qo=F9cKrfil0A zF?EAZOcKd8Bnrl~D2*N$IphTg3)ZsKyRWY=WB%l~a>N5F| z8jEcI3{V?5{n6{R%(nIY!#~9BGYXue(FP~9ApC$+AnHH#kmU7jgRuIH4?X-`RXgDv zHUWFx&$-s$S<_}=&u-Or95sKbbesf6;Q;bG@pte;ilv6EPt67&kIro79a>r1%I)7k z5#0Xoy2c^Dt}S16d^^upr=Gy3Gx$<){m9>TG~cQ!O*4H#CCZVa=X(t4;s zuYLTe?di;9Rtmj#NjQ=aA;(DY1K1>LosYstzn+B5&#sN=oNZvO=`>x~|jvWWN5S6_*C!jv!nmL>O7;WU~+Z{zauv7basb!Eu z68t`Zfo2o?i7C$s=Rz=rfLzHOK24vD5Gpo_R6J0=oJ9JdD~h;U5f<5ZH${sED;W-) z!-V7=2)DCXhR@=|{jH0YAb%Xf&h6U_Q`gdYeKA$@ET!2* z@J0pr>JByHSK*zuyf1OX%sju&5aKkM9#fA_eLn$z?V51b?`Eow84)rk)tTRMTG>5i zLUJxx{iE#FDsL(VhLIeB_^m%QvZ@hgaFvf{a}3W}YZPN+Ctc=7t4%SFIuJD+S0;QS zQ#rYwg$7-@V%vIsP87>{ps&_%^|{WYCWTMI$5epd+Xm8u_RdsWk1EW@n1bjj-hTZB@YYU$@NctvmAf8J)hRCFo@;~6$U8BPH zWtqkc!%ZCL94C&^ukk@32TUxIUsT^rmbo3;=1~v;myGgF zalA;gch~(H05;IMaq#@r_NT{}`iFPz8=J?QtY6BpqU=nE81! z+EPps`v_zL>~UWVmZM`*5dEIMZg!=`A|_Oi{1q?(sRPR7C5^_?GsKTgEZW~Y$Wqnw zp!Q@>do)~&>~LZlib5uMYdrNeZkz^FID=#rCD$a~N#*3!bc#H3_*Z&r^?K?j1YJN=6x3^a+ZVxWjMTQRtb@+!m8|n6ptFPFN|c{0mhB0)>YCRq_Z)nk((mam zi@wi9@A-v6JX`s0ap)fwn#}8~$~lN!Zg5fp8egwulY&huLvvd}w;xD0FHgj8z)d$+ z#~zktL;1;~pz!v@QRZg_Oo~_}%mC;Q_ABO`L|Uxb;rPrhld4(4N^8fmgj>=usRajS zDR)kV`Je4L`*8jXv*iuOfZWVcfp+@nr%P_VpDgxWCoLBB#MEY=Iwfn$oE`uI?S24@ zzcsHXF*s0GU&FE=5gY&%GDXjNXs;=tFH8SXQ)1RgX5ULV>9>9OQt~y{JNIA|%vJ)3 zxHb-MA2~_Wu0knmPf*hmx`^<<`sgXuY{<2Np?ehhVdut=It?Befea|s3E_)K>8;=iz!w($+1)E+Su1qfge?95>2GvJJV6p&dU`2*a z(p>hO#~F_@x*NCITqQ^qP{#wt8sMN^Ow7uAwOPwihEInjrlx64KHURt+mlxriw)s( z@IPNnA~ZpH15D0(?xgy4!@JyqX_lNY|JZFaA6~L4jb9^b9U+gwDSS00p%1*Gx z3i2Cgc`ykU9&P?`ADFeVRobTO6gN_XEcP;NLO_zp192VP{#ba{qT#3;si%4bo^z9dsvNnz46!oyhTzo~JEtpnmcGVQH*T zFrE$dL|E`YNj2nDhlaf_isJkfvEp`_64Y(aLimCst|SBOzV7{rbpn z3euqpJSw_)O!v{)4u!WkWsKIjD|3FE;IEaR8sNVphAcuXJcb38HeA%7n%#6o<2PcN ztxW4L-Ta5A^g=z0LX6;>MPea=R+0C7g1%DR7Pi=uU*zM{Rb(=LEAvrv3JTe z;_nz82qnL%=di(yabk@WBgsX7*i>A`W?@Vf6b-oH@Phq7U|% zh}RVH1$vTeeL+lqbf0!uhw0rm8m1y9t#qR#MC$=BXkcCT!~X8wR$;#ZgEILZZ94hw zxXyV>k=%TXQY_LLbxU6c0kj-!Tlz0e)v!FS!ab+p5V zvptmksd(o<{p3t=9wg`Ee6`r-#(mV61i3X%KR6|!{^o+YI~}o6ShOoYPR55XYOGm3 zVqKbE`UgoZs4l(>B&*F_D{ASuV#(-2xyXgTVf*mGOtRw*E*&J}84vy0t z2H}r`V)$=C&n$rnWf^`gzFU+wHInkzLh8*_Jz30s72+)TT>z;sqtwOhFxr`E_0wcR zp=zJjWn^Ia!3lYDQ|^5e&HBj z#?>&%Nz0L5jLC%aYFEPisb(jUTHXv?iRz`ls^7P`bdd7ul~poiU9^)Lj3R9#kK?x> z>rh@EY6P#SG-@U~Sv}4_{Ab(-p4Zsu^i8WOfFVus<0I|GEl`5NJUao4BHbm?TZ;Qf zDtOC~a#K>Cm9glt^_R{K){pA2Yaplq51)ba{Q{YZk$T76ICAgZi4deRk=6 zXmH*3(S~LOjIPeNSi}CAV23(DVUJZl@O5zSGqk&@yt#pmNLvkgD}m^`kvv4P{Xhy0 z>x;wgrd3yrc*B?9g_&C%C~IvwZiZ9{jTJKg!>mzZS2g!+%We9U(k1PlZ6`Yj#HF-Z z3vb5_Jro(lxUCcev#uw6S`NRxad|j2o)pZ<`D*?>&d*8!=G5~2=lCO-=l%DL z1NF0UC;{yVo-YK%3%T8AM0%w~>fMO8S$mFPV&#X@m%%L7&p$cXy&{XS!wB-rtw!YK zOJUq0=LwLm9=V+GeMZt+(}hV!r zkiWU*TyYBDdD)4rV+%8Cg_Lpnf3Mpn{WNGVE7JDb#nnZOJ%1=#@;CnwnBOg}I_82L z0_I0&q4YS>*@jf@qE(@e#WSTTU&m8Vu}qxE-ZC&tL8P$j;=DxFC5I&&MI5E8g;p_2 z2Y(YwP3QV%qgE4-)%Sm>;uGC(nOPOv&&7n14>D~syN6qFJ$Vl!S_!Q$^bgN>>=0yR zSiY$kN;}<@DmG`_5$Ugm<&yayPr8b;noK(rWXYjmnq$Hqnp|0f+de%ZF z`TyA78~k-e(tFc4hWc+N6mhwuu67#so3mZQ!r${1TqyBd}`$EA{c&#j#!~iCI<(%EXyQEs5G!2U$w)3Pc}(b?U0@!6SvP zmEORKk4u~1 z^H9>0*Dv&iq-zhkMRO1!N9eLt)gU54m=0BZu|9f zF8Zc>=ho2=O)IkBqFsQ{F&vbd*Uf-j^M%M<8Fm>vYaXu<|34gSX~ zY7HtwOJN|ixm}1WZ$+IrXCBHjqF(l+Oh8Oc8S*FoR%=A}6Lp@{R?WqD{GkaCrt{_B z>AquMwsa^-C$nExVQ)TT<+OtJ zqRLV9>#3j?n%`raKiFrF?|Hl*?~|3!k~BM_k@C}rG)#Uww35ZP-NPJ+W^<~n z_%fQQo}VZjp8E$ zMTBNUhQZN}-3z6}njwX<>G@m>xP;4T{#@1=89NnhW9~~d(~$U5k}q+#zUB}C!dX{xE`T5W8J>el?6nKlTUo?09sMOfFX`ecj;1CYR*D{htC=jt5dKFnN`x7q zk~dkR^x{FuxCWJY%B?;2mSxbe=BPXoBzY5!VM|Q@#@^@!{O6t*BdqU9>X?517F=ST zhcyo`HnKK``Tu`{dRA=lr@;(e69KmgVF>nYZ6%M2gj1FYvy$CfwNHx;`1gMCI7V1e zctBOGM&Euq8x7o=clqx1H|7w@0$e>1^J9WR)HKH1*AF^oi)-p4#@|46DdT*B9jc&~ zM3vJ^0kO&A^bq7^7u7`|wF+$;{_>X{+x2FgiTk*b?q`Ao@GF9 z=$KL7vK}I7@(Vo1J$ye0{B#rLklPNsBpUf>8WIuK{`3Ppz}9`l#wFrbFSLQ|FAs0RV%3-<}gz%ux#zv*vPe>1C1iZQ9;(pe%G zU~2}aNRddV}?{SvWeaP;T}On#f}!arI0(t%~$^K=JZ`yVvYzOc1wS7UH#lo5B2)mJuw$HK8&H@$;|u;r}C)xn!I+ zIe$7vgb#nEFVRQ2b@0NS*G_(1Hk-EhY%OE0XMpRewpfUq-F;<9HLvt0QapPRZ zleLsQ&b-9mMfx-gcCoC)QHVchDou4m5J+GvC^XFp|Ldif#@Z2IS)0_0c=gzvfaAX< zuMY@ucmwPJ0ZMnsO=r%95bNQ_M~u;b6X0n9s61Fy+&zV>tZS15%&a#XpRUSd30V9R zGV}!Rc7P$_5XM0CE7y-4uZD38ZTg$qRf>1lk7Ok{kaeJ&pU;k%{KFy zICSzOdPYXlC!1z;h)N!rkBTMRfAvdC`d9wKmv4&Uc6U~s&wRQT`HL?Q>5c@6jA;s< zBPZC@3Y1;lZWUy*5+dJyA8OqQiL6P4aKMrGim_pq3!bi5meB}C?x7Wzan(+|#n+9~ zQ7)Wn{r^8p|90rpZzNw0zTbVcw&^=pu$BAacPw47&bz7bk#-$lAbeI1-zt6`5RHG4 z@gk*Fra%43gbVF18NJM!^S4{pK`+JPW4MGF3Z6@z;(4W~X zw)rFQqd+4KK-_TnMSCih;#t+G++{M988PM{7Gx53;Zb}F6yFObRudopbCLcYN7r2| z4?nGKZTzW!Okz8wKW*{O zI2vSJK3H4AXZX!gR~T7X`rCuTG6)5&$16g_b~s~Bys+YWB;7*W5egMS0| z=(DRtT&HvI|*3=ASSI@UXMUDgSyHZ6Y#w#s!U%RIm?}L zAr?|qe%lz{hx${RoXs^)0bLid#`Zwm#p=Z~y(}G69xx&gd%P=ZQL-5C<5z6-K4&Ie z)1pCAea8Bf{G6|e#t3vpb^B{de8BXMPMojEnw%BCGdscpZ6Uj|m!Dw~?xz_0IpcY) zOE6hr+0AA^&!Ap5klGUae1f|{ldy^LtFoVTQDYg{gveSz{EfQBOBGfu8I)&0o!`ur z#8$*pwA0E_#1!4}n$HZOp~I_YPfO3ak$R(NX}E9IqjJAvh)kQsTAL~>R*l8<0HI-& zJbHsi6ljp#-9fB&5lbs6t|N$Ey2hYSjey^2u_pt7cdvp9(Vo_0>w4OFj6F$n{C9J` zgtI&5$%!AS0g^pHp}+}(P{*NL7OcP4+=>I%)9x!2gmV{CFxp$(cK(Xle*=LViimbv z8w=H=jW%iRH6*AT4z4=|uhiT=T_1;AYRQi29?oGm3Gl{&L%;>kURH0Ef2 zcT!C%#`7@;W7@Bf){*?=%VW5K;V5L$=qlUxn-mr+d9Lr>mzA^}y9C($c|6DY8Ah+w zKVw%%Kxq8<8faW=1;? zq{#UNrEqknp4;r*HZm$%OV|zfobMofh@B}CQW|Fmcanx-b;T^By`In(SB0XyPPp?K zf9yqSLTK6(>FTdZ`4Vlv$)wx(GBBIjU@)qFqCfGAD3XPw{jt#4&>rI;C094K z+MEq>UBpz|%`L+UJ$uT|v z`&@~Iy)xnplZDB@d}jTU(vB)!<0E^-i5|B6F}Li4ulF^|pam-|fOlo7de>qWHt$}iwbK~YTNRPA36ROc3E=qJ zi?qJ>{j-2wD+G~G>ygsme?11@XzjBsG_0;)Pvb6z4A=aCbiNnLI}|+o)j1UIi>Xn# ziC6Qa;W2r$R%b%>f0Rkca!}EUp?u{XP9~>U#ZTkrTLi`0#g&QTC|^L?%;N(@RW9N; zX@;?t1ETozG}}LxqPy|h3>>}~#g9*MdMHGP<<5fGk}+=3ZCMb!ouiEa6S42H`{;0G z2IN`sIEIU!n**quA2s?z;^66!@rt0F=g<67d}~FARKb)VqVfrg`Lni(L~{oVMAit5 z95dcqHFa!*?Q|!#gQX>HsU$7jP@$Ltm*QFJ60Zv|f5V-%4l2yi6gYQlp!l~*t2;-s zA4q^3{+kOdO))H2Yd!6eDT?SnP#E~l&D6_BP!&Szu~`aXZl#E~B!P0?|a z+yiyxD~?hJ{#wntf}3plcnHmJAKMrKU$WZyne0R9sno9<2ROn zHSr685XyL>zwp%T-5>Ke-FwIG!|%I+NA^cx?JnT&2N!g7J~8zhB>$Q#T>(vh>odRa z;NxT8$080w8RX45yKHZ7kwF9aHAA6J=hk7%Zpu^yU`lo=lo^+0ljva{i5z(i_y&fR z0OUSzbrzKw$s(e1to$Lwa?Yj_t61q zu&Dw-HU$$e7Gf-`#ZuSZuxHNfo~ObVF~ByN0J^|n3Z0%(btU1Gio4~{0K+PbW9VT? zYe7+>^f0%3fS0B8|5S#G9^P5wb@q-!dXM)`@cV3Jhc8)rGx0%@SbfN|tux@i2sA)+ zkhGI7eEYtYb10~48&k_reG}Eg&vdaNd}~XkR6qftNjZKek&DI1gryT=P!?PMgrSIV z(JcNvq2svR|7?(M{|v&51pe2s0+s>g317qjDz{%lOd*$9F%(5<>OhqJKYzW_FPxw1 zt|;p2Q*S^7=kP6f)E`Z4zFg7mG<5%V0cZ9U~95L<>zmp&s`)ePN=EETO68_g}eo3@C3uT z7&z|mTMlXRap>ARNrh(ImzrlZa;?tFYt4=qU;r-J9I&=`xQ^RdB}yA%4}PET zBO3#zZmeGlRw>&DPUhEWh?}d}UM*k!@%T|yA7AtV2Rv-R0_n0-j%an`fL=Judo@J& zmbJ$5;?rl11T%}vPV4t%jS!lKPOj-|$>Mtc41Kn^eCyO7mnZbPkJHWg5vKSWBIiik z@1bA%vaP#uFfWRy?;>rgSlHS@Q*8)QCfI z_+vLOvW~5(%$~|rs`QhtcHIjitD2}v^5M7Kue){N7t!ON!E_;7rdGwPFph{r+HG15 zKD6hUKsD}S)wBe5A?njwJy5Xe@#{ijnWn{(FeseC;igG2wi_&is6I}7&Nja5$x;63%% zJ{ot=PZ38s%7)~GP-8bXbI1yd&RG6SL^wCUNo_T@jC}9|r8ISI>H25)Fv3ZhTxhxB zef_S~UEM!H>OsEOPxhEt9~cRkyme%B#Xrn}mj4RgLXJmNr}Q={o(rRYMY7&zBSGK( z$I(#+MAZaokOpax2I(%9?iQty?oR3M?gm9#8kCeey1S%9knWPa_r3e>@6OK7?!BFz z9)C4Elm-wJ#vgOs$UwWjzRov`Vwwz89t#gEnjYUgJb!-oRs&P%50B)Nmu5fv;CtTu z*c)e|WB(#A zQhoi(>$A{t@95wlo$&p6d)u!#n3EmAT0$W|do!kil-$jum=$T6_P4S7g)+OEUp{Q|fD3d!3BSuUWrP_ac`P#gJ!(IxVg`U_lK8PA$6L5{a8DZK>vkwOQk))xu~Ct?{Uv(9a`r(Hu%HZgY!>|4GuCB?{coZ|Yg;lz=OP5G&j~(xWs5*=Fr?}!&_xn)m7AtnR=Fl z*9TL7w-=DOp>F!E`QP6VRLM zoXg)yxPLELNRc$tkLg{unO2~GD1x6YPb#Pa0Bq|YuaaO*ERGX)%*}D zjJ@>$c`Z<>^?cyRLEUg7E?73zLNT)BmUO0A4+czuVXBeZ_}{qJ-d+r?bW&h_`OzQ7 zOR9D1*W3=DDJvvk4g0GB_K-TU?C}7LO=cmAS1U4^C9u6`f@IrC~x$z;hfNcKZ(TTJlR8@Pn>?6L@ec0n z4d|5rt`;<=wHuE-ymA2E~h zeveFAt}w^8oZoiy&F$MUL})sG8yPC|>er#j>RpTib^!>QQOLzx1Fc@>&FS9?Owk{H z%U>+WF@^qEko^YY!-Xy$(Wdof*_m36LB?+EQWGIurde@qZ(F3PC>{?G1FgD)pMSM2sEbnhyN9KaxH~vm zgz=Er86a&Xc39s5D=d;b2Xl>I^a%?qv06U+K^!U24AL2%&N%dCuTKZ?NXNU$H9*&g z1C7{v4%2*;gg1mEz@n^>=!|(#Lra#ln*2>ul$zz z^@}D)<4L~+0D+Jkq8^*LR!X#H#-2BEjT{K1aUB8_HWnga=nZSmLwrk6BK)h3h;6PK zO~L^aX*(9sf`tL?vewdod)hZ8i5!}DHe-V-aRxcQ{K_@DrwCf{Yu+z*j$H-B%2Uej z2)&-H&u?RGkDLO}`)e)}o5`rk*axAm1j*i>*0Fm5I}S@hV4sE(g6GByfa83vBSjwioQhB zFpr`@JC&v7o^FoWL!aqSYGJd>iwMcFHoAxYp1qtQEQqqV& zZK|5Cl_AS zNpjABh9T23{06~|-*%qU-DNYM+VaDwA{Y?|h;^y@xBkW=8J%5zMJIlXbx2aZxk5yb z{|^O*!CE}FFlg7O4K@4t-r>sl+R=C=L@NT-Rh+fAQcS)^g7`Ub(CM9Jq4bheZZRPP zHO_ZT#^RReT0((yfFr#^$3`()#~?GE4;TL$6gVT20ky!yd~-J*37*TcSI&j+3BiVx zpmEYjj{-;Bzla9;+`G+pzw+lf$9d4bj?zBSB_0(&JhV-GEW4OXt$cf-$`1*oD)7th zJBs`d4G98voY=8^D|t2Vjj+id2cMrsP>dlxr!dOX-uEfElysT3zE@qHppNbTDOBZZ zRk5CpPFrSzf6hsW1bWDx&*93W z8lCVe?ZJlI`4vZM;9Y69LZ5-u!KeFw&lkwDnEv|;kbLOQIzm`AxfCCD)e;bkF$@AA zPrp+sG;Za($d|LXx3G>T zcU)U7x1C&pe9J?fo(TQBZH{HAqb7IV?1=||yOaZLUl?vvzv6<>tqp{B)aSQ7YOAA9 z>mQlFj!W>lV^VzMItOBJ06!F=Y@tsh=@YM_j{_#S{K!amp-TrOu<6%J0D}J;O8;+2 z)4tPk0T0j318LI@GxC~@?C~KiK`?O@U{Yft*^XQIiCfkLr1Rg!C`qxZ@gTdgiw(uF&MvKm&vJt5j%jX@%y`ga~ie@`Utf_2-irmAr-P70&cYY;xm!|fJ zM**z106$amR}s%3xD$?>c5U<1{lr}K5{4a^6(BM6$_%B?mP3_ z8jOdzNM2lN0_FZ3-!YFn&nLj+jDblC!{m22+k0^RVDGNEO z+-(DD30*wSp$#sj9WCww>K|_2tyJKZ6QJ9yU`IUDsX#Bb^0z^iC2DCtmu+Pm7E%NV zK=F@b=Qw`qPSHNXYdO0vdi;q3gxN;hG~YkBWh?iBr6GWICoV-I;JIHt2> zum!8%4(spKav@gQb-ABGuC=m-G;#hWfd9pCS8gWr>FF;aRA&I;Mh$|<1>LM=x??L) z&Oc;B@Rof64?b@d#1QH&!q0u;A;{SMa(@aWRISlAK(6SiL+31;lsG08`Zi^fulP(d z*3?hSZwJ^=KBOcYb54HHszo3R<_+~%7U2_ouHI~Ue4x<2e36eQB-kehO+P(?nOJzS zjtLR^x*}YQ4Ji-PBG0%LHj%ONUMGEI!c$1JlV>A26Fqg-L-u*9d#wLs z*=J?Re>kUBSa9b+p=$PBlltE*{XB+eBwN@i`I6Jdl;@zU&y{oNm^7%4O1}I^NTPt& zGM)0hJwy3J3#{{;a0vn-ziErW-41%=e2Kzksqu5Nc}ka3TL%n-8T7M7c{Ek7xv#Yo zhQWHbQFCU5=(lbw>4QEgtDh-VLg>xhkJdRh?yMlfMP8JVh5LM%83&U57sYahV=b}yx1{2Ae*AHh&bj4$ICCT$811-ITgY;!q zru(o3Ggby+<`-f-Fl{4Eu}>x^Mo%NQ0|GtU2z} z*fp#f-67)$7~$=H1Fj&4Cw>CHSGpu|9fps{*`{?I{ln(RCOC6SCo9*y9e_zF%c%Uh zGU6ia-Rq>uFR(2~**vn2WAq(6xROG z=dE^Yz{Vo`9CFS*_)P);$tMi1#xcXm8mr~=50(<@oM}y7RLh*AswPY!%X1F6Fql!S zxv-h_Hx4gUw}OxS8s&CH2c$JbT+hYm9)*Uch3;w}z^^;RpJK|I;t8i!6x)^$yYp4o zBz&Ue-ov$9Gcv-(W|7M|2}Pf{dZ$#J+Wn_be=hY~57)(s zSOOr=g+OopuZSt>sJ`RR^`X}Wng0r*6fua$3xELt_}olA-=M_g9~RqV<2o(QIgVJW zdsn7^r*DKI|J|Xl@9J>&?}qaQ27V()#T;^EWY_s-KFN_oya#V!E9OQlPBs z_S6rvq*L-FH&WxWA&TJpNqFYbJ6EH3NfkPN-WTXP{bX8Yn$eb+`~zgcK-HQ^St4?z zT-(*4uPU-Rjr8>t9R}G${6L72H9R0wmsIp)6OYXl;E+@J-+X1OZ)?b;uU$c1QlmbG zR(@ibxqvJq6Mg(z19v=%g#b?`2nvQtGNridT5D-LdHj0(r?C13wsE&$#BcmY#=^1z zl(SW0Y$t;rx>a#vA26pCMt>{olG#N$=m=xg2gqZTA_Ey1Sanazb zN!qyh=4+x4q%Z<9PI;+N?R7X_#>0)C=%T&sv{m+Hn>@9TGhbm76e&-|4+1sr+#zA- z>x3T8^VK!IbGrfyaGn!UZ+>p0LQJnMas{7eYSKokV(m@*?<)N4hS2y*l3lmp5W+Zi5B&K?ej5gE*rK=i-!h6VKf0)Y`qbPt;HLy3<-tJiV?}|*;h*9* zjvv%0Fn=|Qy9wj*@a&!5dOoiJCUzd|eU0~zSSoK_g3UU<6fRLP25*D02%xJq_vK;F zJtqV7y4E_`HUXnNnJG+5)->#Mg-~}yYDgyduL8>Qk5o+8i}UP4rs3R@BR%^m*6izs z+9wF!@-Uqh!z=J0J@w|Hz$W#*j}!1u*{Q<9B5*6i_j1ds9~{5>6jEz=+p#VDnpYqj z)#q!TasGBkb8C6d7%Z$eux;#0Q4AgF&cTv~k&Wx=$vsMcL$dGV7`sN;S*XqmXwC-K znHZTCP%`5($kIzxr4hcPTIle`xk$JqmkR1k0qqMK_y*@8Hl^tMD${G5AkLh5+s=By zr$J^!3BvI^by*HvRbIl+s=#aW3LYqig5L?+&c&->{C#3qj-Ux|3{A z`ADWmTF}4&Mi`L}uqYbP8qnz~^&d7!qA_dGJi!En_KzQOBy(fX%enRiKi$mW=jm5w zSvIFdW~y$05!EBWg5cFjbk@rAWyj>*uN*eM(La*-;QGKL;Rh=($?PbpUxG65D4jS% zl)Nv$e9JVgGeB>g8ER8d_nq_TCSweQ1YM zl6R|S8=ARMi;B6 zM!js*cg<@axP?fSXj+OSIj&%wIuKeWQqB5>s5L_e7d^gGvNVdzPz#@xLowt9EP&uA zr2cygb6RIZwKCLE;Fd>0^k^gVsCW6a?++Lf+=eyNp1O*n+!Xq1w;R-& zI;bZdaloUWxuk>qYsRqhAR5=rlHF7q{5K8AZoyUQR^?vXhtv;wW|~yQJp#zG`8CR+ zKn_#z>iXcG?jk*8{~S2;f=djYiyN{uqrv*6;%*(RmsRWIj2rkESb*mHNftPo-;dgUo48Ocop#y`MXKP44&_K6u9iQ0q!Xuy5Ov!s`a_gsyD&uo~1S$jszBD zpA*-0Pe~1Kjz&eK7l>b=hq~+%>OjEXwP*ZeC zr`4jh1Jo4=&3@8qszfJ)JqO_cC4W7~zxN#H4U;J72+E#nRey5@?w7z<3M};?z?}*I zm?#1~Lg|pMRpesb4*5>>i)YoJCe=7@GeUsClJnQU44I0C=hML%@me zBILINL8rVjPlB9RCizSO5l3O*Ball?c)xImM$8j>%#g*wT*zPDCSKCr05iKGTpt&v zZ+HU?Xz`)+sQSkP5@ZBWTY>{f4UG6*I*ALYE8HzLMLFW5FYYK>)%Wmb(W=|gLfsP+ z--9(6Oa=F-LYA)*v$m}BR0e|Y^=C5D8r$(qTOqQTD)pPh|D*9H*2J{t)4S-8t?Q&3 zRU9+&Dd!zCJqHL?xmkxo_mz_X45kCs5pR!hT{up|XsF3qGb|qW3PiKMS87&~| zICtQgqNNd+qmfvnZ3(t+FI8CvROmcg?bg1)ssoAvPsNR~e4F^H*m!Z! z<6#mp9;rD?hE{nw%>rVLSqs0L6@LdF}hEmE7exxH-Q2S<}n?&Xhb8Wkc~yveMEKRxSJ|X z5CVBGnKWYgQgWsRRAvO9X17-se$NZtIF>Vw?xp(WpmaEObdTOt*rR}wH_&zAve}ts zQl0AJ{4C(1`nq0*Z0CrouGIb$4F8-dUgQjUxgFNp`HL)mR5Uqety9bkL!zqicf$uq zqP}3cNx;_jRP^$k%}U+QjJS>lZ_0X%AjN}b1-$>g4qeU)!R~r`sKn)_RvpgheSkZdGaKpVK5u{36lnk2Z-5T*Rk^$;BVm^ufe_Iku9{o zBvSLVG!-y5I&r!YWkylWylnixi6^wKxxd;g zMtZb}Z1C~nH6+b#Qt1^4vmZ%S!HMLbr>oM!em92Mes?!vw_`ZI|E8rgrI-BE7^Z|d zJy_j_8+n`>!tt6lDSU5y*mgzK?zykASurSrZJd?lc_;JlJVI+P8_L`77{1=UPpd7j z#3m3oqC^rr1BL6LfrG+9Y>@}>2qT|G@xI8&`8~k|b%T)GB-HYddIrDNL>{(>V|tOM zZ!a#mX|}lvU}&Wt!d!4tPtBN8Eqs5|b2|PJ^XFY*kDq+y#2I~`8>0(@(LTWnOIuK6 zYMCl2Bem2xCooa}Fs!6U+_)ndJu{TU!wG6{>XOOk3da^S)ryX_m@(f(+d3A>#ck!T z9${h`aF67_?BJ0~FSf{wV7S$}&sw4`nro|jsA=j+z9O-l2ZM1pKym(?s4)DK;C&Y6 zs5|zc@@uwOgWl#bbEkR~ih4lK0Yy>~YlhtP|dyob)9g zd>*IoCU^2e@{c3)GXZxw*wq+m_OKR;_13#e4SH@*M3OpFM!=y?R-uz`hhbPR>QdT7 z*Y)N!D9@@BFF)sXetaz9hjY)Z!htS|ptMAR4?*zHmsZZBmK_G!9T!?hBj!l^epXJz zYd6I09IM8sRooEDs;_Or-r5T=p9s(O&F9uEo|ReRzmboVdy3i>eT$TQ_#a*3VSVat z3|`cH99B#=#YV8uG?=Xz5LL2#@0L&j=5V;koGh_(%YLW1OfpEPpdxcG1ReSK&G2|e zex`D+!3Tb#7(Nd^Tl^v+Z|a~R<&Pf``^Y10C;jY*`WaS5Be1+ay+JKIzMOgG{En9` z9ejN%m8~-})FMoWvkGoEs--`W*+ms-Xu{gOg^MrHDyc}25q{8!q3us8{l5I!*Ee;Bh0 zHa{3-lIK-?cpU4&;SJYl;U9OQ;wWKP+kD?m4)Tq@Mk&rnj_154jy-{ZdjiiB(WZpz z!4=76WQI#7vwt9-LiUuDvR&L`p!!5?yE_+_IuVlT(>)P8xjW*Ii6Pc9WGVj-oCqPg z)dP5F;6y6)eB3^iehxvrYB54t$AsUe3%;N+wgrsnC3%pP6ObYzgZ`Q|+DFO5QYbRT z(ccr%HQ+yG;hP0xS(E0<25or+YLxBMl7OScUTBz@I!^Tm2sOF_rSD%3WXiGrbotOv zt&uwbTFZD?NW(@<)uLr$NEYgTeMW(4>rF&hH!rZH#`VP$c-Px{COmUX+Y!(Da4TJ9 zK^HO5`v?BH%>UMWAl2K~T}DB%LjgV2e!Rxf!w$B2?ciCF#Dl*RWbLOZZciCcYpeTC z%R7{55!$j&&xs~)wn3P@AvU(QGhU>g{paawPjgRz*dBzGCyCI<#({P{Lq7Dw26sG_qRQ z{EHZwL;3iWbJDbw6@RwGI_ms(EBNw%Q!|7^kbLT_`sL!+R{w*5Up9$2Gv_}~-CgJe zeq=aInSoCu0CafuFdU%Nj8d78Wl{6KUsSwDDh~v)K}{P0M)W& zVG_Fx)#5KGC#H^=kax!*o!TvCDG>Ipupf2q#QGS?)Qug?E!3y}+eG)LB=RuxY5irS zI9&y!(0SSY{g(0X6Lw3Fhtef_qt#1TtcL%EUg0O|-8EaLp8``YNcwAyW|3a6J^7|S z7v)mHE^X7WQK_>5YF~aEJ1>F$GHamo8I>Dxeosr~qX=9wOm~h&d-b_Wgie%*>^<%VG1;x@lYP83 zJnLkfQtmpzfr1NRIY^B=3`=(9O0Gb!=!v2EtiN(`fNKy#NGVGANBM=I5 zbBeGKfqSEs>ZSC^XF{z3Hl4q>cz_TBH|9RrahP5X#o(VDUepmnrqcRWpnE@HWc~J< zNEJw=qRr~$QKo;wm z=@c3T7zYBlOz208Cg%O%+#9{wtOA}Kcs@0a&wf2t`u`-=)&++BJgvJM|1x1NwQHW+ zzv{^c2yzp9H-!*seQ2g&o9ZGRFfkVEbKBoFRTh-S>9;_a@-_K#f7htrux9{hgtx%mG($f>BEl9MQPIK58VT-(EzMAJ~{!k&W9d%W=bT?)QTk(r?%ZxXsbWc-~DD7`|S++<=NYrU;SMT@8K}`cZc@w}$ z1%tlrb!6|P%J)8A_i6cF*sS=HB_!00h@(NOpFDD1ViN;VlxX_dQY4tip*kpQY;mwy z?}Lybi56vJYn(W43_#5{bJ;_3XT;y+c>_vVCo3A4aFn@Q=PaWA0>XnnClj!Bwg+xM+v2+u=Qhu9Ukg&P%393B4B1-7~Ls0G! z(_J_W1iH<-#&-Ao<<@~L$G%fVU!3}f6~+*VhxOz+5g@PR&$V*-c-?+Q0Bho)QmUJU zD`L*eCWspr;3U37qVc5FD^>tkCJ5Wwy?^pJ5w+G!g0~NG@9HAP_2Ko5^AFvcaJ-b) z>1jkffm-S)p+jnk*R&Yq7sS5zpU|N|?E}<7n1auekUO6TH*GK|MqG^oaRgC96O##C zZk8#XzCY-X_>?fpXT9fA!4mbYMNnQrzU$J^&Ru-^g}Q9!-(aN>+%uPSdv$0AzVtPK zf}xP>*TP?uq^I84?$i?)Nq&r!CFR$of*`7og z|6GvpIY?;JWHa!K+V+sHh6ev!9MoO!c7fZXxwonNVf{2-iM02cW{?)1qi+~z)R@+q zjTZbjbxQ@6)KOo4FvA;mys0qoQ5y1!-ki?(|9SCsLEGgfk42^biBg}H*xw@)g*1zc z$M@D@bFjYOO27klW^P={+Pj)&C%Ox-+6+vvjr92CN8XnnxBHbiQ&}wX_d~(_tHGg6 zR|nEz!L{=TI=<*L>a5WcXzOZy?pHLBJ6T_O9jx9;coe?6`8*Yxr)|v~1ZL)Fe`b{x zVJQkKvbRYZ0|6;T~?8#=z=n#hDgCWzXZ*T;k zVMH$*j09y3d3g-I@9R1#?1dZw5JyPhvxmH`R}8!T;=!1(8(F?(wwPq!hi&sz1uf*O|2o>+@P)_&wDul% zPP2}i@?k!NvmRXXHIDxklT-1lvid(Kdju0pTo;*C>>;8JiF@Vmwzs%dUni2@t;6t~ zjOc|pyNG)Byx)>^cz>7g=*`TAz(O_YLt8iU+k+|`2J_K~8XfNH68>TA2#ID@&uot! zFS#vowu?vM`yU*fVX?EHK>&6g&YAL21tY=KwYyjqY?g$B_D1%O?y~WGWgqv~65~Y_ ztP@`Bu`;up8V;~G#Uu=7GTj31%U=nn*xKO4zh_;KVrXQ8;()U#yNw$eFE1Y`GXnr~ zZm{B^9mgain_pVJSdcZ4Aa;fK_1Q#v1+m=;-ryUMTL8S&ydSc}GZ!<8pa7OiE}9<$ zHl<;6J5mmUS}3X1p@ZD71Q6>Y*-P;3A@6b<$ONI6e;!c5TD)Lx1Mdw>9^#)Qf8lwm zez(O%HymxnCw-tpFdy~e7_5s9&?(E5o2JvIkV&SeNgilq^4pHXkQbVq_Y{Yr^}i4( z=Vth>pCkw`qBgxV+x;TIzmob7@O+!;Bo?ml5r^QfD-RpY?&ehBx6X=@zIK%Q<=*MWoTlniL*msq z>p#bckUIx;cz~0LVcYTeabTV>% z_GYbm`M5!xJAt7fF-e^#Vjq?IDhLRfx3lo14|7aq)U|B?fEYuNdP~KHG-VYWmHUwy z(XR?WGSE~}x8^(9d4r?adOKES9hrcqXBHz>fB=L+=veK>JA?=gWGtY!q9=B^_PU8R zsIKYzYA22zjdcFEGr|S93$HFy6P@>y5}^Oi;9YHcg!<3AQu$6aSDJMJH3VcRq7zTlJq& zR3jcO_co^3Cuq&hrin?edett`^hZrVmCnc`=*iXYbyt_@wh)4Kr*ECysVxa^G~C0V zW5J;=BNVRSzmybX(>@V0UClsjzPYK-7OvNhxrdXAKXsh>0w3%^?CNL9jnWDclkuo$ zHy)uke3ov%8Z*9}vHzwiLqlqlgP9{$J&#H~8@~Ve^qV?OcV~eg&76{V6%gJx0k1?z zpJMX_YIh$6v&S)HonyShlQ;U!2PEhU(CTJ~78mtKeYIPIVOQLxR}7PJmt_m0gm4w= zY&!As9Xt_zGbqe7+XY@mzN}vhTo4@Pxz~K0O@`B23}FUcmjD;<`V?^_o?Gc6YemPm zTS{iyUHOB!X#IcL)%fO~@I8R8PNjS5PG#>pF}7(!CNan+YCUm62k3Xb-qa8=39O>N zbnEPz!a+bW>hc6Q?=1K8{0^Fa&?pX$?v;`*nsM)q&RQ6NE19l{jhm0Xn8g~$P0M;Y zF#eN#eiUZ9n%wV7ylG42X;t7KG_Pt_L zWZ|R>h0jKAh_#=Zs{CCbJm#Dc$*T`(1^GkGd(_|_EDH$OxiqtbB43xT2x*h^Kod3CJ5Xbyaj(u(Q1gIdW(2|R{o4LT z85aSM+Z`(m199O`pO~X#+UmSHor;nJR}aTy7H6?H_Sh#|%-D0EV7i9N{+p2N>3Vpl z+oCLG#Bd!Wh@5bzHLJ~y-&=$nJ6i^WwK{^3so z8wWRJhy4RQQA42yj?}nDukW^TkrA20_&@cyo`VK7;Qcwu;p?RicfO%S#E?W@Q8LPV zA?Z?6QPDh4wC@{Gh+f1i$+rP7{iU+@ingX{FpDlO{G=jIY9Fj~1>fee4CWTvs|BXe zwm<8foFQG{IJFQUU1QOZJH=dn9D*f~4XnuAC()SKi)1H63p!8qabno11@)98+x!0` zh0z!`!)9^)vB3+nJ?UJ|kJnD^{(*RgMAt2&G)Idce_0-8K#Q&nq5kM%aolq|Xk(C4 zA)l=JtL)&-;09(ftd4qT;?n+ow>KO_JeTCU)~8a?4E1;f*%B?X6*NfpKSl89VPKaZ z$dJ1RrE20zGA!uxhB+JjR%C*$F8zYPoTXTmbwEQmy4J$=yE- zG5P~1dGpRIaDOXl+*(uuKisWlAA}L6LU9{<6?wplok(Ss{YWycF#S}QpTwW@^)EOI z5$+v~eYFVrMSx_-=Ip>S{81)ptE!5g`HfTzFB`hPH27dMmmm?MO!HNnhi5CRGnTNt zQQ+KAfp4R}l=91Osup8wg9i30)!UZc{_a@gtX;MUuuoYi@iQlI2RkitG8Pmph-o2^ zP=bqX+)=bo3{sry=%m*gjqUzW=!M_I3!3yEm762~r*R4MFC)Kx`wQ7~xO*?8>c%1K z&lvK)Wt)S5Wj&QF*uxVLm&U!*tUc{w3n54}JgIuW%Z6>`gxbvc@V^p?Z7DS6mXJF; z`^$rg-I?-DtRaHYyClOq=!xR@Fc#ZfP^SSTsx3mxm{mS#$1N~eGRp8y6&32A&)Gf7&$ak zU<18Wf*28ArxGpF)8)_-Z@iIQFP0NUu56kMWKn-Cv*>h<16A&4t}xhH@d~$IAwC} zzIMos#wc3>W_BYEv(qKu8w<7|do3B0RVwy@=J}T7%4Jw?NAmHPJQcA3E%Ev!mv?zc}byN`dauN0#F`9u-`(>ncR&jWtNR8;b)MZOW`gscLHhA zvtwyci2YcqWBh^HPz{;V;ll;bd=G}y*b>ZomcO;#dS82@N!-G!y)s5QI2Ktgu;;Kr z>C*lTMugbG8LNinMsPNrI*R(pY)-K{n-&PWOE2$6DN=mlgVkk{+W zFv9nLrKng(Z9VV_n6rw$oh4XsrU0azK;XFVV?aLqdO&iH#yJ9Ey8w)f3|yU9N%cO=L-omKx(AF_|qd70?QoA4-8^i z?4Dwa5AvwaI~p(bmNnF07;S={}-i& z+UWl_Y77xrRJ)k4^f1koR$JEAsBw@*6faYP9^)j%%%5T9u}aO_R#KD5X>@U*YRsv=JDfVY4aBpqHan4*Wxe? zo%&oDVRDF<48gk8JY-2{Ne$wB6xL;3ct*yOp#+n)Fc_xVkUdk%-R{RH9g$yF34fWC zDL1e3569%f>RO}Tqk%$T8 zGyXpDeqtO268dS0ctn z*mz8~UKr*f(;A2!p97DU)++>$`n>1kQ%%Y9ToX@}SJ1Ny;76rr8G?Ef!aC-OwVSb7 z$W4MS(qfmO6qV31`4_yzVZ;qC@1aJg2q;bh;9-pLlC##Ix54S%JK`7cYA86WVp~EuTntD zon=a^J{F6=(k5zBp_slKQPD%t0D~F8G(c-#T@ANzsyR`8QL^E4sdGWWDJl4e2Jj=g zoqS&d`aq240@MV?B-o{=syC4ik9>ad;QW6{!@`37mn1B^OfXtIZVurK2MRJ0S&Q~Z zW3xX9o7^A02DBG}{=vl0r=qHy9fDyM(iTF*$d&5MSXL-cke-3qkg-ZyO@_kqttcMN z1wsSja(LUaXh~-QO)$<5P|!HK;{6wZToO}ZyUrnD*ZlrDUS)6gMVdKCwTyJwYQM9G zn%y?e-q`sUsTmcWR|Dz1_mS{FU~e*7{~TzD~~ZA}%;N z7%^D~X=ap?0xk1#>mk!X6JHS{h1L+P+)yej>!N2%B3QaxR^d{?Bz@=x3M+W{Nix|y z9|%194>Xwd@_ws|wfxA29o8E_Sq2H-U z;L}~AD?+$*GU^cgc0__3W_AkUtP>m0z%`OdFdB1@Yk>W^mSl{RBl|N zM2uYQFhab#`>T8p+fvyxfoN}ufl#n;do0qJbeux~#|nyVFz0C7u!%35FJeC!{RcpP z5Bi;xJBfNls0(CU5_foDi;x0TlZr<}a)WcKA)k|9v zVe$HljD_!N3`7!26(&zD5_{&dg7?E z_4|5}69sW7UH>0`P;4AYrgMjjBWvgwvJrdXrWxu4FVl2vO^8xaIBr?2u= zvi!jC(Ndl5|1$!9+*PNL$BamZg!iNPPb0XCUTy8aR6IZq4B5BX_LTis_Gye+G84hz z0Tn4*Z*DBaO(n_?BrDLeLZF2&h3g#?+kAOJg+|Lvp?Db!dO_JUVz`#P2~5laDz6Y{ zPEVxkQ{TVd07Qf{re__4XZq<=?~hl7#t5@N!C-o6m4o)^bAIZu3wnA)-YnfvzZcGx zTUKg*)->lHCk4$MV5Y0Y`c3)e%$KqjuTskI`9snuEAms^*XYIC2xI)H;r#nxf0fr_ zL1Ih4QoyzX@da)ObE5`rX914jTu9iNf81iISY1v%|9l&Ba+Ub=F?7L@->G^_Q<&bt z40Hnlp90dPuDV~Qplajzyv$u#ZfbH@{~cX!r|to|od9GNC(OC$mBXeECy&mNgGwChWQ%08{0WRW-%oYWndR;6M z1R{dMFC8BOjTY;lgyFE^CPx2yePcuv%`i=5`w#?HSTsDM75V-JS}`l*(|PT=`KZF# zI03%OMmc9$v$F{SsLQ%I<6^&>+~V^1A71GMF8{+ZYN^GAYWplyrEUZ@@~IAn*8IKI zRs^X5(5@3scSe7*1udx6EYh^TddEyr2U%M%zE*9D(Y``81WynMWtQzkpUOcV#lX5T+`~{z z-%j;y3@-m0ltR!Rm8|A&Lq7kTrvFdYcLgz+MvLuOixfF>p-Tg0s z+kK*Pwo4e1Q*upzmHS_PL(J!ZQzT$5U>i`4M99nt6H3F*=0}F30c$t_9ttDBzpc&& zt_Q%~qqjnvbDfi5M47R#YFIS1n=}9@`V@qWeoMH}3>*}p z(BANKhPc|y7C`z_m^_uOQb3m5ctr9*YP%GzER;kcPqZSpujS58rVmrVqNAdcxTYgPMoywKaQ?4Ad4ml)7{;j(jX<>ozfsF-QA5yw@65Xq=b~T zG}0;E-5pZ*-TVE%+1c5>-PvbiXYcV`G{BI;dU+AtKY^R$Ab&;jd zWXQ4~jglTSCOvxQ!qOm^r|VIXW~wlJqaMCR!jnwLy7`ME@)GscMj??W&ukyDoDe27`j35NJbv9MnQLm;(`ekfl z6CK(bJ66d=3}+^9Lf$5y=x zWXU9!8E?FGsFb9{N)iH{K&T6hcPr=4*`y2I$*jh6^>mmJH{`07bb9wxJb||)fYZ)p zioHU+Zg?B-u~r}YcZG-UYEbDp5#QQC=nq7WMW(mpXZqf!KzV&FY2v&)6Erm%U6NH@ z3@U_ys6Ki1`X!xU{NAGZ7>>2z`)oyaKOZckr@~YSDgy43?I<_2FOcZR=#j@eV$MZT z18JQI9{cMXdU5kuS)L&@4a!w_Imxv6;X7>o0-IvCFt0C%Dp2drG2 zXFux2<;uf%z6Qs4XpxyrZwN!dl)n4O;0nrJd>4xD&Z3^ELi#8m_*NSqFXg58K<$O| z+9Mz8#2oal1VddXFH|12ATr;a*flQL&2L< zQD;O(&n|WhYa$@~`5V5P^Z?{Tu$iT6#uhA9@n-8vjkf2gLd6Bo*j+JjLyGYcSce*2 zLOk}|e-T^zmj|q1UXiu;Ylv?H9MUtNPu7KJyirrcg(bE0AP~LnFRy>iM>uwW4cEqx zEE@dXOpWg{s(*$GuDblc(?@h{*JNyMt&1tR;)O~Jn3PX3;<1mmvy^&+_bpdfA?g^Q zc89GGs11a7^zub6-u~#7-cSFXJ995mpj)4qh<4>Ogr?VTeQecYMGn51cryBpk9<~> zg>2#lNoU)AMQ@PUOgw}}tG~w(=i&8;rq)h7Pc5deg-Ga|U?Rc-jY!?S@eE~t=WmArKnm*Ed!c=%B&63dL&v#FJzC|}j4zOy1u^3U=$~7u(H4)x zHX_j#)x%PM{p3~C8}N$-;T$7c^mZ+4RVF9eH-bwan96uNushviU%uA3E7>B1jVdF$ ziH$hcIOK`P1F_zxP$HZ{R)HX!>Rp4$V#t)1XS9=etYkdB*NdzVI&dICr8g#LEeDbb=&oQ6S2kkV zKht0z3**>X{oFa!Sr>6&t;r;D3CKbLV}qoF$i}9GS|%@NoiiLCk|9Tc1!0R8lDc7q z(5V-?@wY0ipvzBEPlp!c`M*j|`|kn{02#iE3W35|VVmWa=%GJ~+G#P46lJ2609f;F z)<0x-reQ~9g@9A#2(u)vSE983u>NC7j|FHK05SIUS_2ncKPv^^ack#P+;t3MK4sj0 z_%WPhLJb2nEmfJyE168Gb6xN<(r~~<09a8#qG034 z+j}m1-<2kb$&?UnXiWK=wpZ_$ivxF)YarvwdFPMFpo1TC)WZ1>$U6GxgxSOZ*L&o_ zMoYiLz|Lp$o4ndpupj2v|4C5&SG!pJNG&q}?YF%>Z5DGB>ymJxfA^OYz$S~>a)c`6 zM|8T$n4;0L2-!xJS|EhFepo8J8JVp%ZzfnSgE=w`{S1J05Uw|-ND~4m$mPZlh@Jxv z5u=%SUprpy*w|J9FlBpG&T`LXdPwRQcb4Gv&jn=8Pg>cb97i^w^6n>esC9kg!9r1C zW|+;l_;D$2D(}1+9PT=+K|hw=?~}XFkM(!TL+09ASAIOIg`$${Xqy0KxKW^o?;S6S z+^lhWfr9a`OfcG*OXbfKcHyvJcB7N7Sr!VAn&ziCf4f@yxbmH30{)pFa$hk3yR-Y1 zM)QZP&ZeQdY^7q!yMd(4@_D?y2PANt>l;lU78!(uyd>&{0JwQOjLjPtkVZAJ%Wg3jK|*Xj=!7&hO*T{v9#pQi0%l-)@kreel3QUVG~Af`Vz@ zR+R9Fcp(_x$$k)vf3Hh$mn>bWt@v_c&n(16ME?J|S^HPce^!gD+J)o+zFtWrd-B@9 zvjf*uQh3*0e9G1Gf4IWT?~F;gS#H^T>!g_eV4F~#uK&f0KA?ex=P~Rsl^_^052zI$ z3KfKizYS~S333)@7B303rc$&x5^|bNvswS#&4AJY25-H$f`prMnKR-?Ou6u{V)3rse?ze@MAGdF4>S1=sc(NoVZjeHt#Gs`an_tj}0x{Ipo+@|87R z-2lRY@5w2!iiuy;t9@DC(17?$%6Xkj&NDqx(AuU1r`;$bujG(R{~U)Nu7`T>uvOHLJPi#`ptd=I z#yW8Hl>=s@U84!_J}3=kbEYE$6*WXpt8!RwzZLu%yr<{oH1E!O&?kf#?q10V{mVN@ zrzUM{-az=IJAvZ={6gcIO3o)0AXe1_*TzV({KM$XE~x>JM{UHioG&kB12RMsfimUP zkOf{s9jd3N0uc#ONmf2AIs#8YPG#v<=}yN@ye@Jkc%N3nj$$wagSN7``JFQ6Z~GR3Q8j>uryh zQn?#Vq=Z~X?Yav%_jl!2{GENRuvXu+b}GorXn&WTc+~~rkVy$^Cj0^apA9|zH23By zuW+D3BX=+AHaw3{)ArNvU@+_fbojnuGjXaB9~<9tQ?JK8fYMIb+=v?~loU|F2Es!7 zh7>s2f46(DgXiI}1Hv)!?gh@nmf@Ma;t>wC>)YIK4*$9#>0&^17iC}5UtLYLtuK@^ zUcOC5R>`^tIc1ps0=&8AN?s5zB49h!nA16Fr9aRz>vOk}Kdn^{^AIv%>A`{>-uZ*DD=hfCBvOBO9I71o*z1#>lt*BaT{1zvMQVQg3(QWH1~nmC?t zNSDDeMwvok?s1<7x1T&=@&KV>!9Jw8}DGm3X_X2Qw&yPfzF3?Y(&c) z|4Q*z#IoEA$P*OxM>4{Lbb~ssSR7>bqOf`rKf;8K!{#(A&o|azfkz2aErgKDNrl6} zUT=zsIOg-u5?R~9VU@O$(!Zh_l)b1g05(fxC!xJ}A`O2JaU(H#74b~a-vc^F)@X4J zer3arI(d2-!Pm<`#qFfQk34AN@-B>;JnBr_&bmB_)%-;%uzV$8KlTbU;S%z<;stF| zulX~{Duu!EUG$$*pi9qY^i-INV^g`o-{!}vNj`DKy;TQfqST`9_Z=c4cyLf&| z*06EavktvBF07f3A-3e~<$=5ZRz2<}h^*QbcBHz|`a#w}jLBqQJQ)}9eU2K$PG`#@ zvF4PuOUAJ#8^<>@sUr~(%}R0IjIo3ny!~KIHNpSw+y{8brg(sITT`>M7C}zCo&3l zrQjBQlHni%-(9iQ+eu(mZWLrbx#@*ZO5UPPmv|+Vw}Jp9MYUYAGj;xho8LbJcJYPl zp%K!pFW~d*j4_9f{X~$0dxIzS9&fTl@)I668E_)JT3=AI3Lt`cVP@obiBTII-BU6D zaFV6`j6s3twMRl>SiM1|uVKE{E@G#MO zMnP!Uj){bOx!->hFoZina7?_0$3{oA^;HxLfBW~r=eBhKLNi#BGa$C@mOaiGrAOan z4EuKK5pLP`rP3$TFAqzoBN(uPdWf_w|A)M@nshNI$q8_Q_YDEk))cL`$h5m+r!Sgz^Wby)JI`XDr|i&qOQ4|qefQGQqfi~}AOPpZ1v3M-8H;AU)Q6+A}zoN z#V7snO_xpq{S+Bd$-bkqcjtVL>WHieF}>hbsHTe1^ib~dTG_9m@BW5O?K3P$eHaEg z2XkS?37d-cc}BD8-Y6MaC9s1v;~#vTU#(E3WExY;nO z{*Q1VJeKdRJJ8yFA&9|hGe}|=KPviwK5LQ8;|quKp4}A%B6k04ue}kcCgs#zqC~am zlII7&N72C1PXI5U`_PQh8npSruyAb4AiP%p#PH)H1?uu+!51rfk!6nL0jvi7;0Q5aX-H8u_ya1#K_)!KomoyOOz ztm&3+pWyoiiqm$FU-LV-U?3f-o=w*Ko>af`tjC(s{`JG9tVQ`;JyyZfA~-u-5X@7I zD)9_(WYB&|NB>q}8Gx|);y$iO18K-+$AWty)?DkWl@bwy{lm{U)~2oPDbrLxZE68S zgZO+M)cMnTHHh@b?-6QL(U?_|Cuq#)MOra}hl-MGARIb^SOR=GeK1#>!dNtC?lmQD zF*T)^3)Y9~MvCm`d6yo*YxM6^@rh^g8(B=smLKlRLx$I$CV9sU$|5J$Kn68G13!JA zLBLSs$7%byYO!`}=3OP*v;9kA85VwAFC}N^&vg<{E6eLUz90LX7GVL9B=|Pp#Qwepz^juGIE)AIV z1~`T_#8tuRs1=-IZmYOi_t3g;n4#sIR$c1w&+FpyV?U$~u~PO$3dv1_)u^eUmM0hj zzk~_6aOS*nmp!sX3fvX_1EtP(d+~82F<&Irpu`Msr^(n_Sk_pa3|`FYS;*!9L56y* z3cAF}X=xZ{p0fdk|Mj6g(o1X1-QSr~h#lm=CeJGMZQh~Ow`xwBwTugsm~IqXktG?c z8*(5XHQ_trZU{^=k}(!;YT)X$_w%L#PI~c`;sAccE0xu;@6FoF%>^aJP%sJYJtpKY zSoh_5`|_oTP$RB41syUpM(0e?Rs* zK8pQD7-V}%G<*~W_saX5yJinO#5yF{6% zV`+X%sz?q_2rpyMARPxPkzNK6J7l1%o6IvQ>}Has3iTtaO+rr7O$rNFUq!749LNmE z{)e5qOG;Y7I#FxY9M9)7*sq1q!!nGTAwdGq+m!aUb!X>~pqs44?^KL!Fu!Y^6XmP$ zsw>US)CAR^_e(tG00;X#0-4afW!Ak7HjI*eK8R6+sVyy3*6MXM3UnHH1XC*rL=$_n z664HAs32;^ES##!l$a?sspXTbKsa-jdH~bm`o5 zOEoSH=mDe^Yt^&_Ugt*WfOk0mVCaT~qmMuu99#LJ#51}cUmWbYq$Em0J&YRShn(3i z@qRt+^RQYSZKkk+^?Q@GUl4{gDI>{TZC~M24cg#6#W|UO8m3`DrJ}C2e6)a}*uFOTw;-m0qC_S(mVX$Xhxx4x0yYni?^p(ri{g1ICsE_ZH7 zl-BTV)$ht5GmIfd06?@8v*W4Vn?f&Z+Q9yZE!{POG(K`qVk90*wtSj;E(DfJpJW>6 z^oG@%B_9Dsx}cijPe4xs0Q^`GCaFB+{>&IPtH?X*N*$wA$`5l$ii4z#B<(C8k_8bD zOB@3(=%C5J&T&JfI^=u)l8|)5omWSuUovQ;1E2qT@9)#yd~lA{T8n4%UgUZRu?z_b{qg0;fyfm<95px#BdRF zKi6EAIv3e2(r!p&Q&6M-D-SydYSLf%la);9`Oo8G3bS-PHMa$*8nIjLd3_Ood7Ogye5_5ll zzg0T13frJh;&&U>{(irq9VNgBB#FFM^at49)P=7*_kUgNM3ljL5>)xY*Il>X1FV~( zL_XD@`4%m4{DE!Om^6lDIUjZS6Hyg;s3&5k%tb1xX!NR1dN+-Vs@}{&dX%Tu*=bRu zZSzUe2nb=o`mByM$$+rBufuxnnrS@tksU%q^B{lvc9}=_Y!+6WSG&BeF03QVILauQ z#h?EIg@)J)G=>0aF;xpYZU5Qyafjau8tE-22+8!7f9x>NHzCPEs#g_)MnU}A%{iKL zt!W{gxEkMf`s(QJl1Cu1&w9b>CliGO#Psppv!Oxd8mkZ|Wm-%TyQ3LUH_S{{=X<+- zjuQp`xLl>Jo3-sP%@~in4C~Z<@7i3y39zT0TUaUV5_M4fz@=xlHUgJt+Zpy3=u0k6 z=jFsdLFZgkEm|gT1>+DxJID=(UbhDxY2TGm?wwR4-j6&wGeQQ4qP?z$hv4e1cWu^} z6W&+_%O7dr(e?q6gD|9`Y7lz{V($Al3;yoaY(&i5^LJ*u<@rWj+O;Ke@mL>&2I27J z>|K+Pv8d9CvPxl+;IZ$rFnpC#(WK)Ykv$sWJNXSl(^sCy=*1yO`B1aER|}ok#6^`5 zGpnZK_4tI$$(1_=uGZk*F9rr<)9@Y!bA~>g=!ruKgV);phR(K?pS&Q?nFno`er+p# z;p0E~6loQy$NYsc?E}HT%(vME#e^^DxeP%m@3Lr`HOHfKyeeOVdGubz99K+}36o85 z+EQOpq*04Nzs;*mUDP-;K?<7W>M!ngCY@qZ-A)6XSetnk%UE;JA=L#$YFjBu+Ul|t zq7b6?ql)L0qow|6H^3M(?I)0i{E_+AUmM+f^nKW;)5_fXE%VC?OHd@NYd=G-k0HZs z=3INmF@VXHak;1v`;9AlrL(>I!r1vz#on;5%98W{ks$;_W9zqSVN#KZS{HYsKTwxI z{~@L1Eq0YHLP3I60~316C0GJg&0V<2q$rx8_C_K*y}=;4 zM=fk}csdZlLLEO}-T{*PO{%mD`w`1y#Yf)D`;#@Nm6Y4T*j$F@BTX=bLxMRU)d)_h z*p1YPkb8N3o5_d5Q4AY;M7p{YzG<}=3Dkq)2tm~$kW#fzaj==6E!k3GArDa_Sm#4V z8{)R7fqwiE=($E$U7Tc9dNh_bIrmo!3fIfc>C1Ztg0UafIJ+JO-mbHn_`73#5Y*oN zTNF{g0t7S4k3Q);Y<_YH#u9Qq@Xt{ax&^B~u_1qv>nkx3(9dAGol>PjdGTVu!r(R? z1Wb%14q4n&lfSI4P@Nll&IDD+{QyNGe3c3HXpR6f0y(~y6;@TqM;fN}o&dT(BdnZUJ%FyJ?mNvYYOZCV1lP$~Xwdp?VDn-|(w9WAe`lgbW7bd` zgU+^j=6K-&tQ6ZX1KtQSQ%@0Ng>`Ts0WfJ}_DQFVzh$*xNlMOK@YwKDpu?_=>TR92 z%0vl!IR-gMlh}ILFJmAn8?MbwoK_yfCiXoIm#(q+&FmUPUE2>_ZJd`P_TFp8OOE}! zTo((N?KHG1zL`P#pp5~lnJ*RJ=Xnt|DKo$9`H-LrSI3z2T?nLas9VG;AL$wppAyU6 zjOkR|fhp)f+U2qeH*({vlKm`EZE2i{YlWzo&bv#5%X^$#!VM|Jx`(LbPQE>KRWQGz z#>N?`=2%X&r|a;boMLGPrh~d&v=1Mgrt`;<9+cNi<%?1cr{<&LD#~NtcB1Q+HB_1I zTF8)1r2F1rZR4YmBDwk93_!`iB4A-CM1LTf*$jval=-&50niDthB(>K9;67>8%!fs_s z)3KJ0wYi0ba5KPDJXbPCvSYk6H8A^86oBBcHnh)GQ(0l=IJ#Ux51u<++dcaDE4})w zecIs~J=hi5R919VsY#b_oR*m&9OMf_-bUx2YSVTBpSlzx1r;q&E_3F$32`1C6w?jJ z$~eM8fkZFr&4J7|W;3kktQ;Xot1hyPMunVw29(N3ICOJ3Z5V2eX0C+g)|6N*28jiA zYS0w`AXU1sxMAZ&oF=sk1xL=zMb*)J{p9d!=q(#&@ zPPSwLUSG^9(9Y`g7VxQnuJ&kENw*vwv@}DMc7iHo7vEU|`!-?fF%?heksEbA;1+1} zM{>!7FC53^$4qO15{b7F;UHK6bfuh0lIvY2U@Z-Wohs44PJ+#JX=7MR6V{+2$U-_- zhu2R(OLZV}j0@|jf@RgdhWQK|g^VfY#TcOF?jjq6K@uUs4HNxEiM1{CMSI1&5iV5V zx_TR-zYq@F4ZFX>w5y)nLn9YbBiS8BLhDA za_0zyJgG0iQ`SNFoKf?Qytn=MZb?;+Zgn^O=* zTIn$lw11scje5Mc9?|3&t8gK5CRjjSU-CMQ@@Y@JBT+`d7t^zCmgxM9*tmQ#9Kt-+ z2)?rg1WRv8;1=b_*y|L;T)sooAp425p$s|j3i*ru+S5&#!c}cqK7QZlWgo_dWMF?wI_K{d?-i6p$YO6`NX7Ww2`- z&xWsgo4o8+y3#6NEqcKU-`Rd;n}C5B^ziw|^fBhQmwx2&RJxSpya!Z#0b*^Q^+YKD z>kmEO!QD*LFb%w6gZj!>-zoQ5By^5&g6smzk^I$bPk-?#u((#pKt%$BK0Bt!$U9WE zjcut7PH?sep&Wds+%m+Fu)n#)aVx9SICA5^?*@dFH^QL`Dijp4_S3Fpv-~n3a`O1H zZ!sY2&81Kwu>^D!?kB#gC1P&&@Ig`vd?aTayAgrb^7Eha*w?S%%5$%tpnnzjb@#`3v$&}0oP#) zV~Ha55ExuQ9A{GbNZBfHCa6*|P-Cev)~NfsYrK03Id%Z!suFGH?;~_~7*`=sY$D^` zZAZ0vLlO#DQ_5lmm;q)epZH(6s!Z=HpsG6_xkxrD1^{m&B9y4Y_L+FQN9@4E{NSGe zVLOp@WQkaf@L6!^MtkzJ$ht3nFUUMCmsF`TYOmv7KMJwtJ$)?I+I#y1@s_Q5*evjC zFozp<;&OVktM;e2XE8Mx*!2+=a)IN4gxIFpATAkVusf_JMGt+9cX*gkEo~ZnIYu1&P}fZ zrg8}j1+W+7f~KGGqQQUGwHFfj^DglsGT%1^x9hi8djQ)*e%$M+B_XT;q*qa(!~57&q4A0j>D=A(#X)eeV6=N7)Dm6{E4jKYG3x%@^;BH zAolhD-8SL#@myqAdgMk?isA!&lgH<=tL|o8gAQhDH=Y7+|M#6Lc(0Pst(oc(N5ZsNr>(VQNdh;8QfYFlLU#w`TutXY{xRI z9fo3hjtoNwZGW2bVukvs^tCD91SLqyHewlheg~SS*;^T zhCp@pYln}QSP&gNg%&4&LqOKFOs14K8Q2ccS`Zn?d~zg|C`X*~ShCR-B#|fmS=C{Y z6rCfLzhVzTeE`{xxwWW&hyPgn(4aQnRg4aPwVwJ+(r0DqZ-1#V3rQeP6ZXe7WguM8 zLSxk0+~m9Ba48~htB?)q$^`w77`olW0&nMQPS)?VT#q`#xQniISkdd6aE}N44~`~Y zY|!LK7L(av$H(m3(QX_mbV-G@`;Y0)!?<&#;3}UT~Xc%yevP7 zBp0jgvJ16#z((NBSdo^9-7nSlYF(tH=f1FMERheQOpZdLDT!8tXC3YQU_Mx2fRG)#b6k z#=LY#%G+bo_vh>2@wD0leRUgOt`^}P5)f!%N1e=unkgV|-UvFmzz6A|HS5tbtgQYz zW43YK929zmzqUgEfLKj!A0FSmv49d;+^-+7vDI~WrO~^N;X=Ym8)|B4i$YGtw$Z z`!O7M3PfzNx$?>twf*0czsp7q1i%&QCFRFx;6XTR1k8O|ns0p84VvJ`u{Dz4coP))&6g{*iCRNua&+U60xK znJA9(bebveJ@U7*G$qY~dfr#ij|K+X^96x%ZSj-O;-CgV{eQQV7C zSmo*6ioyuN^PsIw0~sadmxdXJR*R#AoqUk&fDR6BSU$l8hqbD}0$P zQ&f-oAB3vC8A#QM5KhrGB$?q<)x(mZM#c4-8wih-5W9x1UKRsc05LCS3ly~LudG>T zL=SgG5BpNh3fxjmJy4V|Fn6Zy`?{iMfzI`-K(R8l!O`N3?TTTO z8U{$$MS)o*nZJm)5Yv6rB9*w2E)x%}8nMaqD{?Y+$ zCdY-~QO;kTj{ka1(K(n{`Q>rQgYx}+a|YLwQQn}!1E9Ff`gPFveKCds!XLW7bYOD% zI&$>K5%G?y>q2d)OU0O5%elvy4W$RY8opZ~y@npEcd+lv*(~$9@#37bJVdB;ffTmb z^*DzO;rf!1(eZ3-EfTmglzb%rY@|>d6@~xJE9qDRl2ksrU+8ZlDPo<$$iEB@<#)Q$OSywZo0!F8Z1?MbDg;JO)@aLDg=q`6G@>MOt zB{YSC*@P$JfMJa1duCy~yA%?9uv5l(a!=9ze#0E+vHc!psv-ajiC28#qAQ}JpTJ#H zk3< z4y+33=mH2}MNH<1XKgjU*6Pg@FWBnmcr)u|zQ3HYfXq*aENnlWBcm9{H+bTzf#vQ+ z?v3mqti7_gCP?@Lex%@Qq~PJn3O5#f%J(^5kW+F5%H(UEzM~+LTkq@OzEX z%cAB)x2pLbhQG|{UTx7QhUb!RW7KM4dvR57Aib=28XdQ|(?Z=`#WyUjTqX;Il*-Mo z)xA`=M@fcOeeSpcX`21jy(hg*9yhONi`-fG64yG<8+TE*^5JyLAc}ka`!XqlcB&D3 z`zp`Csl?n!NG1XWN4OOU`*Fw}w;H4u&$Ct)li;Z-nwLJz<&Nj|w2em(VKOho&fI&d zsj%PMG9V3d9nM7MMy)M+cTs=$zo~G)>hk;h03pp>W$;Y7^k=u8Uil|m78BX|dGikx z4rjh|()g}aaTN&s0qu*Jv}cT5JE-$=#O<`rm$HdFq8#*e$8*uuq%zRo;`@(rl)0aL z*hv0M$64d#C$I^J>4NsHAM_7#XxHyB8(SF`tE2iGHm;_k9R%_REue}4tcd!DpV!Dwb=SaA)wVf>iK62 zjWvEKevgoFx@q-~1eib!+DJXsIv62&RF5zTa009wABkAjNdC$3_}{Oh&X$(*c1Od# z0t2z;GugE>GId`DxFf#zYXiFNNnO5rv3+7$t5aY5L{TzZ>yF?6p?skJr`7S~x8z3s zD7!}S?XtUN+27}SdV?z0`C-U3P592iXXG7=XDskxeok~~ThgG|tJ{78bkqU* z!to}}E9_CFkuLA2-kX>Nh0=>QIlS{yScW7(Fv4*}7aP{l7~n8FrE^5}H4IxT6wBv% zbx=W4+BB;?1K6V@8avE->3@bYSV?dNE5f7v_+^0756(>85FvRZpLPZt^cP7@lXc#< zMc1!d{AcDZuH)O_KK5ETOp!M@RY;efwwo|TE)H0wB;ok{^GmgPCB=H}N2Y=4Kb7>! z9sxe;r^&A@%h=jzCz`)b%kHAy5Kh(E2ss{!krmFPU?>Qr5$y%fgSSkV<1Vi#>!(WT zqFH3ab!OA@?ZObSDK48TSR6M1b-j8%lp>UZ3~d^cYG3dw8GuKZR@aJyyiL|UC zsOD&{Tu@OD3RbXT;$cIfWN5!?1N|w#i=RDC8D`7E?+_94yF~*d5CkOpRt%Q1guSNH zO!Mp1S-;&mk^aW@Ia(S?B7Oj0J=Hoky31#``GtlvaIOANQXS#C*#Pgg0v$u@3xWFP zGn}kP0eBMPem`UvU>Xq^qEZinyZ5TJI)5F>2aTPh%ycLibW(!u5yCK@ZzFTuE`4aK zPR*8Z{SJV)62QHiZV1QDg(~2b*(kJ2?|TlnF4Am5k4w^|6gSOQ!Xzm5|FX=bU}~6z z7hl#%XvKKhsr+jtiiooKlJRgmuqf-0xhM+$`8!y?Zw}%g^Qg1OJo}9H9#@n^qE;!) zU7ZN8B*EkoNd&J8cQQ0xaf9T{m!*kh&Qma8ffq2XgHrAK%NG^T=dkftAP=6+VF`($ zH)tuu;iVfP`&}y*E7ibt1kx`|vq(4_BkSR0{^}xq0FIm9`~Wb*Zqs5S)_+jFIDH=u zuP_EJ8`@mMwJ%+phUf3Q&b0Z=gE%_1+D&Ki9Amn+Wg>o6oMnreMlR4)DmBP}X|>3o zas_JU3{*-+>n6S=MAF2&m5zLhwv9K1PO*hW%#`G^B1Z3lCtdxhC#Gz zjv{U`@|)?PhRkQuC3_ynfl;>`{FRhAR@#f0ow}q&Vd(W=$P%r}2KDdZ4Uz?v57zIAeBb zmdcjDS2Ym2A!P&N0Ly)a!!A-E_>%W;kg90b5AVd2EOx@fxIxcLE1%TNpst~E z*4U)7n`A=|vI5Qs;fv6j!*jaUqabpsJEhF820v4hRqw#ki_lA+C@2XE_sm`B)Z` zIIB7*2I@PocF@y_Acv>xbNlJ>#H4rtZU1%bSytKZn-WjtYG4ENe|dhf|KT!;*zVg4 zE5ZHYfo-s=x^`dE={$S>Tu)5K)7$L)Jp`C8CLh?VvxB?(`QexH9>i%o=qlznsj#$M z{+-N#LSw5Y_plc?Q9bYo5*RYM=q}1}pY`p-5Z02|h^c%w5g_w=bN;t?ZITjFB)zHC ztwM&_B3OoPySIDb9s~1QL{|rb^(tKo(lb*U^fTzZL;lGp9L~ZnyqX%ylj5d*_}^zf za|;!tSi`z5$Zpv?<{^0B2KbtpA=H*fGLtvaG z5}@L`@2HpvpmQhEEqbi&%EVNTqs_B5_ez-#2JLYYr@wP%!9t0BU)xrO{|0SwH4ec{ z*tzcHp~FSM1Enp~qE!8wZ`eCk!EpXrAqvUB(O!@E+Md{T>8B*Z5Dpi4t$+^a2cg$a zPjVOb-O#w+WLXBS@ir&^BI_&2FVIvzDc*>BwKfiocjfV5suA~so%m;U?bC!wQEdL$ zF7g7}KeKuBTRH^#8=p%^V|h+F?FJ`4yogd{t|Y`>f*iUUdVai>&n{?tlT=iizZ*W- z<>JVUVzWf3$!}a~w($g_KcKpks$>p*QPByxZNHCpFV&9I1FvE=`W6S&cU?ycSUVMp z%D2c-LxUQ&+PfYI0nLyb1v-V^_gvjs7KQY}XyvcA z<_UlsJ-FL6Hta%{O|ObG?8Q=dkbTRPbRV5jf2xCAqaY5>=E1GcQ})#$HGX*7hk4Qi){GZ6d1>Cjd^t~jrX>dn@ywrR>Z;h8Vt?MoJ ziY+-FD9^c58@&LwEl;beVw&>B!KK^y^O^=DB&loyN#sOoS33XW6)t9#@L|kwa zB9I@d^SyUy@AH~{pMk-XML=~-Xo&xVMwO=qznF_a6qpkMY{&HtDt#1usYRLoR{04TJ(v{9aRLuJ1&QPcw$x>CknR-ITJ^Tp=QH*szTb5-WL!^N{o9C;?pk z@>}n4iy8|Q68TQnVq&0rWj{cnXt)h;z z!gK;5+#xQbajJYrKA#{WVP+Tjt`lH%>5(l4o69#VnXj{?vT4%4%1~x}&0#$A;DJI5DZZg30zpE0P4cz;0Z74`N0+( zXk0gsh<`aFgsO5}y+w_Fw{WsGeuoY*=sbGmUkA@~6_`S8NksYJZ~@rc&Za#nM*blo ze6S&)t`lp9+2VV@8syz3M|xbC`f9w! z8vDYBgBP4=RGj70v|BS)j<-=erc*HJ>ot>;dwJ8WB@mJJ`8I3{u$44g(e;MEh+HUC zJN1s@YCg_#lb$-%R=g91(9lI6rD(?HUuf(IbP^{C|3NumJJY#w?cFVb{w9F%o(RrJ z1_}#yBoIglhW5!;;W(vTLw^n9k8h`Z`=|*8;cx|qjM6p@2ejZ~>DP#>x#IDg?)#ni z+Q%v^M-R%ofEF%zv5R0DYo@i3#wyBfw#idlE`mNS8mTc_T$`pVDrBw<9YSNEy3N#T z<@iEZtkTjpHm(`0VTn6}{6NJ)xnv|2`FsN@=Gz$Y616!mMi8O+r}^g4D4%~R?AZx# zMuy31x)`*7z=+t53l%Zj+r;%lLmL4uBP$ZIHSZV z^DP7F*tXrlTGBT6^@D^k_ll%u6HUjiy zz(U)QKFpmCXQd$m%zPn?Gly2I&{=CG`5O~6hfdRAh8;kI6m0=UfU9*l9u-800@~i= zXMB4@XmjxL3`BMXolCi7ELkS;4OE{s(zEXbQx;f%abpL9>zH?(GxrP=SS!z!c{~+c zrXIomfeJcJY4YTwUa2v$<3Mwq(uPr2_IF&LBz_Cc1eUg$t3hZg9f6qC+DJrd1~MgE zOhFkp)Clxm-uToItuo|Z23uFqC$#ySMAonW?Lff_@{h8X72Gk;y1WBOTVZp?>-xql z^;Sg9UDj!t@BZt}SkL|5zXZYoYZkC5*UaAs$G}hw(|*9Ia{mgMsZFT zJwAvqX81s7e54o{c7qJoZ%yX?yr4%)>Bc+;1ku8U$GQypkXuB;5WF?Ri_UknpN>?( zqV>~;hjc-XVasAedO?Ncf^W7mYc{lF_I0v&Y7NP$4fA>0@wl1}R7yvGSB>|3hmp;K zG};YX7Dg$+f=52a&wpgVxShYLWb_nYs1fU`Z#cEuNU_ zcgWhd;;t#{BVnihF}dUsSzqZb1p0$Mu*#!*~$`o5j>V1oHQY zH>9nEBklut5uFP&g98b{Q^C-Ezr7OyQH(iL`)_IKjfNBVAV|FfpN89shdbbgleCBV zgEIb9xHd#(VuN0_pFc`q0Ow3l0vroQ5#WShW0cA#!-hllIAHK;KcXAHw?$~Y>E4U9 zdU)5-dWmGPQbzh2P0e|X9duLyn{vvZNs9J;)M?1w3Sr7ro-I-L9J}VeQizWfg8F6;2fSPbMUPqKLuFve4*YDyX3&Zib$i1nnmk!NMptU(RjE%^@{bk(< z@9o=$8p3I~4;b?I0U7|mf%hYftv1@^C@g}CPK`0{J~<1xgmyF};d-etZP&aitQ7~_5%2!xPw!7J9teLsNpXNij zzBST(AM5<5QbN)4ag-(KlC3Qu3v68jv)sX0x?!{CoA?5aq8T6WDKd9JsyUzVY1i+z z_kjcJMM&*cgxcf#vqPiH=%&z#mK*@s5kDxoIWxyc6Ekv``UcxxgA zxMOqBve9XL?J2b6p=|g=;yVyEQFz<|86ZVT2LdIVzlbsS;<^&?-7ZIm;zc}fk(;2b zcGr}*$NvWvPr(RR%Q^p}H=YP?0~KzPwmr=sH|Yl|?`U4^6Y-r?5b!)`4ydnuB63&5 zcU!zum(#@;IZ{Q}+12N0f_O{-CduEyo2v$mvUx&1<~@pHC0-(vx`w|OR3hhmoNQ{t z02ZW8;jzssqYytn7rL?P=>Jo|2TF4IUJb3vGc|m`L_pg!%{sPC}q&3`Ptg)3Xj90YDlr!M3(G8zFnD`ytgmB+(#g&Zm@8!lv zsRJ-1nz=y7Ih6d-CWbD(@Q#6Rv6gItIc+c`SZxgblN4tG}p`_;)DjK>A z`V!M9F(OUuI=SC}xdflQcjo-q#*BUs@DGxcw4}Q4nKxHS*Cs>W`ZKkmGGS$EU95*5 zk*vCXtIFY-@~Qf=h@-ajJNn&k4agAz?v|pt^X9cxi;9$NdOIu4?!!MY3wCE)hG5nq zKhlyRsO6L-8r2a_fUhRpSkUtY84OunH2UVkdny^q&fBpzJD=`n`YY7*i@4tr1G3$( z8DHE~4yD{#PrJLp(q`azl?-_Zc_~kItw*$_06~m&M~!hEsW(Gh2aE&WnP<(pszI~T zm6m*hwloS%{fkqq29bP`HQT{VTg$l_e>TUIx$tu!|F7V>`5!IrAp$rR87cqcR@DRR zJvCtoDV;MB>YL=1Ii+@F*w*Os4Rf>VjD883pHYB{`y$mIepClcco-vgxI^|J=@nYP zYu&YLfMc^ivF$2NphoEXD6h_UfBgVqX~?)Yl~+GFBU!&o__2~h7182yCN!V~h-)ZK z1W|q`Q10x727wN~VyS6Ll>zPM=c__P5ol*5FaRcuCwYZ$JGnQPb3gOKZg-uZES%Mn z7TJen-M+@Rm-&6{tK#ve+ID!YojxvsGmmDPAMIexof9eW4IH0jO}x5DMMV@ zkib?EkJKSw3N976alh8{OmJg*E&(f3)|~kdM&fIFa$9+gldMxtRK`FJaLLxGE^Cjn zrY5&ZO_9H2v}*<#9H=+aYEH`>ixV7M3^B)gzg)2IR-gB3{{y3T0C{AEAAg499Kf>v zH@+Noibof>cr0c126U>qcxR0IaZme<2S~lD!oCaI-s`Ib(G_1g%96}ZE8&n{%lMCv zF}2HBKy_KV-l2;{{(S|3t%&q0t@qO}yM|0z+=CAh8b<_7_&0R*gnRPs7y-5R^O~_z zL>{znz+FL5aTsLk@Q>7%CKo&WCAKz&k-HQiSK+T}krfi7p>bsfb)~n1k1vKnEfFav zwD>Sokfcw@2fNjo4|6tRN34{FviJJAaOnJQgop@k)>Q_LR3L~1YaCl>DnDSS(vTkd zJNj3h>N|*v*vKE#ImubQ{`zgJ6sW#!d%4w~X>uH%TP;2?Xg`>VE@$!xb%Sm>@p7@& zgrqT0#+d0@)d}$#ZcG(KgIO~xEzm`r2|vhVWCM{5IzMycYf@#tIS+iJHj50@Z zkg=qR5RWUa{wxo0VkYz|ja+w$n>KeM&Ri~2mM1E$+hPRv^l-eahc&Yn)&eDMqP)I~ z=}QjLE__F4usJC>^^^#RApeRNlc?ky%x%LFlHN-HWYVVab<1P4rxol_rpUop5G%6t zD6_KA$F|ttiq$ab{%asIFixc@UeDO&J>@-xM9B`1JLwlc&u6ub&|zT#uYmgmGKCsT zOaT}eC24Xx6Q#=bI*euCPiDzZHdfOhTLeHrqMR;r+px588_urG zA747a)3$&I`d9g2VwDf?8*+t`$}@N(yy!eyR;j$tX(1mC>}9_I;|;pb@9X;9p0ML) zM)bgj7L;h-H*j1&G4fBQJ{oV6dEQ83XY+!@0Cg;3$F`+T1)t;|iAonewewVEA_u=Q z6N*MSL7$ko9Rt)BFf2j!OL!bM4{^IaIUY1~Ew8^ELoHVNRNMB@=#Ac4(2=0Jx2?Df zIW4u@w~IUi<{s6-J!Q54lJv}!EyCBmM3pjzCw)2X^2yKTc}=Hdj*)AA085VZ%U2>) zI3sLR-WYQF2-$}J(T44&9I{EH0Z-Eu*~jXBKMM`iYYRiAjq$w0)=uABCKqdPeEi&R z+;2UH*2xu(y;PjCl>)E+fQJgwYUxu+R2%2DM$i}>NnG>v5{;`el|d`?;!u~3#IUj5 zHW{nwDOc{T;vHuyTYEQ|$Nj&@hx20o>9IMts39jR@lOQ<#k1OV+|K?H``~J*pk8EK zxgSvTvVWmHftJKxl9!V4+Pd(53g&<7BVO1W&Q+?!*`zpWhnxMYk_&N5YdyD4Auv%!3c;=P@jqFLc}$9r^Lm-y^3W@V#~P$H==$jG;T7L za+b+B@>k_^cJm-Qx_?k7Z`bA&E8*C$)tB1n&_7rz|0M@aAC8)FA)^rwTnt}|9aO%k z@c{Hku_S|+wd>Rrb6;~^(_NvtNjU$*xNo3LEdxI()kRaSw6jC8O4QoUb(AhdGK37e zLPq@C{J`K(!^vN^uP8fZ{fxWSe-46kY;KK$rDM}Z>i~$o36WHW(qVdnTH4M_mW|}Ay@r|02;et*E86o%C(H+1wrf~U$g2O1dL4K7Z$-Z) z{DkA)xMfL#&iW1ud#SYl0BR#GYVs$<6E8i>E7R*nI$)SEN*te=K>`l7%^QOCwsKfh z87`88K)5Z8l@ZUgpE3l`s*y5MM{v1bvWdElHK~ac;2yXc`ihd|AQQhwz?}F<5^F(Y z2I-mbd-=ZkP9ubzd%!s={ZY|9lMtF)n@TkCoHa5PT(2CUNK~heGt6QMUD=OD3A=_g zQj~cc1HT`p--ZlyM^u&QesgxtI5Kfr^SYIs?K}?QgNX$F@TRXH>ivXxRh!i+@*e4O zXoq|jAKAx{@ zOFk|mND_B2f5T{X0bRC3baARS4-xd9-{Wv1+scuo)ARH`hfh`M&JEt(?T0Trl^(wO z9Lt3;^Qp9iC92_u(kFN?egHkj>RtCLVw+P(#W@>EOZ0KUkKd44`{)Jun%mBy3QM5j z-8;8q;ax8AAFj+Pzoit+$xDFafzWjGC&X~|)lTy&*8N;Z(|z07-vv|t>rHv3Kc99x zjfy9P=Fx6@Z>Pk@eD@2c-kdX0CGR>)h3nV;_jL&fT?jF$_7J@%nTBp3UyF=kA%#7z zmdb>KXpd#@r>9rE?G54JMI#@RrWGB|MARwGaUEP%z9$2%DI%hzMLa4bQu2F+r2{}I z9Vz;{xH^S%Jy64c?}ncQE(iddD(WfT9Q98|S7%3BRM#mm@xby%O-@L-y$ZzpfQhO( z_rp&X*XLzVk5{8l4lLVdjk?~xcLom zFDFIroZ>BT&{Pe2Q!Q1-Q0Na-(g=bT^&6b>+nr0Z{9VpepdvDtGmGES(xdVJH76pv zpc?bq{;<0N+*HXt0-+lWXKzWGU#WEkUT74ZV?bW|!us)=oSz(S97Q~J7M=HavLo9D z3v{wBcvCFi=#|yTnmkp0d{d}DWd)p|pXdJsa09m3;bOVD z#wq+QbS+v16eCvE(EG9CYuBDc2fPEahEP~!b5{@WhG1D2UUefNCpl_l$9)aZOMxq&Ehza2gAu8q@+s z)idlGRZzI5kon-YEK+mon~%>MbH2;{hRMU~R$Rv?Yjm9V0q6UP3{AQS=w&Z76s6}@ zk>LG6nf`u}Rj#JFjtAQ;2)_KT&wP)$eZKlC#J?R1#s9f&pF0a4BbsqKP~kc%-(zf4i1i>1;h3;GulS0 zRIE>|ah6%Vvt`O$G zN55{!xBj{`{r&i9?HZ?gkt2wq&Z<0E-G>QM)&ykIP1lVEnMz1Lx4O>gWoE8w^yJEK z1|dimYkg0u4=P$>xd%)*i@H*SIixp9Ll8w`C8jEAgHrm)C?T&a@KCW7%sthfeor&V zvpPl9K7-<2eF_dO%_Wis&9w?n}#FcExU64-86Us%5H| zc57Xs2dvQLn(p5U;f@Ln$E)D}LrITNP|Of2qn_qU3uD*mL|-Y<$_H7&a?NkB&zo&= z5wQ95>ix)Z^z4!R<}A!PBMGsL8Cd#@H)<>od6NO#>Is?jc!~$&p3_YJ!tjzOv7iy0 z$oN%GLIeBn?t}hOvqd7aVqUb?==$+La4Ym8GVJ2qHy2T=qe~oEk;vMWnZKI4J#gFd z{$EYqMZc@$6AMGZoXezM^=6~E2*Xx!(t%M(B{%ff^S@#Q7hU56%g*Un-^1h}{t6OM z{hrU;oMn%<%oy&I^t8L338KEV=`SzFZs|P~0nCR$UY&_vkYe#z7Yot{n&i?omB&tF zZ>n&B;rErb7lzU==vxUwKej080WeSitSqn^Y|yuSsv2|Z4D8bfBuZeQ;xu316cs+B zir(YFNl|R{k{2iKf-V*J^ZPQz*#4rnUd@6U7_uteb*0%e((uxQfPN4Nae0CD$wf+W ztIe5b_I$Ns-gBR_?fuj6Y5D?OT4k)Crx%~7EnNS?GI|U@L!xCHRjO^G)iX-G)cxExAkhE_h$6glb8pTm9hwCYdMSNmKDm-P?FNrH zfM<6KjmXKAQzXaN%F8x=sH6kBa*GL?!u%V{t+4Hb&^?L4`(KL;-|KmtZH=F78=>$O zUMYWC0|m;=op{N0QD3^-Id4NhQ*X&TlZ3h79-H(Xg|HPgjV`ps@ir_MS9beWg<8`j zu%lEi7qqP4+eALY@G0v;^bmN~^d@GAe%OdN#Px#?$Em~u&R}#F{TI}^%6Y;tBiTUI zuN^sci*mcPPl=SJ3_C1&XoVcTI~+Xj0C3V8v-QcRO;aLms@014XCxIKfqBk%)L%To zdq421VAbFEB$~p{nBl$Fft4mD8fQ=@ zfF%WA3#wMYj18%c`!9X%W<@TB0JW7laRpT1z!DWX<+HZI&Iz~}S^ksE8k=>g?w6Gd zx7|Ts&SS>}*0?U&v*oXtp&+XjGxiQQ%w0kJOil|%ph|2kQN+6q>E>@d6cpLfl|$D1 zb_=k=Ze_b153V&vxEk4aAXT^#siz(p3VHVhba#Mz>$EkOBU5y3`c@K2CF|z;lf&+x z01xIOh$DqD6Wmz84Sb(b^TPebyAW4=ZbmJO;vKMdz4n`KgB9P~DW^EXTqDTH^<(cd z=$E8#3SaaFp6(lZo!M9HWcF&<*9)tv#gG>V`kuTl;E(NHN+3G;I^UvZg z@ORA|PCSvT&`;G|w8J+QeaMT|5bGn_1~oW%-xxRUNilZ3$!y|a0m?j-58I8#bYIkj z0aX&I9+O`#O8W!Y^H3&Hyo>jXnkJ91=Sl_P*^%Cm^2FWLxX?1_Ke0U8jBczVw>@Zh zs(8NyhA&N9emPhltf1Z>fGl}~z|feF`pr`J_v)R#f`R5W{?fo$J;9a=$NhtFS%?HJ z#{p3u4RKb>g{aw?hTbBmhmH|^-`m=We>~B=@Mjo6Xn4KRk&-hhjDcSPo79q3QirUl zRasD7{J-1=ib=)ONg*_ySQzK|m^Qz}hQx^wiFysYF_*IvIW|73kGObW2ois2A4h-P zz8>=bc18Ny0?%^f9SG)~0JpYYzBpGx3!mdWQ$Ju)M*xnMRLB#z*`#>_{PqNoxoD5y z1k%uc%$>%G8?u))s_<2G<-LuR;~3)PJoGhV#K@K8vDtv|{KV z%=O!8jc|OmBx*73YjwT_+yDi@pTr)XV(D-xA{|)DiXahB1@MVsDr7y8M5^bb>G zU%x)VkJhYcb?y)HjDsM6WJbDw_8dH7>~ukIi9c5$Ih>-Cl%@U+pl_Mz8;X)O&#pLc zT;%{?I+ggIqhIX=?jIxphsa<2_rr?|U+VW~N_g4DQEWQ2f=8BaLk5;LFbwyHw}Jl1 z(UhbXwW36Wl2TRK<=T0zC@`1N046a2o@aIbCqD)hOd+Y`W4&q{Q+!qmXrAhNVd1b=Hw>9|O7HnRybn3E)eC^@|gWNTKxcJ0+jqJ1_h2@*D z)()(3(X15EWSvc-8_+%d_;}6^<22}jb%=lh+^tg0EM;Jd zCj||vzNh)`aGN_M)$gHX1?=+Sf8)=~cOuC=o}6_86!^WkuRyIo`f3Y`Ytt!N=%7hET=XSwCQwk&3t9R@2bl#99xPZ<=8YxS%;XddQ?T8>dB)5{dHwqp zh3=XTsSGSW2CKHr<~QWm8Q|>{Cl-B!so&}|1;}@4cMSi7B8r4N>G+n`_TuON<44>p zW?Bw4o#PvL`_U{o$cqcC&ZPb?g;8bE=JR@O*5k)`Gtf-6nS-XTt%wnyPE;UuO@tgz zDYe3m(Sv;FtEw**71p2m8;Dby^~4}JBw#E0g=pMR*Q`&_{hsxR*b(PtcB}uxhaPLw z^BQ>cn$;KRXP{$l+*Z)JP{S)&F_IZ0O)4((o{5$ znU+%_K2QGr}h1CY)j4&(R&b@{(KU~Jbsth%cOJe&}IStfu-Yp zv#7dd=~eyBwV#y>kQLeT-yVs~d>_6ha#^wdCkvfsYf~KauHK>Q44OcBxW57IYi5kO3 zR!eRP{bvIg)MsokSh0O%MG}vO39x58)QV2NNUhnENQyL+f@=M^idh0<&>7;izuT!} z0y<;hy(AV2jYn zFP^G9*=xIuD_Ym>8T0O5+COhXSAATGgjWddc;B2mgGT{?<;y~T;ue3?P`4i6r)suZ zS^k{+$e23F>nxjJ#)SKo~GdU~Kolz6p-NdV?N|AmY3MKIU-I)N8 z#Fb|28wTC(9|8yx$!>tY^B)es#$IHKn^DHNe;ig>XkKV-kWrLl#9&FfV+_aNMJqhM z=N$Q1Jo9wv@=zIh@5Ate|8qQqCb6qF%qxN{=PPf&l1g(@omGn2G>ftzb`dzI`RgNi3h5p8zsMJx}&5uXlH z%hHMt5*ZdS*gq4vhT5NFTDhxtru>{UYCzT(-*pf^oxKjKYY?t#jq>S#wq>QM!-^5crezfI{OD&04Hs%Y5B+g80J+#i~If>M^Ftk)L|0~p~I)=6qBl-O!$A7sruUI1(N+DB-tVTm&5k+O-I+Pp_oAr3b-Osjh71!g612CLLVeLFUi%Kbxt!S$cT`81rJTzdy{7?x$lmT z)W09gUwbR$m0m}psZ;fk1gz9IqYAv{NWb)@hm$X+ID-}-@A5W#)wUa1KV{s4%S_33 z$+qGvc=;cw{P;+_;5jk^vs-K!#W3;dFzA>*cNy4HUjRo)N{D)PvUK!?oqp@+=VICr zgh~~IlEXxG&^VjbVW%j<=CE1^no2f4`((3H?+x$kn#ECQkGr^tiW0h7va)$d(|Nf> zmN2FdIWd4j*nHQ{$PgyOQ1;I9@3%-r$Zk?{D3_H`Kuk#eD=RoNOh1@t+M+vutJ#Co zJ4yA`>=-=Zbp&i|CG|d@RwJe`CPn|{$91)q!{To={@9rv4B;R*P4QFhEX_vS+x6{; zeHMv-!<77i%R2mG1x1mb|u0>Ms&fsX&02o zaI@lUPYKi{NHPvKdk(s{Ed}-{~s)x{UCRn+wG4I=&Hld}x%E@JIY@{&}IOJAl z@?kveIu`3fXtFz|t>$3#E_3u|S=6@AvNLwSUG{nCh#89TPDb(A#cuQQKQlBX(F%>_8sZJPVBr&j)l3nSdQ zv7Iw3#osoBU3OS~06@QjvzBqOfGk+uC`tN})f*H5?{ywGFt)7bhWGt5qWN@)<}&A# z75@Z0T2yfV;~9u5t!H1HOOfz%!DQGi-M)go%m6QScUDp?`TFsh=EUdvm*EoqZg)u8 zud`pp;u?*5FkE4<*5#IdtzJjwif#60tHpzC*b8`D4DemO!v8vVJc)mpM#;`L@{gy+ zo!;pD%AajgeLFBEU8!)o;UY{fT(fX0yZOsl{|FS1%Bt$Ksjifn`N6FyyyfzxPDY*2 zi{T(ur8PVFRH4+m_7{rJ-^-u3^P@zwF7B>vbOaSH@Fuk2Lm>R`+Xx;#W0)H>#0|8M z_VN>YQli1Ke*G~4C`sbs6o{a{kpCsk6-jB-NEv5O8PiRby(N_cC(Ax22)=zHj+P{z z&_kj;a!EU8U=cJQe-!*!Kcau%@bK+oul*(L)#h@6Z_>Dp@-}G+j-Qz|J`zW!hF!$V zYYr?FZX&Ij9>#EX<;U6n*+kn}i|5FKE6NL`(lsQS;$dK`)yR9quV{M zu#Been^ZiU4qcb|Yk1~CA+biAm!EJIdmRjk&77te8lkmnj2C$v53$+R3asa?K_BfM zS=*p(ylLCba7njg$aKs;q0+PYyBCGw1}F<5zE$1)xpmyt<7&!#gEW{E z^lFs=-Zr*!{Cd8wk9W>)_vr^c2N-)jhVjA)8hto)dHCSN*h5E%%x{k(_tOfNTrv|+ ztPjXj`OWm@hzbUVAWM&T95PDlm}wm^SM@;!G|x!BYc%P@W&_Pz&z-lK!#_xPiVd+` z%7Q}dCEvBv9vW}~-d6X-aIdiZqvw_V0Xrt&dHq=>du{xts1*PgpGV?^j}AeV!8gO6 zK}dP;2Jt1cLH_Si0uIX)eq$DGeUCYGpKF|Cnan;iylbTcofKBl!*os$+`=c~06QB* zmXwa#$?DAnh*TF>VvElN<%Q>&#;WFWr5vaSL;I7eJ%|$6CV4Xjx+kD>2AuunyQv0@ z)>HaFAIzoo{+4Z9Y|>owxF$P#!Uj$v5{VGMSQrnjCUoOtAS@bwhBWIbJH#5=D_M7_ z{#PkV!g3oevMNi8aoflXQM!* z%GXP%qCTh9Rw=}+$6Umg=&Tbdtdt`kQpi{Vs;=EvC2a3=?(?s_JQbT}M@C7aqRE~C zb&(va!xP-rt}uF?{TIQ96{|B)5IzIt=NOMFh4cl%dqgH(JNi6z0&38aKD?rBp)6#% zc{Jrn8Ruai!HcjWY+vm@aKs*jbmF|{iIqQE?B{?>4)2eaS)I8#X}j3969`qb2Bnif zR>V%eb@|?;v)ou0k@CA0M;sX^04<(k?kz<4ZCCc_Q@gTwY6i!>lMrCXa^gn|uWJrf zuIWtDyCkSHuyqQ+85fsb7WG$q<-<=NNx5;}_>nD6)2I39zD@`S_XGJJf`>-8)Xght zZ4nIWVJ>^8i$;~0sqy?zRu#7vX8+pXUR7w>;;4_2FhKpW8gQ&Jhf{V{BXJROby&lJAE(lPrl2+!x4 z=U0Twap$bzz1VzXOzxh8$gbnqI?3B@g#-nQVC$24vi_rN6QSRnUj6 z&mLhtUZmrnxIHqutbd+r?6sSisb@Ln=$jzH{Ej;4%0O0z(0`JYAfax5h*$`Sij*Pc zC6Uy*KyYy?{O#&M*-CO~!VTvAf#eT}jBB>3b_OWs9+b81_%&R*=IkVhCsXMV4lWgG z1Xgx)r@MUtODtpY#;%l&BoW+xD>W$*^(f1W|L?0GsJ5lOPn(DA=>dp;(jqvUzc^39 zQa@<$El1g`{B@{72Hp26?5UQ`-e#*fSq_qSqbt<<%f%pqNq9LK-+q!5Hae&xR(+)U zr9X~LG&u0=%?xDdu><2*VNRlw;O@a_0;s~Mnn4d?E~28OgR$xNik==?kdu7WHEhv8 zX@BPTjsNnRAC{cB7X1Fv%pCmq0if^$Go#tJQdKnX*ekZg;-t)frUWW14GANC^D2-W z)QOH-B$4oqgZihaX(S%vk=KPeH(K%W6tFj%q_hr10Q`$T2%g6kqKu?aB(x$z4f)Xs z1Elan*#lcsBWG<)@prcK zeM(^pD(BGK=Td=2tk<)5ZaVYBlYN5-zy;j?>86umq7U<{g&Ls5*I))8l+zGy>M5;~~REX;Ov z`61gn%Z}>4k$Z66g1T6F_m_P`rHdiL4ur;xA9>r8>d!C~fuDu2(0awPZbk*b<&=Kx5wMU3l#squ7tNi;5{mla{ynG@ zSI`VK1}iOq#yY~D#Yiv_>IA-^V zJdK0#w_E}W8~Rkg1mc|khxzmV_7Y8tBoURo3VYNGPrhq-?&VPQC25OfE^{MGn^)Dus(Ie zDpf&io~B6VYHQ5DR(+9evs#Xrh%mg3E76%Jjaf%3A8ul>5HFWmW=~f1Wkv6r3mmGo z7?U70uPnhP%0<7Bx4#%~l3>h|gk%*M!JbbTzj>YUH5?PO5yt|6xDhY+CERLC*ll=# zdm8}~;px9YW34Gnnp;jWVLaszUm}KoeA7rDIwVc6tIDQp58zmG)Ox2nrY4k0+>zM z7f#e-$oKKP#>|1u7=bm%MqDGPzrc>ya}8v=e>SJ&K4U$4qRl9g3n)!BY8@XXt{q8X zAIyS^g8N1JzFQGrtX4Wx{%bvsn1H>x@#wu!eHO|v3P3LcoI6z94zC#190wnLI-icR z){q0I`9a^5i*M_s!+0k(kW()-9~^1zmq*Pwxg)m3-9vhY_q)JvLfs$Q-l(FAkH~My z+$}MHd(OxWD*wZ;hlS;}CU_U9O()XLiarLVOL1H4a*)CK`fb26Y_Q~#EAvS93O0_u140~b*{~2vDHEq z)e)H5eo8{==%R*Kx`vG8>g&IXQ4@(YvN1EM43mh5VyN&lhUe5{k5^=CyAdI zNG>MUTa{>GgVQKalTMu$#Rd%T!fs9C}whLkvYLb68O*J`r+vY;{5|GybBrBM$5g(EWDU+TT zvx9D7gKe@}8M*V?GIBE^D+UhB*sL%IN`Y^L`g|g|KU-dpr^bX{@AEun&M7?j6eDp> z8?@o1zb~3i@k3G_r_61cl;2V2n#k}qG=jbhZ0E4nM&c#VQg#W0pHC#aGQFXql2NCe zZ+N1KYJ6*HGHv06iGYw1cRnDz!51{<0+6RTQD1$f!{FFajMKAoHn zQ1*+&u0Z-XOL-9G3hL&=k?Id)anr6pM5_wKeObaO_XTp_@+Kzcp;F(u*?mUefbhKYz_#^uF z=!}lrY;SKrM8o;~F+VSG6O`H5%YyO+Phd4wFPZX~CNUB_6{50>3eSOm>Y5$JAXYf8 z4fpX$6{3q#as7<{(uo26^8-1lzVRl|ZOxTuAvhN!{*k4Jzy14&Cmhs05W{-q!C{Ds zwfRMbX^k8{NrDqLZs_ADwwAST;%^v+>3fRb5q}} zJ%*0rkzHjy+2})U--DT(l2;En$*Q*dpF>xnXsUh7+CvZK?EGJPVN?HyJpgVp=DESU z*zG{ed{33DzuT^};~$Lnp^Q9!pyzp#hz3BU+JZa7%#HM(6@k5_5w%X=4eZEctP{c6 zlWO44Q&pu?gJ=iDTsHMzJX+&j28=Nqi4@&PZj+TK+G&%wu%iulAU?;!D}01@mJiqv zINmMay-oK&SmTgw>i7o!SN9Vduq0|Q(mU~y0jl>20$hhk{XI;UKTzx3yS;I)-G1lK z-HYY*l~HDJ2t+1)efYrbiFEUocTAyX(v-~PefvXcd;{oh0cE95 zxOvDnp9baMR#g8Zc2!(T>1AJ7W#Rfiq@s%^|H9TsvH8=CVEV}eDO&7+)~hUSQv$*B z{Y9B9!T*jz)cR-1)pGihaAW8n>#XGq3l3J2(J%$rDB(<(?t7siTKHxhp?ZG5Qu9G= z?k~%q=lQD0+E-}b`@Iw9Yo4Cj;~zGbW9?u;#TqaB04A?0e{b_bsEq52v90&NrKtZ+ ziTuZmfIySRRlGauXLejn<+he+&2O)+J|uG@Hi$AItB)>(J^DkfobF2>3L*zx!HL@< z#C?-8em*4!o@ZT_(!};+|J1|T%KBekLJlDUIBr`mNv}A4y(Z+EQpOe5C$f_nB~j2n)NAf`(=zP-7ed1}Yh#O-wt>V)>2uJw(cOcM!;FkM zZRE$urNuUaQvbgR;3Gp3l}as+#cYwm`no7uuf4PJ_s1DZ#Mvslt7jL7WU`tpX2Hpj1rSB;c!pVct~A<8fW&QLPq;~1Pl zn+)1|5=N&FIz{!L?Z4XJu~_cU9=95-XLwlaZH=*?L(UaZ(%(Tt|6h|eBSH*Y86EIU z6S=Bjv5ziXT?NxYs{kD?8As}Xn(xX;x&eNhQrkpwJ#P>%2`;e~gXV)jSlNJ0X-e2@ zQ(_GWys<5B)7De`yP7?bwyO&f z+}{AhC({JcL_S^BWF^(hxbI$T!q=sGWpYdAj~$414FI>y`HyjKmm_#PO`GR98>2ax z|Bq?-tmAy-p}>l%<}ZIdK`dKrF}Wv@&f}>*J|9G@AU_9Sg<}g1CTbKd`pDgXrIUkJ zD8XppO|F?Js<0L#5@L+0gG2d@Yy;#!8pUKZHp$xwAM`_~dZA3n&53M6BCM!XF#w)Y zd8`r)@j&xYPwSi)sBZ5oM~8xVcx@fZotiL=aDBHT*C8eE-`E;V0j&Q31Z`Q`(NnuEb>-##TocKZg?}?SxS6Lnp9P z0XUt`fSu&Z93zB3$`(gDz3-G_WDr$D&i?q=h?3s*H-iM0NJkbrS&tfqs2t{Ly_gyk zf*qY*1OqQx_uyWaMvg_8fAaQ)nfPmP1DR0U<@9Sgy3`(Po?M6c; zU!8=J|4h=UJ%ArNpl@UrqoTkd!O+D(M#&5#l5b!l@;+wYiE1N=FvEeLqxq$g)N6MZ zRIk#m%gjHP1ndlK|23aAcR+2w*6V=`08uwB$A6i@j(G9Df@;2x@-;tOFMW#FgJJYs zPIS#@K|kZ&>tmr)my=3&7uATia8`p&c%UOne92EG+Yyj4_^Y2IXbfyZy!-X-!3mYh z@$LI~4BS@M1O}A@@6BlTWr!E?W-4usjOg3;mX!`$Wa)W(Khi9t zP3PL7iHRa!;_wYq9JuvYa~EKSa5qE!^(n{ENA>JJK2A`A0Rf;cC@b*iwIg;IZ2oq} z_?CCyWpsS%^%s$B>XirSGw3s&C38kWGv-Y!XQSB(o~a^X%Bl^nj;*qLySSWP)? zhWZX}AC4r(4u$AIU7pnboOSVyDkz6h zbD>{G=x@R^yGA_k%~!4T*9WWJ{gQi*>N6>%tB|K){Wayo`1I|l$N~9zV+%E01(%r< z{T%!Pq?2WEN}yUUSNpXS6!X3|?a2<29rxIKilK2#ZD!X>+KwX&3l&a44jNHhRI)m@ko{qp#Ww^9+CNe1mj^Eu1RO@>0O zKJ$mWffl7jkJ&gS*iZf zZGN*3;jI6KPG4EuoICL32(b8UkiqsUD{>~N(Yyatv@D_%Y*|A=2jFD<2Hn|*22+a) zYu~m*B#CVBEZT0wev9ADn~2UTh5K0@oLoLQ@SMlMu9bZc1c>>Eq!3dnWpG_F-Rdlg|=a zOe&Aw;pj`^-LB!1!jCyHYhZgXx|mCFy04MHHt_r!7;S1d4ZT1t;G!>xngiH+&o#Va zT0r3|e%baQxE#EWZ8ud15WZaWps!MGFpRBN-cNn=2JfC3xl}S(%h+S~nY-9udsbtU zUPyi#T{Axfs7wY}4)`NSb~)u@(R`ZpX7Pl5fV(m(+t}(heHxzc*-{jwpi})B^H?~( zDZ4|p%F}q>=I}3?EcCN&+e2P}hkt!6XZ-hFaPD}_4c!w&@}9`=%`yi_o3@|-Zg(*? z^eZuXlhesU7O+7<1}Lxvj-VgT(I1*uOb2CjH=sp#m3b{#F(lKf?I1M8DqYon$|s}+ ziio~V=NHZgl}ynyK?b`5huYt-!ajojKZsf<>CDaQCDXEA!Pjr+2gQkNzbZ6098k*A zJWw9W?_zsRy#f(Gat1L#B|t!c5#f?^fGz$3L;gq31>pVBR)r?@J-z&Aaf;usq4Jj; zN%l4?tKLsx0n5vu$O(?b#VBMHI0VR3_rBxKLV_E%6pdG0iMU?GI8IVE6rfI*S%f_>Y6ek)V`i*q6C-Q5a0wNFK;#tL; z>6!J=)`3+-t;CJmzC0KF18Dy>8$Vd?aw90kwI8z^o?X~)v=7M`p8S|fMyV{XST2_@ zIU$&huR16R^tg#=Z;Ny#g$CLSFQIo&zN(MIj9y}!u^+;MDqF9)a2Q@Hcb>Z8i8`H3 z-d?7caVX-s+zSG{8g9_F`BF~YN@04nZ#h9R@&%#1v@C4m%pRrs3^6= z$;n}#v@MG+YpMxykj2I*B=-$dz^Mx~E(Ibjea2^u;GSFcafa_ev*X>rJCj5C+w1ZA zfGO|sxz{^gPVnWVEJ}-5&B^K|`DmxM`%Dylye3g()BlD(HQb74&?D z297I)zJT}!7zFNAg&|g6N>eMd2`#BN2yr#NcW3VF%*WU=HGgxf`UIj@fSs$8Eh|)}hDg#AN=v&q zT4y%An5z7+dW20SA3_eFN5&at=0`7 zZV2+G_faXf!Jd^3|s%T0DYrplhYxl=hpZPS3R9q(>?UrvannVo9)?k!<0;B8vQz0wxDabh0@Q=5+XYQAMxCA;98NVxp z$N2Ik`>8X4J6zxfLW9BTUOCLGK{wwu^4Tv9x>E)|nViB`*M=mk#9&T`o&)9ryc9G8 zEi}vkD+3p$KYQfg?FQRN&$Lb53QG>*^3WSQFDs?~h+WBRX*=`l{RT$Ph#NqlyH@m(=c zlUJaFx&DA0vqwap3PB0xwzBRl^x*h-Yhs12;;>_|7{(zo)5>ilH2h_tqaRI301wK+ z_P`ftW|R1zTG?N&Mm_W3Ht8#I3v=hci98sI$E-+YCANWC)9O(Y%lb~8H(t@Jf>?;5 zJ2Z#AvIy&%E3H3tVQflQ?EQk4TAGrh(DdUgTY5B1T5Z&+OTp2a= zG(n}(w9QEv*9H2ua9n~fIad&$p*zZBZ<7CAGwpEPNmVa{%%PCa!ii!URumZbs?saS z-yYcc8k}A?&%fTPR?omBhFvQFZH-|a-=B%S?B<#ualt<4Kf9p8MbLZiy+s8!GY-N? z7_e;<@6x^1_%0-+Ey{Sc;)yztZ8gJ>Z^Aweopku!Gf3dYg^!9)(ddE_x#{6_!DfCN z?z5#e;nw11q@h+0J7@cF-{?je{4JZ85tjc#vn>5h#{qM&vNmFp@0QcA784w==5L$jHDbbtyGT!;(-zkS%ofz>9i1q^^ zyJLsH+-W=g5mYBcjI1U;{-kveslAyv6bGQmggjLQQa9(S{X|75*|t>PpddhX!Cvnr zp7#U3us4DTk8=m2+xWcD>gqZm^7mOR8RHRj0eA z$){%hb6SJuQ5em=1X~RD@hfpN>VOdK4b@V5Rc=vHb`wnwg`{G4Lw(rdjffd&tnGY3 zU%f%u!Vb5IKG`(K+#I12-<$&rRbVEBxp#wuMB0O=f5J0Wuy9JWrSLS8Ju?d(t^z>WN#<2gvJc( z3Y%aY-mXyP>>#j+RrE2tT(ErRnxXfQ7~}bMzg;dUhAI4t5JZvyn^e%3X0F;K^`c4b zXN;cyJv6F(Cic{FrDi=2oFxMej*jnNsZrnJ1oGN-mVQzzk0Mg(hyt1SP|1*rjLDt( zqiI-p53|ALTf67QofDCQ20%^G;%a~!0#15vDZiP}ge#SY`#%{}ek8D!5-PV8D!ldO z_;|l`(DoqKyTZO~pevX@s|<#f>0)xoM@+MMhknF_v(gVbQGZLrXb}D=TrvO(_fDM+bDyrcZkAGkBS&h@bejKUS*H!d!;eQ79+{b zt2oR6M1c#?5C&nBK+C;XMCBMxBBUtlX9*N39F0qk5JU2Yj&(uMKq`OVI%L60az7o-J_2h&8TnH|q&+aEgq+8COw(fVIMTs#j z3~4^3F(^)h^sb6UuQc2ZNcSfcpDT;XB;|C^NR*OjqIh0`e}@0D%PYF7qiRTlWYe;s zZZQsm2~&DVVdey!U>&Z_=Y>eI);9J78(dQju8E|)O<09NN>*pTw_;n4NR?6XX#8iR#k}I(|K|GXBMztEQpEX&1XDbI>COBbD<0*B5$(^X4V)mrL@lBN zAMcek_Ef4wDPTY`JqQCO7c?djZMa;Lj?#p&wZ9$q!by33R{v)S2;%h}V`+y!*SFY+ z+Ao(m{|CCR76K{NqjH66UpXZ(3#j)ym-7zpiK2$F(NM%yc)0(gxp+xv;bP&LIGH4d ze_=1EHcsskV0%xp{SLE}JRo?^8XP_lw;NjbZida*;0xQg*vL8I>U@3D-!kv!j@6ZL z9HP-;V&MrN+aJUt7p(m?iJ%x@wnXC+K3GyccH!rItG&VjJ%b8uKLbaC zDtAZODTxJDJLmpB0KnNjkSK9~*Q#+SOjsS4>zDBY^bmW=?IcJUAFja%T$wNRRi?at zkhta?jaTHJ$zT!d-6`dLG9DK%c$N?Xf|f7WxGV81K!6B_ zqiUCWQO7n0^_Ba1U(6ef^st|kRnN3zMs&D?=LevQk}4u$cu<@cT6%$4`-X9AzWAKO zPWO^G@BLmF$R6kpIc&@e-Q4)_enIeZEQ0K4!8LbxG2eAPhc(3o`D+URO`7#%Pjd}f zX!A|-=A7Z2+ROzNP7p>D!A>D}eleRySi3pyxzQwn?9H_z4)q@J&A~hT99#;c*@n3E z(mEbsHD3N^kQCdM7elL4mw4BtoB3ws?>#Z$e|)41>J~ z!Y8~MbMnKVyIv}beP0A) zO{AdsEY1;+`L{J(!Ti^&Icq=Um3b#%%K`}zIHd`n8Q}M?{eZu$&5%|(EPfzboeCwvjAxJ1IpLj7>xlD!ECX` zL>@(9+PTvs8Z~;)x5&kfYyaK#c25+R)RusySEw15sYI^zl)?>?m~`X{gc?duI`EtT z^OSAm|GwE*D|Wn{6u*8WH7#)R@diFklA7Uu>>OEVDN(Yzog$LO-|A#i~zxo^rfesJnnp7=|i6A`3z&|<5R{ke3 zE8APMY)tI2j%z6<4{WQzV14}Qv!q*S55&+gF?28T-rOZ>Q~yrvCyX;N5LJ?bcCCV2 z`eB!75I7Q=j2|`9*wTjJls^xM5uW@or3l0$ojwM9@$nYHK z%#x>@!GrOfCq|_?!ZEfBp2;qsF#G-G6vJfG%q0pK(bH^xDSnivvm)Jjbx(^Ae3r{- zkHSMUh`5Vdiwa{yS=9Ta=_My4Nh>|dg>jGvT+a>YlW~zMTq^QKEk->@MX({jkPF~U z5ol@fO?8bh*vGAtdFdQS^Nz>pg^rQT=NLQfNo|7_kmjxKmv$LlL;{D=zBG6vXA1Eu zld5#(tj9)u=U{SqP}ikk3V8lOeRnbVv&zVAZLfa!k8It$${`@I*jYdgIo_S$x~tsh zNz&4@gv*GoSZ`(nN7)MdO@p1|H2fDmTtkd0SCntmn&!|b13vLNOk})(hY5i0<*%hG z69@$UrO;?@imHPeVfcg?7=UeRe!#$;X>UP5V5rRXs$FGjR!Q422C0{wa086*Wz@&* zm1$nRLwO{Ie*~-Dakje^M$vF!%Ba7n)BkUs;HlhC7V)a{@V0Rblvps=d3l`dgu0&! zOL=)yn6(;!76L@KBV0>BWL+Hn0C z=U<#}&dr8Z6HSKdr$1!)h*CNwzTY10Q=CGVK$o=G^Lr2LdZ;PsKG&s*X3gCDMou6V z@r>qsc{0NShTx)-RZyi$gy3w^&tiR~bWj8rmB%t5hmYOC!_Kv=zOixk5hZcdrnq^D!=&9iGccX` zadrBTD^_5-qd(r8w)ZbUZohG{jZMS#CffTkU`MS)O9gzAhb46^cOAtF39AYlGFbxl z3BbeEo(p)3OY9Yej#xZKK1M7MBznhtAlRKi2;~*7pa;gy8SULj*-ZVtTx>G~fG+OY z(Gh|Jj}049S0SQ|3!K-F)@{QMQS`@DiDU*;2#7ENs8eS&-d~5e851hQ6EGCSK3tmE z&^^@7>{k+@uV2lj*~QebvEu&mh&uZRs+OOxFj&%e8!yECJU<%Z9;LqHs5rhF;*dfE zIRR3H$9%l*>(d{dtocNJS!p775-JXcK1m;}(a>1>b^NEy`#7`l2gryEqi|)%6lhLp zF%)n?5PHb^x#j~GlA{(wvk)9_+v_<*XtlXXIbzHr<)R7g)B0qn;-8 z1YW0b@SALIfp8qH_=s|dF;v3l*e`ES9%||wPr+wC6@9zDI<^>*Vn=E>Ry!_u08uT5 z>>Rb=#M&S-gjT*~RW6;`YCkbu8n=1Fwt|-mtbc%8>ya0^5O@x@&+6>A;(19_0A9JD z!>_%?7^o6}2p0iziNL!UP(@&kqT3O(iMm<8F2_#v$=v+Z@l-nhZFLQq8hot4<#t@> z#YXho$z#v&Z!1V5r1{9`@f%@5K{X3gd|0}=-xm&;TnmU7iwZ&Ww*68kM5stEJjl?b4A{d9^y zt~RvPI|{Wgd&zOgjt>NXfzyy$eYUfJZ)yy(0@>C)nHvuhwD{9+;b@by~-t ztKRmmM2975^e+=3I$OG`_IJWTi=^%I5&Mdj*>KNlvEJ(f(>>(SL`Es-8O^tenY?Nn z4p4Uq?45uo-u)W}-K?Cz*97=ApolBYl-fQSn6P-5up04MuMSE`jJ4=#kYK{Qa2&~H zo>yLf#mls57~^G25rP3?N&xOowj;0<4F^>ODJYCXmlD|Z?!+#&PF7WWXH78}xQ_kb zWtq|DWk!oS{qvPRr6X5b_f|oj=9ANcy`=$9~{7;i=pPeDRD zolK0hW&Q;lRo2%qhFrJl)6N{2B9l8|5@_9EGJkD%`|+k*(XaVt2u-mM^_tasFHrVF z)4-Tch-&%{!)`o`;gwi2I;}^t=D)_aUVn2}?;Z~F7~OB7Ox>QgF{>Y9yF$9&@QPD^pT*i8@*p0TbC*)M3ap7I-fxt6BuJ|K-DIWpi zQz#;`m;r~ay^~W(A`p4IT?#u*lxzdMBvnyaOsK!^F{W0!{p&|5_x_jjeaf%zzm@Tc zScW-#!dA=kbJzi!g2{5k`r4?wld$88%m~SJAR@>Dx4+{@-|X;IKJk4hei<=*Ru=ly zwAhIDPfm9J_Sd)_FYCTzC8|Y4RNX^^QNCNlX6(O{AFt#4Jx~uYw!gQ!W-G!mW}okLAN+4sDMXGJcYf9Q}rAl?Y%1IEqBIzSGZX`YugPuz-2pJPXg%lAJT1^aq_4 zGEtwvI@$vQ4I^ADqPvW;4k{#7`SHOY)hddL^rO7~$2!wSOFxJggu{N%-O|~b!^O=u z?YZBHM_Bxef_x}`ntCU#fFBJM2U0x@Gw%DKokn6bRBK%lj+86c;&+I8@o-?GvOx5*BT*85V|0FEl2SUM>m*O?)eFC z)&zxf)T484&$FXfVV9y@#qc}wm4_YN3A~D#L}2A8xIaHb5a)37$~)koP2;`ag8u!{ zPWch`3}D^Pq-^I2%wPBuY~-xCYF5nIwXBQ=o&wOHxF+6z^Dv9%-hc2}z=-(va0a4E z354>&nY-JT@ll#J)X08mAdcDS1?B<)rpT!(lWhI?Q`Q1&534~;*u1*BM4ty01eEK2 z1>o|Q!Ob5CVll|3Uw5NWZ6Y!^yKvqO^e{?+O$8^{yt22LV!r0Mw@5YaR=%FOJSMkF zHa?FAt@z6ey0D(>YflvKjxcz&(wXuv|E|~B;n71` zgJR1qY#b6tfOx<2)#cy6P4Fx=ge=6UB;Ofm>OO(*GQVMuR~pNblnjP!j0N8v%!@<( z9*&NVhe^6&hX%CqH8ZzUPWlAZOSdI&er8iqxWrju@25|tD$JSX@EV|R8NfW-zdbsD zAFcoDPe|3M^P5$dem6D>HxzdpR0IHzSBF2}w+e@Nr@A-i@U{}jEw(NX+ShB1p#e4C zgVKBO8NT(sbdg0-;J7_JVdd?tbEBp_u7GLZ z+!ly$0UJr2h3*<9Sb?_P)g)oxY}1M41~~BYe<&PYf;(5k!y$^cPhLAnyG?YMF=F6Z zq}{{&J8a49#P?`flN&vG4SRhHx!8WV{RT%HE8q8dU6JVJR|>eq&xe+!+-T^-52utL zu+@=s;MT5l^q4vs!M2i?W_h?=eIz`=Sb*}}qg4RHD~$S{y68I86w*wRpMrr885uMg znULVO_LPG2>X!2OArswmM7ep0!dGCW)fa0G0m@TTvu!Z z5?NjiPMYqg8$fX`HBnWFe;W-!PHc-{HkKdPJU&0}H7^1#_yr&;+7a{<`ACq6_taID z6l%1b&k688aK6a6_{>~vvc`tMt_lJN%4kBOuxU*(zH_TqLkU zM-2|xP_~V%(cn-{hJ*3k^fN?!NwHmkCV0884&YjCjE+QDDxh%CW8Av-+L~$ z$SbNs(fj!??awiFjh>te$fQdx5yx}s+VHC;p}pXJeZMPexRChvyTY1V+MAXICc!3vSp_)b*TDR;bOh?cpe};U| z0|X`i!BfViKvmO+BzFU9T$J-15I3d4!)980lB7&kvWOnb?fqo&U~k?|#B&HZY#Hy! z7~}^W#8=^{>a2ElF}N?AZYY_Y-$R4Zdz@9rwe3P!p}b+UCpk#oN%(S2MWWYvd@oxxW^Po zy<^0~V=z_w`t9r2`yh9`TR7Y?{UH$YafQ^*jExBM3Or||roI5k*$X-$d8E9S-gX&P z_bvd&De=y>bGuHtvl4S#d3|>`OvR#|v^ihh%AfXa?|>tr>|*^Z*UBXb*kD>( z!MDXomI?xpcz|EdGAwZS}Xmw4AdPxF&z(pS=8yak}E&Y$95O&Nyk93cOz z&C~VjC%;8(Rdi71izhI`R1=q$%CZvex?LTJ3pRW@t$VT(6#@@#f^M;ra&yHhgc8&+^KNEam9VoC!>mP78_T^{OW-tN*@=Gmse~t z-cisirVsd11o)yB&*rkBpG9?`fGk(MY~Np*nFJbENltuNTv|d(s(DF#-0((~(yPb7 zB-Z-@Fnp-#Z|rom`m^S83s2|4v(#_@14D)iJ{F$p8C>SC?FghPpn@H|OL5`8c51*> z2;yz#nGyK`Td%5{b6U=e?9wU760Mp5rK{=riLUNHQtiFC@xcJeTCluP~ z2F2k!m1iu>A#_WURD=pE3hbDAcHd+f-vxqSH7+U_4sShPsMu)vFR z4%m`JJNl-b6Fbv5vso6ZAv8rnnw#1h`c;h_y z6~?;Ft8Fv7(D&w^pn}c)EY8Wbw?{3c7tI~VSO9>;Nz3N<_bLU3u&uQc!NZ^T z!e99e9a6-JN8O2R0pW(nyN1v>;%%m9YtA5v1CO;~095VersT~zI zCSqx`st|!DY?WGhi;!oyCU$z%z5+hYSGjd0tds%qnF}Dz>8fezAi1pqI}XK3*Kc>p z8$aybvi#jpl(={opvHH8`9$b!&fB-IDCDHx9DGUZ{lWVbPx-fx^uT6U;e~oyQKHH+Hke(xkMzRl zok0)X7pWiHPKm_5J{UnBKfvfHz!2$-Pk^7UcWt}Q?u=f_u^DwC9Ze7eBDCuXFE2WkcGxhkZh3oI5 z?!mJ~fLL<~;?g{gUdGI^{Kgv(Uz`~=0S__wZwQ2Yh?yNkrWDH0lDpG=$aO~Vj) za|-6+Z?T+0W?cmY1DzZl`4$(M@FQNDx58K{5XzG{)XrP9Fisg(^4k>}7%mn86P)=L+jiV7_#b4)eelHM*6Y(Xl!5Y;5Zyn$va{)*JXT8jv%N=pEO; za&-IMF2e9JxXJGpR62hh>0#R6BQ6_9LRje|j-56!Up60LmV$?tlP1qwE~w{3=An>r zE#?#Jb*?*V<6G-mVEzP{PBS;Nu&^<+u`x%+Hirm#UZM5>M9{kfc7bkW0|!$aPi}5& zGX;T-OTkQ}rB4z1{JgT@0~$;!U?psK_u3a~OSD(Z&%X)1-OxgrgZ1L<{hCblZQxp37G}q{a3(0(1U5S)rqEe{fKQM5hcR*XMPtXu2XU$Dut!R6TdedJBFdjJc+ z%4R+9Ue(+|F9zn~yZs?&E?%M401`o3WXS;Uz)mB(CYMLcd zvCl`@Y}^(7HW~7d!L<92`qyo_LUyjD1A?)Z ztFKtbxzL@cS8cEdK&(2@FNItN_|VgDJqP@mB?P5D{$<=D)}=o)^T&ca%*hf#fTluJ z+v~EUjns=NtQsWHMWn#?Lr`cSQ z!TV5@Jp0ADf@LJ;4pwGR*BIQ|lrqYGt3t=r^-2Bj?rS3FHL#H=wx-EDx|@R+4h;=- zF6#|vYCIaD_?6dC$$$=^in`98HiUmX4W zGPjfGmZW#>!_hugCpqFgs^h2(B3U5u^J}`4`BFzuaQdK8Y|b4+RcXGS^?Kp<acFKQkcpdVwXt*tTJ69(3Go6T)TabMbgW z{cZ2_89`MMyz`scFC2aK1o~r7Ap=pFNk6R?$lFPlmKP{vhC?Q!K|QIjj{>U%4~rC) z44!vTo?-%q^kM6v55`bp@n1@C=waFL;qh+IiQB%us&shZ1GN#Sld36-@@f>>g+Ezy zb%WiP7n^HWRYieyVE|ePZkTDcdRYrHN_Y2xP&KTU2`~j0lquQCYm8f6s?W{Iv&}o4 zYCBYFn?i82lVEaccLFX1QN2>ux_$QKV=DsDE-${tTj^JC_YRdP&D+OB8o$1;>{B(xA z@vuK^XYh1}iQ&h%?~+Wy;)aB@ev8gm@FgqB`)*|13{v9bK%{kPQntXqMLOd6L?B=T z92!J6SXQX~EskGT9CCp~?L(vxaq&)`^&(!9Frol~cyN5Cvng*f9W$a%uASfcF-V%$ z+V%3Lm&28z7Z8S^Ik|izQ^E<%}Q*EIl1@jET&J(Bp>{(X7YqlBhk1WtCS)y9418N+;lQ_!`AN+ zukb)a><#%3K?1gru4rg>LC-LdBp6xjQSKt)H_Bfow-y_O(WfrnYVKXJCy+Y z%~&;V4iQ)4-A}(yfBT(um9YT47MAW0L6Ne zjg^qY0>P~R1U7QnposoTPD$yMqw)G-E`(sVD)*aR+h1b3`tqu~qrVuX(pga-0j)1PJ4D!2 zcJjK#PnwM2K?w{-JO`nwcXJ`pFkOB@5~i_%tknQsJ$+r`0^{tGeC7Xe}) za1By5s09q(2=71BSWA~8X)+OdHXk|pFtxj1vln*5GPTOWAYz4|270ywdPss~>ZJ1Z zrF73#s7!vW#L=7sc&H5Vd+xfk|74G)2nWEz6hP1da-Ke0eOnt^&u)z=lTYzMpNhA| z!>_BNvjQk&jVBsTSXI}faf%oZ{7wJ{wy}wc%H_?~g5JEXt%fPWp33SW95UX_TZQ5E zO@^Q#-=cdO)Pw&n>(vM5)0RO0zf&sQs3A})gAEkpyzjp+M{rg?L zL`$u;ISQ$Uth4^0=KhRVkRMrQ%KB244hJ$78qc!zI{3s@C_8#DQYX_JG?OLhEIbBho)6FYOnzs(&a zG#(o(gvs;@;t6Ku00>HRAR4GVHP#c9{Kfo-I~Rn08zWdP=azY}@&H=MCYkg|T?tW# zK=|et{18!a&>4{m-LC3?6lR*l%EC?Ba0)qp^hfnzC*a5?`Qu4KZKN)RE)Iu|&V&l? zfN~x#E?ycHa|aI#8pih!*(7d(v{OBse$;pk;vpDuC(bDdI zJJ@Q`(%1K|Rr3ZDqJtv7CYyB)#^wvPC|CJ|1VeAzm|?~9)Z|fzH{gf!st!!~{fA+G zx~NXzYAQ0XRk@ZB2nq4Si-`&;djh>ZH2SE$;Z-<|t5FKnN8vS4_WHX zG@&9AV8_|WO$R!q{T}}7_t?jA!yC&N4vWQ^Fg!@ zG|pcCf_NDUj=n`M)#?4&uGqn}18mMyfMt%rpR9c5l+JxUUr_@~>enxAkqOPlz~Nu< z@=*TnyGXx%tKov74q>4XW#vJ4DR@lvjYDO|= z#11EdG!Mil0pJ3sO*ax@m(#+4NSe1bHQ4Ulu=8y&F2X{({%q-8`z2s}4TMjeN}QMT z{d&$m)neO!+mKAhnh6^-i~= ze|aFODk}gbL%cxtpog)iw#s+*P_t<{P(=se%idN%X5Tl(Bgb!hD;z8MpzuFXm-Rrt zneSAN6-rSNBEU;%l!pUoMEHWtqT29EXQS#syd-38IFNU>aEq3Gt8RliPap77nPr9J z3iCdapKNBVDJFga4h|5Dp&6vPqWu(l3-ZH)qBHdVg>+2oW3A52TrP38SbKz{Tsk|2B zoALG4yWq}_?}VER^Ehb4(L`7SZ54;&GYe?l=^Ed$RFTs!3~p&ob#nFCcN?u=vPIN4$4-p zdf_+f&#vwP5yt~XxJ6iLu5&s$dXR8t7~IfL8XP7yNln)(rjVKdIBSDPXlf95{seyv z9`uiB10izosTkd#=k9>~uWwyk7*XnIjq`-lU6}8DVgv&sf9{@^-8uIPJfU=+l9eh5Y*&$itb6K4I&_=QPk6!e_ zIZ2J-LkIi&x=*P{i?20bf*-Z&?YUS&(hp=sQP#>6C0r^J`XnW@5y6L3e5Q791Zg%R zSqF7F)VMGBoiUASJV&@yE9AiXOWfE_M@JElA*%qA(CF-znr~Y)&%k{o^H;7PE{3^# z89r!__#XI@=vEvU=(s4^qd1nD}1XNvq<^Hh#SS>?*FXi4)fEQnn(r0Ov{cg~75dy)9WX{4ki%h_mZe2XWyp4JS<0l{ zKd?Z5iGXl%?`H!zUjq@ga$Qb7CxJF6JCtlw;AD;VHN6NA*}6$mFW`%wW-5kL`eN>|t4_r=1bGWT9T<{# z#LG+S-eQ>Nc+~Nni>T%&DXT3t^StZr(+~S>^=uq>$>bN@4R1c9Zn{1Arn{h&$}z$h zzmZ~2>G)+T1u78ts4CmZ8XAo3?>ff56>@avNQvZ4zy-k31X;jNwcf%2@9+gbQ`DcO z{^F=i@qTtrcEIhxpE==SQ8ad;Afz7L%lH7H)4ZU-(A}WJQkTp3Cfo^`OY7|Dz+JD@ z^eKS{b`%0~qjDka^_vqH$x>>?&|nS0KTG$YFFE#|JHv+Y%t^E|JNLn|rIFd=4BqLy zJwNTg4tUa`Ms^dS_I?;Hn+XiIK5-~vAn}I}8Z>&AJ^%tG1F=TB9NJ6{`-g$x;sbc{ zY*1EH9ye@UncDXHoZ?+Bd6i7K!? z;pq+ZTZoJ&o2npi<3>Wk)K~y0sv$zR5ew2kBc!F08Bj&tik9mPiCVzbL6m2Xk*H*Y z(KL3ft`0;#RaC{iCPN*w;xXM3B)vVf_PrkBbax3dBZtwr@R8MZHF(&^CVk_XnBW-t zK#`3D@rds=Gt-EF4OL$QY<}FYtY4L@Jjo3H zibLiNbKYY(!j)4>4b1<)GNKY!kJ!XPM&2)W_?&hkTzPn8e^f$i>8#>0n;CR7q!us) z9Kfudub@GEZIDJdn8T);DN$mNR7-33I^-C3ogHsvh-GP}(XaXaEZBM=TO4seAc8v( zLG$@afJ#CG69e~btwo)XwaiF6_}Z7tWc~3Ud2tG^gl=Axl8~6lt>-yNgH0DhyDK6k z`cpZ1wveKHTXU&bM}`I3hDTD38LbM4CLU5UJ9@M(%SZlNb+?L2ED}gDf^{Aa{jzJQ zMb;Cck$)+09HjC6O$d_u8x95b`+@>k-w^|086*U($jWMr(y{ghRm61X(pb@W)3+O; zXnBgSVD2>_el8Emp44z9#In>PH=kY8FVnu%^Vg}YDnf7WQF?9{7~Tcw&6^mgzESyL z`NG8k4I<K1Ak!!M@o0h1w*<{w6xQiUL>E%f-FEXsd5jD@r}$A$47O{5xWa3I3*w;i&pVH# z>=qcB7;36Og#uTzuX7Q$oZ>*$;rG2*%8>e@imc0t@5oXEpbCO1fyI3fzin8a?utrn zZu4JhRIL0sH?`>O*u{h8#q6dcIA0}Do-5>K7ToVBJotTwMh?%;Y`%t}CV*BzgKyp6 zsGm0Cb2E}f3d1uh%*7gCDK%VzCjb6^x?(tZb@UEb&9W5oUm5Vvp*5) zh1>SWlXVRcl89fn!xQd{;);GZrefWHo!@d?f;1Cdu*Rm)XPA67C^H#b7oeIWssQXq06EPb7oD)yZ&=}rHig)7u%!`deo`yXkAp2SF|684pg3efUJeyY zc7Z#tjiM{>8kA(-;vl)-RDQpMPbJ=xHms*kjSnIfA5ue@TsIm9k7Ssm4aj8O@3D2S z+QeqAAv#S-Q>=i!9S_v8Kc@WavmQXMd0DiFFZJhlcvy>d0BJkNlt(mi@V(1BJDD^0 z8=6wT6bdIxIIsy&H2qEShFaD{;7}fM^8P%DHxtW2ukN`zbx*rMRr-XMv*a9zTz$Q& z+HX1cM~EQ}o53OG^uLB<>7&8(N(#(#EL+a4F0`rk%QwA(Z)zl=nVLP3U*H29q#l`@ zkf7ujdFf|zPRum{fnc-S<4ZY~8A7lA06_yEhdAhcTm;Ioonr>#K&rAM)UXHeJK6m? zZT;mBXUUm;OVuv;#+0cQDe?!wqgDJ8QRjx6|ZrYF#PFE>9v2pdyModdxK!eQu5^=Bbe5rYu#V(uZ&14lERW%*VIlqQQPC`({}d@tbwI(%{_>G-)B>}XXMjdrQ1C=LenZSbt=3;M;{ zHgo0u@0-+{!Dc{{uI0*#$Gjb1M!At%qUB%XI6`V_o)X*78GaW(C>KEr44PrQ#y&r~ zZ)8ykI0o!pUE2e!UfOCuvMb+x04V!_3=x;Qy;ViW*Ni09B=jF@jBkN+91X{Ng6Y&v zrRRk?R)o@SK#K;M5)U7BWZjVtfv+6&h1D3@>3HD|**@>q@8*oJ*}-OA;5#{A6xru= z0dk`TovI=U5`RrTLc)S%neP=i*)Q9UKE8ha0Zk&4&ibtRoY1v z_8JXXrGOOcVJ+F?Ctt;dFK+0`4bQ8nF?q-O6I@6n!t`e6KmBI_33er}$3(Gwkok2N zJ8lDA^yxe#@QxdpK9hgg#A*XGqrhLyPVRVpzgE0_{~rdFM5IOyTWxAvo*BPmPb16S z^XhDHV$J|$8pw2w=zPh{zESVfH}mz?A6rV=|EU8^StVHm#qR{N&!KQC+ba@n4`cS_ zXF9W96ygGx)F{zFAVR(z7eeIO&5D+#N{ecTz+F8CDEt|*9gwk@zq>yWm$X>05A7ce z?Ui-A$#kiK69DB3szSsS=@yyZsi{~O%OV_~B2~XH`=AWU>mpY`%NvbqHAh?Gc7N2r zt6W~E`RlBm@LiXU?)8D-6Lhnu$*7hsDeBwh!d-DMaRf!403zu8UVnC8<;wL5c8lpl?KwUf1~Dt z`biD;&!A9Nr@V@CxS1i*6%wDm`LB&ZV76NcRdg+rNWKhu0@fp8&=RQ=HZ7;s$R zrUu(~3fr)|&7TyJb3Rjy^yF)nx%!Bm!n9Qv zpV9tL-L4!d8m0HUP}ky`K)b>0Ca1Tb%fO8Mk?z8{q0d)!t|Nuz2fSN4 z!AKg4I+d{A!$3FPDK4VV{IhHZ{+nD$Kub(SrAlqabr#Oa>2BNXY;{S{DiXNeA$4vg zBa$0TmEVmFwVK9HBiwCYzcB+3l2UvPbrrdi0TKs$JN<=7dRF67jY=wVa+u#9=-<93 z%=zWEWV-A1R!?um*Y~%$&%M&z#gHIo*B+pe{#07RuI}n`D>3cz>gk^;!rsy!E?kL1=9l-&Dw}4GzKrz>#e1K^C4S`OA5M+}i~a%I8GPz`OkN15 z;=kH-`?QnGqVza_{L>^H1Z4+Sq?NEYlQ&Ag(vDn+X`T=9Lxn9bX&%1%j+ho`dv9YpIy6zUa6~ z3%!tOaCHCz(aOXxLUiqC(j#c(ET#&2lDm;OOg+vkhgR7eN4biKl zFW9()%wD*FU&{r+B+F{1-)nb9R51Uf!PLnKKO&06+W4^+Z@)vS4K`A3^R{aw8qx&% zljni-aHTd>4@I8kLX|7}u%-PDD)RG0X=t9MKPQ+;A0v|zr zelZQ0g#g^TW^`*ZQo?aAWva)w1gdfbn20O{lt%_h_NX}B{R;;w2!XS^yZ!GAx;>gd zb%-_n_!xMNOu$$e=w5TDk_t6sXU&ZRfLBfy@@rqXxALT-)uf;X|2@Fwy=qM>d3AEp zpyjgsD(ltg5@Uk!u2mmWgjiR1<1l84%t4Knk7Q znY%vd)aevg#FpbpgC|HC1-%5odqQc#2YnI0`0Dr$doYq`;62d zQ81)cOB3;&+dtIt9V!|g?be!EXD~wvSU@_^Tq$S&VE^lh2!{wB0fMwxHj5@O;q@!O z2(R`4SarUT+!V?EMTzI*-4v(+atqX(>(J1pZgF{+kQK+^Q$1|^F{CNNxy8uT(En=S z`+JZCaQgT$>@Iskc^@IqH*9K6OP$uFyLEhIk4dWkc)c`#0=(*O!z(PKM&yFNR6q<* z*4bPd?oY(uyh)+g$|`9A4acCot*9AIbV9j5LCOMSONodSwh(T76{0Y}^wUd15=)Xl z+BU4&F~Id{*f_Q5fCN&W`If#B2=FG;DZ9eJIO8(7*jGPB9b;&ua*B>F@pULu?@gMb zt$la+U~A%q?b+J)mXJcIg<80@>jQ*tKhe?7wP|nTw(_qFPux1>_1O6M^r^P||LFSe zxF((_&~yTX-h1dE1d`CJgx-5ELP#iq0FlsQ`O*;q6%a)f=_ra+snP`%6r?ChQA9-n z1yMi|Ti)gOKJU-RACu*7c6Mg(c4lv9c9t)iW$BoiP`H&_^sNQ?9O4>CN5$dbVZ{ zNe_lp=gPl-=Sl;%qkF*;47;N`m!N#-%ura5Tlzk?yjk17r#AQ?4=JXTXNG-dsvb8V zOq>n}tXk>%p?SqRC+N0#r*px;^|9hT4}=7Kk;8PAFRYOD{{wD2bpj@4#`Zuuxs6WkxN?W z99)EpPlmnN*khUb=A7H7^_9UNotr$r#`gJ^twdCt+t>l7nOAHjB}dMBvH5cKWyY#& z;EmMi0`HzDG&oWJrPemFXIus~DVoLDubk}fI*>X8@W6RH6sL6R;@wx}dlM#a_7uY( zCMq=Ra1HByX)^_#IH^8y@iBsdH;DSNJw zlw2*&RrrR7B8skg%hP|1XTY2D#1SAEDkj(JVvkm`)H&(W)Ov&~oQBVAmwiz(?Q(K4sY~JzxGifRL zn2fH2A<(=8QG~gJLxYOmA7-jl&zHT%cx-+4=!dn(kDXp?*BhE5Oto=fJ?MQV--X)2 zf!78tp2sRaK34b%;9t%)R~QR0DM}HxuQv{U>fEGMJ~}GXoby!)gq<$`9RZvK1qaC& z^>fvU*`^FT=N!(xxs=A7*JQYgGx?wHKR7NDt?>bJ@<8G|gcHRE@^U%A^mEO)WFzGZ zO(H#r@jGvTZuqfs`J{*4a)&})Cx>^S5S!4S>thr4f>a?9!q~`=9ps-AZ_srZA3>1s zIIZ2P6?h?;mo)A@H&f)s5HRM;k&Utg2Os;6K9ZGfTFzflnQZeeNGB;?Yz{@uWd6wN$*=IxU3ZviYojIzk@!@#3!v)1+uMN1FaQpQGrL!WEM(D z*7d!YfJ#Jc+J5KFdQrWgvf}maRg6dUx%J-uU#@*&f0)GEYj?CXP<5&C;lX^3X{Oo0 z%y^%a)V6g)^FQftE~F8GxXQsg%~5J9TC*!erb;S>z@0l zzrQd^0n&Q5SQee)oks~l-EXVJimseGnDb01UfdO4@;_C)eR^`zWo~>GNRzTUE$Zog zJK%H7-I&|yXWI-jha~9V4*B(d^NVn8c`{Zd8}M+7P%(T zYIrYDSFusuTRT|9gx9LT78o_Iskv$B+~?WpSpN?pgB`=?O-@dv{sJ~;WLw9Gq>K8Z z=V+bL(IT~)HXE!ZA!fvx`G558he3@8Af~O{&)qLmUprs_(HsH=cKyuLdwVsmLGk>p zzhE!|Vm!TP428iFY+a9Ud`Iel_xi2X8aWXtE}J~VX>J~I;C_EDqM)$kN;%f8ZyUS< zhV3>ld6jail;JXyq6!20` zS$jG=aKg%!ovP>)ub6i&9{6b z<|g>M^y69F{v5^Z83;FHJBFAQlyGIML|5;7FTYY6x@m9*#yN$Mb!&B#n8CxRbgR@v zwQyItB1746XIsOeS8-bIg(F`t)&-W!k_1WKs*z*5d2z8?RYe)xrQj+{L2Vb?ncHat z5O#lUgBwpzPpyQLI6__d6L=#+l{r*4lD7G=nxYueEcX0)OpgVO%X#(#=o%gUskjQJ zlmD$2cG?ER1v1}iuzdfi(NNk-{;te3v<9d~;j%~94JGoiE-U%Mw+OPiW8H?}iy+qv z)fPJUs2vX13)K8B;np$+o(Eup@F>CBCXAsXZ#nyWe)IW<^ES02n2VMKFq~m-5`k9X zy`Bf8z|7P5(5s2-w7P}yBj$%qHC>LR5HZ2&mta8&IJ^0>`4O8^!;Z6UDjEm@o?P0Q zn$KER@)D!{YI=DOm-52&#A|i@xH1@}7~LP17fr57DynQhQ!c}Z$BHfz#A*tDeB&zv z8UN5s`|!xy)maSYp-;ugen@MC+}S({z}%gb$i$y zg^Y^*=tYRE^plYF2xTNDdi^wzu>R&@8#nn+LcM@S?D8=tq9fy1%#0@L3I7P*QF1^H4*%cNOs6K_&9!(SGV< z0z)I|7U33-gk*Hcf6++s=yIG-<^Jg+YmAkT(&^K}{6%kRu1Ynt7@F`aimQNA*?aNJ zV^uW%z?G{?t+yKS_#h8+T1br8j~sh@xs0PuU(Gy|2c_sBE2R`l@b4PbHCkQ>#@H>x z6ia3EP)d^F@4(2cqQK&D@Bt-EMv(b})eysGbNOv=JP{nXHIVPxfhL`auxP!3&c}RXw}5EQ zl#%4F=-ycXxdgk4cV~yy-Bl?rc;a{~_s7Zu4Q18L_~683i-#MSXzO>S7}J(W{iG6F z!uK8&4_S}$K zTP`;uwKM&~RN*|k_gln|2Vs$QqwnDS`$QcO4v`!r`pF8)*C@#hsm$|4WQ?b57W8`_fq_34ERv;VP+w0mNI_6TWRTv1gf%8NGn&m za!I%2M0Ow^k1q1xLlPo_6cbs4Qo<5J{p;uS1__X27i zub{JvY4z7w$DvAkhBGj_DpGD7z9D*EfrxPZR*G{%hKy_9FvsLPNrcVfAWc0+tnE!) znhv~Ibq+-vPC5wcO;tmxcPPq?`bM%*<-26gQWnF_#@>s)C%5plM&4QX@qUn&41#Vu z5PtH9Q1`{IOIbH}i6E#aU1GItLqf!-HHZx%X>EdKZ;gzGL)dE-gA}(xY@!%7<;>`9 zwQZT&mewGm>T#*WDhu9wqI*@Dl55M0_jUCh-%r+J9Z6GsZ)H5RxK+N>i|DkfMT?(@ z8loUIRT46rP$ce$PB9~gIn`BpQhzIOX$=Hutlk(ch)|%{n^}+I@E0C?W>G_Z!_^-M znWc_raO?WG&m5DOa_}R#I2lb0zu1Zi9lq{I2v5tBjOLTF6~ES23aaLNwFqi);1I8> zb@nRLZKLNU#^*0cpR~RekoaaYot(^kLf^B=7~H z2-xpwJ-dLIj8apecxU9rXV4C#Vx1y%Gv0-3t`q`<9^*?-Hm5f|j7N3%F zt@Q!p>h#{q9`c(Mo`q%;n0Wry6i^y`w(*yJSNf{Uo{1Ls&utR;i|y=<+yr*Ck&fIP zo**+<6UCWQc)Ow5ckV=vm zGhA!2F|)}bEs)KIiw(G%%%P-UPz)4Y!%v$5Xuwv*75KP53c)#E+?Y5msjLgklkj%r zG+@r;lUrEHnme_PvF1)M*MF#$75gB;60GVPrXIb(Z^Wrg;2*V;de*hBM+=S``{p(KBNl7Gk6+X&pxk`E zx|MZpY|dZ1c;={3D@58KZ=>dwS=g1JQ)TYDsgZJGU|T@&K2C!kAA^jy8h30+5I+C- z=HY9p*xxGZ7Hn&3RZJP!5LFnhhPJqjWlL5ka(}t!#`+3jmWhqUuwB@XqUqF=Hft}D zEAY9?+;u}A^btGSD;^mEKoHODUYfm3b&v0-}Fi=>7M$-LcCyXe*^+vB}^D}+H7 zPS)w?OX8o`UdOm~KHqLPv&m|BnxJX5iNG3eLzH=eZ zjiY0Yj`30)*9al=@y8=t08dNJ>>AYA<~hvaZ#LIlbZ1UOrw*0LE%Eb8yZMWW-NXJn z@2Ly;L>9HcH&)YJFJAeX%r@S^E-D#KV*GmD~I0 zjnwNMUhwQ!=BZ}|VUEv#`x4uop86X8>#u!>?K2`!na>IJZ|q-QTDU(poBIL? z?F8b-HYpZ=7Gt%ob0eB&dP0`y7?|Y;DX3PkBggHDQ(Uiy3L*cDkHcMW6Ck#ngE?r_ z1T&xVSFtnF=We#r^YGrvHR4n5{~LyT?8?NVs@#>C){cgkk3>xF`lWMqXcz?!bT?7& z4Wl!ASj}yB-5t7$de;TLI@gw9U^D-zC3)_;kkT?NQ}`8~pOXYE>@eSF8Iem&qhh!k z{G(2APIIqaXR=>ZZk}wbNX5ziVLNSkk>~5$naEwR^uPNong~jePw2suh_JNdx>T`s zM09MD#PffvYR}I4pIG9Zv}fVGj);5Hdw94rc-~^LTV(!xYsg0Jix>Z0oUI#%o09Q3u_2+a)!w1xE>vmLK*|-H;RHRbU?&VRR?tjn|uqhMn`V zIL08wx&Wxjd09L&yuWHLPEq$=r2D00)Fjk~v#(beBB#k(TxY_)2954LP~jYCFZSP< z7w}=>fZ!SSLze_k^t@|UYdfhg(S^Epey*5naQ;L0&Z|?hZ&*0XoX_W;<(R*F{_W@8 z*O9TAOEOc!gXsZEy+7V2x5g#g0CIlo7X9e|ix$Phd~AdW599>%F)P9@P?|%3KKlhM z{xYM9xm4klcN|q;=D1#ZX2P8B--Q|w0opBJZXO7S%sAOl?3R;bP3@y*n_v0ASPbWU zWA@c(fz`U6M|1zJ2NiuQsnhK?o6JtEWs$k|bS9yKcQ2JU}u2ZG5+dk-o=oV$6b zU76mO*J5;x*IGr+HkwEsilo&AMbW{_x7>uBanVK zGb@K>A9M5a3(i#lrSlhxFI~9?TwzpHR#n%q?$zCBxOMwFP-?u>)N*%^J0}l(r@0x? z$|Bm{(baRWf13W)crZ;jBl`@UmTr8u5Xe=(Z9ILstQz)XzJDs45uL?eOYX{vZ)B8 z_1CXY?^$DQQ9%exmbKT%_64pzeolC`XZ&YNQn%1rcH|-)u8OR^7Gxz&s11n>`_Q!5 zaaUi8cvT{MJDXiBvMNDs?|F=x7%zb;K7vx03sFB6(}0|@G>I7>YcJaM4nSP6D@7YP z^X1Rc(X(Ov6ZD{}I&^8RK>X3CsHt3Nl9$v904g5m1TS zx`n!5-3TEA5xZQD9{sX<%U8F2(R|_Zg!uUJ35H*aukx94NvdPKJBs>3mX39b(_g3v zbFoH?T$k$4)GOq&y%jzoE7uX$g& zva+(C41wV12NaZjeH|U)GfK+t+!21zQ1CY#=+Z?m3o~Q+n=$Otyca&QKUuIHd}yVMelX+1%5qahc~!;(GkCmCklm<$k5r_VWnjHYx?GBqEHq% zY8kh-fDZcBjKNRIigyXefHY=*dMmfa+rjT}hWyZoFwhX8{B~}c3nk`Apry<}N+3s%2T{z6RI{x`zJ;Jk(D6+wm(l5d z46+EOaebN49gH!rqFG1ZSDT63(LCD{QSfN?!_by!W59RKCTo0$4sT@TyYTiEt(&Q4 z<0Bf^QgNs(#|b=Mi~m=9i2_M}OemJmXa6i#?Z8eTNzM!F!RL%mpObG7Q5H>WlK9?D ze`sIe@a9@ZqrKCtjYov~Gp9(N3m1R|5Vv_Vv1i5$QSrdE+5$fgWK__aK--|TwKFBtQQA5> zL>OK{Cq_^rTHQ@i_LgqjE!~?*XUnoDYtfbXCbJwpd*PGO=dV}G*IF0-XDCB4jEB*xk5NR!0wTq?`(Xwpao1jyV z2h&zTwiIqb%Tf=i?;3Os9z(=}bFYTU9@we|+*&m{B)ILbZyl3rHDNV@*J43!9TwEp zV?lj`nzfoW92Q4;U$usJMRYg}JkCz-@G{>>sBtGnGgYr%5?%(gr!Uz%0~83`qp5gS zH7#ux)X`-@J$*9(8eofMR1PhP^hm4Yi9~AEIeWE6a9)Oaxm_&aAr|twG<+o?Jr7Y( zx0R}gQ#rJXB^TrpoRFtd-F7p=zk>-NfDc{sR0|e6mR2liZNq}Lb}VS`z=DoWEa>dQ zg05~X=s<^&XPvug(T`rKCTpE=w#0*=-Y1nH-rQ)@KAA4;b7Sz>aL45VD&0w3%QT0+XH=Z3&6;@QHh)wK;cP%p)};7-SPWZh5yENkOtx3q75ZjAW?qks#K^0`#ysa5`J| z1Cv62DdGn-sGsL^@485F^*6QCNva@@2ZH<7figkRcmZcw)bLy@+kFQ2NRCiJwQjtH zLCmij_rhMAOC7gek1lSgZGuhEU;;f;)&zNC$@X5(F(Thytc`nDs@S2JUz#+#Z!OM_ z4NQ^X9Ue~c)jcW93937LMsGPeChVo39{~rOu%+6&c^;7qNohH1hdttsWLNmvt=3X8 zi|I)W5J@>gcq%XZNQ!aDT^m#mk-*81>dU9$orNoYNMxnk{P|`H65T~;yRv3ufz(q4 zDmcoKTnmk~mg0kM{d_U`|EN>x%K*I7zB1tZh%k5;0l-+3< z`ecu?FMscaj07@;rZ~JHx@z2C2o8Kg#xG0hhk6W;*WIs9@ zUR0iuaOtFx0hcpDTo1%{6RiV^aT0XqdC_HvVUN6sel}+fmU#K(Ayu1wFBxRd0SU5< zu>7&`U%*-pMvInWgjT#Km!DB`PY11wD9tM23&zyhSVZY#hIDPButQvtlw7V&B{b}r z*qok@VwK^fRE&_Div9lc?M}NKTZg!Ql$VF9bl>($+N6)DmsR51_hJ0x{g0|yYpW}h zv2@MXwuCdV2d_$x3tGQ?`qbu!CmgUGt z4r?X)4BMeCETVsRBcl931=&`hDg>~+wbH>o{%RkUlLD6eV-ko^1Vx@`9TrIE7`L?H z`&m+~85CJ)-YQRCil<*HYd~I6&D&ch?;ekur0$m zLy);GiHK*%Sr~?sZ%TMU;sxQ3UVnIKpv4we0@9@LHlOeG_ccMfJW)f0=+EL|#YJ8;-$T1s%8g z@0-zd@i<*xw(#W}J%V%)i5^!KqTF~vm)hy4!C`KYbK*m2MpD=g`-%3%U@8BZ2PIKb z>WWHr$N64zv|sQChjU;O5|O8TE+1L$2#}|Mvo!cL$yN8;x2GqF9ch$`+#Rc)Mv^~u zLr6QlHtsb?w944k<}YEjIxy$f%yaeR#K3p3%DZ{AcnzeasE2xHm|NZ~0;KH3lx+57J4SNds%4 zhtuY9nrNL69gG?Rg~X~Vo29{^ir-Ma*bpa~xAHRxu$$R)X!TGhXvE&CF>+`?s$N&F z56o_xXG*U z54x`%S$z#$HrCKHLqTPL9u&ZE{1-@k@`Q8w@_Zyd`f<@QByU`d^_cI2Xo^_@FD@bs zLK(w?P7iq%gVN**UBTWkceIO&x=P`Jl38=l5VuhCTF@>+5UHeX%UW4H7ROp`%)D}k zwc0rJ{F9=`u00qmJSpf61dy#fpn)YGaVTL~m=<0=X&3Jgv2*G-H!$Uufi=)h6J-Z) z)?#RQLPjAN>CJ>NO8Yql5d0iU=-eaxYRu_tpk9C6WveryHC*F^>7OVYXmZ+4Nr^{O3s{fGCbVA{@J&z5@yrjbRx(3KP;Zj!j6ZvTk zN=Qs?>QTicP3q)Pu@hiB;;@RxKIAwd+BIXi#9Gd?dRcFO$HGH`Kveh(>jjN?%`tCm z8G`gNp_CjJ%r=~*9%EQ`(5=O-w%QZnZXRjnGyond{ zXid~LoJT(~lyE<>p2dcvOSmeZjeg{lo&V%jd_<}wKT(`!rhI@_=Q62(VOoIZH9?xp zc(o>|EXlpse;^&?buMd4I=-cwJv~c*gthzFd;7I%cTP1T z)7e!$BgfT{7>#zjSG0EGT^)y@Hb$3y$;z^YdS%ulx^nBSDFh7DZIp5x{ zJLio8#*$(1H(P|AlcsM#Fvr||z^Cr17B8vi9^y2YVn~cst#?X%D;hBgy55SeSXz3Z z*ij5JX%TOBjC|V!oF+bx<@Vzk$+&Cw;tBDRN*N#Igh8KLEM+A0@=^C!bDWr3OI^_0 z-%+)({L3EN5<$lIZ9_fi-6coZA9>)~u4f2dR1^;Hg`a)rpnUU^4(cnH6DTX5FF)Pz z*SRP?c88s}nKKZC%f(zT-_VuE#3y zE!^tWJu7JY!L{?ZnZOqc1Eh#g^!{x;{d-N;7BqwCZzxdIIQ7+>ACK(7rYNRp$g(+J z=1BN*YN+1-vMyQ%od`Ab)iq0gRF531;i@glP0I4P%R@t*AIWyGGk>&!l$G)FZ3fbD zGDp3HZd;EGbqJo#7z!GCkv^Pm#qKYZ`@HCy_iP&909Oq`JNKHRd|sZJ!jR&Qob^$p zk~nJ+spy!q29tM$T5&pZ2>Q^zIYU84`&Kb$4O0%o5NU-o1rY*(zhIlGtYcnSe<{$# zcIb0>swTo%GeuulgG5zBzCnO3&uLkTOf_HTHgfrD<7gyfd4~U=o?x<(jisHDTLQ-Y zU;MG2>(xfa0Ukdi#@mNQ3|s{=54zg;%0#T>dx!0R#V3X`8r37nlx$w^RvPVgLK68C zA-v;ArYK6zEt=ZwkWBZZ~K^8cG^h;kOLfDUw28F zw~I%uQLM_J^r%)R;&x|^_sdEze-WjlhQr)xW~ZJFCORpNn@g>lp0HeJ{JX}sA7Klc zT)kqSYf;{F=8|cs=!srcSrc@HcheBOEw4Qvp}qA?a`DtyUR^=_1=7l((X^+PH(R<$ zdf~zOE~wRv1Sp=4`ve$2_v|L<`XdUVbt6YEj`g7qKwwCn) z)h?caib+H>Yt^x^^5?~wwW|5Zx5oXYpawopa38L(DM$BB=J2tNlzxeaR!Vb-R-HJ#tJ}*$MslmYNU>d9Lh|naMw3>sYtZWlBV7 zG6x2%-sGOHT5(5NE%~=(dqR7whewZ7!GDiK>D=EnFe!Fmz3%kR+B?DwQFSDlj6;lM z>d{DgxD8TD)gSt*@B)b}eLj?=F)5lE*)+iOj_x0mhHC+XuuRSlp3A7_Km;NL!&o^4 zJy8<$1-vr3;47MW=0%oz$ESY}ch)a=ZU)@XfXa?+e+F^#H(uw->!{}P_C`z0BiNY88|x+uaEFdR-+W+)HgA= zvl8rI-D(Y7$~{bScQd^b^N@vuYZzCCwmwSr8`|SseP~m3bKZ^g7!jeWDwxgDt*kH0 z!jaJU6Qk}Vz@_iuN#_XbQe+$#oHO429dwZcF&Cx=?E>!$3* zA`XE2*p}xp*WnvZ@&p!zHa0;EMZR14m_^A{6jFe42y3T4l2d65xpv0bMeP@|&i;HY z!b~4_s^aG1WX+x2gvr{{ zLyM%jyv_{~60pK)V>;u|o5XYX$Rk}Liq&Tb)?4lYs?8pw5Q8Z}mr&Z@)}=HPRdog? zz%m|n@cYpkY zClg%lWGSC?3t*&E3N9`kL;2Q8D+y`D1a#iXtDQac^UCw)XoLZZhRXK0ZOTdX9S{N$JeCs%%>DwU2GdTsAMMXv|#f{0|& z5nAJuJKNs*X_96Y^n?>+QW``yDLx>-$}Bg87@eOMnPyBTjby|j591T4DrZ%%^-S0S~tOi0;#{=fE`cQAGJ$EjDFT;E*YB>Ot5&-8L%+^XJ^NZ)%gc%i1QfL@08$PsU^-~cPx%>YJk2NeZH zL<{(cuGmYb(A62E-W}#jCoY@`zw^UG^*5C~f1Le1Lmn$H`})W|^__DmjjCCw6h)6^ z#5k1`xNi4&39Z?Riu&|RY#iXE{Yb< zqM|VYid6g7?qZ-aSau~!F`(?m4c^hDLq$4IF^}kI0t0yLTxtwO^%N`kZYYN$iS{WS zx<;ar-o>afJjLR}f?tCeLI)(8fA)e|Bc>zZ73*J0tpCChTRy928-^h=uJB|crH{sT z>-CX?cGa?0o7pIjgV->ag{33*2bh4Q0wKi%6-vOwEk0Q|IcyX>8xU|nJ{lU4U243TVIWNKxK_#qBl@ zYqx+WW7u>_dMNq358g}uNlJ=tF?5_1Mvrgt-i^AFGNhhzmnR@^4@59z_vP}tpe!%% zVQFqiQj1jn0a7GELEc!c1zQgPg<^B@mW-5PQ5HuRxM$qHj_W`9z!>1`ox;G;kj|Tj{l7T|D-iukLo`;cd$3`H%qbCI;(v7n z$Y?wweIKZ$O&?brHOt#$95CLfj_D!>*d74hQ5QFA^Yj)0Aa(WO<cc1+?&i_&?k>v(1 zZh|cM++p<*`yzdSZOIK_Wcu0%&1J@AmQbIOujEsvHWUIossTMZqoFJUg+WvE*YcAfM-dRjesOIf z1p4FKjnjtoW4k;G`nxi`#+_ED69fkl`#_H!!h{6t1Utr93p&rUO0eYu72(T@GJlj1 zX3DM!tj@dg3Z$Z-{cP~&VT1CduW+3L+m@=Y>+z(Q(uwPIyQ~c!1^H`nOM*!M;#jw2HkeEU)6Gg`YG+^r^iXOh=67ml!TyE5?@j9s`rV z$hF~#FB_i9;b?j+^rHDFFt>NKEMTxHXJ;n zbl8oL6Y1s*;Z=Wy;rAw@sYWL`ThrG#%78}P)IH+08Ju}SchLE5oS4Fk{gl}FxX=;4 z`?`*lU4S|ij}MEB?+6G8kkI=jvh4k>>#aOg%IGAo(}U}{Z7SVrqcu`OWV_iTi~Ghl zjq!qp04Da$e_8Y|0`zhJqyIMtpr76N7k=?a>v-}*MrG{1SE10DxFn)HBQRdbK}1U{ zV7Waju1`WQMxxJGMC7}?zfdge>#tOBlUJ3P;}xdw*7=rE_(vOc{@V`FJG|?`nv}$wu_2-tw0Lt$cL=O(1Tu zMl{V8EAe{=h!eTF*q%kUWN9Bw9>~)#y=AP3(GW8gbz~`hy?>t`UruMKBccj&V{@Dp0Mn2fWq$-vU=>23)s5li z{}E;Ygg>)xQl8w(@YDu0^SU7O~1xS z;{vLdz}|Zn$18*7i8d_4%51yudhetFTHTmr!SU(sW0uS3b{^4DokbXRu=?))|H5r5 z&Qh?vUx9m9-z@i)#aptJmjdkF%2eGRz%ebr2(r@k8fc;)QIp|kslWh?3~cAs(t}nO zr-4FSY$clUUrwp`mw|?5QFV3EV0CR z&{3Ict;7-o@$Kbo%Z2~-4?&js;uDMTd^I2v%Zv!@%|E+)kAO{u zV8jwb;`g(U59?SRpXIG94BKIeF}HlPINpFoSnP0iv9}DkxyNwFOCgWexbHllxiPKT z%jpQxSfdPr5xX4Y1*dfZ!y6myn$Pu0fB{@?p|}}5edfHYFKEc4v@e_%Aj@Ghbn_6= z;_0b@*zm|=b*?Y6&OJqC3~1x3+ZEe2*B;AC;E}JobVR~hou`eKlQj?_4$fbl5V`83 zfY_*2N8kiDM2KqfltY6j6l!3W1BMtFtQE3055OS~!O-|>ngR=4XrQ|_Fa5Fe>R<{Kh! z=VZB_eF!?|jjIas1{Eb;{-*Kr+`p@!@^({DE$9YVGXGcxs1elk1JurqpN+~=J<*@- z#oq8`B>a)Lb>q1EQ+K^FOR+cp>pw)n)^r4CTQz^*O#2|y3&94FfbeNIeP6C zm>bLo76gleCBV{PIj|yF6|4@%g0;YUsd{FA!G>T{Frmg4>^^m!Aal~KyCm{^K@`F_$>GwxCnd+d=*>)t^wZwhkLxSZ3ef4yTKdqw?N%d z@Hlu9JOiEw1BV5I-+?~@Srqmq?t%BfKf!>E0F7u8psVu?71EEA{I5ZkcgC;;3(Ep&B&|GK%v&0goL4Byf7h{ z7)%N#3sZz0foZ_-z%3?B7iI`Eg_*;wVfHX*m^;i1<_8Oc5n*AlNEj7H`yUP+mJB-q z`wx~5%ZBB`3Sbvt#jwk;GFUmR5>^Ad!QugS3w8(A0&9nL!n$GiU<0sW*eL7)Y#jCk zHU*nurdE?7^RSn&Mc6CY3Tzej9`=E?=?=CI+k}0FZNqk8-(Y*N@30@RpRixB->|87z+sU6$_!0Qt4wK0SN5VPaoNyGJ3(gJaf%C%oApCFvxZrx>lRY80u!yKwXOq8c zJ;L=eG>x1Tboxpf*lc+CDJboG$lHV;X5sfmi_4M{A-wh+L7*yCl#Pw`E@w+*2j7rF z4KVn<3=0t{Rj7?>=k`Nwm~l+F>G;pL30k!j5i;)AfnOT^7kKo3o;|9$bg`8+_sBKYVLA<*Y} zKoM!bXt@yQ!U~ks{jRD#P&=}fVbNA{Cb+5fSCAN4+ z-U(EV+f*x&f6kiA6Mmuhm7N^=U|c3(8sVR_x&O*>6SQI?N8NH&ajFm}kS>zJqX*h71p=5vTCw6VDSFTsCuCRDLZ;j@Q9+wTu|B{^i z(Q`PS{F6sICpxewc6*VoAjxl|t}+lqZ(g@J-YsbDXodJw`SF=4(wuu^%rfMs8Kv?E zMc7!~0@0C1u&%4AJG~=`py_TLMU2Y%L>gbv_EyR)sXzB4Zx~W62_w!$8=i(M3Wm z_kZ!gH+Vc3UvY3c)&Cn+_!SNm=w4CcX6f!s9b9MEkVZ8i%$%}ZcLr`QCb;|=m)^1_ zBYJ>{oIXcy1n*aebvbg)OphGERaGv{75K(m*GD7w?Vr;Dt~$!C0Ip62ex%Dz+o}lu zv0DeY+8FOBx17i?MsC!Lx&EN9zT7E(B8uD3B3FG7!&M@( zB8q8|vVb*r)klMX5hSwVJ=0SM1Sl0}k?ospD;(8P)7jdZKfM;lTBqT=#^t9XUG0_Z zP5V8|`{fuKz9GKBR=bWxW+`a5c7}eS;4!gp8Hh^bQSP|Kt6vd_ksJ4gOYXC!0~3do z`&3uh;=hEWFc_El>b!dK*>pu+m$&BKj@pT#mRAVvsa z?kg;mIKD{Fb^t@!_*w?V3CEfb2_8s2?Y@=<^kQnL6;;e-kK(K@CGbn~?KlgqrSd{* z{N4)ecbH_VqlOkj2pH)f_a&ZnmS?V93#p87kVrPt&_Kwt8Wm*wCBD7Nnz1~(*Hm?J z9Vq26s2;jvLE|T{ii`byxb`GLvSJ<4THM%tbUKk2C&48@Od;Q8es|J73e8cV99v;`$aRghR-G$2c#>Cs@BI87IxWIZ2| z2xS|#lSTm&(P|EybS;n9_^(U>lDq}n|>!W6CG3rbg_$H1}CJbdS6l36y08JT)`zu?* z&lw*(7(5!O<9r=dt+>xu-VBz2@sbKrCksaFxr&MW1oC#{(4G>3swBP$Ek_aRQhc`E z?}&ajocjOg+evt|mZ~Dy^~g%_8TWz$zsUDww{L?rVF+%azUXPG>vJd)uDoUR5Htgq z5a9i8{Pz{JKl~5`Lcmh;(!sruJyJq*?hW^3q=g~Li{ROH`F#+W z!o&KHI59CON##J8YAx!>W~`g{tg^ZURwGdobr5nu@=#*H^ek{t3L3LU zER9xoO)aQ{X5|D?_nVdugpiK;P5apK!cbT3JdBGE9L|e~?%OYhTM3qIm5@Bhbx2BD z2AO#zKNw20`z3OKvhC~W&f79Fw8DK-SV9qf5;t_~!YomICG`|MuH@uUwT3|m5k?SZpkGN{^-$xUL4nv zh*sygvSNI@F&=V=TO0jw=+`jN?lN2$!b|6yGBL5ELAYV^P(Jn@v+*EEd1UV4gE7u^ z`s1H0jfLd6C-3(8F7m;!Fd?*5S(<+}1pbzPN@()$@QN#13c?5HhYP}mB3vIAFt38o z{Ct9ZLVOTKuJU33W;h8RvL{clN%+k^|K`aM`^^IgNkb`jWQaleaFl$$QoU-w+BC{w zx_R=OHjh3Uu56-<4FCzT1S_JQm7~pM$ogYDaYtnr19u_qqw-!Hoj=rHPiH}f{&(Xd&Z82S=oKlP$ZXSpWt3$bUE;(wmLFKSd4*OA1Fc!NZe5e9 zN({LEy2juZhhNd{uXn(e;KsqG;mr^O?uW*Y+Mnii-UE4;KYqrX=>7PFHNc^pefDao z^S`R$b0eI1?OsWYO^;uBI~g+KPn!5XIX$cKzI&EKXE{Ic0kcrg5?$V4wP6Y-O_bef%Hj^sdOG9eCj;C(ei;b{j`l_k3Ai^q&qf z7+knLpYz^6e2SBGw|6Gvim!xT{(cTVY(9fe_P^-u?QZKlzdjk#)OP=2llXn*1_Lmq z)3=3Q*1o^-jloyRVX07VR_b>pyP!3Xla0lkgIUfO^HM<`{;!fGXeSd|;`w7apZQeu z(=+PfB_XS(<->b|=>dQJd}XMKr68u;U=A6}p-~*>%|tz_PMTH|YDt|FucBJ;;YTWal|k>c;_PdAf?PY&ScXIQ zM9S^ZhGdZh9>Jm8JkTPRu-^`pGSg{M6u$`A73}>g2ny2hPXQh|ev3WPeCMnDn;Upn z;pki*dv18uVyA;kKi56@0L*m-3ijZ7c_!Z=56+(jKeN61er~WMILa=7wsKp+CwYVS z{Nc|QJS22S*hqA6pPLw`8~b=56tOLld{98DP+AgMC95D`tDve>r>v}c<1kXKRGmX3 zin^%zM=MNcR@Y9y!$1+8WAxqF9n)rtz=4N^2ukJv?Fn#>IBX$h6+~*WevTt2*)i?^ zIOsYBIhVUU=WuZSK1NiYaf{@QdKg8C1~UZOtG#)a5HlGQ68k$gHEvIQ zRy@zS3+L9)d7mFRe>fpCVSz)FV00nt!rKediIl`^iEk43(9kqr+C|zeS|4qK_L;VM ze%C3mX+%R3;#kEZ~ zTnH~K!Y3}HjN;>lB^h8X?cI~W5Fh`rm_!jUDE(4#B@7Iyz1Q0P6r|(^v5SK6B>X>Y zFI7u|gOw13r~JdFfFb{|T3`?d3kO5~VL?hk4pxjmrS~7!tlCkPg9WY8r~SjGfg%5} zps5ai4wfGb`G*B5#W+|1NwQtTgt2FKZT__HsBDAxp-lU#dFio|=;FdF9GcdmnL^$| zgM#48)%ox9Wb%A3-O1g_vCXN@-px9m#mwZ;sALvpz%vpqZl%Yh|4B(pBjQIzOF@4jo>5yaneMS5-c0 zPzjdh$*bO-G5%pk64RxND{Ei8cyaHZ=)dw`TmuX91*iPQ!E(og_uvj7h?5!shE`H5$RS#fknnPhYFi?Z8f8r~9D3pt1Z4*MaGTpg=K;MD z4X2H_01dQf8}B5z0-&2SS;WZg5OlMaXjgu}>tfY*MO~Z|AQc8|2Vb|)x!e!rn_H*? znEx(!pdX<-(B0@BbU*qT`Z@X~dK5j5euthyzemrbK|9go zEVQu|Ja|vG;2q(?eIE~OO9)6wA{98w9RXD(WmTk_DC&>atZs)vj*&YCfqO|fN0hQ^ zvBr^^_TZIXK-a0<<(He8XY#QYuXjEx)bGB_ek1<1fuX^Qboj1eF(v$Cgj?jpDDK3N zQ967kCM*6z@L}JqKs?vMW7nL0Z6T>aG_hAVg)Z$>2jJAPL<~P6FF5Htj-+& z|3q*T6elf?D9CUGj3a^^0sDvHG&LL%E6)A}c$dvvr25P|G3E@UpYeIA{Wt22Jh|_}y8V0nLV9f)-pag_d_Rm;$xc&>CnR^iKT) z=rYjBXt~z`?S}S3`=QUE&!NL00@XSWeFvTDn1?Q`C3g#Se}S$-H~KcAJ8f@R$xnZB z`Ts@@?k#?~4<-(iL@hG~UL#@hFeR8OOnr)z03DeAtO+<$HiKEfNQ_QK=b}B#>5C`q zILE(s0_OKU7#21MCTuer77IHEy8v8-Wx;aOM$<-N`S4;`89(En|Ax?QSi`<%K5xFi zuvS<*tm|MO>?x2oN|AX18-cxsy-}Wq&A~pxKEaj|W(YIX8tj|SHtY}VgWX#g`y)3O zFSryeW(IJHa*1&vxDHy%aX%#A42Ig0Z@+bx>wBZ@@$d;0z|VyoXMFihEx3Q1)naH*p_y18w~=S+3EpJg%iKYA#G?H|G_n6elUC zR>u{Gf8CdZvcrJApFNL#tsTj3g`7{;BTv~T*{a%(+Qi!^*bIXa0M_x=O4hGPG?E5s z#wy1OW3_5oW$9$eZP{iKVj*Yo4kTG5<`Q?!Tg*evmCfhP%FNu%M9qc?nFLD$Hvw!0 zfAry#@BnU$@WK4CMXr^TwSa9W`Gh^-P~;>ZUQh$L+;&xUzwRM+6n)&r`xX;aW#|J? zoKG-(zns)EZVdPmC>t!@@(pk~of2|CbTSMGmp>yP%*frAu(+bmQQ(IGc(;dtx<`#yA>C?b)V>n-6+N8-O(}ZebXd-0t$+*k7&^X8# zZ;UWrGa4|eFp4w+)~{z+V>i*m=o<7nv=dqd4a6pmvJKgWNroPV8iw44QwBDp0MKZV zZs290W3b0yPQOJz3%o!9GLOaRf6#lRm#gQiht}Jxx1igmo2z?L7p=Qj_oEK5N&E9i zCr9UmmyUqWoOX+LhPJmh1g<@$bx$khpC&*LEj2Ab^R;HJ<~dC}O*zeIy5-x&()x6=xFe0yi>oeeqP;99jX3J?TK2En!lQ%+8(v3Bf$D^;LeeRBjh8} zM^+DaAHIY+j5^F#eW`j)HB=Sz8#T7ADxf;0(yC&qBBlZw5a;()PE;lb@b-08wtyN)ZE*7qC*$%sWMRUFf_Jw@~I@{=H?V!A%r_P=UAn z2K>2u-tmd@8SrA^l00SNvuXExWQwI>gOHafW&U$2<%By=gv=V&b|7_(ht0dja3KIX zdGyN0{Z;H5TzGpm$o7!|0;h_U-03Qm5)qo0Sm(QYcG_eVm1@YVhbXwbI)=oXYzQ@M zRJ<<;m_V3}3inIyU{uUj}( z{9uUqAAnRSA8viDTjjY}bPP^B?&s6xbqk#CO?bB)J$2#u$a(vzALoR2)<40g&l@&f zD5ITuoQPFRloJ9cbX^GeUakuXj)eF}s~6nPx1I-;EuuCpD>3U7?9x(Lf|&31m**AW zI*4wXHmxMnk+F&w$)$c;^AHK_x^f#l2a-Y=ORyW0DZBzdSR}Fu zZY{xg3%gtD3rA{##;+%ma^xlR{dW$|l_6RF&0neC6hekVeO&dfgj=4@j88b{m02-t zH#T#ER{QH$E$u{wW!ZhbOt13^=Q2;b*2L$B`-BgLDtz<(+N>;@pE-9hr|dE^h}5=o zWiy(0u{PfyFBfG;`jO%){Jzkz;Ce%O?f2m;vFWL4HL-qG^xF2IvSR`Q$LLjlmhWE_ z#eyTX3m31@%6NDD8?NUY7Q7d}cEB#j)zZ@6PS@%$xAX0dNjjGj*Ob|pBc|}cjsvhC zFmKY?&z;a4_s%CCgW3vhP)Hp*P-UnTbRTq2>ULpp%{`mX&NHsn4MIO(Z9WaIA?B7n zUhHT*J2jqbPzSkLUul_n@Kj}~e@w9Wo4Wk;?2qX-U+N3&lXDWo`f85cK9?ACyHfE@ z(wUkN?t?Z+A24g^aqpjm-~RAJM+gTqW6% zogk0txuuL+&GRvj>dhWBw^)*F9h_!QZ2|PG!ZOCqI#3BqV-wMeWV`CU1(4|(`Nido znp?Nc9}sg|t;7ESolyG4+``fd#*Ny#`i8sr8ZE3Unm1|I^z`ifD_5`KZ>E}Oo}b1I z6RqfJS$TyeW%%niQ}3AfGLKGKK(Lv)mqGO{l?=W=%rx)XRC9|KdTK^aeqr%de0WLd z>h+qZb>^8w?8WR$msfOp9~Sjh;Q7+bGVe;C$I(+RX64dL33cYH?OWwUYc`ik^pAJ(rWX34GVo z;vS`$(?M-8kV{E@QJXWZgtQ@CPf}m#o^%Yp(gB;A9`d4R1`OaKq)nDJKfuwS5YohB zCQosQ2x*Pef?hZ%=u<)eXnKZC>oKEWEzZ4KOn8P(iOx2?*^`q*z@-nS$BgvS2{pLM z;usZ356A)+Rh|HcCKVE@t4#wU=t(I_y-9@bmP39xNKX=>Y7?H~g6)CyCdDjG6ccb+ z^e3n~vsQxPk%HvWB0eRnKg>(AvASq29b;o(eSRgqKt&fFU7fv7)RP6O+8Xa+F{7?XPZS!)%v=7WzqRBlF#!yh?8HSHH z&G-$lN(uRZqdqyAb>Zr4kraeJDERxloZl34vrS9ftO}3&zL_3_G!FvIP-Z;?GOKkx zRTBfKWD1jrw4m9tA2O-;(n!mInFIlv9_#y#?Te&`eHhcH5O7|DiogdVpq~(ex7&S0 z6Gh@xUf)AD%UpW{sfXM;sA;xH8B8NEvTxUY8W^^yMT8~tw&i<~(pd5x=2e9JY;UnSOC)|H zyqB56E7v%jiM`LqRvH#J&H;xD6#1un7c3r8$Jf4vG%K-hV|w!0+-CH+WL@&B*r{NU z0tgnj_22u$oW8K;OP~EvvtY)TK@nRtzpZym0{)4|${Dz?zWqb|t^8Yd{lL{5ai!S& z0`*9I`M;&gFM+>|0#fEKz0RI?EU>@+nCP1EYSm2HeB=_vBHQlqZO&x_!0RSZhCGi*b(p-|C$y$_98zr3Mw^crt^9|xb<(q zR4n?gY5pS{y1(k!$!=6K0Q}s071Fskl9YlC)xy&6wI(x@z_q6Vq;-u_pyJtNy8>ay zh2Z8pGHJidRFbSgbCUvzH|0K23lsSVuKds=Rc_L5U;DJj-wYM=AQhL6OnEOWyREks zJTC?E2K8Rezl={3_z=}w{X3Am)jaFSmn;X_n4vF&f2Fs&-V&O&;(h^F?)Wt~>B1v| zpDG8;G88Eu4VQfmhx}H2q@jMw=T@Bo*PY#boB(?ONx$E6i0ejWg#(Y7&rJ>PP1(L8 zC~^_hyB>Q#<4UD$)SCQWOPjqmnN8fs?fm_evM;;>UQWTB4k?a_-n*4p(kLc6f@FaU ziQo5syiF|&CoxT2@Y$hKo!6uDlR}_aF(BJJmj9XY>8_f9Ip;vl#i?quk+ZX& z5Z$*c%KH1XNn!-44wjL)vFr>12Jq|(4xWJ0VXxy=KFcudAb z%U|s*Z7>cPaItZB*wu%rJIQ917ZHUI9(SlVye@BkCESX8EyKO!^6Dkr0NcKUJ=?&X z0Cy&{?kfJJUN^O1I))dfZtY2XOj&92{ihZ@#vs``jX%yT)<-&B%Sz}bi~km>)ToP_ zIUgJOZ07zAfOcniZLBL7Sp1qnjC*>6kVmLL(Ck>4d^rW^FdKhWlriSqBcpj8$HxXV zjSZdU#XQSN$$PZfvmM_I&rzP?hL}SW-}(9s4G9$isHax5)+68o);0IC|CGq{&-=pT zx?YRkuT@0G&&d{XsHk^*ONxc7UpuUCZviMb*6a)y0Q7Jxh{A{$PVu;Es>@ z(PIg3W^=AL{MLN#U3G!N0}Pp> z_%^&wpZ#0%f#&ywc}&#cl*ak)4v7={oinrQyC=4#+017|3m4bQt54VdHiP&%pWEV) z9*6dH^zRFMzvfG-IJCT7{l3;;Lw<1NgY>T@Xkx*TR+0-W4_h|6dh78rBTT>Y!_w;v zWYQw>D2hVQ(Tt%ZlSIaMv;X3>NHvF|^P+Af#nX|GpT6^OSLmD&Ht@N0O(u|duM3${ zl|Ao^NJdhb*?ZW4Ha(tcOuBAYf7RP>)u1F1*_rMAC#{uS7RpRTp6spyr&nCQ$f7@P zwV6B~_RYHP=Q1ssrXfI1#(ZIDv$-1f`YgL$m3}M$UT)I)6=#QSFDdzQTq}J-|L$n_ z{n6c{wMd9P_f%6*HM?zYF03WD6XLNFmRLlnQ{dXLN&B4Qge7B13z4cmFf*TJ@|*#+TwHfTwl3;Mt@W0Pn$$C;?FdD zUZ~18aWA_Z?!$GXEv>3&=#R&S&*Fg!TAAa~ipNHYHh^#D{Eyl>T8OiRQsz>hH`u-t zZnayj>*VfV{9T`AD=ZdqS^KEmu7~Y8)ZIn#pNavQJBfr$o+$jZkB}|*jVKIh*S#*IGSYhn+>}vD%_~7lf z^5=ls+P+K5%{MP;YX0h&mwW%oA)ygGnAx~jyUzAH#z9y%TrQjcKk=_;Ub7oWsF+ni z2CY=x69OHGLhi?Lk5UE)kfMu+4%w^%1G6F6OA`S#$uP>isrXUz(2=CYJUyEz+G#+j z=JHC$xA3Y<{ykd4`wolG?O_5VixegMmh|L`PJtvwExknl{*BXrrT+$1#jl84$mU@~ zW#SG!5pSVA$fljg^_|vKv_>QI1==SPXprQ?+lbCsBy4ZpjeTLr35$paP~_P;0cM08 zqEigX*Nff zvZwjJSAn`DZM}QecrN7mnzvtl)$s$Alduk|SnTALT4jgMF_kv_L&A%hX_HXc@dL!F zuYZ9y=a)X&FPbvt=K?Oi=%@@rR$EJEG|xM{`SEt{r)9~$I`sGx1F2!anXq2 zy4-{r(&z29gsri|77c50o>~pF`ehY?LM?{x*`_=U;G^+;lg9l*&Frzc8w#Y z?7zU3eX%&aj(n%uQuAL!3!j#rtJq$dd%;KiWiqab+7AGokAmrt4ih=WDyj++WX+pv zD9nhzkFd^9v^(juh$eb5F!sQ>s9hHL@)GP`CEw=H7h#RLyI-^LMci7^EwTCs(ii?n zGQq8n3d4bj2K2skOxo4Vu z^Ek*-IyLa>*#n_HAMaWjR@vSZ)5Eu^TGIn#pSysIbD)_pKg&z;uiRO`9?g&CuWdiw z6?4d1J{f(l_>%5dscb)vEhQk=->&sH%Q|Qom6;ffD!lacy~Qo2%d3j?Y2+D?lp}Vh zM8Kl`X?{s8xo*$53t0_84_(&*HAOyp1hsx7=NsZQZ5p7pp4cuSO;uG3B#u%(E;nwJP>?y3 zc$yiPdR70xETwK6(Mtq=AQh!t_v>C7K*dx5HI$o3gsnC^NliMO@dk&a${`}N&Q!P={^*n; z5GfaHGMi*y73Qg=i~?)r!Y|~{2Vg&5MUks|w2g@TPB<7daga`#+WL@5Kzx5Pq4%JX zsX1Jg-*nu4&mV1rHg46+TlW{@uhk(VQ@!TLon&4L>@@$KUHKfIIoExyQRPg>)$icf zQ!^xu9WT0PaZ}zxc;E5Vn*+zUlDzGo4Gy3T$|&W?3Y^$S3jKF~dTMUs^6V1=xFk+{ za32@`*}zU|;iV|Emk*-$flC6fw(r5sfuEA)-gzT)J-7j2nhnuBjX#FPw&G=~cY?n^ zyWAw+S_zIU{Yrj^RGmiZv-NgmlOx?QV*vhaJy3U!W}&x=grL*u@YBc$oHsXO;BZxS z)m?%1{A^@HW%FUe0t0cZqq3D9zm51K>@jtOnGmsS(IU-m0DKXL5|Ov70%5xs-O51u z`9L+lVr(OQ?PEyhs^Gq#CQ*cH9ZU;+L`R!r!4>c+U4Qmw+^oY+gBOb`{#oI>xZam! z_W1J9+gQ=p;L-78nq7At?=%14o?P=lWi?!(lXZAUVGDxN9c3EDY+?4xLdIF?lv1`q{tQmeH{+_H=DhL$dwr zaG7Bi>EfwhV4nqG{u<2Uarw0QzrIxaocFW06#P#;q?;Bqj}CYZ3O8c2)Mk~A^%8D5 z-(rKNJM$2JPiCoXr_W4U^_^nB#uLnH;Vk9v)B>8^7?L6H{vY=zo%OsBn$kVcL?x@T z{-s6SZT{H7S;6TIUj-s^|CTDVCb1=Lm)bceqdPsJirluE!u1W`8mWf7?tT+FMoAB- zdYvyIdARb3()GbVh)zYE=-awso4`bwGvJ*5(^ZRanU)ll^Xb`cZk$t_hJ1K>unO0_@cNp*jqBUu*;uQ4h7XI^Rje$T%$+xj8(rZ2*T zCD0n7Rwavk#uVB;eeZ!ZaE^V%>X7Q};Jd2RNf+j}5_eS5SJ=0+A&4i}kbN{%4A1r= zdrumIa)+|fv$LNUXE6{WadfIpgmv;u4BpqV9FvJ;m5U+3EPG&{R}uJx1M zxNlz&c2EIWFaGtm^hFeAV>Yy6)vErR-Bg~M7x~n&G9+XbTswf`bP0Wjq`Hgpvo9q5 zO3Zq0hQxzgwoLYIB76K2lXT7h(80MKAoN7!JAgUgD{#z*<@|dxZ3(h7>k@cI*RqB7 z3b@v^VSYJy|E1&$X7b4nc}CvA9l?*HE^|c954p_=FG;tSD*#{$u)2=Q8ldLHDDI{8 zI+q8f)zw+v;448WN>hsCzX)zHqmNwyNE-7g;^59wR=9W5@>mk`Qg&DWU$7*sp&1 zT0Ju}acZ^4llT5S5OMBU2QzUu=|YW6FC%j$4mV%$7YbZwZd&mGkiMBsHWKgNesraZ zJ{(Yd>jIOZqqA6bpm9N%VByTVd1*GQn8v%A^p|0Gv!4lhx$zxI{YJ%+x7Bq|OpPGt zV=LyVNUrbDc-T3HtWI13U3id}b@hiUL;1!o^`^pSF(ZD7&->lH3>SV8pvv2B((rnGdTo3k+=v)Ym zigZ2WpY`94&)uv>k7Hee0CUf_Rt@`Td}6RdZ2Qt}>HQ5|tgAFWhl(D+y6jT)0#mW| z1D%O`0d=GG0!9y0YaBZC>ysio$}K0yt(JWg3&9$ExyyEsu&`9)Wqh^Wd%+3bGY1#j zevQSIlWhRQ*ZoCbYFkf^rG5R;p7f~KM)hN?fF;9c;lc$GKmn00f3qp^;vt{pDXqYF z<|!brTJIwhhuyE+k-}Ad3_Xe0BOjnYZu19UpX_Db!G8v}{(DR+3(~vkvp2KRY8ODf z>Tx+?aP|^G?kf#*HbBh;!pDTn-nYp8a($08XlI=I{eOHige`4A|afyq#nZz5={UisWQNzrIq)^eH*vH@0@OGDeiz zQI$bUL)w5Va2H2g`aG8`pAPsiW*cz1xGX{NtQxTK=3eBaDd|S4-!*o7?^D2cKQAqv za_TLsquM@3j>&_~p2D@JBvXLFADU^u`3ULy@Af+iB;_u1+M1xm-lP&U{}JYSmw8)B zuNg||kqu4OC4aNPM%qL64twqc1@gDfEyJuTYwwA{4E z(!xwn--oq2vMboQNAK|F*v6B)nVvLu->|+pQ0#ug0q2`W{&TVV%jdnRCb&G#*uRWY zcO~Y5KzlhJxIsg)%uofFZ-K!BloDJm_&&erdOl|kP>8&w;l;flO1U~$8o^nXM4>df z^I%jRQk$le6=XXi>eN}kdJ2BZVjOjn5*dvjHy`5?YSY5?xyGB2jeV*qy5gMA612FOZzI8 zc~7-alpu%w?;&5yxQw%c{E!w$^j_47{XxDDa-Qbl)6hfBgz?>gX7ot9;{%lN-h@64#q66k$(9Z24VC?<+vX+<4-b{+_0+)nUv!-5l{Gbe6*xv&y}N07n3)~!7-dG_wf-S5%-&*{ z(tklTjLFt!=0~mU*i0^lnT7>P!I!rw(-qho7HnAIcsQm=<394j`f#o!bjHV z()OR}c<)$0jQCa;7oS)lDnCTV5?d0DU^J3+dvw1`?pVg@jgFhlD}ob?=#0qp4LpSK z*i>OoM4YZC>s6%%KD?`agr_+6S5XNutE{WI2yVJZ(Fo{muZ!zi8bt)%_wHm-wlxLK z#4(*LmXRzS?WkFSDe(%VQ%g4rPM0(yUW}XhWuK35V9twcu9(d&#Rk9(giCe#Ahd0t z2rF!h3Aed>xQO|+YZok+rObt8%^%^-XZ<#>T2VJ}2*#HE?CLB|mKat=6`x@g2u<70 z6EET{DliIj;yJqH=)iX<$(?1LREAYo`DVds#JsE}1&tU|DgiIeWRN3SQ9T%4h!q~S zqg+C#SdrRU1-2v-so=CN${Ime)NE(<%*)!8c%2`jGHfU|wvnq3l@N5>SlcO(gDsg% zu|>7B$YeY4zrfDU&Ypt@ccZ|6l!Jo<_}}i}=*XdQbadj-I5{~vFM-?*_72saY_WJgAO#xG3SO<`)>CNYnb;R1%HDIGSkU$f~dHI)2Lz8fN%FVXSpazc_W=m8R8h0A(>{#Rq>}$Wv6!`$_)p zSFjhy?Z)ski45hp7js)zMCb*?9P}Z&Azj^Ye*aw@8ssyIc5s{fQ<1P$1kJ%9Vr#-8 zhm>0S5$7XU3&vT%Pi}XWht@Cc#oPlF-SrSkCDGGF4}@n3C?Zqzs-ikv7otYzd;4ez zhNWlH^w@7#%%f5eqwXO*J)~Gfe6=`DB--vtB!eYe?LA#JI`X%FazHj3OA@~sfR8++AL6CwfDhlC9 z2wsFwjH9bxL_$J}x~3KbtnlvY+zi6F_arWBFF z)IN`>YLh#qt)zi;$2Vabib6k$DX5oWXh0812TI~@j z4{P#UWFX_r%%Oq_gGFrej=6R z=_vx*Mf-^wkiaO1Gp)y+%aBGg%Bnhb#QJFNq~iym6Ea-La~pRVPI5>`Ml{jl^U)-h6Zzh)or(UVJ82;N1N&i!4XBo4u_NqGg=>%%v1a&Pi$U!s*w?HxRENMzK`!nmgR&p!ed|3MIL&fA_o9tfAoT z_GfopEU1(mP@Q*7vHmS%e33Z8FQ>BS#dvqtSfGzk``rE%uU^Rx9SAN2OB<6-6Q+Za5}2x%9J7R zEf{2$TYK(ucJBPiYAb!$Gf+tRj%kooC{17ALJ~3`sA+gAaD6Y23i`cvK(GL09zAAg ze<1gRktx&2O^PbrGNiUDGGT0gTib%8J)Eec+YM!Ki_`w63!JBjiyzSEA5Qaqlx;x+ zXhO&DiH&+l`DTk}(yYVmT4jo~iM^9$$=((;m)D{p`nPEYAq~Y>KjR>fBT|RE9bbw& zrCw#ybjbtvxFFvwXqj9P83XbOs5QWMGLF<7+`13#XIKg5pXv{ZZXCb|G zTGm7Ev-(aJxWSP_j>mC2S{9ZNiO-NMeHh;L0Td$Tdzhwgm+s3eCuu=*^-b9aIZPYi zgIqK;ujZy_PJm&48GGBo#OU(a3*HgjH?TJJ)=@KocC+ahS=%0WFhrUG=(yabesvA8 zpy|3C&+~nkX+hI-5gdREIa$yQd=WRHXTUAfqE?iv9PJ7`Ley~RsBEih9xb8uV0XyY z4;pxrlwU`eqe@**AA-)$G_-(7@F;K5Nu%AGPKPXL%Yv_-9;E3-iuM-ArqJ~H2HYb~ zrO_a0qArbQ;6i$(Y!+`pgJ_9%KBO5&5C+DVEC95?)Emer3z`U>IAk3rN6pfBL({YV zV*gmI-p<;AY<5!9)Iw$IuHti_#wL|O+Ekp2qdAdi?xxaLaGz!8Ot5>K76iyxdYYYm zrej5I$lFWObPEd=c8KWo*VNR#Xs-8gLQRsY>0sqT(KnD&v2xK{=MSqYs@BvE`2JvQ zP4_7xPS1+y;utbjBIW2p&_>u<>8u`#)$@r*>al_ZV84(qZrWzpd|n4La~C49B?TJq z>}u|N80on()f;siX^soW`B#j!Cq*)&Hxhs4t~*I9_jjk zL=vDoaW(Qf@n*vty_-|JW?@FHS@Tw;zE$*JEv%5_L*e+ruDGOlFBpE3M}3M z9<*EB@ZhA1ytWpj;lxD?743p6p@;w5(#&uS9tqW?I*2`#qMVA-Jj7=gtlMm%$!l@d zmZJPvut;A+Q~&&JqPJ~{?(TgZ$*UBpRYF&9x^>B@*S6NTW`IGz@L`| z(~LCGd^RGu^g_lphK!t3G*8N7jfp}Jy@;dY!7#y@V<$?Vh#z@@(>Fv)wukmjA-5=o z6XB(&Wod>KqBXKr@bwG@OGIzJdf6)Ip<<;=Q~~uLeh2lGdRUQZ2QTKMjmC7exaC|g zlY*lv?taLR$bI%iz|yylrdO`NZ+{~w;A1lx;-M)&5GI#z!(<(&L?D$*xm`k0C*Yt7 z7tRgDQ~rTL!JG^6;GOX37>DNg%GkL06A<5%oLjVhoVT0O(79?baRP`J_ z#cQD#7xA2gfLCd$ft+iS5#Vjw{L-cP5uDVHJA_dOZ)|&qiL2}x+=bI+Cd9$J{$2C% z<&AB~5+5g8yGS3 zQKF0&Z)0{n;y0sua1DHA#7pp;+p?1z<0gr9CT-x?ZRl@n+gr7{)2%qa2kr?m#f~ps z_qA|$yk^nVNli-A0sI8q@IZz9kCev@pE}bLUF{fe13fX z1)c<%4{6#tb6_S>Py`}UwWuq)44F@D2|q$IcxY9L?IvTh^OsI6V-+QyoHi)^X>gTT z4wtfYAvB$w!6uesfBK|igs~VcK|MQAGeAXLIb5BH>y{X+;4c7+%oWrtH%OAu3oPXs zO8E;X%aQ!CeyJFJ&ykRBYSfP)A4NS^^$PAni+273UTmXcB^Xy~oL0!|2a^dK=oQcIm{`tW9NI2Kb5&-pfEkNrXB z8EUk5ebEbMwTDsj1n*O|rg!`qyiF=jb6j@+8Q+Fx=VG`JGu$ymP_O$p3XT~IVgC?v zh7bpLoFEO`>N|n@SeF&C9bkC_;m_R_8zSLMbCn?rC17|Fp)a97?eT%-!?8)b-F#eV zt{hlg5k{^E=FF!bq%f)8?Yf=14d2x5w{I5QTA_)l39ZiRz4U|A=)cp8b{C`iu~26~ zR(8eqn&FV+N-CV3sF*D?sIJeg)jgppf&VV1C``!Ahv|<zL2+?U`zVf>Q` z*b1$|rBMgc*zH;gp$Y8#vgurj3sHZ?#T@BKE@ze7dw9uAxCTc-71f9>-s0={EYgbg|Ar?jr~F=Zf&)tjT0tvvIz}D{|G-tk5RLbDYw_Y@C4}lZ5Hd)(#FqX)S(F$AT_@Nmw`(|B1AcozMj6yoFcqjtj(8fEQ~3^C;)!>8s|QD8RstsC zi8wlW(C+OuI;bv5@wwNoOnAooPC!b=6%OsO_qu;Ug*V3Uh0Mk~pKZA8chIuLMEC@X zQ8)h1;^Pl8tF#fckMQKBJzR4mzx33_Epn68sa?`rM;|$-jRH?Tqmk7NfipnZJzmq* zA6$C7;Gs+Ize4jXeY#QuaHNrg>R$%|R^Sz^Ba=LUSWPAwQi1s-GHQ77$1ytGPl!)~ zo|;Y^aY`~Rf-~vl*|CsT*R=_^(xYU&OsZLOu44C$gnz}my?ioOaWbPmVyXT#oR&BJ zsPTF&T<@aPbb>jqU&%??Nwej2VMt|adczVJcWqfuvf63VO8S>6tA4oEb~U9ZZpN!6Pe zrcOGWz_q8o#LdRnKJs97NirW(cf>u>(p?h;svxV-qgs~M>4JKBi1YncElZ#spV19*_+Wp*-Mi6w zU0WV&);<{PR#tr2;5y1P5H}t6L2^75o1+1jb*K}6X~;V74rycR)%VJeu(~JyV92TS zSWLn}xYW6e4qDWtZg?Gl8R>DRt+e391{Z(G)}^GTM5(?U*iIw@+!&wnBOh+LBQMUC z%l8xs(8RE=>Q7Tmm z&zh_-y98=6V|lXTXM+@kSn!Crb3(IAbj3rp3n&(=t0AEuC}lY@Saqx;!(+*oELIO| zEVn`eH_Dozuy$s}p0IEm2HSARCvY@#i;pwH0S7vjTK`5kaiEto!chm+tDHyCg)-pa zu!i%xuCc9WaFjD7nwSTNN86xk9LOREya+0$sio1?Wv@rlmx?O7+sLdz|K>ytUIb5F z2n5yKg&&EqjDyoN1|We~^3k=WiB^{tZe3rXH7>L*xKDRD1f2i?FE)0YyNOryab&kM)qiU>1Fj+p5-V`1(Po<;|Fi(YHQ2@En2or z^w4hYR0j00mf>0spgN!UN)i#Rhw)pNoQfyY1|v|>;E?e=yeqMP^u@Rbcuc%!aARUL zpczzD8|cVzT5%mr9_e&hgOdl{6D!=SHcee-R>y!15pX2{%+o_S?@u()7o2+d&beC%FqQLAMSTV!un`D|0ReL$ zkO2flfPg*_hzA02AV3QQ7=Zv65Rd`_PC(!y5U>LRKs7B;%?MO;0@ad0wH;7h08|?S z)ro)G{@dq&x3#~2V}JK8fA^{Xf4i5|gN{$)*j{G?pK{E^j*@rSYkN~|cY!^Sa@&aI z;*Q}vtST}zZn}oonBRyRso8836e`~eDJ6H|7ejupBG z;PQ@ls#=$j*db1=B)1(k3mAzjB2NRk z7UNL=jG{Zu)P>o4Im0B4oj__#5GnW3EZ8aF6E9Amm|3IUTH8uN;3JXdiKnP*ESI(| z@a|To>T$v+o+_o9el&sz7twa2n#PtsqAY*`%S8b~IucAe=eNcdYPxdwBA2ME$>k7( zG9QhwMF2I*=0TZc`bdyvDi3+8{Lzvmuu~glgCuiCPa=I%snu24frt?>220AtL|67M z@a_TYKex;K=RabL1?Dg4dy>lAsHH&c71PFNlz)0Qul;CNm2)2w3(C`)NgiR_4>l)_ z$@9-Br|`yE)dJb1(q3hf4N@Cy=aAb$A76ruuB0x&I3jSsEwh7KX3hlTq?(0!aB+L0 zZ!g8@;1H!`DfT0e{^LB z{gG!tmAOBuvID%boHidq8v7?viR6}djEJOYQ`e##Lz<)$ z82Qj{E$UhjOE;(HAm(?>iXAnk=D>qm5y$|MsTCx?sBxAPRB-LFbR_mv%{xG5lJj^v zGAO@m33%qq_7irAr5$--bBXZ{nR7^E&m?LoK+TC{Jwt*WC-SfvH6y&)B_K8oYALsQ z8btaKC-abQ*vvL+zG===0m!|X<<$Kt!0NT9OOUD5nyz`rnPY{|2lcDn2A!!w?gguO z=d`}#%+)5IqNd-OmON|jQ%X(m*pLUt0E2$13XyYb%b*jBnxTAoPvA1`RPwA?ffHCC zHzx7UtiXAFYTF{_w$T^54e!evj?QfyFT7d=XvH9%qVt;*2dtGkeiGk{5cBSqxevuhY`Mp53QFz~Ry z#Yc)h#stEEbzhTMQ6?TQWuY)vSV|BLJ9@zLm}g~pHBpwSi;K+`Z~L}J^pKG&>SQhb zJ5g_YInSnp&a7ysM^5o55|jQ$*BE<`mwGT9BytMQ==zXy!0@V~lc<&R?uY2s12jkI z2NY?oZY$doO=umRf?c8R%aIYbFg8cda0SQ@@)x~aO%$hdddOWGDBKqlYLkc zyhhSdq9#eQB-}OB_(+P69&Y|pjxw!LwX%spe3%5 zOPoyz9Zsc_%NIaMC(%V!7NShX=??4HYUVw9bhww!UW zis%qLzO&piullSo4-G_vAhEF2@J?Cu#*Ek^AegKhXjVG#U3i)#1mRlRyL@*B`Ry3F zcux^mZL1vCjp3d=ys)-Km+<;2tT@b@i=h>D9?ilq(%T5Kg>2?h>oJf9zr^bj zi{W0Oi{g0r@fM4mU^ZTkAjHgRFkZ!@3z0`*-N__IB^WF#kp$lMXpfuZn z1ae)W8UfBcOU#SJ38Qa|{jkVbSPt ztVjsj-x%$;H8e+Bw*0WRMVJ-tftmpwuBD#e)%p<;V;Domr6@10xMKX#MnR}02Q+po zfnS`~k5|IY5!sM%kKZ{g$lhODG2rT^DttaJO!+EWLsCTJ&L>)VCoI7L%i+p;dYQt0 z(FKK#*yQMf(W+t|4<|-&_9yxgh3!?D%Y5l>xuW2vlaASe^oG-6RkpstCQ->qqZ{l6 zk|ji5_&MjibOU5Tv~lJxCF89z-JF*+6fY+li`hQq+a9H+T$#~Ye&|p>UPxVooU3Ft zE#`=eSW$c0AWZw@qA0En?CX0#_)R&DZ>ahiA$(50K57HKrr{}Be5|^`4#Uc6B8SD@ z&2Fz9`TU6LU9q&m7O4cT*NzPy^IKO${eld!JW`|)j8P`CDbA>jADa~(qVVosz18zqE?`0Nz_>k;N89Xt7jj%ylS$ODl z9oiuP|G+fL(fGh(&|VZal(W}%ne$FHcc>pehE+cjkBiE!i|V1jP-M*(C3>5s_8Ir> zz%Vh^FnVjk?nh_RHn?uM!y1Z@_v(6&j|pQ(u+T)`ec!N*_wkSLz98s1R)ftCVe>Yg zsK0gQnYI zjKiPVREQA7PT_LPatI4NWZ*i@7hJ;^BW!)=0FDHgkM@tT9kC?7GoEJOL?6k~TOZ(j zfQ8pzF@PU-;KZs$C@K)GXl!RyGgp4nCwQl0gs+iH5Wa3Mf2)#)=s3Qg`NT476mLYB z_Le46Bg^A0`^;g->Z1bRG7H`Ph#C4SY3&aF*ubHLAa(FEGaC!xstbZNuq@n-v9k*7r?Dn<$>hy3Ie?3t?^ zUt6OuzEnpcF_9fY0UlMlYWCuGj^1zYsoEQ93tVRRXLRdF3cq2bS5U$`n?ybtR+VgK z)X&c&SPY2sbXg~-4=JeGSs3kX;=!7j6e#bGcx%#U>ZU_hwx3l{COxY|_RtO-a;>SLv-f|Hz6MDv>LnSZBXQ zZc{VsTpMD%)W5=5-Uu`4>nCVSJZj5y*)_JzR>4oG1{QFp+5?9a2#4 z5K{FII-x3rW$cD4`k_qpRL~lICA=DHH%)L>KHi_p9Tn`9yloWiFMm+6u}Um_DT>ji}8KyrA8+Zc>@kZxmmXky5f7Bgkj z?KV*ypMpD;PsXdqITHiUsjA*o$7$SDQ@3|Pxk)K1qu{SqN*YVJcLr~fXk=(teyx^| z@=+wO-esEB_PrM-eD1%8b@8;+*j2W@yDq7$6f6ax)h|OV0ldu$CZ$OhtLm>MgWjF3vr&7iQg2Y0f`n1zhN#jy%PEyy z`D(X9i=)1BEedQ0ng!I)(MWf_dD&>4+N2y&M3CvZ!R4stMsQYwkZ`1!%^}*O^!&JJ zpBUWADMwEfcZa_tUcW-8kJE$ps*Xl9L$+WBhardMDV+p95}PFlhCSV-Fi=aW`?HHe z#@!s}L`V90`6bQ>f+6$?7iC?dia(vKU5jy4uXHq@>9*S|lslms$rtJ^s-?lXXDgqR z`ep?c!b#?dX$1?(Xr!5{JXcX)KW~brN+x&rW#mTbz)^Lz$_oniW)A+N>fL;%M+Gp3 zUu*-67X=jM&2d6|HafmVawgb94xBxg8PbmNHflBpnV%(H&QLMk=SEBDTRqykW6CGF7q71{L z3$92K2JJLuPi8s+ zb`fxXGi16OPwa3N7)}mT5Btu@0S~6|EJmEP`Lc42nB)Pg&_+lgFxYmxnab`^mBI9_ zzG$oodhewbw+NGH|I7aF)d5nMw;HJV;%eJuZmVs(o)s>j=%->WB1$CRWIQ+Fa*hA| z%P8VwdA}g~1h?C%eh$J1=GAQ+n`NzuUE#%)#$dliuI&$!cGC%-s%TSE!auPzY2sB5 z47Q&%3YP9CO2dwvNG^R+PK>cDMQ@DVFjUjMQ+Y?JN~4PclEAHT+CTxJ8@s|^3ANxu5pVOr|MF~^CQir$8^QFB?$?2Hb6 z5k^+!7r5^Dg;<*@(6M;FadG7IitRxV*j?3}t=T{D7M-%TxnTLm#m)W{+tY}qdUrii zG$!;8uh_M&ax+XAdyf#^^9@~SyhRoBqi1Sd63+GS9@`L&>cgFPkFg;MX7AIs!j<`r9YhMea1myuEZzcHd1- z55)i+W&GBb4vR1a)6IgIq$9FsO151gm-Oi}mh3`qMLZwZu(uRJM>5SMm%*QVEBo!u zy>iul2o)B1a9d=EXKaL{qIX24j#at8KoR^EU3^t!x3TzGxo>h#TM}-+f@9TR|fqGE*W>`tQY`t{SZ#mNpgEr+btXl5@BEMkupxIUg~?ZmXc@bUE;j!sU%s zQzdo^U3OFIS`&pK9C(c$`9m!L6fDlR3^z`(D?h=hrHjUw(5uXt#zv_rJ}=WU z8Lr~eC3mwKdUG zYZ7NIJC=6E1Mka(Th@szSMdwIAiwpdE=sjPHTVkOmMAN(Q9hnJI%kOjOod7* zfj2wJC`2U=9ah0wM$qbfu(dKu&lfT0%|v@R zgH0fP{rr$Ug0}50S$(3{Um68ensgt**;*J0C@V=F3OkH{+0U+x zui$gj@u^8+S^kb{G_8E7bG26Zv63q5cr6Fv&jfw8WZLT!n(iqnJD-~n?TM#@+k$aU z!l$ETWiz-Pj}wD^C#=Pgy*(-_(!rc1k-lit8vnLNfpUu=Ev2Gzn7sR`c>x|KtHdoH z=r7Jel?hYrXOLVw_?-{3*BQ6l;?v$#oSuPuDk<3EQr)ixnD-s0Za{)m3w(0JXM<=x!}_<1b+Ttg+!o1y(WC^&pWQ;<=f zj%7q}ypB)87H@3CJExQaJ%u|q2M=S2iS;tbD?P8w_m2*2^rkYSXL}y=G?Xav54dkgmSjirEq8xP#MWg1y&%W&? zota4`r!k`f+N%_Pv?U4Gg*8M)S2E`N29}0ZC`NfQX)mi7+?qatxx$TP-p1rXVn?YZ z-&D_;M5%U0H03FCYs8>YK8)?^o0uJV#kSrrHMCFn!I4drh@OsSc31 zYg{<|`8LU0Cmjjpw+OmwvHeT1nmL~Z*zT}#BMoB&Bd<*D?JHZjj9&Vt7+y2*y~LbY z*_zZ^5bOz^DE2MY58J7DL6L!*PkpL)M;EsM#(-lw>5{Pe4c;ML`*@M4qx)plD(3TW zrX1V6G(3>Z0UNgL9O!2}>E=4p#jmh2mYYs5^zjyB`m8bS+0DE(r@!!DBOs)OH3Wk= zVxQf6W4q6&z)0lfeO62p{YBXJO^!apa^|>DU)-D_fyi(Vb`CRd$bSLvkU)@4EG%7q z!7NUHuubc;u{PILBaL_i|KR6B+y+=40aa=JWPC-0;uhNO&AaF1t>^>2tKg_m=QA>~ z<&1mCOr+lFB!eYGq-7k;4V9hy?PQbuBsXh z37(|_WL3)}jF97v*~=@!+3zMhCMMJ=?WW#7 z*ZSuwc*Qx3K9o zn3Y{t;L|wK4fiee7Wb>m{?It)p-Qk7kiylA8^$<|(bor=4HJAL#11KI#kjg*RW=*d z`N}B6q)oy#k@6vait-Ux>9RI1I0fUS8ZY~q5<(rDo_A~cqED+M4R36SdR9lKm8ZC7 zjTrjAI&^8+?hiYL9cwDN zKa4t_7J-+hSx9s*{5b-i(X|Y+g2R*XXXg7+zE7|Cc#Tm9udY?@-D>!+phD%}Ioepdm6HMYEyCl|m z)XgJM!)wBrhKX~08{UNZn)&`Cm0C;Y#87PZMg1-#CF=~;ptezK22=;%U@j9+0iFi= zVA$1|rs>5^jkmTN3(``` zZV?Mb#m%pr$U)raahoXi5c0-@5Uf4n6Pwu839iC}T{ry_AL+i2G~sdIf>%div^w$m zc&JaW#_Yh^%SO?6qsiM9N|?t-(&nvAGzWb)L&#p2@f{Z>h%@aD0ShivJ1tC1j zhi*3_ygjlMdC+y$gP|~f?u5PatNW5yiHfF4QKO0(8(Xa7d^ckrFl@ItDE#77#kmwF z3O(&8?a&C1yqBby3z%;q?J4hI~hcdC<;AG-)ugH!4cU7beNcB1qnRgG$+rB5%-oJ4rONk9vduEiY z(O&tnZ2$ueVym5+iU_i+8WoQoRyD#Wm%T|-RBj5aG=061d)E!RLsd09W7MvMTGEyq z5V5L86ZDlVeF~9UzS~9lDh#9!Jt|jDzOc`dE;~@ouRh6+zFKehB_&JV2S(BS3Qi@V zZJ&d})V)s{%`-i(EK_+It6ay{KA=(kWc+{-#GY4V)%W5Y{Ie6zAUrT~#E}bml5B3a z7276RjF0Jd^%ShcHaqNPEq4$X#vki|W3$c9zG!0Nb_))0Kt+YV@tiX~v{^^cAOezk z?vGdhG-y=$^r zEZ9xFn>&x5386beAIx|>L1YL?y!sHTrPxwR)7-fdmU12A~dI(GrlHUb{&Ho{B ztYiJ@<1q(?#|a}e;7@@l^gwyS^eQpp`NEN=F{X85;mro?&+e`}VSfy)O+_&LVvX=F zp&lN;3@xs%COn6yampnuFGaE>!wmszi-`GAL-2>|De#2*h$D0f4-pBYh^QG@>nL?? z!Cgn@Z}ECVP%@p__7QDZ)I3Q~F5+VfU9vYKpninDp3HWraoYlEYy>t<%}blq_4akz zU5G6hN}*#Q6SY&k5ow9?jgNyN*eAP$hxDu2y-$LnETE2_Ozb`K#nt@dRp-@g3b+Ww zLFFYhAjaOTW>13)DOcZt|ADq?uvr(x20?aC!3am!)t709&jIg}MB+$3l5uW!PIlCb zZm2Y4F;Xz3(HQYHVVpFoo}KlNmA1YD|BnBY2dFbP-!6hF8xWBM9%cdI0tmtH6HL9LL!XiWvI2ZAq+o zm=Qpb=ghxIHqbZdfS4H%vuD+#XGf9(O=nY|B{8Lwn0#+YJ`qiME3{34E|uuUNw-dU&U3q?bRZcp209Jhzl zOX|Flpy8-Eu}DvmA5Vb zZB?1~r$iS$&4j{TF2&M~CwTRrqiseH?%U5E?W2KLnf9WvTD0hJsfvwqi<5GlKI|8r z_NAzhUysJ|EDtZMPg_%B$-d$T`dw$${I@xO*l$Zoovm=C;JYgrYlLb9Y8;j5>ns^W zjIwT@JH-6qEVF?Am$@p_4;qeQ$a^3|v z-pGMqOP6k@ScGUR*wKe$%4OV}8NO>$ZH$59LH=UVvaCatKh7*pVgaP+D54Z&pC0lX zV#33#$Y;?0lO4IN0!NAF4Efesx8vCHG%hz^;q)FllW&o$mG#}iOmdFOrtRo+jX&si zE9~CcC7%#ZSsGmdO}0@hy}L154wn{R!PVfc41$)hQaas}9leJQ=|m^&;Xww)lLN_I zPpnu3b{yLPbKR;EwP!@XDB?D4kVEmLZG&uV#7A5hbjthE;?yA)WA_V)w!|HM!c2P^ zPVs4GAIPB>aJ{r>33Qd&!+Fh$C$~^S$a4jL+iEPxn5^5Y^KJ3wpE98bc9#}4+;sMi zpli_zT+z7V$<_^mNy=skq(V^FSG$5%VIWVzJ!r~2c#@}p=2*ojqYv?%p+sD50Ceth z$FdOh+BR5fzQcT=-}|~3cU@t_t{?WFX^Vd}k_lA-^~>?|P%E>bCF`kkx<&b!kSeHx zOXOP8$;0WzW>&QQUYBB*wV8G>_z)h#FC1n$|8Si3j`&2HByAxg0~i3ihR-TJZm5ly zB(hysse7%qM`yab&0zMTVEhfKhKbG_vOLCtjC-P+Sn+6*3 zIod1I@4nE%!HE2JZ2Qhaq`r!>+M?L4(BX^5HN0O{VW1T-s(zN}n`iMk+-6`dECG!( zyDEW}oo3B`Yv@G0ks;k?r<*(EOYd4jqx_TN1%qs47y7xr*mCo)Gl!?z&S#!i zXHzL*zU<9G`tUpj#j*o3`0NMgg?6!P(!;PfvILFjp0|EgfT{bqjEMNty!1sVD-a== zm4Qbr&toee)QHGlPL1&fl*n>BYLWjAuQVT_tNR#Zm5k=-t328jsFch~3dO;F4pxRDuyf8>qRs0TfInOkbB7)5xX%ZCLzbSjeB-~fngqgC< zrz~Z#p5^G-(;!pB;!>Hdutz|^;W9V=73GY*5jWNJzgp-q^T#HY+q4}%vHZ5Eul*s4 zOxJ!*1|BwJPn0g_jP7lkxv}Y9m?bDfDcyehQUvIKuy>01$(Ioqe4K-O{BWrl@~0Qq zLQ^&xWtT(@n(XBaO_9;xvklKUJrs6llAFZ}Y!vB=Jo!b^oql`N?xlHXW)=;v;g9B@ zc5)z$nSDJ}=@!JuZ+0oFK1?tYe2+h8vAP#l?#1IfiFW*`U32vOwk}h-htROk{Ip4V z+*dc&y|2ukzbDtprk@By7HD*FgRVz(&f>b7>KS>SGp+mCcOWNfbT8d%o=45vD{s0o zA5DW7illWVy22uSDpCd?-kv$I0}?d9##!~y^m?FQ-$9lK$jq-ZA1({N5?6_G$fldM zpJgol+!ZSsIC$(S*l?_?X~r&3t_YEFY)2m}q=kAc0`E`q+VpPEksg|>=3oKC2itX% zBM~-anU9vEc43g=&jY%NjiGI zp(1u^S5N0Yc02<kV&fR{m5P)J#4bQ>Q|xzK^Qatc+_(xmPDvHaCX!t=?iv?nExIg{V(CO>=j zfpnXe9{l#SpeZ^Vv%cNKpu3Bbww<=0b*GGVVJ-FCY4^Tvn)z~8$lMiziK)!1PYb(k ztYLZ-arpv82>brbKF&IZnw%A#FZIEE{ZoY_Pk|(ZNJb^&%${*6ADC)eJ1!el++_{g z*;ZAvU75jmGfLorUnReWNzhSmgO@bUb@VQGIlY-LzcsL5@eVf9Q#ZMPgJ&Ywt|MTV zcS_;NnF%3%hJ5IF&Z6}6E{elfX@*`4j%q#KWR@n`#p)KF^B+&s=YA+0xgVKVim+n? z_cEj>{ob?{3%J6dC#(ovSDkNd{6G=P9V;9$(oJ^Pyr9BlC!ckDVAB~{?GyczC)E(+ znH{~CpWm%Fd(ITE)z#Ht@IW;wZJSp+mQK_Q#%bk1kd9xyFLiHEjL$Srsy)-2!XP?| zCh=pn@5ZYAK9M(U?ckF6MMEp;eJs6=4+6yNhTJKqkFAJ$J&9$n>Tq}ew72xRx#QXF zOo&nH(yi5oU|O)kDIBZko0;!@K@YJ@W2aaGt7z*c5uw=>0#1< z-HJi|HRvezi;1vFZQG*bxxS%tsrCfZMWi_CIJgP1c6G$5Gu-q$iN2%DaI27cLswYJV> zad-P4&@T!~!7|&6Q{^*UeCBcNbYBdFd8y;nH&Y zNV{Gl$LpdC=Qrx#0^|uJBBr}_rkfO2_VZB6Clf_I)V1s2j&R9a@5$E;=@bscl8&Z1 zOzG|Y66fZ+<+!z=rRKzCgk9KJ{5kv59Ma)Yi>0cKf#b2P58|IX9$ zLtOmAFMVyQ#Z{{BI?Ugz4~CmAR!2F)bF(^n1qb&I_=7**y?-k8tWg}(8Hmq{tjk(iLC7wlPpF zDBdqtXa`THPlRoGBQRMQWIxZLpK!?ynFAL{@=9-R7?SwZt=ZG=PWNtf)UW*|W-NY@ z)Duq&K3@G?>0z05>_bm2TBgcsp^K!T&AeCS(yfpOiw}sQU*o?V78_Kj$A6I^Az5mz z24JaDvb8V1S1ms=(xPaF%Z5RA;*+8liQCVAAN zMWxo{B{Zj$Sw3W#w+L76V(IxZhwcJ@dzlzA)BAx-UrVS-wS0jg(&BEWl;wR}ToY*$m$}lWRvG@6q z)%e{dDZcHHP*Ha`OHHU7?e^kY28um}*`lSd{p~01=@$ZTk9AHQ^MVJJ3#(q&5>{8g zF__){jJ){b;aTMxJ~#8MTEd<>gK_S6&KiPojz-|G5CeP- zR}{62qa~STOP;W5s(0?eGKOc2m%z`#!f0fX`;T{cy1ai7ytGrmF$d%+feAy;@)sSg z>n4MIRGDSzWQ(3~lnIGk(g07^DqUsz7bLpeOIyh*WZ*)b?l&`4MU#3>Grcn$BXkpXa{pUNJ5TK@jNZOJv} z$hWqQI~uE-jyG0~`YEbjRe-e!`G@w6Fyz-CBdb;D`l4N`Y%^cGu|FSm!UUkKYq?R@ zTKhL>gThuv3VaoJk-Og6G_wa1HlgV{P##(_d9(Fle^e|?&Pq7ehgs$ViosWO2mRSS z;qN#K>kHhJ9*R26e7=%JKH~HRtu)|yY0=fM_>o8GN``y93hS3`7jk9orC*rvCai^oI$NT)ix0G+`~OBqwiR8;&^4}Nxmt5>4-SaD%2zV(FAca z4SA}ZD^%Y=FMVVZK3HR>JSxI7{v4P4K&>yj5t=&?Ez!dd5N#9t_?7v8AB6`>g5A9)RS(K5Fs(}W3ci-Ka{KoU+*qN>yo&s_RU0Ckn zo4YyqJs&*xu`NYcAuW?zX_PK1y0q@wlyLNXLV5h8+Vg>GL?CQ{mz+cR@J^1->`Tri z?&Op~Z<^KQGTi9!&Mfa+>Oy=_Kw`SFyW$oigdTnyy=@v(YGB!UMewPQ__S-e?-2~j z?-=*!d=`x7;gxtfKUW%71j~gU?u;-AHT^(K^Ww$X#V1KAgBRj)ezbT?_~CZzSLGIP zwown+^us5O;xMjB23vjR zA00iME>4$HA)O2EDJpMyXc^4hBiJu)s9{=RUeF!Y-+6SJtX7_l<=;>g@tzr5afI_# zsJ_t^*r(yQ3!6%9@=rcFbQ03z4{K1xMsxe9xJb)1eP$S+7xSXLUD!{#_u8La`c9U1 zrSd(G46N(I6VcL{M9$XXc$2TQQ?fh{)qDrR$KeHYffO^3{a+hOBB0LDA;TBWh7POv7;79JIoJ5%=S ze!*$2~f<+B%8NQ>n!zKDKuJ3J+Q z=F3p0>`{IJn%soYJ0h=ZxN1&G>CtnM<~R6E9i-m;&k!aPLOIkp7Rjd$P8cd9w0XK> zGaFb?bz9HvI9JUVoss5ovaIpL3*iSF^9N?%c+Tv|Yqz!v>FS^m;D?oR251h~sD}m1 z7>&(8WG?aJm(5KLZ4jHd#qW_5L;G^FO!reB16ize^N<*pzw8!SI)1r=W8WTbIg^m7 zYg}%=HB2=;SK{1Y8^A`O3C|AV4!tc5Vo{Ze)*o>*osOc|@jSeTn`0=%vFh^0-q?Q# zsrTRkolR3!SoYBNCfU}j#ZPqlq79}_Cr|LJ)ApEuqQ{PvzJB*A;Lb~gyw1Mno_8T* z6;CI@b3y+N`e>xvm_W#N#!3^*7tzVt&un1q-v{$Sm5+{1@sUaT-z z8m5awS{KH38qOS?BzZj$rZXm17f!Q%A%f9Yg(~H*DD3OW;Njb9ec<^&h$7t;>cCz~ zlTO&ZH{^u2<#IZNTgds>^GMR@M}BCpDLZ{NdXX%kUo9?)TBe~xe1N;;Oh_xkd-eX}j1o2E`9 z_d@CkZ=2QTlMCZt_Y*Ym1%%XFzF`}r%UMs{*+_P$gi{oG9^RTgD7g!s@di`Z3O6el zu-_F)rwebM$z!e32wiZ+Qq+zjmI>I5nE;-LtwZ>|`naq2XYv{F>b*U{0s zJHy(;?sxBdTFmh$DU+U-Z_SH)w$SBa50_+{(%2Y6sR^OjX}(OmowB_JdG%vn``M67 z>`$exk8LE%Re8mXzpV+eyq^Uz-j8Kz8Y+z~NWNwzv0CmGf2D5NcsM7lX^vA>bKtS^ zC&8`{_q99)j&|KrvqdkNd={8`Ej-55#v~EVwdhvztuOgHbST|KRf%VTG@m=wTf=|diY(=En3?C84*e4M0&|t=Ku%8Mj1S99 zm31`~UlcOO+Mvr`bSfPRQ^(OzRb4`n{HXyHy*cRlw6_}Efu%IRq)f`^=crmwSm-RWO4l4AgJHdll3dIESDX^sW%Qx`8xoz0 z9(t>9Kan>K^G3wgDYkRz^Ewkho@|<)aJO}U)BBl@Kt)FK*nE z1Mve>_$@M{uLn+UB$*34!s!Q}x53OU_sq=~BiJ6$6wqX3&yG)lf#+1MiaJEmLKvL; z5R0hX4hU7+FqeJeZ7u!%h=b40Y}ALIDI|X0Un_%`RIKVDnW{wzO{zK<(w=`$E|#AR zr(6e&L`Kg9vrm6%t9X>8%ewu;`xC-MS~kz_jpG3wTo=u`joM}EcUXflhz`z5JNIBl z_sH9{lBC&|NYS~W6L=T6#N5-ztUI8C$L7wTW8Ds3$dON?2kr=*8n~Ya=@>BN>%Z{A z*uW;41T7Cgi42Jm#_vd}g?~=GzI^`c0adz*oCq>&!9`a{vx9U6Gz@?T;!dC@o)52B?oGiz84ttS-j&YvGa2zo2IC~g zcLG`P8}U-*W+2Uf8(th=M(E|xJS7U+_2#M5hhJW5rJG|GusNoa7<%h2StE>9(29K< zEc4X-IGw-&@dF7ohaJVDd?i*4hikNm@+KvSHkuchhMir`_1k6xEoOF5q_7e16P7j0 zUP+0Qgx-Q~(vRksZgQiPz{j{a9mZbx5~4=f?SlaIg-Qp!_|p~FA*<*jp*eUujp*&# zh8DIjPC2S1-jJ7{<)_ulZ@)S@F$Ba|qg$PP6y<5v*=n6n(KTrij(dR>Tr-O$f~2~+ADS;t|8{=0!qBc7K(!=mT$t{;JviHDP@nn zf4NhAon5CXI>OK!dRr45;3GsDi8sltLG#{z&&@`+i z-rfh8yO-H(Q@sy~r!pU{#GU`^CXIk5^Uf9F>l0TTpWSxY38us#3lkgTtA;)YK=e^B zhB|i%$piQRz#tLuKbVaCVIFbq;@|)M?Sa2N@V5v4_Q3xw53H;(Kr1Vn(CR7{gy{f9 zAbt&mmjJRsJQ{?SAmsW#MSNvN9&kDbxQzjO4rV1#kkg)X!)Bzd2S{ z8G!vPfWrwuasqVbuZw* z{1^D2j2vBIl-j!r2izwBKI-YM-T|R2z`xf&wLq*;3uFio3XlwN1|SdM1i&5u7XUGU zf7G|Kik3gLIYVglTGlT$qoS|Wmx;gv z^&Y&sx*dcz0RAA310e>$6~xs+xbYu&tUCdmudn00onqSD^{0u0jKHt# z0PTR=k3RpgEiD2$dBFeOU&x=@{+$0Tf54doaB2YfvCaQxS%6#$;9vYZZRYpd({H7H z-t-8}ss6zO@P-4J0rUd=*iL@$`~l!D0DRWFRtM|b$8W{gUt8aqd^AXEWiCp*6+L&?aEJ6qM!9 z_CIeyUc2ukzZ7uo1Kd}r0Q^Tl7zsfA@_Fsh(_1+MxKi8iPr3a&WdZrezw2BJTOeh? z<0QZv0BZlfzKyK!f2i?K0JQ+V01WH(0M5Apt3RM=IiF|kUB%S!a}t%`Ux1hE?fx2X z2KQC!{k0jg1_%c6SPw{T}|Ax&V2Ke&zfZMF3Y7zo^-2a8V+IV#zkj~u6R`Cs5Q$h-Ee^jDPu_!|STOyy4X{cri7dhM4w;L+Dx z8d~qqKM-F6zPJ9XcvJNN&YpnV{LeW5aD9-P$7RP`ZNT{xwH^I|wnUYUqvroB4#1lO z;5fjV-$D3$ZRgjt(JVPus(rv;6JU_)`+o!TK!)&Vc>`|Dz>gaNgaORJIrSbj2JjF4 z47Ci@Yrl6L^rgQ(F9Uya0;B_OQ`CB(f?Ae!@vk6W383(2xl{82Ug-dH0E+-?oI&`j zPyb+?{YNfDIsQal{N?xj zKU!SC84K_)?^C}~#tv|e-$58+~V8U0ACZy4C4lLdq{8X)UCWrUoR4mzNq+AoaC(_yyQE>D6CyQKwO;$65&V z0=sbPYzrtW3<7pRGK>UxP(zB|T1d0z2MVB1IH$4 zRT!B2y#dC2jsX1jTy+aX561GX0FnTx^DcD&w*U$NA^_yp{5AUsd_%Q#2ypl|5B>AH z7zQ!~#PlkSisvdXu)7RE9S@|=fhGWan-^{Y-E#|s1^584es1Kq;t!zb+~3CAmgnh# zep7&GfJ}fqfa3rJ09^pY_xc585BSCQ`tiu*we%Kn+xxlQ_46~|`G9$R*!J(b|5XU= zG6D4ehJC6(RDtc$-?9JQ=0Aqb(2;*-mzoar(*soehVAcuCLyEHh^ky{yf(OV1EK2*#4&c}KZea5P z!1r;H_v0tG%XnIMJN^rMKXT~()&3ud0K2>ZU)R}R1!LE5b3%_w0{dV80Ea*IO&746 zwchsk_}~fE!;Th1=l)Im)P6wb4-|V%6xgDUfBfdW1n|L|?2r?jU@o`&UvQwdjp#pO z8`u;9I1BK*WAwf0ddwz<^P7NvYCHU~zNzQ40N8)WHn3#^a2?<|0CkM^dwct72z>DC zy$;wh0yqj#4p0IR4#4~G*rv(=d(<(gpW6D3w6!^`e^>v%k^}l_0Q!H!&d)fd{wtk- zG#%J>1o+)L|ApTW2!HJ#{-~YblLvYu0DiO0|6+R-gi61slK1z6t>KZ5hq z0Gs}|`v2Yhz!n>T9DpRiuitO{yZQf?``ZKSJpdkGe>lKU1oaJL8jL|uAiZBeM`i=h zsR&s7+CU7=3Q(~CK?o6uyaDu+Ai9QW2nL2?Kq``M1q^9Wu}TF=7z~x@0i8dX0;jwj z-^MDaLlYtZ-^VKSe|>rd7yqvxSy{Bu$cQcQS^_{Sw6K7Mo;>+=F8z1uA3H{Uj(-O5 z{XOpcd&~l~v}E(Ud8vuzr#6DT>)%Je=U=5CTqP*$4A^elcIn$ZPa#;}vIRN{&r01GvHL;OI#@9$dQZBxU(A31(M2XjjMLEg1{ z>ik)u*X~w*g+JJ)`XK1LJT*M+!^}Q?k`o2;T?P1u`(q9^o*BrK0I1LZP2d}eUF-8w zjmSj3*X+L!C>n*`y>!70Z_no>iFw4z(U-&Jk)$7o?ws) zx-szox1L4=%-zBudHHW=)HQM8kch}HXP`@>f!M(R)IN#2zAZH$8R*c~iw?z#M54n9 z7+jc+sDiA#s0cdD59f~w3)B&Hb~2Sw7Zo88!M2AeEG`VKBN~Gyi0bJwYNH4Qbf_;j zMg-&!Bj|`mgokMo{DQzvhy5^@8$gE`_6WzNH0zl_ODt_xtdm|Y|aEK zhew*?>vAFPm>Dwt9~*g^4_DcW1eME0#g(&}6!%;yVkP=K+FF6%u(V_FTb6bLe%sRCgO@DrBlw!7eFk5*v{Uew zrJaF4wzRL{JxluzKD4xaq)X^O5jQXP$sNQR!a?Ze8GLDQYVfVWcLqNg{ABQp!Bc~0 z2G0#%8r<+V2Yyh$U-5!~&^m2bDCdMyHCbj^B<4xn%JPLw1WnVf*T*$_>kKdIa#mZ< z$l@?mahg6G`h#v>coe%*u}1pADDEavmX3RVkZ*Z0_BTyQLIOFV+O8BEJ1qJTBYQE7e4G(obXpZ`! d6!3!tCF33@d?GnzYB-6fTj|8Q@c&huz%Q^ks!IR> literal 0 HcmV?d00001 diff --git a/pixelshaders/Curvature/fragment b/pixelshaders/Curvature/fragment deleted file mode 100644 index 5c311da9..00000000 --- a/pixelshaders/Curvature/fragment +++ /dev/null @@ -1,17 +0,0 @@ -//CRT curvature shader -//license: GPL -//author: DOLLS - -uniform sampler2D rubyTexture; - -#define distortion 0.2 - -vec2 barrelDistortion(vec2 coord) { - vec2 cc = coord - 0.5; - float dist = dot(cc, cc); - return coord + cc * (dist + distortion * dist * dist) * distortion; -} - -void main(void) { - gl_FragColor = texture2D(rubyTexture, barrelDistortion(gl_TexCoord[0].xy)); -} diff --git a/pixelshaders/HDRTV/fragment b/pixelshaders/HDRTV/fragment deleted file mode 100644 index 16098b90..00000000 --- a/pixelshaders/HDRTV/fragment +++ /dev/null @@ -1,14 +0,0 @@ -//HDRTV GLSL shader -//license: GPL -//original version by SimoneT -//ruby port by byuu - -uniform sampler2D rubyTexture; - -void main(void) { - vec4 rgb = texture2D(rubyTexture, gl_TexCoord[0].xy); - vec4 intens = smoothstep(0.2,0.8,rgb) + normalize(vec4(rgb.xyz, 1.0)); - - if(fract(gl_FragCoord.y * 0.5) > 0.5) intens = rgb * 0.8; - gl_FragColor = intens; -} diff --git a/pixelshaders/HDRTV/vertex b/pixelshaders/HDRTV/vertex deleted file mode 100644 index 70591d55..00000000 --- a/pixelshaders/HDRTV/vertex +++ /dev/null @@ -1,9 +0,0 @@ -//HDRTV GLSL shader -//license: GPL -//original version by SimoneT -//ruby port by byuu - -void main(void) { - gl_Position = ftransform(); - gl_TexCoord[0] = gl_MultiTexCoord0; -} diff --git a/pixelshaders/HLSL/sepia.fx b/pixelshaders/HLSL/sepia.fx deleted file mode 100644 index a9295d06..00000000 --- a/pixelshaders/HLSL/sepia.fx +++ /dev/null @@ -1,25 +0,0 @@ -texture rubyTexture; - -float4 vec; - -sampler s0 = sampler_state { texture = ; }; -float3 LightColor = { 1.0, 0.7, 0.5 }; -float3 DarkColor = { 0.2, 0.05, 0.0 }; - -float4 DiffColorPass(in float2 Tex : TEXCOORD0) : COLOR0 -{ - vec.x = 0.5; - vec.y = 1.0; - float3 scnColor = LightColor * tex2D(s0, Tex).xyz; - float3 grayXfer = float3(0.3, 0.59, 0.11); - float gray = dot(grayXfer, scnColor); - float3 muted = lerp(scnColor, gray.xxx, vec.x); - float3 sepia = lerp(DarkColor, LightColor, gray); - float3 result = lerp(muted, sepia, vec.y); - return float4(result, 1); -} - -Technique T0 -{ - pass p0 { PixelShader = compile ps_2_0 DiffColorPass(); } -} diff --git a/pixelshaders/HQ2x/fragment b/pixelshaders/HQ2x/fragment deleted file mode 100644 index 0bf24db3..00000000 --- a/pixelshaders/HQ2x/fragment +++ /dev/null @@ -1,49 +0,0 @@ -//HQ2x GLSL shader -//license: GPL -//original version by guest(r) -//ruby port by byuu - -uniform sampler2D rubyTexture; - -const float mx = 0.325; // start smoothing wt. -const float k = -0.250; // wt. decrease factor -const float max_w = 0.25; // max filter weigth -const float min_w =-0.05; // min filter weigth -const float lum_add = 0.25; // effects smoothing - -void main() { - vec3 c00 = texture2D(rubyTexture, gl_TexCoord[1].xy).xyz; - vec3 c10 = texture2D(rubyTexture, gl_TexCoord[1].zw).xyz; - vec3 c20 = texture2D(rubyTexture, gl_TexCoord[2].xy).xyz; - vec3 c01 = texture2D(rubyTexture, gl_TexCoord[4].zw).xyz; - vec3 c11 = texture2D(rubyTexture, gl_TexCoord[0].xy).xyz; - vec3 c21 = texture2D(rubyTexture, gl_TexCoord[2].zw).xyz; - vec3 c02 = texture2D(rubyTexture, gl_TexCoord[4].xy).xyz; - vec3 c12 = texture2D(rubyTexture, gl_TexCoord[3].zw).xyz; - vec3 c22 = texture2D(rubyTexture, gl_TexCoord[3].xy).xyz; - vec3 dt = vec3(1.0, 1.0, 1.0); - - float md1 = dot(abs(c00 - c22), dt); - float md2 = dot(abs(c02 - c20), dt); - - float w1 = dot(abs(c22 - c11), dt) * md2; - float w2 = dot(abs(c02 - c11), dt) * md1; - float w3 = dot(abs(c00 - c11), dt) * md2; - float w4 = dot(abs(c20 - c11), dt) * md1; - - float t1 = w1 + w3; - float t2 = w2 + w4; - float ww = max(t1, t2) + 0.0001; - - c11 = (w1 * c00 + w2 * c20 + w3 * c22 + w4 * c02 + ww * c11) / (t1 + t2 + ww); - - float lc1 = k / (0.12 * dot(c10 + c12 + c11, dt) + lum_add); - float lc2 = k / (0.12 * dot(c01 + c21 + c11, dt) + lum_add); - - w1 = clamp(lc1 * dot(abs(c11 - c10), dt) + mx, min_w, max_w); - w2 = clamp(lc2 * dot(abs(c11 - c21), dt) + mx, min_w, max_w); - w3 = clamp(lc1 * dot(abs(c11 - c12), dt) + mx, min_w, max_w); - w4 = clamp(lc2 * dot(abs(c11 - c01), dt) + mx, min_w, max_w); - - gl_FragColor.xyz = w1 * c10 + w2 * c21 + w3 * c12 + w4 * c01 + (1.0 - w1 - w2 - w3 - w4) * c11; -} diff --git a/pixelshaders/HQ2x/vertex b/pixelshaders/HQ2x/vertex deleted file mode 100644 index 488a870e..00000000 --- a/pixelshaders/HQ2x/vertex +++ /dev/null @@ -1,26 +0,0 @@ -//HQ2x GLSL shader -//license: GPL -//original version by guest(r) -//ruby port by byuu - -uniform vec2 rubyTextureSize; - -void main() { - float x = 0.5 * (1.0 / rubyTextureSize.x); - float y = 0.5 * (1.0 / rubyTextureSize.y); - vec2 dg1 = vec2( x, y); - vec2 dg2 = vec2(-x, y); - vec2 dx = vec2(x, 0.0); - vec2 dy = vec2(0.0, y); - - gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; - gl_TexCoord[0] = gl_MultiTexCoord0; - gl_TexCoord[1].xy = gl_TexCoord[0].xy - dg1; - gl_TexCoord[1].zw = gl_TexCoord[0].xy - dy; - gl_TexCoord[2].xy = gl_TexCoord[0].xy - dg2; - gl_TexCoord[2].zw = gl_TexCoord[0].xy + dx; - gl_TexCoord[3].xy = gl_TexCoord[0].xy + dg1; - gl_TexCoord[3].zw = gl_TexCoord[0].xy + dy; - gl_TexCoord[4].xy = gl_TexCoord[0].xy + dg2; - gl_TexCoord[4].zw = gl_TexCoord[0].xy - dx; -} diff --git a/pixelshaders/Pixellate/fragment b/pixelshaders/Pixellate/fragment deleted file mode 100644 index ff94deea..00000000 --- a/pixelshaders/Pixellate/fragment +++ /dev/null @@ -1,36 +0,0 @@ -//Pixellate shader -//license: GPL -//author: Fes - -uniform sampler2D rubyTexture; -uniform vec2 rubyTextureSize; - -void main() { - vec2 texelSize = 1.0 / rubyTextureSize; - - vec2 range; - range.x = dFdx(gl_TexCoord[0].x) / 2.0 * 0.99; - range.y = dFdy(gl_TexCoord[0].y) / 2.0 * 0.99; - - float left = gl_TexCoord[0].x - range.x; - float top = gl_TexCoord[0].y + range.y; - float right = gl_TexCoord[0].x + range.x; - float bottom = gl_TexCoord[0].y - range.y; - - vec4 topLeftColor = texture2D(rubyTexture, (floor(vec2(left, top) / texelSize) + 0.5) * texelSize); - vec4 bottomRightColor = texture2D(rubyTexture, (floor(vec2(right, bottom) / texelSize) + 0.5) * texelSize); - vec4 bottomLeftColor = texture2D(rubyTexture, (floor(vec2(left, bottom) / texelSize) + 0.5) * texelSize); - vec4 topRightColor = texture2D(rubyTexture, (floor(vec2(right, top) / texelSize) + 0.5) * texelSize); - - vec2 border = clamp(round(gl_TexCoord[0] / texelSize) * texelSize, vec2(left, bottom), vec2(right, top)); - - float totalArea = 4.0 * range.x * range.y; - - vec4 averageColor; - averageColor = ((border.x - left) * (top - border.y) / totalArea) * topLeftColor; - averageColor += ((right - border.x) * (border.y - bottom) / totalArea) * bottomRightColor; - averageColor += ((border.x - left) * (border.y - bottom) / totalArea) * bottomLeftColor; - averageColor += ((right - border.x) * (top - border.y) / totalArea) * topRightColor; - - gl_FragColor = averageColor; -} diff --git a/pixelshaders/Pixellate/vertex b/pixelshaders/Pixellate/vertex deleted file mode 100644 index 898112ee..00000000 --- a/pixelshaders/Pixellate/vertex +++ /dev/null @@ -1,8 +0,0 @@ -//Pixellate shader -//license: GPL -//author: Fes - -void main() { - gl_Position = ftransform(); - gl_TexCoord[0] = gl_MultiTexCoord0; -} diff --git a/pixelshaders/Scale2x/fragment b/pixelshaders/Scale2x/fragment deleted file mode 100644 index c72625ae..00000000 --- a/pixelshaders/Scale2x/fragment +++ /dev/null @@ -1,28 +0,0 @@ -//Scale2x GLSL shader -//license: GPL -//original version by Pete Bernert -//ruby port by byuu - uniform sampler2D rubyTexture; -uniform vec2 rubyTextureSize; - -void main() { - vec4 colD, colF, colB, colH, col, tmp; - vec2 sel; - - col = texture2DProj(rubyTexture, gl_TexCoord[0]); //central (can be E0-E3) - colD = texture2DProj(rubyTexture, gl_TexCoord[1]); //D (left) - colF = texture2DProj(rubyTexture, gl_TexCoord[2]); //F (right) - colB = texture2DProj(rubyTexture, gl_TexCoord[3]); //B (top) - colH = texture2DProj(rubyTexture, gl_TexCoord[4]); //H (bottom) - - sel = fract(gl_TexCoord[0].xy * rubyTextureSize.xy); //where are we (E0-E3)? - //E0 is default - if(sel.y >= 0.5) { tmp = colB; colB = colH; colH = tmp; } //E1 (or E3): swap B and H - if(sel.x >= 0.5) { tmp = colF; colF = colD; colD = tmp; } //E2 (or E3): swap D and F - - if(colB == colD && colB != colF && colD != colH) { //do the Scale2x rule - col = colD; - } - - gl_FragColor = col; -} diff --git a/pixelshaders/Scale2x/vertex b/pixelshaders/Scale2x/vertex deleted file mode 100644 index 6e172cd1..00000000 --- a/pixelshaders/Scale2x/vertex +++ /dev/null @@ -1,28 +0,0 @@ -//Scale2x GLSL shader -//license: GPL -//original version by Pete Bernert -//ruby port by byuu - -uniform vec2 rubyTextureSize; - -void main() { - vec4 offsetx; - vec4 offsety; - - gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; - - offsetx.x = 1.0 / rubyTextureSize.x; - offsetx.y = 0.0; - offsetx.w = 0.0; - offsetx.z = 0.0; - offsety.y = 1.0 / rubyTextureSize.y; - offsety.x = 0.0; - offsety.w = 0.0; - offsety.z = 0.0; - - gl_TexCoord[0] = gl_MultiTexCoord0; //center - gl_TexCoord[1] = gl_TexCoord[0] - offsetx; //left - gl_TexCoord[2] = gl_TexCoord[0] + offsetx; //right - gl_TexCoord[3] = gl_TexCoord[0] - offsety; //top - gl_TexCoord[4] = gl_TexCoord[0] + offsety; //bottom -} diff --git a/snesfilter/2xsai/2xsai.cpp b/snesfilter/2xsai/2xsai.cpp deleted file mode 100644 index 75923a0e..00000000 --- a/snesfilter/2xsai/2xsai.cpp +++ /dev/null @@ -1,132 +0,0 @@ -//2xSaI / Super 2xSaI / Super Eagle filter -//authors: kode54 and Kreed -//license: GPL - -#include "2xsai.hpp" -#include "implementation.cpp" - -//===== -//2xSaI -//===== - -void _2xSaIFilter::size(unsigned &outwidth, unsigned &outheight, unsigned width, unsigned height) { - outwidth = width; - outheight = height; - - if(width <= 256 && height <= 240) { - outwidth *= 2; - outheight *= 2; - } -} - -void _2xSaIFilter::render( - uint32_t *output, unsigned outpitch, const uint16_t *input, unsigned pitch, - const unsigned *line, unsigned width, unsigned height -) { - if(width > 256 || height > 240) { - filter_direct.render(output, outpitch, input, pitch, line, width, height); - return; - } - - for(unsigned y = 0; y < height; y++) { - const uint16_t *line_in = (const uint16_t *) (((const uint8_t*)input) + pitch * y); - uint32_t *line_out = temp + y * 256; - for(unsigned x = 0; x < width; x++) { - line_out[x] = colortable[line_in[x]]; - } - } - - _2xSaI32( (unsigned char *) temp, 1024, 0, (unsigned char *) output, outpitch, width, height ); -} - -_2xSaIFilter::_2xSaIFilter() { - temp = new uint32_t[256*240]; -} - -_2xSaIFilter::~_2xSaIFilter() { - delete[] temp; -} - -//=========== -//Super 2xSaI -//=========== - -void Super2xSaIFilter::size(unsigned &outwidth, unsigned &outheight, unsigned width, unsigned height) { - outwidth = width; - outheight = height; - - if(width <= 256 && height <= 240) { - outwidth *= 2; - outheight *= 2; - } -} - -void Super2xSaIFilter::render( - uint32_t *output, unsigned outpitch, const uint16_t *input, unsigned pitch, - const unsigned *line, unsigned width, unsigned height -) { - if(width > 256 || height > 240) { - filter_direct.render(output, outpitch, input, pitch, line, width, height); - return; - } - - for(unsigned y = 0; y < height; y++) { - const uint16_t *line_in = (const uint16_t *) (((const uint8_t*)input) + pitch * y); - uint32_t *line_out = temp + y * 256; - for(unsigned x = 0; x < width; x++) { - line_out[x] = colortable[line_in[x]]; - } - } - - Super2xSaI32( (unsigned char *) temp, 1024, 0, (unsigned char *) output, outpitch, width, height ); -} - -Super2xSaIFilter::Super2xSaIFilter() { - temp = new uint32_t[256*240]; -} - -Super2xSaIFilter::~Super2xSaIFilter() { - delete[] temp; -} - -//=========== -//Super Eagle -//=========== - -void SuperEagleFilter::size(unsigned &outwidth, unsigned &outheight, unsigned width, unsigned height) { - outwidth = width; - outheight = height; - - if(width <= 256 && height <= 240) { - outwidth *= 2; - outheight *= 2; - } -} - -void SuperEagleFilter::render( - uint32_t *output, unsigned outpitch, const uint16_t *input, unsigned pitch, - const unsigned *line, unsigned width, unsigned height -) { - if(width > 256 || height > 240) { - filter_direct.render(output, outpitch, input, pitch, line, width, height); - return; - } - - for(unsigned y = 0; y < height; y++) { - const uint16_t *line_in = (const uint16_t *) (((const uint8_t*)input) + pitch * y); - uint32_t *line_out = temp + y * 256; - for(unsigned x = 0; x < width; x++) { - line_out[x] = colortable[line_in[x]]; - } - } - - SuperEagle32( (unsigned char *) temp, 1024, 0, (unsigned char *) output, outpitch, width, height ); -} - -SuperEagleFilter::SuperEagleFilter() { - temp = new uint32_t[256*240]; -} - -SuperEagleFilter::~SuperEagleFilter() { - delete[] temp; -} diff --git a/snesfilter/2xsai/2xsai.hpp b/snesfilter/2xsai/2xsai.hpp deleted file mode 100644 index 361f47e9..00000000 --- a/snesfilter/2xsai/2xsai.hpp +++ /dev/null @@ -1,35 +0,0 @@ -class _2xSaIFilter { -public: - void size(unsigned&, unsigned&, unsigned, unsigned); - void render(uint32_t*, unsigned, const uint16_t*, unsigned, const unsigned*, unsigned, unsigned); - - _2xSaIFilter(); - ~_2xSaIFilter(); - -private: - uint32_t *temp; -} filter_2xsai; - -class Super2xSaIFilter { -public: - void size(unsigned&, unsigned&, unsigned, unsigned); - void render(uint32_t*, unsigned, const uint16_t*, unsigned, const unsigned*, unsigned, unsigned); - - Super2xSaIFilter(); - ~Super2xSaIFilter(); - -private: - uint32_t *temp; -} filter_super2xsai; - -class SuperEagleFilter { -public: - void size(unsigned&, unsigned&, unsigned, unsigned); - void render(uint32_t*, unsigned, const uint16_t*, unsigned, const unsigned*, unsigned, unsigned); - - SuperEagleFilter(); - ~SuperEagleFilter(); - -private: - uint32_t *temp; -} filter_supereagle; diff --git a/snesfilter/2xsai/implementation.cpp b/snesfilter/2xsai/implementation.cpp deleted file mode 100644 index cebca7ef..00000000 --- a/snesfilter/2xsai/implementation.cpp +++ /dev/null @@ -1,1171 +0,0 @@ -static uint32_t colorMask = 0xFEFEFE; -static uint32_t lowPixelMask = 0x010101; -static uint32_t qcolorMask = 0xFCFCFC; -static uint32_t qlowpixelMask = 0x030303; -static uint32_t redblueMask = 0xFF00FF; -static uint32_t greenMask = 0xFF00; - -uint32_t qRGB_COLOR_MASK[2] = { 0xFEFEFE, 0xFEFEFE }; - -static inline int GetResult1 (uint32_t A, uint32_t B, uint32_t C, uint32_t D, - uint32_t /* E */) -{ - int x = 0; - int y = 0; - int r = 0; - - if (A == C) - x += 1; - else if (B == C) - y += 1; - if (A == D) - x += 1; - else if (B == D) - y += 1; - if (x <= 1) - r += 1; - if (y <= 1) - r -= 1; - return r; -} - -static inline int GetResult2 (uint32_t A, uint32_t B, uint32_t C, uint32_t D, - uint32_t /* E */) -{ - int x = 0; - int y = 0; - int r = 0; - - if (A == C) - x += 1; - else if (B == C) - y += 1; - if (A == D) - x += 1; - else if (B == D) - y += 1; - if (x <= 1) - r -= 1; - if (y <= 1) - r += 1; - return r; -} - -static inline int GetResult (uint32_t A, uint32_t B, uint32_t C, uint32_t D) -{ - int x = 0; - int y = 0; - int r = 0; - - if (A == C) - x += 1; - else if (B == C) - y += 1; - if (A == D) - x += 1; - else if (B == D) - y += 1; - if (x <= 1) - r += 1; - if (y <= 1) - r -= 1; - return r; -} - -static inline uint32_t INTERPOLATE (uint32_t A, uint32_t B) -{ - if (A != B) { - return (((A & colorMask) >> 1) + ((B & colorMask) >> 1) + - (A & B & lowPixelMask)); - } else - return A; -} - -static inline uint32_t Q_INTERPOLATE (uint32_t A, uint32_t B, uint32_t C, uint32_t D) -{ - register uint32_t x = ((A & qcolorMask) >> 2) + - ((B & qcolorMask) >> 2) + - ((C & qcolorMask) >> 2) + ((D & qcolorMask) >> 2); - register uint32_t y = (A & qlowpixelMask) + - (B & qlowpixelMask) + (C & qlowpixelMask) + (D & qlowpixelMask); - - y = (y >> 2) & qlowpixelMask; - return x + y; -} - -static inline int GetResult1_32 (uint32_t A, uint32_t B, uint32_t C, uint32_t D, - uint32_t /* E */) -{ - int x = 0; - int y = 0; - int r = 0; - - if (A == C) - x += 1; - else if (B == C) - y += 1; - if (A == D) - x += 1; - else if (B == D) - y += 1; - if (x <= 1) - r += 1; - if (y <= 1) - r -= 1; - return r; -} - -static inline int GetResult2_32 (uint32_t A, uint32_t B, uint32_t C, uint32_t D, - uint32_t /* E */) -{ - int x = 0; - int y = 0; - int r = 0; - - if (A == C) - x += 1; - else if (B == C) - y += 1; - if (A == D) - x += 1; - else if (B == D) - y += 1; - if (x <= 1) - r -= 1; - if (y <= 1) - r += 1; - return r; -} - -#define BLUE_MASK565 0x001F001F -#define RED_MASK565 0xF800F800 -#define GREEN_MASK565 0x07E007E0 - -#define BLUE_MASK555 0x001F001F -#define RED_MASK555 0x7C007C00 -#define GREEN_MASK555 0x03E003E0 - -void Super2xSaI (uint8_t *srcPtr, uint32_t srcPitch, - uint8_t *deltaPtr, uint8_t *dstPtr, uint32_t dstPitch, - int width, int height) -{ - uint16_t *bP; - uint8_t *dP; - uint32_t inc_bP; - uint32_t Nextline = srcPitch >> 1; - { - inc_bP = 1; - - for (; height; height--) { - bP = (uint16_t *) srcPtr; - dP = (uint8_t *) dstPtr; - - for (uint32_t finish = width; finish; finish -= inc_bP) { - uint32_t color4, color5, color6; - uint32_t color1, color2, color3; - uint32_t colorA0, colorA1, colorA2, colorA3, - colorB0, colorB1, colorB2, colorB3, colorS1, colorS2; - uint32_t product1a, product1b, product2a, product2b; - - //--------------------------------------- B1 B2 - // 4 5 6 S2 - // 1 2 3 S1 - // A1 A2 - - colorB0 = *(bP - Nextline - 1); - colorB1 = *(bP - Nextline); - colorB2 = *(bP - Nextline + 1); - colorB3 = *(bP - Nextline + 2); - - color4 = *(bP - 1); - color5 = *(bP); - color6 = *(bP + 1); - colorS2 = *(bP + 2); - - color1 = *(bP + Nextline - 1); - color2 = *(bP + Nextline); - color3 = *(bP + Nextline + 1); - colorS1 = *(bP + Nextline + 2); - - colorA0 = *(bP + Nextline + Nextline - 1); - colorA1 = *(bP + Nextline + Nextline); - colorA2 = *(bP + Nextline + Nextline + 1); - colorA3 = *(bP + Nextline + Nextline + 2); - - //-------------------------------------- - if (color2 == color6 && color5 != color3) { - product2b = product1b = color2; - } else if (color5 == color3 && color2 != color6) { - product2b = product1b = color5; - } else if (color5 == color3 && color2 == color6) { - register int r = 0; - - r += GetResult (color6, color5, color1, colorA1); - r += GetResult (color6, color5, color4, colorB1); - r += GetResult (color6, color5, colorA2, colorS1); - r += GetResult (color6, color5, colorB2, colorS2); - - if (r > 0) - product2b = product1b = color6; - else if (r < 0) - product2b = product1b = color5; - else { - product2b = product1b = INTERPOLATE (color5, color6); - } - } else { - if (color6 == color3 && color3 == colorA1 - && color2 != colorA2 && color3 != colorA0) - product2b = - Q_INTERPOLATE (color3, color3, color3, color2); - else if (color5 == color2 && color2 == colorA2 - && colorA1 != color3 && color2 != colorA3) - product2b = - Q_INTERPOLATE (color2, color2, color2, color3); - else - product2b = INTERPOLATE (color2, color3); - - if (color6 == color3 && color6 == colorB1 - && color5 != colorB2 && color6 != colorB0) - product1b = - Q_INTERPOLATE (color6, color6, color6, color5); - else if (color5 == color2 && color5 == colorB2 - && colorB1 != color6 && color5 != colorB3) - product1b = - Q_INTERPOLATE (color6, color5, color5, color5); - else - product1b = INTERPOLATE (color5, color6); - } - - if (color5 == color3 && color2 != color6 && color4 == color5 - && color5 != colorA2) - product2a = INTERPOLATE (color2, color5); - else - if (color5 == color1 && color6 == color5 - && color4 != color2 && color5 != colorA0) - product2a = INTERPOLATE (color2, color5); - else - product2a = color2; - - if (color2 == color6 && color5 != color3 && color1 == color2 - && color2 != colorB2) - product1a = INTERPOLATE (color2, color5); - else - if (color4 == color2 && color3 == color2 - && color1 != color5 && color2 != colorB0) - product1a = INTERPOLATE (color2, color5); - else - product1a = color5; - -#ifdef WORDS_BIGENDIAN - product1a = (product1a << 16) | product1b; - product2a = (product2a << 16) | product2b; -#else - product1a = product1a | (product1b << 16); - product2a = product2a | (product2b << 16); -#endif - - *((uint32_t *) dP) = product1a; - *((uint32_t *) (dP + dstPitch)) = product2a; - - bP += inc_bP; - dP += sizeof (uint32_t); - } // end of for ( finish= width etc..) - - srcPtr += srcPitch; - dstPtr += dstPitch << 1; - deltaPtr += srcPitch; - } // endof: for (; height; height--) - } -} - -void Super2xSaI32 (uint8_t *srcPtr, uint32_t srcPitch, - uint8_t * /* deltaPtr */, uint8_t *dstPtr, uint32_t dstPitch, - int width, int height) -{ - uint32_t *bP; - uint32_t *dP; - uint32_t inc_bP; - uint32_t Nextline = srcPitch >> 2; - inc_bP = 1; - - for (; height; height--) { - bP = (uint32_t *) srcPtr; - dP = (uint32_t *) dstPtr; - - for (uint32_t finish = width; finish; finish -= inc_bP) { - uint32_t color4, color5, color6; - uint32_t color1, color2, color3; - uint32_t colorA0, colorA1, colorA2, colorA3, - colorB0, colorB1, colorB2, colorB3, colorS1, colorS2; - uint32_t product1a, product1b, product2a, product2b; - - //--------------------------------------- B1 B2 - // 4 5 6 S2 - // 1 2 3 S1 - // A1 A2 - - colorB0 = *(bP - Nextline - 1); - colorB1 = *(bP - Nextline); - colorB2 = *(bP - Nextline + 1); - colorB3 = *(bP - Nextline + 2); - - color4 = *(bP - 1); - color5 = *(bP); - color6 = *(bP + 1); - colorS2 = *(bP + 2); - - color1 = *(bP + Nextline - 1); - color2 = *(bP + Nextline); - color3 = *(bP + Nextline + 1); - colorS1 = *(bP + Nextline + 2); - - colorA0 = *(bP + Nextline + Nextline - 1); - colorA1 = *(bP + Nextline + Nextline); - colorA2 = *(bP + Nextline + Nextline + 1); - colorA3 = *(bP + Nextline + Nextline + 2); - - //-------------------------------------- - if (color2 == color6 && color5 != color3) { - product2b = product1b = color2; - } else if (color5 == color3 && color2 != color6) { - product2b = product1b = color5; - } else if (color5 == color3 && color2 == color6) { - register int r = 0; - - r += GetResult (color6, color5, color1, colorA1); - r += GetResult (color6, color5, color4, colorB1); - r += GetResult (color6, color5, colorA2, colorS1); - r += GetResult (color6, color5, colorB2, colorS2); - - if (r > 0) - product2b = product1b = color6; - else if (r < 0) - product2b = product1b = color5; - else { - product2b = product1b = INTERPOLATE (color5, color6); - } - } else { - if (color6 == color3 && color3 == colorA1 - && color2 != colorA2 && color3 != colorA0) - product2b = - Q_INTERPOLATE (color3, color3, color3, color2); - else if (color5 == color2 && color2 == colorA2 - && colorA1 != color3 && color2 != colorA3) - product2b = - Q_INTERPOLATE (color2, color2, color2, color3); - else - product2b = INTERPOLATE (color2, color3); - - if (color6 == color3 && color6 == colorB1 - && color5 != colorB2 && color6 != colorB0) - product1b = - Q_INTERPOLATE (color6, color6, color6, color5); - else if (color5 == color2 && color5 == colorB2 - && colorB1 != color6 && color5 != colorB3) - product1b = - Q_INTERPOLATE (color6, color5, color5, color5); - else - product1b = INTERPOLATE (color5, color6); - } - - if (color5 == color3 && color2 != color6 && color4 == color5 - && color5 != colorA2) - product2a = INTERPOLATE (color2, color5); - else - if (color5 == color1 && color6 == color5 - && color4 != color2 && color5 != colorA0) - product2a = INTERPOLATE (color2, color5); - else - product2a = color2; - - if (color2 == color6 && color5 != color3 && color1 == color2 - && color2 != colorB2) - product1a = INTERPOLATE (color2, color5); - else - if (color4 == color2 && color3 == color2 - && color1 != color5 && color2 != colorB0) - product1a = INTERPOLATE (color2, color5); - else - product1a = color5; - *(dP) = product1a; - *(dP+1) = product1b; - *(dP + (dstPitch >> 2)) = product2a; - *(dP + (dstPitch >> 2) + 1) = product2b; - - bP += inc_bP; - dP += 2; - } // end of for ( finish= width etc..) - - srcPtr += srcPitch; - dstPtr += dstPitch << 1; - // deltaPtr += srcPitch; - } // endof: for (; height; height--) -} - -void SuperEagle (uint8_t *srcPtr, uint32_t srcPitch, uint8_t *deltaPtr, - uint8_t *dstPtr, uint32_t dstPitch, int width, int height) -{ - uint8_t *dP; - uint16_t *bP; - uint16_t *xP; - uint32_t inc_bP; - - { - inc_bP = 1; - - uint32_t Nextline = srcPitch >> 1; - - for (; height; height--) { - bP = (uint16_t *) srcPtr; - xP = (uint16_t *) deltaPtr; - dP = dstPtr; - for (uint32_t finish = width; finish; finish -= inc_bP) { - uint32_t color4, color5, color6; - uint32_t color1, color2, color3; - uint32_t colorA1, colorA2, colorB1, colorB2, colorS1, colorS2; - uint32_t product1a, product1b, product2a, product2b; - - colorB1 = *(bP - Nextline); - colorB2 = *(bP - Nextline + 1); - - color4 = *(bP - 1); - color5 = *(bP); - color6 = *(bP + 1); - colorS2 = *(bP + 2); - - color1 = *(bP + Nextline - 1); - color2 = *(bP + Nextline); - color3 = *(bP + Nextline + 1); - colorS1 = *(bP + Nextline + 2); - - colorA1 = *(bP + Nextline + Nextline); - colorA2 = *(bP + Nextline + Nextline + 1); - - // -------------------------------------- - if (color2 == color6 && color5 != color3) { - product1b = product2a = color2; - if ((color1 == color2) || (color6 == colorB2)) { - product1a = INTERPOLATE (color2, color5); - product1a = INTERPOLATE (color2, product1a); - // product1a = color2; - } else { - product1a = INTERPOLATE (color5, color6); - } - - if ((color6 == colorS2) || (color2 == colorA1)) { - product2b = INTERPOLATE (color2, color3); - product2b = INTERPOLATE (color2, product2b); - // product2b = color2; - } else { - product2b = INTERPOLATE (color2, color3); - } - } else if (color5 == color3 && color2 != color6) { - product2b = product1a = color5; - - if ((colorB1 == color5) || (color3 == colorS1)) { - product1b = INTERPOLATE (color5, color6); - product1b = INTERPOLATE (color5, product1b); - // product1b = color5; - } else { - product1b = INTERPOLATE (color5, color6); - } - - if ((color3 == colorA2) || (color4 == color5)) { - product2a = INTERPOLATE (color5, color2); - product2a = INTERPOLATE (color5, product2a); - // product2a = color5; - } else { - product2a = INTERPOLATE (color2, color3); - } - - } else if (color5 == color3 && color2 == color6) { - register int r = 0; - - r += GetResult (color6, color5, color1, colorA1); - r += GetResult (color6, color5, color4, colorB1); - r += GetResult (color6, color5, colorA2, colorS1); - r += GetResult (color6, color5, colorB2, colorS2); - - if (r > 0) { - product1b = product2a = color2; - product1a = product2b = INTERPOLATE (color5, color6); - } else if (r < 0) { - product2b = product1a = color5; - product1b = product2a = INTERPOLATE (color5, color6); - } else { - product2b = product1a = color5; - product1b = product2a = color2; - } - } else { - product2b = product1a = INTERPOLATE (color2, color6); - product2b = - Q_INTERPOLATE (color3, color3, color3, product2b); - product1a = - Q_INTERPOLATE (color5, color5, color5, product1a); - - product2a = product1b = INTERPOLATE (color5, color3); - product2a = - Q_INTERPOLATE (color2, color2, color2, product2a); - product1b = - Q_INTERPOLATE (color6, color6, color6, product1b); - - // product1a = color5; - // product1b = color6; - // product2a = color2; - // product2b = color3; - } -#ifdef WORDS_BIGENDIAN - product1a = (product1a << 16) | product1b; - product2a = (product2a << 16) | product2b; -#else - product1a = product1a | (product1b << 16); - product2a = product2a | (product2b << 16); -#endif - - *((uint32_t *) dP) = product1a; - *((uint32_t *) (dP + dstPitch)) = product2a; - *xP = color5; - - bP += inc_bP; - xP += inc_bP; - dP += sizeof (uint32_t); - } // end of for ( finish= width etc..) - - srcPtr += srcPitch; - dstPtr += dstPitch << 1; - deltaPtr += srcPitch; - } // endof: for (height; height; height--) - } -} - -void SuperEagle32 (uint8_t *srcPtr, uint32_t srcPitch, uint8_t */*deltaPtr*/, - uint8_t *dstPtr, uint32_t dstPitch, int width, int height) -{ - uint32_t *dP; - uint32_t *bP; - //uint32_t *xP; - uint32_t inc_bP; - - inc_bP = 1; - - uint32_t Nextline = srcPitch >> 2; - - for (; height; height--) { - bP = (uint32_t *) srcPtr; - //xP = (uint32_t *) deltaPtr; - dP = (uint32_t *)dstPtr; - for (uint32_t finish = width; finish; finish -= inc_bP) { - uint32_t color4, color5, color6; - uint32_t color1, color2, color3; - uint32_t colorA1, colorA2, colorB1, colorB2, colorS1, colorS2; - uint32_t product1a, product1b, product2a, product2b; - - colorB1 = *(bP - Nextline); - colorB2 = *(bP - Nextline + 1); - - color4 = *(bP - 1); - color5 = *(bP); - color6 = *(bP + 1); - colorS2 = *(bP + 2); - - color1 = *(bP + Nextline - 1); - color2 = *(bP + Nextline); - color3 = *(bP + Nextline + 1); - colorS1 = *(bP + Nextline + 2); - - colorA1 = *(bP + Nextline + Nextline); - colorA2 = *(bP + Nextline + Nextline + 1); - - // -------------------------------------- - if (color2 == color6 && color5 != color3) { - product1b = product2a = color2; - if ((color1 == color2) || (color6 == colorB2)) { - product1a = INTERPOLATE (color2, color5); - product1a = INTERPOLATE (color2, product1a); - // product1a = color2; - } else { - product1a = INTERPOLATE (color5, color6); - } - - if ((color6 == colorS2) || (color2 == colorA1)) { - product2b = INTERPOLATE (color2, color3); - product2b = INTERPOLATE (color2, product2b); - // product2b = color2; - } else { - product2b = INTERPOLATE (color2, color3); - } - } else if (color5 == color3 && color2 != color6) { - product2b = product1a = color5; - - if ((colorB1 == color5) || (color3 == colorS1)) { - product1b = INTERPOLATE (color5, color6); - product1b = INTERPOLATE (color5, product1b); - // product1b = color5; - } else { - product1b = INTERPOLATE (color5, color6); - } - - if ((color3 == colorA2) || (color4 == color5)) { - product2a = INTERPOLATE (color5, color2); - product2a = INTERPOLATE (color5, product2a); - // product2a = color5; - } else { - product2a = INTERPOLATE (color2, color3); - } - - } else if (color5 == color3 && color2 == color6) { - register int r = 0; - - r += GetResult (color6, color5, color1, colorA1); - r += GetResult (color6, color5, color4, colorB1); - r += GetResult (color6, color5, colorA2, colorS1); - r += GetResult (color6, color5, colorB2, colorS2); - - if (r > 0) { - product1b = product2a = color2; - product1a = product2b = INTERPOLATE (color5, color6); - } else if (r < 0) { - product2b = product1a = color5; - product1b = product2a = INTERPOLATE (color5, color6); - } else { - product2b = product1a = color5; - product1b = product2a = color2; - } - } else { - product2b = product1a = INTERPOLATE (color2, color6); - product2b = - Q_INTERPOLATE (color3, color3, color3, product2b); - product1a = - Q_INTERPOLATE (color5, color5, color5, product1a); - - product2a = product1b = INTERPOLATE (color5, color3); - product2a = - Q_INTERPOLATE (color2, color2, color2, product2a); - product1b = - Q_INTERPOLATE (color6, color6, color6, product1b); - - // product1a = color5; - // product1b = color6; - // product2a = color2; - // product2b = color3; - } - *(dP) = product1a; - *(dP+1) = product1b; - *(dP + (dstPitch >> 2)) = product2a; - *(dP + (dstPitch >> 2) +1) = product2b; - //*xP = color5; - - bP += inc_bP; - //xP += inc_bP; - dP += 2; - } // end of for ( finish= width etc..) - - srcPtr += srcPitch; - dstPtr += dstPitch << 1; - //deltaPtr += srcPitch; - } // endof: for (height; height; height--) -} - -void _2xSaI (uint8_t *srcPtr, uint32_t srcPitch, uint8_t *deltaPtr, - uint8_t *dstPtr, uint32_t dstPitch, int width, int height) -{ - uint8_t *dP; - uint16_t *bP; - uint32_t inc_bP; - - { - inc_bP = 1; - - uint32_t Nextline = srcPitch >> 1; - - for (; height; height--) { - bP = (uint16_t *) srcPtr; - dP = dstPtr; - - for (uint32_t finish = width; finish; finish -= inc_bP) { - - register uint32_t colorA, colorB; - uint32_t colorC, colorD, - colorE, colorF, colorG, colorH, - colorI, colorJ, colorK, colorL, - - colorM, colorN, colorO, colorP; - uint32_t product, product1, product2; - - //--------------------------------------- - // Map of the pixels: I|E F|J - // G|A B|K - // H|C D|L - // M|N O|P - colorI = *(bP - Nextline - 1); - colorE = *(bP - Nextline); - colorF = *(bP - Nextline + 1); - colorJ = *(bP - Nextline + 2); - - colorG = *(bP - 1); - colorA = *(bP); - colorB = *(bP + 1); - colorK = *(bP + 2); - - colorH = *(bP + Nextline - 1); - colorC = *(bP + Nextline); - colorD = *(bP + Nextline + 1); - colorL = *(bP + Nextline + 2); - - colorM = *(bP + Nextline + Nextline - 1); - colorN = *(bP + Nextline + Nextline); - colorO = *(bP + Nextline + Nextline + 1); - colorP = *(bP + Nextline + Nextline + 2); - - if ((colorA == colorD) && (colorB != colorC)) { - if (((colorA == colorE) && (colorB == colorL)) || - ((colorA == colorC) && (colorA == colorF) - && (colorB != colorE) && (colorB == colorJ))) { - product = colorA; - } else { - product = INTERPOLATE (colorA, colorB); - } - - if (((colorA == colorG) && (colorC == colorO)) || - ((colorA == colorB) && (colorA == colorH) - && (colorG != colorC) && (colorC == colorM))) { - product1 = colorA; - } else { - product1 = INTERPOLATE (colorA, colorC); - } - product2 = colorA; - } else if ((colorB == colorC) && (colorA != colorD)) { - if (((colorB == colorF) && (colorA == colorH)) || - ((colorB == colorE) && (colorB == colorD) - && (colorA != colorF) && (colorA == colorI))) { - product = colorB; - } else { - product = INTERPOLATE (colorA, colorB); - } - - if (((colorC == colorH) && (colorA == colorF)) || - ((colorC == colorG) && (colorC == colorD) - && (colorA != colorH) && (colorA == colorI))) { - product1 = colorC; - } else { - product1 = INTERPOLATE (colorA, colorC); - } - product2 = colorB; - } else if ((colorA == colorD) && (colorB == colorC)) { - if (colorA == colorB) { - product = colorA; - product1 = colorA; - product2 = colorA; - } else { - register int r = 0; - - product1 = INTERPOLATE (colorA, colorC); - product = INTERPOLATE (colorA, colorB); - - r += - GetResult1 (colorA, colorB, colorG, colorE, - colorI); - r += - GetResult2 (colorB, colorA, colorK, colorF, - colorJ); - r += - GetResult2 (colorB, colorA, colorH, colorN, - colorM); - r += - GetResult1 (colorA, colorB, colorL, colorO, - colorP); - - if (r > 0) - product2 = colorA; - else if (r < 0) - product2 = colorB; - else { - product2 = - Q_INTERPOLATE (colorA, colorB, colorC, - colorD); - } - } - } else { - product2 = Q_INTERPOLATE (colorA, colorB, colorC, colorD); - - if ((colorA == colorC) && (colorA == colorF) - && (colorB != colorE) && (colorB == colorJ)) { - product = colorA; - } else if ((colorB == colorE) && (colorB == colorD) - && (colorA != colorF) && (colorA == colorI)) { - product = colorB; - } else { - product = INTERPOLATE (colorA, colorB); - } - - if ((colorA == colorB) && (colorA == colorH) - && (colorG != colorC) && (colorC == colorM)) { - product1 = colorA; - } else if ((colorC == colorG) && (colorC == colorD) - && (colorA != colorH) && (colorA == colorI)) { - product1 = colorC; - } else { - product1 = INTERPOLATE (colorA, colorC); - } - } - -#ifdef WORDS_BIGENDIAN - product = (colorA << 16) | product ; - product1 = (product1 << 16) | product2 ; -#else - product = colorA | (product << 16); - product1 = product1 | (product2 << 16); -#endif - *((int32_t *) dP) = product; - *((uint32_t *) (dP + dstPitch)) = product1; - - bP += inc_bP; - dP += sizeof (uint32_t); - } // end of for ( finish= width etc..) - - srcPtr += srcPitch; - dstPtr += dstPitch << 1; - deltaPtr += srcPitch; - } // endof: for (height; height; height--) - } -} - -void _2xSaI32 (uint8_t *srcPtr, uint32_t srcPitch, uint8_t * /* deltaPtr */, - uint8_t *dstPtr, uint32_t dstPitch, int width, int height) -{ - uint32_t *dP; - uint32_t *bP; - uint32_t inc_bP = 1; - - uint32_t Nextline = srcPitch >> 2; - - for (; height; height--) { - bP = (uint32_t *) srcPtr; - dP = (uint32_t *) dstPtr; - - for (uint32_t finish = width; finish; finish -= inc_bP) { - register uint32_t colorA, colorB; - uint32_t colorC, colorD, - colorE, colorF, colorG, colorH, - colorI, colorJ, colorK, colorL, - - colorM, colorN, colorO, colorP; - uint32_t product, product1, product2; - - //--------------------------------------- - // Map of the pixels: I|E F|J - // G|A B|K - // H|C D|L - // M|N O|P - colorI = *(bP - Nextline - 1); - colorE = *(bP - Nextline); - colorF = *(bP - Nextline + 1); - colorJ = *(bP - Nextline + 2); - - colorG = *(bP - 1); - colorA = *(bP); - colorB = *(bP + 1); - colorK = *(bP + 2); - - colorH = *(bP + Nextline - 1); - colorC = *(bP + Nextline); - colorD = *(bP + Nextline + 1); - colorL = *(bP + Nextline + 2); - - colorM = *(bP + Nextline + Nextline - 1); - colorN = *(bP + Nextline + Nextline); - colorO = *(bP + Nextline + Nextline + 1); - colorP = *(bP + Nextline + Nextline + 2); - - if ((colorA == colorD) && (colorB != colorC)) { - if (((colorA == colorE) && (colorB == colorL)) || - ((colorA == colorC) && (colorA == colorF) - && (colorB != colorE) && (colorB == colorJ))) { - product = colorA; - } else { - product = INTERPOLATE (colorA, colorB); - } - - if (((colorA == colorG) && (colorC == colorO)) || - ((colorA == colorB) && (colorA == colorH) - && (colorG != colorC) && (colorC == colorM))) { - product1 = colorA; - } else { - product1 = INTERPOLATE (colorA, colorC); - } - product2 = colorA; - } else if ((colorB == colorC) && (colorA != colorD)) { - if (((colorB == colorF) && (colorA == colorH)) || - ((colorB == colorE) && (colorB == colorD) - && (colorA != colorF) && (colorA == colorI))) { - product = colorB; - } else { - product = INTERPOLATE (colorA, colorB); - } - - if (((colorC == colorH) && (colorA == colorF)) || - ((colorC == colorG) && (colorC == colorD) - && (colorA != colorH) && (colorA == colorI))) { - product1 = colorC; - } else { - product1 = INTERPOLATE (colorA, colorC); - } - product2 = colorB; - } else if ((colorA == colorD) && (colorB == colorC)) { - if (colorA == colorB) { - product = colorA; - product1 = colorA; - product2 = colorA; - } else { - register int r = 0; - - product1 = INTERPOLATE (colorA, colorC); - product = INTERPOLATE (colorA, colorB); - - r += - GetResult1 (colorA, colorB, colorG, colorE, - colorI); - r += - GetResult2 (colorB, colorA, colorK, colorF, - colorJ); - r += - GetResult2 (colorB, colorA, colorH, colorN, - colorM); - r += - GetResult1 (colorA, colorB, colorL, colorO, - colorP); - - if (r > 0) - product2 = colorA; - else if (r < 0) - product2 = colorB; - else { - product2 = - Q_INTERPOLATE (colorA, colorB, colorC, - colorD); - } - } - } else { - product2 = Q_INTERPOLATE (colorA, colorB, colorC, colorD); - - if ((colorA == colorC) && (colorA == colorF) - && (colorB != colorE) && (colorB == colorJ)) { - product = colorA; - } else if ((colorB == colorE) && (colorB == colorD) - && (colorA != colorF) && (colorA == colorI)) { - product = colorB; - } else { - product = INTERPOLATE (colorA, colorB); - } - - if ((colorA == colorB) && (colorA == colorH) - && (colorG != colorC) && (colorC == colorM)) { - product1 = colorA; - } else if ((colorC == colorG) && (colorC == colorD) - && (colorA != colorH) && (colorA == colorI)) { - product1 = colorC; - } else { - product1 = INTERPOLATE (colorA, colorC); - } - } - *(dP) = colorA; - *(dP + 1) = product; - *(dP + (dstPitch >> 2)) = product1; - *(dP + (dstPitch >> 2) + 1) = product2; - - bP += inc_bP; - dP += 2; - } // end of for ( finish= width etc..) - - srcPtr += srcPitch; - dstPtr += dstPitch << 1; - // deltaPtr += srcPitch; - } // endof: for (height; height; height--) -} - -static uint32_t Bilinear (uint32_t A, uint32_t B, uint32_t x) -{ - unsigned long areaA, areaB; - unsigned long result; - - if (A == B) - return A; - - areaB = (x >> 11) & 0x1f; // reduce 16 bit fraction to 5 bits - areaA = 0x20 - areaB; - - A = (A & redblueMask) | ((A & greenMask) << 16); - B = (B & redblueMask) | ((B & greenMask) << 16); - - result = ((areaA * A) + (areaB * B)) >> 5; - - return (result & redblueMask) | ((result >> 16) & greenMask); -} - -static uint32_t Bilinear4 (uint32_t A, uint32_t B, uint32_t C, uint32_t D, uint32_t x, - uint32_t y) -{ - unsigned long areaA, areaB, areaC, areaD; - unsigned long result, xy; - - x = (x >> 11) & 0x1f; - y = (y >> 11) & 0x1f; - xy = (x * y) >> 5; - - A = (A & redblueMask) | ((A & greenMask) << 16); - B = (B & redblueMask) | ((B & greenMask) << 16); - C = (C & redblueMask) | ((C & greenMask) << 16); - D = (D & redblueMask) | ((D & greenMask) << 16); - - areaA = 0x20 + xy - x - y; - areaB = x - xy; - areaC = y - xy; - areaD = xy; - - result = ((areaA * A) + (areaB * B) + (areaC * C) + (areaD * D)) >> 5; - - return (result & redblueMask) | ((result >> 16) & greenMask); -} - -void Scale_2xSaI (uint8_t *srcPtr, uint32_t srcPitch, uint8_t * /* deltaPtr */, - uint8_t *dstPtr, uint32_t dstPitch, - uint32_t dstWidth, uint32_t dstHeight, int width, int height) -{ - uint8_t *dP; - uint16_t *bP; - - uint32_t w; - uint32_t h; - uint32_t dw; - uint32_t dh; - uint32_t hfinish; - uint32_t wfinish; - - uint32_t Nextline = srcPitch >> 1; - - wfinish = (width - 1) << 16; // convert to fixed point - dw = wfinish / (dstWidth - 1); - hfinish = (height - 1) << 16; // convert to fixed point - dh = hfinish / (dstHeight - 1); - - for (h = 0; h < hfinish; h += dh) { - uint32_t y1, y2; - - y1 = h & 0xffff; // fraction part of fixed point - bP = (uint16_t *) (srcPtr + ((h >> 16) * srcPitch)); - dP = dstPtr; - y2 = 0x10000 - y1; - - w = 0; - - for (; w < wfinish;) { - uint32_t A, B, C, D; - uint32_t E, F, G, H; - uint32_t I, J, K, L; - uint32_t x1, x2, a1, f1, f2; - uint32_t position, product1; - - position = w >> 16; - A = bP[position]; // current pixel - B = bP[position + 1]; // next pixel - C = bP[position + Nextline]; - D = bP[position + Nextline + 1]; - E = bP[position - Nextline]; - F = bP[position - Nextline + 1]; - G = bP[position - 1]; - H = bP[position + Nextline - 1]; - I = bP[position + 2]; - J = bP[position + Nextline + 2]; - K = bP[position + Nextline + Nextline]; - L = bP[position + Nextline + Nextline + 1]; - - x1 = w & 0xffff; // fraction part of fixed point - x2 = 0x10000 - x1; - - /*0*/ - if (A == B && C == D && A == C) - product1 = A; - else /*1*/ if (A == D && B != C) { - f1 = (x1 >> 1) + (0x10000 >> 2); - f2 = (y1 >> 1) + (0x10000 >> 2); - if (y1 <= f1 && A == J && A != E) // close to B - { - a1 = f1 - y1; - product1 = Bilinear (A, B, a1); - } else if (y1 >= f1 && A == G && A != L) // close to C - { - a1 = y1 - f1; - product1 = Bilinear (A, C, a1); - } - else if (x1 >= f2 && A == E && A != J) // close to B - { - a1 = x1 - f2; - product1 = Bilinear (A, B, a1); - } - else if (x1 <= f2 && A == L && A != G) // close to C - { - a1 = f2 - x1; - product1 = Bilinear (A, C, a1); - } - else if (y1 >= x1) // close to C - { - a1 = y1 - x1; - product1 = Bilinear (A, C, a1); - } - else if (y1 <= x1) // close to B - { - a1 = x1 - y1; - product1 = Bilinear (A, B, a1); - } - } - else - /*2*/ - if (B == C && A != D) - { - f1 = (x1 >> 1) + (0x10000 >> 2); - f2 = (y1 >> 1) + (0x10000 >> 2); - if (y2 >= f1 && B == H && B != F) // close to A - { - a1 = y2 - f1; - product1 = Bilinear (B, A, a1); - } - else if (y2 <= f1 && B == I && B != K) // close to D - { - a1 = f1 - y2; - product1 = Bilinear (B, D, a1); - } - else if (x2 >= f2 && B == F && B != H) // close to A - { - a1 = x2 - f2; - product1 = Bilinear (B, A, a1); - } - else if (x2 <= f2 && B == K && B != I) // close to D - { - a1 = f2 - x2; - product1 = Bilinear (B, D, a1); - } - else if (y2 >= x1) // close to A - { - a1 = y2 - x1; - product1 = Bilinear (B, A, a1); - } - else if (y2 <= x1) // close to D - { - a1 = x1 - y2; - product1 = Bilinear (B, D, a1); - } - } - /*3*/ - else - { - product1 = Bilinear4 (A, B, C, D, x1, y1); - } - - //end First Pixel - *(uint32_t *) dP = product1; - dP += 2; - w += dw; - } - dstPtr += dstPitch; - } -} diff --git a/snesfilter/Makefile b/snesfilter/Makefile deleted file mode 100644 index 089b86ee..00000000 --- a/snesfilter/Makefile +++ /dev/null @@ -1,89 +0,0 @@ -include nall/Makefile - -qtlibs := QtCore QtGui -include nall/qt/Makefile - -c := $(compiler) -std=gnu99 -cpp := $(subst cc,++,$(compiler)) -std=gnu++0x -flags := -O3 -I. -Iobj -fomit-frame-pointer $(qtinc) -link := - -ifeq ($(platform),x) - flags := -fPIC -fopenmp $(flags) - link += -s -fopenmp -lpthread -lgomp -else ifeq ($(platform),osx) - flags := -fPIC -fopenmp $(flags) - link += -fopenmp -lpthread -lgomp -else ifeq ($(platform),win) - flags := -fopenmp $(flags) - link += -fopenmp -lpthread -endif - -objects := snesfilter - -compile = \ - $(strip \ - $(if $(filter %.c,$<), \ - $(c) $(flags) $1 -c $< -o $@, \ - $(if $(filter %.cpp,$<), \ - $(cpp) $(flags) $1 -c $< -o $@ \ - ) \ - ) \ - ) - -%.o: $<; $(call compile) - -all: build; - -objects := $(patsubst %,obj/%.o,$(objects)) -moc_headers := $(call rwildcard,./,%.moc.hpp) -moc_objects := $(foreach f,$(moc_headers),obj/$(notdir $(patsubst %.moc.hpp,%.moc,$f))) - -# automatically run moc on all .moc.hpp (MOC header) files -%.moc: $<; $(moc) -i $< -o $@ - -# automatically generate %.moc build rules -__list = $(moc_headers) -$(foreach f,$(moc_objects), \ - $(eval __file = $(word 1,$(__list))) \ - $(eval __list = $(wordlist 2,$(words $(__list)),$(__list))) \ - $(eval $f: $(__file)) \ -) - -################## -### snesfilter ### -################## - -obj/snesfilter.o: snesfilter.cpp * - -############### -### targets ### -############### - -build: $(moc_objects) $(objects) -ifeq ($(platform),x) - ar rcs libsnesfilter.a $(objects) - $(cpp) $(link) -o libsnesfilter.so -shared -Wl,-soname,libsnesfilter.so.1 $(objects) $(qtlib) -else ifeq ($(platform),osx) - ar rcs libsnesfilter.a $(objects) - $(cpp) $(link) -o libsnesfilter.dylib -shared -dynamiclib $(objects) $(qtlib) -else ifeq ($(platform),win) - $(cpp) $(link) -o snesfilter.dll -shared -Wl,--out-implib,libsnesfilter.a $(objects) $(qtlib) -endif - -install: -ifeq ($(platform),x) - install -D -m 755 libsnesfilter.a $(DESTDIR)$(prefix)/lib - install -D -m 755 libsnesfilter.so $(DESTDIR)$(prefix)/lib - ldconfig -n $(DESTDIR)$(prefix)/lib -else ifeq ($(platform),osx) - cp libsnesfilter.dylib /usr/local/lib/libsnesfilter.dylib -endif - -clean: - -@$(call delete,obj/*.o) - -@$(call delete,obj/*.moc) - -@$(call delete,libsnesfilter.a) - -@$(call delete,libsnesfilter.so) - -@$(call delete,libsnesfilter.dylib) - -@$(call delete,snesfilter.dll) diff --git a/snesfilter/cc.bat b/snesfilter/cc.bat deleted file mode 100644 index 8359a530..00000000 --- a/snesfilter/cc.bat +++ /dev/null @@ -1,2 +0,0 @@ -@mingw32-make -@pause \ No newline at end of file diff --git a/snesfilter/clean.bat b/snesfilter/clean.bat deleted file mode 100644 index d8bb7e0b..00000000 --- a/snesfilter/clean.bat +++ /dev/null @@ -1 +0,0 @@ -@mingw32-make clean diff --git a/snesfilter/direct/direct.cpp b/snesfilter/direct/direct.cpp deleted file mode 100644 index d5214367..00000000 --- a/snesfilter/direct/direct.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "direct.hpp" - -void DirectFilter::size(unsigned &outwidth, unsigned &outheight, unsigned width, unsigned height) { - outwidth = width; - outheight = height; -} - -void DirectFilter::render( - uint32_t *output, unsigned outpitch, const uint16_t *input, unsigned pitch, - const unsigned *line, unsigned width, unsigned height -) { - pitch >>= 1; - outpitch >>= 2; - - for(unsigned y = 0; y < height; y++) { - if(width == 512 && line[y] == 256) { - for(unsigned x = 0; x < 256; x++) { - uint16_t p = *input++; - *output++ = colortable[p]; - *output++ = colortable[p]; - } - input += 256; - } else { - for(unsigned x = 0; x < width; x++) { - uint16_t p = *input++; - *output++ = colortable[p]; - } - } - input += pitch - width; - output += outpitch - width; - } -} diff --git a/snesfilter/direct/direct.hpp b/snesfilter/direct/direct.hpp deleted file mode 100644 index d990b4fa..00000000 --- a/snesfilter/direct/direct.hpp +++ /dev/null @@ -1,5 +0,0 @@ -class DirectFilter { -public: - void size(unsigned&, unsigned&, unsigned, unsigned); - void render(uint32_t*, unsigned, const uint16_t*, unsigned, const unsigned*, unsigned, unsigned); -} filter_direct; diff --git a/snesfilter/hq2x/hq2x.cpp b/snesfilter/hq2x/hq2x.cpp deleted file mode 100644 index 7a285e8c..00000000 --- a/snesfilter/hq2x/hq2x.cpp +++ /dev/null @@ -1,203 +0,0 @@ -//HQ2x filter -//authors: byuu and blargg -//license: public domain -// -//note: this is a clean reimplementation of the original HQ2x filter, which was -//written by Maxim Stepin (MaxSt). it is not 100% identical, but very similar. - -#include "hq2x.hpp" - -void HQ2xFilter::size(unsigned &outwidth, unsigned &outheight, unsigned width, unsigned height) { - if(height > 240) return filter_direct.size(outwidth, outheight, width, height); - outwidth = (width <= 256) ? width * 2 : width; - outheight = (height <= 240) ? height * 2 : height; -} - -void HQ2xFilter::render( - uint32_t *output, unsigned outpitch, const uint16_t *input, unsigned pitch, - const unsigned *line, unsigned width, unsigned height -) { - if(height > 240) { - filter_direct.render(output, outpitch, input, pitch, line, width, height); - return; - } - - pitch >>= 1; - outpitch >>= 2; - - #pragma omp parallel for - for(unsigned y = 0; y < height; y++) { - const uint16_t *in = input + y * pitch; - uint32_t *out0 = output + y * pitch; - uint32_t *out1 = output + y * pitch + outpitch; - - unsigned linewidth = line[y]; - - if(linewidth == 256) { - int prevline = (y == 0) || (linewidth != line[y - 1]) ? 0 : pitch; - int nextline = (y == height - 1) || (linewidth != line[y + 1]) ? 0 : pitch; - - in++; - *out0++ = 0; *out0++ = 0; - *out1++ = 0; *out1++ = 0; - - for(unsigned x = 1; x < 256 - 1; x++) { - uint16_t A = *(in - prevline - 1); - uint16_t B = *(in - prevline + 0); - uint16_t C = *(in - prevline + 1); - uint16_t D = *(in - 1); - uint16_t E = *(in + 0); - uint16_t F = *(in + 1); - uint16_t G = *(in + nextline - 1); - uint16_t H = *(in + nextline + 0); - uint16_t I = *(in + nextline + 1); - uint32_t e = yuvTable[E] + diff_offset; - - uint8_t pattern; - pattern = diff(e, A) << 0; - pattern |= diff(e, B) << 1; - pattern |= diff(e, C) << 2; - pattern |= diff(e, D) << 3; - pattern |= diff(e, F) << 4; - pattern |= diff(e, G) << 5; - pattern |= diff(e, H) << 6; - pattern |= diff(e, I) << 7; - - *(out0 + 0) = colortable[blend(hqTable[pattern], E, A, B, D, F, H)]; pattern = rotate[pattern]; - *(out0 + 1) = colortable[blend(hqTable[pattern], E, C, F, B, H, D)]; pattern = rotate[pattern]; - *(out1 + 1) = colortable[blend(hqTable[pattern], E, I, H, F, D, B)]; pattern = rotate[pattern]; - *(out1 + 0) = colortable[blend(hqTable[pattern], E, G, D, H, B, F)]; - - in++; - out0 += 2; - out1 += 2; - } - - in++; - *out0++ = 0; *out0++ = 0; - *out1++ = 0; *out1++ = 0; - } else { - for(unsigned x = 0; x < 512; x++) { - *out0++ = *out1++ = colortable[*in++]; - } - } - } -} - -HQ2xFilter::HQ2xFilter() { - yuvTable = new uint32_t[32768]; - - for(unsigned i = 0; i < 32768; i++) { - uint8_t R = (i >> 0) & 31; - uint8_t G = (i >> 5) & 31; - uint8_t B = (i >> 10) & 31; - - //bgr555->bgr888 - double r = (R << 3) | (R >> 2); - double g = (G << 3) | (G >> 2); - double b = (B << 3) | (B >> 2); - - //bgr888->yuv888 - double y = (r + g + b) * (0.25f * (63.5f / 48.0f)); - double u = ((r - b) * 0.25f + 128.0f) * (7.5f / 7.0f); - double v = ((g * 2.0f - r - b) * 0.125f + 128.0f) * (7.5f / 6.0f); - - yuvTable[i] = ((unsigned)y << 21) + ((unsigned)u << 11) + ((unsigned)v); - } - - for(unsigned n = 0; n < 256; n++) { - rotate[n] = ((n >> 2) & 0x11) | ((n << 2) & 0x88) - | ((n & 0x01) << 5) | ((n & 0x08) << 3) - | ((n & 0x10) >> 3) | ((n & 0x80) >> 5); - } -} - -HQ2xFilter::~HQ2xFilter() { - delete[] yuvTable; -} - -bool HQ2xFilter::same(uint16_t x, uint16_t y) { - return !((yuvTable[x] - yuvTable[y] + diff_offset) & diff_mask); -} - -bool HQ2xFilter::diff(uint32_t x, uint16_t y) { - return ((x - yuvTable[y]) & diff_mask); -} - -void HQ2xFilter::grow(uint32_t &n) { n |= n << 16; n &= 0x03e07c1f; } -uint16_t HQ2xFilter::pack(uint32_t n) { n &= 0x03e07c1f; return n | (n >> 16); } - -uint16_t HQ2xFilter::blend1(uint32_t A, uint32_t B) { - grow(A); grow(B); - A = (A * 3 + B) >> 2; - return pack(A); -} - -uint16_t HQ2xFilter::blend2(uint32_t A, uint32_t B, uint32_t C) { - grow(A); grow(B); grow(C); - return pack((A * 2 + B + C) >> 2); -} - -uint16_t HQ2xFilter::blend3(uint32_t A, uint32_t B, uint32_t C) { - grow(A); grow(B); grow(C); - return pack((A * 5 + B * 2 + C) >> 3); -} - -uint16_t HQ2xFilter::blend4(uint32_t A, uint32_t B, uint32_t C) { - grow(A); grow(B); grow(C); - return pack((A * 6 + B + C) >> 3); -} - -uint16_t HQ2xFilter::blend5(uint32_t A, uint32_t B, uint32_t C) { - grow(A); grow(B); grow(C); - return pack((A * 2 + (B + C) * 3) >> 3); -} - -uint16_t HQ2xFilter::blend6(uint32_t A, uint32_t B, uint32_t C) { - grow(A); grow(B); grow(C); - return pack((A * 14 + B + C) >> 4); -} - -uint16_t HQ2xFilter::blend(unsigned rule, uint16_t E, uint16_t A, uint16_t B, uint16_t D, uint16_t F, uint16_t H) { - switch(rule) { default: - case 0: return E; - case 1: return blend1(E, A); - case 2: return blend1(E, D); - case 3: return blend1(E, B); - case 4: return blend2(E, D, B); - case 5: return blend2(E, A, B); - case 6: return blend2(E, A, D); - case 7: return blend3(E, B, D); - case 8: return blend3(E, D, B); - case 9: return blend4(E, D, B); - case 10: return blend5(E, D, B); - case 11: return blend6(E, D, B); - case 12: return same(B, D) ? blend2(E, D, B) : E; - case 13: return same(B, D) ? blend5(E, D, B) : E; - case 14: return same(B, D) ? blend6(E, D, B) : E; - case 15: return same(B, D) ? blend2(E, D, B) : blend1(E, A); - case 16: return same(B, D) ? blend4(E, D, B) : blend1(E, A); - case 17: return same(B, D) ? blend5(E, D, B) : blend1(E, A); - case 18: return same(B, F) ? blend3(E, B, D) : blend1(E, D); - case 19: return same(D, H) ? blend3(E, D, B) : blend1(E, B); - } -} - -const uint8_t HQ2xFilter::hqTable[256] = { - 4, 4, 6, 2, 4, 4, 6, 2, 5, 3, 15, 12, 5, 3, 17, 13, - 4, 4, 6, 18, 4, 4, 6, 18, 5, 3, 12, 12, 5, 3, 1, 12, - 4, 4, 6, 2, 4, 4, 6, 2, 5, 3, 17, 13, 5, 3, 16, 14, - 4, 4, 6, 18, 4, 4, 6, 18, 5, 3, 16, 12, 5, 3, 1, 14, - 4, 4, 6, 2, 4, 4, 6, 2, 5, 19, 12, 12, 5, 19, 16, 12, - 4, 4, 6, 2, 4, 4, 6, 2, 5, 3, 16, 12, 5, 3, 16, 12, - 4, 4, 6, 2, 4, 4, 6, 2, 5, 19, 1, 12, 5, 19, 1, 14, - 4, 4, 6, 2, 4, 4, 6, 18, 5, 3, 16, 12, 5, 19, 1, 14, - 4, 4, 6, 2, 4, 4, 6, 2, 5, 3, 15, 12, 5, 3, 17, 13, - 4, 4, 6, 2, 4, 4, 6, 2, 5, 3, 16, 12, 5, 3, 16, 12, - 4, 4, 6, 2, 4, 4, 6, 2, 5, 3, 17, 13, 5, 3, 16, 14, - 4, 4, 6, 2, 4, 4, 6, 2, 5, 3, 16, 13, 5, 3, 1, 14, - 4, 4, 6, 2, 4, 4, 6, 2, 5, 3, 16, 12, 5, 3, 16, 13, - 4, 4, 6, 2, 4, 4, 6, 2, 5, 3, 16, 12, 5, 3, 1, 12, - 4, 4, 6, 2, 4, 4, 6, 2, 5, 3, 16, 12, 5, 3, 1, 14, - 4, 4, 6, 2, 4, 4, 6, 2, 5, 3, 1, 12, 5, 3, 1, 14, -}; diff --git a/snesfilter/hq2x/hq2x.hpp b/snesfilter/hq2x/hq2x.hpp deleted file mode 100644 index 5aaab806..00000000 --- a/snesfilter/hq2x/hq2x.hpp +++ /dev/null @@ -1,30 +0,0 @@ -class HQ2xFilter { -public: - void size(unsigned&, unsigned&, unsigned, unsigned); - void render(uint32_t*, unsigned, const uint16_t*, unsigned, const unsigned*, unsigned, unsigned); - - HQ2xFilter(); - ~HQ2xFilter(); - -private: - enum { - diff_offset = (0x440 << 21) + (0x207 << 11) + 0x407, - diff_mask = (0x380 << 21) + (0x1f0 << 11) + 0x3f0, - }; - - static const uint8_t hqTable[256]; - uint32_t *yuvTable; - uint8_t rotate[256]; - - alwaysinline bool same(uint16_t x, uint16_t y); - alwaysinline bool diff(uint32_t x, uint16_t y); - alwaysinline void grow(uint32_t &n); - alwaysinline uint16_t pack(uint32_t n); - alwaysinline uint16_t blend1(uint32_t A, uint32_t B); - alwaysinline uint16_t blend2(uint32_t A, uint32_t B, uint32_t C); - alwaysinline uint16_t blend3(uint32_t A, uint32_t B, uint32_t C); - alwaysinline uint16_t blend4(uint32_t A, uint32_t B, uint32_t C); - alwaysinline uint16_t blend5(uint32_t A, uint32_t B, uint32_t C); - alwaysinline uint16_t blend6(uint32_t A, uint32_t B, uint32_t C); - alwaysinline uint16_t blend(unsigned rule, uint16_t E, uint16_t A, uint16_t B, uint16_t D, uint16_t F, uint16_t H); -} filter_hq2x; diff --git a/snesfilter/lq2x/lq2x.cpp b/snesfilter/lq2x/lq2x.cpp deleted file mode 100644 index ead1cf58..00000000 --- a/snesfilter/lq2x/lq2x.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include "lq2x.hpp" - -void LQ2xFilter::size(unsigned &outwidth, unsigned &outheight, unsigned width, unsigned height) { - if(height > 240) return filter_direct.size(outwidth, outheight, width, height); - outwidth = (width <= 256) ? width * 2 : width; - outheight = (height <= 240) ? height * 2 : height; -} - -void LQ2xFilter::render( - uint32_t *output, unsigned outpitch, const uint16_t *input, unsigned pitch, - const unsigned *line, unsigned width, unsigned height -) { - if(height > 240) { - filter_direct.render(output, outpitch, input, pitch, line, width, height); - return; - } - - pitch >>= 1; - outpitch >>= 2; - - uint32_t *out0 = output; - uint32_t *out1 = output + outpitch; - - for(unsigned y = 0; y < height; y++) { - unsigned linewidth = line[y]; - - if(linewidth == 256) { - int prevline = (y == 0) || (linewidth != line[y - 1]) ? 0 : pitch; - int nextline = (y == height - 1) || (linewidth != line[y + 1]) ? 0 : pitch; - - for(unsigned x = 0; x < 256; x++) { - uint16_t A = *(input - prevline); - uint16_t B = (x > 0) ? *(input - 1) : *input; - uint16_t C = *input; - uint16_t D = (x < 255) ? *(input + 1) : *input; - uint16_t E = *(input++ + nextline); - uint32_t c = colortable[C]; - - if(A != E && B != D) { - *out0++ = (A == B ? colortable[C + A - ((C ^ A) & 0x0421) >> 1] : c); - *out0++ = (A == D ? colortable[C + A - ((C ^ A) & 0x0421) >> 1] : c); - *out1++ = (E == B ? colortable[C + E - ((C ^ E) & 0x0421) >> 1] : c); - *out1++ = (E == D ? colortable[C + E - ((C ^ E) & 0x0421) >> 1] : c); - } else { - *out0++ = c; - *out0++ = c; - *out1++ = c; - *out1++ = c; - } - } - } else { - for(unsigned x = 0; x < 512; x++) { - *out0++ = *out1++ = colortable[*input++]; - } - } - - input += pitch - linewidth; - out0 += outpitch + outpitch - 512; - out1 += outpitch + outpitch - 512; - } -} diff --git a/snesfilter/lq2x/lq2x.hpp b/snesfilter/lq2x/lq2x.hpp deleted file mode 100644 index 07d95639..00000000 --- a/snesfilter/lq2x/lq2x.hpp +++ /dev/null @@ -1,5 +0,0 @@ -class LQ2xFilter { -public: - void size(unsigned&, unsigned&, unsigned, unsigned); - void render(uint32_t*, unsigned, const uint16_t*, unsigned, const unsigned*, unsigned, unsigned); -} filter_lq2x; diff --git a/snesfilter/nall/Makefile b/snesfilter/nall/Makefile deleted file mode 100644 index 8149bf15..00000000 --- a/snesfilter/nall/Makefile +++ /dev/null @@ -1,107 +0,0 @@ -# Makefile -# author: byuu -# license: public domain - -[A-Z] = A B C D E F G H I J K L M N O P Q R S T U V W X Y Z -[a-z] = a b c d e f g h i j k l m n o p q r s t u v w x y z -[0-9] = 0 1 2 3 4 5 6 7 8 9 -[markup] = ` ~ ! @ \# $$ % ^ & * ( ) - _ = + [ { ] } \ | ; : ' " , < . > / ? -[all] = $([A-Z]) $([a-z]) $([0-9]) $([markup]) -[space] := -[space] += - -##### -# platform detection -##### - -ifeq ($(platform),) - uname := $(shell uname -a) - ifeq ($(uname),) - platform := win - delete = del $(subst /,\,$1) - else ifneq ($(findstring Darwin,$(uname)),) - platform := osx - delete = rm -f $1 - else - platform := x - delete = rm -f $1 - endif -endif - -ifeq ($(compiler),) - ifeq ($(platform),osx) - compiler := gcc-4.2 - else - compiler := gcc - endif -endif - -ifeq ($(prefix),) - prefix := /usr/local -endif - -##### -# function rwildcard(directory, pattern) -##### -rwildcard = \ - $(strip \ - $(filter $(if $2,$2,%), \ - $(foreach f, \ - $(wildcard $1*), \ - $(eval t = $(call rwildcard,$f/)) \ - $(if $t,$t,$f) \ - ) \ - ) \ - ) - -##### -# function strtr(source, from, to) -##### -strtr = \ - $(eval __temp := $1) \ - $(strip \ - $(foreach c, \ - $(join $(addsuffix :,$2),$3), \ - $(eval __temp := \ - $(subst $(word 1,$(subst :, ,$c)),$(word 2,$(subst :, ,$c)),$(__temp)) \ - ) \ - ) \ - $(__temp) \ - ) - -##### -# function strupper(source) -##### -strupper = $(call strtr,$1,$([a-z]),$([A-Z])) - -##### -# function strlower(source) -##### -strlower = $(call strtr,$1,$([A-Z]),$([a-z])) - -##### -# function strlen(source) -##### -strlen = \ - $(eval __temp := $(subst $([space]),_,$1)) \ - $(words \ - $(strip \ - $(foreach c, \ - $([all]), \ - $(eval __temp := \ - $(subst $c,$c ,$(__temp)) \ - ) \ - ) \ - $(__temp) \ - ) \ - ) - -##### -# function streq(source) -##### -streq = $(if $(filter-out xx,x$(subst $1,,$2)$(subst $2,,$1)x),,1) - -##### -# function strne(source) -##### -strne = $(if $(filter-out xx,x$(subst $1,,$2)$(subst $2,,$1)x),1,) diff --git a/snesfilter/nall/algorithm.hpp b/snesfilter/nall/algorithm.hpp deleted file mode 100644 index cdc48dcf..00000000 --- a/snesfilter/nall/algorithm.hpp +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef NALL_ALGORITHM_HPP -#define NALL_ALGORITHM_HPP - -#undef min -#undef max - -namespace nall { - template T min(const T &t, const U &u) { - return t < u ? t : u; - } - - template T max(const T &t, const U &u) { - return t > u ? t : u; - } - - //pseudo-random number generator - inline unsigned prng() { - static unsigned n = 0; - return n = (n >> 1) ^ (((n & 1) - 1) & 0xedb88320); - } -} - -#endif diff --git a/snesfilter/nall/any.hpp b/snesfilter/nall/any.hpp deleted file mode 100644 index b31cff3c..00000000 --- a/snesfilter/nall/any.hpp +++ /dev/null @@ -1,74 +0,0 @@ -#ifndef NALL_ANY_HPP -#define NALL_ANY_HPP - -#include -#include -#include - -namespace nall { - class any { - public: - bool empty() const { return container; } - const std::type_info& type() const { return container ? container->type() : typeid(void); } - - template any& operator=(const T& value_) { - typedef typename static_if< - std::is_array::value, - typename std::remove_extent::type>::type*, - T - >::type auto_t; - - if(type() == typeid(auto_t)) { - static_cast*>(container)->value = (auto_t)value_; - } else { - if(container) delete container; - container = new holder((auto_t)value_); - } - - return *this; - } - - any() : container(0) {} - template any(const T& value_) : container(0) { operator=(value_); } - - private: - struct placeholder { - virtual const std::type_info& type() const = 0; - } *container; - - template struct holder : placeholder { - T value; - const std::type_info& type() const { return typeid(T); } - holder(const T& value_) : value(value_) {} - }; - - template friend T any_cast(any&); - template friend T any_cast(const any&); - template friend T* any_cast(any*); - template friend const T* any_cast(const any*); - }; - - template T any_cast(any &value) { - typedef typename std::remove_reference::type nonref; - if(value.type() != typeid(nonref)) throw; - return static_cast*>(value.container)->value; - } - - template T any_cast(const any &value) { - typedef const typename std::remove_reference::type nonref; - if(value.type() != typeid(nonref)) throw; - return static_cast*>(value.container)->value; - } - - template T* any_cast(any *value) { - if(!value || value->type() != typeid(T)) return 0; - return &static_cast*>(value->container)->value; - } - - template const T* any_cast(const any *value) { - if(!value || value->type() != typeid(T)) return 0; - return &static_cast*>(value->container)->value; - } -} - -#endif diff --git a/snesfilter/nall/array.hpp b/snesfilter/nall/array.hpp deleted file mode 100644 index c1d33fd1..00000000 --- a/snesfilter/nall/array.hpp +++ /dev/null @@ -1,120 +0,0 @@ -#ifndef NALL_ARRAY_HPP -#define NALL_ARRAY_HPP - -#include -#include -#include -#include -#include -#include -#include - -namespace nall { - //dynamic vector array - //neither constructor nor destructor is ever invoked; - //thus, this should only be used for POD objects. - template class array { - protected: - T *pool; - unsigned poolsize, buffersize; - - public: - unsigned size() const { return buffersize; } - unsigned capacity() const { return poolsize; } - - void reset() { - if(pool) free(pool); - pool = 0; - poolsize = 0; - buffersize = 0; - } - - void reserve(unsigned newsize) { - if(newsize == poolsize) return; - - pool = (T*)realloc(pool, newsize * sizeof(T)); - poolsize = newsize; - buffersize = min(buffersize, newsize); - } - - void resize(unsigned newsize) { - if(newsize > poolsize) reserve(bit::round(newsize)); //round reserve size up to power of 2 - buffersize = newsize; - } - - T* get(unsigned minsize = 0) { - if(minsize > buffersize) resize(minsize); - if(minsize > buffersize) throw "array[] out of bounds"; - return pool; - } - - void add(const T data) { - operator[](buffersize) = data; - } - - signed find(const T data) { - for(unsigned i = 0; i < size(); i++) if(pool[i] == data) return i; - return -1; //not found - } - - void clear() { - memset(pool, 0, buffersize * sizeof(T)); - } - - array() : pool(0), poolsize(0), buffersize(0) { - } - - array(std::initializer_list list) : pool(0), poolsize(0), buffersize(0) { - for(const T *p = list.begin(); p != list.end(); ++p) add(*p); - } - - ~array() { - reset(); - } - - //copy - array& operator=(const array &source) { - if(pool) free(pool); - buffersize = source.buffersize; - poolsize = source.poolsize; - pool = (T*)malloc(sizeof(T) * poolsize); //allocate entire pool size, - memcpy(pool, source.pool, sizeof(T) * buffersize); //... but only copy used pool objects - return *this; - } - - array(const array &source) : pool(0), poolsize(0), buffersize(0) { - operator=(source); - } - - //move - array& operator=(array &&source) { - if(pool) free(pool); - pool = source.pool; - poolsize = source.poolsize; - buffersize = source.buffersize; - source.pool = 0; - source.reset(); - return *this; - } - - array(array &&source) : pool(0), poolsize(0), buffersize(0) { - operator=(std::move(source)); - } - - //index - inline T& operator[](unsigned index) { - if(index >= buffersize) resize(index + 1); - if(index >= buffersize) throw "array[] out of bounds"; - return pool[index]; - } - - inline const T& operator[](unsigned index) const { - if(index >= buffersize) throw "array[] out of bounds"; - return pool[index]; - } - }; - - template struct has_size> { enum { value = true }; }; -} - -#endif diff --git a/snesfilter/nall/base64.hpp b/snesfilter/nall/base64.hpp deleted file mode 100644 index e41c87b7..00000000 --- a/snesfilter/nall/base64.hpp +++ /dev/null @@ -1,90 +0,0 @@ -#ifndef NALL_BASE64_HPP -#define NALL_BASE64_HPP - -#include -#include - -namespace nall { - class base64 { - public: - static bool encode(char *&output, const uint8_t* input, unsigned inlength) { - output = new char[inlength * 8 / 6 + 6](); - - unsigned i = 0, o = 0; - while(i < inlength) { - switch(i % 3) { - case 0: { - output[o++] = enc(input[i] >> 2); - output[o] = enc((input[i] & 3) << 4); - } break; - - case 1: { - uint8_t prev = dec(output[o]); - output[o++] = enc(prev + (input[i] >> 4)); - output[o] = enc((input[i] & 15) << 2); - } break; - - case 2: { - uint8_t prev = dec(output[o]); - output[o++] = enc(prev + (input[i] >> 6)); - output[o++] = enc(input[i] & 63); - } break; - } - - i++; - } - - return true; - } - - static bool decode(uint8_t *&output, unsigned &outlength, const char *input) { - unsigned inlength = strlen(input), infix = 0; - output = new uint8_t[inlength](); - - unsigned i = 0, o = 0; - while(i < inlength) { - uint8_t x = dec(input[i]); - - switch(i++ & 3) { - case 0: { - output[o] = x << 2; - } break; - - case 1: { - output[o++] |= x >> 4; - output[o] = (x & 15) << 4; - } break; - - case 2: { - output[o++] |= x >> 2; - output[o] = (x & 3) << 6; - } break; - - case 3: { - output[o++] |= x; - } break; - } - } - - outlength = o; - return true; - } - - private: - static char enc(uint8_t n) { - static char lookup_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; - return lookup_table[n & 63]; - } - - static uint8_t dec(char n) { - if(n >= 'A' && n <= 'Z') return n - 'A'; - if(n >= 'a' && n <= 'z') return n - 'a' + 26; - if(n >= '0' && n <= '9') return n - '0' + 52; - if(n == '-') return 62; - if(n == '_') return 63; - return 0; - } - }; -} - -#endif diff --git a/snesfilter/nall/bit.hpp b/snesfilter/nall/bit.hpp deleted file mode 100644 index 169fc144..00000000 --- a/snesfilter/nall/bit.hpp +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef NALL_BIT_HPP -#define NALL_BIT_HPP - -namespace nall { - template inline unsigned uclamp(const unsigned x) { - enum { y = (1U << bits) - 1 }; - return y + ((x - y) & -(x < y)); //min(x, y); - } - - template inline unsigned uclip(const unsigned x) { - enum { m = (1U << bits) - 1 }; - return (x & m); - } - - template inline signed sclamp(const signed x) { - enum { b = 1U << (bits - 1), m = (1U << (bits - 1)) - 1 }; - return (x > m) ? m : (x < -b) ? -b : x; - } - - template inline signed sclip(const signed x) { - enum { b = 1U << (bits - 1), m = (1U << bits) - 1 }; - return ((x & m) ^ b) - b; - } - - namespace bit { - //lowest(0b1110) == 0b0010 - template inline T lowest(const T x) { - return x & -x; - } - - //clear_lowest(0b1110) == 0b1100 - template inline T clear_lowest(const T x) { - return x & (x - 1); - } - - //set_lowest(0b0101) == 0b0111 - template inline T set_lowest(const T x) { - return x | (x + 1); - } - - //round up to next highest single bit: - //round(15) == 16, round(16) == 16, round(17) == 32 - inline unsigned round(unsigned x) { - if((x & (x - 1)) == 0) return x; - while(x & (x - 1)) x &= x - 1; - return x << 1; - } - } -} - -#endif diff --git a/snesfilter/nall/concept.hpp b/snesfilter/nall/concept.hpp deleted file mode 100644 index 2949cd5e..00000000 --- a/snesfilter/nall/concept.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef NALL_CONCEPT_HPP -#define NALL_CONCEPT_HPP - -namespace nall { - //unsigned count() const; - template struct has_count { enum { value = false }; }; - - //unsigned length() const; - template struct has_length { enum { value = false }; }; - - //unsigned size() const; - template struct has_size { enum { value = false }; }; -} - -#endif diff --git a/snesfilter/nall/config.hpp b/snesfilter/nall/config.hpp deleted file mode 100644 index 31ae4e00..00000000 --- a/snesfilter/nall/config.hpp +++ /dev/null @@ -1,124 +0,0 @@ -#ifndef NALL_CONFIG_HPP -#define NALL_CONFIG_HPP - -#include -#include -#include - -namespace nall { - namespace configuration_traits { - template struct is_boolean { enum { value = false }; }; - template<> struct is_boolean { enum { value = true }; }; - - template struct is_signed { enum { value = false }; }; - template<> struct is_signed { enum { value = true }; }; - - template struct is_unsigned { enum { value = false }; }; - template<> struct is_unsigned { enum { value = true }; }; - - template struct is_double { enum { value = false }; }; - template<> struct is_double { enum { value = true }; }; - - template struct is_string { enum { value = false }; }; - template<> struct is_string { enum { value = true }; }; - } - - class configuration { - public: - enum type_t { boolean_t, signed_t, unsigned_t, double_t, string_t, unknown_t }; - struct item_t { - uintptr_t data; - string name; - string desc; - type_t type; - - string get() const { - switch(type) { - case boolean_t: return string() << *(bool*)data; - case signed_t: return string() << *(signed*)data; - case unsigned_t: return string() << *(unsigned*)data; - case double_t: return string() << *(double*)data; - case string_t: return string() << "\"" << *(string*)data << "\""; - } - return "???"; - } - - void set(string s) { - switch(type) { - case boolean_t: *(bool*)data = (s == "true"); break; - case signed_t: *(signed*)data = strsigned(s); break; - case unsigned_t: *(unsigned*)data = strunsigned(s); break; - case double_t: *(double*)data = strdouble(s); break; - case string_t: trim(s, "\""); *(string*)data = s; break; - } - } - }; - linear_vector list; - - template - void attach(T &data, const char *name, const char *desc = "") { - unsigned n = list.size(); - list[n].data = (uintptr_t)&data; - list[n].name = name; - list[n].desc = desc; - - if(configuration_traits::is_boolean::value) list[n].type = boolean_t; - else if(configuration_traits::is_signed::value) list[n].type = signed_t; - else if(configuration_traits::is_unsigned::value) list[n].type = unsigned_t; - else if(configuration_traits::is_double::value) list[n].type = double_t; - else if(configuration_traits::is_string::value) list[n].type = string_t; - else list[n].type = unknown_t; - } - - virtual bool load(const char *filename) { - string data; - if(data.readfile(filename) == true) { - data.replace("\r", ""); - lstring line; - line.split("\n", data); - - for(unsigned i = 0; i < line.size(); i++) { - int position = qstrpos(line[i], "#"); - if(position >= 0) line[i][position] = 0; - if(qstrpos(line[i], " = ") < 0) continue; - - lstring part; - part.qsplit(" = ", line[i]); - trim(part[0]); - trim(part[1]); - - for(unsigned n = 0; n < list.size(); n++) { - if(part[0] == list[n].name) { - list[n].set(part[1]); - break; - } - } - } - - return true; - } else { - return false; - } - } - - virtual bool save(const char *filename) const { - file fp; - if(fp.open(filename, file::mode_write)) { - for(unsigned i = 0; i < list.size(); i++) { - string output; - output << list[i].name << " = " << list[i].get(); - if(list[i].desc != "") output << " # " << list[i].desc; - output << "\r\n"; - fp.print(output); - } - - fp.close(); - return true; - } else { - return false; - } - } - }; -} - -#endif diff --git a/snesfilter/nall/crc32.hpp b/snesfilter/nall/crc32.hpp deleted file mode 100644 index ad36fbf6..00000000 --- a/snesfilter/nall/crc32.hpp +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef NALL_CRC32_HPP -#define NALL_CRC32_HPP - -#include - -namespace nall { - const uint32_t crc32_table[256] = { - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, - 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, - 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, - 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, - 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, - 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, - 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, - 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, - 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, - 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, - 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, - 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, - 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, - 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, - 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, - 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, - 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, - 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, - 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, - 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, - 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, - 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, - 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, - 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, - 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, - 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, - 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, - 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, - 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, - 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, - 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, - 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, - 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, - 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, - 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, - 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, - 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, - 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, - 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, - 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d - }; - - inline uint32_t crc32_adjust(uint32_t crc32, uint8_t input) { - return ((crc32 >> 8) & 0x00ffffff) ^ crc32_table[(crc32 ^ input) & 0xff]; - } - - inline uint32_t crc32_calculate(const uint8_t *data, unsigned length) { - uint32_t crc32 = ~0; - for(unsigned i = 0; i < length; i++) { - crc32 = crc32_adjust(crc32, data[i]); - } - return ~crc32; - } -} - -#endif diff --git a/snesfilter/nall/detect.hpp b/snesfilter/nall/detect.hpp deleted file mode 100644 index b4991aaf..00000000 --- a/snesfilter/nall/detect.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef NALL_DETECT_HPP -#define NALL_DETECT_HPP - -/* Compiler detection */ - -#if defined(__GNUC__) - #define COMPILER_GCC -#elif defined(_MSC_VER) - #define COMPILER_VISUALC -#endif - -/* Platform detection */ - -#if defined(_WIN32) - #define PLATFORM_WIN -#elif defined(__APPLE__) - #define PLATFORM_OSX -#elif defined(linux) || defined(__sun__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) - #define PLATFORM_X -#endif - -/* Endian detection */ - -#if defined(__i386__) || defined(__amd64__) || defined(_M_IX86) || defined(_M_AMD64) - #define ARCH_LSB -#elif defined(__powerpc__) || defined(_M_PPC) || defined(__BIG_ENDIAN__) - #define ARCH_MSB -#endif - -#endif diff --git a/snesfilter/nall/dictionary.hpp b/snesfilter/nall/dictionary.hpp deleted file mode 100644 index f14e2095..00000000 --- a/snesfilter/nall/dictionary.hpp +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef NALL_DICTIONARY_HPP -#define NALL_DICTIONARY_HPP - -#include -#include -#include - -namespace nall { - class dictionary { - public: - string operator[](const char *input) { - for(unsigned i = 0; i < index_input.size(); i++) { - if(index_input[i] == input) return index_output[i]; - } - - //no match, use input; remove input identifier, if one exists - if(strbegin(input, "{{")) { - int pos = strpos(input, "}}"); - if(pos >= 0) { - string temp = substr(input, pos + 2); - return temp; - } - } - - return input; - } - - bool import(const char *filename) { - string data; - if(data.readfile(filename) == false) return false; - ltrim_once(data, "\xef\xbb\xbf"); //remove UTF-8 marker, if it exists - data.replace("\r", ""); - - lstring line; - line.split("\n", data); - for(unsigned i = 0; i < line.size(); i++) { - lstring part; - //format: "Input" = "Output" - part.qsplit("=", line[i]); - if(part.size() != 2) continue; - - //remove whitespace - trim(part[0]); - trim(part[1]); - - //remove quotes - trim_once(part[0], "\""); - trim_once(part[1], "\""); - - unsigned n = index_input.size(); - index_input[n] = part[0]; - index_output[n] = part[1]; - } - - return true; - } - - void reset() { - index_input.reset(); - index_output.reset(); - } - - ~dictionary() { - reset(); - } - - dictionary& operator=(const dictionary&) = delete; - dictionary(const dictionary&) = delete; - - protected: - lstring index_input; - lstring index_output; - }; -} - -#endif diff --git a/snesfilter/nall/dl.hpp b/snesfilter/nall/dl.hpp deleted file mode 100644 index 22acf51f..00000000 --- a/snesfilter/nall/dl.hpp +++ /dev/null @@ -1,119 +0,0 @@ -#ifndef NALL_DL_HPP -#define NALL_DL_HPP - -//dynamic linking support - -#include -#include -#include -#include - -#if defined(PLATFORM_X) || defined(PLATFORM_OSX) - #include -#elif defined(PLATFORM_WIN) - #include - #include -#endif - -namespace nall { - struct library { - bool opened() const { return handle; } - bool open(const char*); - void* sym(const char*); - void close(); - - library() : handle(0) {} - ~library() { close(); } - - library& operator=(const library&) = delete; - library(const library&) = delete; - - private: - uintptr_t handle; - }; - - #if defined(PLATFORM_X) - inline bool library::open(const char *name) { - if(handle) close(); - char *t = new char[strlen(name) + 256]; - strcpy(t, "lib"); - strcat(t, name); - strcat(t, ".so"); - handle = (uintptr_t)dlopen(t, RTLD_LAZY); - if(!handle) { - strcpy(t, "/usr/local/lib/lib"); - strcat(t, name); - strcat(t, ".so"); - handle = (uintptr_t)dlopen(t, RTLD_LAZY); - } - delete[] t; - return handle; - } - - inline void* library::sym(const char *name) { - if(!handle) return 0; - return dlsym((void*)handle, name); - } - - inline void library::close() { - if(!handle) return; - dlclose((void*)handle); - handle = 0; - } - #elif defined(PLATFORM_OSX) - inline bool library::open(const char *name) { - if(handle) close(); - char *t = new char[strlen(name) + 256]; - strcpy(t, "lib"); - strcat(t, name); - strcat(t, ".dylib"); - handle = (uintptr_t)dlopen(t, RTLD_LAZY); - if(!handle) { - strcpy(t, "/usr/local/lib/lib"); - strcat(t, name); - strcat(t, ".dylib"); - handle = (uintptr_t)dlopen(t, RTLD_LAZY); - } - delete[] t; - return handle; - } - - inline void* library::sym(const char *name) { - if(!handle) return 0; - return dlsym((void*)handle, name); - } - - inline void library::close() { - if(!handle) return; - dlclose((void*)handle); - handle = 0; - } - #elif defined(PLATFORM_WIN) - inline bool library::open(const char *name) { - if(handle) close(); - char *t = new char[strlen(name) + 8]; - strcpy(t, name); - strcat(t, ".dll"); - handle = (uintptr_t)LoadLibraryW(utf16_t(t)); - delete[] t; - return handle; - } - - inline void* library::sym(const char *name) { - if(!handle) return 0; - return (void*)GetProcAddress((HMODULE)handle, name); - } - - inline void library::close() { - if(!handle) return; - FreeLibrary((HMODULE)handle); - handle = 0; - } - #else - inline bool library::open(const char*) { return false; } - inline void* library::sym(const char*) { return 0; } - inline void library::close() {} - #endif -}; - -#endif diff --git a/snesfilter/nall/endian.hpp b/snesfilter/nall/endian.hpp deleted file mode 100644 index 40d15633..00000000 --- a/snesfilter/nall/endian.hpp +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef NALL_ENDIAN_HPP -#define NALL_ENDIAN_HPP - -#if !defined(ARCH_MSB) - //little-endian: uint8_t[] { 0x01, 0x02, 0x03, 0x04 } == 0x04030201 - #define order_lsb2(a,b) a,b - #define order_lsb3(a,b,c) a,b,c - #define order_lsb4(a,b,c,d) a,b,c,d - #define order_lsb5(a,b,c,d,e) a,b,c,d,e - #define order_lsb6(a,b,c,d,e,f) a,b,c,d,e,f - #define order_lsb7(a,b,c,d,e,f,g) a,b,c,d,e,f,g - #define order_lsb8(a,b,c,d,e,f,g,h) a,b,c,d,e,f,g,h - #define order_msb2(a,b) b,a - #define order_msb3(a,b,c) c,b,a - #define order_msb4(a,b,c,d) d,c,b,a - #define order_msb5(a,b,c,d,e) e,d,c,b,a - #define order_msb6(a,b,c,d,e,f) f,e,d,c,b,a - #define order_msb7(a,b,c,d,e,f,g) g,f,e,d,c,b,a - #define order_msb8(a,b,c,d,e,f,g,h) h,g,f,e,d,c,b,a -#else - //big-endian: uint8_t[] { 0x01, 0x02, 0x03, 0x04 } == 0x01020304 - #define order_lsb2(a,b) b,a - #define order_lsb3(a,b,c) c,b,a - #define order_lsb4(a,b,c,d) d,c,b,a - #define order_lsb5(a,b,c,d,e) e,d,c,b,a - #define order_lsb6(a,b,c,d,e,f) f,e,d,c,b,a - #define order_lsb7(a,b,c,d,e,f,g) g,f,e,d,c,b,a - #define order_lsb8(a,b,c,d,e,f,g,h) h,g,f,e,d,c,b,a - #define order_msb2(a,b) a,b - #define order_msb3(a,b,c) a,b,c - #define order_msb4(a,b,c,d) a,b,c,d - #define order_msb5(a,b,c,d,e) a,b,c,d,e - #define order_msb6(a,b,c,d,e,f) a,b,c,d,e,f - #define order_msb7(a,b,c,d,e,f,g) a,b,c,d,e,f,g - #define order_msb8(a,b,c,d,e,f,g,h) a,b,c,d,e,f,g,h -#endif - -#endif diff --git a/snesfilter/nall/file.hpp b/snesfilter/nall/file.hpp deleted file mode 100644 index 4c8ca8ee..00000000 --- a/snesfilter/nall/file.hpp +++ /dev/null @@ -1,259 +0,0 @@ -#ifndef NALL_FILE_HPP -#define NALL_FILE_HPP - -#include -#include - -#if !defined(_WIN32) - #include -#else - #include -#endif - -#include -#include -#include - -namespace nall { - inline FILE* fopen_utf8(const char *utf8_filename, const char *mode) { - #if !defined(_WIN32) - return fopen(utf8_filename, mode); - #else - return _wfopen(utf16_t(utf8_filename), utf16_t(mode)); - #endif - } - - class file { - public: - enum FileMode { mode_read, mode_write, mode_readwrite, mode_writeread }; - enum SeekMode { seek_absolute, seek_relative }; - - uint8_t read() { - if(!fp) return 0xff; //file not open - if(file_mode == mode_write) return 0xff; //reads not permitted - if(file_offset >= file_size) return 0xff; //cannot read past end of file - buffer_sync(); - return buffer[(file_offset++) & buffer_mask]; - } - - uintmax_t readl(unsigned length = 1) { - uintmax_t data = 0; - for(int i = 0; i < length; i++) { - data |= (uintmax_t)read() << (i << 3); - } - return data; - } - - uintmax_t readm(unsigned length = 1) { - uintmax_t data = 0; - while(length--) { - data <<= 8; - data |= read(); - } - return data; - } - - void read(uint8_t *buffer, unsigned length) { - while(length--) *buffer++ = read(); - } - - void write(uint8_t data) { - if(!fp) return; //file not open - if(file_mode == mode_read) return; //writes not permitted - buffer_sync(); - buffer[(file_offset++) & buffer_mask] = data; - buffer_dirty = true; - if(file_offset > file_size) file_size = file_offset; - } - - void writel(uintmax_t data, unsigned length = 1) { - while(length--) { - write(data); - data >>= 8; - } - } - - void writem(uintmax_t data, unsigned length = 1) { - for(int i = length - 1; i >= 0; i--) { - write(data >> (i << 3)); - } - } - - void write(const uint8_t *buffer, unsigned length) { - while(length--) write(*buffer++); - } - - void print(const char *string) { - if(!string) return; - while(*string) write(*string++); - } - - void flush() { - buffer_flush(); - fflush(fp); - } - - void seek(int offset, SeekMode mode = seek_absolute) { - if(!fp) return; //file not open - buffer_flush(); - - uintmax_t req_offset = file_offset; - switch(mode) { - case seek_absolute: req_offset = offset; break; - case seek_relative: req_offset += offset; break; - } - - if(req_offset < 0) req_offset = 0; //cannot seek before start of file - if(req_offset > file_size) { - if(file_mode == mode_read) { //cannot seek past end of file - req_offset = file_size; - } else { //pad file to requested location - file_offset = file_size; - while(file_size < req_offset) write(0x00); - } - } - - file_offset = req_offset; - } - - int offset() { - if(!fp) return -1; //file not open - return file_offset; - } - - int size() { - if(!fp) return -1; //file not open - return file_size; - } - - bool truncate(unsigned size) { - if(!fp) return false; //file not open - #if !defined(_WIN32) - return ftruncate(fileno(fp), size) == 0; - #else - return _chsize(fileno(fp), size) == 0; - #endif - } - - bool end() { - if(!fp) return true; //file not open - return file_offset >= file_size; - } - - static bool exists(const char *fn) { - #if !defined(_WIN32) - FILE *fp = fopen(fn, "rb"); - #else - FILE *fp = _wfopen(utf16_t(fn), L"rb"); - #endif - if(fp) { - fclose(fp); - return true; - } - return false; - } - - static unsigned size(const char *fn) { - #if !defined(_WIN32) - FILE *fp = fopen(fn, "rb"); - #else - FILE *fp = _wfopen(utf16_t(fn), L"rb"); - #endif - unsigned filesize = 0; - if(fp) { - fseek(fp, 0, SEEK_END); - filesize = ftell(fp); - fclose(fp); - } - return filesize; - } - - bool open() { - return fp; - } - - bool open(const char *fn, FileMode mode) { - if(fp) return false; - - switch(file_mode = mode) { - #if !defined(_WIN32) - case mode_read: fp = fopen(fn, "rb"); break; - case mode_write: fp = fopen(fn, "wb+"); break; //need read permission for buffering - case mode_readwrite: fp = fopen(fn, "rb+"); break; - case mode_writeread: fp = fopen(fn, "wb+"); break; - #else - case mode_read: fp = _wfopen(utf16_t(fn), L"rb"); break; - case mode_write: fp = _wfopen(utf16_t(fn), L"wb+"); break; - case mode_readwrite: fp = _wfopen(utf16_t(fn), L"rb+"); break; - case mode_writeread: fp = _wfopen(utf16_t(fn), L"wb+"); break; - #endif - } - if(!fp) return false; - buffer_offset = -1; //invalidate buffer - file_offset = 0; - fseek(fp, 0, SEEK_END); - file_size = ftell(fp); - fseek(fp, 0, SEEK_SET); - return true; - } - - void close() { - if(!fp) return; - buffer_flush(); - fclose(fp); - fp = 0; - } - - file() { - memset(buffer, 0, sizeof buffer); - buffer_offset = -1; - buffer_dirty = false; - fp = 0; - file_offset = 0; - file_size = 0; - file_mode = mode_read; - } - - ~file() { - close(); - } - - file& operator=(const file&) = delete; - file(const file&) = delete; - - private: - enum { buffer_size = 1 << 12, buffer_mask = buffer_size - 1 }; - char buffer[buffer_size]; - int buffer_offset; - bool buffer_dirty; - FILE *fp; - unsigned file_offset; - unsigned file_size; - FileMode file_mode; - - void buffer_sync() { - if(!fp) return; //file not open - if(buffer_offset != (file_offset & ~buffer_mask)) { - buffer_flush(); - buffer_offset = file_offset & ~buffer_mask; - fseek(fp, buffer_offset, SEEK_SET); - unsigned length = (buffer_offset + buffer_size) <= file_size ? buffer_size : (file_size & buffer_mask); - if(length) unsigned unused = fread(buffer, 1, length, fp); - } - } - - void buffer_flush() { - if(!fp) return; //file not open - if(file_mode == mode_read) return; //buffer cannot be written to - if(buffer_offset < 0) return; //buffer unused - if(buffer_dirty == false) return; //buffer unmodified since read - fseek(fp, buffer_offset, SEEK_SET); - unsigned length = (buffer_offset + buffer_size) <= file_size ? buffer_size : (file_size & buffer_mask); - if(length) unsigned unused = fwrite(buffer, 1, length, fp); - buffer_offset = -1; //invalidate buffer - buffer_dirty = false; - } - }; -} - -#endif diff --git a/snesfilter/nall/filemap.hpp b/snesfilter/nall/filemap.hpp deleted file mode 100644 index a05f0eb7..00000000 --- a/snesfilter/nall/filemap.hpp +++ /dev/null @@ -1,190 +0,0 @@ -#ifndef NALL_FILEMAP_HPP -#define NALL_FILEMAP_HPP - -#include -#include - -#include -#include -#if defined(_WIN32) - #include -#else - #include - #include - #include - #include - #include -#endif - -namespace nall { - class filemap { - public: - enum filemode { mode_read, mode_write, mode_readwrite, mode_writeread }; - - bool open(const char *filename, filemode mode) { return p_open(filename, mode); } - void close() { return p_close(); } - unsigned size() const { return p_size; } - uint8_t* handle() { return p_handle; } - const uint8_t* handle() const { return p_handle; } - filemap() : p_size(0), p_handle(0) { p_ctor(); } - ~filemap() { p_dtor(); } - - private: - unsigned p_size; - uint8_t *p_handle; - - #if defined(_WIN32) - //============= - //MapViewOfFile - //============= - - HANDLE p_filehandle, p_maphandle; - - bool p_open(const char *filename, filemode mode) { - int desired_access, creation_disposition, flprotect, map_access; - - switch(mode) { - default: return false; - case mode_read: - desired_access = GENERIC_READ; - creation_disposition = OPEN_EXISTING; - flprotect = PAGE_READONLY; - map_access = FILE_MAP_READ; - break; - case mode_write: - //write access requires read access - desired_access = GENERIC_WRITE; - creation_disposition = CREATE_ALWAYS; - flprotect = PAGE_READWRITE; - map_access = FILE_MAP_ALL_ACCESS; - break; - case mode_readwrite: - desired_access = GENERIC_READ | GENERIC_WRITE; - creation_disposition = OPEN_EXISTING; - flprotect = PAGE_READWRITE; - map_access = FILE_MAP_ALL_ACCESS; - break; - case mode_writeread: - desired_access = GENERIC_READ | GENERIC_WRITE; - creation_disposition = CREATE_NEW; - flprotect = PAGE_READWRITE; - map_access = FILE_MAP_ALL_ACCESS; - break; - } - - p_filehandle = CreateFileW(utf16_t(filename), desired_access, FILE_SHARE_READ, NULL, - creation_disposition, FILE_ATTRIBUTE_NORMAL, NULL); - if(p_filehandle == INVALID_HANDLE_VALUE) return false; - - p_size = GetFileSize(p_filehandle, NULL); - - p_maphandle = CreateFileMapping(p_filehandle, NULL, flprotect, 0, p_size, NULL); - if(p_maphandle == INVALID_HANDLE_VALUE) { - CloseHandle(p_filehandle); - p_filehandle = INVALID_HANDLE_VALUE; - return false; - } - - p_handle = (uint8_t*)MapViewOfFile(p_maphandle, map_access, 0, 0, p_size); - return p_handle; - } - - void p_close() { - if(p_handle) { - UnmapViewOfFile(p_handle); - p_handle = 0; - } - - if(p_maphandle != INVALID_HANDLE_VALUE) { - CloseHandle(p_maphandle); - p_maphandle = INVALID_HANDLE_VALUE; - } - - if(p_filehandle != INVALID_HANDLE_VALUE) { - CloseHandle(p_filehandle); - p_filehandle = INVALID_HANDLE_VALUE; - } - } - - void p_ctor() { - p_filehandle = INVALID_HANDLE_VALUE; - p_maphandle = INVALID_HANDLE_VALUE; - } - - void p_dtor() { - close(); - } - - #else - //==== - //mmap - //==== - - int p_fd; - - bool p_open(const char *filename, filemode mode) { - int open_flags, mmap_flags; - - switch(mode) { - default: return false; - case mode_read: - open_flags = O_RDONLY; - mmap_flags = PROT_READ; - break; - case mode_write: - open_flags = O_RDWR | O_CREAT; //mmap() requires read access - mmap_flags = PROT_WRITE; - break; - case mode_readwrite: - open_flags = O_RDWR; - mmap_flags = PROT_READ | PROT_WRITE; - break; - case mode_writeread: - open_flags = O_RDWR | O_CREAT; - mmap_flags = PROT_READ | PROT_WRITE; - break; - } - - p_fd = ::open(filename, open_flags); - if(p_fd < 0) return false; - - struct stat p_stat; - fstat(p_fd, &p_stat); - p_size = p_stat.st_size; - - p_handle = (uint8_t*)mmap(0, p_size, mmap_flags, MAP_SHARED, p_fd, 0); - if(p_handle == MAP_FAILED) { - p_handle = 0; - ::close(p_fd); - p_fd = -1; - return false; - } - - return p_handle; - } - - void p_close() { - if(p_handle) { - munmap(p_handle, p_size); - p_handle = 0; - } - - if(p_fd >= 0) { - ::close(p_fd); - p_fd = -1; - } - } - - void p_ctor() { - p_fd = -1; - } - - void p_dtor() { - p_close(); - } - - #endif - }; -} - -#endif diff --git a/snesfilter/nall/foreach.hpp b/snesfilter/nall/foreach.hpp deleted file mode 100644 index ea975b84..00000000 --- a/snesfilter/nall/foreach.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef NALL_FOREACH_HPP -#define NALL_FOREACH_HPP - -#undef foreach -#define foreach(iter, object) \ - for(unsigned foreach_counter = 0, foreach_limit = foreach_size(object), foreach_once = 0, foreach_broken = 0; foreach_counter < foreach_limit && foreach_broken == 0; foreach_counter++, foreach_once = 0) \ - for(auto &iter = object[foreach_counter]; foreach_once == 0 && (foreach_broken = 1); foreach_once++, foreach_broken = 0) - -#include -#include -#include - -namespace nall { - template unsigned foreach_size(const T& object, typename mp_enable_if>::type = 0) { - return object.count(); - } - - template unsigned foreach_size(const T& object, typename mp_enable_if>::type = 0) { - return object.length(); - } - - template unsigned foreach_size(const T& object, typename mp_enable_if>::type = 0) { - return object.size(); - } - - template unsigned foreach_size(const T& object, typename mp_enable_if>::type = 0) { - return sizeof(T) / sizeof(typename std::remove_extent::type); - } -} - -#endif diff --git a/snesfilter/nall/function.hpp b/snesfilter/nall/function.hpp deleted file mode 100644 index 3f0f704e..00000000 --- a/snesfilter/nall/function.hpp +++ /dev/null @@ -1,102 +0,0 @@ -#ifndef NALL_FUNCTION_HPP -#define NALL_FUNCTION_HPP - -#include -#include - -namespace nall { - template class function; - - template - class function { - private: - struct base1 { virtual void func1(P...) {} }; - struct base2 { virtual void func2(P...) {} }; - struct derived : base1, virtual base2 {}; - - struct data_t { - R (*callback)(const data_t&, P...); - union { - R (*callback_global)(P...); - struct { - R (derived::*callback_member)(P...); - void *object; - }; - }; - } data; - - static R callback_global(const data_t &data, P... p) { - return data.callback_global(p...); - } - - template - static R callback_member(const data_t &data, P... p) { - return (((C*)data.object)->*((R (C::*&)(P...))data.callback_member))(p...); - } - - public: - R operator()(P... p) const { return data.callback(data, p...); } - operator bool() const { return data.callback; } - void reset() { data.callback = 0; } - - function& operator=(const function &source) { memcpy(&data, &source.data, sizeof(data_t)); return *this; } - function(const function &source) { operator=(source); } - - //no pointer - function() { - data.callback = 0; - } - - //symbolic link pointer (nall/dl.hpp::sym, etc) - function(void *callback) { - data.callback = callback ? &callback_global : 0; - data.callback_global = (R (*)(P...))callback; - } - - //global function pointer - function(R (*callback)(P...)) { - data.callback = &callback_global; - data.callback_global = callback; - } - - //member function pointer - template - function(R (C::*callback)(P...), C *object) { - static_assert(sizeof data.callback_member >= sizeof callback, "callback_member is too small"); - data.callback = &callback_member; - (R (C::*&)(P...))data.callback_member = callback; - data.object = object; - } - - //const member function pointer - template - function(R (C::*callback)(P...) const, C *object) { - static_assert(sizeof data.callback_member >= sizeof callback, "callback_member is too small"); - data.callback = &callback_member; - (R (C::*&)(P...))data.callback_member = (R (C::*&)(P...))callback; - data.object = object; - } - - //lambda function pointer - template - function(T callback) { - static_assert(std::is_same::type>::value, "lambda mismatch"); - data.callback = &callback_global; - data.callback_global = (R (*)(P...))callback; - } - }; - - //bind functions to ease construction and assignment of function() with more than one argument - - template - function bind(R (C::*callback)(P...), C *object) { - return function(callback, object); - } - - template - function bind(R (C::*callback)(P...) const, C *object) { - return function(callback, object); - } -} - -#endif diff --git a/snesfilter/nall/input.hpp b/snesfilter/nall/input.hpp deleted file mode 100644 index b3ce9ebf..00000000 --- a/snesfilter/nall/input.hpp +++ /dev/null @@ -1,386 +0,0 @@ -#ifndef NALL_INPUT_HPP -#define NALL_INPUT_HPP - -#include -#include -#include - -#include -#include - -namespace nall { - -struct Keyboard; -Keyboard& keyboard(unsigned = 0); - -static const char KeyboardScancodeName[][64] = { - "Escape", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", - "PrintScreen", "ScrollLock", "Pause", "Tilde", - "Num1", "Num2", "Num3", "Num4", "Num5", "Num6", "Num7", "Num8", "Num9", "Num0", - "Dash", "Equal", "Backspace", - "Insert", "Delete", "Home", "End", "PageUp", "PageDown", - "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", - "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", - "LeftBracket", "RightBracket", "Backslash", "Semicolon", "Apostrophe", "Comma", "Period", "Slash", - "Keypad1", "Keypad2", "Keypad3", "Keypad4", "Keypad5", "Keypad6", "Keypad7", "Keypad8", "Keypad9", "Keypad0", - "Point", "Enter", "Add", "Subtract", "Multiply", "Divide", - "NumLock", "CapsLock", - "Up", "Down", "Left", "Right", - "Tab", "Return", "Spacebar", "Menu", - "Shift", "Control", "Alt", "Super", -}; - -struct Keyboard { - const unsigned ID; - enum { Base = 1 }; - enum { Count = 8, Size = 128 }; - - enum Scancode { - Escape, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, - PrintScreen, ScrollLock, Pause, Tilde, - Num1, Num2, Num3, Num4, Num5, Num6, Num7, Num8, Num9, Num0, - Dash, Equal, Backspace, - Insert, Delete, Home, End, PageUp, PageDown, - A, B, C, D, E, F, G, H, I, J, K, L, M, - N, O, P, Q, R, S, T, U, V, W, X, Y, Z, - LeftBracket, RightBracket, Backslash, Semicolon, Apostrophe, Comma, Period, Slash, - Keypad1, Keypad2, Keypad3, Keypad4, Keypad5, Keypad6, Keypad7, Keypad8, Keypad9, Keypad0, - Point, Enter, Add, Subtract, Multiply, Divide, - NumLock, CapsLock, - Up, Down, Left, Right, - Tab, Return, Spacebar, Menu, - Shift, Control, Alt, Super, - Limit, - }; - - static signed numberDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(keyboard(i).belongsTo(scancode)) return i; - } - return -1; - } - - static signed keyDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(keyboard(i).isKey(scancode)) return scancode - keyboard(i).key(Escape); - } - return -1; - } - - static signed modifierDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(keyboard(i).isModifier(scancode)) return scancode - keyboard(i).key(Shift); - } - return -1; - } - - static bool isAnyKey(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(keyboard(i).isKey(scancode)) return true; - } - return false; - } - - static bool isAnyModifier(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(keyboard(i).isModifier(scancode)) return true; - } - return false; - } - - static uint16_t decode(const char *name) { - string s(name); - if(!strbegin(name, "KB")) return 0; - ltrim(s, "KB"); - unsigned id = strunsigned(s); - int pos = strpos(s, "::"); - if(pos < 0) return 0; - s = substr(s, pos + 2); - for(unsigned i = 0; i < Limit; i++) { - if(s == KeyboardScancodeName[i]) return Base + Size * id + i; - } - return 0; - } - - string encode(uint16_t code) const { - unsigned index = 0; - for(unsigned i = 0; i < Count; i++) { - if(code >= Base + Size * i && code < Base + Size * (i + 1)) { - index = code - (Base + Size * i); - break; - } - } - return string() << "KB" << ID << "::" << KeyboardScancodeName[index]; - } - - uint16_t operator[](Scancode code) const { return Base + ID * Size + code; } - uint16_t key(unsigned id) const { return Base + Size * ID + id; } - bool isKey(unsigned id) const { return id >= key(Escape) && id <= key(Menu); } - bool isModifier(unsigned id) const { return id >= key(Shift) && id <= key(Super); } - bool belongsTo(uint16_t scancode) const { return isKey(scancode) || isModifier(scancode); } - - Keyboard(unsigned ID_) : ID(ID_) {} -}; - -inline Keyboard& keyboard(unsigned id) { - static Keyboard kb0(0), kb1(1), kb2(2), kb3(3), kb4(4), kb5(5), kb6(6), kb7(7); - switch(id) { default: - case 0: return kb0; case 1: return kb1; case 2: return kb2; case 3: return kb3; - case 4: return kb4; case 5: return kb5; case 6: return kb6; case 7: return kb7; - } -} - -static const char MouseScancodeName[][64] = { - "Xaxis", "Yaxis", "Zaxis", - "Button0", "Button1", "Button2", "Button3", "Button4", "Button5", "Button6", "Button7", -}; - -struct Mouse; -Mouse& mouse(unsigned = 0); - -struct Mouse { - const unsigned ID; - enum { Base = Keyboard::Base + Keyboard::Size * Keyboard::Count }; - enum { Count = 8, Size = 16 }; - enum { Axes = 3, Buttons = 8 }; - - enum Scancode { - Xaxis, Yaxis, Zaxis, - Button0, Button1, Button2, Button3, Button4, Button5, Button6, Button7, - Limit, - }; - - static signed numberDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(mouse(i).belongsTo(scancode)) return i; - } - return -1; - } - - static signed axisDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(mouse(i).isAxis(scancode)) return scancode - mouse(i).axis(0); - } - return -1; - } - - static signed buttonDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(mouse(i).isButton(scancode)) return scancode - mouse(i).button(0); - } - return -1; - } - - static bool isAnyAxis(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(mouse(i).isAxis(scancode)) return true; - } - return false; - } - - static bool isAnyButton(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(mouse(i).isButton(scancode)) return true; - } - return false; - } - - static uint16_t decode(const char *name) { - string s(name); - if(!strbegin(name, "MS")) return 0; - ltrim(s, "MS"); - unsigned id = strunsigned(s); - int pos = strpos(s, "::"); - if(pos < 0) return 0; - s = substr(s, pos + 2); - for(unsigned i = 0; i < Limit; i++) { - if(s == MouseScancodeName[i]) return Base + Size * id + i; - } - return 0; - } - - string encode(uint16_t code) const { - unsigned index = 0; - for(unsigned i = 0; i < Count; i++) { - if(code >= Base + Size * i && code < Base + Size * (i + 1)) { - index = code - (Base + Size * i); - break; - } - } - return string() << "MS" << ID << "::" << MouseScancodeName[index]; - } - - uint16_t operator[](Scancode code) const { return Base + ID * Size + code; } - uint16_t axis(unsigned id) const { return Base + Size * ID + Xaxis + id; } - uint16_t button(unsigned id) const { return Base + Size * ID + Button0 + id; } - bool isAxis(unsigned id) const { return id >= axis(0) && id <= axis(2); } - bool isButton(unsigned id) const { return id >= button(0) && id <= button(7); } - bool belongsTo(uint16_t scancode) const { return isAxis(scancode) || isButton(scancode); } - - Mouse(unsigned ID_) : ID(ID_) {} -}; - -inline Mouse& mouse(unsigned id) { - static Mouse ms0(0), ms1(1), ms2(2), ms3(3), ms4(4), ms5(5), ms6(6), ms7(7); - switch(id) { default: - case 0: return ms0; case 1: return ms1; case 2: return ms2; case 3: return ms3; - case 4: return ms4; case 5: return ms5; case 6: return ms6; case 7: return ms7; - } -} - -static const char JoypadScancodeName[][64] = { - "Hat0", "Hat1", "Hat2", "Hat3", "Hat4", "Hat5", "Hat6", "Hat7", - "Axis0", "Axis1", "Axis2", "Axis3", "Axis4", "Axis5", "Axis6", "Axis7", - "Axis8", "Axis9", "Axis10", "Axis11", "Axis12", "Axis13", "Axis14", "Axis15", - "Button0", "Button1", "Button2", "Button3", "Button4", "Button5", "Button6", "Button7", - "Button8", "Button9", "Button10", "Button11", "Button12", "Button13", "Button14", "Button15", - "Button16", "Button17", "Button18", "Button19", "Button20", "Button21", "Button22", "Button23", - "Button24", "Button25", "Button26", "Button27", "Button28", "Button29", "Button30", "Button31", -}; - -struct Joypad; -Joypad& joypad(unsigned = 0); - -struct Joypad { - const unsigned ID; - enum { Base = Mouse::Base + Mouse::Size * Mouse::Count }; - enum { Count = 8, Size = 64 }; - enum { Hats = 8, Axes = 16, Buttons = 32 }; - - enum Scancode { - Hat0, Hat1, Hat2, Hat3, Hat4, Hat5, Hat6, Hat7, - Axis0, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7, - Axis8, Axis9, Axis10, Axis11, Axis12, Axis13, Axis14, Axis15, - Button0, Button1, Button2, Button3, Button4, Button5, Button6, Button7, - Button8, Button9, Button10, Button11, Button12, Button13, Button14, Button15, - Button16, Button17, Button18, Button19, Button20, Button21, Button22, Button23, - Button24, Button25, Button26, Button27, Button28, Button29, Button30, Button31, - Limit, - }; - - enum Hat { HatCenter = 0, HatUp = 1, HatRight = 2, HatDown = 4, HatLeft = 8 }; - - static signed numberDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(joypad(i).belongsTo(scancode)) return i; - } - return -1; - } - - static signed hatDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(joypad(i).isHat(scancode)) return scancode - joypad(i).hat(0); - } - return -1; - } - - static signed axisDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(joypad(i).isAxis(scancode)) return scancode - joypad(i).axis(0); - } - return -1; - } - - static signed buttonDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(joypad(i).isButton(scancode)) return scancode - joypad(i).button(0); - } - return -1; - } - - static bool isAnyHat(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(joypad(i).isHat(scancode)) return true; - } - return false; - } - - static bool isAnyAxis(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(joypad(i).isAxis(scancode)) return true; - } - return false; - } - - static bool isAnyButton(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(joypad(i).isButton(scancode)) return true; - } - return false; - } - - static uint16_t decode(const char *name) { - string s(name); - if(!strbegin(name, "JP")) return 0; - ltrim(s, "JP"); - unsigned id = strunsigned(s); - int pos = strpos(s, "::"); - if(pos < 0) return 0; - s = substr(s, pos + 2); - for(unsigned i = 0; i < Limit; i++) { - if(s == JoypadScancodeName[i]) return Base + Size * id + i; - } - return 0; - } - - string encode(uint16_t code) const { - unsigned index = 0; - for(unsigned i = 0; i < Count; i++) { - if(code >= Base + Size * i && code < Base + Size * (i + 1)) { - index = code - (Base + Size * i); - } - } - return string() << "JP" << ID << "::" << JoypadScancodeName[index]; - } - - uint16_t operator[](Scancode code) const { return Base + ID * Size + code; } - uint16_t hat(unsigned id) const { return Base + Size * ID + Hat0 + id; } - uint16_t axis(unsigned id) const { return Base + Size * ID + Axis0 + id; } - uint16_t button(unsigned id) const { return Base + Size * ID + Button0 + id; } - bool isHat(unsigned id) const { return id >= hat(0) && id <= hat(7); } - bool isAxis(unsigned id) const { return id >= axis(0) && id <= axis(15); } - bool isButton(unsigned id) const { return id >= button(0) && id <= button(31); } - bool belongsTo(uint16_t scancode) const { return isHat(scancode) || isAxis(scancode) || isButton(scancode); } - - Joypad(unsigned ID_) : ID(ID_) {} -}; - -inline Joypad& joypad(unsigned id) { - static Joypad jp0(0), jp1(1), jp2(2), jp3(3), jp4(4), jp5(5), jp6(6), jp7(7); - switch(id) { default: - case 0: return jp0; case 1: return jp1; case 2: return jp2; case 3: return jp3; - case 4: return jp4; case 5: return jp5; case 6: return jp6; case 7: return jp7; - } -} - -struct Scancode { - enum { None = 0, Limit = Joypad::Base + Joypad::Size * Joypad::Count }; - - static uint16_t decode(const char *name) { - uint16_t code; - code = Keyboard::decode(name); - if(code) return code; - code = Mouse::decode(name); - if(code) return code; - code = Joypad::decode(name); - if(code) return code; - return None; - } - - static string encode(uint16_t code) { - for(unsigned i = 0; i < Keyboard::Count; i++) { - if(keyboard(i).belongsTo(code)) return keyboard(i).encode(code); - } - for(unsigned i = 0; i < Mouse::Count; i++) { - if(mouse(i).belongsTo(code)) return mouse(i).encode(code); - } - for(unsigned i = 0; i < Joypad::Count; i++) { - if(joypad(i).belongsTo(code)) return joypad(i).encode(code); - } - return "None"; - } -}; - -} - -#endif diff --git a/snesfilter/nall/lzss.hpp b/snesfilter/nall/lzss.hpp deleted file mode 100644 index 202bc814..00000000 --- a/snesfilter/nall/lzss.hpp +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef NALL_LZSS_HPP -#define NALL_LZSS_HPP - -#include -#include -#include - -namespace nall { - class lzss { - public: - static bool encode(uint8_t *&output, unsigned &outlength, const uint8_t *input, unsigned inlength) { - output = new(zeromemory) uint8_t[inlength * 9 / 8 + 9]; - - unsigned i = 0, o = 0; - while(i < inlength) { - unsigned flagoffset = o++; - uint8_t flag = 0x00; - - for(unsigned b = 0; b < 8 && i < inlength; b++) { - unsigned longest = 0, pointer; - for(unsigned index = 1; index < 4096; index++) { - unsigned count = 0; - while(true) { - if(count >= 15 + 3) break; //verify pattern match is not longer than max length - if(i + count >= inlength) break; //verify pattern match does not read past end of input - if(i + count < index) break; //verify read is not before start of input - if(input[i + count] != input[i + count - index]) break; //verify pattern still matches - count++; - } - - if(count > longest) { - longest = count; - pointer = index; - } - } - - if(longest < 3) output[o++] = input[i++]; - else { - flag |= 1 << b; - uint16_t x = ((longest - 3) << 12) + pointer; - output[o++] = x; - output[o++] = x >> 8; - i += longest; - } - } - - output[flagoffset] = flag; - } - - outlength = o; - return true; - } - - static bool decode(uint8_t *&output, const uint8_t *input, unsigned length) { - output = new(zeromemory) uint8_t[length]; - - unsigned i = 0, o = 0; - while(o < length) { - uint8_t flag = input[i++]; - - for(unsigned b = 0; b < 8 && o < length; b++) { - if(!(flag & (1 << b))) output[o++] = input[i++]; - else { - uint16_t offset = input[i++]; - offset += input[i++] << 8; - uint16_t lookuplength = (offset >> 12) + 3; - offset &= 4095; - for(unsigned index = 0; index < lookuplength && o + index < length; index++) { - output[o + index] = output[o + index - offset]; - } - o += lookuplength; - } - } - } - - return true; - } - }; -} - -#endif diff --git a/snesfilter/nall/moduloarray.hpp b/snesfilter/nall/moduloarray.hpp deleted file mode 100644 index be549ae9..00000000 --- a/snesfilter/nall/moduloarray.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef NALL_MODULO_HPP -#define NALL_MODULO_HPP - -#include - -namespace nall { - template class modulo_array { - public: - inline T operator[](int index) const { - return buffer[size + index]; - } - - inline T read(int index) const { - return buffer[size + index]; - } - - inline void write(unsigned index, const T value) { - buffer[index] = - buffer[index + size] = - buffer[index + size + size] = value; - } - - void serialize(serializer &s) { - s.array(buffer, size * 3); - } - - modulo_array() { - buffer = new T[size * 3](); - } - - ~modulo_array() { - delete[] buffer; - } - - private: - T *buffer; - }; -} - -#endif diff --git a/snesfilter/nall/platform.hpp b/snesfilter/nall/platform.hpp deleted file mode 100644 index 68ed37ce..00000000 --- a/snesfilter/nall/platform.hpp +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef NALL_PLATFORM_HPP -#define NALL_PLATFORM_HPP - -#include - -//========================= -//standard platform headers -//========================= - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(_WIN32) - #include - #include - #include - #undef interface -#else - #include - #include - #include -#endif - -//================== -//warning supression -//================== - -//Visual C++ -#if defined(_MSC_VER) - //disable libc "deprecation" warnings - #pragma warning(disable:4996) -#endif - -//================ -//POSIX compliance -//================ - -#if defined(_MSC_VER) - #define PATH_MAX _MAX_PATH - #define va_copy(dest, src) ((dest) = (src)) -#endif - -#if defined(_WIN32) - #define getcwd _getcwd - #define ftruncate _chsize - #define putenv _putenv - #define mkdir(n, m) _wmkdir(nall::utf16_t(n)) - #define rmdir _rmdir - #define vsnprintf _vsnprintf - #define usleep(n) Sleep(n / 1000) -#endif - -//================ -//inline expansion -//================ - -#if defined(__GNUC__) - #define noinline __attribute__((noinline)) - #define inline inline - #define alwaysinline inline __attribute__((always_inline)) -#elif defined(_MSC_VER) - #define noinline __declspec(noinline) - #define inline inline - #define alwaysinline inline __forceinline -#else - #define noinline - #define inline inline - #define alwaysinline inline -#endif - -#endif - diff --git a/snesfilter/nall/priorityqueue.hpp b/snesfilter/nall/priorityqueue.hpp deleted file mode 100644 index 7104e791..00000000 --- a/snesfilter/nall/priorityqueue.hpp +++ /dev/null @@ -1,109 +0,0 @@ -#ifndef NALL_PRIORITYQUEUE_HPP -#define NALL_PRIORITYQUEUE_HPP - -#include -#include -#include -#include - -namespace nall { - template void priority_queue_nocallback(type_t) {} - - //priority queue implementation using binary min-heap array; - //does not require normalize() function. - //O(1) find (tick) - //O(log n) insert (enqueue) - //O(log n) remove (dequeue) - template class priority_queue { - public: - inline void tick(unsigned ticks) { - basecounter += ticks; - while(heapsize && gte(basecounter, heap[0].counter)) callback(dequeue()); - } - - //counter is relative to current time (eg enqueue(64, ...) fires in 64 ticks); - //counter cannot exceed std::numeric_limits::max() >> 1. - void enqueue(unsigned counter, type_t event) { - unsigned child = heapsize++; - counter += basecounter; - - while(child) { - unsigned parent = (child - 1) >> 1; - if(gte(counter, heap[parent].counter)) break; - - heap[child].counter = heap[parent].counter; - heap[child].event = heap[parent].event; - child = parent; - } - - heap[child].counter = counter; - heap[child].event = event; - } - - type_t dequeue() { - type_t event(heap[0].event); - unsigned parent = 0; - unsigned counter = heap[--heapsize].counter; - - while(true) { - unsigned child = (parent << 1) + 1; - if(child >= heapsize) break; - if(child + 1 < heapsize && gte(heap[child].counter, heap[child + 1].counter)) child++; - if(gte(heap[child].counter, counter)) break; - - heap[parent].counter = heap[child].counter; - heap[parent].event = heap[child].event; - parent = child; - } - - heap[parent].counter = counter; - heap[parent].event = heap[heapsize].event; - return event; - } - - void reset() { - basecounter = 0; - heapsize = 0; - } - - void serialize(serializer &s) { - s.integer(basecounter); - s.integer(heapsize); - for(unsigned n = 0; n < heapcapacity; n++) { - s.integer(heap[n].counter); - s.integer(heap[n].event); - } - } - - priority_queue(unsigned size, function callback_ = &priority_queue_nocallback) - : callback(callback_) { - heap = new heap_t[size]; - heapcapacity = size; - reset(); - } - - ~priority_queue() { - delete[] heap; - } - - priority_queue& operator=(const priority_queue&) = delete; - priority_queue(const priority_queue&) = delete; - - private: - function callback; - unsigned basecounter; - unsigned heapsize; - unsigned heapcapacity; - struct heap_t { - unsigned counter; - type_t event; - } *heap; - - //return true if x is greater than or equal to y - inline bool gte(unsigned x, unsigned y) { - return x - y < (std::numeric_limits::max() >> 1); - } - }; -} - -#endif diff --git a/snesfilter/nall/property.hpp b/snesfilter/nall/property.hpp deleted file mode 100644 index 6fd33acd..00000000 --- a/snesfilter/nall/property.hpp +++ /dev/null @@ -1,91 +0,0 @@ -#ifndef NALL_PROPERTY_HPP -#define NALL_PROPERTY_HPP - -//nall::property implements ownership semantics into container classes -//example: property::readonly implies that only owner has full -//access to type; and all other code has readonly access. -// -//this code relies on extended friend semantics from C++0x to work, as it -//declares a friend class via a template paramter. it also exploits a bug in -//G++ 4.x to work even in C++98 mode. -// -//if compiling elsewhere, simply remove the friend class and private semantics - -//property can be used either of two ways: -//struct foo { -// property::readonly x; -// property::readwrite y; -//}; -//-or- -//struct foo : property { -// readonly x; -// readwrite y; -//}; - -//return types are const T& (byref) instead fo T (byval) to avoid major speed -//penalties for objects with expensive copy constructors - -//operator-> provides access to underlying object type: -//readonly foo; -//foo->bar(); -//... will call Object::bar(); - -//operator='s reference is constant so as to avoid leaking a reference handle -//that could bypass access restrictions - -//both constant and non-constant operators are provided, though it may be -//necessary to cast first, for instance: -//struct foo : property { readonly bar; } object; -//int main() { int value = const_cast(object); } - -//writeonly is useful for objects that have non-const reads, but const writes. -//however, to avoid leaking handles, the interface is very restricted. the only -//way to write is via operator=, which requires conversion via eg copy -//constructor. example: -//struct foo { -// foo(bool value) { ... } -//}; -//writeonly bar; -//bar = true; - -namespace nall { - template struct property { - template struct traits { typedef T type; }; - - template struct readonly { - const T* operator->() const { return &value; } - const T& operator()() const { return value; } - operator const T&() const { return value; } - private: - T* operator->() { return &value; } - operator T&() { return value; } - const T& operator=(const T& value_) { return value = value_; } - T value; - friend class traits::type; - }; - - template struct writeonly { - void operator=(const T& value_) { value = value_; } - private: - const T* operator->() const { return &value; } - const T& operator()() const { return value; } - operator const T&() const { return value; } - T* operator->() { return &value; } - operator T&() { return value; } - T value; - friend class traits::type; - }; - - template struct readwrite { - const T* operator->() const { return &value; } - const T& operator()() const { return value; } - operator const T&() const { return value; } - T* operator->() { return &value; } - operator T&() { return value; } - const T& operator=(const T& value_) { return value = value_; } - T value; - }; - }; -} - -#endif diff --git a/snesfilter/nall/qt/Makefile b/snesfilter/nall/qt/Makefile deleted file mode 100644 index 69e84960..00000000 --- a/snesfilter/nall/qt/Makefile +++ /dev/null @@ -1,55 +0,0 @@ -# requires nall/Makefile - -# imports: -# $(qtlibs) -- list of Qt components to link against - -# exports the following symbols: -# $(moc) -- meta-object compiler -# $(rcc) -- resource compiler -# $(qtinc) -- includes for compiling -# $(qtlib) -- libraries for linking - -ifeq ($(moc),) -moc := moc -endif - -ifeq ($(rcc),) -rcc := rcc -endif - -ifeq ($(platform),x) - qtinc := `pkg-config --cflags $(qtlibs)` - qtlib := `pkg-config --libs $(qtlibs)` -else ifeq ($(platform),osx) - qtinc := $(foreach lib,$(qtlibs),-I/Library/Frameworks/$(lib).framework/Versions/4/Headers) - - qtlib := -L/Library/Frameworks - qtlib += $(foreach lib,$(qtlibs),-framework $(lib)) - qtlib += -framework Carbon - qtlib += -framework Cocoa - qtlib += -framework OpenGL - qtlib += -framework AppKit - qtlib += -framework ApplicationServices -else ifeq ($(platform),win) - ifeq ($(qtpath),) - # find Qt install directory from PATH environment variable - qtpath := $(foreach path,$(subst ;, ,$(PATH)),$(if $(wildcard $(path)/$(moc).exe),$(path))) - qtpath := $(strip $(qtpath)) - qtpath := $(subst \,/,$(qtpath)) - qtpath := $(patsubst %/bin,%,$(qtpath)) - endif - - qtinc := -I$(qtpath)/include - qtinc += $(foreach lib,$(qtlibs),-I$(qtpath)/include/$(lib)) - - qtlib := -L$(qtpath)/lib - qtlib += -L$(qtpath)/plugins/imageformats - - qtlib += $(foreach lib,$(qtlibs),-l$(lib)4) - qtlib += -lmingw32 -lqtmain -lcomdlg32 -loleaut32 -limm32 -lwinmm - qtlib += -lwinspool -lmsimg32 -lole32 -ladvapi32 -lws2_32 -luuid -lgdi32 - qtlib += $(foreach lib,$(qtlibs),-l$(lib)4) - - # optional image-file support: - # qtlib += -lqjpeg -lqmng -endif diff --git a/snesfilter/nall/qt/check-action.moc.hpp b/snesfilter/nall/qt/check-action.moc.hpp deleted file mode 100644 index db378fe9..00000000 --- a/snesfilter/nall/qt/check-action.moc.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef NALL_QT_CHECKACTION_HPP -#define NALL_QT_CHECKACTION_HPP - -namespace nall { - -class CheckAction : public QAction { - Q_OBJECT - -public: - bool isChecked() const; - void setChecked(bool); - void toggleChecked(); - CheckAction(const QString&, QObject*); - -protected slots: - -protected: - bool checked; -}; - -inline bool CheckAction::isChecked() const { - return checked; -} - -inline void CheckAction::setChecked(bool checked_) { - checked = checked_; - if(checked) setIcon(QIcon(":/16x16/item-check-on.png")); - else setIcon(QIcon(":/16x16/item-check-off.png")); -} - -inline void CheckAction::toggleChecked() { - setChecked(!isChecked()); -} - -inline CheckAction::CheckAction(const QString &text, QObject *parent) : QAction(text, parent) { - setChecked(false); -} - -} - -#endif diff --git a/snesfilter/nall/qt/concept.hpp b/snesfilter/nall/qt/concept.hpp deleted file mode 100644 index 51cacef4..00000000 --- a/snesfilter/nall/qt/concept.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef NALL_QT_CONCEPT_HPP -#define NALL_QT_CONCEPT_HPP - -#include - -namespace nall { - template struct has_count> { enum { value = true }; }; -} - -#endif diff --git a/snesfilter/nall/qt/file-dialog.moc.hpp b/snesfilter/nall/qt/file-dialog.moc.hpp deleted file mode 100644 index bcccfaf5..00000000 --- a/snesfilter/nall/qt/file-dialog.moc.hpp +++ /dev/null @@ -1,392 +0,0 @@ -#ifndef NALL_QT_FILEDIALOG_HPP -#define NALL_QT_FILEDIALOG_HPP - -#include -#include -#include - -namespace nall { - -class FileDialog; - -class NewFolderDialog : public Window { - Q_OBJECT - -public: - void show(); - NewFolderDialog(FileDialog*); - -protected slots: - void createFolderAction(); - -protected: - FileDialog *parent; - QVBoxLayout *layout; - QLineEdit *folderNameEdit; - QHBoxLayout *controlLayout; - QPushButton *okButton; - QPushButton *cancelButton; -}; - -class FileView : public QListView { - Q_OBJECT - -protected: - void keyPressEvent(QKeyEvent*); - -signals: - void changed(const QModelIndex&); - void browseUp(); - -protected slots: - void currentChanged(const QModelIndex&, const QModelIndex&); -}; - -class FileDialog : public Window { - Q_OBJECT - -public: - void showLoad(); - void showSave(); - void showFolder(); - - void setPath(string path); - void setNameFilters(const string &filters); - FileDialog(); - -signals: - void changed(const string&); - void activated(const string&); - void accepted(const string&); - void rejected(); - -protected slots: - void fileViewChange(const QModelIndex&); - void fileViewActivate(const QModelIndex&); - void pathBoxChanged(); - void filterBoxChanged(); - void createNewFolder(); - void browseUp(); - void acceptAction(); - void rejectAction(); - -protected: - NewFolderDialog *newFolderDialog; - QVBoxLayout *layout; - QHBoxLayout *navigationLayout; - QComboBox *pathBox; - QPushButton *newFolderButton; - QPushButton *upFolderButton; - QHBoxLayout *browseLayout; - QFileSystemModel *fileSystemModel; - FileView *fileView; - QGroupBox *previewFrame; - QLineEdit *fileNameEdit; - QHBoxLayout *controlLayout; - QComboBox *filterBox; - QPushButton *optionsButton; - QPushButton *acceptButton; - QPushButton *rejectButton; - bool lock; - void createFolderAction(const string &name); - void closeEvent(QCloseEvent*); - - friend class NewFolderDialog; -}; - -inline void NewFolderDialog::show() { - folderNameEdit->setText(""); - Window::show(); - folderNameEdit->setFocus(); -} - -inline void NewFolderDialog::createFolderAction() { - string name = folderNameEdit->text().toUtf8().constData(); - if(name == "") { - folderNameEdit->setFocus(); - } else { - parent->createFolderAction(name); - close(); - } -} - -inline NewFolderDialog::NewFolderDialog(FileDialog *fileDialog) : parent(fileDialog) { - setMinimumWidth(240); - setWindowTitle("Create New Folder"); - - layout = new QVBoxLayout; - layout->setAlignment(Qt::AlignTop); - layout->setMargin(5); - layout->setSpacing(5); - setLayout(layout); - - folderNameEdit = new QLineEdit; - layout->addWidget(folderNameEdit); - - controlLayout = new QHBoxLayout; - controlLayout->setAlignment(Qt::AlignRight); - layout->addLayout(controlLayout); - - okButton = new QPushButton("Ok"); - controlLayout->addWidget(okButton); - - cancelButton = new QPushButton("Cancel"); - controlLayout->addWidget(cancelButton); - - connect(folderNameEdit, SIGNAL(returnPressed()), this, SLOT(createFolderAction())); - connect(okButton, SIGNAL(released()), this, SLOT(createFolderAction())); - connect(cancelButton, SIGNAL(released()), this, SLOT(close())); -} - -inline void FileView::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) { - QAbstractItemView::currentChanged(current, previous); - emit changed(current); -} - -inline void FileView::keyPressEvent(QKeyEvent *event) { - //enhance consistency: force OS X to act like Windows and Linux; enter = activate item - if(event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) { - emit activated(currentIndex()); - return; - } - - //simulate popular file manager behavior; backspace = go up one directory - if(event->key() == Qt::Key_Backspace) { - emit browseUp(); - return; - } - - //fallback: unrecognized keypresses get handled by the widget itself - QListView::keyPressEvent(event); -} - -inline void FileDialog::showLoad() { - acceptButton->setText("Load"); - fileNameEdit->hide(); - filterBox->show(); - show(); -} - -inline void FileDialog::showSave() { - acceptButton->setText("Save"); - fileNameEdit->show(); - filterBox->show(); - show(); -} - -inline void FileDialog::showFolder() { - acceptButton->setText("Choose"); - fileNameEdit->hide(); - filterBox->hide(); - setNameFilters("Folders ()"); - show(); -} - -inline void FileDialog::fileViewChange(const QModelIndex &index) { - string path = fileSystemModel->filePath(index).toUtf8().constData(); - if(path == fileSystemModel->rootPath().toUtf8().constData()) path = ""; - fileNameEdit->setText(notdir(path)); - emit changed(path); -} - -inline void FileDialog::fileViewActivate(const QModelIndex &index) { - string path = fileSystemModel->filePath(index).toUtf8().constData(); - if(fileSystemModel->isDir(index)) { - emit activated(path); - setPath(path); - } else { - emit activated(path); - close(); - } -} - -inline void FileDialog::pathBoxChanged() { - if(lock) return; - setPath(pathBox->currentText().toUtf8().constData()); -} - -inline void FileDialog::filterBoxChanged() { - if(lock) return; - string filters = filterBox->currentText().toUtf8().constData(); - if(filters.length() == 0) { - fileSystemModel->setNameFilters(QStringList() << "*"); - } else { - filters = substr(filters, strpos(filters, "(")); - ltrim(filters, "("); - rtrim(filters, ")"); - lstring part; - part.split(" ", filters); - QStringList list; - for(unsigned i = 0; i < part.size(); i++) list << part[i]; - fileSystemModel->setNameFilters(list); - } -} - -inline void FileDialog::createNewFolder() { - newFolderDialog->show(); -} - -inline void FileDialog::browseUp() { - if(pathBox->count() > 1) pathBox->setCurrentIndex(1); -} - -inline void FileDialog::setPath(string path) { - lock = true; - newFolderDialog->close(); - - if(QDir(path).exists()) { - newFolderButton->setEnabled(true); - } else { - newFolderButton->setEnabled(false); - path = ""; - } - - fileSystemModel->setRootPath(path); - fileView->setRootIndex(fileSystemModel->index(path)); - fileView->setCurrentIndex(fileView->rootIndex()); - fileView->setFocus(); - - pathBox->clear(); - if(path.length() > 0) { - QDir directory(path); - while(true) { - pathBox->addItem(directory.absolutePath()); - if(directory.isRoot()) break; - directory.cdUp(); - } - } - pathBox->addItem(""); - fileNameEdit->setText(""); - - lock = false; -} - -inline void FileDialog::setNameFilters(const string &filters) { - lock = true; - - lstring list; - list.split("\n", filters); - - filterBox->clear(); - for(unsigned i = 0; i < list.size(); i++) { - filterBox->addItem(list[i]); - } - - lock = false; - filterBoxChanged(); -} - -inline void FileDialog::acceptAction() { - string path = fileSystemModel->rootPath().toUtf8().constData(); - path << "/" << notdir(fileNameEdit->text().toUtf8().constData()); - rtrim(path, "/"); - if(QDir(path).exists()) { - emit accepted(path); - setPath(path); - } else { - emit accepted(path); - close(); - } -} - -inline void FileDialog::rejectAction() { - emit rejected(); - close(); -} - -inline void FileDialog::createFolderAction(const string &name) { - string path = fileSystemModel->rootPath().toUtf8().constData(); - path << "/" << notdir(name); - mkdir(path, 0755); -} - -inline void FileDialog::closeEvent(QCloseEvent *event) { - newFolderDialog->close(); - Window::closeEvent(event); -} - -inline FileDialog::FileDialog() { - newFolderDialog = new NewFolderDialog(this); - resize(640, 360); - - layout = new QVBoxLayout; - layout->setMargin(5); - layout->setSpacing(5); - setLayout(layout); - - navigationLayout = new QHBoxLayout; - layout->addLayout(navigationLayout); - - pathBox = new QComboBox; - pathBox->setEditable(true); - pathBox->setMinimumContentsLength(16); - pathBox->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLength); - pathBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); - navigationLayout->addWidget(pathBox); - - newFolderButton = new QPushButton; - newFolderButton->setIconSize(QSize(16, 16)); - newFolderButton->setIcon(QIcon(":/16x16/folder-new.png")); - navigationLayout->addWidget(newFolderButton); - - upFolderButton = new QPushButton; - upFolderButton->setIconSize(QSize(16, 16)); - upFolderButton->setIcon(QIcon(":/16x16/go-up.png")); - navigationLayout->addWidget(upFolderButton); - - browseLayout = new QHBoxLayout; - layout->addLayout(browseLayout); - - fileSystemModel = new QFileSystemModel; - fileSystemModel->setFilter(QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot); - fileSystemModel->setNameFilterDisables(false); - - fileView = new FileView; - fileView->setMinimumWidth(320); - fileView->setModel(fileSystemModel); - fileView->setIconSize(QSize(16, 16)); - browseLayout->addWidget(fileView); - - previewFrame = new QGroupBox; - previewFrame->hide(); - browseLayout->addWidget(previewFrame); - - fileNameEdit = new QLineEdit; - layout->addWidget(fileNameEdit); - - controlLayout = new QHBoxLayout; - controlLayout->setAlignment(Qt::AlignRight); - layout->addLayout(controlLayout); - - filterBox = new QComboBox; - filterBox->setMinimumContentsLength(16); - filterBox->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLength); - filterBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); - controlLayout->addWidget(filterBox); - - optionsButton = new QPushButton("Options"); - optionsButton->hide(); - controlLayout->addWidget(optionsButton); - - acceptButton = new QPushButton("Ok"); - controlLayout->addWidget(acceptButton); - - rejectButton = new QPushButton("Cancel"); - controlLayout->addWidget(rejectButton); - - lock = false; - connect(pathBox, SIGNAL(currentIndexChanged(int)), this, SLOT(pathBoxChanged())); - connect(newFolderButton, SIGNAL(released()), this, SLOT(createNewFolder())); - connect(upFolderButton, SIGNAL(released()), this, SLOT(browseUp())); - connect(fileView, SIGNAL(changed(const QModelIndex&)), this, SLOT(fileViewChange(const QModelIndex&))); - connect(fileView, SIGNAL(activated(const QModelIndex&)), this, SLOT(fileViewActivate(const QModelIndex&))); - connect(fileView, SIGNAL(browseUp()), this, SLOT(browseUp())); - connect(fileNameEdit, SIGNAL(returnPressed()), this, SLOT(acceptAction())); - connect(filterBox, SIGNAL(currentIndexChanged(int)), this, SLOT(filterBoxChanged())); - connect(acceptButton, SIGNAL(released()), this, SLOT(acceptAction())); - connect(rejectButton, SIGNAL(released()), this, SLOT(rejectAction())); -} - -} - -#endif diff --git a/snesfilter/nall/qt/hex-editor.moc.hpp b/snesfilter/nall/qt/hex-editor.moc.hpp deleted file mode 100644 index d59f4be9..00000000 --- a/snesfilter/nall/qt/hex-editor.moc.hpp +++ /dev/null @@ -1,173 +0,0 @@ -#ifndef NALL_QT_HEXEDITOR_HPP -#define NALL_QT_HEXEDITOR_HPP - -#include -#include -#include - -namespace nall { - -class HexEditor : public QTextEdit { - Q_OBJECT - -public: - function reader; - function writer; - - void setColumns(unsigned columns); - void setRows(unsigned rows); - void setOffset(unsigned offset); - void setSize(unsigned size); - unsigned lineWidth() const; - void refresh(); - - HexEditor(); - -protected slots: - void scrolled(); - -protected: - QHBoxLayout *layout; - QScrollBar *scrollBar; - unsigned editorColumns; - unsigned editorRows; - unsigned editorOffset; - unsigned editorSize; - bool lock; - - void keyPressEvent(QKeyEvent*); -}; - -inline void HexEditor::keyPressEvent(QKeyEvent *event) { - QTextCursor cursor = textCursor(); - unsigned x = cursor.position() % lineWidth(); - unsigned y = cursor.position() / lineWidth(); - - int hexCode = -1; - switch(event->key()) { - case Qt::Key_0: hexCode = 0; break; - case Qt::Key_1: hexCode = 1; break; - case Qt::Key_2: hexCode = 2; break; - case Qt::Key_3: hexCode = 3; break; - case Qt::Key_4: hexCode = 4; break; - case Qt::Key_5: hexCode = 5; break; - case Qt::Key_6: hexCode = 6; break; - case Qt::Key_7: hexCode = 7; break; - case Qt::Key_8: hexCode = 8; break; - case Qt::Key_9: hexCode = 9; break; - case Qt::Key_A: hexCode = 10; break; - case Qt::Key_B: hexCode = 11; break; - case Qt::Key_C: hexCode = 12; break; - case Qt::Key_D: hexCode = 13; break; - case Qt::Key_E: hexCode = 14; break; - case Qt::Key_F: hexCode = 15; break; - } - - if(cursor.hasSelection() == false && hexCode != -1) { - bool cursorOffsetValid = (x >= 11 && ((x - 11) % 3) != 2); - if(cursorOffsetValid) { - bool nibble = (x - 11) % 3; //0 = top nibble, 1 = bottom nibble - unsigned cursorOffset = y * editorColumns + ((x - 11) / 3); - unsigned effectiveOffset = editorOffset + cursorOffset; - if(effectiveOffset >= editorSize) effectiveOffset %= editorSize; - - uint8_t data = reader ? reader(effectiveOffset) : 0x00; - data &= (nibble == 0 ? 0x0f : 0xf0); - data |= (nibble == 0 ? (hexCode << 4) : (hexCode << 0)); - if(writer) writer(effectiveOffset, data); - refresh(); - - cursor.setPosition(y * lineWidth() + x + 1); //advance cursor - setTextCursor(cursor); - } - } else { - //allow navigation keys to move cursor, but block text input - setTextInteractionFlags(Qt::TextSelectableByKeyboard | Qt::TextSelectableByMouse); - QTextEdit::keyPressEvent(event); - setTextInteractionFlags(Qt::TextEditorInteraction); - } -} - -inline void HexEditor::setColumns(unsigned columns) { - editorColumns = columns; -} - -inline void HexEditor::setRows(unsigned rows) { - editorRows = rows; - scrollBar->setPageStep(editorRows); -} - -inline void HexEditor::setOffset(unsigned offset) { - lock = true; - editorOffset = offset; - scrollBar->setSliderPosition(editorOffset / editorColumns); - lock = false; -} - -inline void HexEditor::setSize(unsigned size) { - editorSize = size; - bool indivisible = (editorSize % editorColumns) != 0; //add one for incomplete row - scrollBar->setRange(0, editorSize / editorColumns + indivisible - editorRows); -} - -inline unsigned HexEditor::lineWidth() const { - return 11 + 3 * editorColumns; -} - -inline void HexEditor::refresh() { - string output; - char temp[256]; - unsigned offset = editorOffset; - - for(unsigned y = 0; y < editorRows; y++) { - if(offset >= editorSize) break; - sprintf(temp, "%.4x:%.4x", (offset >> 16) & 0xffff, (offset >> 0) & 0xffff); - output << "" << temp << "  "; - - for(unsigned x = 0; x < editorColumns; x++) { - if(offset >= editorSize) break; - sprintf(temp, "%.2x", reader ? reader(offset) : 0x00); - offset++; - output << "" << temp << ""; - if(x != (editorColumns - 1)) output << " "; - } - - if(y != (editorRows - 1)) output << "
"; - } - - setHtml(output); -} - -inline void HexEditor::scrolled() { - if(lock) return; - unsigned offset = scrollBar->sliderPosition(); - editorOffset = offset * editorColumns; - refresh(); -} - -inline HexEditor::HexEditor() { - setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - - layout = new QHBoxLayout; - layout->setAlignment(Qt::AlignRight); - layout->setMargin(0); - layout->setSpacing(0); - setLayout(layout); - - scrollBar = new QScrollBar(Qt::Vertical); - scrollBar->setSingleStep(1); - layout->addWidget(scrollBar); - - lock = false; - connect(scrollBar, SIGNAL(actionTriggered(int)), this, SLOT(scrolled())); - - setColumns(16); - setRows(16); - setSize(0); - setOffset(0); -} - -} - -#endif diff --git a/snesfilter/nall/qt/radio-action.moc.hpp b/snesfilter/nall/qt/radio-action.moc.hpp deleted file mode 100644 index a2bbca48..00000000 --- a/snesfilter/nall/qt/radio-action.moc.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef NALL_QT_RADIOACTION_HPP -#define NALL_QT_RADIOACTION_HPP - -namespace nall { - -class RadioAction : public QAction { - Q_OBJECT - -public: - bool isChecked() const; - void setChecked(bool); - void toggleChecked(); - RadioAction(const QString&, QObject*); - -protected slots: - -protected: - bool checked; -}; - -inline bool RadioAction::isChecked() const { - return checked; -} - -inline void RadioAction::setChecked(bool checked_) { - checked = checked_; - if(checked) setIcon(QIcon(":/16x16/item-radio-on.png")); - else setIcon(QIcon(":/16x16/item-radio-off.png")); -} - -inline void RadioAction::toggleChecked() { - setChecked(!isChecked()); -} - -inline RadioAction::RadioAction(const QString &text, QObject *parent) : QAction(text, parent) { - setChecked(false); -} - -} - -#endif diff --git a/snesfilter/nall/qt/window.moc.hpp b/snesfilter/nall/qt/window.moc.hpp deleted file mode 100644 index 0d3bf390..00000000 --- a/snesfilter/nall/qt/window.moc.hpp +++ /dev/null @@ -1,105 +0,0 @@ -#ifndef NALL_QT_WINDOW_HPP -#define NALL_QT_WINDOW_HPP - -#include -#include - -namespace nall { - -class Window : public QWidget { - Q_OBJECT - -public: - void setGeometryString(string *geometryString); - void setCloseOnEscape(bool); - void show(); - void hide(); - void shrink(); - - Window(); - -protected slots: - -protected: - string *geometryString; - bool closeOnEscape; - void keyReleaseEvent(QKeyEvent *event); - void closeEvent(QCloseEvent *event); -}; - -inline void Window::setGeometryString(string *geometryString_) { - geometryString = geometryString_; - if(geometryString && isVisible() == false) { - uint8_t *data; - unsigned length; - base64::decode(data, length, *geometryString); - QByteArray array((const char*)data, length); - delete[] data; - restoreGeometry(array); - } -} - -inline void Window::setCloseOnEscape(bool value) { - closeOnEscape = value; -} - -inline void Window::show() { - if(geometryString && isVisible() == false) { - uint8_t *data; - unsigned length; - base64::decode(data, length, *geometryString); - QByteArray array((const char*)data, length); - delete[] data; - restoreGeometry(array); - } - QWidget::show(); - QApplication::processEvents(); - activateWindow(); - raise(); -} - -inline void Window::hide() { - if(geometryString && isVisible() == true) { - char *data; - QByteArray geometry = saveGeometry(); - base64::encode(data, (const uint8_t*)geometry.data(), geometry.length()); - *geometryString = data; - delete[] data; - } - QWidget::hide(); -} - -inline void Window::shrink() { - if(isFullScreen()) return; - - for(unsigned i = 0; i < 2; i++) { - resize(0, 0); - usleep(2000); - QApplication::processEvents(); - } -} - -inline void Window::keyReleaseEvent(QKeyEvent *event) { - if(closeOnEscape && (event->key() == Qt::Key_Escape)) close(); - QWidget::keyReleaseEvent(event); -} - -inline void Window::closeEvent(QCloseEvent *event) { - if(geometryString) { - char *data; - QByteArray geometry = saveGeometry(); - base64::encode(data, (const uint8_t*)geometry.data(), geometry.length()); - *geometryString = data; - delete[] data; - } - QWidget::closeEvent(event); -} - -inline Window::Window() { - geometryString = 0; - closeOnEscape = true; -} - -} - -#endif diff --git a/snesfilter/nall/serial.hpp b/snesfilter/nall/serial.hpp deleted file mode 100644 index 6f5cf6d6..00000000 --- a/snesfilter/nall/serial.hpp +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef NALL_SERIAL_HPP -#define NALL_SERIAL_HPP - -#include -#include -#include -#include - -#include - -namespace nall { - class serial { - public: - //-1 on error, otherwise return bytes read - int read(uint8_t *data, unsigned length) { - if(port_open == false) return -1; - return ::read(port, (void*)data, length); - } - - //-1 on error, otherwise return bytes written - int write(const uint8_t *data, unsigned length) { - if(port_open == false) return -1; - return ::write(port, (void*)data, length); - } - - bool open(const char *portname, unsigned rate) { - close(); - - port = ::open(portname, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK); - if(port == -1) return false; - - if(ioctl(port, TIOCEXCL) == -1) { close(); return false; } - if(fcntl(port, F_SETFL, 0) == -1) { close(); return false; } - if(tcgetattr(port, &original_attr) == -1) { close(); return false; } - - termios attr = original_attr; - cfmakeraw(&attr); - cfsetspeed(&attr, rate); - - attr.c_lflag &=~ (ECHO | ECHONL | ISIG | ICANON | IEXTEN); - attr.c_iflag &=~ (BRKINT | PARMRK | INPCK | ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXOFF | IXANY); - attr.c_iflag |= (IGNBRK | IGNPAR); - attr.c_oflag &=~ (OPOST); - attr.c_cflag &=~ (CSIZE | CSTOPB | PARENB); - attr.c_cflag |= (CS8 | CREAD | CLOCAL); - attr.c_cc[VTIME] = attr.c_cc[VMIN] = 0; - - if(tcsetattr(port, TCSANOW, &attr) == -1) { close(); return false; } - return port_open = true; - } - - void close() { - if(port != -1) { - tcdrain(port); - if(port_open == true) { - tcsetattr(port, TCSANOW, &original_attr); - port_open = false; - } - ::close(port); - port = -1; - } - } - - serial() { - port = -1; - port_open = false; - } - - ~serial() { - close(); - } - - private: - int port; - bool port_open; - termios original_attr; - }; -} - -#endif diff --git a/snesfilter/nall/serializer.hpp b/snesfilter/nall/serializer.hpp deleted file mode 100644 index 9f816dfe..00000000 --- a/snesfilter/nall/serializer.hpp +++ /dev/null @@ -1,145 +0,0 @@ -#ifndef NALL_SERIALIZER_HPP -#define NALL_SERIALIZER_HPP - -#include -#include -#include -#include - -namespace nall { - //serializer: a class designed to save and restore the state of classes. - // - //benefits: - //- data() will be portable in size (it is not necessary to specify type sizes.) - //- data() will be portable in endianness (always stored internally as little-endian.) - //- one serialize function can both save and restore class states. - // - //caveats: - //- only plain-old-data can be stored. complex classes must provide serialize(serializer&); - //- floating-point usage is not portable across platforms - - class serializer { - public: - enum mode_t { Load, Save, Size }; - - mode_t mode() const { - return imode; - } - - const uint8_t* data() const { - return idata; - } - - unsigned size() const { - return isize; - } - - unsigned capacity() const { - return icapacity; - } - - template void floatingpoint(T &value) { - enum { size = sizeof(T) }; - //this is rather dangerous, and not cross-platform safe; - //but there is no standardized way to export FP-values - uint8_t *p = (uint8_t*)&value; - if(imode == Save) { - for(unsigned n = 0; n < size; n++) idata[isize++] = p[n]; - } else if(imode == Load) { - for(unsigned n = 0; n < size; n++) p[n] = idata[isize++]; - } else { - isize += size; - } - } - - template void integer(T &value) { - enum { size = std::is_same::value ? 1 : sizeof(T) }; - if(imode == Save) { - for(unsigned n = 0; n < size; n++) idata[isize++] = value >> (n << 3); - } else if(imode == Load) { - value = 0; - for(unsigned n = 0; n < size; n++) value |= idata[isize++] << (n << 3); - } else if(imode == Size) { - isize += size; - } - } - - template void array(T &array) { - enum { size = sizeof(T) / sizeof(typename std::remove_extent::type) }; - for(unsigned n = 0; n < size; n++) integer(array[n]); - } - - template void array(T array, unsigned size) { - for(unsigned n = 0; n < size; n++) integer(array[n]); - } - - //copy - serializer& operator=(const serializer &s) { - if(idata) delete[] idata; - - imode = s.imode; - idata = new uint8_t[s.icapacity]; - isize = s.isize; - icapacity = s.icapacity; - - memcpy(idata, s.idata, s.icapacity); - return *this; - } - - serializer(const serializer &s) : idata(0) { - operator=(s); - } - - //move - serializer& operator=(serializer &&s) { - if(idata) delete[] idata; - - imode = s.imode; - idata = s.idata; - isize = s.isize; - icapacity = s.icapacity; - - s.idata = 0; - return *this; - } - - serializer(serializer &&s) { - operator=(std::move(s)); - } - - //construction - serializer() { - imode = Size; - idata = 0; - isize = 0; - } - - serializer(unsigned capacity) { - imode = Save; - idata = new uint8_t[capacity](); - isize = 0; - icapacity = capacity; - } - - serializer(const uint8_t *data, unsigned capacity) { - imode = Load; - idata = new uint8_t[capacity]; - isize = 0; - icapacity = capacity; - memcpy(idata, data, capacity); - } - - ~serializer() { - if(idata) delete[] idata; - } - - private: - mode_t imode; - uint8_t *idata; - unsigned isize; - unsigned icapacity; - }; - -}; - -#endif diff --git a/snesfilter/nall/sha256.hpp b/snesfilter/nall/sha256.hpp deleted file mode 100644 index 7f41f04e..00000000 --- a/snesfilter/nall/sha256.hpp +++ /dev/null @@ -1,143 +0,0 @@ -#ifndef NALL_SHA256_HPP -#define NALL_SHA256_HPP - -//author: vladitx - -namespace nall { - #define PTR(t, a) ((t*)(a)) - - #define SWAP32(x) ((uint32_t)( \ - (((uint32_t)(x) & 0x000000ff) << 24) | \ - (((uint32_t)(x) & 0x0000ff00) << 8) | \ - (((uint32_t)(x) & 0x00ff0000) >> 8) | \ - (((uint32_t)(x) & 0xff000000) >> 24) \ - )) - - #define ST32(a, d) *PTR(uint32_t, a) = (d) - #define ST32BE(a, d) ST32(a, SWAP32(d)) - - #define LD32(a) *PTR(uint32_t, a) - #define LD32BE(a) SWAP32(LD32(a)) - - #define LSL32(x, n) ((uint32_t)(x) << (n)) - #define LSR32(x, n) ((uint32_t)(x) >> (n)) - #define ROR32(x, n) (LSR32(x, n) | LSL32(x, 32 - (n))) - - //first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19 - static const uint32_t T_H[8] = { - 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19, - }; - - //first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311 - static const uint32_t T_K[64] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, - }; - - struct sha256_ctx { - uint8_t in[64]; - unsigned inlen; - - uint32_t w[64]; - uint32_t h[8]; - uint64_t len; - }; - - void sha256_init(sha256_ctx *p) { - memset(p, 0, sizeof(sha256_ctx)); - memcpy(p->h, T_H, sizeof(T_H)); - } - - static void sha256_block(sha256_ctx *p) { - unsigned i; - uint32_t s0, s1; - uint32_t a, b, c, d, e, f, g, h; - uint32_t t1, t2, maj, ch; - - for(i = 0; i < 16; i++) p->w[i] = LD32BE(p->in + i * 4); - - for(i = 16; i < 64; i++) { - s0 = ROR32(p->w[i - 15], 7) ^ ROR32(p->w[i - 15], 18) ^ LSR32(p->w[i - 15], 3); - s1 = ROR32(p->w[i - 2], 17) ^ ROR32(p->w[i - 2], 19) ^ LSR32(p->w[i - 2], 10); - p->w[i] = p->w[i - 16] + s0 + p->w[i - 7] + s1; - } - - a = p->h[0]; b = p->h[1]; c = p->h[2]; d = p->h[3]; - e = p->h[4]; f = p->h[5]; g = p->h[6]; h = p->h[7]; - - for(i = 0; i < 64; i++) { - s0 = ROR32(a, 2) ^ ROR32(a, 13) ^ ROR32(a, 22); - maj = (a & b) ^ (a & c) ^ (b & c); - t2 = s0 + maj; - s1 = ROR32(e, 6) ^ ROR32(e, 11) ^ ROR32(e, 25); - ch = (e & f) ^ (~e & g); - t1 = h + s1 + ch + T_K[i] + p->w[i]; - - h = g; g = f; f = e; e = d + t1; - d = c; c = b; b = a; a = t1 + t2; - } - - p->h[0] += a; p->h[1] += b; p->h[2] += c; p->h[3] += d; - p->h[4] += e; p->h[5] += f; p->h[6] += g; p->h[7] += h; - - //next block - p->inlen = 0; - } - - void sha256_chunk(sha256_ctx *p, const uint8_t *s, unsigned len) { - unsigned l; - p->len += len; - - while(len) { - l = 64 - p->inlen; - l = (len < l) ? len : l; - - memcpy(p->in + p->inlen, s, l); - s += l; - p->inlen += l; - len -= l; - - if(p->inlen == 64) sha256_block(p); - } - } - - void sha256_final(sha256_ctx *p) { - uint64_t len; - p->in[p->inlen++] = 0x80; - - if(p->inlen > 56) { - memset(p->in + p->inlen, 0, 64 - p->inlen); - sha256_block(p); - } - - memset(p->in + p->inlen, 0, 56 - p->inlen); - - len = p->len << 3; - ST32BE(p->in + 56, len >> 32); - ST32BE(p->in + 60, len); - sha256_block(p); - } - - void sha256_hash(sha256_ctx *p, uint8_t *s) { - uint32_t *t = (uint32_t*)s; - for(unsigned i = 0; i < 8; i++) ST32BE(t++, p->h[i]); - } - - #undef PTR - #undef SWAP32 - #undef ST32 - #undef ST32BE - #undef LD32 - #undef LD32BE - #undef LSL32 - #undef LSR32 - #undef ROR32 -} - -#endif diff --git a/snesfilter/nall/sort.hpp b/snesfilter/nall/sort.hpp deleted file mode 100644 index 23c317a5..00000000 --- a/snesfilter/nall/sort.hpp +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef NALL_SORT_HPP -#define NALL_SORT_HPP - -#include - -//class: merge sort -//average: O(n log n) -//worst: O(n log n) -//memory: O(n) -//stack: O(log n) -//stable?: yes - -//notes: -//there are two primary reasons for choosing merge sort -//over the (usually) faster quick sort*: -//1: it is a stable sort. -//2: it lacks O(n^2) worst-case overhead. -//(* which is also O(n log n) in the average case.) - -namespace nall { - template - void sort(T list[], unsigned length) { - if(length <= 1) return; //nothing to sort - - //use insertion sort to quickly sort smaller blocks - if(length < 64) { - for(unsigned i = 0; i < length; i++) { - unsigned min = i; - for(unsigned j = i + 1; j < length; j++) { - if(list[j] < list[min]) min = j; - } - if(min != i) swap(list[i], list[min]); - } - return; - } - - //split list in half and recursively sort both - unsigned middle = length / 2; - sort(list, middle); - sort(list + middle, length - middle); - - //left and right are sorted here; perform merge sort - T *buffer = new T[length]; - unsigned offset = 0; - unsigned left = 0; - unsigned right = middle; - while(left < middle && right < length) { - if(list[left] < list[right]) { - buffer[offset++] = list[left++]; - } else { - buffer[offset++] = list[right++]; - } - } - while(left < middle) buffer[offset++] = list[left++]; - while(right < length) buffer[offset++] = list[right++]; - - for(unsigned i = 0; i < length; i++) list[i] = buffer[i]; - delete[] buffer; - } -} - -#endif diff --git a/snesfilter/nall/static.hpp b/snesfilter/nall/static.hpp deleted file mode 100644 index 4acb9fd0..00000000 --- a/snesfilter/nall/static.hpp +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef NALL_STATIC_HPP -#define NALL_STATIC_HPP - -namespace nall { - template struct static_if { typedef T type; }; - template struct static_if { typedef F type; }; - template struct mp_static_if { typedef typename static_if::type type; }; - - template struct static_and { enum { value = false }; }; - template<> struct static_and { enum { value = true }; }; - template struct mp_static_and { enum { value = static_and::value }; }; - - template struct static_or { enum { value = false }; }; - template<> struct static_or { enum { value = true }; }; - template<> struct static_or { enum { value = true }; }; - template<> struct static_or { enum { value = true }; }; - template struct mp_static_or { enum { value = static_or::value }; }; -} - -#endif diff --git a/snesfilter/nall/stdint.hpp b/snesfilter/nall/stdint.hpp deleted file mode 100644 index d8b6c788..00000000 --- a/snesfilter/nall/stdint.hpp +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef NALL_STDINT_HPP -#define NALL_STDINT_HPP - -#include - -#if defined(_MSC_VER) - typedef signed char int8_t; - typedef signed short int16_t; - typedef signed int int32_t; - typedef signed long long int64_t; - typedef int64_t intmax_t; - #if defined(_WIN64) - typedef int64_t intptr_t; - #else - typedef int32_t intptr_t; - #endif - - typedef unsigned char uint8_t; - typedef unsigned short uint16_t; - typedef unsigned int uint32_t; - typedef unsigned long long uint64_t; - typedef uint64_t uintmax_t; - #if defined(_WIN64) - typedef uint64_t uintptr_t; - #else - typedef uint32_t uintptr_t; - #endif -#else - #include -#endif - -namespace nall { - static_assert(sizeof(int8_t) == 1, "int8_t is not of the correct size" ); - static_assert(sizeof(int16_t) == 2, "int16_t is not of the correct size"); - static_assert(sizeof(int32_t) == 4, "int32_t is not of the correct size"); - static_assert(sizeof(int64_t) == 8, "int64_t is not of the correct size"); - - static_assert(sizeof(uint8_t) == 1, "int8_t is not of the correct size" ); - static_assert(sizeof(uint16_t) == 2, "int16_t is not of the correct size"); - static_assert(sizeof(uint32_t) == 4, "int32_t is not of the correct size"); - static_assert(sizeof(uint64_t) == 8, "int64_t is not of the correct size"); -} - -#endif diff --git a/snesfilter/nall/string.hpp b/snesfilter/nall/string.hpp deleted file mode 100644 index 65a4a4b8..00000000 --- a/snesfilter/nall/string.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef NALL_STRING_HPP -#define NALL_STRING_HPP - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace nall { - template<> struct has_length { enum { value = true }; }; - template<> struct has_size { enum { value = true }; }; -} - -#endif diff --git a/snesfilter/nall/string/base.hpp b/snesfilter/nall/string/base.hpp deleted file mode 100644 index 179a7dd4..00000000 --- a/snesfilter/nall/string/base.hpp +++ /dev/null @@ -1,137 +0,0 @@ -#ifndef NALL_STRING_BASE_HPP -#define NALL_STRING_BASE_HPP - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace nall { - class string; - template inline string to_string(T); - - class string { - public: - inline void reserve(unsigned); - inline unsigned length() const; - - inline string& assign(const char*); - inline string& append(const char*); - template inline string& operator= (T value); - template inline string& operator<<(T value); - - inline operator const char*() const; - inline char* operator()(); - inline char& operator[](int); - - inline bool operator==(const char*) const; - inline bool operator!=(const char*) const; - inline bool operator< (const char*) const; - inline bool operator<=(const char*) const; - inline bool operator> (const char*) const; - inline bool operator>=(const char*) const; - - inline string(); - inline string(const char*); - inline string(const string&); - inline string(string&&); - inline string& operator=(const string&); - inline string& operator=(string&&); - inline ~string(); - - inline bool readfile(const char*); - inline string& replace (const char*, const char*); - inline string& qreplace(const char*, const char*); - - protected: - char *data; - unsigned size; - - #if defined(QT_CORE_LIB) - public: - inline operator QString() const; - #endif - }; - - class lstring : public linear_vector { - public: - template inline lstring& operator<<(T value); - - inline int find(const char*); - inline void split (const char*, const char*, unsigned = 0); - inline void qsplit(const char*, const char*, unsigned = 0); - - lstring(); - lstring(std::initializer_list); - }; - - //compare.hpp - inline char chrlower(char c); - inline char chrupper(char c); - inline int stricmp(const char *dest, const char *src); - inline int strpos (const char *str, const char *key); - inline int qstrpos(const char *str, const char *key); - inline bool strbegin (const char *str, const char *key); - inline bool stribegin(const char *str, const char *key); - inline bool strend (const char *str, const char *key); - inline bool striend(const char *str, const char *key); - - //convert.hpp - inline char* strlower(char *str); - inline char* strupper(char *str); - inline char* strtr(char *dest, const char *before, const char *after); - inline uintmax_t strhex (const char *str); - inline intmax_t strsigned (const char *str); - inline uintmax_t strunsigned(const char *str); - inline uintmax_t strbin (const char *str); - inline double strdouble (const char *str); - - //match.hpp - inline bool match(const char *pattern, const char *str); - - //math.hpp - inline bool strint (const char *str, int &result); - inline bool strmath(const char *str, int &result); - - //strl.hpp - inline unsigned strlcpy(char *dest, const char *src, unsigned length); - inline unsigned strlcat(char *dest, const char *src, unsigned length); - - //trim.hpp - inline char* ltrim(char *str, const char *key = " "); - inline char* rtrim(char *str, const char *key = " "); - inline char* trim (char *str, const char *key = " "); - inline char* ltrim_once(char *str, const char *key = " "); - inline char* rtrim_once(char *str, const char *key = " "); - inline char* trim_once (char *str, const char *key = " "); - - //utility.hpp - inline unsigned strlcpy(string &dest, const char *src, unsigned length); - inline unsigned strlcat(string &dest, const char *src, unsigned length); - inline string substr(const char *src, unsigned start = 0, unsigned length = 0); - inline string& strlower(string &str); - inline string& strupper(string &str); - inline string& strtr(string &dest, const char *before, const char *after); - inline string& ltrim(string &str, const char *key = " "); - inline string& rtrim(string &str, const char *key = " "); - inline string& trim (string &str, const char *key = " "); - inline string& ltrim_once(string &str, const char *key = " "); - inline string& rtrim_once(string &str, const char *key = " "); - inline string& trim_once (string &str, const char *key = " "); - template inline string strhex(uintmax_t value); - template inline string strsigned(intmax_t value); - template inline string strunsigned(uintmax_t value); - template inline string strbin(uintmax_t value); - inline unsigned strdouble(char *str, double value); - inline string strdouble(double value); - - //variadic.hpp - template inline string sprint(Args... args); - template inline void print(Args... args); -}; - -#endif diff --git a/snesfilter/nall/string/cast.hpp b/snesfilter/nall/string/cast.hpp deleted file mode 100644 index 7b48eda0..00000000 --- a/snesfilter/nall/string/cast.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef NALL_STRING_CAST_HPP -#define NALL_STRING_CAST_HPP - -namespace nall { - -//this is needed, as C++0x does not support explicit template specialization inside classes -template<> inline string to_string (bool v) { return v ? "true" : "false"; } -template<> inline string to_string (signed int v) { return strsigned(v); } -template<> inline string to_string (unsigned int v) { return strunsigned(v); } -template<> inline string to_string (double v) { return strdouble(v); } -template<> inline string to_string (char *v) { return v; } -template<> inline string to_string (const char *v) { return v; } -template<> inline string to_string (string v) { return v; } -template<> inline string to_string(const string &v) { return v; } - -template string& string::operator= (T value) { return assign(to_string(value)); } -template string& string::operator<<(T value) { return append(to_string(value)); } - -template lstring& lstring::operator<<(T value) { - operator[](size()).assign(to_string(value)); - return *this; -} - -#if defined(QT_CORE_LIB) -template<> inline string to_string(QString v) { return v.toUtf8().constData(); } -template<> inline string to_string(const QString &v) { return v.toUtf8().constData(); } -string::operator QString() const { return QString::fromUtf8(*this); } -#endif - -} - -#endif diff --git a/snesfilter/nall/string/compare.hpp b/snesfilter/nall/string/compare.hpp deleted file mode 100644 index e1173de4..00000000 --- a/snesfilter/nall/string/compare.hpp +++ /dev/null @@ -1,104 +0,0 @@ -#ifndef NALL_STRING_COMPARE_HPP -#define NALL_STRING_COMPARE_HPP - -namespace nall { - -char chrlower(char c) { - return (c >= 'A' && c <= 'Z') ? c + ('a' - 'A') : c; -} - -char chrupper(char c) { - return (c >= 'a' && c <= 'z') ? c - ('a' - 'A') : c; -} - -int stricmp(const char *dest, const char *src) { - while(*dest) { - if(chrlower(*dest) != chrlower(*src)) break; - dest++; - src++; - } - - return (int)chrlower(*dest) - (int)chrlower(*src); -} - -int strpos(const char *str, const char *key) { - int ssl = strlen(str), ksl = strlen(key); - - if(ksl > ssl) return -1; - for(int i = 0; i <= ssl - ksl; i++) { - if(!memcmp(str + i, key, ksl)) { - return i; - } - } - return -1; -} - -int qstrpos(const char *str, const char *key) { - int ssl = strlen(str), ksl = strlen(key); - - if(ksl > ssl) return -1; - for(int i = 0; i <= ssl - ksl;) { - uint8_t x = str[i]; - if(x == '\"' || x == '\'') { - uint8_t z = i++; - while(str[i] != x && i < ssl) i++; - if(i >= ssl) i = z; - } - if(!memcmp(str + i, key, ksl)) { - return i; - } else { - i++; - } - } - return -1; -} - -bool strbegin(const char *str, const char *key) { - int i, ssl = strlen(str), ksl = strlen(key); - - if(ksl > ssl) return false; - return (!memcmp(str, key, ksl)); -} - -bool stribegin(const char *str, const char *key) { - int ssl = strlen(str), ksl = strlen(key); - - if(ksl > ssl) return false; - for(int i = 0; i < ksl; i++) { - if(str[i] >= 'A' && str[i] <= 'Z') { - if(str[i] != key[i] && str[i]+0x20 != key[i])return false; - } else if(str[i] >= 'a' && str[i] <= 'z') { - if(str[i] != key[i] && str[i]-0x20 != key[i])return false; - } else { - if(str[i] != key[i])return false; - } - } - return true; -} - -bool strend(const char *str, const char *key) { - int ssl = strlen(str), ksl = strlen(key); - - if(ksl > ssl) return false; - return (!memcmp(str + ssl - ksl, key, ksl)); -} - -bool striend(const char *str, const char *key) { - int ssl = strlen(str), ksl = strlen(key); - - if(ksl > ssl) return false; - for(int i = ssl - ksl, z = 0; i < ssl; i++, z++) { - if(str[i] >= 'A' && str[i] <= 'Z') { - if(str[i] != key[z] && str[i]+0x20 != key[z])return false; - } else if(str[i] >= 'a' && str[i] <= 'z') { - if(str[i] != key[z] && str[i]-0x20 != key[z])return false; - } else { - if(str[i] != key[z])return false; - } - } - return true; -} - -} - -#endif diff --git a/snesfilter/nall/string/convert.hpp b/snesfilter/nall/string/convert.hpp deleted file mode 100644 index 3ff134be..00000000 --- a/snesfilter/nall/string/convert.hpp +++ /dev/null @@ -1,153 +0,0 @@ -#ifndef NALL_STRING_CONVERT_HPP -#define NALL_STRING_CONVERT_HPP - -namespace nall { - -char* strlower(char *str) { - if(!str) return 0; - int i = 0; - while(str[i]) { - str[i] = chrlower(str[i]); - i++; - } - return str; -} - -char* strupper(char *str) { - if(!str) return 0; - int i = 0; - while(str[i]) { - str[i] = chrupper(str[i]); - i++; - } - return str; -} - -char* strtr(char *dest, const char *before, const char *after) { - if(!dest || !before || !after) return dest; - int sl = strlen(dest), bsl = strlen(before), asl = strlen(after); - - if(bsl != asl || bsl == 0) return dest; //patterns must be the same length for 1:1 replace - for(unsigned i = 0; i < sl; i++) { - for(unsigned l = 0; l < bsl; l++) { - if(dest[i] == before[l]) { - dest[i] = after[l]; - break; - } - } - } - - return dest; -} - -uintmax_t strhex(const char *str) { - if(!str) return 0; - uintmax_t result = 0; - - //skip hex identifiers 0x and $, if present - if(*str == '0' && (*(str + 1) == 'X' || *(str + 1) == 'x')) str += 2; - else if(*str == '$') str++; - - while(*str) { - uint8_t x = *str++; - if(x >= '0' && x <= '9') x -= '0'; - else if(x >= 'A' && x <= 'F') x -= 'A' - 10; - else if(x >= 'a' && x <= 'f') x -= 'a' - 10; - else break; //stop at first invalid character - result = result * 16 + x; - } - - return result; -} - -intmax_t strsigned(const char *str) { - if(!str) return 0; - intmax_t result = 0; - bool negate = false; - - //check for negation - if(*str == '-') { - negate = true; - str++; - } - - while(*str) { - uint8_t x = *str++; - if(x >= '0' && x <= '9') x -= '0'; - else break; //stop at first invalid character - result = result * 10 + x; - } - - return !negate ? result : -result; -} - -uintmax_t strunsigned(const char *str) { - if(!str) return 0; - uintmax_t result = 0; - - while(*str) { - uint8_t x = *str++; - if(x >= '0' && x <= '9') x -= '0'; - else break; //stop at first invalid character - result = result * 10 + x; - } - - return result; -} - -uintmax_t strbin(const char *str) { - if(!str) return 0; - uintmax_t result = 0; - - //skip bin identifiers 0b and %, if present - if(*str == '0' && (*(str + 1) == 'B' || *(str + 1) == 'b')) str += 2; - else if(*str == '%') str++; - - while(*str) { - uint8_t x = *str++; - if(x == '0' || x == '1') x -= '0'; - else break; //stop at first invalid character - result = result * 2 + x; - } - - return result; -} - -double strdouble(const char *str) { - if(!str) return 0.0; - bool negate = false; - - //check for negation - if(*str == '-') { - negate = true; - str++; - } - - intmax_t result_integral = 0; - while(*str) { - uint8_t x = *str++; - if(x >= '0' && x <= '9') x -= '0'; - else if(x == '.') break; //break loop and read fractional part - else return (double)result_integral; //invalid value, assume no fractional part - result_integral = result_integral * 10 + x; - } - - intmax_t result_fractional = 0; - while(*str) { - uint8_t x = *str++; - if(x >= '0' && x <= '9') x -= '0'; - else break; //stop at first invalid character - result_fractional = result_fractional * 10 + x; - } - - //calculate fractional portion - double result = (double)result_fractional; - while((uintmax_t)result > 0) result /= 10.0; - result += (double)result_integral; - - return !negate ? result : -result; -} - -} - -#endif diff --git a/snesfilter/nall/string/core.hpp b/snesfilter/nall/string/core.hpp deleted file mode 100644 index d13bfc38..00000000 --- a/snesfilter/nall/string/core.hpp +++ /dev/null @@ -1,133 +0,0 @@ -#ifndef NALL_STRING_CORE_HPP -#define NALL_STRING_CORE_HPP - -namespace nall { - -void string::reserve(unsigned size_) { - if(size_ > size) { - size = size_; - data = (char*)realloc(data, size + 1); - data[size] = 0; - } -} - -unsigned string::length() const { - return strlen(data); -} - -string& string::assign(const char *s) { - unsigned length = strlen(s); - reserve(length); - strcpy(data, s); - return *this; -} - -string& string::append(const char *s) { - unsigned length = strlen(data) + strlen(s); - reserve(length); - strcat(data, s); - return *this; -} - -string::operator const char*() const { - return data; -} - -char* string::operator()() { - return data; -} - -char& string::operator[](int index) { - reserve(index); - return data[index]; -} - -bool string::operator==(const char *str) const { return strcmp(data, str) == 0; } -bool string::operator!=(const char *str) const { return strcmp(data, str) != 0; } -bool string::operator< (const char *str) const { return strcmp(data, str) < 0; } -bool string::operator<=(const char *str) const { return strcmp(data, str) <= 0; } -bool string::operator> (const char *str) const { return strcmp(data, str) > 0; } -bool string::operator>=(const char *str) const { return strcmp(data, str) >= 0; } - -string::string() { - size = 64; - data = (char*)malloc(size + 1); - *data = 0; -} - -string::string(const char *value) { - size = strlen(value); - data = strdup(value); -} - -string::string(const string &value) { - size = strlen(value); - data = strdup(value); -} - -string::string(string &&source) { - size = source.size; - data = source.data; - source.data = 0; -} - -string& string::operator=(const string &value) { - assign(value); - return *this; -} - -string& string::operator=(string &&source) { - if(data) free(data); - size = source.size; - data = source.data; - source.data = 0; - source.size = 0; - return *this; -} - -string::~string() { - free(data); -} - -bool string::readfile(const char *filename) { - assign(""); - - #if !defined(_WIN32) - FILE *fp = fopen(filename, "rb"); - #else - FILE *fp = _wfopen(utf16_t(filename), L"rb"); - #endif - if(!fp) return false; - - fseek(fp, 0, SEEK_END); - unsigned size = ftell(fp); - rewind(fp); - char *fdata = new char[size + 1]; - unsigned unused = fread(fdata, 1, size, fp); - fclose(fp); - fdata[size] = 0; - assign(fdata); - delete[] fdata; - - return true; -} - -int lstring::find(const char *key) { - for(unsigned i = 0; i < size(); i++) { - if(operator[](i) == key) return i; - } - return -1; -} - -inline lstring::lstring() { -} - -inline lstring::lstring(std::initializer_list list) { - for(const string *s = list.begin(); s != list.end(); ++s) { - operator<<(*s); - } -} - -} - -#endif diff --git a/snesfilter/nall/string/filename.hpp b/snesfilter/nall/string/filename.hpp deleted file mode 100644 index f3750760..00000000 --- a/snesfilter/nall/string/filename.hpp +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef NALL_FILENAME_HPP -#define NALL_FILENAME_HPP - -namespace nall { - -// "foo/bar.c" -> "foo/", "bar.c" -> "./" -inline string dir(char const *name) { - string result = name; - for(signed i = strlen(result); i >= 0; i--) { - if(result[i] == '/' || result[i] == '\\') { - result[i + 1] = 0; - break; - } - if(i == 0) result = "./"; - } - return result; -} - -// "foo/bar.c" -> "bar.c" -inline string notdir(char const *name) { - for(signed i = strlen(name); i >= 0; i--) { - if(name[i] == '/' || name[i] == '\\') { - name += i + 1; - break; - } - } - string result = name; - return result; -} - -// "foo/bar.c" -> "foo/bar" -inline string basename(char const *name) { - string result = name; - for(signed i = strlen(result); i >= 0; i--) { - if(result[i] == '/' || result[i] == '\\') { - //file has no extension - break; - } - if(result[i] == '.') { - result[i] = 0; - break; - } - } - return result; -} - -// "foo/bar.c" -> "c" -inline string extension(char const *name) { - for(signed i = strlen(name); i >= 0; i--) { - if(name[i] == '.') { - name += i + 1; - break; - } - } - string result = name; - return result; -} - -} - -#endif diff --git a/snesfilter/nall/string/match.hpp b/snesfilter/nall/string/match.hpp deleted file mode 100644 index d8cf702d..00000000 --- a/snesfilter/nall/string/match.hpp +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef NALL_STRING_MATCH_HPP -#define NALL_STRING_MATCH_HPP - -namespace nall { - -bool match(const char *p, const char *s) { - const char *p_ = 0, *s_ = 0; - - for(;;) { - if(!*s) { - while(*p == '*') p++; - return !*p; - } - - //wildcard match - if(*p == '*') { - p_ = p++, s_ = s; - continue; - } - - //any match - if(*p == '?') { - p++, s++; - continue; - } - - //ranged match - if(*p == '{') { - #define pattern(name_, rule_) \ - if(strbegin(p, name_)) { \ - if(rule_) { \ - p += sizeof(name_) - 1, s++; \ - continue; \ - } \ - goto failure; \ - } - - pattern("{alpha}", (*s >= 'A' && *s <= 'Z') || (*s >= 'a' && *s <= 'z')) - pattern("{alphanumeric}", (*s >= 'A' && *s <= 'Z') || (*s >= 'a' && *s <= 'z') || (*s >= '0' && *s <= '9')) - pattern("{binary}", (*s == '0' || *s == '1')) - pattern("{hex}", (*s >= '0' && *s <= '9') || (*s >= 'A' && *s <= 'F') || (*s >= 'a' && *s <= 'f')) - pattern("{lowercase}", (*s >= 'a' && *s <= 'z')) - pattern("{numeric}", (*s >= '0' && *s <= '9')) - pattern("{uppercase}", (*s >= 'A' && *s <= 'Z')) - pattern("{whitespace}", (*s == ' ' || *s == '\t')) - - #undef pattern - goto failure; - } - - //reserved character match - if(*p == '\\') { - p++; - //fallthrough - } - - //literal match - if(*p == *s) { - p++, *s++; - continue; - } - - //attempt wildcard rematch - failure: - if(p_) { - p = p_, s = s_ + 1; - continue; - } - - return false; - } -} - -} - -#endif diff --git a/snesfilter/nall/string/math.hpp b/snesfilter/nall/string/math.hpp deleted file mode 100644 index ea8b99c8..00000000 --- a/snesfilter/nall/string/math.hpp +++ /dev/null @@ -1,164 +0,0 @@ -#ifndef NALL_STRING_MATH_HPP -#define NALL_STRING_MATH_HPP - -namespace nall { - -static int eval_integer(const char *&s) { - if(!*s) throw "unrecognized_integer"; - int value = 0, x = *s, y = *(s + 1); - - //hexadecimal - if(x == '0' && (y == 'X' || y == 'x')) { - s += 2; - while(true) { - if(*s >= '0' && *s <= '9') { value = value * 16 + (*s++ - '0'); continue; } - if(*s >= 'A' && *s <= 'F') { value = value * 16 + (*s++ - 'A' + 10); continue; } - if(*s >= 'a' && *s <= 'f') { value = value * 16 + (*s++ - 'a' + 10); continue; } - return value; - } - } - - //binary - if(x == '0' && (y == 'B' || y == 'b')) { - s += 2; - while(true) { - if(*s == '0' || *s == '1') { value = value * 2 + (*s++ - '0'); continue; } - return value; - } - } - - //octal (or decimal '0') - if(x == '0') { - s += 1; - while(true) { - if(*s >= '0' && *s <= '7') { value = value * 8 + (*s++ - '0'); continue; } - return value; - } - } - - //decimal - if(x >= '0' && x <= '9') { - while(true) { - if(*s >= '0' && *s <= '9') { value = value * 10 + (*s++ - '0'); continue; } - return value; - } - } - - //char - if(x == '\'' && y != '\'') { - s += 1; - while(true) { - value = value * 256 + *s++; - if(*s == '\'') { s += 1; return value; } - if(!*s) throw "mismatched_char"; - } - } - - throw "unrecognized_integer"; -} - -static int eval(const char *&s, int depth = 0) { - while(*s == ' ' || *s == '\t') s++; //trim whitespace - if(!*s) throw "unrecognized_token"; - int value = 0, x = *s, y = *(s + 1); - - if(*s == '(') { - value = eval(++s, 1); - if(*s++ != ')') throw "mismatched_group"; - } - - else if(x == '!') value = !eval(++s, 13); - else if(x == '~') value = ~eval(++s, 13); - else if(x == '+') value = +eval(++s, 13); - else if(x == '-') value = -eval(++s, 13); - - else if((x >= '0' && x <= '9') || x == '\'') value = eval_integer(s); - - else throw "unrecognized_token"; - - while(true) { - while(*s == ' ' || *s == '\t') s++; //trim whitespace - if(!*s) break; - x = *s, y = *(s + 1); - - if(depth >= 13) break; - if(x == '*') { value *= eval(++s, 13); continue; } - if(x == '/') { value /= eval(++s, 13); continue; } - if(x == '%') { value %= eval(++s, 13); continue; } - - if(depth >= 12) break; - if(x == '+') { value += eval(++s, 12); continue; } - if(x == '-') { value -= eval(++s, 12); continue; } - - if(depth >= 11) break; - if(x == '<' && y == '<') { value <<= eval(++++s, 11); continue; } - if(x == '>' && y == '>') { value >>= eval(++++s, 11); continue; } - - if(depth >= 10) break; - if(x == '<' && y == '=') { value = value <= eval(++++s, 10); continue; } - if(x == '>' && y == '=') { value = value >= eval(++++s, 10); continue; } - if(x == '<') { value = value < eval(++s, 10); continue; } - if(x == '>') { value = value > eval(++s, 10); continue; } - - if(depth >= 9) break; - if(x == '=' && y == '=') { value = value == eval(++++s, 9); continue; } - if(x == '!' && y == '=') { value = value != eval(++++s, 9); continue; } - - if(depth >= 8) break; - if(x == '&' && y != '&') { value = value & eval(++s, 8); continue; } - - if(depth >= 7) break; - if(x == '^' && y != '^') { value = value ^ eval(++s, 7); continue; } - - if(depth >= 6) break; - if(x == '|' && y != '|') { value = value | eval(++s, 6); continue; } - - if(depth >= 5) break; - if(x == '&' && y == '&') { value = eval(++++s, 5) && value; continue; } - - if(depth >= 4) break; - if(x == '^' && y == '^') { value = (!eval(++++s, 4) != !value); continue; } - - if(depth >= 3) break; - if(x == '|' && y == '|') { value = eval(++++s, 3) || value; continue; } - - if(x == '?') { - int lhs = eval(++s, 2); - if(*s != ':') throw "mismatched_ternary"; - int rhs = eval(++s, 2); - value = value ? lhs : rhs; - continue; - } - if(depth >= 2) break; - - if(depth > 0 && x == ')') break; - - throw "unrecognized_token"; - } - - return value; -} - -bool strint(const char *s, int &result) { - try { - result = eval_integer(s); - return true; - } catch(const char*) { - result = 0; - return false; - } -} - -bool strmath(const char *s, int &result) { - try { - result = eval(s); - return true; - } catch(const char*) { - result = 0; - return false; - } -} - -} - -#endif diff --git a/snesfilter/nall/string/replace.hpp b/snesfilter/nall/string/replace.hpp deleted file mode 100644 index db405a9b..00000000 --- a/snesfilter/nall/string/replace.hpp +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef NALL_STRING_REPLACE_HPP -#define NALL_STRING_REPLACE_HPP - -namespace nall { - -string& string::replace(const char *key, const char *token) { - int i, z, ksl = strlen(key), tsl = strlen(token), ssl = length(); - unsigned int replace_count = 0, size = ssl; - char *buffer; - - if(ksl <= ssl) { - if(tsl > ksl) { //the new string may be longer than the old string... - for(i = 0; i <= ssl - ksl;) { //so let's find out how big of a string we'll need... - if(!memcmp(data + i, key, ksl)) { - replace_count++; - i += ksl; - } else i++; - } - size = ssl + ((tsl - ksl) * replace_count); - reserve(size); - } - - buffer = new char[size + 1]; - for(i = z = 0; i < ssl;) { - if(i <= ssl - ksl) { - if(!memcmp(data + i, key, ksl)) { - memcpy(buffer + z, token, tsl); - z += tsl; - i += ksl; - } else buffer[z++] = data[i++]; - } else buffer[z++] = data[i++]; - } - buffer[z] = 0; - - assign(buffer); - delete[] buffer; - } - - return *this; -} - -string& string::qreplace(const char *key, const char *token) { - int i, l, z, ksl = strlen(key), tsl = strlen(token), ssl = length(); - unsigned int replace_count = 0, size = ssl; - uint8_t x; - char *buffer; - - if(ksl <= ssl) { - if(tsl > ksl) { - for(i = 0; i <= ssl - ksl;) { - x = data[i]; - if(x == '\"' || x == '\'') { - l = i; - i++; - while(data[i++] != x) { - if(i == ssl) { - i = l; - break; - } - } - } - if(!memcmp(data + i, key, ksl)) { - replace_count++; - i += ksl; - } else i++; - } - size = ssl + ((tsl - ksl) * replace_count); - reserve(size); - } - - buffer = new char[size + 1]; - for(i = z = 0; i < ssl;) { - x = data[i]; - if(x == '\"' || x == '\'') { - l = i++; - while(data[i] != x && i < ssl)i++; - if(i >= ssl)i = l; - else { - memcpy(buffer + z, data + l, i - l); - z += i - l; - } - } - if(i <= ssl - ksl) { - if(!memcmp(data + i, key, ksl)) { - memcpy(buffer + z, token, tsl); - z += tsl; - i += ksl; - replace_count++; - } else buffer[z++] = data[i++]; - } else buffer[z++] = data[i++]; - } - buffer[z] = 0; - - assign(buffer); - delete[] buffer; - } - - return *this; -} - -}; - -#endif diff --git a/snesfilter/nall/string/split.hpp b/snesfilter/nall/string/split.hpp deleted file mode 100644 index bb77dfcd..00000000 --- a/snesfilter/nall/string/split.hpp +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef NALL_STRING_SPLIT_HPP -#define NALL_STRING_SPLIT_HPP - -namespace nall { - -void lstring::split(const char *key, const char *src, unsigned limit) { - reset(); - - int ssl = strlen(src), ksl = strlen(key); - int lp = 0, split_count = 0; - - for(int i = 0; i <= ssl - ksl;) { - if(!memcmp(src + i, key, ksl)) { - strlcpy(operator[](split_count++), src + lp, i - lp + 1); - i += ksl; - lp = i; - if(!--limit) break; - } else i++; - } - - operator[](split_count++) = src + lp; -} - -void lstring::qsplit(const char *key, const char *src, unsigned limit) { - reset(); - - int ssl = strlen(src), ksl = strlen(key); - int lp = 0, split_count = 0; - - for(int i = 0; i <= ssl - ksl;) { - uint8_t x = src[i]; - - if(x == '\"' || x == '\'') { - int z = i++; //skip opening quote - while(i < ssl && src[i] != x) i++; - if(i >= ssl) i = z; //failed match, rewind i - else { - i++; //skip closing quote - continue; //restart in case next char is also a quote - } - } - - if(!memcmp(src + i, key, ksl)) { - strlcpy(operator[](split_count++), src + lp, i - lp + 1); - i += ksl; - lp = i; - if(!--limit) break; - } else i++; - } - - operator[](split_count++) = src + lp; -} - -}; - -#endif diff --git a/snesfilter/nall/string/strl.hpp b/snesfilter/nall/string/strl.hpp deleted file mode 100644 index 84c841fa..00000000 --- a/snesfilter/nall/string/strl.hpp +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef NALL_STRING_STRL_HPP -#define NALL_STRING_STRL_HPP - -namespace nall { - -//strlcpy, strlcat based on OpenBSD implementation by Todd C. Miller - -//return = strlen(src) -unsigned strlcpy(char *dest, const char *src, unsigned length) { - char *d = dest; - const char *s = src; - unsigned n = length; - - if(n) { - while(--n && (*d++ = *s++)); //copy as many bytes as possible, or until null terminator reached - } - - if(!n) { - if(length) *d = 0; - while(*s++); //traverse rest of s, so that s - src == strlen(src) - } - - return (s - src - 1); //return length of copied string, sans null terminator -} - -//return = strlen(src) + min(length, strlen(dest)) -unsigned strlcat(char *dest, const char *src, unsigned length) { - char *d = dest; - const char *s = src; - unsigned n = length; - - while(n-- && *d) d++; //find end of dest - unsigned dlength = d - dest; - n = length - dlength; //subtract length of dest from maximum string length - - if(!n) return dlength + strlen(s); - - while(*s) { - if(n != 1) { - *d++ = *s; - n--; - } - s++; - } - *d = 0; - - return dlength + (s - src); //return length of resulting string, sans null terminator -} - -} - -#endif diff --git a/snesfilter/nall/string/trim.hpp b/snesfilter/nall/string/trim.hpp deleted file mode 100644 index b13ab9ba..00000000 --- a/snesfilter/nall/string/trim.hpp +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef NALL_STRING_TRIM_HPP -#define NALL_STRING_TRIM_HPP - -namespace nall { - -char* ltrim(char *str, const char *key) { - if(!key || !*key) return str; - while(strbegin(str, key)) { - char *dest = str, *src = str + strlen(key); - while(true) { - *dest = *src++; - if(!*dest) break; - dest++; - } - } - return str; -} - -char* rtrim(char *str, const char *key) { - if(!key || !*key) return str; - while(strend(str, key)) str[strlen(str) - strlen(key)] = 0; - return str; -} - -char* trim(char *str, const char *key) { - return ltrim(rtrim(str, key), key); -} - -char* ltrim_once(char *str, const char *key) { - if(!key || !*key) return str; - if(strbegin(str, key)) { - char *dest = str, *src = str + strlen(key); - while(true) { - *dest = *src++; - if(!*dest) break; - dest++; - } - } - return str; -} - -char* rtrim_once(char *str, const char *key) { - if(!key || !*key) return str; - if(strend(str, key)) str[strlen(str) - strlen(key)] = 0; - return str; -} - -char* trim_once(char *str, const char *key) { - return ltrim_once(rtrim_once(str, key), key); -} - -} - -#endif diff --git a/snesfilter/nall/string/utility.hpp b/snesfilter/nall/string/utility.hpp deleted file mode 100644 index 2da2762b..00000000 --- a/snesfilter/nall/string/utility.hpp +++ /dev/null @@ -1,169 +0,0 @@ -#ifndef NALL_STRING_UTILITY_HPP -#define NALL_STRING_UTILITY_HPP - -namespace nall { - -unsigned strlcpy(string &dest, const char *src, unsigned length) { - dest.reserve(length); - return strlcpy(dest(), src, length); -} - -unsigned strlcat(string &dest, const char *src, unsigned length) { - dest.reserve(length); - return strlcat(dest(), src, length); -} - -string substr(const char *src, unsigned start, unsigned length) { - string dest; - if(length == 0) { - //copy entire string - dest = src + start; - } else { - //copy partial string - strlcpy(dest, src + start, length + 1); - } - return dest; -} - -/* very simplistic wrappers to return string& instead of char* type */ - -string& strlower(string &str) { strlower(str()); return str; } -string& strupper(string &str) { strupper(str()); return str; } -string& strtr(string &dest, const char *before, const char *after) { strtr(dest(), before, after); return dest; } -string& ltrim(string &str, const char *key) { ltrim(str(), key); return str; } -string& rtrim(string &str, const char *key) { rtrim(str(), key); return str; } -string& trim (string &str, const char *key) { trim (str(), key); return str; } -string& ltrim_once(string &str, const char *key) { ltrim_once(str(), key); return str; } -string& rtrim_once(string &str, const char *key) { rtrim_once(str(), key); return str; } -string& trim_once (string &str, const char *key) { trim_once (str(), key); return str; } - -/* arithmetic <> string */ - -template string strhex(uintmax_t value) { - string output; - unsigned offset = 0; - - //render string backwards, as we do not know its length yet - do { - unsigned n = value & 15; - output[offset++] = n < 10 ? '0' + n : 'a' + n - 10; - value >>= 4; - } while(value); - - while(offset < length) output[offset++] = padding; - output[offset--] = 0; - - //reverse the string in-place - for(unsigned i = 0; i < (offset + 1) >> 1; i++) { - char temp = output[i]; - output[i] = output[offset - i]; - output[offset - i] = temp; - } - - return output; -} - -template string strsigned(intmax_t value) { - string output; - unsigned offset = 0; - - bool negative = value < 0; - if(negative) value = abs(value); - - do { - unsigned n = value % 10; - output[offset++] = '0' + n; - value /= 10; - } while(value); - - while(offset < length) output[offset++] = padding; - if(negative) output[offset++] = '-'; - output[offset--] = 0; - - for(unsigned i = 0; i < (offset + 1) >> 1; i++) { - char temp = output[i]; - output[i] = output[offset - i]; - output[offset - i] = temp; - } - - return output; -} - -template string strunsigned(uintmax_t value) { - string output; - unsigned offset = 0; - - do { - unsigned n = value % 10; - output[offset++] = '0' + n; - value /= 10; - } while(value); - - while(offset < length) output[offset++] = padding; - output[offset--] = 0; - - for(unsigned i = 0; i < (offset + 1) >> 1; i++) { - char temp = output[i]; - output[i] = output[offset - i]; - output[offset - i] = temp; - } - - return output; -} - -template string strbin(uintmax_t value) { - string output; - unsigned offset = 0; - - do { - unsigned n = value & 1; - output[offset++] = '0' + n; - value >>= 1; - } while(value); - - while(offset < length) output[offset++] = padding; - output[offset--] = 0; - - for(unsigned i = 0; i < (offset + 1) >> 1; i++) { - char temp = output[i]; - output[i] = output[offset - i]; - output[offset - i] = temp; - } - - return output; -} - -//using sprintf is certainly not the most ideal method to convert -//a double to a string ... but attempting to parse a double by -//hand, digit-by-digit, results in subtle rounding errors. -unsigned strdouble(char *str, double value) { - char buffer[256]; - sprintf(buffer, "%f", value); - - //remove excess 0's in fraction (2.500000 -> 2.5) - for(char *p = buffer; *p; p++) { - if(*p == '.') { - char *p = buffer + strlen(buffer) - 1; - while(*p == '0') { - if(*(p - 1) != '.') *p = 0; //... but not for eg 1.0 -> 1. - p--; - } - break; - } - } - - unsigned length = strlen(buffer); - if(str) strcpy(str, buffer); - return length + 1; -} - -string strdouble(double value) { - string temp; - temp.reserve(strdouble(0, value)); - strdouble(temp(), value); - return temp; -} - -} - -#endif diff --git a/snesfilter/nall/string/variadic.hpp b/snesfilter/nall/string/variadic.hpp deleted file mode 100644 index 13c477a8..00000000 --- a/snesfilter/nall/string/variadic.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef NALL_STRING_VARIADIC_HPP -#define NALL_STRING_VARIADIC_HPP - -namespace nall { - -static void isprint(string &output) { -} - -template -static void isprint(string &output, T value, Args... args) { - output << to_string(value); - isprint(output, args...); -} - -template inline string sprint(Args... args) { - string output; - isprint(output, args...); - return output; -} - -template inline void print(Args... args) { - printf("%s", (const char*)sprint(args...)); -} - -} - -#endif diff --git a/snesfilter/nall/string/xml.hpp b/snesfilter/nall/string/xml.hpp deleted file mode 100644 index d423f87f..00000000 --- a/snesfilter/nall/string/xml.hpp +++ /dev/null @@ -1,257 +0,0 @@ -#ifndef NALL_STRING_XML_HPP -#define NALL_STRING_XML_HPP - -//XML subset parser -//version 0.05 - -namespace nall { - -struct xml_attribute { - string name; - string content; - virtual string parse() const; -}; - -struct xml_element : xml_attribute { - string parse() const; - linear_vector attribute; - linear_vector element; - -protected: - void parse_doctype(const char *&data); - bool parse_head(string data); - bool parse_body(const char *&data); - friend xml_element xml_parse(const char *data); -}; - -inline string xml_attribute::parse() const { - string data; - unsigned offset = 0; - - const char *source = content; - while(*source) { - if(*source == '&') { - if(strbegin(source, "<")) { data[offset++] = '<'; source += 4; continue; } - if(strbegin(source, ">")) { data[offset++] = '>'; source += 4; continue; } - if(strbegin(source, "&")) { data[offset++] = '&'; source += 5; continue; } - if(strbegin(source, "'")) { data[offset++] = '\''; source += 6; continue; } - if(strbegin(source, """)) { data[offset++] = '"'; source += 6; continue; } - } - - //reject illegal characters - if(*source == '&') return ""; - if(*source == '<') return ""; - if(*source == '>') return ""; - - data[offset++] = *source++; - } - - data[offset] = 0; - return data; -} - -inline string xml_element::parse() const { - string data; - unsigned offset = 0; - - const char *source = content; - while(*source) { - if(*source == '&') { - if(strbegin(source, "<")) { data[offset++] = '<'; source += 4; continue; } - if(strbegin(source, ">")) { data[offset++] = '>'; source += 4; continue; } - if(strbegin(source, "&")) { data[offset++] = '&'; source += 5; continue; } - if(strbegin(source, "'")) { data[offset++] = '\''; source += 6; continue; } - if(strbegin(source, """)) { data[offset++] = '"'; source += 6; continue; } - } - - if(strbegin(source, ""); - if(pos == -1) return ""; - source += pos + 3; - continue; - } - - if(strbegin(source, ""); - if(pos == -1) return ""; - string cdata = substr(source, 9, pos - 9); - data << cdata; - offset += strlen(cdata); - - source += offset + 3; - continue; - } - - //reject illegal characters - if(*source == '&') return ""; - if(*source == '<') return ""; - if(*source == '>') return ""; - - data[offset++] = *source++; - } - - data[offset] = 0; - return data; -} - -inline void xml_element::parse_doctype(const char *&data) { - name = "!DOCTYPE"; - const char *content_begin = data; - - signed counter = 0; - while(*data) { - char value = *data++; - if(value == '<') counter++; - if(value == '>') counter--; - if(counter < 0) { - content = substr(content_begin, 0, data - content_begin - 1); - return; - } - } - throw "..."; -} - -inline bool xml_element::parse_head(string data) { - data.qreplace("\t", " "); - data.qreplace("\r", " "); - data.qreplace("\n", " "); - while(qstrpos(data, " ") >= 0) data.qreplace(" ", " "); - data.qreplace(" =", "="); - data.qreplace("= ", "="); - rtrim(data); - - lstring part; - part.qsplit(" ", data); - - name = part[0]; - if(name == "") throw "..."; - - for(unsigned i = 1; i < part.size(); i++) { - lstring side; - side.qsplit("=", part[i]); - if(side.size() != 2) throw "..."; - - xml_attribute attr; - attr.name = side[0]; - attr.content = side[1]; - if(strbegin(attr.content, "\"") && strend(attr.content, "\"")) trim_once(attr.content, "\""); - else if(strbegin(attr.content, "'") && strend(attr.content, "'")) trim_once(attr.content, "'"); - else throw "..."; - attribute.add(attr); - } -} - -inline bool xml_element::parse_body(const char *&data) { - while(true) { - if(!*data) return false; - if(*data++ != '<') continue; - if(*data == '/') return false; - - if(strbegin(data, "!DOCTYPE") == true) { - parse_doctype(data); - return true; - } - - if(strbegin(data, "!--")) { - signed offset = strpos(data, "-->"); - if(offset == -1) throw "..."; - data += offset + 3; - continue; - } - - if(strbegin(data, "![CDATA[")) { - signed offset = strpos(data, "]]>"); - if(offset == -1) throw "..."; - data += offset + 3; - continue; - } - - signed offset = strpos(data, ">"); - if(offset == -1) throw "..."; - - string tag = substr(data, 0, offset); - data += offset + 1; - const char *content_begin = data; - - bool self_terminating = false; - - if(strend(tag, "?") == true) { - self_terminating = true; - rtrim_once(tag, "?"); - } else if(strend(tag, "/") == true) { - self_terminating = true; - rtrim_once(tag, "/"); - } - - parse_head(tag); - if(self_terminating) return true; - - while(*data) { - unsigned index = element.size(); - xml_element node; - if(node.parse_body(data) == false) { - if(*data == '/') { - signed length = data - content_begin - 1; - if(length > 0) content = substr(content_begin, 0, length); - - data++; - offset = strpos(data, ">"); - if(offset == -1) throw "..."; - - tag = substr(data, 0, offset); - data += offset + 1; - - tag.replace("\t", " "); - tag.replace("\r", " "); - tag.replace("\n", " "); - while(strpos(tag, " ") >= 0) tag.replace(" ", " "); - rtrim(tag); - - if(name != tag) throw "..."; - return true; - } - } else { - element.add(node); - } - } - } -} - -//ensure there is only one root element -inline bool xml_validate(xml_element &document) { - unsigned root_counter = 0; - - for(unsigned i = 0; i < document.element.size(); i++) { - string &name = document.element[i].name; - if(strbegin(name, "?")) continue; - if(strbegin(name, "!")) continue; - if(++root_counter > 1) return false; - } - - return true; -} - -inline xml_element xml_parse(const char *data) { - xml_element self; - - try { - while(*data) { - xml_element node; - if(node.parse_body(data) == false) { - break; - } else { - self.element.add(node); - } - } - - if(xml_validate(self) == false) throw "..."; - return self; - } catch(const char*) { - xml_element empty; - return empty; - } -} - -} - -#endif diff --git a/snesfilter/nall/ups.hpp b/snesfilter/nall/ups.hpp deleted file mode 100644 index f255ecb3..00000000 --- a/snesfilter/nall/ups.hpp +++ /dev/null @@ -1,190 +0,0 @@ -#ifndef NALL_UPS_HPP -#define NALL_UPS_HPP - -#include - -#include -#include -#include -#include - -namespace nall { - class ups { - public: - enum result { - ok, - patch_unreadable, - patch_unwritable, - patch_invalid, - input_invalid, - output_invalid, - patch_crc32_invalid, - input_crc32_invalid, - output_crc32_invalid, - }; - - ups::result create(const char *patch_fn, const uint8_t *x_data, unsigned x_size, const uint8_t *y_data, unsigned y_size) { - if(!fp.open(patch_fn, file::mode_write)) return patch_unwritable; - - crc32 = ~0; - uint32_t x_crc32 = crc32_calculate(x_data, x_size); - uint32_t y_crc32 = crc32_calculate(y_data, y_size); - - //header - write('U'); - write('P'); - write('S'); - write('1'); - encptr(x_size); - encptr(y_size); - - //body - unsigned max_size = max(x_size, y_size); - unsigned relative = 0; - for(unsigned i = 0; i < max_size;) { - uint8_t x = i < x_size ? x_data[i] : 0x00; - uint8_t y = i < y_size ? y_data[i] : 0x00; - - if(x == y) { - i++; - continue; - } - - encptr(i++ - relative); - write(x ^ y); - - while(true) { - if(i >= max_size) { - write(0x00); - break; - } - - x = i < x_size ? x_data[i] : 0x00; - y = i < y_size ? y_data[i] : 0x00; - i++; - write(x ^ y); - if(x == y) break; - } - - relative = i; - } - - //footer - for(unsigned i = 0; i < 4; i++) write(x_crc32 >> (i << 3)); - for(unsigned i = 0; i < 4; i++) write(y_crc32 >> (i << 3)); - uint32_t p_crc32 = ~crc32; - for(unsigned i = 0; i < 4; i++) write(p_crc32 >> (i << 3)); - - fp.close(); - return ok; - } - - ups::result apply(const uint8_t *p_data, unsigned p_size, const uint8_t *x_data, unsigned x_size, uint8_t *&y_data, unsigned &y_size) { - if(p_size < 18) return patch_invalid; - p_buffer = p_data; - - crc32 = ~0; - - //header - if(read() != 'U') return patch_invalid; - if(read() != 'P') return patch_invalid; - if(read() != 'S') return patch_invalid; - if(read() != '1') return patch_invalid; - - unsigned px_size = decptr(); - unsigned py_size = decptr(); - - //mirror - if(x_size != px_size && x_size != py_size) return input_invalid; - y_size = (x_size == px_size) ? py_size : px_size; - y_data = new uint8_t[y_size](); - - for(unsigned i = 0; i < x_size && i < y_size; i++) y_data[i] = x_data[i]; - for(unsigned i = x_size; i < y_size; i++) y_data[i] = 0x00; - - //body - unsigned relative = 0; - while(p_buffer < p_data + p_size - 12) { - relative += decptr(); - - while(true) { - uint8_t x = read(); - if(x && relative < y_size) { - uint8_t y = relative < x_size ? x_data[relative] : 0x00; - y_data[relative] = x ^ y; - } - relative++; - if(!x) break; - } - } - - //footer - unsigned px_crc32 = 0, py_crc32 = 0, pp_crc32 = 0; - for(unsigned i = 0; i < 4; i++) px_crc32 |= read() << (i << 3); - for(unsigned i = 0; i < 4; i++) py_crc32 |= read() << (i << 3); - uint32_t p_crc32 = ~crc32; - for(unsigned i = 0; i < 4; i++) pp_crc32 |= read() << (i << 3); - - uint32_t x_crc32 = crc32_calculate(x_data, x_size); - uint32_t y_crc32 = crc32_calculate(y_data, y_size); - - if(px_size != py_size) { - if(x_size == px_size && x_crc32 != px_crc32) return input_crc32_invalid; - if(x_size == py_size && x_crc32 != py_crc32) return input_crc32_invalid; - if(y_size == px_size && y_crc32 != px_crc32) return output_crc32_invalid; - if(y_size == py_size && y_crc32 != py_crc32) return output_crc32_invalid; - } else { - if(x_crc32 != px_crc32 && x_crc32 != py_crc32) return input_crc32_invalid; - if(y_crc32 != px_crc32 && y_crc32 != py_crc32) return output_crc32_invalid; - if(x_crc32 == y_crc32 && px_crc32 != py_crc32) return output_crc32_invalid; - if(x_crc32 != y_crc32 && px_crc32 == py_crc32) return output_crc32_invalid; - } - - if(p_crc32 != pp_crc32) return patch_crc32_invalid; - return ok; - } - - private: - file fp; - uint32_t crc32; - const uint8_t *p_buffer; - - uint8_t read() { - uint8_t n = *p_buffer++; - crc32 = crc32_adjust(crc32, n); - return n; - } - - void write(uint8_t n) { - fp.write(n); - crc32 = crc32_adjust(crc32, n); - } - - void encptr(uint64_t offset) { - while(true) { - uint64_t x = offset & 0x7f; - offset >>= 7; - if(offset == 0) { - write(0x80 | x); - break; - } - write(x); - offset--; - } - } - - uint64_t decptr() { - uint64_t offset = 0, shift = 1; - while(true) { - uint8_t x = read(); - offset += (x & 0x7f) * shift; - if(x & 0x80) break; - shift <<= 7; - offset += shift; - } - return offset; - } - }; -} - -#endif diff --git a/snesfilter/nall/utf8.hpp b/snesfilter/nall/utf8.hpp deleted file mode 100644 index c66c341a..00000000 --- a/snesfilter/nall/utf8.hpp +++ /dev/null @@ -1,72 +0,0 @@ -#ifndef NALL_UTF8_HPP -#define NALL_UTF8_HPP - -//UTF-8 <> UTF-16 conversion -//used only for Win32; Linux, etc use UTF-8 internally - -#if defined(_WIN32) - -#undef _WIN32_WINNT -#define _WIN32_WINNT 0x0501 -#undef NOMINMAX -#define NOMINMAX -#include -#undef interface - -namespace nall { - //UTF-8 to UTF-16 - class utf16_t { - public: - operator wchar_t*() { - return buffer; - } - - operator const wchar_t*() const { - return buffer; - } - - utf16_t(const char *s = "") { - if(!s) s = ""; - unsigned length = MultiByteToWideChar(CP_UTF8, 0, s, -1, 0, 0); - buffer = new wchar_t[length + 1](); - MultiByteToWideChar(CP_UTF8, 0, s, -1, buffer, length); - } - - ~utf16_t() { - delete[] buffer; - } - - private: - wchar_t *buffer; - }; - - //UTF-16 to UTF-8 - class utf8_t { - public: - operator char*() { - return buffer; - } - - operator const char*() const { - return buffer; - } - - utf8_t(const wchar_t *s = L"") { - if(!s) s = L""; - unsigned length = WideCharToMultiByte(CP_UTF8, 0, s, -1, 0, 0, (const char*)0, (BOOL*)0); - buffer = new char[length + 1](); - WideCharToMultiByte(CP_UTF8, 0, s, -1, buffer, length, (const char*)0, (BOOL*)0); - } - - ~utf8_t() { - delete[] buffer; - } - - private: - char *buffer; - }; -} - -#endif //if defined(_WIN32) - -#endif diff --git a/snesfilter/nall/utility.hpp b/snesfilter/nall/utility.hpp deleted file mode 100644 index 2a63f515..00000000 --- a/snesfilter/nall/utility.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef NALL_UTILITY_HPP -#define NALL_UTILITY_HPP - -#include -#include - -namespace nall { - template struct enable_if { typedef T type; }; - template struct enable_if {}; - template struct mp_enable_if : enable_if {}; - - template inline void swap(T &x, T &y) { - T temp(std::move(x)); - x = std::move(y); - y = std::move(temp); - } - - template struct base_from_member { - T value; - base_from_member(T value_) : value(value_) {} - }; - - template inline T* allocate(size_t size, const T &value) { - T *array = new T[size]; - for(size_t i = 0; i < size; i++) array[i] = value; - return array; - } -} - -#endif diff --git a/snesfilter/nall/varint.hpp b/snesfilter/nall/varint.hpp deleted file mode 100644 index cc3bb17c..00000000 --- a/snesfilter/nall/varint.hpp +++ /dev/null @@ -1,92 +0,0 @@ -#ifndef NALL_VARINT_HPP -#define NALL_VARINT_HPP - -#include -#include -#include - -namespace nall { - template class uint_t { - private: - enum { bytes = (bits + 7) >> 3 }; //minimum number of bytes needed to store value - typedef typename static_if< - sizeof(int) >= bytes, - unsigned int, - typename static_if< - sizeof(long) >= bytes, - unsigned long, - typename static_if< - sizeof(long long) >= bytes, - unsigned long long, - void - >::type - >::type - >::type T; - static_assert::value> uint_assert; - T data; - - public: - inline operator T() const { return data; } - inline T operator ++(int) { T r = data; data = uclip(data + 1); return r; } - inline T operator --(int) { T r = data; data = uclip(data - 1); return r; } - inline T operator ++() { return data = uclip(data + 1); } - inline T operator --() { return data = uclip(data - 1); } - inline T operator =(const T i) { return data = uclip(i); } - inline T operator |=(const T i) { return data = uclip(data | i); } - inline T operator ^=(const T i) { return data = uclip(data ^ i); } - inline T operator &=(const T i) { return data = uclip(data & i); } - inline T operator<<=(const T i) { return data = uclip(data << i); } - inline T operator>>=(const T i) { return data = uclip(data >> i); } - inline T operator +=(const T i) { return data = uclip(data + i); } - inline T operator -=(const T i) { return data = uclip(data - i); } - inline T operator *=(const T i) { return data = uclip(data * i); } - inline T operator /=(const T i) { return data = uclip(data / i); } - inline T operator %=(const T i) { return data = uclip(data % i); } - - inline uint_t() : data(0) {} - inline uint_t(const T i) : data(uclip(i)) {} - }; - - template class int_t { - private: - enum { bytes = (bits + 7) >> 3 }; //minimum number of bytes needed to store value - typedef typename static_if< - sizeof(int) >= bytes, - signed int, - typename static_if< - sizeof(long) >= bytes, - signed long, - typename static_if< - sizeof(long long) >= bytes, - signed long long, - void - >::type - >::type - >::type T; - static_assert::value> int_assert; - T data; - - public: - inline operator T() const { return data; } - inline T operator ++(int) { T r = data; data = sclip(data + 1); return r; } - inline T operator --(int) { T r = data; data = sclip(data - 1); return r; } - inline T operator ++() { return data = sclip(data + 1); } - inline T operator --() { return data = sclip(data - 1); } - inline T operator =(const T i) { return data = sclip(i); } - inline T operator |=(const T i) { return data = sclip(data | i); } - inline T operator ^=(const T i) { return data = sclip(data ^ i); } - inline T operator &=(const T i) { return data = sclip(data & i); } - inline T operator<<=(const T i) { return data = sclip(data << i); } - inline T operator>>=(const T i) { return data = sclip(data >> i); } - inline T operator +=(const T i) { return data = sclip(data + i); } - inline T operator -=(const T i) { return data = sclip(data - i); } - inline T operator *=(const T i) { return data = sclip(data * i); } - inline T operator /=(const T i) { return data = sclip(data / i); } - inline T operator %=(const T i) { return data = sclip(data % i); } - - inline int_t() : data(0) {} - inline int_t(const T i) : data(sclip(i)) {} - }; -} - -#endif diff --git a/snesfilter/nall/vector.hpp b/snesfilter/nall/vector.hpp deleted file mode 100644 index 3d69d4d5..00000000 --- a/snesfilter/nall/vector.hpp +++ /dev/null @@ -1,240 +0,0 @@ -#ifndef NALL_VECTOR_HPP -#define NALL_VECTOR_HPP - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace nall { - //linear_vector - //memory: O(capacity * 2) - // - //linear_vector uses placement new + manual destructor calls to create a - //contiguous block of memory for all objects. accessing individual elements - //is fast, though resizing the array incurs significant overhead. - //reserve() overhead is reduced from quadratic time to amortized constant time - //by resizing twice as much as requested. - // - //if objects hold memory address references to themselves (introspection), a - //valid copy constructor will be needed to keep pointers valid. - - template class linear_vector { - protected: - T *pool; - unsigned poolsize, objectsize; - - public: - unsigned size() const { return objectsize; } - unsigned capacity() const { return poolsize; } - - void reset() { - if(pool) { - for(unsigned i = 0; i < objectsize; i++) pool[i].~T(); - free(pool); - } - pool = 0; - poolsize = 0; - objectsize = 0; - } - - void reserve(unsigned newsize) { - newsize = bit::round(newsize); //round to nearest power of two (for amortized growth) - - T *poolcopy = (T*)malloc(newsize * sizeof(T)); - for(unsigned i = 0; i < min(objectsize, newsize); i++) new(poolcopy + i) T(pool[i]); - for(unsigned i = 0; i < objectsize; i++) pool[i].~T(); - free(pool); - pool = poolcopy; - poolsize = newsize; - objectsize = min(objectsize, newsize); - } - - void resize(unsigned newsize) { - if(newsize > poolsize) reserve(newsize); - - if(newsize < objectsize) { - //vector is shrinking; destroy excess objects - for(unsigned i = newsize; i < objectsize; i++) pool[i].~T(); - } else if(newsize > objectsize) { - //vector is expanding; allocate new objects - for(unsigned i = objectsize; i < newsize; i++) new(pool + i) T; - } - - objectsize = newsize; - } - - void add(const T data) { - if(objectsize + 1 > poolsize) reserve(objectsize + 1); - new(pool + objectsize++) T(data); - } - - inline T& operator[](unsigned index) { - if(index >= objectsize) resize(index + 1); - return pool[index]; - } - - inline const T& operator[](unsigned index) const { - if(index >= objectsize) throw "vector[] out of bounds"; - return pool[index]; - } - - //copy - inline linear_vector& operator=(const linear_vector &source) { - reset(); - reserve(source.capacity()); - resize(source.size()); - for(unsigned i = 0; i < source.size(); i++) operator[](i) = source.operator[](i); - return *this; - } - - linear_vector(const linear_vector &source) : pool(0), poolsize(0), objectsize(0) { - operator=(source); - } - - //move - inline linear_vector& operator=(linear_vector &&source) { - reset(); - pool = source.pool; - poolsize = source.poolsize; - objectsize = source.objectsize; - source.pool = 0; - source.reset(); - return *this; - } - - linear_vector(linear_vector &&source) : pool(0), poolsize(0), objectsize(0) { - operator=(std::move(source)); - } - - //construction - linear_vector() : pool(0), poolsize(0), objectsize(0) { - } - - linear_vector(std::initializer_list list) : pool(0), poolsize(0), objectsize(0) { - for(const T *p = list.begin(); p != list.end(); ++p) add(*p); - } - - ~linear_vector() { - reset(); - } - }; - - //pointer_vector - //memory: O(1) - // - //pointer_vector keeps an array of pointers to each vector object. this adds - //significant overhead to individual accesses, but allows for optimal memory - //utilization. - // - //by guaranteeing that the base memory address of each objects never changes, - //this avoids the need for an object to have a valid copy constructor. - - template class pointer_vector { - protected: - T **pool; - unsigned poolsize, objectsize; - - public: - unsigned size() const { return objectsize; } - unsigned capacity() const { return poolsize; } - - void reset() { - if(pool) { - for(unsigned i = 0; i < objectsize; i++) { if(pool[i]) delete pool[i]; } - free(pool); - } - pool = 0; - poolsize = 0; - objectsize = 0; - } - - void reserve(unsigned newsize) { - newsize = bit::round(newsize); //round to nearest power of two (for amortized growth) - - for(unsigned i = newsize; i < objectsize; i++) { - if(pool[i]) { delete pool[i]; pool[i] = 0; } - } - - pool = (T**)realloc(pool, newsize * sizeof(T*)); - for(unsigned i = poolsize; i < newsize; i++) pool[i] = 0; - poolsize = newsize; - objectsize = min(objectsize, newsize); - } - - void resize(unsigned newsize) { - if(newsize > poolsize) reserve(newsize); - - for(unsigned i = newsize; i < objectsize; i++) { - if(pool[i]) { delete pool[i]; pool[i] = 0; } - } - - objectsize = newsize; - } - - void add(const T data) { - if(objectsize + 1 > poolsize) reserve(objectsize + 1); - pool[objectsize++] = new T(data); - } - - inline T& operator[](unsigned index) { - if(index >= objectsize) resize(index + 1); - if(!pool[index]) pool[index] = new T; - return *pool[index]; - } - - inline const T& operator[](unsigned index) const { - if(index >= objectsize || !pool[index]) throw "vector[] out of bounds"; - return *pool[index]; - } - - //copy - inline pointer_vector& operator=(const pointer_vector &source) { - reset(); - reserve(source.capacity()); - resize(source.size()); - for(unsigned i = 0; i < source.size(); i++) operator[](i) = source.operator[](i); - return *this; - } - - pointer_vector(const pointer_vector &source) : pool(0), poolsize(0), objectsize(0) { - operator=(source); - } - - //move - inline pointer_vector& operator=(pointer_vector &&source) { - reset(); - pool = source.pool; - poolsize = source.poolsize; - objectsize = source.objectsize; - source.pool = 0; - source.reset(); - return *this; - } - - pointer_vector(pointer_vector &&source) : pool(0), poolsize(0), objectsize(0) { - operator=(std::move(source)); - } - - //construction - pointer_vector() : pool(0), poolsize(0), objectsize(0) { - } - - pointer_vector(std::initializer_list list) : pool(0), poolsize(0), objectsize(0) { - for(const T *p = list.begin(); p != list.end(); ++p) add(*p); - } - - ~pointer_vector() { - reset(); - } - }; - - template struct has_size> { enum { value = true }; }; - template struct has_size> { enum { value = true }; }; -} - -#endif diff --git a/snesfilter/ntsc/ntsc.cpp b/snesfilter/ntsc/ntsc.cpp deleted file mode 100644 index 142ce8f8..00000000 --- a/snesfilter/ntsc/ntsc.cpp +++ /dev/null @@ -1,396 +0,0 @@ -#include "snes_ntsc/snes_ntsc.h" -#include "snes_ntsc/snes_ntsc.c" - -#include "ntsc.moc.hpp" -#include "ntsc.moc" - -void NTSCFilter::bind(configuration &config) { - config.attach(hue = 0.0, "snesfilter.ntsc.hue"); - config.attach(saturation = 0.0, "snesfilter.ntsc.saturation"); - config.attach(contrast = 0.0, "snesfilter.ntsc.contrast"); - config.attach(brightness = 0.0, "snesfilter.ntsc.brightness"); - config.attach(sharpness = 0.0, "snesfilter.ntsc.sharpness"); - config.attach(gamma = 0.0, "snesfilter.ntsc.gamma"); - config.attach(resolution = 0.0, "snesfilter.ntsc.resolution"); - config.attach(artifacts = 0.0, "snesfilter.ntsc.artifacts"); - config.attach(fringing = 0.0, "snesfilter.ntsc.fringing"); - config.attach(bleed = 0.0, "snesfilter.ntsc.bleed"); - config.attach(mergeFields = true, "snesfilter.ntsc.mergeFields"); -} - -void NTSCFilter::size(unsigned &outwidth, unsigned &outheight, unsigned width, unsigned height) { - outwidth = SNES_NTSC_OUT_WIDTH(256); - outheight = height; -} - -void NTSCFilter::render( - uint32_t *output, unsigned outpitch, const uint16_t *input, unsigned pitch, - const unsigned *line, unsigned width, unsigned height -) { - if(!ntsc) return; - - width = SNES_NTSC_OUT_WIDTH(256); - burst ^= burst_toggle; - - pitch >>= 1; - outpitch >>= 2; - - unsigned line_burst = burst; - for(unsigned y = 0; y < height;) { - const uint16_t *in = input + y * pitch; - uint32_t *out = output + y * outpitch; - - //render as many lines in one snes_ntsc_blit as possible: - //do this by determining for how many lines the width stays the same - unsigned rheight = 1; - unsigned rwidth = line[y]; - while(y + rheight < height && rwidth == line[y + rheight]) rheight++; - - if(rwidth == 256) { - snes_ntsc_blit (ntsc, in, pitch, line_burst, rwidth, rheight, out, outpitch << 2); - } else { - snes_ntsc_blit_hires(ntsc, in, pitch, line_burst, rwidth, rheight, out, outpitch << 2); - } - - line_burst = (line_burst + rheight) % 3; - y += rheight; - } -} - -QWidget* NTSCFilter::settings() { - if(!widget) { - widget = new QWidget; - widget->setWindowTitle("NTSC Filter Configuration"); - - layout = new QVBoxLayout; - layout->setAlignment(Qt::AlignTop); - widget->setLayout(layout); - - gridLayout = new QGridLayout; - layout->addLayout(gridLayout); - - basicSettings = new QLabel("Basic settings:"); - gridLayout->addWidget(basicSettings, 0, 0, 1, 3); - - hueLabel = new QLabel("Hue:"); - gridLayout->addWidget(hueLabel, 1, 0); - - hueValue = new QLabel; - hueValue->setMinimumWidth(hueValue->fontMetrics().width("-100.0")); - hueValue->setAlignment(Qt::AlignHCenter); - gridLayout->addWidget(hueValue, 1, 1); - - hueSlider = new QSlider(Qt::Horizontal); - hueSlider->setMinimum(-100); - hueSlider->setMaximum(+100); - gridLayout->addWidget(hueSlider, 1, 2); - - saturationLabel = new QLabel("Saturation:"); - gridLayout->addWidget(saturationLabel, 2, 0); - - saturationValue = new QLabel; - saturationValue->setAlignment(Qt::AlignHCenter); - gridLayout->addWidget(saturationValue, 2, 1); - - saturationSlider = new QSlider(Qt::Horizontal); - saturationSlider->setMinimum(-100); - saturationSlider->setMaximum(+100); - gridLayout->addWidget(saturationSlider, 2, 2); - - contrastLabel = new QLabel("Contrast:"); - gridLayout->addWidget(contrastLabel, 3, 0); - - contrastValue = new QLabel; - contrastValue->setAlignment(Qt::AlignHCenter); - gridLayout->addWidget(contrastValue, 3, 1); - - contrastSlider = new QSlider(Qt::Horizontal); - contrastSlider->setMinimum(-100); - contrastSlider->setMaximum(+100); - gridLayout->addWidget(contrastSlider, 3, 2); - - brightnessLabel = new QLabel("Brightness:"); - gridLayout->addWidget(brightnessLabel, 4, 0); - - brightnessValue = new QLabel; - brightnessValue->setAlignment(Qt::AlignHCenter); - gridLayout->addWidget(brightnessValue, 4, 1); - - brightnessSlider = new QSlider(Qt::Horizontal); - brightnessSlider->setMinimum(-100); - brightnessSlider->setMaximum(+100); - gridLayout->addWidget(brightnessSlider, 4, 2); - - sharpnessLabel = new QLabel("Sharpness:"); - gridLayout->addWidget(sharpnessLabel, 5, 0); - - sharpnessValue = new QLabel; - sharpnessValue->setAlignment(Qt::AlignHCenter); - gridLayout->addWidget(sharpnessValue, 5, 1); - - sharpnessSlider = new QSlider(Qt::Horizontal); - sharpnessSlider->setMinimum(-100); - sharpnessSlider->setMaximum(+100); - gridLayout->addWidget(sharpnessSlider, 5, 2); - - advancedSettings = new QLabel("Advanced settings:"); - gridLayout->addWidget(advancedSettings, 6, 0, 1, 3); - - gammaLabel = new QLabel("Gamma:"); - gridLayout->addWidget(gammaLabel, 7, 0); - - gammaValue = new QLabel; - gammaValue->setAlignment(Qt::AlignHCenter); - gridLayout->addWidget(gammaValue, 7, 1); - - gammaSlider = new QSlider(Qt::Horizontal); - gammaSlider->setMinimum(-100); - gammaSlider->setMaximum(+100); - gridLayout->addWidget(gammaSlider, 7, 2); - - resolutionLabel = new QLabel("Resolution:"); - gridLayout->addWidget(resolutionLabel, 8, 0); - - resolutionValue = new QLabel; - resolutionValue->setAlignment(Qt::AlignHCenter); - gridLayout->addWidget(resolutionValue, 8, 1); - - resolutionSlider = new QSlider(Qt::Horizontal); - resolutionSlider->setMinimum(-100); - resolutionSlider->setMaximum(+100); - gridLayout->addWidget(resolutionSlider, 8, 2); - - artifactsLabel = new QLabel("Artifacts:"); - gridLayout->addWidget(artifactsLabel, 9, 0); - - artifactsValue = new QLabel; - artifactsValue->setAlignment(Qt::AlignHCenter); - gridLayout->addWidget(artifactsValue, 9, 1); - - artifactsSlider = new QSlider(Qt::Horizontal); - artifactsSlider->setMinimum(-100); - artifactsSlider->setMaximum(+100); - gridLayout->addWidget(artifactsSlider, 9, 2); - - fringingLabel = new QLabel("Fringing:"); - gridLayout->addWidget(fringingLabel, 10, 0); - - fringingValue = new QLabel; - fringingValue->setAlignment(Qt::AlignHCenter); - gridLayout->addWidget(fringingValue, 10, 1); - - fringingSlider = new QSlider(Qt::Horizontal); - fringingSlider->setMinimum(-100); - fringingSlider->setMaximum(+100); - gridLayout->addWidget(fringingSlider, 10, 2); - - bleedLabel = new QLabel("Color bleed:"); - gridLayout->addWidget(bleedLabel, 11, 0); - - bleedValue = new QLabel; - bleedValue->setAlignment(Qt::AlignHCenter); - gridLayout->addWidget(bleedValue, 11, 1); - - bleedSlider = new QSlider(Qt::Horizontal); - bleedSlider->setMinimum(-100); - bleedSlider->setMaximum(+100); - gridLayout->addWidget(bleedSlider, 11, 2); - - mergeFieldsBox = new QCheckBox("Merge even and odd fields to reduce flicker"); - gridLayout->addWidget(mergeFieldsBox, 12, 0, 1, 3); - - presets = new QLabel("Presets:"); - gridLayout->addWidget(presets, 13, 0, 1, 3); - - controlLayout = new QHBoxLayout; - layout->addLayout(controlLayout); - - rfPreset = new QPushButton("RF"); - controlLayout->addWidget(rfPreset); - - compositePreset = new QPushButton("Composite"); - controlLayout->addWidget(compositePreset); - - svideoPreset = new QPushButton("S-Video"); - controlLayout->addWidget(svideoPreset); - - rgbPreset = new QPushButton("RGB"); - controlLayout->addWidget(rgbPreset); - - monoPreset = new QPushButton("Monochrome"); - controlLayout->addWidget(monoPreset); - - spacer = new QWidget; - spacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); - spacer->setMinimumWidth(50); - controlLayout->addWidget(spacer); - - ok = new QPushButton("Ok"); - controlLayout->addWidget(ok); - - blockSignals = true; - loadSettingsFromConfig(); - syncUiToSettings(); - initialize(); - - connect(hueSlider, SIGNAL(valueChanged(int)), this, SLOT(syncSettingsToUi())); - connect(saturationSlider, SIGNAL(valueChanged(int)), this, SLOT(syncSettingsToUi())); - connect(contrastSlider, SIGNAL(valueChanged(int)), this, SLOT(syncSettingsToUi())); - connect(brightnessSlider, SIGNAL(valueChanged(int)), this, SLOT(syncSettingsToUi())); - connect(sharpnessSlider, SIGNAL(valueChanged(int)), this, SLOT(syncSettingsToUi())); - connect(gammaSlider, SIGNAL(valueChanged(int)), this, SLOT(syncSettingsToUi())); - connect(resolutionSlider, SIGNAL(valueChanged(int)), this, SLOT(syncSettingsToUi())); - connect(artifactsSlider, SIGNAL(valueChanged(int)), this, SLOT(syncSettingsToUi())); - connect(fringingSlider, SIGNAL(valueChanged(int)), this, SLOT(syncSettingsToUi())); - connect(bleedSlider, SIGNAL(valueChanged(int)), this, SLOT(syncSettingsToUi())); - connect(mergeFieldsBox, SIGNAL(stateChanged(int)), this, SLOT(syncSettingsToUi())); - connect(rfPreset, SIGNAL(released()), this, SLOT(setRfPreset())); - connect(compositePreset, SIGNAL(released()), this, SLOT(setCompositePreset())); - connect(svideoPreset, SIGNAL(released()), this, SLOT(setSvideoPreset())); - connect(rgbPreset, SIGNAL(released()), this, SLOT(setRgbPreset())); - connect(monoPreset, SIGNAL(released()), this, SLOT(setMonoPreset())); - connect(ok, SIGNAL(released()), widget, SLOT(hide())); - - blockSignals = false; - } - - return widget; -} - -void NTSCFilter::initialize() { - burst = 0; - burst_toggle = (setup.merge_fields ? 0 : 1); //don't toggle burst when fields are merged - snes_ntsc_init(ntsc, &setup); -} - -void NTSCFilter::loadSettingsFromConfig() { - setup.hue = hue; - setup.saturation = saturation; - setup.contrast = contrast; - setup.brightness = brightness; - setup.sharpness = sharpness; - - setup.gamma = gamma; - setup.resolution = resolution; - setup.artifacts = artifacts; - setup.fringing = fringing; - setup.bleed = bleed; - - setup.merge_fields = mergeFields; -} - -void NTSCFilter::syncUiToSettings() { - blockSignals = true; - - hue = setup.hue; - saturation = setup.saturation; - contrast = setup.contrast; - brightness = setup.brightness; - sharpness = setup.sharpness; - - gamma = setup.gamma; - resolution = setup.resolution; - artifacts = setup.artifacts; - fringing = setup.fringing; - bleed = setup.bleed; - - mergeFields = setup.merge_fields; - - hueValue->setText(string() << hue); - hueSlider->setSliderPosition(hue * 100); - - saturationValue->setText(string() << saturation); - saturationSlider->setSliderPosition(saturation * 100); - - contrastValue->setText(string() << contrast); - contrastSlider->setSliderPosition(contrast * 100); - - brightnessValue->setText(string() << brightness); - brightnessSlider->setSliderPosition(brightness * 100); - - sharpnessValue->setText(string() << sharpness); - sharpnessSlider->setSliderPosition(sharpness * 100); - - gammaValue->setText(string() << gamma); - gammaSlider->setSliderPosition(gamma * 100); - - resolutionValue->setText(string() << resolution); - resolutionSlider->setSliderPosition(resolution * 100); - - artifactsValue->setText(string() << artifacts); - artifactsSlider->setSliderPosition(artifacts * 100); - - fringingValue->setText(string() << fringing); - fringingSlider->setSliderPosition(fringing * 100); - - bleedValue->setText(string() << bleed); - bleedSlider->setSliderPosition(bleed * 100); - - mergeFieldsBox->setChecked(mergeFields); - - blockSignals = false; -} - -void NTSCFilter::syncSettingsToUi() { - if(blockSignals) return; - - hue = hueSlider->sliderPosition() / 100.0; - saturation = saturationSlider->sliderPosition() / 100.0; - contrast = contrastSlider->sliderPosition() / 100.0; - brightness = brightnessSlider->sliderPosition() / 100.0; - sharpness = sharpnessSlider->sliderPosition() / 100.0; - - gamma = gammaSlider->sliderPosition() / 100.0; - resolution = resolutionSlider->sliderPosition() / 100.0; - artifacts = artifactsSlider->sliderPosition() / 100.0; - fringing = fringingSlider->sliderPosition() / 100.0; - bleed = bleedSlider->sliderPosition() / 100.0; - - mergeFields = mergeFieldsBox->isChecked(); - - loadSettingsFromConfig(); - syncUiToSettings(); - initialize(); -} - -void NTSCFilter::setRfPreset() { - static snes_ntsc_setup_t defaults; - setup = defaults; - syncUiToSettings(); - initialize(); -} - -void NTSCFilter::setCompositePreset() { - setup = snes_ntsc_composite; - syncUiToSettings(); - initialize(); -} - -void NTSCFilter::setSvideoPreset() { - setup = snes_ntsc_svideo; - syncUiToSettings(); - initialize(); -} - -void NTSCFilter::setRgbPreset() { - setup = snes_ntsc_rgb; - syncUiToSettings(); - initialize(); -} - -void NTSCFilter::setMonoPreset() { - setup = snes_ntsc_monochrome; - syncUiToSettings(); - initialize(); -} - -NTSCFilter::NTSCFilter() : widget(0) { - ntsc = (snes_ntsc_t*)malloc(sizeof *ntsc); - static snes_ntsc_setup_t defaults; - setup = defaults; - initialize(); -} - -NTSCFilter::~NTSCFilter() { - if(ntsc) free(ntsc); -} diff --git a/snesfilter/ntsc/ntsc.moc.hpp b/snesfilter/ntsc/ntsc.moc.hpp deleted file mode 100644 index a99a6bb4..00000000 --- a/snesfilter/ntsc/ntsc.moc.hpp +++ /dev/null @@ -1,91 +0,0 @@ -class NTSCFilter : public QObject { - Q_OBJECT - -public: - void bind(configuration&); - void size(unsigned&, unsigned&, unsigned, unsigned); - void render(uint32_t*, unsigned, const uint16_t*, unsigned, const unsigned*, unsigned, unsigned); - QWidget* settings(); - - NTSCFilter(); - ~NTSCFilter(); - -private: - void initialize(); - void loadSettingsFromConfig(); - void syncUiToSettings(); - -private slots: - void syncSettingsToUi(); - void setRfPreset(); - void setCompositePreset(); - void setSvideoPreset(); - void setRgbPreset(); - void setMonoPreset(); - -private: - QWidget *widget; - QVBoxLayout *layout; - QGridLayout *gridLayout; - QLabel *basicSettings; - QLabel *hueLabel; - QLabel *hueValue; - QSlider *hueSlider; - QLabel *saturationLabel; - QLabel *saturationValue; - QSlider *saturationSlider; - QLabel *contrastLabel; - QLabel *contrastValue; - QSlider *contrastSlider; - QLabel *brightnessLabel; - QLabel *brightnessValue; - QSlider *brightnessSlider; - QLabel *sharpnessLabel; - QLabel *sharpnessValue; - QSlider *sharpnessSlider; - QLabel *advancedSettings; - QLabel *gammaLabel; - QLabel *gammaValue; - QSlider *gammaSlider; - QLabel *resolutionLabel; - QLabel *resolutionValue; - QSlider *resolutionSlider; - QLabel *artifactsLabel; - QLabel *artifactsValue; - QSlider *artifactsSlider; - QLabel *fringingLabel; - QLabel *fringingValue; - QSlider *fringingSlider; - QLabel *bleedLabel; - QLabel *bleedValue; - QSlider *bleedSlider; - QCheckBox *mergeFieldsBox; - QLabel *presets; - QHBoxLayout *controlLayout; - QPushButton *rfPreset; - QPushButton *compositePreset; - QPushButton *svideoPreset; - QPushButton *rgbPreset; - QPushButton *monoPreset; - QWidget *spacer; - QPushButton *ok; - - bool blockSignals; - - struct snes_ntsc_t *ntsc; - snes_ntsc_setup_t setup; - int burst, burst_toggle; - - //settings - double hue; - double saturation; - double contrast; - double brightness; - double sharpness; - double gamma; - double resolution; - double artifacts; - double fringing; - double bleed; - bool mergeFields; -} filter_ntsc; diff --git a/snesfilter/ntsc/snes_ntsc/snes_ntsc.c b/snesfilter/ntsc/snes_ntsc/snes_ntsc.c deleted file mode 100644 index f622baf8..00000000 --- a/snesfilter/ntsc/snes_ntsc/snes_ntsc.c +++ /dev/null @@ -1,251 +0,0 @@ -/* snes_ntsc 0.2.2. http://www.slack.net/~ant/ */ - -#include "snes_ntsc.h" - -/* Copyright (C) 2006-2007 Shay Green. This module 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 -module is distributed in the hope that 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 module; if not, write to the Free Software Foundation, -Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -snes_ntsc_setup_t const snes_ntsc_monochrome = { 0,-1, 0, 0,.2, 0,.2,-.2,-.2,-1, 1, 0, 0 }; -snes_ntsc_setup_t const snes_ntsc_composite = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0 }; -snes_ntsc_setup_t const snes_ntsc_svideo = { 0, 0, 0, 0,.2, 0,.2, -1, -1, 0, 1, 0, 0 }; -snes_ntsc_setup_t const snes_ntsc_rgb = { 0, 0, 0, 0,.2, 0,.7, -1, -1,-1, 1, 0, 0 }; - -#define alignment_count 3 -#define burst_count 3 -#define rescale_in 8 -#define rescale_out 7 - -#define artifacts_mid 1.0f -#define fringing_mid 1.0f -#define std_decoder_hue 0 - -#define rgb_bits 7 /* half normal range to allow for doubled hires pixels */ -#define gamma_size 32 - -#include "snes_ntsc_impl.h" - -/* 3 input pixels -> 8 composite samples */ -pixel_info_t const snes_ntsc_pixels [alignment_count] = { - { PIXEL_OFFSET( -4, -9 ), { 1, 1, .6667f, 0 } }, - { PIXEL_OFFSET( -2, -7 ), { .3333f, 1, 1, .3333f } }, - { PIXEL_OFFSET( 0, -5 ), { 0, .6667f, 1, 1 } }, -}; - -static void merge_kernel_fields( snes_ntsc_rgb_t* io ) -{ - int n; - for ( n = burst_size; n; --n ) - { - snes_ntsc_rgb_t p0 = io [burst_size * 0] + rgb_bias; - snes_ntsc_rgb_t p1 = io [burst_size * 1] + rgb_bias; - snes_ntsc_rgb_t p2 = io [burst_size * 2] + rgb_bias; - /* merge colors without losing precision */ - io [burst_size * 0] = - ((p0 + p1 - ((p0 ^ p1) & snes_ntsc_rgb_builder)) >> 1) - rgb_bias; - io [burst_size * 1] = - ((p1 + p2 - ((p1 ^ p2) & snes_ntsc_rgb_builder)) >> 1) - rgb_bias; - io [burst_size * 2] = - ((p2 + p0 - ((p2 ^ p0) & snes_ntsc_rgb_builder)) >> 1) - rgb_bias; - ++io; - } -} - -static void correct_errors( snes_ntsc_rgb_t color, snes_ntsc_rgb_t* out ) -{ - int n; - for ( n = burst_count; n; --n ) - { - unsigned i; - for ( i = 0; i < rgb_kernel_size / 2; i++ ) - { - snes_ntsc_rgb_t error = color - - out [i ] - out [(i+12)%14+14] - out [(i+10)%14+28] - - out [i + 7] - out [i + 5 +14] - out [i + 3 +28]; - DISTRIBUTE_ERROR( i+3+28, i+5+14, i+7 ); - } - out += alignment_count * rgb_kernel_size; - } -} - -void snes_ntsc_init( snes_ntsc_t* ntsc, snes_ntsc_setup_t const* setup ) -{ - int merge_fields; - int entry; - init_t impl; - if ( !setup ) - setup = &snes_ntsc_composite; - init( &impl, setup ); - - merge_fields = setup->merge_fields; - if ( setup->artifacts <= -1 && setup->fringing <= -1 ) - merge_fields = 1; - - for ( entry = 0; entry < snes_ntsc_palette_size; entry++ ) - { - /* Reduce number of significant bits of source color. Clearing the - low bits of R and B were least notictable. Modifying green was too - noticeable. */ - int ir = entry >> 8 & 0x1E; - int ig = entry >> 4 & 0x1F; - int ib = entry << 1 & 0x1E; - - #if SNES_NTSC_BSNES_COLORTBL - if ( setup->bsnes_colortbl ) - { - int bgr15 = (ib << 10) | (ig << 5) | ir; - unsigned long rgb16 = setup->bsnes_colortbl [bgr15]; - ir = rgb16 >> 11 & 0x1E; - ig = rgb16 >> 6 & 0x1F; - ib = rgb16 & 0x1E; - } - #endif - - { - float rr = impl.to_float [ir]; - float gg = impl.to_float [ig]; - float bb = impl.to_float [ib]; - - float y, i, q = RGB_TO_YIQ( rr, gg, bb, y, i ); - - int r, g, b = YIQ_TO_RGB( y, i, q, impl.to_rgb, int, r, g ); - snes_ntsc_rgb_t rgb = PACK_RGB( r, g, b ); - - snes_ntsc_rgb_t* out = ntsc->table [entry]; - gen_kernel( &impl, y, i, q, out ); - if ( merge_fields ) - merge_kernel_fields( out ); - correct_errors( rgb, out ); - } - } -} - -#ifndef SNES_NTSC_NO_BLITTERS - -void snes_ntsc_blit( snes_ntsc_t const* ntsc, SNES_NTSC_IN_T const* input, long in_row_width, - int burst_phase, int in_width, int in_height, void* rgb_out, long out_pitch ) -{ - int chunk_count = (in_width - 1) / snes_ntsc_in_chunk; - for ( ; in_height; --in_height ) - { - SNES_NTSC_IN_T const* line_in = input; - SNES_NTSC_BEGIN_ROW( ntsc, burst_phase, - snes_ntsc_black, snes_ntsc_black, SNES_NTSC_ADJ_IN( *line_in ) ); - snes_ntsc_out_t* restrict line_out = (snes_ntsc_out_t*) rgb_out; - int n; - ++line_in; - - for ( n = chunk_count; n; --n ) - { - /* order of input and output pixels must not be altered */ - SNES_NTSC_COLOR_IN( 0, SNES_NTSC_ADJ_IN( line_in [0] ) ); - SNES_NTSC_RGB_OUT( 0, line_out [0], SNES_NTSC_OUT_DEPTH ); - SNES_NTSC_RGB_OUT( 1, line_out [1], SNES_NTSC_OUT_DEPTH ); - - SNES_NTSC_COLOR_IN( 1, SNES_NTSC_ADJ_IN( line_in [1] ) ); - SNES_NTSC_RGB_OUT( 2, line_out [2], SNES_NTSC_OUT_DEPTH ); - SNES_NTSC_RGB_OUT( 3, line_out [3], SNES_NTSC_OUT_DEPTH ); - - SNES_NTSC_COLOR_IN( 2, SNES_NTSC_ADJ_IN( line_in [2] ) ); - SNES_NTSC_RGB_OUT( 4, line_out [4], SNES_NTSC_OUT_DEPTH ); - SNES_NTSC_RGB_OUT( 5, line_out [5], SNES_NTSC_OUT_DEPTH ); - SNES_NTSC_RGB_OUT( 6, line_out [6], SNES_NTSC_OUT_DEPTH ); - - line_in += 3; - line_out += 7; - } - - /* finish final pixels */ - SNES_NTSC_COLOR_IN( 0, snes_ntsc_black ); - SNES_NTSC_RGB_OUT( 0, line_out [0], SNES_NTSC_OUT_DEPTH ); - SNES_NTSC_RGB_OUT( 1, line_out [1], SNES_NTSC_OUT_DEPTH ); - - SNES_NTSC_COLOR_IN( 1, snes_ntsc_black ); - SNES_NTSC_RGB_OUT( 2, line_out [2], SNES_NTSC_OUT_DEPTH ); - SNES_NTSC_RGB_OUT( 3, line_out [3], SNES_NTSC_OUT_DEPTH ); - - SNES_NTSC_COLOR_IN( 2, snes_ntsc_black ); - SNES_NTSC_RGB_OUT( 4, line_out [4], SNES_NTSC_OUT_DEPTH ); - SNES_NTSC_RGB_OUT( 5, line_out [5], SNES_NTSC_OUT_DEPTH ); - SNES_NTSC_RGB_OUT( 6, line_out [6], SNES_NTSC_OUT_DEPTH ); - - burst_phase = (burst_phase + 1) % snes_ntsc_burst_count; - input += in_row_width; - rgb_out = (char*) rgb_out + out_pitch; - } -} - -void snes_ntsc_blit_hires( snes_ntsc_t const* ntsc, SNES_NTSC_IN_T const* input, long in_row_width, - int burst_phase, int in_width, int in_height, void* rgb_out, long out_pitch ) -{ - int chunk_count = (in_width - 2) / (snes_ntsc_in_chunk * 2); - for ( ; in_height; --in_height ) - { - SNES_NTSC_IN_T const* line_in = input; - SNES_NTSC_HIRES_ROW( ntsc, burst_phase, - snes_ntsc_black, snes_ntsc_black, snes_ntsc_black, - SNES_NTSC_ADJ_IN( line_in [0] ), - SNES_NTSC_ADJ_IN( line_in [1] ) ); - snes_ntsc_out_t* restrict line_out = (snes_ntsc_out_t*) rgb_out; - int n; - line_in += 2; - - for ( n = chunk_count; n; --n ) - { - /* twice as many input pixels per chunk */ - SNES_NTSC_COLOR_IN( 0, SNES_NTSC_ADJ_IN( line_in [0] ) ); - SNES_NTSC_HIRES_OUT( 0, line_out [0], SNES_NTSC_OUT_DEPTH ); - - SNES_NTSC_COLOR_IN( 1, SNES_NTSC_ADJ_IN( line_in [1] ) ); - SNES_NTSC_HIRES_OUT( 1, line_out [1], SNES_NTSC_OUT_DEPTH ); - - SNES_NTSC_COLOR_IN( 2, SNES_NTSC_ADJ_IN( line_in [2] ) ); - SNES_NTSC_HIRES_OUT( 2, line_out [2], SNES_NTSC_OUT_DEPTH ); - - SNES_NTSC_COLOR_IN( 3, SNES_NTSC_ADJ_IN( line_in [3] ) ); - SNES_NTSC_HIRES_OUT( 3, line_out [3], SNES_NTSC_OUT_DEPTH ); - - SNES_NTSC_COLOR_IN( 4, SNES_NTSC_ADJ_IN( line_in [4] ) ); - SNES_NTSC_HIRES_OUT( 4, line_out [4], SNES_NTSC_OUT_DEPTH ); - - SNES_NTSC_COLOR_IN( 5, SNES_NTSC_ADJ_IN( line_in [5] ) ); - SNES_NTSC_HIRES_OUT( 5, line_out [5], SNES_NTSC_OUT_DEPTH ); - SNES_NTSC_HIRES_OUT( 6, line_out [6], SNES_NTSC_OUT_DEPTH ); - - line_in += 6; - line_out += 7; - } - - SNES_NTSC_COLOR_IN( 0, snes_ntsc_black ); - SNES_NTSC_HIRES_OUT( 0, line_out [0], SNES_NTSC_OUT_DEPTH ); - - SNES_NTSC_COLOR_IN( 1, snes_ntsc_black ); - SNES_NTSC_HIRES_OUT( 1, line_out [1], SNES_NTSC_OUT_DEPTH ); - - SNES_NTSC_COLOR_IN( 2, snes_ntsc_black ); - SNES_NTSC_HIRES_OUT( 2, line_out [2], SNES_NTSC_OUT_DEPTH ); - - SNES_NTSC_COLOR_IN( 3, snes_ntsc_black ); - SNES_NTSC_HIRES_OUT( 3, line_out [3], SNES_NTSC_OUT_DEPTH ); - - SNES_NTSC_COLOR_IN( 4, snes_ntsc_black ); - SNES_NTSC_HIRES_OUT( 4, line_out [4], SNES_NTSC_OUT_DEPTH ); - - SNES_NTSC_COLOR_IN( 5, snes_ntsc_black ); - SNES_NTSC_HIRES_OUT( 5, line_out [5], SNES_NTSC_OUT_DEPTH ); - SNES_NTSC_HIRES_OUT( 6, line_out [6], SNES_NTSC_OUT_DEPTH ); - - burst_phase = (burst_phase + 1) % snes_ntsc_burst_count; - input += in_row_width; - rgb_out = (char*) rgb_out + out_pitch; - } -} - -#endif diff --git a/snesfilter/ntsc/snes_ntsc/snes_ntsc.h b/snesfilter/ntsc/snes_ntsc/snes_ntsc.h deleted file mode 100644 index fff97ecd..00000000 --- a/snesfilter/ntsc/snes_ntsc/snes_ntsc.h +++ /dev/null @@ -1,228 +0,0 @@ -/* SNES NTSC video filter */ - -/* snes_ntsc 0.2.2 */ -#ifndef SNES_NTSC_H -#define SNES_NTSC_H - -#include "snes_ntsc_config.h" - -#ifdef __cplusplus - extern "C" { -#endif - -/* Image parameters, ranging from -1.0 to 1.0. Actual internal values shown -in parenthesis and should remain fairly stable in future versions. */ -typedef struct snes_ntsc_setup_t -{ - /* Basic parameters */ - double hue; /* -1 = -180 degrees +1 = +180 degrees */ - double saturation; /* -1 = grayscale (0.0) +1 = oversaturated colors (2.0) */ - double contrast; /* -1 = dark (0.5) +1 = light (1.5) */ - double brightness; /* -1 = dark (0.5) +1 = light (1.5) */ - double sharpness; /* edge contrast enhancement/blurring */ - - /* Advanced parameters */ - double gamma; /* -1 = dark (1.5) +1 = light (0.5) */ - double resolution; /* image resolution */ - double artifacts; /* artifacts caused by color changes */ - double fringing; /* color artifacts caused by brightness changes */ - double bleed; /* color bleed (color resolution reduction) */ - int merge_fields; /* if 1, merges even and odd fields together to reduce flicker */ - float const* decoder_matrix; /* optional RGB decoder matrix, 6 elements */ - - unsigned long const* bsnes_colortbl; /* undocumented; set to 0 */ -} snes_ntsc_setup_t; - -/* Video format presets */ -extern snes_ntsc_setup_t const snes_ntsc_composite; /* color bleeding + artifacts */ -extern snes_ntsc_setup_t const snes_ntsc_svideo; /* color bleeding only */ -extern snes_ntsc_setup_t const snes_ntsc_rgb; /* crisp image */ -extern snes_ntsc_setup_t const snes_ntsc_monochrome;/* desaturated + artifacts */ - -/* Initializes and adjusts parameters. Can be called multiple times on the same -snes_ntsc_t object. Can pass NULL for either parameter. */ -typedef struct snes_ntsc_t snes_ntsc_t; -void snes_ntsc_init( snes_ntsc_t* ntsc, snes_ntsc_setup_t const* setup ); - -/* Filters one or more rows of pixels. Input pixel format is set by SNES_NTSC_IN_FORMAT -and output RGB depth is set by SNES_NTSC_OUT_DEPTH. Both default to 16-bit RGB. -In_row_width is the number of pixels to get to the next input row. Out_pitch -is the number of *bytes* to get to the next output row. */ -void snes_ntsc_blit( snes_ntsc_t const* ntsc, SNES_NTSC_IN_T const* input, - long in_row_width, int burst_phase, int in_width, int in_height, - void* rgb_out, long out_pitch ); - -void snes_ntsc_blit_hires( snes_ntsc_t const* ntsc, SNES_NTSC_IN_T const* input, - long in_row_width, int burst_phase, int in_width, int in_height, - void* rgb_out, long out_pitch ); - -/* Number of output pixels written by low-res blitter for given input width. Width -might be rounded down slightly; use SNES_NTSC_IN_WIDTH() on result to find rounded -value. Guaranteed not to round 256 down at all. */ -#define SNES_NTSC_OUT_WIDTH( in_width ) \ - ((((in_width) - 1) / snes_ntsc_in_chunk + 1) * snes_ntsc_out_chunk) - -/* Number of low-res input pixels that will fit within given output width. Might be -rounded down slightly; use SNES_NTSC_OUT_WIDTH() on result to find rounded -value. */ -#define SNES_NTSC_IN_WIDTH( out_width ) \ - (((out_width) / snes_ntsc_out_chunk - 1) * snes_ntsc_in_chunk + 1) - - -/* Interface for user-defined custom blitters */ - -enum { snes_ntsc_in_chunk = 3 }; /* number of input pixels read per chunk */ -enum { snes_ntsc_out_chunk = 7 }; /* number of output pixels generated per chunk */ -enum { snes_ntsc_black = 0 }; /* palette index for black */ -enum { snes_ntsc_burst_count = 3 }; /* burst phase cycles through 0, 1, and 2 */ - -/* Begins outputting row and starts three pixels. First pixel will be cut off a bit. -Use snes_ntsc_black for unused pixels. Declares variables, so must be before first -statement in a block (unless you're using C++). */ -#define SNES_NTSC_BEGIN_ROW( ntsc, burst, pixel0, pixel1, pixel2 ) \ - char const* ktable = \ - (char const*) (ntsc)->table + burst * (snes_ntsc_burst_size * sizeof (snes_ntsc_rgb_t));\ - SNES_NTSC_BEGIN_ROW_6_( pixel0, pixel1, pixel2, SNES_NTSC_IN_FORMAT, ktable ) - -/* Begins input pixel */ -#define SNES_NTSC_COLOR_IN( index, color ) \ - SNES_NTSC_COLOR_IN_( index, color, SNES_NTSC_IN_FORMAT, ktable ) - -/* Generates output pixel. Bits can be 24, 16, 15, 14, 32 (treated as 24), or 0: -24: RRRRRRRR GGGGGGGG BBBBBBBB (8-8-8 RGB) -16: RRRRRGGG GGGBBBBB (5-6-5 RGB) -15: RRRRRGG GGGBBBBB (5-5-5 RGB) -14: BBBBBGG GGGRRRRR (5-5-5 BGR, native SNES format) - 0: xxxRRRRR RRRxxGGG GGGGGxxB BBBBBBBx (native internal format; x = junk bits) */ -#define SNES_NTSC_RGB_OUT( index, rgb_out, bits ) \ - SNES_NTSC_RGB_OUT_14_( index, rgb_out, bits, 1 ) - -/* Hires equivalents */ -#define SNES_NTSC_HIRES_ROW( ntsc, burst, pixel1, pixel2, pixel3, pixel4, pixel5 ) \ - char const* ktable = \ - (char const*) (ntsc)->table + burst * (snes_ntsc_burst_size * sizeof (snes_ntsc_rgb_t));\ - unsigned const snes_ntsc_pixel1_ = (pixel1);\ - snes_ntsc_rgb_t const* kernel1 = SNES_NTSC_IN_FORMAT( ktable, snes_ntsc_pixel1_ );\ - unsigned const snes_ntsc_pixel2_ = (pixel2);\ - snes_ntsc_rgb_t const* kernel2 = SNES_NTSC_IN_FORMAT( ktable, snes_ntsc_pixel2_ );\ - unsigned const snes_ntsc_pixel3_ = (pixel3);\ - snes_ntsc_rgb_t const* kernel3 = SNES_NTSC_IN_FORMAT( ktable, snes_ntsc_pixel3_ );\ - unsigned const snes_ntsc_pixel4_ = (pixel4);\ - snes_ntsc_rgb_t const* kernel4 = SNES_NTSC_IN_FORMAT( ktable, snes_ntsc_pixel4_ );\ - unsigned const snes_ntsc_pixel5_ = (pixel5);\ - snes_ntsc_rgb_t const* kernel5 = SNES_NTSC_IN_FORMAT( ktable, snes_ntsc_pixel5_ );\ - snes_ntsc_rgb_t const* kernel0 = kernel1;\ - snes_ntsc_rgb_t const* kernelx0;\ - snes_ntsc_rgb_t const* kernelx1 = kernel1;\ - snes_ntsc_rgb_t const* kernelx2 = kernel1;\ - snes_ntsc_rgb_t const* kernelx3 = kernel1;\ - snes_ntsc_rgb_t const* kernelx4 = kernel1;\ - snes_ntsc_rgb_t const* kernelx5 = kernel1 - -#define SNES_NTSC_HIRES_OUT( x, rgb_out, bits ) {\ - snes_ntsc_rgb_t raw_ =\ - kernel0 [ x ] + kernel2 [(x+5)%7+14] + kernel4 [(x+3)%7+28] +\ - kernelx0 [(x+7)%7+7] + kernelx2 [(x+5)%7+21] + kernelx4 [(x+3)%7+35] +\ - kernel1 [(x+6)%7 ] + kernel3 [(x+4)%7+14] + kernel5 [(x+2)%7+28] +\ - kernelx1 [(x+6)%7+7] + kernelx3 [(x+4)%7+21] + kernelx5 [(x+2)%7+35];\ - SNES_NTSC_CLAMP_( raw_, 0 );\ - SNES_NTSC_RGB_OUT_( rgb_out, (bits), 0 );\ -} - - -/* private */ -enum { snes_ntsc_entry_size = 128 }; -enum { snes_ntsc_palette_size = 0x2000 }; -typedef unsigned long snes_ntsc_rgb_t; -struct snes_ntsc_t { - snes_ntsc_rgb_t table [snes_ntsc_palette_size] [snes_ntsc_entry_size]; -}; -enum { snes_ntsc_burst_size = snes_ntsc_entry_size / snes_ntsc_burst_count }; - -#define SNES_NTSC_RGB16( ktable, n ) \ - (snes_ntsc_rgb_t const*) (ktable + ((n & 0x001E) | (n >> 1 & 0x03E0) | (n >> 2 & 0x3C00)) * \ - (snes_ntsc_entry_size / 2 * sizeof (snes_ntsc_rgb_t))) - -#define SNES_NTSC_BGR15( ktable, n ) \ - (snes_ntsc_rgb_t const*) (ktable + ((n << 9 & 0x3C00) | (n & 0x03E0) | (n >> 10 & 0x001E)) * \ - (snes_ntsc_entry_size / 2 * sizeof (snes_ntsc_rgb_t))) - -/* common 3->7 ntsc macros */ -#define SNES_NTSC_BEGIN_ROW_6_( pixel0, pixel1, pixel2, ENTRY, table ) \ - unsigned const snes_ntsc_pixel0_ = (pixel0);\ - snes_ntsc_rgb_t const* kernel0 = ENTRY( table, snes_ntsc_pixel0_ );\ - unsigned const snes_ntsc_pixel1_ = (pixel1);\ - snes_ntsc_rgb_t const* kernel1 = ENTRY( table, snes_ntsc_pixel1_ );\ - unsigned const snes_ntsc_pixel2_ = (pixel2);\ - snes_ntsc_rgb_t const* kernel2 = ENTRY( table, snes_ntsc_pixel2_ );\ - snes_ntsc_rgb_t const* kernelx0;\ - snes_ntsc_rgb_t const* kernelx1 = kernel0;\ - snes_ntsc_rgb_t const* kernelx2 = kernel0 - -#define SNES_NTSC_RGB_OUT_14_( x, rgb_out, bits, shift ) {\ - snes_ntsc_rgb_t raw_ =\ - kernel0 [x ] + kernel1 [(x+12)%7+14] + kernel2 [(x+10)%7+28] +\ - kernelx0 [(x+7)%14] + kernelx1 [(x+ 5)%7+21] + kernelx2 [(x+ 3)%7+35];\ - SNES_NTSC_CLAMP_( raw_, shift );\ - SNES_NTSC_RGB_OUT_( rgb_out, bits, shift );\ -} - -/* common ntsc macros */ -#define snes_ntsc_rgb_builder ((1L << 21) | (1 << 11) | (1 << 1)) -#define snes_ntsc_clamp_mask (snes_ntsc_rgb_builder * 3 / 2) -#define snes_ntsc_clamp_add (snes_ntsc_rgb_builder * 0x101) -#define SNES_NTSC_CLAMP_( io, shift ) {\ - snes_ntsc_rgb_t sub = (io) >> (9-(shift)) & snes_ntsc_clamp_mask;\ - snes_ntsc_rgb_t clamp = snes_ntsc_clamp_add - sub;\ - io |= clamp;\ - clamp -= sub;\ - io &= clamp;\ -} - -#define SNES_NTSC_COLOR_IN_( index, color, ENTRY, table ) {\ - unsigned color_;\ - kernelx##index = kernel##index;\ - kernel##index = (color_ = (color), ENTRY( table, color_ ));\ -} - -/* x is always zero except in snes_ntsc library */ -/* original routine */ -/* -#define SNES_NTSC_RGB_OUT_( rgb_out, bits, x ) {\ - if ( bits == 16 )\ - rgb_out = (raw_>>(13-x)& 0xF800)|(raw_>>(8-x)&0x07E0)|(raw_>>(4-x)&0x001F);\ - if ( bits == 24 || bits == 32 )\ - rgb_out = (raw_>>(5-x)&0xFF0000)|(raw_>>(3-x)&0xFF00)|(raw_>>(1-x)&0xFF);\ - if ( bits == 15 )\ - rgb_out = (raw_>>(14-x)& 0x7C00)|(raw_>>(9-x)&0x03E0)|(raw_>>(4-x)&0x001F);\ - if ( bits == 14 )\ - rgb_out = (raw_>>(24-x)& 0x001F)|(raw_>>(9-x)&0x03E0)|(raw_<<(6+x)&0x7C00);\ - if ( bits == 0 )\ - rgb_out = raw_ << x;\ -} -*/ - -/* custom bsnes routine -- hooks into bsnes colortable */ -#define SNES_NTSC_RGB_OUT_( rgb_out, bits, x ) {\ - if ( bits == 16 ) {\ - rgb_out = (raw_>>(13-x)& 0xF800)|(raw_>>(8-x)&0x07E0)|(raw_>>(4-x)&0x001F);\ - rgb_out = ((rgb_out&0xf800)>>11)|((rgb_out&0x07c0)>>1)|((rgb_out&0x001f)<<10);\ - rgb_out = colortable[rgb_out];\ - } else if ( bits == 24 || bits == 32 ) {\ - rgb_out = (raw_>>(5-x)&0xFF0000)|(raw_>>(3-x)&0xFF00)|(raw_>>(1-x)&0xFF);\ - rgb_out = ((rgb_out&0xf80000)>>19)|((rgb_out&0x00f800)>>6)|((rgb_out&0x0000f8)<<7);\ - rgb_out = colortable[rgb_out];\ - } else if ( bits == 15 ) {\ - rgb_out = (raw_>>(14-x)& 0x7C00)|(raw_>>(9-x)&0x03E0)|(raw_>>(4-x)&0x001F);\ - rgb_out = ((rgb_out&0x7c00)>>10)|((rgb_out&0x03e0))|((rgb_out&0x001f)<<10);\ - rgb_out = colortable[rgb_out];\ - } else {\ - rgb_out = raw_ << x;\ - }\ -} - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/snesfilter/ntsc/snes_ntsc/snes_ntsc_config.h b/snesfilter/ntsc/snes_ntsc/snes_ntsc_config.h deleted file mode 100644 index 7ab94c2c..00000000 --- a/snesfilter/ntsc/snes_ntsc/snes_ntsc_config.h +++ /dev/null @@ -1,26 +0,0 @@ -/* Configure library by modifying this file */ - -#ifndef SNES_NTSC_CONFIG_H -#define SNES_NTSC_CONFIG_H - -/* Format of source pixels */ -/* #define SNES_NTSC_IN_FORMAT SNES_NTSC_RGB16 */ -#define SNES_NTSC_IN_FORMAT SNES_NTSC_BGR15 - -/* The following affect the built-in blitter only; a custom blitter can -handle things however it wants. */ - -/* Bits per pixel of output. Can be 15, 16, 32, or 24 (same as 32). */ -#define SNES_NTSC_OUT_DEPTH 32 - -/* Type of input pixel values */ -#define SNES_NTSC_IN_T unsigned short - -/* Each raw pixel input value is passed through this. You might want to mask -the pixel index if you use the high bits as flags, etc. */ -#define SNES_NTSC_ADJ_IN( in ) in - -/* For each pixel, this is the basic operation: -output_color = SNES_NTSC_ADJ_IN( SNES_NTSC_IN_T ) */ - -#endif diff --git a/snesfilter/ntsc/snes_ntsc/snes_ntsc_impl.h b/snesfilter/ntsc/snes_ntsc/snes_ntsc_impl.h deleted file mode 100644 index 1d7adc78..00000000 --- a/snesfilter/ntsc/snes_ntsc/snes_ntsc_impl.h +++ /dev/null @@ -1,439 +0,0 @@ -/* snes_ntsc 0.2.2. http://www.slack.net/~ant/ */ - -/* Common implementation of NTSC filters */ - -#include -#include - -/* Copyright (C) 2006 Shay Green. This module 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 -module is distributed in the hope that 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 module; if not, write to the Free Software Foundation, -Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -#define DISABLE_CORRECTION 0 - -#undef PI -#define PI 3.14159265358979323846f - -#ifndef LUMA_CUTOFF - #define LUMA_CUTOFF 0.20 -#endif -#ifndef gamma_size - #define gamma_size 1 -#endif -#ifndef rgb_bits - #define rgb_bits 8 -#endif -#ifndef artifacts_max - #define artifacts_max (artifacts_mid * 1.5f) -#endif -#ifndef fringing_max - #define fringing_max (fringing_mid * 2) -#endif -#ifndef STD_HUE_CONDITION - #define STD_HUE_CONDITION( setup ) 1 -#endif - -#define ext_decoder_hue (std_decoder_hue + 15) -#define rgb_unit (1 << rgb_bits) -#define rgb_offset (rgb_unit * 2 + 0.5f) - -enum { burst_size = snes_ntsc_entry_size / burst_count }; -enum { kernel_half = 16 }; -enum { kernel_size = kernel_half * 2 + 1 }; - -typedef struct init_t -{ - float to_rgb [burst_count * 6]; - float to_float [gamma_size]; - float contrast; - float brightness; - float artifacts; - float fringing; - float kernel [rescale_out * kernel_size * 2]; -} init_t; - -#define ROTATE_IQ( i, q, sin_b, cos_b ) {\ - float t;\ - t = i * cos_b - q * sin_b;\ - q = i * sin_b + q * cos_b;\ - i = t;\ -} - -static void init_filters( init_t* impl, snes_ntsc_setup_t const* setup ) -{ -#if rescale_out > 1 - float kernels [kernel_size * 2]; -#else - float* const kernels = impl->kernel; -#endif - - /* generate luma (y) filter using sinc kernel */ - { - /* sinc with rolloff (dsf) */ - float const rolloff = 1 + (float) setup->sharpness * (float) 0.032; - float const maxh = 32; - float const pow_a_n = (float) pow( rolloff, maxh ); - float sum; - int i; - /* quadratic mapping to reduce negative (blurring) range */ - float to_angle = (float) setup->resolution + 1; - to_angle = PI / maxh * (float) LUMA_CUTOFF * (to_angle * to_angle + 1); - - kernels [kernel_size * 3 / 2] = maxh; /* default center value */ - for ( i = 0; i < kernel_half * 2 + 1; i++ ) - { - int x = i - kernel_half; - float angle = x * to_angle; - /* instability occurs at center point with rolloff very close to 1.0 */ - if ( x || pow_a_n > (float) 1.056 || pow_a_n < (float) 0.981 ) - { - float rolloff_cos_a = rolloff * (float) cos( angle ); - float num = 1 - rolloff_cos_a - - pow_a_n * (float) cos( maxh * angle ) + - pow_a_n * rolloff * (float) cos( (maxh - 1) * angle ); - float den = 1 - rolloff_cos_a - rolloff_cos_a + rolloff * rolloff; - float dsf = num / den; - kernels [kernel_size * 3 / 2 - kernel_half + i] = dsf - (float) 0.5; - } - } - - /* apply blackman window and find sum */ - sum = 0; - for ( i = 0; i < kernel_half * 2 + 1; i++ ) - { - float x = PI * 2 / (kernel_half * 2) * i; - float blackman = 0.42f - 0.5f * (float) cos( x ) + 0.08f * (float) cos( x * 2 ); - sum += (kernels [kernel_size * 3 / 2 - kernel_half + i] *= blackman); - } - - /* normalize kernel */ - sum = 1.0f / sum; - for ( i = 0; i < kernel_half * 2 + 1; i++ ) - { - int x = kernel_size * 3 / 2 - kernel_half + i; - kernels [x] *= sum; - assert( kernels [x] == kernels [x] ); /* catch numerical instability */ - } - } - - /* generate chroma (iq) filter using gaussian kernel */ - { - float const cutoff_factor = -0.03125f; - float cutoff = (float) setup->bleed; - int i; - - if ( cutoff < 0 ) - { - /* keep extreme value accessible only near upper end of scale (1.0) */ - cutoff *= cutoff; - cutoff *= cutoff; - cutoff *= cutoff; - cutoff *= -30.0f / 0.65f; - } - cutoff = cutoff_factor - 0.65f * cutoff_factor * cutoff; - - for ( i = -kernel_half; i <= kernel_half; i++ ) - kernels [kernel_size / 2 + i] = (float) exp( i * i * cutoff ); - - /* normalize even and odd phases separately */ - for ( i = 0; i < 2; i++ ) - { - float sum = 0; - int x; - for ( x = i; x < kernel_size; x += 2 ) - sum += kernels [x]; - - sum = 1.0f / sum; - for ( x = i; x < kernel_size; x += 2 ) - { - kernels [x] *= sum; - assert( kernels [x] == kernels [x] ); /* catch numerical instability */ - } - } - } - - /* - printf( "luma:\n" ); - for ( i = kernel_size; i < kernel_size * 2; i++ ) - printf( "%f\n", kernels [i] ); - printf( "chroma:\n" ); - for ( i = 0; i < kernel_size; i++ ) - printf( "%f\n", kernels [i] ); - */ - - /* generate linear rescale kernels */ - #if rescale_out > 1 - { - float weight = 1.0f; - float* out = impl->kernel; - int n = rescale_out; - do - { - float remain = 0; - int i; - weight -= 1.0f / rescale_in; - for ( i = 0; i < kernel_size * 2; i++ ) - { - float cur = kernels [i]; - float m = cur * weight; - *out++ = m + remain; - remain = cur - m; - } - } - while ( --n ); - } - #endif -} - -static float const default_decoder [6] = - { 0.956f, 0.621f, -0.272f, -0.647f, -1.105f, 1.702f }; - -static void init( init_t* impl, snes_ntsc_setup_t const* setup ) -{ - impl->brightness = (float) setup->brightness * (0.5f * rgb_unit) + rgb_offset; - impl->contrast = (float) setup->contrast * (0.5f * rgb_unit) + rgb_unit; - #ifdef default_palette_contrast - if ( !setup->palette ) - impl->contrast *= default_palette_contrast; - #endif - - impl->artifacts = (float) setup->artifacts; - if ( impl->artifacts > 0 ) - impl->artifacts *= artifacts_max - artifacts_mid; - impl->artifacts = impl->artifacts * artifacts_mid + artifacts_mid; - - impl->fringing = (float) setup->fringing; - if ( impl->fringing > 0 ) - impl->fringing *= fringing_max - fringing_mid; - impl->fringing = impl->fringing * fringing_mid + fringing_mid; - - init_filters( impl, setup ); - - /* generate gamma table */ - if ( gamma_size > 1 ) - { - float const to_float = 1.0f / (gamma_size - (gamma_size > 1)); - float const gamma = 1.1333f - (float) setup->gamma * 0.5f; - /* match common PC's 2.2 gamma to TV's 2.65 gamma */ - int i; - for ( i = 0; i < gamma_size; i++ ) - impl->to_float [i] = - (float) pow( i * to_float, gamma ) * impl->contrast + impl->brightness; - } - - /* setup decoder matricies */ - { - float hue = (float) setup->hue * PI + PI / 180 * ext_decoder_hue; - float sat = (float) setup->saturation + 1; - float const* decoder = setup->decoder_matrix; - if ( !decoder ) - { - decoder = default_decoder; - if ( STD_HUE_CONDITION( setup ) ) - hue += PI / 180 * (std_decoder_hue - ext_decoder_hue); - } - - { - float s = (float) sin( hue ) * sat; - float c = (float) cos( hue ) * sat; - float* out = impl->to_rgb; - int n; - - n = burst_count; - do - { - float const* in = decoder; - int n = 3; - do - { - float i = *in++; - float q = *in++; - *out++ = i * c - q * s; - *out++ = i * s + q * c; - } - while ( --n ); - if ( burst_count <= 1 ) - break; - ROTATE_IQ( s, c, 0.866025f, -0.5f ); /* +120 degrees */ - } - while ( --n ); - } - } -} - -/* kernel generation */ - -#define RGB_TO_YIQ( r, g, b, y, i ) (\ - (y = (r) * 0.299f + (g) * 0.587f + (b) * 0.114f),\ - (i = (r) * 0.596f - (g) * 0.275f - (b) * 0.321f),\ - ((r) * 0.212f - (g) * 0.523f + (b) * 0.311f)\ -) - -#define YIQ_TO_RGB( y, i, q, to_rgb, type, r, g ) (\ - r = (type) (y + to_rgb [0] * i + to_rgb [1] * q),\ - g = (type) (y + to_rgb [2] * i + to_rgb [3] * q),\ - (type) (y + to_rgb [4] * i + to_rgb [5] * q)\ -) - -#define PACK_RGB( r, g, b ) ((r) << 21 | (g) << 11 | (b) << 1) - -enum { rgb_kernel_size = burst_size / alignment_count }; -enum { rgb_bias = rgb_unit * 2 * snes_ntsc_rgb_builder }; - -typedef struct pixel_info_t -{ - int offset; - float negate; - float kernel [4]; -} pixel_info_t; - -#if rescale_in > 1 - #define PIXEL_OFFSET_( ntsc, scaled ) \ - (kernel_size / 2 + ntsc + (scaled != 0) + (rescale_out - scaled) % rescale_out + \ - (kernel_size * 2 * scaled)) - - #define PIXEL_OFFSET( ntsc, scaled ) \ - PIXEL_OFFSET_( ((ntsc) - (scaled) / rescale_out * rescale_in),\ - (((scaled) + rescale_out * 10) % rescale_out) ),\ - (1.0f - (((ntsc) + 100) & 2)) -#else - #define PIXEL_OFFSET( ntsc, scaled ) \ - (kernel_size / 2 + (ntsc) - (scaled)),\ - (1.0f - (((ntsc) + 100) & 2)) -#endif - -extern pixel_info_t const snes_ntsc_pixels [alignment_count]; - -/* Generate pixel at all burst phases and column alignments */ -static void gen_kernel( init_t* impl, float y, float i, float q, snes_ntsc_rgb_t* out ) -{ - /* generate for each scanline burst phase */ - float const* to_rgb = impl->to_rgb; - int burst_remain = burst_count; - y -= rgb_offset; - do - { - /* Encode yiq into *two* composite signals (to allow control over artifacting). - Convolve these with kernels which: filter respective components, apply - sharpening, and rescale horizontally. Convert resulting yiq to rgb and pack - into integer. Based on algorithm by NewRisingSun. */ - pixel_info_t const* pixel = snes_ntsc_pixels; - int alignment_remain = alignment_count; - do - { - /* negate is -1 when composite starts at odd multiple of 2 */ - float const yy = y * impl->fringing * pixel->negate; - float const ic0 = (i + yy) * pixel->kernel [0]; - float const qc1 = (q + yy) * pixel->kernel [1]; - float const ic2 = (i - yy) * pixel->kernel [2]; - float const qc3 = (q - yy) * pixel->kernel [3]; - - float const factor = impl->artifacts * pixel->negate; - float const ii = i * factor; - float const yc0 = (y + ii) * pixel->kernel [0]; - float const yc2 = (y - ii) * pixel->kernel [2]; - - float const qq = q * factor; - float const yc1 = (y + qq) * pixel->kernel [1]; - float const yc3 = (y - qq) * pixel->kernel [3]; - - float const* k = &impl->kernel [pixel->offset]; - int n; - ++pixel; - for ( n = rgb_kernel_size; n; --n ) - { - float i = k[0]*ic0 + k[2]*ic2; - float q = k[1]*qc1 + k[3]*qc3; - float y = k[kernel_size+0]*yc0 + k[kernel_size+1]*yc1 + - k[kernel_size+2]*yc2 + k[kernel_size+3]*yc3 + rgb_offset; - if ( rescale_out <= 1 ) - k--; - else if ( k < &impl->kernel [kernel_size * 2 * (rescale_out - 1)] ) - k += kernel_size * 2 - 1; - else - k -= kernel_size * 2 * (rescale_out - 1) + 2; - { - int r, g, b = YIQ_TO_RGB( y, i, q, to_rgb, int, r, g ); - *out++ = PACK_RGB( r, g, b ) - rgb_bias; - } - } - } - while ( alignment_count > 1 && --alignment_remain ); - - if ( burst_count <= 1 ) - break; - - to_rgb += 6; - - ROTATE_IQ( i, q, -0.866025f, -0.5f ); /* -120 degrees */ - } - while ( --burst_remain ); -} - -static void correct_errors( snes_ntsc_rgb_t color, snes_ntsc_rgb_t* out ); - -#if DISABLE_CORRECTION - #define CORRECT_ERROR( a ) { out [i] += rgb_bias; } - #define DISTRIBUTE_ERROR( a, b, c ) { out [i] += rgb_bias; } -#else - #define CORRECT_ERROR( a ) { out [a] += error; } - #define DISTRIBUTE_ERROR( a, b, c ) {\ - snes_ntsc_rgb_t fourth = (error + 2 * snes_ntsc_rgb_builder) >> 2;\ - fourth &= (rgb_bias >> 1) - snes_ntsc_rgb_builder;\ - fourth -= rgb_bias >> 2;\ - out [a] += fourth;\ - out [b] += fourth;\ - out [c] += fourth;\ - out [i] += error - (fourth * 3);\ - } -#endif - -#define RGB_PALETTE_OUT( rgb, out_ )\ -{\ - unsigned char* out = (out_);\ - snes_ntsc_rgb_t clamped = (rgb);\ - SNES_NTSC_CLAMP_( clamped, (8 - rgb_bits) );\ - out [0] = (unsigned char) (clamped >> 21);\ - out [1] = (unsigned char) (clamped >> 11);\ - out [2] = (unsigned char) (clamped >> 1);\ -} - -/* blitter related */ - -#ifndef restrict - #if defined (__GNUC__) - #define restrict __restrict__ - #elif defined (_MSC_VER) && _MSC_VER > 1300 - #define restrict __restrict - #else - /* no support for restricted pointers */ - #define restrict - #endif -#endif - -#include - -#if SNES_NTSC_OUT_DEPTH <= 16 - #if USHRT_MAX == 0xFFFF - typedef unsigned short snes_ntsc_out_t; - #else - #error "Need 16-bit int type" - #endif - -#else - #if UINT_MAX == 0xFFFFFFFF - typedef unsigned int snes_ntsc_out_t; - #elif ULONG_MAX == 0xFFFFFFFF - typedef unsigned long snes_ntsc_out_t; - #else - #error "Need 32-bit int type" - #endif - -#endif diff --git a/snesfilter/pixellate2x/pixellate2x.cpp b/snesfilter/pixellate2x/pixellate2x.cpp deleted file mode 100644 index 6259efc0..00000000 --- a/snesfilter/pixellate2x/pixellate2x.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#include "pixellate2x.hpp" - -void Pixellate2xFilter::size(unsigned &outwidth, unsigned &outheight, unsigned width, unsigned height) { - outwidth = (width <= 256) ? width * 2 : width; - outheight = (height <= 240) ? height * 2 : height; -} - -void Pixellate2xFilter::render( - uint32_t *output, unsigned outpitch, const uint16_t *input, unsigned pitch, - const unsigned *line, unsigned width, unsigned height -) { - pitch >>= 1; - outpitch >>= 2; - - uint32_t *out0 = output; - uint32_t *out1 = output + outpitch; - - for(unsigned y = 0; y < height; y++) { - unsigned linewidth = line[y]; - for(unsigned x = 0; x < linewidth; x++) { - uint32_t p = colortable[*input++]; - - *out0++ = p; - if(height <= 240) *out1++ = p; - if(linewidth > 256) continue; - - *out0++ = p; - if(height <= 240) *out1++ = p; - } - - input += pitch - linewidth; - if(height <= 240) { - out0 += outpitch + outpitch - 512; - out1 += outpitch + outpitch - 512; - } else { - out0 += outpitch - 512; - } - } -} diff --git a/snesfilter/pixellate2x/pixellate2x.hpp b/snesfilter/pixellate2x/pixellate2x.hpp deleted file mode 100644 index 4e597e4b..00000000 --- a/snesfilter/pixellate2x/pixellate2x.hpp +++ /dev/null @@ -1,5 +0,0 @@ -class Pixellate2xFilter { -public: - void size(unsigned&, unsigned&, unsigned, unsigned); - void render(uint32_t*, unsigned, const uint16_t*, unsigned, const unsigned*, unsigned, unsigned); -} filter_pixellate2x; diff --git a/snesfilter/scale2x/scale2x.cpp b/snesfilter/scale2x/scale2x.cpp deleted file mode 100644 index f1915ab3..00000000 --- a/snesfilter/scale2x/scale2x.cpp +++ /dev/null @@ -1,61 +0,0 @@ -#include "scale2x.hpp" - -void Scale2xFilter::size(unsigned &outwidth, unsigned &outheight, unsigned width, unsigned height) { - if(height > 240) return filter_direct.size(outwidth, outheight, width, height); - outwidth = (width <= 256) ? width * 2 : width; - outheight = (height <= 240) ? height * 2 : height; -} - -void Scale2xFilter::render( - uint32_t *output, unsigned outpitch, const uint16_t *input, unsigned pitch, - const unsigned *line, unsigned width, unsigned height -) { - if(height > 240) { - filter_direct.render(output, outpitch, input, pitch, line, width, height); - return; - } - - pitch >>= 1; - outpitch >>= 2; - - uint32_t *out0 = output; - uint32_t *out1 = output + outpitch; - - for(unsigned y = 0; y < height; y++) { - unsigned linewidth = line[y]; - - if(linewidth == 256) { - int prevline = (y == 0) || (linewidth != line[y - 1]) ? 0 : pitch; - int nextline = (y == height - 1) || (linewidth != line[y + 1]) ? 0 : pitch; - - for(unsigned x = 0; x < 256; x++) { - uint16_t A = *(input - prevline); - uint16_t B = (x > 0) ? *(input - 1) : *input; - uint16_t C = *input; - uint16_t D = (x < 255) ? *(input + 1) : *input; - uint16_t E = *(input++ + nextline); - uint32_t c = colortable[C]; - - if(A != E && B != D) { - *out0++ = (A == B ? colortable[A] : c); - *out0++ = (A == D ? colortable[A] : c); - *out1++ = (E == B ? colortable[E] : c); - *out1++ = (E == D ? colortable[E] : c); - } else { - *out0++ = c; - *out0++ = c; - *out1++ = c; - *out1++ = c; - } - } - } else { - for(unsigned x = 0; x < 512; x++) { - *out0++ = *out1++ = colortable[*input++]; - } - } - - input += pitch - linewidth; - out0 += outpitch + outpitch - 512; - out1 += outpitch + outpitch - 512; - } -} diff --git a/snesfilter/scale2x/scale2x.hpp b/snesfilter/scale2x/scale2x.hpp deleted file mode 100644 index fad44e6a..00000000 --- a/snesfilter/scale2x/scale2x.hpp +++ /dev/null @@ -1,5 +0,0 @@ -class Scale2xFilter { -public: - void size(unsigned&, unsigned&, unsigned, unsigned); - void render(uint32_t*, unsigned, const uint16_t*, unsigned, const unsigned*, unsigned, unsigned); -} filter_scale2x; diff --git a/snesfilter/snesfilter.cpp b/snesfilter/snesfilter.cpp deleted file mode 100644 index b73b9072..00000000 --- a/snesfilter/snesfilter.cpp +++ /dev/null @@ -1,84 +0,0 @@ -#include "snesfilter.hpp" - -#if defined(_WIN32) - #define dllexport __declspec(dllexport) -#else - #define dllexport -#endif - -#include -#include -#include - -#define QT_CORE_LIB -#include - -#include -#include -#include -using namespace nall; - -const uint32_t *colortable; -configuration *config; - -#include "direct/direct.cpp" -#include "pixellate2x/pixellate2x.cpp" -#include "scale2x/scale2x.cpp" -#include "2xsai/2xsai.cpp" -#include "lq2x/lq2x.cpp" -#include "hq2x/hq2x.cpp" -#include "ntsc/ntsc.cpp" - -dllexport const char* snesfilter_supported() { - return "Pixellate2x;Scale2x;2xSaI;Super 2xSaI;Super Eagle;LQ2x;HQ2x;NTSC"; -} - -dllexport void snesfilter_configuration(configuration &config_) { - config = &config_; - if(config) { - filter_ntsc.bind(*config); - } -} - -dllexport void snesfilter_colortable(const uint32_t *colortable_) { - colortable = colortable_; -} - -dllexport void snesfilter_size(unsigned filter, unsigned &outwidth, unsigned &outheight, unsigned width, unsigned height) { - switch(filter) { - default: return filter_direct.size(outwidth, outheight, width, height); - case 1: return filter_pixellate2x.size(outwidth, outheight, width, height); - case 2: return filter_scale2x.size(outwidth, outheight, width, height); - case 3: return filter_2xsai.size(outwidth, outheight, width, height); - case 4: return filter_super2xsai.size(outwidth, outheight, width, height); - case 5: return filter_supereagle.size(outwidth, outheight, width, height); - case 6: return filter_lq2x.size(outwidth, outheight, width, height); - case 7: return filter_hq2x.size(outwidth, outheight, width, height); - case 8: return filter_ntsc.size(outwidth, outheight, width, height); - } -} - -dllexport void snesfilter_render( - unsigned filter, uint32_t *output, unsigned outpitch, - const uint16_t *input, unsigned pitch, - const unsigned *line, unsigned width, unsigned height -) { - switch(filter) { - default: return filter_direct.render(output, outpitch, input, pitch, line, width, height); - case 1: return filter_pixellate2x.render(output, outpitch, input, pitch, line, width, height); - case 2: return filter_scale2x.render(output, outpitch, input, pitch, line, width, height); - case 3: return filter_2xsai.render(output, outpitch, input, pitch, line, width, height); - case 4: return filter_super2xsai.render(output, outpitch, input, pitch, line, width, height); - case 5: return filter_supereagle.render(output, outpitch, input, pitch, line, width, height); - case 6: return filter_lq2x.render(output, outpitch, input, pitch, line, width, height); - case 7: return filter_hq2x.render(output, outpitch, input, pitch, line, width, height); - case 8: return filter_ntsc.render(output, outpitch, input, pitch, line, width, height); - } -} - -dllexport QWidget* snesfilter_settings(unsigned filter) { - switch(filter) { - default: return 0; - case 8: return filter_ntsc.settings(); - } -} diff --git a/snesfilter/snesfilter.hpp b/snesfilter/snesfilter.hpp deleted file mode 100644 index 15a5ba4a..00000000 --- a/snesfilter/snesfilter.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#include -class QWidget; -namespace nall { class configuration; } - -extern "C" { - const char* snesfilter_supported(); - void snesfilter_configuration(nall::configuration&); - void snesfilter_colortable(const uint32_t*); - void snesfilter_size(unsigned, unsigned&, unsigned&, unsigned, unsigned); - void snesfilter_render( - unsigned, uint32_t*, unsigned, - const uint16_t*, unsigned, - const unsigned*, unsigned, unsigned - ); - QWidget* snesfilter_settings(unsigned); -} diff --git a/snesfilter/sync.sh b/snesfilter/sync.sh deleted file mode 100644 index 4bbaf34f..00000000 --- a/snesfilter/sync.sh +++ /dev/null @@ -1,2 +0,0 @@ -rm -r nall -cp -r ../nall ./nall diff --git a/snesreader/7z_C/7zAlloc.c b/snesreader/7z_C/7zAlloc.c deleted file mode 100644 index 4bfaf42a..00000000 --- a/snesreader/7z_C/7zAlloc.c +++ /dev/null @@ -1,77 +0,0 @@ -/* 7zAlloc.c -- Allocation functions -2008-10-04 : Igor Pavlov : Public domain */ - -#include -#include "7zAlloc.h" - -/* #define _SZ_ALLOC_DEBUG */ -/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */ - -#ifdef _SZ_ALLOC_DEBUG - -#ifdef _WIN32 -#include -#endif - -#include -int g_allocCount = 0; -int g_allocCountTemp = 0; - -#endif - -void *SzAlloc(void *p, size_t size) -{ - p = p; - if (size == 0) - return 0; - #ifdef _SZ_ALLOC_DEBUG - fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount); - g_allocCount++; - #endif - return malloc(size); -} - -void SzFree(void *p, void *address) -{ - p = p; - #ifdef _SZ_ALLOC_DEBUG - if (address != 0) - { - g_allocCount--; - fprintf(stderr, "\nFree; count = %10d", g_allocCount); - } - #endif - free(address); -} - -void *SzAllocTemp(void *p, size_t size) -{ - p = p; - if (size == 0) - return 0; - #ifdef _SZ_ALLOC_DEBUG - fprintf(stderr, "\nAlloc_temp %10d bytes; count = %10d", size, g_allocCountTemp); - g_allocCountTemp++; - #ifdef _WIN32 - return HeapAlloc(GetProcessHeap(), 0, size); - #endif - #endif - return malloc(size); -} - -void SzFreeTemp(void *p, void *address) -{ - p = p; - #ifdef _SZ_ALLOC_DEBUG - if (address != 0) - { - g_allocCountTemp--; - fprintf(stderr, "\nFree_temp; count = %10d", g_allocCountTemp); - } - #ifdef _WIN32 - HeapFree(GetProcessHeap(), 0, address); - return; - #endif - #endif - free(address); -} diff --git a/snesreader/7z_C/7zAlloc.h b/snesreader/7z_C/7zAlloc.h deleted file mode 100644 index f84ca5ae..00000000 --- a/snesreader/7z_C/7zAlloc.h +++ /dev/null @@ -1,23 +0,0 @@ -/* 7zAlloc.h -- Allocation functions -2008-10-04 : Igor Pavlov : Public domain */ - -#ifndef __7Z_ALLOC_H -#define __7Z_ALLOC_H - -#include - -#ifdef __cplusplus - extern "C" { -#endif - -void *SzAlloc(void *p, size_t size); -void SzFree(void *p, void *address); - -void *SzAllocTemp(void *p, size_t size); -void SzFreeTemp(void *p, void *address); - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/snesreader/7z_C/7zBuf.c b/snesreader/7z_C/7zBuf.c deleted file mode 100644 index 14e7f4e2..00000000 --- a/snesreader/7z_C/7zBuf.c +++ /dev/null @@ -1,36 +0,0 @@ -/* 7zBuf.c -- Byte Buffer -2008-03-28 -Igor Pavlov -Public domain */ - -#include "7zBuf.h" - -void Buf_Init(CBuf *p) -{ - p->data = 0; - p->size = 0; -} - -int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc) -{ - p->size = 0; - if (size == 0) - { - p->data = 0; - return 1; - } - p->data = (Byte *)alloc->Alloc(alloc, size); - if (p->data != 0) - { - p->size = size; - return 1; - } - return 0; -} - -void Buf_Free(CBuf *p, ISzAlloc *alloc) -{ - alloc->Free(alloc, p->data); - p->data = 0; - p->size = 0; -} diff --git a/snesreader/7z_C/7zBuf.h b/snesreader/7z_C/7zBuf.h deleted file mode 100644 index c5bd7187..00000000 --- a/snesreader/7z_C/7zBuf.h +++ /dev/null @@ -1,31 +0,0 @@ -/* 7zBuf.h -- Byte Buffer -2008-10-04 : Igor Pavlov : Public domain */ - -#ifndef __7Z_BUF_H -#define __7Z_BUF_H - -#include "Types.h" - -typedef struct -{ - Byte *data; - size_t size; -} CBuf; - -void Buf_Init(CBuf *p); -int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc); -void Buf_Free(CBuf *p, ISzAlloc *alloc); - -typedef struct -{ - Byte *data; - size_t size; - size_t pos; -} CDynBuf; - -void DynBuf_Construct(CDynBuf *p); -void DynBuf_SeekToBeg(CDynBuf *p); -int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc); -void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc); - -#endif diff --git a/snesreader/7z_C/7zC.txt b/snesreader/7z_C/7zC.txt deleted file mode 100644 index 4ff63250..00000000 --- a/snesreader/7z_C/7zC.txt +++ /dev/null @@ -1,194 +0,0 @@ -7z ANSI-C Decoder 4.62 ----------------------- - -7z ANSI-C provides 7z/LZMA decoding. -7z ANSI-C version is simplified version ported from C++ code. - -LZMA is default and general compression method of 7z format -in 7-Zip compression program (www.7-zip.org). LZMA provides high -compression ratio and very fast decompression. - - -LICENSE -------- - -7z ANSI-C Decoder is part of the LZMA SDK. -LZMA SDK is written and placed in the public domain by Igor Pavlov. - -Files ---------------------- - -7zDecode.* - Low level 7z decoding -7zExtract.* - High level 7z decoding -7zHeader.* - .7z format constants -7zIn.* - .7z archive opening -7zItem.* - .7z structures -7zMain.c - Test application - - -How To Use ----------- - -You must download 7-Zip program from www.7-zip.org. - -You can create .7z archive with 7z.exe or 7za.exe: - - 7za.exe a archive.7z *.htm -r -mx -m0fb=255 - -If you have big number of files in archive, and you need fast extracting, -you can use partly-solid archives: - - 7za.exe a archive.7z *.htm -ms=512K -r -mx -m0fb=255 -m0d=512K - -In that example 7-Zip will use 512KB solid blocks. So it needs to decompress only -512KB for extracting one file from such archive. - - -Limitations of current version of 7z ANSI-C Decoder ---------------------------------------------------- - - - It reads only "FileName", "Size", "LastWriteTime" and "CRC" information for each file in archive. - - It supports only LZMA and Copy (no compression) methods with BCJ or BCJ2 filters. - - It converts original UTF-16 Unicode file names to UTF-8 Unicode file names. - -These limitations will be fixed in future versions. - - -Using 7z ANSI-C Decoder Test application: ------------------------------------------ - -Usage: 7zDec - -: - e: Extract files from archive - l: List contents of archive - t: Test integrity of archive - -Example: - - 7zDec l archive.7z - -lists contents of archive.7z - - 7zDec e archive.7z - -extracts files from archive.7z to current folder. - - -How to use .7z Decoder ----------------------- - -Memory allocation -~~~~~~~~~~~~~~~~~ - -7z Decoder uses two memory pools: -1) Temporary pool -2) Main pool -Such scheme can allow you to avoid fragmentation of allocated blocks. - - -Steps for using 7z decoder --------------------------- - -Use code at 7zMain.c as example. - -1) Declare variables: - inStream /* implements ILookInStream interface */ - CSzArEx db; /* 7z archive database structure */ - ISzAlloc allocImp; /* memory functions for main pool */ - ISzAlloc allocTempImp; /* memory functions for temporary pool */ - -2) call CrcGenerateTable(); function to initialize CRC structures. - -3) call SzArEx_Init(&db); function to initialize db structures. - -4) call SzArEx_Open(&db, inStream, &allocMain, &allocTemp) to open archive - -This function opens archive "inStream" and reads headers to "db". -All items in "db" will be allocated with "allocMain" functions. -SzArEx_Open function allocates and frees temporary structures by "allocTemp" functions. - -5) List items or Extract items - - Listing code: - ~~~~~~~~~~~~~ - { - UInt32 i; - for (i = 0; i < db.db.NumFiles; i++) - { - CFileItem *f = db.db.Files + i; - printf("%10d %s\n", (int)f->Size, f->Name); - } - } - - Extracting code: - ~~~~~~~~~~~~~~~~ - - SZ_RESULT SzAr_Extract( - CArchiveDatabaseEx *db, - ILookInStream *inStream, - UInt32 fileIndex, /* index of file */ - UInt32 *blockIndex, /* index of solid block */ - Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ - size_t *outBufferSize, /* buffer size for output buffer */ - size_t *offset, /* offset of stream for required file in *outBuffer */ - size_t *outSizeProcessed, /* size of file in *outBuffer */ - ISzAlloc *allocMain, - ISzAlloc *allocTemp); - - If you need to decompress more than one file, you can send these values from previous call: - blockIndex, - outBuffer, - outBufferSize, - You can consider "outBuffer" as cache of solid block. If your archive is solid, - it will increase decompression speed. - - After decompressing you must free "outBuffer": - allocImp.Free(outBuffer); - -6) call SzArEx_Free(&db, allocImp.Free) to free allocated items in "db". - - - - -Memory requirements for .7z decoding ------------------------------------- - -Memory usage for Archive opening: - - Temporary pool: - - Memory for uncompressed .7z headers - - some other temporary blocks - - Main pool: - - Memory for database: - Estimated size of one file structures in solid archive: - - Size (4 or 8 Bytes) - - CRC32 (4 bytes) - - LastWriteTime (8 bytes) - - Some file information (4 bytes) - - File Name (variable length) + pointer + allocation structures - -Memory usage for archive Decompressing: - - Temporary pool: - - Memory for LZMA decompressing structures - - Main pool: - - Memory for decompressed solid block - - Memory for temprorary buffers, if BCJ2 fileter is used. Usually these - temprorary buffers can be about 15% of solid block size. - - -7z Decoder doesn't allocate memory for compressed blocks. -Instead of this, you must allocate buffer with desired -size before calling 7z Decoder. Use 7zMain.c as example. - - -Defines -------- - -_SZ_ALLOC_DEBUG - define it if you want to debug alloc/free operations to stderr. - - ---- - -http://www.7-zip.org -http://www.7-zip.org/sdk.html -http://www.7-zip.org/support.html diff --git a/snesreader/7z_C/7zCrc.c b/snesreader/7z_C/7zCrc.c deleted file mode 100644 index 71962b2c..00000000 --- a/snesreader/7z_C/7zCrc.c +++ /dev/null @@ -1,35 +0,0 @@ -/* 7zCrc.c -- CRC32 calculation -2008-08-05 -Igor Pavlov -Public domain */ - -#include "7zCrc.h" - -#define kCrcPoly 0xEDB88320 -UInt32 g_CrcTable[256]; - -void MY_FAST_CALL CrcGenerateTable(void) -{ - UInt32 i; - for (i = 0; i < 256; i++) - { - UInt32 r = i; - int j; - for (j = 0; j < 8; j++) - r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1)); - g_CrcTable[i] = r; - } -} - -UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size) -{ - const Byte *p = (const Byte *)data; - for (; size > 0 ; size--, p++) - v = CRC_UPDATE_BYTE(v, *p); - return v; -} - -UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size) -{ - return CrcUpdate(CRC_INIT_VAL, data, size) ^ 0xFFFFFFFF; -} diff --git a/snesreader/7z_C/7zCrc.h b/snesreader/7z_C/7zCrc.h deleted file mode 100644 index ab8cf8c4..00000000 --- a/snesreader/7z_C/7zCrc.h +++ /dev/null @@ -1,32 +0,0 @@ -/* 7zCrc.h -- CRC32 calculation -2008-03-13 -Igor Pavlov -Public domain */ - -#ifndef __7Z_CRC_H -#define __7Z_CRC_H - -#include - -#include "Types.h" - -#ifdef __cplusplus - extern "C" { -#endif - -extern UInt32 g_CrcTable[]; - -void MY_FAST_CALL CrcGenerateTable(void); - -#define CRC_INIT_VAL 0xFFFFFFFF -#define CRC_GET_DIGEST(crc) ((crc) ^ 0xFFFFFFFF) -#define CRC_UPDATE_BYTE(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8)) - -UInt32 MY_FAST_CALL CrcUpdate(UInt32 crc, const void *data, size_t size); -UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size); - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/snesreader/7z_C/7zDecode.c b/snesreader/7z_C/7zDecode.c deleted file mode 100644 index c643da5f..00000000 --- a/snesreader/7z_C/7zDecode.c +++ /dev/null @@ -1,257 +0,0 @@ -/* 7zDecode.c -- Decoding from 7z folder -2008-11-23 : Igor Pavlov : Public domain */ - -#include - -#include "Bcj2.h" -#include "Bra.h" -#include "LzmaDec.h" -#include "7zDecode.h" - -#define k_Copy 0 -#define k_LZMA 0x30101 -#define k_BCJ 0x03030103 -#define k_BCJ2 0x0303011B - -static SRes SzDecodeLzma(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream, - Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain) -{ - CLzmaDec state; - SRes res = SZ_OK; - - LzmaDec_Construct(&state); - RINOK(LzmaDec_AllocateProbs(&state, coder->Props.data, (unsigned)coder->Props.size, allocMain)); - state.dic = outBuffer; - state.dicBufSize = outSize; - LzmaDec_Init(&state); - - for (;;) - { - Byte *inBuf = NULL; - size_t lookahead = (1 << 18); - if (lookahead > inSize) - lookahead = (size_t)inSize; - res = inStream->Look((void *)inStream, (void **)&inBuf, &lookahead); - if (res != SZ_OK) - break; - - { - SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos; - ELzmaStatus status; - res = LzmaDec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status); - lookahead -= inProcessed; - inSize -= inProcessed; - if (res != SZ_OK) - break; - if (state.dicPos == state.dicBufSize || (inProcessed == 0 && dicPos == state.dicPos)) - { - if (state.dicBufSize != outSize || lookahead != 0 || - (status != LZMA_STATUS_FINISHED_WITH_MARK && - status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK)) - res = SZ_ERROR_DATA; - break; - } - res = inStream->Skip((void *)inStream, inProcessed); - if (res != SZ_OK) - break; - } - } - - LzmaDec_FreeProbs(&state, allocMain); - return res; -} - -static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer) -{ - while (inSize > 0) - { - void *inBuf; - size_t curSize = (1 << 18); - if (curSize > inSize) - curSize = (size_t)inSize; - RINOK(inStream->Look((void *)inStream, (void **)&inBuf, &curSize)); - if (curSize == 0) - return SZ_ERROR_INPUT_EOF; - memcpy(outBuffer, inBuf, curSize); - outBuffer += curSize; - inSize -= curSize; - RINOK(inStream->Skip((void *)inStream, curSize)); - } - return SZ_OK; -} - -#define IS_UNSUPPORTED_METHOD(m) ((m) != k_Copy && (m) != k_LZMA) -#define IS_UNSUPPORTED_CODER(c) (IS_UNSUPPORTED_METHOD(c.MethodID) || c.NumInStreams != 1 || c.NumOutStreams != 1) -#define IS_NO_BCJ(c) (c.MethodID != k_BCJ || c.NumInStreams != 1 || c.NumOutStreams != 1) -#define IS_NO_BCJ2(c) (c.MethodID != k_BCJ2 || c.NumInStreams != 4 || c.NumOutStreams != 1) - -static -SRes CheckSupportedFolder(const CSzFolder *f) -{ - if (f->NumCoders < 1 || f->NumCoders > 4) - return SZ_ERROR_UNSUPPORTED; - if (IS_UNSUPPORTED_CODER(f->Coders[0])) - return SZ_ERROR_UNSUPPORTED; - if (f->NumCoders == 1) - { - if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0) - return SZ_ERROR_UNSUPPORTED; - return SZ_OK; - } - if (f->NumCoders == 2) - { - if (IS_NO_BCJ(f->Coders[1]) || - f->NumPackStreams != 1 || f->PackStreams[0] != 0 || - f->NumBindPairs != 1 || - f->BindPairs[0].InIndex != 1 || f->BindPairs[0].OutIndex != 0) - return SZ_ERROR_UNSUPPORTED; - return SZ_OK; - } - if (f->NumCoders == 4) - { - if (IS_UNSUPPORTED_CODER(f->Coders[1]) || - IS_UNSUPPORTED_CODER(f->Coders[2]) || - IS_NO_BCJ2(f->Coders[3])) - return SZ_ERROR_UNSUPPORTED; - if (f->NumPackStreams != 4 || - f->PackStreams[0] != 2 || - f->PackStreams[1] != 6 || - f->PackStreams[2] != 1 || - f->PackStreams[3] != 0 || - f->NumBindPairs != 3 || - f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 || - f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 || - f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2) - return SZ_ERROR_UNSUPPORTED; - return SZ_OK; - } - return SZ_ERROR_UNSUPPORTED; -} - -static -UInt64 GetSum(const UInt64 *values, UInt32 index) -{ - UInt64 sum = 0; - UInt32 i; - for (i = 0; i < index; i++) - sum += values[i]; - return sum; -} - -static -SRes SzDecode2(const UInt64 *packSizes, const CSzFolder *folder, - ILookInStream *inStream, UInt64 startPos, - Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain, - Byte *tempBuf[]) -{ - UInt32 ci; - SizeT tempSizes[3] = { 0, 0, 0}; - SizeT tempSize3 = 0; - Byte *tempBuf3 = 0; - - RINOK(CheckSupportedFolder(folder)); - - for (ci = 0; ci < folder->NumCoders; ci++) - { - CSzCoderInfo *coder = &folder->Coders[ci]; - - if (coder->MethodID == k_Copy || coder->MethodID == k_LZMA) - { - UInt32 si = 0; - UInt64 offset; - UInt64 inSize; - Byte *outBufCur = outBuffer; - SizeT outSizeCur = outSize; - if (folder->NumCoders == 4) - { - UInt32 indices[] = { 3, 2, 0 }; - UInt64 unpackSize = folder->UnpackSizes[ci]; - si = indices[ci]; - if (ci < 2) - { - Byte *temp; - outSizeCur = (SizeT)unpackSize; - if (outSizeCur != unpackSize) - return SZ_ERROR_MEM; - temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur); - if (temp == 0 && outSizeCur != 0) - return SZ_ERROR_MEM; - outBufCur = tempBuf[1 - ci] = temp; - tempSizes[1 - ci] = outSizeCur; - } - else if (ci == 2) - { - if (unpackSize > outSize) /* check it */ - return SZ_ERROR_PARAM; - tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize); - tempSize3 = outSizeCur = (SizeT)unpackSize; - } - else - return SZ_ERROR_UNSUPPORTED; - } - offset = GetSum(packSizes, si); - inSize = packSizes[si]; - RINOK(LookInStream_SeekTo(inStream, startPos + offset)); - - if (coder->MethodID == k_Copy) - { - if (inSize != outSizeCur) /* check it */ - return SZ_ERROR_DATA; - RINOK(SzDecodeCopy(inSize, inStream, outBufCur)); - } - else - { - RINOK(SzDecodeLzma(coder, inSize, inStream, outBufCur, outSizeCur, allocMain)); - } - } - else if (coder->MethodID == k_BCJ) - { - UInt32 state; - if (ci != 1) - return SZ_ERROR_UNSUPPORTED; - x86_Convert_Init(state); - x86_Convert(outBuffer, outSize, 0, &state, 0); - } - else if (coder->MethodID == k_BCJ2) - { - UInt64 offset = GetSum(packSizes, 1); - UInt64 s3Size = packSizes[1]; - SRes res; - if (ci != 3) - return SZ_ERROR_UNSUPPORTED; - RINOK(LookInStream_SeekTo(inStream, startPos + offset)); - tempSizes[2] = (SizeT)s3Size; - if (tempSizes[2] != s3Size) - return SZ_ERROR_MEM; - tempBuf[2] = (Byte *)IAlloc_Alloc(allocMain, tempSizes[2]); - if (tempBuf[2] == 0 && tempSizes[2] != 0) - return SZ_ERROR_MEM; - res = SzDecodeCopy(s3Size, inStream, tempBuf[2]); - RINOK(res) - - res = Bcj2_Decode( - tempBuf3, tempSize3, - tempBuf[0], tempSizes[0], - tempBuf[1], tempSizes[1], - tempBuf[2], tempSizes[2], - outBuffer, outSize); - RINOK(res) - } - else - return SZ_ERROR_UNSUPPORTED; - } - return SZ_OK; -} - -SRes SzDecode(const UInt64 *packSizes, const CSzFolder *folder, - ILookInStream *inStream, UInt64 startPos, - Byte *outBuffer, size_t outSize, ISzAlloc *allocMain) -{ - Byte *tempBuf[3] = { 0, 0, 0}; - int i; - SRes res = SzDecode2(packSizes, folder, inStream, startPos, - outBuffer, (SizeT)outSize, allocMain, tempBuf); - for (i = 0; i < 3; i++) - IAlloc_Free(allocMain, tempBuf[i]); - return res; -} diff --git a/snesreader/7z_C/7zDecode.h b/snesreader/7z_C/7zDecode.h deleted file mode 100644 index e19fe387..00000000 --- a/snesreader/7z_C/7zDecode.h +++ /dev/null @@ -1,13 +0,0 @@ -/* 7zDecode.h -- Decoding from 7z folder -2008-11-23 : Igor Pavlov : Public domain */ - -#ifndef __7Z_DECODE_H -#define __7Z_DECODE_H - -#include "7zItem.h" - -SRes SzDecode(const UInt64 *packSizes, const CSzFolder *folder, - ILookInStream *stream, UInt64 startPos, - Byte *outBuffer, size_t outSize, ISzAlloc *allocMain); - -#endif diff --git a/snesreader/7z_C/7zExtract.c b/snesreader/7z_C/7zExtract.c deleted file mode 100644 index 99ef3654..00000000 --- a/snesreader/7z_C/7zExtract.c +++ /dev/null @@ -1,93 +0,0 @@ -/* 7zExtract.c -- Extracting from 7z archive -2008-11-23 : Igor Pavlov : Public domain */ - -#include "7zCrc.h" -#include "7zDecode.h" -#include "7zExtract.h" - -SRes SzAr_Extract( - const CSzArEx *p, - ILookInStream *inStream, - UInt32 fileIndex, - UInt32 *blockIndex, - Byte **outBuffer, - size_t *outBufferSize, - size_t *offset, - size_t *outSizeProcessed, - ISzAlloc *allocMain, - ISzAlloc *allocTemp) -{ - UInt32 folderIndex = p->FileIndexToFolderIndexMap[fileIndex]; - SRes res = SZ_OK; - *offset = 0; - *outSizeProcessed = 0; - if (folderIndex == (UInt32)-1) - { - IAlloc_Free(allocMain, *outBuffer); - *blockIndex = folderIndex; - *outBuffer = 0; - *outBufferSize = 0; - return SZ_OK; - } - - if (*outBuffer == 0 || *blockIndex != folderIndex) - { - CSzFolder *folder = p->db.Folders + folderIndex; - UInt64 unpackSizeSpec = SzFolder_GetUnpackSize(folder); - size_t unpackSize = (size_t)unpackSizeSpec; - UInt64 startOffset = SzArEx_GetFolderStreamPos(p, folderIndex, 0); - - if (unpackSize != unpackSizeSpec) - return SZ_ERROR_MEM; - *blockIndex = folderIndex; - IAlloc_Free(allocMain, *outBuffer); - *outBuffer = 0; - - RINOK(LookInStream_SeekTo(inStream, startOffset)); - - if (res == SZ_OK) - { - *outBufferSize = unpackSize; - if (unpackSize != 0) - { - *outBuffer = (Byte *)IAlloc_Alloc(allocMain, unpackSize); - if (*outBuffer == 0) - res = SZ_ERROR_MEM; - } - if (res == SZ_OK) - { - res = SzDecode(p->db.PackSizes + - p->FolderStartPackStreamIndex[folderIndex], folder, - inStream, startOffset, - *outBuffer, unpackSize, allocTemp); - if (res == SZ_OK) - { - if (folder->UnpackCRCDefined) - { - if (CrcCalc(*outBuffer, unpackSize) != folder->UnpackCRC) - res = SZ_ERROR_CRC; - } - } - } - } - } - if (res == SZ_OK) - { - UInt32 i; - CSzFileItem *fileItem = p->db.Files + fileIndex; - *offset = 0; - for (i = p->FolderStartFileIndex[folderIndex]; i < fileIndex; i++) - *offset += (UInt32)p->db.Files[i].Size; - *outSizeProcessed = (size_t)fileItem->Size; - if (*offset + *outSizeProcessed > *outBufferSize) - return SZ_ERROR_FAIL; - { - if (fileItem->FileCRCDefined) - { - if (CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->FileCRC) - res = SZ_ERROR_CRC; - } - } - } - return res; -} diff --git a/snesreader/7z_C/7zExtract.h b/snesreader/7z_C/7zExtract.h deleted file mode 100644 index 1ca110c6..00000000 --- a/snesreader/7z_C/7zExtract.h +++ /dev/null @@ -1,49 +0,0 @@ -/* 7zExtract.h -- Extracting from 7z archive -2008-11-23 : Igor Pavlov : Public domain */ - -#ifndef __7Z_EXTRACT_H -#define __7Z_EXTRACT_H - -#include "7zIn.h" - -#ifdef __cplusplus - extern "C" { -#endif - -/* - SzExtract extracts file from archive - - *outBuffer must be 0 before first call for each new archive. - - Extracting cache: - If you need to decompress more than one file, you can send - these values from previous call: - *blockIndex, - *outBuffer, - *outBufferSize - You can consider "*outBuffer" as cache of solid block. If your archive is solid, - it will increase decompression speed. - - If you use external function, you can declare these 3 cache variables - (blockIndex, outBuffer, outBufferSize) as static in that external function. - - Free *outBuffer and set *outBuffer to 0, if you want to flush cache. -*/ - -SRes SzAr_Extract( - const CSzArEx *db, - ILookInStream *inStream, - UInt32 fileIndex, /* index of file */ - UInt32 *blockIndex, /* index of solid block */ - Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */ - size_t *outBufferSize, /* buffer size for output buffer */ - size_t *offset, /* offset of stream for required file in *outBuffer */ - size_t *outSizeProcessed, /* size of file in *outBuffer */ - ISzAlloc *allocMain, - ISzAlloc *allocTemp); - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/snesreader/7z_C/7zHeader.c b/snesreader/7z_C/7zHeader.c deleted file mode 100644 index e48faa48..00000000 --- a/snesreader/7z_C/7zHeader.c +++ /dev/null @@ -1,6 +0,0 @@ -/* 7zHeader.c -- 7z Headers -2008-10-04 : Igor Pavlov : Public domain */ - -#include "7zHeader.h" - -Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C}; diff --git a/snesreader/7z_C/7zHeader.h b/snesreader/7z_C/7zHeader.h deleted file mode 100644 index ad095df4..00000000 --- a/snesreader/7z_C/7zHeader.h +++ /dev/null @@ -1,57 +0,0 @@ -/* 7zHeader.h -- 7z Headers -2008-10-04 : Igor Pavlov : Public domain */ - -#ifndef __7Z_HEADER_H -#define __7Z_HEADER_H - -#include "Types.h" - -#define k7zSignatureSize 6 -extern Byte k7zSignature[k7zSignatureSize]; - -#define k7zMajorVersion 0 - -#define k7zStartHeaderSize 0x20 - -enum EIdEnum -{ - k7zIdEnd, - - k7zIdHeader, - - k7zIdArchiveProperties, - - k7zIdAdditionalStreamsInfo, - k7zIdMainStreamsInfo, - k7zIdFilesInfo, - - k7zIdPackInfo, - k7zIdUnpackInfo, - k7zIdSubStreamsInfo, - - k7zIdSize, - k7zIdCRC, - - k7zIdFolder, - - k7zIdCodersUnpackSize, - k7zIdNumUnpackStream, - - k7zIdEmptyStream, - k7zIdEmptyFile, - k7zIdAnti, - - k7zIdName, - k7zIdCTime, - k7zIdATime, - k7zIdMTime, - k7zIdWinAttributes, - k7zIdComment, - - k7zIdEncodedHeader, - - k7zIdStartPos, - k7zIdDummy -}; - -#endif diff --git a/snesreader/7z_C/7zIn.c b/snesreader/7z_C/7zIn.c deleted file mode 100644 index e594b7de..00000000 --- a/snesreader/7z_C/7zIn.c +++ /dev/null @@ -1,1204 +0,0 @@ -/* 7zIn.c -- 7z Input functions -2008-12-31 : Igor Pavlov : Public domain */ - -#include "7zCrc.h" -#include "CpuArch.h" - -#include "7zDecode.h" -#include "7zIn.h" - -#define RINOM(x) { if ((x) == 0) return SZ_ERROR_MEM; } - -#define NUM_FOLDER_CODERS_MAX 32 -#define NUM_CODER_STREAMS_MAX 32 - -void SzArEx_Init(CSzArEx *p) -{ - SzAr_Init(&p->db); - p->FolderStartPackStreamIndex = 0; - p->PackStreamStartPositions = 0; - p->FolderStartFileIndex = 0; - p->FileIndexToFolderIndexMap = 0; -} - -void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc) -{ - IAlloc_Free(alloc, p->FolderStartPackStreamIndex); - IAlloc_Free(alloc, p->PackStreamStartPositions); - IAlloc_Free(alloc, p->FolderStartFileIndex); - IAlloc_Free(alloc, p->FileIndexToFolderIndexMap); - SzAr_Free(&p->db, alloc); - SzArEx_Init(p); -} - -/* -UInt64 GetFolderPackStreamSize(int folderIndex, int streamIndex) const -{ - return PackSizes[FolderStartPackStreamIndex[folderIndex] + streamIndex]; -} - -UInt64 GetFilePackSize(int fileIndex) const -{ - int folderIndex = FileIndexToFolderIndexMap[fileIndex]; - if (folderIndex >= 0) - { - const CSzFolder &folderInfo = Folders[folderIndex]; - if (FolderStartFileIndex[folderIndex] == fileIndex) - return GetFolderFullPackSize(folderIndex); - } - return 0; -} -*/ - -#define MY_ALLOC(T, p, size, alloc) { if ((size) == 0) p = 0; else \ - if ((p = (T *)IAlloc_Alloc(alloc, (size) * sizeof(T))) == 0) return SZ_ERROR_MEM; } - -static SRes SzArEx_Fill(CSzArEx *p, ISzAlloc *alloc) -{ - UInt32 startPos = 0; - UInt64 startPosSize = 0; - UInt32 i; - UInt32 folderIndex = 0; - UInt32 indexInFolder = 0; - MY_ALLOC(UInt32, p->FolderStartPackStreamIndex, p->db.NumFolders, alloc); - for (i = 0; i < p->db.NumFolders; i++) - { - p->FolderStartPackStreamIndex[i] = startPos; - startPos += p->db.Folders[i].NumPackStreams; - } - - MY_ALLOC(UInt64, p->PackStreamStartPositions, p->db.NumPackStreams, alloc); - - for (i = 0; i < p->db.NumPackStreams; i++) - { - p->PackStreamStartPositions[i] = startPosSize; - startPosSize += p->db.PackSizes[i]; - } - - MY_ALLOC(UInt32, p->FolderStartFileIndex, p->db.NumFolders, alloc); - MY_ALLOC(UInt32, p->FileIndexToFolderIndexMap, p->db.NumFiles, alloc); - - for (i = 0; i < p->db.NumFiles; i++) - { - CSzFileItem *file = p->db.Files + i; - int emptyStream = !file->HasStream; - if (emptyStream && indexInFolder == 0) - { - p->FileIndexToFolderIndexMap[i] = (UInt32)-1; - continue; - } - if (indexInFolder == 0) - { - /* - v3.13 incorrectly worked with empty folders - v4.07: Loop for skipping empty folders - */ - for (;;) - { - if (folderIndex >= p->db.NumFolders) - return SZ_ERROR_ARCHIVE; - p->FolderStartFileIndex[folderIndex] = i; - if (p->db.Folders[folderIndex].NumUnpackStreams != 0) - break; - folderIndex++; - } - } - p->FileIndexToFolderIndexMap[i] = folderIndex; - if (emptyStream) - continue; - indexInFolder++; - if (indexInFolder >= p->db.Folders[folderIndex].NumUnpackStreams) - { - folderIndex++; - indexInFolder = 0; - } - } - return SZ_OK; -} - - -UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder) -{ - return p->dataPos + - p->PackStreamStartPositions[p->FolderStartPackStreamIndex[folderIndex] + indexInFolder]; -} - -int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize) -{ - UInt32 packStreamIndex = p->FolderStartPackStreamIndex[folderIndex]; - CSzFolder *folder = p->db.Folders + folderIndex; - UInt64 size = 0; - UInt32 i; - for (i = 0; i < folder->NumPackStreams; i++) - { - UInt64 t = size + p->db.PackSizes[packStreamIndex + i]; - if (t < size) /* check it */ - return SZ_ERROR_FAIL; - size = t; - } - *resSize = size; - return SZ_OK; -} - - -/* -SRes SzReadTime(const CObjectVector &dataVector, - CObjectVector &files, UInt64 type) -{ - CBoolVector boolVector; - RINOK(ReadBoolVector2(files.Size(), boolVector)) - - CStreamSwitch streamSwitch; - RINOK(streamSwitch.Set(this, &dataVector)); - - for (int i = 0; i < files.Size(); i++) - { - CSzFileItem &file = files[i]; - CArchiveFileTime fileTime; - bool defined = boolVector[i]; - if (defined) - { - UInt32 low, high; - RINOK(SzReadUInt32(low)); - RINOK(SzReadUInt32(high)); - fileTime.dwLowDateTime = low; - fileTime.dwHighDateTime = high; - } - switch(type) - { - case k7zIdCTime: file.IsCTimeDefined = defined; if (defined) file.CTime = fileTime; break; - case k7zIdATime: file.IsATimeDefined = defined; if (defined) file.ATime = fileTime; break; - case k7zIdMTime: file.IsMTimeDefined = defined; if (defined) file.MTime = fileTime; break; - } - } - return SZ_OK; -} -*/ - -static int TestSignatureCandidate(Byte *testBytes) -{ - size_t i; - for (i = 0; i < k7zSignatureSize; i++) - if (testBytes[i] != k7zSignature[i]) - return 0; - return 1; -} - -typedef struct _CSzState -{ - Byte *Data; - size_t Size; -}CSzData; - -static SRes SzReadByte(CSzData *sd, Byte *b) -{ - if (sd->Size == 0) - return SZ_ERROR_ARCHIVE; - sd->Size--; - *b = *sd->Data++; - return SZ_OK; -} - -static SRes SzReadBytes(CSzData *sd, Byte *data, size_t size) -{ - size_t i; - for (i = 0; i < size; i++) - { - RINOK(SzReadByte(sd, data + i)); - } - return SZ_OK; -} - -static SRes SzReadUInt32(CSzData *sd, UInt32 *value) -{ - int i; - *value = 0; - for (i = 0; i < 4; i++) - { - Byte b; - RINOK(SzReadByte(sd, &b)); - *value |= ((UInt32)(b) << (8 * i)); - } - return SZ_OK; -} - -static SRes SzReadNumber(CSzData *sd, UInt64 *value) -{ - Byte firstByte; - Byte mask = 0x80; - int i; - RINOK(SzReadByte(sd, &firstByte)); - *value = 0; - for (i = 0; i < 8; i++) - { - Byte b; - if ((firstByte & mask) == 0) - { - UInt64 highPart = firstByte & (mask - 1); - *value += (highPart << (8 * i)); - return SZ_OK; - } - RINOK(SzReadByte(sd, &b)); - *value |= ((UInt64)b << (8 * i)); - mask >>= 1; - } - return SZ_OK; -} - -static SRes SzReadNumber32(CSzData *sd, UInt32 *value) -{ - UInt64 value64; - RINOK(SzReadNumber(sd, &value64)); - if (value64 >= 0x80000000) - return SZ_ERROR_UNSUPPORTED; - if (value64 >= ((UInt64)(1) << ((sizeof(size_t) - 1) * 8 + 2))) - return SZ_ERROR_UNSUPPORTED; - *value = (UInt32)value64; - return SZ_OK; -} - -static SRes SzReadID(CSzData *sd, UInt64 *value) -{ - return SzReadNumber(sd, value); -} - -static SRes SzSkeepDataSize(CSzData *sd, UInt64 size) -{ - if (size > sd->Size) - return SZ_ERROR_ARCHIVE; - sd->Size -= (size_t)size; - sd->Data += (size_t)size; - return SZ_OK; -} - -static SRes SzSkeepData(CSzData *sd) -{ - UInt64 size; - RINOK(SzReadNumber(sd, &size)); - return SzSkeepDataSize(sd, size); -} - -static SRes SzReadArchiveProperties(CSzData *sd) -{ - for (;;) - { - UInt64 type; - RINOK(SzReadID(sd, &type)); - if (type == k7zIdEnd) - break; - SzSkeepData(sd); - } - return SZ_OK; -} - -static SRes SzWaitAttribute(CSzData *sd, UInt64 attribute) -{ - for (;;) - { - UInt64 type; - RINOK(SzReadID(sd, &type)); - if (type == attribute) - return SZ_OK; - if (type == k7zIdEnd) - return SZ_ERROR_ARCHIVE; - RINOK(SzSkeepData(sd)); - } -} - -static SRes SzReadBoolVector(CSzData *sd, size_t numItems, Byte **v, ISzAlloc *alloc) -{ - Byte b = 0; - Byte mask = 0; - size_t i; - MY_ALLOC(Byte, *v, numItems, alloc); - for (i = 0; i < numItems; i++) - { - if (mask == 0) - { - RINOK(SzReadByte(sd, &b)); - mask = 0x80; - } - (*v)[i] = (Byte)(((b & mask) != 0) ? 1 : 0); - mask >>= 1; - } - return SZ_OK; -} - -static SRes SzReadBoolVector2(CSzData *sd, size_t numItems, Byte **v, ISzAlloc *alloc) -{ - Byte allAreDefined; - size_t i; - RINOK(SzReadByte(sd, &allAreDefined)); - if (allAreDefined == 0) - return SzReadBoolVector(sd, numItems, v, alloc); - MY_ALLOC(Byte, *v, numItems, alloc); - for (i = 0; i < numItems; i++) - (*v)[i] = 1; - return SZ_OK; -} - -static SRes SzReadHashDigests( - CSzData *sd, - size_t numItems, - Byte **digestsDefined, - UInt32 **digests, - ISzAlloc *alloc) -{ - size_t i; - RINOK(SzReadBoolVector2(sd, numItems, digestsDefined, alloc)); - MY_ALLOC(UInt32, *digests, numItems, alloc); - for (i = 0; i < numItems; i++) - if ((*digestsDefined)[i]) - { - RINOK(SzReadUInt32(sd, (*digests) + i)); - } - return SZ_OK; -} - -static SRes SzReadPackInfo( - CSzData *sd, - UInt64 *dataOffset, - UInt32 *numPackStreams, - UInt64 **packSizes, - Byte **packCRCsDefined, - UInt32 **packCRCs, - ISzAlloc *alloc) -{ - UInt32 i; - RINOK(SzReadNumber(sd, dataOffset)); - RINOK(SzReadNumber32(sd, numPackStreams)); - - RINOK(SzWaitAttribute(sd, k7zIdSize)); - - MY_ALLOC(UInt64, *packSizes, (size_t)*numPackStreams, alloc); - - for (i = 0; i < *numPackStreams; i++) - { - RINOK(SzReadNumber(sd, (*packSizes) + i)); - } - - for (;;) - { - UInt64 type; - RINOK(SzReadID(sd, &type)); - if (type == k7zIdEnd) - break; - if (type == k7zIdCRC) - { - RINOK(SzReadHashDigests(sd, (size_t)*numPackStreams, packCRCsDefined, packCRCs, alloc)); - continue; - } - RINOK(SzSkeepData(sd)); - } - if (*packCRCsDefined == 0) - { - MY_ALLOC(Byte, *packCRCsDefined, (size_t)*numPackStreams, alloc); - MY_ALLOC(UInt32, *packCRCs, (size_t)*numPackStreams, alloc); - for (i = 0; i < *numPackStreams; i++) - { - (*packCRCsDefined)[i] = 0; - (*packCRCs)[i] = 0; - } - } - return SZ_OK; -} - -static SRes SzReadSwitch(CSzData *sd) -{ - Byte external; - RINOK(SzReadByte(sd, &external)); - return (external == 0) ? SZ_OK: SZ_ERROR_UNSUPPORTED; -} - -static SRes SzGetNextFolderItem(CSzData *sd, CSzFolder *folder, ISzAlloc *alloc) -{ - UInt32 numCoders, numBindPairs, numPackStreams, i; - UInt32 numInStreams = 0, numOutStreams = 0; - - RINOK(SzReadNumber32(sd, &numCoders)); - if (numCoders > NUM_FOLDER_CODERS_MAX) - return SZ_ERROR_UNSUPPORTED; - folder->NumCoders = numCoders; - - MY_ALLOC(CSzCoderInfo, folder->Coders, (size_t)numCoders, alloc); - - for (i = 0; i < numCoders; i++) - SzCoderInfo_Init(folder->Coders + i); - - for (i = 0; i < numCoders; i++) - { - Byte mainByte; - CSzCoderInfo *coder = folder->Coders + i; - { - unsigned idSize, j; - Byte longID[15]; - RINOK(SzReadByte(sd, &mainByte)); - idSize = (unsigned)(mainByte & 0xF); - RINOK(SzReadBytes(sd, longID, idSize)); - if (idSize > sizeof(coder->MethodID)) - return SZ_ERROR_UNSUPPORTED; - coder->MethodID = 0; - for (j = 0; j < idSize; j++) - coder->MethodID |= (UInt64)longID[idSize - 1 - j] << (8 * j); - - if ((mainByte & 0x10) != 0) - { - RINOK(SzReadNumber32(sd, &coder->NumInStreams)); - RINOK(SzReadNumber32(sd, &coder->NumOutStreams)); - if (coder->NumInStreams > NUM_CODER_STREAMS_MAX || - coder->NumOutStreams > NUM_CODER_STREAMS_MAX) - return SZ_ERROR_UNSUPPORTED; - } - else - { - coder->NumInStreams = 1; - coder->NumOutStreams = 1; - } - if ((mainByte & 0x20) != 0) - { - UInt64 propertiesSize = 0; - RINOK(SzReadNumber(sd, &propertiesSize)); - if (!Buf_Create(&coder->Props, (size_t)propertiesSize, alloc)) - return SZ_ERROR_MEM; - RINOK(SzReadBytes(sd, coder->Props.data, (size_t)propertiesSize)); - } - } - while ((mainByte & 0x80) != 0) - { - RINOK(SzReadByte(sd, &mainByte)); - RINOK(SzSkeepDataSize(sd, (mainByte & 0xF))); - if ((mainByte & 0x10) != 0) - { - UInt32 n; - RINOK(SzReadNumber32(sd, &n)); - RINOK(SzReadNumber32(sd, &n)); - } - if ((mainByte & 0x20) != 0) - { - UInt64 propertiesSize = 0; - RINOK(SzReadNumber(sd, &propertiesSize)); - RINOK(SzSkeepDataSize(sd, propertiesSize)); - } - } - numInStreams += coder->NumInStreams; - numOutStreams += coder->NumOutStreams; - } - - if (numOutStreams == 0) - return SZ_ERROR_UNSUPPORTED; - - folder->NumBindPairs = numBindPairs = numOutStreams - 1; - MY_ALLOC(CBindPair, folder->BindPairs, (size_t)numBindPairs, alloc); - - for (i = 0; i < numBindPairs; i++) - { - CBindPair *bp = folder->BindPairs + i; - RINOK(SzReadNumber32(sd, &bp->InIndex)); - RINOK(SzReadNumber32(sd, &bp->OutIndex)); - } - - if (numInStreams < numBindPairs) - return SZ_ERROR_UNSUPPORTED; - - folder->NumPackStreams = numPackStreams = numInStreams - numBindPairs; - MY_ALLOC(UInt32, folder->PackStreams, (size_t)numPackStreams, alloc); - - if (numPackStreams == 1) - { - for (i = 0; i < numInStreams ; i++) - if (SzFolder_FindBindPairForInStream(folder, i) < 0) - break; - if (i == numInStreams) - return SZ_ERROR_UNSUPPORTED; - folder->PackStreams[0] = i; - } - else - for (i = 0; i < numPackStreams; i++) - { - RINOK(SzReadNumber32(sd, folder->PackStreams + i)); - } - return SZ_OK; -} - -static SRes SzReadUnpackInfo( - CSzData *sd, - UInt32 *numFolders, - CSzFolder **folders, /* for alloc */ - ISzAlloc *alloc, - ISzAlloc *allocTemp) -{ - UInt32 i; - RINOK(SzWaitAttribute(sd, k7zIdFolder)); - RINOK(SzReadNumber32(sd, numFolders)); - { - RINOK(SzReadSwitch(sd)); - - MY_ALLOC(CSzFolder, *folders, (size_t)*numFolders, alloc); - - for (i = 0; i < *numFolders; i++) - SzFolder_Init((*folders) + i); - - for (i = 0; i < *numFolders; i++) - { - RINOK(SzGetNextFolderItem(sd, (*folders) + i, alloc)); - } - } - - RINOK(SzWaitAttribute(sd, k7zIdCodersUnpackSize)); - - for (i = 0; i < *numFolders; i++) - { - UInt32 j; - CSzFolder *folder = (*folders) + i; - UInt32 numOutStreams = SzFolder_GetNumOutStreams(folder); - - MY_ALLOC(UInt64, folder->UnpackSizes, (size_t)numOutStreams, alloc); - - for (j = 0; j < numOutStreams; j++) - { - RINOK(SzReadNumber(sd, folder->UnpackSizes + j)); - } - } - - for (;;) - { - UInt64 type; - RINOK(SzReadID(sd, &type)); - if (type == k7zIdEnd) - return SZ_OK; - if (type == k7zIdCRC) - { - SRes res; - Byte *crcsDefined = 0; - UInt32 *crcs = 0; - res = SzReadHashDigests(sd, *numFolders, &crcsDefined, &crcs, allocTemp); - if (res == SZ_OK) - { - for (i = 0; i < *numFolders; i++) - { - CSzFolder *folder = (*folders) + i; - folder->UnpackCRCDefined = crcsDefined[i]; - folder->UnpackCRC = crcs[i]; - } - } - IAlloc_Free(allocTemp, crcs); - IAlloc_Free(allocTemp, crcsDefined); - RINOK(res); - continue; - } - RINOK(SzSkeepData(sd)); - } -} - -static SRes SzReadSubStreamsInfo( - CSzData *sd, - UInt32 numFolders, - CSzFolder *folders, - UInt32 *numUnpackStreams, - UInt64 **unpackSizes, - Byte **digestsDefined, - UInt32 **digests, - ISzAlloc *allocTemp) -{ - UInt64 type = 0; - UInt32 i; - UInt32 si = 0; - UInt32 numDigests = 0; - - for (i = 0; i < numFolders; i++) - folders[i].NumUnpackStreams = 1; - *numUnpackStreams = numFolders; - - for (;;) - { - RINOK(SzReadID(sd, &type)); - if (type == k7zIdNumUnpackStream) - { - *numUnpackStreams = 0; - for (i = 0; i < numFolders; i++) - { - UInt32 numStreams; - RINOK(SzReadNumber32(sd, &numStreams)); - folders[i].NumUnpackStreams = numStreams; - *numUnpackStreams += numStreams; - } - continue; - } - if (type == k7zIdCRC || type == k7zIdSize) - break; - if (type == k7zIdEnd) - break; - RINOK(SzSkeepData(sd)); - } - - if (*numUnpackStreams == 0) - { - *unpackSizes = 0; - *digestsDefined = 0; - *digests = 0; - } - else - { - *unpackSizes = (UInt64 *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(UInt64)); - RINOM(*unpackSizes); - *digestsDefined = (Byte *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(Byte)); - RINOM(*digestsDefined); - *digests = (UInt32 *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(UInt32)); - RINOM(*digests); - } - - for (i = 0; i < numFolders; i++) - { - /* - v3.13 incorrectly worked with empty folders - v4.07: we check that folder is empty - */ - UInt64 sum = 0; - UInt32 j; - UInt32 numSubstreams = folders[i].NumUnpackStreams; - if (numSubstreams == 0) - continue; - if (type == k7zIdSize) - for (j = 1; j < numSubstreams; j++) - { - UInt64 size; - RINOK(SzReadNumber(sd, &size)); - (*unpackSizes)[si++] = size; - sum += size; - } - (*unpackSizes)[si++] = SzFolder_GetUnpackSize(folders + i) - sum; - } - if (type == k7zIdSize) - { - RINOK(SzReadID(sd, &type)); - } - - for (i = 0; i < *numUnpackStreams; i++) - { - (*digestsDefined)[i] = 0; - (*digests)[i] = 0; - } - - - for (i = 0; i < numFolders; i++) - { - UInt32 numSubstreams = folders[i].NumUnpackStreams; - if (numSubstreams != 1 || !folders[i].UnpackCRCDefined) - numDigests += numSubstreams; - } - - - si = 0; - for (;;) - { - if (type == k7zIdCRC) - { - int digestIndex = 0; - Byte *digestsDefined2 = 0; - UInt32 *digests2 = 0; - SRes res = SzReadHashDigests(sd, numDigests, &digestsDefined2, &digests2, allocTemp); - if (res == SZ_OK) - { - for (i = 0; i < numFolders; i++) - { - CSzFolder *folder = folders + i; - UInt32 numSubstreams = folder->NumUnpackStreams; - if (numSubstreams == 1 && folder->UnpackCRCDefined) - { - (*digestsDefined)[si] = 1; - (*digests)[si] = folder->UnpackCRC; - si++; - } - else - { - UInt32 j; - for (j = 0; j < numSubstreams; j++, digestIndex++) - { - (*digestsDefined)[si] = digestsDefined2[digestIndex]; - (*digests)[si] = digests2[digestIndex]; - si++; - } - } - } - } - IAlloc_Free(allocTemp, digestsDefined2); - IAlloc_Free(allocTemp, digests2); - RINOK(res); - } - else if (type == k7zIdEnd) - return SZ_OK; - else - { - RINOK(SzSkeepData(sd)); - } - RINOK(SzReadID(sd, &type)); - } -} - - -static SRes SzReadStreamsInfo( - CSzData *sd, - UInt64 *dataOffset, - CSzAr *p, - UInt32 *numUnpackStreams, - UInt64 **unpackSizes, /* allocTemp */ - Byte **digestsDefined, /* allocTemp */ - UInt32 **digests, /* allocTemp */ - ISzAlloc *alloc, - ISzAlloc *allocTemp) -{ - for (;;) - { - UInt64 type; - RINOK(SzReadID(sd, &type)); - if ((UInt64)(int)type != type) - return SZ_ERROR_UNSUPPORTED; - switch((int)type) - { - case k7zIdEnd: - return SZ_OK; - case k7zIdPackInfo: - { - RINOK(SzReadPackInfo(sd, dataOffset, &p->NumPackStreams, - &p->PackSizes, &p->PackCRCsDefined, &p->PackCRCs, alloc)); - break; - } - case k7zIdUnpackInfo: - { - RINOK(SzReadUnpackInfo(sd, &p->NumFolders, &p->Folders, alloc, allocTemp)); - break; - } - case k7zIdSubStreamsInfo: - { - RINOK(SzReadSubStreamsInfo(sd, p->NumFolders, p->Folders, - numUnpackStreams, unpackSizes, digestsDefined, digests, allocTemp)); - break; - } - default: - return SZ_ERROR_UNSUPPORTED; - } - } -} - -Byte kUtf8Limits[5] = { 0xC0, 0xE0, 0xF0, 0xF8, 0xFC }; - -static SRes SzReadFileNames(CSzData *sd, UInt32 numFiles, CSzFileItem *files, ISzAlloc *alloc) -{ - UInt32 i; - for (i = 0; i < numFiles; i++) - { - UInt32 len = 0; - UInt32 pos = 0; - CSzFileItem *file = files + i; - while (pos + 2 <= sd->Size) - { - int numAdds; - UInt32 value = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8)); - pos += 2; - len++; - if (value == 0) - break; - if (value < 0x80) - continue; - if (value >= 0xD800 && value < 0xE000) - { - UInt32 c2; - if (value >= 0xDC00) - return SZ_ERROR_ARCHIVE; - if (pos + 2 > sd->Size) - return SZ_ERROR_ARCHIVE; - c2 = (UInt32)(sd->Data[pos] | (((UInt32)sd->Data[pos + 1]) << 8)); - pos += 2; - if (c2 < 0xDC00 || c2 >= 0xE000) - return SZ_ERROR_ARCHIVE; - value = ((value - 0xD800) << 10) | (c2 - 0xDC00); - } - for (numAdds = 1; numAdds < 5; numAdds++) - if (value < (((UInt32)1) << (numAdds * 5 + 6))) - break; - len += numAdds; - } - - MY_ALLOC(char, file->Name, (size_t)len, alloc); - - len = 0; - while (2 <= sd->Size) - { - int numAdds; - UInt32 value = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8)); - SzSkeepDataSize(sd, 2); - if (value < 0x80) - { - file->Name[len++] = (char)value; - if (value == 0) - break; - continue; - } - if (value >= 0xD800 && value < 0xE000) - { - UInt32 c2 = (UInt32)(sd->Data[0] | (((UInt32)sd->Data[1]) << 8)); - SzSkeepDataSize(sd, 2); - value = ((value - 0xD800) << 10) | (c2 - 0xDC00); - } - for (numAdds = 1; numAdds < 5; numAdds++) - if (value < (((UInt32)1) << (numAdds * 5 + 6))) - break; - file->Name[len++] = (char)(kUtf8Limits[numAdds - 1] + (value >> (6 * numAdds))); - do - { - numAdds--; - file->Name[len++] = (char)(0x80 + ((value >> (6 * numAdds)) & 0x3F)); - } - while (numAdds > 0); - - len += numAdds; - } - } - return SZ_OK; -} - -static SRes SzReadHeader2( - CSzArEx *p, /* allocMain */ - CSzData *sd, - UInt64 **unpackSizes, /* allocTemp */ - Byte **digestsDefined, /* allocTemp */ - UInt32 **digests, /* allocTemp */ - Byte **emptyStreamVector, /* allocTemp */ - Byte **emptyFileVector, /* allocTemp */ - Byte **lwtVector, /* allocTemp */ - ISzAlloc *allocMain, - ISzAlloc *allocTemp) -{ - UInt64 htype; - UInt32 numUnpackStreams = 0; - UInt32 numFiles = 0; - CSzFileItem *files = 0; - UInt32 numEmptyStreams = 0; - UInt32 i; - - RINOK(SzReadID(sd, &htype)); - - if (htype == k7zIdArchiveProperties) - { - RINOK(SzReadArchiveProperties(sd)); - RINOK(SzReadID(sd, &htype)); - } - - - if (htype == k7zIdMainStreamsInfo) - { - RINOK(SzReadStreamsInfo(sd, - &p->dataPos, - &p->db, - &numUnpackStreams, - unpackSizes, - digestsDefined, - digests, allocMain, allocTemp)); - p->dataPos += p->startPosAfterHeader; - RINOK(SzReadID(sd, &htype)); - } - - if (htype == k7zIdEnd) - return SZ_OK; - if (htype != k7zIdFilesInfo) - return SZ_ERROR_ARCHIVE; - - RINOK(SzReadNumber32(sd, &numFiles)); - p->db.NumFiles = numFiles; - - MY_ALLOC(CSzFileItem, files, (size_t)numFiles, allocMain); - - p->db.Files = files; - for (i = 0; i < numFiles; i++) - SzFile_Init(files + i); - - for (;;) - { - UInt64 type; - UInt64 size; - RINOK(SzReadID(sd, &type)); - if (type == k7zIdEnd) - break; - RINOK(SzReadNumber(sd, &size)); - - if ((UInt64)(int)type != type) - { - RINOK(SzSkeepDataSize(sd, size)); - } - else - switch((int)type) - { - case k7zIdName: - { - RINOK(SzReadSwitch(sd)); - RINOK(SzReadFileNames(sd, numFiles, files, allocMain)) - break; - } - case k7zIdEmptyStream: - { - RINOK(SzReadBoolVector(sd, numFiles, emptyStreamVector, allocTemp)); - numEmptyStreams = 0; - for (i = 0; i < numFiles; i++) - if ((*emptyStreamVector)[i]) - numEmptyStreams++; - break; - } - case k7zIdEmptyFile: - { - RINOK(SzReadBoolVector(sd, numEmptyStreams, emptyFileVector, allocTemp)); - break; - } - case k7zIdMTime: - { - RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp)); - RINOK(SzReadSwitch(sd)); - for (i = 0; i < numFiles; i++) - { - CSzFileItem *f = &files[i]; - Byte defined = (*lwtVector)[i]; - f->MTimeDefined = defined; - f->MTime.Low = f->MTime.High = 0; - if (defined) - { - RINOK(SzReadUInt32(sd, &f->MTime.Low)); - RINOK(SzReadUInt32(sd, &f->MTime.High)); - } - } - break; - } - default: - { - RINOK(SzSkeepDataSize(sd, size)); - } - } - } - - { - UInt32 emptyFileIndex = 0; - UInt32 sizeIndex = 0; - for (i = 0; i < numFiles; i++) - { - CSzFileItem *file = files + i; - file->IsAnti = 0; - if (*emptyStreamVector == 0) - file->HasStream = 1; - else - file->HasStream = (Byte)((*emptyStreamVector)[i] ? 0 : 1); - if (file->HasStream) - { - file->IsDir = 0; - file->Size = (*unpackSizes)[sizeIndex]; - file->FileCRC = (*digests)[sizeIndex]; - file->FileCRCDefined = (Byte)(*digestsDefined)[sizeIndex]; - sizeIndex++; - } - else - { - if (*emptyFileVector == 0) - file->IsDir = 1; - else - file->IsDir = (Byte)((*emptyFileVector)[emptyFileIndex] ? 0 : 1); - emptyFileIndex++; - file->Size = 0; - file->FileCRCDefined = 0; - } - } - } - return SzArEx_Fill(p, allocMain); -} - -static SRes SzReadHeader( - CSzArEx *p, - CSzData *sd, - ISzAlloc *allocMain, - ISzAlloc *allocTemp) -{ - UInt64 *unpackSizes = 0; - Byte *digestsDefined = 0; - UInt32 *digests = 0; - Byte *emptyStreamVector = 0; - Byte *emptyFileVector = 0; - Byte *lwtVector = 0; - SRes res = SzReadHeader2(p, sd, - &unpackSizes, &digestsDefined, &digests, - &emptyStreamVector, &emptyFileVector, &lwtVector, - allocMain, allocTemp); - IAlloc_Free(allocTemp, unpackSizes); - IAlloc_Free(allocTemp, digestsDefined); - IAlloc_Free(allocTemp, digests); - IAlloc_Free(allocTemp, emptyStreamVector); - IAlloc_Free(allocTemp, emptyFileVector); - IAlloc_Free(allocTemp, lwtVector); - return res; -} - -static SRes SzReadAndDecodePackedStreams2( - ILookInStream *inStream, - CSzData *sd, - CBuf *outBuffer, - UInt64 baseOffset, - CSzAr *p, - UInt64 **unpackSizes, - Byte **digestsDefined, - UInt32 **digests, - ISzAlloc *allocTemp) -{ - - UInt32 numUnpackStreams = 0; - UInt64 dataStartPos; - CSzFolder *folder; - UInt64 unpackSize; - SRes res; - - RINOK(SzReadStreamsInfo(sd, &dataStartPos, p, - &numUnpackStreams, unpackSizes, digestsDefined, digests, - allocTemp, allocTemp)); - - dataStartPos += baseOffset; - if (p->NumFolders != 1) - return SZ_ERROR_ARCHIVE; - - folder = p->Folders; - unpackSize = SzFolder_GetUnpackSize(folder); - - RINOK(LookInStream_SeekTo(inStream, dataStartPos)); - - if (!Buf_Create(outBuffer, (size_t)unpackSize, allocTemp)) - return SZ_ERROR_MEM; - - res = SzDecode(p->PackSizes, folder, - inStream, dataStartPos, - outBuffer->data, (size_t)unpackSize, allocTemp); - RINOK(res); - if (folder->UnpackCRCDefined) - if (CrcCalc(outBuffer->data, (size_t)unpackSize) != folder->UnpackCRC) - return SZ_ERROR_CRC; - return SZ_OK; -} - -static SRes SzReadAndDecodePackedStreams( - ILookInStream *inStream, - CSzData *sd, - CBuf *outBuffer, - UInt64 baseOffset, - ISzAlloc *allocTemp) -{ - CSzAr p; - UInt64 *unpackSizes = 0; - Byte *digestsDefined = 0; - UInt32 *digests = 0; - SRes res; - SzAr_Init(&p); - res = SzReadAndDecodePackedStreams2(inStream, sd, outBuffer, baseOffset, - &p, &unpackSizes, &digestsDefined, &digests, - allocTemp); - SzAr_Free(&p, allocTemp); - IAlloc_Free(allocTemp, unpackSizes); - IAlloc_Free(allocTemp, digestsDefined); - IAlloc_Free(allocTemp, digests); - return res; -} - -static SRes SzArEx_Open2( - CSzArEx *p, - ILookInStream *inStream, - ISzAlloc *allocMain, - ISzAlloc *allocTemp) -{ - Byte header[k7zStartHeaderSize]; - UInt64 nextHeaderOffset, nextHeaderSize; - size_t nextHeaderSizeT; - UInt32 nextHeaderCRC; - CBuf buffer; - SRes res; - - RINOK(LookInStream_Read2(inStream, header, k7zStartHeaderSize, SZ_ERROR_NO_ARCHIVE)); - - if (!TestSignatureCandidate(header)) - return SZ_ERROR_NO_ARCHIVE; - if (header[6] != k7zMajorVersion) - return SZ_ERROR_UNSUPPORTED; - - nextHeaderOffset = GetUi64(header + 12); - nextHeaderSize = GetUi64(header + 20); - nextHeaderCRC = GetUi32(header + 28); - - p->startPosAfterHeader = k7zStartHeaderSize; - - if (CrcCalc(header + 12, 20) != GetUi32(header + 8)) - return SZ_ERROR_CRC; - - nextHeaderSizeT = (size_t)nextHeaderSize; - if (nextHeaderSizeT != nextHeaderSize) - return SZ_ERROR_MEM; - if (nextHeaderSizeT == 0) - return SZ_OK; - if (nextHeaderOffset > nextHeaderOffset + nextHeaderSize || - nextHeaderOffset > nextHeaderOffset + nextHeaderSize + k7zStartHeaderSize) - return SZ_ERROR_NO_ARCHIVE; - - { - Int64 pos = 0; - RINOK(inStream->Seek(inStream, &pos, SZ_SEEK_END)); - if ((UInt64)pos < nextHeaderOffset || - (UInt64)pos < k7zStartHeaderSize + nextHeaderOffset || - (UInt64)pos < k7zStartHeaderSize + nextHeaderOffset + nextHeaderSize) - return SZ_ERROR_INPUT_EOF; - } - - RINOK(LookInStream_SeekTo(inStream, k7zStartHeaderSize + nextHeaderOffset)); - - if (!Buf_Create(&buffer, nextHeaderSizeT, allocTemp)) - return SZ_ERROR_MEM; - - res = LookInStream_Read(inStream, buffer.data, nextHeaderSizeT); - if (res == SZ_OK) - { - res = SZ_ERROR_ARCHIVE; - if (CrcCalc(buffer.data, nextHeaderSizeT) == nextHeaderCRC) - { - CSzData sd; - UInt64 type; - sd.Data = buffer.data; - sd.Size = buffer.size; - res = SzReadID(&sd, &type); - if (res == SZ_OK) - { - if (type == k7zIdEncodedHeader) - { - CBuf outBuffer; - Buf_Init(&outBuffer); - res = SzReadAndDecodePackedStreams(inStream, &sd, &outBuffer, p->startPosAfterHeader, allocTemp); - if (res != SZ_OK) - Buf_Free(&outBuffer, allocTemp); - else - { - Buf_Free(&buffer, allocTemp); - buffer.data = outBuffer.data; - buffer.size = outBuffer.size; - sd.Data = buffer.data; - sd.Size = buffer.size; - res = SzReadID(&sd, &type); - } - } - } - if (res == SZ_OK) - { - if (type == k7zIdHeader) - res = SzReadHeader(p, &sd, allocMain, allocTemp); - else - res = SZ_ERROR_UNSUPPORTED; - } - } - } - Buf_Free(&buffer, allocTemp); - return res; -} - -SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp) -{ - SRes res = SzArEx_Open2(p, inStream, allocMain, allocTemp); - if (res != SZ_OK) - SzArEx_Free(p, allocMain); - return res; -} diff --git a/snesreader/7z_C/7zIn.h b/snesreader/7z_C/7zIn.h deleted file mode 100644 index 89e0fb85..00000000 --- a/snesreader/7z_C/7zIn.h +++ /dev/null @@ -1,49 +0,0 @@ -/* 7zIn.h -- 7z Input functions -2008-11-23 : Igor Pavlov : Public domain */ - -#ifndef __7Z_IN_H -#define __7Z_IN_H - -#include "7zHeader.h" -#include "7zItem.h" - -#ifdef __cplusplus - extern "C" { -#endif - -typedef struct -{ - CSzAr db; - - UInt64 startPosAfterHeader; - UInt64 dataPos; - - UInt32 *FolderStartPackStreamIndex; - UInt64 *PackStreamStartPositions; - UInt32 *FolderStartFileIndex; - UInt32 *FileIndexToFolderIndexMap; -} CSzArEx; - -void SzArEx_Init(CSzArEx *p); -void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc); -UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder); -int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize); - -/* -Errors: -SZ_ERROR_NO_ARCHIVE -SZ_ERROR_ARCHIVE -SZ_ERROR_UNSUPPORTED -SZ_ERROR_MEM -SZ_ERROR_CRC -SZ_ERROR_INPUT_EOF -SZ_ERROR_FAIL -*/ - -SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp); - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/snesreader/7z_C/7zItem.c b/snesreader/7z_C/7zItem.c deleted file mode 100644 index 4a092614..00000000 --- a/snesreader/7z_C/7zItem.c +++ /dev/null @@ -1,129 +0,0 @@ -/* 7zItem.c -- 7z Items -2008-10-04 : Igor Pavlov : Public domain */ - -#include "7zItem.h" - -void SzCoderInfo_Init(CSzCoderInfo *p) -{ - Buf_Init(&p->Props); -} - -void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc) -{ - Buf_Free(&p->Props, alloc); - SzCoderInfo_Init(p); -} - -void SzFolder_Init(CSzFolder *p) -{ - p->Coders = 0; - p->BindPairs = 0; - p->PackStreams = 0; - p->UnpackSizes = 0; - p->NumCoders = 0; - p->NumBindPairs = 0; - p->NumPackStreams = 0; - p->UnpackCRCDefined = 0; - p->UnpackCRC = 0; - p->NumUnpackStreams = 0; -} - -static -void SzFolder_Free(CSzFolder *p, ISzAlloc *alloc) -{ - UInt32 i; - if (p->Coders) - for (i = 0; i < p->NumCoders; i++) - SzCoderInfo_Free(&p->Coders[i], alloc); - IAlloc_Free(alloc, p->Coders); - IAlloc_Free(alloc, p->BindPairs); - IAlloc_Free(alloc, p->PackStreams); - IAlloc_Free(alloc, p->UnpackSizes); - SzFolder_Init(p); -} - -UInt32 SzFolder_GetNumOutStreams(CSzFolder *p) -{ - UInt32 result = 0; - UInt32 i; - for (i = 0; i < p->NumCoders; i++) - result += p->Coders[i].NumOutStreams; - return result; -} - -int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex) -{ - UInt32 i; - for (i = 0; i < p->NumBindPairs; i++) - if (p->BindPairs[i].InIndex == inStreamIndex) - return i; - return -1; -} - - -static -int SzFolder_FindBindPairForOutStream(CSzFolder *p, UInt32 outStreamIndex) -{ - UInt32 i; - for (i = 0; i < p->NumBindPairs; i++) - if (p->BindPairs[i].OutIndex == outStreamIndex) - return i; - return -1; -} - -UInt64 SzFolder_GetUnpackSize(CSzFolder *p) -{ - int i = (int)SzFolder_GetNumOutStreams(p); - if (i == 0) - return 0; - for (i--; i >= 0; i--) - if (SzFolder_FindBindPairForOutStream(p, i) < 0) - return p->UnpackSizes[i]; - /* throw 1; */ - return 0; -} - -void SzFile_Init(CSzFileItem *p) -{ - p->HasStream = 1; - p->IsDir = 0; - p->IsAnti = 0; - p->FileCRCDefined = 0; - p->MTimeDefined = 0; - p->Name = 0; -} - -static void SzFile_Free(CSzFileItem *p, ISzAlloc *alloc) -{ - IAlloc_Free(alloc, p->Name); - SzFile_Init(p); -} - -void SzAr_Init(CSzAr *p) -{ - p->PackSizes = 0; - p->PackCRCsDefined = 0; - p->PackCRCs = 0; - p->Folders = 0; - p->Files = 0; - p->NumPackStreams = 0; - p->NumFolders = 0; - p->NumFiles = 0; -} - -void SzAr_Free(CSzAr *p, ISzAlloc *alloc) -{ - UInt32 i; - if (p->Folders) - for (i = 0; i < p->NumFolders; i++) - SzFolder_Free(&p->Folders[i], alloc); - if (p->Files) - for (i = 0; i < p->NumFiles; i++) - SzFile_Free(&p->Files[i], alloc); - IAlloc_Free(alloc, p->PackSizes); - IAlloc_Free(alloc, p->PackCRCsDefined); - IAlloc_Free(alloc, p->PackCRCs); - IAlloc_Free(alloc, p->Folders); - IAlloc_Free(alloc, p->Files); - SzAr_Init(p); -} diff --git a/snesreader/7z_C/7zItem.h b/snesreader/7z_C/7zItem.h deleted file mode 100644 index 7ef24731..00000000 --- a/snesreader/7z_C/7zItem.h +++ /dev/null @@ -1,83 +0,0 @@ -/* 7zItem.h -- 7z Items -2008-10-04 : Igor Pavlov : Public domain */ - -#ifndef __7Z_ITEM_H -#define __7Z_ITEM_H - -#include "7zBuf.h" - -typedef struct -{ - UInt32 NumInStreams; - UInt32 NumOutStreams; - UInt64 MethodID; - CBuf Props; -} CSzCoderInfo; - -void SzCoderInfo_Init(CSzCoderInfo *p); -void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc); - -typedef struct -{ - UInt32 InIndex; - UInt32 OutIndex; -} CBindPair; - -typedef struct -{ - CSzCoderInfo *Coders; - CBindPair *BindPairs; - UInt32 *PackStreams; - UInt64 *UnpackSizes; - UInt32 NumCoders; - UInt32 NumBindPairs; - UInt32 NumPackStreams; - int UnpackCRCDefined; - UInt32 UnpackCRC; - - UInt32 NumUnpackStreams; -} CSzFolder; - -void SzFolder_Init(CSzFolder *p); -UInt64 SzFolder_GetUnpackSize(CSzFolder *p); -int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex); -UInt32 SzFolder_GetNumOutStreams(CSzFolder *p); - -typedef struct -{ - UInt32 Low; - UInt32 High; -} CNtfsFileTime; - -typedef struct -{ - CNtfsFileTime MTime; - UInt64 Size; - char *Name; - UInt32 FileCRC; - - Byte HasStream; - Byte IsDir; - Byte IsAnti; - Byte FileCRCDefined; - Byte MTimeDefined; -} CSzFileItem; - -void SzFile_Init(CSzFileItem *p); - -typedef struct -{ - UInt64 *PackSizes; - Byte *PackCRCsDefined; - UInt32 *PackCRCs; - CSzFolder *Folders; - CSzFileItem *Files; - UInt32 NumPackStreams; - UInt32 NumFolders; - UInt32 NumFiles; -} CSzAr; - -void SzAr_Init(CSzAr *p); -void SzAr_Free(CSzAr *p, ISzAlloc *alloc); - -#endif diff --git a/snesreader/7z_C/7zStream.c b/snesreader/7z_C/7zStream.c deleted file mode 100644 index 6dc333ef..00000000 --- a/snesreader/7z_C/7zStream.c +++ /dev/null @@ -1,184 +0,0 @@ -/* 7zStream.c -- 7z Stream functions -2008-11-23 : Igor Pavlov : Public domain */ - -#include - -#include "Types.h" - -#if NEVER_CALLED -SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType) -{ - while (size != 0) - { - size_t processed = size; - RINOK(stream->Read(stream, buf, &processed)); - if (processed == 0) - return errorType; - buf = (void *)((Byte *)buf + processed); - size -= processed; - } - return SZ_OK; -} - -SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size) -{ - return SeqInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); -} - -SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf) -{ - size_t processed = 1; - RINOK(stream->Read(stream, buf, &processed)); - return (processed == 1) ? SZ_OK : SZ_ERROR_INPUT_EOF; -} -#endif - -SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset) -{ - Int64 t = offset; - return stream->Seek(stream, &t, SZ_SEEK_SET); -} - -#if NEVER_CALLED -SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size) -{ - void *lookBuf; - if (*size == 0) - return SZ_OK; - RINOK(stream->Look(stream, &lookBuf, size)); - memcpy(buf, lookBuf, *size); - return stream->Skip(stream, *size); -} -#endif - -SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType) -{ - while (size != 0) - { - size_t processed = size; - RINOK(stream->Read(stream, buf, &processed)); - if (processed == 0) - return errorType; - buf = (void *)((Byte *)buf + processed); - size -= processed; - } - return SZ_OK; -} - -SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size) -{ - return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF); -} - -static SRes LookToRead_Look_Lookahead(void *pp, void **buf, size_t *size) -{ - SRes res = SZ_OK; -#if !NEVER_CALLED - (void)pp; - (void)buf; - (void)size; -#else - CLookToRead *p = (CLookToRead *)pp; - size_t size2 = p->size - p->pos; - if (size2 == 0 && *size > 0) - { - p->pos = 0; - size2 = LookToRead_BUF_SIZE; - res = p->realStream->Read(p->realStream, p->buf, &size2); - p->size = size2; - } - if (size2 < *size) - *size = size2; - *buf = p->buf + p->pos; -#endif - return res; -} - -static SRes LookToRead_Look_Exact(void *pp, void **buf, size_t *size) -{ - SRes res = SZ_OK; - CLookToRead *p = (CLookToRead *)pp; - size_t size2 = p->size - p->pos; - if (size2 == 0 && *size > 0) - { - p->pos = 0; - if (*size > LookToRead_BUF_SIZE) - *size = LookToRead_BUF_SIZE; - res = p->realStream->Read(p->realStream, p->buf, size); - size2 = p->size = *size; - } - if (size2 < *size) - *size = size2; - *buf = p->buf + p->pos; - return res; -} - -static SRes LookToRead_Skip(void *pp, size_t offset) -{ - CLookToRead *p = (CLookToRead *)pp; - p->pos += offset; - return SZ_OK; -} - -static SRes LookToRead_Read(void *pp, void *buf, size_t *size) -{ - CLookToRead *p = (CLookToRead *)pp; - size_t rem = p->size - p->pos; - if (rem == 0) - return p->realStream->Read(p->realStream, buf, size); - if (rem > *size) - rem = *size; - memcpy(buf, p->buf + p->pos, rem); - p->pos += rem; - *size = rem; - return SZ_OK; -} - -static SRes LookToRead_Seek(void *pp, Int64 *pos, ESzSeek origin) -{ - CLookToRead *p = (CLookToRead *)pp; - p->pos = p->size = 0; - return p->realStream->Seek(p->realStream, pos, origin); -} - -void LookToRead_CreateVTable(CLookToRead *p, int lookahead) -{ -#if !NEVER_CALLED - lookahead = 0; -#endif - p->s.Look = lookahead ? - LookToRead_Look_Lookahead : - LookToRead_Look_Exact; - p->s.Skip = LookToRead_Skip; - p->s.Read = LookToRead_Read; - p->s.Seek = LookToRead_Seek; -} - -void LookToRead_Init(CLookToRead *p) -{ - p->pos = p->size = 0; -} - -#if NEVER_CALLED -static SRes SecToLook_Read(void *pp, void *buf, size_t *size) -{ - CSecToLook *p = (CSecToLook *)pp; - return LookInStream_LookRead(p->realStream, buf, size); -} - -void SecToLook_CreateVTable(CSecToLook *p) -{ - p->s.Read = SecToLook_Read; -} - -static SRes SecToRead_Read(void *pp, void *buf, size_t *size) -{ - CSecToRead *p = (CSecToRead *)pp; - return p->realStream->Read(p->realStream, buf, size); -} - -void SecToRead_CreateVTable(CSecToRead *p) -{ - p->s.Read = SecToRead_Read; -} -#endif diff --git a/snesreader/7z_C/Bcj2.c b/snesreader/7z_C/Bcj2.c deleted file mode 100644 index bc3dae92..00000000 --- a/snesreader/7z_C/Bcj2.c +++ /dev/null @@ -1,132 +0,0 @@ -/* Bcj2.c -- Converter for x86 code (BCJ2) -2008-10-04 : Igor Pavlov : Public domain */ - -#include "Bcj2.h" - -#ifdef _LZMA_PROB32 -#define CProb UInt32 -#else -#define CProb UInt16 -#endif - -#define IsJcc(b0, b1) ((b0) == 0x0F && ((b1) & 0xF0) == 0x80) -#define IsJ(b0, b1) ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1)) - -#define kNumTopBits 24 -#define kTopValue ((UInt32)1 << kNumTopBits) - -#define kNumBitModelTotalBits 11 -#define kBitModelTotal (1 << kNumBitModelTotalBits) -#define kNumMoveBits 5 - -#define RC_READ_BYTE (*buffer++) -#define RC_TEST { if (buffer == bufferLim) return SZ_ERROR_DATA; } -#define RC_INIT2 code = 0; range = 0xFFFFFFFF; \ - { int i; for (i = 0; i < 5; i++) { RC_TEST; code = (code << 8) | RC_READ_BYTE; }} - -#define NORMALIZE if (range < kTopValue) { RC_TEST; range <<= 8; code = (code << 8) | RC_READ_BYTE; } - -#define IF_BIT_0(p) ttt = *(p); bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) -#define UPDATE_0(p) range = bound; *(p) = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); NORMALIZE; -#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CProb)(ttt - (ttt >> kNumMoveBits)); NORMALIZE; - -int Bcj2_Decode( - const Byte *buf0, SizeT size0, - const Byte *buf1, SizeT size1, - const Byte *buf2, SizeT size2, - const Byte *buf3, SizeT size3, - Byte *outBuf, SizeT outSize) -{ - CProb p[256 + 2]; - SizeT inPos = 0, outPos = 0; - - const Byte *buffer, *bufferLim; - UInt32 range, code; - Byte prevByte = 0; - { - unsigned int i; - for (i = 0; i < sizeof(p) / sizeof(p[0]); i++) - p[i] = kBitModelTotal >> 1; - } - buffer = buf3; - bufferLim = buffer + size3; - RC_INIT2 - - if (outSize == 0) - return SZ_OK; - - for (;;) - { - Byte b; - CProb *prob; - UInt32 bound; - UInt32 ttt; - - SizeT limit = size0 - inPos; - if (outSize - outPos < limit) - limit = outSize - outPos; - while (limit != 0) - { - Byte bb = buf0[inPos]; - outBuf[outPos++] = bb; - if (IsJ(prevByte, bb)) - break; - inPos++; - prevByte = bb; - limit--; - } - - if (limit == 0 || outPos == outSize) - break; - - b = buf0[inPos++]; - - if (b == 0xE8) - prob = p + prevByte; - else if (b == 0xE9) - prob = p + 256; - else - prob = p + 257; - - IF_BIT_0(prob) - { - UPDATE_0(prob) - prevByte = b; - } - else - { - UInt32 dest; - const Byte *v; - UPDATE_1(prob) - if (b == 0xE8) - { - v = buf1; - if (size1 < 4) - return SZ_ERROR_DATA; - buf1 += 4; - size1 -= 4; - } - else - { - v = buf2; - if (size2 < 4) - return SZ_ERROR_DATA; - buf2 += 4; - size2 -= 4; - } - dest = (((UInt32)v[0] << 24) | ((UInt32)v[1] << 16) | - ((UInt32)v[2] << 8) | ((UInt32)v[3])) - ((UInt32)outPos + 4); - outBuf[outPos++] = (Byte)dest; - if (outPos == outSize) - break; - outBuf[outPos++] = (Byte)(dest >> 8); - if (outPos == outSize) - break; - outBuf[outPos++] = (Byte)(dest >> 16); - if (outPos == outSize) - break; - outBuf[outPos++] = prevByte = (Byte)(dest >> 24); - } - } - return (outPos == outSize) ? SZ_OK : SZ_ERROR_DATA; -} diff --git a/snesreader/7z_C/Bcj2.h b/snesreader/7z_C/Bcj2.h deleted file mode 100644 index 32d450b3..00000000 --- a/snesreader/7z_C/Bcj2.h +++ /dev/null @@ -1,30 +0,0 @@ -/* Bcj2.h -- Converter for x86 code (BCJ2) -2008-10-04 : Igor Pavlov : Public domain */ - -#ifndef __BCJ2_H -#define __BCJ2_H - -#include "Types.h" - -/* -Conditions: - outSize <= FullOutputSize, - where FullOutputSize is full size of output stream of x86_2 filter. - -If buf0 overlaps outBuf, there are two required conditions: - 1) (buf0 >= outBuf) - 2) (buf0 + size0 >= outBuf + FullOutputSize). - -Returns: - SZ_OK - SZ_ERROR_DATA - Data error -*/ - -int Bcj2_Decode( - const Byte *buf0, SizeT size0, - const Byte *buf1, SizeT size1, - const Byte *buf2, SizeT size2, - const Byte *buf3, SizeT size3, - Byte *outBuf, SizeT outSize); - -#endif diff --git a/snesreader/7z_C/Bra.h b/snesreader/7z_C/Bra.h deleted file mode 100644 index 45e231e8..00000000 --- a/snesreader/7z_C/Bra.h +++ /dev/null @@ -1,60 +0,0 @@ -/* Bra.h -- Branch converters for executables -2008-10-04 : Igor Pavlov : Public domain */ - -#ifndef __BRA_H -#define __BRA_H - -#include "Types.h" - -/* -These functions convert relative addresses to absolute addresses -in CALL instructions to increase the compression ratio. - - In: - data - data buffer - size - size of data - ip - current virtual Instruction Pinter (IP) value - state - state variable for x86 converter - encoding - 0 (for decoding), 1 (for encoding) - - Out: - state - state variable for x86 converter - - Returns: - The number of processed bytes. If you call these functions with multiple calls, - you must start next call with first byte after block of processed bytes. - - Type Endian Alignment LookAhead - - x86 little 1 4 - ARMT little 2 2 - ARM little 4 0 - PPC big 4 0 - SPARC big 4 0 - IA64 little 16 0 - - size must be >= Alignment + LookAhead, if it's not last block. - If (size < Alignment + LookAhead), converter returns 0. - - Example: - - UInt32 ip = 0; - for () - { - ; size must be >= Alignment + LookAhead, if it's not last block - SizeT processed = Convert(data, size, ip, 1); - data += processed; - size -= processed; - ip += processed; - } -*/ - -#define x86_Convert_Init(state) { state = 0; } -SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding); -SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); -SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); -SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); -SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); -SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding); - -#endif diff --git a/snesreader/7z_C/Bra86.c b/snesreader/7z_C/Bra86.c deleted file mode 100644 index 1ee0e709..00000000 --- a/snesreader/7z_C/Bra86.c +++ /dev/null @@ -1,85 +0,0 @@ -/* Bra86.c -- Converter for x86 code (BCJ) -2008-10-04 : Igor Pavlov : Public domain */ - -#include "Bra.h" - -#define Test86MSByte(b) ((b) == 0 || (b) == 0xFF) - -const Byte kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0}; -const Byte kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3}; - -SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding) -{ - SizeT bufferPos = 0, prevPosT; - UInt32 prevMask = *state & 0x7; - if (size < 5) - return 0; - ip += 5; - prevPosT = (SizeT)0 - 1; - - for (;;) - { - Byte *p = data + bufferPos; - Byte *limit = data + size - 4; - for (; p < limit; p++) - if ((*p & 0xFE) == 0xE8) - break; - bufferPos = (SizeT)(p - data); - if (p >= limit) - break; - prevPosT = bufferPos - prevPosT; - if (prevPosT > 3) - prevMask = 0; - else - { - prevMask = (prevMask << ((int)prevPosT - 1)) & 0x7; - if (prevMask != 0) - { - Byte b = p[4 - kMaskToBitNumber[prevMask]]; - if (!kMaskToAllowedStatus[prevMask] || Test86MSByte(b)) - { - prevPosT = bufferPos; - prevMask = ((prevMask << 1) & 0x7) | 1; - bufferPos++; - continue; - } - } - } - prevPosT = bufferPos; - - if (Test86MSByte(p[4])) - { - UInt32 src = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]); - UInt32 dest; - for (;;) - { - Byte b; - int index; - if (encoding) - dest = (ip + (UInt32)bufferPos) + src; - else - dest = src - (ip + (UInt32)bufferPos); - if (prevMask == 0) - break; - index = kMaskToBitNumber[prevMask] * 8; - b = (Byte)(dest >> (24 - index)); - if (!Test86MSByte(b)) - break; - src = dest ^ ((1 << (32 - index)) - 1); - } - p[4] = (Byte)(~(((dest >> 24) & 1) - 1)); - p[3] = (Byte)(dest >> 16); - p[2] = (Byte)(dest >> 8); - p[1] = (Byte)dest; - bufferPos += 5; - } - else - { - prevMask = ((prevMask << 1) & 0x7) | 1; - bufferPos++; - } - } - prevPosT = bufferPos - prevPosT; - *state = ((prevPosT > 3) ? 0 : ((prevMask << ((int)prevPosT - 1)) & 0x7)); - return bufferPos; -} diff --git a/snesreader/7z_C/CpuArch.h b/snesreader/7z_C/CpuArch.h deleted file mode 100644 index 7384b0c3..00000000 --- a/snesreader/7z_C/CpuArch.h +++ /dev/null @@ -1,69 +0,0 @@ -/* CpuArch.h -2008-08-05 -Igor Pavlov -Public domain */ - -#ifndef __CPUARCH_H -#define __CPUARCH_H - -/* -LITTLE_ENDIAN_UNALIGN means: - 1) CPU is LITTLE_ENDIAN - 2) it's allowed to make unaligned memory accesses -if LITTLE_ENDIAN_UNALIGN is not defined, it means that we don't know -about these properties of platform. -*/ - -#if defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || defined(__i386__) || defined(__x86_64__) -#define LITTLE_ENDIAN_UNALIGN -#endif - -#ifdef LITTLE_ENDIAN_UNALIGN - -#define GetUi16(p) (*(const UInt16 *)(p)) -#define GetUi32(p) (*(const UInt32 *)(p)) -#define GetUi64(p) (*(const UInt64 *)(p)) -#define SetUi32(p, d) *(UInt32 *)(p) = (d); - -#else - -#define GetUi16(p) (((const Byte *)(p))[0] | ((UInt16)((const Byte *)(p))[1] << 8)) - -#define GetUi32(p) ( \ - ((const Byte *)(p))[0] | \ - ((UInt32)((const Byte *)(p))[1] << 8) | \ - ((UInt32)((const Byte *)(p))[2] << 16) | \ - ((UInt32)((const Byte *)(p))[3] << 24)) - -#define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32)) - -#define SetUi32(p, d) { UInt32 _x_ = (d); \ - ((Byte *)(p))[0] = (Byte)_x_; \ - ((Byte *)(p))[1] = (Byte)(_x_ >> 8); \ - ((Byte *)(p))[2] = (Byte)(_x_ >> 16); \ - ((Byte *)(p))[3] = (Byte)(_x_ >> 24); } - -#endif - -#if defined(LITTLE_ENDIAN_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300) - -#pragma intrinsic(_byteswap_ulong) -#pragma intrinsic(_byteswap_uint64) -#define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p)) -#define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p)) - -#else - -#define GetBe32(p) ( \ - ((UInt32)((const Byte *)(p))[0] << 24) | \ - ((UInt32)((const Byte *)(p))[1] << 16) | \ - ((UInt32)((const Byte *)(p))[2] << 8) | \ - ((const Byte *)(p))[3] ) - -#define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4)) - -#endif - -#define GetBe16(p) (((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1]) - -#endif diff --git a/snesreader/7z_C/LzmaDec.c b/snesreader/7z_C/LzmaDec.c deleted file mode 100644 index fb08e786..00000000 --- a/snesreader/7z_C/LzmaDec.c +++ /dev/null @@ -1,1010 +0,0 @@ -/* LzmaDec.c -- LZMA Decoder -2008-11-06 : Igor Pavlov : Public domain */ - -#include "LzmaDec.h" - -#include - -#define kNumTopBits 24 -#define kTopValue ((UInt32)1 << kNumTopBits) - -#define kNumBitModelTotalBits 11 -#define kBitModelTotal (1 << kNumBitModelTotalBits) -#define kNumMoveBits 5 - -#define RC_INIT_SIZE 5 - -#define NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | (*buf++); } - -#define IF_BIT_0(p) ttt = *(p); NORMALIZE; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) -#define UPDATE_0(p) range = bound; *(p) = (CLzmaProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); -#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CLzmaProb)(ttt - (ttt >> kNumMoveBits)); -#define GET_BIT2(p, i, A0, A1) IF_BIT_0(p) \ - { UPDATE_0(p); i = (i + i); A0; } else \ - { UPDATE_1(p); i = (i + i) + 1; A1; } -#define GET_BIT(p, i) GET_BIT2(p, i, ; , ;) - -#define TREE_GET_BIT(probs, i) { GET_BIT((probs + i), i); } -#define TREE_DECODE(probs, limit, i) \ - { i = 1; do { TREE_GET_BIT(probs, i); } while (i < limit); i -= limit; } - -/* #define _LZMA_SIZE_OPT */ - -#ifdef _LZMA_SIZE_OPT -#define TREE_6_DECODE(probs, i) TREE_DECODE(probs, (1 << 6), i) -#else -#define TREE_6_DECODE(probs, i) \ - { i = 1; \ - TREE_GET_BIT(probs, i); \ - TREE_GET_BIT(probs, i); \ - TREE_GET_BIT(probs, i); \ - TREE_GET_BIT(probs, i); \ - TREE_GET_BIT(probs, i); \ - TREE_GET_BIT(probs, i); \ - i -= 0x40; } -#endif - -#define NORMALIZE_CHECK if (range < kTopValue) { if (buf >= bufLimit) return DUMMY_ERROR; range <<= 8; code = (code << 8) | (*buf++); } - -#define IF_BIT_0_CHECK(p) ttt = *(p); NORMALIZE_CHECK; bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound) -#define UPDATE_0_CHECK range = bound; -#define UPDATE_1_CHECK range -= bound; code -= bound; -#define GET_BIT2_CHECK(p, i, A0, A1) IF_BIT_0_CHECK(p) \ - { UPDATE_0_CHECK; i = (i + i); A0; } else \ - { UPDATE_1_CHECK; i = (i + i) + 1; A1; } -#define GET_BIT_CHECK(p, i) GET_BIT2_CHECK(p, i, ; , ;) -#define TREE_DECODE_CHECK(probs, limit, i) \ - { i = 1; do { GET_BIT_CHECK(probs + i, i) } while (i < limit); i -= limit; } - - -#define kNumPosBitsMax 4 -#define kNumPosStatesMax (1 << kNumPosBitsMax) - -#define kLenNumLowBits 3 -#define kLenNumLowSymbols (1 << kLenNumLowBits) -#define kLenNumMidBits 3 -#define kLenNumMidSymbols (1 << kLenNumMidBits) -#define kLenNumHighBits 8 -#define kLenNumHighSymbols (1 << kLenNumHighBits) - -#define LenChoice 0 -#define LenChoice2 (LenChoice + 1) -#define LenLow (LenChoice2 + 1) -#define LenMid (LenLow + (kNumPosStatesMax << kLenNumLowBits)) -#define LenHigh (LenMid + (kNumPosStatesMax << kLenNumMidBits)) -#define kNumLenProbs (LenHigh + kLenNumHighSymbols) - - -#define kNumStates 12 -#define kNumLitStates 7 - -#define kStartPosModelIndex 4 -#define kEndPosModelIndex 14 -#define kNumFullDistances (1 << (kEndPosModelIndex >> 1)) - -#define kNumPosSlotBits 6 -#define kNumLenToPosStates 4 - -#define kNumAlignBits 4 -#define kAlignTableSize (1 << kNumAlignBits) - -#define kMatchMinLen 2 -#define kMatchSpecLenStart (kMatchMinLen + kLenNumLowSymbols + kLenNumMidSymbols + kLenNumHighSymbols) - -#define IsMatch 0 -#define IsRep (IsMatch + (kNumStates << kNumPosBitsMax)) -#define IsRepG0 (IsRep + kNumStates) -#define IsRepG1 (IsRepG0 + kNumStates) -#define IsRepG2 (IsRepG1 + kNumStates) -#define IsRep0Long (IsRepG2 + kNumStates) -#define PosSlot (IsRep0Long + (kNumStates << kNumPosBitsMax)) -#define SpecPos (PosSlot + (kNumLenToPosStates << kNumPosSlotBits)) -#define Align (SpecPos + kNumFullDistances - kEndPosModelIndex) -#define LenCoder (Align + kAlignTableSize) -#define RepLenCoder (LenCoder + kNumLenProbs) -#define Literal (RepLenCoder + kNumLenProbs) - -#define LZMA_BASE_SIZE 1846 -#define LZMA_LIT_SIZE 768 - -#define LzmaProps_GetNumProbs(p) ((UInt32)LZMA_BASE_SIZE + (LZMA_LIT_SIZE << ((p)->lc + (p)->lp))) - -#if Literal != LZMA_BASE_SIZE -StopCompilingDueBUG -#endif - -static const Byte kLiteralNextStates[kNumStates * 2] = -{ - 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5, - 7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10 -}; - -#define LZMA_DIC_MIN (1 << 12) - -/* First LZMA-symbol is always decoded. -And it decodes new LZMA-symbols while (buf < bufLimit), but "buf" is without last normalization -Out: - Result: - SZ_OK - OK - SZ_ERROR_DATA - Error - p->remainLen: - < kMatchSpecLenStart : normal remain - = kMatchSpecLenStart : finished - = kMatchSpecLenStart + 1 : Flush marker - = kMatchSpecLenStart + 2 : State Init Marker -*/ - -static int MY_FAST_CALL LzmaDec_DecodeReal(CLzmaDec *p, SizeT limit, const Byte *bufLimit) -{ - CLzmaProb *probs = p->probs; - - unsigned state = p->state; - UInt32 rep0 = p->reps[0], rep1 = p->reps[1], rep2 = p->reps[2], rep3 = p->reps[3]; - unsigned pbMask = ((unsigned)1 << (p->prop.pb)) - 1; - unsigned lpMask = ((unsigned)1 << (p->prop.lp)) - 1; - unsigned lc = p->prop.lc; - - Byte *dic = p->dic; - SizeT dicBufSize = p->dicBufSize; - SizeT dicPos = p->dicPos; - - UInt32 processedPos = p->processedPos; - UInt32 checkDicSize = p->checkDicSize; - unsigned len = 0; - - const Byte *buf = p->buf; - UInt32 range = p->range; - UInt32 code = p->code; - - do - { - CLzmaProb *prob; - UInt32 bound; - unsigned ttt; - unsigned posState = processedPos & pbMask; - - prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; - IF_BIT_0(prob) - { - unsigned symbol; - UPDATE_0(prob); - prob = probs + Literal; - if (checkDicSize != 0 || processedPos != 0) - prob += (LZMA_LIT_SIZE * (((processedPos & lpMask) << lc) + - (dic[(dicPos == 0 ? dicBufSize : dicPos) - 1] >> (8 - lc)))); - - if (state < kNumLitStates) - { - symbol = 1; - do { GET_BIT(prob + symbol, symbol) } while (symbol < 0x100); - } - else - { - unsigned matchByte = p->dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; - unsigned offs = 0x100; - symbol = 1; - do - { - unsigned bit; - CLzmaProb *probLit; - matchByte <<= 1; - bit = (matchByte & offs); - probLit = prob + offs + bit + symbol; - GET_BIT2(probLit, symbol, offs &= ~bit, offs &= bit) - } - while (symbol < 0x100); - } - dic[dicPos++] = (Byte)symbol; - processedPos++; - - state = kLiteralNextStates[state]; - /* if (state < 4) state = 0; else if (state < 10) state -= 3; else state -= 6; */ - continue; - } - else - { - UPDATE_1(prob); - prob = probs + IsRep + state; - IF_BIT_0(prob) - { - UPDATE_0(prob); - state += kNumStates; - prob = probs + LenCoder; - } - else - { - UPDATE_1(prob); - if (checkDicSize == 0 && processedPos == 0) - return SZ_ERROR_DATA; - prob = probs + IsRepG0 + state; - IF_BIT_0(prob) - { - UPDATE_0(prob); - prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; - IF_BIT_0(prob) - { - UPDATE_0(prob); - dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; - dicPos++; - processedPos++; - state = state < kNumLitStates ? 9 : 11; - continue; - } - UPDATE_1(prob); - } - else - { - UInt32 distance; - UPDATE_1(prob); - prob = probs + IsRepG1 + state; - IF_BIT_0(prob) - { - UPDATE_0(prob); - distance = rep1; - } - else - { - UPDATE_1(prob); - prob = probs + IsRepG2 + state; - IF_BIT_0(prob) - { - UPDATE_0(prob); - distance = rep2; - } - else - { - UPDATE_1(prob); - distance = rep3; - rep3 = rep2; - } - rep2 = rep1; - } - rep1 = rep0; - rep0 = distance; - } - state = state < kNumLitStates ? 8 : 11; - prob = probs + RepLenCoder; - } - { - unsigned limit2, offset; - CLzmaProb *probLen = prob + LenChoice; - IF_BIT_0(probLen) - { - UPDATE_0(probLen); - probLen = prob + LenLow + (posState << kLenNumLowBits); - offset = 0; - limit2 = (1 << kLenNumLowBits); - } - else - { - UPDATE_1(probLen); - probLen = prob + LenChoice2; - IF_BIT_0(probLen) - { - UPDATE_0(probLen); - probLen = prob + LenMid + (posState << kLenNumMidBits); - offset = kLenNumLowSymbols; - limit2 = (1 << kLenNumMidBits); - } - else - { - UPDATE_1(probLen); - probLen = prob + LenHigh; - offset = kLenNumLowSymbols + kLenNumMidSymbols; - limit2 = (1 << kLenNumHighBits); - } - } - TREE_DECODE(probLen, limit2, len); - len += offset; - } - - if (state >= kNumStates) - { - UInt32 distance; - prob = probs + PosSlot + - ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << kNumPosSlotBits); - TREE_6_DECODE(prob, distance); - if (distance >= kStartPosModelIndex) - { - unsigned posSlot = (unsigned)distance; - int numDirectBits = (int)(((distance >> 1) - 1)); - distance = (2 | (distance & 1)); - if (posSlot < kEndPosModelIndex) - { - distance <<= numDirectBits; - prob = probs + SpecPos + distance - posSlot - 1; - { - UInt32 mask = 1; - unsigned i = 1; - do - { - GET_BIT2(prob + i, i, ; , distance |= mask); - mask <<= 1; - } - while (--numDirectBits != 0); - } - } - else - { - numDirectBits -= kNumAlignBits; - do - { - NORMALIZE - range >>= 1; - - { - UInt32 t; - code -= range; - t = (0 - ((UInt32)code >> 31)); /* (UInt32)((Int32)code >> 31) */ - distance = (distance << 1) + (t + 1); - code += range & t; - } - /* - distance <<= 1; - if (code >= range) - { - code -= range; - distance |= 1; - } - */ - } - while (--numDirectBits != 0); - prob = probs + Align; - distance <<= kNumAlignBits; - { - unsigned i = 1; - GET_BIT2(prob + i, i, ; , distance |= 1); - GET_BIT2(prob + i, i, ; , distance |= 2); - GET_BIT2(prob + i, i, ; , distance |= 4); - GET_BIT2(prob + i, i, ; , distance |= 8); - } - if (distance == (UInt32)0xFFFFFFFF) - { - len += kMatchSpecLenStart; - state -= kNumStates; - break; - } - } - } - rep3 = rep2; - rep2 = rep1; - rep1 = rep0; - rep0 = distance + 1; - if (checkDicSize == 0) - { - if (distance >= processedPos) - return SZ_ERROR_DATA; - } - else if (distance >= checkDicSize) - return SZ_ERROR_DATA; - state = (state < kNumStates + kNumLitStates) ? kNumLitStates : kNumLitStates + 3; - /* state = kLiteralNextStates[state]; */ - } - - len += kMatchMinLen; - - if (limit == dicPos) - return SZ_ERROR_DATA; - { - SizeT rem = limit - dicPos; - unsigned curLen = ((rem < len) ? (unsigned)rem : len); - SizeT pos = (dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0); - - processedPos += curLen; - - len -= curLen; - if (pos + curLen <= dicBufSize) - { - Byte *dest = dic + dicPos; - ptrdiff_t src = (ptrdiff_t)pos - (ptrdiff_t)dicPos; - const Byte *lim = dest + curLen; - dicPos += curLen; - do - *(dest) = (Byte)*(dest + src); - while (++dest != lim); - } - else - { - do - { - dic[dicPos++] = dic[pos]; - if (++pos == dicBufSize) - pos = 0; - } - while (--curLen != 0); - } - } - } - } - while (dicPos < limit && buf < bufLimit); - NORMALIZE; - p->buf = buf; - p->range = range; - p->code = code; - p->remainLen = len; - p->dicPos = dicPos; - p->processedPos = processedPos; - p->reps[0] = rep0; - p->reps[1] = rep1; - p->reps[2] = rep2; - p->reps[3] = rep3; - p->state = state; - - return SZ_OK; -} - -static void MY_FAST_CALL LzmaDec_WriteRem(CLzmaDec *p, SizeT limit) -{ - if (p->remainLen != 0 && p->remainLen < kMatchSpecLenStart) - { - Byte *dic = p->dic; - SizeT dicPos = p->dicPos; - SizeT dicBufSize = p->dicBufSize; - unsigned len = p->remainLen; - UInt32 rep0 = p->reps[0]; - if (limit - dicPos < len) - len = (unsigned)(limit - dicPos); - - if (p->checkDicSize == 0 && p->prop.dicSize - p->processedPos <= len) - p->checkDicSize = p->prop.dicSize; - - p->processedPos += len; - p->remainLen -= len; - while (len-- != 0) - { - dic[dicPos] = dic[(dicPos - rep0) + ((dicPos < rep0) ? dicBufSize : 0)]; - dicPos++; - } - p->dicPos = dicPos; - } -} - -static int MY_FAST_CALL LzmaDec_DecodeReal2(CLzmaDec *p, SizeT limit, const Byte *bufLimit) -{ - do - { - SizeT limit2 = limit; - if (p->checkDicSize == 0) - { - UInt32 rem = p->prop.dicSize - p->processedPos; - if (limit - p->dicPos > rem) - limit2 = p->dicPos + rem; - } - RINOK(LzmaDec_DecodeReal(p, limit2, bufLimit)); - if (p->processedPos >= p->prop.dicSize) - p->checkDicSize = p->prop.dicSize; - LzmaDec_WriteRem(p, limit); - } - while (p->dicPos < limit && p->buf < bufLimit && p->remainLen < kMatchSpecLenStart); - - if (p->remainLen > kMatchSpecLenStart) - { - p->remainLen = kMatchSpecLenStart; - } - return 0; -} - -typedef enum -{ - DUMMY_ERROR, /* unexpected end of input stream */ - DUMMY_LIT, - DUMMY_MATCH, - DUMMY_REP -} ELzmaDummy; - -static ELzmaDummy LzmaDec_TryDummy(const CLzmaDec *p, const Byte *buf, SizeT inSize) -{ - UInt32 range = p->range; - UInt32 code = p->code; - const Byte *bufLimit = buf + inSize; - CLzmaProb *probs = p->probs; - unsigned state = p->state; - ELzmaDummy res; - - { - CLzmaProb *prob; - UInt32 bound; - unsigned ttt; - unsigned posState = (p->processedPos) & ((1 << p->prop.pb) - 1); - - prob = probs + IsMatch + (state << kNumPosBitsMax) + posState; - IF_BIT_0_CHECK(prob) - { - UPDATE_0_CHECK - - /* if (bufLimit - buf >= 7) return DUMMY_LIT; */ - - prob = probs + Literal; - if (p->checkDicSize != 0 || p->processedPos != 0) - prob += (LZMA_LIT_SIZE * - ((((p->processedPos) & ((1 << (p->prop.lp)) - 1)) << p->prop.lc) + - (p->dic[(p->dicPos == 0 ? p->dicBufSize : p->dicPos) - 1] >> (8 - p->prop.lc)))); - - if (state < kNumLitStates) - { - unsigned symbol = 1; - do { GET_BIT_CHECK(prob + symbol, symbol) } while (symbol < 0x100); - } - else - { - unsigned matchByte = p->dic[p->dicPos - p->reps[0] + - ((p->dicPos < p->reps[0]) ? p->dicBufSize : 0)]; - unsigned offs = 0x100; - unsigned symbol = 1; - do - { - unsigned bit; - CLzmaProb *probLit; - matchByte <<= 1; - bit = (matchByte & offs); - probLit = prob + offs + bit + symbol; - GET_BIT2_CHECK(probLit, symbol, offs &= ~bit, offs &= bit) - } - while (symbol < 0x100); - } - res = DUMMY_LIT; - } - else - { - unsigned len; - UPDATE_1_CHECK; - - prob = probs + IsRep + state; - IF_BIT_0_CHECK(prob) - { - UPDATE_0_CHECK; - state = 0; - prob = probs + LenCoder; - res = DUMMY_MATCH; - } - else - { - UPDATE_1_CHECK; - res = DUMMY_REP; - prob = probs + IsRepG0 + state; - IF_BIT_0_CHECK(prob) - { - UPDATE_0_CHECK; - prob = probs + IsRep0Long + (state << kNumPosBitsMax) + posState; - IF_BIT_0_CHECK(prob) - { - UPDATE_0_CHECK; - NORMALIZE_CHECK; - return DUMMY_REP; - } - else - { - UPDATE_1_CHECK; - } - } - else - { - UPDATE_1_CHECK; - prob = probs + IsRepG1 + state; - IF_BIT_0_CHECK(prob) - { - UPDATE_0_CHECK; - } - else - { - UPDATE_1_CHECK; - prob = probs + IsRepG2 + state; - IF_BIT_0_CHECK(prob) - { - UPDATE_0_CHECK; - } - else - { - UPDATE_1_CHECK; - } - } - } - state = kNumStates; - prob = probs + RepLenCoder; - } - { - unsigned limit, offset; - CLzmaProb *probLen = prob + LenChoice; - IF_BIT_0_CHECK(probLen) - { - UPDATE_0_CHECK; - probLen = prob + LenLow + (posState << kLenNumLowBits); - offset = 0; - limit = 1 << kLenNumLowBits; - } - else - { - UPDATE_1_CHECK; - probLen = prob + LenChoice2; - IF_BIT_0_CHECK(probLen) - { - UPDATE_0_CHECK; - probLen = prob + LenMid + (posState << kLenNumMidBits); - offset = kLenNumLowSymbols; - limit = 1 << kLenNumMidBits; - } - else - { - UPDATE_1_CHECK; - probLen = prob + LenHigh; - offset = kLenNumLowSymbols + kLenNumMidSymbols; - limit = 1 << kLenNumHighBits; - } - } - TREE_DECODE_CHECK(probLen, limit, len); - len += offset; - } - - if (state < 4) - { - unsigned posSlot; - prob = probs + PosSlot + - ((len < kNumLenToPosStates ? len : kNumLenToPosStates - 1) << - kNumPosSlotBits); - TREE_DECODE_CHECK(prob, 1 << kNumPosSlotBits, posSlot); - if (posSlot >= kStartPosModelIndex) - { - int numDirectBits = ((posSlot >> 1) - 1); - - /* if (bufLimit - buf >= 8) return DUMMY_MATCH; */ - - if (posSlot < kEndPosModelIndex) - { - prob = probs + SpecPos + ((2 | (posSlot & 1)) << numDirectBits) - posSlot - 1; - } - else - { - numDirectBits -= kNumAlignBits; - do - { - NORMALIZE_CHECK - range >>= 1; - code -= range & (((code - range) >> 31) - 1); - /* if (code >= range) code -= range; */ - } - while (--numDirectBits != 0); - prob = probs + Align; - numDirectBits = kNumAlignBits; - } - { - unsigned i = 1; - do - { - GET_BIT_CHECK(prob + i, i); - } - while (--numDirectBits != 0); - } - } - } - } - } - NORMALIZE_CHECK; - return res; -} - - -static void LzmaDec_InitRc(CLzmaDec *p, const Byte *data) -{ - p->code = ((UInt32)data[1] << 24) | ((UInt32)data[2] << 16) | ((UInt32)data[3] << 8) | ((UInt32)data[4]); - p->range = 0xFFFFFFFF; - p->needFlush = 0; -} - -static -void LzmaDec_InitDicAndState(CLzmaDec *p, Bool initDic, Bool initState) -{ - p->needFlush = 1; - p->remainLen = 0; - p->tempBufSize = 0; - - if (initDic) - { - p->processedPos = 0; - p->checkDicSize = 0; - p->needInitState = 1; - } - if (initState) - p->needInitState = 1; -} - -void LzmaDec_Init(CLzmaDec *p) -{ - p->dicPos = 0; - LzmaDec_InitDicAndState(p, True, True); -} - -static void LzmaDec_InitStateReal(CLzmaDec *p) -{ - UInt32 numProbs = Literal + ((UInt32)LZMA_LIT_SIZE << (p->prop.lc + p->prop.lp)); - UInt32 i; - CLzmaProb *probs = p->probs; - for (i = 0; i < numProbs; i++) - probs[i] = kBitModelTotal >> 1; - p->reps[0] = p->reps[1] = p->reps[2] = p->reps[3] = 1; - p->state = 0; - p->needInitState = 0; -} - -SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, const Byte *src, SizeT *srcLen, - ELzmaFinishMode finishMode, ELzmaStatus *status) -{ - SizeT inSize = *srcLen; - (*srcLen) = 0; - LzmaDec_WriteRem(p, dicLimit); - - *status = LZMA_STATUS_NOT_SPECIFIED; - - while (p->remainLen != kMatchSpecLenStart) - { - int checkEndMarkNow; - - if (p->needFlush != 0) - { - for (; inSize > 0 && p->tempBufSize < RC_INIT_SIZE; (*srcLen)++, inSize--) - p->tempBuf[p->tempBufSize++] = *src++; - if (p->tempBufSize < RC_INIT_SIZE) - { - *status = LZMA_STATUS_NEEDS_MORE_INPUT; - return SZ_OK; - } - if (p->tempBuf[0] != 0) - return SZ_ERROR_DATA; - - LzmaDec_InitRc(p, p->tempBuf); - p->tempBufSize = 0; - } - - checkEndMarkNow = 0; - if (p->dicPos >= dicLimit) - { - if (p->remainLen == 0 && p->code == 0) - { - *status = LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK; - return SZ_OK; - } - if (finishMode == LZMA_FINISH_ANY) - { - *status = LZMA_STATUS_NOT_FINISHED; - return SZ_OK; - } - if (p->remainLen != 0) - { - *status = LZMA_STATUS_NOT_FINISHED; - return SZ_ERROR_DATA; - } - checkEndMarkNow = 1; - } - - if (p->needInitState) - LzmaDec_InitStateReal(p); - - if (p->tempBufSize == 0) - { - SizeT processed; - const Byte *bufLimit; - if (inSize < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) - { - int dummyRes = LzmaDec_TryDummy(p, src, inSize); - if (dummyRes == DUMMY_ERROR) - { - memcpy(p->tempBuf, src, inSize); - p->tempBufSize = (unsigned)inSize; - (*srcLen) += inSize; - *status = LZMA_STATUS_NEEDS_MORE_INPUT; - return SZ_OK; - } - if (checkEndMarkNow && dummyRes != DUMMY_MATCH) - { - *status = LZMA_STATUS_NOT_FINISHED; - return SZ_ERROR_DATA; - } - bufLimit = src; - } - else - bufLimit = src + inSize - LZMA_REQUIRED_INPUT_MAX; - p->buf = src; - if (LzmaDec_DecodeReal2(p, dicLimit, bufLimit) != 0) - return SZ_ERROR_DATA; - processed = (SizeT)(p->buf - src); - (*srcLen) += processed; - src += processed; - inSize -= processed; - } - else - { - unsigned rem = p->tempBufSize, lookAhead = 0; - while (rem < LZMA_REQUIRED_INPUT_MAX && lookAhead < inSize) - p->tempBuf[rem++] = src[lookAhead++]; - p->tempBufSize = rem; - if (rem < LZMA_REQUIRED_INPUT_MAX || checkEndMarkNow) - { - int dummyRes = LzmaDec_TryDummy(p, p->tempBuf, rem); - if (dummyRes == DUMMY_ERROR) - { - (*srcLen) += lookAhead; - *status = LZMA_STATUS_NEEDS_MORE_INPUT; - return SZ_OK; - } - if (checkEndMarkNow && dummyRes != DUMMY_MATCH) - { - *status = LZMA_STATUS_NOT_FINISHED; - return SZ_ERROR_DATA; - } - } - p->buf = p->tempBuf; - if (LzmaDec_DecodeReal2(p, dicLimit, p->buf) != 0) - return SZ_ERROR_DATA; - lookAhead -= (rem - (unsigned)(p->buf - p->tempBuf)); - (*srcLen) += lookAhead; - src += lookAhead; - inSize -= lookAhead; - p->tempBufSize = 0; - } - } - if (p->code == 0) - *status = LZMA_STATUS_FINISHED_WITH_MARK; - return (p->code == 0) ? SZ_OK : SZ_ERROR_DATA; -} - -#if NEVER_CALLED -SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status) -{ - SizeT outSize = *destLen; - SizeT inSize = *srcLen; - *srcLen = *destLen = 0; - for (;;) - { - SizeT inSizeCur = inSize, outSizeCur, dicPos; - ELzmaFinishMode curFinishMode; - SRes res; - if (p->dicPos == p->dicBufSize) - p->dicPos = 0; - dicPos = p->dicPos; - if (outSize > p->dicBufSize - dicPos) - { - outSizeCur = p->dicBufSize; - curFinishMode = LZMA_FINISH_ANY; - } - else - { - outSizeCur = dicPos + outSize; - curFinishMode = finishMode; - } - - res = LzmaDec_DecodeToDic(p, outSizeCur, src, &inSizeCur, curFinishMode, status); - src += inSizeCur; - inSize -= inSizeCur; - *srcLen += inSizeCur; - outSizeCur = p->dicPos - dicPos; - memcpy(dest, p->dic + dicPos, outSizeCur); - dest += outSizeCur; - outSize -= outSizeCur; - *destLen += outSizeCur; - if (res != 0) - return res; - if (outSizeCur == 0 || outSize == 0) - return SZ_OK; - } -} -#endif - -void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc) -{ - alloc->Free(alloc, p->probs); - p->probs = 0; -} - -static void LzmaDec_FreeDict(CLzmaDec *p, ISzAlloc *alloc) -{ - alloc->Free(alloc, p->dic); - p->dic = 0; -} - -void LzmaDec_Free(CLzmaDec *p, ISzAlloc *alloc) -{ - LzmaDec_FreeProbs(p, alloc); - LzmaDec_FreeDict(p, alloc); -} - -SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size) -{ - UInt32 dicSize; - Byte d; - - if (size < LZMA_PROPS_SIZE) - return SZ_ERROR_UNSUPPORTED; - else - dicSize = data[1] | ((UInt32)data[2] << 8) | ((UInt32)data[3] << 16) | ((UInt32)data[4] << 24); - - if (dicSize < LZMA_DIC_MIN) - dicSize = LZMA_DIC_MIN; - p->dicSize = dicSize; - - d = data[0]; - if (d >= (9 * 5 * 5)) - return SZ_ERROR_UNSUPPORTED; - - p->lc = d % 9; - d /= 9; - p->pb = d / 5; - p->lp = d % 5; - - return SZ_OK; -} - -static SRes LzmaDec_AllocateProbs2(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc) -{ - UInt32 numProbs = LzmaProps_GetNumProbs(propNew); - if (p->probs == 0 || numProbs != p->numProbs) - { - LzmaDec_FreeProbs(p, alloc); - p->probs = (CLzmaProb *)alloc->Alloc(alloc, numProbs * sizeof(CLzmaProb)); - p->numProbs = numProbs; - if (p->probs == 0) - return SZ_ERROR_MEM; - } - return SZ_OK; -} - -SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) -{ - CLzmaProps propNew; - RINOK(LzmaProps_Decode(&propNew, props, propsSize)); - RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); - p->prop = propNew; - return SZ_OK; -} - -SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc) -{ - CLzmaProps propNew; - SizeT dicBufSize; - RINOK(LzmaProps_Decode(&propNew, props, propsSize)); - RINOK(LzmaDec_AllocateProbs2(p, &propNew, alloc)); - dicBufSize = propNew.dicSize; - if (p->dic == 0 || dicBufSize != p->dicBufSize) - { - LzmaDec_FreeDict(p, alloc); - p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize); - if (p->dic == 0) - { - LzmaDec_FreeProbs(p, alloc); - return SZ_ERROR_MEM; - } - } - p->dicBufSize = dicBufSize; - p->prop = propNew; - return SZ_OK; -} - -SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, - const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, - ELzmaStatus *status, ISzAlloc *alloc) -{ - CLzmaDec p; - SRes res; - SizeT inSize = *srcLen; - SizeT outSize = *destLen; - *srcLen = *destLen = 0; - if (inSize < RC_INIT_SIZE) - return SZ_ERROR_INPUT_EOF; - - LzmaDec_Construct(&p); - res = LzmaDec_AllocateProbs(&p, propData, propSize, alloc); - if (res != 0) - return res; - p.dic = dest; - p.dicBufSize = outSize; - - LzmaDec_Init(&p); - - *srcLen = inSize; - res = LzmaDec_DecodeToDic(&p, outSize, src, srcLen, finishMode, status); - - if (res == SZ_OK && *status == LZMA_STATUS_NEEDS_MORE_INPUT) - res = SZ_ERROR_INPUT_EOF; - - (*destLen) = p.dicPos; - LzmaDec_FreeProbs(&p, alloc); - return res; -} diff --git a/snesreader/7z_C/LzmaDec.h b/snesreader/7z_C/LzmaDec.h deleted file mode 100644 index 98cdbe94..00000000 --- a/snesreader/7z_C/LzmaDec.h +++ /dev/null @@ -1,223 +0,0 @@ -/* LzmaDec.h -- LZMA Decoder -2008-10-04 : Igor Pavlov : Public domain */ - -#ifndef __LZMADEC_H -#define __LZMADEC_H - -#include "Types.h" - -/* #define _LZMA_PROB32 */ -/* _LZMA_PROB32 can increase the speed on some CPUs, - but memory usage for CLzmaDec::probs will be doubled in that case */ - -#ifdef _LZMA_PROB32 -#define CLzmaProb UInt32 -#else -#define CLzmaProb UInt16 -#endif - - -/* ---------- LZMA Properties ---------- */ - -#define LZMA_PROPS_SIZE 5 - -typedef struct _CLzmaProps -{ - unsigned lc, lp, pb; - UInt32 dicSize; -} CLzmaProps; - -/* LzmaProps_Decode - decodes properties -Returns: - SZ_OK - SZ_ERROR_UNSUPPORTED - Unsupported properties -*/ - -SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size); - - -/* ---------- LZMA Decoder state ---------- */ - -/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case. - Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */ - -#define LZMA_REQUIRED_INPUT_MAX 20 - -typedef struct -{ - CLzmaProps prop; - CLzmaProb *probs; - Byte *dic; - const Byte *buf; - UInt32 range, code; - SizeT dicPos; - SizeT dicBufSize; - UInt32 processedPos; - UInt32 checkDicSize; - unsigned state; - UInt32 reps[4]; - unsigned remainLen; - int needFlush; - int needInitState; - UInt32 numProbs; - unsigned tempBufSize; - Byte tempBuf[LZMA_REQUIRED_INPUT_MAX]; -} CLzmaDec; - -#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; } - -void LzmaDec_Init(CLzmaDec *p); - -/* There are two types of LZMA streams: - 0) Stream with end mark. That end mark adds about 6 bytes to compressed size. - 1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */ - -typedef enum -{ - LZMA_FINISH_ANY, /* finish at any point */ - LZMA_FINISH_END /* block must be finished at the end */ -} ELzmaFinishMode; - -/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!! - - You must use LZMA_FINISH_END, when you know that current output buffer - covers last bytes of block. In other cases you must use LZMA_FINISH_ANY. - - If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK, - and output value of destLen will be less than output buffer size limit. - You can check status result also. - - You can use multiple checks to test data integrity after full decompression: - 1) Check Result and "status" variable. - 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. - 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. - You must use correct finish mode in that case. */ - -typedef enum -{ - LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */ - LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */ - LZMA_STATUS_NOT_FINISHED, /* stream was not finished */ - LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */ - LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */ -} ELzmaStatus; - -/* ELzmaStatus is used only as output value for function call */ - - -/* ---------- Interfaces ---------- */ - -/* There are 3 levels of interfaces: - 1) Dictionary Interface - 2) Buffer Interface - 3) One Call Interface - You can select any of these interfaces, but don't mix functions from different - groups for same object. */ - - -/* There are two variants to allocate state for Dictionary Interface: - 1) LzmaDec_Allocate / LzmaDec_Free - 2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs - You can use variant 2, if you set dictionary buffer manually. - For Buffer Interface you must always use variant 1. - -LzmaDec_Allocate* can return: - SZ_OK - SZ_ERROR_MEM - Memory allocation error - SZ_ERROR_UNSUPPORTED - Unsupported properties -*/ - -SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc); -void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc); - -SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc); -void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc); - -/* ---------- Dictionary Interface ---------- */ - -/* You can use it, if you want to eliminate the overhead for data copying from - dictionary to some other external buffer. - You must work with CLzmaDec variables directly in this interface. - - STEPS: - LzmaDec_Constr() - LzmaDec_Allocate() - for (each new stream) - { - LzmaDec_Init() - while (it needs more decompression) - { - LzmaDec_DecodeToDic() - use data from CLzmaDec::dic and update CLzmaDec::dicPos - } - } - LzmaDec_Free() -*/ - -/* LzmaDec_DecodeToDic - - The decoding to internal dictionary buffer (CLzmaDec::dic). - You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!! - -finishMode: - It has meaning only if the decoding reaches output limit (dicLimit). - LZMA_FINISH_ANY - Decode just dicLimit bytes. - LZMA_FINISH_END - Stream must be finished after dicLimit. - -Returns: - SZ_OK - status: - LZMA_STATUS_FINISHED_WITH_MARK - LZMA_STATUS_NOT_FINISHED - LZMA_STATUS_NEEDS_MORE_INPUT - LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK - SZ_ERROR_DATA - Data error -*/ - -SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit, - const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); - - -/* ---------- Buffer Interface ---------- */ - -/* It's zlib-like interface. - See LzmaDec_DecodeToDic description for information about STEPS and return results, - but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need - to work with CLzmaDec variables manually. - -finishMode: - It has meaning only if the decoding reaches output limit (*destLen). - LZMA_FINISH_ANY - Decode just destLen bytes. - LZMA_FINISH_END - Stream must be finished after (*destLen). -*/ - -SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, - const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status); - - -/* ---------- One Call Interface ---------- */ - -/* LzmaDecode - -finishMode: - It has meaning only if the decoding reaches output limit (*destLen). - LZMA_FINISH_ANY - Decode just destLen bytes. - LZMA_FINISH_END - Stream must be finished after (*destLen). - -Returns: - SZ_OK - status: - LZMA_STATUS_FINISHED_WITH_MARK - LZMA_STATUS_NOT_FINISHED - LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK - SZ_ERROR_DATA - Data error - SZ_ERROR_MEM - Memory allocation error - SZ_ERROR_UNSUPPORTED - Unsupported properties - SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). -*/ - -SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, - const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, - ELzmaStatus *status, ISzAlloc *alloc); - -#endif diff --git a/snesreader/7z_C/Types.h b/snesreader/7z_C/Types.h deleted file mode 100644 index 286ce83b..00000000 --- a/snesreader/7z_C/Types.h +++ /dev/null @@ -1,206 +0,0 @@ -/* Types.h -- Basic types -2008-11-23 : Igor Pavlov : Public domain */ - -#ifndef __7Z_TYPES_H -#define __7Z_TYPES_H - -#include - -#ifdef __cplusplus - extern "C" { -#endif - -#define SZ_OK 0 - -#define SZ_ERROR_DATA 1 -#define SZ_ERROR_MEM 2 -#define SZ_ERROR_CRC 3 -#define SZ_ERROR_UNSUPPORTED 4 -#define SZ_ERROR_PARAM 5 -#define SZ_ERROR_INPUT_EOF 6 -#define SZ_ERROR_OUTPUT_EOF 7 -#define SZ_ERROR_READ 8 -#define SZ_ERROR_WRITE 9 -#define SZ_ERROR_PROGRESS 10 -#define SZ_ERROR_FAIL 11 -#define SZ_ERROR_THREAD 12 - -#define SZ_ERROR_ARCHIVE 16 -#define SZ_ERROR_NO_ARCHIVE 17 - -typedef int SRes; - -#ifndef RINOK -#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; } -#endif - -typedef unsigned char Byte; -typedef short Int16; -typedef unsigned short UInt16; - -#ifdef _LZMA_UINT32_IS_ULONG -typedef long Int32; -typedef unsigned long UInt32; -#else -typedef int Int32; -typedef unsigned int UInt32; -#endif - -#ifdef _SZ_NO_INT_64 - -/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers. - NOTES: Some code will work incorrectly in that case! */ - -typedef long Int64; -typedef unsigned long UInt64; - -#else - -#if defined(_MSC_VER) || defined(__BORLANDC__) -typedef __int64 Int64; -typedef unsigned __int64 UInt64; -#else -typedef long long int Int64; -typedef unsigned long long int UInt64; -#endif - -#endif - -#ifdef _LZMA_NO_SYSTEM_SIZE_T -typedef UInt32 SizeT; -#else -typedef size_t SizeT; -#endif - -typedef int Bool; -#define True 1 -#define False 0 - - -#ifdef _MSC_VER - -#if _MSC_VER >= 1300 -#define MY_NO_INLINE __declspec(noinline) -#else -#define MY_NO_INLINE -#endif - -#define MY_CDECL __cdecl -#define MY_STD_CALL __stdcall -#define MY_FAST_CALL MY_NO_INLINE __fastcall - -#else - -#define MY_CDECL -#define MY_STD_CALL -#define MY_FAST_CALL - -#endif - - -/* The following interfaces use first parameter as pointer to structure */ - -typedef struct -{ - SRes (*Read)(void *p, void *buf, size_t *size); - /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. - (output(*size) < input(*size)) is allowed */ -} ISeqInStream; - -/* it can return SZ_ERROR_INPUT_EOF */ -SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size); -SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType); -SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf); - -typedef struct -{ - size_t (*Write)(void *p, const void *buf, size_t size); - /* Returns: result - the number of actually written bytes. - (result < size) means error */ -} ISeqOutStream; - -typedef enum -{ - SZ_SEEK_SET = 0, - SZ_SEEK_CUR = 1, - SZ_SEEK_END = 2 -} ESzSeek; - -typedef struct -{ - SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */ - SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); -} ISeekInStream; - -typedef struct -{ - SRes (*Look)(void *p, void **buf, size_t *size); - /* if (input(*size) != 0 && output(*size) == 0) means end_of_stream. - (output(*size) > input(*size)) is not allowed - (output(*size) < input(*size)) is allowed */ - SRes (*Skip)(void *p, size_t offset); - /* offset must be <= output(*size) of Look */ - - SRes (*Read)(void *p, void *buf, size_t *size); - /* reads directly (without buffer). It's same as ISeqInStream::Read */ - SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin); -} ILookInStream; - -SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size); -SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset); - -/* reads via ILookInStream::Read */ -SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType); -SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size); - -#define LookToRead_BUF_SIZE (1 << 14) - -typedef struct -{ - ILookInStream s; - ISeekInStream *realStream; - size_t pos; - size_t size; - Byte buf[LookToRead_BUF_SIZE]; -} CLookToRead; - -void LookToRead_CreateVTable(CLookToRead *p, int lookahead); -void LookToRead_Init(CLookToRead *p); - -typedef struct -{ - ISeqInStream s; - ILookInStream *realStream; -} CSecToLook; - -void SecToLook_CreateVTable(CSecToLook *p); - -typedef struct -{ - ISeqInStream s; - ILookInStream *realStream; -} CSecToRead; - -void SecToRead_CreateVTable(CSecToRead *p); - -typedef struct -{ - SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize); - /* Returns: result. (result != SZ_OK) means break. - Value (UInt64)(Int64)-1 for size means unknown value. */ -} ICompressProgress; - -typedef struct -{ - void *(*Alloc)(void *p, size_t size); - void (*Free)(void *p, void *address); /* address can be 0 */ -} ISzAlloc; - -#define IAlloc_Alloc(p, size) (p)->Alloc((p), size) -#define IAlloc_Free(p, a) (p)->Free((p), a) - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/snesreader/7z_C/lzma.txt b/snesreader/7z_C/lzma.txt deleted file mode 100644 index d4f4af92..00000000 --- a/snesreader/7z_C/lzma.txt +++ /dev/null @@ -1,594 +0,0 @@ -LZMA SDK 4.65 -------------- - -LZMA SDK provides the documentation, samples, header files, libraries, -and tools you need to develop applications that use LZMA compression. - -LZMA is default and general compression method of 7z format -in 7-Zip compression program (www.7-zip.org). LZMA provides high -compression ratio and very fast decompression. - -LZMA is an improved version of famous LZ77 compression algorithm. -It was improved in way of maximum increasing of compression ratio, -keeping high decompression speed and low memory requirements for -decompressing. - - - -LICENSE -------- - -LZMA SDK is written and placed in the public domain by Igor Pavlov. - - -LZMA SDK Contents ------------------ - -LZMA SDK includes: - - - ANSI-C/C++/C#/Java source code for LZMA compressing and decompressing - - Compiled file->file LZMA compressing/decompressing program for Windows system - - -UNIX/Linux version ------------------- -To compile C++ version of file->file LZMA encoding, go to directory -C++/7zip/Compress/LZMA_Alone -and call make to recompile it: - make -f makefile.gcc clean all - -In some UNIX/Linux versions you must compile LZMA with static libraries. -To compile with static libraries, you can use -LIB = -lm -static - - -Files ---------------------- -lzma.txt - LZMA SDK description (this file) -7zFormat.txt - 7z Format description -7zC.txt - 7z ANSI-C Decoder description -methods.txt - Compression method IDs for .7z -lzma.exe - Compiled file->file LZMA encoder/decoder for Windows -history.txt - history of the LZMA SDK - - -Source code structure ---------------------- - -C/ - C files - 7zCrc*.* - CRC code - Alloc.* - Memory allocation functions - Bra*.* - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code - LzFind.* - Match finder for LZ (LZMA) encoders - LzFindMt.* - Match finder for LZ (LZMA) encoders for multithreading encoding - LzHash.h - Additional file for LZ match finder - LzmaDec.* - LZMA decoding - LzmaEnc.* - LZMA encoding - LzmaLib.* - LZMA Library for DLL calling - Types.h - Basic types for another .c files - Threads.* - The code for multithreading. - - LzmaLib - LZMA Library (.DLL for Windows) - - LzmaUtil - LZMA Utility (file->file LZMA encoder/decoder). - - Archive - files related to archiving - 7z - 7z ANSI-C Decoder - -CPP/ -- CPP files - - Common - common files for C++ projects - Windows - common files for Windows related code - - 7zip - files related to 7-Zip Project - - Common - common files for 7-Zip - - Compress - files related to compression/decompression - - Copy - Copy coder - RangeCoder - Range Coder (special code of compression/decompression) - LZMA - LZMA compression/decompression on C++ - LZMA_Alone - file->file LZMA compression/decompression - Branch - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code - - Archive - files related to archiving - - Common - common files for archive handling - 7z - 7z C++ Encoder/Decoder - - Bundles - Modules that are bundles of other modules - - Alone7z - 7zr.exe: Standalone version of 7z.exe that supports only 7z/LZMA/BCJ/BCJ2 - Format7zR - 7zr.dll: Reduced version of 7za.dll: extracting/compressing to 7z/LZMA/BCJ/BCJ2 - Format7zExtractR - 7zxr.dll: Reduced version of 7zxa.dll: extracting from 7z/LZMA/BCJ/BCJ2. - - UI - User Interface files - - Client7z - Test application for 7za.dll, 7zr.dll, 7zxr.dll - Common - Common UI files - Console - Code for console archiver - - - -CS/ - C# files - 7zip - Common - some common files for 7-Zip - Compress - files related to compression/decompression - LZ - files related to LZ (Lempel-Ziv) compression algorithm - LZMA - LZMA compression/decompression - LzmaAlone - file->file LZMA compression/decompression - RangeCoder - Range Coder (special code of compression/decompression) - -Java/ - Java files - SevenZip - Compression - files related to compression/decompression - LZ - files related to LZ (Lempel-Ziv) compression algorithm - LZMA - LZMA compression/decompression - RangeCoder - Range Coder (special code of compression/decompression) - - -C/C++ source code of LZMA SDK is part of 7-Zip project. -7-Zip source code can be downloaded from 7-Zip's SourceForge page: - - http://sourceforge.net/projects/sevenzip/ - - - -LZMA features -------------- - - Variable dictionary size (up to 1 GB) - - Estimated compressing speed: about 2 MB/s on 2 GHz CPU - - Estimated decompressing speed: - - 20-30 MB/s on 2 GHz Core 2 or AMD Athlon 64 - - 1-2 MB/s on 200 MHz ARM, MIPS, PowerPC or other simple RISC - - Small memory requirements for decompressing (16 KB + DictionarySize) - - Small code size for decompressing: 5-8 KB - -LZMA decoder uses only integer operations and can be -implemented in any modern 32-bit CPU (or on 16-bit CPU with some conditions). - -Some critical operations that affect the speed of LZMA decompression: - 1) 32*16 bit integer multiply - 2) Misspredicted branches (penalty mostly depends from pipeline length) - 3) 32-bit shift and arithmetic operations - -The speed of LZMA decompressing mostly depends from CPU speed. -Memory speed has no big meaning. But if your CPU has small data cache, -overall weight of memory speed will slightly increase. - - -How To Use ----------- - -Using LZMA encoder/decoder executable --------------------------------------- - -Usage: LZMA inputFile outputFile [...] - - e: encode file - - d: decode file - - b: Benchmark. There are two tests: compressing and decompressing - with LZMA method. Benchmark shows rating in MIPS (million - instructions per second). Rating value is calculated from - measured speed and it is normalized with Intel's Core 2 results. - Also Benchmark checks possible hardware errors (RAM - errors in most cases). Benchmark uses these settings: - (-a1, -d21, -fb32, -mfbt4). You can change only -d parameter. - Also you can change the number of iterations. Example for 30 iterations: - LZMA b 30 - Default number of iterations is 10. - - - - - -a{N}: set compression mode 0 = fast, 1 = normal - default: 1 (normal) - - d{N}: Sets Dictionary size - [0, 30], default: 23 (8MB) - The maximum value for dictionary size is 1 GB = 2^30 bytes. - Dictionary size is calculated as DictionarySize = 2^N bytes. - For decompressing file compressed by LZMA method with dictionary - size D = 2^N you need about D bytes of memory (RAM). - - -fb{N}: set number of fast bytes - [5, 273], default: 128 - Usually big number gives a little bit better compression ratio - and slower compression process. - - -lc{N}: set number of literal context bits - [0, 8], default: 3 - Sometimes lc=4 gives gain for big files. - - -lp{N}: set number of literal pos bits - [0, 4], default: 0 - lp switch is intended for periodical data when period is - equal 2^N. For example, for 32-bit (4 bytes) - periodical data you can use lp=2. Often it's better to set lc0, - if you change lp switch. - - -pb{N}: set number of pos bits - [0, 4], default: 2 - pb switch is intended for periodical data - when period is equal 2^N. - - -mf{MF_ID}: set Match Finder. Default: bt4. - Algorithms from hc* group doesn't provide good compression - ratio, but they often works pretty fast in combination with - fast mode (-a0). - - Memory requirements depend from dictionary size - (parameter "d" in table below). - - MF_ID Memory Description - - bt2 d * 9.5 + 4MB Binary Tree with 2 bytes hashing. - bt3 d * 11.5 + 4MB Binary Tree with 3 bytes hashing. - bt4 d * 11.5 + 4MB Binary Tree with 4 bytes hashing. - hc4 d * 7.5 + 4MB Hash Chain with 4 bytes hashing. - - -eos: write End Of Stream marker. By default LZMA doesn't write - eos marker, since LZMA decoder knows uncompressed size - stored in .lzma file header. - - -si: Read data from stdin (it will write End Of Stream marker). - -so: Write data to stdout - - -Examples: - -1) LZMA e file.bin file.lzma -d16 -lc0 - -compresses file.bin to file.lzma with 64 KB dictionary (2^16=64K) -and 0 literal context bits. -lc0 allows to reduce memory requirements -for decompression. - - -2) LZMA e file.bin file.lzma -lc0 -lp2 - -compresses file.bin to file.lzma with settings suitable -for 32-bit periodical data (for example, ARM or MIPS code). - -3) LZMA d file.lzma file.bin - -decompresses file.lzma to file.bin. - - -Compression ratio hints ------------------------ - -Recommendations ---------------- - -To increase the compression ratio for LZMA compressing it's desirable -to have aligned data (if it's possible) and also it's desirable to locate -data in such order, where code is grouped in one place and data is -grouped in other place (it's better than such mixing: code, data, code, -data, ...). - - -Filters -------- -You can increase the compression ratio for some data types, using -special filters before compressing. For example, it's possible to -increase the compression ratio on 5-10% for code for those CPU ISAs: -x86, IA-64, ARM, ARM-Thumb, PowerPC, SPARC. - -You can find C source code of such filters in C/Bra*.* files - -You can check the compression ratio gain of these filters with such -7-Zip commands (example for ARM code): -No filter: - 7z a a1.7z a.bin -m0=lzma - -With filter for little-endian ARM code: - 7z a a2.7z a.bin -m0=arm -m1=lzma - -It works in such manner: -Compressing = Filter_encoding + LZMA_encoding -Decompressing = LZMA_decoding + Filter_decoding - -Compressing and decompressing speed of such filters is very high, -so it will not increase decompressing time too much. -Moreover, it reduces decompression time for LZMA_decoding, -since compression ratio with filtering is higher. - -These filters convert CALL (calling procedure) instructions -from relative offsets to absolute addresses, so such data becomes more -compressible. - -For some ISAs (for example, for MIPS) it's impossible to get gain from such filter. - - -LZMA compressed file format ---------------------------- -Offset Size Description - 0 1 Special LZMA properties (lc,lp, pb in encoded form) - 1 4 Dictionary size (little endian) - 5 8 Uncompressed size (little endian). -1 means unknown size - 13 Compressed data - - -ANSI-C LZMA Decoder -~~~~~~~~~~~~~~~~~~~ - -Please note that interfaces for ANSI-C code were changed in LZMA SDK 4.58. -If you want to use old interfaces you can download previous version of LZMA SDK -from sourceforge.net site. - -To use ANSI-C LZMA Decoder you need the following files: -1) LzmaDec.h + LzmaDec.c + Types.h -LzmaUtil/LzmaUtil.c is example application that uses these files. - - -Memory requirements for LZMA decoding -------------------------------------- - -Stack usage of LZMA decoding function for local variables is not -larger than 200-400 bytes. - -LZMA Decoder uses dictionary buffer and internal state structure. -Internal state structure consumes - state_size = (4 + (1.5 << (lc + lp))) KB -by default (lc=3, lp=0), state_size = 16 KB. - - -How To decompress data ----------------------- - -LZMA Decoder (ANSI-C version) now supports 2 interfaces: -1) Single-call Decompressing -2) Multi-call State Decompressing (zlib-like interface) - -You must use external allocator: -Example: -void *SzAlloc(void *p, size_t size) { p = p; return malloc(size); } -void SzFree(void *p, void *address) { p = p; free(address); } -ISzAlloc alloc = { SzAlloc, SzFree }; - -You can use p = p; operator to disable compiler warnings. - - -Single-call Decompressing -------------------------- -When to use: RAM->RAM decompressing -Compile files: LzmaDec.h + LzmaDec.c + Types.h -Compile defines: no defines -Memory Requirements: - - Input buffer: compressed size - - Output buffer: uncompressed size - - LZMA Internal Structures: state_size (16 KB for default settings) - -Interface: - int LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, - const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, - ELzmaStatus *status, ISzAlloc *alloc); - In: - dest - output data - destLen - output data size - src - input data - srcLen - input data size - propData - LZMA properties (5 bytes) - propSize - size of propData buffer (5 bytes) - finishMode - It has meaning only if the decoding reaches output limit (*destLen). - LZMA_FINISH_ANY - Decode just destLen bytes. - LZMA_FINISH_END - Stream must be finished after (*destLen). - You can use LZMA_FINISH_END, when you know that - current output buffer covers last bytes of stream. - alloc - Memory allocator. - - Out: - destLen - processed output size - srcLen - processed input size - - Output: - SZ_OK - status: - LZMA_STATUS_FINISHED_WITH_MARK - LZMA_STATUS_NOT_FINISHED - LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK - SZ_ERROR_DATA - Data error - SZ_ERROR_MEM - Memory allocation error - SZ_ERROR_UNSUPPORTED - Unsupported properties - SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src). - - If LZMA decoder sees end_marker before reaching output limit, it returns OK result, - and output value of destLen will be less than output buffer size limit. - - You can use multiple checks to test data integrity after full decompression: - 1) Check Result and "status" variable. - 2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize. - 3) Check that output(srcLen) = compressedSize, if you know real compressedSize. - You must use correct finish mode in that case. */ - - -Multi-call State Decompressing (zlib-like interface) ----------------------------------------------------- - -When to use: file->file decompressing -Compile files: LzmaDec.h + LzmaDec.c + Types.h - -Memory Requirements: - - Buffer for input stream: any size (for example, 16 KB) - - Buffer for output stream: any size (for example, 16 KB) - - LZMA Internal Structures: state_size (16 KB for default settings) - - LZMA dictionary (dictionary size is encoded in LZMA properties header) - -1) read LZMA properties (5 bytes) and uncompressed size (8 bytes, little-endian) to header: - unsigned char header[LZMA_PROPS_SIZE + 8]; - ReadFile(inFile, header, sizeof(header) - -2) Allocate CLzmaDec structures (state + dictionary) using LZMA properties - - CLzmaDec state; - LzmaDec_Constr(&state); - res = LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc); - if (res != SZ_OK) - return res; - -3) Init LzmaDec structure before any new LZMA stream. And call LzmaDec_DecodeToBuf in loop - - LzmaDec_Init(&state); - for (;;) - { - ... - int res = LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen, - const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode); - ... - } - - -4) Free all allocated structures - LzmaDec_Free(&state, &g_Alloc); - -For full code example, look at C/LzmaUtil/LzmaUtil.c code. - - -How To compress data --------------------- - -Compile files: LzmaEnc.h + LzmaEnc.c + Types.h + -LzFind.c + LzFind.h + LzFindMt.c + LzFindMt.h + LzHash.h - -Memory Requirements: - - (dictSize * 11.5 + 6 MB) + state_size - -Lzma Encoder can use two memory allocators: -1) alloc - for small arrays. -2) allocBig - for big arrays. - -For example, you can use Large RAM Pages (2 MB) in allocBig allocator for -better compression speed. Note that Windows has bad implementation for -Large RAM Pages. -It's OK to use same allocator for alloc and allocBig. - - -Single-call Compression with callbacks --------------------------------------- - -Check C/LzmaUtil/LzmaUtil.c as example, - -When to use: file->file decompressing - -1) you must implement callback structures for interfaces: -ISeqInStream -ISeqOutStream -ICompressProgress -ISzAlloc - -static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); } -static void SzFree(void *p, void *address) { p = p; MyFree(address); } -static ISzAlloc g_Alloc = { SzAlloc, SzFree }; - - CFileSeqInStream inStream; - CFileSeqOutStream outStream; - - inStream.funcTable.Read = MyRead; - inStream.file = inFile; - outStream.funcTable.Write = MyWrite; - outStream.file = outFile; - - -2) Create CLzmaEncHandle object; - - CLzmaEncHandle enc; - - enc = LzmaEnc_Create(&g_Alloc); - if (enc == 0) - return SZ_ERROR_MEM; - - -3) initialize CLzmaEncProps properties; - - LzmaEncProps_Init(&props); - - Then you can change some properties in that structure. - -4) Send LZMA properties to LZMA Encoder - - res = LzmaEnc_SetProps(enc, &props); - -5) Write encoded properties to header - - Byte header[LZMA_PROPS_SIZE + 8]; - size_t headerSize = LZMA_PROPS_SIZE; - UInt64 fileSize; - int i; - - res = LzmaEnc_WriteProperties(enc, header, &headerSize); - fileSize = MyGetFileLength(inFile); - for (i = 0; i < 8; i++) - header[headerSize++] = (Byte)(fileSize >> (8 * i)); - MyWriteFileAndCheck(outFile, header, headerSize) - -6) Call encoding function: - res = LzmaEnc_Encode(enc, &outStream.funcTable, &inStream.funcTable, - NULL, &g_Alloc, &g_Alloc); - -7) Destroy LZMA Encoder Object - LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc); - - -If callback function return some error code, LzmaEnc_Encode also returns that code. - - -Single-call RAM->RAM Compression --------------------------------- - -Single-call RAM->RAM Compression is similar to Compression with callbacks, -but you provide pointers to buffers instead of pointers to stream callbacks: - -HRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen, - CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark, - ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig); - -Return code: - SZ_OK - OK - SZ_ERROR_MEM - Memory allocation error - SZ_ERROR_PARAM - Incorrect paramater - SZ_ERROR_OUTPUT_EOF - output buffer overflow - SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version) - - - -LZMA Defines ------------- - -_LZMA_SIZE_OPT - Enable some optimizations in LZMA Decoder to get smaller executable code. - -_LZMA_PROB32 - It can increase the speed on some 32-bit CPUs, but memory usage for - some structures will be doubled in that case. - -_LZMA_UINT32_IS_ULONG - Define it if int is 16-bit on your compiler and long is 32-bit. - -_LZMA_NO_SYSTEM_SIZE_T - Define it if you don't want to use size_t type. - - -C++ LZMA Encoder/Decoder -~~~~~~~~~~~~~~~~~~~~~~~~ -C++ LZMA code use COM-like interfaces. So if you want to use it, -you can study basics of COM/OLE. -C++ LZMA code is just wrapper over ANSI-C code. - - -C++ Notes -~~~~~~~~~~~~~~~~~~~~~~~~ -If you use some C++ code folders in 7-Zip (for example, C++ code for .7z handling), -you must check that you correctly work with "new" operator. -7-Zip can be compiled with MSVC 6.0 that doesn't throw "exception" from "new" operator. -So 7-Zip uses "CPP\Common\NewHandler.cpp" that redefines "new" operator: -operator new(size_t size) -{ - void *p = ::malloc(size); - if (p == 0) - throw CNewException(); - return p; -} -If you use MSCV that throws exception for "new" operator, you can compile without -"NewHandler.cpp". So standard exception will be used. Actually some code of -7-Zip catches any exception in internal code and converts it to HRESULT code. -So you don't need to catch CNewException, if you call COM interfaces of 7-Zip. - ---- - -http://www.7-zip.org -http://www.7-zip.org/sdk.html -http://www.7-zip.org/support.html diff --git a/snesreader/7z_C/readme.txt b/snesreader/7z_C/readme.txt deleted file mode 100644 index a07f1fcc..00000000 --- a/snesreader/7z_C/readme.txt +++ /dev/null @@ -1,19 +0,0 @@ -Modified LZMA 4.65 ------------------- -This is just the ANSI C 7-zip extraction code from the LZMA 4.65 source -code release, with unnecessary files removed. I've made minor changes to -allow the code to compile with almost all warnings enabled in GCC. - -* Made relevant functions extern "C" so that they can be called from -C++. - -* Put all files in same directory and removed "../../" from #includes. - -* Made private (unprototyped) functions static. - -* #if'd out code that is never called. - -* Removed a couple of Windows references. - --- -Shay Green diff --git a/snesreader/Makefile b/snesreader/Makefile deleted file mode 100644 index 761317b0..00000000 --- a/snesreader/Makefile +++ /dev/null @@ -1,187 +0,0 @@ -include nall/Makefile - -qtlibs := QtCore QtGui -include nall/qt/Makefile - -c := $(compiler) -std=gnu99 -cpp := $(subst cc,++,$(compiler)) -std=gnu++0x -flags := -O3 -I. -Iobj -fomit-frame-pointer -link := - -ifeq ($(platform),x) - flags := -fPIC $(flags) - link += -s -else ifeq ($(platform),osx) - flags := -fPIC $(flags) -endif - -objects := snesreader - -# fex -objects += Binary_Extractor blargg_common blargg_errors Data_Reader fex File_Extractor Gzip_Extractor Gzip_Reader Rar_Extractor Zip7_Extractor Zip_Extractor Zlib_Inflater -# zlib -objects += adler32 crc32 inffast inflate inftrees zutil -# 7-zip -objects += 7zAlloc 7zBuf 7zCrc 7zDecode 7zExtract 7zHeader 7zIn 7zItem 7zStream Bcj2 Bra86 LzmaDec -# unrar -objects += archive arcread coder crc encname extract getbits model rarvm rarvmtbl rawread suballoc unicode unpack unpack15 unpack20 unrar unrar_misc unrar_open -# micro-bunzip -objects += micro-bunzip -# jma -objects += jma jcrc32 lzmadecode 7zlzma iiostrm inbyte lzma winout - -compile = \ - $(strip \ - $(if $(filter %.c,$<), \ - $(c) $(flags) $1 -c $< -o $@, \ - $(if $(filter %.cpp,$<), \ - $(cpp) $(flags) $1 -c $< -o $@ \ - ) \ - ) \ - ) - -%.o: $<; $(call compile) - -all: build; - -objects := $(patsubst %,obj/%.o,$(objects)) -moc_headers := $(call rwildcard,./,%.moc.hpp) -moc_objects := $(foreach f,$(moc_headers),obj/$(notdir $(patsubst %.moc.hpp,%.moc,$f))) - -# automatically run moc on all .moc.hpp (MOC header) files -%.moc: $<; $(moc) -i $< -o $@ - -# automatically generate %.moc build rules -__list = $(moc_headers) -$(foreach f,$(moc_objects), \ - $(eval __file = $(word 1,$(__list))) \ - $(eval __list = $(wordlist 2,$(words $(__list)),$(__list))) \ - $(eval $f: $(__file)) \ -) - -################## -### snesreader ### -################## - -obj/snesreader.o: snesreader.cpp * - $(call compile,$(qtinc)) - -########### -### fex ### -########### - -obj/Binary_Extractor.o: fex/Binary_Extractor.cpp fex/* -obj/blargg_common.o : fex/blargg_common.cpp fex/* -obj/blargg_errors.o : fex/blargg_errors.cpp fex/* -obj/Data_Reader.o : fex/Data_Reader.cpp fex/* -obj/fex.o : fex/fex.cpp fex/* -obj/File_Extractor.o : fex/File_Extractor.cpp fex/* -obj/Gzip_Extractor.o : fex/Gzip_Extractor.cpp fex/* -obj/Gzip_Reader.o : fex/Gzip_Reader.cpp fex/* -obj/Rar_Extractor.o : fex/Rar_Extractor.cpp fex/* -obj/Zip7_Extractor.o : fex/Zip7_Extractor.cpp fex/* -obj/Zip_Extractor.o : fex/Zip_Extractor.cpp fex/* -obj/Zlib_Inflater.o : fex/Zlib_Inflater.cpp fex/* - -############ -### zlib ### -############ - -obj/adler32.o : zlib/adler32.c zlib/* -obj/crc32.o : zlib/crc32.c zlib/* -obj/inffast.o : zlib/inffast.c zlib/* -obj/inflate.o : zlib/inflate.c zlib/* -obj/inftrees.o: zlib/inftrees.c zlib/* -obj/zutil.o : zlib/zutil.c zlib/* - -############# -### 7-zip ### -############# - -obj/7zAlloc.o : 7z_C/7zAlloc.c 7z_C/* -obj/7zBuf.o : 7z_C/7zBuf.c 7z_C/* -obj/7zCrc.o : 7z_C/7zCrc.c 7z_C/* -obj/7zDecode.o : 7z_C/7zDecode.c 7z_C/* -obj/7zExtract.o: 7z_C/7zExtract.c 7z_C/* -obj/7zHeader.o : 7z_C/7zHeader.c 7z_C/* -obj/7zIn.o : 7z_C/7zIn.c 7z_C/* -obj/7zItem.o : 7z_C/7zItem.c 7z_C/* -obj/7zStream.o : 7z_C/7zStream.c 7z_C/* -obj/Bcj2.o : 7z_C/Bcj2.c 7z_C/* -obj/Bra86.o : 7z_C/Bra86.c 7z_C/* -obj/LzmaDec.o : 7z_C/LzmaDec.c 7z_C/* - -#################### -### micro-bunzip ### -#################### - -obj/micro-bunzip.o: micro-bunzip/micro-bunzip.c micro-bunzip/* - -############# -### unrar ### -############# - -obj/archive.o : unrar/archive.cpp unrar/* -obj/arcread.o : unrar/arcread.cpp unrar/* -obj/coder.o : unrar/coder.cpp unrar/* -obj/crc.o : unrar/crc.cpp unrar/* -obj/encname.o : unrar/encname.cpp unrar/* -obj/extract.o : unrar/extract.cpp unrar/* -obj/getbits.o : unrar/getbits.cpp unrar/* -obj/model.o : unrar/model.cpp unrar/* -obj/rarvm.o : unrar/rarvm.cpp unrar/* -obj/rarvmtbl.o : unrar/rarvmtbl.cpp unrar/* -obj/rawread.o : unrar/rawread.cpp unrar/* -obj/suballoc.o : unrar/suballoc.cpp unrar/* -obj/unicode.o : unrar/unicode.cpp unrar/* -obj/unpack.o : unrar/unpack.cpp unrar/* -obj/unpack15.o : unrar/unpack15.cpp unrar/* -obj/unpack20.o : unrar/unpack20.cpp unrar/* -obj/unrar.o : unrar/unrar.cpp unrar/* -obj/unrar_misc.o: unrar/unrar_misc.cpp unrar/* -obj/unrar_open.o: unrar/unrar_open.cpp unrar/* - -############## -### libjma ### -############## - -obj/jma.o : libjma/jma.cpp libjma/* -obj/jcrc32.o : libjma/jcrc32.cpp libjma/* -obj/lzmadecode.o: libjma/lzmadecode.cpp libjma/* -obj/7zlzma.o : libjma/7zlzma.cpp libjma/* -obj/iiostrm.o : libjma/iiostrm.cpp libjma/* -obj/inbyte.o : libjma/inbyte.cpp libjma/* -obj/lzma.o : libjma/lzma.cpp libjma/* -obj/winout.o : libjma/winout.cpp libjma/* - -############### -### targets ### -############### - -build: $(moc_objects) $(objects) -ifeq ($(platform),x) - ar rcs libsnesreader.a $(objects) - $(cpp) $(link) -o libsnesreader.so -shared -Wl,-soname,libsnesreader.so.1 $(objects) $(qtlib) -else ifeq ($(platform),osx) - ar rcs libsnesreader.a $(objects) - $(cpp) $(link) -o libsnesreader.dylib -shared -dynamiclib $(objects) $(qtlib) -else ifeq ($(platform),win) - $(cpp) $(link) -o snesreader.dll -shared -Wl,--out-implib,libsnesreader.a $(objects) $(qtlib) -endif - -install: -ifeq ($(platform),x) - install -D -m 755 libsnesreader.a $(DESTDIR)$(prefix)/lib - install -D -m 755 libsnesreader.so $(DESTDIR)$(prefix)/lib - ldconfig -n $(DESTDIR)$(prefix)/lib -else ifeq ($(platform),osx) - cp libsnesreader.dylib /usr/local/lib/libsnesreader.dylib -endif - -clean: - -@$(call delete,obj/*.o) - -@$(call delete,obj/*.moc) - -@$(call delete,libsnesreader.a) - -@$(call delete,libsnesreader.so) - -@$(call delete,libsnesreader.dylib) - -@$(call delete,snesreader.dll) diff --git a/snesreader/cc.bat b/snesreader/cc.bat deleted file mode 100644 index 8359a530..00000000 --- a/snesreader/cc.bat +++ /dev/null @@ -1,2 +0,0 @@ -@mingw32-make -@pause \ No newline at end of file diff --git a/snesreader/clean.bat b/snesreader/clean.bat deleted file mode 100644 index d8bb7e0b..00000000 --- a/snesreader/clean.bat +++ /dev/null @@ -1 +0,0 @@ -@mingw32-make clean diff --git a/snesreader/fex/Binary_Extractor.cpp b/snesreader/fex/Binary_Extractor.cpp deleted file mode 100644 index 8c85b992..00000000 --- a/snesreader/fex/Binary_Extractor.cpp +++ /dev/null @@ -1,77 +0,0 @@ -// File_Extractor 1.0.0. http://www.slack.net/~ant/ - -#include "Binary_Extractor.h" - -/* Copyright (C) 2005-2009 Shay Green. This module 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 -module is distributed in the hope that 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 module; if not, write to the Free Software Foundation, -Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -#include "blargg_source.h" - -// TODO: could close file once data has been read into memory - -static File_Extractor* new_binary() -{ - return BLARGG_NEW Binary_Extractor; -} - -fex_type_t_ const fex_bin_type [1] = {{ - "", - &new_binary, - "file", - NULL -}}; - -Binary_Extractor::Binary_Extractor() : - File_Extractor( fex_bin_type ) -{ } - -Binary_Extractor::~Binary_Extractor() -{ - close(); -} - -blargg_err_t Binary_Extractor::open_path_v() -{ - set_name( arc_path() ); - return blargg_ok; -} - -blargg_err_t Binary_Extractor::open_v() -{ - set_name( arc_path() ); - set_info( arc().remain(), 0, 0 ); - return blargg_ok; -} - -void Binary_Extractor::close_v() -{ } - -blargg_err_t Binary_Extractor::next_v() -{ - return blargg_ok; -} - -blargg_err_t Binary_Extractor::rewind_v() -{ - return open_path_v(); -} - -blargg_err_t Binary_Extractor::stat_v() -{ - RETURN_ERR( open_arc_file() ); - RETURN_ERR( arc().seek( 0 ) ); - return open_v(); -} - -blargg_err_t Binary_Extractor::extract_v( void* p, int n ) -{ - return arc().read( p, n ); -} diff --git a/snesreader/fex/Binary_Extractor.h b/snesreader/fex/Binary_Extractor.h deleted file mode 100644 index 339a0873..00000000 --- a/snesreader/fex/Binary_Extractor.h +++ /dev/null @@ -1,26 +0,0 @@ -// Presents a single file as an "archive" of just that file. - -// File_Extractor 1.0.0 -#ifndef BINARY_EXTRACTOR_H -#define BINARY_EXTRACTOR_H - -#include "File_Extractor.h" - -class Binary_Extractor : public File_Extractor { -public: - Binary_Extractor(); - virtual ~Binary_Extractor(); - -protected: - virtual blargg_err_t open_path_v(); - virtual blargg_err_t open_v(); - virtual void close_v(); - - virtual blargg_err_t next_v(); - virtual blargg_err_t rewind_v(); - - virtual blargg_err_t stat_v(); - virtual blargg_err_t extract_v( void*, int ); -}; - -#endif diff --git a/snesreader/fex/Data_Reader.cpp b/snesreader/fex/Data_Reader.cpp deleted file mode 100644 index cbea9f47..00000000 --- a/snesreader/fex/Data_Reader.cpp +++ /dev/null @@ -1,551 +0,0 @@ -// File_Extractor 1.0.0. http://www.slack.net/~ant/ - -#include "Data_Reader.h" - -#include "blargg_endian.h" -#include -#include - -#if BLARGG_UTF8_PATHS - #include -#endif - -/* Copyright (C) 2005-2009 Shay Green. This module 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 -module is distributed in the hope that 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 module; if not, write to the Free Software Foundation, -Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -#include "blargg_source.h" - -// Data_Reader - -blargg_err_t Data_Reader::read( void* p, int n ) -{ - assert( n >= 0 ); - - if ( n < 0 ) - return blargg_err_caller; - - if ( n <= 0 ) - return blargg_ok; - - if ( n > remain() ) - return blargg_err_file_eof; - - blargg_err_t err = read_v( p, n ); - if ( !err ) - remain_ -= n; - - return err; -} - -blargg_err_t Data_Reader::read_avail( void* p, int* n_ ) -{ - assert( *n_ >= 0 ); - - int n = min( *n_, remain() ); - *n_ = 0; - - if ( n < 0 ) - return blargg_err_caller; - - if ( n <= 0 ) - return blargg_ok; - - blargg_err_t err = read_v( p, n ); - if ( !err ) - { - remain_ -= n; - *n_ = n; - } - - return err; -} - -blargg_err_t Data_Reader::read_avail( void* p, long* n ) -{ - int i = STATIC_CAST(int, *n); - blargg_err_t err = read_avail( p, &i ); - *n = i; - return err; -} - -blargg_err_t Data_Reader::skip_v( int count ) -{ - char buf [512]; - while ( count ) - { - int n = min( count, (int) sizeof buf ); - count -= n; - RETURN_ERR( read_v( buf, n ) ); - } - return blargg_ok; -} - -blargg_err_t Data_Reader::skip( int n ) -{ - assert( n >= 0 ); - - if ( n < 0 ) - return blargg_err_caller; - - if ( n <= 0 ) - return blargg_ok; - - if ( n > remain() ) - return blargg_err_file_eof; - - blargg_err_t err = skip_v( n ); - if ( !err ) - remain_ -= n; - - return err; -} - - -// File_Reader - -blargg_err_t File_Reader::seek( int n ) -{ - assert( n >= 0 ); - - if ( n < 0 ) - return blargg_err_caller; - - if ( n == tell() ) - return blargg_ok; - - if ( n > size() ) - return blargg_err_file_eof; - - blargg_err_t err = seek_v( n ); - if ( !err ) - set_tell( n ); - - return err; -} - -blargg_err_t File_Reader::skip_v( int n ) -{ - return seek_v( tell() + n ); -} - - -// Subset_Reader - -Subset_Reader::Subset_Reader( Data_Reader* dr, int size ) : - in( dr ) -{ - set_remain( min( size, dr->remain() ) ); -} - -blargg_err_t Subset_Reader::read_v( void* p, int s ) -{ - return in->read( p, s ); -} - - -// Remaining_Reader - -Remaining_Reader::Remaining_Reader( void const* h, int size, Data_Reader* r ) : - in( r ) -{ - header = h; - header_remain = size; - - set_remain( size + r->remain() ); -} - -blargg_err_t Remaining_Reader::read_v( void* out, int count ) -{ - int first = min( count, header_remain ); - if ( first ) - { - memcpy( out, header, first ); - header = STATIC_CAST(char const*, header) + first; - header_remain -= first; - } - - return in->read( STATIC_CAST(char*, out) + first, count - first ); -} - - -// Mem_File_Reader - -Mem_File_Reader::Mem_File_Reader( const void* p, long s ) : - begin( STATIC_CAST(const char*, p) ) -{ - set_size( s ); -} - -blargg_err_t Mem_File_Reader::read_v( void* p, int s ) -{ - memcpy( p, begin + tell(), s ); - return blargg_ok; -} - -blargg_err_t Mem_File_Reader::seek_v( int ) -{ - return blargg_ok; -} - - -// Callback_Reader - -Callback_Reader::Callback_Reader( callback_t c, long s, void* d ) : - callback( c ), - user_data( d ) -{ - set_remain( s ); -} - -blargg_err_t Callback_Reader::read_v( void* out, int count ) -{ - return callback( user_data, out, count ); -} - - -// Callback_File_Reader - -Callback_File_Reader::Callback_File_Reader( callback_t c, long s, void* d ) : - callback( c ), - user_data( d ) -{ - set_size( s ); -} - -blargg_err_t Callback_File_Reader::read_v( void* out, int count ) -{ - return callback( user_data, out, count, tell() ); -} - -blargg_err_t Callback_File_Reader::seek_v( int ) -{ - return blargg_ok; -} - - -// BLARGG_UTF8_PATHS - -#if BLARGG_UTF8_PATHS - -// Thanks to byuu for the idea for BLARGG_UTF8_PATHS and the implementations - -// Converts wide-character path to UTF-8. Free result with free(). Only supported on Windows. -char* blargg_to_utf8( const wchar_t* wpath ) -{ - if ( wpath == NULL ) - return NULL; - - int needed = WideCharToMultiByte( CP_UTF8, 0, wpath, -1, NULL, 0, NULL, NULL ); - if ( needed <= 0 ) - return NULL; - - char* path = (char*) malloc( needed ); - if ( path == NULL ) - return NULL; - - int actual = WideCharToMultiByte( CP_UTF8, 0, wpath, -1, path, needed, NULL, NULL ); - if ( actual == 0 ) - { - free( path ); - return NULL; - } - - assert( actual == needed ); - return path; -} - -// Converts UTF-8 path to wide-character. Free result with free() Only supported on Windows. -wchar_t* blargg_to_wide( const char* path ) -{ - if ( path == NULL ) - return NULL; - - int needed = MultiByteToWideChar( CP_UTF8, 0, path, -1, NULL, 0 ); - if ( needed <= 0 ) - return NULL; - - wchar_t* wpath = (wchar_t*) malloc( needed * sizeof *wpath ); - if ( wpath == NULL ) - return NULL; - - int actual = MultiByteToWideChar( CP_UTF8, 0, path, -1, wpath, needed ); - if ( actual == 0 ) - { - free( wpath ); - return NULL; - } - - assert( actual == needed ); - return wpath; -} - -static FILE* blargg_fopen( const char path [], const char mode [] ) -{ - FILE* file = NULL; - wchar_t* wmode = NULL; - wchar_t* wpath = NULL; - - wpath = blargg_to_wide( path ); - if ( wpath ) - { - wmode = blargg_to_wide( mode ); - if ( wmode ) - file = _wfopen( wpath, wmode ); - } - - // Save and restore errno in case free() clears it - int saved_errno = errno; - free( wmode ); - free( wpath ); - errno = saved_errno; - - return file; -} - -#else - -static inline FILE* blargg_fopen( const char path [], const char mode [] ) -{ - return fopen( path, mode ); -} - -#endif - - -// Std_File_Reader - -Std_File_Reader::Std_File_Reader() -{ - file_ = NULL; -} - -Std_File_Reader::~Std_File_Reader() -{ - close(); -} - -static blargg_err_t blargg_fopen( FILE** out, const char path [] ) -{ - errno = 0; - *out = blargg_fopen( path, "rb" ); - if ( !*out ) - { - #ifdef ENOENT - if ( errno == ENOENT ) - return blargg_err_file_missing; - #endif - #ifdef ENOMEM - if ( errno == ENOMEM ) - return blargg_err_memory; - #endif - return blargg_err_file_read; - } - - return blargg_ok; -} - -static blargg_err_t blargg_fsize( FILE* f, long* out ) -{ - if ( fseek( f, 0, SEEK_END ) ) - return blargg_err_file_io; - - *out = ftell( f ); - if ( *out < 0 ) - return blargg_err_file_io; - - if ( fseek( f, 0, SEEK_SET ) ) - return blargg_err_file_io; - - return blargg_ok; -} - -blargg_err_t Std_File_Reader::open( const char path [] ) -{ - close(); - - FILE* f; - RETURN_ERR( blargg_fopen( &f, path ) ); - - long s; - blargg_err_t err = blargg_fsize( f, &s ); - if ( err ) - { - fclose( f ); - return err; - } - - file_ = f; - set_size( s ); - - return blargg_ok; -} - -void Std_File_Reader::make_unbuffered() -{ - if ( setvbuf( STATIC_CAST(FILE*, file_), NULL, _IONBF, 0 ) ) - check( false ); // shouldn't fail, but OK if it does -} - -blargg_err_t Std_File_Reader::read_v( void* p, int s ) -{ - if ( (size_t) s != fread( p, 1, s, STATIC_CAST(FILE*, file_) ) ) - { - // Data_Reader's wrapper should prevent EOF - check( !feof( STATIC_CAST(FILE*, file_) ) ); - - return blargg_err_file_io; - } - - return blargg_ok; -} - -blargg_err_t Std_File_Reader::seek_v( int n ) -{ - if ( fseek( STATIC_CAST(FILE*, file_), n, SEEK_SET ) ) - { - // Data_Reader's wrapper should prevent EOF - check( !feof( STATIC_CAST(FILE*, file_) ) ); - - return blargg_err_file_io; - } - - return blargg_ok; -} - -void Std_File_Reader::close() -{ - if ( file_ ) - { - fclose( STATIC_CAST(FILE*, file_) ); - file_ = NULL; - } -} - - -// Gzip_File_Reader - -#ifdef HAVE_ZLIB_H - -#include "zlib.h" - -static const char* get_gzip_eof( const char path [], long* eof ) -{ - FILE* file; - RETURN_ERR( blargg_fopen( &file, path ) ); - - int const h_size = 4; - unsigned char h [h_size]; - - // read four bytes to ensure that we can seek to -4 later - if ( fread( h, 1, h_size, file ) != (size_t) h_size || h[0] != 0x1F || h[1] != 0x8B ) - { - // Not gzipped - if ( ferror( file ) ) - return blargg_err_file_io; - - if ( fseek( file, 0, SEEK_END ) ) - return blargg_err_file_io; - - *eof = ftell( file ); - if ( *eof < 0 ) - return blargg_err_file_io; - } - else - { - // Gzipped; get uncompressed size from end - if ( fseek( file, -h_size, SEEK_END ) ) - return blargg_err_file_io; - - if ( fread( h, 1, h_size, file ) != (size_t) h_size ) - return blargg_err_file_io; - - *eof = get_le32( h ); - } - - if ( fclose( file ) ) - check( false ); - - return blargg_ok; -} - -Gzip_File_Reader::Gzip_File_Reader() -{ - file_ = NULL; -} - -Gzip_File_Reader::~Gzip_File_Reader() -{ - close(); -} - -blargg_err_t Gzip_File_Reader::open( const char path [] ) -{ - close(); - - long s; - RETURN_ERR( get_gzip_eof( path, &s ) ); - - file_ = gzopen( path, "rb" ); - if ( !file_ ) - return blargg_err_file_read; - - set_size( s ); - return blargg_ok; -} - -static blargg_err_t convert_gz_error( gzFile file ) -{ - int err; - gzerror( file, &err ); - - switch ( err ) - { - case Z_STREAM_ERROR: break; - case Z_DATA_ERROR: return blargg_err_file_corrupt; - case Z_MEM_ERROR: return blargg_err_memory; - case Z_BUF_ERROR: break; - } - return blargg_err_internal; -} - -blargg_err_t Gzip_File_Reader::read_v( void* p, int s ) -{ - int result = gzread( file_, p, s ); - if ( result != s ) - { - if ( result < 0 ) - return convert_gz_error( file_ ); - - return blargg_err_file_corrupt; - } - - return blargg_ok; -} - -blargg_err_t Gzip_File_Reader::seek_v( int n ) -{ - if ( gzseek( file_, n, SEEK_SET ) < 0 ) - return convert_gz_error( file_ ); - - return blargg_ok; -} - -void Gzip_File_Reader::close() -{ - if ( file_ ) - { - if ( gzclose( file_ ) ) - check( false ); - file_ = NULL; - } -} - -#endif diff --git a/snesreader/fex/Data_Reader.h b/snesreader/fex/Data_Reader.h deleted file mode 100644 index be206f7b..00000000 --- a/snesreader/fex/Data_Reader.h +++ /dev/null @@ -1,264 +0,0 @@ -// Lightweight interface for reading data from byte stream - -// File_Extractor 1.0.0 -#ifndef DATA_READER_H -#define DATA_READER_H - -#include "blargg_common.h" - -/* Some functions accept a long instead of int for convenience where caller has -a long due to some other interface, and would otherwise have to get a warning, -or cast it (and verify that it wasn't outside the range of an int). - -To really support huge (>2GB) files, long isn't a solution, since there's no -guarantee it's more than 32 bits. We'd need to use long long (if available), or -something compiler-specific, and change all places file sizes or offsets are -used. */ - -// Supports reading and finding out how many bytes are remaining -class Data_Reader { -public: - - // Reads min(*n,remain()) bytes and sets *n to this number, thus trying to read more - // tham remain() bytes doesn't result in error, just *n being set to remain(). - blargg_err_t read_avail( void* p, int* n ); - blargg_err_t read_avail( void* p, long* n ); - - // Reads exactly n bytes, or returns error if they couldn't ALL be read. - // Reading past end of file results in blargg_err_file_eof. - blargg_err_t read( void* p, int n ); - - // Number of bytes remaining until end of file - int remain() const { return remain_; } - - // Reads and discards n bytes. Skipping past end of file results in blargg_err_file_eof. - blargg_err_t skip( int n ); - - virtual ~Data_Reader() { } - -private: - // noncopyable - Data_Reader( const Data_Reader& ); - Data_Reader& operator = ( const Data_Reader& ); - -// Derived interface -protected: - Data_Reader() : remain_( 0 ) { } - - // Sets remain - void set_remain( int n ) { assert( n >= 0 ); remain_ = n; } - - // Do same as read(). Guaranteed that 0 < n <= remain(). Value of remain() is updated - // AFTER this call succeeds, not before. set_remain() should NOT be called from this. - virtual blargg_err_t read_v( void*, int n ) BLARGG_PURE( { (void)n; return blargg_ok; } ) - - // Do same as skip(). Guaranteed that 0 < n <= remain(). Default just reads data - // and discards it. Value of remain() is updated AFTER this call succeeds, not - // before. set_remain() should NOT be called from this. - virtual blargg_err_t skip_v( int n ); - -// Implementation -public: - BLARGG_DISABLE_NOTHROW - -private: - int remain_; -}; - - -// Supports seeking in addition to Data_Reader operations -class File_Reader : public Data_Reader { -public: - - // Size of file - int size() const { return size_; } - - // Current position in file - int tell() const { return size_ - remain(); } - - // Goes to new position - blargg_err_t seek( int ); - -// Derived interface -protected: - // Sets size and resets position - void set_size( int n ) { size_ = n; Data_Reader::set_remain( n ); } - void set_size( long n ) { set_size( STATIC_CAST(int, n) ); } - - // Sets reported position - void set_tell( int i ) { assert( 0 <= i && i <= size_ ); Data_Reader::set_remain( size_ - i ); } - - // Do same as seek(). Guaranteed that 0 <= n <= size(). Value of tell() is updated - // AFTER this call succeeds, not before. set_* functions should NOT be called from this. - virtual blargg_err_t seek_v( int n ) BLARGG_PURE( { (void)n; return blargg_ok; } ) - -// Implementation -protected: - File_Reader() : size_( 0 ) { } - - virtual blargg_err_t skip_v( int ); - -private: - int size_; - - void set_remain(); // avoid accidental use of set_remain -}; - - -// Reads from file on disk -class Std_File_Reader : public File_Reader { -public: - - // Opens file - blargg_err_t open( const char path [] ); - - // Closes file if one was open - void close(); - - // Switches to unbuffered mode. Useful if buffering is already being - // done at a higher level. - void make_unbuffered(); - -// Implementation -public: - Std_File_Reader(); - virtual ~Std_File_Reader(); - -protected: - virtual blargg_err_t read_v( void*, int ); - virtual blargg_err_t seek_v( int ); - -private: - void* file_; -}; - - -// Treats range of memory as a file -class Mem_File_Reader : public File_Reader { -public: - - Mem_File_Reader( const void* begin, long size ); - -// Implementation -protected: - virtual blargg_err_t read_v( void*, int ); - virtual blargg_err_t seek_v( int ); - -private: - const char* const begin; -}; - - -// Allows only count bytes to be read from reader passed -class Subset_Reader : public Data_Reader { -public: - - Subset_Reader( Data_Reader*, int count ); - -// Implementation -protected: - virtual blargg_err_t read_v( void*, int ); - -private: - Data_Reader* const in; -}; - - -// Joins already-read header and remaining data into original file. -// Meant for cases where you've already read header and don't want -// to seek and re-read data (for efficiency). -class Remaining_Reader : public Data_Reader { -public: - - Remaining_Reader( void const* header, int header_size, Data_Reader* ); - -// Implementation -protected: - virtual blargg_err_t read_v( void*, int ); - -private: - Data_Reader* const in; - void const* header; - int header_remain; -}; - - -// Invokes callback function to read data -extern "C" { // necessary to be usable from C - typedef const char* (*callback_reader_func_t)( - void* user_data, // Same value passed to constructor - void* out, // Buffer to place data into - int count // Number of bytes to read - ); -} -class Callback_Reader : public Data_Reader { -public: - typedef callback_reader_func_t callback_t; - Callback_Reader( callback_t, long size, void* user_data ); - -// Implementation -protected: - virtual blargg_err_t read_v( void*, int ); - -private: - callback_t const callback; - void* const user_data; -}; - - -// Invokes callback function to read data -extern "C" { // necessary to be usable from C - typedef const char* (*callback_file_reader_func_t)( - void* user_data, // Same value passed to constructor - void* out, // Buffer to place data into - int count, // Number of bytes to read - int pos // Position in file to read from - ); -} -class Callback_File_Reader : public File_Reader { -public: - typedef callback_file_reader_func_t callback_t; - Callback_File_Reader( callback_t, long size, void* user_data ); - -// Implementation -protected: - virtual blargg_err_t read_v( void*, int ); - virtual blargg_err_t seek_v( int ); - -private: - callback_t const callback; - void* const user_data; -}; - - -#ifdef HAVE_ZLIB_H - -// Reads file compressed with gzip (or uncompressed) -class Gzip_File_Reader : public File_Reader { -public: - - // Opens possibly gzipped file - blargg_err_t open( const char path [] ); - - // Closes file if one was open - void close(); - -// Implementation -public: - Gzip_File_Reader(); - ~Gzip_File_Reader(); - -protected: - virtual blargg_err_t read_v( void*, int ); - virtual blargg_err_t seek_v( int ); - -private: - // void* so "zlib.h" doesn't have to be included here - void* file_; -}; -#endif - -char* blargg_to_utf8( const wchar_t* ); -wchar_t* blargg_to_wide( const char* ); - -#endif diff --git a/snesreader/fex/File_Extractor.cpp b/snesreader/fex/File_Extractor.cpp deleted file mode 100644 index e060e095..00000000 --- a/snesreader/fex/File_Extractor.cpp +++ /dev/null @@ -1,341 +0,0 @@ -// File_Extractor 1.0.0. http://www.slack.net/~ant/ - -#include "File_Extractor.h" - -/* Copyright (C) 2005-2009 Shay Green. This module 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 -module is distributed in the hope that 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 module; if not, write to the Free Software Foundation, -Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -#include "blargg_source.h" - -File_Extractor::fex_t( fex_type_t t ) : - type_( t ) -{ - own_file_ = NULL; - - close_(); -} - -// Open - -blargg_err_t File_Extractor::set_path( const char* path ) -{ - if ( !path ) - path = ""; - - RETURN_ERR( path_.resize( strlen( path ) + 1 ) ); - memcpy( path_.begin(), path, path_.size() ); - return blargg_ok; -} - -blargg_err_t File_Extractor::open( const char path [] ) -{ - close(); - - RETURN_ERR( set_path( path ) ); - - blargg_err_t err = open_path_v(); - if ( err ) - close(); - else - opened_ = true; - - return err; -} - -blargg_err_t File_Extractor::open_path_v() -{ - RETURN_ERR( open_arc_file() ); - - return open_v(); -} - -inline -static void make_unbuffered( Std_File_Reader* r ) -{ - r->make_unbuffered(); -} - -inline -static void make_unbuffered( void* ) -{ } - -blargg_err_t File_Extractor::open_arc_file( bool unbuffered ) -{ - if ( reader_ ) - return blargg_ok; - - FEX_FILE_READER* in = BLARGG_NEW FEX_FILE_READER; - CHECK_ALLOC( in ); - - blargg_err_t err = in->open( arc_path() ); - if ( err ) - { - delete in; - } - else - { - reader_ = in; - own_file(); - if ( unbuffered ) - make_unbuffered( in ); - } - - return err; -} - -blargg_err_t File_Extractor::open( File_Reader* input, const char* path ) -{ - close(); - - RETURN_ERR( set_path( path ) ); - - RETURN_ERR( input->seek( 0 ) ); - - reader_ = input; - blargg_err_t err = open_v(); - if ( err ) - close(); - else - opened_ = true; - - return err; -} - -// Close - -void File_Extractor::close() -{ - close_v(); - close_(); -} - -void File_Extractor::close_() -{ - delete own_file_; - own_file_ = NULL; - - tell_ = 0; - reader_ = NULL; - opened_ = false; - - path_.clear(); - clear_file(); -} - -File_Extractor::~fex_t() -{ - check( !opened() ); // fails if derived destructor didn't call close() - - delete own_file_; -} - -// Scanning - -void File_Extractor::clear_file() -{ - name_ = NULL; - wname_ = NULL; - done_ = true; - stat_called = false; - data_ptr_ = NULL; - - set_info( 0 ); - own_data_.clear(); - clear_file_v(); -} - -void File_Extractor::set_name( const char new_name [], const wchar_t* new_wname ) -{ - name_ = new_name; - wname_ = new_wname; - done_ = false; -} - -void File_Extractor::set_info( int new_size, unsigned date, unsigned crc ) -{ - size_ = new_size; - date_ = (date != 0xFFFFFFFF ? date : 0); - crc32_ = crc; - set_remain( new_size ); -} - -blargg_err_t File_Extractor::next_() -{ - tell_++; - clear_file(); - - blargg_err_t err = next_v(); - if ( err ) - clear_file(); - - return err; -} - -blargg_err_t File_Extractor::next() -{ - assert( !done() ); - return next_(); -} - -blargg_err_t File_Extractor::rewind() -{ - assert( opened() ); - - tell_ = 0; - clear_file(); - - blargg_err_t err = rewind_v(); - if ( err ) - clear_file(); - - return err; -} - -blargg_err_t File_Extractor::stat() -{ - assert( !done() ); - - if ( !stat_called ) - { - RETURN_ERR( stat_v() ); - stat_called = true; - } - return blargg_ok; -} - -// Tell/seek - -int const pos_offset = 1; - -fex_pos_t File_Extractor::tell_arc() const -{ - assert( opened() ); - - fex_pos_t pos = tell_arc_v(); - assert( pos >= 0 ); - - return pos + pos_offset; -} - -blargg_err_t File_Extractor::seek_arc( fex_pos_t pos ) -{ - assert( opened() ); - assert( pos != 0 ); - - clear_file(); - - blargg_err_t err = seek_arc_v( pos - pos_offset ); - if ( err ) - clear_file(); - - return err; -} - -fex_pos_t File_Extractor::tell_arc_v() const -{ - return tell_; -} - -blargg_err_t File_Extractor::seek_arc_v( fex_pos_t pos ) -{ - // >= because seeking to current file should always reset read pointer etc. - if ( tell_ >= pos ) - RETURN_ERR( rewind() ); - - while ( tell_ < pos ) - { - RETURN_ERR( next_() ); - - if ( done() ) - { - assert( false ); - return blargg_err_caller; - } - } - - assert( tell_ == pos ); - - return blargg_ok; -} - -// Extraction - -blargg_err_t File_Extractor::rewind_file() -{ - RETURN_ERR( stat() ); - - if ( tell() > 0 ) - { - if ( data_ptr_ ) - { - set_remain( size() ); - } - else - { - RETURN_ERR( seek_arc( tell_arc() ) ); - RETURN_ERR( stat() ); - } - } - - return blargg_ok; -} - -blargg_err_t File_Extractor::data( const void** data_out ) -{ - assert( !done() ); - - *data_out = NULL; - if ( !data_ptr_ ) - { - int old_tell = tell(); - - RETURN_ERR( rewind_file() ); - - void const* ptr; - RETURN_ERR( data_v( &ptr ) ); - data_ptr_ = ptr; - - // Now that data is in memory, we can seek by simply setting remain - set_remain( size() - old_tell ); - } - - *data_out = data_ptr_; - return blargg_ok; -} - -blargg_err_t File_Extractor::data_v( void const** out ) -{ - RETURN_ERR( own_data_.resize( size() ) ); - *out = own_data_.begin(); - - blargg_err_t err = extract_v( own_data_.begin(), own_data_.size() ); - if ( err ) - own_data_.clear(); - - return err; -} - -blargg_err_t File_Extractor::extract_v( void* out, int count ) -{ - void const* p; - RETURN_ERR( data( &p ) ); - memcpy( out, STATIC_CAST(char const*,p) + (size() - remain()), count ); - - return blargg_ok; -} - -blargg_err_t File_Extractor::read_v( void* out, int count ) -{ - if ( data_ptr_ ) - return File_Extractor::extract_v( out, count ); - - return extract_v( out, count ); -} diff --git a/snesreader/fex/File_Extractor.h b/snesreader/fex/File_Extractor.h deleted file mode 100644 index ad25d5f8..00000000 --- a/snesreader/fex/File_Extractor.h +++ /dev/null @@ -1,191 +0,0 @@ -// Compressed file archive interface - -// File_Extractor 1.0.0 -#ifndef FILE_EXTRACTOR_H -#define FILE_EXTRACTOR_H - -#include "blargg_common.h" -#include "Data_Reader.h" -#include "fex.h" - -struct fex_t : private Data_Reader { -public: - virtual ~fex_t(); - -// Open/close - - // Opens archive from custom data source. Keeps pointer until close(). - blargg_err_t open( File_Reader* input, const char* path = NULL ); - - // Takes ownership of File_Reader* passed to open(), so that close() - // will delete it. - void own_file() { own_file_ = reader_; } - - // See fex.h - blargg_err_t open( const char path [] ); - fex_type_t type() const { return type_; } - void close(); - -// Scanning - - // See fex.h - bool done() const { return done_; } - blargg_err_t next(); - blargg_err_t rewind(); - fex_pos_t tell_arc() const; - blargg_err_t seek_arc( fex_pos_t ); - -// Info - - // See fex.h - const char* name() const { return name_; } - const wchar_t* wname() const { return wname_; } - blargg_err_t stat(); - int size() const { assert( stat_called ); return size_; } - unsigned int dos_date() const { return date_; } - unsigned int crc32() const { return crc32_; } - -// Extraction - - // Data_Reader to current file's data, so standard Data_Reader interface can - // be used, rather than having to treat archives specially. stat() must have - // been called. - Data_Reader& reader() { assert( stat_called ); return *this; } - - // See fex.h - blargg_err_t data( const void** data_out ); - int tell() const { return size_ - remain(); } - -// Derived interface -protected: - - // Sets type of object - fex_t( fex_type_t ); - - // Path to archive file, or "" if none supplied - const char* arc_path() const { return path_.begin(); } - - // Opens archive file if it's not already. If unbuffered is true, opens file - // without any buffering. - blargg_err_t open_arc_file( bool unbuffered = false ); - - // Archive file - File_Reader& arc() const { return *reader_; } - - // Sets current file name - void set_name( const char name [], const wchar_t* wname = NULL ); - - // Sets current file information - void set_info( int size, unsigned date = 0, unsigned crc = 0 ); - -// User overrides - - // Overrides must do indicated task. Non-pure functions have reasonable default - // implementation. Overrides should avoid calling public functions like - // next() and rewind(). - - // Open archive using file_path(). OK to delay actual file opening until later. - // Default just calls open_arc_file(), then open_v(). - virtual blargg_err_t open_path_v(); - - // Open archive using file() for source data. If unsupported, return error. - virtual blargg_err_t open_v() BLARGG_PURE( ; ) - - // Go to next file in archive and call set_name() and optionally set_info() - virtual blargg_err_t next_v() BLARGG_PURE( ; ) - - // Go back to first file in archive - virtual blargg_err_t rewind_v() BLARGG_PURE( ; ) - - // Close archive. Called even if open_path_v() or open_v() return unsuccessfully. - virtual void close_v() BLARGG_PURE( ; ) - - // Clear any fields related to current file - virtual void clear_file_v() { } - - // Call set_info() if not already called by next_v() - virtual blargg_err_t stat_v() { return blargg_ok; } - - // Return value that allows later return to this file. Result must be >= 0. - virtual fex_pos_t tell_arc_v() const; - - // Return to previously saved position - virtual blargg_err_t seek_arc_v( fex_pos_t ); - - // One or both of the following must be overridden - - // Provide pointer to data for current file in archive - virtual blargg_err_t data_v( const void** out ); - - // Extract next n bytes - virtual blargg_err_t extract_v( void* out, int n ); - -// Implementation -public: - BLARGG_DISABLE_NOTHROW - -private: - fex_type_t const type_; - - // Archive file - blargg_vector path_; - File_Reader* reader_; - File_Reader* own_file_; - bool opened_; - - // Position in archive - fex_pos_t tell_; // only used by default implementation of tell/seek - bool done_; - - // Info for current file in archive - const char* name_; - const wchar_t* wname_; - unsigned date_; - unsigned crc32_; - int size_; - bool stat_called; - - // Current file contents - void const* data_ptr_; // NULL if not read into memory - blargg_vector own_data_; - - bool opened() const { return opened_; } - void clear_file(); - void close_(); - blargg_err_t set_path( const char* path ); - blargg_err_t rewind_file(); - blargg_err_t next_(); - - // Data_Reader overrides - // TODO: override skip_v? - virtual blargg_err_t read_v( void* out, int n ); -}; - -struct fex_type_t_ -{ - const char* extension; - File_Extractor* (*new_fex)(); - const char* name; - blargg_err_t (*init)(); // Called by fex_init(). Can be NULL. -}; - -extern const fex_type_t_ - fex_7z_type [1], - fex_gz_type [1], - fex_rar_type [1], - fex_zip_type [1], - fex_bin_type [1]; - -inline blargg_err_t File_Extractor::open_v() { return blargg_ok; } -inline blargg_err_t File_Extractor::next_v() { return blargg_ok; } -inline blargg_err_t File_Extractor::rewind_v() { return blargg_ok; } -inline void File_Extractor::close_v() { } - -// Default to Std_File_Reader for archive access -#ifndef FEX_FILE_READER - #define FEX_FILE_READER Std_File_Reader -#elif defined (FEX_FILE_READER_INCLUDE) - #include FEX_FILE_READER_INCLUDE -#endif - -#endif diff --git a/snesreader/fex/Gzip_Extractor.cpp b/snesreader/fex/Gzip_Extractor.cpp deleted file mode 100644 index f169fed9..00000000 --- a/snesreader/fex/Gzip_Extractor.cpp +++ /dev/null @@ -1,98 +0,0 @@ -// File_Extractor 1.0.0. http://www.slack.net/~ant/ - -#include "Gzip_Extractor.h" - -/* Copyright (C) 2005-2009 Shay Green. This module 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 -module is distributed in the hope that 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 module; if not, write to the Free Software Foundation, -Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -#include "blargg_source.h" - -// TODO: could close file once data has been read into memory - -static blargg_err_t init_gzip_file() -{ - get_crc_table(); // initialize zlib's CRC-32 tables - return blargg_ok; -} - -static File_Extractor* new_gzip() -{ - return BLARGG_NEW Gzip_Extractor; -} - -fex_type_t_ const fex_gz_type [1] = {{ - ".gz", - &new_gzip, - "gzipped file", - &init_gzip_file -}}; - -Gzip_Extractor::Gzip_Extractor() : - File_Extractor( fex_gz_type ) -{ } - -Gzip_Extractor::~Gzip_Extractor() -{ - close(); -} - -blargg_err_t Gzip_Extractor::open_path_v() -{ - // skip opening file - return open_v(); -} - -blargg_err_t Gzip_Extractor::stat_v() -{ - RETURN_ERR( open_arc_file( true ) ); - if ( !gr.opened() || gr.tell() != 0 ) - RETURN_ERR( gr.open( &arc() ) ); - - set_info( gr.remain(), 0, gr.crc32() ); - return blargg_ok; -} - -blargg_err_t Gzip_Extractor::open_v() -{ - // Remove .gz suffix - size_t len = strlen( arc_path() ); - if ( fex_has_extension( arc_path(), ".gz" ) ) - len -= 3; - - RETURN_ERR( name.resize( len + 1 ) ); - memcpy( name.begin(), arc_path(), name.size() ); - name [name.size() - 1] = '\0'; - - set_name( name.begin() ); - return blargg_ok; -} - -void Gzip_Extractor::close_v() -{ - name.clear(); - gr.close(); -} - -blargg_err_t Gzip_Extractor::next_v() -{ - return blargg_ok; -} - -blargg_err_t Gzip_Extractor::rewind_v() -{ - set_name( name.begin() ); - return blargg_ok; -} - -blargg_err_t Gzip_Extractor::extract_v( void* p, int n ) -{ - return gr.read( p, n ); -} diff --git a/snesreader/fex/Gzip_Extractor.h b/snesreader/fex/Gzip_Extractor.h deleted file mode 100644 index 814dc9b3..00000000 --- a/snesreader/fex/Gzip_Extractor.h +++ /dev/null @@ -1,34 +0,0 @@ -// Presents a gzipped file as an "archive" of just that file. -// Also handles non-gzipped files. - -// File_Extractor 1.0.0 -#ifndef GZIP_EXTRACTOR_H -#define GZIP_EXTRACTOR_H - -#include "File_Extractor.h" -#include "Gzip_Reader.h" - -class Gzip_Extractor : public File_Extractor { -public: - Gzip_Extractor(); - virtual ~Gzip_Extractor(); - -protected: - virtual blargg_err_t open_path_v(); - virtual blargg_err_t open_v(); - virtual void close_v(); - - virtual blargg_err_t next_v(); - virtual blargg_err_t rewind_v(); - - virtual blargg_err_t stat_v(); - virtual blargg_err_t extract_v( void*, int ); - -private: - Gzip_Reader gr; - blargg_vector name; - - void set_info_(); -}; - -#endif diff --git a/snesreader/fex/Gzip_Reader.cpp b/snesreader/fex/Gzip_Reader.cpp deleted file mode 100644 index 2aad302c..00000000 --- a/snesreader/fex/Gzip_Reader.cpp +++ /dev/null @@ -1,85 +0,0 @@ -// File_Extractor 1.0.0. http://www.slack.net/~ant/ - -#include "Gzip_Reader.h" - -#include "blargg_endian.h" - -/* Copyright (C) 2006-2009 Shay Green. This module 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 -module is distributed in the hope that 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 module; if not, write to the Free Software Foundation, -Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -#include "blargg_source.h" - -Gzip_Reader::Gzip_Reader() -{ - close(); -} - -Gzip_Reader::~Gzip_Reader() -{ } - -static blargg_err_t gzip_reader_read( void* file, void* out, int* count ) -{ - return STATIC_CAST(File_Reader*,file)->read_avail( out, count ); -} - -blargg_err_t Gzip_Reader::calc_size() -{ - size_ = in->size(); - crc32_ = 0; - if ( inflater.deflated() ) - { - byte trailer [8]; - int old_pos = in->tell(); - RETURN_ERR( in->seek( size_ - sizeof trailer ) ); - RETURN_ERR( in->read( trailer, sizeof trailer ) ); - RETURN_ERR( in->seek( old_pos ) ); - crc32_ = get_le32( trailer + 0 ); - - unsigned n = get_le32( trailer + 4 ); - if ( n > INT_MAX ) - return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "gzip larger than 2GB" ); - - size_ = n; - } - return blargg_ok; -} - -blargg_err_t Gzip_Reader::open( File_Reader* new_in ) -{ - close(); - - in = new_in; - RETURN_ERR( in->seek( 0 ) ); - RETURN_ERR( inflater.begin( gzip_reader_read, new_in ) ); - RETURN_ERR( inflater.set_mode( inflater.mode_auto ) ); - RETURN_ERR( calc_size() ); - set_remain( size_ ); - - return blargg_ok; -} - -void Gzip_Reader::close() -{ - in = NULL; - inflater.end(); -} - -blargg_err_t Gzip_Reader::read_v( void* out, int count ) -{ - assert( in ); - int actual = count; - RETURN_ERR( inflater.read( out, &actual ) ); - - if ( actual != count ) - return blargg_err_file_corrupt; - - return blargg_ok; -} diff --git a/snesreader/fex/Gzip_Reader.h b/snesreader/fex/Gzip_Reader.h deleted file mode 100644 index a9b2d6a9..00000000 --- a/snesreader/fex/Gzip_Reader.h +++ /dev/null @@ -1,46 +0,0 @@ -// Transparently decompresses gzip files, as well as uncompressed - -// File_Extractor 1.0.0 -#ifndef GZIP_READER_H -#define GZIP_READER_H - -#include "Data_Reader.h" -#include "Zlib_Inflater.h" - -class Gzip_Reader : public Data_Reader { -public: - // Keeps pointer to reader until close(). If - blargg_err_t open( File_Reader* ); - - // True if file is open - bool opened() const { return in != NULL; } - - // Frees memory - void close(); - - // True if file is compressed - bool deflated() const { return inflater.deflated(); } - - // CRC-32 of data, of 0 if unavailable - unsigned int crc32() const { return crc32_; } - - // Number of bytes read since opening - int tell() const { return size_ - remain(); } - -public: - Gzip_Reader(); - virtual ~Gzip_Reader(); - -protected: - virtual blargg_err_t read_v( void*, int ); - -private: - File_Reader* in; - unsigned crc32_; - int size_; - Zlib_Inflater inflater; - - blargg_err_t calc_size(); -}; - -#endif diff --git a/snesreader/fex/Rar_Extractor.cpp b/snesreader/fex/Rar_Extractor.cpp deleted file mode 100644 index afade7fa..00000000 --- a/snesreader/fex/Rar_Extractor.cpp +++ /dev/null @@ -1,197 +0,0 @@ -// File_Extractor 1.0.0. http://www.slack.net/~ant/ - -#include "blargg_common.h" - -#if FEX_ENABLE_RAR - -#include "Rar_Extractor.h" - -/* Copyright (C) 2009 Shay Green. This module 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 -module is distributed in the hope that 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 module; if not, write to the Free Software Foundation, -Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -#include "blargg_source.h" - -static blargg_err_t init_rar() -{ - unrar_init(); - return blargg_ok; -} - -static File_Extractor* new_rar() -{ - return BLARGG_NEW Rar_Extractor; -} - -fex_type_t_ const fex_rar_type [1] = {{ - ".rar", - &new_rar, - "RAR archive", - &init_rar -}}; - -blargg_err_t Rar_Extractor::convert_err( unrar_err_t err ) -{ - blargg_err_t reader_err = reader.err; - reader.err = blargg_ok; - if ( reader_err ) - check( err == unrar_next_err ); - - switch ( err ) - { - case unrar_ok: return blargg_ok; - case unrar_err_memory: return blargg_err_memory; - case unrar_err_open: return blargg_err_file_read; - case unrar_err_not_arc: return blargg_err_file_type; - case unrar_err_corrupt: return blargg_err_file_corrupt; - case unrar_err_io: return blargg_err_file_io; - case unrar_err_arc_eof: return blargg_err_internal; - case unrar_err_encrypted: return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "RAR encryption not supported" ); - case unrar_err_segmented: return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "RAR segmentation not supported" ); - case unrar_err_huge: return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "Huge RAR files not supported" ); - case unrar_err_old_algo: return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "Old RAR compression not supported" ); - case unrar_err_new_algo: return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "RAR uses unknown newer compression" ); - case unrar_next_err: break; - default: - check( false ); // unhandled RAR error - } - - if ( reader_err ) - return reader_err; - - check( false ); - return BLARGG_ERR( BLARGG_ERR_INTERNAL, "RAR archive" ); -} - -static inline unrar_err_t handle_err( Rar_Extractor::read_callback_t* h, blargg_err_t err ) -{ - if ( !err ) - return unrar_ok; - - h->err = err; - return unrar_next_err; -} - -extern "C" -{ - static unrar_err_t my_unrar_read( void* data, void* out, int* count, unrar_pos_t pos ) - { - // TODO: 64-bit file support - - Rar_Extractor::read_callback_t* h = STATIC_CAST(Rar_Extractor::read_callback_t*,data); - if ( h->pos != pos ) - { - blargg_err_t err = h->in->seek( pos ); - if ( err ) - return handle_err( h, err ); - - h->pos = pos; - } - - blargg_err_t err = h->in->read_avail( out, count ); - if ( err ) - return handle_err( h, err ); - - h->pos += *count; - - return unrar_ok; - } -} - -Rar_Extractor::Rar_Extractor() : - File_Extractor( fex_rar_type ) -{ - unrar = NULL; -} - -Rar_Extractor::~Rar_Extractor() -{ - close(); -} - -blargg_err_t Rar_Extractor::open_v() -{ - reader.pos = 0; - reader.in = &arc(); - reader.err = blargg_ok; - - RETURN_ERR( arc().seek( 0 ) ); - RETURN_ERR( convert_err( unrar_open_custom( &unrar, &my_unrar_read, &reader ) ) ); - return skip_unextractables(); -} - -void Rar_Extractor::close_v() -{ - unrar_close( unrar ); - - unrar = NULL; - reader.in = NULL; -} - -blargg_err_t Rar_Extractor::skip_unextractables() -{ - while ( !unrar_done( unrar ) && unrar_try_extract( unrar ) ) - RETURN_ERR( next_raw() ); - - if ( !unrar_done( unrar ) ) - { - unrar_info_t const* info = unrar_info( unrar ); - - set_name( info->name, (info->name_w && *info->name_w) ? info->name_w : NULL ); - set_info( info->size, info->dos_date, (info->is_crc32 ? info->crc : 0) ); - } - - return blargg_ok; -} - -blargg_err_t Rar_Extractor::next_raw() -{ - return convert_err( unrar_next( unrar ) ); -} - -blargg_err_t Rar_Extractor::next_v() -{ - RETURN_ERR( next_raw() ); - return skip_unextractables(); -} - -blargg_err_t Rar_Extractor::rewind_v() -{ - RETURN_ERR( convert_err( unrar_rewind( unrar ) ) ); - return skip_unextractables(); -} - -fex_pos_t Rar_Extractor::tell_arc_v() const -{ - return unrar_tell( unrar ); -} - -blargg_err_t Rar_Extractor::seek_arc_v( fex_pos_t pos ) -{ - RETURN_ERR( convert_err( unrar_seek( unrar, pos ) ) ); - return skip_unextractables(); -} - -blargg_err_t Rar_Extractor::data_v( void const** out ) -{ - return convert_err( unrar_extract_mem( unrar, out ) ); -} - -blargg_err_t Rar_Extractor::extract_v( void* out, int count ) -{ - // We can read entire file directly into user buffer - if ( count == size() ) - return convert_err( unrar_extract( unrar, out, count ) ); - - // This will call data_v() and copy from that buffer for us - return File_Extractor::extract_v( out, count ); -} - -#endif diff --git a/snesreader/fex/Rar_Extractor.h b/snesreader/fex/Rar_Extractor.h deleted file mode 100644 index 9a74dea3..00000000 --- a/snesreader/fex/Rar_Extractor.h +++ /dev/null @@ -1,43 +0,0 @@ -// RAR archive extractor - -// File_Extractor 1.0.0 -#ifndef RAR_EXTRACTOR_H -#define RAR_EXTRACTOR_H - -#include "File_Extractor.h" -#include "unrar/unrar.h" - -class Rar_Extractor : public File_Extractor { -public: - Rar_Extractor(); - virtual ~Rar_Extractor(); - - struct read_callback_t - { - const char* err; - int pos; - File_Reader* in; - }; - -protected: - virtual blargg_err_t open_v(); - virtual void close_v(); - - virtual blargg_err_t next_v(); - virtual blargg_err_t rewind_v(); - virtual fex_pos_t tell_arc_v() const; - virtual blargg_err_t seek_arc_v( fex_pos_t ); - - virtual blargg_err_t data_v( void const** ); - virtual blargg_err_t extract_v( void*, int ); - -private: - unrar_t* unrar; - read_callback_t reader; - - blargg_err_t convert_err( unrar_err_t ); - blargg_err_t skip_unextractables(); - blargg_err_t next_raw(); -}; - -#endif diff --git a/snesreader/fex/Zip7_Extractor.cpp b/snesreader/fex/Zip7_Extractor.cpp deleted file mode 100644 index 1803a71c..00000000 --- a/snesreader/fex/Zip7_Extractor.cpp +++ /dev/null @@ -1,252 +0,0 @@ -// File_Extractor 1.0.0. http://www.slack.net/~ant/ - -#include "Zip7_Extractor.h" - -#include "7z_C/7zExtract.h" -#include "7z_C/7zAlloc.h" -#include "7z_C/7zCrc.h" - -/* Copyright (C) 2005-2009 Shay Green. This module 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 -module is distributed in the hope that 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 module; if not, write to the Free Software Foundation, -Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -#include "blargg_source.h" - -static ISzAlloc zip7_alloc = { SzAlloc, SzFree }; -static ISzAlloc zip7_alloc_temp = { SzAllocTemp, SzFreeTemp }; - -struct Zip7_Extractor_Impl : - ISeekInStream -{ - CLookToRead look; - CSzArEx db; - - // SzExtract state - UInt32 block_index; - Byte* buf; - size_t buf_size; - - File_Reader* in; - const char* in_err; -}; - -extern "C" -{ - // 7-zip callbacks pass an ISeekInStream* for data, so we must cast it - // back to ISeekInStream* FIRST, then cast to our Impl structure - - static SRes zip7_read_( void* vstream, void* out, size_t* size ) - { - assert( out && size ); - ISeekInStream* stream = STATIC_CAST(ISeekInStream*,vstream); - Zip7_Extractor_Impl* impl = STATIC_CAST(Zip7_Extractor_Impl*,stream); - - long lsize = *size; - blargg_err_t err = impl->in->read_avail( out, &lsize ); - if ( err ) - { - *size = 0; - impl->in_err = err; - return SZ_ERROR_READ; - } - - *size = lsize; - return SZ_OK; - } - - static SRes zip7_seek_( void* vstream, Int64* pos, ESzSeek mode ) - { - ISeekInStream* stream = STATIC_CAST(ISeekInStream*,vstream); - Zip7_Extractor_Impl* impl = STATIC_CAST(Zip7_Extractor_Impl*,stream); - - assert( mode != SZ_SEEK_CUR ); // never used - - if ( mode == SZ_SEEK_END ) - { - assert( *pos == 0 ); // only used to find file length - *pos = impl->in->size(); - return SZ_OK; - } - - assert( mode == SZ_SEEK_SET ); - blargg_err_t err = impl->in->seek( *pos ); - if ( err ) - { - // don't set in_err in this case, since it might be benign - if ( err == blargg_err_file_eof ) - return SZ_ERROR_INPUT_EOF; - - impl->in_err = err; - return SZ_ERROR_READ; - } - - return SZ_OK; - } -} - -blargg_err_t Zip7_Extractor::zip7_err( int err ) -{ - // TODO: ignore in_err in some cases? unsure about which error to use - blargg_err_t in_err = impl->in_err; - impl->in_err = NULL; - if ( in_err ) - { - check( err != SZ_OK ); - return in_err; - } - - switch ( err ) - { - case SZ_OK: return blargg_ok; - case SZ_ERROR_MEM: return blargg_err_memory; - case SZ_ERROR_READ: return blargg_err_file_io; - case SZ_ERROR_CRC: - case SZ_ERROR_DATA: - case SZ_ERROR_INPUT_EOF: - case SZ_ERROR_ARCHIVE: return blargg_err_file_corrupt; - case SZ_ERROR_UNSUPPORTED: return blargg_err_file_feature; - case SZ_ERROR_NO_ARCHIVE: return blargg_err_file_type; - } - - return blargg_err_generic; -} - -static blargg_err_t init_7z() -{ - static bool inited; - if ( !inited ) - { - inited = true; - CrcGenerateTable(); - } - return blargg_ok; -} - -static File_Extractor* new_7z() -{ - return BLARGG_NEW Zip7_Extractor; -} - -fex_type_t_ const fex_7z_type [1] = {{ - ".7z", - &new_7z, - "7-zip archive", - &init_7z -}}; - -Zip7_Extractor::Zip7_Extractor() : - File_Extractor( fex_7z_type ) -{ - impl = NULL; -} - -Zip7_Extractor::~Zip7_Extractor() -{ - close(); -} - -blargg_err_t Zip7_Extractor::open_v() -{ - RETURN_ERR( init_7z() ); - - if ( !impl ) - { - impl = (Zip7_Extractor_Impl*) malloc( sizeof *impl ); - CHECK_ALLOC( impl ); - } - - impl->in = &arc(); - impl->block_index = (UInt32) -1; - impl->buf = NULL; - impl->buf_size = 0; - - LookToRead_CreateVTable( &impl->look, false ); - impl->ISeekInStream::Read = zip7_read_; - impl->ISeekInStream::Seek = zip7_seek_; - impl->look.realStream = impl; - LookToRead_Init( &impl->look ); - - SzArEx_Init( &impl->db ); - - impl->in_err = NULL; - RETURN_ERR( zip7_err( SzArEx_Open( &impl->db, &impl->look.s, - &zip7_alloc, &zip7_alloc_temp ) ) ); - - return seek_arc_v( 0 ); -} - -void Zip7_Extractor::close_v() -{ - if ( impl ) - { - if ( impl->in ) - { - impl->in = NULL; - SzArEx_Free( &impl->db, &zip7_alloc ); - } - IAlloc_Free( &zip7_alloc, impl->buf ); - free( impl ); - impl = NULL; - } -} - -blargg_err_t Zip7_Extractor::next_v() -{ - while ( ++index < (int) impl->db.db.NumFiles ) - { - CSzFileItem const& item = impl->db.db.Files [index]; - if ( !item.IsDir ) - { - // TODO: Support date. - // NTFS representation, stored as 64-bit value. - // Divide by 10000000 (ten million) to get seconds - //item.MTime.Low + (.High << 32) - // How to convert to DOS style? - - set_name( item.Name ); - set_info( item.Size, 0, (item.FileCRCDefined ? item.FileCRC : 0) ); - break; - } - } - - return blargg_ok; -} - -blargg_err_t Zip7_Extractor::rewind_v() -{ - return seek_arc_v( 0 ); -} - -fex_pos_t Zip7_Extractor::tell_arc_v() const -{ - return index; -} - -blargg_err_t Zip7_Extractor::seek_arc_v( fex_pos_t pos ) -{ - assert( 0 <= pos && pos <= (int) impl->db.db.NumFiles ); - - index = pos - 1; - return next_v(); -} - -blargg_err_t Zip7_Extractor::data_v( void const** out ) -{ - impl->in_err = NULL; - size_t offset = 0; - size_t count = 0; - RETURN_ERR( zip7_err( SzAr_Extract( &impl->db, &impl->look.s, index, - &impl->block_index, &impl->buf, &impl->buf_size, - &offset, &count, &zip7_alloc, &zip7_alloc_temp ) ) ); - assert( count == (size_t) size() ); - - *out = impl->buf + offset; - return blargg_ok; -} diff --git a/snesreader/fex/Zip7_Extractor.h b/snesreader/fex/Zip7_Extractor.h deleted file mode 100644 index f658ba04..00000000 --- a/snesreader/fex/Zip7_Extractor.h +++ /dev/null @@ -1,34 +0,0 @@ -// 7-zip archive extractor - -// File_Extractor 1.0.0 -#ifndef ZIP7_EXTRACTOR_H -#define ZIP7_EXTRACTOR_H - -#include "File_Extractor.h" - -struct Zip7_Extractor_Impl; - -class Zip7_Extractor : public File_Extractor { -public: - Zip7_Extractor(); - virtual ~Zip7_Extractor(); - -protected: - virtual blargg_err_t open_v(); - virtual void close_v(); - - virtual blargg_err_t next_v(); - virtual blargg_err_t rewind_v(); - virtual fex_pos_t tell_arc_v() const; - virtual blargg_err_t seek_arc_v( fex_pos_t ); - - virtual blargg_err_t data_v( void const** out ); - -private: - Zip7_Extractor_Impl* impl; - int index; - - blargg_err_t zip7_err( int err ); -}; - -#endif diff --git a/snesreader/fex/Zip_Extractor.cpp b/snesreader/fex/Zip_Extractor.cpp deleted file mode 100644 index 8bcc61c3..00000000 --- a/snesreader/fex/Zip_Extractor.cpp +++ /dev/null @@ -1,390 +0,0 @@ -// File_Extractor 1.0.0. http://www.slack.net/~ant/ - -#include "Zip_Extractor.h" - -#include "blargg_endian.h" - -/* Copyright (C) 2005-2009 Shay Green. This module 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 -module is distributed in the hope that 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 module; if not, write to the Free Software Foundation, -Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -/* To avoid copying filename string from catalog, I terminate it by modifying -catalog data. This potentially requires moving the first byte of the type -of the next entry elsewhere; I move it to the first byte of made_by. Kind -of hacky, but I'd rather not have to allocate memory for a copy of it. */ - -#include "blargg_source.h" - -/* Reads this much from end of file when first opening. Only this much is -searched for the end catalog entry. If whole catalog is within this data, -nothing more needs to be read on open. */ -int const end_read_size = 8 * 1024; - -/* Reads are are made using file offset that's a multiple of this, -increasing performance. */ -int const disk_block_size = 4 * 1024; - -// Read buffer used for extracting file data -int const read_buf_size = 16 * 1024; - -struct header_t -{ - char type [4]; - byte vers [2]; - byte flags [2]; - byte method [2]; - byte date [4]; - byte crc [4]; - byte raw_size [4]; - byte size [4]; - byte filename_len [2]; - byte extra_len [2]; - char filename [2]; // [filename_len] - //char extra [extra_len]; -}; -int const header_size = 30; - -struct entry_t -{ - char type [4]; - byte made_by [2]; - byte vers [2]; - byte flags [2]; - byte method [2]; - byte date [4]; - byte crc [4]; - byte raw_size [4]; - byte size [4]; - byte filename_len [2]; - byte extra_len [2]; - byte comment_len [2]; - byte disk [2]; - byte int_attrib [2]; - byte ext_attrib [4]; - byte file_offset [4]; - char filename [2]; // [filename_len] - //char extra [extra_len]; - //char comment [comment_len]; -}; -int const entry_size = 46; - -struct end_entry_t -{ - char type [4]; - byte disk [2]; - byte first_disk [2]; - byte disk_entry_count [2]; - byte entry_count [2]; - byte dir_size [4]; - byte dir_offset [4]; - byte comment_len [2]; - char comment [2]; // [comment_len] -}; -int const end_entry_size = 22; - -static blargg_err_t init_zip() -{ - get_crc_table(); // initialize zlib's CRC-32 tables - return blargg_ok; -} - -static File_Extractor* new_zip() -{ - return BLARGG_NEW Zip_Extractor; -} - -fex_type_t_ const fex_zip_type [1] = {{ - ".zip", - &new_zip, - "ZIP archive", - &init_zip -}}; - -Zip_Extractor::Zip_Extractor() : - File_Extractor( fex_zip_type ) -{ - Zip_Extractor::clear_file_v(); - - // If these fail, structures had extra padding inserted by compiler - assert( offsetof (header_t,filename) == header_size ); - assert( offsetof (entry_t,filename) == entry_size ); - assert( offsetof (end_entry_t,comment) == end_entry_size ); -} - -Zip_Extractor::~Zip_Extractor() -{ - close(); -} - -blargg_err_t Zip_Extractor::open_path_v() -{ - RETURN_ERR( open_arc_file( true ) ); - return File_Extractor::open_path_v(); -} - -inline -void Zip_Extractor::reorder_entry_header( int offset ) -{ - catalog [offset + 0] = 0; - catalog [offset + 4] = 'P'; -} - -blargg_err_t Zip_Extractor::open_v() -{ - if ( arc().size() < end_entry_size ) - return blargg_err_file_type; - - // Read final end_read_size bytes of file - int file_pos = max( 0, arc().size() - end_read_size ); - file_pos -= file_pos % disk_block_size; - RETURN_ERR( catalog.resize( arc().size() - file_pos ) ); - RETURN_ERR( arc().seek( file_pos ) ); - RETURN_ERR( arc().read( catalog.begin(), catalog.size() ) ); - - // Find end-of-catalog entry - int end_pos = catalog.size() - end_entry_size; - while ( end_pos >= 0 && memcmp( &catalog [end_pos], "PK\5\6", 4 ) ) - end_pos--; - if ( end_pos < 0 ) - return blargg_err_file_type; - end_entry_t const& end_entry = (end_entry_t&) catalog [end_pos]; - end_pos += file_pos; - - // some idiotic zip compressors add data to end of zip without setting comment len -// check( arc().size() == end_pos + end_entry_size + get_le16( end_entry.comment_len ) ); - - // Find file offset of beginning of catalog - catalog_begin = get_le32( end_entry.dir_offset ); - int catalog_size = end_pos - catalog_begin; - if ( catalog_size < 0 ) - return blargg_err_file_corrupt; - catalog_size += end_entry_size; - - // See if catalog is entirely contained in bytes already read - int begin_offset = catalog_begin - file_pos; - if ( begin_offset >= 0 ) - memmove( catalog.begin(), &catalog [begin_offset], catalog_size ); - - RETURN_ERR( catalog.resize( catalog_size ) ); - if ( begin_offset < 0 ) - { - // Catalog begins before bytes read, so it needs to be read - RETURN_ERR( arc().seek( catalog_begin ) ); - RETURN_ERR( arc().read( catalog.begin(), catalog.size() ) ); - } - - // First entry in catalog should be a file or end of archive - if ( memcmp( catalog.begin(), "PK\1\2", 4 ) && memcmp( catalog.begin(), "PK\5\6", 4 ) ) - return blargg_err_file_type; - - reorder_entry_header( 0 ); - return rewind_v(); -} - -void Zip_Extractor::close_v() -{ - catalog.clear(); -} - -// Scanning - -inline -static bool is_normal_file( entry_t const& e, unsigned len ) -{ - int last_char = (len ? e.filename [len - 1] : '/'); - bool is_dir = (last_char == '/' || last_char == '\\'); - if ( is_dir && get_le32( e.size ) == 0 ) - return false; - check( !is_dir ); - - // Mac OS X puts meta-information in separate files with normal extensions, - // so they must be filtered out or caller will mistake them for normal files. - if ( e.made_by[1] == 3 ) - { - const char* dir = strrchr( e.filename, '/' ); - if ( dir ) - dir++; - else - dir = e.filename; - - if ( *dir == '.' ) - return false; - - if ( !strcmp( dir, "Icon\x0D" ) ) - return false; - } - - return true; -} - -blargg_err_t Zip_Extractor::update_info( bool advance_first ) -{ - while ( 1 ) - { - entry_t& e = (entry_t&) catalog [catalog_pos]; - - if ( memcmp( e.type, "\0K\1\2P", 5 ) && memcmp( e.type, "PK\1\2", 4 ) ) - { - check( !memcmp( e.type, "\0K\5\6P", 5 ) ); - break; - } - - unsigned len = get_le16( e.filename_len ); - int next_offset = catalog_pos + entry_size + len + get_le16( e.extra_len ) + - get_le16( e.comment_len ); - if ( (unsigned) next_offset > catalog.size() - end_entry_size ) - return blargg_err_file_corrupt; - - if ( catalog [next_offset] == 'P' ) - reorder_entry_header( next_offset ); - - if ( !advance_first ) - { - e.filename [len] = 0; // terminate name - - if ( is_normal_file( e, len ) ) - { - set_name( e.filename ); - set_info( get_le32( e.size ), get_le32( e.date ), get_le32( e.crc ) ); - break; - } - } - - catalog_pos = next_offset; - advance_first = false; - } - - return blargg_ok; -} - -blargg_err_t Zip_Extractor::next_v() -{ - return update_info( true ); -} - -blargg_err_t Zip_Extractor::rewind_v() -{ - return seek_arc_v( 0 ); -} - -fex_pos_t Zip_Extractor::tell_arc_v() const -{ - return catalog_pos; -} - -blargg_err_t Zip_Extractor::seek_arc_v( fex_pos_t pos ) -{ - assert( 0 <= pos && (size_t) pos <= catalog.size() - end_entry_size ); - - catalog_pos = pos; - return update_info( false ); -} - -// Reading - -void Zip_Extractor::clear_file_v() -{ - buf.end(); -} - -blargg_err_t Zip_Extractor::inflater_read( void* data, void* out, int* count ) -{ - Zip_Extractor& self = *STATIC_CAST(Zip_Extractor*,data); - - if ( *count > self.raw_remain ) - *count = self.raw_remain; - - self.raw_remain -= *count; - - return self.arc().read( out, *count ); -} - -blargg_err_t Zip_Extractor::fill_buf( int offset, int buf_size, int initial_read ) -{ - raw_remain = arc().size() - offset; - RETURN_ERR( arc().seek( offset ) ); - return buf.begin( inflater_read, this, buf_size, initial_read ); -} - -blargg_err_t Zip_Extractor::first_read( int count ) -{ - entry_t const& e = (entry_t&) catalog [catalog_pos]; - - // Determine compression - { - int method = get_le16( e.method ); - if ( (method && method != Z_DEFLATED) || get_le16( e.vers ) > 20 ) - return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "compression method" ); - file_deflated = (method != 0); - } - - int raw_size = get_le32( e.raw_size ); - - int file_offset = get_le32( e.file_offset ); - int align = file_offset % disk_block_size; - { - // read header - int buf_size = 3 * disk_block_size - 1 + raw_size; // space for all raw data - buf_size -= buf_size % disk_block_size; - int initial_read = buf_size; - if ( !file_deflated || count < size() ) - { - buf_size = read_buf_size; - initial_read = disk_block_size * 2; - } - // TODO: avoid re-reading if buffer already has data we want? - RETURN_ERR( fill_buf( file_offset - align, buf_size, initial_read ) ); - } - header_t const& h = (header_t&) buf.data() [align]; - if ( buf.filled() < align + header_size || memcmp( h.type, "PK\3\4", 4 ) ) - return blargg_err_file_corrupt; - - // CRCs of header and file data - correct_crc = get_le32( h.crc ); - if ( !correct_crc ) - correct_crc = get_le32( e.crc ); - check( correct_crc == get_le32( e.crc ) ); // catalog CRC should match - crc = ::crc32( 0, NULL, 0 ); - - // Data offset - int data_offset = file_offset + header_size + - get_le16( h.filename_len ) + get_le16( h.extra_len ); - if ( data_offset + raw_size > catalog_begin ) - return blargg_err_file_corrupt; - - // Refill buffer if there's lots of extra data after header - int buf_offset = data_offset - file_offset + align; - if ( buf_offset > buf.filled() ) - { - // TODO: this will almost never occur, making it a good place for bugs - buf_offset = data_offset % disk_block_size; - RETURN_ERR( fill_buf( data_offset - buf_offset, read_buf_size, disk_block_size ) ); - } - - raw_remain = raw_size - (buf.filled() - buf_offset); - return buf.set_mode( (file_deflated ? buf.mode_raw_deflate : buf.mode_copy), buf_offset ); -} - -blargg_err_t Zip_Extractor::extract_v( void* out, int count ) -{ - if ( tell() == 0 ) - RETURN_ERR( first_read( count ) ); - - int actual = count; - RETURN_ERR( buf.read( out, &actual ) ); - if ( actual < count ) - return blargg_err_file_corrupt; - - crc = ::crc32( crc, (byte const*) out, count ); - if ( count == reader().remain() && crc != correct_crc ) - return blargg_err_file_corrupt; - - return blargg_ok; -} diff --git a/snesreader/fex/Zip_Extractor.h b/snesreader/fex/Zip_Extractor.h deleted file mode 100644 index 9742df99..00000000 --- a/snesreader/fex/Zip_Extractor.h +++ /dev/null @@ -1,45 +0,0 @@ -// ZIP archive extractor. Only supports deflation and store (no compression). - -// File_Extractor 1.0.0 -#ifndef ZIP_EXTRACTOR_H -#define ZIP_EXTRACTOR_H - -#include "File_Extractor.h" -#include "Zlib_Inflater.h" - -class Zip_Extractor : public File_Extractor { -public: - Zip_Extractor(); - virtual ~Zip_Extractor(); - -protected: - virtual blargg_err_t open_path_v(); - virtual blargg_err_t open_v(); - virtual void close_v(); - - virtual void clear_file_v(); - virtual blargg_err_t next_v(); - virtual blargg_err_t rewind_v(); - virtual fex_pos_t tell_arc_v() const; - virtual blargg_err_t seek_arc_v( fex_pos_t ); - - virtual blargg_err_t extract_v( void*, int ); - -private: - blargg_vector catalog; - int catalog_begin; // offset of first catalog entry in file (to detect corruption) - int catalog_pos; // position of current entry in catalog - int raw_remain; // bytes remaining to be read from zip file for current file - unsigned crc; // ongoing CRC of extracted bytes - unsigned correct_crc; - bool file_deflated; - Zlib_Inflater buf; - - blargg_err_t fill_buf( int offset, int buf_size, int initial_read ); - blargg_err_t update_info( bool advance_first ); - blargg_err_t first_read( int count ); - void reorder_entry_header( int offset ); - static blargg_err_t inflater_read( void* data, void* out, int* count ); -}; - -#endif diff --git a/snesreader/fex/Zlib_Inflater.cpp b/snesreader/fex/Zlib_Inflater.cpp deleted file mode 100644 index 8d31b514..00000000 --- a/snesreader/fex/Zlib_Inflater.cpp +++ /dev/null @@ -1,257 +0,0 @@ -// File_Extractor 1.0.0. http://www.slack.net/~ant/ - -#include "Zlib_Inflater.h" - -/* Copyright (C) 2006-2009 Shay Green. This module 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 -module is distributed in the hope that 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 module; if not, write to the Free Software Foundation, -Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -#include "blargg_source.h" - -int const block_size = 4096; - -static const char* get_zlib_err( int code ) -{ - assert( code != Z_OK ); - switch ( code ) - { - case Z_MEM_ERROR: return blargg_err_memory; - case Z_DATA_ERROR: return blargg_err_file_corrupt; - // TODO: handle more error codes - } - - const char* str = zError( code ); - if ( !str ) - str = BLARGG_ERR( BLARGG_ERR_GENERIC, "problem unzipping data" ); - - return str; -} - -void Zlib_Inflater::end() -{ - if ( deflated_ ) - { - deflated_ = false; - if ( inflateEnd( &zbuf ) ) - check( false ); - } - buf.clear(); - - static z_stream const empty = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - memcpy( &zbuf, &empty, sizeof zbuf ); -} - -Zlib_Inflater::Zlib_Inflater() -{ - deflated_ = false; - end(); // initialize things -} - -Zlib_Inflater::~Zlib_Inflater() -{ - end(); -} - -blargg_err_t Zlib_Inflater::fill_buf( int count ) -{ - byte* out = buf.end() - count; - RETURN_ERR( callback( user_data, out, &count ) ); - zbuf.avail_in = count; - zbuf.next_in = out; - return blargg_ok; -} - -blargg_err_t Zlib_Inflater::begin( callback_t new_callback, void* new_user_data, - int new_buf_size, int initial_read ) -{ - callback = new_callback; - user_data = new_user_data; - - end(); - - // TODO: decide whether using different size on alloc failure is a good idea - //RETURN_ERR( buf.resize( new_buf_size ? new_buf_size : 4 * block_size ) ); - if ( new_buf_size && buf.resize( new_buf_size ) ) - { - ACK_FAILURE(); - new_buf_size = 0; - } - - if ( !new_buf_size ) - { - RETURN_ERR( buf.resize( 4 * block_size ) ); - initial_read = 0; - } - - // Fill buffer with some data, less than normal buffer size since caller might - // just be examining beginning of file. - return fill_buf( initial_read ? initial_read : block_size ); -} - -blargg_err_t Zlib_Inflater::set_mode( mode_t mode, int data_offset ) -{ - zbuf.next_in += data_offset; - zbuf.avail_in -= data_offset; - - if ( mode == mode_auto ) - { - // examine buffer for gzip header - mode = mode_copy; - unsigned const min_gzip_size = 2 + 8 + 8; - if ( zbuf.avail_in >= min_gzip_size && - zbuf.next_in [0] == 0x1F && zbuf.next_in [1] == 0x8B ) - mode = mode_ungz; - } - - if ( mode != mode_copy ) - { - int wb = MAX_WBITS + 16; // have zlib handle gzip header - if ( mode == mode_raw_deflate ) - wb = -MAX_WBITS; - - int zerr = inflateInit2( &zbuf, wb ); - if ( zerr ) - { - zbuf.next_in = NULL; - return get_zlib_err( zerr ); - } - - deflated_ = true; - } - return blargg_ok; -} - -/* -// Reads/inflates entire stream. All input must be in buffer, and count must be total -// of all output. -blargg_err_t read_all( void* out, int count ); - - -// zlib automatically applies this optimization (uses inflateFast) -// TODO: remove -blargg_err_t Zlib_Inflater::read_all( void* out, int count ) -{ - if ( deflated_ ) - { - zbuf.next_out = (Bytef*) out; - zbuf.avail_out = count; - - int err = inflate( &zbuf, Z_FINISH ); - - if ( zbuf.avail_out || err != Z_STREAM_END ) - return blargg_err_file_corrupt; - } - else - { - if ( zbuf.avail_in < count ) - return blargg_err_file_corrupt; - - memcpy( out, zbuf.next_in, count ); - - zbuf.next_in += count; - zbuf.avail_in -= count; - } - - return blargg_ok; -} -*/ - -blargg_err_t Zlib_Inflater::read( void* out, int* count_io ) -{ - int remain = *count_io; - if ( remain && zbuf.next_in ) - { - if ( deflated_ ) - { - zbuf.next_out = (Bytef*) out; - zbuf.avail_out = remain; - - while ( 1 ) - { - uInt old_avail_in = zbuf.avail_in; - int err = inflate( &zbuf, Z_NO_FLUSH ); - if ( err == Z_STREAM_END ) - { - remain = zbuf.avail_out; - end(); - break; // no more data to inflate - } - - if ( err && (err != Z_BUF_ERROR || old_avail_in) ) - return get_zlib_err( err ); - - if ( !zbuf.avail_out ) - { - remain = 0; - break; // requested number of bytes inflated - } - - if ( zbuf.avail_in ) - { - // inflate() should never leave input if there's still space for output - check( false ); - return blargg_err_file_corrupt; - } - - RETURN_ERR( fill_buf( buf.size() ) ); - if ( !zbuf.avail_in ) - return blargg_err_file_corrupt; // stream didn't end but there's no more data - } - } - else - { - while ( 1 ) - { - // copy buffered data - if ( zbuf.avail_in ) - { - long count = zbuf.avail_in; - if ( count > remain ) - count = remain; - memcpy( out, zbuf.next_in, count ); - zbuf.total_out += count; - out = (char*) out + count; - remain -= count; - zbuf.next_in += count; - zbuf.avail_in -= count; - } - - if ( !zbuf.avail_in && zbuf.next_in < buf.end() ) - { - end(); - break; - } - - // read large request directly - if ( remain + zbuf.total_out % block_size >= buf.size() ) - { - int count = remain; - RETURN_ERR( callback( user_data, out, &count ) ); - zbuf.total_out += count; - out = (char*) out + count; - remain -= count; - - if ( remain ) - { - end(); - break; - } - } - - if ( !remain ) - break; - - RETURN_ERR( fill_buf( buf.size() - zbuf.total_out % block_size ) ); - } - } - } - *count_io -= remain; - return blargg_ok; -} diff --git a/snesreader/fex/Zlib_Inflater.h b/snesreader/fex/Zlib_Inflater.h deleted file mode 100644 index 8a49ff52..00000000 --- a/snesreader/fex/Zlib_Inflater.h +++ /dev/null @@ -1,70 +0,0 @@ -// Simplifies use of zlib for inflating data - -// File_Extractor 1.0.0 -#ifndef ZLIB_INFLATER_H -#define ZLIB_INFLATER_H - -#include "blargg_common.h" -#include "Data_Reader.h" -#include "zlib/zlib.h" - -class Zlib_Inflater { -public: - - // Reads at most min(*count,bytes_until_eof()) bytes into *out and set *count - // to that number, or returns error if that many can't be read. - typedef blargg_err_t (*callback_t)( void* user_data, void* out, int* count ); - - // Begins by setting callback and filling buffer. Default buffer is 16K and - // filled to 4K, or specify buf_size and initial_read for custom buffer size - // and how much to read initially. - blargg_err_t begin( callback_t, void* user_data, - int buf_size = 0, int initial_read = 0 ); - - // Data read into buffer by begin() - const unsigned char* data() const { return zbuf.next_in; } - int filled() const { return zbuf.avail_in; } - - // Begins inflation using specified mode. Using mode_auto selects between - // mode_copy and mode_ungz by examining first two bytes of buffer. Use - // buf_offset to specify where data begins in buffer, in case there is - // header data that should be skipped. - enum mode_t { mode_copy, mode_ungz, mode_raw_deflate, mode_auto }; - blargg_err_t set_mode( mode_t, int buf_offset = 0 ); - - // True if set_mode() has been called with mode_ungz or mode_raw_deflate - bool deflated() const { return deflated_; } - - // Reads/inflates at most *count_io bytes into *out and sets *count_io to actual - // number of bytes read (less than requested if end of data was reached). - // Buffers source data internally, even in copy mode, so input file can be - // unbuffered without sacrificing performance. - blargg_err_t read( void* out, int* count_io ); - - // Total number of bytes read since begin() - int tell() const { return zbuf.total_out; } - - // Ends inflation and frees memory - void end(); - -private: - // noncopyable - Zlib_Inflater( const Zlib_Inflater& ); - Zlib_Inflater& operator = ( const Zlib_Inflater& ); - -// Implementation -public: - Zlib_Inflater(); - ~Zlib_Inflater(); - -private: - z_stream_s zbuf; - blargg_vector buf; - bool deflated_; - callback_t callback; - void* user_data; - - blargg_err_t fill_buf( int count ); -}; - -#endif diff --git a/snesreader/fex/blargg_common.cpp b/snesreader/fex/blargg_common.cpp deleted file mode 100644 index 9f3e9ebd..00000000 --- a/snesreader/fex/blargg_common.cpp +++ /dev/null @@ -1,51 +0,0 @@ -// File_Extractor 1.0.0. http://www.slack.net/~ant/ - -#include "blargg_common.h" - -/* Copyright (C) 2008-2009 Shay Green. This module 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 -module is distributed in the hope that 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 module; if not, write to the Free Software Foundation, -Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -#include "blargg_source.h" - -void blargg_vector_::init() -{ - begin_ = NULL; - size_ = 0; -} - -void blargg_vector_::clear() -{ - void* p = begin_; - begin_ = NULL; - size_ = 0; - free( p ); -} - -blargg_err_t blargg_vector_::resize_( size_t n, size_t elem_size ) -{ - if ( n != size_ ) - { - if ( n == 0 ) - { - // Simpler to handle explicitly. Realloc will handle a size of 0, - // but then we have to avoid raising an error for a NULL return. - clear(); - } - else - { - void* p = realloc( begin_, n * elem_size ); - CHECK_ALLOC( p ); - begin_ = p; - size_ = n; - } - } - return blargg_ok; -} diff --git a/snesreader/fex/blargg_common.h b/snesreader/fex/blargg_common.h deleted file mode 100644 index a11579fd..00000000 --- a/snesreader/fex/blargg_common.h +++ /dev/null @@ -1,206 +0,0 @@ -// Sets up common environment for Shay Green's libraries. -// To change configuration options, modify blargg_config.h, not this file. - -// File_Extractor 1.0.0 -#ifndef BLARGG_COMMON_H -#define BLARGG_COMMON_H - -#include -#include -#include - -typedef const char* blargg_err_t; // 0 on success, otherwise error string - -// Success; no error -int const blargg_ok = 0; - -// BLARGG_RESTRICT: equivalent to C99's restrict, where supported -#if __GNUC__ >= 3 || _MSC_VER >= 1100 - #define BLARGG_RESTRICT __restrict -#else - #define BLARGG_RESTRICT -#endif - -#if __cplusplus >= 199711 - #define BLARGG_MUTABLE mutable -#else - #define BLARGG_MUTABLE -#endif - -/* BLARGG_4CHAR('a','b','c','d') = 'abcd' (four character integer constant). -I don't just use 'abcd' because that's implementation-dependent. */ -#define BLARGG_4CHAR( a, b, c, d ) \ - ((a&0xFF)*0x1000000 + (b&0xFF)*0x10000 + (c&0xFF)*0x100 + (d&0xFF)) - -/* BLARGG_STATIC_ASSERT( expr ): Generates compile error if expr is 0. -Can be used at file, function, or class scope. */ -#ifdef _MSC_VER - // MSVC6 (_MSC_VER < 1300) __LINE__ fails when /Zl is specified - #define BLARGG_STATIC_ASSERT( expr ) \ - void blargg_failed_( int (*arg) [2 / (int) !!(expr) - 1] ) -#else - // Others fail when declaring same function multiple times in class, - // so differentiate them by line - #define BLARGG_STATIC_ASSERT( expr ) \ - void blargg_failed_( int (*arg) [2 / !!(expr) - 1] [__LINE__] ) -#endif - -/* Pure virtual functions cause a vtable entry to a "called pure virtual" -error handler, requiring linkage to the C++ runtime library. This macro is -used in place of the "= 0", and simply expands to its argument. During -development, it expands to "= 0", allowing detection of missing overrides. */ -#define BLARGG_PURE( def ) def - -/* My code depends on ASCII anywhere a character or string constant is -compared with data read from a file, and anywhere file data is read and -treated as a string. */ -#if '\n'!=0x0A || ' '!=0x20 || '0'!=0x30 || 'A'!=0x41 || 'a'!=0x61 - #error "ASCII character set required" -#endif - -/* My code depends on int being at least 32 bits. Almost everything these days -uses at least 32-bit ints, so it's hard to even find a system with 16-bit ints -to test with. The issue can't be gotten around by using a suitable blargg_int -everywhere either, because int is often converted to implicitly when doing -arithmetic on smaller types. */ -#if UINT_MAX < 0xFFFFFFFF - #error "int must be at least 32 bits" -#endif - -// In case compiler doesn't support these properly. Used rarely. -#define STATIC_CAST(T,expr) static_cast (expr) -#define CONST_CAST( T,expr) const_cast (expr) - -// User configuration can override the above macros if necessary -#include "blargg_config.h" - -/* BLARGG_DEPRECATED [_TEXT] for any declarations/text to be removed in a -future version. In GCC, we can let the compiler warn. In other compilers, -we strip it out unless BLARGG_LEGACY is true. */ -#if BLARGG_LEGACY - // Allow old client code to work without warnings - #define BLARGG_DEPRECATED_TEXT( text ) text - #define BLARGG_DEPRECATED( text ) text -#elif __GNUC__ >= 4 - // In GCC, we can mark declarations and let the compiler warn - #define BLARGG_DEPRECATED_TEXT( text ) text - #define BLARGG_DEPRECATED( text ) __attribute__ ((deprecated)) text -#else - // By default, deprecated items are removed, to avoid use in new code - #define BLARGG_DEPRECATED_TEXT( text ) - #define BLARGG_DEPRECATED( text ) -#endif - -/* BOOST::int8_t, BOOST::int32_t, etc. -I used BOOST since I originally was going to allow use of the boost library -for prividing the definitions. If I'm defining them, they must be scoped or -else they could conflict with the standard ones at global scope. Even if -HAVE_STDINT_H isn't defined, I can't assume the typedefs won't exist at -global scope already. */ -#if defined (HAVE_STDINT_H) || \ - UCHAR_MAX != 0xFF || USHRT_MAX != 0xFFFF || UINT_MAX != 0xFFFFFFFF - #include - #define BOOST -#else - struct BOOST - { - typedef signed char int8_t; - typedef unsigned char uint8_t; - typedef short int16_t; - typedef unsigned short uint16_t; - typedef int int32_t; - typedef unsigned int uint32_t; - }; -#endif - -/* My code is not written with exceptions in mind, so either uses new (nothrow) -OR overrides operator new in my classes. The former is best since clients -creating objects will get standard exceptions on failure, but that causes it -to require the standard C++ library. So, when the client is using the C -interface, I override operator new to use malloc. */ - -// BLARGG_DISABLE_NOTHROW is put inside classes -#ifndef BLARGG_DISABLE_NOTHROW - // throw spec mandatory in ISO C++ if NULL can be returned - #if __cplusplus >= 199711 || __GNUC__ >= 3 || _MSC_VER >= 1300 - #define BLARGG_THROWS_NOTHING throw () - #else - #define BLARGG_THROWS_NOTHING - #endif - - #define BLARGG_DISABLE_NOTHROW \ - void* operator new ( size_t s ) BLARGG_THROWS_NOTHING { return malloc( s ); }\ - void operator delete( void* p ) BLARGG_THROWS_NOTHING { free( p ); } - - #define BLARGG_NEW new -#else - // BLARGG_NEW is used in place of new in library code - #include - #define BLARGG_NEW new (std::nothrow) -#endif - - class blargg_vector_ { - protected: - void* begin_; - size_t size_; - void init(); - blargg_err_t resize_( size_t n, size_t elem_size ); - public: - size_t size() const { return size_; } - void clear(); - }; - -// Very lightweight vector for POD types (no constructor/destructor) -template -class blargg_vector : public blargg_vector_ { - union T_must_be_pod { T t; }; // fails if T is not POD -public: - blargg_vector() { init(); } - ~blargg_vector() { clear(); } - - blargg_err_t resize( size_t n ) { return resize_( n, sizeof (T) ); } - - T* begin() { return static_cast (begin_); } - const T* begin() const { return static_cast (begin_); } - - T* end() { return static_cast (begin_) + size_; } - const T* end() const { return static_cast (begin_) + size_; } - - T& operator [] ( size_t n ) - { - assert( n < size_ ); - return static_cast (begin_) [n]; - } - - const T& operator [] ( size_t n ) const - { - assert( n < size_ ); - return static_cast (begin_) [n]; - } -}; - -// Callback function with user data. -// blargg_callback set_callback; // for user, this acts like... -// void set_callback( T func, void* user_data = NULL ); // ...this -// To call function, do set_callback.f( .. set_callback.data ... ); -template -struct blargg_callback -{ - T f; - void* data; - blargg_callback() { f = NULL; } - void operator () ( T callback, void* user_data = NULL ) { f = callback; data = user_data; } -}; - -#ifndef _WIN32 - // Not supported on any other platforms - #undef BLARGG_UTF8_PATHS -#endif - -BLARGG_DEPRECATED( typedef signed int blargg_long; ) -BLARGG_DEPRECATED( typedef unsigned int blargg_ulong; ) -#if BLARGG_LEGACY - #define BOOST_STATIC_ASSERT BLARGG_STATIC_ASSERT -#endif - -#endif diff --git a/snesreader/fex/blargg_config.h b/snesreader/fex/blargg_config.h deleted file mode 100644 index eb862609..00000000 --- a/snesreader/fex/blargg_config.h +++ /dev/null @@ -1,34 +0,0 @@ -// Library configuration. Modify this file as necessary. - -// File_Extractor 1.0.0 -#ifndef BLARGG_CONFIG_H -#define BLARGG_CONFIG_H - -// Uncomment a #define line below to have effect described. - -// Enable RAR archive support. Doing so adds extra licensing restrictions -// to this library (see unrar/readme.txt for more information). -#define FEX_ENABLE_RAR 1 - -// Accept file paths encoded as UTF-8. Currently only affects Windows, -// as Unix/Linux/Mac OS X already use UTF-8 paths. -#define BLARGG_UTF8_PATHS 1 - -// Enable support for as building DLL on Windows. -//#define BLARGG_BUILD_DLL 1 - -// Support only the listed archive types. Remove any you don't need. -/* -#define FEX_TYPE_LIST \ - fex_7z_type,\ - fex_gz_type,\ - fex_rar_type,\ - fex_zip_type, -*/ - -// Use standard config.h if present -#ifdef HAVE_CONFIG_H - #include "config.h" -#endif - -#endif diff --git a/snesreader/fex/blargg_endian.h b/snesreader/fex/blargg_endian.h deleted file mode 100644 index c32c12f5..00000000 --- a/snesreader/fex/blargg_endian.h +++ /dev/null @@ -1,185 +0,0 @@ -// CPU Byte Order Utilities - -// File_Extractor 1.0.0 -#ifndef BLARGG_ENDIAN_H -#define BLARGG_ENDIAN_H - -#include "blargg_common.h" - -// BLARGG_CPU_CISC: Defined if CPU has very few general-purpose registers (< 16) -#if defined (__i386__) || defined (__x86_64__) || defined (_M_IX86) || defined (_M_X64) - #define BLARGG_CPU_X86 1 - #define BLARGG_CPU_CISC 1 -#endif - -#if defined (__powerpc__) || defined (__ppc__) || defined (__ppc64__) || \ - defined (__POWERPC__) || defined (__powerc) - #define BLARGG_CPU_POWERPC 1 - #define BLARGG_CPU_RISC 1 -#endif - -// BLARGG_BIG_ENDIAN, BLARGG_LITTLE_ENDIAN: Determined automatically, otherwise only -// one may be #defined to 1. Only needed if something actually depends on byte order. -#if !defined (BLARGG_BIG_ENDIAN) && !defined (BLARGG_LITTLE_ENDIAN) -#ifdef __GLIBC__ - // GCC handles this for us - #include - #if __BYTE_ORDER == __LITTLE_ENDIAN - #define BLARGG_LITTLE_ENDIAN 1 - #elif __BYTE_ORDER == __BIG_ENDIAN - #define BLARGG_BIG_ENDIAN 1 - #endif -#else - -#if defined (LSB_FIRST) || defined (__LITTLE_ENDIAN__) || BLARGG_CPU_X86 || \ - (defined (LITTLE_ENDIAN) && LITTLE_ENDIAN+0 != 1234) - #define BLARGG_LITTLE_ENDIAN 1 -#endif - -#if defined (MSB_FIRST) || defined (__BIG_ENDIAN__) || defined (WORDS_BIGENDIAN) || \ - defined (__sparc__) || BLARGG_CPU_POWERPC || \ - (defined (BIG_ENDIAN) && BIG_ENDIAN+0 != 4321) - #define BLARGG_BIG_ENDIAN 1 -#elif !defined (__mips__) - // No endian specified; assume little-endian, since it's most common - #define BLARGG_LITTLE_ENDIAN 1 -#endif -#endif -#endif - -#if BLARGG_LITTLE_ENDIAN && BLARGG_BIG_ENDIAN - #undef BLARGG_LITTLE_ENDIAN - #undef BLARGG_BIG_ENDIAN -#endif - -inline void blargg_verify_byte_order() -{ - #ifndef NDEBUG - #if BLARGG_BIG_ENDIAN - volatile int i = 1; - assert( *(volatile char*) &i == 0 ); - #elif BLARGG_LITTLE_ENDIAN - volatile int i = 1; - assert( *(volatile char*) &i != 0 ); - #endif - #endif -} - -inline unsigned get_le16( void const* p ) -{ - return (unsigned) ((unsigned char const*) p) [1] << 8 | - (unsigned) ((unsigned char const*) p) [0]; -} - -inline unsigned get_be16( void const* p ) -{ - return (unsigned) ((unsigned char const*) p) [0] << 8 | - (unsigned) ((unsigned char const*) p) [1]; -} - -inline unsigned get_le32( void const* p ) -{ - return (unsigned) ((unsigned char const*) p) [3] << 24 | - (unsigned) ((unsigned char const*) p) [2] << 16 | - (unsigned) ((unsigned char const*) p) [1] << 8 | - (unsigned) ((unsigned char const*) p) [0]; -} - -inline unsigned get_be32( void const* p ) -{ - return (unsigned) ((unsigned char const*) p) [0] << 24 | - (unsigned) ((unsigned char const*) p) [1] << 16 | - (unsigned) ((unsigned char const*) p) [2] << 8 | - (unsigned) ((unsigned char const*) p) [3]; -} - -inline void set_le16( void* p, unsigned n ) -{ - ((unsigned char*) p) [1] = (unsigned char) (n >> 8); - ((unsigned char*) p) [0] = (unsigned char) n; -} - -inline void set_be16( void* p, unsigned n ) -{ - ((unsigned char*) p) [0] = (unsigned char) (n >> 8); - ((unsigned char*) p) [1] = (unsigned char) n; -} - -inline void set_le32( void* p, unsigned n ) -{ - ((unsigned char*) p) [0] = (unsigned char) n; - ((unsigned char*) p) [1] = (unsigned char) (n >> 8); - ((unsigned char*) p) [2] = (unsigned char) (n >> 16); - ((unsigned char*) p) [3] = (unsigned char) (n >> 24); -} - -inline void set_be32( void* p, unsigned n ) -{ - ((unsigned char*) p) [3] = (unsigned char) n; - ((unsigned char*) p) [2] = (unsigned char) (n >> 8); - ((unsigned char*) p) [1] = (unsigned char) (n >> 16); - ((unsigned char*) p) [0] = (unsigned char) (n >> 24); -} - -#if BLARGG_NONPORTABLE - // Optimized implementation if byte order is known - #if BLARGG_LITTLE_ENDIAN - #define GET_LE16( addr ) (*(BOOST::uint16_t const*) (addr)) - #define GET_LE32( addr ) (*(BOOST::uint32_t const*) (addr)) - #define SET_LE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data)) - #define SET_LE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data)) - #elif BLARGG_BIG_ENDIAN - #define GET_BE16( addr ) (*(BOOST::uint16_t const*) (addr)) - #define GET_BE32( addr ) (*(BOOST::uint32_t const*) (addr)) - #define SET_BE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data)) - #define SET_BE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data)) - - #if BLARGG_CPU_POWERPC - // PowerPC has special byte-reversed instructions - #if defined (__MWERKS__) - #define GET_LE16( addr ) (__lhbrx( addr, 0 )) - #define GET_LE32( addr ) (__lwbrx( addr, 0 )) - #define SET_LE16( addr, in ) (__sthbrx( in, addr, 0 )) - #define SET_LE32( addr, in ) (__stwbrx( in, addr, 0 )) - #elif defined (__GNUC__) - #define GET_LE16( addr ) ({unsigned short ppc_lhbrx_; __asm__ volatile( "lhbrx %0,0,%1" : "=r" (ppc_lhbrx_) : "r" (addr) : "memory" ); ppc_lhbrx_;}) - #define GET_LE32( addr ) ({unsigned short ppc_lwbrx_; __asm__ volatile( "lwbrx %0,0,%1" : "=r" (ppc_lwbrx_) : "r" (addr) : "memory" ); ppc_lwbrx_;}) - #define SET_LE16( addr, in ) ({__asm__ volatile( "sthbrx %0,0,%1" : : "r" (in), "r" (addr) : "memory" );}) - #define SET_LE32( addr, in ) ({__asm__ volatile( "stwbrx %0,0,%1" : : "r" (in), "r" (addr) : "memory" );}) - #endif - #endif - #endif -#endif - -#ifndef GET_LE16 - #define GET_LE16( addr ) get_le16( addr ) - #define SET_LE16( addr, data ) set_le16( addr, data ) -#endif - -#ifndef GET_LE32 - #define GET_LE32( addr ) get_le32( addr ) - #define SET_LE32( addr, data ) set_le32( addr, data ) -#endif - -#ifndef GET_BE16 - #define GET_BE16( addr ) get_be16( addr ) - #define SET_BE16( addr, data ) set_be16( addr, data ) -#endif - -#ifndef GET_BE32 - #define GET_BE32( addr ) get_be32( addr ) - #define SET_BE32( addr, data ) set_be32( addr, data ) -#endif - -// auto-selecting versions - -inline void set_le( BOOST::uint16_t* p, unsigned n ) { SET_LE16( p, n ); } -inline void set_le( BOOST::uint32_t* p, unsigned n ) { SET_LE32( p, n ); } -inline void set_be( BOOST::uint16_t* p, unsigned n ) { SET_BE16( p, n ); } -inline void set_be( BOOST::uint32_t* p, unsigned n ) { SET_BE32( p, n ); } -inline unsigned get_le( BOOST::uint16_t const* p ) { return GET_LE16( p ); } -inline unsigned get_le( BOOST::uint32_t const* p ) { return GET_LE32( p ); } -inline unsigned get_be( BOOST::uint16_t const* p ) { return GET_BE16( p ); } -inline unsigned get_be( BOOST::uint32_t const* p ) { return GET_BE32( p ); } - -#endif diff --git a/snesreader/fex/blargg_errors.cpp b/snesreader/fex/blargg_errors.cpp deleted file mode 100644 index 14076cdb..00000000 --- a/snesreader/fex/blargg_errors.cpp +++ /dev/null @@ -1,113 +0,0 @@ -// File_Extractor 1.0.0. http://www.slack.net/~ant/ - -#include "blargg_errors.h" - -/* Copyright (C) 2009 Shay Green. This module 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 -module is distributed in the hope that 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 module; if not, write to the Free Software Foundation, -Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -#include "blargg_source.h" - -blargg_err_def_t blargg_err_generic = BLARGG_ERR_GENERIC; -blargg_err_def_t blargg_err_memory = BLARGG_ERR_MEMORY; -blargg_err_def_t blargg_err_caller = BLARGG_ERR_CALLER; -blargg_err_def_t blargg_err_internal = BLARGG_ERR_INTERNAL; -blargg_err_def_t blargg_err_limitation = BLARGG_ERR_LIMITATION; - -blargg_err_def_t blargg_err_file_missing = BLARGG_ERR_FILE_MISSING; -blargg_err_def_t blargg_err_file_read = BLARGG_ERR_FILE_READ; -blargg_err_def_t blargg_err_file_write = BLARGG_ERR_FILE_WRITE; -blargg_err_def_t blargg_err_file_io = BLARGG_ERR_FILE_IO; -blargg_err_def_t blargg_err_file_full = BLARGG_ERR_FILE_FULL; -blargg_err_def_t blargg_err_file_eof = BLARGG_ERR_FILE_EOF; - -blargg_err_def_t blargg_err_file_type = BLARGG_ERR_FILE_TYPE; -blargg_err_def_t blargg_err_file_feature = BLARGG_ERR_FILE_FEATURE; -blargg_err_def_t blargg_err_file_corrupt = BLARGG_ERR_FILE_CORRUPT; - -const char* blargg_err_str( blargg_err_t err ) -{ - if ( !err ) - return ""; - - if ( *err == BLARGG_ERR_TYPE("")[0] ) - return err + 1; - - return err; -} - -bool blargg_is_err_type( blargg_err_t err, const char type [] ) -{ - if ( err ) - { - // True if first strlen(type) characters of err match type - char const* p = err; - while ( *type && *type == *p ) - { - type++; - p++; - } - - if ( !*type ) - return true; - } - - return false; -} - -const char* blargg_err_details( blargg_err_t err ) -{ - const char* p = err; - if ( !p ) - { - p = ""; - } - else if ( *p == BLARGG_ERR_TYPE("")[0] ) - { - while ( *p && *p != ';' ) - p++; - - // Skip ; and space after it - if ( *p ) - { - p++; - - check( *p == ' ' ); - if ( *p ) - p++; - } - } - return p; -} - -int blargg_err_to_code( blargg_err_t err, blargg_err_to_code_t const codes [] ) -{ - if ( !err ) - return 0; - - while ( codes->str && !blargg_is_err_type( err, codes->str ) ) - codes++; - - return codes->code; -} - -blargg_err_t blargg_code_to_err( int code, blargg_err_to_code_t const codes [] ) -{ - if ( !code ) - return blargg_ok; - - while ( codes->str && codes->code != code ) - codes++; - - if ( !codes->str ) - return blargg_err_generic; - - return codes->str; -} diff --git a/snesreader/fex/blargg_errors.h b/snesreader/fex/blargg_errors.h deleted file mode 100644 index 9c5206d5..00000000 --- a/snesreader/fex/blargg_errors.h +++ /dev/null @@ -1,80 +0,0 @@ -// Error strings and conversion functions - -// File_Extractor 1.0.0 -#ifndef BLARGG_ERRORS_H -#define BLARGG_ERRORS_H - -#ifndef BLARGG_COMMON_H - #include "blargg_common.h" -#endif - -typedef const char blargg_err_def_t []; - -// Basic errors -extern blargg_err_def_t blargg_err_generic; -extern blargg_err_def_t blargg_err_memory; -extern blargg_err_def_t blargg_err_caller; -extern blargg_err_def_t blargg_err_internal; -extern blargg_err_def_t blargg_err_limitation; - -// File low-level -extern blargg_err_def_t blargg_err_file_missing; // not found -extern blargg_err_def_t blargg_err_file_read; -extern blargg_err_def_t blargg_err_file_write; -extern blargg_err_def_t blargg_err_file_io; -extern blargg_err_def_t blargg_err_file_full; -extern blargg_err_def_t blargg_err_file_eof; - -// File high-level -extern blargg_err_def_t blargg_err_file_type; // wrong file type -extern blargg_err_def_t blargg_err_file_feature; -extern blargg_err_def_t blargg_err_file_corrupt; - -// C string describing error, or "" if err == NULL -const char* blargg_err_str( blargg_err_t err ); - -// True iff error is of given type, or false if err == NULL -bool blargg_is_err_type( blargg_err_t, const char type [] ); - -// Details of error without describing main cause, or "" if err == NULL -const char* blargg_err_details( blargg_err_t err ); - -// Converts error string to integer code using mapping table. Calls blargg_is_err_type() -// for each str and returns code on first match. Returns 0 if err == NULL. -struct blargg_err_to_code_t { - const char* str; - int code; -}; -int blargg_err_to_code( blargg_err_t err, blargg_err_to_code_t const [] ); - -// Converts error code back to string. If code == 0, returns NULL. If not in table, -// returns blargg_err_generic. -blargg_err_t blargg_code_to_err( int code, blargg_err_to_code_t const [] ); - -// Generates error string literal with details of cause -#define BLARGG_ERR( type, str ) (type "; " str) - -// Extra space to make it clear when blargg_err_str() isn't called to get -// printable version of error. At some point, I might prefix error strings -// with a code, to speed conversion to a code. -#define BLARGG_ERR_TYPE( str ) " " str - -// Error types to pass to BLARGG_ERR macro -#define BLARGG_ERR_GENERIC BLARGG_ERR_TYPE( "operation failed" ) -#define BLARGG_ERR_MEMORY BLARGG_ERR_TYPE( "out of memory" ) -#define BLARGG_ERR_CALLER BLARGG_ERR_TYPE( "internal usage bug" ) -#define BLARGG_ERR_INTERNAL BLARGG_ERR_TYPE( "internal bug" ) -#define BLARGG_ERR_LIMITATION BLARGG_ERR_TYPE( "exceeded limitation" ) - -#define BLARGG_ERR_FILE_MISSING BLARGG_ERR_TYPE( "file not found" ) -#define BLARGG_ERR_FILE_READ BLARGG_ERR_TYPE( "couldn't open file" ) -#define BLARGG_ERR_FILE_WRITE BLARGG_ERR_TYPE( "couldn't modify file" ) -#define BLARGG_ERR_FILE_IO BLARGG_ERR_TYPE( "read/write error" ) -#define BLARGG_ERR_FILE_FULL BLARGG_ERR_TYPE( "disk full" ) -#define BLARGG_ERR_FILE_EOF BLARGG_ERR_TYPE( "truncated file" ) - -#define BLARGG_ERR_FILE_TYPE BLARGG_ERR_TYPE( "wrong file type" ) -#define BLARGG_ERR_FILE_FEATURE BLARGG_ERR_TYPE( "unsupported file feature" ) -#define BLARGG_ERR_FILE_CORRUPT BLARGG_ERR_TYPE( "corrupt file" ) - -#endif diff --git a/snesreader/fex/blargg_source.h b/snesreader/fex/blargg_source.h deleted file mode 100644 index 659f34c5..00000000 --- a/snesreader/fex/blargg_source.h +++ /dev/null @@ -1,125 +0,0 @@ -/* Included at the beginning of library source files, AFTER all other #include -lines. Sets up helpful macros and services used in my source code. Since this -is only "active" in my source code, I don't have to worry about polluting the -global namespace with unprefixed names. */ - -// File_Extractor 1.0.0 -#ifndef BLARGG_SOURCE_H -#define BLARGG_SOURCE_H - -#ifndef BLARGG_COMMON_H // optimization only - #include "blargg_common.h" -#endif -#include "blargg_errors.h" - -#include /* memcpy(), memset(), memmove() */ -#include /* offsetof() */ - -/* The following four macros are for debugging only. Some or all might be -defined to do nothing, depending on the circumstances. Described is what -happens when a particular macro is defined to do something. When defined to -do nothing, the macros do NOT evaluate their argument(s). */ - -/* If expr is false, prints file and line number, then aborts program. Meant -for checking internal state and consistency. A failed assertion indicates a bug -in MY code. - -void assert( bool expr ); */ -#include - -/* If expr is false, prints file and line number, then aborts program. Meant -for checking caller-supplied parameters and operations that are outside the -control of the module. A failed requirement probably indicates a bug in YOUR -code. - -void require( bool expr ); */ -#undef require -#define require( expr ) assert( expr ) - -/* Like printf() except output goes to debugging console/file. - -void dprintf( const char format [], ... ); */ -static inline void blargg_dprintf_( const char [], ... ) { } -#undef dprintf -#define dprintf (1) ? (void) 0 : blargg_dprintf_ - -/* If expr is false, prints file and line number to debug console/log, then -continues execution normally. Meant for flagging potential problems or things -that should be looked into, but that aren't serious problems. - -void check( bool expr ); */ -#undef check -#define check( expr ) ((void) 0) - -/* If expr yields non-NULL error string, returns it from current function, -otherwise continues normally. */ -#undef RETURN_ERR -#define RETURN_ERR( expr ) \ - do {\ - blargg_err_t blargg_return_err_ = (expr);\ - if ( blargg_return_err_ )\ - return blargg_return_err_;\ - } while ( 0 ) - -/* If ptr is NULL, returns out-of-memory error, otherwise continues normally. */ -#undef CHECK_ALLOC -#define CHECK_ALLOC( ptr ) \ - do {\ - if ( !(ptr) )\ - return blargg_err_memory;\ - } while ( 0 ) - -/* The usual min/max functions for built-in types. - -template T min( T x, T y ) { return x < y ? x : y; } -template T max( T x, T y ) { return x > y ? x : y; } */ -#define BLARGG_DEF_MIN_MAX( type ) \ - static inline type blargg_min( type x, type y ) { if ( y < x ) x = y; return x; }\ - static inline type blargg_max( type x, type y ) { if ( x < y ) x = y; return x; } - -BLARGG_DEF_MIN_MAX( int ) -BLARGG_DEF_MIN_MAX( unsigned ) -BLARGG_DEF_MIN_MAX( long ) -BLARGG_DEF_MIN_MAX( unsigned long ) -BLARGG_DEF_MIN_MAX( float ) -BLARGG_DEF_MIN_MAX( double ) - -#undef min -#define min blargg_min - -#undef max -#define max blargg_max - -// typedef unsigned char byte; -typedef unsigned char blargg_byte; -#undef byte -#define byte blargg_byte - -#ifndef BLARGG_EXPORT - #if defined (_WIN32) && BLARGG_BUILD_DLL - #define BLARGG_EXPORT __declspec(dllexport) - #elif defined (__GNUC__) - // can always set visibility, even when not building DLL - #define BLARGG_EXPORT __attribute__ ((visibility ("default"))) - #else - #define BLARGG_EXPORT - #endif -#endif - -#if BLARGG_LEGACY - #define BLARGG_CHECK_ALLOC CHECK_ALLOC - #define BLARGG_RETURN_ERR RETURN_ERR -#endif - -// Called after failed operation when overall operation may still complete OK. -// Only used by unit testing framework. -#undef ACK_FAILURE -#define ACK_FAILURE() ((void)0) - -/* BLARGG_SOURCE_BEGIN: If defined, #included, allowing redefition of dprintf etc. -and check */ -#ifdef BLARGG_SOURCE_BEGIN - #include BLARGG_SOURCE_BEGIN -#endif - -#endif diff --git a/snesreader/fex/fex.cpp b/snesreader/fex/fex.cpp deleted file mode 100644 index d0946dd9..00000000 --- a/snesreader/fex/fex.cpp +++ /dev/null @@ -1,323 +0,0 @@ -// File_Extractor 1.0.0. http://www.slack.net/~ant/ - -#include "fex.h" - -#include "File_Extractor.h" -#include "blargg_endian.h" -#include -#include - -/* Copyright (C) 2005-2009 Shay Green. This module 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 -module is distributed in the hope that 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 module; if not, write to the Free Software Foundation, -Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ - -#include "blargg_source.h" - - -//// Types - -BLARGG_EXPORT const fex_type_t* fex_type_list( void ) -{ - static fex_type_t const fex_type_list_ [] = - { - #ifdef FEX_TYPE_LIST - FEX_TYPE_LIST - #else - // Modify blargg_config.h to change type list, NOT this file - fex_7z_type, - fex_gz_type, - #if FEX_ENABLE_RAR - fex_rar_type, - #endif - fex_zip_type, - #endif - fex_bin_type, - NULL - }; - - return fex_type_list_; -} - -BLARGG_EXPORT fex_err_t fex_init( void ) -{ - static bool inited; - if ( !inited ) - { - for ( fex_type_t const* t = fex_type_list(); *t != NULL; ++t ) - { - if ( (*t)->init ) - RETURN_ERR( (*t)->init() ); - } - inited = true; - } - return blargg_ok; -} - -BLARGG_EXPORT const char* fex_identify_header( void const* header ) -{ - unsigned four = get_be32( header ); - switch ( four ) - { - case 0x52457E5E: - case 0x52617221: return ".rar"; - - case 0x377ABCAF: return ".7z"; - - case 0x504B0304: - case 0x504B0506: return ".zip"; - - case 0x53495421: return ".sit"; - case 0x41724301: return ".arc"; - case 0x4D534346: return ".cab"; - case 0x5A4F4F20: return ".zoo"; - } - - unsigned three = four >> 8; - switch ( three ) - { - case 0x425A68: return ".bz2"; - } - - unsigned two = four >> 16; - switch ( two ) - { - case 0x1F8B: return ".gz"; - case 0x60EA: return ".arj"; - } - - unsigned skip_first_two = four & 0xFFFF; - if ( skip_first_two == 0x2D6C ) - return ".lha"; - - return ""; -} - -static int fex_has_extension_( const char str [], const char suffix [], size_t str_len ) -{ - size_t suffix_len = strlen( suffix ); - if ( str_len >= suffix_len ) - { - str += str_len - suffix_len; - while ( *str && tolower( (unsigned char) *str ) == *suffix ) - { - str++; - suffix++; - } - } - return *suffix == 0; -} - -BLARGG_EXPORT int fex_has_extension( const char str [], const char suffix [] ) -{ - return fex_has_extension_( str, suffix, strlen( str ) ); -} - -static int is_archive_extension( const char str [] ) -{ - static const char exts [] [6] = { - ".7z", - ".arc", - ".arj", - ".bz2", - ".cab", - ".dmg", - ".gz", - ".lha", - ".lz", - ".lzh", - ".lzma", - ".lzo", - ".lzx", - ".pea", - ".rar", - ".sit", - ".sitx", - ".tgz", - ".tlz", - ".z", - ".zip", - ".zoo", - "" - }; - - size_t str_len = strlen( str ); - const char (*ext) [6] = exts; - for ( ; **ext; ext++ ) - { - if ( fex_has_extension_( str, *ext, str_len ) ) - return 1; - } - return 0; -} - -BLARGG_EXPORT fex_type_t fex_identify_extension( const char str [] ) -{ - size_t str_len = strlen( str ); - for ( fex_type_t const* types = fex_type_list(); *types; types++ ) - { - if ( fex_has_extension_( str, (*types)->extension, str_len ) ) - { - // Avoid treating known archive type as binary - if ( *(*types)->extension || !is_archive_extension( str ) ) - return *types; - } - } - return NULL; -} - -BLARGG_EXPORT fex_err_t fex_identify_file( fex_type_t* type_out, const char path [] ) -{ - *type_out = NULL; - - fex_type_t type = fex_identify_extension( path ); - - // Unsupported extension? - if ( !type ) - return blargg_ok; // reject - - // Unknown/no extension? - if ( !*(type->extension) ) - { - // Examine header - FEX_FILE_READER in; - RETURN_ERR( in.open( path ) ); - if ( in.remain() >= fex_identify_header_size ) - { - char h [fex_identify_header_size]; - RETURN_ERR( in.read( h, sizeof h ) ); - - type = fex_identify_extension( fex_identify_header( h ) ); - } - } - - *type_out = type; - return blargg_ok; -} - -BLARGG_EXPORT fex_err_t fex_open_type( fex_t** fe_out, const char path [], fex_type_t type ) -{ - *fe_out = NULL; - - if ( !type ) - return blargg_err_file_type; - - fex_t* fe = type->new_fex(); - CHECK_ALLOC( fe ); - - fex_err_t err = fe->open( path ); - if ( err ) - { - delete fe; - return err; - } - - *fe_out = fe; - return blargg_ok; -} - -BLARGG_EXPORT fex_err_t fex_open( fex_t** fe_out, const char path [] ) -{ - *fe_out = NULL; - - fex_type_t type; - RETURN_ERR( fex_identify_file( &type, path ) ); - - return fex_open_type( fe_out, path, type ); -} - - -//// Wide paths - -#if BLARGG_UTF8_PATHS -char* fex_wide_to_path( const wchar_t* wide ) -{ - return blargg_to_utf8( wide ); -} - -void fex_free_path( char* path ) -{ - free( path ); -} -#endif - - -//// Errors - -#define ENTRY( name ) { blargg_err_##name, fex_err_##name } -static blargg_err_to_code_t const fex_codes [] = -{ - ENTRY( generic ), - ENTRY( memory ), - ENTRY( caller ), - ENTRY( internal ), - ENTRY( limitation ), - - ENTRY( file_missing ), - ENTRY( file_read ), - ENTRY( file_io ), - ENTRY( file_eof ), - - ENTRY( file_type ), - ENTRY( file_feature ), - ENTRY( file_corrupt ), - - { 0, -1 } -}; -#undef ENTRY - -static int err_code( fex_err_t err ) -{ - return blargg_err_to_code( err, fex_codes ); -} - -BLARGG_EXPORT int fex_err_code( fex_err_t err ) -{ - int code = err_code( err ); - return (code >= 0 ? code : fex_err_generic); -} - -BLARGG_EXPORT fex_err_t fex_code_to_err( int code ) -{ - return blargg_code_to_err( code, fex_codes ); -} - -BLARGG_EXPORT const char* fex_err_details( fex_err_t err ) -{ - // If we don't have error code assigned, return entire string - return (err_code( err ) >= 0 ? blargg_err_details( err ) : blargg_err_str( err )); -} - - -//// Wrappers - -BLARGG_EXPORT fex_err_t fex_read( fex_t* fe, void* out, int count ) -{ - RETURN_ERR( fe->stat() ); - return fe->reader().read( out, count ); -} - -BLARGG_EXPORT void fex_close ( fex_t* fe ) { delete fe; } -BLARGG_EXPORT fex_type_t fex_type ( const fex_t* fe ) { return fe->type(); } -BLARGG_EXPORT int fex_done ( const fex_t* fe ) { return fe->done(); } -BLARGG_EXPORT const char* fex_name ( const fex_t* fe ) { return fe->name(); } -BLARGG_EXPORT const wchar_t* fex_wname ( const fex_t* fe ) { return fe->wname(); } -BLARGG_EXPORT int fex_size ( const fex_t* fe ) { return fe->size(); } -BLARGG_EXPORT unsigned fex_dos_date ( const fex_t* fe ) { return fe->dos_date(); } -BLARGG_EXPORT unsigned fex_crc32 ( const fex_t* fe ) { return fe->crc32(); } -BLARGG_EXPORT fex_err_t fex_stat ( fex_t* fe ) { return fe->stat(); } -BLARGG_EXPORT fex_err_t fex_next ( fex_t* fe ) { return fe->next(); } -BLARGG_EXPORT fex_err_t fex_rewind ( fex_t* fe ) { return fe->rewind(); } -BLARGG_EXPORT int fex_tell ( const fex_t* fe ) { return fe->tell(); } -BLARGG_EXPORT fex_pos_t fex_tell_arc ( const fex_t* fe ) { return fe->tell_arc(); } -BLARGG_EXPORT fex_err_t fex_seek_arc ( fex_t* fe, fex_pos_t pos ) { return fe->seek_arc( pos ); } -BLARGG_EXPORT const char* fex_type_extension ( fex_type_t t ) { return t->extension; } -BLARGG_EXPORT const char* fex_type_name ( fex_type_t t ) { return t->name; } -BLARGG_EXPORT fex_err_t fex_data ( fex_t* fe, const void** data_out ) { return fe->data( data_out ); } -BLARGG_EXPORT const char* fex_err_str ( fex_err_t err ) { return blargg_err_str( err ); } diff --git a/snesreader/fex/fex.h b/snesreader/fex/fex.h deleted file mode 100644 index f9452771..00000000 --- a/snesreader/fex/fex.h +++ /dev/null @@ -1,206 +0,0 @@ -/** Uniform access to zip, gzip, 7-zip, and RAR compressed archives \file */ - -/* File_Extractor 1.0.0 */ -#ifndef FEX_H -#define FEX_H - -#include - -#ifdef __cplusplus - extern "C" { -#endif - - -/** First parameter of most functions is fex_t*, or const fex_t* if nothing is -changed. Once one of these functions returns an error, the archive should not -be used any further, other than to close it. One exception is -fex_error_file_eof; the archive may still be used after this. */ -typedef struct fex_t fex_t; - -/** Pointer to error, or NULL if function was successful. See error functions -below. */ -#ifndef fex_err_t /* (#ifndef allows better testing of library) */ - typedef const char* fex_err_t; -#endif - - -/**** File types ****/ - -/** Archive file type identifier. Can also hold NULL. */ -typedef const struct fex_type_t_* fex_type_t; - -/** Array of supported types, with NULL at end */ -const fex_type_t* fex_type_list( void ); - -/** Name of this archive type, e.g. "ZIP archive", "file" */ -const char* fex_type_name( fex_type_t ); - -/** Usual file extension for type, e.g. ".zip", ".7z". For binary file type, -returns "", since it can open any file. */ -const char* fex_type_extension( fex_type_t ); - - -/**** Wide-character file paths (Windows only) ****/ - -/** Converts wide-character path to form suitable for use with fex functions. -Only supported when BLARGG_UTF8_PATHS is defined and building on Windows. */ -char* fex_wide_to_path( const wchar_t* wide ); - -/** Frees converted path. OK to pass NULL. Only supported when BLARGG_UTF8_PATHS -is defined and building on Windows */ -void fex_free_path( char* ); - - -/**** Identification ****/ - -/** True if str ends in extension. If extension is "", always returns true. -Converts str to lowercase before comparison, so extension should ALREADY be -lowercase (i.e. pass ".zip", NOT ".ZIP"). */ -int fex_has_extension( const char str [], const char extension [] ); - -/** Determines type based on first fex_identify_header_size bytes of file. -Returns usual file extension this should have (e.g. ".zip", ".gz", etc.). -Returns "" if file header is not recognized. */ -const char* fex_identify_header( const void* header ); -enum { fex_identify_header_size = 16 }; - -/** Determines type based on extension of a file path, or just a lone extension -(must include '.', e.g. ".zip", NOT just "zip"). Returns NULL if extension is -for an unsupported type (e.g. ".lzh"). */ -fex_type_t fex_identify_extension( const char path_or_extension [] ); - -/** Determines type based on filename extension and/or file header. Sets *out -to determined type, or NULL if type is not supported. */ -fex_err_t fex_identify_file( fex_type_t* out, const char path [] ); - -/** Type of an already-opened archive */ -fex_type_t fex_type( const fex_t* ); - - -/**** Open/close ****/ - -/** Initializes static tables used by library. Automatically called by -fex_open(). OK to call more than once. */ -fex_err_t fex_init( void ); - -/** Opens archive and points *out at it. If error, sets *out to NULL. */ -fex_err_t fex_open( fex_t** out, const char path [] ); - -/** Opens archive of specified type and sets *out. Returns error if file is not -of that archive type. If error, sets *out to NULL. */ -fex_err_t fex_open_type( fex_t** out, const char path [], fex_type_t ); - -/** Closes archive and frees memory. OK to pass NULL. */ -void fex_close( fex_t* ); - - -/**** Scanning ****/ - -/** True if at end of archive. Must be called after fex_open() or fex_rewind(), -as an archive might contain no files. */ -int fex_done( const fex_t* ); - -/** Goes to next file in archive. If there are no more files, fex_done() will -now return true. */ -fex_err_t fex_next( fex_t* ); - -/** Goes back to first file in archive, as if it were just opened with -fex_open() */ -fex_err_t fex_rewind( fex_t* ); - -/** Saved position in archive. Can also store zero. */ -typedef int fex_pos_t; - -/** Position of current file in archive. Never returns zero. */ -fex_pos_t fex_tell_arc( const fex_t* ); - -/** Returns to file at previously-saved position */ -fex_err_t fex_seek_arc( fex_t*, fex_pos_t ); - - -/**** Info ****/ - -/** Name of current file */ -const char* fex_name( const fex_t* ); - -/** Wide-character name of current file, or NULL if unavailable */ -const wchar_t* fex_wname( const fex_t* ); - -/** Makes further information available for file */ -fex_err_t fex_stat( fex_t* ); - -/** Size of current file. fex_stat() or fex_data() must have been called. */ -int fex_size( const fex_t* ); - -/** Modification date of current file (MS-DOS format), or 0 if unavailable. -fex_stat() must have been called. */ -unsigned int fex_dos_date( const fex_t* ); - -/** CRC-32 checksum of current file's contents, or 0 if unavailable. Doesn't -require calculation; simply gets it from file's header. fex_stat() must have -been called. */ -unsigned int fex_crc32( const fex_t* ); - - -/**** Extraction ****/ - -/** Reads n bytes from current file. Reading past end of file results in -fex_err_file_eof. */ -fex_err_t fex_read( fex_t*, void* out, int n ); - -/** Number of bytes read from current file */ -int fex_tell( const fex_t* ); - -/** Points *out at current file's data in memory. Pointer is valid until -fex_next(), fex_rewind(), fex_seek_arc(), or fex_close() is called. Pointer -must NOT be freed(); library frees it automatically. If error, sets *out to -NULL. */ -fex_err_t fex_data( fex_t*, const void** out ); - - -/**** Errors ****/ - -/** Error string associated with err. Returns "" if err is NULL. Returns err -unchanged if it isn't a fex_err_t returned by library. */ -const char* fex_err_str( fex_err_t err ); - -/** Details of error beyond main cause, or "" if none or err is NULL. Returns -err unchanged if it isn't a fex_err_t returned by library. */ -const char* fex_err_details( fex_err_t err ); - -/** Numeric code corresponding to err. Returns fex_ok if err is NULL. Returns -fex_err_generic if err isn't a fex_err_t returned by library. */ -int fex_err_code( fex_err_t err ); - -enum { - fex_ok = 0,/**< Successful call. Guaranteed to be zero. */ - fex_err_generic = 0x01,/**< Error of unspecified type */ - fex_err_memory = 0x02,/**< Out of memory */ - fex_err_caller = 0x03,/**< Caller called function with bad args */ - fex_err_internal = 0x04,/**< Internal problem, bug, etc. */ - fex_err_limitation = 0x05,/**< Exceeded program limit */ - - fex_err_file_missing = 0x20,/**< File not found at specified path */ - fex_err_file_read = 0x21,/**< Couldn't open file for reading */ - fex_err_file_io = 0x23,/**< Read/write error */ - fex_err_file_eof = 0x25,/**< Tried to read past end of file */ - - fex_err_file_type = 0x30,/**< File is of wrong type */ - fex_err_file_feature = 0x32,/**< File requires unsupported feature */ - fex_err_file_corrupt = 0x33 /**< File is corrupt */ -}; - -/** fex_err_t corresponding to numeric code. Note that this might not recover -the original fex_err_t before it was converted to a numeric code; in -particular, fex_err_details(fex_code_to_err(code)) will be "" in most cases. */ -fex_err_t fex_code_to_err( int code ); - - -/* Deprecated */ -typedef fex_t File_Extractor; - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/snesreader/filechooser.cpp b/snesreader/filechooser.cpp deleted file mode 100644 index e1f9d8b0..00000000 --- a/snesreader/filechooser.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include "filechooser.moc.hpp" -#include "filechooser.moc" - -//FileChooser is implemented as a modal QWidget instead of a QDialog -//due to a bug in Qt 4.6.0 (QTBUG-7188); which causes the FileChooser -//to not refresh when a QTimer is active from the main application. -string FileChooser::exec() { - if(list.size() == 0) return ""; - if(list.size() == 1) return list[0]; - - listWidget->clear(); - for(unsigned i = 0; i < list.size(); i++) { - listWidget->addItem(list[i]); - } - listWidget->sortItems(Qt::AscendingOrder); - listWidget->setCurrentRow(0); - listWidget->setFocus(); - - name = ""; - setWindowModality(Qt::ApplicationModal); - show(); - while(isVisible()) QApplication::processEvents(); - setWindowModality(Qt::NonModal); - return name; -} - -void FileChooser::load() { - QListWidgetItem *item = listWidget->currentItem(); - if(item) name = item->text().toUtf8().constData(); - close(); -} - -FileChooser::FileChooser() { - setWindowTitle("Select Cartridge To Load"); - setMinimumWidth(480); - setMinimumHeight(320); - - layout = new QVBoxLayout; - setLayout(layout); - - listWidget = new QListWidget; - layout->addWidget(listWidget); - - controlLayout = new QHBoxLayout; - controlLayout->setAlignment(Qt::AlignRight); - layout->addLayout(controlLayout); - - okButton = new QPushButton("Ok"); - controlLayout->addWidget(okButton); - - cancelButton = new QPushButton("Cancel"); - controlLayout->addWidget(cancelButton); - - connect(listWidget, SIGNAL(itemActivated(QListWidgetItem*)), this, SLOT(load())); - connect(okButton, SIGNAL(released()), this, SLOT(load())); - connect(cancelButton, SIGNAL(released()), this, SLOT(close())); -} diff --git a/snesreader/filechooser.moc.hpp b/snesreader/filechooser.moc.hpp deleted file mode 100644 index e024cab0..00000000 --- a/snesreader/filechooser.moc.hpp +++ /dev/null @@ -1,20 +0,0 @@ -class FileChooser : public QWidget { - Q_OBJECT - -public: - lstring list; - string name; - string exec(); - - FileChooser(); - -private slots: - void load(); - -private: - QVBoxLayout *layout; - QListWidget *listWidget; - QHBoxLayout *controlLayout; - QPushButton *okButton; - QPushButton *cancelButton; -} *fileChooser; diff --git a/snesreader/libjma/7z.h b/snesreader/libjma/7z.h deleted file mode 100644 index 50e1f242..00000000 --- a/snesreader/libjma/7z.h +++ /dev/null @@ -1,28 +0,0 @@ -/* -Copyright (C) 2005-2007 NSRT Team ( http://nsrt.edgeemu.com ) -Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net ) - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License version 2.1 as published by the Free Software Foundation. - -This library is distributed in the hope that 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 library; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef __7Z_H -#define __7Z_H - -#include "iiostrm.h" - -bool decompress_lzma_7z(ISequentialInStream& in, unsigned in_size, ISequentialOutStream& out, unsigned out_size) throw (); -bool decompress_lzma_7z(const unsigned char* in_data, unsigned in_size, unsigned char* out_data, unsigned out_size) throw (); - -#endif - diff --git a/snesreader/libjma/7zlzma.cpp b/snesreader/libjma/7zlzma.cpp deleted file mode 100644 index b849d8df..00000000 --- a/snesreader/libjma/7zlzma.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* -Copyright (C) 2005-2007 NSRT Team ( http://nsrt.edgeemu.com ) -Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net ) - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License version 2.1 as published by the Free Software Foundation. - -This library is distributed in the hope that 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 library; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "7z.h" - -#include "lzmadec.h" - -bool decompress_lzma_7z(ISequentialInStream& in, unsigned in_size, ISequentialOutStream& out, unsigned out_size) throw () -{ - try - { - NCompress::NLZMA::CDecoder cc; - - UINT64 in_size_l = in_size; - UINT64 out_size_l = out_size; - - if (cc.ReadCoderProperties(&in) != S_OK) { return(false); } - if (cc.Code(&in, &out, &in_size_l, &out_size_l) != S_OK) { return(false); } - if (out.size_get() != out_size || out.overflow_get()) { return(false); } - - return(true); - } - catch (...) - { - return(false); - } -} - -bool decompress_lzma_7z(const unsigned char* in_data, unsigned int in_size, unsigned char* out_data, unsigned int out_size) throw () -{ - ISequentialInStream_Array in(reinterpret_cast(in_data), in_size); - ISequentialOutStream_Array out(reinterpret_cast(out_data), out_size); - - return(decompress_lzma_7z(in, in_size, out, out_size)); -} diff --git a/snesreader/libjma/aribitcd.h b/snesreader/libjma/aribitcd.h deleted file mode 100644 index 1fb421ba..00000000 --- a/snesreader/libjma/aribitcd.h +++ /dev/null @@ -1,73 +0,0 @@ -#ifndef __COMPRESSION_BITCODER_H -#define __COMPRESSION_BITCODER_H - -#include "rngcoder.h" - -namespace NCompression { -namespace NArithmetic { - -const int kNumBitModelTotalBits = 11; -const UINT32 kBitModelTotal = (1 << kNumBitModelTotalBits); - -const int kNumMoveReducingBits = 2; - -///////////////////////////// -// CBitModel - -template -class CBitModel -{ -public: - UINT32 m_Probability; - void UpdateModel(UINT32 aSymbol) - { - /* - m_Probability -= (m_Probability + ((aSymbol - 1) & ((1 << aNumMoveBits) - 1))) >> aNumMoveBits; - m_Probability += (1 - aSymbol) << (kNumBitModelTotalBits - aNumMoveBits); - */ - if (aSymbol == 0) - m_Probability += (kBitModelTotal - m_Probability) >> aNumMoveBits; - else - m_Probability -= (m_Probability) >> aNumMoveBits; - } -public: - void Init() { m_Probability = kBitModelTotal / 2; } -}; - -template -class CBitDecoder: public CBitModel -{ -public: - UINT32 Decode(CRangeDecoder *aRangeDecoder) - { - UINT32 aNewBound = (aRangeDecoder->m_Range >> kNumBitModelTotalBits) * CBitModel::m_Probability; - if (aRangeDecoder->m_Code < aNewBound) - { - aRangeDecoder->m_Range = aNewBound; - CBitModel::m_Probability += (kBitModelTotal - CBitModel::m_Probability) >> aNumMoveBits; - if (aRangeDecoder->m_Range < kTopValue) - { - aRangeDecoder->m_Code = (aRangeDecoder->m_Code << 8) | aRangeDecoder->m_Stream.ReadByte(); - aRangeDecoder->m_Range <<= 8; - } - return 0; - } - else - { - aRangeDecoder->m_Range -= aNewBound; - aRangeDecoder->m_Code -= aNewBound; - CBitModel::m_Probability -= (CBitModel::m_Probability) >> aNumMoveBits; - if (aRangeDecoder->m_Range < kTopValue) - { - aRangeDecoder->m_Code = (aRangeDecoder->m_Code << 8) | aRangeDecoder->m_Stream.ReadByte(); - aRangeDecoder->m_Range <<= 8; - } - return 1; - } - } -}; - -}} - - -#endif diff --git a/snesreader/libjma/ariconst.h b/snesreader/libjma/ariconst.h deleted file mode 100644 index 751b2b7c..00000000 --- a/snesreader/libjma/ariconst.h +++ /dev/null @@ -1,29 +0,0 @@ -/* -Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net ) -Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org ) - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License version 2.1 as published by the Free Software Foundation. - -This library is distributed in the hope that 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 library; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef __ARICONST_H -#define __ARICONST_H - -#include "aribitcd.h" - - -typedef NCompression::NArithmetic::CRangeDecoder CMyRangeDecoder; -template class CMyBitDecoder: - public NCompression::NArithmetic::CBitDecoder {}; - -#endif diff --git a/snesreader/libjma/ariprice.h b/snesreader/libjma/ariprice.h deleted file mode 100644 index ccc398e1..00000000 --- a/snesreader/libjma/ariprice.h +++ /dev/null @@ -1,12 +0,0 @@ -#ifndef __COMPRESSION_ARIPRICE_H -#define __COMPRESSION_ARIPRICE_H - -namespace NCompression { -namespace NArithmetic { - -const UINT32 kNumBitPriceShiftBits = 6; -const UINT32 kBitPrice = 1 << kNumBitPriceShiftBits; - -}} - -#endif diff --git a/snesreader/libjma/btreecd.h b/snesreader/libjma/btreecd.h deleted file mode 100644 index acce3664..00000000 --- a/snesreader/libjma/btreecd.h +++ /dev/null @@ -1,126 +0,0 @@ -/* -Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net ) -Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org ) - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License version 2.1 as published by the Free Software Foundation. - -This library is distributed in the hope that 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 library; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef __BITTREECODER_H -#define __BITTREECODER_H - -#include "aribitcd.h" -#include "rcdefs.h" - - -////////////////////////// -// CBitTreeDecoder - -template -class CBitTreeDecoder -{ - CMyBitDecoder m_Models[1 << m_NumBitLevels]; -public: - void Init() - { - for(UINT32 i = 1; i < (1 << m_NumBitLevels); i++) - m_Models[i].Init(); - } - UINT32 Decode(CMyRangeDecoder *aRangeDecoder) - { - UINT32 aModelIndex = 1; - RC_INIT_VAR - for(UINT32 aBitIndex = m_NumBitLevels; aBitIndex > 0; aBitIndex--) - { - // aModelIndex = (aModelIndex << 1) + m_Models[aModelIndex].Decode(aRangeDecoder); - RC_GETBIT(aNumMoveBits, m_Models[aModelIndex].m_Probability, aModelIndex) - } - RC_FLUSH_VAR - return aModelIndex - (1 << m_NumBitLevels); - }; -}; - -//////////////////////////////// -// CReverseBitTreeDecoder - -template -class CReverseBitTreeDecoder2 -{ - CMyBitDecoder *m_Models; - UINT32 m_NumBitLevels; -public: - CReverseBitTreeDecoder2(): m_Models(0) { } - ~CReverseBitTreeDecoder2() { delete []m_Models; } - bool Create(UINT32 aNumBitLevels) - { - m_NumBitLevels = aNumBitLevels; - m_Models = new CMyBitDecoder[1 << aNumBitLevels]; - return (m_Models != 0); - } - void Init() - { - UINT32 aNumModels = 1 << m_NumBitLevels; - for(UINT32 i = 1; i < aNumModels; i++) - m_Models[i].Init(); - } - UINT32 Decode(CMyRangeDecoder *aRangeDecoder) - { - UINT32 aModelIndex = 1; - UINT32 aSymbol = 0; - RC_INIT_VAR - for(UINT32 aBitIndex = 0; aBitIndex < m_NumBitLevels; aBitIndex++) - { - // UINT32 aBit = m_Models[aModelIndex].Decode(aRangeDecoder); - // aModelIndex <<= 1; - // aModelIndex += aBit; - // aSymbol |= (aBit << aBitIndex); - RC_GETBIT2(aNumMoveBits, m_Models[aModelIndex].m_Probability, aModelIndex, ; , aSymbol |= (1 << aBitIndex)) - } - RC_FLUSH_VAR - return aSymbol; - }; -}; -//////////////////////////// -// CReverseBitTreeDecoder2 - -template -class CReverseBitTreeDecoder -{ - CMyBitDecoder m_Models[1 << m_NumBitLevels]; -public: - void Init() - { - for(UINT32 i = 1; i < (1 << m_NumBitLevels); i++) - m_Models[i].Init(); - } - UINT32 Decode(CMyRangeDecoder *aRangeDecoder) - { - UINT32 aModelIndex = 1; - UINT32 aSymbol = 0; - RC_INIT_VAR - for(UINT32 aBitIndex = 0; aBitIndex < m_NumBitLevels; aBitIndex++) - { - // UINT32 aBit = m_Models[aModelIndex].Decode(aRangeDecoder); - // aModelIndex <<= 1; - // aModelIndex += aBit; - // aSymbol |= (aBit << aBitIndex); - RC_GETBIT2(aNumMoveBits, m_Models[aModelIndex].m_Probability, aModelIndex, ; , aSymbol |= (1 << aBitIndex)) - } - RC_FLUSH_VAR - return aSymbol; - } -}; - - - -#endif diff --git a/snesreader/libjma/crc32.h b/snesreader/libjma/crc32.h deleted file mode 100644 index 876a7d3d..00000000 --- a/snesreader/libjma/crc32.h +++ /dev/null @@ -1,26 +0,0 @@ -/* -Copyright (C) 2004-2007 NSRT Team ( http://nsrt.edgeemu.com ) - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -version 2 as published by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You 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 CRC32_H -#define CRC32_H - -namespace CRC32lib -{ - unsigned int CRC32(const unsigned char *, size_t, register unsigned int crc32 = 0xFFFFFFFF); -} - -#endif diff --git a/snesreader/libjma/iiostrm.cpp b/snesreader/libjma/iiostrm.cpp deleted file mode 100644 index f2719969..00000000 --- a/snesreader/libjma/iiostrm.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/* -Copyright (C) 2005-2007 NSRT Team ( http://nsrt.edgeemu.com ) -Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net ) -Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org ) - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License version 2.1 as published by the Free Software Foundation. - -This library is distributed in the hope that 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 library; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "portable.h" -#include "iiostrm.h" -#include "crc32.h" - -HRESULT ISequentialInStream_Array::Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize) -{ - if (aSize > size) - { - aSize = size; - } - - *aProcessedSize = aSize; - memcpy(aData, data, aSize); - size -= aSize; - data += aSize; - return(S_OK); -} - -HRESULT ISequentialOutStream_Array::Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize) -{ - if (aSize > size) - { - overflow = true; - aSize = size; - } - - *aProcessedSize = aSize; - memcpy(data, aData, aSize); - size -= aSize; - data += aSize; - total += aSize; - return(S_OK); -} - -HRESULT ISequentialInStream_String::Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize) -{ - if (aSize > data.size()) - { - aSize = data.size(); - } - - *aProcessedSize = aSize; - memcpy(aData, data.c_str(), aSize); - data.erase(0, aSize); - return(S_OK); -} - -HRESULT ISequentialOutStream_String::Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize) -{ - *aProcessedSize = aSize; - data.append((const char *)aData, aSize); - total += aSize; - return(S_OK); -} - -HRESULT ISequentialInStream_Istream::Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize) -{ - data.read((char *)aData, aSize); - *aProcessedSize = data.gcount(); - return(S_OK); -} - -HRESULT ISequentialOutStream_Ostream::Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize) -{ - *aProcessedSize = aSize; - data.write((char *)aData, aSize); - total += aSize; - return(S_OK); -} - - - -HRESULT ISequentialInStreamCRC32_Array::Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize) -{ - ISequentialInStream_Array::Read(aData, aSize, aProcessedSize); - crc32 = CRC32lib::CRC32((const unsigned char *)aData, *aProcessedSize, ~crc32); - return(S_OK); -} - -HRESULT ISequentialOutStreamCRC32_Array::Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize) -{ - ISequentialOutStream_Array::Write(aData, aSize, aProcessedSize); - crc32 = CRC32lib::CRC32((const unsigned char *)aData, *aProcessedSize, ~crc32); - return(S_OK); -} - -HRESULT ISequentialInStreamCRC32_String::Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize) -{ - ISequentialInStream_String::Read(aData, aSize, aProcessedSize); - crc32 = CRC32lib::CRC32((const unsigned char *)aData, *aProcessedSize, ~crc32); - return(S_OK); -} - -HRESULT ISequentialOutStreamCRC32_String::Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize) -{ - ISequentialOutStream_String::Write(aData, aSize, aProcessedSize); - crc32 = CRC32lib::CRC32((const unsigned char *)aData, *aProcessedSize, ~crc32); - return(S_OK); -} - -HRESULT ISequentialInStreamCRC32_Istream::Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize) -{ - ISequentialInStream_Istream::Read(aData, aSize, aProcessedSize); - crc32 = CRC32lib::CRC32((const unsigned char *)aData, *aProcessedSize, ~crc32); - return(S_OK); -} - -HRESULT ISequentialOutStreamCRC32_Ostream::Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize) -{ - ISequentialOutStream_Ostream::Write(aData, aSize, aProcessedSize); - crc32 = CRC32lib::CRC32((const unsigned char *)aData, *aProcessedSize, ~crc32); - return(S_OK); -} diff --git a/snesreader/libjma/iiostrm.h b/snesreader/libjma/iiostrm.h deleted file mode 100644 index a5b2ab20..00000000 --- a/snesreader/libjma/iiostrm.h +++ /dev/null @@ -1,210 +0,0 @@ -/* -Copyright (C) 2005-2007 NSRT Team ( http://nsrt.edgeemu.com ) -Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net ) -Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org ) - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License version 2.1 as published by the Free Software Foundation. - -This library is distributed in the hope that 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 library; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef __IINOUTSTREAMS_H -#define __IINOUTSTREAMS_H - -#include -#include - -#include "portable.h" - - -class ISequentialInStream -{ -public: - virtual HRESULT Read(void *, UINT32, UINT32 *) = 0; - - virtual ~ISequentialInStream() {} -}; - - -class ISequentialInStream_Array : public ISequentialInStream -{ - const char *data; - unsigned int size; -public: - ISequentialInStream_Array(const char *Adata, unsigned Asize) : data(Adata), size(Asize) { } - - HRESULT Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize); - - virtual ~ISequentialInStream_Array() {} -}; - -class ISequentialInStream_String : public ISequentialInStream -{ - std::string& data; -public: - ISequentialInStream_String(std::string& Adata) : data(Adata) { } - - HRESULT Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize); - - virtual ~ISequentialInStream_String() {} -}; - -class ISequentialInStream_Istream : public ISequentialInStream -{ - std::istream& data; -public: - ISequentialInStream_Istream(std::istream& Adata) : data(Adata) { } - - HRESULT Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize); - - virtual ~ISequentialInStream_Istream() {} -}; - - - -class ISequentialOutStream -{ -public: - virtual bool overflow_get() const = 0; - virtual unsigned int size_get() const = 0; - - virtual HRESULT Write(const void *, UINT32, UINT32 *) = 0; - - virtual ~ISequentialOutStream() {} -}; - - -class ISequentialOutStream_Array : public ISequentialOutStream -{ - char *data; - unsigned int size; - bool overflow; - unsigned int total; -public: - ISequentialOutStream_Array(char *Adata, unsigned Asize) : data(Adata), size(Asize), overflow(false), total(0) { } - - bool overflow_get() const { return(overflow); } - unsigned int size_get() const { return(total); } - - HRESULT Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize); - - virtual ~ISequentialOutStream_Array() {} -}; - -class ISequentialOutStream_String : public ISequentialOutStream -{ - std::string& data; - unsigned int total; -public: - ISequentialOutStream_String(std::string& Adata) : data(Adata), total(0) { } - - bool overflow_get() const { return(false); } - unsigned int size_get() const { return(total); } - - HRESULT Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize); - - virtual ~ISequentialOutStream_String() {} -}; - - -class ISequentialOutStream_Ostream : public ISequentialOutStream -{ - std::ostream& data; - unsigned int total; -public: - ISequentialOutStream_Ostream(std::ostream& Adata) : data(Adata), total(0) { } - - bool overflow_get() const { return(false); } - unsigned int size_get() const { return(total); } - - HRESULT Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize); - - virtual ~ISequentialOutStream_Ostream() {} -}; - - - -class ISequentialStreamCRC32 -{ -protected: - unsigned int crc32; -public: - ISequentialStreamCRC32() : crc32(0) {} - unsigned int crc32_get() const { return(crc32); } - - virtual ~ISequentialStreamCRC32() {} -}; - - -class ISequentialInStreamCRC32_Array : public ISequentialInStream_Array, public ISequentialStreamCRC32 -{ -public: - ISequentialInStreamCRC32_Array(const char *Adata, unsigned Asize) : ISequentialInStream_Array(Adata, Asize) { } - - HRESULT Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize); - - virtual ~ISequentialInStreamCRC32_Array() {} -}; - -class ISequentialInStreamCRC32_String : public ISequentialInStream_String, public ISequentialStreamCRC32 -{ -public: - ISequentialInStreamCRC32_String(std::string& Adata) : ISequentialInStream_String(Adata) { } - - HRESULT Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize); - - virtual ~ISequentialInStreamCRC32_String() {} -}; - -class ISequentialInStreamCRC32_Istream : public ISequentialInStream_Istream, public ISequentialStreamCRC32 -{ -public: - ISequentialInStreamCRC32_Istream(std::istream& Adata) : ISequentialInStream_Istream(Adata) { } - - HRESULT Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize); - - virtual ~ISequentialInStreamCRC32_Istream() {} -}; - - -class ISequentialOutStreamCRC32_Array : public ISequentialOutStream_Array, public ISequentialStreamCRC32 -{ -public: - ISequentialOutStreamCRC32_Array(char *Adata, unsigned Asize) : ISequentialOutStream_Array(Adata, Asize) { } - - HRESULT Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize); - - virtual ~ISequentialOutStreamCRC32_Array() {} -}; - -class ISequentialOutStreamCRC32_String : public ISequentialOutStream_String, public ISequentialStreamCRC32 -{ -public: - ISequentialOutStreamCRC32_String(std::string& Adata) : ISequentialOutStream_String(Adata) { } - - HRESULT Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize); - - virtual ~ISequentialOutStreamCRC32_String() {} -}; - - -class ISequentialOutStreamCRC32_Ostream : public ISequentialOutStream_Ostream, public ISequentialStreamCRC32 -{ -public: - ISequentialOutStreamCRC32_Ostream(std::ostream& Adata) : ISequentialOutStream_Ostream(Adata) { } - - HRESULT Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize); - - virtual ~ISequentialOutStreamCRC32_Ostream() {} -}; - -#endif diff --git a/snesreader/libjma/inbyte.cpp b/snesreader/libjma/inbyte.cpp deleted file mode 100644 index c727a4b2..00000000 --- a/snesreader/libjma/inbyte.cpp +++ /dev/null @@ -1,60 +0,0 @@ -/* -Copyright (C) 2005-2007 NSRT Team ( http://nsrt.edgeemu.com ) -Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net ) -Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org ) - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License version 2.1 as published by the Free Software Foundation. - -This library is distributed in the hope that 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 library; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "inbyte.h" - -namespace NStream{ - -CInByte::CInByte(UINT32 aBufferSize): - m_BufferBase(0), - m_BufferSize(aBufferSize) -{ - m_BufferBase = new BYTE[m_BufferSize]; -} - -CInByte::~CInByte() -{ - delete []m_BufferBase; -} - -void CInByte::Init(ISequentialInStream *aStream) -{ - m_Stream = aStream; - m_ProcessedSize = 0; - m_Buffer = m_BufferBase; - m_BufferLimit = m_Buffer; - m_StreamWasExhausted = false; -} - -bool CInByte::ReadBlock() -{ - if (m_StreamWasExhausted) - return false; - m_ProcessedSize += (m_Buffer - m_BufferBase); - UINT32 aNumProcessedBytes; - HRESULT aResult = m_Stream->Read(m_BufferBase, m_BufferSize, &aNumProcessedBytes); - if (aResult != S_OK) - throw aResult; - m_Buffer = m_BufferBase; - m_BufferLimit = m_Buffer + aNumProcessedBytes; - m_StreamWasExhausted = (aNumProcessedBytes == 0); - return (!m_StreamWasExhausted); -} - -} diff --git a/snesreader/libjma/inbyte.h b/snesreader/libjma/inbyte.h deleted file mode 100644 index 53afa171..00000000 --- a/snesreader/libjma/inbyte.h +++ /dev/null @@ -1,76 +0,0 @@ -/* -Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net ) -Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org ) - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License version 2.1 as published by the Free Software Foundation. - -This library is distributed in the hope that 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 library; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef __STREAM_INBYTE_H -#define __STREAM_INBYTE_H - -#include "iiostrm.h" - -namespace NStream { - -class CInByte -{ - UINT64 m_ProcessedSize; - BYTE *m_BufferBase; - UINT32 m_BufferSize; - BYTE *m_Buffer; - BYTE *m_BufferLimit; - ISequentialInStream* m_Stream; - bool m_StreamWasExhausted; - - bool ReadBlock(); - -public: - CInByte(UINT32 aBufferSize = 0x100000); - ~CInByte(); - - void Init(ISequentialInStream *aStream); - - bool ReadByte(BYTE &aByte) - { - if(m_Buffer >= m_BufferLimit) - if(!ReadBlock()) - return false; - aByte = *m_Buffer++; - return true; - } - BYTE ReadByte() - { - if(m_Buffer >= m_BufferLimit) - if(!ReadBlock()) - return 0x0; - return *m_Buffer++; - } - void ReadBytes(void *aData, UINT32 aSize, UINT32 &aProcessedSize) - { - for(aProcessedSize = 0; aProcessedSize < aSize; aProcessedSize++) - if (!ReadByte(((BYTE *)aData)[aProcessedSize])) - return; - } - bool ReadBytes(void *aData, UINT32 aSize) - { - UINT32 aProcessedSize; - ReadBytes(aData, aSize, aProcessedSize); - return (aProcessedSize == aSize); - } - UINT64 GetProcessedSize() const { return m_ProcessedSize + (m_Buffer - m_BufferBase); } -}; - -} - -#endif diff --git a/snesreader/libjma/jcrc32.cpp b/snesreader/libjma/jcrc32.cpp deleted file mode 100644 index e3377d58..00000000 --- a/snesreader/libjma/jcrc32.cpp +++ /dev/null @@ -1,80 +0,0 @@ -/* -Copyright (C) 2004-2007 NSRT Team ( http://nsrt.edgeemu.com ) - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -version 2 as published by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You 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. -*/ - -#include - -namespace CRC32lib -{ - //Don't ask questions, this is the PKZip CRC32 table - const unsigned int crc32Table[256] = { - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, - 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, - 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, - 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, - 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, - 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, - 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, - 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, - 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, - 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, - 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, - 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, - 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, - 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, - 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, - 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, - 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, - 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, - 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, - 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, - 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, - 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, - 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, - 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, - 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, - 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, - 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, - 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, - 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, - 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, - 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, - 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, - 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, - 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, - 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, - 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, - 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, - 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, - 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, - 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d }; - - - //CRC32 for char arrays - unsigned int CRC32(const unsigned char *array, size_t size, register unsigned int crc32) - { - const unsigned char *end_p = array+size; - for (register const unsigned char *p = array; p < end_p; p++) - { - crc32 = ((crc32 >> 8) & 0x00FFFFFF) ^ crc32Table[(crc32 ^ *p) & 0xFF]; - } - - return(~crc32); - } -} diff --git a/snesreader/libjma/jma.cpp b/snesreader/libjma/jma.cpp deleted file mode 100644 index 87e03228..00000000 --- a/snesreader/libjma/jma.cpp +++ /dev/null @@ -1,550 +0,0 @@ -/* -Copyright (C) 2005-2007 NSRT Team ( http://nsrt.edgeemu.com ) - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -version 2 as published by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You 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. -*/ - -#include -#include "jma.h" -using namespace std; - -#include "portable.h" -#include "7z.h" -#include "crc32.h" - -namespace JMA -{ - const char jma_magic[] = { 'J', 'M', 'A', 0, 'N' }; - const unsigned int jma_header_length = 5; - const unsigned char jma_version = 1; - const unsigned int jma_version_length = 1; - const unsigned int jma_total_header_length = jma_header_length + jma_version_length + UINT_SIZE; - - //Convert DOS/zip/JMA integer time to to time_t - time_t uint_to_time(unsigned short date, unsigned short time) - { - tm formatted_time; - - formatted_time.tm_mday = date & 0x1F; - formatted_time.tm_mon = ((date >> 5) & 0xF) - 1; - formatted_time.tm_year = ((date >> 9) & 0x7f) + 80; - formatted_time.tm_sec = (time & 0x1F) * 2; - formatted_time.tm_min = (time >> 5) & 0x3F; - formatted_time.tm_hour = (time >> 11) & 0x1F; - - return(mktime(&formatted_time)); - } - - - //Retreive the file block, what else? - void jma_open::retrieve_file_block() throw(jma_errors) - { - unsigned char uint_buffer[UINT_SIZE]; - unsigned char ushort_buffer[USHORT_SIZE]; - - //File block size is the last UINT in the file - stream.seekg(-UINT_SIZE,ios::end); - stream.read((char *)uint_buffer, UINT_SIZE); - size_t file_block_size = charp_to_uint(uint_buffer); - - //Currently at the end of the file, so that's the file size - size_t jma_file_size = stream.tellg(); - - //The file block can't be larger than the JMA file without it's header. - //This if can probably be improved - if (file_block_size >= jma_file_size-jma_total_header_length) - { - throw(JMA_BAD_FILE); - } - - //Seek to before file block so we can read the file block - stream.seekg(-((int)file_block_size+UINT_SIZE),ios::end); - - //This is needed if the file block is compressed - stringstream decompressed_file_block; - //Pointer to where to read file block from (file or decompressed buffer) - istream *file_block_stream; - - //Setup file info buffer and byte to read with - jma_file_info file_info; - char byte; - - stream.get(byte); - if (!byte) //If file block is compressed - { - //Compressed size isn't counting the byte we just read or the UINT for compressed size - size_t compressed_size = file_block_size - (1+UINT_SIZE); - - //Read decompressed size / true file block size - stream.read((char *)uint_buffer, UINT_SIZE); - file_block_size = charp_to_uint(uint_buffer); - - //Setup access methods for decompression - ISequentialInStream_Istream compressed_data(stream); - ISequentialOutStream_Ostream decompressed_data(decompressed_file_block); - - //Decompress the data - if (!decompress_lzma_7z(compressed_data, compressed_size, decompressed_data, file_block_size)) - { - throw(JMA_DECOMPRESS_FAILED); - } - - //Go to beginning, setup pointer to buffer - decompressed_file_block.seekg(0, ios::beg); - file_block_stream = &decompressed_file_block; - } - else - { - stream.putback(byte); //Putback byte, byte is part of filename, not compressed indicator - file_block_stream = &stream; - } - - - //Minimum file name length is 2 bytes, a char and a null - //Minimum comment length is 1 byte, a null - //There are currently 2 UINTs and 2 USHORTs per file - while (file_block_size >= 2+1+UINT_SIZE*2+USHORT_SIZE*2) //This does allow for a gap, but that's okay - { - //First stored in the file block is the file name null terminated - file_info.name = ""; - - file_block_stream->get(byte); - while (byte) - { - file_info.name += byte; - file_block_stream->get(byte); - } - - //There must be a file name or the file is bad - if (!file_info.name.length()) - { - throw(JMA_BAD_FILE); - } - - //Same trick as above for the comment - file_info.comment = ""; - - file_block_stream->get(byte); - while (byte) - { - file_info.comment += byte; - file_block_stream->get(byte); - } - - //Next is a UINT representing the file's size - file_block_stream->read((char *)uint_buffer, UINT_SIZE); - file_info.size = charp_to_uint(uint_buffer); - - //Followed by CRC32 - file_block_stream->read((char *)uint_buffer, UINT_SIZE); - file_info.crc32 = charp_to_uint(uint_buffer); - - //Special USHORT representation of file's date - file_block_stream->read((char *)ushort_buffer, USHORT_SIZE); - file_info.date = charp_to_ushort(ushort_buffer); - - //Special USHORT representation of file's time - file_block_stream->read((char *)ushort_buffer, USHORT_SIZE); - file_info.time = charp_to_ushort(ushort_buffer); - - file_info.buffer = 0; //Pointing to null till we decompress files - - files.push_back(file_info); //Put file info into our structure - - //Subtract size of the file info we just read - file_block_size -= file_info.name.length()+file_info.comment.length()+2+UINT_SIZE*2+USHORT_SIZE*2; - } - } - - //Constructor for opening JMA files for reading - jma_open::jma_open(const char *compressed_file_name) throw (jma_errors) - { - decompressed_buffer = 0; - compressed_buffer = 0; - - stream.open(compressed_file_name, ios::in | ios::binary); - if (!stream.is_open()) - { - throw(JMA_NO_OPEN); - } - - //Header is "JMA\0N" - unsigned char header[jma_header_length]; - stream.read((char *)header, jma_header_length); - if (memcmp(jma_magic, header, jma_header_length)) - { - throw(JMA_BAD_FILE); - } - - //Not the cleanest code but logical - stream.read((char *)header, 5); - if (*header <= jma_version) - { - chunk_size = charp_to_uint(header+1); //Chunk size is a UINT that follows version # - retrieve_file_block(); - } - else - { - throw(JMA_UNSUPPORTED_VERSION); - } - } - - //Destructor only has to close the stream if neccesary - jma_open::~jma_open() - { - if (stream.is_open()) - { - stream.close(); - } - } - - //Return a vector containing useful info about the files in the JMA - vector jma_open::get_files_info() - { - vector file_info_vector; - jma_public_file_info file_info; - - for (vector::iterator i = files.begin(); i != files.end(); i++) - { - file_info.name = i->name; - file_info.comment = i->comment; - file_info.size = i->size; - file_info.datetime = uint_to_time(i->date, i->time); - file_info.crc32 = i->crc32; - file_info_vector.push_back(file_info); - } - - return(file_info_vector); - } - - //Skip forward a given number of chunks - void jma_open::chunk_seek(unsigned int chunk_num) throw(jma_errors) - { - //Check the stream is open - if (!stream.is_open()) - { - throw(JMA_NO_OPEN); - } - - //Clear possible errors so the seek will work - stream.clear(); - - //Move forward over header - stream.seekg(jma_total_header_length, ios::beg); - - unsigned char int4_buffer[UINT_SIZE]; - - while (chunk_num--) - { - //Read in size of chunk - stream.read((char *)int4_buffer, UINT_SIZE); - - //Skip chunk plus it's CRC32 - stream.seekg(charp_to_uint(int4_buffer)+UINT_SIZE, ios::cur); - } - } - - //Return a vector of pointers to each file in the JMA, the buffer to hold all the files - //must be initilized outside. - vector jma_open::get_all_files(unsigned char *buffer) throw(jma_errors) - { - //If there's no stream we can't read from it, so exit - if (!stream.is_open()) - { - throw(JMA_NO_OPEN); - } - - //Seek to the first chunk - chunk_seek(0); - - //Set the buffer that decompressed data goes to - decompressed_buffer = buffer; - - //If the JMA is not solid - if (chunk_size) - { - unsigned char int4_buffer[UINT_SIZE]; - size_t size = get_total_size(files); - - //For each chunk in the file... - for (size_t remaining_size = size; remaining_size; remaining_size -= chunk_size) - { - //Read the compressed size - stream.read((char *)int4_buffer, UINT_SIZE); - size_t compressed_size = charp_to_uint(int4_buffer); - - //Allocate memory of the correct size to hold the compressed data in the JMA - //Throw error on failure as that is unrecoverable from - try - { - compressed_buffer = new unsigned char[compressed_size]; - } - catch (bad_alloc xa) - { - throw(JMA_NO_MEM_ALLOC); - } - - //Read all the compressed data in - stream.read((char *)compressed_buffer, compressed_size); - - //Read the expected CRC of compressed data from the file - stream.read((char *)int4_buffer, UINT_SIZE); - - //If it doesn't match, throw error and cleanup memory - if (CRC32lib::CRC32(compressed_buffer, compressed_size) != charp_to_uint(int4_buffer)) - { - delete[] compressed_buffer; - throw(JMA_BAD_FILE); - } - - //Decompress the data, cleanup memory on failure - if (!decompress_lzma_7z(compressed_buffer, compressed_size, - decompressed_buffer+size-remaining_size, - (remaining_size > chunk_size) ? chunk_size : remaining_size)) - { - delete[] compressed_buffer; - throw(JMA_DECOMPRESS_FAILED); - } - delete[] compressed_buffer; - - if (remaining_size <= chunk_size) //If we just decompressed the remainder - { - break; - } - } - } - else //Solidly compressed JMA - { - unsigned char int4_buffer[UINT_SIZE]; - - //Read the size of the compressed data - stream.read((char *)int4_buffer, UINT_SIZE); - size_t compressed_size = charp_to_uint(int4_buffer); - - //Get decompressed size - size_t size = get_total_size(files); - - //Setup access methods for decompression - ISequentialInStream_Istream compressed_data(stream); - ISequentialOutStream_Array decompressed_data(reinterpret_cast(decompressed_buffer), size); - - //Decompress the data - if (!decompress_lzma_7z(compressed_data, compressed_size, decompressed_data, size)) - { - throw(JMA_DECOMPRESS_FAILED); - } - - /* - //Allocate memory of the right size to hold the compressed data in the JMA - try - { - compressed_buffer = new unsigned char[compressed_size]; - } - catch (bad_alloc xa) - { - throw(JMA_NO_MEM_ALLOC); - } - - //Copy the compressed data into memory - stream.read((char *)compressed_buffer, compressed_size); - size_t size = get_total_size(files); - - //Read the CRC of the compressed data - stream.read((char *)int4_buffer, UINT_SIZE); - - //If it doesn't match, complain - if (CRC32lib::CRC32(compressed_buffer, compressed_size) != charp_to_uint(int4_buffer)) - { - delete[] compressed_buffer; - throw(JMA_BAD_FILE); - } - - //Decompress the data - if (!decompress_lzma_7z(compressed_buffer, compressed_size, decompressed_buffer, size)) - { - delete[] compressed_buffer; - throw(JMA_DECOMPRESS_FAILED); - } - delete[] compressed_buffer; - */ - } - - vector file_pointers; - size_t size = 0; - - //For each file, add it's pointer to the vector, size is pointer offset in the buffer - for (vector::iterator i = files.begin(); i != files.end(); i++) - { - i->buffer = decompressed_buffer+size; - file_pointers.push_back(decompressed_buffer+size); - size += i->size; - } - - //Return the vector of pointers - return(file_pointers); - } - - //Extracts the file with a given name found in the archive to the given buffer - void jma_open::extract_file(string& name, unsigned char *buffer) throw(jma_errors) - { - if (!stream.is_open()) - { - throw(JMA_NO_OPEN); - } - - size_t size_to_skip = 0; - size_t our_file_size = 0; - - //Search through the vector of file information - for (vector::iterator i = files.begin(); i != files.end(); i++) - { - if (i->name == name) - { - //Set the variable so we can tell we found it - our_file_size = i->size; - break; - } - - //Keep a running total of size - size_to_skip += i->size; - } - - if (!our_file_size) //File with the specified name was not found in the archive - { - throw(JMA_FILE_NOT_FOUND); - } - - //If the JMA only contains one file, we can skip a lot of overhead - if (files.size() == 1) - { - get_all_files(buffer); - return; - } - - if (chunk_size) //we are using non-solid archive.. - { - unsigned int chunks_to_skip = size_to_skip / chunk_size; - - //skip over requisite number of chunks - chunk_seek(chunks_to_skip); - - //Allocate memory for compressed and decompressed data - unsigned char *comp_buffer = 0, *decomp_buffer = 0; - try - { - //Compressed data size is <= non compressed size - unsigned char *combined_buffer = new unsigned char[chunk_size*2]; - comp_buffer = combined_buffer; - decomp_buffer = combined_buffer+chunk_size; - } - catch (bad_alloc xa) - { - throw(JMA_NO_MEM_ALLOC); - } - - size_t first_chunk_offset = size_to_skip % chunk_size; - unsigned char int4_buffer[UINT_SIZE]; - for (size_t i = 0; i < our_file_size;) - { - //Get size - stream.read((char *)int4_buffer, UINT_SIZE); - size_t compressed_size = charp_to_uint(int4_buffer); - - //Read all the compressed data in - stream.read((char *)comp_buffer, compressed_size); - - //Read the CRC of the compressed data - stream.read((char *)int4_buffer, UINT_SIZE); - - //If it doesn't match, complain - if (CRC32lib::CRC32(comp_buffer, compressed_size) != charp_to_uint(int4_buffer)) - { - delete[] comp_buffer; - throw(JMA_BAD_FILE); - } - - //Decompress chunk - if (!decompress_lzma_7z(comp_buffer, compressed_size, decomp_buffer, chunk_size)) - { - delete[] comp_buffer; - throw(JMA_DECOMPRESS_FAILED); - } - - size_t copy_amount = our_file_size-i > chunk_size-first_chunk_offset ? chunk_size-first_chunk_offset : our_file_size-i; - - memcpy(buffer+i, decomp_buffer+first_chunk_offset, copy_amount); - first_chunk_offset = 0; //Set to zero since this is only for the first iteration - i += copy_amount; - } - delete[] comp_buffer; - } - else //Solid JMA - { - unsigned char *decomp_buffer = 0; - try - { - decomp_buffer = new unsigned char[get_total_size(files)]; - } - catch (bad_alloc xa) - { - throw(JMA_NO_MEM_ALLOC); - } - - get_all_files(decomp_buffer); - - memcpy(buffer, decomp_buffer+size_to_skip, our_file_size); - - delete[] decomp_buffer; - } - } - - bool jma_open::is_solid() - { - return(chunk_size ? false : true); - } - - const char *jma_error_text(jma_errors error) - { - switch (error) - { - case JMA_NO_CREATE: - return("JMA could not be created"); - - case JMA_NO_MEM_ALLOC: - return("Memory for JMA could be allocated"); - - case JMA_NO_OPEN: - return("JMA could not be opened"); - - case JMA_BAD_FILE: - return("Invalid/Corrupt JMA"); - - case JMA_UNSUPPORTED_VERSION: - return("JMA version not supported"); - - case JMA_COMPRESS_FAILED: - return("JMA compression failed"); - - case JMA_DECOMPRESS_FAILED: - return("JMA decompression failed"); - - case JMA_FILE_NOT_FOUND: - return("File not found in JMA"); - } - return("Unknown error"); - } - -} - - diff --git a/snesreader/libjma/jma.h b/snesreader/libjma/jma.h deleted file mode 100644 index 2aaa5ca1..00000000 --- a/snesreader/libjma/jma.h +++ /dev/null @@ -1,88 +0,0 @@ -/* -Copyright (C) 2005-2007 NSRT Team ( http://nsrt.edgeemu.com ) - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -version 2 as published by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You 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 JMA_H -#define JMA_H - -#include -#include -#include -#include - -namespace JMA -{ - enum jma_errors { JMA_NO_CREATE, JMA_NO_MEM_ALLOC, JMA_NO_OPEN, JMA_BAD_FILE, - JMA_UNSUPPORTED_VERSION, JMA_COMPRESS_FAILED, JMA_DECOMPRESS_FAILED, - JMA_FILE_NOT_FOUND }; - - struct jma_file_info_base - { - std::string name; - std::string comment; - size_t size; - unsigned int crc32; - }; - - struct jma_public_file_info : jma_file_info_base - { - time_t datetime; - }; - - struct jma_file_info : jma_file_info_base - { - unsigned short date; - unsigned short time; - const unsigned char *buffer; - }; - - template - inline size_t get_total_size(std::vector& files) - { - size_t size = 0; - for (typename std::vector::iterator i = files.begin(); i != files.end(); i++) - { - size += i->size; //We do have a problem if this wraps around - } - - return(size); - } - - class jma_open - { - public: - jma_open(const char *) throw(jma_errors); - ~jma_open(); - - std::vector get_files_info(); - std::vector get_all_files(unsigned char *) throw(jma_errors); - void extract_file(std::string& name, unsigned char *) throw(jma_errors); - bool is_solid(); - - private: - std::ifstream stream; - std::vector files; - size_t chunk_size; - unsigned char *decompressed_buffer; - unsigned char *compressed_buffer; - - void chunk_seek(unsigned int) throw(jma_errors); - void retrieve_file_block() throw(jma_errors); - }; - - const char *jma_error_text(jma_errors); -} -#endif diff --git a/snesreader/libjma/lencoder.h b/snesreader/libjma/lencoder.h deleted file mode 100644 index 6f30e478..00000000 --- a/snesreader/libjma/lencoder.h +++ /dev/null @@ -1,93 +0,0 @@ -/* -Copyright (C) 2005-2007 NSRT Team ( http://nsrt.edgeemu.com ) -Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net ) -Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org ) - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License version 2.1 as published by the Free Software Foundation. - -This library is distributed in the hope that 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 library; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef __LENCODER_H -#define __LENCODER_H - -#include "btreecd.h" - -namespace NLength { - -const UINT32 kNumPosStatesBitsMax = 4; -const int kNumPosStatesMax = (1 << kNumPosStatesBitsMax); - - -const int kNumPosStatesBitsEncodingMax = 4; -const int kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); - - -const int kNumMoveBits = 5; - -const int kNumLenBits = 3; -const int kNumLowSymbols = 1 << kNumLenBits; -const int kNumMidBits = 3; -const int kNumMidSymbols = 1 << kNumMidBits; - -const int kNumHighBits = 8; - -const int kNumSymbolsTotal = kNumLowSymbols + kNumMidSymbols + (1 << kNumHighBits); - -const int kNumSpecSymbols = kNumLowSymbols + kNumMidSymbols; - -class CDecoder -{ - CMyBitDecoder m_Choice; - CBitTreeDecoder m_LowCoder[kNumPosStatesMax]; - CMyBitDecoder m_Choice2; - CBitTreeDecoder m_MidCoder[kNumPosStatesMax]; - CBitTreeDecoder m_HighCoder; - UINT32 m_NumPosStates; -public: - void Create(UINT32 aNumPosStates) - { m_NumPosStates = aNumPosStates; } - void Init() - { - m_Choice.Init(); - for (UINT32 aPosState = 0; aPosState < m_NumPosStates; aPosState++) - { - m_LowCoder[aPosState].Init(); - m_MidCoder[aPosState].Init(); - } - m_Choice2.Init(); - m_HighCoder.Init(); - } - UINT32 Decode(CMyRangeDecoder *aRangeDecoder, UINT32 aPosState) - { - if(m_Choice.Decode(aRangeDecoder) == 0) - return m_LowCoder[aPosState].Decode(aRangeDecoder); - else - { - UINT32 aSymbol = kNumLowSymbols; - if(m_Choice2.Decode(aRangeDecoder) == 0) - aSymbol += m_MidCoder[aPosState].Decode(aRangeDecoder); - else - { - aSymbol += kNumMidSymbols; - aSymbol += m_HighCoder.Decode(aRangeDecoder); - } - return aSymbol; - } - } - -}; - -} - - -#endif diff --git a/snesreader/libjma/litcoder.h b/snesreader/libjma/litcoder.h deleted file mode 100644 index 639d6c55..00000000 --- a/snesreader/libjma/litcoder.h +++ /dev/null @@ -1,122 +0,0 @@ -/* -Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net ) -Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org ) - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License version 2.1 as published by the Free Software Foundation. - -This library is distributed in the hope that 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 library; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef __LITERALCODER_H -#define __LITERALCODER_H - -#include "aribitcd.h" -#include "rcdefs.h" - -namespace NLiteral { - -const int kNumMoveBits = 5; - -class CDecoder2 -{ - CMyBitDecoder m_Decoders[3][1 << 8]; -public: - void Init() - { - for (int i = 0; i < 3; i++) - for (int j = 1; j < (1 << 8); j++) - m_Decoders[i][j].Init(); - } - - BYTE DecodeNormal(CMyRangeDecoder *aRangeDecoder) - { - UINT32 aSymbol = 1; - RC_INIT_VAR - do - { - // aSymbol = (aSymbol << 1) | m_Decoders[0][aSymbol].Decode(aRangeDecoder); - RC_GETBIT(kNumMoveBits, m_Decoders[0][aSymbol].m_Probability, aSymbol) - } - while (aSymbol < 0x100); - RC_FLUSH_VAR - return aSymbol; - } - - BYTE DecodeWithMatchByte(CMyRangeDecoder *aRangeDecoder, BYTE aMatchByte) - { - UINT32 aSymbol = 1; - RC_INIT_VAR - do - { - UINT32 aMatchBit = (aMatchByte >> 7) & 1; - aMatchByte <<= 1; - // UINT32 aBit = m_Decoders[1 + aMatchBit][aSymbol].Decode(aRangeDecoder); - // aSymbol = (aSymbol << 1) | aBit; - UINT32 aBit; - RC_GETBIT2(kNumMoveBits, m_Decoders[1 + aMatchBit][aSymbol].m_Probability, aSymbol, - aBit = 0, aBit = 1) - if (aMatchBit != aBit) - { - while (aSymbol < 0x100) - { - // aSymbol = (aSymbol << 1) | m_Decoders[0][aSymbol].Decode(aRangeDecoder); - RC_GETBIT(kNumMoveBits, m_Decoders[0][aSymbol].m_Probability, aSymbol) - } - break; - } - } - while (aSymbol < 0x100); - RC_FLUSH_VAR - return aSymbol; - } -}; - -class CDecoder -{ - CDecoder2 *m_Coders; - UINT32 m_NumPrevBits; - UINT32 m_NumPosBits; - UINT32 m_PosMask; -public: - CDecoder(): m_Coders(0) {} - ~CDecoder() { Free(); } - void Free() - { - delete []m_Coders; - m_Coders = 0; - } - void Create(UINT32 aNumPosBits, UINT32 aNumPrevBits) - { - Free(); - m_NumPosBits = aNumPosBits; - m_PosMask = (1 << aNumPosBits) - 1; - m_NumPrevBits = aNumPrevBits; - UINT32 aNumStates = 1 << (m_NumPrevBits + m_NumPosBits); - m_Coders = new CDecoder2[aNumStates]; - } - void Init() - { - UINT32 aNumStates = 1 << (m_NumPrevBits + m_NumPosBits); - for (UINT32 i = 0; i < aNumStates; i++) - m_Coders[i].Init(); - } - UINT32 GetState(UINT32 aPos, BYTE aPrevByte) const - { return ((aPos & m_PosMask) << m_NumPrevBits) + (aPrevByte >> (8 - m_NumPrevBits)); } - BYTE DecodeNormal(CMyRangeDecoder *aRangeDecoder, UINT32 aPos, BYTE aPrevByte) - { return m_Coders[GetState(aPos, aPrevByte)].DecodeNormal(aRangeDecoder); } - BYTE DecodeWithMatchByte(CMyRangeDecoder *aRangeDecoder, UINT32 aPos, BYTE aPrevByte, BYTE aMatchByte) - { return m_Coders[GetState(aPos, aPrevByte)].DecodeWithMatchByte(aRangeDecoder, aMatchByte); } -}; - -} - -#endif diff --git a/snesreader/libjma/lzma.cpp b/snesreader/libjma/lzma.cpp deleted file mode 100644 index d020ed27..00000000 --- a/snesreader/libjma/lzma.cpp +++ /dev/null @@ -1,41 +0,0 @@ -/* -Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net ) -Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org ) - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License version 2.1 as published by the Free Software Foundation. - -This library is distributed in the hope that 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 library; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "lzma.h" - -namespace NCompress { -namespace NLZMA { - -UINT32 kDistStart[kDistTableSizeMax]; - -static class CConstInit -{ -public: - CConstInit() - { - UINT32 aStartValue = 0; - int i; - for (i = 0; i < kDistTableSizeMax; i++) - { - kDistStart[i] = aStartValue; - aStartValue += (1 << kDistDirectBits[i]); - } - } -} g_ConstInit; - -}} diff --git a/snesreader/libjma/lzma.h b/snesreader/libjma/lzma.h deleted file mode 100644 index 949b70b3..00000000 --- a/snesreader/libjma/lzma.h +++ /dev/null @@ -1,124 +0,0 @@ -/* -Copyright (C) 2005-2007 NSRT Team ( http://nsrt.edgeemu.com ) -Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net ) -Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org ) - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License version 2.1 as published by the Free Software Foundation. - -This library is distributed in the hope that 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 library; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "lencoder.h" - -#ifndef __LZMA_H -#define __LZMA_H - -namespace NCompress { -namespace NLZMA { - -const UINT32 kNumRepDistances = 4; - -const BYTE kNumStates = 12; - -const BYTE kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; -const BYTE kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; -const BYTE kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; -const BYTE kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; - -class CState -{ -public: - BYTE m_Index; - void Init() - { m_Index = 0; } - void UpdateChar() - { m_Index = kLiteralNextStates[m_Index]; } - void UpdateMatch() - { m_Index = kMatchNextStates[m_Index]; } - void UpdateRep() - { m_Index = kRepNextStates[m_Index]; } - void UpdateShortRep() - { m_Index = kShortRepNextStates[m_Index]; } -}; - -class CBaseCoder -{ -protected: - CState m_State; - BYTE m_PreviousByte; - bool m_PeviousIsMatch; - UINT32 m_RepDistances[kNumRepDistances]; - void Init() - { - m_State.Init(); - m_PreviousByte = 0; - m_PeviousIsMatch = false; - for(UINT32 i = 0 ; i < kNumRepDistances; i++) - m_RepDistances[i] = 0; - } -}; - -const int kNumPosSlotBits = 6; -const int kDicLogSizeMax = 28; -const int kDistTableSizeMax = kDicLogSizeMax * 2; - -extern UINT32 kDistStart[kDistTableSizeMax]; -const BYTE kDistDirectBits[kDistTableSizeMax] = -{ - 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, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19, - 20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26 -}; - -const UINT32 kNumLenToPosStates = 4; -inline UINT32 GetLenToPosState(UINT32 aLen) -{ - aLen -= 2; - if (aLen < kNumLenToPosStates) - return aLen; - return kNumLenToPosStates - 1; -} - -const int kMatchMinLen = 2; - -const int kMatchMaxLen = kMatchMinLen + NLength::kNumSymbolsTotal - 1; - -const int kNumAlignBits = 4; -const int kAlignTableSize = 1 << kNumAlignBits; -const UINT32 kAlignMask = (kAlignTableSize - 1); - -const int kStartPosModelIndex = 4; -const int kEndPosModelIndex = 14; -const int kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; - -const int kNumFullDistances = 1 << (kEndPosModelIndex / 2); - - -const int kMainChoiceLiteralIndex = 0; -const int kMainChoiceMatchIndex = 1; - -const int kMatchChoiceDistanceIndex= 0; -const int kMatchChoiceRepetitionIndex = 1; - -const int kNumMoveBitsForMainChoice = 5; -const int kNumMoveBitsForPosCoders = 5; - -const int kNumMoveBitsForAlignCoders = 5; - -const int kNumMoveBitsForPosSlotCoder = 5; - -const int kNumLitPosStatesBitsEncodingMax = 4; -const int kNumLitContextBitsMax = 8; - -}} - -#endif diff --git a/snesreader/libjma/lzmadec.h b/snesreader/libjma/lzmadec.h deleted file mode 100644 index bb91912e..00000000 --- a/snesreader/libjma/lzmadec.h +++ /dev/null @@ -1,82 +0,0 @@ -/* -Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net ) -Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org ) - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License version 2.1 as published by the Free Software Foundation. - -This library is distributed in the hope that 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 library; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef __LZARITHMETIC_DECODER_H -#define __LZARITHMETIC_DECODER_H - -#include "winout.h" -#include "lzma.h" -#include "lencoder.h" -#include "litcoder.h" - -namespace NCompress { -namespace NLZMA { - -typedef CMyBitDecoder CMyBitDecoder2; - -class CDecoder -{ - NStream::NWindow::COut m_OutWindowStream; - CMyRangeDecoder m_RangeDecoder; - - CMyBitDecoder2 m_MainChoiceDecoders[kNumStates][NLength::kNumPosStatesMax]; - CMyBitDecoder2 m_MatchChoiceDecoders[kNumStates]; - CMyBitDecoder2 m_MatchRepChoiceDecoders[kNumStates]; - CMyBitDecoder2 m_MatchRep1ChoiceDecoders[kNumStates]; - CMyBitDecoder2 m_MatchRep2ChoiceDecoders[kNumStates]; - CMyBitDecoder2 m_MatchRepShortChoiceDecoders[kNumStates][NLength::kNumPosStatesMax]; - - CBitTreeDecoder m_PosSlotDecoder[kNumLenToPosStates]; - - CReverseBitTreeDecoder2 m_PosDecoders[kNumPosModels]; - CReverseBitTreeDecoder m_PosAlignDecoder; - // CBitTreeDecoder2 m_PosDecoders[kNumPosModels]; - // CBitTreeDecoder m_PosAlignDecoder; - - NLength::CDecoder m_LenDecoder; - NLength::CDecoder m_RepMatchLenDecoder; - - NLiteral::CDecoder m_LiteralDecoder; - - UINT32 m_DictionarySize; - - UINT32 m_PosStateMask; - - HRESULT Create(); - - HRESULT Init(ISequentialInStream *anInStream, ISequentialOutStream *anOutStream); - - HRESULT Flush() { return m_OutWindowStream.Flush(); } - - HRESULT CodeReal(ISequentialInStream *anInStream, ISequentialOutStream *anOutStream, const UINT64 *anInSize, const UINT64 *anOutSize); - -public: - - CDecoder(); - - HRESULT Code(ISequentialInStream *anInStream, ISequentialOutStream *anOutStream, const UINT64 *anInSize, const UINT64 *anOutSize); - HRESULT ReadCoderProperties(ISequentialInStream *anInStream); - - HRESULT SetDictionarySize(UINT32 aDictionarySize); - HRESULT SetLiteralProperties(UINT32 aLiteralPosStateBits, UINT32 aLiteralContextBits); - HRESULT SetPosBitsProperties(UINT32 aNumPosStateBits); -}; - -}} - -#endif diff --git a/snesreader/libjma/lzmadecode.cpp b/snesreader/libjma/lzmadecode.cpp deleted file mode 100644 index ad6b5709..00000000 --- a/snesreader/libjma/lzmadecode.cpp +++ /dev/null @@ -1,298 +0,0 @@ -/* -Copyright (C) 2005-2007 NSRT Team ( http://nsrt.edgeemu.com ) -Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net ) -Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org ) - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License version 2.1 as published by the Free Software Foundation. - -This library is distributed in the hope that 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 library; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "portable.h" -#include "lzmadec.h" - -#define RETURN_E_OUTOFMEMORY_IF_FALSE(x) { if (!(x)) return E_OUTOFMEMORY; } - -namespace NCompress { -namespace NLZMA { - -HRESULT CDecoder::SetDictionarySize(UINT32 aDictionarySize) -{ - if (aDictionarySize > (1 << kDicLogSizeMax)) - return E_INVALIDARG; - - UINT32 aWindowReservSize = MyMax(aDictionarySize, UINT32(1 << 21)); - - if (m_DictionarySize != aDictionarySize) - { - m_OutWindowStream.Create(aDictionarySize, kMatchMaxLen, aWindowReservSize); - m_DictionarySize = aDictionarySize; - } - return S_OK; -} - -HRESULT CDecoder::SetLiteralProperties( - UINT32 aLiteralPosStateBits, UINT32 aLiteralContextBits) -{ - if (aLiteralPosStateBits > 8) - return E_INVALIDARG; - if (aLiteralContextBits > 8) - return E_INVALIDARG; - m_LiteralDecoder.Create(aLiteralPosStateBits, aLiteralContextBits); - return S_OK; -} - -HRESULT CDecoder::SetPosBitsProperties(UINT32 aNumPosStateBits) -{ - if (aNumPosStateBits > NLength::kNumPosStatesBitsMax) - return E_INVALIDARG; - UINT32 aNumPosStates = 1 << aNumPosStateBits; - m_LenDecoder.Create(aNumPosStates); - m_RepMatchLenDecoder.Create(aNumPosStates); - m_PosStateMask = aNumPosStates - 1; - return S_OK; -} - -CDecoder::CDecoder(): - m_DictionarySize((UINT32)-1) -{ - Create(); -} - -HRESULT CDecoder::Create() -{ - for(int i = 0; i < kNumPosModels; i++) - { - RETURN_E_OUTOFMEMORY_IF_FALSE( - m_PosDecoders[i].Create(kDistDirectBits[kStartPosModelIndex + i])); - } - return S_OK; -} - - -HRESULT CDecoder::Init(ISequentialInStream *anInStream, - ISequentialOutStream *anOutStream) -{ - m_RangeDecoder.Init(anInStream); - - m_OutWindowStream.Init(anOutStream); - - int i; - for(i = 0; i < kNumStates; i++) - { - for (UINT32 j = 0; j <= m_PosStateMask; j++) - { - m_MainChoiceDecoders[i][j].Init(); - m_MatchRepShortChoiceDecoders[i][j].Init(); - } - m_MatchChoiceDecoders[i].Init(); - m_MatchRepChoiceDecoders[i].Init(); - m_MatchRep1ChoiceDecoders[i].Init(); - m_MatchRep2ChoiceDecoders[i].Init(); - } - - m_LiteralDecoder.Init(); - - // m_RepMatchLenDecoder.Init(); - - for (i = 0; (UINT32) i < kNumLenToPosStates; i++) - m_PosSlotDecoder[i].Init(); - - for(i = 0; i < kNumPosModels; i++) - m_PosDecoders[i].Init(); - - m_LenDecoder.Init(); - m_RepMatchLenDecoder.Init(); - - m_PosAlignDecoder.Init(); - return S_OK; - -} - -HRESULT CDecoder::CodeReal(ISequentialInStream *anInStream, - ISequentialOutStream *anOutStream, - const UINT64 *anInSize, const UINT64 *anOutSize) -{ - if (anOutSize == NULL) - return E_INVALIDARG; - - Init(anInStream, anOutStream); - - CState aState; - aState.Init(); - bool aPeviousIsMatch = false; - BYTE aPreviousByte = 0; - UINT32 aRepDistances[kNumRepDistances]; - for(UINT32 i = 0 ; i < kNumRepDistances; i++) - aRepDistances[i] = 0; - - UINT64 aNowPos64 = 0; - UINT64 aSize = *anOutSize; - while(aNowPos64 < aSize) - { - UINT64 aNext = MyMin(aNowPos64 + (1 << 18), aSize); - while(aNowPos64 < aNext) - { - UINT32 aPosState = UINT32(aNowPos64) & m_PosStateMask; - if (m_MainChoiceDecoders[aState.m_Index][aPosState].Decode(&m_RangeDecoder) == (UINT32) kMainChoiceLiteralIndex) - { - // aCounts[0]++; - aState.UpdateChar(); - if(aPeviousIsMatch) - { - BYTE aMatchByte = m_OutWindowStream.GetOneByte(0 - aRepDistances[0] - 1); - aPreviousByte = m_LiteralDecoder.DecodeWithMatchByte(&m_RangeDecoder, - UINT32(aNowPos64), aPreviousByte, aMatchByte); - aPeviousIsMatch = false; - } - else - aPreviousByte = m_LiteralDecoder.DecodeNormal(&m_RangeDecoder, - UINT32(aNowPos64), aPreviousByte); - m_OutWindowStream.PutOneByte(aPreviousByte); - aNowPos64++; - } - else - { - aPeviousIsMatch = true; - UINT32 aDistance, aLen; - if(m_MatchChoiceDecoders[aState.m_Index].Decode(&m_RangeDecoder) == - (UINT32) kMatchChoiceRepetitionIndex) - { - if(m_MatchRepChoiceDecoders[aState.m_Index].Decode(&m_RangeDecoder) == 0) - { - if(m_MatchRepShortChoiceDecoders[aState.m_Index][aPosState].Decode(&m_RangeDecoder) == 0) - { - aState.UpdateShortRep(); - aPreviousByte = m_OutWindowStream.GetOneByte(0 - aRepDistances[0] - 1); - m_OutWindowStream.PutOneByte(aPreviousByte); - aNowPos64++; - // aCounts[3 + 4]++; - continue; - } - // aCounts[3 + 0]++; - aDistance = aRepDistances[0]; - } - else - { - if(m_MatchRep1ChoiceDecoders[aState.m_Index].Decode(&m_RangeDecoder) == 0) - { - aDistance = aRepDistances[1]; - aRepDistances[1] = aRepDistances[0]; - // aCounts[3 + 1]++; - } - else - { - if (m_MatchRep2ChoiceDecoders[aState.m_Index].Decode(&m_RangeDecoder) == 0) - { - // aCounts[3 + 2]++; - aDistance = aRepDistances[2]; - } - else - { - // aCounts[3 + 3]++; - aDistance = aRepDistances[3]; - aRepDistances[3] = aRepDistances[2]; - } - aRepDistances[2] = aRepDistances[1]; - aRepDistances[1] = aRepDistances[0]; - } - aRepDistances[0] = aDistance; - } - aLen = m_RepMatchLenDecoder.Decode(&m_RangeDecoder, aPosState) + kMatchMinLen; - // aCounts[aLen]++; - aState.UpdateRep(); - } - else - { - aLen = kMatchMinLen + m_LenDecoder.Decode(&m_RangeDecoder, aPosState); - aState.UpdateMatch(); - UINT32 aPosSlot = m_PosSlotDecoder[GetLenToPosState(aLen)].Decode(&m_RangeDecoder); - // aCounts[aPosSlot]++; - if (aPosSlot >= (UINT32) kStartPosModelIndex) - { - aDistance = kDistStart[aPosSlot]; - if (aPosSlot < (UINT32) kEndPosModelIndex) - aDistance += m_PosDecoders[aPosSlot - kStartPosModelIndex].Decode(&m_RangeDecoder); - else - { - aDistance += (m_RangeDecoder.DecodeDirectBits(kDistDirectBits[aPosSlot] - - kNumAlignBits) << kNumAlignBits); - aDistance += m_PosAlignDecoder.Decode(&m_RangeDecoder); - } - } - else - aDistance = aPosSlot; - - - aRepDistances[3] = aRepDistances[2]; - aRepDistances[2] = aRepDistances[1]; - aRepDistances[1] = aRepDistances[0]; - - aRepDistances[0] = aDistance; - // UpdateStat(aLen, aPosSlot); - } - if (aDistance >= aNowPos64) - throw E_INVALIDDATA; - m_OutWindowStream.CopyBackBlock(aDistance, aLen); - aNowPos64 += aLen; - aPreviousByte = m_OutWindowStream.GetOneByte(0 - 1); - } - } - } - return Flush(); -} - -HRESULT CDecoder::Code(ISequentialInStream *anInStream, ISequentialOutStream *anOutStream, const UINT64 *anInSize, const UINT64 *anOutSize) -{ - try { - return CodeReal(anInStream, anOutStream, anInSize, anOutSize); - } catch (HRESULT& e) { - return e; - } catch (...) { - return E_FAIL; - } -} - -HRESULT CDecoder::ReadCoderProperties(ISequentialInStream *anInStream) -{ - UINT32 aNumPosStateBits; - UINT32 aLiteralPosStateBits; - UINT32 aLiteralContextBits; - UINT32 aDictionarySize; - - UINT32 aProcessesedSize; - - BYTE aByte; - RETURN_IF_NOT_S_OK(anInStream->Read(&aByte, sizeof(aByte), &aProcessesedSize)); - if (aProcessesedSize != sizeof(aByte)) - return E_INVALIDARG; - - aLiteralContextBits = aByte % 9; - BYTE aRemainder = aByte / 9; - aLiteralPosStateBits = aRemainder % 5; - aNumPosStateBits = aRemainder / 5; - - UINT8 uint_buffer[UINT_SIZE]; - RETURN_IF_NOT_S_OK(anInStream->Read(uint_buffer, sizeof(aDictionarySize), &aProcessesedSize)); - aDictionarySize = charp_to_uint(uint_buffer); - - if (aProcessesedSize != sizeof(aDictionarySize)) - return E_INVALIDARG; - - RETURN_IF_NOT_S_OK(SetDictionarySize(aDictionarySize)); - RETURN_IF_NOT_S_OK(SetLiteralProperties(aLiteralPosStateBits, aLiteralContextBits)); - RETURN_IF_NOT_S_OK(SetPosBitsProperties(aNumPosStateBits)); - - return S_OK; -} - -}} diff --git a/snesreader/libjma/portable.h b/snesreader/libjma/portable.h deleted file mode 100644 index 12416c7f..00000000 --- a/snesreader/libjma/portable.h +++ /dev/null @@ -1,83 +0,0 @@ -/* -Copyright (C) 2004-2007 NSRT Team ( http://nsrt.edgeemu.com ) -Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net ) - -This program is free software; you can redistribute it and/or -modify it under the terms of the GNU General Public License -version 2 as published by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License for more details. - -You 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 __PORTABLE_H -#define __PORTABLE_H - -#include - -typedef signed char INT8; -typedef unsigned char UINT8; -typedef short INT16; -typedef unsigned short UINT16; -typedef long INT32; -typedef unsigned long UINT32; -typedef long long INT64; -typedef unsigned long long UINT64; - -typedef UINT8 BYTE; -typedef UINT16 WORD; -typedef UINT32 DWORD; - -typedef unsigned UINT_PTR; - -typedef int BOOL; -#define FALSE 0 -#define TRUE 1 - -#define HRESULT int -#define S_OK 0 -#define E_INVALIDARG -1 -#define E_OUTOFMEMORY -2 -#define E_FAIL -3 -#define E_INTERNAL_ERROR -4 -#define E_INVALIDDATA -5 - -template inline T MyMin(T a, T b) { - return a < b ? a : b; -} - -template inline T MyMax(T a, T b) { - return a > b ? a : b; -} - -#define RETURN_IF_NOT_S_OK(x) { HRESULT __aResult_ = (x); if(__aResult_ != S_OK) return __aResult_; } - - -#define UINT_SIZE (4) -#define USHORT_SIZE (2) - -//Convert an array of 4 bytes back into an integer -inline unsigned int charp_to_uint(const unsigned char buffer[UINT_SIZE]) -{ - unsigned int num = (unsigned int)buffer[3]; - num |= ((unsigned int)buffer[2]) << 8; - num |= ((unsigned int)buffer[1]) << 16; - num |= ((unsigned int)buffer[0]) << 24; - return(num); -} - -//Convert an array of 2 bytes back into a short integer -inline unsigned short charp_to_ushort(const unsigned char buffer[USHORT_SIZE]) -{ - unsigned short num = (unsigned short)buffer[1]; - num |= ((unsigned short)buffer[0]) << 8; - return(num); -} - -#endif diff --git a/snesreader/libjma/rcdefs.h b/snesreader/libjma/rcdefs.h deleted file mode 100644 index 6106b57a..00000000 --- a/snesreader/libjma/rcdefs.h +++ /dev/null @@ -1,60 +0,0 @@ -/* -Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net ) -Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org ) - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License version 2.1 as published by the Free Software Foundation. - -This library is distributed in the hope that 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 library; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef __RCDEFS_H -#define __RCDEFS_H - -#include "aribitcd.h" -#include "ariconst.h" - -#define RC_INIT_VAR \ - UINT32 aRange = aRangeDecoder->m_Range; \ - UINT32 aCode = aRangeDecoder->m_Code; - -#define RC_FLUSH_VAR \ - aRangeDecoder->m_Range = aRange; \ - aRangeDecoder->m_Code = aCode; - -#define RC_NORMALIZE \ - if (aRange < NCompression::NArithmetic::kTopValue) \ - { \ - aCode = (aCode << 8) | aRangeDecoder->m_Stream.ReadByte(); \ - aRange <<= 8; } - -#define RC_GETBIT2(aNumMoveBits, aProb, aModelIndex, Action0, Action1) \ - {UINT32 aNewBound = (aRange >> NCompression::NArithmetic::kNumBitModelTotalBits) * aProb; \ - if (aCode < aNewBound) \ - { \ - Action0; \ - aRange = aNewBound; \ - aProb += (NCompression::NArithmetic::kBitModelTotal - aProb) >> aNumMoveBits; \ - aModelIndex <<= 1; \ - } \ - else \ - { \ - Action1; \ - aRange -= aNewBound; \ - aCode -= aNewBound; \ - aProb -= (aProb) >> aNumMoveBits; \ - aModelIndex = (aModelIndex << 1) + 1; \ - }} \ - RC_NORMALIZE - -#define RC_GETBIT(aNumMoveBits, aProb, aModelIndex) RC_GETBIT2(aNumMoveBits, aProb, aModelIndex, ; , ;) - -#endif diff --git a/snesreader/libjma/rngcoder.h b/snesreader/libjma/rngcoder.h deleted file mode 100644 index 711c2de8..00000000 --- a/snesreader/libjma/rngcoder.h +++ /dev/null @@ -1,143 +0,0 @@ -/* -Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net ) -Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org ) - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License version 2.1 as published by the Free Software Foundation. - -This library is distributed in the hope that 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 library; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef __COMPRESSION_RANGECODER_H -#define __COMPRESSION_RANGECODER_H - -#include "inbyte.h" - -namespace NCompression { -namespace NArithmetic { - -const UINT32 kNumTopBits = 24; -const UINT32 kTopValue = (1 << kNumTopBits); - -class CRangeDecoder -{ -public: - NStream::CInByte m_Stream; - UINT32 m_Range; - UINT32 m_Code; - UINT32 m_Word; - void Normalize() - { - while (m_Range < kTopValue) - { - m_Code = (m_Code << 8) | m_Stream.ReadByte(); - m_Range <<= 8; - } - } - - void Init(ISequentialInStream *aStream) - { - m_Stream.Init(aStream); - m_Code = 0; - m_Range = UINT32(-1); - for(int i = 0; i < 5; i++) - m_Code = (m_Code << 8) | m_Stream.ReadByte(); - } - - UINT32 GetThreshold(UINT32 aTotal) - { - return (m_Code) / ( m_Range /= aTotal); - } - - void Decode(UINT32 aStart, UINT32 aSize, UINT32 aTotal) - { - m_Code -= aStart * m_Range; - m_Range *= aSize; - Normalize(); - } - - /* - UINT32 DecodeDirectBitsDiv(UINT32 aNumTotalBits) - { - m_Range >>= aNumTotalBits; - UINT32 aThreshold = m_Code / m_Range; - m_Code -= aThreshold * m_Range; - - Normalize(); - return aThreshold; - } - - UINT32 DecodeDirectBitsDiv2(UINT32 aNumTotalBits) - { - if (aNumTotalBits <= kNumBottomBits) - return DecodeDirectBitsDiv(aNumTotalBits); - UINT32 aResult = DecodeDirectBitsDiv(aNumTotalBits - kNumBottomBits) << kNumBottomBits; - return (aResult | DecodeDirectBitsDiv(kNumBottomBits)); - } - */ - - UINT32 DecodeDirectBits(UINT32 aNumTotalBits) - { - UINT32 aRange = m_Range; - UINT32 aCode = m_Code; - UINT32 aResult = 0; - for (UINT32 i = aNumTotalBits; i > 0; i--) - { - aRange >>= 1; - /* - aResult <<= 1; - if (aCode >= aRange) - { - aCode -= aRange; - aResult |= 1; - } - */ - UINT32 t = (aCode - aRange) >> 31; - aCode -= aRange & (t - 1); - // aRange = aRangeTmp + ((aRange & 1) & (1 - t)); - aResult = (aResult << 1) | (1 - t); - - if (aRange < kTopValue) - { - aCode = (aCode << 8) | m_Stream.ReadByte(); - aRange <<= 8; - } - } - m_Range = aRange; - m_Code = aCode; - return aResult; - } - - UINT32 DecodeBit(UINT32 aSize0, UINT32 aNumTotalBits) - { - UINT32 aNewBound = (m_Range >> aNumTotalBits) * aSize0; - UINT32 aSymbol; - if (m_Code < aNewBound) - { - aSymbol = 0; - m_Range = aNewBound; - } - else - { - aSymbol = 1; - m_Code -= aNewBound; - m_Range -= aNewBound; - } - Normalize(); - return aSymbol; - } - - UINT64 GetProcessedSize() {return m_Stream.GetProcessedSize(); } -}; - -}} - -#endif diff --git a/snesreader/libjma/winout.cpp b/snesreader/libjma/winout.cpp deleted file mode 100644 index 1f33885c..00000000 --- a/snesreader/libjma/winout.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/* -Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net ) -Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org ) - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License version 2.1 as published by the Free Software Foundation. - -This library is distributed in the hope that 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 library; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include "winout.h" - -namespace NStream { -namespace NWindow { - -void COut::Create(UINT32 aKeepSizeBefore, UINT32 aKeepSizeAfter, UINT32 aKeepSizeReserv) -{ - m_Pos = 0; - m_PosLimit = aKeepSizeReserv + aKeepSizeBefore; - m_KeepSizeBefore = aKeepSizeBefore; - m_KeepSizeAfter = aKeepSizeAfter; - m_KeepSizeReserv = aKeepSizeReserv; - m_StreamPos = 0; - m_MoveFrom = m_KeepSizeReserv; - m_WindowSize = aKeepSizeBefore; - UINT32 aBlockSize = m_KeepSizeBefore + m_KeepSizeAfter + m_KeepSizeReserv; - delete []m_Buffer; - m_Buffer = new BYTE[aBlockSize]; -} - -COut::~COut() -{ - delete []m_Buffer; -} - -void COut::SetWindowSize(UINT32 aWindowSize) -{ - m_WindowSize = aWindowSize; - m_MoveFrom = m_KeepSizeReserv + m_KeepSizeBefore - aWindowSize; -} - -void COut::Init(ISequentialOutStream *aStream, bool aSolid) -{ - m_Stream = aStream; - - if(aSolid) - m_StreamPos = m_Pos; - else - { - m_Pos = 0; - m_PosLimit = m_KeepSizeReserv + m_KeepSizeBefore; - m_StreamPos = 0; - } -} - -HRESULT COut::Flush() -{ - UINT32 aSize = m_Pos - m_StreamPos; - if(aSize == 0) - return S_OK; - UINT32 aProcessedSize; - HRESULT aResult = m_Stream->Write(m_Buffer + m_StreamPos, aSize, &aProcessedSize); - if (aResult != S_OK) - return aResult; - if (aSize != aProcessedSize) - return E_FAIL; - m_StreamPos = m_Pos; - return S_OK; -} - -void COut::MoveBlockBackward() -{ - HRESULT aResult = Flush(); - if (aResult != S_OK) - throw aResult; - memmove(m_Buffer, m_Buffer + m_MoveFrom, m_WindowSize + m_KeepSizeAfter); - m_Pos -= m_MoveFrom; - m_StreamPos -= m_MoveFrom; -} - -}} diff --git a/snesreader/libjma/winout.h b/snesreader/libjma/winout.h deleted file mode 100644 index 1f6d7e33..00000000 --- a/snesreader/libjma/winout.h +++ /dev/null @@ -1,90 +0,0 @@ -/* -Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net ) -Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org ) - -This library is free software; you can redistribute it and/or -modify it under the terms of the GNU Lesser General Public -License version 2.1 as published by the Free Software Foundation. - -This library is distributed in the hope that 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 library; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#ifndef __STREAM_WINDOWOUT_H -#define __STREAM_WINDOWOUT_H - -#include "iiostrm.h" - -namespace NStream { -namespace NWindow { - -// m_KeepSizeBefore: how mach BYTEs must be in buffer before m_Pos; -// m_KeepSizeAfter: how mach BYTEs must be in buffer after m_Pos; -// m_KeepSizeReserv: how mach BYTEs must be in buffer for Moving Reserv; -// must be >= aKeepSizeAfter; // test it - -class COut -{ - BYTE *m_Buffer; - UINT32 m_Pos; - UINT32 m_PosLimit; - UINT32 m_KeepSizeBefore; - UINT32 m_KeepSizeAfter; - UINT32 m_KeepSizeReserv; - UINT32 m_StreamPos; - - UINT32 m_WindowSize; - UINT32 m_MoveFrom; - - ISequentialOutStream *m_Stream; - - virtual void MoveBlockBackward(); -public: - COut(): m_Buffer(0), m_Stream(0) {} - virtual ~COut(); - void Create(UINT32 aKeepSizeBefore, - UINT32 aKeepSizeAfter, UINT32 aKeepSizeReserv = (1<<17)); - void SetWindowSize(UINT32 aWindowSize); - - void Init(ISequentialOutStream *aStream, bool aSolid = false); - HRESULT Flush(); - - UINT32 GetCurPos() const { return m_Pos; } - const BYTE *GetPointerToCurrentPos() const { return m_Buffer + m_Pos;}; - - void CopyBackBlock(UINT32 aDistance, UINT32 aLen) - { - if (m_Pos >= m_PosLimit) - MoveBlockBackward(); - BYTE *p = m_Buffer + m_Pos; - aDistance++; - BYTE *p2 = p - aDistance; - for(UINT32 i = 0; i < aLen; i++) - p[i] = p2[i]; - m_Pos += aLen; - } - - void PutOneByte(BYTE aByte) - { - if (m_Pos >= m_PosLimit) - MoveBlockBackward(); - m_Buffer[m_Pos++] = aByte; - } - - BYTE GetOneByte(UINT32 anIndex) const - { - return m_Buffer[m_Pos + anIndex]; - } - - BYTE *GetBuffer() const { return m_Buffer; } -}; - -}} - -#endif diff --git a/snesreader/micro-bunzip/micro-bunzip.c b/snesreader/micro-bunzip/micro-bunzip.c deleted file mode 100644 index e7f6f7dc..00000000 --- a/snesreader/micro-bunzip/micro-bunzip.c +++ /dev/null @@ -1,515 +0,0 @@ -/* vi: set sw=4 ts=4: */ -/* micro-bunzip, a small, simple bzip2 decompression implementation. - Copyright 2003 by Rob Landley (rob@landley.net). - - Based on bzip2 decompression code by Julian R Seward (jseward@acm.org), - which also acknowledges contributions by Mike Burrows, David Wheeler, - Peter Fenwick, Alistair Moffat, Radford Neal, Ian H. Witten, - Robert Sedgewick, and Jon L. Bentley. - - I hereby release this code under the GNU Library General Public License - (LGPL) version 2, available at http://www.gnu.org/copyleft/lgpl.html -*/ - -#include -#include -#include -#include -#include - -/* Constants for huffman coding */ -#define MAX_GROUPS 6 -#define GROUP_SIZE 50 /* 64 would have been more efficient */ -#define MAX_HUFCODE_BITS 20 /* Longest huffman code allowed */ -#define MAX_SYMBOLS 258 /* 256 literals + RUNA + RUNB */ -#define SYMBOL_RUNA 0 -#define SYMBOL_RUNB 1 - -/* Status return values */ -#define RETVAL_OK 0 -#define RETVAL_LAST_BLOCK (-1) -#define RETVAL_NOT_BZIP_DATA (-2) -#define RETVAL_UNEXPECTED_INPUT_EOF (-3) -#define RETVAL_UNEXPECTED_OUTPUT_EOF (-4) -#define RETVAL_DATA_ERROR (-5) -#define RETVAL_OUT_OF_MEMORY (-6) -#define RETVAL_OBSOLETE_INPUT (-7) - -/* Other housekeeping constants */ -#define IOBUF_SIZE 4096 - -char *bunzip_errors[]={NULL,"Bad file checksum","Not bzip data", - "Unexpected input EOF","Unexpected output EOF","Data error", - "Out of memory","Obsolete (pre 0.9.5) bzip format not supported."}; - -/* This is what we know about each huffman coding group */ -struct group_data { - int limit[MAX_HUFCODE_BITS],base[MAX_HUFCODE_BITS],permute[MAX_SYMBOLS]; - char minLen, maxLen; -}; - -/* Structure holding all the housekeeping data, including IO buffers and - memory that persists between calls to bunzip */ -typedef struct { - /* For I/O error handling */ - jmp_buf jmpbuf; - /* Input stream, input buffer, input bit buffer */ - int in_fd,inbufCount,inbufPos; - unsigned char *inbuf; - unsigned int inbufBitCount, inbufBits; - /* Output buffer */ - char outbuf[IOBUF_SIZE]; - int outbufPos; - /* The CRC values stored in the block header and calculated from the data */ - unsigned int crc32Table[256],headerCRC, dataCRC, totalCRC; - /* Intermediate buffer and its size (in bytes) */ - unsigned int *dbuf, dbufSize; - /* State for interrupting output loop */ - int writePos,writeRun,writeCount,writeCurrent; - - /* These things are a bit too big to go on the stack */ - unsigned char selectors[32768]; /* nSelectors=15 bits */ - struct group_data groups[MAX_GROUPS]; /* huffman coding tables */ -} bunzip_data; - -/* Return the next nnn bits of input. All reads from the compressed input - are done through this function. All reads are big endian */ -static unsigned int get_bits(bunzip_data *bd, char bits_wanted) -{ - unsigned int bits=0; - - /* If we need to get more data from the byte buffer, do so. (Loop getting - one byte at a time to enforce endianness and avoid unaligned access.) */ - while (bd->inbufBitCountinbufPos==bd->inbufCount) { - if(!(bd->inbufCount = read(bd->in_fd, bd->inbuf, IOBUF_SIZE))) - longjmp(bd->jmpbuf,RETVAL_UNEXPECTED_INPUT_EOF); - bd->inbufPos=0; - } - /* Avoid 32-bit overflow (dump bit buffer to top of output) */ - if(bd->inbufBitCount>=24) { - bits=bd->inbufBits&((1<inbufBitCount)-1); - bits_wanted-=bd->inbufBitCount; - bits<<=bits_wanted; - bd->inbufBitCount=0; - } - /* Grab next 8 bits of input from buffer. */ - bd->inbufBits=(bd->inbufBits<<8)|bd->inbuf[bd->inbufPos++]; - bd->inbufBitCount+=8; - } - /* Calculate result */ - bd->inbufBitCount-=bits_wanted; - bits|=(bd->inbufBits>>bd->inbufBitCount)&((1<headerCRC=get_bits(bd,32); - /* Is this the last block (with CRC for file)? */ - if(!strcmp(mtfSymbol,"\x17\x72\x45\x38\x50\x90")) - return RETVAL_LAST_BLOCK; - /* If it's not a valid data block, barf. */ - if(strcmp(mtfSymbol,"\x31\x41\x59\x26\x53\x59")) - return RETVAL_NOT_BZIP_DATA; - - dbuf=bd->dbuf; - dbufSize=bd->dbufSize; - selectors=bd->selectors; - /* We can add support for blockRandomised if anybody complains. There was - some code for this in busybox 1.0.0-pre3, but nobody ever noticed that - it didn't actually work. */ - if(get_bits(bd,1)) return RETVAL_OBSOLETE_INPUT; - if((origPtr=get_bits(bd,24)) > dbufSize) return RETVAL_DATA_ERROR; - /* mapping table: if some byte values are never used (encoding things - like ascii text), the compression code removes the gaps to have fewer - symbols to deal with, and writes a sparse bitfield indicating which - values were present. We make a translation table to convert the symbols - back to the corresponding bytes. */ - t=get_bits(bd, 16); - memset(symToByte,0,256); - symTotal=0; - for (i=0;i<16;i++) { - if(t&(1<<(15-i))) { - k=get_bits(bd,16); - for(j=0;j<16;j++) - if(k&(1<<(15-j))) symToByte[symTotal++]=(16*i)+j; - } - } - /* How many different huffman coding groups does this block use? */ - groupCount=get_bits(bd,3); - if (groupCount<2 || groupCount>MAX_GROUPS) return RETVAL_DATA_ERROR; - /* nSelectors: Every GROUP_SIZE many symbols we select a new huffman coding - group. Read in the group selector list, which is stored as MTF encoded - bit runs. */ - if(!(nSelectors=get_bits(bd, 15))) return RETVAL_DATA_ERROR; - for(i=0; i=groupCount) return RETVAL_DATA_ERROR; - /* Decode MTF to get the next selector */ - uc = mtfSymbol[j]; - memmove(mtfSymbol+1,mtfSymbol,j); - mtfSymbol[0]=selectors[i]=uc; - } - /* Read the huffman coding tables for each group, which code for symTotal - literal symbols, plus two run symbols (RUNA, RUNB) */ - symCount=symTotal+2; - for (j=0; j MAX_HUFCODE_BITS) return RETVAL_DATA_ERROR; - if(!get_bits(bd, 1)) break; - if(!get_bits(bd, 1)) t++; - else t--; - } - length[i] = t; - } - /* Find largest and smallest lengths in this group */ - minLen=maxLen=length[0]; - for(i = 1; i < symCount; i++) { - if(length[i] > maxLen) maxLen = length[i]; - else if(length[i] < minLen) minLen = length[i]; - } - /* Calculate permute[], base[], and limit[] tables from length[]. - * - * permute[] is the lookup table for converting huffman coded symbols - * into decoded symbols. base[] is the amount to subtract from the - * value of a huffman symbol of a given length when using permute[]. - * - * limit[] indicates the largest numerical value a symbol with a given - * number of bits can have. It lets us know when to stop reading. - * - * To use these, keep reading bits until value<=limit[bitcount] or - * you've read over 20 bits (error). Then the decoded symbol - * equals permute[hufcode_value-base[hufcode_bitcount]]. - */ - hufGroup=bd->groups+j; - hufGroup->minLen = minLen; - hufGroup->maxLen = maxLen; - /* Note that minLen can't be smaller than 1, so we adjust the base - and limit array pointers so we're not always wasting the first - entry. We do this again when using them (during symbol decoding).*/ - base=hufGroup->base-1; - limit=hufGroup->limit-1; - /* Calculate permute[] */ - pp = 0; - for(i=minLen;i<=maxLen;i++) - for(t=0;tpermute[pp++] = t; - /* Count cumulative symbols coded for at each bit length */ - for (i=minLen;i<=maxLen;i++) temp[i]=limit[i]=0; - for (i=0;i=nSelectors) return RETVAL_DATA_ERROR; - hufGroup=bd->groups+selectors[selector++]; - base=hufGroup->base-1; - limit=hufGroup->limit-1; - } - /* Read next huffman-coded symbol */ - i = hufGroup->minLen; - j=get_bits(bd, i); - for(;;) { - if (i > hufGroup->maxLen) return RETVAL_DATA_ERROR; - if (j <= limit[i]) break; - i++; - - j = (j << 1) | get_bits(bd,1); - } - /* Huffman decode nextSym (with bounds checking) */ - j-=base[i]; - if (j < 0 || j >= MAX_SYMBOLS) return RETVAL_DATA_ERROR; - nextSym = hufGroup->permute[j]; - /* If this is a repeated run, loop collecting data */ - if (nextSym == SYMBOL_RUNA || nextSym == SYMBOL_RUNB) { - /* If this is the start of a new run, zero out counter */ - if(!runPos) { - runPos = 1; - t = 0; - } - /* Neat trick that saves 1 symbol: instead of or-ing 0 or 1 at - each bit position, add 1 or 2 instead. For example, - 1011 is 1<<0 + 1<<1 + 2<<2. 1010 is 2<<0 + 2<<1 + 1<<2. - You can make any bit pattern that way using 1 less symbol than - the basic or 0/1 method (except all bits 0, which would use no - symbols, but a run of length 0 doesn't mean anything in this - context). Thus space is saved. */ - if (nextSym == SYMBOL_RUNA) t += runPos; - else t += 2*runPos; - runPos <<= 1; - continue; - } - /* When we hit the first non-run symbol after a run, we now know - how many times to repeat the last literal, so append that many - copies to our buffer of decoded symbols (dbuf) now. (The last - literal used is the one at the head of the mtfSymbol array.) */ - if(runPos) { - runPos=0; - if(dbufCount+t>=dbufSize) return RETVAL_DATA_ERROR; - - uc = symToByte[mtfSymbol[0]]; - byteCount[uc] += t; - while(t--) dbuf[dbufCount++]=uc; - } - /* Is this the terminating symbol? */ - if(nextSym>symTotal) break; - /* At this point, the symbol we just decoded indicates a new literal - character. Subtract one to get the position in the MTF array - at which this literal is currently to be found. (Note that the - result can't be -1 or 0, because 0 and 1 are RUNA and RUNB. - Another instance of the first symbol in the mtf array, position 0, - would have been handled as part of a run.) */ - if(dbufCount>=dbufSize) return RETVAL_DATA_ERROR; - i = nextSym - 1; - uc = mtfSymbol[i]; - memmove(mtfSymbol+1,mtfSymbol,i); - mtfSymbol[0] = uc; - uc=symToByte[uc]; - /* We have our literal byte. Save it into dbuf. */ - byteCount[uc]++; - dbuf[dbufCount++] = (unsigned int)uc; - } - /* At this point, we've finished reading huffman-coded symbols and - compressed runs from the input stream. There are dbufCount many of - them in dbuf[]. Now undo the Burrows-Wheeler transform on dbuf. - See http://dogma.net/markn/articles/bwt/bwt.htm - */ - - /* Now we know what dbufCount is, do a better sanity check on origPtr. */ - if (origPtr<0 || origPtr>=dbufCount) return RETVAL_DATA_ERROR; - /* Turn byteCount into cumulative occurrence counts of 0 to n-1. */ - j=0; - for(i=0;i<256;i++) { - k=j+byteCount[i]; - byteCount[i] = j; - j=k; - } - /* Figure out what order dbuf would be in if we sorted it. */ - for (i=0;idataCRC = 0xffffffffL; - /* Decode first byte by hand to initialize "previous" byte. Note that it - doesn't get output, and if the first three characters are identical - it doesn't qualify as a run (hence uc=255, which will either wrap - to 1 or get reset). */ - if(dbufCount) { - bd->writePos=dbuf[origPtr]; - bd->writeCurrent=(unsigned char)(bd->writePos&0xff); - bd->writePos>>=8; - bd->writeRun=-1; - } - bd->writeCount=dbufCount; - - return RETVAL_OK; -} - -/* Flush output buffer to disk */ -extern void flush_bunzip_outbuf(bunzip_data *bd, int out_fd) -{ - if(bd->outbufPos) { - if(write(out_fd, bd->outbuf, bd->outbufPos) != bd->outbufPos) - longjmp(bd->jmpbuf,RETVAL_UNEXPECTED_OUTPUT_EOF); - bd->outbufPos=0; - } -} - - -/* Undo burrows-wheeler transform on intermediate buffer to produce output. - If !len, write up to len bytes of data to buf. Otherwise write to out_fd. - Returns len ? bytes written : RETVAL_OK. Notice all errors negative #'s. */ -extern int write_bunzip_data(bunzip_data *bd, int out_fd, char *outbuf, int len) -{ - unsigned int *dbuf=bd->dbuf; - int count,pos,current, run,copies,outbyte,previous,gotcount=0; - - for(;;) { - /* If last read was short due to end of file, return last block now */ - if(bd->writeCount<0) return bd->writeCount; - /* If we need to refill dbuf, do it. */ - if(!bd->writeCount) { - int i=read_bunzip_data(bd); - if(i) { - if(i==RETVAL_LAST_BLOCK) { - bd->writeCount=i; - return gotcount; - } else return i; - } - } - /* Loop generating output */ - count=bd->writeCount; - pos=bd->writePos; - current=bd->writeCurrent; - run=bd->writeRun; - while(count) { - /* If somebody (like busybox tar) wants a certain number of bytes of - data from memory instead of written to a file, humor them */ - if(len && bd->outbufPos>=len) goto dataus_interruptus; - count--; - /* Follow sequence vector to undo Burrows-Wheeler transform */ - previous=current; - pos=dbuf[pos]; - current=pos&0xff; - pos>>=8; - /* Whenever we see 3 consecutive copies of the same byte, - the 4th is a repeat count */ - if(run++==3) { - copies=current; - outbyte=previous; - current=-1; - } else { - copies=1; - outbyte=current; - } - /* Output bytes to buffer, flushing to file if necessary */ - while(copies--) { - if(bd->outbufPos == IOBUF_SIZE) flush_bunzip_outbuf(bd,out_fd); - bd->outbuf[bd->outbufPos++] = outbyte; - bd->dataCRC = (bd->dataCRC << 8) - ^ bd->crc32Table[(bd->dataCRC >> 24) ^ outbyte]; - } - if(current!=previous) run=0; - } - /* Decompression of this block completed successfully */ - bd->dataCRC=~(bd->dataCRC); - bd->totalCRC=((bd->totalCRC << 1) | (bd->totalCRC >> 31)) ^ bd->dataCRC; - /* If this block had a CRC error, force file level CRC error. */ - if(bd->dataCRC!=bd->headerCRC) { - bd->totalCRC=bd->headerCRC+1; - return RETVAL_LAST_BLOCK; - } -dataus_interruptus: - bd->writeCount=count; - if(len) { - gotcount+=bd->outbufPos; - memcpy(outbuf,bd->outbuf,len); - /* If we got enough data, checkpoint loop state and return */ - if((len-=bd->outbufPos)<1) { - bd->outbufPos-=len; - if(bd->outbufPos) - memmove(bd->outbuf,bd->outbuf+len,bd->outbufPos); - bd->writePos=pos; - bd->writeCurrent=current; - bd->writeRun=run; - return gotcount; - } - } - } -} - -/* Allocate the structure, read file header. If !len, src_fd contains - filehandle to read from. Else inbuf contains data. */ -extern int start_bunzip(bunzip_data **bdp, int src_fd, char *inbuf, int len) -{ - bunzip_data *bd; - unsigned int i,j,c; - - /* Figure out how much data to allocate */ - i=sizeof(bunzip_data); - if(!len) i+=IOBUF_SIZE; - /* Allocate bunzip_data. Most fields initialize to zero. */ - if(!(bd=*bdp=malloc(i))) return RETVAL_OUT_OF_MEMORY; - memset(bd,0,sizeof(bunzip_data)); - if(len) { - bd->inbuf=inbuf; - bd->inbufCount=len; - bd->in_fd=-1; - } else { - bd->inbuf=(char *)(bd+1); - bd->in_fd=src_fd; - } - /* Init the CRC32 table (big endian) */ - for(i=0;i<256;i++) { - c=i<<24; - for(j=8;j;j--) - c=c&0x80000000 ? (c<<1)^0x04c11db7 : (c<<1); - bd->crc32Table[i]=c; - } - /* Setup for I/O error handling via longjmp */ - i=setjmp(bd->jmpbuf); - if(i) return i; - /* Ensure that file starts with "BZh" */ - for(i=0;i<3;i++) if(get_bits(bd,8)!="BZh"[i]) return RETVAL_NOT_BZIP_DATA; - /* Next byte ascii '1'-'9', indicates block size in units of 100k of - uncompressed data. Allocate intermediate buffer for block. */ - i=get_bits(bd,8); - if (i<'1' || i>'9') return RETVAL_NOT_BZIP_DATA; - bd->dbufSize=100000*(i-'0'); - if(!(bd->dbuf=malloc(bd->dbufSize * sizeof(int)))) - return RETVAL_OUT_OF_MEMORY; - return RETVAL_OK; -} - -/* Example usage: decompress src_fd to dst_fd. (Stops at end of bzip data, - not end of file.) */ -extern char *uncompressStream(int src_fd, int dst_fd) -{ - bunzip_data *bd; - int i; - - if(!(i=start_bunzip(&bd,src_fd,0,0))) { - i=write_bunzip_data(bd,dst_fd,0,0); - if(i==RETVAL_LAST_BLOCK && bd->headerCRC==bd->totalCRC) i=RETVAL_OK; - } - flush_bunzip_outbuf(bd,dst_fd); - if(bd->dbuf) free(bd->dbuf); - free(bd); - return bunzip_errors[-i]; -} - -/* Dumb little test thing, decompress stdin to stdout */ -/*int main(int argc, char *argv[]) -{ - char *c=uncompressStream(0,1); - fprintf(stderr,"\n%s\n", c ? c : "Completed OK"); -}*/ diff --git a/snesreader/nall/Makefile b/snesreader/nall/Makefile deleted file mode 100644 index 8149bf15..00000000 --- a/snesreader/nall/Makefile +++ /dev/null @@ -1,107 +0,0 @@ -# Makefile -# author: byuu -# license: public domain - -[A-Z] = A B C D E F G H I J K L M N O P Q R S T U V W X Y Z -[a-z] = a b c d e f g h i j k l m n o p q r s t u v w x y z -[0-9] = 0 1 2 3 4 5 6 7 8 9 -[markup] = ` ~ ! @ \# $$ % ^ & * ( ) - _ = + [ { ] } \ | ; : ' " , < . > / ? -[all] = $([A-Z]) $([a-z]) $([0-9]) $([markup]) -[space] := -[space] += - -##### -# platform detection -##### - -ifeq ($(platform),) - uname := $(shell uname -a) - ifeq ($(uname),) - platform := win - delete = del $(subst /,\,$1) - else ifneq ($(findstring Darwin,$(uname)),) - platform := osx - delete = rm -f $1 - else - platform := x - delete = rm -f $1 - endif -endif - -ifeq ($(compiler),) - ifeq ($(platform),osx) - compiler := gcc-4.2 - else - compiler := gcc - endif -endif - -ifeq ($(prefix),) - prefix := /usr/local -endif - -##### -# function rwildcard(directory, pattern) -##### -rwildcard = \ - $(strip \ - $(filter $(if $2,$2,%), \ - $(foreach f, \ - $(wildcard $1*), \ - $(eval t = $(call rwildcard,$f/)) \ - $(if $t,$t,$f) \ - ) \ - ) \ - ) - -##### -# function strtr(source, from, to) -##### -strtr = \ - $(eval __temp := $1) \ - $(strip \ - $(foreach c, \ - $(join $(addsuffix :,$2),$3), \ - $(eval __temp := \ - $(subst $(word 1,$(subst :, ,$c)),$(word 2,$(subst :, ,$c)),$(__temp)) \ - ) \ - ) \ - $(__temp) \ - ) - -##### -# function strupper(source) -##### -strupper = $(call strtr,$1,$([a-z]),$([A-Z])) - -##### -# function strlower(source) -##### -strlower = $(call strtr,$1,$([A-Z]),$([a-z])) - -##### -# function strlen(source) -##### -strlen = \ - $(eval __temp := $(subst $([space]),_,$1)) \ - $(words \ - $(strip \ - $(foreach c, \ - $([all]), \ - $(eval __temp := \ - $(subst $c,$c ,$(__temp)) \ - ) \ - ) \ - $(__temp) \ - ) \ - ) - -##### -# function streq(source) -##### -streq = $(if $(filter-out xx,x$(subst $1,,$2)$(subst $2,,$1)x),,1) - -##### -# function strne(source) -##### -strne = $(if $(filter-out xx,x$(subst $1,,$2)$(subst $2,,$1)x),1,) diff --git a/snesreader/nall/algorithm.hpp b/snesreader/nall/algorithm.hpp deleted file mode 100644 index cdc48dcf..00000000 --- a/snesreader/nall/algorithm.hpp +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef NALL_ALGORITHM_HPP -#define NALL_ALGORITHM_HPP - -#undef min -#undef max - -namespace nall { - template T min(const T &t, const U &u) { - return t < u ? t : u; - } - - template T max(const T &t, const U &u) { - return t > u ? t : u; - } - - //pseudo-random number generator - inline unsigned prng() { - static unsigned n = 0; - return n = (n >> 1) ^ (((n & 1) - 1) & 0xedb88320); - } -} - -#endif diff --git a/snesreader/nall/any.hpp b/snesreader/nall/any.hpp deleted file mode 100644 index b31cff3c..00000000 --- a/snesreader/nall/any.hpp +++ /dev/null @@ -1,74 +0,0 @@ -#ifndef NALL_ANY_HPP -#define NALL_ANY_HPP - -#include -#include -#include - -namespace nall { - class any { - public: - bool empty() const { return container; } - const std::type_info& type() const { return container ? container->type() : typeid(void); } - - template any& operator=(const T& value_) { - typedef typename static_if< - std::is_array::value, - typename std::remove_extent::type>::type*, - T - >::type auto_t; - - if(type() == typeid(auto_t)) { - static_cast*>(container)->value = (auto_t)value_; - } else { - if(container) delete container; - container = new holder((auto_t)value_); - } - - return *this; - } - - any() : container(0) {} - template any(const T& value_) : container(0) { operator=(value_); } - - private: - struct placeholder { - virtual const std::type_info& type() const = 0; - } *container; - - template struct holder : placeholder { - T value; - const std::type_info& type() const { return typeid(T); } - holder(const T& value_) : value(value_) {} - }; - - template friend T any_cast(any&); - template friend T any_cast(const any&); - template friend T* any_cast(any*); - template friend const T* any_cast(const any*); - }; - - template T any_cast(any &value) { - typedef typename std::remove_reference::type nonref; - if(value.type() != typeid(nonref)) throw; - return static_cast*>(value.container)->value; - } - - template T any_cast(const any &value) { - typedef const typename std::remove_reference::type nonref; - if(value.type() != typeid(nonref)) throw; - return static_cast*>(value.container)->value; - } - - template T* any_cast(any *value) { - if(!value || value->type() != typeid(T)) return 0; - return &static_cast*>(value->container)->value; - } - - template const T* any_cast(const any *value) { - if(!value || value->type() != typeid(T)) return 0; - return &static_cast*>(value->container)->value; - } -} - -#endif diff --git a/snesreader/nall/array.hpp b/snesreader/nall/array.hpp deleted file mode 100644 index c1d33fd1..00000000 --- a/snesreader/nall/array.hpp +++ /dev/null @@ -1,120 +0,0 @@ -#ifndef NALL_ARRAY_HPP -#define NALL_ARRAY_HPP - -#include -#include -#include -#include -#include -#include -#include - -namespace nall { - //dynamic vector array - //neither constructor nor destructor is ever invoked; - //thus, this should only be used for POD objects. - template class array { - protected: - T *pool; - unsigned poolsize, buffersize; - - public: - unsigned size() const { return buffersize; } - unsigned capacity() const { return poolsize; } - - void reset() { - if(pool) free(pool); - pool = 0; - poolsize = 0; - buffersize = 0; - } - - void reserve(unsigned newsize) { - if(newsize == poolsize) return; - - pool = (T*)realloc(pool, newsize * sizeof(T)); - poolsize = newsize; - buffersize = min(buffersize, newsize); - } - - void resize(unsigned newsize) { - if(newsize > poolsize) reserve(bit::round(newsize)); //round reserve size up to power of 2 - buffersize = newsize; - } - - T* get(unsigned minsize = 0) { - if(minsize > buffersize) resize(minsize); - if(minsize > buffersize) throw "array[] out of bounds"; - return pool; - } - - void add(const T data) { - operator[](buffersize) = data; - } - - signed find(const T data) { - for(unsigned i = 0; i < size(); i++) if(pool[i] == data) return i; - return -1; //not found - } - - void clear() { - memset(pool, 0, buffersize * sizeof(T)); - } - - array() : pool(0), poolsize(0), buffersize(0) { - } - - array(std::initializer_list list) : pool(0), poolsize(0), buffersize(0) { - for(const T *p = list.begin(); p != list.end(); ++p) add(*p); - } - - ~array() { - reset(); - } - - //copy - array& operator=(const array &source) { - if(pool) free(pool); - buffersize = source.buffersize; - poolsize = source.poolsize; - pool = (T*)malloc(sizeof(T) * poolsize); //allocate entire pool size, - memcpy(pool, source.pool, sizeof(T) * buffersize); //... but only copy used pool objects - return *this; - } - - array(const array &source) : pool(0), poolsize(0), buffersize(0) { - operator=(source); - } - - //move - array& operator=(array &&source) { - if(pool) free(pool); - pool = source.pool; - poolsize = source.poolsize; - buffersize = source.buffersize; - source.pool = 0; - source.reset(); - return *this; - } - - array(array &&source) : pool(0), poolsize(0), buffersize(0) { - operator=(std::move(source)); - } - - //index - inline T& operator[](unsigned index) { - if(index >= buffersize) resize(index + 1); - if(index >= buffersize) throw "array[] out of bounds"; - return pool[index]; - } - - inline const T& operator[](unsigned index) const { - if(index >= buffersize) throw "array[] out of bounds"; - return pool[index]; - } - }; - - template struct has_size> { enum { value = true }; }; -} - -#endif diff --git a/snesreader/nall/base64.hpp b/snesreader/nall/base64.hpp deleted file mode 100644 index e41c87b7..00000000 --- a/snesreader/nall/base64.hpp +++ /dev/null @@ -1,90 +0,0 @@ -#ifndef NALL_BASE64_HPP -#define NALL_BASE64_HPP - -#include -#include - -namespace nall { - class base64 { - public: - static bool encode(char *&output, const uint8_t* input, unsigned inlength) { - output = new char[inlength * 8 / 6 + 6](); - - unsigned i = 0, o = 0; - while(i < inlength) { - switch(i % 3) { - case 0: { - output[o++] = enc(input[i] >> 2); - output[o] = enc((input[i] & 3) << 4); - } break; - - case 1: { - uint8_t prev = dec(output[o]); - output[o++] = enc(prev + (input[i] >> 4)); - output[o] = enc((input[i] & 15) << 2); - } break; - - case 2: { - uint8_t prev = dec(output[o]); - output[o++] = enc(prev + (input[i] >> 6)); - output[o++] = enc(input[i] & 63); - } break; - } - - i++; - } - - return true; - } - - static bool decode(uint8_t *&output, unsigned &outlength, const char *input) { - unsigned inlength = strlen(input), infix = 0; - output = new uint8_t[inlength](); - - unsigned i = 0, o = 0; - while(i < inlength) { - uint8_t x = dec(input[i]); - - switch(i++ & 3) { - case 0: { - output[o] = x << 2; - } break; - - case 1: { - output[o++] |= x >> 4; - output[o] = (x & 15) << 4; - } break; - - case 2: { - output[o++] |= x >> 2; - output[o] = (x & 3) << 6; - } break; - - case 3: { - output[o++] |= x; - } break; - } - } - - outlength = o; - return true; - } - - private: - static char enc(uint8_t n) { - static char lookup_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; - return lookup_table[n & 63]; - } - - static uint8_t dec(char n) { - if(n >= 'A' && n <= 'Z') return n - 'A'; - if(n >= 'a' && n <= 'z') return n - 'a' + 26; - if(n >= '0' && n <= '9') return n - '0' + 52; - if(n == '-') return 62; - if(n == '_') return 63; - return 0; - } - }; -} - -#endif diff --git a/snesreader/nall/bit.hpp b/snesreader/nall/bit.hpp deleted file mode 100644 index 169fc144..00000000 --- a/snesreader/nall/bit.hpp +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef NALL_BIT_HPP -#define NALL_BIT_HPP - -namespace nall { - template inline unsigned uclamp(const unsigned x) { - enum { y = (1U << bits) - 1 }; - return y + ((x - y) & -(x < y)); //min(x, y); - } - - template inline unsigned uclip(const unsigned x) { - enum { m = (1U << bits) - 1 }; - return (x & m); - } - - template inline signed sclamp(const signed x) { - enum { b = 1U << (bits - 1), m = (1U << (bits - 1)) - 1 }; - return (x > m) ? m : (x < -b) ? -b : x; - } - - template inline signed sclip(const signed x) { - enum { b = 1U << (bits - 1), m = (1U << bits) - 1 }; - return ((x & m) ^ b) - b; - } - - namespace bit { - //lowest(0b1110) == 0b0010 - template inline T lowest(const T x) { - return x & -x; - } - - //clear_lowest(0b1110) == 0b1100 - template inline T clear_lowest(const T x) { - return x & (x - 1); - } - - //set_lowest(0b0101) == 0b0111 - template inline T set_lowest(const T x) { - return x | (x + 1); - } - - //round up to next highest single bit: - //round(15) == 16, round(16) == 16, round(17) == 32 - inline unsigned round(unsigned x) { - if((x & (x - 1)) == 0) return x; - while(x & (x - 1)) x &= x - 1; - return x << 1; - } - } -} - -#endif diff --git a/snesreader/nall/concept.hpp b/snesreader/nall/concept.hpp deleted file mode 100644 index 2949cd5e..00000000 --- a/snesreader/nall/concept.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef NALL_CONCEPT_HPP -#define NALL_CONCEPT_HPP - -namespace nall { - //unsigned count() const; - template struct has_count { enum { value = false }; }; - - //unsigned length() const; - template struct has_length { enum { value = false }; }; - - //unsigned size() const; - template struct has_size { enum { value = false }; }; -} - -#endif diff --git a/snesreader/nall/config.hpp b/snesreader/nall/config.hpp deleted file mode 100644 index 31ae4e00..00000000 --- a/snesreader/nall/config.hpp +++ /dev/null @@ -1,124 +0,0 @@ -#ifndef NALL_CONFIG_HPP -#define NALL_CONFIG_HPP - -#include -#include -#include - -namespace nall { - namespace configuration_traits { - template struct is_boolean { enum { value = false }; }; - template<> struct is_boolean { enum { value = true }; }; - - template struct is_signed { enum { value = false }; }; - template<> struct is_signed { enum { value = true }; }; - - template struct is_unsigned { enum { value = false }; }; - template<> struct is_unsigned { enum { value = true }; }; - - template struct is_double { enum { value = false }; }; - template<> struct is_double { enum { value = true }; }; - - template struct is_string { enum { value = false }; }; - template<> struct is_string { enum { value = true }; }; - } - - class configuration { - public: - enum type_t { boolean_t, signed_t, unsigned_t, double_t, string_t, unknown_t }; - struct item_t { - uintptr_t data; - string name; - string desc; - type_t type; - - string get() const { - switch(type) { - case boolean_t: return string() << *(bool*)data; - case signed_t: return string() << *(signed*)data; - case unsigned_t: return string() << *(unsigned*)data; - case double_t: return string() << *(double*)data; - case string_t: return string() << "\"" << *(string*)data << "\""; - } - return "???"; - } - - void set(string s) { - switch(type) { - case boolean_t: *(bool*)data = (s == "true"); break; - case signed_t: *(signed*)data = strsigned(s); break; - case unsigned_t: *(unsigned*)data = strunsigned(s); break; - case double_t: *(double*)data = strdouble(s); break; - case string_t: trim(s, "\""); *(string*)data = s; break; - } - } - }; - linear_vector list; - - template - void attach(T &data, const char *name, const char *desc = "") { - unsigned n = list.size(); - list[n].data = (uintptr_t)&data; - list[n].name = name; - list[n].desc = desc; - - if(configuration_traits::is_boolean::value) list[n].type = boolean_t; - else if(configuration_traits::is_signed::value) list[n].type = signed_t; - else if(configuration_traits::is_unsigned::value) list[n].type = unsigned_t; - else if(configuration_traits::is_double::value) list[n].type = double_t; - else if(configuration_traits::is_string::value) list[n].type = string_t; - else list[n].type = unknown_t; - } - - virtual bool load(const char *filename) { - string data; - if(data.readfile(filename) == true) { - data.replace("\r", ""); - lstring line; - line.split("\n", data); - - for(unsigned i = 0; i < line.size(); i++) { - int position = qstrpos(line[i], "#"); - if(position >= 0) line[i][position] = 0; - if(qstrpos(line[i], " = ") < 0) continue; - - lstring part; - part.qsplit(" = ", line[i]); - trim(part[0]); - trim(part[1]); - - for(unsigned n = 0; n < list.size(); n++) { - if(part[0] == list[n].name) { - list[n].set(part[1]); - break; - } - } - } - - return true; - } else { - return false; - } - } - - virtual bool save(const char *filename) const { - file fp; - if(fp.open(filename, file::mode_write)) { - for(unsigned i = 0; i < list.size(); i++) { - string output; - output << list[i].name << " = " << list[i].get(); - if(list[i].desc != "") output << " # " << list[i].desc; - output << "\r\n"; - fp.print(output); - } - - fp.close(); - return true; - } else { - return false; - } - } - }; -} - -#endif diff --git a/snesreader/nall/crc32.hpp b/snesreader/nall/crc32.hpp deleted file mode 100644 index ad36fbf6..00000000 --- a/snesreader/nall/crc32.hpp +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef NALL_CRC32_HPP -#define NALL_CRC32_HPP - -#include - -namespace nall { - const uint32_t crc32_table[256] = { - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, - 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, - 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, - 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, - 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, - 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, - 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, - 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, - 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, - 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, - 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, - 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, - 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, - 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, - 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, - 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, - 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, - 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, - 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, - 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, - 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, - 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, - 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, - 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, - 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, - 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, - 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, - 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, - 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, - 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, - 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, - 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, - 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, - 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, - 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, - 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, - 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, - 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, - 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, - 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d - }; - - inline uint32_t crc32_adjust(uint32_t crc32, uint8_t input) { - return ((crc32 >> 8) & 0x00ffffff) ^ crc32_table[(crc32 ^ input) & 0xff]; - } - - inline uint32_t crc32_calculate(const uint8_t *data, unsigned length) { - uint32_t crc32 = ~0; - for(unsigned i = 0; i < length; i++) { - crc32 = crc32_adjust(crc32, data[i]); - } - return ~crc32; - } -} - -#endif diff --git a/snesreader/nall/detect.hpp b/snesreader/nall/detect.hpp deleted file mode 100644 index b4991aaf..00000000 --- a/snesreader/nall/detect.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef NALL_DETECT_HPP -#define NALL_DETECT_HPP - -/* Compiler detection */ - -#if defined(__GNUC__) - #define COMPILER_GCC -#elif defined(_MSC_VER) - #define COMPILER_VISUALC -#endif - -/* Platform detection */ - -#if defined(_WIN32) - #define PLATFORM_WIN -#elif defined(__APPLE__) - #define PLATFORM_OSX -#elif defined(linux) || defined(__sun__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) - #define PLATFORM_X -#endif - -/* Endian detection */ - -#if defined(__i386__) || defined(__amd64__) || defined(_M_IX86) || defined(_M_AMD64) - #define ARCH_LSB -#elif defined(__powerpc__) || defined(_M_PPC) || defined(__BIG_ENDIAN__) - #define ARCH_MSB -#endif - -#endif diff --git a/snesreader/nall/dictionary.hpp b/snesreader/nall/dictionary.hpp deleted file mode 100644 index f14e2095..00000000 --- a/snesreader/nall/dictionary.hpp +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef NALL_DICTIONARY_HPP -#define NALL_DICTIONARY_HPP - -#include -#include -#include - -namespace nall { - class dictionary { - public: - string operator[](const char *input) { - for(unsigned i = 0; i < index_input.size(); i++) { - if(index_input[i] == input) return index_output[i]; - } - - //no match, use input; remove input identifier, if one exists - if(strbegin(input, "{{")) { - int pos = strpos(input, "}}"); - if(pos >= 0) { - string temp = substr(input, pos + 2); - return temp; - } - } - - return input; - } - - bool import(const char *filename) { - string data; - if(data.readfile(filename) == false) return false; - ltrim_once(data, "\xef\xbb\xbf"); //remove UTF-8 marker, if it exists - data.replace("\r", ""); - - lstring line; - line.split("\n", data); - for(unsigned i = 0; i < line.size(); i++) { - lstring part; - //format: "Input" = "Output" - part.qsplit("=", line[i]); - if(part.size() != 2) continue; - - //remove whitespace - trim(part[0]); - trim(part[1]); - - //remove quotes - trim_once(part[0], "\""); - trim_once(part[1], "\""); - - unsigned n = index_input.size(); - index_input[n] = part[0]; - index_output[n] = part[1]; - } - - return true; - } - - void reset() { - index_input.reset(); - index_output.reset(); - } - - ~dictionary() { - reset(); - } - - dictionary& operator=(const dictionary&) = delete; - dictionary(const dictionary&) = delete; - - protected: - lstring index_input; - lstring index_output; - }; -} - -#endif diff --git a/snesreader/nall/dl.hpp b/snesreader/nall/dl.hpp deleted file mode 100644 index 22acf51f..00000000 --- a/snesreader/nall/dl.hpp +++ /dev/null @@ -1,119 +0,0 @@ -#ifndef NALL_DL_HPP -#define NALL_DL_HPP - -//dynamic linking support - -#include -#include -#include -#include - -#if defined(PLATFORM_X) || defined(PLATFORM_OSX) - #include -#elif defined(PLATFORM_WIN) - #include - #include -#endif - -namespace nall { - struct library { - bool opened() const { return handle; } - bool open(const char*); - void* sym(const char*); - void close(); - - library() : handle(0) {} - ~library() { close(); } - - library& operator=(const library&) = delete; - library(const library&) = delete; - - private: - uintptr_t handle; - }; - - #if defined(PLATFORM_X) - inline bool library::open(const char *name) { - if(handle) close(); - char *t = new char[strlen(name) + 256]; - strcpy(t, "lib"); - strcat(t, name); - strcat(t, ".so"); - handle = (uintptr_t)dlopen(t, RTLD_LAZY); - if(!handle) { - strcpy(t, "/usr/local/lib/lib"); - strcat(t, name); - strcat(t, ".so"); - handle = (uintptr_t)dlopen(t, RTLD_LAZY); - } - delete[] t; - return handle; - } - - inline void* library::sym(const char *name) { - if(!handle) return 0; - return dlsym((void*)handle, name); - } - - inline void library::close() { - if(!handle) return; - dlclose((void*)handle); - handle = 0; - } - #elif defined(PLATFORM_OSX) - inline bool library::open(const char *name) { - if(handle) close(); - char *t = new char[strlen(name) + 256]; - strcpy(t, "lib"); - strcat(t, name); - strcat(t, ".dylib"); - handle = (uintptr_t)dlopen(t, RTLD_LAZY); - if(!handle) { - strcpy(t, "/usr/local/lib/lib"); - strcat(t, name); - strcat(t, ".dylib"); - handle = (uintptr_t)dlopen(t, RTLD_LAZY); - } - delete[] t; - return handle; - } - - inline void* library::sym(const char *name) { - if(!handle) return 0; - return dlsym((void*)handle, name); - } - - inline void library::close() { - if(!handle) return; - dlclose((void*)handle); - handle = 0; - } - #elif defined(PLATFORM_WIN) - inline bool library::open(const char *name) { - if(handle) close(); - char *t = new char[strlen(name) + 8]; - strcpy(t, name); - strcat(t, ".dll"); - handle = (uintptr_t)LoadLibraryW(utf16_t(t)); - delete[] t; - return handle; - } - - inline void* library::sym(const char *name) { - if(!handle) return 0; - return (void*)GetProcAddress((HMODULE)handle, name); - } - - inline void library::close() { - if(!handle) return; - FreeLibrary((HMODULE)handle); - handle = 0; - } - #else - inline bool library::open(const char*) { return false; } - inline void* library::sym(const char*) { return 0; } - inline void library::close() {} - #endif -}; - -#endif diff --git a/snesreader/nall/endian.hpp b/snesreader/nall/endian.hpp deleted file mode 100644 index 40d15633..00000000 --- a/snesreader/nall/endian.hpp +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef NALL_ENDIAN_HPP -#define NALL_ENDIAN_HPP - -#if !defined(ARCH_MSB) - //little-endian: uint8_t[] { 0x01, 0x02, 0x03, 0x04 } == 0x04030201 - #define order_lsb2(a,b) a,b - #define order_lsb3(a,b,c) a,b,c - #define order_lsb4(a,b,c,d) a,b,c,d - #define order_lsb5(a,b,c,d,e) a,b,c,d,e - #define order_lsb6(a,b,c,d,e,f) a,b,c,d,e,f - #define order_lsb7(a,b,c,d,e,f,g) a,b,c,d,e,f,g - #define order_lsb8(a,b,c,d,e,f,g,h) a,b,c,d,e,f,g,h - #define order_msb2(a,b) b,a - #define order_msb3(a,b,c) c,b,a - #define order_msb4(a,b,c,d) d,c,b,a - #define order_msb5(a,b,c,d,e) e,d,c,b,a - #define order_msb6(a,b,c,d,e,f) f,e,d,c,b,a - #define order_msb7(a,b,c,d,e,f,g) g,f,e,d,c,b,a - #define order_msb8(a,b,c,d,e,f,g,h) h,g,f,e,d,c,b,a -#else - //big-endian: uint8_t[] { 0x01, 0x02, 0x03, 0x04 } == 0x01020304 - #define order_lsb2(a,b) b,a - #define order_lsb3(a,b,c) c,b,a - #define order_lsb4(a,b,c,d) d,c,b,a - #define order_lsb5(a,b,c,d,e) e,d,c,b,a - #define order_lsb6(a,b,c,d,e,f) f,e,d,c,b,a - #define order_lsb7(a,b,c,d,e,f,g) g,f,e,d,c,b,a - #define order_lsb8(a,b,c,d,e,f,g,h) h,g,f,e,d,c,b,a - #define order_msb2(a,b) a,b - #define order_msb3(a,b,c) a,b,c - #define order_msb4(a,b,c,d) a,b,c,d - #define order_msb5(a,b,c,d,e) a,b,c,d,e - #define order_msb6(a,b,c,d,e,f) a,b,c,d,e,f - #define order_msb7(a,b,c,d,e,f,g) a,b,c,d,e,f,g - #define order_msb8(a,b,c,d,e,f,g,h) a,b,c,d,e,f,g,h -#endif - -#endif diff --git a/snesreader/nall/file.hpp b/snesreader/nall/file.hpp deleted file mode 100644 index 4c8ca8ee..00000000 --- a/snesreader/nall/file.hpp +++ /dev/null @@ -1,259 +0,0 @@ -#ifndef NALL_FILE_HPP -#define NALL_FILE_HPP - -#include -#include - -#if !defined(_WIN32) - #include -#else - #include -#endif - -#include -#include -#include - -namespace nall { - inline FILE* fopen_utf8(const char *utf8_filename, const char *mode) { - #if !defined(_WIN32) - return fopen(utf8_filename, mode); - #else - return _wfopen(utf16_t(utf8_filename), utf16_t(mode)); - #endif - } - - class file { - public: - enum FileMode { mode_read, mode_write, mode_readwrite, mode_writeread }; - enum SeekMode { seek_absolute, seek_relative }; - - uint8_t read() { - if(!fp) return 0xff; //file not open - if(file_mode == mode_write) return 0xff; //reads not permitted - if(file_offset >= file_size) return 0xff; //cannot read past end of file - buffer_sync(); - return buffer[(file_offset++) & buffer_mask]; - } - - uintmax_t readl(unsigned length = 1) { - uintmax_t data = 0; - for(int i = 0; i < length; i++) { - data |= (uintmax_t)read() << (i << 3); - } - return data; - } - - uintmax_t readm(unsigned length = 1) { - uintmax_t data = 0; - while(length--) { - data <<= 8; - data |= read(); - } - return data; - } - - void read(uint8_t *buffer, unsigned length) { - while(length--) *buffer++ = read(); - } - - void write(uint8_t data) { - if(!fp) return; //file not open - if(file_mode == mode_read) return; //writes not permitted - buffer_sync(); - buffer[(file_offset++) & buffer_mask] = data; - buffer_dirty = true; - if(file_offset > file_size) file_size = file_offset; - } - - void writel(uintmax_t data, unsigned length = 1) { - while(length--) { - write(data); - data >>= 8; - } - } - - void writem(uintmax_t data, unsigned length = 1) { - for(int i = length - 1; i >= 0; i--) { - write(data >> (i << 3)); - } - } - - void write(const uint8_t *buffer, unsigned length) { - while(length--) write(*buffer++); - } - - void print(const char *string) { - if(!string) return; - while(*string) write(*string++); - } - - void flush() { - buffer_flush(); - fflush(fp); - } - - void seek(int offset, SeekMode mode = seek_absolute) { - if(!fp) return; //file not open - buffer_flush(); - - uintmax_t req_offset = file_offset; - switch(mode) { - case seek_absolute: req_offset = offset; break; - case seek_relative: req_offset += offset; break; - } - - if(req_offset < 0) req_offset = 0; //cannot seek before start of file - if(req_offset > file_size) { - if(file_mode == mode_read) { //cannot seek past end of file - req_offset = file_size; - } else { //pad file to requested location - file_offset = file_size; - while(file_size < req_offset) write(0x00); - } - } - - file_offset = req_offset; - } - - int offset() { - if(!fp) return -1; //file not open - return file_offset; - } - - int size() { - if(!fp) return -1; //file not open - return file_size; - } - - bool truncate(unsigned size) { - if(!fp) return false; //file not open - #if !defined(_WIN32) - return ftruncate(fileno(fp), size) == 0; - #else - return _chsize(fileno(fp), size) == 0; - #endif - } - - bool end() { - if(!fp) return true; //file not open - return file_offset >= file_size; - } - - static bool exists(const char *fn) { - #if !defined(_WIN32) - FILE *fp = fopen(fn, "rb"); - #else - FILE *fp = _wfopen(utf16_t(fn), L"rb"); - #endif - if(fp) { - fclose(fp); - return true; - } - return false; - } - - static unsigned size(const char *fn) { - #if !defined(_WIN32) - FILE *fp = fopen(fn, "rb"); - #else - FILE *fp = _wfopen(utf16_t(fn), L"rb"); - #endif - unsigned filesize = 0; - if(fp) { - fseek(fp, 0, SEEK_END); - filesize = ftell(fp); - fclose(fp); - } - return filesize; - } - - bool open() { - return fp; - } - - bool open(const char *fn, FileMode mode) { - if(fp) return false; - - switch(file_mode = mode) { - #if !defined(_WIN32) - case mode_read: fp = fopen(fn, "rb"); break; - case mode_write: fp = fopen(fn, "wb+"); break; //need read permission for buffering - case mode_readwrite: fp = fopen(fn, "rb+"); break; - case mode_writeread: fp = fopen(fn, "wb+"); break; - #else - case mode_read: fp = _wfopen(utf16_t(fn), L"rb"); break; - case mode_write: fp = _wfopen(utf16_t(fn), L"wb+"); break; - case mode_readwrite: fp = _wfopen(utf16_t(fn), L"rb+"); break; - case mode_writeread: fp = _wfopen(utf16_t(fn), L"wb+"); break; - #endif - } - if(!fp) return false; - buffer_offset = -1; //invalidate buffer - file_offset = 0; - fseek(fp, 0, SEEK_END); - file_size = ftell(fp); - fseek(fp, 0, SEEK_SET); - return true; - } - - void close() { - if(!fp) return; - buffer_flush(); - fclose(fp); - fp = 0; - } - - file() { - memset(buffer, 0, sizeof buffer); - buffer_offset = -1; - buffer_dirty = false; - fp = 0; - file_offset = 0; - file_size = 0; - file_mode = mode_read; - } - - ~file() { - close(); - } - - file& operator=(const file&) = delete; - file(const file&) = delete; - - private: - enum { buffer_size = 1 << 12, buffer_mask = buffer_size - 1 }; - char buffer[buffer_size]; - int buffer_offset; - bool buffer_dirty; - FILE *fp; - unsigned file_offset; - unsigned file_size; - FileMode file_mode; - - void buffer_sync() { - if(!fp) return; //file not open - if(buffer_offset != (file_offset & ~buffer_mask)) { - buffer_flush(); - buffer_offset = file_offset & ~buffer_mask; - fseek(fp, buffer_offset, SEEK_SET); - unsigned length = (buffer_offset + buffer_size) <= file_size ? buffer_size : (file_size & buffer_mask); - if(length) unsigned unused = fread(buffer, 1, length, fp); - } - } - - void buffer_flush() { - if(!fp) return; //file not open - if(file_mode == mode_read) return; //buffer cannot be written to - if(buffer_offset < 0) return; //buffer unused - if(buffer_dirty == false) return; //buffer unmodified since read - fseek(fp, buffer_offset, SEEK_SET); - unsigned length = (buffer_offset + buffer_size) <= file_size ? buffer_size : (file_size & buffer_mask); - if(length) unsigned unused = fwrite(buffer, 1, length, fp); - buffer_offset = -1; //invalidate buffer - buffer_dirty = false; - } - }; -} - -#endif diff --git a/snesreader/nall/filemap.hpp b/snesreader/nall/filemap.hpp deleted file mode 100644 index a05f0eb7..00000000 --- a/snesreader/nall/filemap.hpp +++ /dev/null @@ -1,190 +0,0 @@ -#ifndef NALL_FILEMAP_HPP -#define NALL_FILEMAP_HPP - -#include -#include - -#include -#include -#if defined(_WIN32) - #include -#else - #include - #include - #include - #include - #include -#endif - -namespace nall { - class filemap { - public: - enum filemode { mode_read, mode_write, mode_readwrite, mode_writeread }; - - bool open(const char *filename, filemode mode) { return p_open(filename, mode); } - void close() { return p_close(); } - unsigned size() const { return p_size; } - uint8_t* handle() { return p_handle; } - const uint8_t* handle() const { return p_handle; } - filemap() : p_size(0), p_handle(0) { p_ctor(); } - ~filemap() { p_dtor(); } - - private: - unsigned p_size; - uint8_t *p_handle; - - #if defined(_WIN32) - //============= - //MapViewOfFile - //============= - - HANDLE p_filehandle, p_maphandle; - - bool p_open(const char *filename, filemode mode) { - int desired_access, creation_disposition, flprotect, map_access; - - switch(mode) { - default: return false; - case mode_read: - desired_access = GENERIC_READ; - creation_disposition = OPEN_EXISTING; - flprotect = PAGE_READONLY; - map_access = FILE_MAP_READ; - break; - case mode_write: - //write access requires read access - desired_access = GENERIC_WRITE; - creation_disposition = CREATE_ALWAYS; - flprotect = PAGE_READWRITE; - map_access = FILE_MAP_ALL_ACCESS; - break; - case mode_readwrite: - desired_access = GENERIC_READ | GENERIC_WRITE; - creation_disposition = OPEN_EXISTING; - flprotect = PAGE_READWRITE; - map_access = FILE_MAP_ALL_ACCESS; - break; - case mode_writeread: - desired_access = GENERIC_READ | GENERIC_WRITE; - creation_disposition = CREATE_NEW; - flprotect = PAGE_READWRITE; - map_access = FILE_MAP_ALL_ACCESS; - break; - } - - p_filehandle = CreateFileW(utf16_t(filename), desired_access, FILE_SHARE_READ, NULL, - creation_disposition, FILE_ATTRIBUTE_NORMAL, NULL); - if(p_filehandle == INVALID_HANDLE_VALUE) return false; - - p_size = GetFileSize(p_filehandle, NULL); - - p_maphandle = CreateFileMapping(p_filehandle, NULL, flprotect, 0, p_size, NULL); - if(p_maphandle == INVALID_HANDLE_VALUE) { - CloseHandle(p_filehandle); - p_filehandle = INVALID_HANDLE_VALUE; - return false; - } - - p_handle = (uint8_t*)MapViewOfFile(p_maphandle, map_access, 0, 0, p_size); - return p_handle; - } - - void p_close() { - if(p_handle) { - UnmapViewOfFile(p_handle); - p_handle = 0; - } - - if(p_maphandle != INVALID_HANDLE_VALUE) { - CloseHandle(p_maphandle); - p_maphandle = INVALID_HANDLE_VALUE; - } - - if(p_filehandle != INVALID_HANDLE_VALUE) { - CloseHandle(p_filehandle); - p_filehandle = INVALID_HANDLE_VALUE; - } - } - - void p_ctor() { - p_filehandle = INVALID_HANDLE_VALUE; - p_maphandle = INVALID_HANDLE_VALUE; - } - - void p_dtor() { - close(); - } - - #else - //==== - //mmap - //==== - - int p_fd; - - bool p_open(const char *filename, filemode mode) { - int open_flags, mmap_flags; - - switch(mode) { - default: return false; - case mode_read: - open_flags = O_RDONLY; - mmap_flags = PROT_READ; - break; - case mode_write: - open_flags = O_RDWR | O_CREAT; //mmap() requires read access - mmap_flags = PROT_WRITE; - break; - case mode_readwrite: - open_flags = O_RDWR; - mmap_flags = PROT_READ | PROT_WRITE; - break; - case mode_writeread: - open_flags = O_RDWR | O_CREAT; - mmap_flags = PROT_READ | PROT_WRITE; - break; - } - - p_fd = ::open(filename, open_flags); - if(p_fd < 0) return false; - - struct stat p_stat; - fstat(p_fd, &p_stat); - p_size = p_stat.st_size; - - p_handle = (uint8_t*)mmap(0, p_size, mmap_flags, MAP_SHARED, p_fd, 0); - if(p_handle == MAP_FAILED) { - p_handle = 0; - ::close(p_fd); - p_fd = -1; - return false; - } - - return p_handle; - } - - void p_close() { - if(p_handle) { - munmap(p_handle, p_size); - p_handle = 0; - } - - if(p_fd >= 0) { - ::close(p_fd); - p_fd = -1; - } - } - - void p_ctor() { - p_fd = -1; - } - - void p_dtor() { - p_close(); - } - - #endif - }; -} - -#endif diff --git a/snesreader/nall/foreach.hpp b/snesreader/nall/foreach.hpp deleted file mode 100644 index ea975b84..00000000 --- a/snesreader/nall/foreach.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef NALL_FOREACH_HPP -#define NALL_FOREACH_HPP - -#undef foreach -#define foreach(iter, object) \ - for(unsigned foreach_counter = 0, foreach_limit = foreach_size(object), foreach_once = 0, foreach_broken = 0; foreach_counter < foreach_limit && foreach_broken == 0; foreach_counter++, foreach_once = 0) \ - for(auto &iter = object[foreach_counter]; foreach_once == 0 && (foreach_broken = 1); foreach_once++, foreach_broken = 0) - -#include -#include -#include - -namespace nall { - template unsigned foreach_size(const T& object, typename mp_enable_if>::type = 0) { - return object.count(); - } - - template unsigned foreach_size(const T& object, typename mp_enable_if>::type = 0) { - return object.length(); - } - - template unsigned foreach_size(const T& object, typename mp_enable_if>::type = 0) { - return object.size(); - } - - template unsigned foreach_size(const T& object, typename mp_enable_if>::type = 0) { - return sizeof(T) / sizeof(typename std::remove_extent::type); - } -} - -#endif diff --git a/snesreader/nall/function.hpp b/snesreader/nall/function.hpp deleted file mode 100644 index 3f0f704e..00000000 --- a/snesreader/nall/function.hpp +++ /dev/null @@ -1,102 +0,0 @@ -#ifndef NALL_FUNCTION_HPP -#define NALL_FUNCTION_HPP - -#include -#include - -namespace nall { - template class function; - - template - class function { - private: - struct base1 { virtual void func1(P...) {} }; - struct base2 { virtual void func2(P...) {} }; - struct derived : base1, virtual base2 {}; - - struct data_t { - R (*callback)(const data_t&, P...); - union { - R (*callback_global)(P...); - struct { - R (derived::*callback_member)(P...); - void *object; - }; - }; - } data; - - static R callback_global(const data_t &data, P... p) { - return data.callback_global(p...); - } - - template - static R callback_member(const data_t &data, P... p) { - return (((C*)data.object)->*((R (C::*&)(P...))data.callback_member))(p...); - } - - public: - R operator()(P... p) const { return data.callback(data, p...); } - operator bool() const { return data.callback; } - void reset() { data.callback = 0; } - - function& operator=(const function &source) { memcpy(&data, &source.data, sizeof(data_t)); return *this; } - function(const function &source) { operator=(source); } - - //no pointer - function() { - data.callback = 0; - } - - //symbolic link pointer (nall/dl.hpp::sym, etc) - function(void *callback) { - data.callback = callback ? &callback_global : 0; - data.callback_global = (R (*)(P...))callback; - } - - //global function pointer - function(R (*callback)(P...)) { - data.callback = &callback_global; - data.callback_global = callback; - } - - //member function pointer - template - function(R (C::*callback)(P...), C *object) { - static_assert(sizeof data.callback_member >= sizeof callback, "callback_member is too small"); - data.callback = &callback_member; - (R (C::*&)(P...))data.callback_member = callback; - data.object = object; - } - - //const member function pointer - template - function(R (C::*callback)(P...) const, C *object) { - static_assert(sizeof data.callback_member >= sizeof callback, "callback_member is too small"); - data.callback = &callback_member; - (R (C::*&)(P...))data.callback_member = (R (C::*&)(P...))callback; - data.object = object; - } - - //lambda function pointer - template - function(T callback) { - static_assert(std::is_same::type>::value, "lambda mismatch"); - data.callback = &callback_global; - data.callback_global = (R (*)(P...))callback; - } - }; - - //bind functions to ease construction and assignment of function() with more than one argument - - template - function bind(R (C::*callback)(P...), C *object) { - return function(callback, object); - } - - template - function bind(R (C::*callback)(P...) const, C *object) { - return function(callback, object); - } -} - -#endif diff --git a/snesreader/nall/input.hpp b/snesreader/nall/input.hpp deleted file mode 100644 index b3ce9ebf..00000000 --- a/snesreader/nall/input.hpp +++ /dev/null @@ -1,386 +0,0 @@ -#ifndef NALL_INPUT_HPP -#define NALL_INPUT_HPP - -#include -#include -#include - -#include -#include - -namespace nall { - -struct Keyboard; -Keyboard& keyboard(unsigned = 0); - -static const char KeyboardScancodeName[][64] = { - "Escape", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", - "PrintScreen", "ScrollLock", "Pause", "Tilde", - "Num1", "Num2", "Num3", "Num4", "Num5", "Num6", "Num7", "Num8", "Num9", "Num0", - "Dash", "Equal", "Backspace", - "Insert", "Delete", "Home", "End", "PageUp", "PageDown", - "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", - "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", - "LeftBracket", "RightBracket", "Backslash", "Semicolon", "Apostrophe", "Comma", "Period", "Slash", - "Keypad1", "Keypad2", "Keypad3", "Keypad4", "Keypad5", "Keypad6", "Keypad7", "Keypad8", "Keypad9", "Keypad0", - "Point", "Enter", "Add", "Subtract", "Multiply", "Divide", - "NumLock", "CapsLock", - "Up", "Down", "Left", "Right", - "Tab", "Return", "Spacebar", "Menu", - "Shift", "Control", "Alt", "Super", -}; - -struct Keyboard { - const unsigned ID; - enum { Base = 1 }; - enum { Count = 8, Size = 128 }; - - enum Scancode { - Escape, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, - PrintScreen, ScrollLock, Pause, Tilde, - Num1, Num2, Num3, Num4, Num5, Num6, Num7, Num8, Num9, Num0, - Dash, Equal, Backspace, - Insert, Delete, Home, End, PageUp, PageDown, - A, B, C, D, E, F, G, H, I, J, K, L, M, - N, O, P, Q, R, S, T, U, V, W, X, Y, Z, - LeftBracket, RightBracket, Backslash, Semicolon, Apostrophe, Comma, Period, Slash, - Keypad1, Keypad2, Keypad3, Keypad4, Keypad5, Keypad6, Keypad7, Keypad8, Keypad9, Keypad0, - Point, Enter, Add, Subtract, Multiply, Divide, - NumLock, CapsLock, - Up, Down, Left, Right, - Tab, Return, Spacebar, Menu, - Shift, Control, Alt, Super, - Limit, - }; - - static signed numberDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(keyboard(i).belongsTo(scancode)) return i; - } - return -1; - } - - static signed keyDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(keyboard(i).isKey(scancode)) return scancode - keyboard(i).key(Escape); - } - return -1; - } - - static signed modifierDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(keyboard(i).isModifier(scancode)) return scancode - keyboard(i).key(Shift); - } - return -1; - } - - static bool isAnyKey(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(keyboard(i).isKey(scancode)) return true; - } - return false; - } - - static bool isAnyModifier(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(keyboard(i).isModifier(scancode)) return true; - } - return false; - } - - static uint16_t decode(const char *name) { - string s(name); - if(!strbegin(name, "KB")) return 0; - ltrim(s, "KB"); - unsigned id = strunsigned(s); - int pos = strpos(s, "::"); - if(pos < 0) return 0; - s = substr(s, pos + 2); - for(unsigned i = 0; i < Limit; i++) { - if(s == KeyboardScancodeName[i]) return Base + Size * id + i; - } - return 0; - } - - string encode(uint16_t code) const { - unsigned index = 0; - for(unsigned i = 0; i < Count; i++) { - if(code >= Base + Size * i && code < Base + Size * (i + 1)) { - index = code - (Base + Size * i); - break; - } - } - return string() << "KB" << ID << "::" << KeyboardScancodeName[index]; - } - - uint16_t operator[](Scancode code) const { return Base + ID * Size + code; } - uint16_t key(unsigned id) const { return Base + Size * ID + id; } - bool isKey(unsigned id) const { return id >= key(Escape) && id <= key(Menu); } - bool isModifier(unsigned id) const { return id >= key(Shift) && id <= key(Super); } - bool belongsTo(uint16_t scancode) const { return isKey(scancode) || isModifier(scancode); } - - Keyboard(unsigned ID_) : ID(ID_) {} -}; - -inline Keyboard& keyboard(unsigned id) { - static Keyboard kb0(0), kb1(1), kb2(2), kb3(3), kb4(4), kb5(5), kb6(6), kb7(7); - switch(id) { default: - case 0: return kb0; case 1: return kb1; case 2: return kb2; case 3: return kb3; - case 4: return kb4; case 5: return kb5; case 6: return kb6; case 7: return kb7; - } -} - -static const char MouseScancodeName[][64] = { - "Xaxis", "Yaxis", "Zaxis", - "Button0", "Button1", "Button2", "Button3", "Button4", "Button5", "Button6", "Button7", -}; - -struct Mouse; -Mouse& mouse(unsigned = 0); - -struct Mouse { - const unsigned ID; - enum { Base = Keyboard::Base + Keyboard::Size * Keyboard::Count }; - enum { Count = 8, Size = 16 }; - enum { Axes = 3, Buttons = 8 }; - - enum Scancode { - Xaxis, Yaxis, Zaxis, - Button0, Button1, Button2, Button3, Button4, Button5, Button6, Button7, - Limit, - }; - - static signed numberDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(mouse(i).belongsTo(scancode)) return i; - } - return -1; - } - - static signed axisDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(mouse(i).isAxis(scancode)) return scancode - mouse(i).axis(0); - } - return -1; - } - - static signed buttonDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(mouse(i).isButton(scancode)) return scancode - mouse(i).button(0); - } - return -1; - } - - static bool isAnyAxis(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(mouse(i).isAxis(scancode)) return true; - } - return false; - } - - static bool isAnyButton(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(mouse(i).isButton(scancode)) return true; - } - return false; - } - - static uint16_t decode(const char *name) { - string s(name); - if(!strbegin(name, "MS")) return 0; - ltrim(s, "MS"); - unsigned id = strunsigned(s); - int pos = strpos(s, "::"); - if(pos < 0) return 0; - s = substr(s, pos + 2); - for(unsigned i = 0; i < Limit; i++) { - if(s == MouseScancodeName[i]) return Base + Size * id + i; - } - return 0; - } - - string encode(uint16_t code) const { - unsigned index = 0; - for(unsigned i = 0; i < Count; i++) { - if(code >= Base + Size * i && code < Base + Size * (i + 1)) { - index = code - (Base + Size * i); - break; - } - } - return string() << "MS" << ID << "::" << MouseScancodeName[index]; - } - - uint16_t operator[](Scancode code) const { return Base + ID * Size + code; } - uint16_t axis(unsigned id) const { return Base + Size * ID + Xaxis + id; } - uint16_t button(unsigned id) const { return Base + Size * ID + Button0 + id; } - bool isAxis(unsigned id) const { return id >= axis(0) && id <= axis(2); } - bool isButton(unsigned id) const { return id >= button(0) && id <= button(7); } - bool belongsTo(uint16_t scancode) const { return isAxis(scancode) || isButton(scancode); } - - Mouse(unsigned ID_) : ID(ID_) {} -}; - -inline Mouse& mouse(unsigned id) { - static Mouse ms0(0), ms1(1), ms2(2), ms3(3), ms4(4), ms5(5), ms6(6), ms7(7); - switch(id) { default: - case 0: return ms0; case 1: return ms1; case 2: return ms2; case 3: return ms3; - case 4: return ms4; case 5: return ms5; case 6: return ms6; case 7: return ms7; - } -} - -static const char JoypadScancodeName[][64] = { - "Hat0", "Hat1", "Hat2", "Hat3", "Hat4", "Hat5", "Hat6", "Hat7", - "Axis0", "Axis1", "Axis2", "Axis3", "Axis4", "Axis5", "Axis6", "Axis7", - "Axis8", "Axis9", "Axis10", "Axis11", "Axis12", "Axis13", "Axis14", "Axis15", - "Button0", "Button1", "Button2", "Button3", "Button4", "Button5", "Button6", "Button7", - "Button8", "Button9", "Button10", "Button11", "Button12", "Button13", "Button14", "Button15", - "Button16", "Button17", "Button18", "Button19", "Button20", "Button21", "Button22", "Button23", - "Button24", "Button25", "Button26", "Button27", "Button28", "Button29", "Button30", "Button31", -}; - -struct Joypad; -Joypad& joypad(unsigned = 0); - -struct Joypad { - const unsigned ID; - enum { Base = Mouse::Base + Mouse::Size * Mouse::Count }; - enum { Count = 8, Size = 64 }; - enum { Hats = 8, Axes = 16, Buttons = 32 }; - - enum Scancode { - Hat0, Hat1, Hat2, Hat3, Hat4, Hat5, Hat6, Hat7, - Axis0, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7, - Axis8, Axis9, Axis10, Axis11, Axis12, Axis13, Axis14, Axis15, - Button0, Button1, Button2, Button3, Button4, Button5, Button6, Button7, - Button8, Button9, Button10, Button11, Button12, Button13, Button14, Button15, - Button16, Button17, Button18, Button19, Button20, Button21, Button22, Button23, - Button24, Button25, Button26, Button27, Button28, Button29, Button30, Button31, - Limit, - }; - - enum Hat { HatCenter = 0, HatUp = 1, HatRight = 2, HatDown = 4, HatLeft = 8 }; - - static signed numberDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(joypad(i).belongsTo(scancode)) return i; - } - return -1; - } - - static signed hatDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(joypad(i).isHat(scancode)) return scancode - joypad(i).hat(0); - } - return -1; - } - - static signed axisDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(joypad(i).isAxis(scancode)) return scancode - joypad(i).axis(0); - } - return -1; - } - - static signed buttonDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(joypad(i).isButton(scancode)) return scancode - joypad(i).button(0); - } - return -1; - } - - static bool isAnyHat(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(joypad(i).isHat(scancode)) return true; - } - return false; - } - - static bool isAnyAxis(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(joypad(i).isAxis(scancode)) return true; - } - return false; - } - - static bool isAnyButton(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(joypad(i).isButton(scancode)) return true; - } - return false; - } - - static uint16_t decode(const char *name) { - string s(name); - if(!strbegin(name, "JP")) return 0; - ltrim(s, "JP"); - unsigned id = strunsigned(s); - int pos = strpos(s, "::"); - if(pos < 0) return 0; - s = substr(s, pos + 2); - for(unsigned i = 0; i < Limit; i++) { - if(s == JoypadScancodeName[i]) return Base + Size * id + i; - } - return 0; - } - - string encode(uint16_t code) const { - unsigned index = 0; - for(unsigned i = 0; i < Count; i++) { - if(code >= Base + Size * i && code < Base + Size * (i + 1)) { - index = code - (Base + Size * i); - } - } - return string() << "JP" << ID << "::" << JoypadScancodeName[index]; - } - - uint16_t operator[](Scancode code) const { return Base + ID * Size + code; } - uint16_t hat(unsigned id) const { return Base + Size * ID + Hat0 + id; } - uint16_t axis(unsigned id) const { return Base + Size * ID + Axis0 + id; } - uint16_t button(unsigned id) const { return Base + Size * ID + Button0 + id; } - bool isHat(unsigned id) const { return id >= hat(0) && id <= hat(7); } - bool isAxis(unsigned id) const { return id >= axis(0) && id <= axis(15); } - bool isButton(unsigned id) const { return id >= button(0) && id <= button(31); } - bool belongsTo(uint16_t scancode) const { return isHat(scancode) || isAxis(scancode) || isButton(scancode); } - - Joypad(unsigned ID_) : ID(ID_) {} -}; - -inline Joypad& joypad(unsigned id) { - static Joypad jp0(0), jp1(1), jp2(2), jp3(3), jp4(4), jp5(5), jp6(6), jp7(7); - switch(id) { default: - case 0: return jp0; case 1: return jp1; case 2: return jp2; case 3: return jp3; - case 4: return jp4; case 5: return jp5; case 6: return jp6; case 7: return jp7; - } -} - -struct Scancode { - enum { None = 0, Limit = Joypad::Base + Joypad::Size * Joypad::Count }; - - static uint16_t decode(const char *name) { - uint16_t code; - code = Keyboard::decode(name); - if(code) return code; - code = Mouse::decode(name); - if(code) return code; - code = Joypad::decode(name); - if(code) return code; - return None; - } - - static string encode(uint16_t code) { - for(unsigned i = 0; i < Keyboard::Count; i++) { - if(keyboard(i).belongsTo(code)) return keyboard(i).encode(code); - } - for(unsigned i = 0; i < Mouse::Count; i++) { - if(mouse(i).belongsTo(code)) return mouse(i).encode(code); - } - for(unsigned i = 0; i < Joypad::Count; i++) { - if(joypad(i).belongsTo(code)) return joypad(i).encode(code); - } - return "None"; - } -}; - -} - -#endif diff --git a/snesreader/nall/lzss.hpp b/snesreader/nall/lzss.hpp deleted file mode 100644 index 202bc814..00000000 --- a/snesreader/nall/lzss.hpp +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef NALL_LZSS_HPP -#define NALL_LZSS_HPP - -#include -#include -#include - -namespace nall { - class lzss { - public: - static bool encode(uint8_t *&output, unsigned &outlength, const uint8_t *input, unsigned inlength) { - output = new(zeromemory) uint8_t[inlength * 9 / 8 + 9]; - - unsigned i = 0, o = 0; - while(i < inlength) { - unsigned flagoffset = o++; - uint8_t flag = 0x00; - - for(unsigned b = 0; b < 8 && i < inlength; b++) { - unsigned longest = 0, pointer; - for(unsigned index = 1; index < 4096; index++) { - unsigned count = 0; - while(true) { - if(count >= 15 + 3) break; //verify pattern match is not longer than max length - if(i + count >= inlength) break; //verify pattern match does not read past end of input - if(i + count < index) break; //verify read is not before start of input - if(input[i + count] != input[i + count - index]) break; //verify pattern still matches - count++; - } - - if(count > longest) { - longest = count; - pointer = index; - } - } - - if(longest < 3) output[o++] = input[i++]; - else { - flag |= 1 << b; - uint16_t x = ((longest - 3) << 12) + pointer; - output[o++] = x; - output[o++] = x >> 8; - i += longest; - } - } - - output[flagoffset] = flag; - } - - outlength = o; - return true; - } - - static bool decode(uint8_t *&output, const uint8_t *input, unsigned length) { - output = new(zeromemory) uint8_t[length]; - - unsigned i = 0, o = 0; - while(o < length) { - uint8_t flag = input[i++]; - - for(unsigned b = 0; b < 8 && o < length; b++) { - if(!(flag & (1 << b))) output[o++] = input[i++]; - else { - uint16_t offset = input[i++]; - offset += input[i++] << 8; - uint16_t lookuplength = (offset >> 12) + 3; - offset &= 4095; - for(unsigned index = 0; index < lookuplength && o + index < length; index++) { - output[o + index] = output[o + index - offset]; - } - o += lookuplength; - } - } - } - - return true; - } - }; -} - -#endif diff --git a/snesreader/nall/moduloarray.hpp b/snesreader/nall/moduloarray.hpp deleted file mode 100644 index be549ae9..00000000 --- a/snesreader/nall/moduloarray.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef NALL_MODULO_HPP -#define NALL_MODULO_HPP - -#include - -namespace nall { - template class modulo_array { - public: - inline T operator[](int index) const { - return buffer[size + index]; - } - - inline T read(int index) const { - return buffer[size + index]; - } - - inline void write(unsigned index, const T value) { - buffer[index] = - buffer[index + size] = - buffer[index + size + size] = value; - } - - void serialize(serializer &s) { - s.array(buffer, size * 3); - } - - modulo_array() { - buffer = new T[size * 3](); - } - - ~modulo_array() { - delete[] buffer; - } - - private: - T *buffer; - }; -} - -#endif diff --git a/snesreader/nall/platform.hpp b/snesreader/nall/platform.hpp deleted file mode 100644 index 68ed37ce..00000000 --- a/snesreader/nall/platform.hpp +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef NALL_PLATFORM_HPP -#define NALL_PLATFORM_HPP - -#include - -//========================= -//standard platform headers -//========================= - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(_WIN32) - #include - #include - #include - #undef interface -#else - #include - #include - #include -#endif - -//================== -//warning supression -//================== - -//Visual C++ -#if defined(_MSC_VER) - //disable libc "deprecation" warnings - #pragma warning(disable:4996) -#endif - -//================ -//POSIX compliance -//================ - -#if defined(_MSC_VER) - #define PATH_MAX _MAX_PATH - #define va_copy(dest, src) ((dest) = (src)) -#endif - -#if defined(_WIN32) - #define getcwd _getcwd - #define ftruncate _chsize - #define putenv _putenv - #define mkdir(n, m) _wmkdir(nall::utf16_t(n)) - #define rmdir _rmdir - #define vsnprintf _vsnprintf - #define usleep(n) Sleep(n / 1000) -#endif - -//================ -//inline expansion -//================ - -#if defined(__GNUC__) - #define noinline __attribute__((noinline)) - #define inline inline - #define alwaysinline inline __attribute__((always_inline)) -#elif defined(_MSC_VER) - #define noinline __declspec(noinline) - #define inline inline - #define alwaysinline inline __forceinline -#else - #define noinline - #define inline inline - #define alwaysinline inline -#endif - -#endif - diff --git a/snesreader/nall/priorityqueue.hpp b/snesreader/nall/priorityqueue.hpp deleted file mode 100644 index 7104e791..00000000 --- a/snesreader/nall/priorityqueue.hpp +++ /dev/null @@ -1,109 +0,0 @@ -#ifndef NALL_PRIORITYQUEUE_HPP -#define NALL_PRIORITYQUEUE_HPP - -#include -#include -#include -#include - -namespace nall { - template void priority_queue_nocallback(type_t) {} - - //priority queue implementation using binary min-heap array; - //does not require normalize() function. - //O(1) find (tick) - //O(log n) insert (enqueue) - //O(log n) remove (dequeue) - template class priority_queue { - public: - inline void tick(unsigned ticks) { - basecounter += ticks; - while(heapsize && gte(basecounter, heap[0].counter)) callback(dequeue()); - } - - //counter is relative to current time (eg enqueue(64, ...) fires in 64 ticks); - //counter cannot exceed std::numeric_limits::max() >> 1. - void enqueue(unsigned counter, type_t event) { - unsigned child = heapsize++; - counter += basecounter; - - while(child) { - unsigned parent = (child - 1) >> 1; - if(gte(counter, heap[parent].counter)) break; - - heap[child].counter = heap[parent].counter; - heap[child].event = heap[parent].event; - child = parent; - } - - heap[child].counter = counter; - heap[child].event = event; - } - - type_t dequeue() { - type_t event(heap[0].event); - unsigned parent = 0; - unsigned counter = heap[--heapsize].counter; - - while(true) { - unsigned child = (parent << 1) + 1; - if(child >= heapsize) break; - if(child + 1 < heapsize && gte(heap[child].counter, heap[child + 1].counter)) child++; - if(gte(heap[child].counter, counter)) break; - - heap[parent].counter = heap[child].counter; - heap[parent].event = heap[child].event; - parent = child; - } - - heap[parent].counter = counter; - heap[parent].event = heap[heapsize].event; - return event; - } - - void reset() { - basecounter = 0; - heapsize = 0; - } - - void serialize(serializer &s) { - s.integer(basecounter); - s.integer(heapsize); - for(unsigned n = 0; n < heapcapacity; n++) { - s.integer(heap[n].counter); - s.integer(heap[n].event); - } - } - - priority_queue(unsigned size, function callback_ = &priority_queue_nocallback) - : callback(callback_) { - heap = new heap_t[size]; - heapcapacity = size; - reset(); - } - - ~priority_queue() { - delete[] heap; - } - - priority_queue& operator=(const priority_queue&) = delete; - priority_queue(const priority_queue&) = delete; - - private: - function callback; - unsigned basecounter; - unsigned heapsize; - unsigned heapcapacity; - struct heap_t { - unsigned counter; - type_t event; - } *heap; - - //return true if x is greater than or equal to y - inline bool gte(unsigned x, unsigned y) { - return x - y < (std::numeric_limits::max() >> 1); - } - }; -} - -#endif diff --git a/snesreader/nall/property.hpp b/snesreader/nall/property.hpp deleted file mode 100644 index 6fd33acd..00000000 --- a/snesreader/nall/property.hpp +++ /dev/null @@ -1,91 +0,0 @@ -#ifndef NALL_PROPERTY_HPP -#define NALL_PROPERTY_HPP - -//nall::property implements ownership semantics into container classes -//example: property::readonly implies that only owner has full -//access to type; and all other code has readonly access. -// -//this code relies on extended friend semantics from C++0x to work, as it -//declares a friend class via a template paramter. it also exploits a bug in -//G++ 4.x to work even in C++98 mode. -// -//if compiling elsewhere, simply remove the friend class and private semantics - -//property can be used either of two ways: -//struct foo { -// property::readonly x; -// property::readwrite y; -//}; -//-or- -//struct foo : property { -// readonly x; -// readwrite y; -//}; - -//return types are const T& (byref) instead fo T (byval) to avoid major speed -//penalties for objects with expensive copy constructors - -//operator-> provides access to underlying object type: -//readonly foo; -//foo->bar(); -//... will call Object::bar(); - -//operator='s reference is constant so as to avoid leaking a reference handle -//that could bypass access restrictions - -//both constant and non-constant operators are provided, though it may be -//necessary to cast first, for instance: -//struct foo : property { readonly bar; } object; -//int main() { int value = const_cast(object); } - -//writeonly is useful for objects that have non-const reads, but const writes. -//however, to avoid leaking handles, the interface is very restricted. the only -//way to write is via operator=, which requires conversion via eg copy -//constructor. example: -//struct foo { -// foo(bool value) { ... } -//}; -//writeonly bar; -//bar = true; - -namespace nall { - template struct property { - template struct traits { typedef T type; }; - - template struct readonly { - const T* operator->() const { return &value; } - const T& operator()() const { return value; } - operator const T&() const { return value; } - private: - T* operator->() { return &value; } - operator T&() { return value; } - const T& operator=(const T& value_) { return value = value_; } - T value; - friend class traits::type; - }; - - template struct writeonly { - void operator=(const T& value_) { value = value_; } - private: - const T* operator->() const { return &value; } - const T& operator()() const { return value; } - operator const T&() const { return value; } - T* operator->() { return &value; } - operator T&() { return value; } - T value; - friend class traits::type; - }; - - template struct readwrite { - const T* operator->() const { return &value; } - const T& operator()() const { return value; } - operator const T&() const { return value; } - T* operator->() { return &value; } - operator T&() { return value; } - const T& operator=(const T& value_) { return value = value_; } - T value; - }; - }; -} - -#endif diff --git a/snesreader/nall/qt/Makefile b/snesreader/nall/qt/Makefile deleted file mode 100644 index 69e84960..00000000 --- a/snesreader/nall/qt/Makefile +++ /dev/null @@ -1,55 +0,0 @@ -# requires nall/Makefile - -# imports: -# $(qtlibs) -- list of Qt components to link against - -# exports the following symbols: -# $(moc) -- meta-object compiler -# $(rcc) -- resource compiler -# $(qtinc) -- includes for compiling -# $(qtlib) -- libraries for linking - -ifeq ($(moc),) -moc := moc -endif - -ifeq ($(rcc),) -rcc := rcc -endif - -ifeq ($(platform),x) - qtinc := `pkg-config --cflags $(qtlibs)` - qtlib := `pkg-config --libs $(qtlibs)` -else ifeq ($(platform),osx) - qtinc := $(foreach lib,$(qtlibs),-I/Library/Frameworks/$(lib).framework/Versions/4/Headers) - - qtlib := -L/Library/Frameworks - qtlib += $(foreach lib,$(qtlibs),-framework $(lib)) - qtlib += -framework Carbon - qtlib += -framework Cocoa - qtlib += -framework OpenGL - qtlib += -framework AppKit - qtlib += -framework ApplicationServices -else ifeq ($(platform),win) - ifeq ($(qtpath),) - # find Qt install directory from PATH environment variable - qtpath := $(foreach path,$(subst ;, ,$(PATH)),$(if $(wildcard $(path)/$(moc).exe),$(path))) - qtpath := $(strip $(qtpath)) - qtpath := $(subst \,/,$(qtpath)) - qtpath := $(patsubst %/bin,%,$(qtpath)) - endif - - qtinc := -I$(qtpath)/include - qtinc += $(foreach lib,$(qtlibs),-I$(qtpath)/include/$(lib)) - - qtlib := -L$(qtpath)/lib - qtlib += -L$(qtpath)/plugins/imageformats - - qtlib += $(foreach lib,$(qtlibs),-l$(lib)4) - qtlib += -lmingw32 -lqtmain -lcomdlg32 -loleaut32 -limm32 -lwinmm - qtlib += -lwinspool -lmsimg32 -lole32 -ladvapi32 -lws2_32 -luuid -lgdi32 - qtlib += $(foreach lib,$(qtlibs),-l$(lib)4) - - # optional image-file support: - # qtlib += -lqjpeg -lqmng -endif diff --git a/snesreader/nall/qt/check-action.moc.hpp b/snesreader/nall/qt/check-action.moc.hpp deleted file mode 100644 index db378fe9..00000000 --- a/snesreader/nall/qt/check-action.moc.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef NALL_QT_CHECKACTION_HPP -#define NALL_QT_CHECKACTION_HPP - -namespace nall { - -class CheckAction : public QAction { - Q_OBJECT - -public: - bool isChecked() const; - void setChecked(bool); - void toggleChecked(); - CheckAction(const QString&, QObject*); - -protected slots: - -protected: - bool checked; -}; - -inline bool CheckAction::isChecked() const { - return checked; -} - -inline void CheckAction::setChecked(bool checked_) { - checked = checked_; - if(checked) setIcon(QIcon(":/16x16/item-check-on.png")); - else setIcon(QIcon(":/16x16/item-check-off.png")); -} - -inline void CheckAction::toggleChecked() { - setChecked(!isChecked()); -} - -inline CheckAction::CheckAction(const QString &text, QObject *parent) : QAction(text, parent) { - setChecked(false); -} - -} - -#endif diff --git a/snesreader/nall/qt/concept.hpp b/snesreader/nall/qt/concept.hpp deleted file mode 100644 index 51cacef4..00000000 --- a/snesreader/nall/qt/concept.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef NALL_QT_CONCEPT_HPP -#define NALL_QT_CONCEPT_HPP - -#include - -namespace nall { - template struct has_count> { enum { value = true }; }; -} - -#endif diff --git a/snesreader/nall/qt/file-dialog.moc.hpp b/snesreader/nall/qt/file-dialog.moc.hpp deleted file mode 100644 index bcccfaf5..00000000 --- a/snesreader/nall/qt/file-dialog.moc.hpp +++ /dev/null @@ -1,392 +0,0 @@ -#ifndef NALL_QT_FILEDIALOG_HPP -#define NALL_QT_FILEDIALOG_HPP - -#include -#include -#include - -namespace nall { - -class FileDialog; - -class NewFolderDialog : public Window { - Q_OBJECT - -public: - void show(); - NewFolderDialog(FileDialog*); - -protected slots: - void createFolderAction(); - -protected: - FileDialog *parent; - QVBoxLayout *layout; - QLineEdit *folderNameEdit; - QHBoxLayout *controlLayout; - QPushButton *okButton; - QPushButton *cancelButton; -}; - -class FileView : public QListView { - Q_OBJECT - -protected: - void keyPressEvent(QKeyEvent*); - -signals: - void changed(const QModelIndex&); - void browseUp(); - -protected slots: - void currentChanged(const QModelIndex&, const QModelIndex&); -}; - -class FileDialog : public Window { - Q_OBJECT - -public: - void showLoad(); - void showSave(); - void showFolder(); - - void setPath(string path); - void setNameFilters(const string &filters); - FileDialog(); - -signals: - void changed(const string&); - void activated(const string&); - void accepted(const string&); - void rejected(); - -protected slots: - void fileViewChange(const QModelIndex&); - void fileViewActivate(const QModelIndex&); - void pathBoxChanged(); - void filterBoxChanged(); - void createNewFolder(); - void browseUp(); - void acceptAction(); - void rejectAction(); - -protected: - NewFolderDialog *newFolderDialog; - QVBoxLayout *layout; - QHBoxLayout *navigationLayout; - QComboBox *pathBox; - QPushButton *newFolderButton; - QPushButton *upFolderButton; - QHBoxLayout *browseLayout; - QFileSystemModel *fileSystemModel; - FileView *fileView; - QGroupBox *previewFrame; - QLineEdit *fileNameEdit; - QHBoxLayout *controlLayout; - QComboBox *filterBox; - QPushButton *optionsButton; - QPushButton *acceptButton; - QPushButton *rejectButton; - bool lock; - void createFolderAction(const string &name); - void closeEvent(QCloseEvent*); - - friend class NewFolderDialog; -}; - -inline void NewFolderDialog::show() { - folderNameEdit->setText(""); - Window::show(); - folderNameEdit->setFocus(); -} - -inline void NewFolderDialog::createFolderAction() { - string name = folderNameEdit->text().toUtf8().constData(); - if(name == "") { - folderNameEdit->setFocus(); - } else { - parent->createFolderAction(name); - close(); - } -} - -inline NewFolderDialog::NewFolderDialog(FileDialog *fileDialog) : parent(fileDialog) { - setMinimumWidth(240); - setWindowTitle("Create New Folder"); - - layout = new QVBoxLayout; - layout->setAlignment(Qt::AlignTop); - layout->setMargin(5); - layout->setSpacing(5); - setLayout(layout); - - folderNameEdit = new QLineEdit; - layout->addWidget(folderNameEdit); - - controlLayout = new QHBoxLayout; - controlLayout->setAlignment(Qt::AlignRight); - layout->addLayout(controlLayout); - - okButton = new QPushButton("Ok"); - controlLayout->addWidget(okButton); - - cancelButton = new QPushButton("Cancel"); - controlLayout->addWidget(cancelButton); - - connect(folderNameEdit, SIGNAL(returnPressed()), this, SLOT(createFolderAction())); - connect(okButton, SIGNAL(released()), this, SLOT(createFolderAction())); - connect(cancelButton, SIGNAL(released()), this, SLOT(close())); -} - -inline void FileView::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) { - QAbstractItemView::currentChanged(current, previous); - emit changed(current); -} - -inline void FileView::keyPressEvent(QKeyEvent *event) { - //enhance consistency: force OS X to act like Windows and Linux; enter = activate item - if(event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) { - emit activated(currentIndex()); - return; - } - - //simulate popular file manager behavior; backspace = go up one directory - if(event->key() == Qt::Key_Backspace) { - emit browseUp(); - return; - } - - //fallback: unrecognized keypresses get handled by the widget itself - QListView::keyPressEvent(event); -} - -inline void FileDialog::showLoad() { - acceptButton->setText("Load"); - fileNameEdit->hide(); - filterBox->show(); - show(); -} - -inline void FileDialog::showSave() { - acceptButton->setText("Save"); - fileNameEdit->show(); - filterBox->show(); - show(); -} - -inline void FileDialog::showFolder() { - acceptButton->setText("Choose"); - fileNameEdit->hide(); - filterBox->hide(); - setNameFilters("Folders ()"); - show(); -} - -inline void FileDialog::fileViewChange(const QModelIndex &index) { - string path = fileSystemModel->filePath(index).toUtf8().constData(); - if(path == fileSystemModel->rootPath().toUtf8().constData()) path = ""; - fileNameEdit->setText(notdir(path)); - emit changed(path); -} - -inline void FileDialog::fileViewActivate(const QModelIndex &index) { - string path = fileSystemModel->filePath(index).toUtf8().constData(); - if(fileSystemModel->isDir(index)) { - emit activated(path); - setPath(path); - } else { - emit activated(path); - close(); - } -} - -inline void FileDialog::pathBoxChanged() { - if(lock) return; - setPath(pathBox->currentText().toUtf8().constData()); -} - -inline void FileDialog::filterBoxChanged() { - if(lock) return; - string filters = filterBox->currentText().toUtf8().constData(); - if(filters.length() == 0) { - fileSystemModel->setNameFilters(QStringList() << "*"); - } else { - filters = substr(filters, strpos(filters, "(")); - ltrim(filters, "("); - rtrim(filters, ")"); - lstring part; - part.split(" ", filters); - QStringList list; - for(unsigned i = 0; i < part.size(); i++) list << part[i]; - fileSystemModel->setNameFilters(list); - } -} - -inline void FileDialog::createNewFolder() { - newFolderDialog->show(); -} - -inline void FileDialog::browseUp() { - if(pathBox->count() > 1) pathBox->setCurrentIndex(1); -} - -inline void FileDialog::setPath(string path) { - lock = true; - newFolderDialog->close(); - - if(QDir(path).exists()) { - newFolderButton->setEnabled(true); - } else { - newFolderButton->setEnabled(false); - path = ""; - } - - fileSystemModel->setRootPath(path); - fileView->setRootIndex(fileSystemModel->index(path)); - fileView->setCurrentIndex(fileView->rootIndex()); - fileView->setFocus(); - - pathBox->clear(); - if(path.length() > 0) { - QDir directory(path); - while(true) { - pathBox->addItem(directory.absolutePath()); - if(directory.isRoot()) break; - directory.cdUp(); - } - } - pathBox->addItem(""); - fileNameEdit->setText(""); - - lock = false; -} - -inline void FileDialog::setNameFilters(const string &filters) { - lock = true; - - lstring list; - list.split("\n", filters); - - filterBox->clear(); - for(unsigned i = 0; i < list.size(); i++) { - filterBox->addItem(list[i]); - } - - lock = false; - filterBoxChanged(); -} - -inline void FileDialog::acceptAction() { - string path = fileSystemModel->rootPath().toUtf8().constData(); - path << "/" << notdir(fileNameEdit->text().toUtf8().constData()); - rtrim(path, "/"); - if(QDir(path).exists()) { - emit accepted(path); - setPath(path); - } else { - emit accepted(path); - close(); - } -} - -inline void FileDialog::rejectAction() { - emit rejected(); - close(); -} - -inline void FileDialog::createFolderAction(const string &name) { - string path = fileSystemModel->rootPath().toUtf8().constData(); - path << "/" << notdir(name); - mkdir(path, 0755); -} - -inline void FileDialog::closeEvent(QCloseEvent *event) { - newFolderDialog->close(); - Window::closeEvent(event); -} - -inline FileDialog::FileDialog() { - newFolderDialog = new NewFolderDialog(this); - resize(640, 360); - - layout = new QVBoxLayout; - layout->setMargin(5); - layout->setSpacing(5); - setLayout(layout); - - navigationLayout = new QHBoxLayout; - layout->addLayout(navigationLayout); - - pathBox = new QComboBox; - pathBox->setEditable(true); - pathBox->setMinimumContentsLength(16); - pathBox->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLength); - pathBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); - navigationLayout->addWidget(pathBox); - - newFolderButton = new QPushButton; - newFolderButton->setIconSize(QSize(16, 16)); - newFolderButton->setIcon(QIcon(":/16x16/folder-new.png")); - navigationLayout->addWidget(newFolderButton); - - upFolderButton = new QPushButton; - upFolderButton->setIconSize(QSize(16, 16)); - upFolderButton->setIcon(QIcon(":/16x16/go-up.png")); - navigationLayout->addWidget(upFolderButton); - - browseLayout = new QHBoxLayout; - layout->addLayout(browseLayout); - - fileSystemModel = new QFileSystemModel; - fileSystemModel->setFilter(QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot); - fileSystemModel->setNameFilterDisables(false); - - fileView = new FileView; - fileView->setMinimumWidth(320); - fileView->setModel(fileSystemModel); - fileView->setIconSize(QSize(16, 16)); - browseLayout->addWidget(fileView); - - previewFrame = new QGroupBox; - previewFrame->hide(); - browseLayout->addWidget(previewFrame); - - fileNameEdit = new QLineEdit; - layout->addWidget(fileNameEdit); - - controlLayout = new QHBoxLayout; - controlLayout->setAlignment(Qt::AlignRight); - layout->addLayout(controlLayout); - - filterBox = new QComboBox; - filterBox->setMinimumContentsLength(16); - filterBox->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLength); - filterBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); - controlLayout->addWidget(filterBox); - - optionsButton = new QPushButton("Options"); - optionsButton->hide(); - controlLayout->addWidget(optionsButton); - - acceptButton = new QPushButton("Ok"); - controlLayout->addWidget(acceptButton); - - rejectButton = new QPushButton("Cancel"); - controlLayout->addWidget(rejectButton); - - lock = false; - connect(pathBox, SIGNAL(currentIndexChanged(int)), this, SLOT(pathBoxChanged())); - connect(newFolderButton, SIGNAL(released()), this, SLOT(createNewFolder())); - connect(upFolderButton, SIGNAL(released()), this, SLOT(browseUp())); - connect(fileView, SIGNAL(changed(const QModelIndex&)), this, SLOT(fileViewChange(const QModelIndex&))); - connect(fileView, SIGNAL(activated(const QModelIndex&)), this, SLOT(fileViewActivate(const QModelIndex&))); - connect(fileView, SIGNAL(browseUp()), this, SLOT(browseUp())); - connect(fileNameEdit, SIGNAL(returnPressed()), this, SLOT(acceptAction())); - connect(filterBox, SIGNAL(currentIndexChanged(int)), this, SLOT(filterBoxChanged())); - connect(acceptButton, SIGNAL(released()), this, SLOT(acceptAction())); - connect(rejectButton, SIGNAL(released()), this, SLOT(rejectAction())); -} - -} - -#endif diff --git a/snesreader/nall/qt/hex-editor.moc.hpp b/snesreader/nall/qt/hex-editor.moc.hpp deleted file mode 100644 index d59f4be9..00000000 --- a/snesreader/nall/qt/hex-editor.moc.hpp +++ /dev/null @@ -1,173 +0,0 @@ -#ifndef NALL_QT_HEXEDITOR_HPP -#define NALL_QT_HEXEDITOR_HPP - -#include -#include -#include - -namespace nall { - -class HexEditor : public QTextEdit { - Q_OBJECT - -public: - function reader; - function writer; - - void setColumns(unsigned columns); - void setRows(unsigned rows); - void setOffset(unsigned offset); - void setSize(unsigned size); - unsigned lineWidth() const; - void refresh(); - - HexEditor(); - -protected slots: - void scrolled(); - -protected: - QHBoxLayout *layout; - QScrollBar *scrollBar; - unsigned editorColumns; - unsigned editorRows; - unsigned editorOffset; - unsigned editorSize; - bool lock; - - void keyPressEvent(QKeyEvent*); -}; - -inline void HexEditor::keyPressEvent(QKeyEvent *event) { - QTextCursor cursor = textCursor(); - unsigned x = cursor.position() % lineWidth(); - unsigned y = cursor.position() / lineWidth(); - - int hexCode = -1; - switch(event->key()) { - case Qt::Key_0: hexCode = 0; break; - case Qt::Key_1: hexCode = 1; break; - case Qt::Key_2: hexCode = 2; break; - case Qt::Key_3: hexCode = 3; break; - case Qt::Key_4: hexCode = 4; break; - case Qt::Key_5: hexCode = 5; break; - case Qt::Key_6: hexCode = 6; break; - case Qt::Key_7: hexCode = 7; break; - case Qt::Key_8: hexCode = 8; break; - case Qt::Key_9: hexCode = 9; break; - case Qt::Key_A: hexCode = 10; break; - case Qt::Key_B: hexCode = 11; break; - case Qt::Key_C: hexCode = 12; break; - case Qt::Key_D: hexCode = 13; break; - case Qt::Key_E: hexCode = 14; break; - case Qt::Key_F: hexCode = 15; break; - } - - if(cursor.hasSelection() == false && hexCode != -1) { - bool cursorOffsetValid = (x >= 11 && ((x - 11) % 3) != 2); - if(cursorOffsetValid) { - bool nibble = (x - 11) % 3; //0 = top nibble, 1 = bottom nibble - unsigned cursorOffset = y * editorColumns + ((x - 11) / 3); - unsigned effectiveOffset = editorOffset + cursorOffset; - if(effectiveOffset >= editorSize) effectiveOffset %= editorSize; - - uint8_t data = reader ? reader(effectiveOffset) : 0x00; - data &= (nibble == 0 ? 0x0f : 0xf0); - data |= (nibble == 0 ? (hexCode << 4) : (hexCode << 0)); - if(writer) writer(effectiveOffset, data); - refresh(); - - cursor.setPosition(y * lineWidth() + x + 1); //advance cursor - setTextCursor(cursor); - } - } else { - //allow navigation keys to move cursor, but block text input - setTextInteractionFlags(Qt::TextSelectableByKeyboard | Qt::TextSelectableByMouse); - QTextEdit::keyPressEvent(event); - setTextInteractionFlags(Qt::TextEditorInteraction); - } -} - -inline void HexEditor::setColumns(unsigned columns) { - editorColumns = columns; -} - -inline void HexEditor::setRows(unsigned rows) { - editorRows = rows; - scrollBar->setPageStep(editorRows); -} - -inline void HexEditor::setOffset(unsigned offset) { - lock = true; - editorOffset = offset; - scrollBar->setSliderPosition(editorOffset / editorColumns); - lock = false; -} - -inline void HexEditor::setSize(unsigned size) { - editorSize = size; - bool indivisible = (editorSize % editorColumns) != 0; //add one for incomplete row - scrollBar->setRange(0, editorSize / editorColumns + indivisible - editorRows); -} - -inline unsigned HexEditor::lineWidth() const { - return 11 + 3 * editorColumns; -} - -inline void HexEditor::refresh() { - string output; - char temp[256]; - unsigned offset = editorOffset; - - for(unsigned y = 0; y < editorRows; y++) { - if(offset >= editorSize) break; - sprintf(temp, "%.4x:%.4x", (offset >> 16) & 0xffff, (offset >> 0) & 0xffff); - output << "" << temp << "  "; - - for(unsigned x = 0; x < editorColumns; x++) { - if(offset >= editorSize) break; - sprintf(temp, "%.2x", reader ? reader(offset) : 0x00); - offset++; - output << "" << temp << ""; - if(x != (editorColumns - 1)) output << " "; - } - - if(y != (editorRows - 1)) output << "
"; - } - - setHtml(output); -} - -inline void HexEditor::scrolled() { - if(lock) return; - unsigned offset = scrollBar->sliderPosition(); - editorOffset = offset * editorColumns; - refresh(); -} - -inline HexEditor::HexEditor() { - setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - - layout = new QHBoxLayout; - layout->setAlignment(Qt::AlignRight); - layout->setMargin(0); - layout->setSpacing(0); - setLayout(layout); - - scrollBar = new QScrollBar(Qt::Vertical); - scrollBar->setSingleStep(1); - layout->addWidget(scrollBar); - - lock = false; - connect(scrollBar, SIGNAL(actionTriggered(int)), this, SLOT(scrolled())); - - setColumns(16); - setRows(16); - setSize(0); - setOffset(0); -} - -} - -#endif diff --git a/snesreader/nall/qt/radio-action.moc.hpp b/snesreader/nall/qt/radio-action.moc.hpp deleted file mode 100644 index a2bbca48..00000000 --- a/snesreader/nall/qt/radio-action.moc.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef NALL_QT_RADIOACTION_HPP -#define NALL_QT_RADIOACTION_HPP - -namespace nall { - -class RadioAction : public QAction { - Q_OBJECT - -public: - bool isChecked() const; - void setChecked(bool); - void toggleChecked(); - RadioAction(const QString&, QObject*); - -protected slots: - -protected: - bool checked; -}; - -inline bool RadioAction::isChecked() const { - return checked; -} - -inline void RadioAction::setChecked(bool checked_) { - checked = checked_; - if(checked) setIcon(QIcon(":/16x16/item-radio-on.png")); - else setIcon(QIcon(":/16x16/item-radio-off.png")); -} - -inline void RadioAction::toggleChecked() { - setChecked(!isChecked()); -} - -inline RadioAction::RadioAction(const QString &text, QObject *parent) : QAction(text, parent) { - setChecked(false); -} - -} - -#endif diff --git a/snesreader/nall/qt/window.moc.hpp b/snesreader/nall/qt/window.moc.hpp deleted file mode 100644 index 0d3bf390..00000000 --- a/snesreader/nall/qt/window.moc.hpp +++ /dev/null @@ -1,105 +0,0 @@ -#ifndef NALL_QT_WINDOW_HPP -#define NALL_QT_WINDOW_HPP - -#include -#include - -namespace nall { - -class Window : public QWidget { - Q_OBJECT - -public: - void setGeometryString(string *geometryString); - void setCloseOnEscape(bool); - void show(); - void hide(); - void shrink(); - - Window(); - -protected slots: - -protected: - string *geometryString; - bool closeOnEscape; - void keyReleaseEvent(QKeyEvent *event); - void closeEvent(QCloseEvent *event); -}; - -inline void Window::setGeometryString(string *geometryString_) { - geometryString = geometryString_; - if(geometryString && isVisible() == false) { - uint8_t *data; - unsigned length; - base64::decode(data, length, *geometryString); - QByteArray array((const char*)data, length); - delete[] data; - restoreGeometry(array); - } -} - -inline void Window::setCloseOnEscape(bool value) { - closeOnEscape = value; -} - -inline void Window::show() { - if(geometryString && isVisible() == false) { - uint8_t *data; - unsigned length; - base64::decode(data, length, *geometryString); - QByteArray array((const char*)data, length); - delete[] data; - restoreGeometry(array); - } - QWidget::show(); - QApplication::processEvents(); - activateWindow(); - raise(); -} - -inline void Window::hide() { - if(geometryString && isVisible() == true) { - char *data; - QByteArray geometry = saveGeometry(); - base64::encode(data, (const uint8_t*)geometry.data(), geometry.length()); - *geometryString = data; - delete[] data; - } - QWidget::hide(); -} - -inline void Window::shrink() { - if(isFullScreen()) return; - - for(unsigned i = 0; i < 2; i++) { - resize(0, 0); - usleep(2000); - QApplication::processEvents(); - } -} - -inline void Window::keyReleaseEvent(QKeyEvent *event) { - if(closeOnEscape && (event->key() == Qt::Key_Escape)) close(); - QWidget::keyReleaseEvent(event); -} - -inline void Window::closeEvent(QCloseEvent *event) { - if(geometryString) { - char *data; - QByteArray geometry = saveGeometry(); - base64::encode(data, (const uint8_t*)geometry.data(), geometry.length()); - *geometryString = data; - delete[] data; - } - QWidget::closeEvent(event); -} - -inline Window::Window() { - geometryString = 0; - closeOnEscape = true; -} - -} - -#endif diff --git a/snesreader/nall/serial.hpp b/snesreader/nall/serial.hpp deleted file mode 100644 index 6f5cf6d6..00000000 --- a/snesreader/nall/serial.hpp +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef NALL_SERIAL_HPP -#define NALL_SERIAL_HPP - -#include -#include -#include -#include - -#include - -namespace nall { - class serial { - public: - //-1 on error, otherwise return bytes read - int read(uint8_t *data, unsigned length) { - if(port_open == false) return -1; - return ::read(port, (void*)data, length); - } - - //-1 on error, otherwise return bytes written - int write(const uint8_t *data, unsigned length) { - if(port_open == false) return -1; - return ::write(port, (void*)data, length); - } - - bool open(const char *portname, unsigned rate) { - close(); - - port = ::open(portname, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK); - if(port == -1) return false; - - if(ioctl(port, TIOCEXCL) == -1) { close(); return false; } - if(fcntl(port, F_SETFL, 0) == -1) { close(); return false; } - if(tcgetattr(port, &original_attr) == -1) { close(); return false; } - - termios attr = original_attr; - cfmakeraw(&attr); - cfsetspeed(&attr, rate); - - attr.c_lflag &=~ (ECHO | ECHONL | ISIG | ICANON | IEXTEN); - attr.c_iflag &=~ (BRKINT | PARMRK | INPCK | ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXOFF | IXANY); - attr.c_iflag |= (IGNBRK | IGNPAR); - attr.c_oflag &=~ (OPOST); - attr.c_cflag &=~ (CSIZE | CSTOPB | PARENB); - attr.c_cflag |= (CS8 | CREAD | CLOCAL); - attr.c_cc[VTIME] = attr.c_cc[VMIN] = 0; - - if(tcsetattr(port, TCSANOW, &attr) == -1) { close(); return false; } - return port_open = true; - } - - void close() { - if(port != -1) { - tcdrain(port); - if(port_open == true) { - tcsetattr(port, TCSANOW, &original_attr); - port_open = false; - } - ::close(port); - port = -1; - } - } - - serial() { - port = -1; - port_open = false; - } - - ~serial() { - close(); - } - - private: - int port; - bool port_open; - termios original_attr; - }; -} - -#endif diff --git a/snesreader/nall/serializer.hpp b/snesreader/nall/serializer.hpp deleted file mode 100644 index 9f816dfe..00000000 --- a/snesreader/nall/serializer.hpp +++ /dev/null @@ -1,145 +0,0 @@ -#ifndef NALL_SERIALIZER_HPP -#define NALL_SERIALIZER_HPP - -#include -#include -#include -#include - -namespace nall { - //serializer: a class designed to save and restore the state of classes. - // - //benefits: - //- data() will be portable in size (it is not necessary to specify type sizes.) - //- data() will be portable in endianness (always stored internally as little-endian.) - //- one serialize function can both save and restore class states. - // - //caveats: - //- only plain-old-data can be stored. complex classes must provide serialize(serializer&); - //- floating-point usage is not portable across platforms - - class serializer { - public: - enum mode_t { Load, Save, Size }; - - mode_t mode() const { - return imode; - } - - const uint8_t* data() const { - return idata; - } - - unsigned size() const { - return isize; - } - - unsigned capacity() const { - return icapacity; - } - - template void floatingpoint(T &value) { - enum { size = sizeof(T) }; - //this is rather dangerous, and not cross-platform safe; - //but there is no standardized way to export FP-values - uint8_t *p = (uint8_t*)&value; - if(imode == Save) { - for(unsigned n = 0; n < size; n++) idata[isize++] = p[n]; - } else if(imode == Load) { - for(unsigned n = 0; n < size; n++) p[n] = idata[isize++]; - } else { - isize += size; - } - } - - template void integer(T &value) { - enum { size = std::is_same::value ? 1 : sizeof(T) }; - if(imode == Save) { - for(unsigned n = 0; n < size; n++) idata[isize++] = value >> (n << 3); - } else if(imode == Load) { - value = 0; - for(unsigned n = 0; n < size; n++) value |= idata[isize++] << (n << 3); - } else if(imode == Size) { - isize += size; - } - } - - template void array(T &array) { - enum { size = sizeof(T) / sizeof(typename std::remove_extent::type) }; - for(unsigned n = 0; n < size; n++) integer(array[n]); - } - - template void array(T array, unsigned size) { - for(unsigned n = 0; n < size; n++) integer(array[n]); - } - - //copy - serializer& operator=(const serializer &s) { - if(idata) delete[] idata; - - imode = s.imode; - idata = new uint8_t[s.icapacity]; - isize = s.isize; - icapacity = s.icapacity; - - memcpy(idata, s.idata, s.icapacity); - return *this; - } - - serializer(const serializer &s) : idata(0) { - operator=(s); - } - - //move - serializer& operator=(serializer &&s) { - if(idata) delete[] idata; - - imode = s.imode; - idata = s.idata; - isize = s.isize; - icapacity = s.icapacity; - - s.idata = 0; - return *this; - } - - serializer(serializer &&s) { - operator=(std::move(s)); - } - - //construction - serializer() { - imode = Size; - idata = 0; - isize = 0; - } - - serializer(unsigned capacity) { - imode = Save; - idata = new uint8_t[capacity](); - isize = 0; - icapacity = capacity; - } - - serializer(const uint8_t *data, unsigned capacity) { - imode = Load; - idata = new uint8_t[capacity]; - isize = 0; - icapacity = capacity; - memcpy(idata, data, capacity); - } - - ~serializer() { - if(idata) delete[] idata; - } - - private: - mode_t imode; - uint8_t *idata; - unsigned isize; - unsigned icapacity; - }; - -}; - -#endif diff --git a/snesreader/nall/sha256.hpp b/snesreader/nall/sha256.hpp deleted file mode 100644 index 7f41f04e..00000000 --- a/snesreader/nall/sha256.hpp +++ /dev/null @@ -1,143 +0,0 @@ -#ifndef NALL_SHA256_HPP -#define NALL_SHA256_HPP - -//author: vladitx - -namespace nall { - #define PTR(t, a) ((t*)(a)) - - #define SWAP32(x) ((uint32_t)( \ - (((uint32_t)(x) & 0x000000ff) << 24) | \ - (((uint32_t)(x) & 0x0000ff00) << 8) | \ - (((uint32_t)(x) & 0x00ff0000) >> 8) | \ - (((uint32_t)(x) & 0xff000000) >> 24) \ - )) - - #define ST32(a, d) *PTR(uint32_t, a) = (d) - #define ST32BE(a, d) ST32(a, SWAP32(d)) - - #define LD32(a) *PTR(uint32_t, a) - #define LD32BE(a) SWAP32(LD32(a)) - - #define LSL32(x, n) ((uint32_t)(x) << (n)) - #define LSR32(x, n) ((uint32_t)(x) >> (n)) - #define ROR32(x, n) (LSR32(x, n) | LSL32(x, 32 - (n))) - - //first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19 - static const uint32_t T_H[8] = { - 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19, - }; - - //first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311 - static const uint32_t T_K[64] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, - }; - - struct sha256_ctx { - uint8_t in[64]; - unsigned inlen; - - uint32_t w[64]; - uint32_t h[8]; - uint64_t len; - }; - - void sha256_init(sha256_ctx *p) { - memset(p, 0, sizeof(sha256_ctx)); - memcpy(p->h, T_H, sizeof(T_H)); - } - - static void sha256_block(sha256_ctx *p) { - unsigned i; - uint32_t s0, s1; - uint32_t a, b, c, d, e, f, g, h; - uint32_t t1, t2, maj, ch; - - for(i = 0; i < 16; i++) p->w[i] = LD32BE(p->in + i * 4); - - for(i = 16; i < 64; i++) { - s0 = ROR32(p->w[i - 15], 7) ^ ROR32(p->w[i - 15], 18) ^ LSR32(p->w[i - 15], 3); - s1 = ROR32(p->w[i - 2], 17) ^ ROR32(p->w[i - 2], 19) ^ LSR32(p->w[i - 2], 10); - p->w[i] = p->w[i - 16] + s0 + p->w[i - 7] + s1; - } - - a = p->h[0]; b = p->h[1]; c = p->h[2]; d = p->h[3]; - e = p->h[4]; f = p->h[5]; g = p->h[6]; h = p->h[7]; - - for(i = 0; i < 64; i++) { - s0 = ROR32(a, 2) ^ ROR32(a, 13) ^ ROR32(a, 22); - maj = (a & b) ^ (a & c) ^ (b & c); - t2 = s0 + maj; - s1 = ROR32(e, 6) ^ ROR32(e, 11) ^ ROR32(e, 25); - ch = (e & f) ^ (~e & g); - t1 = h + s1 + ch + T_K[i] + p->w[i]; - - h = g; g = f; f = e; e = d + t1; - d = c; c = b; b = a; a = t1 + t2; - } - - p->h[0] += a; p->h[1] += b; p->h[2] += c; p->h[3] += d; - p->h[4] += e; p->h[5] += f; p->h[6] += g; p->h[7] += h; - - //next block - p->inlen = 0; - } - - void sha256_chunk(sha256_ctx *p, const uint8_t *s, unsigned len) { - unsigned l; - p->len += len; - - while(len) { - l = 64 - p->inlen; - l = (len < l) ? len : l; - - memcpy(p->in + p->inlen, s, l); - s += l; - p->inlen += l; - len -= l; - - if(p->inlen == 64) sha256_block(p); - } - } - - void sha256_final(sha256_ctx *p) { - uint64_t len; - p->in[p->inlen++] = 0x80; - - if(p->inlen > 56) { - memset(p->in + p->inlen, 0, 64 - p->inlen); - sha256_block(p); - } - - memset(p->in + p->inlen, 0, 56 - p->inlen); - - len = p->len << 3; - ST32BE(p->in + 56, len >> 32); - ST32BE(p->in + 60, len); - sha256_block(p); - } - - void sha256_hash(sha256_ctx *p, uint8_t *s) { - uint32_t *t = (uint32_t*)s; - for(unsigned i = 0; i < 8; i++) ST32BE(t++, p->h[i]); - } - - #undef PTR - #undef SWAP32 - #undef ST32 - #undef ST32BE - #undef LD32 - #undef LD32BE - #undef LSL32 - #undef LSR32 - #undef ROR32 -} - -#endif diff --git a/snesreader/nall/sort.hpp b/snesreader/nall/sort.hpp deleted file mode 100644 index 23c317a5..00000000 --- a/snesreader/nall/sort.hpp +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef NALL_SORT_HPP -#define NALL_SORT_HPP - -#include - -//class: merge sort -//average: O(n log n) -//worst: O(n log n) -//memory: O(n) -//stack: O(log n) -//stable?: yes - -//notes: -//there are two primary reasons for choosing merge sort -//over the (usually) faster quick sort*: -//1: it is a stable sort. -//2: it lacks O(n^2) worst-case overhead. -//(* which is also O(n log n) in the average case.) - -namespace nall { - template - void sort(T list[], unsigned length) { - if(length <= 1) return; //nothing to sort - - //use insertion sort to quickly sort smaller blocks - if(length < 64) { - for(unsigned i = 0; i < length; i++) { - unsigned min = i; - for(unsigned j = i + 1; j < length; j++) { - if(list[j] < list[min]) min = j; - } - if(min != i) swap(list[i], list[min]); - } - return; - } - - //split list in half and recursively sort both - unsigned middle = length / 2; - sort(list, middle); - sort(list + middle, length - middle); - - //left and right are sorted here; perform merge sort - T *buffer = new T[length]; - unsigned offset = 0; - unsigned left = 0; - unsigned right = middle; - while(left < middle && right < length) { - if(list[left] < list[right]) { - buffer[offset++] = list[left++]; - } else { - buffer[offset++] = list[right++]; - } - } - while(left < middle) buffer[offset++] = list[left++]; - while(right < length) buffer[offset++] = list[right++]; - - for(unsigned i = 0; i < length; i++) list[i] = buffer[i]; - delete[] buffer; - } -} - -#endif diff --git a/snesreader/nall/static.hpp b/snesreader/nall/static.hpp deleted file mode 100644 index 4acb9fd0..00000000 --- a/snesreader/nall/static.hpp +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef NALL_STATIC_HPP -#define NALL_STATIC_HPP - -namespace nall { - template struct static_if { typedef T type; }; - template struct static_if { typedef F type; }; - template struct mp_static_if { typedef typename static_if::type type; }; - - template struct static_and { enum { value = false }; }; - template<> struct static_and { enum { value = true }; }; - template struct mp_static_and { enum { value = static_and::value }; }; - - template struct static_or { enum { value = false }; }; - template<> struct static_or { enum { value = true }; }; - template<> struct static_or { enum { value = true }; }; - template<> struct static_or { enum { value = true }; }; - template struct mp_static_or { enum { value = static_or::value }; }; -} - -#endif diff --git a/snesreader/nall/stdint.hpp b/snesreader/nall/stdint.hpp deleted file mode 100644 index d8b6c788..00000000 --- a/snesreader/nall/stdint.hpp +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef NALL_STDINT_HPP -#define NALL_STDINT_HPP - -#include - -#if defined(_MSC_VER) - typedef signed char int8_t; - typedef signed short int16_t; - typedef signed int int32_t; - typedef signed long long int64_t; - typedef int64_t intmax_t; - #if defined(_WIN64) - typedef int64_t intptr_t; - #else - typedef int32_t intptr_t; - #endif - - typedef unsigned char uint8_t; - typedef unsigned short uint16_t; - typedef unsigned int uint32_t; - typedef unsigned long long uint64_t; - typedef uint64_t uintmax_t; - #if defined(_WIN64) - typedef uint64_t uintptr_t; - #else - typedef uint32_t uintptr_t; - #endif -#else - #include -#endif - -namespace nall { - static_assert(sizeof(int8_t) == 1, "int8_t is not of the correct size" ); - static_assert(sizeof(int16_t) == 2, "int16_t is not of the correct size"); - static_assert(sizeof(int32_t) == 4, "int32_t is not of the correct size"); - static_assert(sizeof(int64_t) == 8, "int64_t is not of the correct size"); - - static_assert(sizeof(uint8_t) == 1, "int8_t is not of the correct size" ); - static_assert(sizeof(uint16_t) == 2, "int16_t is not of the correct size"); - static_assert(sizeof(uint32_t) == 4, "int32_t is not of the correct size"); - static_assert(sizeof(uint64_t) == 8, "int64_t is not of the correct size"); -} - -#endif diff --git a/snesreader/nall/string.hpp b/snesreader/nall/string.hpp deleted file mode 100644 index 65a4a4b8..00000000 --- a/snesreader/nall/string.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef NALL_STRING_HPP -#define NALL_STRING_HPP - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace nall { - template<> struct has_length { enum { value = true }; }; - template<> struct has_size { enum { value = true }; }; -} - -#endif diff --git a/snesreader/nall/string/base.hpp b/snesreader/nall/string/base.hpp deleted file mode 100644 index 179a7dd4..00000000 --- a/snesreader/nall/string/base.hpp +++ /dev/null @@ -1,137 +0,0 @@ -#ifndef NALL_STRING_BASE_HPP -#define NALL_STRING_BASE_HPP - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace nall { - class string; - template inline string to_string(T); - - class string { - public: - inline void reserve(unsigned); - inline unsigned length() const; - - inline string& assign(const char*); - inline string& append(const char*); - template inline string& operator= (T value); - template inline string& operator<<(T value); - - inline operator const char*() const; - inline char* operator()(); - inline char& operator[](int); - - inline bool operator==(const char*) const; - inline bool operator!=(const char*) const; - inline bool operator< (const char*) const; - inline bool operator<=(const char*) const; - inline bool operator> (const char*) const; - inline bool operator>=(const char*) const; - - inline string(); - inline string(const char*); - inline string(const string&); - inline string(string&&); - inline string& operator=(const string&); - inline string& operator=(string&&); - inline ~string(); - - inline bool readfile(const char*); - inline string& replace (const char*, const char*); - inline string& qreplace(const char*, const char*); - - protected: - char *data; - unsigned size; - - #if defined(QT_CORE_LIB) - public: - inline operator QString() const; - #endif - }; - - class lstring : public linear_vector { - public: - template inline lstring& operator<<(T value); - - inline int find(const char*); - inline void split (const char*, const char*, unsigned = 0); - inline void qsplit(const char*, const char*, unsigned = 0); - - lstring(); - lstring(std::initializer_list); - }; - - //compare.hpp - inline char chrlower(char c); - inline char chrupper(char c); - inline int stricmp(const char *dest, const char *src); - inline int strpos (const char *str, const char *key); - inline int qstrpos(const char *str, const char *key); - inline bool strbegin (const char *str, const char *key); - inline bool stribegin(const char *str, const char *key); - inline bool strend (const char *str, const char *key); - inline bool striend(const char *str, const char *key); - - //convert.hpp - inline char* strlower(char *str); - inline char* strupper(char *str); - inline char* strtr(char *dest, const char *before, const char *after); - inline uintmax_t strhex (const char *str); - inline intmax_t strsigned (const char *str); - inline uintmax_t strunsigned(const char *str); - inline uintmax_t strbin (const char *str); - inline double strdouble (const char *str); - - //match.hpp - inline bool match(const char *pattern, const char *str); - - //math.hpp - inline bool strint (const char *str, int &result); - inline bool strmath(const char *str, int &result); - - //strl.hpp - inline unsigned strlcpy(char *dest, const char *src, unsigned length); - inline unsigned strlcat(char *dest, const char *src, unsigned length); - - //trim.hpp - inline char* ltrim(char *str, const char *key = " "); - inline char* rtrim(char *str, const char *key = " "); - inline char* trim (char *str, const char *key = " "); - inline char* ltrim_once(char *str, const char *key = " "); - inline char* rtrim_once(char *str, const char *key = " "); - inline char* trim_once (char *str, const char *key = " "); - - //utility.hpp - inline unsigned strlcpy(string &dest, const char *src, unsigned length); - inline unsigned strlcat(string &dest, const char *src, unsigned length); - inline string substr(const char *src, unsigned start = 0, unsigned length = 0); - inline string& strlower(string &str); - inline string& strupper(string &str); - inline string& strtr(string &dest, const char *before, const char *after); - inline string& ltrim(string &str, const char *key = " "); - inline string& rtrim(string &str, const char *key = " "); - inline string& trim (string &str, const char *key = " "); - inline string& ltrim_once(string &str, const char *key = " "); - inline string& rtrim_once(string &str, const char *key = " "); - inline string& trim_once (string &str, const char *key = " "); - template inline string strhex(uintmax_t value); - template inline string strsigned(intmax_t value); - template inline string strunsigned(uintmax_t value); - template inline string strbin(uintmax_t value); - inline unsigned strdouble(char *str, double value); - inline string strdouble(double value); - - //variadic.hpp - template inline string sprint(Args... args); - template inline void print(Args... args); -}; - -#endif diff --git a/snesreader/nall/string/cast.hpp b/snesreader/nall/string/cast.hpp deleted file mode 100644 index 7b48eda0..00000000 --- a/snesreader/nall/string/cast.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef NALL_STRING_CAST_HPP -#define NALL_STRING_CAST_HPP - -namespace nall { - -//this is needed, as C++0x does not support explicit template specialization inside classes -template<> inline string to_string (bool v) { return v ? "true" : "false"; } -template<> inline string to_string (signed int v) { return strsigned(v); } -template<> inline string to_string (unsigned int v) { return strunsigned(v); } -template<> inline string to_string (double v) { return strdouble(v); } -template<> inline string to_string (char *v) { return v; } -template<> inline string to_string (const char *v) { return v; } -template<> inline string to_string (string v) { return v; } -template<> inline string to_string(const string &v) { return v; } - -template string& string::operator= (T value) { return assign(to_string(value)); } -template string& string::operator<<(T value) { return append(to_string(value)); } - -template lstring& lstring::operator<<(T value) { - operator[](size()).assign(to_string(value)); - return *this; -} - -#if defined(QT_CORE_LIB) -template<> inline string to_string(QString v) { return v.toUtf8().constData(); } -template<> inline string to_string(const QString &v) { return v.toUtf8().constData(); } -string::operator QString() const { return QString::fromUtf8(*this); } -#endif - -} - -#endif diff --git a/snesreader/nall/string/compare.hpp b/snesreader/nall/string/compare.hpp deleted file mode 100644 index e1173de4..00000000 --- a/snesreader/nall/string/compare.hpp +++ /dev/null @@ -1,104 +0,0 @@ -#ifndef NALL_STRING_COMPARE_HPP -#define NALL_STRING_COMPARE_HPP - -namespace nall { - -char chrlower(char c) { - return (c >= 'A' && c <= 'Z') ? c + ('a' - 'A') : c; -} - -char chrupper(char c) { - return (c >= 'a' && c <= 'z') ? c - ('a' - 'A') : c; -} - -int stricmp(const char *dest, const char *src) { - while(*dest) { - if(chrlower(*dest) != chrlower(*src)) break; - dest++; - src++; - } - - return (int)chrlower(*dest) - (int)chrlower(*src); -} - -int strpos(const char *str, const char *key) { - int ssl = strlen(str), ksl = strlen(key); - - if(ksl > ssl) return -1; - for(int i = 0; i <= ssl - ksl; i++) { - if(!memcmp(str + i, key, ksl)) { - return i; - } - } - return -1; -} - -int qstrpos(const char *str, const char *key) { - int ssl = strlen(str), ksl = strlen(key); - - if(ksl > ssl) return -1; - for(int i = 0; i <= ssl - ksl;) { - uint8_t x = str[i]; - if(x == '\"' || x == '\'') { - uint8_t z = i++; - while(str[i] != x && i < ssl) i++; - if(i >= ssl) i = z; - } - if(!memcmp(str + i, key, ksl)) { - return i; - } else { - i++; - } - } - return -1; -} - -bool strbegin(const char *str, const char *key) { - int i, ssl = strlen(str), ksl = strlen(key); - - if(ksl > ssl) return false; - return (!memcmp(str, key, ksl)); -} - -bool stribegin(const char *str, const char *key) { - int ssl = strlen(str), ksl = strlen(key); - - if(ksl > ssl) return false; - for(int i = 0; i < ksl; i++) { - if(str[i] >= 'A' && str[i] <= 'Z') { - if(str[i] != key[i] && str[i]+0x20 != key[i])return false; - } else if(str[i] >= 'a' && str[i] <= 'z') { - if(str[i] != key[i] && str[i]-0x20 != key[i])return false; - } else { - if(str[i] != key[i])return false; - } - } - return true; -} - -bool strend(const char *str, const char *key) { - int ssl = strlen(str), ksl = strlen(key); - - if(ksl > ssl) return false; - return (!memcmp(str + ssl - ksl, key, ksl)); -} - -bool striend(const char *str, const char *key) { - int ssl = strlen(str), ksl = strlen(key); - - if(ksl > ssl) return false; - for(int i = ssl - ksl, z = 0; i < ssl; i++, z++) { - if(str[i] >= 'A' && str[i] <= 'Z') { - if(str[i] != key[z] && str[i]+0x20 != key[z])return false; - } else if(str[i] >= 'a' && str[i] <= 'z') { - if(str[i] != key[z] && str[i]-0x20 != key[z])return false; - } else { - if(str[i] != key[z])return false; - } - } - return true; -} - -} - -#endif diff --git a/snesreader/nall/string/convert.hpp b/snesreader/nall/string/convert.hpp deleted file mode 100644 index 3ff134be..00000000 --- a/snesreader/nall/string/convert.hpp +++ /dev/null @@ -1,153 +0,0 @@ -#ifndef NALL_STRING_CONVERT_HPP -#define NALL_STRING_CONVERT_HPP - -namespace nall { - -char* strlower(char *str) { - if(!str) return 0; - int i = 0; - while(str[i]) { - str[i] = chrlower(str[i]); - i++; - } - return str; -} - -char* strupper(char *str) { - if(!str) return 0; - int i = 0; - while(str[i]) { - str[i] = chrupper(str[i]); - i++; - } - return str; -} - -char* strtr(char *dest, const char *before, const char *after) { - if(!dest || !before || !after) return dest; - int sl = strlen(dest), bsl = strlen(before), asl = strlen(after); - - if(bsl != asl || bsl == 0) return dest; //patterns must be the same length for 1:1 replace - for(unsigned i = 0; i < sl; i++) { - for(unsigned l = 0; l < bsl; l++) { - if(dest[i] == before[l]) { - dest[i] = after[l]; - break; - } - } - } - - return dest; -} - -uintmax_t strhex(const char *str) { - if(!str) return 0; - uintmax_t result = 0; - - //skip hex identifiers 0x and $, if present - if(*str == '0' && (*(str + 1) == 'X' || *(str + 1) == 'x')) str += 2; - else if(*str == '$') str++; - - while(*str) { - uint8_t x = *str++; - if(x >= '0' && x <= '9') x -= '0'; - else if(x >= 'A' && x <= 'F') x -= 'A' - 10; - else if(x >= 'a' && x <= 'f') x -= 'a' - 10; - else break; //stop at first invalid character - result = result * 16 + x; - } - - return result; -} - -intmax_t strsigned(const char *str) { - if(!str) return 0; - intmax_t result = 0; - bool negate = false; - - //check for negation - if(*str == '-') { - negate = true; - str++; - } - - while(*str) { - uint8_t x = *str++; - if(x >= '0' && x <= '9') x -= '0'; - else break; //stop at first invalid character - result = result * 10 + x; - } - - return !negate ? result : -result; -} - -uintmax_t strunsigned(const char *str) { - if(!str) return 0; - uintmax_t result = 0; - - while(*str) { - uint8_t x = *str++; - if(x >= '0' && x <= '9') x -= '0'; - else break; //stop at first invalid character - result = result * 10 + x; - } - - return result; -} - -uintmax_t strbin(const char *str) { - if(!str) return 0; - uintmax_t result = 0; - - //skip bin identifiers 0b and %, if present - if(*str == '0' && (*(str + 1) == 'B' || *(str + 1) == 'b')) str += 2; - else if(*str == '%') str++; - - while(*str) { - uint8_t x = *str++; - if(x == '0' || x == '1') x -= '0'; - else break; //stop at first invalid character - result = result * 2 + x; - } - - return result; -} - -double strdouble(const char *str) { - if(!str) return 0.0; - bool negate = false; - - //check for negation - if(*str == '-') { - negate = true; - str++; - } - - intmax_t result_integral = 0; - while(*str) { - uint8_t x = *str++; - if(x >= '0' && x <= '9') x -= '0'; - else if(x == '.') break; //break loop and read fractional part - else return (double)result_integral; //invalid value, assume no fractional part - result_integral = result_integral * 10 + x; - } - - intmax_t result_fractional = 0; - while(*str) { - uint8_t x = *str++; - if(x >= '0' && x <= '9') x -= '0'; - else break; //stop at first invalid character - result_fractional = result_fractional * 10 + x; - } - - //calculate fractional portion - double result = (double)result_fractional; - while((uintmax_t)result > 0) result /= 10.0; - result += (double)result_integral; - - return !negate ? result : -result; -} - -} - -#endif diff --git a/snesreader/nall/string/core.hpp b/snesreader/nall/string/core.hpp deleted file mode 100644 index d13bfc38..00000000 --- a/snesreader/nall/string/core.hpp +++ /dev/null @@ -1,133 +0,0 @@ -#ifndef NALL_STRING_CORE_HPP -#define NALL_STRING_CORE_HPP - -namespace nall { - -void string::reserve(unsigned size_) { - if(size_ > size) { - size = size_; - data = (char*)realloc(data, size + 1); - data[size] = 0; - } -} - -unsigned string::length() const { - return strlen(data); -} - -string& string::assign(const char *s) { - unsigned length = strlen(s); - reserve(length); - strcpy(data, s); - return *this; -} - -string& string::append(const char *s) { - unsigned length = strlen(data) + strlen(s); - reserve(length); - strcat(data, s); - return *this; -} - -string::operator const char*() const { - return data; -} - -char* string::operator()() { - return data; -} - -char& string::operator[](int index) { - reserve(index); - return data[index]; -} - -bool string::operator==(const char *str) const { return strcmp(data, str) == 0; } -bool string::operator!=(const char *str) const { return strcmp(data, str) != 0; } -bool string::operator< (const char *str) const { return strcmp(data, str) < 0; } -bool string::operator<=(const char *str) const { return strcmp(data, str) <= 0; } -bool string::operator> (const char *str) const { return strcmp(data, str) > 0; } -bool string::operator>=(const char *str) const { return strcmp(data, str) >= 0; } - -string::string() { - size = 64; - data = (char*)malloc(size + 1); - *data = 0; -} - -string::string(const char *value) { - size = strlen(value); - data = strdup(value); -} - -string::string(const string &value) { - size = strlen(value); - data = strdup(value); -} - -string::string(string &&source) { - size = source.size; - data = source.data; - source.data = 0; -} - -string& string::operator=(const string &value) { - assign(value); - return *this; -} - -string& string::operator=(string &&source) { - if(data) free(data); - size = source.size; - data = source.data; - source.data = 0; - source.size = 0; - return *this; -} - -string::~string() { - free(data); -} - -bool string::readfile(const char *filename) { - assign(""); - - #if !defined(_WIN32) - FILE *fp = fopen(filename, "rb"); - #else - FILE *fp = _wfopen(utf16_t(filename), L"rb"); - #endif - if(!fp) return false; - - fseek(fp, 0, SEEK_END); - unsigned size = ftell(fp); - rewind(fp); - char *fdata = new char[size + 1]; - unsigned unused = fread(fdata, 1, size, fp); - fclose(fp); - fdata[size] = 0; - assign(fdata); - delete[] fdata; - - return true; -} - -int lstring::find(const char *key) { - for(unsigned i = 0; i < size(); i++) { - if(operator[](i) == key) return i; - } - return -1; -} - -inline lstring::lstring() { -} - -inline lstring::lstring(std::initializer_list list) { - for(const string *s = list.begin(); s != list.end(); ++s) { - operator<<(*s); - } -} - -} - -#endif diff --git a/snesreader/nall/string/filename.hpp b/snesreader/nall/string/filename.hpp deleted file mode 100644 index f3750760..00000000 --- a/snesreader/nall/string/filename.hpp +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef NALL_FILENAME_HPP -#define NALL_FILENAME_HPP - -namespace nall { - -// "foo/bar.c" -> "foo/", "bar.c" -> "./" -inline string dir(char const *name) { - string result = name; - for(signed i = strlen(result); i >= 0; i--) { - if(result[i] == '/' || result[i] == '\\') { - result[i + 1] = 0; - break; - } - if(i == 0) result = "./"; - } - return result; -} - -// "foo/bar.c" -> "bar.c" -inline string notdir(char const *name) { - for(signed i = strlen(name); i >= 0; i--) { - if(name[i] == '/' || name[i] == '\\') { - name += i + 1; - break; - } - } - string result = name; - return result; -} - -// "foo/bar.c" -> "foo/bar" -inline string basename(char const *name) { - string result = name; - for(signed i = strlen(result); i >= 0; i--) { - if(result[i] == '/' || result[i] == '\\') { - //file has no extension - break; - } - if(result[i] == '.') { - result[i] = 0; - break; - } - } - return result; -} - -// "foo/bar.c" -> "c" -inline string extension(char const *name) { - for(signed i = strlen(name); i >= 0; i--) { - if(name[i] == '.') { - name += i + 1; - break; - } - } - string result = name; - return result; -} - -} - -#endif diff --git a/snesreader/nall/string/match.hpp b/snesreader/nall/string/match.hpp deleted file mode 100644 index d8cf702d..00000000 --- a/snesreader/nall/string/match.hpp +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef NALL_STRING_MATCH_HPP -#define NALL_STRING_MATCH_HPP - -namespace nall { - -bool match(const char *p, const char *s) { - const char *p_ = 0, *s_ = 0; - - for(;;) { - if(!*s) { - while(*p == '*') p++; - return !*p; - } - - //wildcard match - if(*p == '*') { - p_ = p++, s_ = s; - continue; - } - - //any match - if(*p == '?') { - p++, s++; - continue; - } - - //ranged match - if(*p == '{') { - #define pattern(name_, rule_) \ - if(strbegin(p, name_)) { \ - if(rule_) { \ - p += sizeof(name_) - 1, s++; \ - continue; \ - } \ - goto failure; \ - } - - pattern("{alpha}", (*s >= 'A' && *s <= 'Z') || (*s >= 'a' && *s <= 'z')) - pattern("{alphanumeric}", (*s >= 'A' && *s <= 'Z') || (*s >= 'a' && *s <= 'z') || (*s >= '0' && *s <= '9')) - pattern("{binary}", (*s == '0' || *s == '1')) - pattern("{hex}", (*s >= '0' && *s <= '9') || (*s >= 'A' && *s <= 'F') || (*s >= 'a' && *s <= 'f')) - pattern("{lowercase}", (*s >= 'a' && *s <= 'z')) - pattern("{numeric}", (*s >= '0' && *s <= '9')) - pattern("{uppercase}", (*s >= 'A' && *s <= 'Z')) - pattern("{whitespace}", (*s == ' ' || *s == '\t')) - - #undef pattern - goto failure; - } - - //reserved character match - if(*p == '\\') { - p++; - //fallthrough - } - - //literal match - if(*p == *s) { - p++, *s++; - continue; - } - - //attempt wildcard rematch - failure: - if(p_) { - p = p_, s = s_ + 1; - continue; - } - - return false; - } -} - -} - -#endif diff --git a/snesreader/nall/string/math.hpp b/snesreader/nall/string/math.hpp deleted file mode 100644 index ea8b99c8..00000000 --- a/snesreader/nall/string/math.hpp +++ /dev/null @@ -1,164 +0,0 @@ -#ifndef NALL_STRING_MATH_HPP -#define NALL_STRING_MATH_HPP - -namespace nall { - -static int eval_integer(const char *&s) { - if(!*s) throw "unrecognized_integer"; - int value = 0, x = *s, y = *(s + 1); - - //hexadecimal - if(x == '0' && (y == 'X' || y == 'x')) { - s += 2; - while(true) { - if(*s >= '0' && *s <= '9') { value = value * 16 + (*s++ - '0'); continue; } - if(*s >= 'A' && *s <= 'F') { value = value * 16 + (*s++ - 'A' + 10); continue; } - if(*s >= 'a' && *s <= 'f') { value = value * 16 + (*s++ - 'a' + 10); continue; } - return value; - } - } - - //binary - if(x == '0' && (y == 'B' || y == 'b')) { - s += 2; - while(true) { - if(*s == '0' || *s == '1') { value = value * 2 + (*s++ - '0'); continue; } - return value; - } - } - - //octal (or decimal '0') - if(x == '0') { - s += 1; - while(true) { - if(*s >= '0' && *s <= '7') { value = value * 8 + (*s++ - '0'); continue; } - return value; - } - } - - //decimal - if(x >= '0' && x <= '9') { - while(true) { - if(*s >= '0' && *s <= '9') { value = value * 10 + (*s++ - '0'); continue; } - return value; - } - } - - //char - if(x == '\'' && y != '\'') { - s += 1; - while(true) { - value = value * 256 + *s++; - if(*s == '\'') { s += 1; return value; } - if(!*s) throw "mismatched_char"; - } - } - - throw "unrecognized_integer"; -} - -static int eval(const char *&s, int depth = 0) { - while(*s == ' ' || *s == '\t') s++; //trim whitespace - if(!*s) throw "unrecognized_token"; - int value = 0, x = *s, y = *(s + 1); - - if(*s == '(') { - value = eval(++s, 1); - if(*s++ != ')') throw "mismatched_group"; - } - - else if(x == '!') value = !eval(++s, 13); - else if(x == '~') value = ~eval(++s, 13); - else if(x == '+') value = +eval(++s, 13); - else if(x == '-') value = -eval(++s, 13); - - else if((x >= '0' && x <= '9') || x == '\'') value = eval_integer(s); - - else throw "unrecognized_token"; - - while(true) { - while(*s == ' ' || *s == '\t') s++; //trim whitespace - if(!*s) break; - x = *s, y = *(s + 1); - - if(depth >= 13) break; - if(x == '*') { value *= eval(++s, 13); continue; } - if(x == '/') { value /= eval(++s, 13); continue; } - if(x == '%') { value %= eval(++s, 13); continue; } - - if(depth >= 12) break; - if(x == '+') { value += eval(++s, 12); continue; } - if(x == '-') { value -= eval(++s, 12); continue; } - - if(depth >= 11) break; - if(x == '<' && y == '<') { value <<= eval(++++s, 11); continue; } - if(x == '>' && y == '>') { value >>= eval(++++s, 11); continue; } - - if(depth >= 10) break; - if(x == '<' && y == '=') { value = value <= eval(++++s, 10); continue; } - if(x == '>' && y == '=') { value = value >= eval(++++s, 10); continue; } - if(x == '<') { value = value < eval(++s, 10); continue; } - if(x == '>') { value = value > eval(++s, 10); continue; } - - if(depth >= 9) break; - if(x == '=' && y == '=') { value = value == eval(++++s, 9); continue; } - if(x == '!' && y == '=') { value = value != eval(++++s, 9); continue; } - - if(depth >= 8) break; - if(x == '&' && y != '&') { value = value & eval(++s, 8); continue; } - - if(depth >= 7) break; - if(x == '^' && y != '^') { value = value ^ eval(++s, 7); continue; } - - if(depth >= 6) break; - if(x == '|' && y != '|') { value = value | eval(++s, 6); continue; } - - if(depth >= 5) break; - if(x == '&' && y == '&') { value = eval(++++s, 5) && value; continue; } - - if(depth >= 4) break; - if(x == '^' && y == '^') { value = (!eval(++++s, 4) != !value); continue; } - - if(depth >= 3) break; - if(x == '|' && y == '|') { value = eval(++++s, 3) || value; continue; } - - if(x == '?') { - int lhs = eval(++s, 2); - if(*s != ':') throw "mismatched_ternary"; - int rhs = eval(++s, 2); - value = value ? lhs : rhs; - continue; - } - if(depth >= 2) break; - - if(depth > 0 && x == ')') break; - - throw "unrecognized_token"; - } - - return value; -} - -bool strint(const char *s, int &result) { - try { - result = eval_integer(s); - return true; - } catch(const char*) { - result = 0; - return false; - } -} - -bool strmath(const char *s, int &result) { - try { - result = eval(s); - return true; - } catch(const char*) { - result = 0; - return false; - } -} - -} - -#endif diff --git a/snesreader/nall/string/replace.hpp b/snesreader/nall/string/replace.hpp deleted file mode 100644 index db405a9b..00000000 --- a/snesreader/nall/string/replace.hpp +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef NALL_STRING_REPLACE_HPP -#define NALL_STRING_REPLACE_HPP - -namespace nall { - -string& string::replace(const char *key, const char *token) { - int i, z, ksl = strlen(key), tsl = strlen(token), ssl = length(); - unsigned int replace_count = 0, size = ssl; - char *buffer; - - if(ksl <= ssl) { - if(tsl > ksl) { //the new string may be longer than the old string... - for(i = 0; i <= ssl - ksl;) { //so let's find out how big of a string we'll need... - if(!memcmp(data + i, key, ksl)) { - replace_count++; - i += ksl; - } else i++; - } - size = ssl + ((tsl - ksl) * replace_count); - reserve(size); - } - - buffer = new char[size + 1]; - for(i = z = 0; i < ssl;) { - if(i <= ssl - ksl) { - if(!memcmp(data + i, key, ksl)) { - memcpy(buffer + z, token, tsl); - z += tsl; - i += ksl; - } else buffer[z++] = data[i++]; - } else buffer[z++] = data[i++]; - } - buffer[z] = 0; - - assign(buffer); - delete[] buffer; - } - - return *this; -} - -string& string::qreplace(const char *key, const char *token) { - int i, l, z, ksl = strlen(key), tsl = strlen(token), ssl = length(); - unsigned int replace_count = 0, size = ssl; - uint8_t x; - char *buffer; - - if(ksl <= ssl) { - if(tsl > ksl) { - for(i = 0; i <= ssl - ksl;) { - x = data[i]; - if(x == '\"' || x == '\'') { - l = i; - i++; - while(data[i++] != x) { - if(i == ssl) { - i = l; - break; - } - } - } - if(!memcmp(data + i, key, ksl)) { - replace_count++; - i += ksl; - } else i++; - } - size = ssl + ((tsl - ksl) * replace_count); - reserve(size); - } - - buffer = new char[size + 1]; - for(i = z = 0; i < ssl;) { - x = data[i]; - if(x == '\"' || x == '\'') { - l = i++; - while(data[i] != x && i < ssl)i++; - if(i >= ssl)i = l; - else { - memcpy(buffer + z, data + l, i - l); - z += i - l; - } - } - if(i <= ssl - ksl) { - if(!memcmp(data + i, key, ksl)) { - memcpy(buffer + z, token, tsl); - z += tsl; - i += ksl; - replace_count++; - } else buffer[z++] = data[i++]; - } else buffer[z++] = data[i++]; - } - buffer[z] = 0; - - assign(buffer); - delete[] buffer; - } - - return *this; -} - -}; - -#endif diff --git a/snesreader/nall/string/split.hpp b/snesreader/nall/string/split.hpp deleted file mode 100644 index bb77dfcd..00000000 --- a/snesreader/nall/string/split.hpp +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef NALL_STRING_SPLIT_HPP -#define NALL_STRING_SPLIT_HPP - -namespace nall { - -void lstring::split(const char *key, const char *src, unsigned limit) { - reset(); - - int ssl = strlen(src), ksl = strlen(key); - int lp = 0, split_count = 0; - - for(int i = 0; i <= ssl - ksl;) { - if(!memcmp(src + i, key, ksl)) { - strlcpy(operator[](split_count++), src + lp, i - lp + 1); - i += ksl; - lp = i; - if(!--limit) break; - } else i++; - } - - operator[](split_count++) = src + lp; -} - -void lstring::qsplit(const char *key, const char *src, unsigned limit) { - reset(); - - int ssl = strlen(src), ksl = strlen(key); - int lp = 0, split_count = 0; - - for(int i = 0; i <= ssl - ksl;) { - uint8_t x = src[i]; - - if(x == '\"' || x == '\'') { - int z = i++; //skip opening quote - while(i < ssl && src[i] != x) i++; - if(i >= ssl) i = z; //failed match, rewind i - else { - i++; //skip closing quote - continue; //restart in case next char is also a quote - } - } - - if(!memcmp(src + i, key, ksl)) { - strlcpy(operator[](split_count++), src + lp, i - lp + 1); - i += ksl; - lp = i; - if(!--limit) break; - } else i++; - } - - operator[](split_count++) = src + lp; -} - -}; - -#endif diff --git a/snesreader/nall/string/strl.hpp b/snesreader/nall/string/strl.hpp deleted file mode 100644 index 84c841fa..00000000 --- a/snesreader/nall/string/strl.hpp +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef NALL_STRING_STRL_HPP -#define NALL_STRING_STRL_HPP - -namespace nall { - -//strlcpy, strlcat based on OpenBSD implementation by Todd C. Miller - -//return = strlen(src) -unsigned strlcpy(char *dest, const char *src, unsigned length) { - char *d = dest; - const char *s = src; - unsigned n = length; - - if(n) { - while(--n && (*d++ = *s++)); //copy as many bytes as possible, or until null terminator reached - } - - if(!n) { - if(length) *d = 0; - while(*s++); //traverse rest of s, so that s - src == strlen(src) - } - - return (s - src - 1); //return length of copied string, sans null terminator -} - -//return = strlen(src) + min(length, strlen(dest)) -unsigned strlcat(char *dest, const char *src, unsigned length) { - char *d = dest; - const char *s = src; - unsigned n = length; - - while(n-- && *d) d++; //find end of dest - unsigned dlength = d - dest; - n = length - dlength; //subtract length of dest from maximum string length - - if(!n) return dlength + strlen(s); - - while(*s) { - if(n != 1) { - *d++ = *s; - n--; - } - s++; - } - *d = 0; - - return dlength + (s - src); //return length of resulting string, sans null terminator -} - -} - -#endif diff --git a/snesreader/nall/string/trim.hpp b/snesreader/nall/string/trim.hpp deleted file mode 100644 index b13ab9ba..00000000 --- a/snesreader/nall/string/trim.hpp +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef NALL_STRING_TRIM_HPP -#define NALL_STRING_TRIM_HPP - -namespace nall { - -char* ltrim(char *str, const char *key) { - if(!key || !*key) return str; - while(strbegin(str, key)) { - char *dest = str, *src = str + strlen(key); - while(true) { - *dest = *src++; - if(!*dest) break; - dest++; - } - } - return str; -} - -char* rtrim(char *str, const char *key) { - if(!key || !*key) return str; - while(strend(str, key)) str[strlen(str) - strlen(key)] = 0; - return str; -} - -char* trim(char *str, const char *key) { - return ltrim(rtrim(str, key), key); -} - -char* ltrim_once(char *str, const char *key) { - if(!key || !*key) return str; - if(strbegin(str, key)) { - char *dest = str, *src = str + strlen(key); - while(true) { - *dest = *src++; - if(!*dest) break; - dest++; - } - } - return str; -} - -char* rtrim_once(char *str, const char *key) { - if(!key || !*key) return str; - if(strend(str, key)) str[strlen(str) - strlen(key)] = 0; - return str; -} - -char* trim_once(char *str, const char *key) { - return ltrim_once(rtrim_once(str, key), key); -} - -} - -#endif diff --git a/snesreader/nall/string/utility.hpp b/snesreader/nall/string/utility.hpp deleted file mode 100644 index 2da2762b..00000000 --- a/snesreader/nall/string/utility.hpp +++ /dev/null @@ -1,169 +0,0 @@ -#ifndef NALL_STRING_UTILITY_HPP -#define NALL_STRING_UTILITY_HPP - -namespace nall { - -unsigned strlcpy(string &dest, const char *src, unsigned length) { - dest.reserve(length); - return strlcpy(dest(), src, length); -} - -unsigned strlcat(string &dest, const char *src, unsigned length) { - dest.reserve(length); - return strlcat(dest(), src, length); -} - -string substr(const char *src, unsigned start, unsigned length) { - string dest; - if(length == 0) { - //copy entire string - dest = src + start; - } else { - //copy partial string - strlcpy(dest, src + start, length + 1); - } - return dest; -} - -/* very simplistic wrappers to return string& instead of char* type */ - -string& strlower(string &str) { strlower(str()); return str; } -string& strupper(string &str) { strupper(str()); return str; } -string& strtr(string &dest, const char *before, const char *after) { strtr(dest(), before, after); return dest; } -string& ltrim(string &str, const char *key) { ltrim(str(), key); return str; } -string& rtrim(string &str, const char *key) { rtrim(str(), key); return str; } -string& trim (string &str, const char *key) { trim (str(), key); return str; } -string& ltrim_once(string &str, const char *key) { ltrim_once(str(), key); return str; } -string& rtrim_once(string &str, const char *key) { rtrim_once(str(), key); return str; } -string& trim_once (string &str, const char *key) { trim_once (str(), key); return str; } - -/* arithmetic <> string */ - -template string strhex(uintmax_t value) { - string output; - unsigned offset = 0; - - //render string backwards, as we do not know its length yet - do { - unsigned n = value & 15; - output[offset++] = n < 10 ? '0' + n : 'a' + n - 10; - value >>= 4; - } while(value); - - while(offset < length) output[offset++] = padding; - output[offset--] = 0; - - //reverse the string in-place - for(unsigned i = 0; i < (offset + 1) >> 1; i++) { - char temp = output[i]; - output[i] = output[offset - i]; - output[offset - i] = temp; - } - - return output; -} - -template string strsigned(intmax_t value) { - string output; - unsigned offset = 0; - - bool negative = value < 0; - if(negative) value = abs(value); - - do { - unsigned n = value % 10; - output[offset++] = '0' + n; - value /= 10; - } while(value); - - while(offset < length) output[offset++] = padding; - if(negative) output[offset++] = '-'; - output[offset--] = 0; - - for(unsigned i = 0; i < (offset + 1) >> 1; i++) { - char temp = output[i]; - output[i] = output[offset - i]; - output[offset - i] = temp; - } - - return output; -} - -template string strunsigned(uintmax_t value) { - string output; - unsigned offset = 0; - - do { - unsigned n = value % 10; - output[offset++] = '0' + n; - value /= 10; - } while(value); - - while(offset < length) output[offset++] = padding; - output[offset--] = 0; - - for(unsigned i = 0; i < (offset + 1) >> 1; i++) { - char temp = output[i]; - output[i] = output[offset - i]; - output[offset - i] = temp; - } - - return output; -} - -template string strbin(uintmax_t value) { - string output; - unsigned offset = 0; - - do { - unsigned n = value & 1; - output[offset++] = '0' + n; - value >>= 1; - } while(value); - - while(offset < length) output[offset++] = padding; - output[offset--] = 0; - - for(unsigned i = 0; i < (offset + 1) >> 1; i++) { - char temp = output[i]; - output[i] = output[offset - i]; - output[offset - i] = temp; - } - - return output; -} - -//using sprintf is certainly not the most ideal method to convert -//a double to a string ... but attempting to parse a double by -//hand, digit-by-digit, results in subtle rounding errors. -unsigned strdouble(char *str, double value) { - char buffer[256]; - sprintf(buffer, "%f", value); - - //remove excess 0's in fraction (2.500000 -> 2.5) - for(char *p = buffer; *p; p++) { - if(*p == '.') { - char *p = buffer + strlen(buffer) - 1; - while(*p == '0') { - if(*(p - 1) != '.') *p = 0; //... but not for eg 1.0 -> 1. - p--; - } - break; - } - } - - unsigned length = strlen(buffer); - if(str) strcpy(str, buffer); - return length + 1; -} - -string strdouble(double value) { - string temp; - temp.reserve(strdouble(0, value)); - strdouble(temp(), value); - return temp; -} - -} - -#endif diff --git a/snesreader/nall/string/variadic.hpp b/snesreader/nall/string/variadic.hpp deleted file mode 100644 index 13c477a8..00000000 --- a/snesreader/nall/string/variadic.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef NALL_STRING_VARIADIC_HPP -#define NALL_STRING_VARIADIC_HPP - -namespace nall { - -static void isprint(string &output) { -} - -template -static void isprint(string &output, T value, Args... args) { - output << to_string(value); - isprint(output, args...); -} - -template inline string sprint(Args... args) { - string output; - isprint(output, args...); - return output; -} - -template inline void print(Args... args) { - printf("%s", (const char*)sprint(args...)); -} - -} - -#endif diff --git a/snesreader/nall/string/xml.hpp b/snesreader/nall/string/xml.hpp deleted file mode 100644 index d423f87f..00000000 --- a/snesreader/nall/string/xml.hpp +++ /dev/null @@ -1,257 +0,0 @@ -#ifndef NALL_STRING_XML_HPP -#define NALL_STRING_XML_HPP - -//XML subset parser -//version 0.05 - -namespace nall { - -struct xml_attribute { - string name; - string content; - virtual string parse() const; -}; - -struct xml_element : xml_attribute { - string parse() const; - linear_vector attribute; - linear_vector element; - -protected: - void parse_doctype(const char *&data); - bool parse_head(string data); - bool parse_body(const char *&data); - friend xml_element xml_parse(const char *data); -}; - -inline string xml_attribute::parse() const { - string data; - unsigned offset = 0; - - const char *source = content; - while(*source) { - if(*source == '&') { - if(strbegin(source, "<")) { data[offset++] = '<'; source += 4; continue; } - if(strbegin(source, ">")) { data[offset++] = '>'; source += 4; continue; } - if(strbegin(source, "&")) { data[offset++] = '&'; source += 5; continue; } - if(strbegin(source, "'")) { data[offset++] = '\''; source += 6; continue; } - if(strbegin(source, """)) { data[offset++] = '"'; source += 6; continue; } - } - - //reject illegal characters - if(*source == '&') return ""; - if(*source == '<') return ""; - if(*source == '>') return ""; - - data[offset++] = *source++; - } - - data[offset] = 0; - return data; -} - -inline string xml_element::parse() const { - string data; - unsigned offset = 0; - - const char *source = content; - while(*source) { - if(*source == '&') { - if(strbegin(source, "<")) { data[offset++] = '<'; source += 4; continue; } - if(strbegin(source, ">")) { data[offset++] = '>'; source += 4; continue; } - if(strbegin(source, "&")) { data[offset++] = '&'; source += 5; continue; } - if(strbegin(source, "'")) { data[offset++] = '\''; source += 6; continue; } - if(strbegin(source, """)) { data[offset++] = '"'; source += 6; continue; } - } - - if(strbegin(source, ""); - if(pos == -1) return ""; - source += pos + 3; - continue; - } - - if(strbegin(source, ""); - if(pos == -1) return ""; - string cdata = substr(source, 9, pos - 9); - data << cdata; - offset += strlen(cdata); - - source += offset + 3; - continue; - } - - //reject illegal characters - if(*source == '&') return ""; - if(*source == '<') return ""; - if(*source == '>') return ""; - - data[offset++] = *source++; - } - - data[offset] = 0; - return data; -} - -inline void xml_element::parse_doctype(const char *&data) { - name = "!DOCTYPE"; - const char *content_begin = data; - - signed counter = 0; - while(*data) { - char value = *data++; - if(value == '<') counter++; - if(value == '>') counter--; - if(counter < 0) { - content = substr(content_begin, 0, data - content_begin - 1); - return; - } - } - throw "..."; -} - -inline bool xml_element::parse_head(string data) { - data.qreplace("\t", " "); - data.qreplace("\r", " "); - data.qreplace("\n", " "); - while(qstrpos(data, " ") >= 0) data.qreplace(" ", " "); - data.qreplace(" =", "="); - data.qreplace("= ", "="); - rtrim(data); - - lstring part; - part.qsplit(" ", data); - - name = part[0]; - if(name == "") throw "..."; - - for(unsigned i = 1; i < part.size(); i++) { - lstring side; - side.qsplit("=", part[i]); - if(side.size() != 2) throw "..."; - - xml_attribute attr; - attr.name = side[0]; - attr.content = side[1]; - if(strbegin(attr.content, "\"") && strend(attr.content, "\"")) trim_once(attr.content, "\""); - else if(strbegin(attr.content, "'") && strend(attr.content, "'")) trim_once(attr.content, "'"); - else throw "..."; - attribute.add(attr); - } -} - -inline bool xml_element::parse_body(const char *&data) { - while(true) { - if(!*data) return false; - if(*data++ != '<') continue; - if(*data == '/') return false; - - if(strbegin(data, "!DOCTYPE") == true) { - parse_doctype(data); - return true; - } - - if(strbegin(data, "!--")) { - signed offset = strpos(data, "-->"); - if(offset == -1) throw "..."; - data += offset + 3; - continue; - } - - if(strbegin(data, "![CDATA[")) { - signed offset = strpos(data, "]]>"); - if(offset == -1) throw "..."; - data += offset + 3; - continue; - } - - signed offset = strpos(data, ">"); - if(offset == -1) throw "..."; - - string tag = substr(data, 0, offset); - data += offset + 1; - const char *content_begin = data; - - bool self_terminating = false; - - if(strend(tag, "?") == true) { - self_terminating = true; - rtrim_once(tag, "?"); - } else if(strend(tag, "/") == true) { - self_terminating = true; - rtrim_once(tag, "/"); - } - - parse_head(tag); - if(self_terminating) return true; - - while(*data) { - unsigned index = element.size(); - xml_element node; - if(node.parse_body(data) == false) { - if(*data == '/') { - signed length = data - content_begin - 1; - if(length > 0) content = substr(content_begin, 0, length); - - data++; - offset = strpos(data, ">"); - if(offset == -1) throw "..."; - - tag = substr(data, 0, offset); - data += offset + 1; - - tag.replace("\t", " "); - tag.replace("\r", " "); - tag.replace("\n", " "); - while(strpos(tag, " ") >= 0) tag.replace(" ", " "); - rtrim(tag); - - if(name != tag) throw "..."; - return true; - } - } else { - element.add(node); - } - } - } -} - -//ensure there is only one root element -inline bool xml_validate(xml_element &document) { - unsigned root_counter = 0; - - for(unsigned i = 0; i < document.element.size(); i++) { - string &name = document.element[i].name; - if(strbegin(name, "?")) continue; - if(strbegin(name, "!")) continue; - if(++root_counter > 1) return false; - } - - return true; -} - -inline xml_element xml_parse(const char *data) { - xml_element self; - - try { - while(*data) { - xml_element node; - if(node.parse_body(data) == false) { - break; - } else { - self.element.add(node); - } - } - - if(xml_validate(self) == false) throw "..."; - return self; - } catch(const char*) { - xml_element empty; - return empty; - } -} - -} - -#endif diff --git a/snesreader/nall/ups.hpp b/snesreader/nall/ups.hpp deleted file mode 100644 index f255ecb3..00000000 --- a/snesreader/nall/ups.hpp +++ /dev/null @@ -1,190 +0,0 @@ -#ifndef NALL_UPS_HPP -#define NALL_UPS_HPP - -#include - -#include -#include -#include -#include - -namespace nall { - class ups { - public: - enum result { - ok, - patch_unreadable, - patch_unwritable, - patch_invalid, - input_invalid, - output_invalid, - patch_crc32_invalid, - input_crc32_invalid, - output_crc32_invalid, - }; - - ups::result create(const char *patch_fn, const uint8_t *x_data, unsigned x_size, const uint8_t *y_data, unsigned y_size) { - if(!fp.open(patch_fn, file::mode_write)) return patch_unwritable; - - crc32 = ~0; - uint32_t x_crc32 = crc32_calculate(x_data, x_size); - uint32_t y_crc32 = crc32_calculate(y_data, y_size); - - //header - write('U'); - write('P'); - write('S'); - write('1'); - encptr(x_size); - encptr(y_size); - - //body - unsigned max_size = max(x_size, y_size); - unsigned relative = 0; - for(unsigned i = 0; i < max_size;) { - uint8_t x = i < x_size ? x_data[i] : 0x00; - uint8_t y = i < y_size ? y_data[i] : 0x00; - - if(x == y) { - i++; - continue; - } - - encptr(i++ - relative); - write(x ^ y); - - while(true) { - if(i >= max_size) { - write(0x00); - break; - } - - x = i < x_size ? x_data[i] : 0x00; - y = i < y_size ? y_data[i] : 0x00; - i++; - write(x ^ y); - if(x == y) break; - } - - relative = i; - } - - //footer - for(unsigned i = 0; i < 4; i++) write(x_crc32 >> (i << 3)); - for(unsigned i = 0; i < 4; i++) write(y_crc32 >> (i << 3)); - uint32_t p_crc32 = ~crc32; - for(unsigned i = 0; i < 4; i++) write(p_crc32 >> (i << 3)); - - fp.close(); - return ok; - } - - ups::result apply(const uint8_t *p_data, unsigned p_size, const uint8_t *x_data, unsigned x_size, uint8_t *&y_data, unsigned &y_size) { - if(p_size < 18) return patch_invalid; - p_buffer = p_data; - - crc32 = ~0; - - //header - if(read() != 'U') return patch_invalid; - if(read() != 'P') return patch_invalid; - if(read() != 'S') return patch_invalid; - if(read() != '1') return patch_invalid; - - unsigned px_size = decptr(); - unsigned py_size = decptr(); - - //mirror - if(x_size != px_size && x_size != py_size) return input_invalid; - y_size = (x_size == px_size) ? py_size : px_size; - y_data = new uint8_t[y_size](); - - for(unsigned i = 0; i < x_size && i < y_size; i++) y_data[i] = x_data[i]; - for(unsigned i = x_size; i < y_size; i++) y_data[i] = 0x00; - - //body - unsigned relative = 0; - while(p_buffer < p_data + p_size - 12) { - relative += decptr(); - - while(true) { - uint8_t x = read(); - if(x && relative < y_size) { - uint8_t y = relative < x_size ? x_data[relative] : 0x00; - y_data[relative] = x ^ y; - } - relative++; - if(!x) break; - } - } - - //footer - unsigned px_crc32 = 0, py_crc32 = 0, pp_crc32 = 0; - for(unsigned i = 0; i < 4; i++) px_crc32 |= read() << (i << 3); - for(unsigned i = 0; i < 4; i++) py_crc32 |= read() << (i << 3); - uint32_t p_crc32 = ~crc32; - for(unsigned i = 0; i < 4; i++) pp_crc32 |= read() << (i << 3); - - uint32_t x_crc32 = crc32_calculate(x_data, x_size); - uint32_t y_crc32 = crc32_calculate(y_data, y_size); - - if(px_size != py_size) { - if(x_size == px_size && x_crc32 != px_crc32) return input_crc32_invalid; - if(x_size == py_size && x_crc32 != py_crc32) return input_crc32_invalid; - if(y_size == px_size && y_crc32 != px_crc32) return output_crc32_invalid; - if(y_size == py_size && y_crc32 != py_crc32) return output_crc32_invalid; - } else { - if(x_crc32 != px_crc32 && x_crc32 != py_crc32) return input_crc32_invalid; - if(y_crc32 != px_crc32 && y_crc32 != py_crc32) return output_crc32_invalid; - if(x_crc32 == y_crc32 && px_crc32 != py_crc32) return output_crc32_invalid; - if(x_crc32 != y_crc32 && px_crc32 == py_crc32) return output_crc32_invalid; - } - - if(p_crc32 != pp_crc32) return patch_crc32_invalid; - return ok; - } - - private: - file fp; - uint32_t crc32; - const uint8_t *p_buffer; - - uint8_t read() { - uint8_t n = *p_buffer++; - crc32 = crc32_adjust(crc32, n); - return n; - } - - void write(uint8_t n) { - fp.write(n); - crc32 = crc32_adjust(crc32, n); - } - - void encptr(uint64_t offset) { - while(true) { - uint64_t x = offset & 0x7f; - offset >>= 7; - if(offset == 0) { - write(0x80 | x); - break; - } - write(x); - offset--; - } - } - - uint64_t decptr() { - uint64_t offset = 0, shift = 1; - while(true) { - uint8_t x = read(); - offset += (x & 0x7f) * shift; - if(x & 0x80) break; - shift <<= 7; - offset += shift; - } - return offset; - } - }; -} - -#endif diff --git a/snesreader/nall/utf8.hpp b/snesreader/nall/utf8.hpp deleted file mode 100644 index c66c341a..00000000 --- a/snesreader/nall/utf8.hpp +++ /dev/null @@ -1,72 +0,0 @@ -#ifndef NALL_UTF8_HPP -#define NALL_UTF8_HPP - -//UTF-8 <> UTF-16 conversion -//used only for Win32; Linux, etc use UTF-8 internally - -#if defined(_WIN32) - -#undef _WIN32_WINNT -#define _WIN32_WINNT 0x0501 -#undef NOMINMAX -#define NOMINMAX -#include -#undef interface - -namespace nall { - //UTF-8 to UTF-16 - class utf16_t { - public: - operator wchar_t*() { - return buffer; - } - - operator const wchar_t*() const { - return buffer; - } - - utf16_t(const char *s = "") { - if(!s) s = ""; - unsigned length = MultiByteToWideChar(CP_UTF8, 0, s, -1, 0, 0); - buffer = new wchar_t[length + 1](); - MultiByteToWideChar(CP_UTF8, 0, s, -1, buffer, length); - } - - ~utf16_t() { - delete[] buffer; - } - - private: - wchar_t *buffer; - }; - - //UTF-16 to UTF-8 - class utf8_t { - public: - operator char*() { - return buffer; - } - - operator const char*() const { - return buffer; - } - - utf8_t(const wchar_t *s = L"") { - if(!s) s = L""; - unsigned length = WideCharToMultiByte(CP_UTF8, 0, s, -1, 0, 0, (const char*)0, (BOOL*)0); - buffer = new char[length + 1](); - WideCharToMultiByte(CP_UTF8, 0, s, -1, buffer, length, (const char*)0, (BOOL*)0); - } - - ~utf8_t() { - delete[] buffer; - } - - private: - char *buffer; - }; -} - -#endif //if defined(_WIN32) - -#endif diff --git a/snesreader/nall/utility.hpp b/snesreader/nall/utility.hpp deleted file mode 100644 index 2a63f515..00000000 --- a/snesreader/nall/utility.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef NALL_UTILITY_HPP -#define NALL_UTILITY_HPP - -#include -#include - -namespace nall { - template struct enable_if { typedef T type; }; - template struct enable_if {}; - template struct mp_enable_if : enable_if {}; - - template inline void swap(T &x, T &y) { - T temp(std::move(x)); - x = std::move(y); - y = std::move(temp); - } - - template struct base_from_member { - T value; - base_from_member(T value_) : value(value_) {} - }; - - template inline T* allocate(size_t size, const T &value) { - T *array = new T[size]; - for(size_t i = 0; i < size; i++) array[i] = value; - return array; - } -} - -#endif diff --git a/snesreader/nall/varint.hpp b/snesreader/nall/varint.hpp deleted file mode 100644 index cc3bb17c..00000000 --- a/snesreader/nall/varint.hpp +++ /dev/null @@ -1,92 +0,0 @@ -#ifndef NALL_VARINT_HPP -#define NALL_VARINT_HPP - -#include -#include -#include - -namespace nall { - template class uint_t { - private: - enum { bytes = (bits + 7) >> 3 }; //minimum number of bytes needed to store value - typedef typename static_if< - sizeof(int) >= bytes, - unsigned int, - typename static_if< - sizeof(long) >= bytes, - unsigned long, - typename static_if< - sizeof(long long) >= bytes, - unsigned long long, - void - >::type - >::type - >::type T; - static_assert::value> uint_assert; - T data; - - public: - inline operator T() const { return data; } - inline T operator ++(int) { T r = data; data = uclip(data + 1); return r; } - inline T operator --(int) { T r = data; data = uclip(data - 1); return r; } - inline T operator ++() { return data = uclip(data + 1); } - inline T operator --() { return data = uclip(data - 1); } - inline T operator =(const T i) { return data = uclip(i); } - inline T operator |=(const T i) { return data = uclip(data | i); } - inline T operator ^=(const T i) { return data = uclip(data ^ i); } - inline T operator &=(const T i) { return data = uclip(data & i); } - inline T operator<<=(const T i) { return data = uclip(data << i); } - inline T operator>>=(const T i) { return data = uclip(data >> i); } - inline T operator +=(const T i) { return data = uclip(data + i); } - inline T operator -=(const T i) { return data = uclip(data - i); } - inline T operator *=(const T i) { return data = uclip(data * i); } - inline T operator /=(const T i) { return data = uclip(data / i); } - inline T operator %=(const T i) { return data = uclip(data % i); } - - inline uint_t() : data(0) {} - inline uint_t(const T i) : data(uclip(i)) {} - }; - - template class int_t { - private: - enum { bytes = (bits + 7) >> 3 }; //minimum number of bytes needed to store value - typedef typename static_if< - sizeof(int) >= bytes, - signed int, - typename static_if< - sizeof(long) >= bytes, - signed long, - typename static_if< - sizeof(long long) >= bytes, - signed long long, - void - >::type - >::type - >::type T; - static_assert::value> int_assert; - T data; - - public: - inline operator T() const { return data; } - inline T operator ++(int) { T r = data; data = sclip(data + 1); return r; } - inline T operator --(int) { T r = data; data = sclip(data - 1); return r; } - inline T operator ++() { return data = sclip(data + 1); } - inline T operator --() { return data = sclip(data - 1); } - inline T operator =(const T i) { return data = sclip(i); } - inline T operator |=(const T i) { return data = sclip(data | i); } - inline T operator ^=(const T i) { return data = sclip(data ^ i); } - inline T operator &=(const T i) { return data = sclip(data & i); } - inline T operator<<=(const T i) { return data = sclip(data << i); } - inline T operator>>=(const T i) { return data = sclip(data >> i); } - inline T operator +=(const T i) { return data = sclip(data + i); } - inline T operator -=(const T i) { return data = sclip(data - i); } - inline T operator *=(const T i) { return data = sclip(data * i); } - inline T operator /=(const T i) { return data = sclip(data / i); } - inline T operator %=(const T i) { return data = sclip(data % i); } - - inline int_t() : data(0) {} - inline int_t(const T i) : data(sclip(i)) {} - }; -} - -#endif diff --git a/snesreader/nall/vector.hpp b/snesreader/nall/vector.hpp deleted file mode 100644 index 3d69d4d5..00000000 --- a/snesreader/nall/vector.hpp +++ /dev/null @@ -1,240 +0,0 @@ -#ifndef NALL_VECTOR_HPP -#define NALL_VECTOR_HPP - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace nall { - //linear_vector - //memory: O(capacity * 2) - // - //linear_vector uses placement new + manual destructor calls to create a - //contiguous block of memory for all objects. accessing individual elements - //is fast, though resizing the array incurs significant overhead. - //reserve() overhead is reduced from quadratic time to amortized constant time - //by resizing twice as much as requested. - // - //if objects hold memory address references to themselves (introspection), a - //valid copy constructor will be needed to keep pointers valid. - - template class linear_vector { - protected: - T *pool; - unsigned poolsize, objectsize; - - public: - unsigned size() const { return objectsize; } - unsigned capacity() const { return poolsize; } - - void reset() { - if(pool) { - for(unsigned i = 0; i < objectsize; i++) pool[i].~T(); - free(pool); - } - pool = 0; - poolsize = 0; - objectsize = 0; - } - - void reserve(unsigned newsize) { - newsize = bit::round(newsize); //round to nearest power of two (for amortized growth) - - T *poolcopy = (T*)malloc(newsize * sizeof(T)); - for(unsigned i = 0; i < min(objectsize, newsize); i++) new(poolcopy + i) T(pool[i]); - for(unsigned i = 0; i < objectsize; i++) pool[i].~T(); - free(pool); - pool = poolcopy; - poolsize = newsize; - objectsize = min(objectsize, newsize); - } - - void resize(unsigned newsize) { - if(newsize > poolsize) reserve(newsize); - - if(newsize < objectsize) { - //vector is shrinking; destroy excess objects - for(unsigned i = newsize; i < objectsize; i++) pool[i].~T(); - } else if(newsize > objectsize) { - //vector is expanding; allocate new objects - for(unsigned i = objectsize; i < newsize; i++) new(pool + i) T; - } - - objectsize = newsize; - } - - void add(const T data) { - if(objectsize + 1 > poolsize) reserve(objectsize + 1); - new(pool + objectsize++) T(data); - } - - inline T& operator[](unsigned index) { - if(index >= objectsize) resize(index + 1); - return pool[index]; - } - - inline const T& operator[](unsigned index) const { - if(index >= objectsize) throw "vector[] out of bounds"; - return pool[index]; - } - - //copy - inline linear_vector& operator=(const linear_vector &source) { - reset(); - reserve(source.capacity()); - resize(source.size()); - for(unsigned i = 0; i < source.size(); i++) operator[](i) = source.operator[](i); - return *this; - } - - linear_vector(const linear_vector &source) : pool(0), poolsize(0), objectsize(0) { - operator=(source); - } - - //move - inline linear_vector& operator=(linear_vector &&source) { - reset(); - pool = source.pool; - poolsize = source.poolsize; - objectsize = source.objectsize; - source.pool = 0; - source.reset(); - return *this; - } - - linear_vector(linear_vector &&source) : pool(0), poolsize(0), objectsize(0) { - operator=(std::move(source)); - } - - //construction - linear_vector() : pool(0), poolsize(0), objectsize(0) { - } - - linear_vector(std::initializer_list list) : pool(0), poolsize(0), objectsize(0) { - for(const T *p = list.begin(); p != list.end(); ++p) add(*p); - } - - ~linear_vector() { - reset(); - } - }; - - //pointer_vector - //memory: O(1) - // - //pointer_vector keeps an array of pointers to each vector object. this adds - //significant overhead to individual accesses, but allows for optimal memory - //utilization. - // - //by guaranteeing that the base memory address of each objects never changes, - //this avoids the need for an object to have a valid copy constructor. - - template class pointer_vector { - protected: - T **pool; - unsigned poolsize, objectsize; - - public: - unsigned size() const { return objectsize; } - unsigned capacity() const { return poolsize; } - - void reset() { - if(pool) { - for(unsigned i = 0; i < objectsize; i++) { if(pool[i]) delete pool[i]; } - free(pool); - } - pool = 0; - poolsize = 0; - objectsize = 0; - } - - void reserve(unsigned newsize) { - newsize = bit::round(newsize); //round to nearest power of two (for amortized growth) - - for(unsigned i = newsize; i < objectsize; i++) { - if(pool[i]) { delete pool[i]; pool[i] = 0; } - } - - pool = (T**)realloc(pool, newsize * sizeof(T*)); - for(unsigned i = poolsize; i < newsize; i++) pool[i] = 0; - poolsize = newsize; - objectsize = min(objectsize, newsize); - } - - void resize(unsigned newsize) { - if(newsize > poolsize) reserve(newsize); - - for(unsigned i = newsize; i < objectsize; i++) { - if(pool[i]) { delete pool[i]; pool[i] = 0; } - } - - objectsize = newsize; - } - - void add(const T data) { - if(objectsize + 1 > poolsize) reserve(objectsize + 1); - pool[objectsize++] = new T(data); - } - - inline T& operator[](unsigned index) { - if(index >= objectsize) resize(index + 1); - if(!pool[index]) pool[index] = new T; - return *pool[index]; - } - - inline const T& operator[](unsigned index) const { - if(index >= objectsize || !pool[index]) throw "vector[] out of bounds"; - return *pool[index]; - } - - //copy - inline pointer_vector& operator=(const pointer_vector &source) { - reset(); - reserve(source.capacity()); - resize(source.size()); - for(unsigned i = 0; i < source.size(); i++) operator[](i) = source.operator[](i); - return *this; - } - - pointer_vector(const pointer_vector &source) : pool(0), poolsize(0), objectsize(0) { - operator=(source); - } - - //move - inline pointer_vector& operator=(pointer_vector &&source) { - reset(); - pool = source.pool; - poolsize = source.poolsize; - objectsize = source.objectsize; - source.pool = 0; - source.reset(); - return *this; - } - - pointer_vector(pointer_vector &&source) : pool(0), poolsize(0), objectsize(0) { - operator=(std::move(source)); - } - - //construction - pointer_vector() : pool(0), poolsize(0), objectsize(0) { - } - - pointer_vector(std::initializer_list list) : pool(0), poolsize(0), objectsize(0) { - for(const T *p = list.begin(); p != list.end(); ++p) add(*p); - } - - ~pointer_vector() { - reset(); - } - }; - - template struct has_size> { enum { value = true }; }; - template struct has_size> { enum { value = true }; }; -} - -#endif diff --git a/snesreader/snesreader.cpp b/snesreader/snesreader.cpp deleted file mode 100644 index 055efd48..00000000 --- a/snesreader/snesreader.cpp +++ /dev/null @@ -1,235 +0,0 @@ -#include "snesreader.hpp" - -#if defined(_WIN32) - #define dllexport __declspec(dllexport) -#else - #define dllexport -#endif - -#include "fex/fex.h" -#include "libjma/jma.h" -extern "C" char* uncompressStream(int, int); //micro-bunzip - -#define QT_CORE_LIB -#include - -#include -#include -using namespace nall; - -#include "xml.cpp" - -dllexport const char* snesreader_supported() { - return "*.zip *.z *.7z *.rar *.gz *.bz2 *.jma"; -} - -void snesreader_apply_ips(const char *filename, uint8_t *&data, unsigned &size) { - file fp; - if(fp.open(filename, file::mode_read) == false) return; - - unsigned psize = fp.size(); - uint8_t *pdata = new uint8_t[psize]; - fp.read(pdata, psize); - fp.close(); - - if(psize < 8 || pdata[0] != 'P' || pdata[1] != 'A' || pdata[2] != 'T' || pdata[3] != 'C' || pdata[4] != 'H') { delete[] pdata; return; } - - unsigned outsize = 0; - uint8_t *outdata = new uint8_t[16 * 1024 * 1024]; - memset(outdata, 0, 16 * 1024 * 1024); - memcpy(outdata, data, size); - - unsigned offset = 5; - while(offset < psize - 3) { - unsigned addr; - addr = pdata[offset++] << 16; - addr |= pdata[offset++] << 8; - addr |= pdata[offset++] << 0; - - unsigned size; - size = pdata[offset++] << 8; - size |= pdata[offset++] << 0; - - if(size == 0) { - //RLE - size = pdata[offset++] << 8; - size |= pdata[offset++] << 0; - - for(unsigned n = addr; n < addr + size;) { - outdata[n++] = pdata[offset]; - if(n > outsize) outsize = n; - } - offset++; - } else { - //uncompressed - for(unsigned n = addr; n < addr + size;) { - outdata[n++] = pdata[offset++]; - if(n > outsize) outsize = n; - } - } - } - - delete[] pdata; - delete[] data; - data = outdata; - size = max(size, outsize); -} - -bool snesreader_load_normal(const char *filename, uint8_t *&data, unsigned &size) { - file fp; - if(fp.open(filename, file::mode_read) == false) return false; - size = fp.size(); - data = new uint8_t[size]; - fp.read(data, size); - fp.close(); - return true; -} - -#include "filechooser.cpp" - -bool snesreader_load_fex(string &filename, uint8_t *&data, unsigned &size) { - fex_t *fex; - fex_open(&fex, filename); - if(fex_done(fex)) { fex_close(fex); return false; } - - if(!fileChooser) fileChooser = new FileChooser; - fileChooser->list.reset(); - - while(fex_done(fex) == false) { - fex_stat(fex); - const char *name = fex_name(fex); - //only add valid ROM extensions to list (ignore text files, save RAM files, etc) - if(striend(name, ".sfc") || striend(name, ".smc") - || striend(name, ".swc") || striend(name, ".fig") - || striend(name, ".bs") || striend(name, ".st") - || striend(name, ".gb") || striend(name, ".sgb") || striend(name, ".gbc") - || striend(filename, ".gz") //GZip files only contain a single file - ) { - fileChooser->list[fileChooser->list.size()] = name; - } - fex_next(fex); - } - - string name = fileChooser->exec(); - if(name == "") { fex_close(fex); return false; } - - fex_rewind(fex); - while(fex_done(fex) == false) { - fex_stat(fex); - if(name == fex_name(fex)) { - size = fex_size(fex); - data = new uint8_t[size]; - fex_read(fex, data, size); - fex_close(fex); - - if(fileChooser->list.size() > 1) { - strtr(name, "\\", "/"); - strtr(filename, "\\", "/"); - - //retain only path from filename, "/foo/bar.7z" -> "/foo/" - for(signed i = filename.length() - 1; i >= 0; i--) { - if(filename[i] == '/') { - filename[i + 1] = 0; - break; - } - } - - //append only filename from archive, "foo/bar.sfc" -> "bar.sfc" - lstring part; - part.split("/", name); - filename = string() << filename << part[part.size() - 1]; - } - - return true; - } - fex_next(fex); - } - - fex_close(fex); - return false; -} - -bool snesreader_load_bz2(const char *filename, uint8_t *&data, unsigned &size) { - //TODO: need a way to get the size of a bzip2 file, so we can pre-allocate - //a buffer to decompress into memory. for now, use a temporary file. - - string name = "/tmp/.bz2_temporary_decompression_object"; - FILE *wr; - wr = fopen_utf8(name, "wb"); - if(!wr) { - //try the local directory - name = ".bz2_temporary_decompression_object"; - wr = fopen_utf8(name, "wb"); - //can't get write access, so give up - if(!wr) return false; - } - - FILE *fp = fopen_utf8(filename, "rb"); - uncompressStream(fileno(fp), fileno(wr)); - fclose(fp); - fclose(wr); - - bool success = snesreader_load_normal(name, data, size); - unlink(name); - return success; -} - -bool snesreader_load_jma(const char *filename, uint8_t *&data, unsigned &size) { - try { - JMA::jma_open JMAFile(filename); - std::string name; - - std::vector file_info = JMAFile.get_files_info(); - for(std::vector::iterator i = file_info.begin(); i != file_info.end(); i++) { - name = i->name; - size = i->size; - break; - } - - data = new uint8_t[size]; - JMAFile.extract_file(name, data); - return true; - } catch(JMA::jma_errors) { - return false; - } -} - -dllexport bool snesreader_load(string &filename, uint8_t *&data, unsigned &size) { - if(file::exists(filename) == false) return false; - - bool success = false; - if(striend(filename, ".zip") - || striend(filename, ".z") - || striend(filename, ".7z") - || striend(filename, ".rar") - || striend(filename, ".gz")) { - success = snesreader_load_fex(filename, data, size); - } else if(striend(filename, ".bz2")) { - success = snesreader_load_bz2(filename, data, size); - } else if(striend(filename, ".jma")) { - success = snesreader_load_jma(filename, data, size); - } else { - success = snesreader_load_normal(filename, data, size); - } - - if(success == false) return false; - - //apply IPS patch, if it exists - string patchname = filename; - for(int i = patchname.length() - 1; i >= 0; i--) { - if(patchname[i] == '.') { patchname[i] = 0; break; } - } - patchname << ".ips"; - if(file::exists(patchname)) snesreader_apply_ips(patchname, data, size); - - //remove copier header, if it exists - if((size & 0x7fff) == 512) memmove(data, data + 512, size -= 512); - - return true; -} - -dllexport bool snesreader_map(string &xmldata, const uint8_t *data, unsigned size) { - xmldata = ""; - xml.generate(xmldata, data, size); - return true; -} diff --git a/snesreader/snesreader.hpp b/snesreader/snesreader.hpp deleted file mode 100644 index ad5d63ce..00000000 --- a/snesreader/snesreader.hpp +++ /dev/null @@ -1,8 +0,0 @@ -#include -namespace nall { class string; } - -extern "C" { - const char* snesreader_supported(); - bool snesreader_load(nall::string &filename, uint8_t *&data, unsigned &size); - bool snesreader_map(nall::string &xml, const uint8_t *data, unsigned size); -} diff --git a/snesreader/sync.sh b/snesreader/sync.sh deleted file mode 100644 index 4bbaf34f..00000000 --- a/snesreader/sync.sh +++ /dev/null @@ -1,2 +0,0 @@ -rm -r nall -cp -r ../nall ./nall diff --git a/snesreader/unrar/archive.cpp b/snesreader/unrar/archive.cpp deleted file mode 100644 index 338a0eb7..00000000 --- a/snesreader/unrar/archive.cpp +++ /dev/null @@ -1,97 +0,0 @@ -#include -#include "rar.hpp" - -#include "unrar.h" - -Archive::Archive() : Raw( this ) -{ - OldFormat=false; - Solid=false; - - CurBlockPos=0; - NextBlockPos=0; - - memset(&NewMhd,0,sizeof(NewMhd)); - NewMhd.HeadType=MAIN_HEAD; - NewMhd.HeadSize=SIZEOF_NEWMHD; - HeaderCRC=0; -} - -bool Archive::IsSignature(byte *D) -{ - bool Valid=false; - if (D[0]==0x52) -#ifndef SFX_MODULE - if (D[1]==0x45 && D[2]==0x7e && D[3]==0x5e) - { - OldFormat=true; - Valid=true; - } - else -#endif - if (D[1]==0x61 && D[2]==0x72 && D[3]==0x21 && D[4]==0x1a && D[5]==0x07 && D[6]==0x00) - { - OldFormat=false; - Valid=true; - } - return(Valid); -} - - -unrar_err_t Archive::IsArchive() -{ - if (Read(MarkHead.Mark,SIZEOF_MARKHEAD)!=SIZEOF_MARKHEAD) - return unrar_err_not_arc; - - if (IsSignature(MarkHead.Mark)) - { - if (OldFormat) - Seek(0,SEEK_SET); - } - else - { - if (SFXSize==0) - return unrar_err_not_arc; - } - - unrar_err_t error = - ReadHeader(); - // (no need to seek to next) - if ( error != unrar_ok ) - return error; - -#ifndef SFX_MODULE - if (OldFormat) - { - NewMhd.Flags=OldMhd.Flags & 0x3f; - NewMhd.HeadSize=OldMhd.HeadSize; - } - else -#endif - { - if (HeaderCRC!=NewMhd.HeadCRC) - { - return unrar_err_corrupt; - } - } - bool - Volume=(NewMhd.Flags & MHD_VOLUME); - Solid=(NewMhd.Flags & MHD_SOLID)!=0; - bool - Encrypted=(NewMhd.Flags & MHD_PASSWORD)!=0; - - // (removed decryption and volume handling) - - if ( Encrypted ) - return unrar_err_encrypted; - - if ( Volume ) - return unrar_err_segmented; - - return unrar_ok; -} - -void Archive::SeekToNext() -{ - Seek(NextBlockPos,SEEK_SET); -} diff --git a/snesreader/unrar/archive.hpp b/snesreader/unrar/archive.hpp deleted file mode 100644 index 0106e6fd..00000000 --- a/snesreader/unrar/archive.hpp +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef _RAR_ARCHIVE_ -#define _RAR_ARCHIVE_ - -typedef ComprDataIO File; -#include "rawread.hpp" - -class Archive:public File -{ -private: - bool IsSignature(byte *D); - void ConvertUnknownHeader(); - int ReadOldHeader(); - - RawRead Raw; - - MarkHeader MarkHead; - OldMainHeader OldMhd; - - int CurHeaderType; - -public: - Archive(); - unrar_err_t IsArchive(); - unrar_err_t ReadHeader(); - void SeekToNext(); - bool IsArcDir(); - bool IsArcLabel(); - int GetHeaderType() {return(CurHeaderType);}; - - BaseBlock ShortBlock; - MainHeader NewMhd; - FileHeader NewLhd; - SubBlockHeader SubBlockHead; - FileHeader SubHead; - ProtectHeader ProtectHead; - - Int64 CurBlockPos; - Int64 NextBlockPos; - - bool Solid; - enum { SFXSize = 0 }; // self-extracting not supported - ushort HeaderCRC; -}; - -#endif diff --git a/snesreader/unrar/arcread.cpp b/snesreader/unrar/arcread.cpp deleted file mode 100644 index 3a9f711c..00000000 --- a/snesreader/unrar/arcread.cpp +++ /dev/null @@ -1,314 +0,0 @@ -#include "rar.hpp" - -#include "unrar.h" -#include "unicode.hpp" -#include "encname.hpp" - -// arcread.cpp -unrar_err_t Archive::ReadHeader() -{ - CurBlockPos=Tell(); - -#ifndef SFX_MODULE - if (OldFormat) - { - ReadOldHeader(); - - if ( Raw.Size() == 0 ) - return unrar_err_arc_eof; // right at end of file - - if ( Raw.PaddedSize() > 0 ) // added check - return unrar_err_corrupt; // missing data - - return unrar_ok; - } -#endif - - Raw.Reset(); - - // (removed decryption) - - Raw.Read(SIZEOF_SHORTBLOCKHEAD); - if (Raw.Size()==0) - { - return unrar_err_arc_eof; // right at end of file - } - - Raw.Get(ShortBlock.HeadCRC); - byte HeadType; - Raw.Get(HeadType); - ShortBlock.HeadType=(HEADER_TYPE)HeadType; - Raw.Get(ShortBlock.Flags); - Raw.Get(ShortBlock.HeadSize); - if (ShortBlock.HeadSize 0 ) // fewer than requested bytes read above? - return unrar_err_corrupt; // missing data - - NextBlockPos=CurBlockPos+ShortBlock.HeadSize; - - switch(ShortBlock.HeadType) - { - case MAIN_HEAD: - *(BaseBlock *)&NewMhd=ShortBlock; - Raw.Get(NewMhd.HighPosAV); - Raw.Get(NewMhd.PosAV); - check( Raw.ReadPos == Raw.DataSize ); // we should have read all fields - break; - case FILE_HEAD: - case NEWSUB_HEAD: - { - FileHeader *hd=ShortBlock.HeadType==FILE_HEAD ? &NewLhd:&SubHead; - *(BaseBlock *)hd=ShortBlock; - Raw.Get(hd->PackSize); - Raw.Get(hd->UnpSize); - Raw.Get(hd->HostOS); - Raw.Get(hd->FileCRC); - Raw.Get(hd->FileTime); - Raw.Get(hd->UnpVer); - Raw.Get(hd->Method); - Raw.Get(hd->NameSize); - Raw.Get(hd->FileAttr); - if (hd->Flags & LHD_LARGE) - { - Raw.Get(hd->HighPackSize); - Raw.Get(hd->HighUnpSize); - } - else - { - hd->HighPackSize=hd->HighUnpSize=0; - if (hd->UnpSize==0xffffffff) - { - // TODO: what the heck is this for anyway? - hd->UnpSize=0; - hd->HighUnpSize=0x7fffffff; - } - } - hd->FullPackSize=int32to64(hd->HighPackSize,hd->PackSize); - hd->FullUnpSize=int32to64(hd->HighUnpSize,hd->UnpSize); - - if ( int32to64( 1, 0 ) == 0 && (hd->HighPackSize || hd->HighUnpSize) ) - return unrar_err_huge; - - char (&FileName) [sizeof hd->FileName] = hd->FileName; // eliminated local buffer - int NameSize=Min(hd->NameSize,sizeof(FileName)-1); - Raw.Get((byte *)FileName,NameSize); - FileName[NameSize]=0; - - if (hd->HeadType==NEWSUB_HEAD) - { - // have to adjust this, even through we're ignoring this block - NextBlockPos+=hd->FullPackSize; - break; - } - else - if (hd->HeadType==FILE_HEAD) - { - if (hd->Flags & LHD_UNICODE) - { - EncodeFileName NameCoder; - int Length=strlen(FileName); - if (Length==hd->NameSize) - { - UtfToWide(FileName,hd->FileNameW,sizeof(hd->FileNameW)/sizeof(hd->FileNameW[0])-1); - WideToChar(hd->FileNameW,hd->FileName,sizeof(hd->FileName)/sizeof(hd->FileName[0])-1); - ExtToInt(hd->FileName,hd->FileName); - } - else - { - Length++; - NameCoder.Decode(FileName,(byte *)FileName+Length, - hd->NameSize-Length,hd->FileNameW, - sizeof(hd->FileNameW)/sizeof(hd->FileNameW[0])); - } - if (*hd->FileNameW==0) - hd->Flags &= ~LHD_UNICODE; - } - else - *hd->FileNameW=0; - - ConvertUnknownHeader(); - } - if (hd->Flags & LHD_SALT) - Raw.Get(hd->Salt,SALT_SIZE); - hd->mtime.SetDos(hd->FileTime); - if (hd->Flags & LHD_EXTTIME) - { - ushort Flags; - Raw.Get(Flags); - // Ignore additional time information - for (int I=0;I<4;I++) - { - uint rmode=Flags>>(3-I)*4; - if ((rmode & 8)==0) - continue; - if (I!=0) - { - uint DosTime; - Raw.Get(DosTime); - } - - // skip time info - int count=rmode&3; - for (int J=0;JFullPackSize; - bool CRCProcessedOnly=(hd->Flags & LHD_COMMENT)!=0; - HeaderCRC=~Raw.GetCRC(CRCProcessedOnly)&0xffff; - if (hd->HeadCRC!=HeaderCRC) - return unrar_err_corrupt; - check( CRCProcessedOnly == false ); // I need to test on archives where this doesn't hold - check( Raw.ReadPos == Raw.DataSize ); // we should have read all fields - } - break; -#ifndef SFX_MODULE - // Handle these block types just so we can adjust NextBlockPos properly - case PROTECT_HEAD: - Raw.Get(ProtectHead.DataSize); - NextBlockPos+=ProtectHead.DataSize; - break; - case SUB_HEAD: - Raw.Get(SubBlockHead.DataSize); - NextBlockPos+=SubBlockHead.DataSize; - break; -#endif - default: - if (ShortBlock.Flags & LONG_BLOCK) - { - uint DataSize; - Raw.Get(DataSize); - NextBlockPos+=DataSize; - } - break; - } - HeaderCRC=~Raw.GetCRC(false)&0xffff; - CurHeaderType=ShortBlock.HeadType; - // (removed decryption) - - if (NextBlockPosCurBlockPos ? Raw.Size():0); -} -#endif - -// (removed name case and attribute conversion) - -bool Archive::IsArcDir() -{ - return((NewLhd.Flags & LHD_WINDOWMASK)==LHD_DIRECTORY); -} - - -bool Archive::IsArcLabel() -{ - return(NewLhd.HostOS<=HOST_WIN32 && (NewLhd.FileAttr & 8)); -} - -// TODO: use '\\' on Windows? -char const CPATHDIVIDER = '/'; -#define charnext(s) ((s)+1) - -void Archive::ConvertUnknownHeader() -{ - if (NewLhd.UnpVer<20 && (NewLhd.FileAttr & 0x10)) - NewLhd.Flags|=LHD_DIRECTORY; - if (NewLhd.HostOS>=HOST_MAX) - { - if ((NewLhd.Flags & LHD_WINDOWMASK)==LHD_DIRECTORY) - NewLhd.FileAttr=0x10; - else - NewLhd.FileAttr=0x20; - } - { - for (char *s=NewLhd.FileName;*s!=0;s=charnext(s)) - { - if (*s=='/' || *s=='\\') - *s=CPATHDIVIDER; - } - } - // (removed Apple Unicode handling) - for (wchar *s=NewLhd.FileNameW;*s!=0;s++) - { - if (*s=='/' || *s=='\\') - *s=CPATHDIVIDER; - } -} diff --git a/snesreader/unrar/array.hpp b/snesreader/unrar/array.hpp deleted file mode 100644 index 1f2d4e8c..00000000 --- a/snesreader/unrar/array.hpp +++ /dev/null @@ -1,135 +0,0 @@ -#ifndef _RAR_ARRAY_ -#define _RAR_ARRAY_ - -template class Array -{ -private: - T *Buffer; - int BufSize; - int AllocSize; -public: - Rar_Error_Handler& ErrHandler; - Array(Rar_Error_Handler*); - Array(int Size,Rar_Error_Handler*); - ~Array(); - inline void CleanData(); - inline T& operator [](int Item); - inline int Size(); - void Add(int Items); - void Alloc(int Items); - void Reset(); - void operator = (Array &Src); - void Push(T Item); - T* Addr() {return(Buffer);} -}; - -template void Array::CleanData() -{ - Buffer=NULL; - BufSize=0; - AllocSize=0; -} - - -template Array::Array(Rar_Error_Handler* eh) : ErrHandler( *eh ) -{ - CleanData(); -} - - -template Array::Array(int Size, Rar_Error_Handler* eh) : ErrHandler( *eh ) -{ - Buffer=(T *)rarmalloc(sizeof(T)*Size); - if (Buffer==NULL && Size!=0) - ErrHandler.MemoryError(); - - AllocSize=BufSize=Size; -} - - -template Array::~Array() -{ - if (Buffer!=NULL) - rarfree(Buffer); -} - - -template inline T& Array::operator [](int Item) -{ - return(Buffer[Item]); -} - - -template inline int Array::Size() -{ - return(BufSize); -} - - -template void Array::Add(int Items) -{ - int BufSize = this->BufSize; // don't change actual vars until alloc succeeds - T* Buffer = this->Buffer; - - BufSize+=Items; - if (BufSize>AllocSize) - { - int Suggested=AllocSize+AllocSize/4+32; - int NewSize=Max(BufSize,Suggested); - - Buffer=(T *)rarrealloc(Buffer,NewSize*sizeof(T)); - if (Buffer==NULL) - ErrHandler.MemoryError(); - AllocSize=NewSize; - } - - this->Buffer = Buffer; - this->BufSize = BufSize; -} - - -template void Array::Alloc(int Items) -{ - if (Items>AllocSize) - Add(Items-BufSize); - else - BufSize=Items; -} - - -template void Array::Reset() -{ - // Keep memory allocated if it's small - // Eliminates constant reallocation when scanning archive - if ( AllocSize < 1024/sizeof(T) ) - { - BufSize = 0; - return; - } - - if (Buffer!=NULL) - { - rarfree(Buffer); - Buffer=NULL; - } - BufSize=0; - AllocSize=0; -} - - -template void Array::operator =(Array &Src) -{ - Reset(); - Alloc(Src.BufSize); - if (Src.BufSize!=0) - memcpy((void *)Buffer,(void *)Src.Buffer,Src.BufSize*sizeof(T)); -} - - -template void Array::Push(T Item) -{ - Add(1); - (*this)[Size()-1]=Item; -} - -#endif diff --git a/snesreader/unrar/changes.txt b/snesreader/unrar/changes.txt deleted file mode 100644 index 35345fd5..00000000 --- a/snesreader/unrar/changes.txt +++ /dev/null @@ -1,141 +0,0 @@ -unrar_core source code changes ------------------------------- -Unrar_core is based on UnRAR (unrarsrc-3.8.5.tar.gz) by Alexander L. -Roshal. The original sources have been HEAVILY modified, trimmed down, -and purged of all OS-specific calls for file access and other -unnecessary operations. Support for encryption, recovery records, and -segmentation has been REMOVED. See license.txt for licensing. In -particular, this code cannot be used to re-create the RAR compression -algorithm, which is proprietary. - -If you obtained this code as a part of my File_Extractor library and -want to use it on its own, get my unrar_core library, which includes -examples and documentation. - -The source is as close as possible to the original, to make it simple to -update when a new version of UnRAR comes out. In many places the -original names and object nesting are kept, even though it's a bit -harder to follow. See rar.hpp for the main "glue". - -Website: http://www.slack.net/~ant/ -E-mail : Shay Green - - -Contents --------- -* Diff-friendly changes -* Removal of features -* Error reporting changes -* Minor tweaks -* Unrar findings - - -Diff-friendly changes ---------------------- -To make my source code changes more easily visible with a line-based -file diff, I've tried to make changes by inserting or deleting lines, -rather than modifying them. So if the original declared a static array - - static int array [4] = { 1, 2, 3, 4 }; - -and I want to make it const, I add the const on a line before - - const // added - static int array [4] = { 1, 2, 3, 4 }; - -rather than on the same line - - static const int array [4] = { 1, 2, 3, 4 }; - -This way a diff will simply show an added line, making it clear what was -added. If I simply inserted const on the same line, it wouldn't be as -clear what all I had changed. - -I've also made use of several macros rather than changing the source -text. For example, since a class name like Unpack might easily conflict, -I've renamed it to Rar_Unpack by using #define Unpack Rar_Unpack rather -than changing the source text. These macros are only defined when -compiling the library sources; the user-visible unrar.h is very clean. - - -Removal of features -------------------- -This library is meant for simple access to common archives without -having to extract them first. Encryption, segmentation, huge files, and -self-extracting archives aren't common for things that need to be -accessed in this manner, so I've removed support for them. Also, -encryption adds complexity to the code that must be maintained. -Segmentation would require a way to specify the other segments. - - -Error reporting changes ------------------------ -The original used C++ exceptions to report errors. I've eliminated use -of these through a combination of error codes and longjmp. This allows -use of the library from C or some other language which doesn't easily -support exceptions. - -I tried to make as few changes as possible in the conversion. Due to the -number of places file reads occur, propagating an error code via return -statements would have required too many code changes. Instead, I perform -the read, save the error code, and return 0 bytes read in case of an -error. I also ensure that the calling code interprets this zero in an -acceptable way. I then check this saved error code after the operation -completes, and have it take priority over the error the RAR code -returned. I do a similar thing for write errors. - - -Minor tweaks ------------- -- Eliminated as many GCC warnings as reasonably possible. - -- Non-class array allocations now use malloc(), allowing the code to be -linked without the standard C++ library (particularly, operator new). -Class object allocations use a class-specific allocator that just calls -malloc(), also avoiding calls to operator new. - -- Made all unchanging static data const. Several pieces of static data -in the original code weren't marked const where they could be. - -- Initialization of some static tables was done on an as-needed basis, -creating a problem when extracting from archives in multiple threads. -This initialization can now be done by the user before any archives are -opened. - -- Tweaked CopyString, the major bottleneck during compression. I inlined -it, cached some variables in locals in case the compiler couldn't easily -see that the memory accesses don't modify them, and made them use -memcpy() where possible. This improved performance by at least 20% on -x86. Perhaps it won't work as well on files with lots of smaller string -matches. - -- Some .cpp files are #included by others. I've added guards to these so -that you can simply compile all .cpp files and not get any redefinition -errors. - -- The current solid extraction position is kept track of, allowing the -user to randomly extract files without regard to proper extraction -order. The library optimizes solid extraction and only restarts it if -the user is extracting a file earlier in the archive than the last -solid-extracted one. - -- Most of the time a solid file's data is already contiguously in the -internal Unpack::Window, which unrar_extract_mem() takes advantage of. -This avoids extra allocation in many cases. - -- Allocation of Unpack is delayed until the first extraction, rather -than being allocated immediately on opening the archive. This allows -scanning with minimal memory usage. - - -Unrar findings --------------- -- Apparently the LHD_SOLID flag indicates that file depends on previous -files, rather than that later files depend on the current file's -contents. Thus this flag can't be used to intelligently decide which -files need to be internally extracted when skipping them, making it -necessary to internally extract every file before the one to be -extracted, if the archive is solid. - --- -Shay Green diff --git a/snesreader/unrar/coder.cpp b/snesreader/unrar/coder.cpp deleted file mode 100644 index c3f3aac6..00000000 --- a/snesreader/unrar/coder.cpp +++ /dev/null @@ -1,49 +0,0 @@ -// #included by unpack.cpp -#ifdef RAR_COMMON_HPP - -inline unsigned int RangeCoder::GetChar() -{ - return(UnpackRead->GetChar()); -} - - -void RangeCoder::InitDecoder(Unpack *UnpackRead) -{ - RangeCoder::UnpackRead=UnpackRead; - - low=code=0; - range=uint(-1); - for (int i=0;i < 4;i++) - code=(code << 8) | GetChar(); -} - - -#define ARI_DEC_NORMALIZE(code,low,range,read) \ -{ \ - while ((low^(low+range))GetChar(); \ - range <<= 8; \ - low <<= 8; \ - } \ -} - - -inline int RangeCoder::GetCurrentCount() -{ - return (code-low)/(range /= SubRange.scale); -} - - -inline uint RangeCoder::GetCurrentShiftCount(uint SHIFT) -{ - return (code-low)/(range >>= SHIFT); -} - - -inline void RangeCoder::Decode() -{ - low += range*SubRange.LowCount; - range *= SubRange.HighCount-SubRange.LowCount; -} -#endif diff --git a/snesreader/unrar/coder.hpp b/snesreader/unrar/coder.hpp deleted file mode 100644 index 8384cdc6..00000000 --- a/snesreader/unrar/coder.hpp +++ /dev/null @@ -1,24 +0,0 @@ -/**************************************************************************** - * Contents: 'Carryless rangecoder' by Dmitry Subbotin * - ****************************************************************************/ - -const uint TOP=1 << 24, BOT=1 << 15; - -class RangeCoder -{ -public: - void InitDecoder(Unpack *UnpackRead); - inline int GetCurrentCount(); - inline uint GetCurrentShiftCount(uint SHIFT); - inline void Decode(); - inline void PutChar(unsigned int c); - inline unsigned int GetChar(); - - uint low, code, range; - struct SUBRANGE - { - uint LowCount, HighCount, scale; - } SubRange; - - Unpack *UnpackRead; -}; diff --git a/snesreader/unrar/compress.hpp b/snesreader/unrar/compress.hpp deleted file mode 100644 index 3181e45d..00000000 --- a/snesreader/unrar/compress.hpp +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef _RAR_COMPRESS_ -#define _RAR_COMPRESS_ - -class ComprDataIO; -class PackingFileTable; - -#define CODEBUFSIZE 0x4000 -#define MAXWINSIZE 0x400000 -#define MAXWINMASK (MAXWINSIZE-1) - -#define LOW_DIST_REP_COUNT 16 - -#define NC 299 /* alphabet = {0, 1, 2, ..., NC - 1} */ -#define DC 60 -#define LDC 17 -#define RC 28 -#define HUFF_TABLE_SIZE (NC+DC+RC+LDC) -#define BC 20 - -#define NC20 298 /* alphabet = {0, 1, 2, ..., NC - 1} */ -#define DC20 48 -#define RC20 28 -#define BC20 19 -#define MC20 257 - -enum {CODE_HUFFMAN,CODE_LZ,CODE_LZ2,CODE_REPEATLZ,CODE_CACHELZ, - CODE_STARTFILE,CODE_ENDFILE,CODE_VM,CODE_VMDATA}; - - -enum FilterType { - FILTER_NONE, FILTER_PPM /*dummy*/, FILTER_E8, FILTER_E8E9, - FILTER_UPCASETOLOW, FILTER_AUDIO, FILTER_RGB, FILTER_DELTA, - FILTER_ITANIUM, FILTER_E8E9V2 -}; - -#endif diff --git a/snesreader/unrar/crc.cpp b/snesreader/unrar/crc.cpp deleted file mode 100644 index bc23b5a9..00000000 --- a/snesreader/unrar/crc.cpp +++ /dev/null @@ -1,69 +0,0 @@ -#include "rar.hpp" - -uint CRCTab[256]; - -void InitCRC() -{ - for (int I=0;I<256;I++) - { - uint C=I; - for (int J=0;J<8;J++) - C=(C & 1) ? (C>>1)^0xEDB88320L : (C>>1); - CRCTab[I]=C; - } -} - - -uint CRC(uint StartCRC,const void *Addr,size_t Size) -{ - // Always initialized ahead of time, and this func call makes it a non-leaf func. - if (false) - if (CRCTab[1]==0) - InitCRC(); - byte *Data=(byte *)Addr; -#if defined(LITTLE_ENDIAN) && defined(PRESENT_INT32) && defined(ALLOW_NOT_ALIGNED_INT) - -#ifdef _MSC_VER - // avoid a warning about 'Data' pointer truncation in 64 bit mode - #pragma warning( disable : 4311 ) -#endif - - while (Size>0 && ((long)Data & 7)) - { - StartCRC=CRCTab[(byte)(StartCRC^Data[0])]^(StartCRC>>8); - Size--; - Data++; - } - while (Size>=8) - { - StartCRC^=*(uint32 *)Data; - StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8); - StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8); - StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8); - StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8); - StartCRC^=*(uint32 *)(Data+4); - StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8); - StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8); - StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8); - StartCRC=CRCTab[(byte)StartCRC]^(StartCRC>>8); - Data+=8; - Size-=8; - } -#endif - for (size_t I=0;I>8); - return(StartCRC); -} - -#ifndef SFX_MODULE -ushort OldCRC(ushort StartCRC,const void *Addr,size_t Size) -{ - byte *Data=(byte *)Addr; - for (size_t I=0;I>15))&0xffff; - } - return(StartCRC); -} -#endif diff --git a/snesreader/unrar/encname.cpp b/snesreader/unrar/encname.cpp deleted file mode 100644 index 6f57cd91..00000000 --- a/snesreader/unrar/encname.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include "rar.hpp" - -EncodeFileName::EncodeFileName() -{ - Flags=0; - FlagBits=0; - FlagsPos=0; - DestSize=0; -} - - - - -void EncodeFileName::Decode(char *Name,byte *EncName,int EncSize,wchar *NameW, - int MaxDecSize) -{ - int EncPos=0,DecPos=0; - byte HighByte=EncName[EncPos++]; - while (EncPos>6) - { - case 0: - NameW[DecPos++]=EncName[EncPos++]; - break; - case 1: - NameW[DecPos++]=EncName[EncPos++]+(HighByte<<8); - break; - case 2: - NameW[DecPos++]=EncName[EncPos]+(EncName[EncPos+1]<<8); - EncPos+=2; - break; - case 3: - { - int Length=EncName[EncPos++]; - if (Length & 0x80) - { - byte Correction=EncName[EncPos++]; - for (Length=(Length&0x7f)+2;Length>0 && DecPos0 && DecPos -#include "rar.hpp" - -#include "unrar.h" - -#define DataIO Arc - -unrar_err_t CmdExtract::ExtractCurrentFile( bool SkipSolid, bool check_compatibility_only ) -{ - check( Arc.GetHeaderType() == FILE_HEAD ); - - if ( Arc.NewLhd.Flags & (LHD_SPLIT_AFTER | LHD_SPLIT_BEFORE) ) - return unrar_err_segmented; - - if ( Arc.NewLhd.Flags & LHD_PASSWORD ) - return unrar_err_encrypted; - - if ( !check_compatibility_only ) - { - check( Arc.NextBlockPos-Arc.NewLhd.FullPackSize == Arc.Tell() ); - Arc.Seek(Arc.NextBlockPos-Arc.NewLhd.FullPackSize,SEEK_SET); - } - - // (removed lots of command-line handling) - -#ifdef SFX_MODULE - if ((Arc.NewLhd.UnpVer!=UNP_VER && Arc.NewLhd.UnpVer!=29) && - Arc.NewLhd.Method!=0x30) -#else - if (Arc.NewLhd.UnpVer<13 || Arc.NewLhd.UnpVer>UNP_VER) -#endif - { - if (Arc.NewLhd.UnpVer>UNP_VER) - return unrar_err_new_algo; - return unrar_err_old_algo; - } - - if ( check_compatibility_only ) - return unrar_ok; - - // (removed lots of command-line/encryption/volume handling) - - update_first_file_pos(); - FileCount++; - DataIO.UnpFileCRC=Arc.OldFormat ? 0 : 0xffffffff; - // (removed decryption) - DataIO.SetPackedSizeToRead(Arc.NewLhd.FullPackSize); - // (removed command-line handling) - DataIO.SetSkipUnpCRC(SkipSolid); - - if (Arc.NewLhd.Method==0x30) - UnstoreFile(Arc.NewLhd.FullUnpSize); - else - { - // Defer creation of Unpack until first extraction - if ( !Unp ) - { - Unp = new Unpack( &Arc ); - if ( !Unp ) - return unrar_err_memory; - - Unp->Init( NULL ); - } - - Unp->SetDestSize(Arc.NewLhd.FullUnpSize); -#ifndef SFX_MODULE - if (Arc.NewLhd.UnpVer<=15) - Unp->DoUnpack(15,FileCount>1 && Arc.Solid); - else -#endif - Unp->DoUnpack(Arc.NewLhd.UnpVer,Arc.NewLhd.Flags & LHD_SOLID); - } - - // (no need to seek to next file) - - if (!SkipSolid) - { - if (Arc.OldFormat && UINT32(DataIO.UnpFileCRC)==UINT32(Arc.NewLhd.FileCRC) || - !Arc.OldFormat && UINT32(DataIO.UnpFileCRC)==UINT32(Arc.NewLhd.FileCRC^0xffffffff)) - { - // CRC is correct - } - else - { - return unrar_err_corrupt; - } - } - - // (removed broken file handling) - // (removed command-line handling) - - return unrar_ok; -} - - -void CmdExtract::UnstoreFile(Int64 DestUnpSize) -{ - Buffer.Alloc(Min(DestUnpSize,0x10000)); - while (1) - { - unsigned int Code=DataIO.UnpRead(&Buffer[0],Buffer.Size()); - if (Code==0 || (int)Code==-1) - break; - Code=Code=0) - DestUnpSize-=Code; - } - Buffer.Reset(); -} diff --git a/snesreader/unrar/getbits.cpp b/snesreader/unrar/getbits.cpp deleted file mode 100644 index 559bdd03..00000000 --- a/snesreader/unrar/getbits.cpp +++ /dev/null @@ -1,34 +0,0 @@ -#include "rar.hpp" - -BitInput::BitInput() -{ - InBuf = (byte*) rarmalloc( MAX_SIZE ); - - // Otherwise getbits() reads uninitialized memory - // TODO: instead of clearing entire block, just clear last two - // bytes after reading from file - if ( InBuf ) - memset( InBuf, 0, MAX_SIZE ); -} - -BitInput::~BitInput() -{ - rarfree( InBuf ); -} - -void BitInput::handle_mem_error( Rar_Error_Handler& ErrHandler ) -{ - if ( !InBuf ) - ErrHandler.MemoryError(); -} - -void BitInput::faddbits(int Bits) -{ - addbits(Bits); -} - - -unsigned int BitInput::fgetbits() -{ - return(getbits()); -} diff --git a/snesreader/unrar/getbits.hpp b/snesreader/unrar/getbits.hpp deleted file mode 100644 index 5a4cb4a3..00000000 --- a/snesreader/unrar/getbits.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef _RAR_GETBITS_ -#define _RAR_GETBITS_ - -class BitInput - : public Rar_Allocator -{ -public: - enum BufferSize {MAX_SIZE=0x8000}; -protected: - int InAddr,InBit; -public: - BitInput(); - ~BitInput(); - void handle_mem_error( Rar_Error_Handler& ); - - byte *InBuf; - - void InitBitInput() - { - InAddr=InBit=0; - } - void addbits(int Bits) - { - Bits+=InBit; - InAddr+=Bits>>3; - InBit=Bits&7; - } - unsigned int getbits() - { - unsigned int BitField=(uint)InBuf[InAddr] << 16; - BitField|=(uint)InBuf[InAddr+1] << 8; - BitField|=(uint)InBuf[InAddr+2]; - BitField >>= (8-InBit); - return(BitField & 0xffff); - } - void faddbits(int Bits); - unsigned int fgetbits(); - bool Overflow(int IncPtr) {return(InAddr+IncPtr>=MAX_SIZE);} -}; -#endif diff --git a/snesreader/unrar/headers.hpp b/snesreader/unrar/headers.hpp deleted file mode 100644 index abe1c66a..00000000 --- a/snesreader/unrar/headers.hpp +++ /dev/null @@ -1,145 +0,0 @@ -#ifndef _RAR_HEADERS_ -#define _RAR_HEADERS_ - -#define SIZEOF_MARKHEAD 7 -#define SIZEOF_OLDMHD 7 -#define SIZEOF_NEWMHD 13 -#define SIZEOF_OLDLHD 21 -#define SIZEOF_NEWLHD 32 -#define SIZEOF_SHORTBLOCKHEAD 7 -#define SIZEOF_SUBBLOCKHEAD 14 -#define SIZEOF_COMMHEAD 13 - -#define UNP_VER 36 - -#define MHD_VOLUME 0x0001 -#define MHD_COMMENT 0x0002 -#define MHD_SOLID 0x0008 -#define MHD_PASSWORD 0x0080 - -#define LHD_SPLIT_BEFORE 0x0001 -#define LHD_SPLIT_AFTER 0x0002 -#define LHD_PASSWORD 0x0004 -#define LHD_COMMENT 0x0008 -#define LHD_SOLID 0x0010 - -#define LHD_WINDOWMASK 0x00e0 -#define LHD_DIRECTORY 0x00e0 - -#define LHD_LARGE 0x0100 -#define LHD_UNICODE 0x0200 -#define LHD_SALT 0x0400 -#define LHD_EXTTIME 0x1000 - -#define LONG_BLOCK 0x8000 - -enum HEADER_TYPE { - MARK_HEAD=0x72,MAIN_HEAD=0x73,FILE_HEAD=0x74,COMM_HEAD=0x75,AV_HEAD=0x76, - SUB_HEAD=0x77,PROTECT_HEAD=0x78,SIGN_HEAD=0x79,NEWSUB_HEAD=0x7a, - ENDARC_HEAD=0x7b -}; - -enum HOST_SYSTEM { - HOST_MSDOS=0,HOST_OS2=1,HOST_WIN32=2,HOST_UNIX=3,HOST_MACOS=4, - HOST_BEOS=5,HOST_MAX -}; - -struct OldMainHeader -{ - byte Mark[4]; - ushort HeadSize; - byte Flags; -}; - - -struct OldFileHeader -{ - uint PackSize; - uint UnpSize; - ushort FileCRC; - ushort HeadSize; - uint FileTime; - byte FileAttr; - byte Flags; - byte UnpVer; - byte NameSize; - byte Method; -}; - - -struct MarkHeader -{ - byte Mark[7]; -}; - - -struct BaseBlock -{ - ushort HeadCRC; - HEADER_TYPE HeadType;//byte - ushort Flags; - ushort HeadSize; -}; - -struct BlockHeader:BaseBlock -{ - union { - uint DataSize; - uint PackSize; - }; -}; - - -struct MainHeader:BaseBlock -{ - ushort HighPosAV; - uint PosAV; -}; - -#define SALT_SIZE 8 - -struct FileHeader:BlockHeader -{ - uint UnpSize; - byte HostOS; - uint FileCRC; - uint FileTime; - byte UnpVer; - byte Method; - ushort NameSize; - union { - uint FileAttr; - uint SubFlags; - }; -/* optional */ - uint HighPackSize; - uint HighUnpSize; -/* names */ - char FileName[NM*4]; // *4 to avoid using lots of stack in arcread - wchar FileNameW[NM]; -/* optional */ - byte Salt[SALT_SIZE]; - - RarTime mtime; -/* dummy */ - Int64 FullPackSize; - Int64 FullUnpSize; -}; - -// SubBlockHeader and its successors were used in RAR 2.x format. -// RAR 3.x uses FileHeader with NEWSUB_HEAD HeadType for subblocks. -struct SubBlockHeader:BlockHeader -{ - ushort SubType; - byte Level; -}; - -struct ProtectHeader:BlockHeader -{ - byte Version; - ushort RecSectors; - uint TotalBlocks; - byte Mark[8]; -}; - -#endif diff --git a/snesreader/unrar/license.txt b/snesreader/unrar/license.txt deleted file mode 100644 index 2aa475c7..00000000 --- a/snesreader/unrar/license.txt +++ /dev/null @@ -1,40 +0,0 @@ - ****** ***** ****** UnRAR - free utility for RAR archives - ** ** ** ** ** ** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - ****** ******* ****** License for use and distribution of - ** ** ** ** ** ** ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - ** ** ** ** ** ** FREE portable version - ~~~~~~~~~~~~~~~~~~~~~ - - The source code of UnRAR utility is freeware. This means: - - 1. All copyrights to RAR and the utility UnRAR are exclusively - owned by the author - Alexander Roshal. - - 2. The UnRAR sources may be used in any software to handle RAR - archives without limitations free of charge, but cannot be used - to re-create the RAR compression algorithm, which is proprietary. - Distribution of modified UnRAR sources in separate form or as a - part of other software is permitted, provided that it is clearly - stated in the documentation and source comments that the code may - not be used to develop a RAR (WinRAR) compatible archiver. - - 3. The UnRAR utility may be freely distributed. It is allowed - to distribute UnRAR inside of other software packages. - - 4. THE RAR ARCHIVER AND THE UnRAR UTILITY ARE DISTRIBUTED "AS IS". - NO WARRANTY OF ANY KIND IS EXPRESSED OR IMPLIED. YOU USE AT - YOUR OWN RISK. THE AUTHOR WILL NOT BE LIABLE FOR DATA LOSS, - DAMAGES, LOSS OF PROFITS OR ANY OTHER KIND OF LOSS WHILE USING - OR MISUSING THIS SOFTWARE. - - 5. Installing and using the UnRAR utility signifies acceptance of - these terms and conditions of the license. - - 6. If you don't agree with terms of the license you must remove - UnRAR files from your storage devices and cease to use the - utility. - - Thank you for your interest in RAR and UnRAR. - - - Alexander L. Roshal \ No newline at end of file diff --git a/snesreader/unrar/model.cpp b/snesreader/unrar/model.cpp deleted file mode 100644 index 68e1a4f1..00000000 --- a/snesreader/unrar/model.cpp +++ /dev/null @@ -1,612 +0,0 @@ -// #included by unpack.cpp -#ifdef RAR_COMMON_HPP -/**************************************************************************** - * This file is part of PPMd project * - * Written and distributed to public domain by Dmitry Shkarin 1997, * - * 1999-2000 * - * Contents: model description and encoding/decoding routines * - ****************************************************************************/ - -inline PPM_CONTEXT* PPM_CONTEXT::createChild(ModelPPM *Model,STATE* pStats, - STATE& FirstState) -{ - PPM_CONTEXT* pc = (PPM_CONTEXT*) Model->SubAlloc.AllocContext(); - if ( pc ) - { - pc->NumStats=1; - pc->OneState=FirstState; - pc->Suffix=this; - pStats->Successor=pc; - } - return pc; -} - - -ModelPPM::ModelPPM() -{ - MinContext=NULL; - MaxContext=NULL; - MedContext=NULL; -} - - -void ModelPPM::RestartModelRare() -{ - int i, k, m; - memset(CharMask,0,sizeof(CharMask)); - SubAlloc.InitSubAllocator(); - InitRL=-(MaxOrder < 12 ? MaxOrder:12)-1; - MinContext = MaxContext = (PPM_CONTEXT*) SubAlloc.AllocContext(); - MinContext->Suffix=NULL; - OrderFall=MaxOrder; - MinContext->U.SummFreq=(MinContext->NumStats=256)+1; - FoundState=MinContext->U.Stats=(STATE*)SubAlloc.AllocUnits(256/2); - for (RunLength=InitRL, PrevSuccess=i=0;i < 256;i++) - { - MinContext->U.Stats[i].Symbol=i; - MinContext->U.Stats[i].Freq=1; - MinContext->U.Stats[i].Successor=NULL; - } - - static const ushort InitBinEsc[]={ - 0x3CDD,0x1F3F,0x59BF,0x48F3,0x64A1,0x5ABC,0x6632,0x6051 - }; - - for (i=0;i < 128;i++) - for (k=0;k < 8;k++) - for (m=0;m < 64;m += 8) - BinSumm[i][k+m]=BIN_SCALE-InitBinEsc[k]/(i+2); - for (i=0;i < 25;i++) - for (k=0;k < 16;k++) - SEE2Cont[i][k].init(5*i+10); -} - - -void ModelPPM::StartModelRare(int MaxOrder) -{ - int i, k, m ,Step; - EscCount=1; -/* - if (MaxOrder < 2) - { - memset(CharMask,0,sizeof(CharMask)); - OrderFall=ModelPPM::MaxOrder; - MinContext=MaxContext; - while (MinContext->Suffix != NULL) - { - MinContext=MinContext->Suffix; - OrderFall--; - } - FoundState=MinContext->U.Stats; - MinContext=MaxContext; - } - else -*/ - { - ModelPPM::MaxOrder=MaxOrder; - RestartModelRare(); - NS2BSIndx[0]=2*0; - NS2BSIndx[1]=2*1; - memset(NS2BSIndx+2,2*2,9); - memset(NS2BSIndx+11,2*3,256-11); - for (i=0;i < 3;i++) - NS2Indx[i]=i; - for (m=i, k=Step=1;i < 256;i++) - { - NS2Indx[i]=m; - if ( !--k ) - { - k = ++Step; - m++; - } - } - memset(HB2Flag,0,0x40); - memset(HB2Flag+0x40,0x08,0x100-0x40); - DummySEE2Cont.Shift=PERIOD_BITS; - } -} - - -void PPM_CONTEXT::rescale(ModelPPM *Model) -{ - int OldNS=NumStats, i=NumStats-1, Adder, EscFreq; - STATE* p1, * p; - for (p=Model->FoundState;p != U.Stats;p--) - _PPMD_SWAP(p[0],p[-1]); - U.Stats->Freq += 4; - U.SummFreq += 4; - EscFreq=U.SummFreq-p->Freq; - Adder=(Model->OrderFall != 0); - U.SummFreq = (p->Freq=(p->Freq+Adder) >> 1); - do - { - EscFreq -= (++p)->Freq; - U.SummFreq += (p->Freq=(p->Freq+Adder) >> 1); - if (p[0].Freq > p[-1].Freq) - { - STATE tmp=*(p1=p); - do - { - p1[0]=p1[-1]; - } while (--p1 != U.Stats && tmp.Freq > p1[-1].Freq); - *p1=tmp; - } - } while ( --i ); - if (p->Freq == 0) - { - do - { - i++; - } while ((--p)->Freq == 0); - EscFreq += i; - if ((NumStats -= i) == 1) - { - STATE tmp=*U.Stats; - do - { - tmp.Freq-=(tmp.Freq >> 1); - EscFreq>>=1; - } while (EscFreq > 1); - Model->SubAlloc.FreeUnits(U.Stats,(OldNS+1) >> 1); - *(Model->FoundState=&OneState)=tmp; return; - } - } - U.SummFreq += (EscFreq -= (EscFreq >> 1)); - int n0=(OldNS+1) >> 1, n1=(NumStats+1) >> 1; - if (n0 != n1) - U.Stats = (STATE*) Model->SubAlloc.ShrinkUnits(U.Stats,n0,n1); - Model->FoundState=U.Stats; -} - - -inline PPM_CONTEXT* ModelPPM::CreateSuccessors(bool Skip,STATE* p1) -{ - // (removed conditional static) - STATE UpState; - PPM_CONTEXT* pc=MinContext, * UpBranch=FoundState->Successor; - STATE * p, * ps[MAX_O], ** pps=ps; - if ( !Skip ) - { - *pps++ = FoundState; - if ( !pc->Suffix ) - goto NO_LOOP; - } - if ( p1 ) - { - p=p1; - pc=pc->Suffix; - goto LOOP_ENTRY; - } - do - { - pc=pc->Suffix; - if (pc->NumStats != 1) - { - if ((p=pc->U.Stats)->Symbol != FoundState->Symbol) - do - { - p++; - } while (p->Symbol != FoundState->Symbol); - } - else - p=&(pc->OneState); -LOOP_ENTRY: - if (p->Successor != UpBranch) - { - pc=p->Successor; - break; - } - *pps++ = p; - } while ( pc->Suffix ); -NO_LOOP: - if (pps == ps) - return pc; - UpState.Symbol=*(byte*) UpBranch; - UpState.Successor=(PPM_CONTEXT*) (((byte*) UpBranch)+1); - if (pc->NumStats != 1) - { - if ((byte*) pc <= SubAlloc.pText) - return(NULL); - if ((p=pc->U.Stats)->Symbol != UpState.Symbol) - do - { - p++; - } while (p->Symbol != UpState.Symbol); - uint cf=p->Freq-1; - uint s0=pc->U.SummFreq-pc->NumStats-cf; - UpState.Freq=1+((2*cf <= s0)?(5*cf > s0):((2*cf+3*s0-1)/(2*s0))); - } - else - UpState.Freq=pc->OneState.Freq; - do - { - pc = pc->createChild(this,*--pps,UpState); - if ( !pc ) - return NULL; - } while (pps != ps); - return pc; -} - - -inline void ModelPPM::UpdateModel() -{ - STATE fs = *FoundState, *p = NULL; - PPM_CONTEXT *pc, *Successor; - uint ns1, ns, cf, sf, s0; - if (fs.Freq < MAX_FREQ/4 && (pc=MinContext->Suffix) != NULL) - { - if (pc->NumStats != 1) - { - if ((p=pc->U.Stats)->Symbol != fs.Symbol) - { - do - { - p++; - } while (p->Symbol != fs.Symbol); - if (p[0].Freq >= p[-1].Freq) - { - _PPMD_SWAP(p[0],p[-1]); - p--; - } - } - if (p->Freq < MAX_FREQ-9) - { - p->Freq += 2; - pc->U.SummFreq += 2; - } - } - else - { - p=&(pc->OneState); - p->Freq += (p->Freq < 32); - } - } - if ( !OrderFall ) - { - MinContext=MaxContext=FoundState->Successor=CreateSuccessors(true,p); - if ( !MinContext ) - goto RESTART_MODEL; - return; - } - *SubAlloc.pText++ = fs.Symbol; - Successor = (PPM_CONTEXT*) SubAlloc.pText; - if (SubAlloc.pText >= SubAlloc.FakeUnitsStart) - goto RESTART_MODEL; - if ( fs.Successor ) - { - if ((byte*) fs.Successor <= SubAlloc.pText && - (fs.Successor=CreateSuccessors(false,p)) == NULL) - goto RESTART_MODEL; - if ( !--OrderFall ) - { - Successor=fs.Successor; - SubAlloc.pText -= (MaxContext != MinContext); - } - } - else - { - FoundState->Successor=Successor; - fs.Successor=MinContext; - } - s0=MinContext->U.SummFreq-(ns=MinContext->NumStats)-(fs.Freq-1); - for (pc=MaxContext;pc != MinContext;pc=pc->Suffix) - { - if ((ns1=pc->NumStats) != 1) - { - if ((ns1 & 1) == 0) - { - pc->U.Stats=(STATE*) SubAlloc.ExpandUnits(pc->U.Stats,ns1 >> 1); - if ( !pc->U.Stats ) - goto RESTART_MODEL; - } - pc->U.SummFreq += (2*ns1 < ns)+2*((4*ns1 <= ns) & (pc->U.SummFreq <= 8*ns1)); - } - else - { - p=(STATE*) SubAlloc.AllocUnits(1); - if ( !p ) - goto RESTART_MODEL; - *p=pc->OneState; - pc->U.Stats=p; - if (p->Freq < MAX_FREQ/4-1) - p->Freq += p->Freq; - else - p->Freq = MAX_FREQ-4; - pc->U.SummFreq=p->Freq+InitEsc+(ns > 3); - } - cf=2*fs.Freq*(pc->U.SummFreq+6); - sf=s0+pc->U.SummFreq; - if (cf < 6*sf) - { - cf=1+(cf > sf)+(cf >= 4*sf); - pc->U.SummFreq += 3; - } - else - { - cf=4+(cf >= 9*sf)+(cf >= 12*sf)+(cf >= 15*sf); - pc->U.SummFreq += cf; - } - p=pc->U.Stats+ns1; - p->Successor=Successor; - p->Symbol = fs.Symbol; - p->Freq = cf; - pc->NumStats=++ns1; - } - MaxContext=MinContext=fs.Successor; - return; -RESTART_MODEL: - RestartModelRare(); - EscCount=0; -} - - -// Tabulated escapes for exponential symbol distribution -static const byte ExpEscape[16]={ 25,14, 9, 7, 5, 5, 4, 4, 4, 3, 3, 3, 2, 2, 2, 2 }; -#define GET_MEAN(SUMM,SHIFT,ROUND) ((SUMM+(1 << (SHIFT-ROUND))) >> (SHIFT)) - - - -inline void PPM_CONTEXT::decodeBinSymbol(ModelPPM *Model) -{ - STATE& rs=OneState; - Model->HiBitsFlag=Model->HB2Flag[Model->FoundState->Symbol]; - ushort& bs=Model->BinSumm[rs.Freq-1][Model->PrevSuccess+ - Model->NS2BSIndx[Suffix->NumStats-1]+ - Model->HiBitsFlag+2*Model->HB2Flag[rs.Symbol]+ - ((Model->RunLength >> 26) & 0x20)]; - if (Model->Coder.GetCurrentShiftCount(TOT_BITS) < bs) - { - Model->FoundState=&rs; - rs.Freq += (rs.Freq < 128); - Model->Coder.SubRange.LowCount=0; - Model->Coder.SubRange.HighCount=bs; - bs = SHORT16(bs+INTERVAL-GET_MEAN(bs,PERIOD_BITS,2)); - Model->PrevSuccess=1; - Model->RunLength++; - } - else - { - Model->Coder.SubRange.LowCount=bs; - bs = SHORT16(bs-GET_MEAN(bs,PERIOD_BITS,2)); - Model->Coder.SubRange.HighCount=BIN_SCALE; - Model->InitEsc=ExpEscape[bs >> 10]; - Model->NumMasked=1; - Model->CharMask[rs.Symbol]=Model->EscCount; - Model->PrevSuccess=0; - Model->FoundState=NULL; - } -} - - -inline void PPM_CONTEXT::update1(ModelPPM *Model,STATE* p) -{ - (Model->FoundState=p)->Freq += 4; - U.SummFreq += 4; - if (p[0].Freq > p[-1].Freq) - { - _PPMD_SWAP(p[0],p[-1]); - Model->FoundState=--p; - if (p->Freq > MAX_FREQ) - rescale(Model); - } -} - - - - -inline bool PPM_CONTEXT::decodeSymbol1(ModelPPM *Model) -{ - Model->Coder.SubRange.scale=U.SummFreq; - STATE* p=U.Stats; - int i, HiCnt; - int count=Model->Coder.GetCurrentCount(); - if (count>=Model->Coder.SubRange.scale) - return(false); - if (count < (HiCnt=p->Freq)) - { - Model->PrevSuccess=(2*(Model->Coder.SubRange.HighCount=HiCnt) > Model->Coder.SubRange.scale); - Model->RunLength += Model->PrevSuccess; - (Model->FoundState=p)->Freq=(HiCnt += 4); - U.SummFreq += 4; - if (HiCnt > MAX_FREQ) - rescale(Model); - Model->Coder.SubRange.LowCount=0; - return(true); - } - else - if (Model->FoundState==NULL) - return(false); - Model->PrevSuccess=0; - i=NumStats-1; - while ((HiCnt += (++p)->Freq) <= count) - if (--i == 0) - { - Model->HiBitsFlag=Model->HB2Flag[Model->FoundState->Symbol]; - Model->Coder.SubRange.LowCount=HiCnt; - Model->CharMask[p->Symbol]=Model->EscCount; - i=(Model->NumMasked=NumStats)-1; - Model->FoundState=NULL; - do - { - Model->CharMask[(--p)->Symbol]=Model->EscCount; - } while ( --i ); - Model->Coder.SubRange.HighCount=Model->Coder.SubRange.scale; - return(true); - } - Model->Coder.SubRange.LowCount=(Model->Coder.SubRange.HighCount=HiCnt)-p->Freq; - update1(Model,p); - return(true); -} - - -inline void PPM_CONTEXT::update2(ModelPPM *Model,STATE* p) -{ - (Model->FoundState=p)->Freq += 4; - U.SummFreq += 4; - if (p->Freq > MAX_FREQ) - rescale(Model); - Model->EscCount++; - Model->RunLength=Model->InitRL; -} - - -inline SEE2_CONTEXT* PPM_CONTEXT::makeEscFreq2(ModelPPM *Model,int Diff) -{ - SEE2_CONTEXT* psee2c; - if (NumStats != 256) - { - psee2c=Model->SEE2Cont[Model->NS2Indx[Diff-1]]+ - (Diff < Suffix->NumStats-NumStats)+ - 2*(U.SummFreq < 11*NumStats)+4*(Model->NumMasked > Diff)+ - Model->HiBitsFlag; - Model->Coder.SubRange.scale=psee2c->getMean(); - } - else - { - psee2c=&Model->DummySEE2Cont; - Model->Coder.SubRange.scale=1; - } - return psee2c; -} - - - - -inline bool PPM_CONTEXT::decodeSymbol2(ModelPPM *Model) -{ - int count, HiCnt, i=NumStats-Model->NumMasked; - SEE2_CONTEXT* psee2c=makeEscFreq2(Model,i); - STATE* ps[256], ** pps=ps, * p=U.Stats-1; - HiCnt=0; - do - { - do - { - p++; - } while (Model->CharMask[p->Symbol] == Model->EscCount); - HiCnt += p->Freq; - *pps++ = p; - } while ( --i ); - Model->Coder.SubRange.scale += HiCnt; - count=Model->Coder.GetCurrentCount(); - if (count>=Model->Coder.SubRange.scale) - return(false); - p=*(pps=ps); - if (count < HiCnt) - { - HiCnt=0; - while ((HiCnt += p->Freq) <= count) - p=*++pps; - Model->Coder.SubRange.LowCount = (Model->Coder.SubRange.HighCount=HiCnt)-p->Freq; - psee2c->update(); - update2(Model,p); - } - else - { - Model->Coder.SubRange.LowCount=HiCnt; - Model->Coder.SubRange.HighCount=Model->Coder.SubRange.scale; - i=NumStats-Model->NumMasked; - pps--; - do - { - Model->CharMask[(*++pps)->Symbol]=Model->EscCount; - } while ( --i ); - psee2c->Summ += Model->Coder.SubRange.scale; - Model->NumMasked = NumStats; - } - return(true); -} - - -inline void ModelPPM::ClearMask() -{ - EscCount=1; - memset(CharMask,0,sizeof(CharMask)); -} - - - - -// reset PPM variables after data error allowing safe resuming -// of further data processing -void ModelPPM::CleanUp() -{ - SubAlloc.StopSubAllocator(); - SubAlloc.StartSubAllocator(1); - StartModelRare(2); -} - - -bool ModelPPM::DecodeInit(Unpack *UnpackRead,int &EscChar) -{ - int MaxOrder=UnpackRead->GetChar(); - bool Reset=MaxOrder & 0x20; - - int MaxMB; - MaxMB = 0; // avoids warning of being uninitialized - if (Reset) - MaxMB=UnpackRead->GetChar(); - else - if (SubAlloc.GetAllocatedMemory()==0) - return(false); - if (MaxOrder & 0x40) - EscChar=UnpackRead->GetChar(); - Coder.InitDecoder(UnpackRead); - if (Reset) - { - MaxOrder=(MaxOrder & 0x1f)+1; - if (MaxOrder>16) - MaxOrder=16+(MaxOrder-16)*3; - if (MaxOrder==1) - { - SubAlloc.StopSubAllocator(); - return(false); - } - SubAlloc.StartSubAllocator(MaxMB+1); - StartModelRare(MaxOrder); - } - return(MinContext!=NULL); -} - - -int ModelPPM::DecodeChar() -{ - if ((byte*)MinContext <= SubAlloc.pText || (byte*)MinContext>SubAlloc.HeapEnd) - return(-1); - if (MinContext->NumStats != 1) - { - if ((byte*)MinContext->U.Stats <= SubAlloc.pText || (byte*)MinContext->U.Stats>SubAlloc.HeapEnd) - return(-1); - if (!MinContext->decodeSymbol1(this)) - return(-1); - } - else - MinContext->decodeBinSymbol(this); - Coder.Decode(); - while ( !FoundState ) - { - ARI_DEC_NORMALIZE(Coder.code,Coder.low,Coder.range,Coder.UnpackRead); - do - { - OrderFall++; - MinContext=MinContext->Suffix; - if ((byte*)MinContext <= SubAlloc.pText || (byte*)MinContext>SubAlloc.HeapEnd) - return(-1); - } while (MinContext->NumStats == NumMasked); - if (!MinContext->decodeSymbol2(this)) - return(-1); - Coder.Decode(); - } - int Symbol=FoundState->Symbol; - if (!OrderFall && (byte*) FoundState->Successor > SubAlloc.pText) - MinContext=MaxContext=FoundState->Successor; - else - { - UpdateModel(); - if (EscCount == 0) - ClearMask(); - } - ARI_DEC_NORMALIZE(Coder.code,Coder.low,Coder.range,Coder.UnpackRead); - return(Symbol); -} -#endif diff --git a/snesreader/unrar/model.hpp b/snesreader/unrar/model.hpp deleted file mode 100644 index 1ccf2f1d..00000000 --- a/snesreader/unrar/model.hpp +++ /dev/null @@ -1,133 +0,0 @@ -#ifndef _RAR_PPMMODEL_ -#define _RAR_PPMMODEL_ - -#include "coder.hpp" -#include "suballoc.hpp" - -const int MAX_O=64; /* maximum allowed model order */ - -const int INT_BITS=7, PERIOD_BITS=7, TOT_BITS=INT_BITS+PERIOD_BITS, - INTERVAL=1 << INT_BITS, BIN_SCALE=1 << TOT_BITS, MAX_FREQ=124; - -#ifndef STRICT_ALIGNMENT_REQUIRED -#pragma pack(1) -#endif - -struct SEE2_CONTEXT -{ // SEE-contexts for PPM-contexts with masked symbols - ushort Summ; - byte Shift, Count; - void init(int InitVal) - { - Summ=InitVal << (Shift=PERIOD_BITS-4); - Count=4; - } - uint getMean() - { - uint RetVal=SHORT16(Summ) >> Shift; - Summ -= RetVal; - return RetVal+(RetVal == 0); - } - void update() - { - if (Shift < PERIOD_BITS && --Count == 0) - { - Summ += Summ; - Count=3 << Shift++; - } - } -}; - - -class ModelPPM; -struct PPM_CONTEXT; - -struct STATE -{ - byte Symbol; - byte Freq; - PPM_CONTEXT* Successor; -}; - -struct FreqData -{ - ushort SummFreq; - STATE _PACK_ATTR * Stats; -}; - -struct PPM_CONTEXT -{ - ushort NumStats; - union - { - FreqData U; - STATE OneState; - }; - - PPM_CONTEXT* Suffix; - inline void encodeBinSymbol(ModelPPM *Model,int symbol); // MaxOrder: - inline void encodeSymbol1(ModelPPM *Model,int symbol); // ABCD context - inline void encodeSymbol2(ModelPPM *Model,int symbol); // BCD suffix - inline void decodeBinSymbol(ModelPPM *Model); // BCDE successor - inline bool decodeSymbol1(ModelPPM *Model); // other orders: - inline bool decodeSymbol2(ModelPPM *Model); // BCD context - inline void update1(ModelPPM *Model,STATE* p); // CD suffix - inline void update2(ModelPPM *Model,STATE* p); // BCDE successor - void rescale(ModelPPM *Model); - inline PPM_CONTEXT* createChild(ModelPPM *Model,STATE* pStats,STATE& FirstState); - inline SEE2_CONTEXT* makeEscFreq2(ModelPPM *Model,int Diff); -}; - -#ifndef STRICT_ALIGNMENT_REQUIRED -#ifdef _AIX -#pragma pack(pop) -#else -#pragma pack() -#endif -#endif - -const uint UNIT_SIZE=Max(sizeof(PPM_CONTEXT),sizeof(RAR_MEM_BLK)); -const uint FIXED_UNIT_SIZE=12; - -/* -inline PPM_CONTEXT::PPM_CONTEXT(STATE* pStats,PPM_CONTEXT* ShorterContext): - NumStats(1), Suffix(ShorterContext) { pStats->Successor=this; } -inline PPM_CONTEXT::PPM_CONTEXT(): NumStats(0) {} -*/ - -template -inline void _PPMD_SWAP(T& t1,T& t2) { T tmp=t1; t1=t2; t2=tmp; } - - -class ModelPPM -{ - private: - friend struct PPM_CONTEXT; - - /*_PACK_ATTR*/ SEE2_CONTEXT SEE2Cont[25][16], DummySEE2Cont; - - struct PPM_CONTEXT *MinContext, *MedContext, *MaxContext; - STATE* FoundState; // found next state transition - int NumMasked, InitEsc, OrderFall, MaxOrder, RunLength, InitRL; - byte CharMask[256], NS2Indx[256], NS2BSIndx[256], HB2Flag[256]; - byte EscCount, PrevSuccess, HiBitsFlag; - ushort BinSumm[128][64]; // binary SEE-contexts - - RangeCoder Coder; - SubAllocator SubAlloc; - - void RestartModelRare(); - void StartModelRare(int MaxOrder); - inline PPM_CONTEXT* CreateSuccessors(bool Skip,STATE* p1); - - inline void UpdateModel(); - inline void ClearMask(); - friend class Unpack; - public: - ModelPPM(); - void CleanUp(); // reset PPM variables after data error - bool DecodeInit(Unpack *UnpackRead,int &EscChar); - int DecodeChar(); -}; - -#endif diff --git a/snesreader/unrar/rar.hpp b/snesreader/unrar/rar.hpp deleted file mode 100644 index 3302b2b2..00000000 --- a/snesreader/unrar/rar.hpp +++ /dev/null @@ -1,209 +0,0 @@ -// This source code is a heavily modified version based on the unrar package. -// It may NOT be used to develop a RAR (WinRAR) compatible archiver. -// See license.txt for copyright and licensing. - -// unrar_core 3.8.5 -#ifndef RAR_COMMON_HPP -#define RAR_COMMON_HPP - -#include "unrar.h" - -#include -#include -#include -#include - -//// Glue - -// One goal is to keep source code as close to original as possible, so -// that changes to the original can be found and merged more easily. - -// These names are too generic and might clash (or have already, hmpf) -#define Array Rar_Array -#define uint32 rar_uint32 -#define sint32 rar_sint32 -#define Unpack Rar_Unpack -#define Archive Rar_Archive -#define RawRead Rar_RawRead -#define BitInput Rar_BitInput -#define ModelPPM Rar_ModelPPM -#define RangeCoder Rar_RangeCoder -#define SubAllocator Rar_SubAllocator -#define UnpackFilter Rar_UnpackFilter -#define VM_PreparedProgram Rar_VM_PreparedProgram -#define CRCTab Rar_CRCTab - -// original source used rar* names for these as well -#define rarmalloc malloc -#define rarrealloc realloc -#define rarfree free - -// Internal flags, possibly set later -#undef SFX_MODULE -#undef VM_OPTIMIZE -#undef VM_STANDARDFILTERS -#undef NORARVM - -// During debugging if expr is false, prints message then continues execution -#ifndef check - #define check( expr ) ((void) 0) -#endif - -struct Rar_Error_Handler -{ - jmp_buf jmp_env; - - void MemoryError(); - void ReportError( unrar_err_t ); -}; - -// throw spec is mandatory in ISO C++ if operator new can return NULL -#if __cplusplus >= 199711 || __GNUC__ >= 3 - #define UNRAR_NOTHROW throw () -#else - #define UNRAR_NOTHROW -#endif - -struct Rar_Allocator -{ - // provides allocator that doesn't throw an exception on failure - static void operator delete ( void* p ) { free( p ); } - static void* operator new ( size_t s ) UNRAR_NOTHROW { return malloc( s ); } - static void* operator new ( size_t, void* p ) UNRAR_NOTHROW { return p; } -}; - -//// os.hpp -#undef STRICT_ALIGNMENT_REQUIRED -#undef LITTLE_ENDIAN -#define NM 1024 - -#if defined (__i386__) || defined (__x86_64__) || defined (_M_IX86) || defined (_M_X64) - // Optimizations mostly only apply to x86 - #define LITTLE_ENDIAN - #define ALLOW_NOT_ALIGNED_INT -#endif - -#if defined(__sparc) || defined(sparc) || defined(__sparcv9) -/* prohibit not aligned access to data structures in text comression - algorithm, increases memory requirements */ - #define STRICT_ALIGNMENT_REQUIRED -#endif - -//// rartypes.hpp -#if INT_MAX == 0x7FFFFFFF && UINT_MAX == 0xFFFFFFFF - typedef unsigned int uint32; //32 bits exactly - typedef int sint32; //signed 32 bits exactly - #define PRESENT_INT32 -#endif - -typedef unsigned char byte; //8 bits -typedef unsigned short ushort; //preferably 16 bits, but can be more -typedef unsigned int uint; //32 bits or more - -typedef wchar_t wchar; - -#define SHORT16(x) (sizeof(ushort)==2 ? (ushort)(x):((x)&0xffff)) -#define UINT32(x) (sizeof(uint )==4 ? (uint )(x):((x)&0xffffffff)) - -//// rardefs.hpp -#define Min(x,y) (((x)<(y)) ? (x):(y)) -#define Max(x,y) (((x)>(y)) ? (x):(y)) - -//// int64.hpp -typedef unrar_long_long Int64; - -#define int64to32(x) ((uint)(x)) -#define int32to64(high,low) ((((Int64)(high))<<31<<1)+(low)) -#define is64plus(x) (x>=0) - -#define INT64MAX int32to64(0x7fffffff,0) - -//// crc.hpp -extern uint CRCTab[256]; -void InitCRC(); -uint CRC(uint StartCRC,const void *Addr,size_t Size); -ushort OldCRC(ushort StartCRC,const void *Addr,size_t Size); - -//// rartime.hpp -struct RarTime -{ - unsigned time; - void SetDos(uint DosTime) { time = DosTime; } -}; - -//// rdwrfn.hpp -class ComprDataIO - : public Rar_Error_Handler -{ -public: - unrar_read_func user_read; - unrar_write_func user_write; - void* user_read_data; - void* user_write_data; - unrar_err_t write_error; // once write error occurs, no more writes are made - Int64 Tell_; - bool OldFormat; - -private: - Int64 UnpPackedSize; - bool SkipUnpCRC; - -public: - int UnpRead(byte *Addr,uint Count); - void UnpWrite(byte *Addr,uint Count); - void SetSkipUnpCRC( bool b ) { SkipUnpCRC = b; } - void SetPackedSizeToRead( Int64 n ) { UnpPackedSize = n; } - - uint UnpFileCRC; - - void Seek(Int64 Offset, int Method = 0 ) { (void)Method; Tell_ = Offset; } - Int64 Tell() { return Tell_; } - int Read( void* p, int n ); -}; - -//// rar.hpp -class Unpack; -#include "array.hpp" -#include "headers.hpp" -#include "getbits.hpp" -#include "archive.hpp" -#include "rawread.hpp" -#include "encname.hpp" -#include "compress.hpp" -#include "rarvm.hpp" -#include "model.hpp" -#include "unpack.hpp" - -//// extract.hpp -/** RAR archive */ -struct unrar_t - : public Rar_Allocator -{ - unrar_info_t info; - unrar_pos_t begin_pos; - unrar_pos_t solid_pos; - unrar_pos_t first_file_pos; - void const* data_; - void* own_data_; - void (*close_file)( void* ); // func ptr to avoid linking fclose() in unnecessarily - bool done; - long FileCount; - Unpack* Unp; - Array Buffer; - // large items last - Archive Arc; - - unrar_t(); - ~unrar_t(); - void UnstoreFile( Int64 ); - unrar_err_t ExtractCurrentFile( bool SkipSolid = false, bool check_compatibility_only = false ); - void update_first_file_pos() - { - if ( FileCount == 0 ) - first_file_pos = Arc.CurBlockPos; - } -}; - -typedef unrar_t CmdExtract; - -#endif diff --git a/snesreader/unrar/rarvm.cpp b/snesreader/unrar/rarvm.cpp deleted file mode 100644 index d13e6264..00000000 --- a/snesreader/unrar/rarvm.cpp +++ /dev/null @@ -1,1158 +0,0 @@ -#include "rar.hpp" - -#include "rarvmtbl.cpp" - -// avoids warning of enumeration and non-enumeration in ?: expressions -#define VM_FC ((unsigned) VM_FC) -#define VM_FZ ((unsigned) VM_FZ) -#define VM_FS ((unsigned) VM_FS) - -RarVM::RarVM() -{ - Mem=NULL; -} - - -RarVM::~RarVM() -{ - rarfree( Mem ); -} - - -void RarVM::Init() -{ - if (Mem==NULL) - Mem = (byte*) rarmalloc( VM_MEMSIZE+4 ); -} - -void RarVM::handle_mem_error( Rar_Error_Handler& ErrHandler ) -{ - BitInput::handle_mem_error( ErrHandler ); - if ( !Mem ) - ErrHandler.MemoryError(); -} - -/********************************************************************* - IS_VM_MEM macro checks if address belongs to VM memory pool (Mem). - Only Mem data are always low endian regardless of machine architecture, - so we need to convert them to native format when reading or writing. - VM registers have endianness of host machine. -**********************************************************************/ -#define IS_VM_MEM(a) (((byte*)a)>=Mem && ((byte*)a)>8); - ((byte *)Addr)[2]=(byte)(Value>>16); - ((byte *)Addr)[3]=(byte)(Value>>24); - } - else - *(uint *)Addr=Value; -#else - *(uint32 *)Addr=Value; -#endif - } -} - -#if defined(BIG_ENDIAN) || !defined(ALLOW_NOT_ALIGNED_INT) || !defined(PRESENT_INT32) -#define SET_VALUE(ByteMode,Addr,Value) SetValue(ByteMode,(uint *)Addr,Value) -#else - #define SET_VALUE(ByteMode,Addr,Value) ((ByteMode) ? (*(byte *)(Addr)=(Value)):(*(uint32 *)(Addr)=((uint32)(Value)))) -#endif - - -void RarVM::SetLowEndianValue(uint *Addr,uint Value) -{ -#if defined(BIG_ENDIAN) || !defined(ALLOW_NOT_ALIGNED_INT) || !defined(PRESENT_INT32) - ((byte *)Addr)[0]=(byte)Value; - ((byte *)Addr)[1]=(byte)(Value>>8); - ((byte *)Addr)[2]=(byte)(Value>>16); - ((byte *)Addr)[3]=(byte)(Value>>24); -#else - *(uint32 *)Addr=Value; -#endif -} - - -inline uint* RarVM::GetOperand(VM_PreparedOperand *CmdOp) -{ - if (CmdOp->Type==VM_OPREGMEM) - return((uint *)&Mem[(*CmdOp->Addr+CmdOp->Base)&VM_MEMMASK]); - else - return(CmdOp->Addr); -} - - -void RarVM::Execute(VM_PreparedProgram *Prg) -{ - memcpy(R,Prg->InitR,sizeof(Prg->InitR)); - unsigned int GlobalSize=Min(Prg->GlobalData.Size(),VM_GLOBALMEMSIZE); - if (GlobalSize) - memcpy(Mem+VM_GLOBALMEMADDR,&Prg->GlobalData[0],GlobalSize); - unsigned int StaticSize=Min(Prg->StaticData.Size(),VM_GLOBALMEMSIZE-GlobalSize); - if (StaticSize) - memcpy(Mem+VM_GLOBALMEMADDR+GlobalSize,&Prg->StaticData[0],StaticSize); - - R[7]=VM_MEMSIZE; - Flags=0; - - VM_PreparedCommand *PreparedCode=Prg->AltCmd ? Prg->AltCmd:&Prg->Cmd[0]; - if (!ExecuteCode(PreparedCode,Prg->CmdCount)) - PreparedCode[0].OpCode=VM_RET; - uint NewBlockPos=GET_VALUE(false,&Mem[VM_GLOBALMEMADDR+0x20])&VM_MEMMASK; - uint NewBlockSize=GET_VALUE(false,&Mem[VM_GLOBALMEMADDR+0x1c])&VM_MEMMASK; - if (NewBlockPos+NewBlockSize>=VM_MEMSIZE) - NewBlockPos=NewBlockSize=0; - Prg->FilteredData=Mem+NewBlockPos; - Prg->FilteredDataSize=NewBlockSize; - - Prg->GlobalData.Reset(); - - uint DataSize=Min(GET_VALUE(false,(uint*)&Mem[VM_GLOBALMEMADDR+0x30]),VM_GLOBALMEMSIZE-VM_FIXEDGLOBALSIZE); - if (DataSize!=0) - { - Prg->GlobalData.Add(DataSize+VM_FIXEDGLOBALSIZE); - memcpy(&Prg->GlobalData[0],&Mem[VM_GLOBALMEMADDR],DataSize+VM_FIXEDGLOBALSIZE); - } -} - - -/* -Note: - Due to performance considerations RAR VM may set VM_FS, VM_FC, VM_FZ - incorrectly for byte operands. These flags are always valid only - for 32-bit operands. Check implementation of concrete VM command - to see if it sets flags right. -*/ - -#define SET_IP(IP) \ - if ((IP)>=CodeSize) \ - return(true); \ - if (--MaxOpCount<=0) \ - return(false); \ - Cmd=PreparedCode+(IP); - -bool RarVM::ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize) -{ - int MaxOpCount=25000000; - VM_PreparedCommand *Cmd=PreparedCode; - while (1) - { -#ifndef NORARVM - // Get addresses to quickly access operands. - uint *Op1=GetOperand(&Cmd->Op1); - uint *Op2=GetOperand(&Cmd->Op2); -#endif - switch(Cmd->OpCode) - { -#ifndef NORARVM - case VM_MOV: - SET_VALUE(Cmd->ByteMode,Op1,GET_VALUE(Cmd->ByteMode,Op2)); - break; -#ifdef VM_OPTIMIZE - case VM_MOVB: - SET_VALUE(true,Op1,GET_VALUE(true,Op2)); - break; - case VM_MOVD: - SET_VALUE(false,Op1,GET_VALUE(false,Op2)); - break; -#endif - case VM_CMP: - { - uint Value1=GET_VALUE(Cmd->ByteMode,Op1); - uint Result=UINT32(Value1-GET_VALUE(Cmd->ByteMode,Op2)); - Flags=Result==0 ? VM_FZ:(Result>Value1)|(Result&VM_FS); - } - break; -#ifdef VM_OPTIMIZE - case VM_CMPB: - { - uint Value1=GET_VALUE(true,Op1); - uint Result=UINT32(Value1-GET_VALUE(true,Op2)); - Flags=Result==0 ? VM_FZ:(Result>Value1)|(Result&VM_FS); - } - break; - case VM_CMPD: - { - uint Value1=GET_VALUE(false,Op1); - uint Result=UINT32(Value1-GET_VALUE(false,Op2)); - Flags=Result==0 ? VM_FZ:(Result>Value1)|(Result&VM_FS); - } - break; -#endif - case VM_ADD: - { - uint Value1=GET_VALUE(Cmd->ByteMode,Op1); - uint Result=UINT32(Value1+GET_VALUE(Cmd->ByteMode,Op2)); - if (Cmd->ByteMode) - { - Result&=0xff; - Flags=(ResultByteMode,Op1,Result); - } - break; -#ifdef VM_OPTIMIZE - case VM_ADDB: - SET_VALUE(true,Op1,GET_VALUE(true,Op1)+GET_VALUE(true,Op2)); - break; - case VM_ADDD: - SET_VALUE(false,Op1,GET_VALUE(false,Op1)+GET_VALUE(false,Op2)); - break; -#endif - case VM_SUB: - { - uint Value1=GET_VALUE(Cmd->ByteMode,Op1); - uint Result=UINT32(Value1-GET_VALUE(Cmd->ByteMode,Op2)); - Flags=Result==0 ? VM_FZ:(Result>Value1)|(Result&VM_FS); - SET_VALUE(Cmd->ByteMode,Op1,Result); - } - break; -#ifdef VM_OPTIMIZE - case VM_SUBB: - SET_VALUE(true,Op1,GET_VALUE(true,Op1)-GET_VALUE(true,Op2)); - break; - case VM_SUBD: - SET_VALUE(false,Op1,GET_VALUE(false,Op1)-GET_VALUE(false,Op2)); - break; -#endif - case VM_JZ: - if ((Flags & VM_FZ)!=0) - { - SET_IP(GET_VALUE(false,Op1)); - continue; - } - break; - case VM_JNZ: - if ((Flags & VM_FZ)==0) - { - SET_IP(GET_VALUE(false,Op1)); - continue; - } - break; - case VM_INC: - { - uint Result=UINT32(GET_VALUE(Cmd->ByteMode,Op1)+1); - if (Cmd->ByteMode) - Result&=0xff; - SET_VALUE(Cmd->ByteMode,Op1,Result); - Flags=Result==0 ? VM_FZ:Result&VM_FS; - } - break; -#ifdef VM_OPTIMIZE - case VM_INCB: - SET_VALUE(true,Op1,GET_VALUE(true,Op1)+1); - break; - case VM_INCD: - SET_VALUE(false,Op1,GET_VALUE(false,Op1)+1); - break; -#endif - case VM_DEC: - { - uint Result=UINT32(GET_VALUE(Cmd->ByteMode,Op1)-1); - SET_VALUE(Cmd->ByteMode,Op1,Result); - Flags=Result==0 ? VM_FZ:Result&VM_FS; - } - break; -#ifdef VM_OPTIMIZE - case VM_DECB: - SET_VALUE(true,Op1,GET_VALUE(true,Op1)-1); - break; - case VM_DECD: - SET_VALUE(false,Op1,GET_VALUE(false,Op1)-1); - break; -#endif - case VM_JMP: - SET_IP(GET_VALUE(false,Op1)); - continue; - case VM_XOR: - { - uint Result=UINT32(GET_VALUE(Cmd->ByteMode,Op1)^GET_VALUE(Cmd->ByteMode,Op2)); - Flags=Result==0 ? VM_FZ:Result&VM_FS; - SET_VALUE(Cmd->ByteMode,Op1,Result); - } - break; - case VM_AND: - { - uint Result=UINT32(GET_VALUE(Cmd->ByteMode,Op1)&GET_VALUE(Cmd->ByteMode,Op2)); - Flags=Result==0 ? VM_FZ:Result&VM_FS; - SET_VALUE(Cmd->ByteMode,Op1,Result); - } - break; - case VM_OR: - { - uint Result=UINT32(GET_VALUE(Cmd->ByteMode,Op1)|GET_VALUE(Cmd->ByteMode,Op2)); - Flags=Result==0 ? VM_FZ:Result&VM_FS; - SET_VALUE(Cmd->ByteMode,Op1,Result); - } - break; - case VM_TEST: - { - uint Result=UINT32(GET_VALUE(Cmd->ByteMode,Op1)&GET_VALUE(Cmd->ByteMode,Op2)); - Flags=Result==0 ? VM_FZ:Result&VM_FS; - } - break; - case VM_JS: - if ((Flags & VM_FS)!=0) - { - SET_IP(GET_VALUE(false,Op1)); - continue; - } - break; - case VM_JNS: - if ((Flags & VM_FS)==0) - { - SET_IP(GET_VALUE(false,Op1)); - continue; - } - break; - case VM_JB: - if ((Flags & VM_FC)!=0) - { - SET_IP(GET_VALUE(false,Op1)); - continue; - } - break; - case VM_JBE: - if ((Flags & (VM_FC|VM_FZ))!=0) - { - SET_IP(GET_VALUE(false,Op1)); - continue; - } - break; - case VM_JA: - if ((Flags & (VM_FC|VM_FZ))==0) - { - SET_IP(GET_VALUE(false,Op1)); - continue; - } - break; - case VM_JAE: - if ((Flags & VM_FC)==0) - { - SET_IP(GET_VALUE(false,Op1)); - continue; - } - break; - case VM_PUSH: - R[7]-=4; - SET_VALUE(false,(uint *)&Mem[R[7]&VM_MEMMASK],GET_VALUE(false,Op1)); - break; - case VM_POP: - SET_VALUE(false,Op1,GET_VALUE(false,(uint *)&Mem[R[7] & VM_MEMMASK])); - R[7]+=4; - break; - case VM_CALL: - R[7]-=4; - SET_VALUE(false,(uint *)&Mem[R[7]&VM_MEMMASK],Cmd-PreparedCode+1); - SET_IP(GET_VALUE(false,Op1)); - continue; - case VM_NOT: - SET_VALUE(Cmd->ByteMode,Op1,~GET_VALUE(Cmd->ByteMode,Op1)); - break; - case VM_SHL: - { - uint Value1=GET_VALUE(Cmd->ByteMode,Op1); - uint Value2=GET_VALUE(Cmd->ByteMode,Op2); - uint Result=UINT32(Value1<ByteMode,Op1,Result); - } - break; - case VM_SHR: - { - uint Value1=GET_VALUE(Cmd->ByteMode,Op1); - uint Value2=GET_VALUE(Cmd->ByteMode,Op2); - uint Result=UINT32(Value1>>Value2); - Flags=(Result==0 ? VM_FZ:(Result&VM_FS))|((Value1>>(Value2-1))&VM_FC); - SET_VALUE(Cmd->ByteMode,Op1,Result); - } - break; - case VM_SAR: - { - uint Value1=GET_VALUE(Cmd->ByteMode,Op1); - uint Value2=GET_VALUE(Cmd->ByteMode,Op2); - uint Result=UINT32(((int)Value1)>>Value2); - Flags=(Result==0 ? VM_FZ:(Result&VM_FS))|((Value1>>(Value2-1))&VM_FC); - SET_VALUE(Cmd->ByteMode,Op1,Result); - } - break; - case VM_NEG: - { - uint Result=UINT32(-GET_VALUE(Cmd->ByteMode,Op1)); - Flags=Result==0 ? VM_FZ:VM_FC|(Result&VM_FS); - SET_VALUE(Cmd->ByteMode,Op1,Result); - } - break; -#ifdef VM_OPTIMIZE - case VM_NEGB: - SET_VALUE(true,Op1,-GET_VALUE(true,Op1)); - break; - case VM_NEGD: - SET_VALUE(false,Op1,-GET_VALUE(false,Op1)); - break; -#endif - case VM_PUSHA: - { - const int RegCount=sizeof(R)/sizeof(R[0]); - for (int I=0,SP=R[7]-4;IByteMode,Op1); - SET_VALUE(Cmd->ByteMode,Op1,GET_VALUE(Cmd->ByteMode,Op2)); - SET_VALUE(Cmd->ByteMode,Op2,Value1); - } - break; - case VM_MUL: - { - uint Result=GET_VALUE(Cmd->ByteMode,Op1)*GET_VALUE(Cmd->ByteMode,Op2); - SET_VALUE(Cmd->ByteMode,Op1,Result); - } - break; - case VM_DIV: - { - uint Divider=GET_VALUE(Cmd->ByteMode,Op2); - if (Divider!=0) - { - uint Result=GET_VALUE(Cmd->ByteMode,Op1)/Divider; - SET_VALUE(Cmd->ByteMode,Op1,Result); - } - } - break; - case VM_ADC: - { - uint Value1=GET_VALUE(Cmd->ByteMode,Op1); - uint FC=(Flags&VM_FC); - uint Result=UINT32(Value1+GET_VALUE(Cmd->ByteMode,Op2)+FC); - if (Cmd->ByteMode) - Result&=0xff; - Flags=(ResultByteMode,Op1,Result); - } - break; - case VM_SBB: - { - uint Value1=GET_VALUE(Cmd->ByteMode,Op1); - uint FC=(Flags&VM_FC); - uint Result=UINT32(Value1-GET_VALUE(Cmd->ByteMode,Op2)-FC); - if (Cmd->ByteMode) - Result&=0xff; - Flags=(Result>Value1 || Result==Value1 && FC)|(Result==0 ? VM_FZ:(Result&VM_FS)); - SET_VALUE(Cmd->ByteMode,Op1,Result); - } - break; -#endif // for #ifndef NORARVM - case VM_RET: - if (R[7]>=VM_MEMSIZE) - return(true); - SET_IP(GET_VALUE(false,(uint *)&Mem[R[7] & VM_MEMMASK])); - R[7]+=4; - continue; -#ifdef VM_STANDARDFILTERS - case VM_STANDARD: - ExecuteStandardFilter((VM_StandardFilters)Cmd->Op1.Data); - break; -#endif - case VM_PRINT: - break; - } - Cmd++; - --MaxOpCount; - } -} - - - - -void RarVM::Prepare(byte *Code,int CodeSize,VM_PreparedProgram *Prg) -{ - InitBitInput(); - memcpy(InBuf,Code,Min(CodeSize,BitInput::MAX_SIZE)); - - // Calculate the single byte XOR checksum to check validity of VM code. - byte XorSum=0; - { - for (int I=1;ICmdCount=0; - if (XorSum==Code[0]) // VM code is valid if equal. - { -#ifdef VM_STANDARDFILTERS - VM_StandardFilters FilterType=IsStandardFilter(Code,CodeSize); - if (FilterType!=VMSF_NONE) - { - // VM code is found among standard filters. - Prg->Cmd.Add(1); - VM_PreparedCommand *CurCmd=&Prg->Cmd[Prg->CmdCount++]; - CurCmd->OpCode=VM_STANDARD; - CurCmd->Op1.Data=FilterType; - CurCmd->Op1.Addr=&CurCmd->Op1.Data; - CurCmd->Op2.Addr=&CurCmd->Op2.Data; - CurCmd->Op1.Type=CurCmd->Op2.Type=VM_OPNONE; - CodeSize=0; - } -#endif - uint DataFlag=fgetbits(); - faddbits(1); - - // Read static data contained in DB operators. This data cannot be - // changed, it is a part of VM code, not a filter parameter. - - if (DataFlag&0x8000) - { - int DataSize=ReadData(*this)+1; - for (int I=0;InAddrStaticData.Add(1); - Prg->StaticData[I]=fgetbits()>>8; - faddbits(8); - } - } - - while (InAddrCmd.Add(1); - VM_PreparedCommand *CurCmd=&Prg->Cmd[Prg->CmdCount]; - uint Data=fgetbits(); - if ((Data&0x8000)==0) - { - CurCmd->OpCode=(VM_Commands)(Data>>12); - faddbits(4); - } - else - { - CurCmd->OpCode=(VM_Commands)((Data>>10)-24); - faddbits(6); - } - if (VM_CmdFlags[CurCmd->OpCode] & VMCF_BYTEMODE) - { - CurCmd->ByteMode=fgetbits()>>15; - faddbits(1); - } - else - CurCmd->ByteMode=0; - CurCmd->Op1.Type=CurCmd->Op2.Type=VM_OPNONE; - int OpNum=(VM_CmdFlags[CurCmd->OpCode] & VMCF_OPMASK); - CurCmd->Op1.Addr=CurCmd->Op2.Addr=NULL; - if (OpNum>0) - { - DecodeArg(CurCmd->Op1,CurCmd->ByteMode); // reading the first operand - if (OpNum==2) - DecodeArg(CurCmd->Op2,CurCmd->ByteMode); // reading the second operand - else - { - if (CurCmd->Op1.Type==VM_OPINT && (VM_CmdFlags[CurCmd->OpCode]&(VMCF_JUMP|VMCF_PROC))) - { - // Calculating jump distance. - int Distance=CurCmd->Op1.Data; - if (Distance>=256) - Distance-=256; - else - { - if (Distance>=136) - Distance-=264; - else - if (Distance>=16) - Distance-=8; - else - if (Distance>=8) - Distance-=16; - Distance+=Prg->CmdCount; - } - CurCmd->Op1.Data=Distance; - } - } - } - Prg->CmdCount++; - } - } - - // Adding RET command at the end of program. - Prg->Cmd.Add(1); - VM_PreparedCommand *CurCmd=&Prg->Cmd[Prg->CmdCount++]; - CurCmd->OpCode=VM_RET; - CurCmd->Op1.Addr=&CurCmd->Op1.Data; - CurCmd->Op2.Addr=&CurCmd->Op2.Data; - CurCmd->Op1.Type=CurCmd->Op2.Type=VM_OPNONE; - - // If operand 'Addr' field has not been set by DecodeArg calls above, - // let's set it to point to operand 'Data' field. It is necessary for - // VM_OPINT type operands (usual integers) or maybe if something was - // not set properly for other operands. 'Addr' field is required - // for quicker addressing of operand data. - for (int I=0;ICmdCount;I++) - { - VM_PreparedCommand *Cmd=&Prg->Cmd[I]; - if (Cmd->Op1.Addr==NULL) - Cmd->Op1.Addr=&Cmd->Op1.Data; - if (Cmd->Op2.Addr==NULL) - Cmd->Op2.Addr=&Cmd->Op2.Data; - } - -#ifdef VM_OPTIMIZE - if (CodeSize!=0) - Optimize(Prg); -#endif -} - - -void RarVM::DecodeArg(VM_PreparedOperand &Op,bool ByteMode) -{ - uint Data=fgetbits(); - if (Data & 0x8000) - { - Op.Type=VM_OPREG; // Operand is register (R[0]..R[7]) - Op.Data=(Data>>12)&7; // Register number - Op.Addr=&R[Op.Data]; // Register address - faddbits(4); // 1 flag bit and 3 register number bits - } - else - if ((Data & 0xc000)==0) - { - Op.Type=VM_OPINT; // Operand is integer - if (ByteMode) - { - Op.Data=(Data>>6) & 0xff; // Byte integer. - faddbits(10); - } - else - { - faddbits(2); - Op.Data=ReadData(*this); // 32 bit integer. - } - } - else - { - // Operand is data addressed by register data, base address or both. - Op.Type=VM_OPREGMEM; - if ((Data & 0x2000)==0) - { - // Base address is zero, just use the address from register. - Op.Data=(Data>>10)&7; - Op.Addr=&R[Op.Data]; - Op.Base=0; - faddbits(6); - } - else - { - if ((Data & 0x1000)==0) - { - // Use both register and base address. - Op.Data=(Data>>9)&7; - Op.Addr=&R[Op.Data]; - faddbits(7); - } - else - { - // Use base address only. Access memory by fixed address. - Op.Data=0; - faddbits(4); - } - Op.Base=ReadData(*this); // Read base address. - } - } -} - - -uint RarVM::ReadData(BitInput &Inp) -{ - uint Data=Inp.fgetbits(); - switch(Data&0xc000) - { - case 0: - Inp.faddbits(6); - return((Data>>10)&0xf); - case 0x4000: - if ((Data&0x3c00)==0) - { - Data=0xffffff00|((Data>>2)&0xff); - Inp.faddbits(14); - } - else - { - Data=(Data>>6)&0xff; - Inp.faddbits(10); - } - return(Data); - case 0x8000: - Inp.faddbits(2); - Data=Inp.fgetbits(); - Inp.faddbits(16); - return(Data); - default: - Inp.faddbits(2); - Data=(Inp.fgetbits()<<16); - Inp.faddbits(16); - Data|=Inp.fgetbits(); - Inp.faddbits(16); - return(Data); - } -} - - -void RarVM::SetMemory(unsigned int Pos,byte *Data,unsigned int DataSize) -{ - if (PosCmd[0]; - int CodeSize=Prg->CmdCount; - - for (int I=0;IOpCode) - { - case VM_MOV: - Cmd->OpCode=Cmd->ByteMode ? VM_MOVB:VM_MOVD; - continue; - case VM_CMP: - Cmd->OpCode=Cmd->ByteMode ? VM_CMPB:VM_CMPD; - continue; - } - if ((VM_CmdFlags[Cmd->OpCode] & VMCF_CHFLAGS)==0) - continue; - - // If we do not have jump commands between the current operation - // and next command which will modify processor flags, we can replace - // the current command with faster version which does not need to - // modify flags. - bool FlagsRequired=false; - for (int J=I+1;JOpCode) - { - case VM_ADD: - Cmd->OpCode=Cmd->ByteMode ? VM_ADDB:VM_ADDD; - continue; - case VM_SUB: - Cmd->OpCode=Cmd->ByteMode ? VM_SUBB:VM_SUBD; - continue; - case VM_INC: - Cmd->OpCode=Cmd->ByteMode ? VM_INCB:VM_INCD; - continue; - case VM_DEC: - Cmd->OpCode=Cmd->ByteMode ? VM_DECB:VM_DECD; - continue; - case VM_NEG: - Cmd->OpCode=Cmd->ByteMode ? VM_NEGB:VM_NEGD; - continue; - } - } -} -#endif - - -#ifdef VM_STANDARDFILTERS -VM_StandardFilters RarVM::IsStandardFilter(byte *Code,int CodeSize) -{ - static const - struct StandardFilterSignature - { - int Length; - uint CRC; - VM_StandardFilters Type; - } StdList[]={ - { - 53, 0xad576887, VMSF_E8, - },{ - 57, 0x3cd7e57e, VMSF_E8E9, - },{ - 120, 0x3769893f, VMSF_ITANIUM, - },{ - 29, 0x0e06077d, VMSF_DELTA, - },{ - 149, 0x1c2c5dc8, VMSF_RGB, - },{ - 216, 0xbc85e701, VMSF_AUDIO, - },{ - 40, 0x46b9c560, VMSF_UPCASE - } - }; - uint CodeCRC=CRC(0xffffffff,Code,CodeSize)^0xffffffff; - for (int I=0;I=VM_GLOBALMEMADDR || DataSize<4) - break; - - const int FileSize=0x1000000; - byte CmpByte2=FilterType==VMSF_E8E9 ? 0xe9:0xe8; - for (int CurPos=0;CurPos=0) - SET_VALUE(false,Data,Addr+FileSize); - } - else - if (Addr=VM_GLOBALMEMADDR || DataSize<21) - break; - - int CurPos=0; - - FileOffset>>=4; - - while (CurPos=0) - { - const - static byte Masks[16]={4,4,6,6,0,0,7,7,4,4,0,0,4,4,0,0}; - byte CmdMask=Masks[Byte]; - if (CmdMask!=0) - for (int I=0;I<=2;I++) - if (CmdMask & (1<=VM_GLOBALMEMADDR/2) - break; - - // Bytes from same channels are grouped to continual data blocks, - // so we need to place them back to their interleaving positions. - for (int CurChannel=0;CurChannel=VM_GLOBALMEMADDR/2 || PosR<0) - break; - for (int CurChannel=0;CurChannel=3) - { - byte *UpperData=DestData+UpperPos; - unsigned int UpperByte=*UpperData; - unsigned int UpperLeftByte=*(UpperData-3); - Predicted=PrevByte+UpperByte-UpperLeftByte; - int pa=abs((int)(Predicted-PrevByte)); - int pb=abs((int)(Predicted-UpperByte)); - int pc=abs((int)(Predicted-UpperLeftByte)); - if (pa<=pb && pa<=pc) - Predicted=PrevByte; - else - if (pb<=pc) - Predicted=UpperByte; - else - Predicted=UpperLeftByte; - } - else - Predicted=PrevByte; - DestData[I]=PrevByte=(byte)(Predicted-*(SrcData++)); - } - } - for (int I=PosR,Border=DataSize-2;I=VM_GLOBALMEMADDR/2) - break; - for (int CurChannel=0;CurChannel>3) & 0xff; - - unsigned int CurByte=*(SrcData++); - - Predicted-=CurByte; - DestData[I]=Predicted; - PrevDelta=(signed char)(Predicted-PrevByte); - PrevByte=Predicted; - - int D=((signed char)CurByte)<<3; - - Dif[0]+=abs(D); - Dif[1]+=abs(D-D1); - Dif[2]+=abs(D+D1); - Dif[3]+=abs(D-D2); - Dif[4]+=abs(D+D2); - Dif[5]+=abs(D-D3); - Dif[6]+=abs(D+D3); - - if ((ByteCount & 0x1f)==0) - { - unsigned int MinDif=Dif[0],NumMinDif=0; - Dif[0]=0; - for (int J=1;J=-16) K1--; break; - case 2: if (K1 < 16) K1++; break; - case 3: if (K2>=-16) K2--; break; - case 4: if (K2 < 16) K2++; break; - case 5: if (K3>=-16) K3--; break; - case 6: if (K3 < 16) K3++; break; - } - } - } - } - } - break; - case VMSF_UPCASE: - { - int DataSize=R[4],SrcPos=0,DestPos=DataSize; - if (DataSize>=VM_GLOBALMEMADDR/2) - break; - while (SrcPos>= InBit; - return(BitField & (0xffffffff>>(32-BitCount))); -} - - -void RarVM::FilterItanium_SetBits(byte *Data,unsigned int BitField,int BitPos, - int BitCount) -{ - int InAddr=BitPos/8; - int InBit=BitPos&7; - unsigned int AndMask=0xffffffff>>(32-BitCount); - AndMask=~(AndMask<>8)|0xff000000; - BitField>>=8; - } -} -#endif diff --git a/snesreader/unrar/rarvm.hpp b/snesreader/unrar/rarvm.hpp deleted file mode 100644 index 835e5299..00000000 --- a/snesreader/unrar/rarvm.hpp +++ /dev/null @@ -1,112 +0,0 @@ -#ifndef _RAR_VM_ -#define _RAR_VM_ - -#define VM_STANDARDFILTERS - -#ifndef SFX_MODULE -#define VM_OPTIMIZE -#endif - - -#define VM_MEMSIZE 0x40000 -#define VM_MEMMASK (VM_MEMSIZE-1) -#define VM_GLOBALMEMADDR 0x3C000 -#define VM_GLOBALMEMSIZE 0x2000 -#define VM_FIXEDGLOBALSIZE 64 - -enum VM_Commands -{ - VM_MOV, VM_CMP, VM_ADD, VM_SUB, VM_JZ, VM_JNZ, VM_INC, VM_DEC, - VM_JMP, VM_XOR, VM_AND, VM_OR, VM_TEST, VM_JS, VM_JNS, VM_JB, - VM_JBE, VM_JA, VM_JAE, VM_PUSH, VM_POP, VM_CALL, VM_RET, VM_NOT, - VM_SHL, VM_SHR, VM_SAR, VM_NEG, VM_PUSHA,VM_POPA, VM_PUSHF,VM_POPF, - VM_MOVZX,VM_MOVSX,VM_XCHG, VM_MUL, VM_DIV, VM_ADC, VM_SBB, VM_PRINT, - -#ifdef VM_OPTIMIZE - VM_MOVB, VM_MOVD, VM_CMPB, VM_CMPD, - - VM_ADDB, VM_ADDD, VM_SUBB, VM_SUBD, VM_INCB, VM_INCD, VM_DECB, VM_DECD, - VM_NEGB, VM_NEGD, -#endif - - VM_STANDARD -}; - -enum VM_StandardFilters { - VMSF_NONE, VMSF_E8, VMSF_E8E9, VMSF_ITANIUM, VMSF_RGB, VMSF_AUDIO, - VMSF_DELTA, VMSF_UPCASE -}; - -enum VM_Flags {VM_FC=1,VM_FZ=2,VM_FS=0x80000000}; - -enum VM_OpType {VM_OPREG,VM_OPINT,VM_OPREGMEM,VM_OPNONE}; - -struct VM_PreparedOperand -{ - VM_OpType Type; - uint Data; - uint Base; - uint *Addr; -}; - -struct VM_PreparedCommand -{ - VM_Commands OpCode; - bool ByteMode; - VM_PreparedOperand Op1,Op2; -}; - - -struct VM_PreparedProgram -{ - VM_PreparedProgram( Rar_Error_Handler* eh ) : Cmd( eh ), GlobalData( eh ), StaticData( eh ) - {AltCmd=NULL;} - - Array Cmd; - VM_PreparedCommand *AltCmd; - int CmdCount; - - Array GlobalData; - Array StaticData; // static data contained in DB operators - uint InitR[7]; - - byte *FilteredData; - unsigned int FilteredDataSize; -}; - -class RarVM:private BitInput -{ - private: - inline uint GetValue(bool ByteMode,uint *Addr); - inline void SetValue(bool ByteMode,uint *Addr,uint Value); - inline uint* GetOperand(VM_PreparedOperand *CmdOp); - void DecodeArg(VM_PreparedOperand &Op,bool ByteMode); -#ifdef VM_OPTIMIZE - void Optimize(VM_PreparedProgram *Prg); -#endif - bool ExecuteCode(VM_PreparedCommand *PreparedCode,int CodeSize); -#ifdef VM_STANDARDFILTERS - VM_StandardFilters IsStandardFilter(byte *Code,int CodeSize); - void ExecuteStandardFilter(VM_StandardFilters FilterType); - unsigned int FilterItanium_GetBits(byte *Data,int BitPos,int BitCount); - void FilterItanium_SetBits(byte *Data,unsigned int BitField,int BitPos, - int BitCount); -#endif - - byte *Mem; - uint R[8]; - uint Flags; - public: - RarVM(); - ~RarVM(); - void Init(); - void handle_mem_error( Rar_Error_Handler& ); - friend class Unpack; - void Prepare(byte *Code,int CodeSize,VM_PreparedProgram *Prg); - void Execute(VM_PreparedProgram *Prg); - void SetLowEndianValue(uint *Addr,uint Value); - void SetMemory(unsigned int Pos,byte *Data,unsigned int DataSize); - static uint ReadData(BitInput &Inp); -}; - -#endif diff --git a/snesreader/unrar/rarvmtbl.cpp b/snesreader/unrar/rarvmtbl.cpp deleted file mode 100644 index abfdbeeb..00000000 --- a/snesreader/unrar/rarvmtbl.cpp +++ /dev/null @@ -1,57 +0,0 @@ -// #included by rarvm.cpp -#ifdef RAR_COMMON_HPP -#define VMCF_OP0 0 -#define VMCF_OP1 1 -#define VMCF_OP2 2 -#define VMCF_OPMASK 3 -#define VMCF_BYTEMODE 4 -#define VMCF_JUMP 8 -#define VMCF_PROC 16 -#define VMCF_USEFLAGS 32 -#define VMCF_CHFLAGS 64 - -const -static byte VM_CmdFlags[]= -{ - /* VM_MOV */ VMCF_OP2 | VMCF_BYTEMODE , - /* VM_CMP */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS , - /* VM_ADD */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS , - /* VM_SUB */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS , - /* VM_JZ */ VMCF_OP1 | VMCF_JUMP | VMCF_USEFLAGS , - /* VM_JNZ */ VMCF_OP1 | VMCF_JUMP | VMCF_USEFLAGS , - /* VM_INC */ VMCF_OP1 | VMCF_BYTEMODE | VMCF_CHFLAGS , - /* VM_DEC */ VMCF_OP1 | VMCF_BYTEMODE | VMCF_CHFLAGS , - /* VM_JMP */ VMCF_OP1 | VMCF_JUMP , - /* VM_XOR */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS , - /* VM_AND */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS , - /* VM_OR */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS , - /* VM_TEST */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS , - /* VM_JS */ VMCF_OP1 | VMCF_JUMP | VMCF_USEFLAGS , - /* VM_JNS */ VMCF_OP1 | VMCF_JUMP | VMCF_USEFLAGS , - /* VM_JB */ VMCF_OP1 | VMCF_JUMP | VMCF_USEFLAGS , - /* VM_JBE */ VMCF_OP1 | VMCF_JUMP | VMCF_USEFLAGS , - /* VM_JA */ VMCF_OP1 | VMCF_JUMP | VMCF_USEFLAGS , - /* VM_JAE */ VMCF_OP1 | VMCF_JUMP | VMCF_USEFLAGS , - /* VM_PUSH */ VMCF_OP1 , - /* VM_POP */ VMCF_OP1 , - /* VM_CALL */ VMCF_OP1 | VMCF_PROC , - /* VM_RET */ VMCF_OP0 | VMCF_PROC , - /* VM_NOT */ VMCF_OP1 | VMCF_BYTEMODE , - /* VM_SHL */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS , - /* VM_SHR */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS , - /* VM_SAR */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_CHFLAGS , - /* VM_NEG */ VMCF_OP1 | VMCF_BYTEMODE | VMCF_CHFLAGS , - /* VM_PUSHA */ VMCF_OP0 , - /* VM_POPA */ VMCF_OP0 , - /* VM_PUSHF */ VMCF_OP0 | VMCF_USEFLAGS , - /* VM_POPF */ VMCF_OP0 | VMCF_CHFLAGS , - /* VM_MOVZX */ VMCF_OP2 , - /* VM_MOVSX */ VMCF_OP2 , - /* VM_XCHG */ VMCF_OP2 | VMCF_BYTEMODE , - /* VM_MUL */ VMCF_OP2 | VMCF_BYTEMODE , - /* VM_DIV */ VMCF_OP2 | VMCF_BYTEMODE , - /* VM_ADC */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_USEFLAGS | VMCF_CHFLAGS , - /* VM_SBB */ VMCF_OP2 | VMCF_BYTEMODE | VMCF_USEFLAGS | VMCF_CHFLAGS , - /* VM_PRINT */ VMCF_OP0 -}; -#endif diff --git a/snesreader/unrar/rawread.cpp b/snesreader/unrar/rawread.cpp deleted file mode 100644 index afe6b06f..00000000 --- a/snesreader/unrar/rawread.cpp +++ /dev/null @@ -1,86 +0,0 @@ -#include "rar.hpp" - -RawRead::RawRead(ComprDataIO *SrcFile) : Data( SrcFile ) -{ - RawRead::SrcFile=SrcFile; - ReadPos=0; - DataSize=0; -} - -void RawRead::Reset() -{ - ReadPos=0; - DataSize=0; - Data.Reset(); -} - -void RawRead::Read(int Size) -{ - // (removed decryption) - if (Size!=0) - { - Data.Add(Size); - DataSize+=SrcFile->Read(&Data[DataSize],Size); - } -} - - - - -void RawRead::Get(byte &Field) -{ - if (ReadPos2 ? CRC(0xffffffff,&Data[2],(ProcessedOnly ? ReadPos:DataSize)-2):0xffffffff); -} diff --git a/snesreader/unrar/rawread.hpp b/snesreader/unrar/rawread.hpp deleted file mode 100644 index dc37c304..00000000 --- a/snesreader/unrar/rawread.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef _RAR_RAWREAD_ -#define _RAR_RAWREAD_ - -class RawRead -{ -private: - Array Data; - File *SrcFile; - int DataSize; - int ReadPos; - friend class Archive; -public: - RawRead(File *SrcFile); - void Reset(); - void Read(int Size); - void Get(byte &Field); - void Get(ushort &Field); - void Get(uint &Field); - void Get(byte *Field,int Size); - uint GetCRC(bool ProcessedOnly); - int Size() {return DataSize;} - int PaddedSize() {return Data.Size()-DataSize;} -}; - -#endif diff --git a/snesreader/unrar/readme.txt b/snesreader/unrar/readme.txt deleted file mode 100644 index 20e70c77..00000000 --- a/snesreader/unrar/readme.txt +++ /dev/null @@ -1,63 +0,0 @@ - - Portable UnRAR version - - - 1. General - - This package includes freeware Unrar C++ source and a few makefiles - (makefile.bcc, makefile.msc+msc.dep, makefile.unix). Unrar source - is subset of RAR and generated from RAR source automatically, - by a small program removing blocks like '#ifndef UNRAR ... #endif'. - Such method is not perfect and you may find some RAR related - stuff unnecessary in Unrar, especially in header files. - - If you wish to port Unrar to a new platform, you may need to edit - '#define LITTLE_ENDIAN' in os.hpp and data type definitions - in rartypes.hpp. - - if computer architecture does not allow not aligned data access, - you need to undefine ALLOW_NOT_ALIGNED_INT and define - STRICT_ALIGNMENT_REQUIRED in os.h. Note that it will increase memory - requirements. - - If you use Borland C++ makefile (makefile.bcc), you need to define - BASEPATHCC environment (or makefile) variable containing - the path to Borland C++ installation. - - Makefile.unix contains numerous compiler option sets. - GCC Linux is selected by default. If you need to compile Unrar - for other platforms, uncomment corresponding lines. - - - 2. Unrar binaries - - If you compiled Unrar for OS, which is not present in "Downloads" - and "RAR extras" on www.rarlab.com, we will appreciate if you send - us the compiled executable to place it to our site. - - - 3. Acknowledgements - - This source includes parts of code written by the following authors: - - Dmitry Shkarin PPMII v.H text compression - Dmitry Subbotin Carryless rangecoder - Szymon Stefanek AES encryption - Brian Gladman AES encryption - Steve Reid SHA-1 hash function - Marcus Herbert makefile.unix file - Tomasz Klim fixes for libunrar.so - Robert Riebisch makefile.dj and patches for DJGPP - - - 4. Legal stuff - - Unrar source may be used in any software to handle RAR archives - without limitations free of charge, but cannot be used to re-create - the RAR compression algorithm, which is proprietary. Distribution - of modified Unrar source in separate form or as a part of other - software is permitted, provided that it is clearly stated in - the documentation and source comments that the code may not be used - to develop a RAR (WinRAR) compatible archiver. - - More detailed license text is available in license.txt. diff --git a/snesreader/unrar/suballoc.cpp b/snesreader/unrar/suballoc.cpp deleted file mode 100644 index 66d49d55..00000000 --- a/snesreader/unrar/suballoc.cpp +++ /dev/null @@ -1,261 +0,0 @@ -/**************************************************************************** - * This file is part of PPMd project * - * Written and distributed to public domain by Dmitry Shkarin 1997, * - * 1999-2000 * - * Contents: memory allocation routines * - ****************************************************************************/ - -// #included by unpack.cpp -#ifdef RAR_COMMON_HPP -SubAllocator::SubAllocator() -{ - Clean(); -} - - -void SubAllocator::Clean() -{ - SubAllocatorSize=0; -} - - -inline void SubAllocator::InsertNode(void* p,int indx) -{ - ((RAR_NODE*) p)->next=FreeList[indx].next; - FreeList[indx].next=(RAR_NODE*) p; -} - - -inline void* SubAllocator::RemoveNode(int indx) -{ - RAR_NODE* RetVal=FreeList[indx].next; - FreeList[indx].next=RetVal->next; - return RetVal; -} - - -inline uint SubAllocator::U2B(int NU) -{ - return /*8*NU+4*NU*/UNIT_SIZE*NU; -} - - -/* - calculate RAR_MEM_BLK + Items address. Real RAR_MEM_BLK size must be - equal to UNIT_SIZE, so we cannot just add Items to RAR_MEM_BLK address -*/ -inline RAR_MEM_BLK* SubAllocator::MBPtr(RAR_MEM_BLK *BasePtr,int Items) -{ - return((RAR_MEM_BLK*)( ((byte *)(BasePtr))+U2B(Items) )); -} - - -inline void SubAllocator::SplitBlock(void* pv,int OldIndx,int NewIndx) -{ - int i, UDiff=Indx2Units[OldIndx]-Indx2Units[NewIndx]; - byte* p=((byte*) pv)+U2B(Indx2Units[NewIndx]); - if (Indx2Units[i=Units2Indx[UDiff-1]] != UDiff) - { - InsertNode(p,--i); - p += U2B(i=Indx2Units[i]); - UDiff -= i; - } - InsertNode(p,Units2Indx[UDiff-1]); -} - - - - -void SubAllocator::StopSubAllocator() -{ - if ( SubAllocatorSize ) - { - SubAllocatorSize=0; - rarfree(HeapStart); - } -} - - -bool SubAllocator::StartSubAllocator(int SASize) -{ - uint t=SASize << 20; - if (SubAllocatorSize == t) - return true; - StopSubAllocator(); - uint AllocSize=t/FIXED_UNIT_SIZE*UNIT_SIZE+UNIT_SIZE; -#ifdef STRICT_ALIGNMENT_REQUIRED - AllocSize+=UNIT_SIZE; -#endif - if ((HeapStart=(byte *)rarmalloc(AllocSize)) == NULL) - { - ErrHandler->MemoryError(); - return false; - } - HeapEnd=HeapStart+AllocSize-UNIT_SIZE; - SubAllocatorSize=t; - return true; -} - - -void SubAllocator::InitSubAllocator() -{ - int i, k; - memset(FreeList,0,sizeof(FreeList)); - pText=HeapStart; - uint Size2=FIXED_UNIT_SIZE*(SubAllocatorSize/8/FIXED_UNIT_SIZE*7); - uint RealSize2=Size2/FIXED_UNIT_SIZE*UNIT_SIZE; - uint Size1=SubAllocatorSize-Size2; - uint RealSize1=Size1/FIXED_UNIT_SIZE*UNIT_SIZE+Size1%FIXED_UNIT_SIZE; -#ifdef STRICT_ALIGNMENT_REQUIRED - if (Size1%FIXED_UNIT_SIZE!=0) - RealSize1+=UNIT_SIZE-Size1%FIXED_UNIT_SIZE; -#endif - HiUnit=HeapStart+SubAllocatorSize; - LoUnit=UnitsStart=HeapStart+RealSize1; - FakeUnitsStart=HeapStart+Size1; - HiUnit=LoUnit+RealSize2; - for (i=0,k=1;i < N1 ;i++,k += 1) - Indx2Units[i]=k; - for (k++;i < N1+N2 ;i++,k += 2) - Indx2Units[i]=k; - for (k++;i < N1+N2+N3 ;i++,k += 3) - Indx2Units[i]=k; - for (k++;i < N1+N2+N3+N4;i++,k += 4) - Indx2Units[i]=k; - for (GlueCount=k=i=0;k < 128;k++) - { - i += (Indx2Units[i] < k+1); - Units2Indx[k]=i; - } -} - - -inline void SubAllocator::GlueFreeBlocks() -{ - RAR_MEM_BLK s0, * p, * p1; - int i, k, sz; - if (LoUnit != HiUnit) - *LoUnit=0; - for (i=0, s0.next=s0.prev=&s0;i < N_INDEXES;i++) - while ( FreeList[i].next ) - { - p=(RAR_MEM_BLK*)RemoveNode(i); - p->insertAt(&s0); - p->Stamp=0xFFFF; - p->NU=Indx2Units[i]; - } - for (p=s0.next;p != &s0;p=p->next) - while ((p1=MBPtr(p,p->NU))->Stamp == 0xFFFF && int(p->NU)+p1->NU < 0x10000) - { - p1->remove(); - p->NU += p1->NU; - } - while ((p=s0.next) != &s0) - { - for (p->remove(), sz=p->NU;sz > 128;sz -= 128, p=MBPtr(p,128)) - InsertNode(p,N_INDEXES-1); - if (Indx2Units[i=Units2Indx[sz-1]] != sz) - { - k=sz-Indx2Units[--i]; - InsertNode(MBPtr(p,sz-k),k-1); - } - InsertNode(p,i); - } -} - -void* SubAllocator::AllocUnitsRare(int indx) -{ - if ( !GlueCount ) - { - GlueCount = 255; - GlueFreeBlocks(); - if ( FreeList[indx].next ) - return RemoveNode(indx); - } - int i=indx; - do - { - if (++i == N_INDEXES) - { - GlueCount--; - i=U2B(Indx2Units[indx]); - int j=FIXED_UNIT_SIZE*Indx2Units[indx]; - if (FakeUnitsStart-pText > j) - { - FakeUnitsStart-=j; - UnitsStart -= i; - return(UnitsStart); - } - return(NULL); - } - } while ( !FreeList[i].next ); - void* RetVal=RemoveNode(i); - SplitBlock(RetVal,i,indx); - return RetVal; -} - - -inline void* SubAllocator::AllocUnits(int NU) -{ - int indx=Units2Indx[NU-1]; - if ( FreeList[indx].next ) - return RemoveNode(indx); - void* RetVal=LoUnit; - LoUnit += U2B(Indx2Units[indx]); - if (LoUnit <= HiUnit) - return RetVal; - LoUnit -= U2B(Indx2Units[indx]); - return AllocUnitsRare(indx); -} - - -void* SubAllocator::AllocContext() -{ - if (HiUnit != LoUnit) - return (HiUnit -= UNIT_SIZE); - if ( FreeList->next ) - return RemoveNode(0); - return AllocUnitsRare(0); -} - - -void* SubAllocator::ExpandUnits(void* OldPtr,int OldNU) -{ - int i0=Units2Indx[OldNU-1], i1=Units2Indx[OldNU-1+1]; - if (i0 == i1) - return OldPtr; - void* ptr=AllocUnits(OldNU+1); - if ( ptr ) - { - memcpy(ptr,OldPtr,U2B(OldNU)); - InsertNode(OldPtr,i0); - } - return ptr; -} - - -void* SubAllocator::ShrinkUnits(void* OldPtr,int OldNU,int NewNU) -{ - int i0=Units2Indx[OldNU-1], i1=Units2Indx[NewNU-1]; - if (i0 == i1) - return OldPtr; - if ( FreeList[i1].next ) - { - void* ptr=RemoveNode(i1); - memcpy(ptr,OldPtr,U2B(NewNU)); - InsertNode(OldPtr,i0); - return ptr; - } - else - { - SplitBlock(OldPtr,i0,i1); - return OldPtr; - } -} - - -void SubAllocator::FreeUnits(void* ptr,int OldNU) -{ - InsertNode(ptr,Units2Indx[OldNU-1]); -} -#endif diff --git a/snesreader/unrar/suballoc.hpp b/snesreader/unrar/suballoc.hpp deleted file mode 100644 index 1ea9f217..00000000 --- a/snesreader/unrar/suballoc.hpp +++ /dev/null @@ -1,88 +0,0 @@ -/**************************************************************************** - * This file is part of PPMd project * - * Written and distributed to public domain by Dmitry Shkarin 1997, * - * 1999-2000 * - * Contents: interface to memory allocation routines * - ****************************************************************************/ -#if !defined(_SUBALLOC_H_) -#define _SUBALLOC_H_ - -const int N1=4, N2=4, N3=4, N4=(128+3-1*N1-2*N2-3*N3)/4; -const int N_INDEXES=N1+N2+N3+N4; - -#if defined(__GNUC__) && !defined(STRICT_ALIGNMENT_REQUIRED) -#define _PACK_ATTR __attribute__ ((packed)) -#else -#define _PACK_ATTR -#endif /* defined(__GNUC__) */ - -#ifndef STRICT_ALIGNMENT_REQUIRED -#pragma pack(1) -#endif - -struct RAR_MEM_BLK -{ - ushort Stamp, NU; - RAR_MEM_BLK* next, * prev; - void insertAt(RAR_MEM_BLK* p) - { - next=(prev=p)->next; - p->next=next->prev=this; - } - void remove() - { - prev->next=next; - next->prev=prev; - } -} _PACK_ATTR; - -#ifndef STRICT_ALIGNMENT_REQUIRED -#ifdef _AIX -#pragma pack(pop) -#else -#pragma pack() -#endif -#endif - - -struct RAR_NODE -{ - RAR_NODE* next; -}; - -class SubAllocator -{ - private: - inline void InsertNode(void* p,int indx); - inline void* RemoveNode(int indx); - inline uint U2B(int NU); - inline void SplitBlock(void* pv,int OldIndx,int NewIndx); - uint GetUsedMemory(); - inline void GlueFreeBlocks(); - void* AllocUnitsRare(int indx); - inline RAR_MEM_BLK* MBPtr(RAR_MEM_BLK *BasePtr,int Items); - - long SubAllocatorSize; - byte Indx2Units[N_INDEXES], Units2Indx[128], GlueCount; - byte *HeapStart,*LoUnit, *HiUnit; - struct RAR_NODE FreeList[N_INDEXES]; - public: - Rar_Error_Handler* ErrHandler; - SubAllocator(); - ~SubAllocator() {StopSubAllocator();} - void Clean(); - bool StartSubAllocator(int SASize); - void StopSubAllocator(); - void InitSubAllocator(); - inline void* AllocContext(); - inline void* AllocUnits(int NU); - inline void* ExpandUnits(void* ptr,int OldNU); - inline void* ShrinkUnits(void* ptr,int OldNU,int NewNU); - inline void FreeUnits(void* ptr,int OldNU); - long GetAllocatedMemory() {return(SubAllocatorSize);}; - - byte *pText, *UnitsStart,*HeapEnd,*FakeUnitsStart; -}; - - -#endif /* !defined(_SUBALLOC_H_) */ diff --git a/snesreader/unrar/technote.txt b/snesreader/unrar/technote.txt deleted file mode 100644 index 15e57593..00000000 --- a/snesreader/unrar/technote.txt +++ /dev/null @@ -1,275 +0,0 @@ - - RAR version 3.80 - Technical information - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - THE ARCHIVE FORMAT DESCRIBED BELOW IS ONLY VALID FOR VERSIONS SINCE 1.50 - - ========================================================================== - RAR archive file format - ========================================================================== - - Archive file consists of variable length blocks. The order of these -blocks may vary, but the first block must be a marker block followed by -an archive header block. - - Each block begins with the following fields: - -HEAD_CRC 2 bytes CRC of total block or block part -HEAD_TYPE 1 byte Block type -HEAD_FLAGS 2 bytes Block flags -HEAD_SIZE 2 bytes Block size -ADD_SIZE 4 bytes Optional field - added block size - - Field ADD_SIZE present only if (HEAD_FLAGS & 0x8000) != 0 - - Total block size is HEAD_SIZE if (HEAD_FLAGS & 0x8000) == 0 -and HEAD_SIZE+ADD_SIZE if the field ADD_SIZE is present - when -(HEAD_FLAGS & 0x8000) != 0. - - In each block the followings bits in HEAD_FLAGS have the same meaning: - - 0x4000 - if set, older RAR versions will ignore the block - and remove it when the archive is updated. - if clear, the block is copied to the new archive - file when the archive is updated; - - 0x8000 - if set, ADD_SIZE field is present and the full block - size is HEAD_SIZE+ADD_SIZE. - - Declared block types: - -HEAD_TYPE=0x72 marker block -HEAD_TYPE=0x73 archive header -HEAD_TYPE=0x74 file header -HEAD_TYPE=0x75 old style comment header -HEAD_TYPE=0x76 old style authenticity information -HEAD_TYPE=0x77 old style subblock -HEAD_TYPE=0x78 old style recovery record -HEAD_TYPE=0x79 old style authenticity information -HEAD_TYPE=0x7a subblock - - Comment block is actually used only within other blocks and doesn't -exist separately. - - Archive processing is made in the following manner: - -1. Read and check marker block -2. Read archive header -3. Read or skip HEAD_SIZE-sizeof(MAIN_HEAD) bytes -4. If end of archive encountered then terminate archive processing, - else read 7 bytes into fields HEAD_CRC, HEAD_TYPE, HEAD_FLAGS, - HEAD_SIZE. -5. Check HEAD_TYPE. - if HEAD_TYPE==0x74 - read file header ( first 7 bytes already read ) - read or skip HEAD_SIZE-sizeof(FILE_HEAD) bytes - if (HEAD_FLAGS & 0x100) - read or skip HIGH_PACK_SIZE*0x100000000+PACK_SIZE bytes - else - read or skip PACK_SIZE bytes - else - read corresponding HEAD_TYPE block: - read HEAD_SIZE-7 bytes - if (HEAD_FLAGS & 0x8000) - read ADD_SIZE bytes -6. go to 4. - - - ========================================================================== - Block Formats - ========================================================================== - - - Marker block ( MARK_HEAD ) - - -HEAD_CRC Always 0x6152 -2 bytes - -HEAD_TYPE Header type: 0x72 -1 byte - -HEAD_FLAGS Always 0x1a21 -2 bytes - -HEAD_SIZE Block size = 0x0007 -2 bytes - - The marker block is actually considered as a fixed byte -sequence: 0x52 0x61 0x72 0x21 0x1a 0x07 0x00 - - - - Archive header ( MAIN_HEAD ) - - -HEAD_CRC CRC of fields HEAD_TYPE to RESERVED2 -2 bytes - -HEAD_TYPE Header type: 0x73 -1 byte - -HEAD_FLAGS Bit flags: -2 bytes - 0x0001 - Volume attribute (archive volume) - 0x0002 - Archive comment present - RAR 3.x uses the separate comment block - and does not set this flag. - - 0x0004 - Archive lock attribute - 0x0008 - Solid attribute (solid archive) - 0x0010 - New volume naming scheme ('volname.partN.rar') - 0x0020 - Authenticity information present - RAR 3.x does not set this flag. - - 0x0040 - Recovery record present - 0x0080 - Block headers are encrypted - 0x0100 - First volume (set only by RAR 3.0 and later) - - other bits in HEAD_FLAGS are reserved for - internal use - -HEAD_SIZE Archive header total size including archive comments -2 bytes - -RESERVED1 Reserved -2 bytes - -RESERVED2 Reserved -4 bytes - - - - File header (File in archive) - - -HEAD_CRC CRC of fields from HEAD_TYPE to FILEATTR -2 bytes and file name - -HEAD_TYPE Header type: 0x74 -1 byte - -HEAD_FLAGS Bit flags: -2 bytes - 0x01 - file continued from previous volume - 0x02 - file continued in next volume - 0x04 - file encrypted with password - - 0x08 - file comment present - RAR 3.x uses the separate comment block - and does not set this flag. - - 0x10 - information from previous files is used (solid flag) - (for RAR 2.0 and later) - - bits 7 6 5 (for RAR 2.0 and later) - - 0 0 0 - dictionary size 64 KB - 0 0 1 - dictionary size 128 KB - 0 1 0 - dictionary size 256 KB - 0 1 1 - dictionary size 512 KB - 1 0 0 - dictionary size 1024 KB - 1 0 1 - dictionary size 2048 KB - 1 1 0 - dictionary size 4096 KB - 1 1 1 - file is directory - - 0x100 - HIGH_PACK_SIZE and HIGH_UNP_SIZE fields - are present. These fields are used to archive - only very large files (larger than 2Gb), - for smaller files these fields are absent. - - 0x200 - FILE_NAME contains both usual and encoded - Unicode name separated by zero. In this case - NAME_SIZE field is equal to the length - of usual name plus encoded Unicode name plus 1. - - If this flag is present, but FILE_NAME does not - contain zero bytes, it means that file name - is encoded using UTF-8. - - 0x400 - the header contains additional 8 bytes - after the file name, which are required to - increase encryption security (so called 'salt'). - - 0x800 - Version flag. It is an old file version, - a version number is appended to file name as ';n'. - - 0x1000 - Extended time field present. - - 0x8000 - this bit always is set, so the complete - block size is HEAD_SIZE + PACK_SIZE - (and plus HIGH_PACK_SIZE, if bit 0x100 is set) - -HEAD_SIZE File header full size including file name and comments -2 bytes - -PACK_SIZE Compressed file size -4 bytes - -UNP_SIZE Uncompressed file size -4 bytes - -HOST_OS Operating system used for archiving -1 byte 0 - MS DOS - 1 - OS/2 - 2 - Win32 - 3 - Unix - 4 - Mac OS - 5 - BeOS - -FILE_CRC File CRC -4 bytes - -FTIME Date and time in standard MS DOS format -4 bytes - -UNP_VER RAR version needed to extract file -1 byte - Version number is encoded as - 10 * Major version + minor version. - -METHOD Packing method -1 byte - 0x30 - storing - 0x31 - fastest compression - 0x32 - fast compression - 0x33 - normal compression - 0x34 - good compression - 0x35 - best compression - -NAME_SIZE File name size -2 bytes - -ATTR File attributes -4 bytes - -HIGH_PACK_SIZE High 4 bytes of 64 bit value of compressed file size. -4 bytes Optional value, presents only if bit 0x100 in HEAD_FLAGS - is set. - -HIGH_UNP_SIZE High 4 bytes of 64 bit value of uncompressed file size. -4 bytes Optional value, presents only if bit 0x100 in HEAD_FLAGS - is set. - -FILE_NAME File name - string of NAME_SIZE bytes size - -SALT present if (HEAD_FLAGS & 0x400) != 0 -8 bytes - -EXT_TIME present if (HEAD_FLAGS & 0x1000) != 0 -variable size - -other new fields may appear here. - - - ========================================================================== - Application notes - ========================================================================== - - 1. To process an SFX archive you need to skip the SFX module searching -for the marker block in the archive. There is no marker block sequence (0x52 -0x61 0x72 0x21 0x1a 0x07 0x00) in the SFX module itself. - - 2. The CRC is calculated using the standard polynomial 0xEDB88320. In -case the size of the CRC is less than 4 bytes, only the low order bytes -are used. diff --git a/snesreader/unrar/unicode.cpp b/snesreader/unrar/unicode.cpp deleted file mode 100644 index 3853752c..00000000 --- a/snesreader/unrar/unicode.cpp +++ /dev/null @@ -1,106 +0,0 @@ -#include "rar.hpp" - -#include "unicode.hpp" - -bool WideToChar(const wchar *Src,char *Dest,int DestSize) -{ - bool RetCode=true; -#ifdef _WIN_32 - if (WideCharToMultiByte(CP_ACP,0,Src,-1,Dest,DestSize,NULL,NULL)==0) - RetCode=false; -#else -#ifdef _APPLE - WideToUtf(Src,Dest,DestSize); -#else -#ifdef MBFUNCTIONS - - size_t ResultingSize=wcstombs(Dest,Src,DestSize); - if (ResultingSize==(size_t)-1) - RetCode=false; - if (ResultingSize==0 && *Src!=0) - RetCode=false; - - if ((!RetCode || *Dest==0 && *Src!=0) && DestSize>NM && strlenw(Src)>5)==6) - { - if ((*Src&0xc0)!=0x80) - break; - d=((c&0x1f)<<6)|(*Src&0x3f); - Src++; - } - else - if ((c>>4)==14) - { - if ((Src[0]&0xc0)!=0x80 || (Src[1]&0xc0)!=0x80) - break; - d=((c&0xf)<<12)|((Src[0]&0x3f)<<6)|(Src[1]&0x3f); - Src+=2; - } - else - if ((c>>3)==30) - { - if ((Src[0]&0xc0)!=0x80 || (Src[1]&0xc0)!=0x80 || (Src[2]&0xc0)!=0x80) - break; - d=((c&7)<<18)|((Src[0]&0x3f)<<12)|((Src[1]&0x3f)<<6)|(Src[2]&0x3f); - Src+=3; - } - else - break; - if (--DestSize<0) - break; - if (d>0xffff) - { - if (--DestSize<0 || d>0x10ffff) - break; - *(Dest++)=((d-0x10000)>>10)+0xd800; - *(Dest++)=(d&0x3ff)+0xdc00; - } - else - *(Dest++)=d; - } - *Dest=0; -} - - -// strfn.cpp -void ExtToInt(const char *Src,char *Dest) -{ -#if defined(_WIN_32) - CharToOem(Src,Dest); -#else - if (Dest!=Src) - strcpy(Dest,Src); -#endif -} diff --git a/snesreader/unrar/unicode.hpp b/snesreader/unrar/unicode.hpp deleted file mode 100644 index 2ed90e6a..00000000 --- a/snesreader/unrar/unicode.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef _RAR_UNICODE_ -#define _RAR_UNICODE_ - -bool WideToChar(const wchar *Src,char *Dest,int DestSize=0x1000000); -void UtfToWide(const char *Src,wchar *Dest,int DestSize); - -// strfn.cpp -void ExtToInt(const char *Src,char *Dest); - -#endif diff --git a/snesreader/unrar/unpack.cpp b/snesreader/unrar/unpack.cpp deleted file mode 100644 index 3d9bcf84..00000000 --- a/snesreader/unrar/unpack.cpp +++ /dev/null @@ -1,1065 +0,0 @@ -#include "rar.hpp" - -#include "coder.cpp" -#include "suballoc.cpp" -#include "model.cpp" -#ifndef SFX_MODULE -#include "unpack15.cpp" -#include "unpack20.cpp" -#endif - -Unpack::Unpack(ComprDataIO *DataIO) - : VMCode( DataIO ), Filters( DataIO ), PrgStack( DataIO ), OldFilterLengths( DataIO ), ErrHandler( *DataIO ) -{ - PPM.SubAlloc.ErrHandler = DataIO; - LastStackFilter = NULL; - UnpIO=DataIO; - Window=NULL; - ExternalWindow=false; - UnpAllBuf=false; - UnpSomeRead=false; -} - - -Unpack::~Unpack() -{ - if (Window!=NULL && !ExternalWindow) - rarfree( Window ); - InitFilters(); -} - - -void Unpack::Init(byte *Window) -{ - if (Window==NULL) - { - Unpack::Window = (byte*) rarmalloc( MAXWINSIZE ); - if (Unpack::Window==NULL) - ErrHandler.MemoryError(); - } - else - { - Unpack::Window=Window; - ExternalWindow=true; - } - UnpInitData(false); - BitInput::handle_mem_error( ErrHandler ); - Inp.handle_mem_error( ErrHandler ); - - // Only check BitInput, as VM's memory isn't allocated yet - VM.BitInput::handle_mem_error( ErrHandler ); - -#ifndef SFX_MODULE - // RAR 1.5 decompression initialization - OldUnpInitData(false); - InitHuff(); -#endif -} - - -void Unpack::DoUnpack(int Method,bool Solid) -{ - switch(Method) - { -#ifndef SFX_MODULE - case 15: // rar 1.5 compression - Unpack15(Solid); - break; - case 20: // rar 2.x compression - case 26: // files larger than 2GB - Unpack20(Solid); - break; -#endif - case 29: // rar 3.x compression - case 36: // alternative hash - Unpack29(Solid); - break; - } -} - - -inline void Unpack::InsertOldDist(unsigned int Distance) -{ - OldDist[3]=OldDist[2]; - OldDist[2]=OldDist[1]; - OldDist[1]=OldDist[0]; - OldDist[0]=Distance; -} - - -inline void Unpack::InsertLastMatch(unsigned int Length,unsigned int Distance) -{ - LastDist=Distance; - LastLength=Length; -} - - -// These optimizations give 22% speedup on x86, 44% speedup on PowerPC -void Unpack::CopyString(unsigned int Length,unsigned int Distance) -{ - unsigned UnpPtr = this->UnpPtr; // cache in register - byte* const Window = this->Window; // cache in register - - unsigned int DestPtr=UnpPtr-Distance; - if (UnpPtrUnpPtr += Length; - if ( Distance < Length ) // can't use memcpy when source and dest overlap - { - // Length always >= 1 - do - { - Window[UnpPtr++]=Window[DestPtr++]; - } - while (--Length>0) - ; - } - else - { - memcpy( &Window[UnpPtr], &Window[DestPtr], Length ); - } - } - else - { - while (Length--) - { - Window[UnpPtr]=Window[DestPtr++ & MAXWINMASK]; - UnpPtr=(UnpPtr+1) & MAXWINMASK; - } - - this->UnpPtr = UnpPtr; - } -} - - -int Unpack::DecodeNumber(struct Decode *Dec) -{ - unsigned int Bits; - unsigned int BitField=getbits() & 0xfffe; - if (BitFieldDecodeLen[8]) - if (BitFieldDecodeLen[4]) - if (BitFieldDecodeLen[2]) - if (BitFieldDecodeLen[1]) - Bits=1; - else - Bits=2; - else - if (BitFieldDecodeLen[3]) - Bits=3; - else - Bits=4; - else - if (BitFieldDecodeLen[6]) - if (BitFieldDecodeLen[5]) - Bits=5; - else - Bits=6; - else - if (BitFieldDecodeLen[7]) - Bits=7; - else - Bits=8; - else - if (BitFieldDecodeLen[12]) - if (BitFieldDecodeLen[10]) - if (BitFieldDecodeLen[9]) - Bits=9; - else - Bits=10; - else - if (BitFieldDecodeLen[11]) - Bits=11; - else - Bits=12; - else - if (BitFieldDecodeLen[14]) - if (BitFieldDecodeLen[13]) - Bits=13; - else - Bits=14; - else - Bits=15; - - unsigned int N=Dec->DecodePos[Bits]+((BitField-Dec->DecodeLen[Bits-1])>>(16-Bits)); - if (N>=Dec->MaxNum) - N=0; - // do after reading values, to allow better instruction scheduling - addbits(Bits); - return(Dec->DecodeNum[N]); -} - -const -static unsigned char LDecode[]={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}; -const -static unsigned char LBits[]= {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}; -static int DDecode[DC]; -static byte DBits[DC]; -const -static int DBitLengthCounts[]= {4,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,14,0,12}; -const -static unsigned char SDDecode[]={0,4,8,16,32,64,128,192}; -const -static unsigned char SDBits[]= {2,2,3, 4, 5, 6, 6, 6}; - -void Unpack::init_tables() -{ - if (DDecode[1]==0) - { - int Dist=0,BitLength=0,Slot=0; - for (int I=0;IReadBorder) - { - if (!UnpReadBuf()) - break; - } - if (((WrPtr-UnpPtr) & MAXWINMASK)<260 && WrPtr!=UnpPtr) - { - UnpWriteBuf(); - if (WrittenFileSize>DestUnpSize) - return; - if (Suspended) - { - FileExtracted=false; - return; - } - } - if (UnpBlockType==BLOCK_PPM) - { - int Ch=PPM.DecodeChar(); - if (Ch==-1) - { - PPM.CleanUp(); - - // turn off PPM compression mode in case of error, so UnRAR will - // call PPM.DecodeInit in case it needs to turn it on back later. - UnpBlockType=BLOCK_LZ; - break; - } - if (Ch==PPMEscChar) - { - int NextCh=PPM.DecodeChar(); - if (NextCh==0) - { - if (!ReadTables()) - break; - continue; - } - if (NextCh==2 || NextCh==-1) - break; - if (NextCh==3) - { - if (!ReadVMCodePPM()) - break; - continue; - } - if (NextCh==4) - { - unsigned int Distance=0,Length; - Length = 0; // avoids warning - bool Failed=false; - for (int I=0;I<4 && !Failed;I++) - { - int Ch=PPM.DecodeChar(); - if (Ch==-1) - Failed=true; - else - if (I==3) - Length=(byte)Ch; - else - Distance=(Distance<<8)+(byte)Ch; - } - if (Failed) - break; - -#ifdef _MSC_VER - // avoid a warning about uninitialized 'Length' variable - #pragma warning( disable : 4701 ) -#endif - CopyString(Length+32,Distance+2); - continue; - } - if (NextCh==5) - { - int Length=PPM.DecodeChar(); - if (Length==-1) - break; - CopyString(Length+4,1); - continue; - } - } - Window[UnpPtr++]=Ch; - continue; - } - - int Number=DecodeNumber((struct Decode *)&LD); - if (Number<256) - { - Window[UnpPtr++]=(byte)Number; - continue; - } - if (Number>=271) - { - int Length=LDecode[Number-=271]+3; - if ((Bits=LBits[Number])>0) - { - Length+=getbits()>>(16-Bits); - addbits(Bits); - } - - int DistNumber=DecodeNumber((struct Decode *)&DD); - unsigned int Distance=DDecode[DistNumber]+1; - if ((Bits=DBits[DistNumber])>0) - { - if (DistNumber>9) - { - if (Bits>4) - { - Distance+=((getbits()>>(20-Bits))<<4); - addbits(Bits-4); - } - if (LowDistRepCount>0) - { - LowDistRepCount--; - Distance+=PrevLowDist; - } - else - { - int LowDist=DecodeNumber((struct Decode *)&LDD); - if (LowDist==16) - { - LowDistRepCount=LOW_DIST_REP_COUNT-1; - Distance+=PrevLowDist; - } - else - { - Distance+=LowDist; - PrevLowDist=LowDist; - } - } - } - else - { - Distance+=getbits()>>(16-Bits); - addbits(Bits); - } - } - - if (Distance>=0x2000) - { - Length++; - if (Distance>=0x40000L) - Length++; - } - - InsertOldDist(Distance); - InsertLastMatch(Length,Distance); - CopyString(Length,Distance); - continue; - } - if (Number==256) - { - if (!ReadEndOfBlock()) - break; - continue; - } - if (Number==257) - { - if (!ReadVMCode()) - break; - continue; - } - if (Number==258) - { - if (LastLength!=0) - CopyString(LastLength,LastDist); - continue; - } - if (Number<263) - { - int DistNum=Number-259; - unsigned int Distance=OldDist[DistNum]; - for (int I=DistNum;I>0;I--) - OldDist[I]=OldDist[I-1]; - OldDist[0]=Distance; - - int LengthNumber=DecodeNumber((struct Decode *)&RD); - int Length=LDecode[LengthNumber]+2; - if ((Bits=LBits[LengthNumber])>0) - { - Length+=getbits()>>(16-Bits); - addbits(Bits); - } - InsertLastMatch(Length,Distance); - CopyString(Length,Distance); - continue; - } - if (Number<272) - { - unsigned int Distance=SDDecode[Number-=263]+1; - if ((Bits=SDBits[Number])>0) - { - Distance+=getbits()>>(16-Bits); - addbits(Bits); - } - InsertOldDist(Distance); - InsertLastMatch(2,Distance); - CopyString(2,Distance); - continue; - } - } - UnpWriteBuf(); -} - - -bool Unpack::ReadEndOfBlock() -{ - unsigned int BitField=getbits(); - bool NewTable,NewFile=false; - if (BitField & 0x8000) - { - NewTable=true; - addbits(1); - } - else - { - NewFile=true; - NewTable=(BitField & 0x4000); - addbits(2); - } - TablesRead=!NewTable; - return !(NewFile || NewTable && !ReadTables()); -} - - -bool Unpack::ReadVMCode() -{ - unsigned int FirstByte=getbits()>>8; - addbits(8); - int Length=(FirstByte & 7)+1; - if (Length==7) - { - Length=(getbits()>>8)+7; - addbits(8); - } - else - if (Length==8) - { - Length=getbits(); - addbits(16); - } - VMCode.Alloc( Length ); - for (int I=0;I=ReadTop-1 && !UnpReadBuf() && I>8; - addbits(8); - } - return(AddVMCode(FirstByte,&VMCode[0],Length)); -} - - -bool Unpack::ReadVMCodePPM() -{ - unsigned int FirstByte=PPM.DecodeChar(); - if ((int)FirstByte==-1) - return(false); - int Length=(FirstByte & 7)+1; - if (Length==7) - { - int B1=PPM.DecodeChar(); - if (B1==-1) - return(false); - Length=B1+7; - } - else - if (Length==8) - { - int B1=PPM.DecodeChar(); - if (B1==-1) - return(false); - int B2=PPM.DecodeChar(); - if (B2==-1) - return(false); - Length=B1*256+B2; - } - VMCode.Alloc( Length ); - for (int I=0;IFilters.Size() || FiltPos>OldFilterLengths.Size()) - return(false); - LastFilter=FiltPos; - bool NewFilter=(FiltPos==Filters.Size()); - - delete LastStackFilter; - LastStackFilter = NULL; - UnpackFilter *StackFilter=new UnpackFilter(&ErrHandler); - LastStackFilter = StackFilter; - if ( !StackFilter ) - ErrHandler.MemoryError(); - - UnpackFilter *Filter; - if (NewFilter) // new filter code, never used before since VM reset - { - // too many different filters, corrupt archive - if (FiltPos>1024) - return(false); - - Filters.Add(1); - Filters[Filters.Size()-1]=Filter=new UnpackFilter(&ErrHandler); - if ( !Filter ) - ErrHandler.MemoryError(); - StackFilter->ParentFilter=Filters.Size()-1; - OldFilterLengths.Add(1); - Filter->ExecCount=0; - } - else // filter was used in the past - { - Filter=Filters[FiltPos]; - StackFilter->ParentFilter=FiltPos; - Filter->ExecCount++; - } - - int EmptyCount=0; - { - for (int I=0;I0) - PrgStack[I]=NULL; - } - } - if (EmptyCount==0) - { - PrgStack.Add(1); - EmptyCount=1; - } - int StackPos=PrgStack.Size()-EmptyCount; - PrgStack[StackPos]=StackFilter; - LastStackFilter = NULL; - StackFilter->ExecCount=Filter->ExecCount; - - uint BlockStart=RarVM::ReadData(Inp); - if (FirstByte & 0x40) - BlockStart+=258; - StackFilter->BlockStart=(BlockStart+UnpPtr)&MAXWINMASK; - if (FirstByte & 0x20) - StackFilter->BlockLength=RarVM::ReadData(Inp); - else - StackFilter->BlockLength=FiltPosNextWindow=WrPtr!=UnpPtr && ((WrPtr-UnpPtr)&MAXWINMASK)<=BlockStart; - -// DebugLog("\nNextWindow: UnpPtr=%08x WrPtr=%08x BlockStart=%08x",UnpPtr,WrPtr,BlockStart); - - OldFilterLengths[FiltPos]=StackFilter->BlockLength; - - memset(StackFilter->Prg.InitR,0,sizeof(StackFilter->Prg.InitR)); - StackFilter->Prg.InitR[3]=VM_GLOBALMEMADDR; - StackFilter->Prg.InitR[4]=StackFilter->BlockLength; - StackFilter->Prg.InitR[5]=StackFilter->ExecCount; - - if (FirstByte & 0x10) // set registers to optional parameters if any - { - unsigned int InitMask=Inp.fgetbits()>>9; - Inp.faddbits(7); - for (int I=0;I<7;I++) - if (InitMask & (1<Prg.InitR[I]=RarVM::ReadData(Inp); - } - - if (NewFilter) - { - uint VMCodeSize=RarVM::ReadData(Inp); - if (VMCodeSize>=0x10000 || VMCodeSize==0) - return(false); - VMCode.Alloc( VMCodeSize ); - for (int I=0;I>8; - Inp.faddbits(8); - } - VM.Prepare(&VMCode[0],VMCodeSize,&Filter->Prg); - VMCode.Reset(); - } - StackFilter->Prg.AltCmd=&Filter->Prg.Cmd[0]; - StackFilter->Prg.CmdCount=Filter->Prg.CmdCount; - - int StaticDataSize=Filter->Prg.StaticData.Size(); - if (StaticDataSize>0 && StaticDataSizePrg.StaticData.Add(StaticDataSize); - memcpy(&StackFilter->Prg.StaticData[0],&Filter->Prg.StaticData[0],StaticDataSize); - } - - if (StackFilter->Prg.GlobalData.Size()Prg.GlobalData.Reset(); - StackFilter->Prg.GlobalData.Add(VM_FIXEDGLOBALSIZE); - } - byte *GlobalData=&StackFilter->Prg.GlobalData[0]; - for (int I=0;I<7;I++) - VM.SetLowEndianValue((uint *)&GlobalData[I*4],StackFilter->Prg.InitR[I]); - VM.SetLowEndianValue((uint *)&GlobalData[0x1c],StackFilter->BlockLength); - VM.SetLowEndianValue((uint *)&GlobalData[0x20],0); - VM.SetLowEndianValue((uint *)&GlobalData[0x2c],StackFilter->ExecCount); - memset(&GlobalData[0x30],0,16); - - if (FirstByte & 8) // put data block passed as parameter if any - { - if (Inp.Overflow(3)) - return(false); - uint DataSize=RarVM::ReadData(Inp); - if (DataSize>VM_GLOBALMEMSIZE-VM_FIXEDGLOBALSIZE) - return(false); - unsigned int CurSize=StackFilter->Prg.GlobalData.Size(); - if (CurSizePrg.GlobalData.Add(DataSize+VM_FIXEDGLOBALSIZE-CurSize); - byte *GlobalData=&StackFilter->Prg.GlobalData[VM_FIXEDGLOBALSIZE]; - for (int I=0;I>8; - Inp.faddbits(8); - } - } - Inp.InitBitInput(); - return(true); -} - - -bool Unpack::UnpReadBuf() -{ - int DataSize=ReadTop-InAddr; - if (DataSize<0) - return(false); - if (InAddr>BitInput::MAX_SIZE/2) - { - if (DataSize>0) - memmove(InBuf,InBuf+InAddr,DataSize); - InAddr=0; - ReadTop=DataSize; - } - else - DataSize=ReadTop; - int ReadCode=UnpIO->UnpRead(InBuf+DataSize,(BitInput::MAX_SIZE-DataSize)&~0xf); - if (ReadCode>0) - ReadTop+=ReadCode; - ReadBorder=ReadTop-30; - return(ReadCode!=-1); -} - - -void Unpack::UnpWriteBuf() -{ - unsigned int WrittenBorder=WrPtr; - unsigned int WriteSize=(UnpPtr-WrittenBorder)&MAXWINMASK; - for (int I=0;INextWindow) - { - flt->NextWindow=false; - continue; - } - unsigned int BlockStart=flt->BlockStart; - unsigned int BlockLength=flt->BlockLength; - if (((BlockStart-WrittenBorder)&MAXWINMASK)ParentFilter]->Prg; - VM_PreparedProgram *Prg=&flt->Prg; - - if (ParentPrg->GlobalData.Size()>VM_FIXEDGLOBALSIZE) - { - // copy global data from previous script execution if any - Prg->GlobalData.Alloc(ParentPrg->GlobalData.Size()); - memcpy(&Prg->GlobalData[VM_FIXEDGLOBALSIZE],&ParentPrg->GlobalData[VM_FIXEDGLOBALSIZE],ParentPrg->GlobalData.Size()-VM_FIXEDGLOBALSIZE); - } - - ExecuteCode(Prg); - - if (Prg->GlobalData.Size()>VM_FIXEDGLOBALSIZE) - { - // save global data for next script execution - if (ParentPrg->GlobalData.Size()GlobalData.Size()) - ParentPrg->GlobalData.Alloc(Prg->GlobalData.Size()); - memcpy(&ParentPrg->GlobalData[VM_FIXEDGLOBALSIZE],&Prg->GlobalData[VM_FIXEDGLOBALSIZE],Prg->GlobalData.Size()-VM_FIXEDGLOBALSIZE); - } - else - ParentPrg->GlobalData.Reset(); - - byte *FilteredData=Prg->FilteredData; - unsigned int FilteredDataSize=Prg->FilteredDataSize; - - delete PrgStack[I]; - PrgStack[I]=NULL; - while (I+1BlockStart!=BlockStart || - NextFilter->BlockLength!=FilteredDataSize || NextFilter->NextWindow) - break; - - // apply several filters to same data block - - VM.SetMemory(0,FilteredData,FilteredDataSize); - - VM_PreparedProgram *ParentPrg=&Filters[NextFilter->ParentFilter]->Prg; - VM_PreparedProgram *NextPrg=&NextFilter->Prg; - - if (ParentPrg->GlobalData.Size()>VM_FIXEDGLOBALSIZE) - { - // copy global data from previous script execution if any - NextPrg->GlobalData.Alloc(ParentPrg->GlobalData.Size()); - memcpy(&NextPrg->GlobalData[VM_FIXEDGLOBALSIZE],&ParentPrg->GlobalData[VM_FIXEDGLOBALSIZE],ParentPrg->GlobalData.Size()-VM_FIXEDGLOBALSIZE); - } - - ExecuteCode(NextPrg); - - if (NextPrg->GlobalData.Size()>VM_FIXEDGLOBALSIZE) - { - // save global data for next script execution - if (ParentPrg->GlobalData.Size()GlobalData.Size()) - ParentPrg->GlobalData.Alloc(NextPrg->GlobalData.Size()); - memcpy(&ParentPrg->GlobalData[VM_FIXEDGLOBALSIZE],&NextPrg->GlobalData[VM_FIXEDGLOBALSIZE],NextPrg->GlobalData.Size()-VM_FIXEDGLOBALSIZE); - } - else - ParentPrg->GlobalData.Reset(); - - FilteredData=NextPrg->FilteredData; - FilteredDataSize=NextPrg->FilteredDataSize; - I++; - delete PrgStack[I]; - PrgStack[I]=NULL; - } - UnpIO->UnpWrite(FilteredData,FilteredDataSize); - UnpSomeRead=true; - WrittenFileSize+=FilteredDataSize; - WrittenBorder=BlockEnd; - WriteSize=(UnpPtr-WrittenBorder)&MAXWINMASK; - } - else - { - for (int J=I;JNextWindow) - flt->NextWindow=false; - } - WrPtr=WrittenBorder; - return; - } - } - } - - UnpWriteArea(WrittenBorder,UnpPtr); - WrPtr=UnpPtr; -} - - -void Unpack::ExecuteCode(VM_PreparedProgram *Prg) -{ - if (Prg->GlobalData.Size()>0) - { - Prg->InitR[6]=int64to32(WrittenFileSize); - VM.SetLowEndianValue((uint *)&Prg->GlobalData[0x24],int64to32(WrittenFileSize)); - VM.SetLowEndianValue((uint *)&Prg->GlobalData[0x28],int64to32(WrittenFileSize>>31>>1)); - VM.Execute(Prg); - } -} - - -void Unpack::UnpWriteArea(unsigned int StartPtr,unsigned int EndPtr) -{ - if (EndPtr!=StartPtr) - UnpSomeRead=true; - if (EndPtr=DestUnpSize) - return; - int WriteSize=Size; - Int64 LeftToWrite=DestUnpSize-WrittenFileSize; - if (WriteSize>LeftToWrite) - WriteSize=int64to32(LeftToWrite); - UnpIO->UnpWrite(Data,WriteSize); - WrittenFileSize+=Size; -} - - -bool Unpack::ReadTables() -{ - byte BitLength[BC]; - unsigned char Table[HUFF_TABLE_SIZE]; - if (InAddr>ReadTop-25) - if (!UnpReadBuf()) - return(false); - faddbits((8-InBit)&7); - unsigned int BitField=fgetbits(); - if (BitField & 0x8000) - { - UnpBlockType=BLOCK_PPM; - return(PPM.DecodeInit(this,PPMEscChar)); - } - UnpBlockType=BLOCK_LZ; - - PrevLowDist=0; - LowDistRepCount=0; - - if (!(BitField & 0x4000)) - memset(UnpOldTable,0,sizeof(UnpOldTable)); - faddbits(2); - { - for (int I=0;I> 12); - faddbits(4); - if (Length==15) - { - int ZeroCount=(byte)(fgetbits() >> 12); - faddbits(4); - if (ZeroCount==0) - BitLength[I]=15; - else - { - ZeroCount+=2; - while (ZeroCount-- > 0 && IReadTop-5) - if (!UnpReadBuf()) - return(false); - int Number=DecodeNumber((struct Decode *)&BD); - if (Number<16) - { - Table[I]=(Number+UnpOldTable[I]) & 0xf; - I++; - } - else - if (Number<18) - { - int N; - if (Number==16) - { - N=(fgetbits() >> 13)+3; - faddbits(3); - } - else - { - N=(fgetbits() >> 9)+11; - faddbits(7); - } - while (N-- > 0 && I> 13)+3; - faddbits(3); - } - else - { - N=(fgetbits() >> 9)+11; - faddbits(7); - } - while (N-- > 0 && IReadTop) - return(false); - MakeDecodeTables(&Table[0],(struct Decode *)&LD,NC); - MakeDecodeTables(&Table[NC],(struct Decode *)&DD,DC); - MakeDecodeTables(&Table[NC+DC],(struct Decode *)&LDD,LDC); - MakeDecodeTables(&Table[NC+DC+LDC],(struct Decode *)&RD,RC); - memcpy(UnpOldTable,Table,sizeof(UnpOldTable)); - return(true); -} - - -void Unpack::UnpInitData(int Solid) -{ - if (!Solid) - { - TablesRead=false; - memset(OldDist,0,sizeof(OldDist)); - OldDistPtr=0; - LastDist=LastLength=0; -// memset(Window,0,MAXWINSIZE); - memset(UnpOldTable,0,sizeof(UnpOldTable)); - memset(&LD,0,sizeof(LD)); - memset(&DD,0,sizeof(DD)); - memset(&LDD,0,sizeof(LDD)); - memset(&RD,0,sizeof(RD)); - memset(&BD,0,sizeof(BD)); - UnpPtr=WrPtr=0; - PPMEscChar=2; - UnpBlockType=BLOCK_LZ; - - InitFilters(); - } - InitBitInput(); - WrittenFileSize=0; - ReadTop=0; - ReadBorder=0; -#ifndef SFX_MODULE - UnpInitData20(Solid); -#endif -} - - -void Unpack::InitFilters() -{ - delete LastStackFilter; - LastStackFilter = NULL; - - OldFilterLengths.Reset(); - LastFilter=0; - { - for (int I=0;IDecodeNum,0,Size*sizeof(*Dec->DecodeNum)); - for (I=0;IDecodePos[0]=Dec->DecodeLen[0]=0,N=0,I=1;I<16;I++) - { - N=2*(N+LenCount[I]); - M=N<<(15-I); - if (M>0xFFFF) - M=0xFFFF; - Dec->DecodeLen[I]=(unsigned int)M; - TmpPos[I]=Dec->DecodePos[I]=Dec->DecodePos[I-1]+LenCount[I-1]; - } - - for (I=0;IDecodeNum[TmpPos[LenTab[I] & 0xF]++]=I; - Dec->MaxNum=Size; -} diff --git a/snesreader/unrar/unpack.hpp b/snesreader/unrar/unpack.hpp deleted file mode 100644 index 918fdb6c..00000000 --- a/snesreader/unrar/unpack.hpp +++ /dev/null @@ -1,227 +0,0 @@ -#ifndef _RAR_UNPACK_ -#define _RAR_UNPACK_ - -enum BLOCK_TYPES {BLOCK_LZ,BLOCK_PPM}; - -struct Decode -{ - unsigned int MaxNum; - unsigned int DecodeLen[16]; - unsigned int DecodePos[16]; - unsigned int DecodeNum[2]; -}; - -struct LitDecode -{ - unsigned int MaxNum; - unsigned int DecodeLen[16]; - unsigned int DecodePos[16]; - unsigned int DecodeNum[NC]; -}; - -struct DistDecode -{ - unsigned int MaxNum; - unsigned int DecodeLen[16]; - unsigned int DecodePos[16]; - unsigned int DecodeNum[DC]; -}; - -struct LowDistDecode -{ - unsigned int MaxNum; - unsigned int DecodeLen[16]; - unsigned int DecodePos[16]; - unsigned int DecodeNum[LDC]; -}; - -struct RepDecode -{ - unsigned int MaxNum; - unsigned int DecodeLen[16]; - unsigned int DecodePos[16]; - unsigned int DecodeNum[RC]; -}; - -struct BitDecode -{ - unsigned int MaxNum; - unsigned int DecodeLen[16]; - unsigned int DecodePos[16]; - unsigned int DecodeNum[BC]; -}; - -struct UnpackFilter - : Rar_Allocator -{ - unsigned int BlockStart; - unsigned int BlockLength; - unsigned int ExecCount; - bool NextWindow; - - // position of parent filter in Filters array used as prototype for filter - // in PrgStack array. Not defined for filters in Filters array. - unsigned int ParentFilter; - - VM_PreparedProgram Prg; - UnpackFilter( Rar_Error_Handler* eh ) : Prg( eh ) { } -}; - -/***************************** Unpack v 2.0 *********************************/ -struct MultDecode -{ - unsigned int MaxNum; - unsigned int DecodeLen[16]; - unsigned int DecodePos[16]; - unsigned int DecodeNum[MC20]; -}; - -struct AudioVariables -{ - int K1,K2,K3,K4,K5; - int D1,D2,D3,D4; - int LastDelta; - unsigned int Dif[11]; - unsigned int ByteCount; - int LastChar; -}; -/***************************** Unpack v 2.0 *********************************/ - - -// public so operator new/delete will be accessible, argh -class Unpack:public BitInput -{ -private: - friend class Pack; - - void Unpack29(bool Solid); - bool UnpReadBuf(); - void UnpWriteBuf(); - void ExecuteCode(VM_PreparedProgram *Prg); - void UnpWriteArea(unsigned int StartPtr,unsigned int EndPtr); - void UnpWriteData(byte *Data,int Size); - bool ReadTables(); - void MakeDecodeTables(unsigned char *LenTab,struct Decode *Dec,int Size); - int DecodeNumber(struct Decode *Dec); - void CopyString(); - inline void InsertOldDist(unsigned int Distance); - inline void InsertLastMatch(unsigned int Length,unsigned int Distance); - void UnpInitData(int Solid); - void CopyString(unsigned int Length,unsigned int Distance); - bool ReadEndOfBlock(); - bool ReadVMCode(); - bool ReadVMCodePPM(); - bool AddVMCode(unsigned int FirstByte,byte *Code,int CodeSize); - void InitFilters(); - - ComprDataIO *UnpIO; - ModelPPM PPM; - int PPMEscChar; - - Array VMCode; // here to avoid leaks - BitInput Inp; // here to avoid leaks - - RarVM VM; - - UnpackFilter* LastStackFilter; // avoids leak for stack-based filter - - /* Filters code, one entry per filter */ - Array Filters; - - /* Filters stack, several entrances of same filter are possible */ - Array PrgStack; - - /* lengths of preceding blocks, one length per filter. Used to reduce - size required to write block length if lengths are repeating */ - Array OldFilterLengths; - - int LastFilter; - - bool TablesRead; - struct LitDecode LD; - struct DistDecode DD; - struct LowDistDecode LDD; - struct RepDecode RD; - struct BitDecode BD; - - unsigned int OldDist[4],OldDistPtr; - unsigned int LastDist,LastLength; - - unsigned int UnpPtr,WrPtr; - - int ReadTop; - int ReadBorder; - - unsigned char UnpOldTable[HUFF_TABLE_SIZE]; - - int UnpBlockType; - - byte *Window; - bool ExternalWindow; - - - Int64 DestUnpSize; - - enum { Suspended = false }; // original source could never set to true - bool UnpAllBuf; - bool UnpSomeRead; - Int64 WrittenFileSize; - bool FileExtracted; - - int PrevLowDist,LowDistRepCount; - - /***************************** Unpack v 1.5 *********************************/ - void Unpack15(bool Solid); - void ShortLZ(); - void LongLZ(); - void HuffDecode(); - void GetFlagsBuf(); - void OldUnpInitData(int Solid); - void InitHuff(); - void CorrHuff(unsigned int *CharSet,unsigned int *NumToPlace); - void OldCopyString(unsigned int Distance,unsigned int Length); - unsigned int DecodeNum(int Num,unsigned int StartPos, - const unsigned int *DecTab,const unsigned int *PosTab); - void OldUnpWriteBuf(); - - unsigned int ChSet[256],ChSetA[256],ChSetB[256],ChSetC[256]; - unsigned int Place[256],PlaceA[256],PlaceB[256],PlaceC[256]; - unsigned int NToPl[256],NToPlB[256],NToPlC[256]; - unsigned int FlagBuf,AvrPlc,AvrPlcB,AvrLn1,AvrLn2,AvrLn3; - int Buf60,NumHuf,StMode,LCount,FlagsCnt; - unsigned int Nhfb,Nlzb,MaxDist3; - /***************************** Unpack v 1.5 *********************************/ - - /***************************** Unpack v 2.0 *********************************/ - void Unpack20(bool Solid); - struct MultDecode MD[4]; - unsigned char UnpOldTable20[MC20*4]; - int UnpAudioBlock,UnpChannels,UnpCurChannel,UnpChannelDelta; - void CopyString20(unsigned int Length,unsigned int Distance); - bool ReadTables20(); - void UnpInitData20(int Solid); - void ReadLastTables(); - byte DecodeAudio(int Delta); - struct AudioVariables AudV[4]; - /***************************** Unpack v 2.0 *********************************/ - -public: - Rar_Error_Handler& ErrHandler; - byte const* window_wrptr() const { return &Window [WrPtr & MAXWINMASK]; } - - static void init_tables(); - Unpack(ComprDataIO *DataIO); - ~Unpack(); - void Init(byte *Window=NULL); - void DoUnpack(int Method,bool Solid); - void SetDestSize(Int64 DestSize) {DestUnpSize=DestSize;FileExtracted=false;} - - unsigned int GetChar() - { - if (InAddr>BitInput::MAX_SIZE-30) - UnpReadBuf(); - return(InBuf[InAddr++]); - } -}; - -#endif diff --git a/snesreader/unrar/unpack15.cpp b/snesreader/unrar/unpack15.cpp deleted file mode 100644 index b2a63c05..00000000 --- a/snesreader/unrar/unpack15.cpp +++ /dev/null @@ -1,532 +0,0 @@ -// #included by unpack.cpp -#ifdef RAR_COMMON_HPP -#define STARTL1 2 -const -static unsigned int DecL1[]={0x8000,0xa000,0xc000,0xd000,0xe000,0xea00, - 0xee00,0xf000,0xf200,0xf200,0xffff}; -const -static unsigned int PosL1[]={0,0,0,2,3,5,7,11,16,20,24,32,32}; - -#define STARTL2 3 -const -static unsigned int DecL2[]={0xa000,0xc000,0xd000,0xe000,0xea00,0xee00, - 0xf000,0xf200,0xf240,0xffff}; -const -static unsigned int PosL2[]={0,0,0,0,5,7,9,13,18,22,26,34,36}; - -#define STARTHF0 4 -const -static unsigned int DecHf0[]={0x8000,0xc000,0xe000,0xf200,0xf200,0xf200, - 0xf200,0xf200,0xffff}; -const -static unsigned int PosHf0[]={0,0,0,0,0,8,16,24,33,33,33,33,33}; - - -#define STARTHF1 5 -const -static unsigned int DecHf1[]={0x2000,0xc000,0xe000,0xf000,0xf200,0xf200, - 0xf7e0,0xffff}; -const -static unsigned int PosHf1[]={0,0,0,0,0,0,4,44,60,76,80,80,127}; - - -#define STARTHF2 5 -const -static unsigned int DecHf2[]={0x1000,0x2400,0x8000,0xc000,0xfa00,0xffff, - 0xffff,0xffff}; -const -static unsigned int PosHf2[]={0,0,0,0,0,0,2,7,53,117,233,0,0}; - - -#define STARTHF3 6 -const -static unsigned int DecHf3[]={0x800,0x2400,0xee00,0xfe80,0xffff,0xffff, - 0xffff}; -const -static unsigned int PosHf3[]={0,0,0,0,0,0,0,2,16,218,251,0,0}; - - -#define STARTHF4 8 -const -static unsigned int DecHf4[]={0xff00,0xffff,0xffff,0xffff,0xffff,0xffff}; -const -static unsigned int PosHf4[]={0,0,0,0,0,0,0,0,0,255,0,0,0}; - - -void Unpack::Unpack15(bool Solid) -{ - if (Suspended) - UnpPtr=WrPtr; - else - { - UnpInitData(Solid); - OldUnpInitData(Solid); - UnpReadBuf(); - if (!Solid) - { - InitHuff(); - UnpPtr=0; - } - else - UnpPtr=WrPtr; - --DestUnpSize; - } - if (DestUnpSize>=0) - { - GetFlagsBuf(); - FlagsCnt=8; - } - - while (DestUnpSize>=0) - { - UnpPtr&=MAXWINMASK; - - if (InAddr>ReadTop-30 && !UnpReadBuf()) - break; - if (((WrPtr-UnpPtr) & MAXWINMASK)<270 && WrPtr!=UnpPtr) - { - OldUnpWriteBuf(); - if (Suspended) - return; - } - if (StMode) - { - HuffDecode(); - continue; - } - - if (--FlagsCnt < 0) - { - GetFlagsBuf(); - FlagsCnt=7; - } - - if (FlagBuf & 0x80) - { - FlagBuf<<=1; - if (Nlzb > Nhfb) - LongLZ(); - else - HuffDecode(); - } - else - { - FlagBuf<<=1; - if (--FlagsCnt < 0) - { - GetFlagsBuf(); - FlagsCnt=7; - } - if (FlagBuf & 0x80) - { - FlagBuf<<=1; - if (Nlzb > Nhfb) - HuffDecode(); - else - LongLZ(); - } - else - { - FlagBuf<<=1; - ShortLZ(); - } - } - } - OldUnpWriteBuf(); -} - - -void Unpack::OldUnpWriteBuf() -{ - if (UnpPtr!=WrPtr) - UnpSomeRead=true; - if (UnpPtrUnpWrite(&Window[WrPtr],-WrPtr & MAXWINMASK); - UnpIO->UnpWrite(Window,UnpPtr); - UnpAllBuf=true; - } - else - UnpIO->UnpWrite(&Window[WrPtr],UnpPtr-WrPtr); - WrPtr=UnpPtr; -} - - -#define GetShortLen1(pos) ((pos)==1 ? Buf60+3:ShortLen1[pos]) -#define GetShortLen2(pos) ((pos)==3 ? Buf60+3:ShortLen2[pos]) - -void Unpack::ShortLZ() -{ - const - static unsigned int ShortLen1[]={1,3,4,4,5,6,7,8,8,4,4,5,6,6,4,0}; - const - static unsigned int ShortXor1[]={0,0xa0,0xd0,0xe0,0xf0,0xf8,0xfc,0xfe, - 0xff,0xc0,0x80,0x90,0x98,0x9c,0xb0}; - const - static unsigned int ShortLen2[]={2,3,3,3,4,4,5,6,6,4,4,5,6,6,4,0}; - const - static unsigned int ShortXor2[]={0,0x40,0x60,0xa0,0xd0,0xe0,0xf0,0xf8, - 0xfc,0xc0,0x80,0x90,0x98,0x9c,0xb0}; - - - unsigned int Length,SaveLength; - unsigned int LastDistance; - unsigned int Distance; - int DistancePlace; - NumHuf=0; - - unsigned int BitField=fgetbits(); - if (LCount==2) - { - faddbits(1); - if (BitField >= 0x8000) - { - OldCopyString((unsigned int)LastDist,LastLength); - return; - } - BitField <<= 1; - LCount=0; - } - - BitField>>=8; - -// not thread safe, replaced by GetShortLen1 and GetShortLen2 macro -// ShortLen1[1]=ShortLen2[3]=Buf60+3; - - if (AvrLn1<37) - { - for (Length=0;;Length++) - if (((BitField^ShortXor1[Length]) & (~(0xff>>GetShortLen1(Length))))==0) - break; - faddbits(GetShortLen1(Length)); - } - else - { - for (Length=0;;Length++) - if (((BitField^ShortXor2[Length]) & (~(0xff>>GetShortLen2(Length))))==0) - break; - faddbits(GetShortLen2(Length)); - } - - if (Length >= 9) - { - if (Length == 9) - { - LCount++; - OldCopyString((unsigned int)LastDist,LastLength); - return; - } - if (Length == 14) - { - LCount=0; - Length=DecodeNum(fgetbits(),STARTL2,DecL2,PosL2)+5; - Distance=(fgetbits()>>1) | 0x8000; - faddbits(15); - LastLength=Length; - LastDist=Distance; - OldCopyString(Distance,Length); - return; - } - - LCount=0; - SaveLength=Length; - Distance=OldDist[(OldDistPtr-(Length-9)) & 3]; - Length=DecodeNum(fgetbits(),STARTL1,DecL1,PosL1)+2; - if (Length==0x101 && SaveLength==10) - { - Buf60 ^= 1; - return; - } - if (Distance > 256) - Length++; - if (Distance >= MaxDist3) - Length++; - - OldDist[OldDistPtr++]=Distance; - OldDistPtr = OldDistPtr & 3; - LastLength=Length; - LastDist=Distance; - OldCopyString(Distance,Length); - return; - } - - LCount=0; - AvrLn1 += Length; - AvrLn1 -= AvrLn1 >> 4; - - DistancePlace=DecodeNum(fgetbits(),STARTHF2,DecHf2,PosHf2) & 0xff; - Distance=ChSetA[DistancePlace]; - if (--DistancePlace != -1) - { - PlaceA[Distance]--; - LastDistance=ChSetA[DistancePlace]; - PlaceA[LastDistance]++; - ChSetA[DistancePlace+1]=LastDistance; - ChSetA[DistancePlace]=Distance; - } - Length+=2; - OldDist[OldDistPtr++] = ++Distance; - OldDistPtr = OldDistPtr & 3; - LastLength=Length; - LastDist=Distance; - OldCopyString(Distance,Length); -} - - -void Unpack::LongLZ() -{ - unsigned int Length; - unsigned int Distance; - unsigned int DistancePlace,NewDistancePlace; - unsigned int OldAvr2,OldAvr3; - - NumHuf=0; - Nlzb+=16; - if (Nlzb > 0xff) - { - Nlzb=0x90; - Nhfb >>= 1; - } - OldAvr2=AvrLn2; - - unsigned int BitField=fgetbits(); - if (AvrLn2 >= 122) - Length=DecodeNum(BitField,STARTL2,DecL2,PosL2); - else - if (AvrLn2 >= 64) - Length=DecodeNum(BitField,STARTL1,DecL1,PosL1); - else - if (BitField < 0x100) - { - Length=BitField; - faddbits(16); - } - else - { - for (Length=0;((BitField<> 5; - - BitField=fgetbits(); - if (AvrPlcB > 0x28ff) - DistancePlace=DecodeNum(BitField,STARTHF2,DecHf2,PosHf2); - else - if (AvrPlcB > 0x6ff) - DistancePlace=DecodeNum(BitField,STARTHF1,DecHf1,PosHf1); - else - DistancePlace=DecodeNum(BitField,STARTHF0,DecHf0,PosHf0); - - AvrPlcB += DistancePlace; - AvrPlcB -= AvrPlcB >> 8; - while (1) - { - Distance = ChSetB[DistancePlace & 0xff]; - NewDistancePlace = NToPlB[Distance++ & 0xff]++; - if (!(Distance & 0xff)) - CorrHuff(ChSetB,NToPlB); - else - break; - } - - ChSetB[DistancePlace]=ChSetB[NewDistancePlace]; - ChSetB[NewDistancePlace]=Distance; - - Distance=((Distance & 0xff00) | (fgetbits() >> 8)) >> 1; - faddbits(7); - - OldAvr3=AvrLn3; - if (Length!=1 && Length!=4) - if (Length==0 && Distance <= MaxDist3) - { - AvrLn3++; - AvrLn3 -= AvrLn3 >> 8; - } - else - if (AvrLn3 > 0) - AvrLn3--; - Length+=3; - if (Distance >= MaxDist3) - Length++; - if (Distance <= 256) - Length+=8; - if (OldAvr3 > 0xb0 || AvrPlc >= 0x2a00 && OldAvr2 < 0x40) - MaxDist3=0x7f00; - else - MaxDist3=0x2001; - OldDist[OldDistPtr++]=Distance; - OldDistPtr = OldDistPtr & 3; - LastLength=Length; - LastDist=Distance; - OldCopyString(Distance,Length); -} - - -void Unpack::HuffDecode() -{ - unsigned int CurByte,NewBytePlace; - unsigned int Length; - unsigned int Distance; - int BytePlace; - - unsigned int BitField=fgetbits(); - - if (AvrPlc > 0x75ff) - BytePlace=DecodeNum(BitField,STARTHF4,DecHf4,PosHf4); - else - if (AvrPlc > 0x5dff) - BytePlace=DecodeNum(BitField,STARTHF3,DecHf3,PosHf3); - else - if (AvrPlc > 0x35ff) - BytePlace=DecodeNum(BitField,STARTHF2,DecHf2,PosHf2); - else - if (AvrPlc > 0x0dff) - BytePlace=DecodeNum(BitField,STARTHF1,DecHf1,PosHf1); - else - BytePlace=DecodeNum(BitField,STARTHF0,DecHf0,PosHf0); - BytePlace&=0xff; - if (StMode) - { - if (BytePlace==0 && BitField > 0xfff) - BytePlace=0x100; - if (--BytePlace==-1) - { - BitField=fgetbits(); - faddbits(1); - if (BitField & 0x8000) - { - NumHuf=StMode=0; - return; - } - else - { - Length = (BitField & 0x4000) ? 4 : 3; - faddbits(1); - Distance=DecodeNum(fgetbits(),STARTHF2,DecHf2,PosHf2); - Distance = (Distance << 5) | (fgetbits() >> 11); - faddbits(5); - OldCopyString(Distance,Length); - return; - } - } - } - else - if (NumHuf++ >= 16 && FlagsCnt==0) - StMode=1; - AvrPlc += BytePlace; - AvrPlc -= AvrPlc >> 8; - Nhfb+=16; - if (Nhfb > 0xff) - { - Nhfb=0x90; - Nlzb >>= 1; - } - - Window[UnpPtr++]=(byte)(ChSet[BytePlace]>>8); - --DestUnpSize; - - while (1) - { - CurByte=ChSet[BytePlace]; - NewBytePlace=NToPl[CurByte++ & 0xff]++; - if ((CurByte & 0xff) > 0xa1) - CorrHuff(ChSet,NToPl); - else - break; - } - - ChSet[BytePlace]=ChSet[NewBytePlace]; - ChSet[NewBytePlace]=CurByte; -} - - -void Unpack::GetFlagsBuf() -{ - unsigned int Flags,NewFlagsPlace; - unsigned int FlagsPlace=DecodeNum(fgetbits(),STARTHF2,DecHf2,PosHf2); - - while (1) - { - Flags=ChSetC[FlagsPlace]; - FlagBuf=Flags>>8; - NewFlagsPlace=NToPlC[Flags++ & 0xff]++; - if ((Flags & 0xff) != 0) - break; - CorrHuff(ChSetC,NToPlC); - } - - ChSetC[FlagsPlace]=ChSetC[NewFlagsPlace]; - ChSetC[NewFlagsPlace]=Flags; -} - - -void Unpack::OldUnpInitData(int Solid) -{ - if (!Solid) - { - AvrPlcB=AvrLn1=AvrLn2=AvrLn3=NumHuf=Buf60=0; - AvrPlc=0x3500; - MaxDist3=0x2001; - Nhfb=Nlzb=0x80; - } - FlagsCnt=0; - FlagBuf=0; - StMode=0; - LCount=0; - ReadTop=0; -} - - -void Unpack::InitHuff() -{ - for (unsigned int I=0;I<256;I++) - { - Place[I]=PlaceA[I]=PlaceB[I]=I; - PlaceC[I]=(~I+1) & 0xff; - ChSet[I]=ChSetB[I]=I<<8; - ChSetA[I]=I; - ChSetC[I]=((~I+1) & 0xff)<<8; - } - memset(NToPl,0,sizeof(NToPl)); - memset(NToPlB,0,sizeof(NToPlB)); - memset(NToPlC,0,sizeof(NToPlC)); - CorrHuff(ChSetB,NToPlB); -} - - -void Unpack::CorrHuff(unsigned int *CharSet,unsigned int *NumToPlace) -{ - int I,J; - for (I=7;I>=0;I--) - for (J=0;J<32;J++,CharSet++) - *CharSet=(*CharSet & ~0xff) | I; - memset(NumToPlace,0,sizeof(NToPl)); - for (I=6;I>=0;I--) - NumToPlace[I]=(7-I)*32; -} - - -void Unpack::OldCopyString(unsigned int Distance,unsigned int Length) -{ - DestUnpSize-=Length; - while (Length--) - { - Window[UnpPtr]=Window[(UnpPtr-Distance) & MAXWINMASK]; - UnpPtr=(UnpPtr+1) & MAXWINMASK; - } -} - - -unsigned int Unpack::DecodeNum(int Num,unsigned int StartPos, - const unsigned int *DecTab,const unsigned int *PosTab) -{ - int I; - for (Num&=0xfff0,I=0;DecTab[I]<=Num;I++) - StartPos++; - faddbits(StartPos); - return(((Num-(I ? DecTab[I-1]:0))>>(16-StartPos))+PosTab[StartPos]); -} -#endif diff --git a/snesreader/unrar/unpack20.cpp b/snesreader/unrar/unpack20.cpp deleted file mode 100644 index 0896d1ce..00000000 --- a/snesreader/unrar/unpack20.cpp +++ /dev/null @@ -1,394 +0,0 @@ -// #included by unpack.cpp -#ifdef RAR_COMMON_HPP -#include "rar.hpp" - -// Presumably these optimizations give similar speedup as those for CopyString in unpack.cpp -void Unpack::CopyString20(unsigned int Length,unsigned int Distance) -{ - LastDist=OldDist[OldDistPtr++ & 3]=Distance; - LastLength=Length; - DestUnpSize-=Length; - - unsigned UnpPtr = this->UnpPtr; // cache in register - byte* const Window = this->Window; // cache in register - - unsigned int DestPtr=UnpPtr-Distance; - if (UnpPtrUnpPtr += Length; - if ( Distance < Length ) // can't use memcpy when source and dest overlap - { - Window[UnpPtr++]=Window[DestPtr++]; - Window[UnpPtr++]=Window[DestPtr++]; - while (Length>2) - { - Length--; - Window[UnpPtr++]=Window[DestPtr++]; - } - } - else - { - memcpy( &Window[UnpPtr], &Window[DestPtr], Length ); - } - } - else - { - while (Length--) - { - Window[UnpPtr]=Window[DestPtr++ & MAXWINMASK]; - UnpPtr=(UnpPtr+1) & MAXWINMASK; - } - this->UnpPtr = UnpPtr; - } -} - - -void Unpack::Unpack20(bool Solid) -{ - const - static unsigned char LDecode[]={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}; - const - static unsigned char LBits[]= {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}; - const - static int DDecode[]={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,32768U,49152U,65536,98304,131072,196608,262144,327680,393216,458752,524288,589824,655360,720896,786432,851968,917504,983040}; - const - static unsigned char DBits[]= {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, 14, 14, 15, 15, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16}; - const - static unsigned char SDDecode[]={0,4,8,16,32,64,128,192}; - const - static unsigned char SDBits[]= {2,2,3, 4, 5, 6, 6, 6}; - unsigned int Bits; - - if (Suspended) - UnpPtr=WrPtr; - else - { - UnpInitData(Solid); - if (!UnpReadBuf()) - return; - if (!Solid) - if (!ReadTables20()) - return; - --DestUnpSize; - } - - while (is64plus(DestUnpSize)) - { - UnpPtr&=MAXWINMASK; - - if (InAddr>ReadTop-30) - if (!UnpReadBuf()) - break; - if (((WrPtr-UnpPtr) & MAXWINMASK)<270 && WrPtr!=UnpPtr) - { - OldUnpWriteBuf(); - if (Suspended) - return; - } - if (UnpAudioBlock) - { - int AudioNumber=DecodeNumber((struct Decode *)&MD[UnpCurChannel]); - - if (AudioNumber==256) - { - if (!ReadTables20()) - break; - continue; - } - Window[UnpPtr++]=DecodeAudio(AudioNumber); - if (++UnpCurChannel==UnpChannels) - UnpCurChannel=0; - --DestUnpSize; - continue; - } - - int Number=DecodeNumber((struct Decode *)&LD); - if (Number<256) - { - Window[UnpPtr++]=(byte)Number; - --DestUnpSize; - continue; - } - if (Number>269) - { - int Length=LDecode[Number-=270]+3; - if ((Bits=LBits[Number])>0) - { - Length+=getbits()>>(16-Bits); - addbits(Bits); - } - - int DistNumber=DecodeNumber((struct Decode *)&DD); - unsigned int Distance=DDecode[DistNumber]+1; - if ((Bits=DBits[DistNumber])>0) - { - Distance+=getbits()>>(16-Bits); - addbits(Bits); - } - - if (Distance>=0x2000) - { - Length++; - if (Distance>=0x40000L) - Length++; - } - - CopyString20(Length,Distance); - continue; - } - if (Number==269) - { - if (!ReadTables20()) - break; - continue; - } - if (Number==256) - { - CopyString20(LastLength,LastDist); - continue; - } - if (Number<261) - { - unsigned int Distance=OldDist[(OldDistPtr-(Number-256)) & 3]; - int LengthNumber=DecodeNumber((struct Decode *)&RD); - int Length=LDecode[LengthNumber]+2; - if ((Bits=LBits[LengthNumber])>0) - { - Length+=getbits()>>(16-Bits); - addbits(Bits); - } - if (Distance>=0x101) - { - Length++; - if (Distance>=0x2000) - { - Length++; - if (Distance>=0x40000) - Length++; - } - } - CopyString20(Length,Distance); - continue; - } - if (Number<270) - { - unsigned int Distance=SDDecode[Number-=261]+1; - if ((Bits=SDBits[Number])>0) - { - Distance+=getbits()>>(16-Bits); - addbits(Bits); - } - CopyString20(2,Distance); - continue; - } - } - ReadLastTables(); - OldUnpWriteBuf(); -} - - -bool Unpack::ReadTables20() -{ - byte BitLength[BC20]; - unsigned char Table[MC20*4]; - int TableSize,N,I; - if (InAddr>ReadTop-25) - if (!UnpReadBuf()) - return(false); - unsigned int BitField=getbits(); - UnpAudioBlock=(BitField & 0x8000); - - if (!(BitField & 0x4000)) - memset(UnpOldTable20,0,sizeof(UnpOldTable20)); - addbits(2); - - if (UnpAudioBlock) - { - UnpChannels=((BitField>>12) & 3)+1; - if (UnpCurChannel>=UnpChannels) - UnpCurChannel=0; - addbits(2); - TableSize=MC20*UnpChannels; - } - else - TableSize=NC20+DC20+RC20; - - for (I=0;I> 12); - addbits(4); - } - MakeDecodeTables(BitLength,(struct Decode *)&BD,BC20); - I=0; - while (IReadTop-5) - if (!UnpReadBuf()) - return(false); - int Number=DecodeNumber((struct Decode *)&BD); - if (Number<16) - { - Table[I]=(Number+UnpOldTable20[I]) & 0xf; - I++; - } - else - if (Number==16) - { - N=(getbits() >> 14)+3; - addbits(2); - while (N-- > 0 && I> 13)+3; - addbits(3); - } - else - { - N=(getbits() >> 9)+11; - addbits(7); - } - while (N-- > 0 && IReadTop) - return(true); - if (UnpAudioBlock) - for (I=0;I=InAddr+5) - if (UnpAudioBlock) - { - if (DecodeNumber((struct Decode *)&MD[UnpCurChannel])==256) - ReadTables20(); - } - else - if (DecodeNumber((struct Decode *)&LD)==269) - ReadTables20(); -} - - -void Unpack::UnpInitData20(int Solid) -{ - if (!Solid) - { - UnpAudioBlock=UnpChannelDelta=UnpCurChannel=0; - UnpChannels=1; - - memset(AudV,0,sizeof(AudV)); - memset(UnpOldTable20,0,sizeof(UnpOldTable20)); - memset(MD,0,sizeof(MD)); - } -} - - -byte Unpack::DecodeAudio(int Delta) -{ - struct AudioVariables *V=&AudV[UnpCurChannel]; - V->ByteCount++; - V->D4=V->D3; - V->D3=V->D2; - V->D2=V->LastDelta-V->D1; - V->D1=V->LastDelta; - int PCh=8*V->LastChar+V->K1*V->D1+V->K2*V->D2+V->K3*V->D3+V->K4*V->D4+V->K5*UnpChannelDelta; - PCh=(PCh>>3) & 0xFF; - - unsigned int Ch=PCh-Delta; - - int D=((signed char)Delta)<<3; - - V->Dif[0]+=abs(D); - V->Dif[1]+=abs(D-V->D1); - V->Dif[2]+=abs(D+V->D1); - V->Dif[3]+=abs(D-V->D2); - V->Dif[4]+=abs(D+V->D2); - V->Dif[5]+=abs(D-V->D3); - V->Dif[6]+=abs(D+V->D3); - V->Dif[7]+=abs(D-V->D4); - V->Dif[8]+=abs(D+V->D4); - V->Dif[9]+=abs(D-UnpChannelDelta); - V->Dif[10]+=abs(D+UnpChannelDelta); - - UnpChannelDelta=V->LastDelta=(signed char)(Ch-V->LastChar); - V->LastChar=Ch; - - if ((V->ByteCount & 0x1F)==0) - { - unsigned int MinDif=V->Dif[0],NumMinDif=0; - V->Dif[0]=0; - for (int I=1;IDif)/sizeof(V->Dif[0]);I++) - { - if (V->Dif[I]Dif[I]; - NumMinDif=I; - } - V->Dif[I]=0; - } - switch(NumMinDif) - { - case 1: - if (V->K1>=-16) - V->K1--; - break; - case 2: - if (V->K1<16) - V->K1++; - break; - case 3: - if (V->K2>=-16) - V->K2--; - break; - case 4: - if (V->K2<16) - V->K2++; - break; - case 5: - if (V->K3>=-16) - V->K3--; - break; - case 6: - if (V->K3<16) - V->K3++; - break; - case 7: - if (V->K4>=-16) - V->K4--; - break; - case 8: - if (V->K4<16) - V->K4++; - break; - case 9: - if (V->K5>=-16) - V->K5--; - break; - case 10: - if (V->K5<16) - V->K5++; - break; - } - } - return((byte)Ch); -} -#endif diff --git a/snesreader/unrar/unrar.cpp b/snesreader/unrar/unrar.cpp deleted file mode 100644 index 2c3baa7b..00000000 --- a/snesreader/unrar/unrar.cpp +++ /dev/null @@ -1,350 +0,0 @@ -// unrar_core 3.8.5. http://www.slack.net/~ant/ - -#include "unrar.h" - -#include "rar.hpp" -#include - -// This source code is a heavily modified version based on the unrar package. -// It may not be used to develop a RAR (WinRAR) compatible archiver. -// See unrar/license.txt for copyright and licensing. - -// Same as printf when debugging, otherwise 0 -#ifndef debug_printf - #define debug_printf 1 ? (void)0 : (void) -#endif - -// If expr != unrar_ok, returns its value -#define RETURN_ERR( expr ) \ - do {\ - unrar_err_t err_;\ - if ( (err_ = (expr)) != unrar_ok )\ - return err_;\ - } while ( 0 ) - - -// Receives errors reported from deep within library. -// MUST be macro. -#define NONLOCAL_ERROR( p ) \ - setjmp( p->Arc.jmp_env ) - -void Rar_Error_Handler::ReportError( unrar_err_t err ) -{ - if ( err ) - longjmp( jmp_env, err ); -} - -void Rar_Error_Handler::MemoryError() -{ - ReportError( unrar_err_memory ); -} - - -//// Internal - -unrar_t::unrar_t() : - Buffer( &Arc ) -{ - Arc.user_read = NULL; - Arc.user_write = NULL; - Arc.Tell_ = 0; - Arc.write_error = unrar_ok; - data_ = NULL; - own_data_ = NULL; - close_file = NULL; - FileCount = 0; - Unp = NULL; - - unrar_init(); -} - -unrar_t::~unrar_t() -{ - if ( Arc.write_error ) { } - - if ( close_file ) - close_file( Arc.user_read_data ); - - delete Unp; - - free( own_data_ ); -} - -// True if current file is compressed in way that affects solid extraction state -static inline bool solid_file( const unrar_t* p ) -{ - return p->Arc.Solid && - p->Arc.NewLhd.Method != 0x30 && - p->Arc.NewLhd.FullPackSize != 0; -} - -static void update_solid_pos( unrar_t* p ) -{ - if ( p->solid_pos == p->Arc.CurBlockPos ) - p->solid_pos = p->Arc.NextBlockPos; -} - -static unrar_err_t extract_( unrar_t* p, unrar_write_func user_write, void* user_data ) -{ - assert( !p->done ); - assert( !solid_file( p ) || p->solid_pos == p->Arc.CurBlockPos ); - - if ( p->Arc.write_error ) { } - p->Arc.write_error = unrar_ok; - p->Arc.user_write = user_write; - p->Arc.user_write_data = user_data; - RETURN_ERR( p->ExtractCurrentFile( user_write == NULL ) ); - p->Arc.user_write = NULL; - RETURN_ERR( p->Arc.write_error ); - - update_solid_pos( p ); - - return unrar_ok; -} - -static unrar_err_t skip_solid( unrar_t* p ) -{ - if ( !solid_file( p ) ) - { - update_solid_pos( p ); - return unrar_ok; - } - - return extract_( p, NULL, NULL ); -} - -static inline bool IsLink(uint Attr) -{ - return((Attr & 0xF000)==0xA000); -} - -static unrar_err_t next_( unrar_t* p, bool skipping_solid ) -{ - if ( p->done ) - return unrar_err_arc_eof; - - free( p->own_data_ ); - p->own_data_ = NULL; - p->data_ = NULL; - - for (;;) - { - p->Arc.SeekToNext(); - unrar_err_t const err = p->Arc.ReadHeader(); - if ( err != unrar_err_arc_eof ) - RETURN_ERR( err ); - //else - // debug_printf( "unrar: Didn't end with ENDARC_HEAD\n" ); // rar -en causes this - - HEADER_TYPE const type = (HEADER_TYPE) p->Arc.GetHeaderType(); - - if ( err != unrar_ok || type == ENDARC_HEAD ) - { - p->done = true; - break; - } - - if ( type != FILE_HEAD ) - { - // Skip non-files - if ( type != NEWSUB_HEAD && type != PROTECT_HEAD && type != SIGN_HEAD && type != SUB_HEAD ) - debug_printf( "unrar: Skipping unknown block type: %X\n", (unsigned) type ); - - update_solid_pos( p ); - } - else - { - // Update even for non-solid files, in case it's not extracted - if ( !solid_file( p ) ) - update_solid_pos( p ); - - if ( p->Arc.IsArcLabel() ) - { - // Ignore labels - } - else if ( IsLink( p->Arc.NewLhd.FileAttr ) ) - { - // Ignore links - - p->update_first_file_pos(); - p->FileCount++; // Links are treated as files - } - else if ( p->Arc.IsArcDir() ) - { - // Ignore directories - } - else - { - p->info.size = p->Arc.NewLhd.UnpSize; - p->info.name = p->Arc.NewLhd.FileName; - p->info.name_w = p->Arc.NewLhd.FileNameW; - p->info.is_unicode = (p->Arc.NewLhd.Flags & LHD_UNICODE) != 0; - p->info.dos_date = p->Arc.NewLhd.mtime.time; - p->info.crc = p->Arc.NewLhd.FileCRC; - p->info.is_crc32 = !p->Arc.OldFormat; - - // Stop for files - break; - } - - // Original code assumed that non-file items were never solid compressed - check( !solid_file( p ) ); - - // Skip non-file solid-compressed items (original code assumed there were none) - if ( skipping_solid ) - RETURN_ERR( skip_solid( p ) ); - } - } - - return unrar_ok; -} - -static unrar_err_t open_( unrar_t* p, unrar_read_func read, void* user_data ) -{ - p->Arc.user_read = read; - p->Arc.user_read_data = user_data; - - RETURN_ERR( p->Arc.IsArchive() ); - - p->begin_pos = p->Arc.NextBlockPos; - p->solid_pos = p->Arc.NextBlockPos; - p->first_file_pos = INT_MAX; - p->done = false; - - return unrar_ok; -} - - -//// Interface - - // Needed when user read throws exception - struct unrar_ptr { - unrar_t* p; - unrar_ptr() { p = NULL; } - ~unrar_ptr() { delete p; } - }; - -unrar_err_t unrar_open_custom( unrar_t** impl_out, unrar_read_func read, void* user_data ) -{ - *impl_out = NULL; - - unrar_ptr ptr; - ptr.p = new unrar_t; - if ( !ptr.p ) - return unrar_err_memory; - - RETURN_ERR( NONLOCAL_ERROR( ptr.p ) ); - RETURN_ERR( open_( ptr.p, read, user_data ) ); - RETURN_ERR( next_( ptr.p, false ) ); - - *impl_out = ptr.p; - ptr.p = NULL; - - //delete ptr.p; // done automatically at end of function - - return unrar_ok; -} - -void unrar_close( unrar_t* ar ) -{ - delete ar; -} - -unrar_bool unrar_done( const unrar_t* p ) -{ - return p->done; -} - -unrar_err_t unrar_next( unrar_t* p ) -{ - assert( !unrar_done( p ) ); - - RETURN_ERR( NONLOCAL_ERROR( p ) ); - return next_( p, false ); -} - -const unrar_info_t* unrar_info( unrar_t const* p ) -{ - assert( !unrar_done( p ) ); - - return &p->info; -} - -unrar_pos_t unrar_tell( const unrar_t* p ) -{ - return p->Arc.CurBlockPos; -} - -unrar_err_t unrar_seek( unrar_t* p, unrar_pos_t n ) -{ - p->Arc.NextBlockPos = n; - p->done = false; - p->FileCount = (n <= p->first_file_pos ? 0 : 1); - - return unrar_next( p ); -} - -unrar_err_t unrar_rewind( unrar_t* p ) -{ - return unrar_seek( p, p->begin_pos ); -} - -unrar_err_t unrar_try_extract( const unrar_t* p ) -{ - assert( !unrar_done( p ) ); - - return ((unrar_t*) p)->ExtractCurrentFile( true, true ); -} - - static unrar_err_t reopen( unrar_t* p ) - { - // Save and restore archive reader - unrar_read_func read = p->Arc.user_read; - void* user_data = p->Arc.user_read_data; - - void (*close_file)( void* ) = p->close_file; - p->close_file = NULL; - - p->~unrar_t(); - new (p) unrar_t; - - p->close_file = close_file; - - return open_( p, read, user_data ); - } - -unrar_err_t unrar_extract_custom( unrar_t* p, unrar_write_func user_write, void* user_data ) -{ - assert( !unrar_done( p ) ); - - RETURN_ERR( NONLOCAL_ERROR( p ) ); - - if ( solid_file( p ) ) - { - unrar_pos_t pos = p->Arc.CurBlockPos; - if ( p->solid_pos != pos ) - { - // Next file to solid extract isn't current one - - if ( p->solid_pos > pos ) - RETURN_ERR( reopen( p ) ); - else - p->Arc.NextBlockPos = p->solid_pos; - - RETURN_ERR( next_( p, true ) ); - - // Keep extracting until solid position is at desired file - while ( !p->done && p->solid_pos < pos ) - { - RETURN_ERR( skip_solid( p ) ); - RETURN_ERR( next_( p, true ) ); - } - - // Be sure we're at right file - if ( p->solid_pos != pos || p->Arc.CurBlockPos != pos ) - return unrar_err_corrupt; - } - } - - return extract_( p, user_write, user_data ); -} diff --git a/snesreader/unrar/unrar.h b/snesreader/unrar/unrar.h deleted file mode 100644 index 470bc146..00000000 --- a/snesreader/unrar/unrar.h +++ /dev/null @@ -1,164 +0,0 @@ -/** RAR archive scanning and extraction \file */ - -/* unrar_core 3.8.5 */ -#ifndef UNRAR_H -#define UNRAR_H - -#include -#include - -#if !defined (UNRAR_NO_LONG_LONG) && defined (LLONG_MAX) - typedef long long unrar_long_long; -#else - typedef long unrar_long_long; -#endif - -#ifdef __cplusplus - extern "C" { -#endif - - -/** Error code, or 0 if function was successful. See Errors for more. Except -where noted, once an operation returns an error, that archive should not be -used any further, other than with unrar_close(). */ -#ifndef unrar_err_t /* (#ifndef allows better testing of library) */ - typedef int unrar_err_t; -#endif - -/** First parameter of most functions is unrar_t*, or const unrar_t* if nothing -is changed. */ -typedef struct unrar_t unrar_t; - -/** File position */ -typedef unrar_long_long unrar_pos_t; - -/** Boolean, where 0 is false and 1 is true */ -typedef int unrar_bool; - - -/******** Open/close ********/ - -/** Initializes static tables used by library. Automatically called by -unrar_open(). OK to call more than once. */ -void unrar_init( void ); - -/** Opens archive and points *out at it. If error, sets *out to NULL. */ -unrar_err_t unrar_open( unrar_t** out, const char path [] ); - -/** User archive read callback. When called, user_data is a copy of that passed -to unrar_open_custom(). Callback must do the following: Read avail bytes from -file at offset pos and set *count to avail, where avail is the lesser of *count -and file_size-pos. Put read bytes into *out and return unrar_ok. If fewer than -avail bytes could be read successfully, return a non-zero error code. */ -typedef unrar_err_t (*unrar_read_func)( void* user_data, - void* out, int* count, unrar_pos_t pos ); - -/** Same as unrar_open(), except data is read using supplied function rather -than from file. */ -unrar_err_t unrar_open_custom( unrar_t** unrar_out, - unrar_read_func, void* user_data ); - -/** Closes archive and frees memory. OK to pass NULL. */ -void unrar_close( unrar_t* ); - - -/******** Scanning ********/ - -/** True if at end of archive. Must be called after unrar_open() or -unrar_rewind(), as an archive might contain no files. */ -unrar_bool unrar_done( const unrar_t* ); - -/** Goes to next file in archive. If there are no more files, unrar_done() will -now return true. */ -unrar_err_t unrar_next( unrar_t* ); - -/** Goes back to first file in archive, as if it were just opened with -unrar_open(). */ -unrar_err_t unrar_rewind( unrar_t* ); - -/** Position of current file in archive. Will never return zero. */ -unrar_pos_t unrar_tell( const unrar_t* ); - -/** Returns to file at previously-saved position. */ -unrar_err_t unrar_seek( unrar_t*, unrar_pos_t ); - - -/**** Info ****/ - -/** Information about current file */ -typedef struct unrar_info_t -{ - unrar_pos_t size; /**< Uncompressed size */ - const char* name; /**< Name, in Unicode if is_unicode is true */ - const wchar_t* name_w; /**< Name in Unicode, "" if unavailable */ - unrar_bool is_unicode; /**< True if name is Unicode (UTF-8) */ - unsigned int dos_date; /**< Date in DOS-style format, 0 if unavailable */ - unsigned int crc; /**< Checksum; algorithm depends on archive */ - unrar_bool is_crc32; /**< True if crc is CRC-32 */ -} unrar_info_t; - -/** Information about current file. Pointer is valid until unrar_next(), -unrar_rewind(), unrar_seek(), or unrar_close(). */ -const unrar_info_t* unrar_info( const unrar_t* ); - - -/**** Extraction ****/ - -/** Returns unrar_ok if current file can be extracted, otherwise error -indicating why it can't be extracted (too new/old compression algorithm, -encrypted, segmented). Archive is still usable if this returns error, -just the current file can't be extracted. */ -unrar_err_t unrar_try_extract( const unrar_t* ); - -/** Extracts at most size bytes from current file into out. If file is larger, -discards excess bytes. If file is smaller, only writes unrar_size() bytes. */ -unrar_err_t unrar_extract( unrar_t*, void* out, unrar_pos_t size ); - -/** Extracts data to memory and returns pointer to it in *out. Pointer is -valid until unrar_next(), unrar_rewind(), unrar_seek(), or unrar_close(). OK to -call more than once for same file. Optimized to avoid allocating memory when -entire file will already be kept in internal window. */ -unrar_err_t unrar_extract_mem( unrar_t* p, void const** out ); - -/** User extracted data write callback. When called, user_data is a copy of -that passed to unrar_extract_custom(). Callback must do the following: Write -count bytes from *in to wherever extracted data goes and return unrar_ok. If -data cannot be written successfully, return a non-zero error code. */ -typedef unrar_err_t (*unrar_write_func)( void* user_data, - const void* in, int count ); - -/** Extracts current file and writes data using supplied function. Any error -it returns will be returned by this function, and archive will still be -usable. */ -unrar_err_t unrar_extract_custom( unrar_t*, - unrar_write_func, void* user_data ); - - -/******** Errors ********/ - -/** Error string associated with unrar error code. Always returns valid -pointer to a C string; never returns NULL. Returns "" for unrar_ok. */ -const char* unrar_err_str( unrar_err_t ); - -enum { - unrar_ok = 0,/**< No error; success. Guaranteed to be zero. */ - unrar_err_memory = 1,/**< Out of memory */ - unrar_err_open = 2,/**< Couldn't open file (not found/permissions) */ - unrar_err_not_arc = 3,/**< Not a RAR archive */ - unrar_err_corrupt = 4,/**< Archive is corrupt */ - unrar_err_io = 5,/**< Read failed */ - unrar_err_arc_eof = 6,/**< At end of archive; no more files */ - unrar_err_encrypted = 7,/**< Encryption not supported */ - unrar_err_segmented = 8,/**< Segmentation not supported */ - unrar_err_huge = 9,/**< Huge (2GB+) archives not supported */ - unrar_err_old_algo = 10,/**< Compressed with unsupported old algorithm */ - unrar_err_new_algo = 11,/**< Compressed with unsupported new algorithm */ - unrar_next_err = 100/**< Errors range from 0 to unrar_next_err-1 */ -}; - - -#ifdef __cplusplus - } -#endif - -#endif diff --git a/snesreader/unrar/unrar_misc.cpp b/snesreader/unrar/unrar_misc.cpp deleted file mode 100644 index a0a6551a..00000000 --- a/snesreader/unrar/unrar_misc.cpp +++ /dev/null @@ -1,170 +0,0 @@ -// Misc functions outside the core interface - -#include "unrar.h" - -#include "rar.hpp" -#include - -// This source code is a heavily modified version based on the unrar package. -// It may not be used to develop a RAR (WinRAR) compatible archiver. -// See unrar/license.txt for copyright and licensing. - -void unrar_init() -{ - if (CRCTab[1]==0) - InitCRC(); - - Unpack::init_tables(); -} - -struct unrar_extract_mem_t -{ - char* out; - char* end; -}; - -extern "C" { - static unrar_err_t extract_write( void* user_data, const void* in, int count ) - { - unrar_extract_mem_t* p = (unrar_extract_mem_t*) user_data; - - unrar_pos_t remain = p->end - p->out; - if ( remain > 0 ) - { - if ( count > remain ) - count = remain; - - memcpy( p->out, in, count ); - p->out += count; - } - - return unrar_ok; - } -} - -unrar_err_t unrar_extract( unrar_t* p, void* out, unrar_pos_t size ) -{ - assert( !unrar_done( p ) ); - - unrar_extract_mem_t m; - m.out = (char*) out; - m.end = m.out + size; - return unrar_extract_custom( p, &extract_write, &m ); -} - -inline -static bool is_entire_file( const unrar_t* p, const void* in, int count ) -{ - return (count == p->Arc.NewLhd.UnpSize && p->Unp && in == p->Unp->window_wrptr()); -} - -extern "C" { - static unrar_err_t extract_mem( void* data, void const* in, int count ) - { - unrar_t* p = (unrar_t*) data; - - // We might have pointer to entire file - if ( !p->data_ && is_entire_file( p, in, count ) ) - { - p->data_ = in; - return unrar_ok; - } - - // We don't have it, so allocate memory to read entire file into - if ( !p->own_data_ ) - { - assert( !p->data_ ); - - unrar_pos_t size = unrar_info( p )->size; - p->own_data_ = malloc( size ? size : 1 ); - if ( !p->own_data_ ) - return unrar_err_memory; - - p->data_ = p->own_data_; - } - - memcpy( (void*) p->data_, in, count ); - p->data_ = (char*) p->data_ + count; - - return unrar_ok; - } -} - -unrar_err_t unrar_extract_mem( unrar_t* p, void const** out ) -{ - assert( !unrar_done( p ) ); - - *out = NULL; - - if ( !p->data_ ) - { - unrar_err_t err = unrar_extract_custom( p, &extract_mem, p ); - if ( err ) - return err; - } - - *out = (p->own_data_ ? p->own_data_ : p->data_); - return unrar_ok; -} - -const char* unrar_err_str( unrar_err_t err ) -{ - switch ( err ) - { - case unrar_ok: return ""; - case unrar_err_memory: return "out of memory"; - case unrar_err_open: return "couldn't open RAR archive"; - case unrar_err_not_arc: return "not a RAR archive"; - case unrar_err_corrupt: return "RAR archive is corrupt"; - case unrar_err_io: return "couldn't read/write"; - case unrar_err_arc_eof: return "unexpected end of archive"; - case unrar_err_encrypted: return "encryption not supported"; - case unrar_err_segmented: return "segmentation not supported"; - case unrar_err_huge: return "huge (2GB+) archives are not supported"; - case unrar_err_old_algo: return "compressed using older algorithm than supported"; - case unrar_err_new_algo: return "compressed using newer algorithm than supported"; - } - - assert( false ); - return "problem with RAR"; -} - -int ComprDataIO::Read( void* p, int n ) -{ - unrar_err_t err = user_read( user_read_data, p, &n, Tell_ ); - if ( err ) - ReportError( err ); - - Tell_ += n; - if ( Tell_ < 0 ) - ReportError( unrar_err_huge ); - - return n; -} - -void ComprDataIO::UnpWrite( byte* out, uint count ) -{ - if ( !SkipUnpCRC ) - { - if ( write_error == unrar_ok ) - write_error = user_write( user_write_data, out, count ); - - if ( OldFormat ) - UnpFileCRC = OldCRC( (ushort) UnpFileCRC, out, count ); - else - UnpFileCRC = CRC( UnpFileCRC, out, count ); - } -} - -int ComprDataIO::UnpRead( byte* out, uint count ) -{ - if ( count <= 0 ) - return 0; - - if ( count > (uint) UnpPackedSize ) - count = UnpPackedSize; - - int result = Read( out, count ); - UnpPackedSize -= result; - return result; -} diff --git a/snesreader/unrar/unrar_open.cpp b/snesreader/unrar/unrar_open.cpp deleted file mode 100644 index f9b0c40d..00000000 --- a/snesreader/unrar/unrar_open.cpp +++ /dev/null @@ -1,45 +0,0 @@ -// Separate file to avoid linking to f* functions unless user calls unrar_open_file() - -#include "unrar.h" -#include "rar.hpp" -#include - -extern "C" { - static unrar_err_t unrar_read_file( void* user_data, void* out, int* count, unrar_pos_t pos ) - { - FILE* file = (FILE*) user_data; - - // most of the time, seeking won't be necessary - if ( pos != ftell( file ) && fseek( file, pos, SEEK_SET ) != 0 ) - return unrar_err_corrupt; - - *count = (int) fread( out, 1, *count, file ); - - if ( ferror( file ) != 0 ) - return unrar_err_io; - - return unrar_ok; - } -} - -static void unrar_close_file( void* user_data ) -{ - fclose( (FILE*) user_data ); -} - -unrar_err_t unrar_open( unrar_t** arc_out, const char path [] ) -{ - *arc_out = NULL; - - FILE* file = fopen( path, "rb" ); - if ( file == NULL ) - return unrar_err_open; - - unrar_err_t err = unrar_open_custom( arc_out, &unrar_read_file, file ); - if ( err != unrar_ok ) - fclose( file ); - else - (*arc_out)->close_file = &unrar_close_file; - - return err; -} diff --git a/snesreader/unrar/whatsnew.txt b/snesreader/unrar/whatsnew.txt deleted file mode 100644 index 38012e9a..00000000 --- a/snesreader/unrar/whatsnew.txt +++ /dev/null @@ -1,267 +0,0 @@ - - - WinRAR - What's new in the latest version - - - Version 3.80 - - 1. Added support for ZIP archives containing Unicode file names - in UTF-8 format. When creating ZIP archive, WinRAR stores - names in Unicode only if they cannot be stored correctly using - the current single byte character set. - - 2. Added decompression support for WinZip AES encrypted ZIP archives. - - 3. Improved Unicode support for RAR and ZIP archive names. - - 4. "Ask before overwrite" and "Skip existing files" update modes - are now available in archiving dialog. They allow to specify - WinRAR behavior when updating already existing files in archive. - Unlike already available "Fresh existing files only" and - "Add and update files", these new modes ignore file date - and compare only file names. - - Command line equivalents of these modes are: - - a) switch -o enables "Ask before overwrite" archiving mode; - - b) switch -o- enables "Skip existing files" archiving mode; - - c) switch -o+ enables "Overwrite all" mode (default for archiving). - - 5. New "Add to context menu" option in "Profile parameters" dialog. - If this option is on, the profile name will be displayed in Explorer - context menus allowing to activate a profile from context menu. - - 6. New -cp switch allows to select a compression profile - in command line mode. It is supported only by GUI WinRAR.exe, - not by rar.exe. - - 7. New "Options" page of archiving dialog contains the group of - settings modifying the behavior of "Delete files after archiving" - option from "General" page: - - a) Delete files. Delete files normally like in previous WinRAR - versions. - - b) Move files to Recycle Bin. Deleted files are placed to - Recycle Bin. - - Command line equivalent of this option is -dr switch. - - c) Wipe files. Before deleting file data are overwritten by - zero bytes to prevent recovery of deleted files. - - Command line equivalent of this option is -dw switch. - - All these options have an effect only if "Delete files - after archiving" is on. You can enable any of these options - in the default compression profile to change the default - behavior of "Delete files after archiving". - - 8. WinRAR "Extraction path and options" dialog is now resizable. - You can use the mouse to drag its border to the desired size - and provide more space for folder tree pane. WinRAR will store - new dimensions of this dialog. - - 9. New "Update" SFX script command and "Update mode" group - of options in "Update" page of "Advanced SFX options" dialog. - These command and options allow to check time and implement - file time based updating; - - 10. SFX script "Shortcut" command and "Add shortcut..." command - in "Advanced SFX options" dialog now allow to specify - an icon file containing an icon associated with shortcut. - - 11. New "Wipe temporary files" option in "Settings/Security" dialog - provides more secure, though slower, way to delete temporary - WinRAR files. - - 12. WinRAR and RAR display the total progress bar when unpacking - a multivolume RAR archive if all volumes are present - in the same folder. - - 13. WinRAR and RAR automatically expand names of environment - variables in list files. For example, a list file can contain - lines like: - - %windir%\*.exe - %USERPROFILE%\Desktop - - This feature is available only in Windows RAR version. - - 14. Added support of TAR archives with non-zero "extra field" data. - - 15. Added support of TAR archives, which does not contain - the end of archive entry consisting of 512 zero bytes. - - 16. Improved Unicode support when dragging files from WinRAR window. - - 17. Shift+Tab key combination can be used in main WinRAR window to - switch the input focus between interface elements (files, comment, - tree, address) in reverse order. In previous versions Shift+Tab - used the same order as Tab. - - 18. Corrected a possible WinRAR crash when opening truncated - UDF ISO files. - - - Version 3.71 - - 1. Archive names in rar.log error log file always include - the full path. - - 2. WinRAR tray icon is compatible with high DPI display modes. - - 3. If you modified a file in archive with encrypted names using - an external editor, WinRAR will not ask for archive password again - when prompting to update a file. It will use a password which - you entered when opening an archive, - - 4. Bugs fixed: - - a) switch -tl and "Set archive time to latest file time" option - could fail in previous version. Sometimes they set archive time - to current system time instead of latest file time; - - b) if -ag switch mask contained archive number, month and minute - characters, WinRAR placed 'I' character instead of minute value - into generated archive name for archive numbers exceeding 1; - - c) high ASCII names in ISO files using ISO 9660 format without - Joliet format extension were displayed incorrectly; - - d) WinRAR could crash when decompressing some of corrupt RAR archives; - - e) if "Turn PC off when done" option was set in "Convert archives" - command, WinRAR turned PC off after converting the first archive - in selected group instead of after converting the entire group; - - f) if user specified a non-existent destination path in SFX archive - in Vista, SFX could enter into infinite "create new SFX window" - loop; - - g) WinRAR could fail to unpack an individual file from subfolder - of ACE archive using the drag and drop. - - - Version 3.70 - - 1. Numerous Windows Vista compatibility changes: - - a) help format changed from old HLP to newer HTML based CHM; - - b) GUI self-extracting modules attempt to request for - administrator permissions if they cannot create destination - folder under current user account; - - c) Log file rar.log and WinRAR theme files are stored - in %APPDATA%\WinRAR folder instead of WinRAR program files folder. - - Exported settings file settings.reg is also stored - in %APPDATA%\WinRAR folder by default, but it is possible to - select another folder in "Save WinRAR settings" and "Load WinRAR - settings" dialogs. - - WinRAR searches for registration key and settings.reg - both in its program files folder and in %APPDATA%\WinRAR; - - It is possible to set the string value "AppData" in Registry key - HKEY_CURRENT_USER\Software\WinRAR\Paths to override the default - %appdata%\WinRAR path for WinRAR settings. - - For example, if you wish to store theme files in WinRAR folder, - set this value to "c:\Program Files\WinRAR". - - d) Vista compatibility changes in WinRAR shell integration; - - e) New "Request administrative access" option in "Advanced" page - of "Advanced SFX options" allows to create SFX archive, - which will request the administrative access when started - in Windows Vista. - - Command line equivalent of this option is -iadm switch. - - 2. Added support for ISO 13346 (UDF) file format. This format - is frequently used in ISO images of DVD disks. - - 3. Added Unicode support for ISO 9660 files, so WinRAR should - handle non-English file names in .iso files better. - - 4. Design changes in window displaying archiving and extraction - progress: - - a) it provides more space for file names, allowing lengthy names; - - b) it displays the current archive name in separate line, - allowing much longer archive names than before; - - c) when archiving, it displays the current compression ratio - in separate line; - - d) it can use both standard Windows and classic WinRAR progress bars. - Turn on "Windows progress bars" option in WinRAR "Settings/General" - dialog to use standard progress bars. By default this option is - on if some Windows visual style is active and off if Windows Classic - theme is selected. - - Windows progress bars are two color only, so they do not indicate - the current compression ratio. But now the ratio is displayed - in separate line; - - e) "Mode..." button moved to bottom of window. - - 5. GUI self-extracting modules support following command line - switches: - - -d set the destination path - -p specify a password - -s silent mode, hide all - -s1 same as -s - -s2 silent mode, hide start dialog - -sp specify parameters for setup program - - 6. GUI self-extracting modules do not pass the entire command line - to setup program like they did in previous versions. - If you need to get access to entire command line of SFX archive, - parse sfxcmd environment variable which contains this command line. - - 7. New switch -sc[objects] allowing to select character - sets for archive comments and list files. It replaces -fcu switch - introduced in RAR 3.60, which was removed from list of supported - switches. Now you need to specify -scuc instead of -fcu to use - Unicode comments. Unlike -fcu, -sc also supports OEM and ANSI charset. - - 8. New "Save archive copy as..." command in "File" menu. - This command may be useful if you opened an archive from Internet - directly in WinRAR and then decided to save it on local disk. - - 9. "Word wrap" command added to "View" menu of WinRAR internal viewer, - so you can change the wrapping mode of already opened viewer window. - - State of this option is not stored between viewing sessions. - If you need to change the default word wrap mode, use WinRAR - "Settings/Viewer" dialog. - - 10. Buttons "Up" and "Down" added to "Organize profiles" dialog. - Using these buttons you can change position of selected profile - in the list. - - 11. Operation progress is displayed when adding the recovery record. - - 12. If WinRAR is minimized to tray and mouse is over its icon, - WinRAR diplays a message about the current operation progress. - In previous versions it included only percent done, now it also - contains the time left information. - - 13. Console RAR displays "Calculating the control sum" message - when calculating CRC32 control sum for newly created RAR volume. - Previous versions also calculated the volume control sum, - but did it silently. - - 14. Archives history list in "File" menu allows Unicode names, - providing more reliable support for non-English archive names. - - 15. Stack overflow vulnerability has been corrected in password - processing module of console RAR and UnRAR. GUI WinRAR is not - affected. We are thankful to the iDEFENSE LABS for reporting this bug. diff --git a/snesreader/xml.cpp b/snesreader/xml.cpp deleted file mode 100644 index f173d5cc..00000000 --- a/snesreader/xml.cpp +++ /dev/null @@ -1,752 +0,0 @@ -#include "xml.hpp" -XML xml; - -typedef uint8_t uint8; -typedef uint16_t uint16; -typedef uint32_t uint32; -typedef uint64_t uint64; - -void XML::generate(string &xml, const uint8_t *data, unsigned size) { - read_header(data, size); - - xml = "\n"; - - if(type == TypeBsx) { - xml << ""; - return; - } else if(type == TypeSufamiTurbo) { - xml << ""; - return; - } else if(type == TypeGameBoy) { - xml << "\n"; - if(gameboy_ram_size(data, size) > 0) { - xml << " \n"; - } - xml << "\n"; - return; - } - - xml << "\n"; - - if(type == TypeSuperGameBoy1Bios) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } else if(type == TypeSuperGameBoy2Bios) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } else if(has_spc7110) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - if(has_spc7110rtc) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } else if(mapper == LoROM) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - - if(ram_size > 0) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - if((rom_size > 0x200000) || (ram_size > 32 * 1024)) { - xml << " \n"; - xml << " \n"; - } else { - xml << " \n"; - xml << " \n"; - } - xml << " \n"; - } - } else if(mapper == HiROM) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - - if(ram_size > 0) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - if((rom_size > 0x200000) || (ram_size > 32 * 1024)) { - xml << " \n"; - } else { - xml << " \n"; - } - xml << " \n"; - } - } else if(mapper == ExLoROM) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - - if(ram_size > 0) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } - } else if(mapper == ExHiROM) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - - if(ram_size > 0) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - if((rom_size > 0x200000) || (ram_size > 32 * 1024)) { - xml << " \n"; - } else { - xml << " \n"; - } - xml << " \n"; - } - } else if(mapper == SuperFXROM) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } else if(mapper == SA1ROM) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } else if(mapper == BSCLoROM) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } else if(mapper == BSCHiROM) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } else if(mapper == BSXROM) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } else if(mapper == STROM) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } - - if(has_srtc) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } - - if(has_sdd1) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } - - if(has_cx4) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } - - if(has_dsp1) { - xml << " \n"; - if(dsp1_mapper == DSP1LoROM1MB) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } else if(dsp1_mapper == DSP1LoROM2MB) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } else if(dsp1_mapper == DSP1HiROM) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } - xml << " \n"; - } - - if(has_dsp2) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } - - if(has_dsp3) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } - - if(has_dsp4) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } - - if(has_obc1) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } - - if(has_st010) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } - - if(has_st011) { - //ST-0011 addresses not verified; chip is unsupported - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } - - if(has_st018) { - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - xml << " \n"; - } - - xml << "\n"; -} - -void XML::read_header(const uint8_t *data, unsigned size) { - type = TypeUnknown; - mapper = LoROM; - dsp1_mapper = DSP1Unmapped; - region = NTSC; - rom_size = size; - ram_size = 0; - - has_bsx_slot = false; - has_superfx = false; - has_sa1 = false; - has_srtc = false; - has_sdd1 = false; - has_spc7110 = false; - has_spc7110rtc = false; - has_cx4 = false; - has_dsp1 = false; - has_dsp2 = false; - has_dsp3 = false; - has_dsp4 = false; - has_obc1 = false; - has_st010 = false; - has_st011 = false; - has_st018 = false; - - //===================== - //detect Game Boy carts - //===================== - - if(size >= 0x0140) { - if(data[0x0104] == 0xce && data[0x0105] == 0xed && data[0x0106] == 0x66 && data[0x0107] == 0x66 - && data[0x0108] == 0xcc && data[0x0109] == 0x0d && data[0x010a] == 0x00 && data[0x010b] == 0x0b) { - type = TypeGameBoy; - return; - } - } - - const unsigned index = find_header(data, size); - const uint8 mapperid = data[index + Mapper]; - const uint8 rom_type = data[index + RomType]; - const uint8 rom_size = data[index + RomSize]; - const uint8 company = data[index + Company]; - const uint8 regionid = data[index + CartRegion] & 0x7f; - - ram_size = 1024 << (data[index + RamSize] & 7); - if(ram_size == 1024) ram_size = 0; //no RAM present - - //0, 1, 13 = NTSC; 2 - 12 = PAL - region = (regionid <= 1 || regionid >= 13) ? NTSC : PAL; - - //======================= - //detect BS-X flash carts - //======================= - - if(data[index + 0x13] == 0x00 || data[index + 0x13] == 0xff) { - if(data[index + 0x14] == 0x00) { - const uint8_t n15 = data[index + 0x15]; - if(n15 == 0x00 || n15 == 0x80 || n15 == 0x84 || n15 == 0x9c || n15 == 0xbc || n15 == 0xfc) { - if(data[index + 0x1a] == 0x33 || data[index + 0x1a] == 0xff) { - type = TypeBsx; - mapper = BSXROM; - region = NTSC; //BS-X only released in Japan - return; - } - } - } - } - - //========================= - //detect Sufami Turbo carts - //========================= - - if(!memcmp(data, "BANDAI SFC-ADX", 14)) { - if(!memcmp(data + 16, "SFC-ADX BACKUP", 14)) { - type = TypeSufamiTurboBios; - } else { - type = TypeSufamiTurbo; - } - mapper = STROM; - region = NTSC; //Sufami Turbo only released in Japan - return; //RAM size handled outside this routine - } - - //========================== - //detect Super Game Boy BIOS - //========================== - - if(!memcmp(data + index, "Super GAMEBOY2", 14)) { - type = TypeSuperGameBoy2Bios; - return; - } - - if(!memcmp(data + index, "Super GAMEBOY", 13)) { - type = TypeSuperGameBoy1Bios; - return; - } - - //===================== - //detect standard carts - //===================== - - //detect presence of BS-X flash cartridge connector (reads extended header information) - if(data[index - 14] == 'Z') { - if(data[index - 11] == 'J') { - uint8 n13 = data[index - 13]; - if((n13 >= 'A' && n13 <= 'Z') || (n13 >= '0' && n13 <= '9')) { - if(company == 0x33 || (data[index - 10] == 0x00 && data[index - 4] == 0x00)) { - has_bsx_slot = true; - } - } - } - } - - if(has_bsx_slot) { - if(!memcmp(data + index, "Satellaview BS-X ", 21)) { - //BS-X base cart - type = TypeBsxBios; - mapper = BSXROM; - region = NTSC; //BS-X only released in Japan - return; //RAM size handled internally by load_cart_bsx() -> BSXCart class - } else { - type = TypeBsxSlotted; - mapper = (index == 0x7fc0 ? BSCLoROM : BSCHiROM); - region = NTSC; //BS-X slotted cartridges only released in Japan - } - } else { - //standard cart - type = TypeNormal; - - if(index == 0x7fc0 && size >= 0x401000) { - mapper = ExLoROM; - } else if(index == 0x7fc0 && mapperid == 0x32) { - mapper = ExLoROM; - } else if(index == 0x7fc0) { - mapper = LoROM; - } else if(index == 0xffc0) { - mapper = HiROM; - } else { //index == 0x40ffc0 - mapper = ExHiROM; - } - } - - if(mapperid == 0x20 && (rom_type == 0x13 || rom_type == 0x14 || rom_type == 0x15 || rom_type == 0x1a)) { - has_superfx = true; - mapper = SuperFXROM; - ram_size = 1024 << (data[index - 3] & 7); - if(ram_size == 1024) ram_size = 0; - } - - if(mapperid == 0x23 && (rom_type == 0x32 || rom_type == 0x34 || rom_type == 0x35)) { - has_sa1 = true; - mapper = SA1ROM; - } - - if(mapperid == 0x35 && rom_type == 0x55) { - has_srtc = true; - } - - if(mapperid == 0x32 && (rom_type == 0x43 || rom_type == 0x45)) { - has_sdd1 = true; - } - - if(mapperid == 0x3a && (rom_type == 0xf5 || rom_type == 0xf9)) { - has_spc7110 = true; - has_spc7110rtc = (rom_type == 0xf9); - mapper = SPC7110ROM; - } - - if(mapperid == 0x20 && rom_type == 0xf3) { - has_cx4 = true; - } - - if((mapperid == 0x20 || mapperid == 0x21) && rom_type == 0x03) { - has_dsp1 = true; - } - - if(mapperid == 0x30 && rom_type == 0x05 && company != 0xb2) { - has_dsp1 = true; - } - - if(mapperid == 0x31 && (rom_type == 0x03 || rom_type == 0x05)) { - has_dsp1 = true; - } - - if(has_dsp1 == true) { - if((mapperid & 0x2f) == 0x20 && size <= 0x100000) { - dsp1_mapper = DSP1LoROM1MB; - } else if((mapperid & 0x2f) == 0x20) { - dsp1_mapper = DSP1LoROM2MB; - } else if((mapperid & 0x2f) == 0x21) { - dsp1_mapper = DSP1HiROM; - } - } - - if(mapperid == 0x20 && rom_type == 0x05) { - has_dsp2 = true; - } - - if(mapperid == 0x30 && rom_type == 0x05 && company == 0xb2) { - has_dsp3 = true; - } - - if(mapperid == 0x30 && rom_type == 0x03) { - has_dsp4 = true; - } - - if(mapperid == 0x30 && rom_type == 0x25) { - has_obc1 = true; - } - - if(mapperid == 0x30 && rom_type == 0xf6 && rom_size >= 10) { - has_st010 = true; - } - - if(mapperid == 0x30 && rom_type == 0xf6 && rom_size < 10) { - has_st011 = true; - } - - if(mapperid == 0x30 && rom_type == 0xf5) { - has_st018 = true; - } -} - -unsigned XML::find_header(const uint8_t *data, unsigned size) const { - unsigned score_lo = score_header(data, size, 0x007fc0); - unsigned score_hi = score_header(data, size, 0x00ffc0); - unsigned score_ex = score_header(data, size, 0x40ffc0); - if(score_ex) score_ex += 4; //favor ExHiROM on images > 32mbits - - if(score_lo >= score_hi && score_lo >= score_ex) { - return 0x007fc0; - } else if(score_hi >= score_ex) { - return 0x00ffc0; - } else { - return 0x40ffc0; - } -} - -unsigned XML::score_header(const uint8_t *data, unsigned size, unsigned addr) const { - if(size < addr + 64) return 0; //image too small to contain header at this location? - int score = 0; - - uint16 resetvector = data[addr + ResetVector] | (data[addr + ResetVector + 1] << 8); - uint16 checksum = data[addr + Checksum ] | (data[addr + Checksum + 1] << 8); - uint16 complement = data[addr + Complement ] | (data[addr + Complement + 1] << 8); - - uint8 resetop = data[(addr & ~0x7fff) | (resetvector & 0x7fff)]; //first opcode executed upon reset - uint8 mapper = data[addr + Mapper] & ~0x10; //mask off irrelevent FastROM-capable bit - - //$00:[000-7fff] contains uninitialized RAM and MMIO. - //reset vector must point to ROM at $00:[8000-ffff] to be considered valid. - if(resetvector < 0x8000) return 0; - - //some images duplicate the header in multiple locations, and others have completely - //invalid header information that cannot be relied upon. - //below code will analyze the first opcode executed at the specified reset vector to - //determine the probability that this is the correct header. - - //most likely opcodes - if(resetop == 0x78 //sei - || resetop == 0x18 //clc (clc; xce) - || resetop == 0x38 //sec (sec; xce) - || resetop == 0x9c //stz $nnnn (stz $4200) - || resetop == 0x4c //jmp $nnnn - || resetop == 0x5c //jml $nnnnnn - ) score += 8; - - //plausible opcodes - if(resetop == 0xc2 //rep #$nn - || resetop == 0xe2 //sep #$nn - || resetop == 0xad //lda $nnnn - || resetop == 0xae //ldx $nnnn - || resetop == 0xac //ldy $nnnn - || resetop == 0xaf //lda $nnnnnn - || resetop == 0xa9 //lda #$nn - || resetop == 0xa2 //ldx #$nn - || resetop == 0xa0 //ldy #$nn - || resetop == 0x20 //jsr $nnnn - || resetop == 0x22 //jsl $nnnnnn - ) score += 4; - - //implausible opcodes - if(resetop == 0x40 //rti - || resetop == 0x60 //rts - || resetop == 0x6b //rtl - || resetop == 0xcd //cmp $nnnn - || resetop == 0xec //cpx $nnnn - || resetop == 0xcc //cpy $nnnn - ) score -= 4; - - //least likely opcodes - if(resetop == 0x00 //brk #$nn - || resetop == 0x02 //cop #$nn - || resetop == 0xdb //stp - || resetop == 0x42 //wdm - || resetop == 0xff //sbc $nnnnnn,x - ) score -= 8; - - //at times, both the header and reset vector's first opcode will match ... - //fallback and rely on info validity in these cases to determine more likely header. - - //a valid checksum is the biggest indicator of a valid header. - if((checksum + complement) == 0xffff && (checksum != 0) && (complement != 0)) score += 4; - - if(addr == 0x007fc0 && mapper == 0x20) score += 2; //0x20 is usually LoROM - if(addr == 0x00ffc0 && mapper == 0x21) score += 2; //0x21 is usually HiROM - if(addr == 0x007fc0 && mapper == 0x22) score += 2; //0x22 is usually ExLoROM - if(addr == 0x40ffc0 && mapper == 0x25) score += 2; //0x25 is usually ExHiROM - - if(data[addr + Company] == 0x33) score += 2; //0x33 indicates extended header - if(data[addr + RomType] < 0x08) score++; - if(data[addr + RomSize] < 0x10) score++; - if(data[addr + RamSize] < 0x08) score++; - if(data[addr + CartRegion] < 14) score++; - - if(score < 0) score = 0; - return score; -} - -unsigned XML::gameboy_ram_size(const uint8_t *data, unsigned size) const { - if(size < 512) return 0; - switch(data[0x0149]) { - case 0x00: return 0 * 1024; - case 0x01: return 8 * 1024; - case 0x02: return 8 * 1024; - case 0x03: return 32 * 1024; - case 0x04: return 128 * 1024; - case 0x05: return 128 * 1024; - default: return 128 * 1024; - } -} - -bool XML::gameboy_has_rtc(const uint8_t *data, unsigned size) const { - if(size < 512) return false; - if(data[0x0147] == 0x0f ||data[0x0147] == 0x10) return true; - return false; -} diff --git a/snesreader/xml.hpp b/snesreader/xml.hpp deleted file mode 100644 index c75f8e11..00000000 --- a/snesreader/xml.hpp +++ /dev/null @@ -1,103 +0,0 @@ -class XML { -public: - void generate(nall::string &xml, const uint8_t *data, unsigned size); - -private: - void read_header(const uint8_t *data, unsigned size); - unsigned find_header(const uint8_t *data, unsigned size) const; - unsigned score_header(const uint8_t *data, unsigned size, unsigned addr) const; - - unsigned gameboy_ram_size(const uint8_t *data, unsigned size) const; - bool gameboy_has_rtc(const uint8_t *data, unsigned size) const; - - enum HeaderField { - CartName = 0x00, - Mapper = 0x15, - RomType = 0x16, - RomSize = 0x17, - RamSize = 0x18, - CartRegion = 0x19, - Company = 0x1a, - Version = 0x1b, - Complement = 0x1c, //inverse checksum - Checksum = 0x1e, - ResetVector = 0x3c, - }; - - enum Mode { - ModeNormal, - ModeBsxSlotted, - ModeBsx, - ModeSufamiTurbo, - ModeSuperGameBoy, - }; - - enum Type { - TypeNormal, - TypeBsxSlotted, - TypeBsxBios, - TypeBsx, - TypeSufamiTurboBios, - TypeSufamiTurbo, - TypeSuperGameBoy1Bios, - TypeSuperGameBoy2Bios, - TypeGameBoy, - TypeUnknown, - }; - - enum Region { - NTSC, - PAL, - }; - - enum MemoryMapper { - LoROM, - HiROM, - ExLoROM, - ExHiROM, - SuperFXROM, - SA1ROM, - SPC7110ROM, - BSCLoROM, - BSCHiROM, - BSXROM, - STROM, - }; - - enum DSP1MemoryMapper { - DSP1Unmapped, - DSP1LoROM1MB, - DSP1LoROM2MB, - DSP1HiROM, - }; - - bool loaded; //is a base cartridge inserted? - unsigned crc32; //crc32 of all cartridges (base+slot(s)) - unsigned rom_size; - unsigned ram_size; - - Mode mode; - Type type; - Region region; - MemoryMapper mapper; - DSP1MemoryMapper dsp1_mapper; - - bool has_bsx_slot; - bool has_superfx; - bool has_sa1; - bool has_srtc; - bool has_sdd1; - bool has_spc7110; - bool has_spc7110rtc; - bool has_cx4; - bool has_dsp1; - bool has_dsp2; - bool has_dsp3; - bool has_dsp4; - bool has_obc1; - bool has_st010; - bool has_st011; - bool has_st018; -}; - -extern XML xml; diff --git a/snesreader/zlib/adler32.c b/snesreader/zlib/adler32.c deleted file mode 100644 index 007ba262..00000000 --- a/snesreader/zlib/adler32.c +++ /dev/null @@ -1,149 +0,0 @@ -/* adler32.c -- compute the Adler-32 checksum of a data stream - * Copyright (C) 1995-2004 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#define ZLIB_INTERNAL -#include "zlib.h" - -#define BASE 65521UL /* 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) {adler += (buf)[i]; sum2 += adler;} -#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); - -/* use NO_DIVIDE if your processor does not do division in hardware */ -#ifdef NO_DIVIDE -# define MOD(a) \ - do { \ - if (a >= (BASE << 16)) a -= (BASE << 16); \ - if (a >= (BASE << 15)) a -= (BASE << 15); \ - if (a >= (BASE << 14)) a -= (BASE << 14); \ - if (a >= (BASE << 13)) a -= (BASE << 13); \ - if (a >= (BASE << 12)) a -= (BASE << 12); \ - if (a >= (BASE << 11)) a -= (BASE << 11); \ - if (a >= (BASE << 10)) a -= (BASE << 10); \ - if (a >= (BASE << 9)) a -= (BASE << 9); \ - if (a >= (BASE << 8)) a -= (BASE << 8); \ - if (a >= (BASE << 7)) a -= (BASE << 7); \ - if (a >= (BASE << 6)) a -= (BASE << 6); \ - if (a >= (BASE << 5)) a -= (BASE << 5); \ - if (a >= (BASE << 4)) a -= (BASE << 4); \ - if (a >= (BASE << 3)) a -= (BASE << 3); \ - if (a >= (BASE << 2)) a -= (BASE << 2); \ - if (a >= (BASE << 1)) a -= (BASE << 1); \ - if (a >= BASE) a -= BASE; \ - } while (0) -# define MOD4(a) \ - do { \ - if (a >= (BASE << 4)) a -= (BASE << 4); \ - if (a >= (BASE << 3)) a -= (BASE << 3); \ - if (a >= (BASE << 2)) a -= (BASE << 2); \ - if (a >= (BASE << 1)) a -= (BASE << 1); \ - if (a >= BASE) a -= BASE; \ - } while (0) -#else -# define MOD(a) a %= BASE -# define MOD4(a) a %= BASE -#endif - -/* ========================================================================= */ -uLong ZEXPORT adler32(adler, buf, len) - uLong adler; - const Bytef *buf; - uInt len; -{ - unsigned long sum2; - unsigned n; - - /* split Adler-32 into component sums */ - sum2 = (adler >> 16) & 0xffff; - adler &= 0xffff; - - /* in case user likes doing a byte at a time, keep it fast */ - if (len == 1) { - adler += buf[0]; - if (adler >= BASE) - adler -= BASE; - sum2 += adler; - if (sum2 >= BASE) - sum2 -= BASE; - return adler | (sum2 << 16); - } - - /* initial Adler-32 value (deferred check for len == 1 speed) */ - if (buf == Z_NULL) - return 1L; - - /* in case short lengths are provided, keep it somewhat fast */ - if (len < 16) { - while (len--) { - adler += *buf++; - sum2 += adler; - } - if (adler >= BASE) - adler -= BASE; - MOD4(sum2); /* only added so many BASE's */ - return adler | (sum2 << 16); - } - - /* do length NMAX blocks -- requires just one modulo operation */ - while (len >= NMAX) { - len -= NMAX; - n = NMAX / 16; /* NMAX is divisible by 16 */ - do { - DO16(buf); /* 16 sums unrolled */ - buf += 16; - } while (--n); - MOD(adler); - MOD(sum2); - } - - /* do remaining bytes (less than NMAX, still just one modulo) */ - if (len) { /* avoid modulos if none remaining */ - while (len >= 16) { - len -= 16; - DO16(buf); - buf += 16; - } - while (len--) { - adler += *buf++; - sum2 += adler; - } - MOD(adler); - MOD(sum2); - } - - /* return recombined sums */ - return adler | (sum2 << 16); -} - -/* ========================================================================= */ -uLong ZEXPORT adler32_combine(adler1, adler2, len2) - uLong adler1; - uLong adler2; - z_off_t len2; -{ - unsigned long sum1; - unsigned long sum2; - unsigned rem; - - /* the derivation of this formula is left as an exercise for the reader */ - rem = (unsigned)(len2 % BASE); - sum1 = adler1 & 0xffff; - sum2 = rem * sum1; - MOD(sum2); - sum1 += (adler2 & 0xffff) + BASE - 1; - sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; - if (sum1 > BASE) sum1 -= BASE; - if (sum1 > BASE) sum1 -= BASE; - if (sum2 > (BASE << 1)) sum2 -= (BASE << 1); - if (sum2 > BASE) sum2 -= BASE; - return sum1 | (sum2 << 16); -} diff --git a/snesreader/zlib/crc32.c b/snesreader/zlib/crc32.c deleted file mode 100644 index f658a9ef..00000000 --- a/snesreader/zlib/crc32.c +++ /dev/null @@ -1,423 +0,0 @@ -/* crc32.c -- compute the CRC-32 of a data stream - * Copyright (C) 1995-2005 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - * - * Thanks to Rodney Brown for his contribution of faster - * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing - * tables for updating the shift register in one step with three exclusive-ors - * instead of four steps with four exclusive-ors. This results in about a - * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. - */ - -/* @(#) $Id$ */ - -/* - Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore - protection on the static variables used to control the first-use generation - of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should - first call get_crc_table() to initialize the tables before allowing more than - one thread to use crc32(). - */ - -#ifdef MAKECRCH -# include -# ifndef DYNAMIC_CRC_TABLE -# define DYNAMIC_CRC_TABLE -# endif /* !DYNAMIC_CRC_TABLE */ -#endif /* MAKECRCH */ - -#include "zutil.h" /* for STDC and FAR definitions */ - -#define local static - -/* Find a four-byte integer type for crc32_little() and crc32_big(). */ -#ifndef NOBYFOUR -# ifdef STDC /* need ANSI C limits.h to determine sizes */ -# include -# define BYFOUR -# if (UINT_MAX == 0xffffffffUL) - typedef unsigned int u4; -# else -# if (ULONG_MAX == 0xffffffffUL) - typedef unsigned long u4; -# else -# if (USHRT_MAX == 0xffffffffUL) - typedef unsigned short u4; -# else -# undef BYFOUR /* can't find a four-byte integer type! */ -# endif -# endif -# endif -# endif /* STDC */ -#endif /* !NOBYFOUR */ - -/* Definitions for doing the crc four data bytes at a time. */ -#ifdef BYFOUR -# define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \ - (((w)&0xff00)<<8)+(((w)&0xff)<<24)) - local unsigned long crc32_little OF((unsigned long, - const unsigned char FAR *, unsigned)); - local unsigned long crc32_big OF((unsigned long, - const unsigned char FAR *, unsigned)); -# define TBLS 8 -#else -# define TBLS 1 -#endif /* BYFOUR */ - -/* Local functions for crc concatenation */ -local unsigned long gf2_matrix_times OF((unsigned long *mat, - unsigned long vec)); -local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); - -#ifdef DYNAMIC_CRC_TABLE - -local volatile int crc_table_empty = 1; -local unsigned long FAR crc_table[TBLS][256]; -local void make_crc_table OF((void)); -#ifdef MAKECRCH - local void write_table OF((FILE *, const unsigned long FAR *)); -#endif /* MAKECRCH */ -/* - Generate tables 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 first table is simply the CRC of all possible eight bit values. This is - all the information needed to generate CRCs on data a byte at a time for all - combinations of CRC register values and incoming bytes. The remaining tables - allow for word-at-a-time CRC calculation for both big-endian and little- - endian machines, where a word is four bytes. -*/ -local void make_crc_table() -{ - unsigned long c; - int n, k; - unsigned long poly; /* polynomial exclusive-or pattern */ - /* terms of polynomial defining this crc (except x^32): */ - static volatile int first = 1; /* flag to limit concurrent making */ - static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; - - /* See if another task is already doing this (not thread-safe, but better - than nothing -- significantly reduces duration of vulnerability in - case the advice about DYNAMIC_CRC_TABLE is ignored) */ - if (first) { - first = 0; - - /* make exclusive-or pattern from polynomial (0xedb88320UL) */ - poly = 0UL; - for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++) - poly |= 1UL << (31 - p[n]); - - /* generate a crc for every 8-bit value */ - for (n = 0; n < 256; n++) { - c = (unsigned long)n; - for (k = 0; k < 8; k++) - c = c & 1 ? poly ^ (c >> 1) : c >> 1; - crc_table[0][n] = c; - } - -#ifdef BYFOUR - /* generate crc for each value followed by one, two, and three zeros, - and then the byte reversal of those as well as the first table */ - for (n = 0; n < 256; n++) { - c = crc_table[0][n]; - crc_table[4][n] = REV(c); - for (k = 1; k < 4; k++) { - c = crc_table[0][c & 0xff] ^ (c >> 8); - crc_table[k][n] = c; - crc_table[k + 4][n] = REV(c); - } - } -#endif /* BYFOUR */ - - crc_table_empty = 0; - } - else { /* not first */ - /* wait for the other guy to finish (not efficient, but rare) */ - while (crc_table_empty) - ; - } - -#ifdef MAKECRCH - /* write out CRC tables to crc32.h */ - { - FILE *out; - - out = fopen("crc32.h", "w"); - if (out == NULL) return; - fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); - fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); - fprintf(out, "local const unsigned long FAR "); - fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); - write_table(out, crc_table[0]); -# ifdef BYFOUR - fprintf(out, "#ifdef BYFOUR\n"); - for (k = 1; k < 8; k++) { - fprintf(out, " },\n {\n"); - write_table(out, crc_table[k]); - } - fprintf(out, "#endif\n"); -# endif /* BYFOUR */ - fprintf(out, " }\n};\n"); - fclose(out); - } -#endif /* MAKECRCH */ -} - -#ifdef MAKECRCH -local void write_table(out, table) - FILE *out; - const unsigned long FAR *table; -{ - int n; - - for (n = 0; n < 256; n++) - fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n], - n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); -} -#endif /* MAKECRCH */ - -#else /* !DYNAMIC_CRC_TABLE */ -/* ======================================================================== - * Tables of CRC-32s of all single-byte values, made by make_crc_table(). - */ -#include "crc32.h" -#endif /* DYNAMIC_CRC_TABLE */ - -/* ========================================================================= - * This function can be used by asm versions of crc32() - */ -const unsigned long FAR * ZEXPORT get_crc_table() -{ -#ifdef DYNAMIC_CRC_TABLE - if (crc_table_empty) - make_crc_table(); -#endif /* DYNAMIC_CRC_TABLE */ - return (const unsigned long FAR *)crc_table; -} - -/* ========================================================================= */ -#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) -#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 - -/* ========================================================================= */ -unsigned long ZEXPORT crc32(crc, buf, len) - unsigned long crc; - const unsigned char FAR *buf; - unsigned len; -{ - if (buf == Z_NULL) return 0UL; - -#ifdef DYNAMIC_CRC_TABLE - if (crc_table_empty) - make_crc_table(); -#endif /* DYNAMIC_CRC_TABLE */ - -#ifdef BYFOUR - if (sizeof(void *) == sizeof(ptrdiff_t)) { - u4 endian; - - endian = 1; - if (*((unsigned char *)(&endian))) - return crc32_little(crc, buf, len); - else - return crc32_big(crc, buf, len); - } -#endif /* BYFOUR */ - crc = crc ^ 0xffffffffUL; - while (len >= 8) { - DO8; - len -= 8; - } - if (len) do { - DO1; - } while (--len); - return crc ^ 0xffffffffUL; -} - -#ifdef BYFOUR - -/* ========================================================================= */ -#define DOLIT4 c ^= *buf4++; \ - c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ - crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] -#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 - -/* ========================================================================= */ -local unsigned long crc32_little(crc, buf, len) - unsigned long crc; - const unsigned char FAR *buf; - unsigned len; -{ - register u4 c; - register const u4 FAR *buf4; - - c = (u4)crc; - c = ~c; - while (len && ((ptrdiff_t)buf & 3)) { - c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); - len--; - } - - buf4 = (const u4 FAR *)(const void FAR *)buf; - while (len >= 32) { - DOLIT32; - len -= 32; - } - while (len >= 4) { - DOLIT4; - len -= 4; - } - buf = (const unsigned char FAR *)buf4; - - if (len) do { - c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); - } while (--len); - c = ~c; - return (unsigned long)c; -} - -/* ========================================================================= */ -#define DOBIG4 c ^= *++buf4; \ - c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ - crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] -#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 - -/* ========================================================================= */ -local unsigned long crc32_big(crc, buf, len) - unsigned long crc; - const unsigned char FAR *buf; - unsigned len; -{ - register u4 c; - register const u4 FAR *buf4; - - c = REV((u4)crc); - c = ~c; - while (len && ((ptrdiff_t)buf & 3)) { - c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); - len--; - } - - buf4 = (const u4 FAR *)(const void FAR *)buf; - buf4--; - while (len >= 32) { - DOBIG32; - len -= 32; - } - while (len >= 4) { - DOBIG4; - len -= 4; - } - buf4++; - buf = (const unsigned char FAR *)buf4; - - if (len) do { - c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); - } while (--len); - c = ~c; - return (unsigned long)(REV(c)); -} - -#endif /* BYFOUR */ - -#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ - -/* ========================================================================= */ -local unsigned long gf2_matrix_times(mat, vec) - unsigned long *mat; - unsigned long vec; -{ - unsigned long sum; - - sum = 0; - while (vec) { - if (vec & 1) - sum ^= *mat; - vec >>= 1; - mat++; - } - return sum; -} - -/* ========================================================================= */ -local void gf2_matrix_square(square, mat) - unsigned long *square; - unsigned long *mat; -{ - int n; - - for (n = 0; n < GF2_DIM; n++) - square[n] = gf2_matrix_times(mat, mat[n]); -} - -/* ========================================================================= */ -uLong ZEXPORT crc32_combine(crc1, crc2, len2) - uLong crc1; - uLong crc2; - z_off_t len2; -{ - int n; - unsigned long row; - unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ - unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ - - /* degenerate case */ - if (len2 == 0) - return crc1; - - /* put operator for one zero bit in odd */ - odd[0] = 0xedb88320L; /* CRC-32 polynomial */ - row = 1; - for (n = 1; n < GF2_DIM; n++) { - odd[n] = row; - row <<= 1; - } - - /* put operator for two zero bits in even */ - gf2_matrix_square(even, odd); - - /* put operator for four zero bits in odd */ - gf2_matrix_square(odd, even); - - /* apply len2 zeros to crc1 (first square will put the operator for one - zero byte, eight zero bits, in even) */ - do { - /* apply zeros operator for this bit of len2 */ - gf2_matrix_square(even, odd); - if (len2 & 1) - crc1 = gf2_matrix_times(even, crc1); - len2 >>= 1; - - /* if no more bits set, then done */ - if (len2 == 0) - break; - - /* another iteration of the loop with odd and even swapped */ - gf2_matrix_square(odd, even); - if (len2 & 1) - crc1 = gf2_matrix_times(odd, crc1); - len2 >>= 1; - - /* if no more bits set, then done */ - } while (len2 != 0); - - /* return combined crc */ - crc1 ^= crc2; - return crc1; -} diff --git a/snesreader/zlib/crc32.h b/snesreader/zlib/crc32.h deleted file mode 100644 index 8053b611..00000000 --- a/snesreader/zlib/crc32.h +++ /dev/null @@ -1,441 +0,0 @@ -/* crc32.h -- tables for rapid CRC calculation - * Generated automatically by crc32.c - */ - -local const unsigned long FAR crc_table[TBLS][256] = -{ - { - 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, - 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, - 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, - 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, - 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, - 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, - 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, - 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, - 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, - 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, - 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, - 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, - 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, - 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, - 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, - 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, - 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, - 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, - 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, - 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, - 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, - 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, - 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, - 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, - 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, - 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, - 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, - 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, - 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, - 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, - 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, - 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, - 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, - 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, - 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, - 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, - 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, - 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, - 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, - 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, - 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, - 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, - 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, - 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, - 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, - 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, - 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, - 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, - 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, - 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, - 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, - 0x2d02ef8dUL -#ifdef BYFOUR - }, - { - 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, - 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, - 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, - 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, - 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, - 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, - 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, - 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, - 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, - 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, - 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, - 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, - 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, - 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, - 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, - 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, - 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, - 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, - 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, - 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, - 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, - 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, - 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, - 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, - 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, - 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, - 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, - 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, - 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, - 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, - 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, - 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, - 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, - 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, - 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, - 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, - 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, - 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, - 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, - 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, - 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, - 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, - 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, - 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, - 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, - 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, - 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, - 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, - 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, - 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, - 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, - 0x9324fd72UL - }, - { - 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, - 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, - 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, - 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, - 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, - 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, - 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, - 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, - 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, - 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, - 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, - 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, - 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, - 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, - 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, - 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, - 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, - 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, - 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, - 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, - 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, - 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, - 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, - 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, - 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, - 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, - 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, - 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, - 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, - 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, - 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, - 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, - 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, - 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, - 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, - 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, - 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, - 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, - 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, - 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, - 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, - 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, - 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, - 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, - 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, - 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, - 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, - 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, - 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, - 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, - 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, - 0xbe9834edUL - }, - { - 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, - 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, - 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, - 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, - 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, - 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, - 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, - 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, - 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, - 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, - 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, - 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, - 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, - 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, - 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, - 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, - 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, - 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, - 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, - 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, - 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, - 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, - 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, - 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, - 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, - 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, - 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, - 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, - 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, - 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, - 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, - 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, - 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, - 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, - 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, - 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, - 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, - 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, - 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, - 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, - 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, - 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, - 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, - 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, - 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, - 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, - 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, - 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, - 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, - 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, - 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, - 0xde0506f1UL - }, - { - 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, - 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, - 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, - 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, - 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, - 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, - 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, - 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, - 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, - 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, - 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, - 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, - 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, - 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, - 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, - 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, - 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, - 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, - 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, - 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, - 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, - 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, - 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, - 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, - 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, - 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, - 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, - 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, - 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, - 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, - 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, - 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, - 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, - 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, - 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, - 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, - 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, - 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, - 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, - 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, - 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, - 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, - 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, - 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, - 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, - 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, - 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, - 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, - 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, - 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, - 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, - 0x8def022dUL - }, - { - 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, - 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, - 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, - 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, - 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, - 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, - 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, - 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, - 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, - 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, - 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, - 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, - 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, - 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, - 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, - 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, - 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, - 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, - 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, - 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, - 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, - 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, - 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, - 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, - 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, - 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, - 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, - 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, - 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, - 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, - 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, - 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, - 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, - 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, - 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, - 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, - 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, - 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, - 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, - 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, - 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, - 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, - 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, - 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, - 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, - 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, - 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, - 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, - 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, - 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, - 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, - 0x72fd2493UL - }, - { - 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, - 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, - 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, - 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, - 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, - 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, - 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, - 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, - 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, - 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, - 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, - 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, - 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, - 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, - 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, - 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, - 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, - 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, - 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, - 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, - 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, - 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, - 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, - 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, - 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, - 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, - 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, - 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, - 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, - 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, - 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, - 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, - 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, - 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, - 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, - 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, - 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, - 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, - 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, - 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, - 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, - 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, - 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, - 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, - 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, - 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, - 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, - 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, - 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, - 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, - 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, - 0xed3498beUL - }, - { - 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, - 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, - 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, - 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, - 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, - 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, - 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, - 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, - 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, - 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, - 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, - 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, - 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, - 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, - 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, - 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, - 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, - 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, - 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, - 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, - 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, - 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, - 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, - 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, - 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, - 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, - 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, - 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, - 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, - 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, - 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, - 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, - 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, - 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, - 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, - 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, - 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, - 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, - 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, - 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, - 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, - 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, - 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, - 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, - 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, - 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, - 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, - 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, - 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, - 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, - 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, - 0xf10605deUL -#endif - } -}; diff --git a/snesreader/zlib/inffast.c b/snesreader/zlib/inffast.c deleted file mode 100644 index 7a148eb7..00000000 --- a/snesreader/zlib/inffast.c +++ /dev/null @@ -1,318 +0,0 @@ -/* inffast.c -- fast decoding - * Copyright (C) 1995-2004 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zutil.h" -#include "inftrees.h" -#include "inflate.h" -#include "inffast.h" - -#ifndef ASMINF - -/* Allow machine dependent optimization for post-increment or pre-increment. - Based on testing to date, - Pre-increment preferred for: - - PowerPC G3 (Adler) - - MIPS R5000 (Randers-Pehrson) - Post-increment preferred for: - - none - No measurable difference: - - Pentium III (Anderson) - - M68060 (Nikl) - */ -#ifdef POSTINC -# define OFF 0 -# define PUP(a) *(a)++ -#else -# define OFF 1 -# define PUP(a) *++(a) -#endif - -/* - Decode literal, length, and distance codes and write out the resulting - literal and match bytes until either not enough input or output is - available, an end-of-block is encountered, or a data error is encountered. - When large enough input and output buffers are supplied to inflate(), for - example, a 16K input buffer and a 64K output buffer, more than 95% of the - inflate execution time is spent in this routine. - - Entry assumptions: - - state->mode == LEN - strm->avail_in >= 6 - strm->avail_out >= 258 - start >= strm->avail_out - state->bits < 8 - - On return, state->mode is one of: - - LEN -- ran out of enough output space or enough available input - TYPE -- reached end of block code, inflate() to interpret next block - BAD -- error in block data - - Notes: - - - The maximum input bits used by a length/distance pair is 15 bits for the - length code, 5 bits for the length extra, 15 bits for the distance code, - and 13 bits for the distance extra. This totals 48 bits, or six bytes. - Therefore if strm->avail_in >= 6, then there is enough input to avoid - checking for available input while decoding. - - - The maximum bytes that a single length/distance pair can output is 258 - bytes, which is the maximum length that can be coded. inflate_fast() - requires strm->avail_out >= 258 for each loop to avoid checking for - output space. - */ -void inflate_fast(strm, start) -z_streamp strm; -unsigned start; /* inflate()'s starting value for strm->avail_out */ -{ - struct inflate_state FAR *state; - unsigned char FAR *in; /* local strm->next_in */ - unsigned char FAR *last; /* while in < last, enough input available */ - unsigned char FAR *out; /* local strm->next_out */ - unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ - unsigned char FAR *end; /* while out < end, enough space available */ -#ifdef INFLATE_STRICT - unsigned dmax; /* maximum distance from zlib header */ -#endif - unsigned wsize; /* window size or zero if not using window */ - unsigned whave; /* valid bytes in the window */ - unsigned write; /* window write index */ - unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ - unsigned long hold; /* local strm->hold */ - unsigned bits; /* local strm->bits */ - code const FAR *lcode; /* local strm->lencode */ - code const FAR *dcode; /* local strm->distcode */ - unsigned lmask; /* mask for first level of length codes */ - unsigned dmask; /* mask for first level of distance codes */ - code this; /* retrieved table entry */ - unsigned op; /* code bits, operation, extra bits, or */ - /* window position, window bytes to copy */ - unsigned len; /* match length, unused bytes */ - unsigned dist; /* match distance */ - unsigned char FAR *from; /* where to copy match from */ - - /* copy state to local variables */ - state = (struct inflate_state FAR *)strm->state; - in = strm->next_in - OFF; - last = in + (strm->avail_in - 5); - out = strm->next_out - OFF; - beg = out - (start - strm->avail_out); - end = out + (strm->avail_out - 257); -#ifdef INFLATE_STRICT - dmax = state->dmax; -#endif - wsize = state->wsize; - whave = state->whave; - write = state->write; - window = state->window; - hold = state->hold; - bits = state->bits; - lcode = state->lencode; - dcode = state->distcode; - lmask = (1U << state->lenbits) - 1; - dmask = (1U << state->distbits) - 1; - - /* decode literals and length/distances until end-of-block or not enough - input data or output space */ - do { - if (bits < 15) { - hold += (unsigned long)(PUP(in)) << bits; - bits += 8; - hold += (unsigned long)(PUP(in)) << bits; - bits += 8; - } - this = lcode[hold & lmask]; - dolen: - op = (unsigned)(this.bits); - hold >>= op; - bits -= op; - op = (unsigned)(this.op); - if (op == 0) { /* literal */ - Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? - "inflate: literal '%c'\n" : - "inflate: literal 0x%02x\n", this.val)); - PUP(out) = (unsigned char)(this.val); - } - else if (op & 16) { /* length base */ - len = (unsigned)(this.val); - op &= 15; /* number of extra bits */ - if (op) { - if (bits < op) { - hold += (unsigned long)(PUP(in)) << bits; - bits += 8; - } - len += (unsigned)hold & ((1U << op) - 1); - hold >>= op; - bits -= op; - } - Tracevv((stderr, "inflate: length %u\n", len)); - if (bits < 15) { - hold += (unsigned long)(PUP(in)) << bits; - bits += 8; - hold += (unsigned long)(PUP(in)) << bits; - bits += 8; - } - this = dcode[hold & dmask]; - dodist: - op = (unsigned)(this.bits); - hold >>= op; - bits -= op; - op = (unsigned)(this.op); - if (op & 16) { /* distance base */ - dist = (unsigned)(this.val); - op &= 15; /* number of extra bits */ - if (bits < op) { - hold += (unsigned long)(PUP(in)) << bits; - bits += 8; - if (bits < op) { - hold += (unsigned long)(PUP(in)) << bits; - bits += 8; - } - } - dist += (unsigned)hold & ((1U << op) - 1); -#ifdef INFLATE_STRICT - if (dist > dmax) { - strm->msg = "invalid distance too far back"; - state->mode = BAD; - break; - } -#endif - hold >>= op; - bits -= op; - Tracevv((stderr, "inflate: distance %u\n", dist)); - op = (unsigned)(out - beg); /* max distance in output */ - if (dist > op) { /* see if copy from window */ - op = dist - op; /* distance back in window */ - if (op > whave) { - strm->msg = "invalid distance too far back"; - state->mode = BAD; - break; - } - from = window - OFF; - if (write == 0) { /* very common case */ - from += wsize - op; - if (op < len) { /* some from window */ - len -= op; - do { - PUP(out) = PUP(from); - } while (--op); - from = out - dist; /* rest from output */ - } - } - else if (write < op) { /* wrap around window */ - from += wsize + write - op; - op -= write; - if (op < len) { /* some from end of window */ - len -= op; - do { - PUP(out) = PUP(from); - } while (--op); - from = window - OFF; - if (write < len) { /* some from start of window */ - op = write; - len -= op; - do { - PUP(out) = PUP(from); - } while (--op); - from = out - dist; /* rest from output */ - } - } - } - else { /* contiguous in window */ - from += write - op; - if (op < len) { /* some from window */ - len -= op; - do { - PUP(out) = PUP(from); - } while (--op); - from = out - dist; /* rest from output */ - } - } - while (len > 2) { - PUP(out) = PUP(from); - PUP(out) = PUP(from); - PUP(out) = PUP(from); - len -= 3; - } - if (len) { - PUP(out) = PUP(from); - if (len > 1) - PUP(out) = PUP(from); - } - } - else { - from = out - dist; /* copy direct from output */ - do { /* minimum length is three */ - PUP(out) = PUP(from); - PUP(out) = PUP(from); - PUP(out) = PUP(from); - len -= 3; - } while (len > 2); - if (len) { - PUP(out) = PUP(from); - if (len > 1) - PUP(out) = PUP(from); - } - } - } - else if ((op & 64) == 0) { /* 2nd level distance code */ - this = dcode[this.val + (hold & ((1U << op) - 1))]; - goto dodist; - } - else { - strm->msg = "invalid distance code"; - state->mode = BAD; - break; - } - } - else if ((op & 64) == 0) { /* 2nd level length code */ - this = lcode[this.val + (hold & ((1U << op) - 1))]; - goto dolen; - } - else if (op & 32) { /* end-of-block */ - Tracevv((stderr, "inflate: end of block\n")); - state->mode = TYPE; - break; - } - else { - strm->msg = "invalid literal/length code"; - state->mode = BAD; - break; - } - } while (in < last && out < end); - - /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ - len = bits >> 3; - in -= len; - bits -= len << 3; - hold &= (1U << bits) - 1; - - /* update state and return */ - strm->next_in = in + OFF; - strm->next_out = out + OFF; - strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); - strm->avail_out = (unsigned)(out < end ? - 257 + (end - out) : 257 - (out - end)); - state->hold = hold; - state->bits = bits; - return; -} - -/* - inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): - - Using bit fields for code structure - - Different op definition to avoid & for extra bits (do & for table bits) - - Three separate decoding do-loops for direct, window, and write == 0 - - Special case for distance > 1 copies to do overlapped load and store copy - - Explicit branch predictions (based on measured branch probabilities) - - Deferring match copy and interspersed it with decoding subsequent codes - - Swapping literal/length else - - Swapping window/direct else - - Larger unrolled copy loops (three is about right) - - Moving len -= 3 statement into middle of loop - */ - -#endif /* !ASMINF */ diff --git a/snesreader/zlib/inffast.h b/snesreader/zlib/inffast.h deleted file mode 100644 index 1e88d2d9..00000000 --- a/snesreader/zlib/inffast.h +++ /dev/null @@ -1,11 +0,0 @@ -/* inffast.h -- header to use inffast.c - * Copyright (C) 1995-2003 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. - */ - -void inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/snesreader/zlib/inffixed.h b/snesreader/zlib/inffixed.h deleted file mode 100644 index 75ed4b59..00000000 --- a/snesreader/zlib/inffixed.h +++ /dev/null @@ -1,94 +0,0 @@ - /* inffixed.h -- table for decoding fixed codes - * Generated automatically by makefixed(). - */ - - /* 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. - */ - - static const code lenfix[512] = { - {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, - {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, - {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, - {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, - {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, - {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, - {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, - {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, - {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, - {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, - {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, - {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, - {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, - {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, - {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, - {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, - {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, - {0,9,220},{18,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,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, - {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, - {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, - {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, - {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, - {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, - {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, - {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, - {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, - {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, - {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, - {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, - {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, - {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, - {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, - {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, - {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, - {0,8,127},{0,8,63},{0,9,222},{18,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,0},{0,8,80},{0,8,16}, - {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, - {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, - {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, - {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, - {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, - {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, - {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, - {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, - {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, - {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, - {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, - {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, - {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, - {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, - {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, - {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, - {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,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,0}, - {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, - {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, - {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, - {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, - {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, - {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, - {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, - {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, - {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, - {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, - {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, - {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, - {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, - {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, - {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, - {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, - {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, - {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, - {0,9,255} - }; - - static const code distfix[32] = { - {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, - {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, - {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, - {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, - {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, - {22,5,193},{64,5,0} - }; diff --git a/snesreader/zlib/inflate.c b/snesreader/zlib/inflate.c deleted file mode 100644 index 37744b3e..00000000 --- a/snesreader/zlib/inflate.c +++ /dev/null @@ -1,1368 +0,0 @@ -/* inflate.c -- zlib decompression - * Copyright (C) 1995-2005 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* - * Change history: - * - * 1.2.beta0 24 Nov 2002 - * - First version -- complete rewrite of inflate to simplify code, avoid - * creation of window when not needed, minimize use of window when it is - * needed, make inffast.c even faster, implement gzip decoding, and to - * improve code readability and style over the previous zlib inflate code - * - * 1.2.beta1 25 Nov 2002 - * - Use pointers for available input and output checking in inffast.c - * - Remove input and output counters in inffast.c - * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 - * - Remove unnecessary second byte pull from length extra in inffast.c - * - Unroll direct copy to three copies per loop in inffast.c - * - * 1.2.beta2 4 Dec 2002 - * - Change external routine names to reduce potential conflicts - * - Correct filename to inffixed.h for fixed tables in inflate.c - * - Make hbuf[] unsigned char to match parameter type in inflate.c - * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) - * to avoid negation problem on Alphas (64 bit) in inflate.c - * - * 1.2.beta3 22 Dec 2002 - * - Add comments on state->bits assertion in inffast.c - * - Add comments on op field in inftrees.h - * - Fix bug in reuse of allocated window after inflateReset() - * - Remove bit fields--back to byte structure for speed - * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths - * - Change post-increments to pre-increments in inflate_fast(), PPC biased? - * - Add compile time option, POSTINC, to use post-increments instead (Intel?) - * - Make MATCH copy in inflate() much faster for when inflate_fast() not used - * - Use local copies of stream next and avail values, as well as local bit - * buffer and bit count in inflate()--for speed when inflate_fast() not used - * - * 1.2.beta4 1 Jan 2003 - * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings - * - Move a comment on output buffer sizes from inffast.c to inflate.c - * - Add comments in inffast.c to introduce the inflate_fast() routine - * - Rearrange window copies in inflate_fast() for speed and simplification - * - Unroll last copy for window match in inflate_fast() - * - Use local copies of window variables in inflate_fast() for speed - * - Pull out common write == 0 case for speed in inflate_fast() - * - Make op and len in inflate_fast() unsigned for consistency - * - Add FAR to lcode and dcode declarations in inflate_fast() - * - Simplified bad distance check in inflate_fast() - * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new - * source file infback.c to provide a call-back interface to inflate for - * programs like gzip and unzip -- uses window as output buffer to avoid - * window copying - * - * 1.2.beta5 1 Jan 2003 - * - Improved inflateBack() interface to allow the caller to provide initial - * input in strm. - * - Fixed stored blocks bug in inflateBack() - * - * 1.2.beta6 4 Jan 2003 - * - Added comments in inffast.c on effectiveness of POSTINC - * - Typecasting all around to reduce compiler warnings - * - Changed loops from while (1) or do {} while (1) to for (;;), again to - * make compilers happy - * - Changed type of window in inflateBackInit() to unsigned char * - * - * 1.2.beta7 27 Jan 2003 - * - Changed many types to unsigned or unsigned short to avoid warnings - * - Added inflateCopy() function - * - * 1.2.0 9 Mar 2003 - * - Changed inflateBack() interface to provide separate opaque descriptors - * for the in() and out() functions - * - Changed inflateBack() argument and in_func typedef to swap the length - * and buffer address return values for the input function - * - Check next_in and next_out for Z_NULL on entry to inflate() - * - * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. - */ - -#include "zutil.h" -#include "inftrees.h" -#include "inflate.h" -#include "inffast.h" - -#ifdef MAKEFIXED -# ifndef BUILDFIXED -# define BUILDFIXED -# endif -#endif - -/* function prototypes */ -local void fixedtables OF((struct inflate_state FAR *state)); -local int updatewindow OF((z_streamp strm, unsigned out)); -#ifdef BUILDFIXED - void makefixed OF((void)); -#endif -local unsigned syncsearch OF((unsigned FAR *have, unsigned char FAR *buf, - unsigned len)); - -int ZEXPORT inflateReset(strm) -z_streamp strm; -{ - struct inflate_state FAR *state; - - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - strm->total_in = strm->total_out = state->total = 0; - strm->msg = Z_NULL; - strm->adler = 1; /* to support ill-conceived Java test suite */ - state->mode = HEAD; - state->last = 0; - state->havedict = 0; - state->dmax = 32768U; - state->head = Z_NULL; - state->wsize = 0; - state->whave = 0; - state->write = 0; - state->hold = 0; - state->bits = 0; - state->lencode = state->distcode = state->next = state->codes; - Tracev((stderr, "inflate: reset\n")); - return Z_OK; -} - -int ZEXPORT inflatePrime(strm, bits, value) -z_streamp strm; -int bits; -int value; -{ - struct inflate_state FAR *state; - - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - if (bits > 16 || state->bits + bits > 32) return Z_STREAM_ERROR; - value &= (1L << bits) - 1; - state->hold += value << state->bits; - state->bits += bits; - return Z_OK; -} - -int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) -z_streamp strm; -int windowBits; -const char *version; -int stream_size; -{ - struct inflate_state FAR *state; - - if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || - stream_size != (int)(sizeof(z_stream))) - return Z_VERSION_ERROR; - if (strm == Z_NULL) return Z_STREAM_ERROR; - strm->msg = Z_NULL; /* in case we return an error */ - if (strm->zalloc == (alloc_func)0) { - strm->zalloc = zcalloc; - strm->opaque = (voidpf)0; - } - if (strm->zfree == (free_func)0) strm->zfree = zcfree; - state = (struct inflate_state FAR *) - ZALLOC(strm, 1, sizeof(struct inflate_state)); - if (state == Z_NULL) return Z_MEM_ERROR; - Tracev((stderr, "inflate: allocated\n")); - strm->state = (struct internal_state FAR *)state; - if (windowBits < 0) { - state->wrap = 0; - windowBits = -windowBits; - } - else { - state->wrap = (windowBits >> 4) + 1; -#ifdef GUNZIP - if (windowBits < 48) windowBits &= 15; -#endif - } - if (windowBits < 8 || windowBits > 15) { - ZFREE(strm, state); - strm->state = Z_NULL; - return Z_STREAM_ERROR; - } - state->wbits = (unsigned)windowBits; - state->window = Z_NULL; - return inflateReset(strm); -} - -int ZEXPORT inflateInit_(strm, version, stream_size) -z_streamp strm; -const char *version; -int stream_size; -{ - return inflateInit2_(strm, DEF_WBITS, version, stream_size); -} - -/* - Return state with length and distance decoding tables and index sizes set to - fixed code decoding. Normally this returns fixed tables from inffixed.h. - If BUILDFIXED is defined, then instead this routine builds the tables the - first time it's called, and returns those tables the first time and - thereafter. This reduces the size of the code by about 2K bytes, in - exchange for a little execution time. However, BUILDFIXED should not be - used for threaded applications, since the rewriting of the tables and virgin - may not be thread-safe. - */ -local void fixedtables(state) -struct inflate_state FAR *state; -{ -#ifdef BUILDFIXED - static int virgin = 1; - static code *lenfix, *distfix; - static code fixed[544]; - - /* build fixed huffman tables if first call (may not be thread safe) */ - if (virgin) { - unsigned sym, bits; - static code *next; - - /* literal/length table */ - sym = 0; - while (sym < 144) state->lens[sym++] = 8; - while (sym < 256) state->lens[sym++] = 9; - while (sym < 280) state->lens[sym++] = 7; - while (sym < 288) state->lens[sym++] = 8; - next = fixed; - lenfix = next; - bits = 9; - inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); - - /* distance table */ - sym = 0; - while (sym < 32) state->lens[sym++] = 5; - distfix = next; - bits = 5; - inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); - - /* do this just once */ - virgin = 0; - } -#else /* !BUILDFIXED */ -# include "inffixed.h" -#endif /* BUILDFIXED */ - state->lencode = lenfix; - state->lenbits = 9; - state->distcode = distfix; - state->distbits = 5; -} - -#ifdef MAKEFIXED -#include - -/* - Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also - defines BUILDFIXED, so the tables are built on the fly. makefixed() writes - those tables to stdout, which would be piped to inffixed.h. A small program - can simply call makefixed to do this: - - void makefixed(void); - - int main(void) - { - makefixed(); - return 0; - } - - Then that can be linked with zlib built with MAKEFIXED defined and run: - - a.out > inffixed.h - */ -void makefixed() -{ - unsigned low, size; - struct inflate_state state; - - fixedtables(&state); - puts(" /* inffixed.h -- table for decoding fixed codes"); - puts(" * Generated automatically by makefixed()."); - puts(" */"); - puts(""); - puts(" /* WARNING: this file should *not* be used by applications."); - puts(" It is part of the implementation of this library and is"); - puts(" subject to change. Applications should only use zlib.h."); - puts(" */"); - puts(""); - size = 1U << 9; - printf(" static const code lenfix[%u] = {", size); - low = 0; - for (;;) { - if ((low % 7) == 0) printf("\n "); - printf("{%u,%u,%d}", state.lencode[low].op, state.lencode[low].bits, - state.lencode[low].val); - if (++low == size) break; - putchar(','); - } - puts("\n };"); - size = 1U << 5; - printf("\n static const code distfix[%u] = {", size); - low = 0; - for (;;) { - if ((low % 6) == 0) printf("\n "); - printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, - state.distcode[low].val); - if (++low == size) break; - putchar(','); - } - puts("\n };"); -} -#endif /* MAKEFIXED */ - -/* - Update the window with the last wsize (normally 32K) bytes written before - returning. If window does not exist yet, create it. This is only called - when a window is already in use, or when output has been written during this - inflate call, but the end of the deflate stream has not been reached yet. - It is also called to create a window for dictionary data when a dictionary - is loaded. - - Providing output buffers larger than 32K to inflate() should provide a speed - advantage, since only the last 32K of output is copied to the sliding window - upon return from inflate(), and since all distances after the first 32K of - output will fall in the output data, making match copies simpler and faster. - The advantage may be dependent on the size of the processor's data caches. - */ -local int updatewindow(strm, out) -z_streamp strm; -unsigned out; -{ - struct inflate_state FAR *state; - unsigned copy, dist; - - state = (struct inflate_state FAR *)strm->state; - - /* if it hasn't been done already, allocate space for the window */ - if (state->window == Z_NULL) { - state->window = (unsigned char FAR *) - ZALLOC(strm, 1U << state->wbits, - sizeof(unsigned char)); - if (state->window == Z_NULL) return 1; - } - - /* if window not in use yet, initialize */ - if (state->wsize == 0) { - state->wsize = 1U << state->wbits; - state->write = 0; - state->whave = 0; - } - - /* copy state->wsize or less output bytes into the circular window */ - copy = out - strm->avail_out; - if (copy >= state->wsize) { - zmemcpy(state->window, strm->next_out - state->wsize, state->wsize); - state->write = 0; - state->whave = state->wsize; - } - else { - dist = state->wsize - state->write; - if (dist > copy) dist = copy; - zmemcpy(state->window + state->write, strm->next_out - copy, dist); - copy -= dist; - if (copy) { - zmemcpy(state->window, strm->next_out - copy, copy); - state->write = copy; - state->whave = state->wsize; - } - else { - state->write += dist; - if (state->write == state->wsize) state->write = 0; - if (state->whave < state->wsize) state->whave += dist; - } - } - return 0; -} - -/* Macros for inflate(): */ - -/* check function to use adler32() for zlib or crc32() for gzip */ -#ifdef GUNZIP -# define UPDATE(check, buf, len) \ - (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) -#else -# define UPDATE(check, buf, len) adler32(check, buf, len) -#endif - -/* check macros for header crc */ -#ifdef GUNZIP -# define CRC2(check, word) \ - do { \ - hbuf[0] = (unsigned char)(word); \ - hbuf[1] = (unsigned char)((word) >> 8); \ - check = crc32(check, hbuf, 2); \ - } while (0) - -# define CRC4(check, word) \ - do { \ - hbuf[0] = (unsigned char)(word); \ - hbuf[1] = (unsigned char)((word) >> 8); \ - hbuf[2] = (unsigned char)((word) >> 16); \ - hbuf[3] = (unsigned char)((word) >> 24); \ - check = crc32(check, hbuf, 4); \ - } while (0) -#endif - -/* Load registers with state in inflate() for speed */ -#define LOAD() \ - do { \ - put = strm->next_out; \ - left = strm->avail_out; \ - next = strm->next_in; \ - have = strm->avail_in; \ - hold = state->hold; \ - bits = state->bits; \ - } while (0) - -/* Restore state from registers in inflate() */ -#define RESTORE() \ - do { \ - strm->next_out = put; \ - strm->avail_out = left; \ - strm->next_in = next; \ - strm->avail_in = have; \ - state->hold = hold; \ - state->bits = bits; \ - } while (0) - -/* Clear the input bit accumulator */ -#define INITBITS() \ - do { \ - hold = 0; \ - bits = 0; \ - } while (0) - -/* Get a byte of input into the bit accumulator, or return from inflate() - if there is no input available. */ -#define PULLBYTE() \ - do { \ - if (have == 0) goto inf_leave; \ - have--; \ - hold += (unsigned long)(*next++) << bits; \ - bits += 8; \ - } while (0) - -/* Assure that there are at least n bits in the bit accumulator. If there is - not enough available input to do that, then return from inflate(). */ -#define NEEDBITS(n) \ - do { \ - while (bits < (unsigned)(n)) \ - PULLBYTE(); \ - } while (0) - -/* Return the low n bits of the bit accumulator (n < 16) */ -#define BITS(n) \ - ((unsigned)hold & ((1U << (n)) - 1)) - -/* Remove n bits from the bit accumulator */ -#define DROPBITS(n) \ - do { \ - hold >>= (n); \ - bits -= (unsigned)(n); \ - } while (0) - -/* Remove zero to seven bits as needed to go to a byte boundary */ -#define BYTEBITS() \ - do { \ - hold >>= bits & 7; \ - bits -= bits & 7; \ - } while (0) - -/* Reverse the bytes in a 32-bit value */ -#define REVERSE(q) \ - ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ - (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) - -/* - inflate() uses a state machine to process as much input data and generate as - much output data as possible before returning. The state machine is - structured roughly as follows: - - for (;;) switch (state) { - ... - case STATEn: - if (not enough input data or output space to make progress) - return; - ... make progress ... - state = STATEm; - break; - ... - } - - so when inflate() is called again, the same case is attempted again, and - if the appropriate resources are provided, the machine proceeds to the - next state. The NEEDBITS() macro is usually the way the state evaluates - whether it can proceed or should return. NEEDBITS() does the return if - the requested bits are not available. The typical use of the BITS macros - is: - - NEEDBITS(n); - ... do something with BITS(n) ... - DROPBITS(n); - - where NEEDBITS(n) either returns from inflate() if there isn't enough - input left to load n bits into the accumulator, or it continues. BITS(n) - gives the low n bits in the accumulator. When done, DROPBITS(n) drops - the low n bits off the accumulator. INITBITS() clears the accumulator - and sets the number of available bits to zero. BYTEBITS() discards just - enough bits to put the accumulator on a byte boundary. After BYTEBITS() - and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. - - NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return - if there is no input available. The decoding of variable length codes uses - PULLBYTE() directly in order to pull just enough bytes to decode the next - code, and no more. - - Some states loop until they get enough input, making sure that enough - state information is maintained to continue the loop where it left off - if NEEDBITS() returns in the loop. For example, want, need, and keep - would all have to actually be part of the saved state in case NEEDBITS() - returns: - - case STATEw: - while (want < need) { - NEEDBITS(n); - keep[want++] = BITS(n); - DROPBITS(n); - } - state = STATEx; - case STATEx: - - As shown above, if the next state is also the next case, then the break - is omitted. - - A state may also return if there is not enough output space available to - complete that state. Those states are copying stored data, writing a - literal byte, and copying a matching string. - - When returning, a "goto inf_leave" is used to update the total counters, - update the check value, and determine whether any progress has been made - during that inflate() call in order to return the proper return code. - Progress is defined as a change in either strm->avail_in or strm->avail_out. - When there is a window, goto inf_leave will update the window with the last - output written. If a goto inf_leave occurs in the middle of decompression - and there is no window currently, goto inf_leave will create one and copy - output to the window for the next call of inflate(). - - In this implementation, the flush parameter of inflate() only affects the - return code (per zlib.h). inflate() always writes as much as possible to - strm->next_out, given the space available and the provided input--the effect - documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers - the allocation of and copying into a sliding window until necessary, which - provides the effect documented in zlib.h for Z_FINISH when the entire input - stream available. So the only thing the flush parameter actually does is: - when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it - will return Z_BUF_ERROR if it has not reached the end of the stream. - */ - -int ZEXPORT inflate(strm, flush) -z_streamp strm; -int flush; -{ - struct inflate_state FAR *state; - unsigned char FAR *next; /* next input */ - unsigned char FAR *put; /* next output */ - unsigned have, left; /* available input and output */ - unsigned long hold; /* bit buffer */ - unsigned bits; /* bits in bit buffer */ - unsigned in, out; /* save starting available input and output */ - unsigned copy; /* number of stored or match bytes to copy */ - unsigned char FAR *from; /* where to copy match bytes from */ - code this; /* current decoding table entry */ - code last; /* parent table entry */ - unsigned len; /* length to copy for repeats, bits to drop */ - int ret; /* return code */ -#ifdef GUNZIP - unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ -#endif - static const unsigned short order[19] = /* permutation of code lengths */ - {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; - - if (strm == Z_NULL || strm->state == Z_NULL || strm->next_out == Z_NULL || - (strm->next_in == Z_NULL && strm->avail_in != 0)) - return Z_STREAM_ERROR; - - state = (struct inflate_state FAR *)strm->state; - if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ - LOAD(); - in = have; - out = left; - ret = Z_OK; - for (;;) - switch (state->mode) { - case HEAD: - if (state->wrap == 0) { - state->mode = TYPEDO; - break; - } - NEEDBITS(16); -#ifdef GUNZIP - if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ - state->check = crc32(0L, Z_NULL, 0); - CRC2(state->check, hold); - INITBITS(); - state->mode = FLAGS; - break; - } - state->flags = 0; /* expect zlib header */ - if (state->head != Z_NULL) - state->head->done = -1; - if (!(state->wrap & 1) || /* check if zlib header allowed */ -#else - if ( -#endif - ((BITS(8) << 8) + (hold >> 8)) % 31) { - strm->msg = "incorrect header check"; - state->mode = BAD; - break; - } - if (BITS(4) != Z_DEFLATED) { - strm->msg = "unknown compression method"; - state->mode = BAD; - break; - } - DROPBITS(4); - len = BITS(4) + 8; - if (len > state->wbits) { - strm->msg = "invalid window size"; - state->mode = BAD; - break; - } - state->dmax = 1U << len; - Tracev((stderr, "inflate: zlib header ok\n")); - strm->adler = state->check = adler32(0L, Z_NULL, 0); - state->mode = hold & 0x200 ? DICTID : TYPE; - INITBITS(); - break; -#ifdef GUNZIP - case FLAGS: - NEEDBITS(16); - state->flags = (int)(hold); - if ((state->flags & 0xff) != Z_DEFLATED) { - strm->msg = "unknown compression method"; - state->mode = BAD; - break; - } - if (state->flags & 0xe000) { - strm->msg = "unknown header flags set"; - state->mode = BAD; - break; - } - if (state->head != Z_NULL) - state->head->text = (int)((hold >> 8) & 1); - if (state->flags & 0x0200) CRC2(state->check, hold); - INITBITS(); - state->mode = TIME; - case TIME: - NEEDBITS(32); - if (state->head != Z_NULL) - state->head->time = hold; - if (state->flags & 0x0200) CRC4(state->check, hold); - INITBITS(); - state->mode = OS; - case OS: - NEEDBITS(16); - if (state->head != Z_NULL) { - state->head->xflags = (int)(hold & 0xff); - state->head->os = (int)(hold >> 8); - } - if (state->flags & 0x0200) CRC2(state->check, hold); - INITBITS(); - state->mode = EXLEN; - case EXLEN: - if (state->flags & 0x0400) { - NEEDBITS(16); - state->length = (unsigned)(hold); - if (state->head != Z_NULL) - state->head->extra_len = (unsigned)hold; - if (state->flags & 0x0200) CRC2(state->check, hold); - INITBITS(); - } - else if (state->head != Z_NULL) - state->head->extra = Z_NULL; - state->mode = EXTRA; - case EXTRA: - if (state->flags & 0x0400) { - copy = state->length; - if (copy > have) copy = have; - if (copy) { - if (state->head != Z_NULL && - state->head->extra != Z_NULL) { - len = state->head->extra_len - state->length; - zmemcpy(state->head->extra + len, next, - len + copy > state->head->extra_max ? - state->head->extra_max - len : copy); - } - if (state->flags & 0x0200) - state->check = crc32(state->check, next, copy); - have -= copy; - next += copy; - state->length -= copy; - } - if (state->length) goto inf_leave; - } - state->length = 0; - state->mode = NAME; - case NAME: - if (state->flags & 0x0800) { - if (have == 0) goto inf_leave; - copy = 0; - do { - len = (unsigned)(next[copy++]); - if (state->head != Z_NULL && - state->head->name != Z_NULL && - state->length < state->head->name_max) - state->head->name[state->length++] = len; - } while (len && copy < have); - if (state->flags & 0x0200) - state->check = crc32(state->check, next, copy); - have -= copy; - next += copy; - if (len) goto inf_leave; - } - else if (state->head != Z_NULL) - state->head->name = Z_NULL; - state->length = 0; - state->mode = COMMENT; - case COMMENT: - if (state->flags & 0x1000) { - if (have == 0) goto inf_leave; - copy = 0; - do { - len = (unsigned)(next[copy++]); - if (state->head != Z_NULL && - state->head->comment != Z_NULL && - state->length < state->head->comm_max) - state->head->comment[state->length++] = len; - } while (len && copy < have); - if (state->flags & 0x0200) - state->check = crc32(state->check, next, copy); - have -= copy; - next += copy; - if (len) goto inf_leave; - } - else if (state->head != Z_NULL) - state->head->comment = Z_NULL; - state->mode = HCRC; - case HCRC: - if (state->flags & 0x0200) { - NEEDBITS(16); - if (hold != (state->check & 0xffff)) { - strm->msg = "header crc mismatch"; - state->mode = BAD; - break; - } - INITBITS(); - } - if (state->head != Z_NULL) { - state->head->hcrc = (int)((state->flags >> 9) & 1); - state->head->done = 1; - } - strm->adler = state->check = crc32(0L, Z_NULL, 0); - state->mode = TYPE; - break; -#endif - case DICTID: - NEEDBITS(32); - strm->adler = state->check = REVERSE(hold); - INITBITS(); - state->mode = DICT; - case DICT: - if (state->havedict == 0) { - RESTORE(); - return Z_NEED_DICT; - } - strm->adler = state->check = adler32(0L, Z_NULL, 0); - state->mode = TYPE; - case TYPE: - if (flush == Z_BLOCK) goto inf_leave; - case TYPEDO: - if (state->last) { - BYTEBITS(); - state->mode = CHECK; - break; - } - NEEDBITS(3); - state->last = BITS(1); - DROPBITS(1); - switch (BITS(2)) { - case 0: /* stored block */ - Tracev((stderr, "inflate: stored block%s\n", - state->last ? " (last)" : "")); - state->mode = STORED; - break; - case 1: /* fixed block */ - fixedtables(state); - Tracev((stderr, "inflate: fixed codes block%s\n", - state->last ? " (last)" : "")); - state->mode = LEN; /* decode codes */ - break; - case 2: /* dynamic block */ - Tracev((stderr, "inflate: dynamic codes block%s\n", - state->last ? " (last)" : "")); - state->mode = TABLE; - break; - case 3: - strm->msg = "invalid block type"; - state->mode = BAD; - } - DROPBITS(2); - break; - case STORED: - BYTEBITS(); /* go to byte boundary */ - NEEDBITS(32); - if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { - strm->msg = "invalid stored block lengths"; - state->mode = BAD; - break; - } - state->length = (unsigned)hold & 0xffff; - Tracev((stderr, "inflate: stored length %u\n", - state->length)); - INITBITS(); - state->mode = COPY; - case COPY: - copy = state->length; - if (copy) { - if (copy > have) copy = have; - if (copy > left) copy = left; - if (copy == 0) goto inf_leave; - zmemcpy(put, next, copy); - have -= copy; - next += copy; - left -= copy; - put += copy; - state->length -= copy; - break; - } - Tracev((stderr, "inflate: stored end\n")); - state->mode = TYPE; - break; - case TABLE: - NEEDBITS(14); - state->nlen = BITS(5) + 257; - DROPBITS(5); - state->ndist = BITS(5) + 1; - DROPBITS(5); - state->ncode = BITS(4) + 4; - DROPBITS(4); -#ifndef PKZIP_BUG_WORKAROUND - if (state->nlen > 286 || state->ndist > 30) { - strm->msg = "too many length or distance symbols"; - state->mode = BAD; - break; - } -#endif - Tracev((stderr, "inflate: table sizes ok\n")); - state->have = 0; - state->mode = LENLENS; - case LENLENS: - while (state->have < state->ncode) { - NEEDBITS(3); - state->lens[order[state->have++]] = (unsigned short)BITS(3); - DROPBITS(3); - } - while (state->have < 19) - state->lens[order[state->have++]] = 0; - state->next = state->codes; - state->lencode = (code const FAR *)(state->next); - state->lenbits = 7; - ret = inflate_table(CODES, state->lens, 19, &(state->next), - &(state->lenbits), state->work); - if (ret) { - strm->msg = "invalid code lengths set"; - state->mode = BAD; - break; - } - Tracev((stderr, "inflate: code lengths ok\n")); - state->have = 0; - state->mode = CODELENS; - case CODELENS: - while (state->have < state->nlen + state->ndist) { - for (;;) { - this = state->lencode[BITS(state->lenbits)]; - if ((unsigned)(this.bits) <= bits) break; - PULLBYTE(); - } - if (this.val < 16) { - NEEDBITS(this.bits); - DROPBITS(this.bits); - state->lens[state->have++] = this.val; - } - else { - if (this.val == 16) { - NEEDBITS(this.bits + 2); - DROPBITS(this.bits); - if (state->have == 0) { - strm->msg = "invalid bit length repeat"; - state->mode = BAD; - break; - } - len = state->lens[state->have - 1]; - copy = 3 + BITS(2); - DROPBITS(2); - } - else if (this.val == 17) { - NEEDBITS(this.bits + 3); - DROPBITS(this.bits); - len = 0; - copy = 3 + BITS(3); - DROPBITS(3); - } - else { - NEEDBITS(this.bits + 7); - DROPBITS(this.bits); - len = 0; - copy = 11 + BITS(7); - DROPBITS(7); - } - if (state->have + copy > state->nlen + state->ndist) { - strm->msg = "invalid bit length repeat"; - state->mode = BAD; - break; - } - while (copy--) - state->lens[state->have++] = (unsigned short)len; - } - } - - /* handle error breaks in while */ - if (state->mode == BAD) break; - - /* build code tables */ - state->next = state->codes; - state->lencode = (code const FAR *)(state->next); - state->lenbits = 9; - ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), - &(state->lenbits), state->work); - if (ret) { - strm->msg = "invalid literal/lengths set"; - state->mode = BAD; - break; - } - state->distcode = (code const FAR *)(state->next); - state->distbits = 6; - ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, - &(state->next), &(state->distbits), state->work); - if (ret) { - strm->msg = "invalid distances set"; - state->mode = BAD; - break; - } - Tracev((stderr, "inflate: codes ok\n")); - state->mode = LEN; - case LEN: - if (have >= 6 && left >= 258) { - RESTORE(); - inflate_fast(strm, out); - LOAD(); - break; - } - for (;;) { - this = state->lencode[BITS(state->lenbits)]; - if ((unsigned)(this.bits) <= bits) break; - PULLBYTE(); - } - if (this.op && (this.op & 0xf0) == 0) { - last = this; - for (;;) { - this = state->lencode[last.val + - (BITS(last.bits + last.op) >> last.bits)]; - if ((unsigned)(last.bits + this.bits) <= bits) break; - PULLBYTE(); - } - DROPBITS(last.bits); - } - DROPBITS(this.bits); - state->length = (unsigned)this.val; - if ((int)(this.op) == 0) { - Tracevv((stderr, this.val >= 0x20 && this.val < 0x7f ? - "inflate: literal '%c'\n" : - "inflate: literal 0x%02x\n", this.val)); - state->mode = LIT; - break; - } - if (this.op & 32) { - Tracevv((stderr, "inflate: end of block\n")); - state->mode = TYPE; - break; - } - if (this.op & 64) { - strm->msg = "invalid literal/length code"; - state->mode = BAD; - break; - } - state->extra = (unsigned)(this.op) & 15; - state->mode = LENEXT; - case LENEXT: - if (state->extra) { - NEEDBITS(state->extra); - state->length += BITS(state->extra); - DROPBITS(state->extra); - } - Tracevv((stderr, "inflate: length %u\n", state->length)); - state->mode = DIST; - case DIST: - for (;;) { - this = state->distcode[BITS(state->distbits)]; - if ((unsigned)(this.bits) <= bits) break; - PULLBYTE(); - } - if ((this.op & 0xf0) == 0) { - last = this; - for (;;) { - this = state->distcode[last.val + - (BITS(last.bits + last.op) >> last.bits)]; - if ((unsigned)(last.bits + this.bits) <= bits) break; - PULLBYTE(); - } - DROPBITS(last.bits); - } - DROPBITS(this.bits); - if (this.op & 64) { - strm->msg = "invalid distance code"; - state->mode = BAD; - break; - } - state->offset = (unsigned)this.val; - state->extra = (unsigned)(this.op) & 15; - state->mode = DISTEXT; - case DISTEXT: - if (state->extra) { - NEEDBITS(state->extra); - state->offset += BITS(state->extra); - DROPBITS(state->extra); - } -#ifdef INFLATE_STRICT - if (state->offset > state->dmax) { - strm->msg = "invalid distance too far back"; - state->mode = BAD; - break; - } -#endif - if (state->offset > state->whave + out - left) { - strm->msg = "invalid distance too far back"; - state->mode = BAD; - break; - } - Tracevv((stderr, "inflate: distance %u\n", state->offset)); - state->mode = MATCH; - case MATCH: - if (left == 0) goto inf_leave; - copy = out - left; - if (state->offset > copy) { /* copy from window */ - copy = state->offset - copy; - if (copy > state->write) { - copy -= state->write; - from = state->window + (state->wsize - copy); - } - else - from = state->window + (state->write - copy); - if (copy > state->length) copy = state->length; - } - else { /* copy from output */ - from = put - state->offset; - copy = state->length; - } - if (copy > left) copy = left; - left -= copy; - state->length -= copy; - do { - *put++ = *from++; - } while (--copy); - if (state->length == 0) state->mode = LEN; - break; - case LIT: - if (left == 0) goto inf_leave; - *put++ = (unsigned char)(state->length); - left--; - state->mode = LEN; - break; - case CHECK: - if (state->wrap) { - NEEDBITS(32); - out -= left; - strm->total_out += out; - state->total += out; - if (out) - strm->adler = state->check = - UPDATE(state->check, put - out, out); - out = left; - if (( -#ifdef GUNZIP - state->flags ? hold : -#endif - REVERSE(hold)) != state->check) { - strm->msg = "incorrect data check"; - state->mode = BAD; - break; - } - INITBITS(); - Tracev((stderr, "inflate: check matches trailer\n")); - } -#ifdef GUNZIP - state->mode = LENGTH; - case LENGTH: - if (state->wrap && state->flags) { - NEEDBITS(32); - if (hold != (state->total & 0xffffffffUL)) { - strm->msg = "incorrect length check"; - state->mode = BAD; - break; - } - INITBITS(); - Tracev((stderr, "inflate: length matches trailer\n")); - } -#endif - state->mode = DONE; - case DONE: - ret = Z_STREAM_END; - goto inf_leave; - case BAD: - ret = Z_DATA_ERROR; - goto inf_leave; - case MEM: - return Z_MEM_ERROR; - case SYNC: - default: - return Z_STREAM_ERROR; - } - - /* - Return from inflate(), updating the total counts and the check value. - If there was no progress during the inflate() call, return a buffer - error. Call updatewindow() to create and/or update the window state. - Note: a memory error from inflate() is non-recoverable. - */ - inf_leave: - RESTORE(); - if (state->wsize || (state->mode < CHECK && out != strm->avail_out)) - if (updatewindow(strm, out)) { - state->mode = MEM; - return Z_MEM_ERROR; - } - in -= strm->avail_in; - out -= strm->avail_out; - strm->total_in += in; - strm->total_out += out; - state->total += out; - if (state->wrap && out) - strm->adler = state->check = - UPDATE(state->check, strm->next_out - out, out); - strm->data_type = state->bits + (state->last ? 64 : 0) + - (state->mode == TYPE ? 128 : 0); - if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) - ret = Z_BUF_ERROR; - return ret; -} - -int ZEXPORT inflateEnd(strm) -z_streamp strm; -{ - struct inflate_state FAR *state; - if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) - return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - if (state->window != Z_NULL) ZFREE(strm, state->window); - ZFREE(strm, strm->state); - strm->state = Z_NULL; - Tracev((stderr, "inflate: end\n")); - return Z_OK; -} - -int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) -z_streamp strm; -const Bytef *dictionary; -uInt dictLength; -{ - struct inflate_state FAR *state; - unsigned long id; - - /* check state */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - if (state->wrap != 0 && state->mode != DICT) - return Z_STREAM_ERROR; - - /* check for correct dictionary id */ - if (state->mode == DICT) { - id = adler32(0L, Z_NULL, 0); - id = adler32(id, dictionary, dictLength); - if (id != state->check) - return Z_DATA_ERROR; - } - - /* copy dictionary to window */ - if (updatewindow(strm, strm->avail_out)) { - state->mode = MEM; - return Z_MEM_ERROR; - } - if (dictLength > state->wsize) { - zmemcpy(state->window, dictionary + dictLength - state->wsize, - state->wsize); - state->whave = state->wsize; - } - else { - zmemcpy(state->window + state->wsize - dictLength, dictionary, - dictLength); - state->whave = dictLength; - } - state->havedict = 1; - Tracev((stderr, "inflate: dictionary set\n")); - return Z_OK; -} - -int ZEXPORT inflateGetHeader(strm, head) -z_streamp strm; -gz_headerp head; -{ - struct inflate_state FAR *state; - - /* check state */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; - - /* save header structure */ - state->head = head; - head->done = 0; - return Z_OK; -} - -/* - Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found - or when out of input. When called, *have is the number of pattern bytes - found in order so far, in 0..3. On return *have is updated to the new - state. If on return *have equals four, then the pattern was found and the - return value is how many bytes were read including the last byte of the - pattern. If *have is less than four, then the pattern has not been found - yet and the return value is len. In the latter case, syncsearch() can be - called again with more data and the *have state. *have is initialized to - zero for the first call. - */ -local unsigned syncsearch(have, buf, len) -unsigned FAR *have; -unsigned char FAR *buf; -unsigned len; -{ - unsigned got; - unsigned next; - - got = *have; - next = 0; - while (next < len && got < 4) { - if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) - got++; - else if (buf[next]) - got = 0; - else - got = 4 - got; - next++; - } - *have = got; - return next; -} - -int ZEXPORT inflateSync(strm) -z_streamp strm; -{ - unsigned len; /* number of bytes to look at or looked at */ - unsigned long in, out; /* temporary to save total_in and total_out */ - unsigned char buf[4]; /* to restore bit buffer to byte string */ - struct inflate_state FAR *state; - - /* check parameters */ - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; - - /* if first time, start search in bit buffer */ - if (state->mode != SYNC) { - state->mode = SYNC; - state->hold <<= state->bits & 7; - state->bits -= state->bits & 7; - len = 0; - while (state->bits >= 8) { - buf[len++] = (unsigned char)(state->hold); - state->hold >>= 8; - state->bits -= 8; - } - state->have = 0; - syncsearch(&(state->have), buf, len); - } - - /* search available input */ - len = syncsearch(&(state->have), strm->next_in, strm->avail_in); - strm->avail_in -= len; - strm->next_in += len; - strm->total_in += len; - - /* return no joy or set up to restart inflate() on a new block */ - if (state->have != 4) return Z_DATA_ERROR; - in = strm->total_in; out = strm->total_out; - inflateReset(strm); - strm->total_in = in; strm->total_out = out; - state->mode = TYPE; - 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(strm) -z_streamp strm; -{ - struct inflate_state FAR *state; - - if (strm == Z_NULL || strm->state == Z_NULL) return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)strm->state; - return state->mode == STORED && state->bits == 0; -} - -int ZEXPORT inflateCopy(dest, source) -z_streamp dest; -z_streamp source; -{ - struct inflate_state FAR *state; - struct inflate_state FAR *copy; - unsigned char FAR *window; - unsigned wsize; - - /* check input */ - if (dest == Z_NULL || source == Z_NULL || source->state == Z_NULL || - source->zalloc == (alloc_func)0 || source->zfree == (free_func)0) - return Z_STREAM_ERROR; - state = (struct inflate_state FAR *)source->state; - - /* allocate space */ - copy = (struct inflate_state FAR *) - ZALLOC(source, 1, sizeof(struct inflate_state)); - if (copy == Z_NULL) return Z_MEM_ERROR; - window = Z_NULL; - if (state->window != Z_NULL) { - window = (unsigned char FAR *) - ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); - if (window == Z_NULL) { - ZFREE(source, copy); - return Z_MEM_ERROR; - } - } - - /* copy state */ - zmemcpy(dest, source, sizeof(z_stream)); - zmemcpy(copy, state, sizeof(struct inflate_state)); - if (state->lencode >= state->codes && - state->lencode <= state->codes + ENOUGH - 1) { - copy->lencode = copy->codes + (state->lencode - state->codes); - copy->distcode = copy->codes + (state->distcode - state->codes); - } - copy->next = copy->codes + (state->next - state->codes); - if (window != Z_NULL) { - wsize = 1U << state->wbits; - zmemcpy(window, state->window, wsize); - } - copy->window = window; - dest->state = (struct internal_state FAR *)copy; - return Z_OK; -} diff --git a/snesreader/zlib/inflate.h b/snesreader/zlib/inflate.h deleted file mode 100644 index 07bd3e78..00000000 --- a/snesreader/zlib/inflate.h +++ /dev/null @@ -1,115 +0,0 @@ -/* inflate.h -- internal inflate state definition - * Copyright (C) 1995-2004 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. - */ - -/* define NO_GZIP when compiling if you want to disable gzip header and - trailer decoding by inflate(). NO_GZIP would be used to avoid linking in - the crc code when it is not needed. For shared libraries, gzip decoding - should be left enabled. */ -#ifndef NO_GZIP -# define GUNZIP -#endif - -/* Possible inflate modes between inflate() calls */ -typedef enum { - HEAD, /* i: waiting for magic header */ - FLAGS, /* i: waiting for method and flags (gzip) */ - TIME, /* i: waiting for modification time (gzip) */ - OS, /* i: waiting for extra flags and operating system (gzip) */ - EXLEN, /* i: waiting for extra length (gzip) */ - EXTRA, /* i: waiting for extra bytes (gzip) */ - NAME, /* i: waiting for end of file name (gzip) */ - COMMENT, /* i: waiting for end of comment (gzip) */ - HCRC, /* i: waiting for header crc (gzip) */ - DICTID, /* i: waiting for dictionary check value */ - DICT, /* waiting for inflateSetDictionary() call */ - TYPE, /* i: waiting for type bits, including last-flag bit */ - TYPEDO, /* i: same, but skip check to exit inflate on new block */ - STORED, /* i: waiting for stored size (length and complement) */ - COPY, /* i/o: waiting for input or output to copy stored block */ - TABLE, /* i: waiting for dynamic block table lengths */ - LENLENS, /* i: waiting for code length code lengths */ - CODELENS, /* i: waiting for length/lit and distance code lengths */ - LEN, /* i: waiting for length/lit code */ - LENEXT, /* i: waiting for length extra bits */ - DIST, /* i: waiting for distance code */ - DISTEXT, /* i: waiting for distance extra bits */ - MATCH, /* o: waiting for output space to copy string */ - LIT, /* o: waiting for output space to write literal */ - CHECK, /* i: waiting for 32-bit check value */ - LENGTH, /* i: waiting for 32-bit length (gzip) */ - DONE, /* finished check, done -- remain here until reset */ - BAD, /* got a data error -- remain here until reset */ - MEM, /* got an inflate() memory error -- remain here until reset */ - SYNC /* looking for synchronization bytes to restart inflate() */ -} inflate_mode; - -/* - State transitions between above modes - - - (most modes can go to the BAD or MEM mode -- not shown for clarity) - - Process header: - HEAD -> (gzip) or (zlib) - (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME - NAME -> COMMENT -> HCRC -> TYPE - (zlib) -> DICTID or TYPE - DICTID -> DICT -> TYPE - Read deflate blocks: - TYPE -> STORED or TABLE or LEN or CHECK - STORED -> COPY -> TYPE - TABLE -> LENLENS -> CODELENS -> LEN - Read deflate codes: - LEN -> LENEXT or LIT or TYPE - LENEXT -> DIST -> DISTEXT -> MATCH -> LEN - LIT -> LEN - Process trailer: - CHECK -> LENGTH -> DONE - */ - -/* state maintained between inflate() calls. Approximately 7K bytes. */ -struct inflate_state { - inflate_mode mode; /* current inflate mode */ - int last; /* true if processing last block */ - int wrap; /* bit 0 true for zlib, bit 1 true for gzip */ - int havedict; /* true if dictionary provided */ - int flags; /* gzip header method and flags (0 if zlib) */ - unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ - unsigned long check; /* protected copy of check value */ - unsigned long total; /* protected copy of output count */ - gz_headerp head; /* where to save gzip header information */ - /* sliding window */ - unsigned wbits; /* log base 2 of requested window size */ - unsigned wsize; /* window size or zero if not using window */ - unsigned whave; /* valid bytes in the window */ - unsigned write; /* window write index */ - unsigned char FAR *window; /* allocated sliding window, if needed */ - /* bit accumulator */ - unsigned long hold; /* input bit accumulator */ - unsigned bits; /* number of bits in "in" */ - /* for string and stored block copying */ - unsigned length; /* literal or length of data to copy */ - unsigned offset; /* distance back to copy string from */ - /* for table and code decoding */ - unsigned extra; /* extra bits needed */ - /* fixed and dynamic code tables */ - code const FAR *lencode; /* starting table for length/literal codes */ - code const FAR *distcode; /* starting table for distance codes */ - unsigned lenbits; /* index bits for lencode */ - unsigned distbits; /* index bits for distcode */ - /* dynamic table building */ - unsigned ncode; /* number of code length code lengths */ - unsigned nlen; /* number of length code lengths */ - unsigned ndist; /* number of distance code lengths */ - unsigned have; /* number of code lengths in lens[] */ - code FAR *next; /* next available space in codes[] */ - unsigned short lens[320]; /* temporary storage for code lengths */ - unsigned short work[288]; /* work area for code table building */ - code codes[ENOUGH]; /* space for code tables */ -}; diff --git a/snesreader/zlib/inftrees.c b/snesreader/zlib/inftrees.c deleted file mode 100644 index 8a9c13ff..00000000 --- a/snesreader/zlib/inftrees.c +++ /dev/null @@ -1,329 +0,0 @@ -/* inftrees.c -- generate Huffman trees for efficient decoding - * Copyright (C) 1995-2005 Mark Adler - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -#include "zutil.h" -#include "inftrees.h" - -#define MAXBITS 15 - -const char inflate_copyright[] = - " inflate 1.2.3 Copyright 1995-2005 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. - */ - -/* - Build a set of tables to decode the provided canonical Huffman code. - The code lengths are lens[0..codes-1]. The result starts at *table, - whose indices are 0..2^bits-1. work is a writable array of at least - lens shorts, which is used as a work area. type is the type of code - to be generated, CODES, LENS, or DISTS. On return, zero is success, - -1 is an invalid code, and +1 means that ENOUGH isn't enough. table - on return points to the next available entry's address. bits is the - requested root table index bits, and on return it is the actual root - table index bits. It will differ if the request is greater than the - longest code or if it is less than the shortest code. - */ -int inflate_table(type, lens, codes, table, bits, work) -codetype type; -unsigned short FAR *lens; -unsigned codes; -code FAR * FAR *table; -unsigned FAR *bits; -unsigned short FAR *work; -{ - unsigned len; /* a code's length in bits */ - unsigned sym; /* index of code symbols */ - unsigned min, max; /* minimum and maximum code lengths */ - unsigned root; /* number of index bits for root table */ - unsigned curr; /* number of index bits for current table */ - unsigned drop; /* code bits to drop for sub-table */ - int left; /* number of prefix codes available */ - unsigned used; /* code entries in table used */ - unsigned huff; /* Huffman code */ - unsigned incr; /* for incrementing code, index */ - unsigned fill; /* index for replicating entries */ - unsigned low; /* low bits for current root entry */ - unsigned mask; /* mask for low root bits */ - code this; /* table entry for duplication */ - code FAR *next; /* next available space in table */ - const unsigned short FAR *base; /* base value table to use */ - const unsigned short FAR *extra; /* extra bits table to use */ - int end; /* use base and extra for symbol > end */ - unsigned short count[MAXBITS+1]; /* number of codes of each length */ - unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ - static const unsigned short lbase[31] = { /* Length codes 257..285 base */ - 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}; - static const unsigned short lext[31] = { /* Length codes 257..285 extra */ - 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, - 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 201, 196}; - static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ - 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, 0, 0}; - static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ - 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, - 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, - 28, 28, 29, 29, 64, 64}; - - /* - Process a set of code lengths to create a canonical Huffman code. The - code lengths are lens[0..codes-1]. Each length corresponds to the - symbols 0..codes-1. The Huffman code is generated by first sorting the - symbols by length from short to long, and retaining the symbol order - for codes with equal lengths. Then the code starts with all zero bits - for the first code of the shortest length, and the codes are integer - increments for the same length, and zeros are appended as the length - increases. For the deflate format, these bits are stored backwards - from their more natural integer increment ordering, and so when the - decoding tables are built in the large loop below, the integer codes - are incremented backwards. - - This routine assumes, but does not check, that all of the entries in - lens[] are in the range 0..MAXBITS. The caller must assure this. - 1..MAXBITS is interpreted as that code length. zero means that that - symbol does not occur in this code. - - The codes are sorted by computing a count of codes for each length, - creating from that a table of starting indices for each length in the - sorted table, and then entering the symbols in order in the sorted - table. The sorted table is work[], with that space being provided by - the caller. - - The length counts are used for other purposes as well, i.e. finding - the minimum and maximum length codes, determining if there are any - codes at all, checking for a valid set of lengths, and looking ahead - at length counts to determine sub-table sizes when building the - decoding tables. - */ - - /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ - for (len = 0; len <= MAXBITS; len++) - count[len] = 0; - for (sym = 0; sym < codes; sym++) - count[lens[sym]]++; - - /* bound code lengths, force root to be within code lengths */ - root = *bits; - for (max = MAXBITS; max >= 1; max--) - if (count[max] != 0) break; - if (root > max) root = max; - if (max == 0) { /* no symbols to code at all */ - this.op = (unsigned char)64; /* invalid code marker */ - this.bits = (unsigned char)1; - this.val = (unsigned short)0; - *(*table)++ = this; /* make a table to force an error */ - *(*table)++ = this; - *bits = 1; - return 0; /* no symbols, but wait for decoding to report error */ - } - for (min = 1; min <= MAXBITS; min++) - if (count[min] != 0) break; - if (root < min) root = min; - - /* check for an over-subscribed or incomplete set of lengths */ - left = 1; - for (len = 1; len <= MAXBITS; len++) { - left <<= 1; - left -= count[len]; - if (left < 0) return -1; /* over-subscribed */ - } - if (left > 0 && (type == CODES || max != 1)) - return -1; /* incomplete set */ - - /* generate offsets into symbol table for each length for sorting */ - offs[1] = 0; - for (len = 1; len < MAXBITS; len++) - offs[len + 1] = offs[len] + count[len]; - - /* sort symbols by length, by symbol order within each length */ - for (sym = 0; sym < codes; sym++) - if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; - - /* - Create and fill in decoding tables. In this loop, the table being - filled is at next and has curr index bits. The code being used is huff - with length len. That code is converted to an index by dropping drop - bits off of the bottom. For codes where len is less than drop + curr, - those top drop + curr - len bits are incremented through all values to - fill the table with replicated entries. - - root is the number of index bits for the root table. When len exceeds - root, sub-tables are created pointed to by the root entry with an index - of the low root bits of huff. This is saved in low to check for when a - new sub-table should be started. drop is zero when the root table is - being filled, and drop is root when sub-tables are being filled. - - When a new sub-table is needed, it is necessary to look ahead in the - code lengths to determine what size sub-table is needed. The length - counts are used for this, and so count[] is decremented as codes are - entered in the tables. - - used keeps track of how many table entries have been allocated from the - provided *table space. It is checked when a LENS table is being made - against the space in *table, ENOUGH, minus the maximum space needed by - the worst case distance code, MAXD. This should never happen, but the - sufficiency of ENOUGH has not been proven exhaustively, hence the check. - This assumes that when type == LENS, bits == 9. - - sym increments through all symbols, and the loop terminates when - all codes of length max, i.e. all codes, have been processed. This - routine permits incomplete codes, so another loop after this one fills - in the rest of the decoding tables with invalid code markers. - */ - - /* set up for code type */ - switch (type) { - case CODES: - base = extra = work; /* dummy value--not used */ - end = 19; - break; - case LENS: - base = lbase; - base -= 257; - extra = lext; - extra -= 257; - end = 256; - break; - default: /* DISTS */ - base = dbase; - extra = dext; - end = -1; - } - - /* initialize state for loop */ - huff = 0; /* starting code */ - sym = 0; /* starting code symbol */ - len = min; /* starting code length */ - next = *table; /* current table to fill in */ - curr = root; /* current table index bits */ - drop = 0; /* current bits to drop from code for index */ - low = (unsigned)(-1); /* trigger new sub-table when len > root */ - used = 1U << root; /* use root table entries */ - mask = used - 1; /* mask for comparing low */ - - /* check available table space */ - if (type == LENS && used >= ENOUGH - MAXD) - return 1; - - /* process all codes and make table entries */ - for (;;) { - /* create table entry */ - this.bits = (unsigned char)(len - drop); - if ((int)(work[sym]) < end) { - this.op = (unsigned char)0; - this.val = work[sym]; - } - else if ((int)(work[sym]) > end) { - this.op = (unsigned char)(extra[work[sym]]); - this.val = base[work[sym]]; - } - else { - this.op = (unsigned char)(32 + 64); /* end of block */ - this.val = 0; - } - - /* replicate for those indices with low len bits equal to huff */ - incr = 1U << (len - drop); - fill = 1U << curr; - min = fill; /* save offset to next table */ - do { - fill -= incr; - next[(huff >> drop) + fill] = this; - } while (fill != 0); - - /* backwards increment the len-bit code huff */ - incr = 1U << (len - 1); - while (huff & incr) - incr >>= 1; - if (incr != 0) { - huff &= incr - 1; - huff += incr; - } - else - huff = 0; - - /* go to next symbol, update count, len */ - sym++; - if (--(count[len]) == 0) { - if (len == max) break; - len = lens[work[sym]]; - } - - /* create new sub-table if needed */ - if (len > root && (huff & mask) != low) { - /* if first time, transition to sub-tables */ - if (drop == 0) - drop = root; - - /* increment past last table */ - next += min; /* here min is 1 << curr */ - - /* determine length of next table */ - curr = len - drop; - left = (int)(1 << curr); - while (curr + drop < max) { - left -= count[curr + drop]; - if (left <= 0) break; - curr++; - left <<= 1; - } - - /* check for enough space */ - used += 1U << curr; - if (type == LENS && used >= ENOUGH - MAXD) - return 1; - - /* point entry in root table to sub-table */ - low = huff & mask; - (*table)[low].op = (unsigned char)curr; - (*table)[low].bits = (unsigned char)root; - (*table)[low].val = (unsigned short)(next - *table); - } - } - - /* - Fill in rest of table for incomplete codes. This loop is similar to the - loop above in incrementing huff for table indices. It is assumed that - len is equal to curr + drop, so there is no loop needed to increment - through high index bits. When the current sub-table is filled, the loop - drops back to the root table to fill in any remaining entries there. - */ - this.op = (unsigned char)64; /* invalid code marker */ - this.bits = (unsigned char)(len - drop); - this.val = (unsigned short)0; - while (huff != 0) { - /* when done with sub-table, drop back to root table */ - if (drop != 0 && (huff & mask) != low) { - drop = 0; - len = root; - next = *table; - this.bits = (unsigned char)len; - } - - /* put invalid code marker in table */ - next[huff >> drop] = this; - - /* backwards increment the len-bit code huff */ - incr = 1U << (len - 1); - while (huff & incr) - incr >>= 1; - if (incr != 0) { - huff &= incr - 1; - huff += incr; - } - else - huff = 0; - } - - /* set return parameters */ - *table += used; - *bits = root; - return 0; -} diff --git a/snesreader/zlib/inftrees.h b/snesreader/zlib/inftrees.h deleted file mode 100644 index b1104c87..00000000 --- a/snesreader/zlib/inftrees.h +++ /dev/null @@ -1,55 +0,0 @@ -/* inftrees.h -- header to use inftrees.c - * Copyright (C) 1995-2005 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. - */ - -/* Structure for decoding tables. Each entry provides either the - information needed to do the operation requested by the code that - indexed that table entry, or it provides a pointer to another - table that indexes more bits of the code. op indicates whether - the entry is a pointer to another table, a literal, a length or - distance, an end-of-block, or an invalid code. For a table - pointer, the low four bits of op is the number of index bits of - that table. For a length or distance, the low four bits of op - is the number of extra bits to get after the code. bits is - the number of bits in this code or part of the code to drop off - of the bit buffer. val is the actual byte to output in the case - of a literal, the base length or distance, or the offset from - the current table to the next table. Each entry is four bytes. */ -typedef struct { - unsigned char op; /* operation, extra bits, table bits */ - unsigned char bits; /* bits in this part of the code */ - unsigned short val; /* offset in table or code value */ -} code; - -/* op values as set by inflate_table(): - 00000000 - literal - 0000tttt - table link, tttt != 0 is the number of table index bits - 0001eeee - length or distance, eeee is the number of extra bits - 01100000 - end of block - 01000000 - invalid code - */ - -/* Maximum size of dynamic tree. The maximum found in a long but non- - exhaustive search was 1444 code structures (852 for length/literals - and 592 for distances, the latter actually the result of an - exhaustive search). The true maximum is not known, but the value - below is more than safe. */ -#define ENOUGH 2048 -#define MAXD 592 - -/* Type of code to build for inftable() */ -typedef enum { - CODES, - LENS, - DISTS -} codetype; - -extern int inflate_table OF((codetype type, unsigned short FAR *lens, - unsigned codes, code FAR * FAR *table, - unsigned FAR *bits, unsigned short FAR *work)); diff --git a/snesreader/zlib/readme.txt b/snesreader/zlib/readme.txt deleted file mode 100644 index d1331635..00000000 --- a/snesreader/zlib/readme.txt +++ /dev/null @@ -1,10 +0,0 @@ -This is NOT the complete zlib distribution; it is just a subset of the -source needed by the File_Extractor library. I've made some minor -changes: - -* Enabled DYNAMIC_CRC_TABLE in zconf.h, to reduce executable size -slightly. -* Made z_stream_s's msg const char* to eliminate many warnings. - -You can remove these sources and link to your own copy of zlib if -desired. diff --git a/snesreader/zlib/zconf.h b/snesreader/zlib/zconf.h deleted file mode 100644 index ee5a9181..00000000 --- a/snesreader/zlib/zconf.h +++ /dev/null @@ -1,335 +0,0 @@ -/* zconf.h -- configuration of the zlib compression library - * Copyright (C) 1995-2005 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#ifndef ZCONF_H -#define ZCONF_H - -/* added for file_extractor; OK to remove, just increases executable size */ -#define DYNAMIC_CRC_TABLE - -/* - * 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 deflateBound z_deflateBound -# define deflatePrime z_deflatePrime -# define inflateInit2_ z_inflateInit2_ -# define inflateSetDictionary z_inflateSetDictionary -# define inflateSync z_inflateSync -# define inflateSyncPoint z_inflateSyncPoint -# define inflateCopy z_inflateCopy -# define inflateReset z_inflateReset -# define inflateBack z_inflateBack -# define inflateBackEnd z_inflateBackEnd -# define compress z_compress -# define compress2 z_compress2 -# define compressBound z_compressBound -# define uncompress z_uncompress -# define adler32 z_adler32 -# define crc32 z_crc32 -# define get_crc_table z_get_crc_table -# define zError z_zError - -# define alloc_func z_alloc_func -# define free_func z_free_func -# define in_func z_in_func -# define out_func z_out_func -# 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(__MSDOS__) && !defined(MSDOS) -# define MSDOS -#endif -#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) -# define OS2 -#endif -#if defined(_WINDOWS) && !defined(WINDOWS) -# define WINDOWS -#endif -#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) -# ifndef WIN32 -# define WIN32 -# endif -#endif -#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) -# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) -# ifndef SYS16BIT -# define SYS16BIT -# endif -# endif -#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). - */ -#ifdef SYS16BIT -# define MAXSEG_64K -#endif -#ifdef MSDOS -# define UNALIGNED_OK -#endif - -#ifdef __STDC_VERSION__ -# ifndef STDC -# define STDC -# endif -# if __STDC_VERSION__ >= 199901L -# ifndef STDC99 -# define STDC99 -# endif -# endif -#endif -#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) -# define STDC -#endif -#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) -# define STDC -#endif -#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) -# define STDC -#endif -#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) -# define STDC -#endif - -#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ -# define STDC -#endif - -#ifndef STDC -# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ -# define const /* note: need a more gentle solution here */ -# 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 - -/* 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. - */ -#ifdef SYS16BIT -# if defined(M_I86SM) || defined(M_I86MM) - /* MSC small or medium model */ -# define SMALL_MEDIUM -# ifdef _MSC_VER -# define FAR _far -# else -# define FAR far -# endif -# endif -# if (defined(__SMALL__) || defined(__MEDIUM__)) - /* Turbo C small or medium model */ -# define SMALL_MEDIUM -# ifdef __BORLANDC__ -# define FAR _far -# else -# define FAR far -# endif -# endif -#endif - -#if defined(WINDOWS) || defined(WIN32) - /* If building or using zlib as a DLL, define ZLIB_DLL. - * This is not mandatory, but it offers a little performance increase. - */ -# ifdef ZLIB_DLL -# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) -# ifdef ZLIB_INTERNAL -# define ZEXTERN extern __declspec(dllexport) -# else -# define ZEXTERN extern __declspec(dllimport) -# endif -# endif -# endif /* ZLIB_DLL */ - /* If building or using zlib with the WINAPI/WINAPIV calling convention, - * define ZLIB_WINAPI. - * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. - */ -# ifdef ZLIB_WINAPI -# ifdef FAR -# undef FAR -# endif -# include - /* No need for _export, use ZLIB.DEF instead. */ - /* For complete Windows compatibility, use WINAPI, not __stdcall. */ -# define ZEXPORT WINAPI -# ifdef WIN32 -# define ZEXPORTVA WINAPIV -# else -# define ZEXPORTVA FAR CDECL -# endif -# endif -#endif - -#if defined (__BEOS__) -# ifdef ZLIB_DLL -# ifdef ZLIB_INTERNAL -# define ZEXPORT __declspec(dllexport) -# define ZEXPORTVA __declspec(dllexport) -# else -# define ZEXPORT __declspec(dllimport) -# define ZEXPORTVA __declspec(dllimport) -# endif -# endif -#endif - -#ifndef ZEXTERN -# define ZEXTERN extern -#endif -#ifndef ZEXPORT -# define ZEXPORT -#endif -#ifndef ZEXPORTVA -# define ZEXPORTVA -#endif - -#ifndef FAR -# define FAR -#endif - -#if !defined(__MACTYPES__) -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 const *voidpc; - typedef void FAR *voidpf; - typedef void *voidp; -#else - typedef Byte const *voidpc; - typedef Byte FAR *voidpf; - typedef Byte *voidp; -#endif - -#if 0 /* HAVE_UNISTD_H -- this line is updated by ./configure */ -# include /* for off_t */ -# include /* for SEEK_* and off_t */ -# ifdef VMS -# include /* for off_t */ -# endif -# 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 - -#if defined(__OS400__) -# define NO_vsnprintf -#endif - -#if defined(__MVS__) -# define NO_vsnprintf -# ifdef FAR -# undef FAR -# endif -#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(deflateBound,"DEBND") -# pragma map(inflateInit_,"ININ") -# pragma map(inflateInit2_,"ININ2") -# pragma map(inflateEnd,"INEND") -# pragma map(inflateSync,"INSY") -# pragma map(inflateSetDictionary,"INSEDI") -# pragma map(compressBound,"CMBND") -# pragma map(inflate_table,"INTABL") -# pragma map(inflate_fast,"INFA") -# pragma map(inflate_copyright,"INCOPY") -#endif - -#endif /* ZCONF_H */ diff --git a/snesreader/zlib/zlib.h b/snesreader/zlib/zlib.h deleted file mode 100644 index e4768717..00000000 --- a/snesreader/zlib/zlib.h +++ /dev/null @@ -1,1357 +0,0 @@ -/* zlib.h -- interface of the 'zlib' general purpose compression library - version 1.2.3, July 18th, 2005 - - Copyright (C) 1995-2005 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 http://www.ietf.org/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.2.3" -#define ZLIB_VERNUM 0x1230 - -/* - 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 compressed data format used by default by the in-memory functions is - the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped - around a deflate stream, which is itself documented in RFC 1951. - - The library also supports reading and writing files in gzip (.gz) format - with an interface similar to that of stdio using the functions that start - with "gz". The gzip format is different from the zlib format. gzip is a - gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. - - This library can optionally read and write gzip streams in memory as well. - - The zlib format was designed to be compact and fast for use in memory - and on communications channels. The gzip format was designed for single- - file compression on file systems, has a larger header than zlib to maintain - directory information, and uses a different, slower check method than zlib. - - 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 */ - - const 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: binary or text */ - uLong adler; /* adler32 value of the uncompressed data */ - uLong reserved; /* reserved for future use */ -} z_stream; - -typedef z_stream FAR *z_streamp; - -/* - gzip header information passed to and from zlib routines. See RFC 1952 - for more details on the meanings of these fields. -*/ -typedef struct gz_header_s { - int text; /* true if compressed data believed to be text */ - uLong time; /* modification time */ - int xflags; /* extra flags (not used when writing a gzip file) */ - int os; /* operating system */ - Bytef *extra; /* pointer to extra field or Z_NULL if none */ - uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ - uInt extra_max; /* space at extra (only when reading header) */ - Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ - uInt name_max; /* space at name (only when reading header) */ - Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ - uInt comm_max; /* space at comment (only when reading header) */ - int hcrc; /* true if there was or will be a header crc */ - int done; /* true when done reading gzip header (not used - when writing a gzip file) */ -} gz_header; - -typedef gz_header FAR *gz_headerp; - -/* - 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 -#define Z_BLOCK 5 -/* Allowed flush values; see deflate() and inflate() 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_RLE 3 -#define Z_FIXED 4 -#define Z_DEFAULT_STRATEGY 0 -/* compression strategy; see deflateInit2() below for details */ - -#define Z_BINARY 0 -#define Z_TEXT 1 -#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ -#define Z_UNKNOWN 2 -/* Possible values of the data_type field (though see inflate()) */ - -#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. - - Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to - decide how much data to accumualte before producing output, in order to - maximize compression. - - 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 - 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). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that - avail_out is greater than six to avoid repeated flush markers due to - avail_out == 0 on return. - - 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 - the value returned by deflateBound (see below). 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 strm->data_type if it can make a good guess about - the input data type (Z_BINARY or Z_TEXT). 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). Note that Z_BUF_ERROR is not - fatal, and deflate() can be called again with more input and more output - space to continue compressing. -*/ - - -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 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. - - The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, - Z_FINISH, or Z_BLOCK. Z_SYNC_FLUSH requests that inflate() flush as much - output as possible to the output buffer. Z_BLOCK requests that inflate() stop - if and when it gets to the next deflate block boundary. When decoding the - zlib or gzip format, this will cause inflate() to return immediately after - the header and before the first block. When doing a raw inflate, inflate() - will go ahead and process the first block, and will return when it gets to - the end of that block, or when it runs out of data. - - The Z_BLOCK option assists in appending to or combining deflate streams. - Also to assist in this, on return inflate() will set strm->data_type to the - number of unused bits in the last byte taken from strm->next_in, plus 64 - if inflate() is currently decoding the last block in the deflate stream, - plus 128 if inflate() returned immediately after decoding an end-of-block - code or decoding the complete header up to just before the first byte of the - deflate stream. The end-of-block will not be indicated until all of the - uncompressed data from that block has been written to strm->next_out. The - number of unused bits may in general be greater than seven, except when - bit 7 of data_type is set, in which case the number of unused bits will be - less than eight. - - 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 approach - may be used for the single inflate() call. - - In this implementation, inflate() always flushes as much output as - possible to the output buffer, and always uses the faster approach on the - first call. So the only effect of the flush parameter in this implementation - is on the return value of inflate(), as noted below, or when it returns early - because Z_BLOCK is used. - - If a preset dictionary is needed after this call (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() will decompress and check either zlib-wrapped or gzip-wrapped - deflate data. The header type is detected automatically. Any information - contained in the gzip header is not retained, so applications that need that - information should instead use raw inflate, see inflateInit2() below, or - inflateBack() and perform their own processing of the gzip header and - trailer. - - 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 check - value), 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. Note that Z_BUF_ERROR is not fatal, and - inflate() can be called again with more input and more output space to - continue decompressing. If Z_DATA_ERROR is returned, the application may then - call inflateSync() to look for a good compression block if a partial recovery - of the data is desired. -*/ - - -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. - - windowBits can also be -8..-15 for raw deflate. In this case, -windowBits - determines the window size. deflate() will then generate raw deflate data - with no zlib header or trailer, and will not compute an adler32 check value. - - windowBits can also be greater than 15 for optional gzip encoding. Add - 16 to windowBits to write a simple gzip header and trailer around the - compressed data instead of a zlib wrapper. The gzip header will have no - file name, no extra data, no comment, no modification time (set to zero), - no header crc, and the operating system will be set to 255 (unknown). If a - gzip stream is being written, strm->adler is a crc32 instead of an adler32. - - 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), Z_HUFFMAN_ONLY to force Huffman encoding only (no - string match), or Z_RLE to limit match distances to one (run-length - encoding). 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. Z_RLE is designed to be almost as fast as - Z_HUFFMAN_ONLY, but give better compression for PNG image data. The strategy - parameter only affects the compression ratio but not the correctness of the - compressed output even if it is not set appropriately. Z_FIXED prevents the - use of dynamic Huffman codes, allowing for a simpler decoder for special - applications. - - 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. In addition, the - current implementation of deflate will use at most the window size minus - 262 bytes of the provided dictionary. - - 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.) If a raw deflate was requested, then the - adler32 value is not computed and strm->adler is not set. - - 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 deflateTune OF((z_streamp strm, - int good_length, - int max_lazy, - int nice_length, - int max_chain)); -/* - Fine tune deflate's internal compression parameters. This should only be - used by someone who understands the algorithm used by zlib's deflate for - searching for the best matching string, and even then only by the most - fanatic optimizer trying to squeeze out the last compressed bit for their - specific input data. Read the deflate.c source code for the meaning of the - max_lazy, good_length, nice_length, and max_chain parameters. - - deflateTune() can be called after deflateInit() or deflateInit2(), and - returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. - */ - -ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, - uLong sourceLen)); -/* - deflateBound() returns an upper bound on the compressed size after - deflation of sourceLen bytes. It must be called after deflateInit() - or deflateInit2(). This would be used to allocate an output buffer - for deflation in a single pass, and so would be called before deflate(). -*/ - -ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, - int bits, - int value)); -/* - deflatePrime() inserts bits in the deflate output stream. The intent - is that this function is used to start off the deflate output with the - bits leftover from a previous deflate stream when appending to it. As such, - this function can only be used for raw deflate, and must be used before the - first deflate() call after a deflateInit2() or deflateReset(). bits must be - less than or equal to 16, and that many of the least significant bits of - value will be inserted in the output. - - deflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, - gz_headerp head)); -/* - deflateSetHeader() provides gzip header information for when a gzip - stream is requested by deflateInit2(). deflateSetHeader() may be called - after deflateInit2() or deflateReset() and before the first call of - deflate(). The text, time, os, extra field, name, and comment information - in the provided gz_header structure are written to the gzip header (xflag is - ignored -- the extra flags are set according to the compression level). The - caller must assure that, if not Z_NULL, name and comment are terminated with - a zero byte, and that if extra is not Z_NULL, that extra_len bytes are - available there. If hcrc is true, a gzip header crc is included. Note that - the current versions of the command-line version of gzip (up through version - 1.3.x) do not support header crc's, and will report that it is a "multi-part - gzip file" and give up. - - If deflateSetHeader is not used, the default gzip header has text false, - the time set to zero, and os set to 255, with no extra, name, or comment - fields. The gzip header is returned to the default state by deflateReset(). - - deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -/* -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. windowBits must be greater than or equal to the windowBits value - provided to deflateInit2() while compressing, or it must be equal to 15 if - deflateInit2() was not used. 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. - - windowBits can also be -8..-15 for raw inflate. In this case, -windowBits - determines the window size. inflate() will then process raw deflate data, - not looking for a zlib or gzip header, not generating a check value, and not - looking for any check values for comparison at the end of the stream. This - is for use with other formats that use the deflate compressed data format - such as zip. Those formats provide their own check values. If a custom - format is developed using the raw deflate format for compressed data, it is - recommended that a check value such as an adler32 or a crc32 be applied to - the uncompressed data as is done in the zlib, gzip, and zip formats. For - most applications, the zlib format should be used as is. Note that comments - above on the use in deflateInit2() applies to the magnitude of windowBits. - - windowBits can also be greater than 15 for optional gzip decoding. Add - 32 to windowBits to enable zlib and gzip decoding with automatic header - detection, or add 16 to decode only the gzip format (the zlib format will - return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is - a crc32 instead of an adler32. - - 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 null strm). 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 that call returned Z_NEED_DICT. The dictionary chosen by the compressor - can be determined from the adler32 value returned by that call of inflate. - The compressor and decompressor must use exactly the same dictionary (see - deflateSetDictionary). For raw inflate, this function can be called - immediately after inflateInit2() or inflateReset() and before any call of - inflate() to set the dictionary. The application must insure that the - dictionary that was used for compression is provided. - - 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 inflateCopy 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 randomly accessing a large stream. The - first pass through the stream can periodically record the inflate state, - allowing restarting inflate at those points when randomly accessing the - stream. - - inflateCopy 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 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). -*/ - -ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, - int bits, - int value)); -/* - This function inserts bits in the inflate input stream. The intent is - that this function is used to start inflating at a bit position in the - middle of a byte. The provided bits will be used before any bytes are used - from next_in. This function should only be used with raw inflate, and - should be used before the first inflate() call after inflateInit2() or - inflateReset(). bits must be less than or equal to 16, and that many of the - least significant bits of value will be inserted in the input. - - inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, - gz_headerp head)); -/* - inflateGetHeader() requests that gzip header information be stored in the - provided gz_header structure. inflateGetHeader() may be called after - inflateInit2() or inflateReset(), and before the first call of inflate(). - As inflate() processes the gzip stream, head->done is zero until the header - is completed, at which time head->done is set to one. If a zlib stream is - being decoded, then head->done is set to -1 to indicate that there will be - no gzip header information forthcoming. Note that Z_BLOCK can be used to - force inflate() to return immediately after header processing is complete - and before any actual data is decompressed. - - The text, time, xflags, and os fields are filled in with the gzip header - contents. hcrc is set to true if there is a header CRC. (The header CRC - was valid if done is set to one.) If extra is not Z_NULL, then extra_max - contains the maximum number of bytes to write to extra. Once done is true, - extra_len contains the actual extra field length, and extra contains the - extra field, or that field truncated if extra_max is less than extra_len. - If name is not Z_NULL, then up to name_max characters are written there, - terminated with a zero unless the length is greater than name_max. If - comment is not Z_NULL, then up to comm_max characters are written there, - terminated with a zero unless the length is greater than comm_max. When - any of extra, name, or comment are not Z_NULL and the respective field is - not present in the header, then that field is set to Z_NULL to signal its - absence. This allows the use of deflateSetHeader() with the returned - structure to duplicate the header. However if those fields are set to - allocated memory, then the application will need to save those pointers - elsewhere so that they can be eventually freed. - - If inflateGetHeader is not used, then the header information is simply - discarded. The header is always checked for validity, including the header - CRC if present. inflateReset() will reset the process to discard the header - information. The application would need to call inflateGetHeader() again to - retrieve the header from the next gzip stream. - - inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source - stream state was inconsistent. -*/ - -/* -ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, - unsigned char FAR *window)); - - Initialize the internal stream state for decompression using inflateBack() - calls. The fields zalloc, zfree and opaque in strm must be initialized - before the call. If zalloc and zfree are Z_NULL, then the default library- - derived memory allocation routines are used. windowBits is the base two - logarithm of the window size, in the range 8..15. window is a caller - supplied buffer of that size. Except for special applications where it is - assured that deflate was used with small window sizes, windowBits must be 15 - and a 32K byte window must be supplied to be able to decompress general - deflate streams. - - See inflateBack() for the usage of these routines. - - inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of - the paramaters are invalid, Z_MEM_ERROR if the internal state could not - be allocated, or Z_VERSION_ERROR if the version of the library does not - match the version of the header file. -*/ - -typedef unsigned (*in_func) OF((void FAR *, unsigned char FAR * FAR *)); -typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); - -ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, - in_func in, void FAR *in_desc, - out_func out, void FAR *out_desc)); -/* - inflateBack() does a raw inflate with a single call using a call-back - interface for input and output. This is more efficient than inflate() for - file i/o applications in that it avoids copying between the output and the - sliding window by simply making the window itself the output buffer. This - function trusts the application to not change the output buffer passed by - the output function, at least until inflateBack() returns. - - inflateBackInit() must be called first to allocate the internal state - and to initialize the state with the user-provided window buffer. - inflateBack() may then be used multiple times to inflate a complete, raw - deflate stream with each call. inflateBackEnd() is then called to free - the allocated state. - - A raw deflate stream is one with no zlib or gzip header or trailer. - This routine would normally be used in a utility that reads zip or gzip - files and writes out uncompressed files. The utility would decode the - header and process the trailer on its own, hence this routine expects - only the raw deflate stream to decompress. This is different from the - normal behavior of inflate(), which expects either a zlib or gzip header and - trailer around the deflate stream. - - inflateBack() uses two subroutines supplied by the caller that are then - called by inflateBack() for input and output. inflateBack() calls those - routines until it reads a complete deflate stream and writes out all of the - uncompressed data, or until it encounters an error. The function's - parameters and return types are defined above in the in_func and out_func - typedefs. inflateBack() will call in(in_desc, &buf) which should return the - number of bytes of provided input, and a pointer to that input in buf. If - there is no input available, in() must return zero--buf is ignored in that - case--and inflateBack() will return a buffer error. inflateBack() will call - out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. out() - should return zero on success, or non-zero on failure. If out() returns - non-zero, inflateBack() will return with an error. Neither in() nor out() - are permitted to change the contents of the window provided to - inflateBackInit(), which is also the buffer that out() uses to write from. - The length written by out() will be at most the window size. Any non-zero - amount of input may be provided by in(). - - For convenience, inflateBack() can be provided input on the first call by - setting strm->next_in and strm->avail_in. If that input is exhausted, then - in() will be called. Therefore strm->next_in must be initialized before - calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called - immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in - must also be initialized, and then if strm->avail_in is not zero, input will - initially be taken from strm->next_in[0 .. strm->avail_in - 1]. - - The in_desc and out_desc parameters of inflateBack() is passed as the - first parameter of in() and out() respectively when they are called. These - descriptors can be optionally used to pass any information that the caller- - supplied in() and out() functions need to do their job. - - On return, inflateBack() will set strm->next_in and strm->avail_in to - pass back any unused input that was provided by the last in() call. The - return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR - if in() or out() returned an error, Z_DATA_ERROR if there was a format - error in the deflate stream (in which case strm->msg is set to indicate the - nature of the error), or Z_STREAM_ERROR if the stream was not properly - initialized. In the case of Z_BUF_ERROR, an input or output error can be - distinguished using strm->next_in which will be Z_NULL only if in() returned - an error. If strm->next is not Z_NULL, then the Z_BUF_ERROR was due to - out() returning non-zero. (in() will always be called before out(), so - strm->next_in is assured to be defined if out() returns non-zero.) Note - that inflateBack() cannot return Z_OK. -*/ - -ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); -/* - All memory allocated by inflateBackInit() is freed. - - inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream - state was inconsistent. -*/ - -ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); -/* Return flags indicating compile-time options. - - Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: - 1.0: size of uInt - 3.2: size of uLong - 5.4: size of voidpf (pointer) - 7.6: size of z_off_t - - Compiler, assembler, and debug options: - 8: DEBUG - 9: ASMV or ASMINF -- use ASM code - 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention - 11: 0 (reserved) - - One-time table building (smaller code, but not thread-safe if true): - 12: BUILDFIXED -- build static block decoding tables when needed - 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed - 14,15: 0 (reserved) - - Library content (indicates missing functionality): - 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking - deflate code when not needed) - 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect - and decode gzip streams (to avoid linking crc code) - 18-19: 0 (reserved) - - Operation variations (changes in library functionality): - 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate - 21: FASTEST -- deflate algorithm with only one, lowest compression level - 22,23: 0 (reserved) - - The sprintf variant used by gzprintf (zero is best): - 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format - 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! - 26: 0 = returns value, 1 = void -- 1 means inferred string length returned - - Remainder: - 27-31: 0 (reserved) - */ - - - /* 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 the value returned - by compressBound(sourceLen). 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 the value returned by - compressBound(sourceLen). 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 uLong ZEXPORT compressBound OF((uLong sourceLen)); -/* - compressBound() returns an upper bound on the compressed size after - compress() or compress2() on sourceLen bytes. It would be used before - a compress() or compress2() call to allocate the destination buffer. -*/ - -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 or incomplete. -*/ - - -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", or 'R' for run-length encoding - as in "wb1R". (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, - voidpc 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). The number of - uncompressed bytes written is limited to 4095. The caller should assure that - this limit is not exceeded. If it is exceeded, then gzprintf() will return - return an error (0) with nothing written. In this case, there may also be a - buffer overflow with unpredictable consequences, which is possible only if - zlib was compiled with the insecure functions sprintf() or vsprintf() - because the secure snprintf() or vsnprintf() functions were not available. -*/ - -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 gzungetc OF((int c, gzFile file)); -/* - Push one character back onto the stream to be read again later. - Only one character of push-back is allowed. gzungetc() returns the - character pushed, or -1 on failure. gzungetc() will fail if a - character has been pushed but not read yet, or if c is -1. The pushed - character will be discarded if the stream is repositioned with gzseek() - or gzrewind(). -*/ - -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 gzdirect OF((gzFile file)); -/* - Returns 1 if file is being read directly without decompression, 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. -*/ - -ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); -/* - Clears the error and end-of-file flags for file. This is analogous to the - clearerr() function in stdio. This is useful for continuing to read a gzip - file that is being written concurrently. -*/ - - /* 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 adler32_combine OF((uLong adler1, uLong adler2, - z_off_t len2)); -/* - Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 - and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for - each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of - seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. -*/ - -ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); -/* - Update a running CRC-32 with the bytes buf[0..len-1] and return the - updated CRC-32. If buf is NULL, this function returns the required initial - value for the 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(); -*/ - -ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); - -/* - Combine two CRC-32 check values into one. For two sequences of bytes, - seq1 and seq2 with lengths len1 and len2, CRC-32 check values were - calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 - check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and - len2. -*/ - - - /* 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)); -ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, - unsigned char FAR *window, - 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)) -#define inflateBackInit(strm, windowBits, window) \ - inflateBackInit_((strm), (windowBits), (window), \ - ZLIB_VERSION, sizeof(z_stream)) - - -#if !defined(ZUTIL_H) && !defined(NO_DUMMY_DECL) - struct internal_state {int dummy;}; /* hack for buggy compilers */ -#endif - -ZEXTERN const char * ZEXPORT zError OF((int)); -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/snesreader/zlib/zlib.txt b/snesreader/zlib/zlib.txt deleted file mode 100644 index 80f71ae8..00000000 --- a/snesreader/zlib/zlib.txt +++ /dev/null @@ -1,125 +0,0 @@ -ZLIB DATA COMPRESSION LIBRARY - -zlib 1.2.3 is a general purpose data compression library. All the code is -thread safe. The data format used by the zlib library is described by RFCs -(Request for Comments) 1950 to 1952 in the files -http://www.ietf.org/rfc/rfc1950.txt (zlib format), rfc1951.txt (deflate format) -and rfc1952.txt (gzip format). These documents are also available in other -formats from ftp://ftp.uu.net/graphics/png/documents/zlib/zdoc-index.html - -All functions of the compression library are documented in the file zlib.h -(volunteer to write man pages welcome, contact zlib@gzip.org). A usage example -of the library is given in the file example.c which also tests that the library -is working correctly. Another example is given in the file minigzip.c. The -compression library itself is composed of all source files except example.c and -minigzip.c. - -To compile all files and run the test program, follow the instructions given at -the top of Makefile. In short "make test; make install" should work for most -machines. For Unix: "./configure; make test; make install". For MSDOS, use one -of the special makefiles such as Makefile.msc. For VMS, use make_vms.com. - -Questions about zlib should be sent to , or to Gilles Vollant - for the Windows DLL version. The zlib home page is -http://www.zlib.org or http://www.gzip.org/zlib/ Before reporting a problem, -please check this site to verify that you have the latest version of zlib; -otherwise get the latest version and check whether the problem still exists or -not. - -PLEASE read the zlib FAQ http://www.gzip.org/zlib/zlib_faq.html before asking -for help. - -Mark Nelson wrote an article about zlib for the Jan. 1997 -issue of Dr. Dobb's Journal; a copy of the article is available in -http://dogma.net/markn/articles/zlibtool/zlibtool.htm - -The changes made in version 1.2.3 are documented in the file ChangeLog. - -Unsupported third party contributions are provided in directory "contrib". - -A Java implementation of zlib is available in the Java Development Kit -http://java.sun.com/j2se/1.4.2/docs/api/java/util/zip/package-summary.html -See the zlib home page http://www.zlib.org for details. - -A Perl interface to zlib written by Paul Marquess is in the -CPAN (Comprehensive Perl Archive Network) sites -http://www.cpan.org/modules/by-module/Compress/ - -A Python interface to zlib written by A.M. Kuchling is -available in Python 1.5 and later versions, see -http://www.python.org/doc/lib/module-zlib.html - -A zlib binding for TCL written by Andreas Kupries is -availlable at http://www.oche.de/~akupries/soft/trf/trf_zip.html - -An experimental package to read and write files in .zip format, written on top -of zlib by Gilles Vollant , is available in the -contrib/minizip directory of zlib. - - -Notes for some targets: - -- For Windows DLL versions, please see win32/DLL_FAQ.txt - -- For 64-bit Irix, deflate.c must be compiled without any optimization. With - -O, one libpng test fails. The test works in 32 bit mode (with the -n32 - compiler flag). The compiler bug has been reported to SGI. - -- zlib doesn't work with gcc 2.6.3 on a DEC 3000/300LX under OSF/1 2.1 it works - when compiled with cc. - -- On Digital Unix 4.0D (formely OSF/1) on AlphaServer, the cc option -std1 is - necessary to get gzprintf working correctly. This is done by configure. - -- zlib doesn't work on HP-UX 9.05 with some versions of /bin/cc. It works with - other compilers. Use "make test" to check your compiler. - -- gzdopen is not supported on RISCOS, BEOS and by some Mac compilers. - -- For PalmOs, see http://palmzlib.sourceforge.net/ - -- When building a shared, i.e. dynamic library on Mac OS X, the library must be - installed before testing (do "make install" before "make test"), since the - library location is specified in the library. - - -Acknowledgments: - - The deflate format used by zlib was defined by Phil Katz. The deflate - and zlib specifications were written by L. Peter Deutsch. Thanks to all the - people who reported problems and suggested various improvements in zlib; - they are too numerous to cite here. - -Copyright notice: - - (C) 1995-2004 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 - -If you use the zlib library in a product, we would appreciate *not* -receiving lengthy legal documents to sign. The sources are provided -for free but without warranty of any kind. The library has been -entirely written by Jean-loup Gailly and Mark Adler; it does not -include third-party code. - -If you redistribute modified sources, we would appreciate that you include -in the file ChangeLog history information documenting your changes. Please -read the FAQ for more information on the distribution of modified source -versions. diff --git a/snesreader/zlib/zutil.c b/snesreader/zlib/zutil.c deleted file mode 100644 index d55f5948..00000000 --- a/snesreader/zlib/zutil.c +++ /dev/null @@ -1,318 +0,0 @@ -/* zutil.c -- target dependent utility functions for the compression library - * Copyright (C) 1995-2005 Jean-loup Gailly. - * For conditions of distribution and use, see copyright notice in zlib.h - */ - -/* @(#) $Id$ */ - -#include "zutil.h" - -#ifndef NO_DUMMY_DECL -struct internal_state {int dummy;}; /* for buggy compilers */ -#endif - -const char * const 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; -} - -uLong ZEXPORT zlibCompileFlags() -{ - uLong flags; - - flags = 0; - switch (sizeof(uInt)) { - case 2: break; - case 4: flags += 1; break; - case 8: flags += 2; break; - default: flags += 3; - } - switch (sizeof(uLong)) { - case 2: break; - case 4: flags += 1 << 2; break; - case 8: flags += 2 << 2; break; - default: flags += 3 << 2; - } - switch (sizeof(voidpf)) { - case 2: break; - case 4: flags += 1 << 4; break; - case 8: flags += 2 << 4; break; - default: flags += 3 << 4; - } - switch (sizeof(z_off_t)) { - case 2: break; - case 4: flags += 1 << 6; break; - case 8: flags += 2 << 6; break; - default: flags += 3 << 6; - } -#ifdef DEBUG - flags += 1 << 8; -#endif -#if defined(ASMV) || defined(ASMINF) - flags += 1 << 9; -#endif -#ifdef ZLIB_WINAPI - flags += 1 << 10; -#endif -#ifdef BUILDFIXED - flags += 1 << 12; -#endif -#ifdef DYNAMIC_CRC_TABLE - flags += 1 << 13; -#endif -#ifdef NO_GZCOMPRESS - flags += 1L << 16; -#endif -#ifdef NO_GZIP - flags += 1L << 17; -#endif -#ifdef PKZIP_BUG_WORKAROUND - flags += 1L << 20; -#endif -#ifdef FASTEST - flags += 1L << 21; -#endif -#ifdef STDC -# ifdef NO_vsnprintf - flags += 1L << 25; -# ifdef HAS_vsprintf_void - flags += 1L << 26; -# endif -# else -# ifdef HAS_vsnprintf_void - flags += 1L << 26; -# endif -# endif -#else - flags += 1L << 24; -# ifdef NO_snprintf - flags += 1L << 25; -# ifdef HAS_sprintf_void - flags += 1L << 26; -# endif -# else -# ifdef HAS_snprintf_void - flags += 1L << 26; -# endif -# endif -#endif - return flags; -} - -#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); -} - -#if defined(_WIN32_WCE) - /* The Microsoft C Run-Time Library for Windows CE doesn't have - * errno. We define it as a global variable to simplify porting. - * Its value is always 0 and should not be used. - */ - int errno = 0; -#endif - -#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 SYS16BIT - -#ifdef __TURBOC__ -/* Turbo C in 16-bit mode */ - -# 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 /* __TURBOC__ */ - - -#ifdef M_I86 -/* 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 /* M_I86 */ - -#endif /* SYS16BIT */ - - -#ifndef MY_ZCALLOC /* Any system without a special alloc function */ - -#ifndef STDC -extern voidp malloc OF((uInt size)); -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 sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : - (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/snesreader/zlib/zutil.h b/snesreader/zlib/zutil.h deleted file mode 100644 index b7d5eff8..00000000 --- a/snesreader/zlib/zutil.h +++ /dev/null @@ -1,269 +0,0 @@ -/* zutil.h -- internal interface and configuration of the compression library - * Copyright (C) 1995-2005 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$ */ - -#ifndef ZUTIL_H -#define ZUTIL_H - -#define ZLIB_INTERNAL -#include "zlib.h" - -#ifdef STDC -# ifndef _WIN32_WCE -# include -# endif -# include -# include -#endif -#ifdef NO_ERRNO_H -# ifdef _WIN32_WCE - /* The Microsoft C Run-Time Library for Windows CE doesn't have - * errno. We define it as a global variable to simplify porting. - * Its value is always 0 and should not be used. We rename it to - * avoid conflict with other libraries that use the same workaround. - */ -# define errno z_errno -# endif - extern int errno; -#else -# ifndef _WIN32_WCE -# include -# endif -#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 * const 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 */ - -#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) -# 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 AMIGA -# define OS_CODE 0x01 -#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 - -#if defined(ATARI) || defined(atarist) -# define OS_CODE 0x05 -#endif - -#ifdef OS2 -# define OS_CODE 0x06 -# ifdef M_I86 - #include -# endif -#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 TOPS20 -# define OS_CODE 0x0a -#endif - -#ifdef WIN32 -# ifndef __CYGWIN__ /* Cygwin is Unix, not Win32 */ -# define OS_CODE 0x0b -# endif -#endif - -#ifdef __50SERIES /* Prime/PRIMOS */ -# define OS_CODE 0x0f -#endif - -#if defined(_BEOS_) || defined(RISCOS) -# define fdopen(fd,mode) NULL /* No fdopen() */ -#endif - -#if (defined(_MSC_VER) && (_MSC_VER > 600)) -# if defined(_WIN32_WCE) -# define fdopen(fd,mode) NULL /* No fdopen() */ -# ifndef _PTRDIFF_T_DEFINED - typedef int ptrdiff_t; -# define _PTRDIFF_T_DEFINED -# endif -# else -# define fdopen(fd,type) _fdopen(fd,type) -# endif -#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 */ - -#if defined(STDC99) || (defined(__TURBOC__) && __TURBOC__ >= 0x550) -# ifndef HAVE_VSNPRINTF -# define HAVE_VSNPRINTF -# endif -#endif -#if defined(__CYGWIN__) -# ifndef HAVE_VSNPRINTF -# define HAVE_VSNPRINTF -# endif -#endif -#ifndef HAVE_VSNPRINTF -# ifdef MSDOS - /* vsnprintf may exist on some MS-DOS compilers (DJGPP?), - but for now we just assume it doesn't. */ -# define NO_vsnprintf -# endif -# ifdef __TURBOC__ -# define NO_vsnprintf -# endif -# ifdef WIN32 - /* In Win32, vsnprintf is available as the "non-ANSI" _vsnprintf. */ -# if !defined(vsnprintf) && !defined(NO_vsnprintf) -# define vsnprintf _vsnprintf -# endif -# endif -# ifdef __SASC -# define NO_vsnprintf -# endif -#endif -#ifdef VMS -# define NO_vsnprintf -#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 - - -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 /* ZUTIL_H */ diff --git a/src/base.hpp b/src/base.hpp index 017c8cc7..35f38f21 100644 --- a/src/base.hpp +++ b/src/base.hpp @@ -1,4 +1,4 @@ -static const char bsnesVersion[] = "063"; +static const char bsnesVersion[] = "063.01"; static const char bsnesTitle[] = "bsnes"; static const unsigned bsnesSerializerVersion = 8; diff --git a/src/lib/nall/config.hpp b/src/lib/nall/config.hpp index 31ae4e00..c713d0b0 100644 --- a/src/lib/nall/config.hpp +++ b/src/lib/nall/config.hpp @@ -78,9 +78,8 @@ namespace nall { line.split("\n", data); for(unsigned i = 0; i < line.size(); i++) { - int position = qstrpos(line[i], "#"); - if(position >= 0) line[i][position] = 0; - if(qstrpos(line[i], " = ") < 0) continue; + if(auto position = qstrpos(line[i], "#")) line[i][position()] = 0; + if(!qstrpos(line[i], " = ")) continue; lstring part; part.qsplit(" = ", line[i]); diff --git a/src/lib/nall/dictionary.hpp b/src/lib/nall/dictionary.hpp index f14e2095..9e0a1620 100644 --- a/src/lib/nall/dictionary.hpp +++ b/src/lib/nall/dictionary.hpp @@ -15,9 +15,8 @@ namespace nall { //no match, use input; remove input identifier, if one exists if(strbegin(input, "{{")) { - int pos = strpos(input, "}}"); - if(pos >= 0) { - string temp = substr(input, pos + 2); + if(auto pos = strpos(input, "}}")) { + string temp = substr(input, pos() + 2); return temp; } } diff --git a/src/lib/nall/input.hpp b/src/lib/nall/input.hpp index b3ce9ebf..83c4a484 100644 --- a/src/lib/nall/input.hpp +++ b/src/lib/nall/input.hpp @@ -93,9 +93,9 @@ struct Keyboard { if(!strbegin(name, "KB")) return 0; ltrim(s, "KB"); unsigned id = strunsigned(s); - int pos = strpos(s, "::"); - if(pos < 0) return 0; - s = substr(s, pos + 2); + auto pos = strpos(s, "::"); + if(!pos) return 0; + s = substr(s, pos() + 2); for(unsigned i = 0; i < Limit; i++) { if(s == KeyboardScancodeName[i]) return Base + Size * id + i; } @@ -190,9 +190,9 @@ struct Mouse { if(!strbegin(name, "MS")) return 0; ltrim(s, "MS"); unsigned id = strunsigned(s); - int pos = strpos(s, "::"); - if(pos < 0) return 0; - s = substr(s, pos + 2); + auto pos = strpos(s, "::"); + if(!pos) return 0; + s = substr(s, pos() + 2); for(unsigned i = 0; i < Limit; i++) { if(s == MouseScancodeName[i]) return Base + Size * id + i; } @@ -314,9 +314,9 @@ struct Joypad { if(!strbegin(name, "JP")) return 0; ltrim(s, "JP"); unsigned id = strunsigned(s); - int pos = strpos(s, "::"); - if(pos < 0) return 0; - s = substr(s, pos + 2); + auto pos = strpos(s, "::"); + if(!pos) return 0; + s = substr(s, pos() + 2); for(unsigned i = 0; i < Limit; i++) { if(s == JoypadScancodeName[i]) return Base + Size * id + i; } diff --git a/src/lib/nall/qt/file-dialog.moc.hpp b/src/lib/nall/qt/file-dialog.moc.hpp index bcccfaf5..6528289b 100644 --- a/src/lib/nall/qt/file-dialog.moc.hpp +++ b/src/lib/nall/qt/file-dialog.moc.hpp @@ -211,7 +211,7 @@ inline void FileDialog::filterBoxChanged() { if(filters.length() == 0) { fileSystemModel->setNameFilters(QStringList() << "*"); } else { - filters = substr(filters, strpos(filters, "(")); + filters = substr(filters, strpos(filters, "(")()); ltrim(filters, "("); rtrim(filters, ")"); lstring part; diff --git a/src/lib/nall/string.hpp b/src/lib/nall/string.hpp index 65a4a4b8..3ff0392c 100644 --- a/src/lib/nall/string.hpp +++ b/src/lib/nall/string.hpp @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include diff --git a/src/lib/nall/string/base.hpp b/src/lib/nall/string/base.hpp index 179a7dd4..40d0e98c 100644 --- a/src/lib/nall/string/base.hpp +++ b/src/lib/nall/string/base.hpp @@ -35,12 +35,13 @@ namespace nall { inline bool operator> (const char*) const; inline bool operator>=(const char*) const; + inline string& operator=(const string&); + inline string& operator=(string&&); + inline string(); inline string(const char*); inline string(const string&); inline string(string&&); - inline string& operator=(const string&); - inline string& operator=(string&&); inline ~string(); inline bool readfile(const char*); @@ -73,8 +74,6 @@ namespace nall { inline char chrlower(char c); inline char chrupper(char c); inline int stricmp(const char *dest, const char *src); - inline int strpos (const char *str, const char *key); - inline int qstrpos(const char *str, const char *key); inline bool strbegin (const char *str, const char *key); inline bool stribegin(const char *str, const char *key); inline bool strend (const char *str, const char *key); diff --git a/src/lib/nall/string/compare.hpp b/src/lib/nall/string/compare.hpp index e1173de4..bd289753 100644 --- a/src/lib/nall/string/compare.hpp +++ b/src/lib/nall/string/compare.hpp @@ -21,38 +21,6 @@ int stricmp(const char *dest, const char *src) { return (int)chrlower(*dest) - (int)chrlower(*src); } -int strpos(const char *str, const char *key) { - int ssl = strlen(str), ksl = strlen(key); - - if(ksl > ssl) return -1; - for(int i = 0; i <= ssl - ksl; i++) { - if(!memcmp(str + i, key, ksl)) { - return i; - } - } - return -1; -} - -int qstrpos(const char *str, const char *key) { - int ssl = strlen(str), ksl = strlen(key); - - if(ksl > ssl) return -1; - for(int i = 0; i <= ssl - ksl;) { - uint8_t x = str[i]; - if(x == '\"' || x == '\'') { - uint8_t z = i++; - while(str[i] != x && i < ssl) i++; - if(i >= ssl) i = z; - } - if(!memcmp(str + i, key, ksl)) { - return i; - } else { - i++; - } - } - return -1; -} - bool strbegin(const char *str, const char *key) { int i, ssl = strlen(str), ksl = strlen(key); diff --git a/src/lib/nall/string/core.hpp b/src/lib/nall/string/core.hpp index d13bfc38..f69802e4 100644 --- a/src/lib/nall/string/core.hpp +++ b/src/lib/nall/string/core.hpp @@ -49,6 +49,20 @@ bool string::operator<=(const char *str) const { return strcmp(data, str) <= 0; bool string::operator> (const char *str) const { return strcmp(data, str) > 0; } bool string::operator>=(const char *str) const { return strcmp(data, str) >= 0; } +string& string::operator=(const string &value) { + assign(value); + return *this; +} + +string& string::operator=(string &&source) { + if(data) free(data); + size = source.size; + data = source.data; + source.data = 0; + source.size = 0; + return *this; +} + string::string() { size = 64; data = (char*)malloc(size + 1); @@ -71,20 +85,6 @@ string::string(string &&source) { source.data = 0; } -string& string::operator=(const string &value) { - assign(value); - return *this; -} - -string& string::operator=(string &&source) { - if(data) free(data); - size = source.size; - data = source.data; - source.data = 0; - source.size = 0; - return *this; -} - string::~string() { free(data); } diff --git a/src/lib/nall/string/strpos.hpp b/src/lib/nall/string/strpos.hpp new file mode 100644 index 00000000..a1bf85b4 --- /dev/null +++ b/src/lib/nall/string/strpos.hpp @@ -0,0 +1,60 @@ +#ifndef NALL_STRING_STRPOS_HPP +#define NALL_STRING_STRPOS_HPP + +//usage example: +//if(auto pos = strpos(str, key)) print(pos(), "\n"); +//prints position of key within str, only if it is found + +namespace nall { + +class strpos { + bool found; + unsigned position; +public: + inline operator bool() const { return found; } + inline unsigned operator()() const { return position; } + inline strpos(const char *str, const char *key) : found(false), position(0) { + unsigned ssl = strlen(str), ksl = strlen(key); + if(ksl > ssl) return; + + for(unsigned i = 0; i <= ssl - ksl; i++) { + if(!memcmp(str + i, key, ksl)) { + found = true; + position = i; + return; + } + } + } +}; + +class qstrpos { + bool found; + unsigned position; +public: + inline operator bool() const { return found; } + inline unsigned operator()() const { return position; } + inline qstrpos(const char *str, const char *key) : found(false), position(0) { + unsigned ssl = strlen(str), ksl = strlen(key); + if(ksl > ssl) return; + + for(unsigned i = 0; i <= ssl - ksl;) { + uint8_t x = str[i]; + if(x == '\"' || x == '\'') { + uint8_t z = i++; + while(str[i] != x && i < ssl) i++; + if(i >= ssl) i = z; + } + if(!memcmp(str + i, key, ksl)) { + found = true; + position = i; + return; + } else { + i++; + } + } + } +}; + +} + +#endif diff --git a/src/lib/nall/string/xml.hpp b/src/lib/nall/string/xml.hpp index d423f87f..218b4cbf 100644 --- a/src/lib/nall/string/xml.hpp +++ b/src/lib/nall/string/xml.hpp @@ -65,21 +65,25 @@ inline string xml_element::parse() const { } if(strbegin(source, ""); - if(pos == -1) return ""; - source += pos + 3; - continue; + if(auto pos = strpos(source, "-->")) { + source += pos() + 3; + continue; + } else { + return ""; + } } if(strbegin(source, ""); - if(pos == -1) return ""; - string cdata = substr(source, 9, pos - 9); - data << cdata; - offset += strlen(cdata); + if(auto pos = strpos(source, "]]>")) { + string cdata = substr(source, 9, pos() - 9); + data << cdata; + offset += strlen(cdata); - source += offset + 3; - continue; + source += offset + 3; + continue; + } else { + return ""; + } } //reject illegal characters @@ -115,7 +119,7 @@ inline bool xml_element::parse_head(string data) { data.qreplace("\t", " "); data.qreplace("\r", " "); data.qreplace("\n", " "); - while(qstrpos(data, " ") >= 0) data.qreplace(" ", " "); + while(qstrpos(data, " ")) data.qreplace(" ", " "); data.qreplace(" =", "="); data.qreplace("= ", "="); rtrim(data); @@ -153,24 +157,28 @@ inline bool xml_element::parse_body(const char *&data) { } if(strbegin(data, "!--")) { - signed offset = strpos(data, "-->"); - if(offset == -1) throw "..."; - data += offset + 3; - continue; + if(auto offset = strpos(data, "-->")) { + data += offset() + 3; + continue; + } else { + throw "..."; + } } if(strbegin(data, "![CDATA[")) { - signed offset = strpos(data, "]]>"); - if(offset == -1) throw "..."; - data += offset + 3; - continue; + if(auto offset = strpos(data, "]]>")) { + data += offset() + 3; + continue; + } else { + throw "..."; + } } - signed offset = strpos(data, ">"); - if(offset == -1) throw "..."; + auto offset = strpos(data, ">"); + if(!offset) throw "..."; - string tag = substr(data, 0, offset); - data += offset + 1; + string tag = substr(data, 0, offset()); + data += offset() + 1; const char *content_begin = data; bool self_terminating = false; @@ -195,16 +203,16 @@ inline bool xml_element::parse_body(const char *&data) { if(length > 0) content = substr(content_begin, 0, length); data++; - offset = strpos(data, ">"); - if(offset == -1) throw "..."; + auto offset = strpos(data, ">"); + if(!offset) throw "..."; - tag = substr(data, 0, offset); - data += offset + 1; + tag = substr(data, 0, offset()); + data += offset() + 1; tag.replace("\t", " "); tag.replace("\r", " "); tag.replace("\n", " "); - while(strpos(tag, " ") >= 0) tag.replace(" ", " "); + while(strpos(tag, " ")) tag.replace(" ", " "); rtrim(tag); if(name != tag) throw "..."; diff --git a/src/ui_qt/base/main.cpp b/src/ui_qt/base/main.cpp index ce227893..2e9282de 100644 --- a/src/ui_qt/base/main.cpp +++ b/src/ui_qt/base/main.cpp @@ -608,6 +608,11 @@ void MainWindow::showAbout() { aboutWindow->show(); } +void MainWindow::resizeEvent(QResizeEvent *event) { + Window::resizeEvent(event); + QApplication::processEvents(); +} + void MainWindow::closeEvent(QCloseEvent *event) { Window::closeEvent(event); quit(); diff --git a/src/ui_qt/base/main.moc.hpp b/src/ui_qt/base/main.moc.hpp index 29743882..4c89134a 100644 --- a/src/ui_qt/base/main.moc.hpp +++ b/src/ui_qt/base/main.moc.hpp @@ -96,6 +96,7 @@ public: void syncUi(); bool isActive(); + void resizeEvent(QResizeEvent*); void closeEvent(QCloseEvent*); MainWindow(); diff --git a/src/ui_qt/config.cpp b/src/ui_qt/config.cpp index 21c8e627..77c99104 100644 --- a/src/ui_qt/config.cpp +++ b/src/ui_qt/config.cpp @@ -77,6 +77,8 @@ Configuration::Configuration() { attach(video.isFullscreen = false, "video.isFullscreen"); attach(video.synchronize = false, "video.synchronize"); + attach(video.autoHideFullscreenMenu = false, "video.autoHideFullscreenMenu"); + attach(video.contrastAdjust = 0, "video.contrastAdjust"); attach(video.brightnessAdjust = 0, "video.brightnessAdjust"); attach(video.gammaAdjust = 0, "video.gammaAdjust"); diff --git a/src/ui_qt/config.hpp b/src/ui_qt/config.hpp index 49f17f67..a30ad275 100644 --- a/src/ui_qt/config.hpp +++ b/src/ui_qt/config.hpp @@ -39,6 +39,9 @@ public: struct Video { bool isFullscreen; bool synchronize; + + bool autoHideFullscreenMenu; + signed contrastAdjust, brightnessAdjust, gammaAdjust, scanlineAdjust; bool enableGammaRamp; double ntscAspectRatio, palAspectRatio; diff --git a/src/ui_qt/settings/video.cpp b/src/ui_qt/settings/video.cpp index cb9dcb8c..8d83ec18 100644 --- a/src/ui_qt/settings/video.cpp +++ b/src/ui_qt/settings/video.cpp @@ -8,6 +8,12 @@ VideoSettingsWindow::VideoSettingsWindow() { layout->setAlignment(Qt::AlignTop); setLayout(layout); + displayLabel = new QLabel("Display"); + layout->addWidget(displayLabel); + + autoHideFullscreenMenu = new QCheckBox("Auto-hide menus when entering fullscreen mode"); + layout->addWidget(autoHideFullscreenMenu); + colorLabel = new QLabel("Color Adjustment"); layout->addWidget(colorLabel); @@ -156,6 +162,7 @@ VideoSettingsWindow::VideoSettingsWindow() { vertexShaderDefault = new QPushButton("Default"); pixelShaderLayout->addWidget(vertexShaderDefault, 1, 3); + connect(autoHideFullscreenMenu, SIGNAL(stateChanged(int)), this, SLOT(autoHideFullscreenMenuToggle())); connect(contrastSlider, SIGNAL(valueChanged(int)), this, SLOT(contrastAdjust(int))); connect(brightnessSlider, SIGNAL(valueChanged(int)), this, SLOT(brightnessAdjust(int))); connect(gammaSlider, SIGNAL(valueChanged(int)), this, SLOT(gammaAdjust(int))); @@ -196,6 +203,8 @@ void VideoSettingsWindow::synchronizePixelShaderSettings() { void VideoSettingsWindow::syncUi() { int n; + autoHideFullscreenMenu->setChecked(config().video.autoHideFullscreenMenu); + n = config().video.contrastAdjust; contrastValue->setText(string() << (n > 0 ? "+" : "") << n << "%"); contrastSlider->setSliderPosition(n); @@ -234,6 +243,10 @@ void VideoSettingsWindow::syncUi() { vertexShaderValue->setText(config().path.vertexShader); } +void VideoSettingsWindow::autoHideFullscreenMenuToggle() { + config().video.autoHideFullscreenMenu = autoHideFullscreenMenu->isChecked(); +} + void VideoSettingsWindow::contrastAdjust(int value) { config().video.contrastAdjust = value; syncUi(); diff --git a/src/ui_qt/settings/video.moc.hpp b/src/ui_qt/settings/video.moc.hpp index eca1d834..38895a30 100644 --- a/src/ui_qt/settings/video.moc.hpp +++ b/src/ui_qt/settings/video.moc.hpp @@ -3,6 +3,8 @@ class VideoSettingsWindow : public QWidget { public: QVBoxLayout *layout; + QLabel *displayLabel; + QCheckBox *autoHideFullscreenMenu; QLabel *colorLabel; QGridLayout *colorLayout; QLabel *contrastLabel; @@ -49,6 +51,7 @@ public: VideoSettingsWindow(); private slots: + void autoHideFullscreenMenuToggle(); void contrastAdjust(int); void brightnessAdjust(int); void gammaAdjust(int); diff --git a/src/ui_qt/tools/cheateditor.cpp b/src/ui_qt/tools/cheateditor.cpp index 62326726..ae5c9333 100644 --- a/src/ui_qt/tools/cheateditor.cpp +++ b/src/ui_qt/tools/cheateditor.cpp @@ -245,12 +245,10 @@ void CheatEditorWindow::findCheatCodes() { file.close(); } - signed position = strpos(data, SNES::cartridge.sha256()) - 19; - if(position >= 0) { - const char *block = (const char*)data + position; - position = strpos(block, ""); - if(position >= 0) { - xml_element document = xml_parse(substr(block, 0, position + 12)); + if(auto position = strpos(data, SNES::cartridge.sha256())) { + const char *block = (const char*)data + position() - 19; + if(position = strpos(block, "")) { + xml_element document = xml_parse(substr(block, 0, position() + 12)); if(document.element.size() == 0) return; cheatImportWindow->refresh(document.element[0]); diff --git a/src/ui_qt/utility/window.cpp b/src/ui_qt/utility/window.cpp index 5489c72f..44bd8e1f 100644 --- a/src/ui_qt/utility/window.cpp +++ b/src/ui_qt/utility/window.cpp @@ -9,8 +9,8 @@ void Utility::updateFullscreenState() { } else { config().video.context = &config().video.fullscreen; mainWindow->showFullScreen(); - mainWindow->menuBar->setVisible(false); - mainWindow->statusBar->setVisible(false); + mainWindow->menuBar->setVisible(config().video.autoHideFullscreenMenu == false); + mainWindow->statusBar->setVisible(config().video.autoHideFullscreenMenu == false); } QApplication::processEvents(); diff --git a/supergameboy/Makefile b/supergameboy/Makefile deleted file mode 100644 index 60409afa..00000000 --- a/supergameboy/Makefile +++ /dev/null @@ -1,126 +0,0 @@ -include nall/Makefile - -c := $(compiler) -std=gnu99 -cpp := $(subst cc,++,$(compiler)) -std=gnu++0x -flags := -O3 -fomit-frame-pointer -I. -Icommon -Ilibgambatte/include -Ilibgambatte/src -link := - -ifeq ($(platform),osx) - flags := -fPIC $(flags) -else ifeq ($(platform),x) - flags := -fPIC $(flags) - link += -s -endif - -objects := supergameboy -objects += bitmap_font colorconversion cpu gambatte initstate interrupter -objects += memory rtc sound state_osd_elements statesaver video -objects += channel1 channel2 channel3 channel4 duty_unit envelope_unit length_counter -objects += basic_add_event break_event irq_event ly_counter lyc_irq -objects += m3_extra_cycles mode3_event mode0_irq mode1_irq mode2_irq -objects += sc_reader scx_reader sprite_mapper we_master_checker we wx_reader wy -objects += catrom2x catrom3x kreed2xsai maxsthq2x maxsthq3x file - -compile = \ - $(strip \ - $(if $(filter %.c,$<), \ - $(c) $(flags) $1 -c $< -o $@, \ - $(if $(filter %.cpp,$<), \ - $(cpp) $(flags) $1 -c $< -o $@ \ - ) \ - ) \ - ) - -%.o: $<; $(call compile) - -all: build; - -objects := $(patsubst %,obj/%.o,$(objects)) - -#################### -### supergameboy ### -#################### - -obj/supergameboy.o: supergameboy.cpp *.cpp *.hpp $(call rwildcard,interface/) - -################### -### libgambatte ### -################### - -obj/bitmap_font.o: libgambatte/src/bitmap_font.cpp $(call rwildcard,common/) $(call rwildcard,libgambatte/) -obj/colorconversion.o: libgambatte/src/colorconversion.cpp $(call rwildcard,common/) $(call rwildcard,libgambatte/) -obj/cpu.o: libgambatte/src/cpu.cpp $(call rwildcard,common/) $(call rwildcard,libgambatte/) -obj/gambatte.o: libgambatte/src/gambatte.cpp $(call rwildcard,common/) $(call rwildcard,libgambatte/) -obj/initstate.o: libgambatte/src/initstate.cpp $(call rwildcard,common/) $(call rwildcard,libgambatte/) -obj/interrupter.o: libgambatte/src/interrupter.cpp $(call rwildcard,common/) $(call rwildcard,libgambatte/) -obj/memory.o: libgambatte/src/memory.cpp $(call rwildcard,common/) $(call rwildcard,libgambatte/) -obj/rtc.o: libgambatte/src/rtc.cpp $(call rwildcard,common/) $(call rwildcard,libgambatte/) -obj/sound.o: libgambatte/src/sound.cpp $(call rwildcard,common/) $(call rwildcard,libgambatte/) -obj/state_osd_elements.o: libgambatte/src/state_osd_elements.cpp $(call rwildcard,common/) $(call rwildcard,libgambatte/) -obj/statesaver.o: libgambatte/src/statesaver.cpp $(call rwildcard,common/) $(call rwildcard,libgambatte/) -obj/video.o: libgambatte/src/video.cpp $(call rwildcard,common/) $(call rwildcard,libgambatte/) - -obj/channel1.o: libgambatte/src/sound/channel1.cpp $(call rwildcard,common/) $(call rwildcard,libgambatte/) -obj/channel2.o: libgambatte/src/sound/channel2.cpp $(call rwildcard,common/) $(call rwildcard,libgambatte/) -obj/channel3.o: libgambatte/src/sound/channel3.cpp $(call rwildcard,common/) $(call rwildcard,libgambatte/) -obj/channel4.o: libgambatte/src/sound/channel4.cpp $(call rwildcard,common/) $(call rwildcard,libgambatte/) -obj/duty_unit.o: libgambatte/src/sound/duty_unit.cpp $(call rwildcard,common/) $(call rwildcard,libgambatte/) -obj/envelope_unit.o: libgambatte/src/sound/envelope_unit.cpp $(call rwildcard,common/) $(call rwildcard,libgambatte/) -obj/length_counter.o: libgambatte/src/sound/length_counter.cpp $(call rwildcard,common/) $(call rwildcard,libgambatte/) - -obj/basic_add_event.o: libgambatte/src/video/basic_add_event.cpp $(call rwildcard,common/) $(call rwildcard,libgambatte/) -obj/break_event.o: libgambatte/src/video/break_event.cpp $(call rwildcard,common/) $(call rwildcard,libgambatte/) -obj/irq_event.o: libgambatte/src/video/irq_event.cpp $(call rwildcard,common/) $(call rwildcard,libgambatte/) -obj/ly_counter.o: libgambatte/src/video/ly_counter.cpp $(call rwildcard,common/) $(call rwildcard,libgambatte/) -obj/lyc_irq.o: libgambatte/src/video/lyc_irq.cpp $(call rwildcard,common/) $(call rwildcard,libgambatte/) -obj/m3_extra_cycles.o: libgambatte/src/video/m3_extra_cycles.cpp $(call rwildcard,common/) $(call rwildcard,libgambatte/) -obj/mode3_event.o: libgambatte/src/video/mode3_event.cpp $(call rwildcard,common/) $(call rwildcard,libgambatte/) -obj/mode0_irq.o: libgambatte/src/video/mode0_irq.cpp $(call rwildcard,common/) $(call rwildcard,libgambatte/) -obj/mode1_irq.o: libgambatte/src/video/mode1_irq.cpp $(call rwildcard,common/) $(call rwildcard,libgambatte/) -obj/mode2_irq.o: libgambatte/src/video/mode2_irq.cpp $(call rwildcard,common/) $(call rwildcard,libgambatte/) -obj/sc_reader.o: libgambatte/src/video/sc_reader.cpp $(call rwildcard,common/) $(call rwildcard,libgambatte/) -obj/scx_reader.o: libgambatte/src/video/scx_reader.cpp $(call rwildcard,common/) $(call rwildcard,libgambatte/) -obj/sprite_mapper.o: libgambatte/src/video/sprite_mapper.cpp $(call rwildcard,common/) $(call rwildcard,libgambatte/) -obj/we_master_checker.o: libgambatte/src/video/we_master_checker.cpp $(call rwildcard,common/) $(call rwildcard,libgambatte/) -obj/we.o: libgambatte/src/video/we.cpp $(call rwildcard,common/) $(call rwildcard,libgambatte/) -obj/wx_reader.o: libgambatte/src/video/wx_reader.cpp $(call rwildcard,common/) $(call rwildcard,libgambatte/) -obj/wy.o: libgambatte/src/video/wy.cpp $(call rwildcard,common/) $(call rwildcard,libgambatte/) - -obj/catrom2x.o: libgambatte/src/video/filters/catrom2x.cpp $(call rwildcard,common/) $(call rwildcard,libgambatte/) -obj/catrom3x.o: libgambatte/src/video/filters/catrom3x.cpp $(call rwildcard,common/) $(call rwildcard,libgambatte/) -obj/kreed2xsai.o: libgambatte/src/video/filters/kreed2xsai.cpp $(call rwildcard,common/) $(call rwildcard,libgambatte/) -obj/maxsthq2x.o: libgambatte/src/video/filters/maxsthq2x.cpp $(call rwildcard,common/) $(call rwildcard,libgambatte/) -obj/maxsthq3x.o: libgambatte/src/video/filters/maxsthq3x.cpp $(call rwildcard,common/) $(call rwildcard,libgambatte/) - -obj/file.o: libgambatte/src/file/file.cpp $(call rwildcard,common/) $(call rwildcard,libgambatte/) - -############### -### targets ### -############### - -build: $(objects) -ifeq ($(platform),win) - $(cpp) $(link) -o supergameboy.dll -shared -Wl,--out-implib,libsupergameboy.a $(objects) $(qtlib) -else ifeq ($(platform),osx) - ar rcs libsupergameboy.a $(objects) - $(cpp) $(link) -o libsupergameboy.dylib -shared -dynamiclib $(objects) $(qtlib) -else - ar rcs libsupergameboy.a $(objects) - $(cpp) $(link) -o libsupergameboy.so -shared -Wl,-soname,libsupergameboy.so.1 $(objects) $(qtlib) -endif - -install: -ifeq ($(platform),osx) - cp libsupergameboy.dylib /usr/local/lib/libsupergameboy.dylib -else - install -D -m 755 libsupergameboy.a $(DESTDIR)$(prefix)/lib - install -D -m 755 libsupergameboy.so $(DESTDIR)$(prefix)/lib - ldconfig -n $(DESTDIR)$(prefix)/lib -endif - -clean: - -@$(call delete,obj/*.o) - -@$(call delete,libsupergameboy.a) - -@$(call delete,supergameboy.dll) - -@$(call delete,libsupergameboy.dylib) - -@$(call delete,libsupergameboy.so) diff --git a/supergameboy/cc.bat b/supergameboy/cc.bat deleted file mode 100644 index 7e2f36ad..00000000 --- a/supergameboy/cc.bat +++ /dev/null @@ -1,2 +0,0 @@ -@mingw32-make -@pause diff --git a/supergameboy/clean.bat b/supergameboy/clean.bat deleted file mode 100644 index d8bb7e0b..00000000 --- a/supergameboy/clean.bat +++ /dev/null @@ -1 +0,0 @@ -@mingw32-make clean diff --git a/supergameboy/common/adaptivesleep.cpp b/supergameboy/common/adaptivesleep.cpp deleted file mode 100644 index 48c40979..00000000 --- a/supergameboy/common/adaptivesleep.cpp +++ /dev/null @@ -1,56 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2008 by Sindre AamÃ¥s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "adaptivesleep.h" - -usec_t AdaptiveSleep::sleepUntil(usec_t base, usec_t inc) { - usec_t now = getusecs(); - usec_t diff = now - base; - - if (diff >= inc) - return diff - inc; - - diff = inc - diff; - - if (diff > oversleep + oversleepVar) { - diff -= oversleep + oversleepVar; - usecsleep(diff); - const usec_t ideal = now + diff; - now = getusecs(); - - { - usec_t curOversleep = now - ideal; - - if (negate(curOversleep) < curOversleep) - curOversleep = 0; - - oversleepVar = (oversleepVar * 15 + (curOversleep < oversleep ? oversleep - curOversleep : curOversleep - oversleep)) >> 4; - oversleep = (oversleep * 15 + curOversleep) >> 4; - } - - noSleep = 60; - } else if (--noSleep == 0) { - noSleep = 60; - oversleep = oversleepVar = 0; - } - - while (now - base < inc) - now = getusecs(); - - return 0; -} diff --git a/supergameboy/common/adaptivesleep.h b/supergameboy/common/adaptivesleep.h deleted file mode 100644 index de2010a0..00000000 --- a/supergameboy/common/adaptivesleep.h +++ /dev/null @@ -1,34 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2008 by Sindre AamÃ¥s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef ADAPTIVE_SLEEP_H -#define ADAPTIVE_SLEEP_H - -#include "usec.h" - -class AdaptiveSleep { - usec_t oversleep; - usec_t oversleepVar; - unsigned noSleep; - -public: - AdaptiveSleep() : oversleep(0), oversleepVar(0), noSleep(60) {} - usec_t sleepUntil(usec_t base, usec_t inc); -}; - -#endif diff --git a/supergameboy/common/array.h b/supergameboy/common/array.h deleted file mode 100644 index f01806ea..00000000 --- a/supergameboy/common/array.h +++ /dev/null @@ -1,40 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2008 by Sindre Aam�s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef ARRAY_H -#define ARRAY_H - -#include - -template -class Array { - T *a; - std::size_t sz; - - Array(const Array &ar); - -public: - Array(const std::size_t size = 0) : a(size ? new T[size] : 0), sz(size) {} - ~Array() { delete []a; } - void reset(const std::size_t size) { delete []a; a = size ? new T[size] : 0; sz = size; } - std::size_t size() const { return sz; } - operator T*() { return a; } - operator const T*() const { return a; } -}; - -#endif diff --git a/supergameboy/common/rateest.cpp b/supergameboy/common/rateest.cpp deleted file mode 100644 index c1feba6c..00000000 --- a/supergameboy/common/rateest.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2008 by Sindre AamÃ¥s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "rateest.h" -#include - -void RateEst::SumQueue::reset() { - q.clear(); - samples_ = usecs_ = 0; -} - -void RateEst::SumQueue::push(const long samples, const usec_t usecs) { - q.push_back(pair_t(samples, usecs)); - samples_ += samples; - usecs_ += usecs; -} - -void RateEst::SumQueue::pop() { - const pair_t &f = q.front(); - samples_ -= f.first; - usecs_ -= f.second; - q.pop_front(); -} - -static usec_t sampleUsecs(long samples, long rate) { - return static_cast((samples * 1000000.0f) / (rate ? rate : 1) + 0.5f); -} - -static long limit(long est, const long reference) { - if (est > reference + (reference >> 6)) - est = reference + (reference >> 6); - else if (est < reference - (reference >> 6)) - est = reference - (reference >> 6); - - return est; -} - -void RateEst::init(long srate, long reference, const long maxSamplePeriod) { - maxPeriod = sampleUsecs(maxSamplePeriod, reference); - - srate <<= UPSHIFT; - reference <<= UPSHIFT; - - this->srate.est = limit(srate, reference); - this->srate.var = srate >> 12; - last = 0; - this->reference = reference; - samples = ((this->srate.est >> UPSHIFT) * 12) << 5; - usecs = 12000000 << 5; - sumq.reset(); -} - -void RateEst::feed(long samplesIn, const usec_t now) { - usec_t usecsIn = now - last; - - if (last && usecsIn < maxPeriod) { - sumq.push(samplesIn, usecsIn); - - while ((usecsIn = sumq.usecs()) > 100000) { - samplesIn = sumq.samples(); - sumq.pop(); - - if (std::abs(static_cast(samplesIn * (1000000.0f * UP) / usecsIn) - reference) < reference >> 1) { - samples += (samplesIn - sumq.samples()) << 5; - usecs += (usecsIn - sumq.usecs()) << 5; - - long est = static_cast(samples * (1000000.0f * UP) / usecs + 0.5f); - est = limit((srate.est * 31 + est + 16) >> 5, reference); - srate.var = (srate.var * 15 + std::abs(est - srate.est) + 8) >> 4; - srate.est = est; - - if (usecs > 16000000 << 5) { - samples = (samples * 3 + 2) >> 2; - usecs = (usecs * 3 + 2) >> 2; - } - } - } - } - - last = now; -} diff --git a/supergameboy/common/rateest.h b/supergameboy/common/rateest.h deleted file mode 100644 index 3e109541..00000000 --- a/supergameboy/common/rateest.h +++ /dev/null @@ -1,73 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2008 by Sindre AamÃ¥s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef RATEEST_H -#define RATEEST_H - -#include "usec.h" -#include -#include - -class RateEst { -public: - struct Result { - long est; - long var; - }; - -private: - class SumQueue { - typedef std::pair pair_t; - typedef std::deque q_t; - - q_t q; - long samples_; - usec_t usecs_; - - public: - SumQueue() : samples_(0), usecs_(0) {} - void reset(); - long samples() const { return samples_; } - usec_t usecs() const { return usecs_; } - void push(long samples, usec_t usecs); - void pop(); - }; - - enum { UPSHIFT = 5 }; - enum { UP = 1 << UPSHIFT }; - - Result srate; - SumQueue sumq; - usec_t last; - usec_t usecs; - usec_t maxPeriod; - long reference; - long samples; - -public: - RateEst(long srate = 0) { init(srate); } - RateEst(long srate, long reference) { init(srate, reference); } - void init(long srate) { init(srate, srate); } - void init(long srate, long reference) { init(srate, reference, reference); } - void init(long srate, long reference, long maxSamplePeriod); - void reset() { last = 0; } - void feed(long samples, usec_t usecs = getusecs()); - const Result result() const { const Result res = { (srate.est + UP / 2) >> UPSHIFT, (srate.var + UP / 2) >> UPSHIFT }; return res; } -}; - -#endif diff --git a/supergameboy/common/resample/blackmansinc.h b/supergameboy/common/resample/blackmansinc.h deleted file mode 100644 index 86578239..00000000 --- a/supergameboy/common/resample/blackmansinc.h +++ /dev/null @@ -1,100 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2008 by Sindre AamÃ¥s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef BLACKMANSINC_H -#define BLACKMANSINC_H - -#include "convoluter.h" -#include "subresampler.h" -#include "makesinckernel.h" -#include "cic4.h" -#include -#include - -template -class BlackmanSinc : public SubResampler { - PolyPhaseConvoluter convoluters[channels]; - short *kernel; - - static double blackmanWin(const long i, const long M) { - static const double PI = 3.14159265358979323846; - return 0.42 - 0.5 * std::cos(2 * PI * i / M) + 0.08 * std::cos(4 * PI * i / M); - } - - void init(unsigned div, unsigned phaseLen, double fc); - -public: - enum { MUL = phases }; - - typedef Cic4 Cic; - static float cicLimit() { return 4.7f; } - - class RollOff { - static unsigned toTaps(const float rollOffWidth) { - static const float widthTimesTaps = 4.5f; - return std::ceil(widthTimesTaps / rollOffWidth); - } - - static float toFc(const float rollOffStart, const int taps) { - static const float startToFcDeltaTimesTaps = 1.69f; - return startToFcDeltaTimesTaps / taps + rollOffStart; - } - - public: - const unsigned taps; - const float fc; - - RollOff(float rollOffStart, float rollOffWidth) : taps(toTaps(rollOffWidth)), fc(toFc(rollOffStart, taps)) {} - }; - - BlackmanSinc(unsigned div, unsigned phaseLen, double fc) { init(div, phaseLen, fc); } - BlackmanSinc(unsigned div, RollOff ro) { init(div, ro.taps, ro.fc); } - ~BlackmanSinc() { delete[] kernel; } - std::size_t resample(short *out, const short *in, std::size_t inlen); - void adjustDiv(unsigned div); - unsigned mul() const { return MUL; } - unsigned div() const { return convoluters[0].div(); } -}; - -template -void BlackmanSinc::init(const unsigned div, const unsigned phaseLen, const double fc) { - kernel = new short[phaseLen * phases]; - - makeSincKernel(kernel, phases, phaseLen, fc, blackmanWin); - - for (unsigned i = 0; i < channels; ++i) - convoluters[i].reset(kernel, phaseLen, div); -} - -template -std::size_t BlackmanSinc::resample(short *const out, const short *const in, const std::size_t inlen) { - std::size_t samplesOut; - - for (unsigned i = 0; i < channels; ++i) - samplesOut = convoluters[i].filter(out + i, in + i, inlen); - - return samplesOut; -} - -template -void BlackmanSinc::adjustDiv(const unsigned div) { - for (unsigned i = 0; i < channels; ++i) - convoluters[i].adjustDiv(div); -} - -#endif diff --git a/supergameboy/common/resample/chainresampler.cpp b/supergameboy/common/resample/chainresampler.cpp deleted file mode 100644 index 6836a05b..00000000 --- a/supergameboy/common/resample/chainresampler.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2008 by Sindre AamÃ¥s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "chainresampler.h" - -float ChainResampler::get2ChainMidRatio(const float ratio, const float rollOff) { - return std::sqrt(0.5f * rollOff * ratio) + 1; -} - -float ChainResampler::get2ChainCost(const float ratio, const float rollOff, const float midRatio) { - return midRatio * ratio / ((midRatio - 1) * 2) + midRatio / rollOff; -} - -float ChainResampler::get3ChainRatio1(float ratio1, const float rollOff, const float ratio) { - for (unsigned n = 8; n--;) { - ratio1 = std::sqrt(ratio - ratio / get3ChainRatio2(ratio1, rollOff)) + 1; - } - - return ratio1; -} - -float ChainResampler::get3ChainCost(const float ratio, const float rollOff, const float ratio1, const float ratio2) { - return ratio1 * ratio / ((ratio1 - 1) * 2) + ratio2 * ratio1 / ((ratio2 - 1) * 2) + ratio2 / rollOff; -} - -std::size_t ChainResampler::reallocateBuffer() { - std::size_t bufSz[2] = { 0, 0 }; - std::size_t inSz = periodSize; - int i = -1; - - for (list_t::iterator it = list.begin(); it != list.end(); ++it) { - inSz = (inSz * (*it)->mul() - 1) / (*it)->div() + 1; - - ++i; - - if (inSz > bufSz[i&1]) - bufSz[i&1] = inSz; - } - - if (inSz >= bufSz[i&1]) - bufSz[i&1] = 0; - - if (bufferSize < bufSz[0] + bufSz[1]) { - delete[] buffer; - buffer = (bufferSize = bufSz[0] + bufSz[1]) ? new short[bufferSize * channels] : NULL; - } - - buffer2 = bufSz[1] ? buffer + bufSz[0] * channels : NULL; - - return (maxOut_ = inSz); -} - -void ChainResampler::adjustRate(const long inRate, const long outRate) { - unsigned long mul, div; - - exactRatio(mul, div); - - bigSinc->adjustDiv(static_cast(inRate) * mul / (static_cast(div / bigSinc->div()) * outRate) + 0.5); - - reallocateBuffer(); - setRate(inRate, outRate); -} - -void ChainResampler::exactRatio(unsigned long &mul, unsigned long &div) const { - mul = 1; - div = 1; - - for (list_t::const_iterator it = list.begin(); it != list.end(); ++it) { - mul *= (*it)->mul(); - div *= (*it)->div(); - } -} - -std::size_t ChainResampler::resample(short *const out, const short *const in, std::size_t inlen) { - assert(inlen <= periodSize); - - short *const buf = buffer != buffer2 ? buffer : out; - short *const buf2 = buffer2 ? buffer2 : out; - - const short *inbuf = in; - short *outbuf = NULL; - - for (list_t::iterator it = list.begin(); it != list.end(); ++it) { - outbuf = ++list_t::iterator(it) == list.end() ? out : (inbuf == buf ? buf2 : buf); - inlen = (*it)->resample(outbuf, inbuf, inlen); - inbuf = outbuf; - } - - return inlen; -} - -void ChainResampler::uninit() { - delete[] buffer; - buffer2 = buffer = NULL; - bufferSize = 0; - periodSize = 0; - bigSinc = NULL; - - for (list_t::iterator it = list.begin(); it != list.end(); ++it) - delete *it; - - list.clear(); -} diff --git a/supergameboy/common/resample/chainresampler.h b/supergameboy/common/resample/chainresampler.h deleted file mode 100644 index aeb52d6c..00000000 --- a/supergameboy/common/resample/chainresampler.h +++ /dev/null @@ -1,189 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2008 by Sindre AamÃ¥s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef CHAINRESAMPLER_H -#define CHAINRESAMPLER_H - -#include -#include -#include -#include -#include -#include "subresampler.h" -#include "resampler.h" -#include "upsampler.h" - -class ChainResampler : public Resampler { - enum { channels = 2 }; - - typedef std::list list_t; - - list_t list; - SubResampler *bigSinc; - short *buffer; - short *buffer2; - std::size_t bufferSize; - std::size_t periodSize; - std::size_t maxOut_; - - static float get1ChainCost(const float ratio, const float rollOff) { - return ratio / rollOff; - } - - static float get2ChainMidRatio(float ratio, float rollOff); - static float get2ChainCost(float ratio, float rollOff, float midRatio); - - static float get3ChainRatio2(const float ratio1, const float rollOff) { - return get2ChainMidRatio(ratio1, rollOff); - } - - static float get3ChainRatio1(float ratio1, float rollOff, float ratio); - static float get3ChainCost(float ratio, float rollOff, float ratio1, float ratio2); - - template class Sinc> - std::size_t downinit(long inRate, long outRate, std::size_t periodSize); - - std::size_t reallocateBuffer(); - - template class Sinc> - std::size_t upinit(long inRate, long outRate, std::size_t periodSize); - -public: - ChainResampler() : bigSinc(NULL), buffer(NULL), buffer2(NULL), bufferSize(0), periodSize(0) {} - ~ChainResampler() { uninit(); } - - void adjustRate(long inRate, long outRate); - void exactRatio(unsigned long &mul, unsigned long &div) const; - - template class Sinc> - std::size_t init(long inRate, long outRate, std::size_t periodSize); - std::size_t maxOut(std::size_t /*inlen*/) const { return maxOut_; } - std::size_t resample(short *out, const short *in, std::size_t inlen); - void uninit(); -}; - -template class Sinc> -std::size_t ChainResampler::init(const long inRate, const long outRate, const std::size_t periodSize) { - setRate(inRate, outRate); - - if (outRate > inRate) - return upinit(inRate, outRate, periodSize); - else - return downinit(inRate, outRate, periodSize); -} - -template class Sinc> -std::size_t ChainResampler::downinit(const long inRate, const long outRate, const std::size_t periodSize) { - typedef Sinc BigSinc; - typedef Sinc SmallSinc; - - uninit(); - this->periodSize = periodSize; - - - const float rollOff = std::max((outRate - 36000.0f + outRate - 40000.0f) / outRate, 0.2f); - - double ratio = static_cast(inRate) / outRate; - - while (ratio >= BigSinc::cicLimit() * 2) { - const int div = std::min(static_cast(ratio / BigSinc::cicLimit()), BigSinc::Cic::MAX_DIV); - - list.push_back(new typename BigSinc::Cic(div)); - ratio /= div; - } - - { - int div_2c = ratio * SmallSinc::MUL / get2ChainMidRatio(ratio, rollOff) + 0.5f; - double ratio_2c = ratio * SmallSinc::MUL / div_2c; - float cost_2c = get2ChainCost(ratio, rollOff, ratio_2c); - - if (cost_2c < get1ChainCost(ratio, rollOff)) { - const int div1_3c = ratio * SmallSinc::MUL / get3ChainRatio1(ratio_2c, rollOff, ratio) + 0.5f; - const double ratio1_3c = ratio * SmallSinc::MUL / div1_3c; - const int div2_3c = ratio1_3c * SmallSinc::MUL / get3ChainRatio2(ratio1_3c, rollOff) + 0.5f; - const double ratio2_3c = ratio1_3c * SmallSinc::MUL / div2_3c; - - if (get3ChainCost(ratio, rollOff, ratio1_3c, ratio2_3c) < cost_2c) { - list.push_back(new SmallSinc(div1_3c, typename SmallSinc::RollOff(0.5f / ratio, (ratio1_3c - 1) / ratio))); - ratio = ratio1_3c; - div_2c = div2_3c; - ratio_2c = ratio2_3c; - } - - list.push_back(new SmallSinc(div_2c, typename SmallSinc::RollOff(0.5f / ratio, (ratio_2c - 1) / ratio))); - ratio = ratio_2c; - } - } - - list.push_back(bigSinc = new BigSinc(BigSinc::MUL * ratio + 0.5, - typename BigSinc::RollOff(0.5f * (1 + std::max((outRate - 40000.0f) / outRate, 0.0f) - rollOff) / ratio, 0.5f * rollOff / ratio))); - - return reallocateBuffer(); -} - -template class Sinc> -std::size_t ChainResampler::upinit(const long inRate, const long outRate, const std::size_t periodSize) { - typedef Sinc BigSinc; - typedef Sinc SmallSinc; - - uninit(); - this->periodSize = periodSize; - - const float rollOff = std::max((inRate - 36000.0f) / inRate, 0.2f); - - double ratio = static_cast(outRate) / inRate; - - // Spectral images above 20 kHz assumed inaudible - { - const int div = outRate / std::max(inRate, 40000l); - - if (div >= 2) { - list.push_front(new Upsampler(div)); - ratio /= div; - } - } - - { - int div_2c = get2ChainMidRatio(ratio, rollOff) * SmallSinc::MUL / ratio + 0.5f; - double ratio_2c = ratio * div_2c / SmallSinc::MUL; - float cost_2c = get2ChainCost(ratio, rollOff, ratio_2c); - - if (cost_2c < get1ChainCost(ratio, rollOff)) { - const int div1_3c = get3ChainRatio1(ratio_2c, rollOff, ratio) * SmallSinc::MUL / ratio + 0.5f; - const double ratio1_3c = ratio * div1_3c / SmallSinc::MUL; - const int div2_3c = get3ChainRatio2(ratio1_3c, rollOff) * SmallSinc::MUL / ratio1_3c + 0.5f; - const double ratio2_3c = ratio1_3c * div2_3c / SmallSinc::MUL; - - if (get3ChainCost(ratio, rollOff, ratio1_3c, ratio2_3c) < cost_2c) { - list.push_front(new SmallSinc(div1_3c, typename SmallSinc::RollOff(0.5f / ratio1_3c, (ratio1_3c - 1) / ratio1_3c))); - ratio = ratio1_3c; - div_2c = div2_3c; - ratio_2c = ratio2_3c; - } - - list.push_front(new SmallSinc(div_2c, typename SmallSinc::RollOff(0.5f / ratio_2c, (ratio_2c - 1) / ratio_2c))); - ratio = ratio_2c; - } - } - - list.push_front(bigSinc = new BigSinc(BigSinc::MUL / ratio + 0.5, typename BigSinc::RollOff(0.5f * (1 - rollOff), 0.5f * rollOff))); - - return reallocateBuffer(); -} - -#endif diff --git a/supergameboy/common/resample/cic2.h b/supergameboy/common/resample/cic2.h deleted file mode 100644 index 1f12bfc9..00000000 --- a/supergameboy/common/resample/cic2.h +++ /dev/null @@ -1,198 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2008 by Sindre AamÃ¥s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef CIC2_H -#define CIC2_H - -#include "subresampler.h" - -template -class Cic2Core { -// enum { BUFLEN = 64 }; -// unsigned long buf[BUFLEN]; - unsigned long sum1; - unsigned long sum2; - unsigned long prev1; - unsigned long prev2; - unsigned div_; - unsigned nextdivn; -// unsigned bufpos; - -public: - Cic2Core(const unsigned div = 2) { - reset(div); - } - - unsigned div() const { return div_; } - std::size_t filter(short *out, const short *in, std::size_t inlen); - void reset(unsigned div); -}; - -template -void Cic2Core::reset(const unsigned div) { - sum2 = sum1 = 0; - prev2 = prev1 = 0; - this->div_ = div; - nextdivn = div; -// bufpos = div - 1; -} - -template -std::size_t Cic2Core::filter(short *out, const short *const in, std::size_t inlen) { -// const std::size_t produced = (inlen + div_ - (bufpos + 1)) / div_; - const std::size_t produced = (inlen + div_ - nextdivn) / div_; - const long mul = 0x10000 / (div_ * div_); // trouble if div is too large, may be better to only support power of 2 div - const short *s = in; - - /*unsigned long sm1 = sum1; - unsigned long sm2 = sum2; - - while (inlen >> 2) { - unsigned n = (inlen < BUFLEN ? inlen >> 2 : BUFLEN >> 2); - const unsigned end = n * 4; - unsigned i = 0; - - do { - unsigned long s1 = sm1 += static_cast(*s); - s += channels; - sm1 += static_cast(*s); - s += channels; - buf[i++] = sm2 += s1; - buf[i++] = sm2 += sm1; - s1 = sm1 += static_cast(*s); - s += channels; - sm1 += static_cast(*s); - s += channels; - buf[i++] = sm2 += s1; - buf[i++] = sm2 += sm1; - } while (--n); - - while (bufpos < end) { - const unsigned long out2 = buf[bufpos] - prev2; - prev2 = buf[bufpos]; - bufpos += div_; - - *out = static_cast(out2 - prev1) * mul / 0x10000; - prev1 = out2; - out += channels; - } - - bufpos -= end; - inlen -= end; - } - - if (inlen) { - unsigned n = inlen; - unsigned i = 0; - - do { - sm1 += static_cast(*s); - s += channels; - buf[i++] = sm2 += sm1; - } while (--n); - - while (bufpos < inlen) { - const unsigned long out2 = buf[bufpos] - prev2; - prev2 = buf[bufpos]; - bufpos += div_; - - *out = static_cast(out2 - prev1) * mul / 0x10000; - prev1 = out2; - out += channels; - } - - bufpos -= inlen; - } - - sum1 = sm1; - sum2 = sm2;*/ - - unsigned long sm1 = sum1; - unsigned long sm2 = sum2; - - if (inlen >= nextdivn) { - unsigned divn = nextdivn; - std::size_t n = produced; - - do { - do { - sm1 += static_cast(*s); - s += channels; - sm2 += sm1; - } while (--divn); - - const unsigned long out2 = sm2 - prev2; - prev2 = sm2; - - *out = static_cast(out2 - prev1) * mul / 0x10000; - prev1 = out2; - out += channels; - - divn = div_; - } while (--n); - - nextdivn = div_; - } - - { - unsigned divn = (in + inlen * channels - s) / channels; - nextdivn -= divn; - - while (divn--) { - sm1 += static_cast(*s); - s += channels; - sm2 += sm1; - } - } - - sum1 = sm1; - sum2 = sm2; - - return produced; -} - -template -class Cic2 : public SubResampler { - Cic2Core cics[channels]; - -public: - enum { MAX_DIV = 64 }; - Cic2(unsigned div); - std::size_t resample(short *out, const short *in, std::size_t inlen); - unsigned mul() const { return 1; } - unsigned div() const { return cics[0].div(); } -}; - -template -Cic2::Cic2(const unsigned div) { - for (unsigned i = 0; i < channels; ++i) - cics[i].reset(div); -} - -template -std::size_t Cic2::resample(short *const out, const short *const in, const std::size_t inlen) { - std::size_t samplesOut; - - for (unsigned i = 0; i < channels; ++i) { - samplesOut = cics[i].filter(out + i, in + i, inlen); - } - - return samplesOut; -} - -#endif diff --git a/supergameboy/common/resample/cic3.h b/supergameboy/common/resample/cic3.h deleted file mode 100644 index 85b9dcee..00000000 --- a/supergameboy/common/resample/cic3.h +++ /dev/null @@ -1,382 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2008 by Sindre AamÃ¥s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef CIC3_H -#define CIC3_H - -#include "subresampler.h" - -template -class Cic3Core { -// enum { BUFLEN = 64 }; -// unsigned long buf[BUFLEN]; - unsigned long sum1; - unsigned long sum2; - unsigned long sum3; - unsigned long prev1; - unsigned long prev2; - unsigned long prev3; - unsigned div_; - unsigned nextdivn; -// unsigned bufpos; - -public: - Cic3Core(const unsigned div = 1) { - reset(div); - } - - unsigned div() const { return div_; } - std::size_t filter(short *out, const short *in, std::size_t inlen); - void reset(unsigned div); -}; - -template -void Cic3Core::reset(const unsigned div) { - sum3 = sum2 = sum1 = 0; - prev3 = prev2 = prev1 = 0; - this->div_ = div; - nextdivn = div; -// bufpos = div - 1; -} - -template -std::size_t Cic3Core::filter(short *out, const short *const in, std::size_t inlen) { -// const std::size_t produced = (inlen + div_ - (bufpos + 1)) / div_; - const std::size_t produced = (inlen + div_ - nextdivn) / div_; - const long mul = 0x10000 / (div_ * div_ * div_); // trouble if div is too large, may be better to only support power of 2 div - const short *s = in; - - /*unsigned long sm1 = sum1; - unsigned long sm2 = sum2; - unsigned long sm3 = sum3; - - while (inlen >> 1) { - unsigned n = (inlen < BUFLEN ? inlen >> 1 : BUFLEN >> 1); - const unsigned end = n * 2; - unsigned i = 0; - - do { - unsigned long s1 = sm1 += static_cast(*s); - s += channels; - sm1 += static_cast(*s); - s += channels; - unsigned long s2 = sm2 += s1; - sm2 += sm1; - buf[i++] = sm3 += s2; - buf[i++] = sm3 += sm2; - } while (--n); - - while (bufpos < end) { - const unsigned long out3 = buf[bufpos] - prev3; - prev3 = buf[bufpos]; - bufpos += div_; - - const unsigned long out2 = out3 - prev2; - prev2 = out3; - - *out = static_cast(out2 - prev1) * mul / 0x10000; - prev1 = out2; - out += channels; - } - - bufpos -= end; - inlen -= end; - } - - if (inlen) { - unsigned n = inlen; - unsigned i = 0; - - do { - sm1 += static_cast(*s); - s += channels; - sm2 += sm1; - buf[i++] = sm3 += sm2; - } while (--n); - - while (bufpos < inlen) { - const unsigned long out3 = buf[bufpos] - prev3; - prev3 = buf[bufpos]; - bufpos += div_; - - const unsigned long out2 = out3 - prev2; - prev2 = out3; - - *out = static_cast(out2 - prev1) * mul / 0x10000; - prev1 = out2; - out += channels; - } - - bufpos -= inlen; - } - - sum1 = sm1; - sum2 = sm2; - sum3 = sm3;*/ - - - unsigned long sm1 = sum1; - unsigned long sm2 = sum2; - unsigned long sm3 = sum3; - - if (inlen >= nextdivn) { - unsigned divn = nextdivn; - std::size_t n = produced; - - do { - do { - sm1 += static_cast(*s); - sm2 += sm1; - sm3 += sm2; - s += channels; - } while (--divn); - - const unsigned long out3 = sm3 - prev3; - prev3 = sm3; - - const unsigned long out2 = out3 - prev2; - prev2 = out3; - - *out = static_cast(out2 - prev1) * mul / 0x10000; - prev1 = out2; - out += channels; - - divn = div_; - } while (--n); - - nextdivn = div_; - } - - { - unsigned divn = (in + inlen * channels - s) / channels; - nextdivn -= divn; - - while (divn--) { - sm1 += static_cast(*s); - sm2 += sm1; - sm3 += sm2; - s += channels; - } - } - - sum1 = sm1; - sum2 = sm2; - sum3 = sm3; - - return produced; -} - -/*template -class Cic3EvenOddCore { - unsigned long sum1; - unsigned long sum2; - unsigned long sum3; - unsigned long prev1; - unsigned long prev2; - unsigned long prev3; - unsigned div_; - unsigned nextdivn; - - static int getMul(unsigned div) { - return 0x10000 / (div * div * div); // trouble if div is too large, may be better to only support power of 2 div - } - - void filterEven(short *out, const short *s, std::size_t n); - void filterOdd(short *out, const short *s, std::size_t n); - -public: - Cic3EvenOddCore(const unsigned div = 2) { - reset(div); - } - - unsigned div() const { return div_; } - std::size_t filter(short *out, const short *in, std::size_t inlen); - void reset(unsigned div); -}; - -template -void Cic3EvenOddCore::reset(const unsigned div) { - sum3 = sum2 = sum1 = 0; - prev3 = prev2 = prev1 = 0; - this->div_ = div; - nextdivn = div; -} - -template -void Cic3EvenOddCore::filterEven(short *out, const short *s, std::size_t n) { - const int mul = getMul(div_); - unsigned long sm1 = sum1; - unsigned long sm2 = sum2; - unsigned long sm3 = sum3; - - while (n--) { - { - unsigned sn = div_ >> 1; - - do { - unsigned long s1 = sm1 += static_cast(*s); - s += channels; - sm1 += static_cast(*s); - s += channels; - unsigned long s2 = sm2 += s1; - sm2 += sm1; - sm3 += s2; - sm3 += sm2; - } while (--sn); - } - - const unsigned long out3 = sm3 - prev3; - prev3 = sm3; - const unsigned long out2 = out3 - prev2; - prev2 = out3; - *out = static_cast(out2 - prev1) * mul / 0x10000; - prev1 = out2; - out += channels; - } - - sum1 = sm1; - sum2 = sm2; - sum3 = sm3; -} - -template -void Cic3EvenOddCore::filterOdd(short *out, const short *s, std::size_t n) { - const int mul = getMul(div_); - unsigned long sm1 = sum1; - unsigned long sm2 = sum2; - unsigned long sm3 = sum3; - - while (n--) { - { - unsigned sn = div_ >> 1; - - do { - unsigned long s1 = sm1 += static_cast(*s); - s += channels; - sm1 += static_cast(*s); - s += channels; - unsigned long s2 = sm2 += s1; - sm2 += sm1; - sm3 += s2; - sm3 += sm2; - } while (--sn); - } - - sm1 += static_cast(*s); - s += channels; - sm2 += sm1; - sm3 += sm2; - - const unsigned long out3 = sm3 - prev3; - prev3 = sm3; - const unsigned long out2 = out3 - prev2; - prev2 = out3; - *out = static_cast(out2 - prev1) * mul / 0x10000; - prev1 = out2; - out += channels; - } - - sum1 = sm1; - sum2 = sm2; - sum3 = sm3; -} - -template -std::size_t Cic3EvenOddCore::filter(short *out, const short *const in, std::size_t inlen) { - short *const outStart = out; - const short *s = in; - - if (inlen >= nextdivn) { - { - { - unsigned divn = nextdivn; - - do { - sum1 += static_cast(*s); - s += channels; - sum2 += sum1; - sum3 += sum2; - } while (--divn); - } - - const unsigned long out3 = sum3 - prev3; - prev3 = sum3; - const unsigned long out2 = out3 - prev2; - prev2 = out3; - *out = static_cast(out2 - prev1) * getMul(div_) / 0x10000; - prev1 = out2; - out += channels; - } - - std::size_t n = (inlen - nextdivn) / div_; - - if (div_ & 1) - filterOdd(out, s, n); - else - filterEven(out, s, n); - - s += n * div_ * channels; - out += n * channels; - nextdivn = div_; - } - - { - unsigned divn = inlen - (s - in) / channels; - nextdivn -= divn; - - while (divn--) { - sum1 += static_cast(*s); - s += channels; - sum2 += sum1; - sum3 += sum2; - } - } - - return (out - outStart) / channels; -}*/ - -template -class Cic3 : public SubResampler { - Cic3Core cics[channels]; - -public: - enum { MAX_DIV = 23 }; - Cic3(unsigned div); - std::size_t resample(short *out, const short *in, std::size_t inlen); - unsigned mul() const { return 1; } - unsigned div() const { return cics[0].div(); } -}; - -template -Cic3::Cic3(const unsigned div) { - for (unsigned i = 0; i < channels; ++i) - cics[i].reset(div); -} - -template -std::size_t Cic3::resample(short *const out, const short *const in, const std::size_t inlen) { - std::size_t samplesOut; - - for (unsigned i = 0; i < channels; ++i) { - samplesOut = cics[i].filter(out + i, in + i, inlen); - } - - return samplesOut; -} - -#endif diff --git a/supergameboy/common/resample/cic4.h b/supergameboy/common/resample/cic4.h deleted file mode 100644 index 430cb03d..00000000 --- a/supergameboy/common/resample/cic4.h +++ /dev/null @@ -1,237 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2008 by Sindre AamÃ¥s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef CIC4_H -#define CIC4_H - -#include "subresampler.h" - -template -class Cic4Core { - enum { BUFLEN = 64 }; - unsigned long buf[BUFLEN]; - unsigned long sum1; - unsigned long sum2; - unsigned long sum3; - unsigned long sum4; - unsigned long prev1; - unsigned long prev2; - unsigned long prev3; - unsigned long prev4; - unsigned div_; -// unsigned nextdivn; - unsigned bufpos; - -public: - Cic4Core(const unsigned div = 1) { - reset(div); - } - - unsigned div() const { return div_; } - std::size_t filter(short *out, const short *in, std::size_t inlen); - void reset(unsigned div); -}; - -template -void Cic4Core::reset(const unsigned div) { - sum4 = sum3 = sum2 = sum1 = 0; - prev4 = prev3 = prev2 = prev1 = 0; - this->div_ = div; -// nextdivn = div; - bufpos = div - 1; -} - -template -std::size_t Cic4Core::filter(short *out, const short *const in, std::size_t inlen) { - const std::size_t produced = (inlen + div_ - (bufpos + 1)) / div_; -// const std::size_t produced = (inlen + div_ - nextdivn) / div_; - const long mul = 0x10000 / (div_ * div_ * div_ * div_); // trouble if div is too large, may be better to only support power of 2 div - const short *s = in; - - unsigned long sm1 = sum1; - unsigned long sm2 = sum2; - unsigned long sm3 = sum3; - unsigned long sm4 = sum4; - - while (inlen >> 2) { - unsigned n = (inlen < BUFLEN ? inlen >> 2 : BUFLEN >> 2); - const unsigned end = n * 4; - unsigned i = 0; - - do { - unsigned long s1 = sm1 += static_cast(*s); - s += channels; - sm1 += static_cast(*s); - s += channels; - unsigned long s2 = sm2 += s1; - sm2 += sm1; - unsigned long s3 = sm3 += s2; - sm3 += sm2; - buf[i++] = sm4 += s3; - buf[i++] = sm4 += sm3; - s1 = sm1 += static_cast(*s); - s += channels; - sm1 += static_cast(*s); - s += channels; - s2 = sm2 += s1; - sm2 += sm1; - s3 = sm3 += s2; - sm3 += sm2; - buf[i++] = sm4 += s3; - buf[i++] = sm4 += sm3; - } while (--n); - - while (bufpos < end) { - const unsigned long out4 = buf[bufpos] - prev4; - prev4 = buf[bufpos]; - bufpos += div_; - - const unsigned long out3 = out4 - prev3; - prev3 = out4; - const unsigned long out2 = out3 - prev2; - prev2 = out3; - - *out = static_cast(out2 - prev1) * mul / 0x10000; - prev1 = out2; - out += channels; - } - - bufpos -= end; - inlen -= end; - } - - if (inlen) { - unsigned n = inlen; - unsigned i = 0; - - do { - sm1 += static_cast(*s); - s += channels; - sm2 += sm1; - sm3 += sm2; - buf[i++] = sm4 += sm3; - } while (--n); - - while (bufpos < inlen) { - const unsigned long out4 = buf[bufpos] - prev4; - prev4 = buf[bufpos]; - bufpos += div_; - - const unsigned long out3 = out4 - prev3; - prev3 = out4; - const unsigned long out2 = out3 - prev2; - prev2 = out3; - - *out = static_cast(out2 - prev1) * mul / 0x10000; - prev1 = out2; - out += channels; - } - - bufpos -= inlen; - } - - sum1 = sm1; - sum2 = sm2; - sum3 = sm3; - sum4 = sm4; - - /*unsigned long sm1 = sum1; - unsigned long sm2 = sum2; - unsigned long sm3 = sum3; - unsigned long sm4 = sum4; - - if (produced) { - unsigned divn = nextdivn; - std::size_t n = produced; - - do { - do { - sm1 += static_cast(*s); - s += channels; - sm2 += sm1; - sm3 += sm2; - sm4 += sm3; - } while (--divn); - - const unsigned long out4 = sm4 - prev4; - prev4 = sm4; - const unsigned long out3 = out4 - prev3; - prev3 = out4; - const unsigned long out2 = out3 - prev2; - prev2 = out3; - *out = static_cast(out2 - prev1) * mul / 0x10000; - prev1 = out2; - out += channels; - - divn = div_; - } while (--n); - - nextdivn = div_; - } - - { - unsigned divn = (in + inlen * channels - s) / channels; - nextdivn -= divn; - - while (divn--) { - sm1 += static_cast(*s); - s += channels; - sm2 += sm1; - sm3 += sm2; - sm4 += sm3; - } - } - - sum1 = sm1; - sum2 = sm2; - sum3 = sm3; - sum4 = sm4;*/ - - return produced; -} - -template -class Cic4 : public SubResampler { - Cic4Core cics[channels]; - -public: - enum { MAX_DIV = 13 }; - Cic4(unsigned div); - std::size_t resample(short *out, const short *in, std::size_t inlen); - unsigned mul() const { return 1; } - unsigned div() const { return cics[0].div(); } -}; - -template -Cic4::Cic4(const unsigned div) { - for (unsigned i = 0; i < channels; ++i) - cics[i].reset(div); -} - -template -std::size_t Cic4::resample(short *const out, const short *const in, const std::size_t inlen) { - std::size_t samplesOut; - - for (unsigned i = 0; i < channels; ++i) { - samplesOut = cics[i].filter(out + i, in + i, inlen); - } - - return samplesOut; -} - -#endif diff --git a/supergameboy/common/resample/convoluter.h b/supergameboy/common/resample/convoluter.h deleted file mode 100644 index 41fab0d0..00000000 --- a/supergameboy/common/resample/convoluter.h +++ /dev/null @@ -1,156 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2008 by Sindre AamÃ¥s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef CONVOLUTER_H -#define CONVOLUTER_H - -#include -#include - -template -class PolyPhaseConvoluter { - const short *kernel; - short *prevbuf; - - unsigned phaseLen; - unsigned div_; - unsigned x_; - -public: - PolyPhaseConvoluter() : kernel(NULL), prevbuf(NULL), phaseLen(0), div_(0), x_(0) {} - PolyPhaseConvoluter(const short *kernel, unsigned phaseLen, unsigned div) { reset(kernel, phaseLen, div); } - ~PolyPhaseConvoluter() { delete[] prevbuf; } - void reset(const short *kernel, unsigned phaseLen, unsigned div); - std::size_t filter(short *out, const short *in, std::size_t inlen); - void adjustDiv(const unsigned div) { this->div_ = div; } - unsigned div() const { return div_; } -}; - -template -void PolyPhaseConvoluter::reset(const short *const kernel, const unsigned phaseLen, const unsigned div) { - this->kernel = kernel; - this->phaseLen = phaseLen; - this->div_ = div; - x_ = 0; - delete[] prevbuf; - prevbuf = new short[phaseLen]; - std::fill(prevbuf, prevbuf + phaseLen, 0); -} - -template -std::size_t PolyPhaseConvoluter::filter(short *out, const short *const in, std::size_t inlen) { - if (!kernel || !inlen) - return 0; - - /*for (std::size_t x = 0; x < inlen + M; ++x) { - const int end = x < inlen ? M + 1 : inlen + M - x; - int j = x < M ? M - x : 0; - j += (phases - (x - M + j) % phases) % phases; // adjust j so we don't start on a virtual 0 sample - - for (; j < end; j += phases) { - buffer[x] += kernel[j] * start[(x - M + j) / phases]; - } - }*/ - - /*for (std::size_t x = 0; x < inlen + M; ++x) { - const int end = x < inlen ? M + 1 : inlen + M - x; - int j = x < M ? M - x : 0; - j += (phases - (x - M + j) % phases) % phases; // adjust j so we don't start on a virtual 0 sample - const short *k = kernel + (j % phases) * phaseLen + j / phases; - const short *s = start + (x - M + j) / phases; - int n = ((end - j) + phases - 1) / phases; - - do { - buffer[x] += *k++ * *s++; - } while (--n); - }*/ - - const std::size_t M = phaseLen * phases - 1; - inlen *= phases; - std::size_t x = x_; - - for (; x < (M < inlen ? M : inlen); x += div_) { - long acc = 0; - const unsigned phase = (phases - (x + 1) % phases) % phases; // adjust phase so we don't start on a virtual 0 sample - const short *s = prevbuf + (x + 1 + phase) / phases; - const short *k = kernel + phase * phaseLen; - unsigned n = prevbuf + phaseLen - s; - - while (n--) { - acc += *k++ * *s++; - } - - s = in; - n = x / phases + 1; - - do { - acc += *k++ * *s; - s += channels; - } while (--n); - - *out = acc / 0x10000; - out += channels; - } - - for (; x < inlen; x += div_) { - long acc = 0; - const unsigned phase = (phases - (x - M) % phases) % phases; // adjust phase so we don't start on a virtual 0 sample - const short *s = in + ((x - M + phase) / phases) * channels; - const short *k = kernel + phase * phaseLen; -// unsigned n = (M + 1/* - phase + phases - 1*/) / phases; - unsigned n = phaseLen; - - do { - acc += *k++ * *s; - s += channels; - } while (--n); - - *out = acc / 0x10000; - out += channels; - } - - const std::size_t produced = (x - x_) / div_; - x_ = x - inlen; - - inlen /= phases; - - { - short *p = prevbuf; - const short *s = in + (inlen - phaseLen) * channels; - unsigned n = phaseLen; - - if (inlen < phaseLen) { - const unsigned i = phaseLen - inlen; - - std::memmove(p, p + inlen, i * sizeof(short)); - - p += i; - n -= i; - s = in; - } - - do { - *p++ = *s; - s += channels; - } while (--n); - } - - return produced; -} - -#endif diff --git a/supergameboy/common/resample/hammingsinc.h b/supergameboy/common/resample/hammingsinc.h deleted file mode 100644 index bb50daee..00000000 --- a/supergameboy/common/resample/hammingsinc.h +++ /dev/null @@ -1,100 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2008 by Sindre AamÃ¥s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef HAMMINGSINC_H -#define HAMMINGSINC_H - -#include "convoluter.h" -#include "subresampler.h" -#include "makesinckernel.h" -#include "cic3.h" -#include -#include - -template -class HammingSinc : public SubResampler { - PolyPhaseConvoluter convoluters[channels]; - short *kernel; - - static double hammingWin(const long i, const long M) { - static const double PI = 3.14159265358979323846; - return 0.53836 - 0.46164 * std::cos(2 * PI * i / M); - } - - void init(unsigned div, unsigned phaseLen, double fc); - -public: - enum { MUL = phases }; - - typedef Cic3 Cic; - static float cicLimit() { return 4.2f; } - - class RollOff { - static unsigned toTaps(const float rollOffWidth) { - static const float widthTimesTaps = 3.0f; - return std::ceil(widthTimesTaps / rollOffWidth); - } - - static float toFc(const float rollOffStart, const int taps) { - static const float startToFcDeltaTimesTaps = 1.27f; - return startToFcDeltaTimesTaps / taps + rollOffStart; - } - - public: - const unsigned taps; - const float fc; - - RollOff(float rollOffStart, float rollOffWidth) : taps(toTaps(rollOffWidth)), fc(toFc(rollOffStart, taps)) {} - }; - - HammingSinc(unsigned div, unsigned phaseLen, double fc) { init(div, phaseLen, fc); } - HammingSinc(unsigned div, RollOff ro) { init(div, ro.taps, ro.fc); } - ~HammingSinc() { delete[] kernel; } - std::size_t resample(short *out, const short *in, std::size_t inlen); - void adjustDiv(unsigned div); - unsigned mul() const { return MUL; } - unsigned div() const { return convoluters[0].div(); } -}; - -template -void HammingSinc::init(const unsigned div, const unsigned phaseLen, const double fc) { - kernel = new short[phaseLen * phases]; - - makeSincKernel(kernel, phases, phaseLen, fc, hammingWin); - - for (unsigned i = 0; i < channels; ++i) - convoluters[i].reset(kernel, phaseLen, div); -} - -template -std::size_t HammingSinc::resample(short *const out, const short *const in, const std::size_t inlen) { - std::size_t samplesOut; - - for (unsigned i = 0; i < channels; ++i) - samplesOut = convoluters[i].filter(out + i, in + i, inlen); - - return samplesOut; -} - -template -void HammingSinc::adjustDiv(const unsigned div) { - for (unsigned i = 0; i < channels; ++i) - convoluters[i].adjustDiv(div); -} - -#endif diff --git a/supergameboy/common/resample/linint.h b/supergameboy/common/resample/linint.h deleted file mode 100644 index 0c6d8cb2..00000000 --- a/supergameboy/common/resample/linint.h +++ /dev/null @@ -1,129 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2008 by Sindre AamÃ¥s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef LININT_H -#define LININT_H - -#include -#include "resampler.h" -#include "u48div.h" - -template -class LinintCore { - unsigned long ratio; - std::size_t pos_; - unsigned fracPos_; - int prevSample_; - -public: - LinintCore(long inRate = 1, long outRate = 1) { init(inRate, outRate); } - void adjustRate(long inRate, long outRate) { ratio = (static_cast(inRate) / outRate) * 0x10000 + 0.5; } - void exactRatio(unsigned long &mul, unsigned long &div) const { mul = 0x10000; div = ratio; } - void init(long inRate, long outRate); - std::size_t maxOut(std::size_t inlen) const { return inlen ? u48div(inlen - 1, 0xFFFF, ratio) + 1 : 0; } - std::size_t resample(short *out, const short *in, std::size_t inlen); -}; - -template -void LinintCore::init(const long inRate, const long outRate) { - adjustRate(inRate, outRate); - pos_ = (ratio >> 16) + 1; - fracPos_ = ratio & 0xFFFF; - prevSample_ = 0; -} - -template -std::size_t LinintCore::resample(short *const out, const short *const in, const std::size_t inlen) { - std::size_t opos = 0; - std::size_t pos = pos_; - unsigned fracPos = fracPos_; - int prevSample = prevSample_; - - if (pos < inlen) { - if (pos != 0) - prevSample = in[(pos-1) * channels]; - - for (;;) { - out[opos] = prevSample + (in[pos * channels] - prevSample) * static_cast(fracPos) / 0x10000; - opos += channels; - - { - const unsigned long next = ratio + fracPos; - - pos += next >> 16; - fracPos = next & 0xFFFF; - } - - if (pos < inlen) { - prevSample = in[(pos-1) * channels]; - } else - break; - } - - if (pos == inlen) - prevSample = in[(pos-1) * channels]; - } - -// const std::size_t produced = ((pos - pos_) * 0x10000 + fracPos - fracPos_) / ratio; - - pos_ = pos - inlen; - fracPos_ = fracPos; - prevSample_ = prevSample; - - return opos / channels; -} - -template -class Linint : public Resampler { - LinintCore cores[channels]; - -public: - Linint(long inRate, long outRate); - void adjustRate(long inRate, long outRate); - void exactRatio(unsigned long &mul, unsigned long &div) const { cores[0].exactRatio(mul, div); } - std::size_t maxOut(std::size_t inlen) const { return cores[0].maxOut(inlen); } - std::size_t resample(short *out, const short *in, std::size_t inlen); -}; - -template -Linint::Linint(const long inRate, const long outRate) { - setRate(inRate, outRate); - - for (unsigned i = 0; i < channels; ++i) - cores[i].init(inRate, outRate); -} - -template -void Linint::adjustRate(const long inRate, const long outRate) { - setRate(inRate, outRate); - - for (unsigned i = 0; i < channels; ++i) - cores[i].adjustRate(inRate, outRate); -} - -template -std::size_t Linint::resample(short *const out, const short *const in, const std::size_t inlen) { - std::size_t outlen = 0; - - for (unsigned i = 0; i < channels; ++i) - outlen = cores[i].resample(out + i, in + i, inlen); - - return outlen; -} - -#endif diff --git a/supergameboy/common/resample/makesinckernel.h b/supergameboy/common/resample/makesinckernel.h deleted file mode 100644 index c6515f2d..00000000 --- a/supergameboy/common/resample/makesinckernel.h +++ /dev/null @@ -1,152 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2008 by Sindre AamÃ¥s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef MAKE_SINC_KERNEL_H -#define MAKE_SINC_KERNEL_H - -#include -#include - -template -void makeSincKernel(short *const kernel, const unsigned phases, const unsigned phaseLen, double fc, Window win) { - static const double PI = 3.14159265358979323846; - fc /= phases; - - /*{ - double *const dkernel = new double[phaseLen * phases]; - const long M = static_cast(phaseLen) * phases - 1; - - for (long i = 0; i < M + 1; ++i) { - const double sinc = i * 2 == M ? - PI * fc : - std::sin(PI * fc * (i * 2 - M)) / (i * 2 - M); - - dkernel[(i % phases) * phaseLen + i / phases] = win(i, M) * sinc; - } - - double maxabsgain = 0; - - for (unsigned ph = 0; ph < phases; ++ph) { - double gain = 0; - double absgain = 0; - - for (unsigned i = 0; i < phaseLen; ++i) { - gain += dkernel[ph * phaseLen + i]; - absgain += std::abs(dkernel[ph * phaseLen + i]); - } - - gain = 1.0 / gain; - - // Per phase normalization to avoid DC fluctuations. - for (unsigned i = 0; i < phaseLen; ++i) - dkernel[ph * phaseLen + i] *= gain; - - absgain *= gain; - - if (absgain > maxabsgain) - maxabsgain = absgain; - } - - const double gain = 0x10000 / maxabsgain; - - for (long i = 0; i < M + 1; ++i) - kernel[i] = std::floor(dkernel[i] * gain + 0.5); - - delete[] dkernel; - }*/ - - // The following is equivalent to the more readable version above - - const long M = static_cast(phaseLen) * phases - 1; - - double *const dkernel = new double[M / 2 + 1]; - - { - double *dk = dkernel; - - for (unsigned ph = 0; ph < phases; ++ph) { - for (long i = ph; i < M / 2 + 1; i += phases) { - const double sinc = i * 2 == M ? - PI * fc : - std::sin(PI * fc * (i * 2 - M)) / (i * 2 - M); - - *dk++ = win(i, M) * sinc; - } - } - } - - double maxabsgain = 0.0; - - { - double *dkp1 = dkernel; - double *dkp2 = dkernel + M / 2; - - for (unsigned ph = 0; ph < (phases + 1) / 2; ++ph) { - double gain = 0.0; - double absgain = 0.0; - - { - const double *kp1 = dkp1; - const double *kp2 = dkp2; - long i = ph; - - for (; i < M / 2 + 1; i += phases) { - gain += *kp1; - absgain += std::abs(*kp1++); - } - - for (; i < M + 1; i += phases) { - gain += *kp2; - absgain += std::abs(*kp2--); - } - } - - gain = 1.0 / gain; - - long i = ph; - - for (; i < M / 2 + 1; i += phases) - *dkp1++ *= gain; - - if (dkp1 < dkp2) { - for (; i < M + 1; i += phases) - *dkp2-- *= gain; - } - - absgain *= gain; - - if (absgain > maxabsgain) - maxabsgain = absgain; - } - } - - const double gain = 0x10000 / maxabsgain; - const double *dk = dkernel; - - for (unsigned ph = 0; ph < phases; ++ph) { - short *k = kernel + ph * phaseLen; - short *km = kernel + M - ph * phaseLen; - - for (long i = ph; i < M / 2 + 1; i += phases) - *km-- = *k++ = std::floor(*dk++ * gain + 0.5); - } - - delete[] dkernel; -} - -#endif diff --git a/supergameboy/common/resample/rectsinc.h b/supergameboy/common/resample/rectsinc.h deleted file mode 100644 index 9f99ed6b..00000000 --- a/supergameboy/common/resample/rectsinc.h +++ /dev/null @@ -1,99 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2008 by Sindre AamÃ¥s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef RECTSINC_H -#define RECTSINC_H - -#include "convoluter.h" -#include "subresampler.h" -#include "makesinckernel.h" -#include "cic2.h" -#include -#include - -template -class RectSinc : public SubResampler { - PolyPhaseConvoluter convoluters[channels]; - short *kernel; - - static double rectWin(const long /*i*/, const long /*M*/) { - return 1; - } - - void init(unsigned div, unsigned phaseLen, double fc); - -public: - enum { MUL = phases }; - - typedef Cic2 Cic; - static float cicLimit() { return 2.0f; } - - class RollOff { - static unsigned toTaps(const float rollOffWidth) { - static const float widthTimesTaps = 0.9f; - return std::ceil(widthTimesTaps / rollOffWidth); - } - - static float toFc(const float rollOffStart, const int taps) { - static const float startToFcDeltaTimesTaps = 0.43f; - return startToFcDeltaTimesTaps / taps + rollOffStart; - } - - public: - const unsigned taps; - const float fc; - - RollOff(float rollOffStart, float rollOffWidth) : taps(toTaps(rollOffWidth)), fc(toFc(rollOffStart, taps)) {} - }; - - RectSinc(unsigned div, unsigned phaseLen, double fc) { init(div, phaseLen, fc); } - RectSinc(unsigned div, RollOff ro) { init(div, ro.taps, ro.fc); } - ~RectSinc() { delete[] kernel; } - std::size_t resample(short *out, const short *in, std::size_t inlen); - void adjustDiv(unsigned div); - unsigned mul() const { return MUL; } - unsigned div() const { return convoluters[0].div(); } -}; - -template -void RectSinc::init(const unsigned div, const unsigned phaseLen, const double fc) { - kernel = new short[phaseLen * phases]; - - makeSincKernel(kernel, phases, phaseLen, fc, rectWin); - - for (unsigned i = 0; i < channels; ++i) - convoluters[i].reset(kernel, phaseLen, div); -} - -template -std::size_t RectSinc::resample(short *const out, const short *const in, const std::size_t inlen) { - std::size_t samplesOut; - - for (unsigned i = 0; i < channels; ++i) - samplesOut = convoluters[i].filter(out + i, in + i, inlen); - - return samplesOut; -} - -template -void RectSinc::adjustDiv(const unsigned div) { - for (unsigned i = 0; i < channels; ++i) - convoluters[i].adjustDiv(div); -} - -#endif diff --git a/supergameboy/common/resample/resampler.h b/supergameboy/common/resample/resampler.h deleted file mode 100644 index f3d448d9..00000000 --- a/supergameboy/common/resample/resampler.h +++ /dev/null @@ -1,43 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2008 by Sindre AamÃ¥s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef RESAMPLER_H -#define RESAMPLER_H - -#include - -class Resampler { - long inRate_; - long outRate_; - -protected: - void setRate(const long inRate, const long outRate) { inRate_ = inRate; outRate_ = outRate; } - -public: - Resampler() : inRate_(0), outRate_(0) {} - long inRate() const { return inRate_; } - long outRate() const { return outRate_; } - - virtual void adjustRate(long inRate, long outRate) = 0; - virtual void exactRatio(unsigned long &mul, unsigned long &div) const = 0; - virtual std::size_t maxOut(std::size_t inlen) const = 0; - virtual std::size_t resample(short *out, const short *in, std::size_t inlen) = 0; - virtual ~Resampler() {} -}; - -#endif diff --git a/supergameboy/common/resample/resamplerinfo.cpp b/supergameboy/common/resample/resamplerinfo.cpp deleted file mode 100644 index 3abcdaf8..00000000 --- a/supergameboy/common/resample/resamplerinfo.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2008 by Sindre AamÃ¥s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "resamplerinfo.h" -#include "chainresampler.h" -#include "hammingsinc.h" -#include "blackmansinc.h" -#include "rectsinc.h" -#include "linint.h" - -struct LinintInfo { - static Resampler* create(long inRate, long outRate, std::size_t) { return new Linint<2>(inRate, outRate); } -}; - -struct RectsincInfo { - static Resampler* create(long inRate, long outRate, std::size_t periodSz) { - ChainResampler *r = new ChainResampler; - r->init(inRate, outRate, periodSz); - return r; - } -}; - -struct HammingsincInfo { - static Resampler* create(long inRate, long outRate, std::size_t periodSz) { - ChainResampler *r = new ChainResampler; - r->init(inRate, outRate, periodSz); - return r; - } -}; - -struct BlackmansincInfo { - static Resampler* create(long inRate, long outRate, std::size_t periodSz) { - ChainResampler *r = new ChainResampler; - r->init(inRate, outRate, periodSz); - return r; - } -}; - -const ResamplerInfo ResamplerInfo::resamplers[] = { - { "2-tap linear interpolation", LinintInfo::create }, - { "Rectangular windowed sinc (~20 dB SNR)", RectsincInfo::create }, - { "Hamming windowed sinc (~50 dB SNR)", HammingsincInfo::create }, - { "Blackman windowed sinc (~70 dB SNR)", BlackmansincInfo::create } -}; - -const unsigned ResamplerInfo::num_ = sizeof(ResamplerInfo::resamplers) / sizeof(ResamplerInfo); diff --git a/supergameboy/common/resample/resamplerinfo.h b/supergameboy/common/resample/resamplerinfo.h deleted file mode 100644 index 23f4a545..00000000 --- a/supergameboy/common/resample/resamplerinfo.h +++ /dev/null @@ -1,36 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2008 by Sindre AamÃ¥s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef RESAMPLER_INFO_H -#define RESAMPLER_INFO_H - -#include "resampler.h" - -struct ResamplerInfo { - const char *desc; - Resampler* (*create)(long inRate, long outRate, std::size_t periodSz); - - static unsigned num() { return num_; } - static const ResamplerInfo& get(unsigned n) { return resamplers[n]; } - -private: - static const ResamplerInfo resamplers[]; - static const unsigned num_; -}; - -#endif diff --git a/supergameboy/common/resample/subresampler.h b/supergameboy/common/resample/subresampler.h deleted file mode 100644 index 134ec80b..00000000 --- a/supergameboy/common/resample/subresampler.h +++ /dev/null @@ -1,33 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2008 by Sindre AamÃ¥s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef SUBRESAMPLER_H -#define SUBRESAMPLER_H - -#include - -class SubResampler { -public: - virtual std::size_t resample(short *out, const short *in, std::size_t inlen) = 0; - virtual unsigned mul() const = 0; - virtual unsigned div() const = 0; - virtual void adjustDiv(unsigned /*div*/) {} - virtual ~SubResampler() {} -}; - -#endif diff --git a/supergameboy/common/resample/u48div.cpp b/supergameboy/common/resample/u48div.cpp deleted file mode 100644 index 077ddfd9..00000000 --- a/supergameboy/common/resample/u48div.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2008 by Sindre AamÃ¥s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "u48div.h" - -unsigned long u48div(unsigned long num1, unsigned num2, const unsigned long den) { - unsigned long res = 0; - unsigned s = 16; - - do { - if (num1 < 0x10000) { - num1 <<= s; - num1 |= num2 & ((1 << s) - 1); - s = 0; - } else { - if (num1 < 0x1000000) { - const unsigned maxs = s < 8 ? s : 8; - num1 <<= maxs; - num1 |= (num2 >> (s -= maxs)) & ((1 << maxs) - 1); - } - - if (num1 < 0x10000000) { - const unsigned maxs = s < 4 ? s : 4; - num1 <<= maxs; - num1 |= (num2 >> (s -= maxs)) & ((1 << maxs) - 1); - } - - while (num1 < den && s) { - num1 <<= 1; // if this overflows we're screwed - num1 |= num2 >> --s & 1; - } - } - - res += (num1 / den) << s; - num1 = (num1 % den); - } while (s); - - return res; -} diff --git a/supergameboy/common/resample/u48div.h b/supergameboy/common/resample/u48div.h deleted file mode 100644 index 26b16af4..00000000 --- a/supergameboy/common/resample/u48div.h +++ /dev/null @@ -1,24 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2008 by Sindre AamÃ¥s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef U48DIV_H -#define U48DIV_H - -unsigned long u48div(unsigned long num1, unsigned num2, unsigned long den); - -#endif diff --git a/supergameboy/common/resample/upsampler.h b/supergameboy/common/resample/upsampler.h deleted file mode 100644 index 8bf88d8a..00000000 --- a/supergameboy/common/resample/upsampler.h +++ /dev/null @@ -1,51 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2008 by Sindre AamÃ¥s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef UPSAMPLER_H -#define UPSAMPLER_H - -#include "subresampler.h" -#include - -template -class Upsampler : public SubResampler { - unsigned mul_; - -public: - Upsampler(const unsigned mul) : mul_(mul) {} - std::size_t resample(short *out, const short *in, std::size_t inlen); - unsigned mul() const { return mul_; } - unsigned div() const { return 1; } -}; - -template -std::size_t Upsampler::resample(short *out, const short *in, std::size_t inlen) { - if (inlen) { - std::memset(out, 0, inlen * mul_ * sizeof(short) * channels); - - do { - std::memcpy(out, in, sizeof(short) * channels); - in += channels; - out += mul_ * channels; - } while (--inlen); - } - - return inlen * mul_; -} - -#endif diff --git a/supergameboy/common/ringbuffer.h b/supergameboy/common/ringbuffer.h deleted file mode 100644 index 34f22bfe..00000000 --- a/supergameboy/common/ringbuffer.h +++ /dev/null @@ -1,112 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2008 by Sindre AamÃ¥s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef RINGBUFFER_H -#define RINGBUFFER_H - -#include "array.h" -#include -#include -#include - -template -class RingBuffer { - Array buf; - std::size_t sz; - std::size_t rpos; - std::size_t wpos; - -public: - RingBuffer(const std::size_t sz_in = 0) : sz(0), rpos(0), wpos(0) { reset(sz_in); } - - std::size_t avail() const { - return (wpos < rpos ? 0 : sz) + rpos - wpos - 1; - } - - void clear() { - wpos = rpos = 0; - } - - void fill(T value); - - void read(T *out, std::size_t num); - - void reset(std::size_t sz_in); - - std::size_t size() const { - return sz - 1; - } - - std::size_t used() const { - return (wpos < rpos ? sz : 0) + wpos - rpos; - } - - void write(const T *in, std::size_t num); -}; - -template -void RingBuffer::fill(const T value) { - std::fill(buf + 0, buf + sz, value); - rpos = 0; - wpos = sz - 1; -} - -template -void RingBuffer::read(T *out, std::size_t num) { - if (rpos + num > sz) { - const std::size_t n = sz - rpos; - - std::memcpy(out, buf + rpos, n * sizeof(T)); - - rpos = 0; - num -= n; - out += n; - } - - std::memcpy(out, buf + rpos, num * sizeof(T)); - - if ((rpos += num) == sz) - rpos = 0; -} - -template -void RingBuffer::reset(const std::size_t sz_in) { - sz = sz_in + 1; - rpos = wpos = 0; - buf.reset(sz_in ? sz : 0); -} - -template -void RingBuffer::write(const T *in, std::size_t num) { - if (wpos + num > sz) { - const std::size_t n = sz - wpos; - - std::memcpy(buf + wpos, in, n * sizeof(T)); - - wpos = 0; - num -= n; - in += n; - } - - std::memcpy(buf + wpos, in, num * sizeof(T)); - - if ((wpos += num) == sz) - wpos = 0; -} - -#endif diff --git a/supergameboy/common/usec.h b/supergameboy/common/usec.h deleted file mode 100644 index 2bc889cf..00000000 --- a/supergameboy/common/usec.h +++ /dev/null @@ -1,31 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2008 by Sindre AamÃ¥s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef USEC_H -#define USEC_H - -typedef unsigned long usec_t; - -static inline usec_t negate(usec_t t) { - return usec_t(0) - t; -} - -usec_t getusecs(); -void usecsleep(usec_t usecs); - -#endif diff --git a/supergameboy/interface/interface.cpp b/supergameboy/interface/interface.cpp deleted file mode 100644 index b726b147..00000000 --- a/supergameboy/interface/interface.cpp +++ /dev/null @@ -1,373 +0,0 @@ -SuperGameBoy supergameboy; - -//==================== -//SuperGameBoy::Packet -//==================== - -const char SuperGameBoy::command_name[32][64] = { - "PAL01", "PAL23", "PAL03", "PAL12", - "ATTR_BLK", "ATTR_LIN", "ATTR_DIV", "ATTR_CHR", - "SOUND", "SOU_TRN", "PAL_SET", "PAL_TRN", - "ATRC_EN", "TEST_EN", "ICON_EN", "DATA_SND", - "DATA_TRN", "MLT_REQ", "JUMP", "CHR_TRN", - "PCT_TRN", "ATTR_TRN", "ATTR_SET", "MASK_EN", - "OBJ_TRN", "19_???", "1A_???", "1B_???", - "1C_???", "1D_???", "1E_ROM", "1F_???", -}; - -void SuperGameBoy::joyp_write(bool p15, bool p14) { - //=============== - //joypad handling - //=============== - - if(p15 == 1 && p14 == 1) { - if(joyp15lock == 0 && joyp14lock == 0) { - joyp15lock = 1; - joyp14lock = 1; - joyp_id = (joyp_id + 1) & 3; - } - } - - if(p15 == 0 && p14 == 1) joyp15lock = 0; - if(p15 == 1 && p14 == 0) joyp14lock = 0; - - //=============== - //packet handling - //=============== - - if(p15 == 0 && p14 == 0) { - //pulse - pulselock = false; - packetoffset = 0; - bitoffset = 0; - strobelock = true; - packetlock = false; - return; - } - - if(pulselock) return; - - if(p15 == 1 && p14 == 1) { - strobelock = false; - return; - } - - if(strobelock) { - if(p15 == 1 || p14 == 1) { - //malformed packet - packetlock = false; - pulselock = true; - bitoffset = 0; - packetoffset = 0; - } else { - return; - } - } - - //p15:1, p14:0 = 0 - //p15:0, p14:1 = 1 - bool bit = (p15 == 0); - strobelock = true; - - if(packetlock) { - if(p15 == 1 && p14 == 0) { - if((joyp_packet[0] >> 3) == 0x11) { - mmio.mlt_req = joyp_packet[1] & 3; - if(mmio.mlt_req == 2) mmio.mlt_req = 3; - joyp_id = 0; - } - - if(packetsize < 64) packet[packetsize++] = joyp_packet; - packetlock = false; - pulselock = true; - } - return; - } - - bitdata = (bit << 7) | (bitdata >> 1); - if(++bitoffset < 8) return; - - bitoffset = 0; - joyp_packet[packetoffset] = bitdata; - if(++packetoffset < 16) return; - packetlock = true; -} - -//================== -//SuperGameBoy::Core -//================== - -static uint8_t null_rom[32768]; - -bool SuperGameBoy::init(bool version_) { - if(!romdata) { romdata = null_rom; romsize = 32768; } - version = version_; - - gambatte = new Gambatte::GB; - gambatte->setVideoBlitter(this); - gambatte->setInputStateGetter(this); - - return true; -} - -void SuperGameBoy::term() { - if(gambatte) { - delete gambatte; - gambatte = 0; - } -} - -unsigned SuperGameBoy::run(uint32_t *samplebuffer, unsigned samples) { - if((mmio.r6003 & 0x80) == 0) { - //Gameboy is inactive - samplebuffer[0] = 0; - return 1; - } - - return gambatte->runFor(samplebuffer, samples); -} - -void SuperGameBoy::save() { - gambatte->saveSavedata(); -} - -void SuperGameBoy::serialize(nall::serializer &s) { - s.integer(vram_row); - s.array(vram); - - s.integer(mmio.r6000); - s.integer(mmio.r6003); - s.integer(mmio.r6004); - s.integer(mmio.r6005); - s.integer(mmio.r6006); - s.integer(mmio.r6007); - s.array(mmio.r7000); - s.integer(mmio.r7800); - s.integer(mmio.mlt_req); - - for(unsigned i = 0; i < 64; i++) s.array(packet[i].data); - s.integer(packetsize); - - s.integer(joyp_id); - s.integer(joyp15lock); - s.integer(joyp14lock); - s.integer(pulselock); - s.integer(strobelock); - s.integer(packetlock); - s.array(joyp_packet.data); - s.integer(packetoffset); - s.integer(bitdata); - s.integer(bitoffset); - - uint8_t *savestate = new uint8_t[256 * 1024]; - if(s.mode() == serializer::Load) { - s.array(savestate, 256 * 1024); - - file fp; - if(fp.open("supergameboy-state.tmp", file::mode_write)) { - fp.write(savestate, 256 * 1024); - fp.close(); - - gambatte->loadState("supergameboy-state.tmp"); - unlink("supergameboy-state.tmp"); - } - } else if(s.mode() == serializer::Save) { - gambatte->saveState("supergameboy-state.tmp"); - - file fp; - if(fp.open("supergameboy-state.tmp", file::mode_read)) { - fp.read(savestate, fp.size() < 256 * 1024 ? fp.size() : 256 * 1024); - fp.close(); - } - - unlink("supergameboy-state.tmp"); - s.array(savestate, 256 * 1024); - } else if(s.mode() == serializer::Size) { - s.array(savestate, 256 * 1024); - } - delete[] savestate; -} - -void SuperGameBoy::power() { - gambatte->load(true); - mmio_reset(); -} - -void SuperGameBoy::reset() { - gambatte->reset(); - mmio_reset(); -} - -void SuperGameBoy::row(unsigned row) { - mmio.r7800 = 0; - vram_row = row; - render(vram_row); -} - -uint8_t SuperGameBoy::read(uint16_t addr) { - //LY counter - if(addr == 0x6000) { - return gambatte->lyCounter(); - } - - //command ready port - if(addr == 0x6002) { - bool data = packetsize > 0; - if(data) { - for(unsigned i = 0; i < 16; i++) mmio.r7000[i] = packet[0][i]; - packetsize--; - for(unsigned i = 0; i < packetsize; i++) packet[i] = packet[i + 1]; - } - return data; - } - - //command port - if((addr & 0xfff0) == 0x7000) { - return mmio.r7000[addr & 15]; - } - - if(addr == 0x7800) { - uint8_t data = vram[mmio.r7800]; - mmio.r7800 = (mmio.r7800 + 1) % 320; - return data; - } - - return 0x00; -} - -void SuperGameBoy::write(uint16_t addr, uint8_t data) { - //control port - //d7 = /RESET line (0 = stop, 1 = run) - if(addr == 0x6003) { - if((mmio.r6003 & 0x80) == 0x00 && (data & 0x80) == 0x80) { - reset(); - command_1e(); - } - - mmio.r6003 = data; - return; - } - - if(addr == 0x6004) { mmio.r6004 = data; return; } //joypad 1 state - if(addr == 0x6005) { mmio.r6005 = data; return; } //joypad 2 state - if(addr == 0x6006) { mmio.r6006 = data; return; } //joypad 3 state - if(addr == 0x6007) { mmio.r6007 = data; return; } //joypad 4 state -} - -void SuperGameBoy::mmio_reset() { - mmio.r6000 = 0x00; - mmio.r6003 = 0x00; - mmio.r6004 = 0xff; - mmio.r6005 = 0xff; - mmio.r6006 = 0xff; - mmio.r6007 = 0xff; - for(unsigned n = 0; n < 16; n++) mmio.r7000[n] = 0; - mmio.r7800 = 0; - mmio.mlt_req = 0; - - packetsize = 0; - - vram_row = 0; - memset(vram, 0, 320); - - joyp_id = 3; - joyp15lock = 0; - joyp14lock = 0; - pulselock = true; -} - -//simulate 256-byte internal SGB BIOS on /RESET -void SuperGameBoy::command_1e() { - for(unsigned i = 0; i < 6; i++) { - Packet p; - p[0] = 0xf1 + (i << 1); - p[1] = 0; - for(unsigned n = 2; n < 16; n++) { - uint8_t data = romdata[0x0104 + (i * 14) + (n - 2)]; - p[1] += data; - p[n] = data; - } - if(packetsize < 64) packet[packetsize++] = p; - } -} - -void SuperGameBoy::render(unsigned row) { - gambatte->updateVideo(); - - uint32_t *source = buffer + row * 160 * 8; - memset(vram, 0x00, 320); - - for(unsigned y = row * 8; y < row * 8 + 8; y++) { - for(unsigned x = 0; x < 160; x++) { - unsigned pixel = *source++ / 0x555555; - pixel ^= 3; - - unsigned addr = (x / 8 * 16) + ((y & 7) * 2); - vram[addr + 0] |= ((pixel & 1) >> 0) << (7 - (x & 7)); - vram[addr + 1] |= ((pixel & 2) >> 1) << (7 - (x & 7)); - } - } -} - -//====================== -//Gambatte::VideoBlitter -//====================== - -//should always be 160x144, as no filters are used -void SuperGameBoy::setBufferDimensions(unsigned width, unsigned height) { - if(buffer) delete[] buffer; - buffer = new uint32_t[width * height]; - bufferWidth = width; - bufferHeight = height; -} - -const Gambatte::PixelBuffer SuperGameBoy::inBuffer() { - Gambatte::PixelBuffer pixelBuffer; - pixelBuffer.pixels = (void*)buffer; - pixelBuffer.format = Gambatte::PixelBuffer::RGB32; - pixelBuffer.pitch = bufferWidth; - return pixelBuffer; -} - -void SuperGameBoy::blit() { -} - -//========================== -//Gambatte::InputStateGetter -//========================== - -const Gambatte::InputState& SuperGameBoy::operator()() { - inputState.joypadId = 0x0f - (joyp_id & mmio.mlt_req); - - unsigned data = 0x00; - switch(joyp_id & mmio.mlt_req) { - case 0: data = mmio.r6004; break; - case 1: data = mmio.r6005; break; - case 2: data = mmio.r6006; break; - case 3: data = mmio.r6007; break; - } - - inputState.startButton = !(data & 0x80); - inputState.selectButton = !(data & 0x40); - inputState.bButton = !(data & 0x20); - inputState.aButton = !(data & 0x10); - inputState.dpadDown = !(data & 0x08); - inputState.dpadUp = !(data & 0x04); - inputState.dpadLeft = !(data & 0x02); - inputState.dpadRight = !(data & 0x01); - - return inputState; -} - -//========================== -//SuperGameBoy::Construction -//========================== - -SuperGameBoy::SuperGameBoy() : gambatte(0), buffer(0) { - romdata = ramdata = rtcdata = 0; - romsize = ramsize = rtcsize = 0; -} - -SuperGameBoy::~SuperGameBoy() { - if(buffer) delete[] buffer; -} diff --git a/supergameboy/interface/interface.hpp b/supergameboy/interface/interface.hpp deleted file mode 100644 index d369a281..00000000 --- a/supergameboy/interface/interface.hpp +++ /dev/null @@ -1,80 +0,0 @@ -class SuperGameBoy : public Gambatte::VideoBlitter, public Gambatte::InputStateGetter { -public: - Gambatte::GB *gambatte; - -//SuperGameBoy::MMIO - unsigned vram_row; - uint8_t vram[320]; - - struct MMIO { - uint8_t r6000; - uint8_t r6003; - uint8_t r6004; - uint8_t r6005; - uint8_t r6006; - uint8_t r6007; - uint8_t r7000[16]; - unsigned r7800; - uint8_t mlt_req; - } mmio; - -//SuperGameBoy::Packet - static const char command_name[32][64]; - - struct Packet { - uint8_t data[16]; - uint8_t& operator[](unsigned addr) { return data[addr & 15]; } - }; - Packet packet[64]; - unsigned packetsize; - - unsigned joyp_id; - bool joyp15lock; - bool joyp14lock; - bool pulselock; - bool strobelock; - bool packetlock; - Packet joyp_packet; - uint8_t packetoffset; - uint8_t bitdata, bitoffset; - - void joyp_write(bool p15, bool p14); - -//SuperGameBoy::Core - uint8_t *romdata, *ramdata, *rtcdata; - unsigned romsize, ramsize, rtcsize; - bool version; - - bool init(bool version); - void term(); - unsigned run(uint32_t *samplebuffer, unsigned samples); - void save(); - void serialize(nall::serializer &s); - void power(); - void reset(); - void row(unsigned row); - uint8_t read(uint16_t addr); - void write(uint16_t addr, uint8_t data); - - void mmio_reset(); - void command_1e(); - void render(unsigned row); - - SuperGameBoy(); - ~SuperGameBoy(); - -//Gambatte::VideoBlitter - unsigned bufferWidth, bufferHeight; - uint32_t *buffer; - - void setBufferDimensions(unsigned width, unsigned height); - const Gambatte::PixelBuffer inBuffer(); - void blit(); - -//Gambatte::InputStateGetter - Gambatte::InputState inputState; - - const Gambatte::InputState& operator()(); -}; - -extern SuperGameBoy supergameboy; diff --git a/supergameboy/libgambatte/SConstruct b/supergameboy/libgambatte/SConstruct deleted file mode 100644 index 47087ba0..00000000 --- a/supergameboy/libgambatte/SConstruct +++ /dev/null @@ -1,64 +0,0 @@ -global_cflags = ARGUMENTS.get('CFLAGS', '-Wall -Wextra -O2 -fomit-frame-pointer') -global_cxxflags = ARGUMENTS.get('CXXFLAGS', global_cflags + ' -fno-exceptions -fno-rtti') -global_defines = ' -DHAVE_STDINT_H -DCHAR_WIDTH_8' - -env = Environment(CPPPATH = ['src', 'include', '../common'], - CFLAGS = global_cflags + global_defines, - CXXFLAGS = global_cxxflags + global_defines) - -sourceFiles = Split(''' - src/bitmap_font.cpp - src/colorconversion.cpp - src/cpu.cpp - src/gambatte.cpp - src/initstate.cpp - src/interrupter.cpp - src/memory.cpp - src/rtc.cpp - src/sound.cpp - src/state_osd_elements.cpp - src/statesaver.cpp - src/video.cpp - src/sound/channel1.cpp - src/sound/channel2.cpp - src/sound/channel3.cpp - src/sound/channel4.cpp - src/sound/duty_unit.cpp - src/sound/envelope_unit.cpp - src/sound/length_counter.cpp - src/video/basic_add_event.cpp - src/video/break_event.cpp - src/video/irq_event.cpp - src/video/ly_counter.cpp - src/video/lyc_irq.cpp - src/video/m3_extra_cycles.cpp - src/video/mode3_event.cpp - src/video/mode0_irq.cpp - src/video/mode1_irq.cpp - src/video/mode2_irq.cpp - src/video/sc_reader.cpp - src/video/scx_reader.cpp - src/video/sprite_mapper.cpp - src/video/we_master_checker.cpp - src/video/we.cpp - src/video/wx_reader.cpp - src/video/wy.cpp - src/video/filters/catrom2x.cpp - src/video/filters/catrom3x.cpp - src/video/filters/kreed2xsai.cpp - src/video/filters/maxsthq2x.cpp - src/video/filters/maxsthq3x.cpp - ''') - -conf = env.Configure() - -if conf.CheckHeader('zlib.h') and conf.CheckLib('z'): - sourceFiles.append('src/file/unzip/unzip.c') - sourceFiles.append('src/file/unzip/ioapi.c') - sourceFiles.append('src/file/file_zip.cpp') -else: - sourceFiles.append('src/file/file.cpp') - -conf.Finish() - -env.Library('gambatte', sourceFiles) diff --git a/supergameboy/libgambatte/include/filterinfo.h b/supergameboy/libgambatte/include/filterinfo.h deleted file mode 100644 index ab5a4726..00000000 --- a/supergameboy/libgambatte/include/filterinfo.h +++ /dev/null @@ -1,32 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aam�s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef GAMBATTE_FILTERINFO_H -#define GAMBATTE_FILTERINFO_H - -#include - -namespace Gambatte { -struct FilterInfo { - std::string handle; - unsigned int outWidth; - unsigned int outHeight; -}; -} - -#endif diff --git a/supergameboy/libgambatte/include/gambatte.h b/supergameboy/libgambatte/include/gambatte.h deleted file mode 100644 index fc787d76..00000000 --- a/supergameboy/libgambatte/include/gambatte.h +++ /dev/null @@ -1,82 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aam�s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef GAMBATTE_H -#define GAMBATTE_H - -class CPU; - -#include "videoblitter.h" -#include "inputstate.h" -#include "inputstategetter.h" -#include "filterinfo.h" -#include "int.h" -#include - -namespace Gambatte { -class GB { - CPU *const z80; - int stateNo; - - void loadState(const char *filepath, bool osdMessage); - -public: - GB(); - ~GB(); - bool load(bool forceDmg = false); - - /** Emulates until at least 'samples' stereo sound samples are produced in the supplied buffer. - * There are 35112 stereo sound samples in a video frame. - * May run for uptil 2064 stereo samples too long. - * A stereo sample consists of two native endian 2s complement 16-bit PCM samples, - * with the left sample preceding the right one. Usually casting soundBuf to/from - * short* is OK and recommended. The reason for not using a short* in the interface - * is to avoid implementation defined behaviour without compromising performance. - * - * @param soundBuf buffer with space >= samples + 2064 - * @param samples number of stereo samples to produce - * @return actual number of samples produced - */ - unsigned runFor(Gambatte::uint_least32_t *soundBuf, unsigned samples); - void updateVideo(); - unsigned lyCounter(); - - void reset(); - void setVideoBlitter(VideoBlitter *vb); - void videoBufferChange(); - unsigned videoWidth() const; - unsigned videoHeight() const; - void setDmgPaletteColor(unsigned palNum, unsigned colorNum, unsigned rgb32); - - void setVideoFilter(unsigned n); - std::vector filterInfo() const; - void setInputStateGetter(InputStateGetter *getInput); - - void set_savedir(const char *sdir); - bool isCgb() const; - void saveSavedata(); - void saveState(); - void loadState(); - void saveState(const char *filepath); - void loadState(const char *filepath); - void selectState(int n); - int currentState() const { return stateNo; } -}; -} - -#endif diff --git a/supergameboy/libgambatte/include/inputstate.h b/supergameboy/libgambatte/include/inputstate.h deleted file mode 100644 index bdfec44f..00000000 --- a/supergameboy/libgambatte/include/inputstate.h +++ /dev/null @@ -1,30 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aam�s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef GAMBATTE_INPUTSTATE_H -#define GAMBATTE_INPUTSTATE_H - -namespace Gambatte { -struct InputState { - unsigned joypadId; - bool startButton, selectButton, bButton, aButton; - bool dpadDown, dpadUp, dpadLeft, dpadRight; -}; -} - -#endif diff --git a/supergameboy/libgambatte/include/inputstategetter.h b/supergameboy/libgambatte/include/inputstategetter.h deleted file mode 100644 index 375dad5e..00000000 --- a/supergameboy/libgambatte/include/inputstategetter.h +++ /dev/null @@ -1,30 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aam�s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef GAMBATTE_INPUTSTATEGETTER_H -#define GAMBATTE_INPUTSTATEGETTER_H - -namespace Gambatte { -class InputStateGetter { -public: - virtual ~InputStateGetter() {}; - virtual const InputState& operator()() = 0; -}; -} - -#endif diff --git a/supergameboy/libgambatte/include/int.h b/supergameboy/libgambatte/include/int.h deleted file mode 100644 index 116ab8b7..00000000 --- a/supergameboy/libgambatte/include/int.h +++ /dev/null @@ -1,29 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aam�s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef GAMBATTE_INT_H -#define GAMBATTE_INT_H - -#include - -namespace Gambatte { -typedef uint32_t uint_least32_t; -typedef uint16_t uint_least16_t; -} - -#endif diff --git a/supergameboy/libgambatte/include/videoblitter.h b/supergameboy/libgambatte/include/videoblitter.h deleted file mode 100644 index d2a9c335..00000000 --- a/supergameboy/libgambatte/include/videoblitter.h +++ /dev/null @@ -1,44 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aam�s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef GAMBATTE_VIDEOBLITTER_H -#define GAMBATTE_VIDEOBLITTER_H - -namespace Gambatte { - -struct PixelBuffer { - enum Format { RGB32, RGB16, UYVY }; - - void *pixels; - Format format; - unsigned pitch; - - PixelBuffer() : pixels(0), format(RGB32), pitch(0) {} -}; - -class VideoBlitter { -public: - virtual void setBufferDimensions(unsigned width, unsigned height) = 0; - virtual const PixelBuffer inBuffer() = 0; - virtual void blit() = 0; - virtual ~VideoBlitter() {} -}; - -} - -#endif diff --git a/supergameboy/libgambatte/src/bitmap_font.cpp b/supergameboy/libgambatte/src/bitmap_font.cpp deleted file mode 100644 index b644c06f..00000000 --- a/supergameboy/libgambatte/src/bitmap_font.cpp +++ /dev/null @@ -1,328 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2008 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -/* - The following font bitmaps (static const unsigned char *_bits[]), only used - as data and included in this source file for convenience, are derived from - the Bitstream Vera Sans font, which is distributed under the following - copyright: - - Copyright (c) 2003 by Bitstream, Inc. All Rights Reserved. Bitstream Vera - is a trademark of Bitstream, Inc. - - Permission is hereby granted, free of charge, to any person obtaining a - copy of the fonts accompanying this license ("Fonts") and associated - documentation files (the "Font Software"), to reproduce and distribute the - Font Software, including without limitation the rights to use, copy, merge, - publish, distribute, and/or sell copies of the Font Software, and to permit - persons to whom the Font Software is furnished to do so, subject to the - following conditions: - - The above copyright and trademark notices and this permission notice shall - be included in all copies of one or more of the Font Software typefaces. - - The Font Software may be modified, altered, or added to, and in particular - the designs of glyphs or characters in the Fonts may be modified and - additional glyphs or characters may be added to the Fonts, only if the fonts - are renamed to names not containing either the words "Bitstream" or the word - "Vera". - - This License becomes null and void to the extent applicable to Fonts or Font - Software that has been modified and is distributed under the "Bitstream Vera" - names. - - The Font Software may be sold as part of a larger software package but no - copy of one or more of the Font Software typefaces may be sold by itself. - - THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF - MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF - COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL BITSTREAM - OR THE GNOME FOUNDATION BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR - CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM - OTHER DEALINGS IN THE FONT SOFTWARE. - - Except as contained in this notice, the names of Gnome, the Gnome - Foundation, and Bitstream Inc., shall not be used in advertising or - otherwise to promote the sale, use or other dealings in this Font Software - without prior written authorization from the Gnome Foundation or - Bitstream Inc., respectively. For further information, contact: fonts at - gnome dot org. -*/ - -#include "bitmap_font.h" - -static const unsigned char n0_bits[] = { 0x68, - 0x00, 0x1c, 0x22, 0x22, 0x22, 0x22, 0x22, 0x1c }; - -static const unsigned char n1_bits[] = { 0x68, - 0x00, 0x0e, 0x08, 0x08, 0x08, 0x08, 0x08, 0x3e }; - -static const unsigned char n2_bits[] = { 0x68, - 0x00, 0x1c, 0x22, 0x20, 0x10, 0x08, 0x04, 0x3e }; - -static const unsigned char n3_bits[] = { 0x68, - 0x00, 0x1c, 0x22, 0x20, 0x1c, 0x20, 0x22, 0x1c }; - -static const unsigned char n4_bits[] = { 0x68, - 0x00, 0x18, 0x18, 0x14, 0x12, 0x3e, 0x10, 0x10 }; - -static const unsigned char n5_bits[] = { 0x68, - 0x00, 0x1e, 0x02, 0x1e, 0x20, 0x20, 0x20, 0x1e }; - -static const unsigned char n6_bits[] = { 0x68, - 0x00, 0x3c, 0x06, 0x02, 0x1e, 0x22, 0x22, 0x1c }; - -static const unsigned char n7_bits[] = { 0x68, - 0x00, 0x3e, 0x20, 0x10, 0x10, 0x08, 0x08, 0x04 }; - -static const unsigned char n8_bits[] = { 0x68, - 0x00, 0x1c, 0x22, 0x22, 0x1c, 0x22, 0x22, 0x1c }; - -static const unsigned char n9_bits[] = { 0x68, - 0x00, 0x1c, 0x22, 0x22, 0x3c, 0x20, 0x30, 0x1e }; - -static const unsigned char A_bits[] = { 0x78, - 0x00, 0x08, 0x14, 0x14, 0x22, 0x3e, 0x22, 0x41 }; - -static const unsigned char a_bits[] = { 0x68, - 0x00, 0x00, 0x00, 0x1c, 0x20, 0x3c, 0x22, 0x3e }; - -static const unsigned char B_bits[] = { 0x78, - 0x00, 0x1e, 0x22, 0x22, 0x1e, 0x22, 0x22, 0x1e }; - -static const unsigned char b_bits[] = { 0x68, - 0x02, 0x02, 0x02, 0x1e, 0x22, 0x22, 0x22, 0x1e }; - -static const unsigned char C_bits[] = { 0x88, - 0x00, 0x38, 0x44, 0x02, 0x02, 0x02, 0x44, 0x38 }; - -static const unsigned char c_bits[] = { 0x58, - 0x00, 0x00, 0x00, 0x1c, 0x02, 0x02, 0x02, 0x1c }; - -static const unsigned char D_bits[] = { 0x88, - 0x00, 0x3e, 0x62, 0x42, 0x42, 0x42, 0x62, 0x3e }; - -static const unsigned char d_bits[] = { 0x68, - 0x20, 0x20, 0x20, 0x3c, 0x22, 0x22, 0x22, 0x3c }; - -static const unsigned char E_bits[] = { 0x78, - 0x00, 0x3e, 0x02, 0x02, 0x3e, 0x02, 0x02, 0x3e }; - -static const unsigned char e_bits[] = { 0x68, - 0x00, 0x00, 0x00, 0x1c, 0x22, 0x3e, 0x02, 0x3c }; - -static const unsigned char F_bits[] = { 0x68, - 0x00, 0x1e, 0x02, 0x02, 0x1e, 0x02, 0x02, 0x02 }; - -static const unsigned char f_bits[] = { 0x48, - 0x0e, 0x02, 0x02, 0x07, 0x02, 0x02, 0x02, 0x02 }; - -static const unsigned char G_bits[] = { 0x88, - 0x00, 0x3c, 0x46, 0x02, 0x72, 0x42, 0x46, 0x3c }; - -static const unsigned char g_bits[] = { 0x6a, - 0x00, 0x00, 0x00, 0x3c, 0x22, 0x22, 0x22, 0x3c, 0x20, 0x1c }; - -static const unsigned char H_bits[] = { 0x88, - 0x00, 0x42, 0x42, 0x42, 0x7e, 0x42, 0x42, 0x42 }; - -static const unsigned char h_bits[] = { 0x68, - 0x02, 0x02, 0x02, 0x1e, 0x22, 0x22, 0x22, 0x22 }; - -static const unsigned char I_bits[] = { 0x38, - 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02 }; - -static const unsigned char i_bits[] = { 0x28, - 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02 }; - -static const unsigned char J_bits[] = { 0x4a, - 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03 }; - -static const unsigned char j_bits[] = { 0x2a, - 0x02, 0x00, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x03 }; - -static const unsigned char K_bits[] = { 0x78, - 0x00, 0x22, 0x12, 0x0a, 0x06, 0x0a, 0x12, 0x22 }; - -static const unsigned char k_bits[] = { 0x58, - 0x02, 0x02, 0x02, 0x12, 0x0a, 0x06, 0x0a, 0x12 }; - -static const unsigned char L_bits[] = { 0x68, - 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x3e }; - -static const unsigned char l_bits[] = { 0x28, - 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02 }; - -static const unsigned char M_bits[] = { 0x98, - 0x00, 0x00, 0x82, 0x00, 0xc6, 0x00, 0xc6, 0x00, 0xaa, 0x00, 0xaa, 0x00, - 0x92, 0x00, 0x82, 0x00 }; - -static const unsigned char m_bits[] = { 0xa8, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xde, 0x01, 0x22, 0x02, 0x22, 0x02, - 0x22, 0x02, 0x22, 0x02 }; - -static const unsigned char N_bits[] = { 0x88, - 0x00, 0x42, 0x46, 0x4a, 0x4a, 0x52, 0x62, 0x42 }; - -static const unsigned char n_bits[] = { 0x68, - 0x00, 0x00, 0x00, 0x1e, 0x22, 0x22, 0x22, 0x22 }; - -static const unsigned char O_bits[] = { 0x88, - 0x00, 0x3c, 0x66, 0x42, 0x42, 0x42, 0x66, 0x3c }; - -static const unsigned char o_bits[] = { 0x68, - 0x00, 0x00, 0x00, 0x1c, 0x22, 0x22, 0x22, 0x1c }; - -static const unsigned char P_bits[] = { 0x78, - 0x00, 0x1e, 0x22, 0x22, 0x1e, 0x02, 0x02, 0x02 }; - -static const unsigned char p_bits[] = { 0x6a, - 0x00, 0x00, 0x00, 0x1e, 0x22, 0x22, 0x22, 0x1e, 0x02, 0x02 }; - -static const unsigned char Q_bits[] = { 0x89, - 0x00, 0x3c, 0x66, 0x42, 0x42, 0x42, 0x26, 0x1c, 0x20 }; - -static const unsigned char q_bits[] = { 0x6a, - 0x00, 0x00, 0x00, 0x3c, 0x22, 0x22, 0x22, 0x3c, 0x20, 0x20 }; - -static const unsigned char R_bits[] = { 0x78, - 0x00, 0x1e, 0x22, 0x22, 0x1e, 0x12, 0x22, 0x42 }; - -static const unsigned char r_bits[] = { 0x48, - 0x00, 0x00, 0x00, 0x0e, 0x02, 0x02, 0x02, 0x02 }; - -static const unsigned char S_bits[] = { 0x78, - 0x00, 0x1c, 0x22, 0x02, 0x1c, 0x20, 0x22, 0x1c }; - -static const unsigned char s_bits[] = { 0x58, - 0x00, 0x00, 0x00, 0x1e, 0x02, 0x1c, 0x10, 0x1e }; - -static const unsigned char T_bits[] = { 0x58, - 0x00, 0x1f, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 }; - -static const unsigned char t_bits[] = { 0x48, - 0x00, 0x02, 0x02, 0x0f, 0x02, 0x02, 0x02, 0x0e }; - -static const unsigned char U_bits[] = { 0x88, - 0x00, 0x42, 0x42, 0x42, 0x42, 0x42, 0x42, 0x3c }; - -static const unsigned char u_bits[] = { 0x68, - 0x00, 0x00, 0x00, 0x22, 0x22, 0x22, 0x22, 0x3c }; - -static const unsigned char V_bits[] = { 0x78, - 0x00, 0x41, 0x41, 0x22, 0x22, 0x14, 0x14, 0x08 }; - -static const unsigned char v_bits[] = { 0x68, - 0x00, 0x00, 0x00, 0x22, 0x22, 0x14, 0x14, 0x08 }; - -static const unsigned char W_bits[] = { 0x98, - 0x00, 0x00, 0x11, 0x01, 0x11, 0x01, 0xaa, 0x00, 0xaa, 0x00, 0xaa, 0x00, - 0x44, 0x00, 0x44, 0x00 }; - -static const unsigned char w_bits[] = { 0x88, - 0x00, 0x00, 0x00, 0x92, 0xaa, 0xaa, 0x44, 0x44 }; - -static const unsigned char X_bits[] = { 0x68, - 0x00, 0x21, 0x12, 0x0c, 0x0c, 0x0c, 0x12, 0x21 }; - -static const unsigned char x_bits[] = { 0x68, - 0x00, 0x00, 0x00, 0x22, 0x14, 0x08, 0x14, 0x22 }; - -static const unsigned char Y_bits[] = { 0x78, - 0x00, 0x41, 0x22, 0x14, 0x08, 0x08, 0x08, 0x08 }; - -static const unsigned char y_bits[] = { 0x6a, - 0x00, 0x00, 0x00, 0x22, 0x22, 0x14, 0x14, 0x08, 0x08, 0x06 }; - -static const unsigned char Z_bits[] = { 0x68, - 0x00, 0x3f, 0x10, 0x08, 0x0c, 0x04, 0x02, 0x3f }; - -static const unsigned char z_bits[] = { 0x58, - 0x00, 0x00, 0x00, 0x1e, 0x10, 0x08, 0x04, 0x1e }; - -static const unsigned char SPC_bits[] = { 0x38, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - -namespace BitmapFont { -const unsigned char *const font[] = { - 0, - n0_bits, n1_bits, n2_bits, n3_bits, n4_bits, n5_bits, n6_bits, n7_bits, n8_bits, n9_bits, - A_bits, B_bits, C_bits, D_bits, E_bits, F_bits, G_bits, H_bits, I_bits, J_bits, K_bits, L_bits, M_bits, - N_bits, O_bits, P_bits, Q_bits, R_bits, S_bits, T_bits, U_bits, V_bits, W_bits, X_bits, Y_bits, Z_bits, - a_bits, b_bits, c_bits, d_bits, e_bits, f_bits, g_bits, h_bits, i_bits, j_bits, k_bits, l_bits, m_bits, - n_bits, o_bits, p_bits, q_bits, r_bits, s_bits, t_bits, u_bits, v_bits, w_bits, x_bits, y_bits, z_bits, - SPC_bits -}; - -unsigned getWidth(const char *chars) { - unsigned w = 0; - - while (const int character = *chars++) { - w += *font[character] >> 4; - } - - return w; -} - -class Rgb32Fill { - const unsigned long color; - -public: - Rgb32Fill(unsigned long color) : color(color) {} - - void operator()(Gambatte::uint_least32_t *dest, unsigned /*pitch*/) { - *dest = color; - } -}; - -void print(Gambatte::uint_least32_t *dest, const unsigned pitch, const unsigned long color, const char *chars) { - print(dest, pitch, Rgb32Fill(color), chars); -} - -static void reverse(char *first, char *last) { - while (first < last) { - const int tmp = *first; - - *first = *last; - *last = tmp; - - ++first; - --last; - } -} - -void utoa(unsigned u, char *a) { - char *aa = a; - - while (u > 9) { - const unsigned div = u / 10; - const unsigned rem = u % 10; - - u = div; - *aa++ = rem + N0; - } - - *aa = u + N0; - - reverse(a, aa); -} -} diff --git a/supergameboy/libgambatte/src/bitmap_font.h b/supergameboy/libgambatte/src/bitmap_font.h deleted file mode 100644 index 8217cf61..00000000 --- a/supergameboy/libgambatte/src/bitmap_font.h +++ /dev/null @@ -1,87 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2008 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef BITMAP_FONT_H -#define BITMAP_FONT_H - -#include "int.h" - -namespace BitmapFont { -enum Char { - NUL, - N0, N1, N2, N3, N4, N5, N6, N7, N8, N9, - A, B, C, D, E, F, G, H, I, J, K, L, M, - N, O, P, Q, R, S, T, U, V, W, X, Y, Z, - a, b, c, d, e, f, g, h, i, j, k, l, m, - n, o, p, q, r, s, t, u, v, w, x, y, z, - SPC -}; - -enum { HEIGHT = 10 }; -enum { MAX_WIDTH = 9 }; -enum { NUMBER_WIDTH = 6 }; - -unsigned getWidth(const char *chars); - -// struct Fill { void operator()(RandomAccessIterator dest, unsigned pitch) { fill pixels at dest } } -template -void print(RandomAccessIterator dest, unsigned pitch, Fill fill, const char *chars); - -void print(Gambatte::uint_least32_t *dest, unsigned pitch, unsigned long color, const char *chars); -void utoa(unsigned u, char *a); - -// --- INTERFACE END --- - - - -extern const unsigned char *const font[]; - -template -void print(RandomAccessIterator dest, const unsigned pitch, Fill fill, const char *chars) { - while (const int character = *chars++) { - RandomAccessIterator dst = dest; - const unsigned char *s = font[character]; - - const unsigned width = *s >> 4; - unsigned h = *s++ & 0xF; - - while (h--) { - RandomAccessIterator d = dst; - - unsigned line = *s++; - - if (width > 8) - line |= *s++ << 8; - - while (line) { - if (line & 1) - fill(d, pitch); - - line >>= 1; - ++d; - } - - dst += pitch; - } - - dest += width; - } -} -} - -#endif diff --git a/supergameboy/libgambatte/src/colorconversion.cpp b/supergameboy/libgambatte/src/colorconversion.cpp deleted file mode 100644 index d76b0aee..00000000 --- a/supergameboy/libgambatte/src/colorconversion.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2008 by Sindre Aam�s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "colorconversion.h" -#include - -Rgb32ToUyvy::Rgb32ToUyvy() { -#ifdef WORDS_BIGENDIAN - const CacheUnit c = { 0, 128ul << 24 | 16ul << 16 | 128 << 8 | 16 }; -#else - const CacheUnit c = { 0, 16ul << 24 | 128ul << 16 | 16 << 8 | 128 }; -#endif - std::fill(cache, cache + cache_size, c); -} - -void Rgb32ToUyvy::operator()(const Gambatte::uint_least32_t *s, Gambatte::uint_least32_t *d, const unsigned w, unsigned h, const unsigned d_pitch) { - while (h--) { - for (const Gambatte::uint_least32_t *const ends = s + w; s != ends;) { - if ((cache[*s & cache_mask].rgb32 - *s) | (cache[*(s+1) & cache_mask].rgb32 - *(s+1))) { - cache[*s & cache_mask].rgb32 = *s; - cache[*(s+1) & cache_mask].rgb32 = *(s+1); - - const unsigned long r = (*s >> 16 & 0x000000FF) | (*(s+1) & 0x00FF0000); - const unsigned long g = (*s >> 8 & 0x000000FF) | (*(s+1) << 8 & 0x00FF0000); - const unsigned long b = (*s & 0x000000FF) | (*(s+1) << 16 & 0x00FF0000); - - const unsigned long y = r * 66 + g * 129 + b * 25 + (16 * 256 + 128) * 0x00010001ul; - const unsigned long u = b * 112 - r * 38 - g * 74 + (128 * 256 + 128) * 0x00010001ul; - const unsigned long v = r * 112 - g * 94 - b * 18 + (128 * 256 + 128) * 0x00010001ul; - -#ifdef WORDS_BIGENDIAN - *d++ = cache[*s & cache_mask].uyvy = (u << 16 & 0xFF000000) | (y << 8 & 0x00FF0000) | (v & 0x0000FF00) | (y >> 8 & 0x000000FF); - *d++ = cache[*(s+1) & cache_mask].uyvy = (u & 0xFF000000) | (y >> 8 & 0x00FF0000) | (v >> 16 & 0x0000FF00) | y >> 24; -#else - *d++ = cache[*s & cache_mask].uyvy = (y << 16 & 0xFF000000) | (v << 8 & 0x00FF0000) | (y & 0x0000FF00) | (u >> 8 & 0x000000FF); - *d++ = cache[*(s+1) & cache_mask].uyvy = (y & 0xFF000000) | (v >> 8 & 0x00FF0000) | (y >> 16 & 0x0000FF00) | u >> 24; -#endif - } else { - *d++ = cache[*s & cache_mask].uyvy; - *d++ = cache[*(s+1) & cache_mask].uyvy; - } - - s += 2; - } - - d += d_pitch - w; - } -} - -unsigned long rgb32ToUyvy(unsigned long rgb32) { - const unsigned r = rgb32 >> 16 & 0xFF; - const unsigned g = rgb32 >> 8 & 0xFF; - const unsigned b = rgb32 & 0xFF; - - const unsigned long y = (r * 66 + g * 129 + b * 25 + 16 * 256 + 128) >> 8; - const unsigned long u = (b * 112 - r * 38 - g * 74 + 128 * 256 + 128) >> 8; - const unsigned long v = (r * 112 - g * 94 - b * 18 + 128 * 256 + 128) >> 8; - -#ifdef WORDS_BIGENDIAN - return u << 24 | y << 16 | v << 8 | y; -#else - return y << 24 | v << 16 | y << 8 | u; -#endif -} - -void rgb32ToRgb16(const Gambatte::uint_least32_t *s, Gambatte::uint_least16_t *d, const unsigned w, unsigned h, const unsigned dstPitch) { - do { - unsigned n = w; - - do { - *d++ = (*s >> 8 & 0xF800) | (*s >> 5 & 0x07E0) | (*s >> 3 & 0x001F); - ++s; - } while (--n); - - d += dstPitch - w; - } while (--h); -} - -unsigned rgb32ToRgb16(const unsigned long rgb32) { - return (rgb32 >> 8 & 0xF800) | (rgb32 >> 5 & 0x07E0) | (rgb32 >> 3 & 0x001F); -} diff --git a/supergameboy/libgambatte/src/colorconversion.h b/supergameboy/libgambatte/src/colorconversion.h deleted file mode 100644 index 9323015e..00000000 --- a/supergameboy/libgambatte/src/colorconversion.h +++ /dev/null @@ -1,46 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2008 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef COLORCONVERSION_H -#define COLORCONVERSION_H - -#include "int.h" -#include - -class Rgb32ToUyvy { - struct CacheUnit { - Gambatte::uint_least32_t rgb32; - Gambatte::uint_least32_t uyvy; - }; - - enum { cache_size = 0x100 }; - enum { cache_mask = cache_size - 1 }; - - CacheUnit cache[cache_size]; - -public: - Rgb32ToUyvy(); - void operator()(const Gambatte::uint_least32_t *s, Gambatte::uint_least32_t *d, unsigned w, unsigned h, unsigned dstPitch); -}; - -unsigned long rgb32ToUyvy(unsigned long rgb32); - -void rgb32ToRgb16(const Gambatte::uint_least32_t *s, Gambatte::uint_least16_t *d, unsigned w, unsigned h, unsigned dstPitch); -unsigned rgb32ToRgb16(unsigned long rgb32); - -#endif diff --git a/supergameboy/libgambatte/src/cpu.cpp b/supergameboy/libgambatte/src/cpu.cpp deleted file mode 100644 index c44b1239..00000000 --- a/supergameboy/libgambatte/src/cpu.cpp +++ /dev/null @@ -1,2842 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aam�s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "cpu.h" -#include "memory.h" -#include "savestate.h" - -CPU::CPU() : -memory(Interrupter(SP, PC_, halted)), -cycleCounter_(0), -PC_(0x100), -SP(0xFFFE), -HF1(0xF), -HF2(0xF), -ZF(0), -CF(0x100), -A_(0x01), -B(0x00), -C(0x13), -D(0x00), -E(0xD8), -H(0x01), -L(0x4D), -skip(false), -halted(false) -{} - -void CPU::runFor(const unsigned long cycles) { - process(cycles/* << memory.isDoubleSpeed()*/); - - if (cycleCounter_ & 0x80000000) - cycleCounter_ = memory.resetCounters(cycleCounter_); -} - -bool CPU::load(const bool forceDmg) { - bool tmp = memory.loadROM(forceDmg); - - return tmp; -} - -/*void CPU::halt() { - while (halted) { - const uint_fast32_t cycles = memory.next_eventtime - memory.CycleCounter; - memory.CycleCounter += cycles + ((4 - (cycles & 3)) & 3); - memory.event(); - } -}*/ - -//Push address of next instruction onto stack and then jump to interrupt address (0x40-0x60): -/*unsigned CPU::interrupt(const unsigned address, unsigned cycleCounter) { - if (halted && memory.isCgb()) - cycleCounter += 4; - - halted = false; - cycleCounter += 8; - memory.write(--SP, PC_ >> 8, cycleCounter); - cycleCounter += 4; - memory.write(--SP, PC_ & 0xFF, cycleCounter); - PC_ = address; - cycleCounter += 8; - - return cycleCounter; -}*/ - -// (HF2 & 0x200) == true means HF is set. -// (HF2 & 0x400) marks the subtract flag. -// (HF2 & 0x800) is set for inc/dec. -// (HF2 & 0x100) is set if there's a carry to add. -static void calcHF(const unsigned HF1, unsigned& HF2) { - unsigned arg1 = HF1 & 0xF; - unsigned arg2 = (HF2 & 0xF) + (HF2 >> 8 & 1); - - if (HF2 & 0x800) { - arg1 = arg2; - arg2 = 1; - } - - if (HF2 & 0x400) - arg1 -= arg2; - else - arg1 = (arg1 + arg2) << 5; - - HF2 |= arg1 & 0x200; -} - -#define F() (((HF2 & 0x600) | (CF & 0x100)) >> 4 | ((ZF & 0xFF) ? 0 : 0x80)) - -#define FROM_F(f_in) do { \ - unsigned from_f_var = f_in; \ -\ - ZF = ~from_f_var & 0x80; \ - HF2 = from_f_var << 4 & 0x600; \ - CF = from_f_var << 4 & 0x100; \ -} while (0) - -void CPU::setStatePtrs(SaveState &state) { - memory.setStatePtrs(state); -} - -void CPU::saveState(SaveState &state) { - cycleCounter_ = memory.saveState(state, cycleCounter_); - - calcHF(HF1, HF2); - - state.cpu.cycleCounter = cycleCounter_; - state.cpu.PC = PC_; - state.cpu.SP = SP; - state.cpu.A = A_; - state.cpu.B = B; - state.cpu.C = C; - state.cpu.D = D; - state.cpu.E = E; - state.cpu.F = F(); - state.cpu.H = H; - state.cpu.L = L; - state.cpu.skip = skip; - state.cpu.halted = halted; -} - -void CPU::loadState(const SaveState &state) { - memory.loadState(state, cycleCounter_); - - cycleCounter_ = state.cpu.cycleCounter; - PC_ = state.cpu.PC; - SP = state.cpu.SP; - A_ = state.cpu.A; - B = state.cpu.B; - C = state.cpu.C; - D = state.cpu.D; - E = state.cpu.E; - FROM_F(state.cpu.F); - H = state.cpu.H; - L = state.cpu.L; - skip = state.cpu.skip; - halted = state.cpu.halted; -} - -#define BC() ( B << 8 | C ) -#define DE() ( D << 8 | E ) -#define HL() ( H << 8 | L ) - -#define READ(dest, addr) do { (dest) = memory.read(addr, cycleCounter); cycleCounter += 4; } while (0) -// #define PC_READ(dest, addr) do { (dest) = memory.pc_read(addr, cycleCounter); cycleCounter += 4; } while (0) -#define PC_READ(dest) do { (dest) = memory.read(PC, cycleCounter); PC = (PC + 1) & 0xFFFF; cycleCounter += 4; } while (0) -#define FF_READ(dest, addr) do { (dest) = memory.ff_read(addr, cycleCounter); cycleCounter += 4; } while (0) - -#define WRITE(addr, data) do { memory.write(addr, data, cycleCounter); cycleCounter += 4; } while (0) -#define FF_WRITE(addr, data) do { memory.ff_write(addr, data, cycleCounter); cycleCounter += 4; } while (0) - -#define PC_MOD(data) do { PC = data; cycleCounter += 4; } while (0) - -#define PUSH(r1, r2) do { \ - SP = (SP - 1) & 0xFFFF; \ - WRITE(SP, (r1)); \ - SP = (SP - 1) & 0xFFFF; \ - WRITE(SP, (r2)); \ -} while (0) - -//CB OPCODES (Shifts, rotates and bits): -//swap r (8 cycles): -//Swap upper and lower nibbles of 8-bit register, reset flags, check zero flag: -#define swap_r(r) do { \ - CF = HF2 = 0; \ - ZF = (r); \ - (r) = (ZF << 4 | ZF >> 4) & 0xFF; \ -} while (0) - -//rlc r (8 cycles): -//Rotate 8-bit register left, store old bit7 in CF. Reset SF and HCF, Check ZF: -#define rlc_r(r) do { \ - CF = (r) << 1; \ - ZF = CF | CF >> 8; \ - (r) = ZF & 0xFF; \ - HF2 = 0; \ -} while (0) - -//rl r (8 cycles): -//Rotate 8-bit register left through CF, store old bit7 in CF, old CF value becomes bit0. Reset SF and HCF, Check ZF: -#define rl_r(r) do { \ - const unsigned rl_r_var_oldcf = CF >> 8 & 1; \ - CF = (r) << 1; \ - ZF = CF | rl_r_var_oldcf; \ - (r) = ZF & 0xFF; \ - HF2 = 0; \ -} while (0) - -//rrc r (8 cycles): -//Rotate 8-bit register right, store old bit0 in CF. Reset SF and HCF, Check ZF: -#define rrc_r(r) do { \ - ZF = (r); \ - CF = ZF << 8; \ - (r) = (ZF | CF) >> 1 & 0xFF; \ - HF2 = 0; \ -} while (0) - -//rr r (8 cycles): -//Rotate 8-bit register right through CF, store old bit0 in CF, old CF value becomes bit7. Reset SF and HCF, Check ZF: -#define rr_r(r) do { \ - const unsigned rr_r_var_oldcf = CF & 0x100; \ - CF = (r) << 8; \ - (r) = ZF = ((r) | rr_r_var_oldcf) >> 1; \ - HF2 = 0; \ -} while (0) - -//sla r (8 cycles): -//Shift 8-bit register left, store old bit7 in CF. Reset SF and HCF, Check ZF: -#define sla_r(r) do { \ - ZF = CF = (r) << 1; \ - (r) = ZF & 0xFF; \ - HF2 = 0; \ -} while (0) - -//sra r (8 cycles): -//Shift 8-bit register right, store old bit0 in CF. bit7=old bit7. Reset SF and HCF, Check ZF: -#define sra_r(r) do { \ - CF = (r) << 8; \ - ZF = (r) >> 1; \ - (r) = ZF | ((r) & 0x80); \ - HF2 = 0; \ -} while (0) - -//srl r (8 cycles): -//Shift 8-bit register right, store old bit0 in CF. Reset SF and HCF, Check ZF: -#define srl_r(r) do { \ - ZF = (r); \ - CF = (r) << 8; \ - ZF >>= 1; \ - (r) = ZF; \ - HF2 = 0; \ -} while (0) - -//bit n,r (8 cycles): -//bit n,(hl) (12 cycles): -//Test bitn in 8-bit value, check ZF, unset SF, set HCF: -#define bitn_u8(bitmask, u8) do { \ - ZF = (u8) & (bitmask); \ - HF2 = 0x200; \ -} while (0) - -#define bit0_u8(u8) bitn_u8(1, (u8)) -#define bit1_u8(u8) bitn_u8(2, (u8)) -#define bit2_u8(u8) bitn_u8(4, (u8)) -#define bit3_u8(u8) bitn_u8(8, (u8)) -#define bit4_u8(u8) bitn_u8(0x10, (u8)) -#define bit5_u8(u8) bitn_u8(0x20, (u8)) -#define bit6_u8(u8) bitn_u8(0x40, (u8)) -#define bit7_u8(u8) bitn_u8(0x80, (u8)) - -//set n,r (8 cycles): -//Set bitn of 8-bit register: -#define set0_r(r) ( (r) |= 0x1 ) -#define set1_r(r) ( (r) |= 0x2 ) -#define set2_r(r) ( (r) |= 0x4 ) -#define set3_r(r) ( (r) |= 0x8 ) -#define set4_r(r) ( (r) |= 0x10 ) -#define set5_r(r) ( (r) |= 0x20 ) -#define set6_r(r) ( (r) |= 0x40 ) -#define set7_r(r) ( (r) |= 0x80 ) - -//set n,(hl) (16 cycles): -//Set bitn of value at address stored in HL: -#define setn_mem_hl(n) do { \ - const unsigned setn_mem_hl_var_addr = HL(); \ - unsigned setn_mem_hl_var_tmp; \ -\ - READ(setn_mem_hl_var_tmp, setn_mem_hl_var_addr); \ - setn_mem_hl_var_tmp |= 1 << (n); \ -\ - WRITE(setn_mem_hl_var_addr, setn_mem_hl_var_tmp); \ -} while (0) - -//res n,r (8 cycles): -//Unset bitn of 8-bit register: -#define res0_r(r) ( (r) &= 0xFE ) -#define res1_r(r) ( (r) &= 0xFD ) -#define res2_r(r) ( (r) &= 0xFB ) -#define res3_r(r) ( (r) &= 0xF7 ) -#define res4_r(r) ( (r) &= 0xEF ) -#define res5_r(r) ( (r) &= 0xDF ) -#define res6_r(r) ( (r) &= 0xBF ) -#define res7_r(r) ( (r) &= 0x7F ) - -//res n,(hl) (16 cycles): -//Unset bitn of value at address stored in HL: -#define resn_mem_hl(n) do { \ - const unsigned resn_mem_hl_var_addr = HL(); \ - unsigned resn_mem_hl_var_tmp; \ -\ - READ(resn_mem_hl_var_tmp, resn_mem_hl_var_addr); \ - resn_mem_hl_var_tmp &= ~(1 << (n)); \ -\ - WRITE(resn_mem_hl_var_addr, resn_mem_hl_var_tmp); \ -} while (0) - - -//16-BIT LOADS: -//ld rr,nn (12 cycles) -//set rr to 16-bit value of next 2 bytes in memory -#define ld_rr_nn(r1, r2) do { \ - PC_READ(r2); \ - PC_READ(r1); \ -} while (0) - -//push rr (16 cycles): -//Push value of register pair onto stack: -#define push_rr(r1, r2) do { \ - PUSH(r1, r2); \ - cycleCounter += 4; \ -} while (0) - -//pop rr (12 cycles): -//Pop two bytes off stack into register pair: -#define pop_rr(r1, r2) do { \ - READ(r2, SP); \ - SP = (SP + 1) & 0xFFFF; \ - READ(r1, SP); \ - SP = (SP + 1) & 0xFFFF; \ -} while (0) - -//8-BIT ALU: -//add a,r (4 cycles): -//add a,(addr) (8 cycles): -//Add 8-bit value to A, check flags: -#define add_a_u8(u8) do { \ - HF1 = A; \ - HF2 = u8; \ - ZF = CF = A + HF2; \ - A = ZF & 0xFF; \ -} while (0) - -//adc a,r (4 cycles): -//adc a,(addr) (8 cycles): -//Add 8-bit value+CF to A, check flags: -#define adc_a_u8(u8) do { \ - HF1 = A; \ - HF2 = (CF & 0x100) | (u8); \ - ZF = CF = (CF >> 8 & 1) + (u8) + A; \ - A = ZF & 0xFF; \ -} while (0) - -//sub a,r (4 cycles): -//sub a,(addr) (8 cycles): -//Subtract 8-bit value from A, check flags: -#define sub_a_u8(u8) do { \ - HF1 = A; \ - HF2 = u8; \ - ZF = CF = A - HF2; \ - A = ZF & 0xFF; \ - HF2 |= 0x400; \ -} while (0) - -//sbc a,r (4 cycles): -//sbc a,(addr) (8 cycles): -//Subtract CF and 8-bit value from A, check flags: -#define sbc_a_u8(u8) do { \ - HF1 = A; \ - HF2 = 0x400 | (CF & 0x100) | (u8); \ - ZF = CF = A - ((CF >> 8) & 1) - (u8); \ - A = ZF & 0xFF; \ -} while (0) - -//and a,r (4 cycles): -//and a,(addr) (8 cycles): -//bitwise and 8-bit value into A, check flags: -#define and_a_u8(u8) do { \ - HF2 = 0x200; \ - CF = 0; \ - A &= (u8); \ - ZF = A; \ -} while (0) - -//or a,r (4 cycles): -//or a,(hl) (8 cycles): -//bitwise or 8-bit value into A, check flags: -#define or_a_u8(u8) do { \ - CF = HF2 = 0; \ - A |= (u8); \ - ZF = A; \ -} while (0) - -//xor a,r (4 cycles): -//xor a,(hl) (8 cycles): -//bitwise xor 8-bit value into A, check flags: -#define xor_a_u8(u8) do { \ - CF = HF2 = 0; \ - A ^= (u8); \ - ZF = A; \ -} while (0) - -//cp a,r (4 cycles): -//cp a,(addr) (8 cycles): -//Compare (subtract without storing result) 8-bit value to A, check flags: -#define cp_a_u8(u8) do { \ - HF1 = A; \ - HF2 = u8; \ - ZF = CF = A - HF2; \ - HF2 |= 0x400; \ -} while (0) - -//inc r (4 cycles): -//Increment value of 8-bit register, check flags except CF: -#define inc_r(r) do { \ - HF2 = (r) | 0x800; \ - ZF = (r) + 1; \ - (r) = ZF & 0xFF; \ -} while (0) - -//dec r (4 cycles): -//Decrement value of 8-bit register, check flags except CF: -#define dec_r(r) do { \ - HF2 = (r) | 0xC00; \ - ZF = (r) - 1; \ - (r) = ZF & 0xFF; \ -} while (0) - -//16-BIT ARITHMETIC -//add hl,rr (8 cycles): -//add 16-bit register to HL, check flags except ZF: -/*#define add_hl_rr(rh, rl) do { \ - L = HF1 = L + (rl); \ - HF1 >>= 8; \ - HF1 += H; \ - HF2 = (rh); \ - H = CF = HF1 + (rh); \ - cycleCounter += 4; \ -} while (0)*/ - -#define add_hl_rr(rh, rl) do { \ - CF = L + (rl); \ - L = CF & 0xFF; \ - HF1 = H; \ - HF2 = (CF & 0x100) | (rh); \ - CF = H + (CF >> 8) + (rh); \ - H = CF & 0xFF; \ - cycleCounter += 4; \ -} while (0) - -//inc rr (8 cycles): -//Increment 16-bit register: -#define inc_rr(rh, rl) do { \ - const unsigned inc_rr_var_tmp = (rl) + 1; \ - (rl) = inc_rr_var_tmp & 0xFF; \ - (rh) = ((rh) + (inc_rr_var_tmp >> 8)) & 0xFF; \ - cycleCounter += 4; \ -} while (0) - -//dec rr (8 cycles): -//Decrement 16-bit register: -#define dec_rr(rh, rl) do { \ - const unsigned dec_rr_var_tmp = (rl) - 1; \ - (rl) = dec_rr_var_tmp & 0xFF; \ - (rh) = ((rh) - (dec_rr_var_tmp >> 8 & 1)) & 0xFF; \ - cycleCounter += 4; \ -} while (0) - -#define sp_plus_n(sumout) do { \ - unsigned sp_plus_n_var_n; \ - PC_READ(sp_plus_n_var_n); \ - sp_plus_n_var_n = (sp_plus_n_var_n ^ 0x80) - 0x80; \ - \ - const unsigned sp_plus_n_var_sum = SP + sp_plus_n_var_n; \ - CF = SP ^ sp_plus_n_var_n ^ sp_plus_n_var_sum; \ - HF2 = CF << 5 & 0x200; \ - ZF = 1; \ - cycleCounter += 4; \ - (sumout) = sp_plus_n_var_sum & 0xFFFF; \ -} while (0) - -//JUMPS: -//jp nn (16 cycles): -//Jump to address stored in the next two bytes in memory: -#define jp_nn() do { \ - unsigned jp_nn_var_l, jp_nn_var_h; \ -\ - PC_READ(jp_nn_var_l); \ - PC_READ(jp_nn_var_h); \ -\ - PC_MOD(jp_nn_var_h << 8 | jp_nn_var_l); \ -} while (0) - -//jr disp (12 cycles): -//Jump to value of next (signed) byte in memory+current address: -#define jr_disp() do { \ - unsigned jr_disp_var_tmp; \ -\ - PC_READ(jr_disp_var_tmp); \ - jr_disp_var_tmp = (jr_disp_var_tmp ^ 0x80) - 0x80; \ -\ - PC_MOD((PC + jr_disp_var_tmp) & 0xFFFF); \ -} while (0) - -//CALLS, RESTARTS AND RETURNS: -//call nn (24 cycles): -//Push address of next instruction onto stack and then jump to address stored in next two bytes in memory: -#define call_nn() do { \ - PUSH(((PC + 2) >> 8) & 0xFF, (PC + 2) & 0xFF); \ - jp_nn(); \ -} while (0) - -//rst n (16 Cycles): -//Push present address onto stack, jump to address n (one of 00h,08h,10h,18h,20h,28h,30h,38h): -#define rst_n(n) do { \ - PUSH(PC >> 8, PC & 0xFF); \ - PC_MOD(n); \ -} while (0) - -//ret (16 cycles): -//Pop two bytes from the stack and jump to that address: -#define ret() do { \ - unsigned ret_var_l, ret_var_h; \ -\ - pop_rr(ret_var_h, ret_var_l); \ -\ - PC_MOD(ret_var_h << 8 | ret_var_l); \ -} while (0) - -void CPU::process(const unsigned long cycles) { - memory.setEndtime(cycleCounter_, cycles); - - unsigned char A = A_; - unsigned long cycleCounter = cycleCounter_; - - while (memory.isActive()) { - unsigned short PC = PC_; - - if (halted) { - if (cycleCounter < memory.getNextEventTime()) { - const unsigned long cycles = memory.getNextEventTime() - cycleCounter; - cycleCounter += cycles + ((4 - (cycles & 3)) & 3); - } - } else while (cycleCounter < memory.getNextEventTime()) { - unsigned char opcode; - - PC_READ(opcode); - - if (skip) { - PC = (PC - 1) & 0xFFFF; - skip = false; - } - - switch (opcode) { - //nop (4 cycles): - //Do nothing for 4 cycles: - case 0x00: - break; - case 0x01: - ld_rr_nn(B, C); - break; - case 0x02: - WRITE(BC(), A); - break; - case 0x03: - inc_rr(B, C); - break; - case 0x04: - inc_r(B); - break; - case 0x05: - dec_r(B); - break; - case 0x06: - PC_READ(B); - break; - - //rlca (4 cycles): - //Rotate 8-bit register A left, store old bit7 in CF. Reset SF, HCF, ZF: - case 0x07: - CF = A << 1; - A = (CF | CF >> 8) & 0xFF; - HF2 = 0; - ZF = 1; - break; - - //ld (nn),SP (20 cycles): - //Put value of SP into address given by next 2 bytes in memory: - case 0x08: - { - unsigned l, h; - - PC_READ(l); - PC_READ(h); - - const unsigned addr = h << 8 | l; - - WRITE(addr, SP & 0xFF); - WRITE((addr + 1) & 0xFFFF, SP >> 8); - } - break; - - case 0x09: - add_hl_rr(B, C); - break; - case 0x0A: - READ(A, BC()); - break; - case 0x0B: - dec_rr(B, C); - break; - case 0x0C: - inc_r(C); - break; - case 0x0D: - dec_r(C); - break; - case 0x0E: - PC_READ(C); - break; - - //rrca (4 cycles): - //Rotate 8-bit register A right, store old bit0 in CF. Reset SF, HCF, ZF: - case 0x0F: - CF = A << 8 | A; - A = CF >> 1 & 0xFF; - HF2 = 0; - ZF = 1; - break; - - //stop (4 cycles): - //Halt CPU and LCD display until button pressed: - case 0x10: - memory.speedChange(cycleCounter); - PC = (PC + 1) & 0xFFFF; - break; - case 0x11: - ld_rr_nn(D, E); - break; - case 0x12: - WRITE(DE(), A); - break; - case 0x13: - inc_rr(D, E); - break; - case 0x14: - inc_r(D); - break; - case 0x15: - dec_r(D); - break; - case 0x16: - PC_READ(D); - break; - - //rla (4 cycles): - //Rotate 8-bit register A left through CF, store old bit7 in CF, old CF value becomes bit0. Reset SF, HCF, ZF: - case 0x17: - { - const unsigned oldcf = CF >> 8 & 1; - CF = A << 1; - A = (CF | oldcf) & 0xFF; - } - - HF2 = 0; - ZF = 1; - break; - - case 0x18: - jr_disp(); - break; - case 0x19: - add_hl_rr(D, E); - break; - case 0x1A: - READ(A, DE()); - break; - case 0x1B: - dec_rr(D, E); - break; - case 0x1C: - inc_r(E); - break; - case 0x1D: - dec_r(E); - break; - case 0x1E: - PC_READ(E); - break; - - //rra (4 cycles): - //Rotate 8-bit register A right through CF, store old bit0 in CF, old CF value becomes bit7. Reset SF, HCF, ZF: - case 0x1F: - { - const unsigned oldcf = CF & 0x100; - CF = A << 8; - A = (A | oldcf) >> 1; - } - - HF2 = 0; - ZF = 1; - break; - - //jr nz,disp (12;8 cycles): - //Jump to value of next (signed) byte in memory+current address if ZF is unset: - case 0x20: - if (ZF & 0xFF) { - jr_disp(); - } else { - PC_MOD((PC + 1) & 0xFFFF); - } - break; - - case 0x21: - ld_rr_nn(H, L); - break; - - //ldi (hl),a (8 cycles): - //Put A into memory address in hl. Increment HL: - case 0x22: - { - unsigned addr = HL(); - - WRITE(addr, A); - - addr = (addr + 1) & 0xFFFF; - L = addr; - H = addr >> 8; - } - break; - - case 0x23: - inc_rr(H, L); - break; - case 0x24: - inc_r(H); - break; - case 0x25: - dec_r(H); - break; - case 0x26: - PC_READ(H); - break; - - - //daa (4 cycles): - //Adjust register A to correctly represent a BCD. Check ZF, HF and CF: - case 0x27: - /*{ - unsigned correction = ((A > 0x99) || (CF & 0x100)) ? 0x60 : 0x00; - - calcHF(HF1, HF2); - - if ((A & 0x0F) > 0x09 || (HF2 & 0x200)) - correction |= 0x06; - - HF1 = A; - HF2 = (HF2 & 0x400) | correction; - CF = (correction & 0x40) << 2; - A = (HF2 & 0x400) ? A - correction : (A + correction); - ZF = A; - }*/ - - calcHF(HF1, HF2); - - { - unsigned correction = (CF & 0x100) ? 0x60 : 0x00; - - if (HF2 & 0x200) - correction |= 0x06; - - if (!(HF2 &= 0x400)) { - if ((A & 0x0F) > 0x09) - correction |= 0x06; - - if (A > 0x99) - correction |= 0x60; - - A += correction; - } else - A -= correction; - - CF = correction << 2 & 0x100; - ZF = A; - A &= 0xFF; - } - break; - - //jr z,disp (12;8 cycles): - //Jump to value of next (signed) byte in memory+current address if ZF is set: - case 0x28: - if (ZF & 0xFF) { - PC_MOD((PC + 1) & 0xFFFF); - } else { - jr_disp(); - } - break; - - //add hl,hl (8 cycles): - //add 16-bit register HL to HL, check flags except ZF: - case 0x29: - add_hl_rr(H, L); - break; - - //ldi a,(hl) (8 cycles): - //Put value at address in hl into A. Increment HL: - case 0x2A: - { - unsigned addr = HL(); - - READ(A, addr); - - addr = (addr + 1) & 0xFFFF; - L = addr; - H = addr >> 8; - } - break; - - case 0x2B: - dec_rr(H, L); - break; - case 0x2C: - inc_r(L); - break; - case 0x2D: - dec_r(L); - break; - case 0x2E: - PC_READ(L); - break; - - //cpl (4 cycles): - //Complement register A. (Flip all bits), set SF and HCF: - case 0x2F: /*setSubtractFlag(); setHalfCarryFlag();*/ - HF2 = 0x600; - A ^= 0xFF; - break; - - //jr nc,disp (12;8 cycles): - //Jump to value of next (signed) byte in memory+current address if CF is unset: - case 0x30: - if (CF & 0x100) { - PC_MOD((PC + 1) & 0xFFFF); - } else { - jr_disp(); - } - break; - - //ld sp,nn (12 cycles) - //set sp to 16-bit value of next 2 bytes in memory - case 0x31: - { - unsigned l, h; - - PC_READ(l); - PC_READ(h); - - SP = h << 8 | l; - } - break; - - //ldd (hl),a (8 cycles): - //Put A into memory address in hl. Decrement HL: - case 0x32: - { - unsigned addr = HL(); - - WRITE(addr, A); - - addr = (addr - 1) & 0xFFFF; - L = addr; - H = addr >> 8; - } - break; - - case 0x33: - SP = (SP + 1) & 0xFFFF; - cycleCounter += 4; - break; - - //inc (hl) (12 cycles): - //Increment value at address in hl, check flags except CF: - case 0x34: - { - const unsigned addr = HL(); - - READ(HF2, addr); - ZF = HF2 + 1; - WRITE(addr, ZF & 0xFF); - HF2 |= 0x800; - } - break; - - //dec (hl) (12 cycles): - //Decrement value at address in hl, check flags except CF: - case 0x35: - { - const unsigned addr = HL(); - - READ(HF2, addr); - ZF = HF2 - 1; - WRITE(addr, ZF & 0xFF); - HF2 |= 0xC00; - } - break; - - //ld (hl),n (12 cycles): - //set memory at address in hl to value of next byte in memory: - case 0x36: - { - unsigned tmp; - - PC_READ(tmp); - WRITE(HL(), tmp); - } - break; - - //scf (4 cycles): - //Set CF. Unset SF and HCF: - case 0x37: /*setCarryFlag(); unsetSubtractFlag(); unsetHalfCarryFlag();*/ - CF = 0x100; - HF2 = 0; - break; - - //jr c,disp (12;8 cycles): - //Jump to value of next (signed) byte in memory+current address if CF is set: - case 0x38: //PC+=(((int8_t)memory.read(PC++))*CarryFlag()); Cycles(8); break; - if (CF & 0x100) { - jr_disp(); - } else { - PC_MOD((PC + 1) & 0xFFFF); - } - break; - - //add hl,sp (8 cycles): - //add SP to HL, check flags except ZF: - case 0x39: /*add_hl_rr(SP>>8, SP); break;*/ - CF = L + SP; - L = CF & 0xFF; - HF1 = H; - HF2 = ((CF ^ SP) & 0x100) | SP >> 8; - CF >>= 8; - CF += H; - H = CF & 0xFF; - cycleCounter += 4; - break; - - //ldd a,(hl) (8 cycles): - //Put value at address in hl into A. Decrement HL: - case 0x3A: - { - unsigned addr = HL(); - - A = memory.read(addr, cycleCounter); - cycleCounter += 4; - - addr = (addr - 1) & 0xFFFF; - L = addr; - H = addr >> 8; - } - break; - - case 0x3B: - SP = (SP - 1) & 0xFFFF; - cycleCounter += 4; - break; - case 0x3C: - inc_r(A); - break; - case 0x3D: - dec_r(A); - break; - case 0x3E: - PC_READ(A); - break; - - //ccf (4 cycles): - //Complement CF (unset if set vv.) Unset SF and HCF. - case 0x3F: /*complementCarryFlag(); unsetSubtractFlag(); unsetHalfCarryFlag();*/ - CF ^= 0x100; - HF2 = 0; - break; - - //ld r,r (4 cycles):next_irqEventTime - //ld r,(r) (8 cycles): - case 0x40: - B = B; - break; - case 0x41: - B = C; - break; - case 0x42: - B = D; - break; - case 0x43: - B = E; - break; - case 0x44: - B = H; - break; - case 0x45: - B = L; - break; - case 0x46: - READ(B, HL()); - break; - case 0x47: - B = A; - break; - case 0x48: - C = B; - break; - case 0x49: - C = C; - break; - case 0x4A: - C = D; - break; - case 0x4B: - C = E; - break; - case 0x4C: - C = H; - break; - case 0x4D: - C = L; - break; - case 0x4E: - READ(C, HL()); - break; - case 0x4F: - C = A; - break; - case 0x50: - D = B; - break; - case 0x51: - D = C; - break; - case 0x52: - D = D; - break; - case 0x53: - D = E; - break; - case 0x54: - D = H; - break; - case 0x55: - D = L; - break; - case 0x56: - READ(D, HL()); - break; - case 0x57: - D = A; - break; - case 0x58: - E = B; - break; - case 0x59: - E = C; - break; - case 0x5A: - E = D; - break; - case 0x5B: - E = E; - break; - case 0x5C: - E = H; - break; - case 0x5D: - E = L; - break; - case 0x5E: - READ(E, HL()); - break; - case 0x5F: - E = A; - break; - case 0x60: - H = B; - break; - case 0x61: - H = C; - break; - case 0x62: - H = D; - break; - case 0x63: - H = E; - break; - case 0x64: - H = H; - break; - case 0x65: - H = L; - break; - case 0x66: - READ(H, HL()); - break; - case 0x67: - H = A; - break; - case 0x68: - L = B; - break; - case 0x69: - L = C; - break; - case 0x6A: - L = D; - break; - case 0x6B: - L = E; - break; - case 0x6C: - L = H; - break; - case 0x6D: - L = L; - break; - case 0x6E: - READ(L, HL()); - break; - case 0x6F: - L = A; - break; - case 0x70: - WRITE(HL(), B); - break; - case 0x71: - WRITE(HL(), C); - break; - case 0x72: - WRITE(HL(), D); - break; - case 0x73: - WRITE(HL(), E); - break; - case 0x74: - WRITE(HL(), H); - break; - case 0x75: - WRITE(HL(), L); - break; - - //halt (4 cycles): - case 0x76: -// printf("halt\n"); - if (memory.getIME()/* || memory.next_eitime*/) { - halted = 1; - - if (cycleCounter < memory.getNextEventTime()) { - const unsigned long cycles = memory.getNextEventTime() - cycleCounter; - cycleCounter += cycles + ((4 - (cycles & 3)) & 3); - } - } else { - if ((memory.ff_read(0xFF0F, cycleCounter) & memory.ff_read(0xFFFF, cycleCounter)) & 0x1F) { - if (memory.isCgb()) - cycleCounter += 8; //two nops. - else - skip = true; - } else { - memory.schedule_unhalt(); - halted = 1; - - if (cycleCounter < memory.getNextEventTime()) { - const unsigned long cycles = memory.getNextEventTime() - cycleCounter; - cycleCounter += cycles + ((4 - (cycles & 3)) & 3); - } - } - } - break; - case 0x77: - WRITE(HL(), A); - break; - case 0x78: - A = B; - break; - case 0x79: - A = C; - break; - case 0x7A: - A = D; - break; - case 0x7B: - A = E; - break; - case 0x7C: - A = H; - break; - case 0x7D: - A = L; - break; - case 0x7E: - READ(A, HL()); - break; - case 0x7F: - A = A; - break; - case 0x80: - add_a_u8(B); - break; - case 0x81: - add_a_u8(C); - break; - case 0x82: - add_a_u8(D); - break; - case 0x83: - add_a_u8(E); - break; - case 0x84: - add_a_u8(H); - break; - case 0x85: - add_a_u8(L); - break; - case 0x86: - { - unsigned data; - - READ(data, HL()); - - add_a_u8(data); - } - break; - case 0x87: - add_a_u8(A); - break; - case 0x88: - adc_a_u8(B); - break; - case 0x89: - adc_a_u8(C); - break; - case 0x8A: - adc_a_u8(D); - break; - case 0x8B: - adc_a_u8(E); - break; - case 0x8C: - adc_a_u8(H); - break; - case 0x8D: - adc_a_u8(L); - break; - case 0x8E: - { - unsigned data; - - READ(data, HL()); - - adc_a_u8(data); - } - break; - case 0x8F: - adc_a_u8(A); - break; - case 0x90: - sub_a_u8(B); - break; - case 0x91: - sub_a_u8(C); - break; - case 0x92: - sub_a_u8(D); - break; - case 0x93: - sub_a_u8(E); - break; - case 0x94: - sub_a_u8(H); - break; - case 0x95: - sub_a_u8(L); - break; - case 0x96: - { - unsigned data; - - READ(data, HL()); - - sub_a_u8(data); - } - break; - //A-A is always 0: - case 0x97: - HF2 = 0x400; - CF = ZF = A = 0; - break; - case 0x98: - sbc_a_u8(B); - break; - case 0x99: - sbc_a_u8(C); - break; - case 0x9A: - sbc_a_u8(D); - break; - case 0x9B: - sbc_a_u8(E); - break; - case 0x9C: - sbc_a_u8(H); - break; - case 0x9D: - sbc_a_u8(L); - break; - case 0x9E: - { - unsigned data; - - READ(data, HL()); - - sbc_a_u8(data); - } - break; - case 0x9F: - sbc_a_u8(A); - break; - case 0xA0: - and_a_u8(B); - break; - case 0xA1: - and_a_u8(C); - break; - case 0xA2: - and_a_u8(D); - break; - case 0xA3: - and_a_u8(E); - break; - case 0xA4: - and_a_u8(H); - break; - case 0xA5: - and_a_u8(L); - break; - case 0xA6: - { - unsigned data; - - READ(data, HL()); - - and_a_u8(data); - } - break; - //A&A will always be A: - case 0xA7: - ZF = A; - CF = 0; - HF2 = 0x200; - break; - case 0xA8: - xor_a_u8(B); - break; - case 0xA9: - xor_a_u8(C); - break; - case 0xAA: - xor_a_u8(D); - break; - case 0xAB: - xor_a_u8(E); - break; - case 0xAC: - xor_a_u8(H); - break; - case 0xAD: - xor_a_u8(L); - break; - case 0xAE: - { - unsigned data; - - READ(data, HL()); - - xor_a_u8(data); - } - break; - //A^A will always be 0: - case 0xAF: - CF = HF2 = ZF = A = 0; - break; - case 0xB0: - or_a_u8(B); - break; - case 0xB1: - or_a_u8(C); - break; - case 0xB2: - or_a_u8(D); - break; - case 0xB3: - or_a_u8(E); - break; - case 0xB4: - or_a_u8(H); - break; - case 0xB5: - or_a_u8(L); - break; - case 0xB6: - { - unsigned data; - - READ(data, HL()); - - or_a_u8(data); - } - break; - //A|A will always be A: - case 0xB7: - ZF = A; - HF2 = CF = 0; - break; - case 0xB8: - cp_a_u8(B); - break; - case 0xB9: - cp_a_u8(C); - break; - case 0xBA: - cp_a_u8(D); - break; - case 0xBB: - cp_a_u8(E); - break; - case 0xBC: - cp_a_u8(H); - break; - case 0xBD: - cp_a_u8(L); - break; - case 0xBE: - { - unsigned data; - - READ(data, HL()); - - cp_a_u8(data); - } - break; - //A always equals A: - case 0xBF: - CF = ZF = 0; - HF2 = 0x400; - break; - - //ret nz (20;8 cycles): - //Pop two bytes from the stack and jump to that address, if ZF is unset: - case 0xC0: - cycleCounter += 4; - - if (ZF & 0xFF) { - ret(); - } - break; - - case 0xC1: - pop_rr(B, C); - break; - - //jp nz,nn (16;12 cycles): - //Jump to address stored in next two bytes in memory if ZF is unset: - case 0xC2: - if (ZF & 0xFF) { - jp_nn(); - } else { - PC_MOD((PC + 2) & 0xFFFF); - cycleCounter += 4; - } - break; - - case 0xC3: - jp_nn(); - break; - - //call nz,nn (24;12 cycles): - //Push address of next instruction onto stack and then jump to address stored in next two bytes in memory, if ZF is unset: - case 0xC4: - if (ZF & 0xFF) { - call_nn(); - } else { - PC_MOD((PC + 2) & 0xFFFF); - cycleCounter += 4; - } - break; - - case 0xC5: - push_rr(B, C); - break; - case 0xC6: - { - unsigned data; - - PC_READ(data); - - add_a_u8(data); - } - break; - case 0xC7: - rst_n(0x00); - break; - - //ret z (20;8 cycles): - //Pop two bytes from the stack and jump to that address, if ZF is set: - case 0xC8: - cycleCounter += 4; - - if (!(ZF & 0xFF)) { - ret(); - } - - break; - - //ret (16 cycles): - //Pop two bytes from the stack and jump to that address: - case 0xC9: - ret(); - break; - - //jp z,nn (16;12 cycles): - //Jump to address stored in next two bytes in memory if ZF is set: - case 0xCA: - if (ZF & 0xFF) { - PC_MOD((PC + 2) & 0xFFFF); - cycleCounter += 4; - } else { - jp_nn(); - } - break; - - - //CB OPCODES (Shifts, rotates and bits): - case 0xCB: - PC_READ(opcode); - - switch (opcode) { - case 0x00: - rlc_r(B); - break; - case 0x01: - rlc_r(C); - break; - case 0x02: - rlc_r(D); - break; - case 0x03: - rlc_r(E); - break; - case 0x04: - rlc_r(H); - break; - case 0x05: - rlc_r(L); - break; - //rlc (hl) (16 cycles): - //Rotate 8-bit value stored at address in HL left, store old bit7 in CF. Reset SF and HCF. Check ZF: - case 0x06: - { - const unsigned addr = HL(); - - READ(CF, addr); - CF <<= 1; - - ZF = CF | (CF >> 8); - - WRITE(addr, ZF & 0xFF); - - HF2 = 0; - } - break; - case 0x07: - rlc_r(A); - break; - case 0x08: - rrc_r(B); - break; - case 0x09: - rrc_r(C); - break; - case 0x0A: - rrc_r(D); - break; - case 0x0B: - rrc_r(E); - break; - case 0x0C: - rrc_r(H); - break; - case 0x0D: - rrc_r(L); - break; - //rrc (hl) (16 cycles): - //Rotate 8-bit value stored at address in HL right, store old bit0 in CF. Reset SF and HCF. Check ZF: - case 0x0E: - { - const unsigned addr = HL(); - - READ(ZF, addr); - - CF = ZF << 8; - - WRITE(addr, (ZF | CF) >> 1 & 0xFF); - - HF2 = 0; - } - break; - case 0x0F: - rrc_r(A); - break; - case 0x10: - rl_r(B); - break; - case 0x11: - rl_r(C); - break; - case 0x12: - rl_r(D); - break; - case 0x13: - rl_r(E); - break; - case 0x14: - rl_r(H); - break; - case 0x15: - rl_r(L); - break; - //rl (hl) (16 cycles): - //Rotate 8-bit value stored at address in HL left thorugh CF, store old bit7 in CF, old CF value becoms bit0. Reset SF and HCF. Check ZF: - case 0x16: - { - const unsigned addr = HL(); - const unsigned oldcf = CF >> 8 & 1; - - READ(CF, addr); - CF <<= 1; - - ZF = CF | oldcf; - - WRITE(addr, ZF & 0xFF); - - HF2 = 0; - } - break; - case 0x17: - rl_r(A); - break; - case 0x18: - rr_r(B); - break; - case 0x19: - rr_r(C); - break; - case 0x1A: - rr_r(D); - break; - case 0x1B: - rr_r(E); - break; - case 0x1C: - rr_r(H); - break; - case 0x1D: - rr_r(L); - break; - //rr (hl) (16 cycles): - //Rotate 8-bit value stored at address in HL right thorugh CF, store old bit0 in CF, old CF value becoms bit7. Reset SF and HCF. Check ZF: - case 0x1E: - { - const unsigned addr = HL(); - - READ(ZF, addr); - - const unsigned oldcf = CF & 0x100; - CF = ZF << 8; - ZF = (ZF | oldcf) >> 1; - - WRITE(addr, ZF); - - HF2 = 0; - } - break; - case 0x1F: - rr_r(A); - break; - case 0x20: - sla_r(B); - break; - case 0x21: - sla_r(C); - break; - case 0x22: - sla_r(D); - break; - case 0x23: - sla_r(E); - break; - case 0x24: - sla_r(H); - break; - case 0x25: - sla_r(L); - break; - //sla (hl) (16 cycles): - //Shift 8-bit value stored at address in HL left, store old bit7 in CF. Reset SF and HCF. Check ZF: - case 0x26: - { - const unsigned addr = HL(); - - READ(CF, addr); - CF <<= 1; - - ZF = CF; - - WRITE(addr, ZF & 0xFF); - - HF2 = 0; - } - break; - case 0x27: - sla_r(A); - break; - case 0x28: - sra_r(B); - break; - case 0x29: - sra_r(C); - break; - case 0x2A: - sra_r(D); - break; - case 0x2B: - sra_r(E); - break; - case 0x2C: - sra_r(H); - break; - case 0x2D: - sra_r(L); - break; - //sra (hl) (16 cycles): - //Shift 8-bit value stored at address in HL right, store old bit0 in CF, bit7=old bit7. Reset SF and HCF. Check ZF: - case 0x2E: - { - const unsigned addr = HL(); - - READ(CF, addr); - - ZF = CF >> 1; - - WRITE(addr, ZF | (CF & 0x80)); - - CF <<= 8; - HF2 = 0; - } - break; - case 0x2F: - sra_r(A); - break; - case 0x30: - swap_r(B); - break; - case 0x31: - swap_r(C); - break; - case 0x32: - swap_r(D); - break; - case 0x33: - swap_r(E); - break; - case 0x34: - swap_r(H); - break; - case 0x35: - swap_r(L); - break; - //swap (hl) (16 cycles): - //Swap upper and lower nibbles of 8-bit value stored at address in HL, reset flags, check zero flag: - case 0x36: - { - const unsigned addr = HL(); - - READ(ZF, addr); - - WRITE(addr, (ZF << 4 | ZF >> 4) & 0xFF); - - CF = HF2 = 0; - } - break; - case 0x37: - swap_r(A); - break; - case 0x38: - srl_r(B); - break; - case 0x39: - srl_r(C); - break; - case 0x3A: - srl_r(D); - break; - case 0x3B: - srl_r(E); - break; - case 0x3C: - srl_r(H); - break; - case 0x3D: - srl_r(L); - break; - //srl (hl) (16 cycles): - //Shift 8-bit value stored at address in HL right, store old bit0 in CF. Reset SF and HCF. Check ZF: - case 0x3E: - { - const unsigned addr = HL(); - - READ(CF, addr); - - ZF = CF >> 1; - - WRITE(addr, ZF); - - CF <<= 8; - HF2 = 0; - } - break; - case 0x3F: - srl_r(A); - break; - case 0x40: - bit0_u8(B); - break; - case 0x41: - bit0_u8(C); - break; - case 0x42: - bit0_u8(D); - break; - case 0x43: - bit0_u8(E); - break; - case 0x44: - bit0_u8(H); - break; - case 0x45: - bit0_u8(L); - break; - case 0x46: - { - unsigned data; - - READ(data, HL()); - - bit0_u8(data); - } - break; - case 0x47: - bit0_u8(A); - break; - case 0x48: - bit1_u8(B); - break; - case 0x49: - bit1_u8(C); - break; - case 0x4A: - bit1_u8(D); - break; - case 0x4B: - bit1_u8(E); - break; - case 0x4C: - bit1_u8(H); - break; - case 0x4D: - bit1_u8(L); - break; - case 0x4E: - { - unsigned data; - - READ(data, HL()); - - bit1_u8(data); - } - break; - case 0x4F: - bit1_u8(A); - break; - case 0x50: - bit2_u8(B); - break; - case 0x51: - bit2_u8(C); - break; - case 0x52: - bit2_u8(D); - break; - case 0x53: - bit2_u8(E); - break; - case 0x54: - bit2_u8(H); - break; - case 0x55: - bit2_u8(L); - break; - case 0x56: - { - unsigned data; - - READ(data, HL()); - - bit2_u8(data); - } - break; - case 0x57: - bit2_u8(A); - break; - case 0x58: - bit3_u8(B); - break; - case 0x59: - bit3_u8(C); - break; - case 0x5A: - bit3_u8(D); - break; - case 0x5B: - bit3_u8(E); - break; - case 0x5C: - bit3_u8(H); - break; - case 0x5D: - bit3_u8(L); - break; - case 0x5E: - { - unsigned data; - - READ(data, HL()); - - bit3_u8(data); - } - break; - case 0x5F: - bit3_u8(A); - break; - case 0x60: - bit4_u8(B); - break; - case 0x61: - bit4_u8(C); - break; - case 0x62: - bit4_u8(D); - break; - case 0x63: - bit4_u8(E); - break; - case 0x64: - bit4_u8(H); - break; - case 0x65: - bit4_u8(L); - break; - case 0x66: - { - unsigned data; - - READ(data, HL()); - - bit4_u8(data); - } - break; - case 0x67: - bit4_u8(A); - break; - case 0x68: - bit5_u8(B); - break; - case 0x69: - bit5_u8(C); - break; - case 0x6A: - bit5_u8(D); - break; - case 0x6B: - bit5_u8(E); - break; - case 0x6C: - bit5_u8(H); - break; - case 0x6D: - bit5_u8(L); - break; - case 0x6E: - { - unsigned data; - - READ(data, HL()); - - bit5_u8(data); - } - break; - case 0x6F: - bit5_u8(A); - break; - case 0x70: - bit6_u8(B); - break; - case 0x71: - bit6_u8(C); - break; - case 0x72: - bit6_u8(D); - break; - case 0x73: - bit6_u8(E); - break; - case 0x74: - bit6_u8(H); - break; - case 0x75: - bit6_u8(L); - break; - case 0x76: - { - unsigned data; - - READ(data, HL()); - - bit6_u8(data); - } - break; - case 0x77: - bit6_u8(A); - break; - case 0x78: - bit7_u8(B); - break; - case 0x79: - bit7_u8(C); - break; - case 0x7A: - bit7_u8(D); - break; - case 0x7B: - bit7_u8(E); - break; - case 0x7C: - bit7_u8(H); - break; - case 0x7D: - bit7_u8(L); - break; - case 0x7E: - { - unsigned data; - - READ(data, HL()); - - bit7_u8(data); - } - break; - case 0x7F: - bit7_u8(A); - break; - case 0x80: - res0_r(B); - break; - case 0x81: - res0_r(C); - break; - case 0x82: - res0_r(D); - break; - case 0x83: - res0_r(E); - break; - case 0x84: - res0_r(H); - break; - case 0x85: - res0_r(L); - break; - case 0x86: - resn_mem_hl(0); - break; - case 0x87: - res0_r(A); - break; - case 0x88: - res1_r(B); - break; - case 0x89: - res1_r(C); - break; - case 0x8A: - res1_r(D); - break; - case 0x8B: - res1_r(E); - break; - case 0x8C: - res1_r(H); - break; - case 0x8D: - res1_r(L); - break; - case 0x8E: - resn_mem_hl(1); - break; - case 0x8F: - res1_r(A); - break; - case 0x90: - res2_r(B); - break; - case 0x91: - res2_r(C); - break; - case 0x92: - res2_r(D); - break; - case 0x93: - res2_r(E); - break; - case 0x94: - res2_r(H); - break; - case 0x95: - res2_r(L); - break; - case 0x96: - resn_mem_hl(2); - break; - case 0x97: - res2_r(A); - break; - case 0x98: - res3_r(B); - break; - case 0x99: - res3_r(C); - break; - case 0x9A: - res3_r(D); - break; - case 0x9B: - res3_r(E); - break; - case 0x9C: - res3_r(H); - break; - case 0x9D: - res3_r(L); - break; - case 0x9E: - resn_mem_hl(3); - break; - case 0x9F: - res3_r(A); - break; - case 0xA0: - res4_r(B); - break; - case 0xA1: - res4_r(C); - break; - case 0xA2: - res4_r(D); - break; - case 0xA3: - res4_r(E); - break; - case 0xA4: - res4_r(H); - break; - case 0xA5: - res4_r(L); - break; - case 0xA6: - resn_mem_hl(4); - break; - case 0xA7: - res4_r(A); - break; - case 0xA8: - res5_r(B); - break; - case 0xA9: - res5_r(C); - break; - case 0xAA: - res5_r(D); - break; - case 0xAB: - res5_r(E); - break; - case 0xAC: - res5_r(H); - break; - case 0xAD: - res5_r(L); - break; - case 0xAE: - resn_mem_hl(5); - break; - case 0xAF: - res5_r(A); - break; - case 0xB0: - res6_r(B); - break; - case 0xB1: - res6_r(C); - break; - case 0xB2: - res6_r(D); - break; - case 0xB3: - res6_r(E); - break; - case 0xB4: - res6_r(H); - break; - case 0xB5: - res6_r(L); - break; - case 0xB6: - resn_mem_hl(6); - break; - case 0xB7: - res6_r(A); - break; - case 0xB8: - res7_r(B); - break; - case 0xB9: - res7_r(C); - break; - case 0xBA: - res7_r(D); - break; - case 0xBB: - res7_r(E); - break; - case 0xBC: - res7_r(H); - break; - case 0xBD: - res7_r(L); - break; - case 0xBE: - resn_mem_hl(7); - break; - case 0xBF: - res7_r(A); - break; - case 0xC0: - set0_r(B); - break; - case 0xC1: - set0_r(C); - break; - case 0xC2: - set0_r(D); - break; - case 0xC3: - set0_r(E); - break; - case 0xC4: - set0_r(H); - break; - case 0xC5: - set0_r(L); - break; - case 0xC6: - setn_mem_hl(0); - break; - case 0xC7: - set0_r(A); - break; - case 0xC8: - set1_r(B); - break; - case 0xC9: - set1_r(C); - break; - case 0xCA: - set1_r(D); - break; - case 0xCB: - set1_r(E); - break; - case 0xCC: - set1_r(H); - break; - case 0xCD: - set1_r(L); - break; - case 0xCE: - setn_mem_hl(1); - break; - case 0xCF: - set1_r(A); - break; - case 0xD0: - set2_r(B); - break; - case 0xD1: - set2_r(C); - break; - case 0xD2: - set2_r(D); - break; - case 0xD3: - set2_r(E); - break; - case 0xD4: - set2_r(H); - break; - case 0xD5: - set2_r(L); - break; - case 0xD6: - setn_mem_hl(2); - break; - case 0xD7: - set2_r(A); - break; - case 0xD8: - set3_r(B); - break; - case 0xD9: - set3_r(C); - break; - case 0xDA: - set3_r(D); - break; - case 0xDB: - set3_r(E); - break; - case 0xDC: - set3_r(H); - break; - case 0xDD: - set3_r(L); - break; - case 0xDE: - setn_mem_hl(3); - break; - case 0xDF: - set3_r(A); - break; - case 0xE0: - set4_r(B); - break; - case 0xE1: - set4_r(C); - break; - case 0xE2: - set4_r(D); - break; - case 0xE3: - set4_r(E); - break; - case 0xE4: - set4_r(H); - break; - case 0xE5: - set4_r(L); - break; - case 0xE6: - setn_mem_hl(4); - break; - case 0xE7: - set4_r(A); - break; - case 0xE8: - set5_r(B); - break; - case 0xE9: - set5_r(C); - break; - case 0xEA: - set5_r(D); - break; - case 0xEB: - set5_r(E); - break; - case 0xEC: - set5_r(H); - break; - case 0xED: - set5_r(L); - break; - case 0xEE: - setn_mem_hl(5); - break; - case 0xEF: - set5_r(A); - break; - case 0xF0: - set6_r(B); - break; - case 0xF1: - set6_r(C); - break; - case 0xF2: - set6_r(D); - break; - case 0xF3: - set6_r(E); - break; - case 0xF4: - set6_r(H); - break; - case 0xF5: - set6_r(L); - break; - case 0xF6: - setn_mem_hl(6); - break; - case 0xF7: - set6_r(A); - break; - case 0xF8: - set7_r(B); - break; - case 0xF9: - set7_r(C); - break; - case 0xFA: - set7_r(D); - break; - case 0xFB: - set7_r(E); - break; - case 0xFC: - set7_r(H); - break; - case 0xFD: - set7_r(L); - break; - case 0xFE: - setn_mem_hl(7); - break; - case 0xFF: - set7_r(A); - break; -// default: break; - } - break; - - - //call z,nn (24;12 cycles): - //Push address of next instruction onto stack and then jump to address stored in next two bytes in memory, if ZF is set: - case 0xCC: - if (ZF & 0xFF) { - PC_MOD((PC + 2) & 0xFFFF); - cycleCounter += 4; - } else { - call_nn(); - } - break; - - case 0xCD: - call_nn(); - break; - case 0xCE: - { - unsigned data; - - PC_READ(data); - - adc_a_u8(data); - } - break; - case 0xCF: - rst_n(0x08); - break; - - //ret nc (20;8 cycles): - //Pop two bytes from the stack and jump to that address, if CF is unset: - case 0xD0: - cycleCounter += 4; - - if (!(CF & 0x100)) { - ret(); - } - - break; - - case 0xD1: - pop_rr(D, E); - break; - - //jp nc,nn (16;12 cycles): - //Jump to address stored in next two bytes in memory if CF is unset: - case 0xD2: - if (CF & 0x100) { - PC_MOD((PC + 2) & 0xFFFF); - cycleCounter += 4; - } else { - jp_nn(); - } - break; - - case 0xD3: /*doesn't exist*/ - break; - - //call nc,nn (24;12 cycles): - //Push address of next instruction onto stack and then jump to address stored in next two bytes in memory, if CF is unset: - case 0xD4: - if (CF & 0x100) { - PC_MOD((PC + 2) & 0xFFFF); - cycleCounter += 4; - } else { - call_nn(); - } - break; - - case 0xD5: - push_rr(D, E); - break; - case 0xD6: - { - unsigned data; - - PC_READ(data); - - sub_a_u8(data); - } - break; - case 0xD7: - rst_n(0x10); - break; - - //ret c (20;8 cycles): - //Pop two bytes from the stack and jump to that address, if CF is set: - case 0xD8: - cycleCounter += 4; - - if (CF & 0x100) { - ret(); - } - - break; - - //reti (16 cycles): - //Pop two bytes from the stack and jump to that address, then enable interrupts: - case 0xD9: - { - unsigned l, h; - - pop_rr(h, l); - - memory.ei(cycleCounter); - - PC_MOD(h << 8 | l); - } - break; - - //jp c,nn (16;12 cycles): - //Jump to address stored in next two bytes in memory if CF is set: - case 0xDA: //PC=( ((PC+2)*(1-CarryFlag())) + (((memory.read(PC+1)<<8)+memory.read(PC))*CarryFlag()) ); Cycles(12); break; - if (CF & 0x100) { - jp_nn(); - } else { - PC_MOD((PC + 2) & 0xFFFF); - cycleCounter += 4; - } - break; - - case 0xDB: /*doesn't exist*/ - break; - - //call z,nn (24;12 cycles): - //Push address of next instruction onto stack and then jump to address stored in next two bytes in memory, if CF is set: - case 0xDC: - if (CF & 0x100) { - call_nn(); - } else { - PC_MOD((PC + 2) & 0xFFFF); - cycleCounter += 4; - } - break; - - case 0xDE: - { - unsigned data; - - PC_READ(data); - - sbc_a_u8(data); - } - break; - case 0xDF: - rst_n(0x18); - break; - - //ld ($FF00+n),a (12 cycles): - //Put value in A into address (0xFF00 + next byte in memory): - case 0xE0: - { - unsigned tmp; - - PC_READ(tmp); - - FF_WRITE(0xFF00 | tmp, A); - } - break; - - case 0xE1: - pop_rr(H, L); - break; - - //ld ($FF00+C),a (8 ycles): - //Put A into address (0xFF00 + register C): - case 0xE2: - FF_WRITE(0xFF00 | C, A); - break; - case 0xE3: /*doesn't exist*/ - break; - case 0xE4: /*doesn't exist*/ - break; - case 0xE5: - push_rr(H, L); - break; - case 0xE6: - { - unsigned data; - - PC_READ(data); - - and_a_u8(data); - } - break; - case 0xE7: - rst_n(0x20); - break; - - //add sp,n (16 cycles): - //Add next (signed) byte in memory to SP, reset ZF and SF, check HCF and CF: - case 0xE8: - /*{ - int8_t tmp = int8_t(memory.pc_read(PC++, cycleCounter)); - HF2 = (((SP & 0xFFF) + tmp) >> 3) & 0x200; - CF = SP + tmp; - SP = CF; - CF >>= 8; - ZF = 1; - cycleCounter += 12; - }*/ - sp_plus_n(SP); - cycleCounter += 4; - break; - - //jp hl (4 cycles): - //Jump to address in hl: - case 0xE9: - PC = HL(); - break; - - //ld (nn),a (16 cycles): - //set memory at address given by the next 2 bytes to value in A: - //Incrementing PC before call, because of possible interrupt. - case 0xEA: - { - unsigned l, h; - - PC_READ(l); - PC_READ(h); - - WRITE(h << 8 | l, A); - } - break; - - case 0xEB: /*doesn't exist*/ - break; - case 0xEC: /*doesn't exist*/ - break; - case 0xED: /*doesn't exist*/ - break; - case 0xEE: - { - unsigned data; - - PC_READ(data); - - xor_a_u8(data); - } - break; - case 0xEF: - rst_n(0x28); - break; - - //ld a,($FF00+n) (12 cycles): - //Put value at address (0xFF00 + next byte in memory) into A: - case 0xF0: - { - unsigned tmp; - - PC_READ(tmp); - - FF_READ(A, 0xFF00 | tmp); - } - break; - - case 0xF1: /*pop_rr(A, F); Cycles(12); break;*/ - { - unsigned F; - - pop_rr(A, F); - - FROM_F(F); - } - break; - - //ld a,($FF00+C) (8 cycles): - //Put value at address (0xFF00 + register C) into A: - case 0xF2: - FF_READ(A, 0xFF00 | C); - break; - - //di (4 cycles): - case 0xF3: - memory.di(); - break; - - case 0xF4: /*doesn't exist*/ - break; - case 0xF5: /*push_rr(A, F); Cycles(16); break;*/ - calcHF(HF1, HF2); - - { - unsigned F = F(); - - push_rr(A, F); - } - break; - - case 0xF6: - { - unsigned data; - - PC_READ(data); - - or_a_u8(data); - } - break; - case 0xF7: - rst_n(0x30); - break; - - //ldhl sp,n (12 cycles): - //Put (sp+next (signed) byte in memory) into hl (unsets ZF and SF, may enable HF and CF): - case 0xF8: - /*{ - int8_t tmp = int8_t(memory.pc_read(PC++, cycleCounter)); - HF2 = (((SP & 0xFFF) + tmp) >> 3) & 0x200; - CF = SP + tmp; - L = CF; - CF >>= 8; - H = CF; - ZF = 1; - cycleCounter += 8; - }*/ - { - unsigned sum; - sp_plus_n(sum); - L = sum & 0xFF; - H = sum >> 8; - } - break; - - //ld sp,hl (8 cycles): - //Put value in HL into SP - case 0xF9: - SP = HL(); - cycleCounter += 4; - break; - - //ld a,(nn) (16 cycles): - //set A to value in memory at address given by the 2 next bytes. - case 0xFA: - { - unsigned l, h; - - PC_READ(l); - PC_READ(h); - - READ(A, h << 8 | l); - } - break; - - //ei (4 cycles): - //Enable Interrupts after next instruction: - case 0xFB: - memory.ei(cycleCounter); - break; - - case 0xFC: /*doesn't exist*/ - break; - case 0xFD: /*doesn't exist*/ - break; - case 0xFE: - { - unsigned data; - - PC_READ(data); - - cp_a_u8(data); - } - break; - case 0xFF: - rst_n(0x38); - break; -// default: break; - } - } - - PC_ = PC; - cycleCounter = memory.event(cycleCounter); - } - - A_ = A; - cycleCounter_ = cycleCounter; -} diff --git a/supergameboy/libgambatte/src/cpu.h b/supergameboy/libgambatte/src/cpu.h deleted file mode 100644 index 300ba5fb..00000000 --- a/supergameboy/libgambatte/src/cpu.h +++ /dev/null @@ -1,115 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aam�s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef CPU_H -#define CPU_H - -class SaveState; - -#include "int.h" -#include "memory.h" - -class CPU { - Memory memory; - - unsigned long cycleCounter_; - - unsigned short PC_; - unsigned short SP; - - unsigned HF1, HF2, ZF, CF; - - unsigned char A_, B, C, D, E, /*F,*/ H, L; - - bool skip; - bool halted; - - void process(unsigned long cycles); - -public: - - CPU(); -// void halt(); - -// unsigned interrupt(unsigned address, unsigned cycleCounter); - - void updateVideo() { memory.updateVideo(cycleCounter_); } - unsigned lyCounter() { return memory.lyCounter(cycleCounter_); } - void setAccumulator(unsigned char value) { A_ = value; } - - void runFor(unsigned long cycles); - void setStatePtrs(SaveState &state); - void saveState(SaveState &state); - void loadState(const SaveState &state); - - void loadSavedata() { memory.loadSavedata(); } - void saveSavedata() { memory.saveSavedata(); } - - void setVideoBlitter(Gambatte::VideoBlitter *vb) { - memory.setVideoBlitter(vb); - } - - void videoBufferChange() { - memory.videoBufferChange(); - } - - unsigned int videoWidth() const { - return memory.videoWidth(); - } - - unsigned int videoHeight() const { - return memory.videoHeight(); - } - - void setVideoFilter(const unsigned int n) { - memory.setVideoFilter(n); - } - - std::vector filterInfo() const { - return memory.filterInfo(); - } - - void setInputStateGetter(Gambatte::InputStateGetter *getInput) { - memory.setInputStateGetter(getInput); - } - - void set_savedir(const char *sdir) { - memory.set_savedir(sdir); - } - - const std::string saveBasePath() const { - return memory.saveBasePath(); - } - - void setOsdElement(std::auto_ptr osdElement) { - memory.setOsdElement(osdElement); - } - - bool load(bool forceDmg); - - void setSoundBuffer(Gambatte::uint_least32_t *const buf) { memory.setSoundBuffer(buf); } - unsigned fillSoundBuffer() { return memory.fillSoundBuffer(cycleCounter_); } - - bool isCgb() const { return memory.isCgb(); } - - void setDmgPaletteColor(unsigned palNum, unsigned colorNum, unsigned rgb32) { - memory.setDmgPaletteColor(palNum, colorNum, rgb32); - } -}; - -#endif diff --git a/supergameboy/libgambatte/src/event_queue.h b/supergameboy/libgambatte/src/event_queue.h deleted file mode 100644 index 94fbebcf..00000000 --- a/supergameboy/libgambatte/src/event_queue.h +++ /dev/null @@ -1,160 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * -***************************************************************************/ -#ifndef EVENT_QUEUE_H -#define EVENT_QUEUE_H - -#include - -template -class event_queue { - Comparer comparer; - T *const a; - const std::size_t capacity_; - std::size_t size_; - - - std::size_t indexOf(T e); - void internalDec(std::size_t i, T e); - template void internalInc(std::size_t i, T e); - -public: - event_queue(std::size_t capacity, const Comparer &comparer); - ~event_queue(); - - std::size_t capacity() const { - return capacity_; - } - - void clear() { - size_ = 0; - } - - void dec(const T oldE, const T newE) { - internalDec(indexOf(oldE), newE); - } - - bool empty() const { - return size_ == 0; - } - - void inc(const T oldE, const T newE) { - internalInc(indexOf(oldE), newE); - } - - void modify_root(const T newRoot) { - internalInc(0, newRoot); - } - - void pop() { - internalInc(0, a[--size_]); - } - - void push(const T e) { - internalDec(size_++, e); - } - - void remove(T e); - - std::size_t size() const { - return size_; - } - - T top() const { - return a[0]; - } -}; - -template -event_queue::event_queue(const std::size_t capacity, const Comparer &comparer_in) : - comparer(comparer_in), - a(new T[capacity]), - capacity_(capacity), - size_(0) -{} - -template -event_queue::~event_queue() { - delete[] a; -} - -template -std::size_t event_queue::indexOf(const T e) { - std::size_t i = 0; - - while (a[i] != e) - ++i; - - return i; -} - -template -void event_queue::internalDec(std::size_t i, const T e) { - a[i] = e; - - while (i != 0) { - const std::size_t parentI = (i - 1) >> 1; - - if (!comparer.less(e, a[parentI])) - break; - - a[i] = a[parentI]; - a[parentI] = e; - i = parentI; - } -} - -template -template -void event_queue::internalInc(std::size_t i, const T e) { - a[i] = e; - - for (;;) { - std::size_t childI = i * 2 + 1; - - if (childI >= size_) - break; - - if ((!child2BoundsCheck || childI + 1 < size_) && comparer.less(a[childI + 1], a[childI])) - ++childI; - - if (!comparer.less(a[childI], e)) - break; - - a[i] = a[childI]; - a[childI] = e; - i = childI; - } -} - -template -void event_queue::remove(const T e) { - std::size_t i = indexOf(e); - - while (i != 0) { - const std::size_t parentI = (i - 1) >> 1; - - a[i] = a[parentI]; - a[parentI] = e; - i = parentI; - } - - pop(); -} - -#endif diff --git a/supergameboy/libgambatte/src/file/file.cpp b/supergameboy/libgambatte/src/file/file.cpp deleted file mode 100644 index 7a8f9966..00000000 --- a/supergameboy/libgambatte/src/file/file.cpp +++ /dev/null @@ -1,73 +0,0 @@ -/*************************************************************************** -Copyright (C) 2007 by Nach -http://nsrt.edgeemu.com - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License version 2 as -published by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License version 2 for more details. - -You should have received a copy of the GNU General Public License -version 2 along with this program; if not, write to the -Free Software Foundation, Inc., -59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -***************************************************************************/ - -#include "file.h" - -using namespace std; - -static const unsigned int MAX_FILE_NAME = 512; - -File::File(const char *filename) : stream(filename, ios::in | ios::binary), is_zip(false), fsize(0), count(0) -{ - if (stream) - { - stream.seekg(0, ios::end); - fsize = stream.tellg(); - stream.seekg(0, ios::beg); - } -} - -File::~File() -{ - close(); -} - -void File::rewind() -{ - if (is_open()) - { - stream.seekg(0, ios::beg); - } -} - -bool File::is_open() -{ - return(stream.is_open()); -} - -void File::close() -{ - if (is_open()) - { - stream.close(); - } -} - -void File::read(char *buffer, size_t amount) -{ - if (is_open()) - { - stream.read(buffer, amount); - count = stream.gcount(); - } - else - { - count = 0; - } -} diff --git a/supergameboy/libgambatte/src/file/file.h b/supergameboy/libgambatte/src/file/file.h deleted file mode 100644 index 3435ef16..00000000 --- a/supergameboy/libgambatte/src/file/file.h +++ /dev/null @@ -1,42 +0,0 @@ -/*************************************************************************** -Copyright (C) 2007 by Nach -http://nsrt.edgeemu.com - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License version 2 as -published by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License version 2 for more details. - -You should have received a copy of the GNU General Public License -version 2 along with this program; if not, write to the -Free Software Foundation, Inc., -59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -***************************************************************************/ - -#include - -class File { - private: - std::ifstream stream; - bool is_zip; //Change this to an enum later - std::size_t fsize, count; - void *zipfile; - bool zip_sub_open; - - void zip(const char *filename); - - public: - File(const char *filename); - ~File(); - void rewind(); - bool is_open(); - void close(); - std::size_t size() const { return fsize; }; - void read(char *buffer, std::size_t amount); - std::size_t gcount() const { return count; } - bool fail() const { return stream.fail(); } -}; diff --git a/supergameboy/libgambatte/src/file/file_zip.cpp b/supergameboy/libgambatte/src/file/file_zip.cpp deleted file mode 100644 index c7fae6db..00000000 --- a/supergameboy/libgambatte/src/file/file_zip.cpp +++ /dev/null @@ -1,167 +0,0 @@ -/*************************************************************************** -Copyright (C) 2007 by Nach -http://nsrt.edgeemu.com - -This program is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License version 2 as -published by the Free Software Foundation. - -This program is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU General Public License version 2 for more details. - -You should have received a copy of the GNU General Public License -version 2 along with this program; if not, write to the -Free Software Foundation, Inc., -59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -***************************************************************************/ - -#include "file.h" - -#include - -namespace zlib { -#include "unzip/unzip.h" -} - -using namespace std; -using namespace zlib; - -static const unsigned int MAX_FILE_NAME = 512; - -File::File(const char *filename) : stream(filename, ios::in | ios::binary), is_zip(false), fsize(0), count(0) -{ - if (stream) - { - char temp[4]; - stream.read(temp, sizeof(temp)); - - //check for standard zip 'magic number' - if ((temp[0] == 'P') && (temp[1] == 'K') && (temp[2] == 3) && (temp[3] == 4)) - { - stream.close(); - is_zip = true; - zip(filename); - } - else - { - stream.seekg(0, ios::end); - fsize = stream.tellg(); - stream.seekg(0, ios::beg); - } - } -} - -void File::zip(const char *filename) -{ - zipfile = unzOpen(filename); - if (zipfile) - { - zip_sub_open = false; - - unz_file_info cFileInfo; - char ourFile[MAX_FILE_NAME] = { '\n' }; - - for (int cFile = unzGoToFirstFile((unzFile)zipfile); cFile == UNZ_OK; cFile = unzGoToNextFile((unzFile)zipfile)) - { - //Temporary char array for file name - char cFileName[MAX_FILE_NAME]; - - //Gets info on current file, and places it in cFileInfo - unzGetCurrentFileInfo((unzFile)zipfile, &cFileInfo, cFileName, MAX_FILE_NAME, 0, 0, 0, 0); - - //Check for largest file which should be the ROM - if ((size_t)cFileInfo.uncompressed_size > fsize) - { - strcpy(ourFile, cFileName); - fsize = (size_t)cFileInfo.uncompressed_size; - } - } - - if (ourFile[0] != '\n') - { - //Sets current file to the file we liked before - unzLocateFile((unzFile)zipfile, ourFile, 1); - - if (unzOpenCurrentFile((unzFile)zipfile) == UNZ_OK) - { - zip_sub_open = true; - } - } - - if (!zip_sub_open) - { - unzClose((unzFile)zipfile); - zipfile = 0; - } - } -} - -File::~File() -{ - close(); -} - -void File::rewind() -{ - if (is_open()) - { - if (!is_zip) - { - stream.seekg(0, ios::beg); - } - else - { - unzCloseCurrentFile((unzFile)zipfile); - unzOpenCurrentFile((unzFile)zipfile); - } - } -} - -bool File::is_open() -{ - if (!is_zip) - { - return(stream.is_open()); - } - return(zipfile && zip_sub_open); -} - -void File::close() -{ - if (is_open()) - { - if (!is_zip) - { - stream.close(); - } - else - { - unzOpenCurrentFile((unzFile)zipfile); - unzClose((unzFile)zipfile); - zipfile = 0; - zip_sub_open = false; - } - } -} - -void File::read(char *buffer, size_t amount) -{ - if (is_open()) - { - if (!is_zip) - { - stream.read(buffer, amount); - count = stream.gcount(); - } - else - { - count = (size_t)unzReadCurrentFile((unzFile)zipfile, buffer, amount); - } - } - else - { - count = 0; - } -} diff --git a/supergameboy/libgambatte/src/file/unzip/crypt.h b/supergameboy/libgambatte/src/file/unzip/crypt.h deleted file mode 100644 index 622f4bc2..00000000 --- a/supergameboy/libgambatte/src/file/unzip/crypt.h +++ /dev/null @@ -1,132 +0,0 @@ -/* crypt.h -- base code for crypt/uncrypt ZIPfile - - - Version 1.01e, February 12th, 2005 - - Copyright (C) 1998-2005 Gilles Vollant - - This code is a modified version of crypting code in Infozip distribution - - The encryption/decryption parts of this source code (as opposed to the - non-echoing password parts) were originally written in Europe. The - whole source package can be freely distributed, including from the USA. - (Prior to January 2000, re-export from the US was a violation of US law.) - - This encryption code is a direct transcription of the algorithm from - Roger Schlafly, described by Phil Katz in the file appnote.txt. This - file (appnote.txt) is distributed with the PKZIP program (even in the - version without encryption capabilities). - - If you don't need crypting in your application, just define symbols - NOCRYPT and NOUNCRYPT. - - This code support the "Traditional PKWARE Encryption". - - The new AES encryption added on Zip format by Winzip (see the page - http://www.winzip.com/aes_info.htm ) and PKWare PKZip 5.x Strong - Encryption is not supported. -*/ - -#define CRC32(c, b) ((*(pcrc_32_tab+(((int)(c) ^ (b)) & 0xff))) ^ ((c) >> 8)) - -/*********************************************************************** - * Return the next byte in the pseudo-random sequence - */ -static int decrypt_byte(unsigned long* pkeys, const unsigned long* pcrc_32_tab) -{ - unsigned temp; /* POTENTIAL BUG: temp*(temp^1) may overflow in an - * unpredictable manner on 16-bit systems; not a problem - * with any known compiler so far, though */ - - temp = ((unsigned)(*(pkeys+2)) & 0xffff) | 2; - return (int)(((temp * (temp ^ 1)) >> 8) & 0xff); -} - -/*********************************************************************** - * Update the encryption keys with the next byte of plain text - */ -static int update_keys(unsigned long* pkeys,const unsigned long* pcrc_32_tab,int c) -{ - (*(pkeys+0)) = CRC32((*(pkeys+0)), c); - (*(pkeys+1)) += (*(pkeys+0)) & 0xff; - (*(pkeys+1)) = (*(pkeys+1)) * 134775813L + 1; - { - register int keyshift = (int)((*(pkeys+1)) >> 24); - (*(pkeys+2)) = CRC32((*(pkeys+2)), keyshift); - } - return c; -} - - -/*********************************************************************** - * Initialize the encryption keys and the random header according to - * the given password. - */ -static void init_keys(const char* passwd,unsigned long* pkeys,const unsigned long* pcrc_32_tab) -{ - *(pkeys+0) = 305419896L; - *(pkeys+1) = 591751049L; - *(pkeys+2) = 878082192L; - while (*passwd != '\0') { - update_keys(pkeys,pcrc_32_tab,(int)*passwd); - passwd++; - } -} - -#define zdecode(pkeys,pcrc_32_tab,c) \ - (update_keys(pkeys,pcrc_32_tab,c ^= decrypt_byte(pkeys,pcrc_32_tab))) - -#define zencode(pkeys,pcrc_32_tab,c,t) \ - (t=decrypt_byte(pkeys,pcrc_32_tab), update_keys(pkeys,pcrc_32_tab,c), t^(c)) - -#ifdef INCLUDECRYPTINGCODE_IFCRYPTALLOWED - -#define RAND_HEAD_LEN 12 - /* "last resort" source for second part of crypt seed pattern */ -# ifndef ZCR_SEED2 -# define ZCR_SEED2 3141592654UL /* use PI as default pattern */ -# endif - -static int crypthead(passwd, buf, bufSize, pkeys, pcrc_32_tab, crcForCrypting) - const char *passwd; /* password string */ - unsigned char *buf; /* where to write header */ - int bufSize; - unsigned long* pkeys; - const unsigned long* pcrc_32_tab; - unsigned long crcForCrypting; -{ - int n; /* index in random header */ - int t; /* temporary */ - int c; /* random byte */ - unsigned char header[RAND_HEAD_LEN-2]; /* random header */ - static unsigned calls = 0; /* ensure different random header each time */ - - if (bufSize> 7) & 0xff; - header[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, c, t); - } - /* Encrypt random header (last two bytes is high word of crc) */ - init_keys(passwd, pkeys, pcrc_32_tab); - for (n = 0; n < RAND_HEAD_LEN-2; n++) - { - buf[n] = (unsigned char)zencode(pkeys, pcrc_32_tab, header[n], t); - } - buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 16) & 0xff, t); - buf[n++] = zencode(pkeys, pcrc_32_tab, (int)(crcForCrypting >> 24) & 0xff, t); - return n; -} - -#endif diff --git a/supergameboy/libgambatte/src/file/unzip/ioapi.c b/supergameboy/libgambatte/src/file/unzip/ioapi.c deleted file mode 100644 index 05b5ef15..00000000 --- a/supergameboy/libgambatte/src/file/unzip/ioapi.c +++ /dev/null @@ -1,177 +0,0 @@ -/* ioapi.c -- IO base function header for compress/uncompress .zip - files using zlib + zip or unzip API - - Version 1.01e, February 12th, 2005 - - Copyright (C) 1998-2005 Gilles Vollant -*/ - -#include -#include -#include - -#include -#include "ioapi.h" - - - -/* 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 - -voidpf ZCALLBACK fopen_file_func OF(( - voidpf opaque, - const char* filename, - int mode)); - -uLong ZCALLBACK fread_file_func OF(( - voidpf opaque, - voidpf stream, - void* buf, - uLong size)); - -uLong ZCALLBACK fwrite_file_func OF(( - voidpf opaque, - voidpf stream, - const void* buf, - uLong size)); - -long ZCALLBACK ftell_file_func OF(( - voidpf opaque, - voidpf stream)); - -long ZCALLBACK fseek_file_func OF(( - voidpf opaque, - voidpf stream, - uLong offset, - int origin)); - -int ZCALLBACK fclose_file_func OF(( - voidpf opaque, - voidpf stream)); - -int ZCALLBACK ferror_file_func OF(( - voidpf opaque, - voidpf stream)); - - -voidpf ZCALLBACK fopen_file_func (opaque, filename, mode) - voidpf opaque; - const char* filename; - int mode; -{ - FILE* file = NULL; - const char* mode_fopen = NULL; - if ((mode & ZLIB_FILEFUNC_MODE_READWRITEFILTER)==ZLIB_FILEFUNC_MODE_READ) - mode_fopen = "rb"; - else - if (mode & ZLIB_FILEFUNC_MODE_EXISTING) - mode_fopen = "r+b"; - else - if (mode & ZLIB_FILEFUNC_MODE_CREATE) - mode_fopen = "wb"; - - if ((filename!=NULL) && (mode_fopen != NULL)) - file = fopen(filename, mode_fopen); - return file; -} - - -uLong ZCALLBACK fread_file_func (opaque, stream, buf, size) - voidpf opaque; - voidpf stream; - void* buf; - uLong size; -{ - uLong ret; - ret = (uLong)fread(buf, 1, (size_t)size, (FILE *)stream); - return ret; -} - - -uLong ZCALLBACK fwrite_file_func (opaque, stream, buf, size) - voidpf opaque; - voidpf stream; - const void* buf; - uLong size; -{ - uLong ret; - ret = (uLong)fwrite(buf, 1, (size_t)size, (FILE *)stream); - return ret; -} - -long ZCALLBACK ftell_file_func (opaque, stream) - voidpf opaque; - voidpf stream; -{ - long ret; - ret = ftell((FILE *)stream); - return ret; -} - -long ZCALLBACK fseek_file_func (opaque, stream, offset, origin) - voidpf opaque; - voidpf stream; - uLong offset; - int origin; -{ - int fseek_origin=0; - long ret; - switch (origin) - { - case ZLIB_FILEFUNC_SEEK_CUR : - fseek_origin = SEEK_CUR; - break; - case ZLIB_FILEFUNC_SEEK_END : - fseek_origin = SEEK_END; - break; - case ZLIB_FILEFUNC_SEEK_SET : - fseek_origin = SEEK_SET; - break; - default: return -1; - } - ret = 0; - fseek((FILE *)stream, offset, fseek_origin); - return ret; -} - -int ZCALLBACK fclose_file_func (opaque, stream) - voidpf opaque; - voidpf stream; -{ - int ret; - ret = fclose((FILE *)stream); - return ret; -} - -int ZCALLBACK ferror_file_func (opaque, stream) - voidpf opaque; - voidpf stream; -{ - int ret; - ret = ferror((FILE *)stream); - return ret; -} - -void fill_fopen_filefunc (pzlib_filefunc_def) - zlib_filefunc_def* pzlib_filefunc_def; -{ - pzlib_filefunc_def->zopen_file = fopen_file_func; - pzlib_filefunc_def->zread_file = fread_file_func; - pzlib_filefunc_def->zwrite_file = fwrite_file_func; - pzlib_filefunc_def->ztell_file = ftell_file_func; - pzlib_filefunc_def->zseek_file = fseek_file_func; - pzlib_filefunc_def->zclose_file = fclose_file_func; - pzlib_filefunc_def->zerror_file = ferror_file_func; - pzlib_filefunc_def->opaque = NULL; -} diff --git a/supergameboy/libgambatte/src/file/unzip/ioapi.h b/supergameboy/libgambatte/src/file/unzip/ioapi.h deleted file mode 100644 index 7d457baa..00000000 --- a/supergameboy/libgambatte/src/file/unzip/ioapi.h +++ /dev/null @@ -1,75 +0,0 @@ -/* ioapi.h -- IO base function header for compress/uncompress .zip - files using zlib + zip or unzip API - - Version 1.01e, February 12th, 2005 - - Copyright (C) 1998-2005 Gilles Vollant -*/ - -#ifndef _ZLIBIOAPI_H -#define _ZLIBIOAPI_H - - -#define ZLIB_FILEFUNC_SEEK_CUR (1) -#define ZLIB_FILEFUNC_SEEK_END (2) -#define ZLIB_FILEFUNC_SEEK_SET (0) - -#define ZLIB_FILEFUNC_MODE_READ (1) -#define ZLIB_FILEFUNC_MODE_WRITE (2) -#define ZLIB_FILEFUNC_MODE_READWRITEFILTER (3) - -#define ZLIB_FILEFUNC_MODE_EXISTING (4) -#define ZLIB_FILEFUNC_MODE_CREATE (8) - - -#ifndef ZCALLBACK - -#if (defined(WIN32) || defined (WINDOWS) || defined (_WINDOWS)) && defined(CALLBACK) && defined (USEWINDOWS_CALLBACK) -#define ZCALLBACK CALLBACK -#else -#define ZCALLBACK -#endif -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -typedef voidpf (ZCALLBACK *open_file_func) OF((voidpf opaque, const char* filename, int mode)); -typedef uLong (ZCALLBACK *read_file_func) OF((voidpf opaque, voidpf stream, void* buf, uLong size)); -typedef uLong (ZCALLBACK *write_file_func) OF((voidpf opaque, voidpf stream, const void* buf, uLong size)); -typedef long (ZCALLBACK *tell_file_func) OF((voidpf opaque, voidpf stream)); -typedef long (ZCALLBACK *seek_file_func) OF((voidpf opaque, voidpf stream, uLong offset, int origin)); -typedef int (ZCALLBACK *close_file_func) OF((voidpf opaque, voidpf stream)); -typedef int (ZCALLBACK *testerror_file_func) OF((voidpf opaque, voidpf stream)); - -typedef struct zlib_filefunc_def_s -{ - open_file_func zopen_file; - read_file_func zread_file; - write_file_func zwrite_file; - tell_file_func ztell_file; - seek_file_func zseek_file; - close_file_func zclose_file; - testerror_file_func zerror_file; - voidpf opaque; -} zlib_filefunc_def; - - - -void fill_fopen_filefunc OF((zlib_filefunc_def* pzlib_filefunc_def)); - -#define ZREAD(filefunc,filestream,buf,size) ((*((filefunc).zread_file))((filefunc).opaque,filestream,buf,size)) -#define ZWRITE(filefunc,filestream,buf,size) ((*((filefunc).zwrite_file))((filefunc).opaque,filestream,buf,size)) -#define ZTELL(filefunc,filestream) ((*((filefunc).ztell_file))((filefunc).opaque,filestream)) -#define ZSEEK(filefunc,filestream,pos,mode) ((*((filefunc).zseek_file))((filefunc).opaque,filestream,pos,mode)) -#define ZCLOSE(filefunc,filestream) ((*((filefunc).zclose_file))((filefunc).opaque,filestream)) -#define ZERROR(filefunc,filestream) ((*((filefunc).zerror_file))((filefunc).opaque,filestream)) - - -#ifdef __cplusplus -} -#endif - -#endif - diff --git a/supergameboy/libgambatte/src/file/unzip/unzip.c b/supergameboy/libgambatte/src/file/unzip/unzip.c deleted file mode 100644 index 325f3d08..00000000 --- a/supergameboy/libgambatte/src/file/unzip/unzip.c +++ /dev/null @@ -1,1605 +0,0 @@ -/* unzip.c -- IO for uncompress .zip files using zlib - Version 1.01e, February 12th, 2005 - - Copyright (C) 1998-2005 Gilles Vollant - - Read unzip.h for more info -*/ - -/* Decryption code comes from crypt.c by Info-ZIP but has been greatly reduced in terms of -compatibility with older software. The following is from the original crypt.c. Code -woven in by Terry Thorsen 1/2003. -*/ -/* - Copyright (c) 1990-2000 Info-ZIP. All rights reserved. - - See the accompanying file LICENSE, version 2000-Apr-09 or later - (the contents of which are also included in zip.h) for terms of use. - If, for some reason, all these files are missing, the Info-ZIP license - also may be found at: ftp://ftp.info-zip.org/pub/infozip/license.html -*/ -/* - crypt.c (full version) by Info-ZIP. Last revised: [see crypt.h] - - The encryption/decryption parts of this source code (as opposed to the - non-echoing password parts) were originally written in Europe. The - whole source package can be freely distributed, including from the USA. - (Prior to January 2000, re-export from the US was a violation of US law.) - */ - -/* - This encryption code is a direct transcription of the algorithm from - Roger Schlafly, described by Phil Katz in the file appnote.txt. This - file (appnote.txt) is distributed with the PKZIP program (even in the - version without encryption capabilities). - */ - - -#include -#include -#include -#include -#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 */ - - -#ifndef CASESENSITIVITYDEFAULT_NO -# if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) -# define CASESENSITIVITYDEFAULT_NO -# endif -#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) - - - - -const char unz_copyright[] = - " unzip 1.01 Copyright 1998-2004 Gilles Vollant - http://www.winimage.com/zLibDll"; - -/* 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*/ - zlib_filefunc_def z_filefunc; - voidpf filestream; /* io structore of the zipfile */ - uLong compression_method; /* compression method (0==store) */ - uLong byte_before_the_zipfile;/* byte before the zipfile, (>0 for sfx)*/ - int raw; -} file_in_zip_read_info_s; - - -/* unz_s contain internal information about the zipfile -*/ -typedef struct -{ - zlib_filefunc_def z_filefunc; - voidpf filestream; /* 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 */ - int encrypted; -# ifndef NOUNCRYPT - unsigned long keys[3]; /* keys defining the pseudo-random sequence */ - const unsigned long* pcrc_32_tab; -# endif -} unz_s; - - -#ifndef NOUNCRYPT -#include "crypt.h" -#endif - -/* =========================================================================== - 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 OF(( - const zlib_filefunc_def* pzlib_filefunc_def, - voidpf filestream, - int *pi)); - -local int unzlocal_getByte(pzlib_filefunc_def,filestream,pi) - const zlib_filefunc_def* pzlib_filefunc_def; - voidpf filestream; - int *pi; -{ - unsigned char c; - int err = (int)ZREAD(*pzlib_filefunc_def,filestream,&c,1); - if (err==1) - { - *pi = (int)c; - return UNZ_OK; - } - else - { - if (ZERROR(*pzlib_filefunc_def,filestream)) - return UNZ_ERRNO; - else - return UNZ_EOF; - } -} - - -/* =========================================================================== - Reads a long in LSB order from the given gz_stream. Sets -*/ -local int unzlocal_getShort OF(( - const zlib_filefunc_def* pzlib_filefunc_def, - voidpf filestream, - uLong *pX)); - -local int unzlocal_getShort (pzlib_filefunc_def,filestream,pX) - const zlib_filefunc_def* pzlib_filefunc_def; - voidpf filestream; - uLong *pX; -{ - uLong x ; - int i = 0; - int err; - - err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); - x = (uLong)i; - - if (err==UNZ_OK) - err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); - x += ((uLong)i)<<8; - - if (err==UNZ_OK) - *pX = x; - else - *pX = 0; - return err; -} - -local int unzlocal_getLong OF(( - const zlib_filefunc_def* pzlib_filefunc_def, - voidpf filestream, - uLong *pX)); - -local int unzlocal_getLong (pzlib_filefunc_def,filestream,pX) - const zlib_filefunc_def* pzlib_filefunc_def; - voidpf filestream; - uLong *pX; -{ - uLong x ; - int i = 0; - int err; - - err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); - x = (uLong)i; - - if (err==UNZ_OK) - err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); - x += ((uLong)i)<<8; - - if (err==UNZ_OK) - err = unzlocal_getByte(pzlib_filefunc_def,filestream,&i); - x += ((uLong)i)<<16; - - if (err==UNZ_OK) - err = unzlocal_getByte(pzlib_filefunc_def,filestream,&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); -} - -#ifndef BUFREADCOMMENT -#define BUFREADCOMMENT (0x400) -#endif - -/* - Locate the Central directory of a zipfile (at the end, just before - the global comment) -*/ -local uLong unzlocal_SearchCentralDir OF(( - const zlib_filefunc_def* pzlib_filefunc_def, - voidpf filestream)); - -local uLong unzlocal_SearchCentralDir(pzlib_filefunc_def,filestream) - const zlib_filefunc_def* pzlib_filefunc_def; - voidpf filestream; -{ - unsigned char* buf; - uLong uSizeFile; - uLong uBackRead; - uLong uMaxBack=0xffff; /* maximum size of global comment */ - uLong uPosFound=0; - - if (ZSEEK(*pzlib_filefunc_def,filestream,0,ZLIB_FILEFUNC_SEEK_END) != 0) - return 0; - - - uSizeFile = ZTELL(*pzlib_filefunc_def,filestream); - - 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 (ZSEEK(*pzlib_filefunc_def,filestream,uReadPos,ZLIB_FILEFUNC_SEEK_SET)!=0) - break; - - if (ZREAD(*pzlib_filefunc_def,filestream,buf,uReadSize)!=uReadSize) - 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\\zlib114.zip" or on an Unix computer - "zlib/zlib114.zip". - If the zipfile cannot be opened (file doesn'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 unzOpen2 (path, pzlib_filefunc_def) - const char *path; - zlib_filefunc_def* pzlib_filefunc_def; -{ - unz_s us; - unz_s *s; - uLong central_pos,uL; - - 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; - - if (pzlib_filefunc_def==NULL) - fill_fopen_filefunc(&us.z_filefunc); - else - us.z_filefunc = *pzlib_filefunc_def; - - us.filestream= (*(us.z_filefunc.zopen_file))(us.z_filefunc.opaque, - path, - ZLIB_FILEFUNC_MODE_READ | - ZLIB_FILEFUNC_MODE_EXISTING); - if (us.filestream==NULL) - return NULL; - - central_pos = unzlocal_SearchCentralDir(&us.z_filefunc,us.filestream); - if (central_pos==0) - err=UNZ_ERRNO; - - if (ZSEEK(us.z_filefunc, us.filestream, - central_pos,ZLIB_FILEFUNC_SEEK_SET)!=0) - err=UNZ_ERRNO; - - /* the signature, already checked */ - if (unzlocal_getLong(&us.z_filefunc, us.filestream,&uL)!=UNZ_OK) - err=UNZ_ERRNO; - - /* number of this disk */ - if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk)!=UNZ_OK) - err=UNZ_ERRNO; - - /* number of the disk with the start of the central directory */ - if (unzlocal_getShort(&us.z_filefunc, us.filestream,&number_disk_with_CD)!=UNZ_OK) - err=UNZ_ERRNO; - - /* total number of entries in the central dir on this disk */ - if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.number_entry)!=UNZ_OK) - err=UNZ_ERRNO; - - /* total number of entries in the central dir */ - if (unzlocal_getShort(&us.z_filefunc, us.filestream,&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(&us.z_filefunc, us.filestream,&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(&us.z_filefunc, us.filestream,&us.offset_central_dir)!=UNZ_OK) - err=UNZ_ERRNO; - - /* zipfile comment length */ - if (unzlocal_getShort(&us.z_filefunc, us.filestream,&us.gi.size_comment)!=UNZ_OK) - err=UNZ_ERRNO; - - if ((central_pospfile_in_zip_read!=NULL) - unzCloseCurrentFile(file); - - ZCLOSE(s->z_filefunc, s->filestream); - 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 (ZSEEK(s->z_filefunc, s->filestream, - s->pos_in_central_dir+s->byte_before_the_zipfile, - ZLIB_FILEFUNC_SEEK_SET)!=0) - err=UNZ_ERRNO; - - - /* we check the magic */ - if (err==UNZ_OK) - { - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) - err=UNZ_ERRNO; - else if (uMagic!=0x02014b50) - err=UNZ_BADZIPFILE; - } - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.version_needed) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.flag) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.compression_method) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.dosDate) != UNZ_OK) - err=UNZ_ERRNO; - - unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date); - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.crc) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.compressed_size) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.uncompressed_size) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_filename) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_extra) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.size_file_comment) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.disk_num_start) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&file_info.internal_fa) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&file_info.external_fa) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&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 (ZREAD(s->z_filefunc, s->filestream,szFileName,uSizeRead)!=uSizeRead) - err=UNZ_ERRNO; - lSeek -= uSizeRead; - } - - - if ((err==UNZ_OK) && (extraField!=NULL)) - { - uLong uSizeRead ; - if (file_info.size_file_extraz_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) - lSeek=0; - else - err=UNZ_ERRNO; - } - if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0)) - if (ZREAD(s->z_filefunc, s->filestream,extraField,uSizeRead)!=uSizeRead) - 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_commentz_filefunc, s->filestream,lSeek,ZLIB_FILEFUNC_SEEK_CUR)==0) - lSeek=0; - else - err=UNZ_ERRNO; - } - if ((file_info.size_file_comment>0) && (commentBufferSize>0)) - if (ZREAD(s->z_filefunc, s->filestream,szComment,uSizeRead)!=uSizeRead) - 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->gi.number_entry != 0xffff) /* 2^16 files overflow hack */ - 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; - - /* We remember the 'current' position in the file so that we can jump - * back there if we fail. - */ - unz_file_info cur_file_infoSaved; - unz_file_info_internal cur_file_info_internalSaved; - 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; - - /* Save the current state */ - num_fileSaved = s->num_file; - pos_in_central_dirSaved = s->pos_in_central_dir; - cur_file_infoSaved = s->cur_file_info; - cur_file_info_internalSaved = s->cur_file_info_internal; - - err = unzGoToFirstFile(file); - - while (err == UNZ_OK) - { - char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1]; - err = unzGetCurrentFileInfo(file,NULL, - szCurrentFileName,sizeof(szCurrentFileName)-1, - NULL,0,NULL,0); - if (err == UNZ_OK) - { - if (unzStringFileNameCompare(szCurrentFileName, - szFileName,iCaseSensitivity)==0) - return UNZ_OK; - err = unzGoToNextFile(file); - } - } - - /* We failed, so restore the state of the 'current file' to where we - * were. - */ - s->num_file = num_fileSaved ; - s->pos_in_central_dir = pos_in_central_dirSaved ; - s->cur_file_info = cur_file_infoSaved; - s->cur_file_info_internal = cur_file_info_internalSaved; - return err; -} - - -/* -/////////////////////////////////////////// -// Contributed by Ryan Haksi (mailto://cryogen@infoserve.net) -// I need random access -// -// Further optimization could be realized by adding an ability -// to cache the directory in memory. The goal being a single -// comprehensive file read to put the file I need in a memory. -*/ - -/* -typedef struct unz_file_pos_s -{ - uLong pos_in_zip_directory; // offset in file - uLong num_of_file; // # of file -} unz_file_pos; -*/ - -extern int ZEXPORT unzGetFilePos(file, file_pos) - unzFile file; - unz_file_pos* file_pos; -{ - unz_s* s; - - if (file==NULL || file_pos==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - if (!s->current_file_ok) - return UNZ_END_OF_LIST_OF_FILE; - - file_pos->pos_in_zip_directory = s->pos_in_central_dir; - file_pos->num_of_file = s->num_file; - - return UNZ_OK; -} - -extern int ZEXPORT unzGoToFilePos(file, file_pos) - unzFile file; - unz_file_pos* file_pos; -{ - unz_s* s; - int err; - - if (file==NULL || file_pos==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - - /* jump to the right spot */ - s->pos_in_central_dir = file_pos->pos_in_zip_directory; - s->num_file = file_pos->num_of_file; - - /* set the current file */ - err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info, - &s->cur_file_info_internal, - NULL,0,NULL,0,NULL,0); - /* return results */ - s->current_file_ok = (err == UNZ_OK); - return err; -} - -/* -// Unzip Helper Functions - should be here? -/////////////////////////////////////////// -*/ - -/* - 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 (ZSEEK(s->z_filefunc, s->filestream,s->cur_file_info_internal.offset_curfile + - s->byte_before_the_zipfile,ZLIB_FILEFUNC_SEEK_SET)!=0) - return UNZ_ERRNO; - - - if (err==UNZ_OK) - { - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&uMagic) != UNZ_OK) - err=UNZ_ERRNO; - else if (uMagic!=0x04034b50) - err=UNZ_BADZIPFILE; - } - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uData) != UNZ_OK) - err=UNZ_ERRNO; -/* - else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion)) - err=UNZ_BADZIPFILE; -*/ - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&uFlags) != UNZ_OK) - err=UNZ_ERRNO; - - if (unzlocal_getShort(&s->z_filefunc, s->filestream,&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->z_filefunc, s->filestream,&uData) != UNZ_OK) /* date/time */ - err=UNZ_ERRNO; - - if (unzlocal_getLong(&s->z_filefunc, s->filestream,&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->z_filefunc, s->filestream,&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->z_filefunc, s->filestream,&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->z_filefunc, s->filestream,&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->z_filefunc, s->filestream,&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 unzOpenCurrentFile3 (file, method, level, raw, password) - unzFile file; - int* method; - int* level; - int raw; - const char* password; -{ - int err=UNZ_OK; - 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 */ -# ifndef NOUNCRYPT - char source[12]; -# else - if (password != NULL) - return UNZ_PARAMERROR; -# endif - - 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; - pfile_in_zip_read_info->raw=raw; - - 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 (method!=NULL) - *method = (int)s->cur_file_info.compression_method; - - if (level!=NULL) - { - *level = 6; - switch (s->cur_file_info.flag & 0x06) - { - case 6 : *level = 1; break; - case 4 : *level = 2; break; - case 2 : *level = 9; break; - } - } - - if ((s->cur_file_info.compression_method!=0) && - (s->cur_file_info.compression_method!=Z_DEFLATED)) - err=UNZ_BADZIPFILE; - - 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->filestream=s->filestream; - pfile_in_zip_read_info->z_filefunc=s->z_filefunc; - pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile; - - pfile_in_zip_read_info->stream.total_out = 0; - - if ((s->cur_file_info.compression_method==Z_DEFLATED) && - (!raw)) - { - 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; - pfile_in_zip_read_info->stream.next_in = (voidpf)0; - pfile_in_zip_read_info->stream.avail_in = 0; - - err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS); - if (err == Z_OK) - pfile_in_zip_read_info->stream_initialised=1; - else - { - TRYFREE(pfile_in_zip_read_info); - return err; - } - /* 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; - -# ifndef NOUNCRYPT - if (password != NULL) - { - int i; - s->pcrc_32_tab = get_crc_table(); - init_keys(password,s->keys,s->pcrc_32_tab); - if (ZSEEK(s->z_filefunc, s->filestream, - s->pfile_in_zip_read->pos_in_zipfile + - s->pfile_in_zip_read->byte_before_the_zipfile, - SEEK_SET)!=0) - return UNZ_INTERNALERROR; - if(ZREAD(s->z_filefunc, s->filestream,source, 12)<12) - return UNZ_INTERNALERROR; - - for (i = 0; i<12; i++) - zdecode(s->keys,s->pcrc_32_tab,source[i]); - - s->pfile_in_zip_read->pos_in_zipfile+=12; - s->encrypted=1; - } -# endif - - - return UNZ_OK; -} - -extern int ZEXPORT unzOpenCurrentFile (file) - unzFile file; -{ - return unzOpenCurrentFile3(file, NULL, NULL, 0, NULL); -} - -extern int ZEXPORT unzOpenCurrentFilePassword (file, password) - unzFile file; - const char* password; -{ - return unzOpenCurrentFile3(file, NULL, NULL, 0, password); -} - -extern int ZEXPORT unzOpenCurrentFile2 (file,method,level,raw) - unzFile file; - int* method; - int* level; - int raw; -{ - return unzOpenCurrentFile3(file, method, level, raw, NULL); -} - -/* - 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->raw))) - pfile_in_zip_read_info->stream.avail_out = - (uInt)pfile_in_zip_read_info->rest_read_uncompressed; - - if ((len>pfile_in_zip_read_info->rest_read_compressed+ - pfile_in_zip_read_info->stream.avail_in) && - (pfile_in_zip_read_info->raw)) - pfile_in_zip_read_info->stream.avail_out = - (uInt)pfile_in_zip_read_info->rest_read_compressed+ - pfile_in_zip_read_info->stream.avail_in; - - 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 (ZSEEK(pfile_in_zip_read_info->z_filefunc, - pfile_in_zip_read_info->filestream, - pfile_in_zip_read_info->pos_in_zipfile + - pfile_in_zip_read_info->byte_before_the_zipfile, - ZLIB_FILEFUNC_SEEK_SET)!=0) - return UNZ_ERRNO; - if (ZREAD(pfile_in_zip_read_info->z_filefunc, - pfile_in_zip_read_info->filestream, - pfile_in_zip_read_info->read_buffer, - uReadThis)!=uReadThis) - return UNZ_ERRNO; - - -# ifndef NOUNCRYPT - if(s->encrypted) - { - uInt i; - for(i=0;iread_buffer[i] = - zdecode(s->keys,s->pcrc_32_tab, - pfile_in_zip_read_info->read_buffer[i]); - } -# endif - - - 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) || (pfile_in_zip_read_info->raw)) - { - uInt uDoCopy,i ; - - if ((pfile_in_zip_read_info->stream.avail_in == 0) && - (pfile_in_zip_read_info->rest_read_compressed == 0)) - return (iRead==0) ? UNZ_EOF : iRead; - - 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); - - if ((err>=0) && (pfile_in_zip_read_info->stream.msg!=NULL)) - err = Z_DATA_ERROR; - - 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 (ZSEEK(pfile_in_zip_read_info->z_filefunc, - pfile_in_zip_read_info->filestream, - pfile_in_zip_read_info->offset_local_extrafield + - pfile_in_zip_read_info->pos_local_extrafield, - ZLIB_FILEFUNC_SEEK_SET)!=0) - return UNZ_ERRNO; - - if (ZREAD(pfile_in_zip_read_info->z_filefunc, - pfile_in_zip_read_info->filestream, - buf,read_now)!=read_now) - 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) && - (!pfile_in_zip_read_info->raw)) - { - 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 (ZSEEK(s->z_filefunc,s->filestream,s->central_pos+22,ZLIB_FILEFUNC_SEEK_SET)!=0) - return UNZ_ERRNO; - - if (uReadThis>0) - { - *szComment='\0'; - if (ZREAD(s->z_filefunc,s->filestream,szComment,uReadThis)!=uReadThis) - return UNZ_ERRNO; - } - - if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment)) - *(szComment+s->gi.size_comment)='\0'; - return (int)uReadThis; -} - -/* Additions by RX '2004 */ -extern uLong ZEXPORT unzGetOffset (file) - unzFile file; -{ - unz_s* s; - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - if (!s->current_file_ok) - return 0; - if (s->gi.number_entry != 0 && s->gi.number_entry != 0xffff) - if (s->num_file==s->gi.number_entry) - return 0; - return s->pos_in_central_dir; -} - -extern int ZEXPORT unzSetOffset (file, pos) - unzFile file; - uLong pos; -{ - unz_s* s; - int err; - - if (file==NULL) - return UNZ_PARAMERROR; - s=(unz_s*)file; - - s->pos_in_central_dir = pos; - s->num_file = s->gi.number_entry; /* hack */ - 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; -} diff --git a/supergameboy/libgambatte/src/file/unzip/unzip.h b/supergameboy/libgambatte/src/file/unzip/unzip.h deleted file mode 100644 index 5bb6a696..00000000 --- a/supergameboy/libgambatte/src/file/unzip/unzip.h +++ /dev/null @@ -1,354 +0,0 @@ -/* unzip.h -- IO for uncompress .zip files using zlib - Version 1.01e, February 12th, 2005 - - Copyright (C) 1998-2005 Gilles Vollant - - This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g - WinZip, InfoZip tools and compatible. - - Multi volume ZipFile (span) are not supported. - Encryption compatible with pkzip 2.04g only supported - Old compressions used by old PKZip 1.x are not supported - - - 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 - http://www.info-zip.org/pub/infozip/doc/appnote-981119-iz.zip - http://www.info-zip.org/pub/infozip/doc/ - 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 -#endif - -#ifndef _ZLIBIOAPI_H -#include "ioapi.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 XP computer "c:\\zlib\\zlib113.zip" or on an Unix computer - "zlib/zlib113.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 unzOpen2 OF((const char *path, - zlib_filefunc_def* pzlib_filefunc_def)); -/* - Open a Zip file, like unzOpen, but provide a set of file low level API - for read/write the zip file (see ioapi.h) -*/ - -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 -*/ - - -/* ****************************************** */ -/* Ryan supplied functions */ -/* unz_file_info contain information about a file in the zipfile */ -typedef struct unz_file_pos_s -{ - uLong pos_in_zip_directory; /* offset in zip file directory */ - uLong num_of_file; /* # of file */ -} unz_file_pos; - -extern int ZEXPORT unzGetFilePos( - unzFile file, - unz_file_pos* file_pos); - -extern int ZEXPORT unzGoToFilePos( - unzFile file, - unz_file_pos* file_pos); - -/* ****************************************** */ - -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 unzOpenCurrentFilePassword OF((unzFile file, - const char* password)); -/* - Open for reading data the current file in the zipfile. - password is a crypting password - If there is no error, the return value is UNZ_OK. -*/ - -extern int ZEXPORT unzOpenCurrentFile2 OF((unzFile file, - int* method, - int* level, - int raw)); -/* - Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) - if raw==1 - *method will receive method of compression, *level will receive level of - compression - note : you can set level parameter as NULL (if you did not want known level, - but you CANNOT set method parameter as NULL -*/ - -extern int ZEXPORT unzOpenCurrentFile3 OF((unzFile file, - int* method, - int* level, - int raw, - const char* password)); -/* - Same than unzOpenCurrentFile, but open for read raw the file (not uncompress) - if raw==1 - *method will receive method of compression, *level will receive level of - compression - note : you can set level parameter as NULL (if you did not want known level, - but you CANNOT set method parameter as NULL -*/ - - -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 -*/ - -/***************************************************************************/ - -/* Get the current file offset */ -extern uLong ZEXPORT unzGetOffset (unzFile file); - -/* Set the current file offset */ -extern int ZEXPORT unzSetOffset (unzFile file, uLong pos); - - - -#ifdef __cplusplus -} -#endif - -#endif /* _unz_H */ diff --git a/supergameboy/libgambatte/src/gambatte.cpp b/supergameboy/libgambatte/src/gambatte.cpp deleted file mode 100644 index 27354c91..00000000 --- a/supergameboy/libgambatte/src/gambatte.cpp +++ /dev/null @@ -1,184 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aam�s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "gambatte.h" -#include "cpu.h" -#include "savestate.h" -#include "statesaver.h" -#include "initstate.h" -#include "state_osd_elements.h" -#include -#include - -#include - -static const std::string itos(int i) { - std::stringstream ss; - - ss << i; - - std::string out; - - ss >> out; - - return out; -} - -static const std::string statePath(const std::string &basePath, int stateNo) { - return basePath + "_" + itos(stateNo) + ".gqs"; -} - -namespace Gambatte { -GB::GB() : z80(new CPU), stateNo(1) {} - -GB::~GB() { - delete z80; -} - -unsigned GB::runFor(Gambatte::uint_least32_t *const soundBuf, const unsigned samples) { - z80->setSoundBuffer(soundBuf); - z80->runFor(samples * 2); - - return z80->fillSoundBuffer(); -} - -void GB::updateVideo() { - z80->updateVideo(); -} - -unsigned GB::lyCounter() { - return z80->lyCounter(); -} - -void GB::reset() { - z80->saveSavedata(); - - SaveState state; - z80->setStatePtrs(state); - setInitState(state, z80->isCgb()); - z80->loadState(state); - z80->loadSavedata(); - - z80->setAccumulator(supergameboy.version == 0 ? 0x01 : 0xff); - -// z80->reset(); -} - -void GB::setVideoBlitter(VideoBlitter *vb) { - z80->setVideoBlitter(vb); -} - -void GB::videoBufferChange() { - z80->videoBufferChange(); -} - -unsigned GB::videoWidth() const { - return z80->videoWidth(); -} - -unsigned GB::videoHeight() const { - return z80->videoHeight(); -} - -void GB::setVideoFilter(const unsigned n) { - z80->setVideoFilter(n); -} - -std::vector GB::filterInfo() const { - return z80->filterInfo(); -} - -void GB::setInputStateGetter(InputStateGetter *getInput) { - z80->setInputStateGetter(getInput); -} - -void GB::set_savedir(const char *sdir) { - z80->set_savedir(sdir); -} - -bool GB::load(const bool forceDmg) { - const bool failed = z80->load(forceDmg); - - if (!failed) { - SaveState state; - z80->setStatePtrs(state); - setInitState(state, z80->isCgb()); - z80->loadState(state); - z80->loadSavedata(); - - z80->setAccumulator(supergameboy.version == 0 ? 0x01 : 0xff); - - stateNo = 1; - z80->setOsdElement(std::auto_ptr()); - } - - return failed; -} - -bool GB::isCgb() const { - return z80->isCgb(); -} - -void GB::setDmgPaletteColor(unsigned palNum, unsigned colorNum, unsigned rgb32) { - z80->setDmgPaletteColor(palNum, colorNum, rgb32); -} - -void GB::saveSavedata() { - z80->saveSavedata(); -} - -void GB::loadState(const char *const filepath, const bool osdMessage) { - z80->saveSavedata(); - - SaveState state; - z80->setStatePtrs(state); - - if (StateSaver::loadState(state, filepath)) { - z80->loadState(state); - - if (osdMessage) - z80->setOsdElement(newStateLoadedOsdElement(stateNo)); - } -} - -void GB::saveState() { - saveState(statePath(z80->saveBasePath(), stateNo).c_str()); - z80->setOsdElement(newStateSavedOsdElement(stateNo)); -} - -void GB::loadState() { - loadState(statePath(z80->saveBasePath(), stateNo).c_str(), true); -} - -void GB::saveState(const char *filepath) { - SaveState state; - z80->setStatePtrs(state); - z80->saveState(state); - StateSaver::saveState(state, filepath); -} - -void GB::loadState(const char *const filepath) { - loadState(filepath, false); -} - -void GB::selectState(int n) { - n -= (n / 10) * 10; - stateNo = n < 0 ? n + 10 : n; - z80->setOsdElement(newSaveStateOsdElement(statePath(z80->saveBasePath(), stateNo).c_str(), stateNo)); -} -} diff --git a/supergameboy/libgambatte/src/initstate.cpp b/supergameboy/libgambatte/src/initstate.cpp deleted file mode 100644 index c16d48b4..00000000 --- a/supergameboy/libgambatte/src/initstate.cpp +++ /dev/null @@ -1,281 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2008 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "initstate.h" -#include "savestate.h" -#include -#include -#include "sound/sound_unit.h" -#include "memory.h" - -void setInitState(SaveState &state, const bool cgb) { - static const unsigned char feaxDump[0x60] = { - 0x18, 0x01, 0xEF, 0xDE, 0x06, 0x4A, 0xCD, 0xBD, - 0x18, 0x01, 0xEF, 0xDE, 0x06, 0x4A, 0xCD, 0xBD, - 0x18, 0x01, 0xEF, 0xDE, 0x06, 0x4A, 0xCD, 0xBD, - 0x18, 0x01, 0xEF, 0xDE, 0x06, 0x4A, 0xCD, 0xBD, - 0x00, 0x90, 0xF7, 0x7F, 0xC0, 0xB1, 0xB4, 0xFB, - 0x00, 0x90, 0xF7, 0x7F, 0xC0, 0xB1, 0xB4, 0xFB, - 0x00, 0x90, 0xF7, 0x7F, 0xC0, 0xB1, 0xB4, 0xFB, - 0x00, 0x90, 0xF7, 0x7F, 0xC0, 0xB1, 0xB4, 0xFB, - 0x24, 0x1B, 0xFD, 0x3A, 0x10, 0x12, 0xAD, 0x45, - 0x24, 0x1B, 0xFD, 0x3A, 0x10, 0x12, 0xAD, 0x45, - 0x24, 0x1B, 0xFD, 0x3A, 0x10, 0x12, 0xAD, 0x45, - 0x24, 0x1B, 0xFD, 0x3A, 0x10, 0x12, 0xAD, 0x45 - }; - - static const unsigned char ffxxDump[0x100] = { - 0xCF, 0x00, 0x7C, 0xFF, 0x43, 0x00, 0x00, 0xF8, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE1, - 0x80, 0xBF, 0xF3, 0xFF, 0xBF, 0xFF, 0x3F, 0x00, - 0xFF, 0xBF, 0x7F, 0xFF, 0x9F, 0xFF, 0xBF, 0xFF, - 0xFF, 0x00, 0x00, 0xBF, 0x77, 0xF3, 0xF1, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, - 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, - 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFC, - 0x00, 0x00, 0x00, 0x00, 0xFF, 0x7E, 0xFF, 0xFE, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x3E, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xC0, 0xFF, 0xC1, 0x00, 0xFE, 0xFF, 0xFF, 0xFF, - 0xF8, 0xFF, 0x00, 0x00, 0x00, 0x8F, 0x00, 0x00, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xCE, 0xED, 0x66, 0x66, 0xCC, 0x0D, 0x00, 0x0B, - 0x03, 0x73, 0x00, 0x83, 0x00, 0x0C, 0x00, 0x0D, - 0x00, 0x08, 0x11, 0x1F, 0x88, 0x89, 0x00, 0x0E, - 0xDC, 0xCC, 0x6E, 0xE6, 0xDD, 0xDD, 0xD9, 0x99, - 0xBB, 0xBB, 0x67, 0x63, 0x6E, 0x0E, 0xEC, 0xCC, - 0xDD, 0xDC, 0x99, 0x9F, 0xBB, 0xB9, 0x33, 0x3E, - 0x45, 0xEC, 0x52, 0xFA, 0x08, 0xB7, 0x07, 0x5D, - 0x01, 0xFD, 0xC0, 0xFF, 0x08, 0xFC, 0x00, 0xE5, - 0x0B, 0xF8, 0xC2, 0xCE, 0xF4, 0xF9, 0x0F, 0x7F, - 0x45, 0x6D, 0x3D, 0xFE, 0x46, 0x97, 0x33, 0x5E, - 0x08, 0xEF, 0xF1, 0xFF, 0x86, 0x83, 0x24, 0x74, - 0x12, 0xFC, 0x00, 0x9F, 0xB4, 0xB7, 0x06, 0xD5, - 0xD0, 0x7A, 0x00, 0x9E, 0x04, 0x5F, 0x41, 0x2F, - 0x1D, 0x77, 0x36, 0x75, 0x81, 0xAA, 0x70, 0x3A, - 0x98, 0xD1, 0x71, 0x02, 0x4D, 0x01, 0xC1, 0xFF, - 0x0D, 0x00, 0xD3, 0x05, 0xF9, 0x00, 0x0B, 0x00 - }; - - static const unsigned char cgbObjpDump[0x40] = { - 0x00, 0x00, 0xF2, 0xAB, - 0x61, 0xC2, 0xD9, 0xBA, - 0x88, 0x6E, 0xDD, 0x63, - 0x28, 0x27, 0xFB, 0x9F, - 0x35, 0x42, 0xD6, 0xD4, - 0x50, 0x48, 0x57, 0x5E, - 0x23, 0x3E, 0x3D, 0xCA, - 0x71, 0x21, 0x37, 0xC0, - 0xC6, 0xB3, 0xFB, 0xF9, - 0x08, 0x00, 0x8D, 0x29, - 0xA3, 0x20, 0xDB, 0x87, - 0x62, 0x05, 0x5D, 0xD4, - 0x0E, 0x08, 0xFE, 0xAF, - 0x20, 0x02, 0xD7, 0xFF, - 0x07, 0x6A, 0x55, 0xEC, - 0x83, 0x40, 0x0B, 0x77 - }; - - state.cpu.cycleCounter = 0x102A0; - state.cpu.PC = 0x100; - state.cpu.SP = 0xFFFE; - state.cpu.A = (cgb * 0x10) | 0x01; - state.cpu.B = 0x00; - state.cpu.C = 0x13; - state.cpu.D = 0x00; - state.cpu.E = 0xD8; - state.cpu.F = 0xB0; - state.cpu.H = 0x01; - state.cpu.L = 0x4D; - state.cpu.skip = false; - state.cpu.halted = false; - - - std::memset(state.mem.vram.ptr, 0, state.mem.vram.getSz()); - std::memset(state.mem.sram.ptr, 0xFF, state.mem.sram.getSz()); - - for (unsigned addr = 0x0000; addr < 0x0800; addr += 0x10) { - std::memset(state.mem.wram.ptr + addr + 0x00, 0xFF, 0x08); - std::memset(state.mem.wram.ptr + addr + 0x08, 0x00, 0x08); - } - - for (unsigned addr = 0x0800; addr < 0x1000; addr += 0x10) { - std::memset(state.mem.wram.ptr + addr + 0x00, 0x00, 0x08); - std::memset(state.mem.wram.ptr + addr + 0x08, 0xFF, 0x08); - } - - for (unsigned addr = 0x0E00; addr < 0x1000; addr += 0x10) { - state.mem.wram.ptr[addr + 0x02] = 0xFF; - state.mem.wram.ptr[addr + 0x0A] = 0x00; - } - - for (unsigned addr = 0x1000; addr < state.mem.wram.getSz(); addr += 0x1000) - std::memcpy(state.mem.wram.ptr + addr, state.mem.wram.ptr, 0x1000); - - std::memset(state.mem.ioamhram.ptr, 0x00, state.mem.ioamhram.getSz()); - std::memcpy(state.mem.ioamhram.ptr + 0xA0, feaxDump, sizeof(feaxDump)); - std::memcpy(state.mem.ioamhram.ptr + 0x100, ffxxDump, sizeof(ffxxDump)); - - state.mem.ioamhram.ptr[0x104] = 0x1C; - state.mem.ioamhram.ptr[0x140] = 0x91; - state.mem.ioamhram.ptr[0x144] = 0x00; - - if (!cgb) { - state.mem.ioamhram.ptr[0x130] = 0xAC; - state.mem.ioamhram.ptr[0x131] = 0xDD; - state.mem.ioamhram.ptr[0x132] = 0xDA; - state.mem.ioamhram.ptr[0x133] = 0x48; - state.mem.ioamhram.ptr[0x134] = 0x36; - state.mem.ioamhram.ptr[0x135] = 0x02; - state.mem.ioamhram.ptr[0x136] = 0xCF; - state.mem.ioamhram.ptr[0x137] = 0x16; - state.mem.ioamhram.ptr[0x138] = 0x2C; - state.mem.ioamhram.ptr[0x139] = 0x04; - state.mem.ioamhram.ptr[0x13A] = 0xE5; - state.mem.ioamhram.ptr[0x13B] = 0x2C; - state.mem.ioamhram.ptr[0x13C] = 0xAC; - state.mem.ioamhram.ptr[0x13D] = 0xDD; - state.mem.ioamhram.ptr[0x13E] = 0xDA; - state.mem.ioamhram.ptr[0x13F] = 0x48; - - state.mem.ioamhram.ptr[0x14D] = 0xFF; - state.mem.ioamhram.ptr[0x14F] = 0xFF; - state.mem.ioamhram.ptr[0x156] = 0xFF; - state.mem.ioamhram.ptr[0x168] = 0xFF; - state.mem.ioamhram.ptr[0x16A] = 0xFF; - state.mem.ioamhram.ptr[0x16B] = 0xFF; - state.mem.ioamhram.ptr[0x16C] = 0xFF; - state.mem.ioamhram.ptr[0x170] = 0xFF; - state.mem.ioamhram.ptr[0x172] = 0xFF; - state.mem.ioamhram.ptr[0x173] = 0xFF; - state.mem.ioamhram.ptr[0x174] = 0xFF; - state.mem.ioamhram.ptr[0x175] = 0xFF; - state.mem.ioamhram.ptr[0x176] = 0xFF; - state.mem.ioamhram.ptr[0x177] = 0xFF; - } - - state.mem.div_lastUpdate = 0; - state.mem.tima_lastUpdate = 0; - state.mem.tmatime = Memory::COUNTER_DISABLED; - state.mem.next_serialtime = Memory::COUNTER_DISABLED; - state.mem.lastOamDmaUpdate = Memory::COUNTER_DISABLED; - state.mem.minIntTime = 0; - state.mem.rombank = 1; - state.mem.dmaSource = 0; - state.mem.dmaDestination = 0; - state.mem.rambank = 0; - state.mem.oamDmaPos = 0xFE; - state.mem.IME = false; - state.mem.enable_ram = false; - state.mem.rambank_mode = false; - state.mem.hdma_transfer = false; - - - for (unsigned i = 0x00; i < 0x40; i += 0x02) { - state.ppu.bgpData.ptr[i] = 0xFF; - state.ppu.bgpData.ptr[i + 1] = 0x7F; - } - - std::memcpy(state.ppu.objpData.ptr, cgbObjpDump, sizeof(cgbObjpDump)); - - if (!cgb) { - state.ppu.bgpData.ptr[0] = state.mem.ioamhram.get()[0x147]; - state.ppu.objpData.ptr[0] = state.mem.ioamhram.get()[0x148]; - state.ppu.objpData.ptr[1] = state.mem.ioamhram.get()[0x149]; - } - - for (unsigned pos = 0; pos < 80; ++pos) - state.ppu.oamReaderBuf.ptr[pos] = state.mem.ioamhram.ptr[((pos * 2) & ~3) | (pos & 1)]; - - std::fill_n(state.ppu.oamReaderSzbuf.ptr, 40, false); - - state.ppu.videoCycles = 144*456ul + 164; - state.ppu.enableDisplayM0Time = state.cpu.cycleCounter - state.ppu.videoCycles + 159; - state.ppu.winYPos = 0xFF; - state.ppu.drawStartCycle = 90; - state.ppu.scReadOffset = 90; - state.ppu.lcdc = state.mem.ioamhram.get()[0x140]; - state.ppu.scx[1] = state.ppu.scx[0] = 0; - state.ppu.scy[1] = state.ppu.scy[0] = 0; - state.ppu.scxAnd7 = 0; - state.ppu.weMaster = false; - state.ppu.wx = 0; - state.ppu.wy = 0; - state.ppu.lycIrqSkip = false; - - - state.spu.cycleCounter = 0x1000 | ((state.cpu.cycleCounter >> 1) & 0xFFF); // spu.cycleCounter >> 12 & 7 represents the frame sequencer position. - - state.spu.ch1.sweep.counter = SoundUnit::COUNTER_DISABLED; - state.spu.ch1.sweep.shadow = 0; - state.spu.ch1.sweep.nr0 = 0; - state.spu.ch1.sweep.negging = false; - state.spu.ch1.duty.nextPosUpdate = (state.spu.cycleCounter & ~1) + 2048 * 2; - state.spu.ch1.duty.nr3 = 0; - state.spu.ch1.duty.pos = 0; - state.spu.ch1.env.counter = SoundUnit::COUNTER_DISABLED; - state.spu.ch1.env.volume = 0; - state.spu.ch1.lcounter.counter = SoundUnit::COUNTER_DISABLED; - state.spu.ch1.lcounter.lengthCounter = 0x40; - state.spu.ch1.nr4 = 0; - state.spu.ch1.master = true; - - state.spu.ch2.duty.nextPosUpdate = (state.spu.cycleCounter & ~1) + 2048 * 2; - state.spu.ch2.duty.nr3 = 0; - state.spu.ch2.duty.pos = 0; - state.spu.ch2.env.counter = state.spu.cycleCounter - ((state.spu.cycleCounter - 0x1000) & 0x7FFF) + 8ul * 0x8000; - state.spu.ch2.env.volume = 0; - state.spu.ch2.lcounter.counter = SoundUnit::COUNTER_DISABLED; - state.spu.ch2.lcounter.lengthCounter = 0x40; - state.spu.ch2.nr4 = 0; - state.spu.ch2.master = false; - - for (unsigned i = 0; i < 0x10; ++i) - state.spu.ch3.waveRam.ptr[i] = state.mem.ioamhram.get()[0x130 + i]; - - state.spu.ch3.lcounter.counter = SoundUnit::COUNTER_DISABLED; - state.spu.ch3.lcounter.lengthCounter = 0x100; - state.spu.ch3.waveCounter = SoundUnit::COUNTER_DISABLED; - state.spu.ch3.lastReadTime = SoundUnit::COUNTER_DISABLED; - state.spu.ch3.nr3 = 0; - state.spu.ch3.nr4 = 0; - state.spu.ch3.wavePos = 0; - state.spu.ch3.sampleBuf = 0; - state.spu.ch3.master = false; - - state.spu.ch4.lfsr.counter = state.spu.cycleCounter + 4; - state.spu.ch4.lfsr.reg = 0xFF; - state.spu.ch4.env.counter = state.spu.cycleCounter - ((state.spu.cycleCounter - 0x1000) & 0x7FFF) + 8ul * 0x8000; - state.spu.ch4.env.volume = 0; - state.spu.ch4.lcounter.counter = SoundUnit::COUNTER_DISABLED; - state.spu.ch4.lcounter.lengthCounter = 0x40; - state.spu.ch4.nr4 = 0; - state.spu.ch4.master = false; - - state.rtc.baseTime = std::time(0); - state.rtc.haltTime = state.rtc.baseTime; - state.rtc.index = 5; - state.rtc.dataDh = 0; - state.rtc.dataDl = 0; - state.rtc.dataH = 0; - state.rtc.dataM = 0; - state.rtc.dataS = 0; - state.rtc.lastLatchData = false; -} diff --git a/supergameboy/libgambatte/src/initstate.h b/supergameboy/libgambatte/src/initstate.h deleted file mode 100644 index d550eed5..00000000 --- a/supergameboy/libgambatte/src/initstate.h +++ /dev/null @@ -1,26 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2008 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef INITSTATE_H -#define INITSTATE_H - -class SaveState; - -void setInitState(SaveState &state, bool cgb); - -#endif diff --git a/supergameboy/libgambatte/src/insertion_sort.h b/supergameboy/libgambatte/src/insertion_sort.h deleted file mode 100644 index 939ba074..00000000 --- a/supergameboy/libgambatte/src/insertion_sort.h +++ /dev/null @@ -1,51 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ - -#ifndef INSERTION_SORT_H -#define INSERTION_SORT_H - -#include - -template -void insertionSort(T *const start, T *const end, Less less) { - if (start >= end) - return; - - T *a = start; - - while (++a < end) { - const T e = *a; - - T *b = a; - - while (b != start && less(e, *(b - 1))) { - *b = *(b - 1); - b = b - 1; - } - - *b = e; - } -} - -template -inline void insertionSort(T *const start, T *const end) { - insertionSort(start, end, std::less()); -} - -#endif /*INSERTION_SORT_H*/ diff --git a/supergameboy/libgambatte/src/interrupter.cpp b/supergameboy/libgambatte/src/interrupter.cpp deleted file mode 100644 index aea9df41..00000000 --- a/supergameboy/libgambatte/src/interrupter.cpp +++ /dev/null @@ -1,44 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aam�s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "interrupter.h" - -#include "memory.h" - -Interrupter::Interrupter(unsigned short &SP_in, unsigned short &PC_in, bool &halted_in) : - SP(SP_in), - PC(PC_in), - halted(halted_in) -{} - -unsigned long Interrupter::interrupt(const unsigned address, unsigned long cycleCounter, Memory &memory) { - if (halted && memory.isCgb()) - cycleCounter += 4; - - halted = false; - cycleCounter += 8; - SP = (SP - 1) & 0xFFFF; - memory.write(SP, PC >> 8, cycleCounter); - cycleCounter += 4; - SP = (SP - 1) & 0xFFFF; - memory.write(SP, PC & 0xFF, cycleCounter); - PC = address; - cycleCounter += 8; - - return cycleCounter; -} diff --git a/supergameboy/libgambatte/src/interrupter.h b/supergameboy/libgambatte/src/interrupter.h deleted file mode 100644 index 18e0d9e1..00000000 --- a/supergameboy/libgambatte/src/interrupter.h +++ /dev/null @@ -1,38 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aam�s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef INTERRUPTER_H -#define INTERRUPTER_H - -class Memory; - -class Interrupter { - unsigned short &SP; - unsigned short &PC; - bool &halted; - -public: - Interrupter(unsigned short &SP, unsigned short &PC, bool &halted); - unsigned long interrupt(const unsigned address, unsigned long cycleCounter, Memory &memory); - - void unhalt() { - halted = false; - } -}; - -#endif diff --git a/supergameboy/libgambatte/src/memory.cpp b/supergameboy/libgambatte/src/memory.cpp deleted file mode 100644 index 2211733d..00000000 --- a/supergameboy/libgambatte/src/memory.cpp +++ /dev/null @@ -1,1867 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aam�s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "memory.h" -#include "video.h" -#include "sound.h" -#include "inputstate.h" -#include "inputstategetter.h" -#include "savestate.h" -#include "file/file.h" -#include -#include - -// static const uint32_t timaClock[4]={ 1024, 16, 64, 256 }; -static const unsigned char timaClock[4] = { 10, 4, 6, 8 }; - -Memory::Memory(const Interrupter &interrupter_in) : -memchunk(NULL), -rambankdata(NULL), -rdisabled_ram(NULL), -wdisabled_ram(NULL), -oamDmaSrc(NULL), -vrambank(vram), -rsrambankptr(NULL), -wsrambankptr(NULL), -getInput(NULL), -div_lastUpdate(0), -tima_lastUpdate(0), -next_timatime(COUNTER_DISABLED), -next_blittime(144*456ul), -nextIntTime(COUNTER_DISABLED), -minIntTime(0), -next_dmatime(COUNTER_DISABLED), -next_hdmaReschedule(COUNTER_DISABLED), -next_unhalttime(COUNTER_DISABLED), -next_endtime(0), -tmatime(COUNTER_DISABLED), -next_serialtime(COUNTER_DISABLED), -lastOamDmaUpdate(COUNTER_DISABLED), -nextOamEventTime(COUNTER_DISABLED), -display(ioamhram, vram), -interrupter(interrupter_in), -romtype(plain), -rombanks(1), -rombank(1), -dmaSource(0), -dmaDestination(0), -rambank(0), -rambanks(1), -oamDmaArea1Lower(0), -oamDmaArea1Width(0), -oamDmaArea2Upper(0), -oamDmaPos(0xFE), -cgb(false), -doubleSpeed(false), -IME(false), -enable_ram(false), -rambank_mode(false), -battery(false), -rtcRom(false), -hdma_transfer(false), -active(false) -{ - romdata[1] = romdata[0] = NULL; - wramdata[1] = wramdata[0] = NULL; - std::fill_n(rmem, 0x10, static_cast(NULL)); - std::fill_n(wmem, 0x10, static_cast(NULL)); - set_irqEvent(); - set_event(); -} - -void Memory::setStatePtrs(SaveState &state) { - state.mem.vram.set(vram, sizeof vram); - state.mem.sram.set(rambankdata, rambanks * 0x2000ul); - state.mem.wram.set(wramdata[0], isCgb() ? 0x8000 : 0x2000); - state.mem.ioamhram.set(ioamhram, sizeof ioamhram); - - display.setStatePtrs(state); - sound.setStatePtrs(state); -} - -unsigned long Memory::saveState(SaveState &state, unsigned long cycleCounter) { - cycleCounter = resetCounters(cycleCounter); - nontrivial_ff_read(0xFF0F, cycleCounter); - nontrivial_ff_read(0xFF26, cycleCounter); - - state.mem.div_lastUpdate = div_lastUpdate; - state.mem.tima_lastUpdate = tima_lastUpdate; - state.mem.tmatime = tmatime; - state.mem.next_serialtime = next_serialtime; - state.mem.lastOamDmaUpdate = lastOamDmaUpdate; - state.mem.minIntTime = minIntTime; - state.mem.rombank = rombank; - state.mem.dmaSource = dmaSource; - state.mem.dmaDestination = dmaDestination; - state.mem.rambank = rambank; - state.mem.oamDmaPos = oamDmaPos; - state.mem.IME = IME; - state.mem.enable_ram = enable_ram; - state.mem.rambank_mode = rambank_mode; - state.mem.hdma_transfer = hdma_transfer; - - rtc.saveState(state); - display.saveState(state); - sound.saveState(state); - - return cycleCounter; -} - -void Memory::loadState(const SaveState &state, const unsigned long oldCc) { - sound.loadState(state); - display.loadState(state, state.mem.oamDmaPos < 0xA0 ? rdisabled_ram : ioamhram); - rtc.loadState(state, rtcRom ? state.mem.enable_ram : false); - - div_lastUpdate = state.mem.div_lastUpdate; - tima_lastUpdate = state.mem.tima_lastUpdate; - tmatime = state.mem.tmatime; - next_serialtime = state.mem.next_serialtime; - lastOamDmaUpdate = state.mem.lastOamDmaUpdate; - minIntTime = state.mem.minIntTime; - rombank = state.mem.rombank & (rombanks - 1); - dmaSource = state.mem.dmaSource; - dmaDestination = state.mem.dmaDestination; - rambank = state.mem.rambank & (rambanks - 1); - oamDmaPos = state.mem.oamDmaPos; - IME = state.mem.IME; - enable_ram = state.mem.enable_ram; - rambank_mode = state.mem.rambank_mode; - hdma_transfer = state.mem.hdma_transfer; - - const bool oldDs = doubleSpeed; - doubleSpeed = isCgb() & ioamhram[0x14D] >> 7; - oamDmaArea2Upper = oamDmaArea1Width = oamDmaArea1Lower = 0; - vrambank = vram + (ioamhram[0x14F] & 0x01 & isCgb()) * 0x2000; - wramdata[1] = wramdata[0] + ((isCgb() && (ioamhram[0x170] & 0x07)) ? (ioamhram[0x170] & 0x07) : 1) * 0x1000; - std::fill_n(rmem, 0x10, static_cast(NULL)); - std::fill_n(wmem, 0x10, static_cast(NULL)); - setBanks(); - - if (lastOamDmaUpdate != COUNTER_DISABLED) { - oamDmaInitSetup(); - - unsigned oamEventPos = 0x100; - - if (oamDmaPos < 0xA0) { - setOamDmaArea(); - oamEventPos = 0xA0; - } - - nextOamEventTime = lastOamDmaUpdate + (oamEventPos - oamDmaPos) * 4; - setOamDmaSrc(); - } - - if (!IME && state.cpu.halted) - schedule_unhalt(); - - next_blittime = (ioamhram[0x140] & 0x80) ? display.nextMode1IrqTime() : static_cast(COUNTER_DISABLED); - - const unsigned long cycleCounter = state.cpu.cycleCounter; - - if (hdma_transfer) { - next_dmatime = display.nextHdmaTime(cycleCounter); - next_hdmaReschedule = display.nextHdmaTimeInvalid(); - } else { - next_hdmaReschedule = next_dmatime = COUNTER_DISABLED; - } - - next_timatime = (ioamhram[0x107] & 4) ? tima_lastUpdate + ((256u - ioamhram[0x105]) << timaClock[ioamhram[0x107] & 3]) + 1 : static_cast(COUNTER_DISABLED); - set_irqEvent(); - rescheduleIrq(cycleCounter); - - if (oldDs != isDoubleSpeed()) - next_endtime = cycleCounter - (isDoubleSpeed() ?( oldCc - next_endtime) << 1 :( oldCc - next_endtime) >> 1); - else - next_endtime = cycleCounter - (oldCc - next_endtime); - -// set_event(); -} - -void Memory::schedule_unhalt() { - next_unhalttime = std::min(next_irqEventTime, display.nextIrqEvent()); - - if (next_unhalttime != COUNTER_DISABLED) - next_unhalttime += isCgb() * 4; - - set_event(); -} - -void Memory::rescheduleIrq(const unsigned long cycleCounter) { - if (IME) { - ioamhram[0x10F] |= display.getIfReg(cycleCounter) & 3; - - nextIntTime = (ioamhram[0x10F] & ioamhram[0x1FF] & 0x1F) ? cycleCounter : std::min(next_irqEventTime, display.nextIrqEvent()); - - if (nextIntTime < minIntTime) - nextIntTime = minIntTime; - - set_event(); - } -} - -void Memory::rescheduleHdmaReschedule() { - if (hdma_transfer && (ioamhram[0x140] & 0x80)) { - const unsigned long newTime = display.nextHdmaTimeInvalid(); - - if (newTime < next_hdmaReschedule) { - next_hdmaReschedule = newTime; - - if (newTime < next_eventtime) { - next_eventtime = newTime; - next_event = HDMA_RESCHEDULE; - } - } - } -} - -void Memory::ei(const unsigned long cycleCounter) { - IME = 1; - minIntTime = cycleCounter + 1; - rescheduleIrq(cycleCounter); -} - -void Memory::incEndtime(const unsigned long inc) { - active = true; - next_endtime += inc << isDoubleSpeed(); - set_event(); -} - -void Memory::setEndtime(const unsigned long cycleCounter, const unsigned long inc) { - next_endtime = cycleCounter; - incEndtime(inc); -} - -void Memory::set_irqEvent() { - next_irqEventTime = next_timatime; - next_irqEvent = TIMA; - - if (next_serialtime < next_irqEventTime) { - next_irqEvent = SERIAL; - next_irqEventTime = next_serialtime; - } -} - -void Memory::update_irqEvents(const unsigned long cc) { - while (next_irqEventTime <= cc) { - switch (next_irqEvent) { - case TIMA: - ioamhram[0x10F] |= 4; - next_timatime += (256u - ioamhram[0x106]) << timaClock[ioamhram[0x107] & 3]; - break; - case SERIAL: - next_serialtime = COUNTER_DISABLED; - ioamhram[0x101] = 0xFF; - ioamhram[0x102] &= 0x7F; - ioamhram[0x10F] |= 8; - break; - } - - set_irqEvent(); - } -} - -void Memory::set_event() { - next_event = INTERRUPTS; - next_eventtime = nextIntTime; - if (next_hdmaReschedule < next_eventtime) { - next_eventtime = next_hdmaReschedule; - next_event = HDMA_RESCHEDULE; - } - if (next_dmatime < next_eventtime) { - next_eventtime = next_dmatime; - next_event = DMA; - } - if (next_unhalttime < next_eventtime) { - next_eventtime = next_unhalttime; - next_event = UNHALT; - } - if (nextOamEventTime < next_eventtime) { - next_eventtime = nextOamEventTime; - next_event = OAM; - } - if (next_blittime < next_eventtime) { - next_event = BLIT; - next_eventtime = next_blittime; - } - if (next_endtime < next_eventtime) { - next_eventtime = next_endtime; - next_event = END; - } -} - -unsigned long Memory::event(unsigned long cycleCounter) { - if (lastOamDmaUpdate != COUNTER_DISABLED) - updateOamDma(cycleCounter); - - switch (next_event) { - case HDMA_RESCHEDULE: -// printf("hdma_reschedule\n"); - next_dmatime = display.nextHdmaTime(cycleCounter); - next_hdmaReschedule = display.nextHdmaTimeInvalid(); - break; - case DMA: -// printf("dma\n"); - { - const bool doubleSpeed = isDoubleSpeed(); - unsigned dmaSrc = dmaSource; - unsigned dmaDest = dmaDestination; - unsigned dmaLength = ((ioamhram[0x155] & 0x7F) + 0x1) * 0x10; - - unsigned length = hdma_transfer ? 0x10 : dmaLength; - - if ((static_cast(dmaDest) + length) & 0x10000) { - length = 0x10000 - dmaDest; - ioamhram[0x155] |= 0x80; - } - - dmaLength -= length; - - if (!(ioamhram[0x140] & 0x80)) - dmaLength = 0; - - { - unsigned long lOamDmaUpdate = lastOamDmaUpdate; - lastOamDmaUpdate = COUNTER_DISABLED; - - while (length--) { - const unsigned src = dmaSrc++ & 0xFFFF; - const unsigned data = ((src & 0xE000) == 0x8000 || src > 0xFDFF) ? 0xFF : read(src, cycleCounter); - - cycleCounter += 2 << doubleSpeed; - - if (cycleCounter - 3 > lOamDmaUpdate) { - oamDmaPos = (oamDmaPos + 1) & 0xFF; - lOamDmaUpdate += 4; - - if (oamDmaPos < 0xA0) { - if (oamDmaPos == 0) - startOamDma(lOamDmaUpdate - 2); - - ioamhram[src & 0xFF] = data; - } else if (oamDmaPos == 0xA0) { - endOamDma(lOamDmaUpdate - 2); - lOamDmaUpdate = COUNTER_DISABLED; - } - } - - nontrivial_write(0x8000 | (dmaDest++ & 0x1FFF), data, cycleCounter); - } - - lastOamDmaUpdate = lOamDmaUpdate; - } - - cycleCounter += 4; - - dmaSource = dmaSrc; - dmaDestination = dmaDest; - ioamhram[0x155] = ((dmaLength / 0x10 - 0x1) & 0xFF) | (ioamhram[0x155] & 0x80); - - if (ioamhram[0x155] & 0x80) { - next_hdmaReschedule = next_dmatime = COUNTER_DISABLED; - hdma_transfer = 0; - } - - if (hdma_transfer) { - if (lastOamDmaUpdate != COUNTER_DISABLED) - updateOamDma(cycleCounter); - - next_dmatime = display.nextHdmaTime(cycleCounter); - } - } - - break; - case INTERRUPTS: -// printf("interrupts\n"); - update_irqEvents(cycleCounter); - ioamhram[0x10F] |= display.getIfReg(cycleCounter) & 3; - - { - /*unsigned interrupt = ioamhram[0x10F] & ioamhram[0x1FF]; - interrupt |= interrupt << 1; - interrupt |= interrupt << 2; - interrupt |= interrupt << 1; - interrupt = ~interrupt; - ++interrupt; - interrupt &= 0x1F; - - if (interrupt) { - ioamhram[0x10F] &= ~interrupt; - display.setIfReg(ioamhram[0x10F], CycleCounter); - IME = false; - - unsigned address = interrupt; - interrupt >>= 1; - address -= interrupt & 0x0C; - interrupt >>= 1; - address -= interrupt & 5; - address += interrupt >> 2; - - address <<= 3; - address += 0x38; - - z80.interrupt(address); - }*/ - - const unsigned interrupt = ioamhram[0x10F] & ioamhram[0x1FF] & 0x1F; - - if (interrupt) { - unsigned n; - unsigned address; - - if ((n = interrupt & 0x01)) - address = 0x40; - else if ((n = interrupt & 0x02)) - address = 0x48; - else if ((n = interrupt & 0x04)) - address = 0x50; - else if ((n = interrupt & 0x08)) - address = 0x58; - else { - n = 0x10; - address = 0x60; - } - - ioamhram[0x10F] &= ~n; - display.setIfReg(ioamhram[0x10F], cycleCounter); - IME = false; - cycleCounter = interrupter.interrupt(address, cycleCounter, *this); - } - } - - nextIntTime = IME ? std::min(next_irqEventTime, display.nextIrqEvent()) : static_cast(COUNTER_DISABLED); - break; - case BLIT: -// printf("blit\n"); - display.updateScreen(next_blittime); - - if (ioamhram[0x140] & 0x80) - next_blittime += 70224 << isDoubleSpeed(); - else - next_blittime = COUNTER_DISABLED; - - break; - case UNHALT: -// printf("unhalt\n"); - update_irqEvents(cycleCounter); - ioamhram[0x10F] |= display.getIfReg(cycleCounter) & 3; - - if (ioamhram[0x10F] & ioamhram[0x1FF] & 0x1F) { - next_unhalttime = COUNTER_DISABLED; - interrupter.unhalt(); - } else - next_unhalttime = std::min(next_irqEventTime, display.nextIrqEvent()) + isCgb() * 4; - - break; - case OAM: - nextOamEventTime = lastOamDmaUpdate == COUNTER_DISABLED ? static_cast(COUNTER_DISABLED) : nextOamEventTime + 0xA0 * 4; - break; - case END: - { - const unsigned long endtime = next_endtime; - next_endtime = COUNTER_DISABLED; - set_event(); - - while (cycleCounter >= next_eventtime) - cycleCounter = event(cycleCounter); - - next_endtime = endtime; - active = false; - } - - break; - } - - set_event(); - - return cycleCounter; -} - -void Memory::speedChange(const unsigned long cycleCounter) { - if (isCgb() && (ioamhram[0x14D] & 0x1)) { - std::printf("speedChange\n"); - - update_irqEvents(cycleCounter); - sound.generate_samples(cycleCounter, isDoubleSpeed()); - display.preSpeedChange(cycleCounter); - - ioamhram[0x14D] = ~ioamhram[0x14D] & 0x80; - doubleSpeed = ioamhram[0x14D] >> 7; - - display.postSpeedChange(cycleCounter); - - if (hdma_transfer) { - next_dmatime = display.nextHdmaTime(cycleCounter); - next_hdmaReschedule = display.nextHdmaTimeInvalid(); - } - - next_blittime = (ioamhram[0x140] & 0x80) ? display.nextMode1IrqTime() : static_cast(COUNTER_DISABLED); - next_endtime = cycleCounter + (isDoubleSpeed() ?( next_endtime - cycleCounter) << 1 : ((next_endtime - cycleCounter) >> 1)); - set_irqEvent(); - rescheduleIrq(cycleCounter); - set_event(); - } -} - -static void decCycles(unsigned long &counter, const unsigned long dec) { - if (counter != Memory::COUNTER_DISABLED) - counter -= dec; -} - -unsigned long Memory::resetCounters(unsigned long cycleCounter) { - std::printf("resetting counters\n"); - - if (lastOamDmaUpdate != COUNTER_DISABLED) - updateOamDma(cycleCounter); - - update_irqEvents(cycleCounter); - rescheduleIrq(cycleCounter); - display.preResetCounter(cycleCounter); - - const unsigned long oldCC = cycleCounter; - - { - const unsigned long divinc = (cycleCounter - div_lastUpdate) >> 8; - ioamhram[0x104] = (ioamhram[0x104] + divinc) & 0xFF; - div_lastUpdate += divinc << 8; - } - - if (ioamhram[0x107] & 0x04) { - update_tima(cycleCounter); - } - - const unsigned long dec = cycleCounter < 0x10000 ? 0 : (cycleCounter & ~0x7FFFul) - 0x8000; - - minIntTime = minIntTime < cycleCounter ? 0 : minIntTime - dec; - - if (ioamhram[0x107] & 0x04) - decCycles(tima_lastUpdate, dec); - - decCycles(div_lastUpdate, dec); - decCycles(lastOamDmaUpdate, dec); - decCycles(next_eventtime, dec); - decCycles(next_irqEventTime, dec); - decCycles(next_timatime, dec); - decCycles(next_blittime, dec); - decCycles(nextOamEventTime, dec); - decCycles(next_endtime, dec); - decCycles(next_dmatime, dec); - decCycles(next_hdmaReschedule, dec); - decCycles(nextIntTime, dec); - decCycles(next_serialtime, dec); - decCycles(tmatime, dec); - decCycles(next_unhalttime, dec); - - cycleCounter -= dec; - - display.postResetCounter(oldCC, cycleCounter); - sound.resetCounter(cycleCounter, oldCC, isDoubleSpeed()); - - return cycleCounter; -} - -void Memory::updateInput() { - unsigned joypadId = 0x0F; - unsigned button = 0xFF; - unsigned dpad = 0xFF; - - if (getInput) { - const Gambatte::InputState &is = (*getInput)(); - - joypadId = is.joypadId; - - button ^= is.startButton << 3; - button ^= is.selectButton << 2; - button ^= is.bButton << 1; - button ^= is.aButton; - - dpad ^= is.dpadDown << 3; - dpad ^= is.dpadUp << 2; - dpad ^= is.dpadLeft << 1; - dpad ^= is.dpadRight; - } - - ioamhram[0x100] |= 0xF; - - if ((ioamhram[0x100] & 0x30) == 0x30) { - ioamhram[0x100] &= 0xf0; - ioamhram[0x100] |= joypadId; - } else { - if (!(ioamhram[0x100] & 0x10)) - ioamhram[0x100] &= dpad; - - if (!(ioamhram[0x100] & 0x20)) - ioamhram[0x100] &= button; - } -} - -void Memory::setRombank() { - unsigned bank = rombank; - - if ((romtype == mbc1 && !(bank & 0x1F)) || (romtype == mbc5 && !bank)) - ++bank; - - romdata[1] = romdata[0] + bank * 0x4000ul - 0x4000; - - if (oamDmaArea1Lower != 0xA0) { - rmem[0x7] = rmem[0x6] = rmem[0x5] = rmem[0x4] = romdata[1]; - } else - setOamDmaSrc(); -} - -void Memory::setRambank() { - rmem[0xB] = rmem[0xA] = rsrambankptr = rdisabled_ram - 0xA000; - wmem[0xB] = wmem[0xA] = wsrambankptr = wdisabled_ram - 0xA000; - - if (enable_ram) { - if (rtc.getActive()) { - wmem[0xB] = wmem[0xA] = rmem[0xB] = rmem[0xA] = wsrambankptr = rsrambankptr = NULL; - } else if (rambanks) { - wmem[0xB] = rmem[0xB] = wmem[0xA] = rmem[0xA] = wsrambankptr = rsrambankptr = rambankdata + rambank * 0x2000ul - 0xA000; - } - } - - if (oamDmaArea1Lower == 0xA0) { - wmem[0xB] = wmem[0xA] = rmem[0xB] = rmem[0xA] = NULL; - setOamDmaSrc(); - } -} - -void Memory::setBanks() { - rmem[0x3] = rmem[0x2] = rmem[0x1] = rmem[0x0] = romdata[0]; - - setRombank(); - setRambank(); - - rmem[0xC] = wmem[0xC] = wramdata[0] - 0xC000; - rmem[0xD] = wmem[0xD] = wramdata[1] - 0xD000; - rmem[0xE] = wmem[0xE] = wramdata[0] - 0xE000; -} - -void Memory::updateOamDma(const unsigned long cycleCounter) { - unsigned cycles = (cycleCounter - lastOamDmaUpdate) >> 2; - - while (cycles--) { - oamDmaPos = (oamDmaPos + 1) & 0xFF; - lastOamDmaUpdate += 4; - - //TODO: reads from vram while the ppu is reading vram should return whatever the ppu is reading. - if (oamDmaPos < 0xA0) { - if (oamDmaPos == 0) - startOamDma(lastOamDmaUpdate - 2); - - ioamhram[oamDmaPos] = oamDmaSrc ? oamDmaSrc[oamDmaPos] : *rtc.getActive(); - } else if (oamDmaPos == 0xA0) { - endOamDma(lastOamDmaUpdate - 2); - lastOamDmaUpdate = COUNTER_DISABLED; - break; - } - } -} - -void Memory::setOamDmaArea() { - if (ioamhram[0x146] < 0xC0) { - if ((ioamhram[0x146] & 0xE0) != 0x80) - oamDmaArea2Upper = 0x80; - - oamDmaArea1Width = 0x20; - } else if (ioamhram[0x146] < 0xE0) - oamDmaArea1Width = 0x3E; -} - -void Memory::oamDmaInitSetup() { - if (ioamhram[0x146] < 0xC0) { - if ((ioamhram[0x146] & 0xE0) == 0x80) { - oamDmaArea1Lower = 0x80; - } else { - oamDmaArea1Lower = 0xA0; - std::fill_n(rmem, 0x8, static_cast(NULL)); - rmem[0xB] = rmem[0xA] = NULL; - wmem[0xB] = wmem[0xA] = NULL; - } - } else if (ioamhram[0x146] < 0xE0) { - oamDmaArea1Lower = 0xC0; - rmem[0xE] = rmem[0xD] = rmem[0xC] = NULL; - wmem[0xE] = wmem[0xD] = wmem[0xC] = NULL; - } -} - -void Memory::setOamDmaSrc() { - oamDmaSrc = NULL; - - if (ioamhram[0x146] < 0xC0) { - if ((ioamhram[0x146] & 0xE0) == 0x80) { - oamDmaSrc = vrambank + (ioamhram[0x146] << 8 & 0x1FFF); - } else { - if (ioamhram[0x146] < 0x80) - oamDmaSrc = romdata[ioamhram[0x146] >> 6] + (ioamhram[0x146] << 8); - else if (rsrambankptr) - oamDmaSrc = rsrambankptr + (ioamhram[0x146] << 8); - } - } else if (ioamhram[0x146] < 0xE0) { - oamDmaSrc = wramdata[ioamhram[0x146] >> 4 & 1] + (ioamhram[0x146] << 8 & 0xFFF); - } else - oamDmaSrc = rdisabled_ram; -} - -void Memory::startOamDma(const unsigned long cycleCounter) { - setOamDmaArea(); - display.oamChange(rdisabled_ram, cycleCounter); - - if (next_unhalttime != COUNTER_DISABLED) - schedule_unhalt(); - else - rescheduleIrq(cycleCounter); - - rescheduleHdmaReschedule(); -} - -void Memory::endOamDma(const unsigned long cycleCounter) { - oamDmaArea2Upper = oamDmaArea1Width = oamDmaArea1Lower = 0; - oamDmaPos = 0xFE; - setBanks(); - display.oamChange(ioamhram, cycleCounter); - - if (next_unhalttime != COUNTER_DISABLED) - schedule_unhalt(); - else - rescheduleIrq(cycleCounter); - - rescheduleHdmaReschedule(); -} - -void Memory::update_tima(const unsigned long cycleCounter) { - const unsigned long ticks = (cycleCounter - tima_lastUpdate) >> timaClock[ioamhram[0x107] & 3]; - - tima_lastUpdate += ticks << timaClock[ioamhram[0x107] & 3]; - - if (cycleCounter >= tmatime) { - if (cycleCounter >= tmatime + 4) - tmatime = COUNTER_DISABLED; - - ioamhram[0x105] = ioamhram[0x106]; - } - - unsigned long tmp = ioamhram[0x105] + ticks; - - while (tmp > 0x100) - tmp -= 0x100 - ioamhram[0x106]; - - if (tmp == 0x100) { - tmp = 0; - tmatime = tima_lastUpdate + 3; - - if (cycleCounter >= tmatime) { - if (cycleCounter >= tmatime + 4) - tmatime = COUNTER_DISABLED; - - tmp = ioamhram[0x106]; - } - } - - ioamhram[0x105] = tmp; -} - -unsigned Memory::nontrivial_ff_read(const unsigned P, const unsigned long cycleCounter) { - if (lastOamDmaUpdate != COUNTER_DISABLED) - updateOamDma(cycleCounter); - - switch (P & 0x7F) { - case 0x00: - updateInput(); - break; - case 0x04: -// printf("div read\n"); - { - const unsigned long divcycles = (cycleCounter - div_lastUpdate) >> 8; - ioamhram[0x104] = (ioamhram[0x104] + divcycles) & 0xFF; - div_lastUpdate += divcycles << 8; - } - - break; - case 0x05: -// printf("tima read\n"); - if (ioamhram[0x107] & 0x04) - update_tima(cycleCounter); - - break; - case 0x0F: - update_irqEvents(cycleCounter); - ioamhram[0x10F] |= display.getIfReg(cycleCounter) & 3; -// rescheduleIrq(cycleCounter); - break; - case 0x26: -// printf("sound status read\n"); - if (ioamhram[0x126] & 0x80) { - sound.generate_samples(cycleCounter, isDoubleSpeed()); - ioamhram[0x126] = 0xF0 | sound.getStatus(); - } else - ioamhram[0x126] = 0x70; - - break; - case 0x30: - case 0x31: - case 0x32: - case 0x33: - case 0x34: - case 0x35: - case 0x36: - case 0x37: - case 0x38: - case 0x39: - case 0x3A: - case 0x3B: - case 0x3C: - case 0x3D: - case 0x3E: - case 0x3F: - sound.generate_samples(cycleCounter, isDoubleSpeed()); - return sound.waveRamRead(P & 0xF); - case 0x41: - return ioamhram[0x141] | display.get_stat(ioamhram[0x145], cycleCounter); - case 0x44: - return display.getLyReg(cycleCounter/*+4*/); - case 0x69: - return display.cgbBgColorRead(ioamhram[0x168] & 0x3F, cycleCounter); - case 0x6B: - return display.cgbSpColorRead(ioamhram[0x16A] & 0x3F, cycleCounter); - default: break; - } - - return ioamhram[P - 0xFE00]; -} - -unsigned Memory::nontrivial_read(const unsigned P, const unsigned long cycleCounter) { - if (P < 0xFF80) { - if (lastOamDmaUpdate != COUNTER_DISABLED) { - updateOamDma(cycleCounter); - - if ((P >> 8) - oamDmaArea1Lower < oamDmaArea1Width || P >> 8 < oamDmaArea2Upper) - return ioamhram[oamDmaPos]; - } - - if (P < 0xC000) { - if (P < 0x8000) - return romdata[P >> 14][P]; - - if (P < 0xA000) { - if (!display.vramAccessible(cycleCounter)) - return 0xFF; - - return vrambank[P & 0x1FFF]; - } - - if (rsrambankptr) - return rsrambankptr[P]; - - return *rtc.getActive(); - } - - if (P < 0xFE00) - return wramdata[P >> 12 & 1][P & 0xFFF]; - - if (P & 0x100) - return nontrivial_ff_read(P, cycleCounter); - - if (!display.oamAccessible(cycleCounter) || oamDmaPos < 0xA0) - return 0xFF; - } - - return ioamhram[P - 0xFE00]; -} - -void Memory::nontrivial_ff_write(const unsigned P, unsigned data, const unsigned long cycleCounter) { -// printf("mem[0x%X] = 0x%X\n", P, data); - - if (lastOamDmaUpdate != COUNTER_DISABLED) - updateOamDma(cycleCounter); - - switch (P & 0xFF) { - case 0x00: - data = (ioamhram[0x100] & 0xCF) | (data & 0xF0); - supergameboy.joyp_write(data & 0x20, data & 0x10); - break; - case 0x01: - update_irqEvents(cycleCounter); - break; - case 0x02: - update_irqEvents(cycleCounter); - - if ((data & 0x81) == 0x81) { - next_serialtime = cycleCounter; - next_serialtime += (isCgb() && (data & 0x2)) ? 128 : 4096; - set_irqEvent(); - } - - rescheduleIrq(cycleCounter); - data |= 0x7C; - break; - //If rom is trying to write to DIV register, reset it to 0. - case 0x04: -// printf("DIV write\n"); - ioamhram[0x104] = 0; - div_lastUpdate = cycleCounter; - return; - case 0x05: - // printf("tima write\n"); - if (ioamhram[0x107] & 0x04) { - update_irqEvents(cycleCounter); - update_tima(cycleCounter); - - if (tmatime - cycleCounter < 4) - tmatime = COUNTER_DISABLED; - - next_timatime = tima_lastUpdate + ((256u - data) << timaClock[ioamhram[0x107] & 3]) + 1; - set_irqEvent(); - rescheduleIrq(cycleCounter); - } - - break; - case 0x06: - if (ioamhram[0x107] & 0x04) { - update_irqEvents(cycleCounter); - update_tima(cycleCounter); - } - - break; - case 0x07: - // printf("tac write: %i\n", data); - data |= 0xF8; - - if (ioamhram[0x107] ^ data) { - if (ioamhram[0x107] & 0x04) { - update_irqEvents(cycleCounter); - update_tima(cycleCounter); - - tima_lastUpdate -= (1u << (timaClock[ioamhram[0x107] & 3] - 1)) + 3; - tmatime -= (1u << (timaClock[ioamhram[0x107] & 3] - 1)) + 3; - next_timatime -= (1u << (timaClock[ioamhram[0x107] & 3] - 1)) + 3; - set_irqEvent(); - update_tima(cycleCounter); - update_irqEvents(cycleCounter); - - tmatime = COUNTER_DISABLED; - next_timatime = COUNTER_DISABLED; - } - - if (data & 4) { - tima_lastUpdate = (cycleCounter >> timaClock[data & 3]) << timaClock[data & 3]; - next_timatime = tima_lastUpdate + ((256u - ioamhram[0x105]) << timaClock[data & 3]) + 1; - } - - set_irqEvent(); - rescheduleIrq(cycleCounter); - } - - break; - case 0x0F: - update_irqEvents(cycleCounter); - display.setIfReg(data, cycleCounter); - ioamhram[0x10F] = 0xE0 | data; - rescheduleIrq(cycleCounter); - return; - case 0x10: - if(!sound.isEnabled()) return; - sound.generate_samples(cycleCounter, isDoubleSpeed()); - sound.set_nr10(data); - data |= 0x80; - break; - case 0x11: - if(!sound.isEnabled()) { - if (isCgb()) - return; - - data &= 0x3F; - } - - sound.generate_samples(cycleCounter, isDoubleSpeed()); - sound.set_nr11(data); - data |= 0x3F; - break; - case 0x12: - if(!sound.isEnabled()) return; - sound.generate_samples(cycleCounter, isDoubleSpeed()); - sound.set_nr12(data); - break; - case 0x13: - if(!sound.isEnabled()) return; - sound.generate_samples(cycleCounter, isDoubleSpeed()); - sound.set_nr13(data); - return; - case 0x14: - if(!sound.isEnabled()) return; - sound.generate_samples(cycleCounter, isDoubleSpeed()); - sound.set_nr14(data); - data |= 0xBF; - break; - case 0x16: - if(!sound.isEnabled()) { - if (isCgb()) - return; - - data &= 0x3F; - } - - sound.generate_samples(cycleCounter, isDoubleSpeed()); - sound.set_nr21(data); - data |= 0x3F; - break; - case 0x17: - if(!sound.isEnabled()) return; - sound.generate_samples(cycleCounter, isDoubleSpeed()); - sound.set_nr22(data); - break; - case 0x18: - if(!sound.isEnabled()) return; - sound.generate_samples(cycleCounter, isDoubleSpeed()); - sound.set_nr23(data); - return; - case 0x19: - if(!sound.isEnabled()) return; - sound.generate_samples(cycleCounter, isDoubleSpeed()); - sound.set_nr24(data); - data |= 0xBF; - break; - case 0x1A: - if(!sound.isEnabled()) return; - sound.generate_samples(cycleCounter, isDoubleSpeed()); - sound.set_nr30(data); - data |= 0x7F; - break; - case 0x1B: - if(!sound.isEnabled() && isCgb()) return; - sound.generate_samples(cycleCounter, isDoubleSpeed()); - sound.set_nr31(data); - return; - case 0x1C: - if(!sound.isEnabled()) return; - sound.generate_samples(cycleCounter, isDoubleSpeed()); - sound.set_nr32(data); - data |= 0x9F; - break; - case 0x1D: - if(!sound.isEnabled()) return; - sound.generate_samples(cycleCounter, isDoubleSpeed()); - sound.set_nr33(data); - return; - case 0x1E: - if(!sound.isEnabled()) return; - sound.generate_samples(cycleCounter, isDoubleSpeed()); - sound.set_nr34(data); - data |= 0xBF; - break; - case 0x20: - if(!sound.isEnabled() && isCgb()) return; - sound.generate_samples(cycleCounter, isDoubleSpeed()); - sound.set_nr41(data); - return; - case 0x21: - if(!sound.isEnabled()) return; - sound.generate_samples(cycleCounter, isDoubleSpeed()); - sound.set_nr42(data); - break; - case 0x22: - if(!sound.isEnabled()) return; - sound.generate_samples(cycleCounter, isDoubleSpeed()); - sound.set_nr43(data); - break; - case 0x23: - if(!sound.isEnabled()) return; - sound.generate_samples(cycleCounter, isDoubleSpeed()); - sound.set_nr44(data); - data |= 0xBF; - break; - case 0x24: - if(!sound.isEnabled()) return; - sound.generate_samples(cycleCounter, isDoubleSpeed()); - sound.set_so_volume(data); - break; - case 0x25: - if(!sound.isEnabled()) return; - sound.generate_samples(cycleCounter, isDoubleSpeed()); - sound.map_so(data); - break; - case 0x26: - if ((ioamhram[0x126] ^ data) & 0x80) { - sound.generate_samples(cycleCounter, isDoubleSpeed()); - - if (!(data & 0x80)) { - for (unsigned i = 0xFF10; i < 0xFF26; ++i) - ff_write(i, 0, cycleCounter); - -// std::memcpy(memory + 0xFF10, soundRegInitValues, sizeof(soundRegInitValues)); - sound.setEnabled(false); - } else { - sound.reset(/*memory + 0xFF00, isDoubleSpeed()*/); - sound.setEnabled(true); - } - } - - data = (data & 0x80) | (ioamhram[0x126] & 0x7F); - break; - case 0x30: - case 0x31: - case 0x32: - case 0x33: - case 0x34: - case 0x35: - case 0x36: - case 0x37: - case 0x38: - case 0x39: - case 0x3A: - case 0x3B: - case 0x3C: - case 0x3D: - case 0x3E: - case 0x3F: - sound.generate_samples(cycleCounter, isDoubleSpeed()); - sound.waveRamWrite(P & 0xF, data); - break; - case 0x40: - if (ioamhram[0x140] != data) { - if ((ioamhram[0x140] ^ data) & 0x80) { - update_irqEvents(cycleCounter); - const unsigned lyc = display.get_stat(ioamhram[0x145], cycleCounter) & 4; - display.enableChange(cycleCounter); - ioamhram[0x144] = 0; -// enable_display = bool(data & 0x80); - ioamhram[0x141] &= 0xF8; - - if (data & 0x80) { - next_blittime = display.nextMode1IrqTime() + (70224 << isDoubleSpeed()); - } else { - ioamhram[0x141] |= lyc; //Mr. Do! needs conicidence flag preserved. - next_blittime = cycleCounter + (456 * 4 << isDoubleSpeed()); - - if (hdma_transfer) - next_dmatime = cycleCounter; - - next_hdmaReschedule = COUNTER_DISABLED; - } - - set_event(); - } - - if ((ioamhram[0x140] ^ data) & 0x4) { - display.spriteSizeChange(data & 0x4, cycleCounter); - } - - if ((ioamhram[0x140] ^ data) & 0x20) { -// printf("%u: weChange to %u\n", CycleCounter, (data & 0x20) != 0); - display.weChange(data & 0x20, cycleCounter); - } - - if ((ioamhram[0x140] ^ data) & 0x40) - display.wdTileMapSelectChange(data & 0x40, cycleCounter); - - if ((ioamhram[0x140] ^ data) & 0x08) - display.bgTileMapSelectChange(data & 0x08, cycleCounter); - - if ((ioamhram[0x140] ^ data) & 0x10) - display.bgTileDataSelectChange(data & 0x10, cycleCounter); - - if ((ioamhram[0x140] ^ data) & 0x02) - display.spriteEnableChange(data & 0x02, cycleCounter); - - if ((ioamhram[0x140] ^ data) & 0x01) - display.bgEnableChange(data & 0x01, cycleCounter); - - ioamhram[0x140] = data; - rescheduleIrq(cycleCounter); - rescheduleHdmaReschedule(); - } - - return; - case 0x41: - display.lcdstatChange(data, cycleCounter); - rescheduleIrq(cycleCounter); - data = (ioamhram[0x141] & 0x87) | (data & 0x78); - break; - case 0x42: - display.scyChange(data, cycleCounter); - break; - case 0x43: - display.scxChange(data, cycleCounter); - rescheduleIrq(cycleCounter); - rescheduleHdmaReschedule(); - break; - //If rom is trying to write to LY register, reset it to 0. - case 0x44: - if (ioamhram[0x140] & 0x80) { - std::printf("ly write\n"); - display.lyWrite(cycleCounter); - rescheduleIrq(cycleCounter); - rescheduleHdmaReschedule(); - } - - return; - case 0x45: - display.lycRegChange(data, cycleCounter); - rescheduleIrq(cycleCounter); - break; - case 0x46: - if (lastOamDmaUpdate != COUNTER_DISABLED) - endOamDma(cycleCounter); - - lastOamDmaUpdate = cycleCounter; - nextOamEventTime = cycleCounter + 8; - ioamhram[0x146] = data; - oamDmaInitSetup(); - setOamDmaSrc(); - return; - case 0x47: - if (!isCgb()) { - display.dmgBgPaletteChange(data, cycleCounter); - } - - break; - case 0x48: - if (!isCgb()) { - display.dmgSpPalette1Change(data, cycleCounter); - } - - break; - case 0x49: - if (!isCgb()) { - display.dmgSpPalette2Change(data, cycleCounter); - } - - break; - case 0x4A: -// printf("%u: wyChange to %u\n", CycleCounter, data); - display.wyChange(data, cycleCounter); - rescheduleIrq(cycleCounter); - rescheduleHdmaReschedule(); - break; - case 0x4B: -// printf("%u: wxChange to %u\n", CycleCounter, data); - display.wxChange(data, cycleCounter); - rescheduleIrq(cycleCounter); - rescheduleHdmaReschedule(); - break; - - //cgb stuff: - case 0x4D: - ioamhram[0x14D] |= data & 0x01; - return; - //Select vram bank - case 0x4F: - if (isCgb()) { - vrambank = vram + (data & 0x01) * 0x2000; - - if (oamDmaArea1Lower == 0x80) - setOamDmaSrc(); - - ioamhram[0x14F] = 0xFE | data; - } - - return; - case 0x51: - dmaSource = data << 8 | (dmaSource & 0xFF); - return; - case 0x52: - dmaSource = (dmaSource & 0xFF00) | (data & 0xF0); - return; - case 0x53: - dmaDestination = data << 8 | (dmaDestination & 0xFF); - return; - case 0x54: - dmaDestination = (dmaDestination & 0xFF00) | (data & 0xF0); - return; - case 0x55: - if (!isCgb()) - return; - - ioamhram[0x155] = data & 0x7F; - - if (hdma_transfer) { - if (!(data & 0x80)) { - ioamhram[0x155] |= 0x80; - - if (next_dmatime > cycleCounter) { - hdma_transfer = 0; - next_hdmaReschedule = next_dmatime = COUNTER_DISABLED; - set_event(); - } - } - - return; - } - - if (data & 0x80) { - hdma_transfer = 1; - - if (!(ioamhram[0x140] & 0x80) || display.isHdmaPeriod(cycleCounter)) { - next_dmatime = cycleCounter; - next_hdmaReschedule = COUNTER_DISABLED; - } else { - next_dmatime = display.nextHdmaTime(cycleCounter); - next_hdmaReschedule = display.nextHdmaTimeInvalid(); - } - } else - next_dmatime = cycleCounter; - - set_event(); - return; - case 0x56: - if (isCgb()) { - ioamhram[0x156] = data | 0x3E; - } - - return; - //Set bg palette index - case 0x68: - if (isCgb()) - ioamhram[0x168] = data | 0x40; - - return; - //Write to bg palette data - case 0x69: - if (isCgb()) { - const unsigned index = ioamhram[0x168] & 0x3F; - - display.cgbBgColorChange(index, data, cycleCounter); - - ioamhram[0x168] = (ioamhram[0x168] & ~0x3F) | ((index + (ioamhram[0x168] >> 7)) & 0x3F); - } - - return; - case 0x6A: - if (isCgb()) - ioamhram[0x16A] = data | 0x40; - - return; - //Write to obj palette data. - case 0x6B: - if (isCgb()) { - const unsigned index = ioamhram[0x16A] & 0x3F; - - display.cgbSpColorChange(index, data, cycleCounter); - - ioamhram[0x16A] = (ioamhram[0x16A] & ~0x3F) | ((index + (ioamhram[0x16A] >> 7)) & 0x3F); - } - - return; - case 0x6C: - if (isCgb()) - ioamhram[0x16C] = data | 0xFE; - - return; - case 0x70: - if (isCgb()) { - wramdata[1] = wramdata[0] + ((data & 0x07) ? (data & 0x07) : 1) * 0x1000; - - if (oamDmaArea1Lower == 0xC0) - setOamDmaSrc(); - else - wmem[0xD] = rmem[0xD] = wramdata[1] - 0xD000; - - ioamhram[0x170] = data | 0xF8; - } - - return; - case 0x72: - case 0x73: - case 0x74: - if (isCgb()) - break; - - return; - case 0x75: - if (isCgb()) - ioamhram[0x175] = data | 0x8F; - - return; - case 0xFF: - ioamhram[0x1FF] = data; - rescheduleIrq(cycleCounter); - return; - default: -// if (P < 0xFF80) - return; - } - - ioamhram[P - 0xFE00] = data; -} - -void Memory::mbc_write(const unsigned P, const unsigned data) { -// printf("mem[0x%X] = 0x%X\n", P, data); - - switch (P >> 12 & 0x7) { - case 0x0: - case 0x1: //Most MBCs write 0x?A to addresses lower than 0x2000 to enable ram. - if (romtype == mbc2 && (P & 0x0100)) break; - - enable_ram = (data & 0x0F) == 0xA; - - if (rtcRom) - rtc.setEnabled(enable_ram); - - setRambank(); - break; - //MBC1 writes ???n nnnn to address area 0x2000-0x3FFF, ???n nnnn makes up the lower digits to determine which rombank to load. - //MBC3 writes ?nnn nnnn to address area 0x2000-0x3FFF, ?nnn nnnn makes up the lower digits to determine which rombank to load. - //MBC5 writes nnnn nnnn to address area 0x2000-0x2FFF, nnnn nnnn makes up the lower digits to determine which rombank to load. - //MBC5 writes bit8 of the number that determines which rombank to load to address 0x3000-0x3FFF. - case 0x2: - switch (romtype) { - case plain: - return; - case mbc5: - rombank = (rombank & 0x100) | data; - rombank = rombank & (rombanks - 1); - setRombank(); - return; - default: - break; //Only supposed to break one level. - } - case 0x3: - switch (romtype) { - case mbc1: - rombank = rambank_mode ? data & 0x1F : ((rombank & 0x60) | (data & 0x1F)); - break; - case mbc2: - if (P & 0x0100) { - rombank = data & 0x0F; - break; - } - - return; - case mbc3: - rombank = data & 0x7F; - break; - case mbc5: - rombank = (data & 0x1) << 8 | (rombank & 0xFF); - break; - default: - return; - } - - rombank = rombank & (rombanks - 1); - setRombank(); - break; - //MBC1 writes ???? ??nn to area 0x4000-0x5FFF either to determine rambank to load, or upper 2 bits of the rombank number to load, depending on rom-mode. - //MBC3 writes ???? ??nn to area 0x4000-0x5FFF to determine rambank to load - //MBC5 writes ???? nnnn to area 0x4000-0x5FFF to determine rambank to load - case 0x4: - case 0x5: - switch (romtype) { - case mbc1: - if (rambank_mode) { - rambank = data & 0x03; - break; - } - - rombank = (data & 0x03) << 5 | (rombank & 0x1F); - rombank = rombank & (rombanks - 1); - setRombank(); - return; - case mbc3: - if (rtcRom) - rtc.swapActive(data); - - rambank = data & 0x03; - break; - case mbc5: - rambank = data & 0x0F; - break; - default: - return; - } - - rambank &= rambanks - 1; - setRambank(); - break; - //MBC1: If ???? ???1 is written to area 0x6000-0x7FFFF rom will be set to rambank mode. - case 0x6: - case 0x7: - switch (romtype) { - case mbc1: - rambank_mode = data & 0x01; - break; - case mbc3: - rtc.latch(data); - break; - default: - break; - } - - break; -// default: break; - } -} - -void Memory::nontrivial_write(const unsigned P, const unsigned data, const unsigned long cycleCounter) { - if (lastOamDmaUpdate != COUNTER_DISABLED) { - updateOamDma(cycleCounter); - - if ((P >> 8) - oamDmaArea1Lower < oamDmaArea1Width || P >> 8 < oamDmaArea2Upper) { - ioamhram[oamDmaPos] = data; - return; - } - } - - if (P < 0xFE00) { - if (P < 0xA000) { - if (P < 0x8000) { - mbc_write(P, data); - } else if (display.vramAccessible(cycleCounter)) { - display.vramChange(cycleCounter); - vrambank[P & 0x1FFF] = data; - } - } else if (P < 0xC000) { - if (wsrambankptr) - wsrambankptr[P] = data; - else - rtc.write(data); - } else - wramdata[P >> 12 & 1][P & 0xFFF] = data; - } else if (((P + 1) & 0xFFFF) < 0xFF81) { - if (P < 0xFF00) { - if (display.oamAccessible(cycleCounter) && oamDmaPos >= 0xA0) { - display.oamChange(cycleCounter); - rescheduleIrq(cycleCounter); - rescheduleHdmaReschedule(); - ioamhram[P - 0xFE00] = data; - } - } else - nontrivial_ff_write(P, data, cycleCounter); - } else - ioamhram[P - 0xFE00] = data; -} - -static const std::string stripExtension(const std::string &str) { - const std::string::size_type lastDot = str.find_last_of('.'); - const std::string::size_type lastSlash = str.find_last_of('/'); - - if (lastDot != std::string::npos && (lastSlash == std::string::npos || lastSlash < lastDot)) - return str.substr(0, lastDot); - - return str; -} - -static const std::string stripDir(const std::string &str) { - const std::string::size_type lastSlash = str.find_last_of('/'); - - if (lastSlash != std::string::npos) - return str.substr(lastSlash + 1); - - return str; -} - -const std::string Memory::saveBasePath() const { - return saveDir.empty() ? defaultSaveBasePath : saveDir + stripDir(defaultSaveBasePath); -} - -void Memory::set_savedir(const char *dir) { - saveDir = dir ? dir : ""; - - if (!saveDir.empty() && saveDir[saveDir.length() - 1] != '/') { - saveDir += '/'; - } -} - -static void enforce8bit(unsigned char *data, unsigned long sz) { - if (static_cast(0x100)) - while (sz--) - *data++ &= 0xFF; -} - -static unsigned pow2ceil(unsigned n) { - --n; - n |= n >> 1; - n |= n >> 2; - n |= n >> 4; - n |= n >> 8; - ++n; - - return n; -} - -bool Memory::loadROM(const bool forceDmg) { - defaultSaveBasePath = ""; - - { - unsigned char *header = (unsigned char*)supergameboy.romdata; - - cgb = header[0x0143] >> 7 & 1; - - if (cgb & forceDmg) { - cgb = false; - defaultSaveBasePath += "_dmg"; - } - - switch (header[0x0147]) { - case 0x00: std::printf("Plain ROM loaded.\n"); - romtype = plain; - break; - case 0x01: std::printf("MBC1 ROM loaded.\n"); - romtype = mbc1; - break; - case 0x02: std::printf("MBC1 ROM+RAM loaded.\n"); - romtype = mbc1; - break; - case 0x03: std::printf("MBC1 ROM+RAM+BATTERY loaded.\n"); - romtype = mbc1; - battery = 1; - break; - case 0x05: std::printf("MBC2 ROM loaded.\n"); - romtype = mbc2; - break; - case 0x06: std::printf("MBC2 ROM+BATTERY loaded.\n"); - romtype = mbc2; - battery = 1; - break; - case 0x08: std::printf("Plain ROM with additional RAM loaded.\n"); - break; - case 0x09: std::printf("Plain ROM with additional RAM and Battery loaded.\n"); - battery = 1; - break; - case 0x0B: /*cout << "MM01 ROM not supported.\n";*/ - return 1; - break; - case 0x0C: /*cout << "MM01 ROM not supported.\n";*/ - return 1; - break; - case 0x0D: /*cout << "MM01 ROM not supported.\n";*/ - return 1; - break; - case 0x0F: std::printf("MBC3 ROM+TIMER+BATTERY loaded.\n"); - romtype = mbc3; - battery = true; - rtcRom = true; - break; - case 0x10: std::printf("MBC3 ROM+TIMER+RAM+BATTERY loaded.\n"); - romtype = mbc3; - battery = true; - rtcRom = true; - break; - case 0x11: std::printf("MBC3 ROM loaded.\n"); - romtype = mbc3; - break; - case 0x12: std::printf("MBC3 ROM+RAM loaded.\n"); - romtype = mbc3; - break; - case 0x13: std::printf("MBC3 ROM+RAM+BATTERY loaded.\n"); - romtype = mbc3; - battery = 1; - break; - case 0x15: /*cout << "MBC4 ROM not supported.\n";*/ - return 1; - break; - case 0x16: /*cout << "MBC4 ROM not supported.\n";*/ - return 1; - break; - case 0x17: /*cout << "MBC4 ROM not supported.\n";*/ - return 1; - break; - case 0x19: std::printf("MBC5 ROM loaded.\n"); - romtype = mbc5; - break; - case 0x1A: std::printf("MBC5 ROM+RAM loaded.\n"); - romtype = mbc5; - break; - case 0x1B: std::printf("MBC5 ROM+RAM+BATTERY loaded.\n"); - romtype = mbc5; - battery = 1; - break; - case 0x1C: std::printf("MBC5+RUMLE ROM not supported.\n"); - romtype = mbc5; - break; - case 0x1D: std::printf("MBC5+RUMLE+RAM ROM not suported.\n"); - romtype = mbc5; - break; - case 0x1E: std::printf("MBC5+RUMLE+RAM+BATTERY ROM not supported.\n"); - romtype = mbc5; - battery = 1; - break; - case 0xFC: /*cout << "Pocket Camera ROM not supported.\n";*/ - return 1; - break; - case 0xFD: /*cout << "Bandai TAMA5 ROM not supported.\n";*/ - return 1; - break; - case 0xFE: /*cout << "HuC3 ROM not supported.\n";*/ - return 1; - break; - case 0xFF: /*cout << "HuC1 ROM not supported.\n";*/ - return 1; - break; - default: /*cout << "Wrong data-format, corrupt or unsupported ROM loaded.\n";*/ - return 1; - } - - /*switch (header[0x0148]) { - case 0x00: - rombanks = 2; - break; - case 0x01: - rombanks = 4; - break; - case 0x02: - rombanks = 8; - break; - case 0x03: - rombanks = 16; - break; - case 0x04: - rombanks = 32; - break; - case 0x05: - rombanks = 64; - break; - case 0x06: - rombanks = 128; - break; - case 0x07: - rombanks = 256; - break; - case 0x08: - rombanks = 512; - break; - case 0x52: - rombanks = 72; - break; - case 0x53: - rombanks = 80; - break; - case 0x54: - rombanks = 96; - break; - default: - return 1; - } - - printf("rombanks: %u\n", rombanks);*/ - - switch (header[0x0149]) { - case 0x00: /*cout << "No RAM\n";*/ rambanks = romtype == mbc2; break; - case 0x01: /*cout << "2kB RAM\n";*/ /*rambankrom=1; break;*/ - case 0x02: /*cout << "8kB RAM\n";*/ - rambanks = 1; - break; - case 0x03: /*cout << "32kB RAM\n";*/ - rambanks = 4; - break; - case 0x04: /*cout << "128kB RAM\n";*/ - rambanks = 16; - break; - case 0x05: /*cout << "undocumented kB RAM\n";*/ - rambanks = 16; - break; - default: /*cout << "Wrong data-format, corrupt or unsupported ROM loaded.\n";*/ - rambanks = 16; - break; - } - } - - std::printf("rambanks: %u\n", rambanks); - - rombanks = pow2ceil(supergameboy.romsize / 0x4000); - std::printf("rombanks: %u\n", supergameboy.romsize / 0x4000); - - delete []memchunk; - memchunk = new unsigned char[0x4000 + rombanks * 0x4000ul + rambanks * 0x2000ul + (isCgb() ? 0x8000 : 0x2000) + 0x4000]; - - romdata[0] = memchunk + 0x4000; - rambankdata = romdata[0] + rombanks * 0x4000ul; - wramdata[0] = rambankdata + rambanks * 0x2000; - rdisabled_ram = wramdata[0] + (isCgb() ? 0x8000 : 0x2000); - wdisabled_ram = rdisabled_ram + 0x2000; - - wramdata[1] = wramdata[0] + 0x1000; - std::memset(rdisabled_ram, 0xFF, 0x2000); - - memcpy((char*)romdata[0], supergameboy.romdata, (supergameboy.romsize / 0x4000) * 0x4000ul); - // In case rombanks isn't a power of 2, allocate a disabled area for invalid rombank addresses. This is only based on speculation. - std::memset(romdata[0] + (supergameboy.romsize / 0x4000) * 0x4000ul, 0xFF, (rombanks - supergameboy.romsize / 0x4000) * 0x4000ul); - enforce8bit(romdata[0], rombanks * 0x4000ul); - - sound.init(isCgb()); - display.reset(ioamhram, isCgb()); - - return 0; -} - -void Memory::loadSavedata() { - if (battery) { - if (supergameboy.ramdata) { - memcpy((char*)rambankdata, supergameboy.ramdata, std::min(supergameboy.ramsize, (unsigned int)(rambanks * 0x2000ul))); - enforce8bit(rambankdata, rambanks * 0x2000ul); - } - } - - if (rtcRom) { - if (supergameboy.rtcdata && supergameboy.rtcsize >= 4) { - unsigned long basetime = 0; - - basetime = basetime << 8 | (supergameboy.rtcdata[0]); - basetime = basetime << 8 | (supergameboy.rtcdata[1]); - basetime = basetime << 8 | (supergameboy.rtcdata[2]); - basetime = basetime << 8 | (supergameboy.rtcdata[3]); - - rtc.setBaseTime(basetime); - } - } -} - -void Memory::saveSavedata() { - if (battery) { - if (supergameboy.ramdata) { - memcpy(supergameboy.ramdata, (char*)rambankdata, std::min(supergameboy.ramsize, (unsigned int)(rambanks * 0x2000ul))); - } - } - - if (rtcRom) { - if (supergameboy.rtcdata && supergameboy.rtcsize >= 4) { - const unsigned long basetime = rtc.getBaseTime(); - - supergameboy.rtcdata[0] = basetime >> 24; - supergameboy.rtcdata[1] = basetime >> 16; - supergameboy.rtcdata[2] = basetime >> 8; - supergameboy.rtcdata[3] = basetime >> 0; - } - } -} - -unsigned Memory::fillSoundBuffer(const unsigned long cycleCounter) { - sound.generate_samples(cycleCounter, isDoubleSpeed()); - return sound.fillBuffer(); -} - -void Memory::setVideoBlitter(Gambatte::VideoBlitter *const vb) { - display.setVideoBlitter(vb); -} - -void Memory::videoBufferChange() { - display.videoBufferChange(); -} - -void Memory::setVideoFilter(const unsigned int n) { - display.setVideoFilter(n); -} - -void Memory::setDmgPaletteColor(unsigned palNum, unsigned colorNum, unsigned long rgb32) { - display.setDmgPaletteColor(palNum, colorNum, rgb32); -} - -Memory::~Memory() { - saveSavedata(); - - delete []memchunk; -} diff --git a/supergameboy/libgambatte/src/memory.h b/supergameboy/libgambatte/src/memory.h deleted file mode 100644 index eb9f3197..00000000 --- a/supergameboy/libgambatte/src/memory.h +++ /dev/null @@ -1,238 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aam�s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef MEMORY_H -#define MEMORY_H - -class SaveState; - -#include "int.h" -#include "video.h" -#include "sound.h" - -#include "interrupter.h" -#include "rtc.h" -#include - -namespace Gambatte { -class InputStateGetter; -class FilterInfo; -} - -class Memory { -public: - enum { COUNTER_DISABLED = 0xFFFFFFFFu }; - -private: - enum cartridgetype { plain, mbc1, mbc2, mbc3, mbc5 }; - enum events { HDMA_RESCHEDULE, DMA, INTERRUPTS, BLIT, UNHALT, OAM, END }; - enum irqEvents { /*MODE0, MODE1, MODE2, LYC,*/ TIMA, /*M0RESC,*/ SERIAL }; - - unsigned char ioamhram[0x200]; - unsigned char vram[0x2000 * 2]; - unsigned char *rmem[0x10]; - unsigned char *wmem[0x10]; - - unsigned char *memchunk; - unsigned char *romdata[2]; - unsigned char *wramdata[2]; - unsigned char *rambankdata; - unsigned char *rdisabled_ram; - unsigned char *wdisabled_ram; - unsigned char *oamDmaSrc; - unsigned char *vrambank; - unsigned char *rsrambankptr; - unsigned char *wsrambankptr; - - Gambatte::InputStateGetter *getInput; - - unsigned long div_lastUpdate; - unsigned long tima_lastUpdate; - unsigned long next_timatime; - unsigned long next_blittime; - unsigned long nextIntTime; - unsigned long minIntTime; - unsigned long next_dmatime; - unsigned long next_hdmaReschedule; - unsigned long next_unhalttime; - unsigned long next_endtime; - unsigned long next_irqEventTime; - unsigned long tmatime; - unsigned long next_serialtime; - unsigned long next_eventtime; - unsigned long lastOamDmaUpdate; - unsigned long nextOamEventTime; - - LCD display; - PSG sound; - Interrupter interrupter; - Rtc rtc; - - events next_event; - irqEvents next_irqEvent; - cartridgetype romtype; - - std::string defaultSaveBasePath; - std::string saveDir; - - unsigned short rombanks; - unsigned short rombank; - unsigned short dmaSource; - unsigned short dmaDestination; - - unsigned char rambank; - unsigned char rambanks; - unsigned char oamDmaArea1Lower; - unsigned char oamDmaArea1Width; - unsigned char oamDmaArea2Upper; - unsigned char oamDmaPos; - - bool cgb; - bool doubleSpeed; - bool IME; - bool enable_ram; - bool rambank_mode; - bool battery, rtcRom; - bool hdma_transfer; - bool active; - - void updateInput(); - - void setRombank(); - void setRambank(); - void setBanks(); - void oamDmaInitSetup(); - void setOamDmaArea(); - void updateOamDma(unsigned long cycleCounter); - void startOamDma(unsigned long cycleCounter); - void endOamDma(unsigned long cycleCounter); - void setOamDmaSrc(); - - unsigned nontrivial_ff_read(unsigned P, unsigned long cycleCounter); - unsigned nontrivial_read(unsigned P, unsigned long cycleCounter); - void nontrivial_ff_write(unsigned P, unsigned data, unsigned long cycleCounter); - void mbc_write(unsigned P, unsigned data); - void nontrivial_write(unsigned P, unsigned data, unsigned long cycleCounter); - - void set_event(); - void set_irqEvent(); - void update_irqEvents(unsigned long cc); - void update_tima(unsigned long cycleCounter); - - void rescheduleIrq(unsigned long cycleCounter); - void rescheduleHdmaReschedule(); - - bool isDoubleSpeed() const { return doubleSpeed; } - -public: - Memory(const Interrupter &interrupter); - ~Memory(); - - void updateVideo(unsigned cycleCounter) { display.update(cycleCounter); } - unsigned lyCounter(unsigned cycleCounter) { return display.getLyReg(cycleCounter); } - - void setStatePtrs(SaveState &state); - unsigned long saveState(SaveState &state, unsigned long cc); - void loadState(const SaveState &state, unsigned long oldCc); - void loadSavedata(); - void saveSavedata(); - const std::string saveBasePath() const; - - void setOsdElement(std::auto_ptr osdElement) { - display.setOsdElement(osdElement); - } - - void speedChange(unsigned long cycleCounter); - bool isCgb() const { return cgb; } - bool getIME() const { return IME; } - unsigned long getNextEventTime() const { return next_eventtime; } - - bool isActive() const { return active; } - - void ei(unsigned long cycleCounter); - - void di() { - IME = 0; - nextIntTime = COUNTER_DISABLED; - - if (next_event == INTERRUPTS) - set_event(); - -// next_eitime=0; -// if(next_event==EI) set_event(); - } - - unsigned ff_read(const unsigned P, const unsigned long cycleCounter) { - return P < 0xFF80 ? nontrivial_ff_read(P, cycleCounter) : ioamhram[P - 0xFE00]; - } - - unsigned read(const unsigned P, const unsigned long cycleCounter) { - return rmem[P >> 12] ? rmem[P >> 12][P] : nontrivial_read(P, cycleCounter); - } - - void write(const unsigned P, const unsigned data, const unsigned long cycleCounter) { - if (wmem[P >> 12]) - wmem[P >> 12][P] = data; - else - nontrivial_write(P, data, cycleCounter); - } - - void ff_write(const unsigned P, const unsigned data, const unsigned long cycleCounter) { - if (((P + 1) & 0xFF) < 0x81) - nontrivial_ff_write(P, data, cycleCounter); - else - ioamhram[P - 0xFE00] = data; - } - - unsigned long event(unsigned long cycleCounter); - unsigned long resetCounters(unsigned long cycleCounter); - - bool loadROM(bool forceDmg); - void set_savedir(const char *dir); - - void setInputStateGetter(Gambatte::InputStateGetter *getInput) { - this->getInput = getInput; - } - - void schedule_unhalt(); - void incEndtime(unsigned long inc); - void setEndtime(unsigned long cc, unsigned long inc); - - void setSoundBuffer(Gambatte::uint_least32_t *const buf) { sound.setBuffer(buf); } - unsigned fillSoundBuffer(unsigned long cc); - void setVideoBlitter(Gambatte::VideoBlitter * vb); - void setVideoFilter(unsigned int n); - - void videoBufferChange(); - - unsigned videoWidth() const { - return display.videoWidth(); - } - - unsigned videoHeight() const { - return display.videoHeight(); - } - - std::vector filterInfo() const { - return display.filterInfo(); - } - - void setDmgPaletteColor(unsigned palNum, unsigned colorNum, unsigned long rgb32); -}; - -#endif diff --git a/supergameboy/libgambatte/src/osd_element.h b/supergameboy/libgambatte/src/osd_element.h deleted file mode 100644 index 2517d34f..00000000 --- a/supergameboy/libgambatte/src/osd_element.h +++ /dev/null @@ -1,65 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2008 by Sindre Aam�s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef OSD_ELEMENT_H -#define OSD_ELEMENT_H - -#include "int.h" - -class OsdElement { -public: - enum Opacity { SEVEN_EIGHTHS, THREE_FOURTHS }; - -private: - Opacity opacity_; - unsigned x_; - unsigned y_; - unsigned w_; - unsigned h_; - -protected: - OsdElement(unsigned x = 0, unsigned y = 0, unsigned w = 0, unsigned h = 0, Opacity opacity = SEVEN_EIGHTHS) { - setPos(x, y); - setSize(w, h); - setOpacity(opacity); - } - - void setPos(unsigned x, unsigned y) { - x_ = x; - y_ = y; - } - - void setSize(unsigned w, unsigned h) { - w_ = w; - h_ = h; - } - - void setOpacity(Opacity opacity) { opacity_ = opacity; } - -public: - virtual ~OsdElement() {} - unsigned x() const { return x_; } - unsigned y() const { return y_; } - unsigned w() const { return w_; } - unsigned h() const { return h_; } - Opacity opacity() const { return opacity_; } - - virtual const Gambatte::uint_least32_t* update() = 0; -}; - -#endif diff --git a/supergameboy/libgambatte/src/rtc.cpp b/supergameboy/libgambatte/src/rtc.cpp deleted file mode 100644 index 75164919..00000000 --- a/supergameboy/libgambatte/src/rtc.cpp +++ /dev/null @@ -1,157 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "rtc.h" -#include "savestate.h" - -using namespace std; - -Rtc::Rtc() : -activeData(NULL), -activeSet(NULL), -baseTime(0), -haltTime(0), -index(5), -dataDh(0), -dataDl(0), -dataH(0), -dataM(0), -dataS(0), -enabled(false), -lastLatchData(false) { -} - -void Rtc::doLatch() { - time_t tmp = ((dataDh & 0x40) ? haltTime : time(NULL)) - baseTime; - - while (tmp > 0x1FF * 86400) { - baseTime += 0x1FF * 86400; - tmp -= 0x1FF * 86400; - dataDh |= 0x80; - } - - dataDl = (tmp / 86400) & 0xFF; - dataDh &= 0xFE; - dataDh |= ((tmp / 86400) & 0x100) >> 8; - tmp %= 86400; - - dataH = tmp / 3600; - tmp %= 3600; - - dataM = tmp / 60; - tmp %= 60; - - dataS = tmp; -} - -void Rtc::doSwapActive() { - if (!enabled || index > 4) { - activeData = NULL; - activeSet = NULL; - } else switch (index) { - case 0x00: - activeData = &dataS; - activeSet = &Rtc::setS; - break; - case 0x01: - activeData = &dataM; - activeSet = &Rtc::setM; - break; - case 0x02: - activeData = &dataH; - activeSet = &Rtc::setH; - break; - case 0x03: - activeData = &dataDl; - activeSet = &Rtc::setDl; - break; - case 0x04: - activeData = &dataDh; - activeSet = &Rtc::setDh; - break; - } -} - -void Rtc::saveState(SaveState &state) const { - state.rtc.baseTime = baseTime; - state.rtc.haltTime = haltTime; - state.rtc.index = index; - state.rtc.dataDh = dataDh; - state.rtc.dataDl = dataDl; - state.rtc.dataH = dataH; - state.rtc.dataM = dataM; - state.rtc.dataS = dataS; - state.rtc.lastLatchData = lastLatchData; -} - -void Rtc::loadState(const SaveState &state, const bool enabled) { - this->enabled = enabled; - - baseTime = state.rtc.baseTime; - haltTime = state.rtc.haltTime; - index = state.rtc.index; - dataDh = state.rtc.dataDh; - dataDl = state.rtc.dataDl; - dataH = state.rtc.dataH; - dataM = state.rtc.dataM; - dataS = state.rtc.dataS; - lastLatchData = state.rtc.lastLatchData; - - doSwapActive(); -} - -void Rtc::setDh(const unsigned new_dh) { - const time_t unixtime = (dataDh & 0x40) ? haltTime : time(NULL); - const time_t old_highdays = ((unixtime - baseTime) / 86400) & 0x100; - baseTime += old_highdays * 86400; - baseTime -= ((new_dh & 0x1) << 8) * 86400; - - if ((dataDh ^ new_dh) & 0x40) { - if (new_dh & 0x40) - haltTime = time(NULL); - else - baseTime += time(NULL) - haltTime; - } -} - -void Rtc::setDl(const unsigned new_lowdays) { - const time_t unixtime = (dataDh & 0x40) ? haltTime : time(NULL); - const time_t old_lowdays = ((unixtime - baseTime) / 86400) & 0xFF; - baseTime += old_lowdays * 86400; - baseTime -= new_lowdays * 86400; -} - -void Rtc::setH(const unsigned new_hours) { - const time_t unixtime = (dataDh & 0x40) ? haltTime : time(NULL); - const time_t old_hours = ((unixtime - baseTime) / 3600) % 24; - baseTime += old_hours * 3600; - baseTime -= new_hours * 3600; -} - -void Rtc::setM(const unsigned new_minutes) { - const time_t unixtime = (dataDh & 0x40) ? haltTime : time(NULL); - const time_t old_minutes = ((unixtime - baseTime) / 60) % 60; - baseTime += old_minutes * 60; - baseTime -= new_minutes * 60; -} - -void Rtc::setS(const unsigned new_seconds) { - const time_t unixtime = (dataDh & 0x40) ? haltTime : time(NULL); - baseTime += (unixtime - baseTime) % 60; - baseTime -= new_seconds; -} diff --git a/supergameboy/libgambatte/src/rtc.h b/supergameboy/libgambatte/src/rtc.h deleted file mode 100644 index 40905c18..00000000 --- a/supergameboy/libgambatte/src/rtc.h +++ /dev/null @@ -1,97 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef RTC_H -#define RTC_H - -class SaveState; - -#include - -class Rtc { -private: - unsigned char *activeData; - void (Rtc::*activeSet)(unsigned); - std::time_t baseTime; - std::time_t haltTime; - unsigned char index; - unsigned char dataDh; - unsigned char dataDl; - unsigned char dataH; - unsigned char dataM; - unsigned char dataS; - bool enabled; - bool lastLatchData; - - void doLatch(); - void doSwapActive(); - void setDh(unsigned new_dh); - void setDl(unsigned new_lowdays); - void setH(unsigned new_hours); - void setM(unsigned new_minutes); - void setS(unsigned new_seconds); - -public: - Rtc(); - - const unsigned char* getActive() const { - return activeData; - } - - std::time_t getBaseTime() const { - return baseTime; - } - - void setBaseTime(const std::time_t baseTime) { - this->baseTime = baseTime; -// doLatch(); - } - - void latch(const unsigned data) { - if (!lastLatchData && data == 1) - doLatch(); - - lastLatchData = data; - } - - void saveState(SaveState &state) const; - void loadState(const SaveState &state, bool enabled); - - void setEnabled(const bool enabled) { - this->enabled = enabled; - - doSwapActive(); - } - - void swapActive(unsigned index) { - index &= 0xF; - index -= 8; - - this->index = index; - - doSwapActive(); - } - - void write(const unsigned data) { -// if (activeSet) - (this->*activeSet)(data); - *activeData = data; - } -}; - -#endif diff --git a/supergameboy/libgambatte/src/savestate.h b/supergameboy/libgambatte/src/savestate.h deleted file mode 100644 index c4b245fd..00000000 --- a/supergameboy/libgambatte/src/savestate.h +++ /dev/null @@ -1,184 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2008 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef SAVESTATE_H -#define SAVESTATE_H - -#include "int.h" - -struct SaveState { - template - class Ptr { - T *ptr; - unsigned long sz; - - public: - Ptr() : ptr(0), sz(0) {} - const T* get() const { return ptr; } - unsigned long getSz() const { return sz; } - void set(T *ptr, const unsigned long sz) { this->ptr = ptr; this->sz = sz; } - - friend class SaverList; - friend void setInitState(SaveState &, bool); - }; - - struct CPU { - unsigned long cycleCounter; - unsigned short PC; - unsigned short SP; - unsigned char A; - unsigned char B; - unsigned char C; - unsigned char D; - unsigned char E; - unsigned char F; - unsigned char H; - unsigned char L; - bool skip; - bool halted; - } cpu; - - struct Mem { - Ptr vram; - Ptr sram; - Ptr wram; - Ptr ioamhram; - unsigned long div_lastUpdate; - unsigned long tima_lastUpdate; - unsigned long tmatime; - unsigned long next_serialtime; - unsigned long lastOamDmaUpdate; - unsigned long minIntTime; - unsigned short rombank; - unsigned short dmaSource; - unsigned short dmaDestination; - unsigned char rambank; - unsigned char oamDmaPos; - bool IME; - bool enable_ram; - bool rambank_mode; - bool hdma_transfer; - } mem; - - struct PPU { - Ptr drawBuffer; - Ptr bgpData; - Ptr objpData; - //SpriteMapper::OamReader - Ptr oamReaderBuf; - Ptr oamReaderSzbuf; - - unsigned long videoCycles; - unsigned long enableDisplayM0Time; - unsigned char winYPos; - unsigned char drawStartCycle; - unsigned char scReadOffset; - unsigned char lcdc; - //ScReader - unsigned char scx[2]; - unsigned char scy[2]; - //ScxReader - unsigned char scxAnd7; - //WeMasterChecker - bool weMaster; - //WxReader - unsigned char wx; - //Wy - unsigned char wy; - bool lycIrqSkip; - } ppu; - - struct SPU { - struct Duty { - unsigned long nextPosUpdate; - unsigned char nr3; - unsigned char pos; - }; - - struct Env { - unsigned long counter; - unsigned char volume; - }; - - struct LCounter { - unsigned long counter; - unsigned short lengthCounter; - }; - - struct { - struct { - unsigned long counter; - unsigned short shadow; - unsigned char nr0; - bool negging; - } sweep; - Duty duty; - Env env; - LCounter lcounter; - unsigned char nr4; - bool master; - } ch1; - - struct { - Duty duty; - Env env; - LCounter lcounter; - unsigned char nr4; - bool master; - } ch2; - - struct { - Ptr waveRam; - LCounter lcounter; - unsigned long waveCounter; - unsigned long lastReadTime; - unsigned char nr3; - unsigned char nr4; - unsigned char wavePos; - unsigned char sampleBuf; - bool master; - } ch3; - - struct { - struct { - unsigned long counter; - unsigned short reg; - } lfsr; - Env env; - LCounter lcounter; - unsigned char nr4; - bool master; - } ch4; - - unsigned long cycleCounter; - } spu; - - struct RTC { - unsigned long baseTime; - unsigned long haltTime; - unsigned char index; - unsigned char dataDh; - unsigned char dataDl; - unsigned char dataH; - unsigned char dataM; - unsigned char dataS; - bool lastLatchData; - } rtc; -}; - -#endif diff --git a/supergameboy/libgambatte/src/sound.cpp b/supergameboy/libgambatte/src/sound.cpp deleted file mode 100644 index 3ff8063f..00000000 --- a/supergameboy/libgambatte/src/sound.cpp +++ /dev/null @@ -1,155 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aam�s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "sound.h" - -#include "savestate.h" -#include -#include - -/* - Frame Sequencer - - Step Length Ctr Vol Env Sweep - - - - - - - - - - - - - - - - - - - - - - 0 Clock - Clock -S 1 - Clock - - 2 Clock - - - 3 - - - - 4 Clock - Clock - 5 - - - - 6 Clock - - - 7 - - - - - - - - - - - - - - - - - - - - - - - - - Rate 256 Hz 64 Hz 128 Hz - -S) start step on sound power on. -*/ - -// static const unsigned bufferSize = 35112 + 16 + 2048; //FIXME: DMA can prevent process from returning for up to 4096 cycles. - -PSG::PSG() : -buffer(NULL), -lastUpdate(0), -soVol(0), -rsum(0x8000), // initialize to 0x8000 to prevent borrows from high word, xor away later -bufferPos(0), -enabled(false) -{} - -void PSG::init(const bool cgb) { - ch1.init(cgb); - ch2.init(cgb); - ch3.init(cgb); - ch4.init(cgb); -} - -void PSG::reset() { - ch1.reset(); - ch2.reset(); - ch3.reset(); - ch4.reset(); -} - -void PSG::setStatePtrs(SaveState &state) { - ch3.setStatePtrs(state); -} - -void PSG::saveState(SaveState &state) { - ch1.saveState(state); - ch2.saveState(state); - ch3.saveState(state); - ch4.saveState(state); -} - -void PSG::loadState(const SaveState &state) { - ch1.loadState(state); - ch2.loadState(state); - ch3.loadState(state); - ch4.loadState(state); - - lastUpdate = state.cpu.cycleCounter; - set_so_volume(state.mem.ioamhram.get()[0x124]); - map_so(state.mem.ioamhram.get()[0x125]); - enabled = state.mem.ioamhram.get()[0x126] >> 7 & 1; -} - -void PSG::accumulate_channels(const unsigned long cycles) { - Gambatte::uint_least32_t *const buf = buffer + bufferPos; - - std::memset(buf, 0, cycles * sizeof(Gambatte::uint_least32_t)); - ch1.update(buf, soVol, cycles); - ch2.update(buf, soVol, cycles); - ch3.update(buf, soVol, cycles); - ch4.update(buf, soVol, cycles); -} - -void PSG::generate_samples(const unsigned long cycleCounter, const unsigned doubleSpeed) { - const unsigned long cycles = (cycleCounter - lastUpdate) >> (1 + doubleSpeed); - lastUpdate += cycles << (1 + doubleSpeed); - - if (cycles) - accumulate_channels(cycles); - - bufferPos += cycles; -} - -void PSG::resetCounter(const unsigned long newCc, const unsigned long oldCc, const unsigned doubleSpeed) { - generate_samples(oldCc, doubleSpeed); - lastUpdate = newCc - (oldCc - lastUpdate); -} - -unsigned PSG::fillBuffer() { - Gambatte::uint_least32_t sum = rsum; - Gambatte::uint_least32_t *b = buffer; - unsigned n = bufferPos; - - while (n--) { - sum += *b; - *b++ = sum ^ 0x8000; // xor away the initial rsum value of 0x8000 (which prevents borrows from the high word) from the low word - } - - rsum = sum; - - return bufferPos; -} - -#ifdef WORDS_BIGENDIAN -static const unsigned long so1Mul = 0x00000001; -static const unsigned long so2Mul = 0x00010000; -#else -static const unsigned long so1Mul = 0x00010000; -static const unsigned long so2Mul = 0x00000001; -#endif - -void PSG::set_so_volume(const unsigned nr50) { - soVol = (((nr50 & 0x7) + 1) * so1Mul + ((nr50 >> 4 & 0x7) + 1) * so2Mul) * 64; -} - -void PSG::map_so(const unsigned nr51) { - const unsigned long tmp = nr51 * so1Mul + (nr51 >> 4) * so2Mul; - - ch1.setSo((tmp & 0x00010001) * 0xFFFF); - ch2.setSo((tmp >> 1 & 0x00010001) * 0xFFFF); - ch3.setSo((tmp >> 2 & 0x00010001) * 0xFFFF); - ch4.setSo((tmp >> 3 & 0x00010001) * 0xFFFF); -} - -unsigned PSG::getStatus() const { - return ch1.isActive() | (ch2.isActive() << 1) | (ch3.isActive() << 2) | (ch4.isActive() << 3); -} diff --git a/supergameboy/libgambatte/src/sound.h b/supergameboy/libgambatte/src/sound.h deleted file mode 100644 index 06916846..00000000 --- a/supergameboy/libgambatte/src/sound.h +++ /dev/null @@ -1,95 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aam�s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef SOUND_H -#define SOUND_H - -class SaveState; - -#include "int.h" - -#include "sound/channel1.h" -#include "sound/channel2.h" -#include "sound/channel3.h" -#include "sound/channel4.h" - -class PSG { - Channel1 ch1; - Channel2 ch2; - Channel3 ch3; - Channel4 ch4; - - Gambatte::uint_least32_t *buffer; - - unsigned long lastUpdate; - unsigned long soVol; - - Gambatte::uint_least32_t rsum; - - unsigned bufferPos; - - bool enabled; - - void accumulate_channels(unsigned long cycles); - -public: - PSG(); - void init(bool cgb); - void reset(); - void setStatePtrs(SaveState &state); - void saveState(SaveState &state); - void loadState(const SaveState &state); - - void generate_samples(unsigned long cycleCounter, unsigned doubleSpeed); - void resetCounter(unsigned long newCc, unsigned long oldCc, unsigned doubleSpeed); - unsigned fillBuffer(); - void setBuffer(Gambatte::uint_least32_t *const buf) { buffer = buf; bufferPos = 0; } - - bool isEnabled() const { return enabled; } - void setEnabled(bool value) { enabled = value; } - - void set_nr10(unsigned data) { ch1.setNr0(data); } - void set_nr11(unsigned data) { ch1.setNr1(data); } - void set_nr12(unsigned data) { ch1.setNr2(data); } - void set_nr13(unsigned data) { ch1.setNr3(data); } - void set_nr14(unsigned data) { ch1.setNr4(data); } - - void set_nr21(unsigned data) { ch2.setNr1(data); } - void set_nr22(unsigned data) { ch2.setNr2(data); } - void set_nr23(unsigned data) { ch2.setNr3(data); } - void set_nr24(unsigned data) { ch2.setNr4(data); } - - void set_nr30(unsigned data) { ch3.setNr0(data); } - void set_nr31(unsigned data) { ch3.setNr1(data); } - void set_nr32(unsigned data) { ch3.setNr2(data); } - void set_nr33(unsigned data) { ch3.setNr3(data); } - void set_nr34(unsigned data) { ch3.setNr4(data); } - unsigned waveRamRead(unsigned index) const { return ch3.waveRamRead(index); } - void waveRamWrite(unsigned index, unsigned data) { ch3.waveRamWrite(index, data); } - - void set_nr41(unsigned data) { ch4.setNr1(data); } - void set_nr42(unsigned data) { ch4.setNr2(data); } - void set_nr43(unsigned data) { ch4.setNr3(data); } - void set_nr44(unsigned data) { ch4.setNr4(data); } - - void set_so_volume(unsigned nr50); - void map_so(unsigned nr51); - unsigned getStatus() const; -}; - -#endif diff --git a/supergameboy/libgambatte/src/sound/channel1.cpp b/supergameboy/libgambatte/src/sound/channel1.cpp deleted file mode 100644 index 5e112eb2..00000000 --- a/supergameboy/libgambatte/src/sound/channel1.cpp +++ /dev/null @@ -1,257 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aam�s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "channel1.h" -#include "../savestate.h" -#include - -Channel1::SweepUnit::SweepUnit(MasterDisabler &disabler, DutyUnit &dutyUnit) : - disableMaster(disabler), - dutyUnit(dutyUnit), - shadow(0), - nr0(0), - negging(false) -{} - -unsigned Channel1::SweepUnit::calcFreq() { - unsigned freq = shadow >> (nr0 & 0x07); - - if (nr0 & 0x08) { - freq = shadow - freq; - negging = true; - } else - freq = shadow + freq; - - if (freq & 2048) - disableMaster(); - - return freq; -} - -void Channel1::SweepUnit::event() { - const unsigned long period = nr0 >> 4 & 0x07; - - if (period) { - const unsigned freq = calcFreq(); - - if (!(freq & 2048) && (nr0 & 0x07)) { - shadow = freq; - dutyUnit.setFreq(freq, counter); - calcFreq(); - } - - counter += period << 14; - } else - counter += 8ul << 14; -} - -void Channel1::SweepUnit::nr0Change(const unsigned newNr0) { - if (negging && !(newNr0 & 0x08)) - disableMaster(); - - nr0 = newNr0; -} - -void Channel1::SweepUnit::nr4Init(const unsigned long cc) { - negging = false; - shadow = dutyUnit.getFreq(); - - const unsigned period = nr0 >> 4 & 0x07; - const unsigned shift = nr0 & 0x07; - - if (period | shift) - counter = ((cc >> 14) + (period ? period : 8)) << 14; - else - counter = COUNTER_DISABLED; - - if (shift) - calcFreq(); -} - -void Channel1::SweepUnit::reset() { - counter = COUNTER_DISABLED; -} - -void Channel1::SweepUnit::saveState(SaveState &state) const { - state.spu.ch1.sweep.counter = counter; - state.spu.ch1.sweep.shadow = shadow; - state.spu.ch1.sweep.nr0 = nr0; - state.spu.ch1.sweep.negging = negging; -} - -void Channel1::SweepUnit::loadState(const SaveState &state) { - counter = std::max(state.spu.ch1.sweep.counter, state.spu.cycleCounter); - shadow = state.spu.ch1.sweep.shadow; - nr0 = state.spu.ch1.sweep.nr0; - negging = state.spu.ch1.sweep.negging; -} - -Channel1::Channel1() : - staticOutputTest(*this, dutyUnit), - disableMaster(master, dutyUnit), - lengthCounter(disableMaster, 0x3F), - envelopeUnit(staticOutputTest), - sweepUnit(disableMaster, dutyUnit), - cycleCounter(0), - soMask(0), - prevOut(0), - nr4(0), - master(false) -{ - setEvent(); -} - -void Channel1::setEvent() { -// nextEventUnit = &dutyUnit; -// if (sweepUnit.getCounter() < nextEventUnit->getCounter()) - nextEventUnit = &sweepUnit; - if (envelopeUnit.getCounter() < nextEventUnit->getCounter()) - nextEventUnit = &envelopeUnit; - if (lengthCounter.getCounter() < nextEventUnit->getCounter()) - nextEventUnit = &lengthCounter; -} - -void Channel1::setNr0(const unsigned data) { - sweepUnit.nr0Change(data); - setEvent(); -} - -void Channel1::setNr1(const unsigned data) { - lengthCounter.nr1Change(data, nr4, cycleCounter); - dutyUnit.nr1Change(data, cycleCounter); - - setEvent(); -} - -void Channel1::setNr2(const unsigned data) { - if (envelopeUnit.nr2Change(data)) - disableMaster(); - else - staticOutputTest(cycleCounter); - - setEvent(); -} - -void Channel1::setNr3(const unsigned data) { - dutyUnit.nr3Change(data, cycleCounter); - setEvent(); -} - -void Channel1::setNr4(const unsigned data) { - lengthCounter.nr4Change(nr4, data, cycleCounter); - - nr4 = data; - - dutyUnit.nr4Change(data, cycleCounter); - - if (data & 0x80) { //init-bit - nr4 &= 0x7F; - master = !envelopeUnit.nr4Init(cycleCounter); - sweepUnit.nr4Init(cycleCounter); - staticOutputTest(cycleCounter); - } - - setEvent(); -} - -void Channel1::setSo(const unsigned long soMask) { - this->soMask = soMask; - staticOutputTest(cycleCounter); - setEvent(); -} - -void Channel1::reset() { - cycleCounter = 0x1000 | (cycleCounter & 0xFFF); // cycleCounter >> 12 & 7 represents the frame sequencer position. - -// lengthCounter.reset(); - dutyUnit.reset(); - envelopeUnit.reset(); - sweepUnit.reset(); - - setEvent(); -} - -void Channel1::init(const bool cgb) { - lengthCounter.init(cgb); -} - -void Channel1::saveState(SaveState &state) { - sweepUnit.saveState(state); - dutyUnit.saveState(state.spu.ch1.duty, cycleCounter); - envelopeUnit.saveState(state.spu.ch1.env); - lengthCounter.saveState(state.spu.ch1.lcounter); - - state.spu.cycleCounter = cycleCounter; - state.spu.ch1.nr4 = nr4; - state.spu.ch1.master = master; -} - -void Channel1::loadState(const SaveState &state) { - sweepUnit.loadState(state); - dutyUnit.loadState(state.spu.ch1.duty, state.mem.ioamhram.get()[0x111], state.spu.ch1.nr4, state.spu.cycleCounter); - envelopeUnit.loadState(state.spu.ch1.env, state.mem.ioamhram.get()[0x112], state.spu.cycleCounter); - lengthCounter.loadState(state.spu.ch1.lcounter, state.spu.cycleCounter); - - cycleCounter = state.spu.cycleCounter; - nr4 = state.spu.ch1.nr4; - master = state.spu.ch1.master; -} - -void Channel1::update(Gambatte::uint_least32_t *buf, const unsigned long soBaseVol, unsigned long cycles) { - const unsigned long outBase = envelopeUnit.dacIsOn() ? soBaseVol & soMask : 0; - const unsigned long outLow = outBase * (0 - 15ul); - const unsigned long endCycles = cycleCounter + cycles; - - for (;;) { - const unsigned long outHigh = master ? outBase * (envelopeUnit.getVolume() * 2 - 15ul) : outLow; - const unsigned long nextMajorEvent = nextEventUnit->getCounter() < endCycles ? nextEventUnit->getCounter() : endCycles; - unsigned long out = dutyUnit.isHighState() ? outHigh : outLow; - - while (dutyUnit.getCounter() <= nextMajorEvent) { - *buf = out - prevOut; - prevOut = out; - buf += dutyUnit.getCounter() - cycleCounter; - cycleCounter = dutyUnit.getCounter(); - - dutyUnit.event(); - out = dutyUnit.isHighState() ? outHigh : outLow; - } - - if (cycleCounter < nextMajorEvent) { - *buf = out - prevOut; - prevOut = out; - buf += nextMajorEvent - cycleCounter; - cycleCounter = nextMajorEvent; - } - - if (nextEventUnit->getCounter() == nextMajorEvent) { - nextEventUnit->event(); - setEvent(); - } else - break; - } - - if (cycleCounter & SoundUnit::COUNTER_MAX) { - dutyUnit.resetCounters(cycleCounter); - lengthCounter.resetCounters(cycleCounter); - envelopeUnit.resetCounters(cycleCounter); - sweepUnit.resetCounters(cycleCounter); - - cycleCounter -= SoundUnit::COUNTER_MAX; - } -} diff --git a/supergameboy/libgambatte/src/sound/channel1.h b/supergameboy/libgambatte/src/sound/channel1.h deleted file mode 100644 index d790e0ec..00000000 --- a/supergameboy/libgambatte/src/sound/channel1.h +++ /dev/null @@ -1,91 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aam�s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef SOUND_CHANNEL1_H -#define SOUND_CHANNEL1_H - -class SaveState; - -#include "int.h" - -#include "master_disabler.h" -#include "length_counter.h" -#include "duty_unit.h" -#include "envelope_unit.h" -#include "static_output_tester.h" - -class Channel1 { - class SweepUnit : public SoundUnit { - MasterDisabler &disableMaster; - DutyUnit &dutyUnit; - unsigned short shadow; - unsigned char nr0; - bool negging; - - unsigned calcFreq(); - - public: - SweepUnit(MasterDisabler &disabler, DutyUnit &dutyUnit); - void event(); - void nr0Change(unsigned newNr0); - void nr4Init(unsigned long cycleCounter); - void reset(); - void saveState(SaveState &state) const; - void loadState(const SaveState &state); - }; - - friend class StaticOutputTester; - - StaticOutputTester staticOutputTest; - DutyMasterDisabler disableMaster; - LengthCounter lengthCounter; - DutyUnit dutyUnit; - EnvelopeUnit envelopeUnit; - SweepUnit sweepUnit; - - SoundUnit *nextEventUnit; - - unsigned long cycleCounter; - unsigned long soMask; - unsigned long prevOut; - - unsigned char nr4; - bool master; - - void setEvent(); - -public: - Channel1(); - void setNr0(unsigned data); - void setNr1(unsigned data); - void setNr2(unsigned data); - void setNr3(unsigned data); - void setNr4(unsigned data); - - void setSo(unsigned long soMask); - bool isActive() const { return master; } - - void update(Gambatte::uint_least32_t *buf, unsigned long soBaseVol, unsigned long cycles); - - void reset(); - void init(bool cgb); - void saveState(SaveState &state); - void loadState(const SaveState &state); -}; - -#endif diff --git a/supergameboy/libgambatte/src/sound/channel2.cpp b/supergameboy/libgambatte/src/sound/channel2.cpp deleted file mode 100644 index 2db30658..00000000 --- a/supergameboy/libgambatte/src/sound/channel2.cpp +++ /dev/null @@ -1,161 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aam�s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "channel2.h" -#include "../savestate.h" - -Channel2::Channel2() : - staticOutputTest(*this, dutyUnit), - disableMaster(master, dutyUnit), - lengthCounter(disableMaster, 0x3F), - envelopeUnit(staticOutputTest), - cycleCounter(0), - soMask(0), - prevOut(0), - nr4(0), - master(false) -{ - setEvent(); -} - -void Channel2::setEvent() { -// nextEventUnit = &dutyUnit; -// if (envelopeUnit.getCounter() < nextEventUnit->getCounter()) - nextEventUnit = &envelopeUnit; - if (lengthCounter.getCounter() < nextEventUnit->getCounter()) - nextEventUnit = &lengthCounter; -} - -void Channel2::setNr1(const unsigned data) { - lengthCounter.nr1Change(data, nr4, cycleCounter); - dutyUnit.nr1Change(data, cycleCounter); - - setEvent(); -} - -void Channel2::setNr2(const unsigned data) { - if (envelopeUnit.nr2Change(data)) - disableMaster(); - else - staticOutputTest(cycleCounter); - - setEvent(); -} - -void Channel2::setNr3(const unsigned data) { - dutyUnit.nr3Change(data, cycleCounter); - setEvent(); -} - -void Channel2::setNr4(const unsigned data) { - lengthCounter.nr4Change(nr4, data, cycleCounter); - - nr4 = data; - - if (data & 0x80) { //init-bit - nr4 &= 0x7F; - master = !envelopeUnit.nr4Init(cycleCounter); - staticOutputTest(cycleCounter); - } - - dutyUnit.nr4Change(data, cycleCounter); - - setEvent(); -} - -void Channel2::setSo(const unsigned long soMask) { - this->soMask = soMask; - staticOutputTest(cycleCounter); - setEvent(); -} - -void Channel2::reset() { - cycleCounter = 0x1000 | (cycleCounter & 0xFFF); // cycleCounter >> 12 & 7 represents the frame sequencer position. - -// lengthCounter.reset(); - dutyUnit.reset(); - envelopeUnit.reset(); - - setEvent(); -} - -void Channel2::init(const bool cgb) { - lengthCounter.init(cgb); -} - -void Channel2::saveState(SaveState &state) { - dutyUnit.saveState(state.spu.ch2.duty, cycleCounter); - envelopeUnit.saveState(state.spu.ch2.env); - lengthCounter.saveState(state.spu.ch2.lcounter); - - state.spu.ch2.nr4 = nr4; - state.spu.ch2.master = master; -} - -void Channel2::loadState(const SaveState &state) { - dutyUnit.loadState(state.spu.ch2.duty, state.mem.ioamhram.get()[0x116], state.spu.ch2.nr4,state.spu.cycleCounter); - envelopeUnit.loadState(state.spu.ch2.env, state.mem.ioamhram.get()[0x117], state.spu.cycleCounter); - lengthCounter.loadState(state.spu.ch2.lcounter, state.spu.cycleCounter); - - cycleCounter = state.spu.cycleCounter; - nr4 = state.spu.ch2.nr4; - master = state.spu.ch2.master; -} - -void Channel2::update(Gambatte::uint_least32_t *buf, const unsigned long soBaseVol, unsigned long cycles) { - const unsigned long outBase = envelopeUnit.dacIsOn() ? soBaseVol & soMask : 0; - const unsigned long outLow = outBase * (0 - 15ul); - const unsigned long endCycles = cycleCounter + cycles; - - for (;;) { - const unsigned long outHigh = master ? outBase * (envelopeUnit.getVolume() * 2 - 15ul) : outLow; - const unsigned long nextMajorEvent = nextEventUnit->getCounter() < endCycles ? nextEventUnit->getCounter() : endCycles; - unsigned long out = dutyUnit.isHighState() ? outHigh : outLow; - - while (dutyUnit.getCounter() <= nextMajorEvent) { - *buf += out - prevOut; - prevOut = out; - buf += dutyUnit.getCounter() - cycleCounter; - cycleCounter = dutyUnit.getCounter(); - - dutyUnit.event(); - out = dutyUnit.isHighState() ? outHigh : outLow; - } - - if (cycleCounter < nextMajorEvent) { - *buf += out - prevOut; - prevOut = out; - buf += nextMajorEvent - cycleCounter; - cycleCounter = nextMajorEvent; - } - - if (nextEventUnit->getCounter() == nextMajorEvent) { - nextEventUnit->event(); - setEvent(); - } else - break; - } - - if (cycleCounter & SoundUnit::COUNTER_MAX) { - dutyUnit.resetCounters(cycleCounter); - lengthCounter.resetCounters(cycleCounter); - envelopeUnit.resetCounters(cycleCounter); - - cycleCounter -= SoundUnit::COUNTER_MAX; - } -} diff --git a/supergameboy/libgambatte/src/sound/channel2.h b/supergameboy/libgambatte/src/sound/channel2.h deleted file mode 100644 index 24bc66a4..00000000 --- a/supergameboy/libgambatte/src/sound/channel2.h +++ /dev/null @@ -1,70 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aam�s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef SOUND_CHANNEL2_H -#define SOUND_CHANNEL2_H - -class SaveState; - -#include "int.h" - -#include "length_counter.h" -#include "duty_unit.h" -#include "envelope_unit.h" -#include "static_output_tester.h" - -class Channel2 { - friend class StaticOutputTester; - - StaticOutputTester staticOutputTest; - DutyMasterDisabler disableMaster; - LengthCounter lengthCounter; - DutyUnit dutyUnit; - EnvelopeUnit envelopeUnit; - - SoundUnit *nextEventUnit; - - unsigned long cycleCounter; - unsigned long soMask; - unsigned long prevOut; - - unsigned char nr4; - bool master; - - void setEvent(); - -public: - Channel2(); - void setNr1(unsigned data); - void setNr2(unsigned data); - void setNr3(unsigned data); - void setNr4(unsigned data); - - void setSo(unsigned long soMask); - // void deactivate() { disableMaster(); setEvent(); } - bool isActive() const { return master; } - - void update(Gambatte::uint_least32_t *buf, unsigned long soBaseVol, unsigned long cycles); - - void reset(); - void init(bool cgb); - void saveState(SaveState &state); - void loadState(const SaveState &state); -}; - -#endif diff --git a/supergameboy/libgambatte/src/sound/channel3.cpp b/supergameboy/libgambatte/src/sound/channel3.cpp deleted file mode 100644 index 944271e3..00000000 --- a/supergameboy/libgambatte/src/sound/channel3.cpp +++ /dev/null @@ -1,207 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aam�s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "channel3.h" -#include "../savestate.h" -#include -#include - -static inline unsigned toPeriod(const unsigned nr3, const unsigned nr4) { - return 0x800 - ((nr4 << 8 & 0x700) | nr3); -} - -Channel3::Channel3() : - disableMaster(master, waveCounter), - lengthCounter(disableMaster, 0xFF), - cycleCounter(0), - soMask(0), - prevOut(0), - waveCounter(SoundUnit::COUNTER_DISABLED), - lastReadTime(0), - nr0(0), - nr3(0), - nr4(0), - wavePos(0), - rShift(4), - sampleBuf(0), - master(false), - cgb(false) -{} - -void Channel3::setNr0(const unsigned data) { - nr0 = data & 0x80; - - if (!(data & 0x80)) - disableMaster(); -} - -void Channel3::setNr2(const unsigned data) { - rShift = (data >> 5 & 3U) - 1; - - if (rShift > 3) - rShift = 4; -} - -void Channel3::setNr4(const unsigned data) { - lengthCounter.nr4Change(nr4, data, cycleCounter); - - nr4 = data & 0x7F; - - if (data & nr0/* & 0x80*/) { - if (!cgb && waveCounter == cycleCounter + 1) { - const unsigned pos = ((wavePos + 1) & 0x1F) >> 1; - - if (pos < 4) - waveRam[0] = waveRam[pos]; - else - std::memcpy(waveRam, waveRam + (pos & ~3), 4); - } - - master = true; - wavePos = 0; - lastReadTime = waveCounter = cycleCounter + toPeriod(nr3, data) + 3; - } -} - -void Channel3::setSo(const unsigned long soMask) { - this->soMask = soMask; -} - -void Channel3::reset() { - cycleCounter = 0x1000 | (cycleCounter & 0xFFF); // cycleCounter >> 12 & 7 represents the frame sequencer position. - -// lengthCounter.reset(); - sampleBuf = 0; -} - -void Channel3::init(const bool cgb) { - this->cgb = cgb; - lengthCounter.init(cgb); -} - -void Channel3::setStatePtrs(SaveState &state) { - state.spu.ch3.waveRam.set(waveRam, sizeof waveRam); -} - -void Channel3::saveState(SaveState &state) const { - lengthCounter.saveState(state.spu.ch3.lcounter); - - state.spu.ch3.waveCounter = waveCounter; - state.spu.ch3.lastReadTime = lastReadTime; - state.spu.ch3.nr3 = nr3; - state.spu.ch3.nr4 = nr4; - state.spu.ch3.wavePos = wavePos; - state.spu.ch3.sampleBuf = sampleBuf; - state.spu.ch3.master = master; -} - -void Channel3::loadState(const SaveState &state) { - lengthCounter.loadState(state.spu.ch3.lcounter, state.spu.cycleCounter); - - cycleCounter = state.spu.cycleCounter; - waveCounter = std::max(state.spu.ch3.waveCounter, state.spu.cycleCounter); - lastReadTime = state.spu.ch3.lastReadTime; - nr3 = state.spu.ch3.nr3; - nr4 = state.spu.ch3.nr4; - wavePos = state.spu.ch3.wavePos & 0x1F; - sampleBuf = state.spu.ch3.sampleBuf; - master = state.spu.ch3.master; - - nr0 = state.mem.ioamhram.get()[0x11A] & 0x80; - setNr2(state.mem.ioamhram.get()[0x11C]); -} - -void Channel3::updateWaveCounter(const unsigned long cc) { - if (cc >= waveCounter) { - const unsigned period = toPeriod(nr3, nr4); - const unsigned long periods = (cc - waveCounter) / period; - - lastReadTime = waveCounter + periods * period; - waveCounter = lastReadTime + period; - - wavePos += periods + 1; - wavePos &= 0x1F; - - sampleBuf = waveRam[wavePos >> 1]; - } -} - -void Channel3::update(Gambatte::uint_least32_t *buf, const unsigned long soBaseVol, unsigned long cycles) { - const unsigned long outBase = (nr0/* & 0x80*/) ? soBaseVol & soMask : 0; - - if (outBase && rShift != 4) { - const unsigned long endCycles = cycleCounter + cycles; - - for (;;) { - const unsigned long nextMajorEvent = lengthCounter.getCounter() < endCycles ? lengthCounter.getCounter() : endCycles; - unsigned long out = outBase * (master ? ((sampleBuf >> (~wavePos << 2 & 4) & 0xF) >> rShift) * 2 - 15ul : 0 - 15ul); - - while (waveCounter <= nextMajorEvent) { - *buf += out - prevOut; - prevOut = out; - buf += waveCounter - cycleCounter; - cycleCounter = waveCounter; - - lastReadTime = waveCounter; - waveCounter += toPeriod(nr3, nr4); - ++wavePos; - wavePos &= 0x1F; - sampleBuf = waveRam[wavePos >> 1]; - out = outBase * (/*master ? */((sampleBuf >> (~wavePos << 2 & 4) & 0xF) >> rShift) * 2 - 15ul/* : 0 - 15ul*/); - } - - if (cycleCounter < nextMajorEvent) { - *buf += out - prevOut; - prevOut = out; - buf += nextMajorEvent - cycleCounter; - cycleCounter = nextMajorEvent; - } - - if (lengthCounter.getCounter() == nextMajorEvent) { - lengthCounter.event(); - } else - break; - } - } else { - if (outBase) { - const unsigned long out = outBase * (0 - 15ul); - - *buf += out - prevOut; - prevOut = out; - } - - cycleCounter += cycles; - - while (lengthCounter.getCounter() <= cycleCounter) { - updateWaveCounter(lengthCounter.getCounter()); - lengthCounter.event(); - } - - updateWaveCounter(cycleCounter); - } - - if (cycleCounter & SoundUnit::COUNTER_MAX) { - lengthCounter.resetCounters(cycleCounter); - - if (waveCounter != SoundUnit::COUNTER_DISABLED) - waveCounter -= SoundUnit::COUNTER_MAX; - - lastReadTime -= SoundUnit::COUNTER_MAX; - cycleCounter -= SoundUnit::COUNTER_MAX; - } -} diff --git a/supergameboy/libgambatte/src/sound/channel3.h b/supergameboy/libgambatte/src/sound/channel3.h deleted file mode 100644 index 8ec8688d..00000000 --- a/supergameboy/libgambatte/src/sound/channel3.h +++ /dev/null @@ -1,100 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aam�s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef SOUND_CHANNEL3_H -#define SOUND_CHANNEL3_H - -class SaveState; - -#include "int.h" - -#include "master_disabler.h" -#include "length_counter.h" - -class Channel3 { - class Ch3MasterDisabler : public MasterDisabler { - unsigned long &waveCounter; - - public: - Ch3MasterDisabler(bool &m, unsigned long &wC) : MasterDisabler(m), waveCounter(wC) {} - void operator()() { MasterDisabler::operator()(); waveCounter = SoundUnit::COUNTER_DISABLED; } - }; - - unsigned char waveRam[0x10]; - - Ch3MasterDisabler disableMaster; - LengthCounter lengthCounter; - - unsigned long cycleCounter; - unsigned long soMask; - unsigned long prevOut; - unsigned long waveCounter; - unsigned long lastReadTime; - - unsigned char nr0; - unsigned char nr3; - unsigned char nr4; - unsigned char wavePos; - unsigned char rShift; - unsigned char sampleBuf; - - bool master; - bool cgb; - - void updateWaveCounter(unsigned long cc); - -public: - Channel3(); - bool isActive() const { return master; } - void reset(); - void init(bool cgb); - void setStatePtrs(SaveState &state); - void saveState(SaveState &state) const; - void loadState(const SaveState &state); - void setNr0(unsigned data); - void setNr1(unsigned data) { lengthCounter.nr1Change(data, nr4, cycleCounter); } - void setNr2(unsigned data); - void setNr3(unsigned data) { nr3 = data; } - void setNr4(unsigned data); - void setSo(unsigned long soMask); - void update(Gambatte::uint_least32_t *buf, unsigned long soBaseVol, unsigned long cycles); - - unsigned waveRamRead(unsigned index) const { - if (master) { - if (!cgb && cycleCounter != lastReadTime) - return 0xFF; - - index = wavePos >> 1; - } - - return waveRam[index]; - } - - void waveRamWrite(unsigned index, unsigned data) { - if (master) { - if (!cgb && cycleCounter != lastReadTime) - return; - - index = wavePos >> 1; - } - - waveRam[index] = data; - } -}; - -#endif diff --git a/supergameboy/libgambatte/src/sound/channel4.cpp b/supergameboy/libgambatte/src/sound/channel4.cpp deleted file mode 100644 index c1efcf28..00000000 --- a/supergameboy/libgambatte/src/sound/channel4.cpp +++ /dev/null @@ -1,300 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aam�s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "channel4.h" -#include "../savestate.h" -#include - -static unsigned long toPeriod(const unsigned nr3) { - unsigned s = (nr3 >> 4) + 3; - unsigned r = nr3 & 7; - - if (!r) { - r = 1; - --s; - } - - return r << s; -} - -Channel4::Lfsr::Lfsr() : -backupCounter(COUNTER_DISABLED), -reg(0xFF), -nr3(0), -master(false) -{} - -void Channel4::Lfsr::updateBackupCounter(const unsigned long cc) { - /*if (backupCounter <= cc) { - const unsigned long period = toPeriod(nr3); - backupCounter = cc - (cc - backupCounter) % period + period; - }*/ - - if (backupCounter <= cc) { - const unsigned long period = toPeriod(nr3); - unsigned long periods = (cc - backupCounter) / period + 1; - - backupCounter += periods * period; - - if (master && nr3 < 0xE0) { - if (nr3 & 8) { - while (periods > 6) { - const unsigned xored = (reg << 1 ^ reg) & 0x7E; - reg = (reg >> 6 & ~0x7E) | xored | xored << 8; - periods -= 6; - } - - const unsigned xored = ((reg ^ reg >> 1) << (7 - periods)) & 0x7F; - reg = (reg >> periods & ~(0x80 - (0x80 >> periods))) | xored | xored << 8; - } else { - while (periods > 15) { - reg = reg ^ reg >> 1; - periods -= 15; - } - - reg = reg >> periods | (((reg ^ reg >> 1) << (15 - periods)) & 0x7FFF); - } - } - } -} - -void Channel4::Lfsr::reviveCounter(const unsigned long cc) { - updateBackupCounter(cc); - counter = backupCounter; -} - -/*static const unsigned char nextStateDistance[0x40] = { - 6, 1, 1, 2, 2, 1, 1, 3, - 3, 1, 1, 2, 2, 1, 1, 4, - 4, 1, 1, 2, 2, 1, 1, 3, - 3, 1, 1, 2, 2, 1, 1, 5, - 5, 1, 1, 2, 2, 1, 1, 3, - 3, 1, 1, 2, 2, 1, 1, 4, - 4, 1, 1, 2, 2, 1, 1, 3, - 3, 1, 1, 2, 2, 1, 1, 6, -};*/ - -inline void Channel4::Lfsr::event() { - if (nr3 < 0xE0) { - const unsigned shifted = reg >> 1; - const unsigned xored = (reg ^ shifted) & 1; - - reg = shifted | xored << 14; - - if (nr3 & 8) - reg = (reg & ~0x40) | xored << 6; - } - - counter += toPeriod(nr3); - backupCounter = counter; - - - /*if (nr3 < 0xE0) { - const unsigned periods = nextStateDistance[reg & 0x3F]; - const unsigned xored = ((reg ^ reg >> 1) << (7 - periods)) & 0x7F; - - reg = reg >> periods | xored << 8; - - if (nr3 & 8) - reg = reg & ~(0x80 - (0x80 >> periods)) | xored; - } - - const unsigned long period = toPeriod(nr3); - backupCounter = counter + period; - counter += period * nextStateDistance[reg & 0x3F];*/ -} - -void Channel4::Lfsr::nr3Change(const unsigned newNr3, const unsigned long cc) { - updateBackupCounter(cc); - nr3 = newNr3; - -// if (counter != COUNTER_DISABLED) -// counter = backupCounter + toPeriod(nr3) * (nextStateDistance[reg & 0x3F] - 1); -} - -void Channel4::Lfsr::nr4Init(unsigned long cc) { - disableMaster(); - updateBackupCounter(cc); - master = true; - backupCounter += 4; - counter = backupCounter; -// counter = backupCounter + toPeriod(nr3) * (nextStateDistance[reg & 0x3F] - 1); -} - -void Channel4::Lfsr::reset(const unsigned long cc) { - nr3 = 0; - disableMaster(); - backupCounter = cc + toPeriod(nr3); -} - -void Channel4::Lfsr::resetCounters(const unsigned long oldCc) { - updateBackupCounter(oldCc); - backupCounter -= COUNTER_MAX; - SoundUnit::resetCounters(oldCc); -} - -void Channel4::Lfsr::saveState(SaveState &state, const unsigned long cc) { - updateBackupCounter(cc); - state.spu.ch4.lfsr.counter = backupCounter; - state.spu.ch4.lfsr.reg = reg; -} - -void Channel4::Lfsr::loadState(const SaveState &state) { - counter = backupCounter = std::max(state.spu.ch4.lfsr.counter, state.spu.cycleCounter); - reg = state.spu.ch4.lfsr.reg; - master = state.spu.ch4.master; - nr3 = state.mem.ioamhram.get()[0x122]; -} - -Channel4::Channel4() : - staticOutputTest(*this, lfsr), - disableMaster(master, lfsr), - lengthCounter(disableMaster, 0x3F), - envelopeUnit(staticOutputTest), - cycleCounter(0), - soMask(0), - prevOut(0), - nr4(0), - master(false) -{ - setEvent(); -} - -void Channel4::setEvent() { -// nextEventUnit = &lfsr; -// if (envelopeUnit.getCounter() < nextEventUnit->getCounter()) - nextEventUnit = &envelopeUnit; - if (lengthCounter.getCounter() < nextEventUnit->getCounter()) - nextEventUnit = &lengthCounter; -} - -void Channel4::setNr1(const unsigned data) { - lengthCounter.nr1Change(data, nr4, cycleCounter); - - setEvent(); -} - -void Channel4::setNr2(const unsigned data) { - if (envelopeUnit.nr2Change(data)) - disableMaster(); - else - staticOutputTest(cycleCounter); - - setEvent(); -} - -void Channel4::setNr4(const unsigned data) { - lengthCounter.nr4Change(nr4, data, cycleCounter); - - nr4 = data; - - if (data & 0x80) { //init-bit - nr4 &= 0x7F; - - master = !envelopeUnit.nr4Init(cycleCounter); - - if (master) - lfsr.nr4Init(cycleCounter); - - staticOutputTest(cycleCounter); - } - - setEvent(); -} - -void Channel4::setSo(const unsigned long soMask) { - this->soMask = soMask; - staticOutputTest(cycleCounter); - setEvent(); -} - -void Channel4::reset() { - cycleCounter = 0x1000 | (cycleCounter & 0xFFF); // cycleCounter >> 12 & 7 represents the frame sequencer position. - -// lengthCounter.reset(); - lfsr.reset(cycleCounter); - envelopeUnit.reset(); - - setEvent(); -} - -void Channel4::init(const bool cgb) { - lengthCounter.init(cgb); -} - -void Channel4::saveState(SaveState &state) { - lfsr.saveState(state, cycleCounter); - envelopeUnit.saveState(state.spu.ch4.env); - lengthCounter.saveState(state.spu.ch4.lcounter); - - state.spu.ch4.nr4 = nr4; - state.spu.ch4.master = master; -} - -void Channel4::loadState(const SaveState &state) { - lfsr.loadState(state); - envelopeUnit.loadState(state.spu.ch4.env, state.mem.ioamhram.get()[0x121], state.spu.cycleCounter); - lengthCounter.loadState(state.spu.ch4.lcounter, state.spu.cycleCounter); - - cycleCounter = state.spu.cycleCounter; - nr4 = state.spu.ch4.nr4; - master = state.spu.ch4.master; -} - -void Channel4::update(Gambatte::uint_least32_t *buf, const unsigned long soBaseVol, unsigned long cycles) { - const unsigned long outBase = envelopeUnit.dacIsOn() ? soBaseVol & soMask : 0; - const unsigned long outLow = outBase * (0 - 15ul); - const unsigned long endCycles = cycleCounter + cycles; - - for (;;) { - const unsigned long outHigh = /*master ? */outBase * (envelopeUnit.getVolume() * 2 - 15ul)/* : outLow*/; - const unsigned long nextMajorEvent = nextEventUnit->getCounter() < endCycles ? nextEventUnit->getCounter() : endCycles; - unsigned long out = lfsr.isHighState() ? outHigh : outLow; - - while (lfsr.getCounter() <= nextMajorEvent) { - *buf += out - prevOut; - prevOut = out; - buf += lfsr.getCounter() - cycleCounter; - cycleCounter = lfsr.getCounter(); - - lfsr.event(); - out = lfsr.isHighState() ? outHigh : outLow; - } - - if (cycleCounter < nextMajorEvent) { - *buf += out - prevOut; - prevOut = out; - buf += nextMajorEvent - cycleCounter; - cycleCounter = nextMajorEvent; - } - - if (nextEventUnit->getCounter() == nextMajorEvent) { - nextEventUnit->event(); - setEvent(); - } else - break; - } - - if (cycleCounter & SoundUnit::COUNTER_MAX) { - lengthCounter.resetCounters(cycleCounter); - lfsr.resetCounters(cycleCounter); - envelopeUnit.resetCounters(cycleCounter); - - cycleCounter -= SoundUnit::COUNTER_MAX; - } -} diff --git a/supergameboy/libgambatte/src/sound/channel4.h b/supergameboy/libgambatte/src/sound/channel4.h deleted file mode 100644 index 7563dc2c..00000000 --- a/supergameboy/libgambatte/src/sound/channel4.h +++ /dev/null @@ -1,99 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aam�s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef SOUND_CHANNEL4_H -#define SOUND_CHANNEL4_H - -class SaveState; - -#include "int.h" - -#include "master_disabler.h" -#include "length_counter.h" -#include "envelope_unit.h" -#include "static_output_tester.h" - -class Channel4 { - class Lfsr : public SoundUnit { - unsigned long backupCounter; - unsigned short reg; - unsigned char nr3; - bool master; - - void updateBackupCounter(unsigned long cc); - - public: - Lfsr(); - void event(); - bool isHighState() const { return ~reg & 1; } - void nr3Change(unsigned newNr3, unsigned long cc); - void nr4Init(unsigned long cc); - void reset(unsigned long cc); - void saveState(SaveState &state, const unsigned long cc); - void loadState(const SaveState &state); - void resetCounters(unsigned long oldCc); - void disableMaster() { killCounter(); master = false; reg = 0xFF; } - void killCounter() { counter = COUNTER_DISABLED; } - void reviveCounter(unsigned long cc); - }; - - class Ch4MasterDisabler : public MasterDisabler { - Lfsr &lfsr; - public: - Ch4MasterDisabler(bool &m, Lfsr &lfsr) : MasterDisabler(m), lfsr(lfsr) {} - void operator()() { MasterDisabler::operator()(); lfsr.disableMaster(); } - }; - - friend class StaticOutputTester; - - StaticOutputTester staticOutputTest; - Ch4MasterDisabler disableMaster; - LengthCounter lengthCounter; - EnvelopeUnit envelopeUnit; - Lfsr lfsr; - - SoundUnit *nextEventUnit; - - unsigned long cycleCounter; - unsigned long soMask; - unsigned long prevOut; - - unsigned char nr4; - bool master; - - void setEvent(); - -public: - Channel4(); - void setNr1(unsigned data); - void setNr2(unsigned data); - void setNr3(unsigned data) { lfsr.nr3Change(data, cycleCounter); /*setEvent();*/ } - void setNr4(unsigned data); - - void setSo(unsigned long soMask); - bool isActive() const { return master; } - - void update(Gambatte::uint_least32_t *buf, unsigned long soBaseVol, unsigned long cycles); - - void reset(); - void init(bool cgb); - void saveState(SaveState &state); - void loadState(const SaveState &state); -}; - -#endif diff --git a/supergameboy/libgambatte/src/sound/duty_unit.cpp b/supergameboy/libgambatte/src/sound/duty_unit.cpp deleted file mode 100644 index d3de6abd..00000000 --- a/supergameboy/libgambatte/src/sound/duty_unit.cpp +++ /dev/null @@ -1,148 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "duty_unit.h" -#include - -static inline bool toOutState(const unsigned duty, const unsigned pos) { - static const unsigned char duties[4] = { 0x80, 0x81, 0xE1, 0x7E }; - - return duties[duty] >> pos & 1; -} - -static inline unsigned toPeriod(const unsigned freq) { - return (2048 - freq) << 1; -} - -void DutyUnit::updatePos(const unsigned long cc) { - if (cc >= nextPosUpdate) { - const unsigned long inc = (cc - nextPosUpdate) / period + 1; - nextPosUpdate += period * inc; - pos += inc; - pos &= 7; - } -} - -void DutyUnit::setDuty(const unsigned nr1) { - duty = nr1 >> 6; - high = toOutState(duty, pos); -} - -void DutyUnit::setCounter() { - static const unsigned char nextStateDistance[4 * 8] = { - 6, 5, 4, 3, 2, 1, 0, 0, - 0, 5, 4, 3, 2, 1, 0, 1, - 0, 3, 2, 1, 0, 3, 2, 1, - 0, 5, 4, 3, 2, 1, 0, 1 - }; - - if (enableEvents && nextPosUpdate != COUNTER_DISABLED) - counter = nextPosUpdate + period * nextStateDistance[(duty * 8) | pos]; - else - counter = COUNTER_DISABLED; -} - -void DutyUnit::setFreq(const unsigned newFreq, const unsigned long cc) { - updatePos(cc); - period = toPeriod(newFreq); - setCounter(); -} - -void DutyUnit::event() { - unsigned inc = period << duty; - - if (duty == 3) - inc -= period * 2; - - if (!(high ^= true)) - inc = period * 8 - inc; - - counter += inc; -} - -void DutyUnit::nr1Change(const unsigned newNr1, const unsigned long cc) { - updatePos(cc); - setDuty(newNr1); - setCounter(); -} - -void DutyUnit::nr3Change(const unsigned newNr3, const unsigned long cc) { - setFreq((getFreq() & 0x700) | newNr3, cc); -} - -void DutyUnit::nr4Change(const unsigned newNr4, const unsigned long cc) { - setFreq((newNr4 << 8 & 0x700) | (getFreq() & 0xFF), cc); - - if (newNr4 & 0x80) { - nextPosUpdate = (cc & ~1) + period; - setCounter(); - } -} - -DutyUnit::DutyUnit() : -nextPosUpdate(COUNTER_DISABLED), -period(4096), -pos(0), -duty(0), -high(false), -enableEvents(true) -{} - -void DutyUnit::reset() { - pos = 0; - high = toOutState(duty, pos); - nextPosUpdate = COUNTER_DISABLED; - setCounter(); -} - -void DutyUnit::saveState(SaveState::SPU::Duty &dstate, const unsigned long cc) { - updatePos(cc); - dstate.nextPosUpdate = nextPosUpdate; - dstate.nr3 = getFreq() & 0xFF; - dstate.pos = pos; -} - -void DutyUnit::loadState(const SaveState::SPU::Duty &dstate, const unsigned nr1, const unsigned nr4, const unsigned long cc) { - nextPosUpdate = std::max(dstate.nextPosUpdate, cc); - pos = dstate.pos & 7; - setDuty(nr1); - period = toPeriod((nr4 << 8 & 0x700) | dstate.nr3); - enableEvents = true; - setCounter(); -} - -void DutyUnit::resetCounters(const unsigned long oldCc) { - if (nextPosUpdate == COUNTER_DISABLED) - return; - - updatePos(oldCc); - nextPosUpdate -= COUNTER_MAX; - SoundUnit::resetCounters(oldCc); -} - -void DutyUnit::killCounter() { - enableEvents = false; - setCounter(); -} - -void DutyUnit::reviveCounter(const unsigned long cc) { - updatePos(cc); - high = toOutState(duty, pos); - enableEvents = true; - setCounter(); -} diff --git a/supergameboy/libgambatte/src/sound/duty_unit.h b/supergameboy/libgambatte/src/sound/duty_unit.h deleted file mode 100644 index e55cec59..00000000 --- a/supergameboy/libgambatte/src/sound/duty_unit.h +++ /dev/null @@ -1,64 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aam�s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef DUTY_UNIT_H -#define DUTY_UNIT_H - -#include "sound_unit.h" -#include "master_disabler.h" -#include "../savestate.h" - -class DutyUnit : public SoundUnit { - unsigned long nextPosUpdate; - unsigned short period; - unsigned char pos; - unsigned char duty; - bool high; - bool enableEvents; - - void setCounter(); - void setDuty(unsigned nr1); - void updatePos(unsigned long cc); - -public: - DutyUnit(); - void event(); - bool isHighState() const { return high; } - void nr1Change(unsigned newNr1, unsigned long cc); - void nr3Change(unsigned newNr3, unsigned long cc); - void nr4Change(unsigned newNr4, unsigned long cc); - void reset(); - void saveState(SaveState::SPU::Duty &dstate, unsigned long cc); - void loadState(const SaveState::SPU::Duty &dstate, unsigned nr1, unsigned nr4, unsigned long cc); - void resetCounters(unsigned long oldCc); - void killCounter(); - void reviveCounter(unsigned long cc); - - //intended for use by SweepUnit only. - unsigned getFreq() const { return 2048 - (period >> 1); } - void setFreq(unsigned newFreq, unsigned long cc); -}; - -class DutyMasterDisabler : public MasterDisabler { - DutyUnit &dutyUnit; -public: - DutyMasterDisabler(bool &m, DutyUnit &dutyUnit) : MasterDisabler(m), dutyUnit(dutyUnit) {} - void operator()() { MasterDisabler::operator()(); dutyUnit.killCounter(); } -}; - -#endif diff --git a/supergameboy/libgambatte/src/sound/envelope_unit.cpp b/supergameboy/libgambatte/src/sound/envelope_unit.cpp deleted file mode 100644 index ed526eb5..00000000 --- a/supergameboy/libgambatte/src/sound/envelope_unit.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "envelope_unit.h" -#include - -EnvelopeUnit::VolOnOffEvent EnvelopeUnit::nullEvent; - -void EnvelopeUnit::event() { - const unsigned long period = nr2 & 7; - - if (period) { - unsigned newVol = volume; - - if (nr2 & 8) - ++newVol; - else - --newVol; - - if (newVol < 0x10U) { - volume = newVol; - - if (volume < 2) - volOnOffEvent(counter); - - counter += period << 15; - } else - counter = COUNTER_DISABLED; - } else - counter += 8ul << 15; -} - -bool EnvelopeUnit::nr2Change(const unsigned newNr2) { - if (!(nr2 & 7) && counter != COUNTER_DISABLED) - ++volume; - else if (!(nr2 & 8)) - volume += 2; - - if ((nr2 ^ newNr2) & 8) - volume = 0x10 - volume; - - volume &= 0xF; - - nr2 = newNr2; - - return !(newNr2 & 0xF8); -} - -bool EnvelopeUnit::nr4Init(const unsigned long cc) { - { - unsigned long period = nr2 & 7; - - if (!period) - period = 8; - - if (!(cc & 0x7000)) - ++period; - - counter = cc - ((cc - 0x1000) & 0x7FFF) + period * 0x8000; - } - - volume = nr2 >> 4; - - return !(nr2 & 0xF8); -} - -EnvelopeUnit::EnvelopeUnit(VolOnOffEvent &volOnOffEvent) : -volOnOffEvent(volOnOffEvent), -nr2(0), -volume(0) -{} - -void EnvelopeUnit::reset() { - counter = COUNTER_DISABLED; -} - -void EnvelopeUnit::saveState(SaveState::SPU::Env &estate) const { - estate.counter = counter; - estate.volume = volume; -} - -void EnvelopeUnit::loadState(const SaveState::SPU::Env &estate, const unsigned nr2, const unsigned long cc) { - counter = std::max(estate.counter, cc); - volume = estate.volume; - this->nr2 = nr2; -} diff --git a/supergameboy/libgambatte/src/sound/envelope_unit.h b/supergameboy/libgambatte/src/sound/envelope_unit.h deleted file mode 100644 index e9bae2f0..00000000 --- a/supergameboy/libgambatte/src/sound/envelope_unit.h +++ /dev/null @@ -1,50 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef ENVELOPE_UNIT_H -#define ENVELOPE_UNIT_H - -#include "sound_unit.h" -#include "../savestate.h" - -class EnvelopeUnit : public SoundUnit { -public: - struct VolOnOffEvent { - virtual ~VolOnOffEvent() {} - virtual void operator()(unsigned long /*cc*/) {} - }; - -private: - static VolOnOffEvent nullEvent; - VolOnOffEvent &volOnOffEvent; - unsigned char nr2; - unsigned char volume; - -public: - EnvelopeUnit(VolOnOffEvent &volOnOffEvent = nullEvent); - void event(); - bool dacIsOn() const { return nr2 & 0xF8; } - unsigned getVolume() const { return volume; } - bool nr2Change(unsigned newNr2); - bool nr4Init(unsigned long cycleCounter); - void reset(); - void saveState(SaveState::SPU::Env &estate) const; - void loadState(const SaveState::SPU::Env &estate, unsigned nr2, unsigned long cc); -}; - -#endif diff --git a/supergameboy/libgambatte/src/sound/length_counter.cpp b/supergameboy/libgambatte/src/sound/length_counter.cpp deleted file mode 100644 index 8bbe85e1..00000000 --- a/supergameboy/libgambatte/src/sound/length_counter.cpp +++ /dev/null @@ -1,87 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * -***************************************************************************/ -#include "length_counter.h" -#include "master_disabler.h" -#include - -LengthCounter::LengthCounter(MasterDisabler &disabler, const unsigned mask) : - disableMaster(disabler), - lengthMask(mask) -{ - init(false); - nr1Change(0, 0, 0); -} - -void LengthCounter::event() { - counter = COUNTER_DISABLED; - lengthCounter = 0; - disableMaster(); -} - -void LengthCounter::nr1Change(const unsigned newNr1, const unsigned nr4, const unsigned long cycleCounter) { - lengthCounter = (~newNr1 & lengthMask) + 1; - counter = (nr4 & 0x40) ?( (cycleCounter >> 13) + lengthCounter) << 13 : static_cast(COUNTER_DISABLED); -} - -void LengthCounter::nr4Change(const unsigned oldNr4, const unsigned newNr4, const unsigned long cycleCounter) { - if (counter != COUNTER_DISABLED) - lengthCounter = (counter >> 13) - (cycleCounter >> 13); - - { - unsigned dec = 0; - - if (newNr4 & 0x40) { - dec = ~cycleCounter >> 12 & 1; - - if (!(oldNr4 & 0x40) && lengthCounter) { - if (!(lengthCounter -= dec)) - disableMaster(); - } - } - - if ((newNr4 & 0x80) && !lengthCounter) - lengthCounter = lengthMask + 1 - dec; - } - - if ((newNr4 & 0x40) && lengthCounter) - counter = ((cycleCounter >> 13) + lengthCounter) << 13; - else - counter = COUNTER_DISABLED; -} - -/*void LengthCounter::reset() { - counter = COUNTER_DISABLED; - - if (cgb) - lengthCounter = lengthMask + 1; -}*/ - -void LengthCounter::init(const bool cgb) { - this->cgb = cgb; -} - -void LengthCounter::saveState(SaveState::SPU::LCounter &lstate) const { - lstate.counter = counter; - lstate.lengthCounter = lengthCounter; -} - -void LengthCounter::loadState(const SaveState::SPU::LCounter &lstate, const unsigned long cc) { - counter = std::max(lstate.counter, cc); - lengthCounter = lstate.lengthCounter; -} diff --git a/supergameboy/libgambatte/src/sound/length_counter.h b/supergameboy/libgambatte/src/sound/length_counter.h deleted file mode 100644 index 2d9451d7..00000000 --- a/supergameboy/libgambatte/src/sound/length_counter.h +++ /dev/null @@ -1,44 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * -***************************************************************************/ -#ifndef LENGTH_COUNTER_H -#define LENGTH_COUNTER_H - -#include "sound_unit.h" -#include "../savestate.h" - -class MasterDisabler; - -class LengthCounter : public SoundUnit { - MasterDisabler &disableMaster; - unsigned short lengthCounter; - const unsigned char lengthMask; - bool cgb; - -public: - LengthCounter(MasterDisabler &disabler, unsigned lengthMask); - void event(); - void nr1Change(unsigned newNr1, unsigned nr4, unsigned long cc); - void nr4Change(unsigned oldNr4, unsigned newNr4, unsigned long cc); -// void reset(); - void init(bool cgb); - void saveState(SaveState::SPU::LCounter &lstate) const; - void loadState(const SaveState::SPU::LCounter &lstate, unsigned long cc); -}; - -#endif diff --git a/supergameboy/libgambatte/src/sound/master_disabler.h b/supergameboy/libgambatte/src/sound/master_disabler.h deleted file mode 100644 index 7dd588c5..00000000 --- a/supergameboy/libgambatte/src/sound/master_disabler.h +++ /dev/null @@ -1,31 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * -***************************************************************************/ -#ifndef MASTER_DISABLER_H -#define MASTER_DISABLER_H - -class MasterDisabler { - bool &master; - -public: - MasterDisabler(bool &m) : master(m) {} - virtual ~MasterDisabler() {} - virtual void operator()() { master = false; } -}; - -#endif diff --git a/supergameboy/libgambatte/src/sound/sound_unit.h b/supergameboy/libgambatte/src/sound/sound_unit.h deleted file mode 100644 index 2857c0c1..00000000 --- a/supergameboy/libgambatte/src/sound/sound_unit.h +++ /dev/null @@ -1,35 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * -***************************************************************************/ -#ifndef SOUND_UNIT_H -#define SOUND_UNIT_H - -class SoundUnit { -protected: - unsigned long counter; -public: - enum { COUNTER_MAX = 0x80000000u, COUNTER_DISABLED = 0xFFFFFFFFu }; - - SoundUnit() : counter(COUNTER_DISABLED) {} - virtual ~SoundUnit() {} - virtual void event() = 0; - unsigned long getCounter() const { return counter; } - virtual void resetCounters(unsigned long /*oldCc*/) { if (counter != COUNTER_DISABLED) counter -= COUNTER_MAX; } -}; - -#endif diff --git a/supergameboy/libgambatte/src/sound/static_output_tester.h b/supergameboy/libgambatte/src/sound/static_output_tester.h deleted file mode 100644 index 3dbe216e..00000000 --- a/supergameboy/libgambatte/src/sound/static_output_tester.h +++ /dev/null @@ -1,41 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef STATIC_OUTPUT_TESTER_H -#define STATIC_OUTPUT_TESTER_H - -#include "envelope_unit.h" - -template -class StaticOutputTester : public EnvelopeUnit::VolOnOffEvent { - const Channel &ch; - Unit &unit; -public: - StaticOutputTester(const Channel &ch, Unit &unit) : ch(ch), unit(unit) {} - void operator()(unsigned long cc); -}; - -template -void StaticOutputTester::operator()(const unsigned long cc) { - if (ch.soMask && ch.master && ch.envelopeUnit.getVolume()) - unit.reviveCounter(cc); - else - unit.killCounter(); -} - -#endif diff --git a/supergameboy/libgambatte/src/state_osd_elements.cpp b/supergameboy/libgambatte/src/state_osd_elements.cpp deleted file mode 100644 index 44740d16..00000000 --- a/supergameboy/libgambatte/src/state_osd_elements.cpp +++ /dev/null @@ -1,169 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2008 by Sindre Aam�s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "state_osd_elements.h" -#include "bitmap_font.h" -#include "statesaver.h" -#include -#include - -using namespace BitmapFont; - -static const char stateLoadedTxt[] = { S,t,a,t,e,SPC,N0,SPC,l,o,a,d,e,d,0 }; -static const char stateSavedTxt[] = { S,t,a,t,e,SPC,N0,SPC,s,a,v,e,d,0 }; -static const unsigned stateLoadedTxtWidth = getWidth(stateLoadedTxt); -static const unsigned stateSavedTxtWidth = getWidth(stateSavedTxt); - -class ShadedTextOsdElment : public OsdElement { - struct ShadeFill { - void operator()(Gambatte::uint_least32_t *dest, const unsigned pitch) { - dest[2] = dest[1] = dest[0] = 0x000000ul; - dest += pitch; - dest[2] = dest[0] = 0x000000ul; - dest += pitch; - dest[2] = dest[1] = dest[0] = 0x000000ul; - } - }; - - Gambatte::uint_least32_t *const pixels; - unsigned life; - -public: - ShadedTextOsdElment(unsigned w, const char *txt); - ~ShadedTextOsdElment(); - const Gambatte::uint_least32_t* update(); -}; - -ShadedTextOsdElment::ShadedTextOsdElment(unsigned width, const char *txt) : -OsdElement(MAX_WIDTH, 144 - HEIGHT - HEIGHT, width + 2, HEIGHT + 2, THREE_FOURTHS), -pixels(new Gambatte::uint_least32_t[w() * h()]), -life(4 * 60) { - std::memset(pixels, 0xFF, w() * h() * sizeof(Gambatte::uint_least32_t)); - - /*print(pixels + 0 * w() + 0, w(), 0x000000ul, txt); - print(pixels + 0 * w() + 1, w(), 0x000000ul, txt); - print(pixels + 0 * w() + 2, w(), 0x000000ul, txt); - print(pixels + 1 * w() + 0, w(), 0x000000ul, txt); - print(pixels + 1 * w() + 2, w(), 0x000000ul, txt); - print(pixels + 2 * w() + 0, w(), 0x000000ul, txt); - print(pixels + 2 * w() + 1, w(), 0x000000ul, txt); - print(pixels + 2 * w() + 2, w(), 0x000000ul, txt); - print(pixels + 1 * w() + 1, w(), 0xE0E0E0ul, txt);*/ - - print(pixels, w(), ShadeFill(), txt); - print(pixels + 1 * w() + 1, w(), 0xE0E0E0ul, txt); -} - -ShadedTextOsdElment::~ShadedTextOsdElment() { - delete []pixels; -} - -const Gambatte::uint_least32_t* ShadedTextOsdElment::update() { - if (life--) - return pixels; - - return 0; -} - -/*class FramedTextOsdElment : public OsdElement { - Gambatte::uint_least32_t *const pixels; - unsigned life; - -public: - FramedTextOsdElment(unsigned w, const char *txt); - ~FramedTextOsdElment(); - const Gambatte::uint_least32_t* update(); -}; - -FramedTextOsdElment::FramedTextOsdElment(unsigned width, const char *txt) : -OsdElement(NUMBER_WIDTH, 144 - HEIGHT * 2 - HEIGHT / 2, width + NUMBER_WIDTH * 2, HEIGHT * 2), -pixels(new Gambatte::uint_least32_t[w() * h()]), -life(4 * 60) { - std::memset(pixels, 0x00, w() * h() * sizeof(Gambatte::uint_least32_t)); - print(pixels + (w() - width) / 2 + ((h() - HEIGHT) / 2) * w(), w(), 0xA0A0A0ul, txt); -} - -FramedTextOsdElment::~FramedTextOsdElment() { - delete []pixels; -} - -const Gambatte::uint_least32_t* FramedTextOsdElment::update() { - if (life--) - return pixels; - - return 0; -}*/ - -std::auto_ptr newStateLoadedOsdElement(unsigned stateNo) { - char txt[sizeof(stateLoadedTxt)]; - - std::memcpy(txt, stateLoadedTxt, sizeof(stateLoadedTxt)); - utoa(stateNo, txt + 6); - - return std::auto_ptr(new ShadedTextOsdElment(stateLoadedTxtWidth, txt)); -} - -std::auto_ptr newStateSavedOsdElement(unsigned stateNo) { - char txt[sizeof(stateSavedTxt)]; - - std::memcpy(txt, stateSavedTxt, sizeof(stateSavedTxt)); - utoa(stateNo, txt + 6); - - return std::auto_ptr(new ShadedTextOsdElment(stateSavedTxtWidth, txt)); -} - -class SaveStateOsdElement : public OsdElement { - Gambatte::uint_least32_t pixels[StateSaver::SS_WIDTH * StateSaver::SS_HEIGHT]; - unsigned life; - -public: - SaveStateOsdElement(const char *fileName, unsigned stateNo); - const Gambatte::uint_least32_t* update(); -}; - -SaveStateOsdElement::SaveStateOsdElement(const char *fileName, unsigned stateNo) : -OsdElement((stateNo ? stateNo - 1 : 9) * ((160 - StateSaver::SS_WIDTH) / 10) + ((160 - StateSaver::SS_WIDTH) / 10) / 2, 4, StateSaver::SS_WIDTH, StateSaver::SS_HEIGHT), -life(4 * 60) { - std::ifstream file(fileName, std::ios_base::binary); - - if (file.is_open()) { - file.ignore(5); - file.read(reinterpret_cast(pixels), sizeof(pixels)); - } else { - std::memset(pixels, 0, sizeof(pixels)); - - { - using namespace BitmapFont; - - static const char txt[] = { E,m,p,t,BitmapFont::y,0 }; - - print(pixels + 3 + (StateSaver::SS_HEIGHT / 2 - BitmapFont::HEIGHT / 2) * StateSaver::SS_WIDTH, StateSaver::SS_WIDTH, 0x808080ul, txt); - } - } -} - -const Gambatte::uint_least32_t* SaveStateOsdElement::update() { - if (life--) - return pixels; - - return 0; -} - -std::auto_ptr newSaveStateOsdElement(const char *fileName, unsigned stateNo) { - return std::auto_ptr(new SaveStateOsdElement(fileName, stateNo)); -} diff --git a/supergameboy/libgambatte/src/state_osd_elements.h b/supergameboy/libgambatte/src/state_osd_elements.h deleted file mode 100644 index c10344d2..00000000 --- a/supergameboy/libgambatte/src/state_osd_elements.h +++ /dev/null @@ -1,29 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2008 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef STATE_OSD_ELEMENTS_H -#define STATE_OSD_ELEMENTS_H - -#include "osd_element.h" -#include - -std::auto_ptr newStateLoadedOsdElement(unsigned stateNo); -std::auto_ptr newStateSavedOsdElement(unsigned stateNo); -std::auto_ptr newSaveStateOsdElement(const char *fileName, unsigned stateNo); - -#endif diff --git a/supergameboy/libgambatte/src/statesaver.cpp b/supergameboy/libgambatte/src/statesaver.cpp deleted file mode 100644 index c157129d..00000000 --- a/supergameboy/libgambatte/src/statesaver.cpp +++ /dev/null @@ -1,407 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2008 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "statesaver.h" -#include "savestate.h" -#include "array.h" -#include -#include -#include -#include - -enum AsciiChar { - NUL, SOH, STX, ETX, EOT, ENQ, ACK, BEL, BS, TAB, LF, VT, FF, CR, SO, SI, - DLE, DC1, DC2, DC3, DC4, NAK, SYN, ETB, CAN, EM, SUB, ESC, FS, GS, RS, US, - SP, XCL, QOT, HSH, DLR, PRC, AMP, APO, LPA, RPA, AST, PLU, COM, HYP, STP, DIV, - NO0, NO1, NO2, NO3, NO4, NO5, NO6, NO7, NO8, NO9, CLN, SCL, LT, EQL, GT, QTN, - AT, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, - P, Q, R, S, T, U, V, W, X, Y, Z, LBX, BSL, RBX, CAT, UND, - ACN, a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, - p, q, r, s, t, u, v, w, x, y, z, LBR, BAR, RBR, TLD, DEL -}; - -struct Saver { - const char *label; - void (*save)(std::ofstream &file, const SaveState &state); - void (*load)(std::ifstream &file, SaveState &state); - unsigned char labelsize; -}; - -static inline bool operator<(const Saver &l, const Saver &r) { - return std::strcmp(l.label, r.label) < 0; -} - -static void put24(std::ofstream &file, const unsigned long data) { - file.put(data >> 16 & 0xFF); - file.put(data >> 8 & 0xFF); - file.put(data & 0xFF); -} - -static void put32(std::ofstream &file, const unsigned long data) { - file.put(data >> 24 & 0xFF); - file.put(data >> 16 & 0xFF); - file.put(data >> 8 & 0xFF); - file.put(data & 0xFF); -} - -static void write(std::ofstream &file, const unsigned char data) { - static const char inf[] = { 0x00, 0x00, 0x01 }; - - file.write(inf, sizeof(inf)); - file.put(data & 0xFF); -} - -static void write(std::ofstream &file, const unsigned short data) { - static const char inf[] = { 0x00, 0x00, 0x02 }; - - file.write(inf, sizeof(inf)); - file.put(data >> 8 & 0xFF); - file.put(data & 0xFF); -} - -static void write(std::ofstream &file, const unsigned long data) { - static const char inf[] = { 0x00, 0x00, 0x04 }; - - file.write(inf, sizeof(inf)); - put32(file, data); -} - -static inline void write(std::ofstream &file, const bool data) { - write(file, static_cast(data)); -} - -static void write(std::ofstream &file, const unsigned char *data, const unsigned long sz) { - put24(file, sz); - file.write(reinterpret_cast(data), sz); -} - -static void write(std::ofstream &file, const bool *data, const unsigned long sz) { - put24(file, sz); - - for (unsigned long i = 0; i < sz; ++i) - file.put(data[i]); -} - -static unsigned long get24(std::ifstream &file) { - unsigned long tmp = file.get() & 0xFF; - - tmp = tmp << 8 | (file.get() & 0xFF); - - return tmp << 8 | (file.get() & 0xFF); -} - -static unsigned long read(std::ifstream &file) { - unsigned long size = get24(file); - - if (size > 4) { - file.ignore(size - 4); - size = 4; - } - - unsigned long out = 0; - - switch (size) { - case 4: out = (out | (file.get() & 0xFF)) << 8; - case 3: out = (out | (file.get() & 0xFF)) << 8; - case 2: out = (out | (file.get() & 0xFF)) << 8; - case 1: out = out | (file.get() & 0xFF); - } - - return out; -} - -static inline void read(std::ifstream &file, unsigned char &data) { - data = read(file) & 0xFF; -} - -static inline void read(std::ifstream &file, unsigned short &data) { - data = read(file) & 0xFFFF; -} - -static inline void read(std::ifstream &file, unsigned long &data) { - data = read(file); -} - -static inline void read(std::ifstream &file, bool &data) { - data = read(file); -} - -static void read(std::ifstream &file, unsigned char *data, unsigned long sz) { - const unsigned long size = get24(file); - - if (size < sz) - sz = size; - - file.read(reinterpret_cast(data), sz); - file.ignore(size - sz); - - if (static_cast(0x100)) { - for (unsigned long i = 0; i < sz; ++i) - data[i] &= 0xFF; - } -} - -static void read(std::ifstream &file, bool *data, unsigned long sz) { - const unsigned long size = get24(file); - - if (size < sz) - sz = size; - - for (unsigned long i = 0; i < sz; ++i) - data[i] = file.get(); - - file.ignore(size - sz); -} - -class SaverList { -public: - typedef std::vector list_t; - typedef list_t::const_iterator const_iterator; - -private: - list_t list; - unsigned char maxLabelsize_; - -public: - SaverList(); - const_iterator begin() const { return list.begin(); } - const_iterator end() const { return list.end(); } - unsigned maxLabelsize() const { return maxLabelsize_; } -}; - -SaverList::SaverList() { -#define ADD(arg) do { \ - struct Func { \ - static void save(std::ofstream &file, const SaveState &state) { write(file, state.arg); } \ - static void load(std::ifstream &file, SaveState &state) { read(file, state.arg); } \ - }; \ - \ - Saver saver = { label, Func::save, Func::load, sizeof label }; \ - list.push_back(saver); \ -} while (0) - -#define ADDPTR(arg) do { \ - struct Func { \ - static void save(std::ofstream &file, const SaveState &state) { write(file, state.arg.get(), state.arg.getSz()); } \ - static void load(std::ifstream &file, SaveState &state) { read(file, state.arg.ptr, state.arg.getSz()); } \ - }; \ - \ - Saver saver = { label, Func::save, Func::load, sizeof label }; \ - list.push_back(saver); \ -} while (0) - - { static const char label[] = { c,c, NUL }; ADD(cpu.cycleCounter); } - { static const char label[] = { p,c, NUL }; ADD(cpu.PC); } - { static const char label[] = { s,p, NUL }; ADD(cpu.SP); } - { static const char label[] = { a, NUL }; ADD(cpu.A); } - { static const char label[] = { b, NUL }; ADD(cpu.B); } - { static const char label[] = { c, NUL }; ADD(cpu.C); } - { static const char label[] = { d, NUL }; ADD(cpu.D); } - { static const char label[] = { e, NUL }; ADD(cpu.E); } - { static const char label[] = { f, NUL }; ADD(cpu.F); } - { static const char label[] = { h, NUL }; ADD(cpu.H); } - { static const char label[] = { l, NUL }; ADD(cpu.L); } - { static const char label[] = { s,k,i,p, NUL }; ADD(cpu.skip); } - { static const char label[] = { h,a,l,t, NUL }; ADD(cpu.halted); } - { static const char label[] = { v,r,a,m, NUL }; ADDPTR(mem.vram); } - { static const char label[] = { s,r,a,m, NUL }; ADDPTR(mem.sram); } - { static const char label[] = { w,r,a,m, NUL }; ADDPTR(mem.wram); } - { static const char label[] = { h,r,a,m, NUL }; ADDPTR(mem.ioamhram); } - { static const char label[] = { l,d,i,v,u,p, NUL }; ADD(mem.div_lastUpdate); } - { static const char label[] = { l,t,i,m,a,u,p, NUL }; ADD(mem.tima_lastUpdate); } - { static const char label[] = { t,m,a,t,i,m,e, NUL }; ADD(mem.tmatime); } - { static const char label[] = { s,e,r,i,a,l,t, NUL }; ADD(mem.next_serialtime); } - { static const char label[] = { l,o,d,m,a,u,p, NUL }; ADD(mem.lastOamDmaUpdate); } - { static const char label[] = { m,i,n,i,n,t,t, NUL }; ADD(mem.minIntTime); } - { static const char label[] = { r,o,m,b,a,n,k, NUL }; ADD(mem.rombank); } - { static const char label[] = { d,m,a,s,r,c, NUL }; ADD(mem.dmaSource); } - { static const char label[] = { d,m,a,d,s,t, NUL }; ADD(mem.dmaDestination); } - { static const char label[] = { r,a,m,b,a,n,k, NUL }; ADD(mem.rambank); } - { static const char label[] = { o,d,m,a,p,o,s, NUL }; ADD(mem.oamDmaPos); } - { static const char label[] = { i,m,e, NUL }; ADD(mem.IME); } - { static const char label[] = { s,r,a,m,o,n, NUL }; ADD(mem.enable_ram); } - { static const char label[] = { r,a,m,b,m,o,d, NUL }; ADD(mem.rambank_mode); } - { static const char label[] = { h,d,m,a, NUL }; ADD(mem.hdma_transfer); } - { static const char label[] = { b,g,p, NUL }; ADDPTR(ppu.bgpData); } - { static const char label[] = { o,b,j,p, NUL }; ADDPTR(ppu.objpData); } - { static const char label[] = { s,p,o,s,b,u,f, NUL }; ADDPTR(ppu.oamReaderBuf); } - { static const char label[] = { s,p,s,z,b,u,f, NUL }; ADDPTR(ppu.oamReaderSzbuf); } - { static const char label[] = { v,c,y,c,l,e,s, NUL }; ADD(ppu.videoCycles); } - { static const char label[] = { e,d,M,NO0,t,i,m, NUL }; ADD(ppu.enableDisplayM0Time); } - { static const char label[] = { w,i,n,y,p,o,s, NUL }; ADD(ppu.winYPos); } - { static const char label[] = { d,r,a,w,c,y,c, NUL }; ADD(ppu.drawStartCycle); } - { static const char label[] = { s,c,r,d,c,y,c, NUL }; ADD(ppu.scReadOffset); } - { static const char label[] = { l,c,d,c, NUL }; ADD(ppu.lcdc); } - { static const char label[] = { s,c,x,NO0, NUL }; ADD(ppu.scx[0]); } - { static const char label[] = { s,c,x,NO1, NUL }; ADD(ppu.scx[1]); } - { static const char label[] = { s,c,y,NO0, NUL }; ADD(ppu.scy[0]); } - { static const char label[] = { s,c,y,NO1, NUL }; ADD(ppu.scy[1]); } - { static const char label[] = { s,c,x,AMP,NO7, NUL }; ADD(ppu.scxAnd7); } - { static const char label[] = { w,e,m,a,s,t,r, NUL }; ADD(ppu.weMaster); } - { static const char label[] = { w,x, NUL }; ADD(ppu.wx); } - { static const char label[] = { w,y, NUL }; ADD(ppu.wy); } - { static const char label[] = { l,y,c,s,k,i,p, NUL }; ADD(ppu.lycIrqSkip); } - { static const char label[] = { s,p,u,c,n,t,r, NUL }; ADD(spu.cycleCounter); } - { static const char label[] = { s,w,p,c,n,t,r, NUL }; ADD(spu.ch1.sweep.counter); } - { static const char label[] = { s,w,p,s,h,d,w, NUL }; ADD(spu.ch1.sweep.shadow); } - { static const char label[] = { s,w,p,n,e,g, NUL }; ADD(spu.ch1.sweep.negging); } - { static const char label[] = { d,u,t,NO1,c,t,r, NUL }; ADD(spu.ch1.duty.nextPosUpdate); } - { static const char label[] = { d,u,t,NO1,p,o,s, NUL }; ADD(spu.ch1.duty.pos); } - { static const char label[] = { e,n,v,NO1,c,t,r, NUL }; ADD(spu.ch1.env.counter); } - { static const char label[] = { e,n,v,NO1,v,o,l, NUL }; ADD(spu.ch1.env.volume); } - { static const char label[] = { l,e,n,NO1,c,t,r, NUL }; ADD(spu.ch1.lcounter.counter); } - { static const char label[] = { l,e,n,NO1,v,a,l, NUL }; ADD(spu.ch1.lcounter.lengthCounter); } - { static const char label[] = { n,r,NO1,NO0, NUL }; ADD(spu.ch1.sweep.nr0); } - { static const char label[] = { n,r,NO1,NO3, NUL }; ADD(spu.ch1.duty.nr3); } - { static const char label[] = { n,r,NO1,NO4, NUL }; ADD(spu.ch1.nr4); } - { static const char label[] = { c,NO1,m,a,s,t,r, NUL }; ADD(spu.ch1.master); } - { static const char label[] = { d,u,t,NO2,c,t,r, NUL }; ADD(spu.ch2.duty.nextPosUpdate); } - { static const char label[] = { d,u,t,NO2,p,o,s, NUL }; ADD(spu.ch2.duty.pos); } - { static const char label[] = { e,n,v,NO2,c,t,r, NUL }; ADD(spu.ch2.env.counter); } - { static const char label[] = { e,n,v,NO2,v,o,l, NUL }; ADD(spu.ch2.env.volume); } - { static const char label[] = { l,e,n,NO2,c,t,r, NUL }; ADD(spu.ch2.lcounter.counter); } - { static const char label[] = { l,e,n,NO2,v,a,l, NUL }; ADD(spu.ch2.lcounter.lengthCounter); } - { static const char label[] = { n,r,NO2,NO3, NUL }; ADD(spu.ch2.duty.nr3); } - { static const char label[] = { n,r,NO2,NO4, NUL }; ADD(spu.ch2.nr4); } - { static const char label[] = { c,NO2,m,a,s,t,r, NUL }; ADD(spu.ch2.master); } - { static const char label[] = { w,a,v,e,r,a,m, NUL }; ADDPTR(spu.ch3.waveRam); } - { static const char label[] = { l,e,n,NO3,c,t,r, NUL }; ADD(spu.ch3.lcounter.counter); } - { static const char label[] = { l,e,n,NO3,v,a,l, NUL }; ADD(spu.ch3.lcounter.lengthCounter); } - { static const char label[] = { w,a,v,e,c,t,r, NUL }; ADD(spu.ch3.waveCounter); } - { static const char label[] = { l,w,a,v,r,d,t, NUL }; ADD(spu.ch3.lastReadTime); } - { static const char label[] = { w,a,v,e,p,o,s, NUL }; ADD(spu.ch3.wavePos); } - { static const char label[] = { w,a,v,s,m,p,l, NUL }; ADD(spu.ch3.sampleBuf); } - { static const char label[] = { n,r,NO3,NO3, NUL }; ADD(spu.ch3.nr3); } - { static const char label[] = { n,r,NO3,NO4, NUL }; ADD(spu.ch3.nr4); } - { static const char label[] = { c,NO3,m,a,s,t,r, NUL }; ADD(spu.ch3.master); } - { static const char label[] = { l,f,s,r,c,t,r, NUL }; ADD(spu.ch4.lfsr.counter); } - { static const char label[] = { l,f,s,r,r,e,g, NUL }; ADD(spu.ch4.lfsr.reg); } - { static const char label[] = { e,n,v,NO4,c,t,r, NUL }; ADD(spu.ch4.env.counter); } - { static const char label[] = { e,n,v,NO4,v,o,l, NUL }; ADD(spu.ch4.env.volume); } - { static const char label[] = { l,e,n,NO4,c,t,r, NUL }; ADD(spu.ch4.lcounter.counter); } - { static const char label[] = { l,e,n,NO4,v,a,l, NUL }; ADD(spu.ch4.lcounter.lengthCounter); } - { static const char label[] = { n,r,NO4,NO4, NUL }; ADD(spu.ch4.nr4); } - { static const char label[] = { c,NO4,m,a,s,t,r, NUL }; ADD(spu.ch4.master); } - { static const char label[] = { r,t,c,b,a,s,e, NUL }; ADD(rtc.baseTime); } - { static const char label[] = { r,t,c,h,a,l,t, NUL }; ADD(rtc.haltTime); } - { static const char label[] = { r,t,c,i,n,d,x, NUL }; ADD(rtc.index); } - { static const char label[] = { r,t,c,d,h, NUL }; ADD(rtc.dataDh); } - { static const char label[] = { r,t,c,d,l, NUL }; ADD(rtc.dataDl); } - { static const char label[] = { r,t,c,h, NUL }; ADD(rtc.dataH); } - { static const char label[] = { r,t,c,m, NUL }; ADD(rtc.dataM); } - { static const char label[] = { r,t,c,s, NUL }; ADD(rtc.dataS); } - { static const char label[] = { r,t,c,l,l,d, NUL }; ADD(rtc.lastLatchData); } - -#undef ADD -#undef ADDPTR -#undef ADDTIME - - list.resize(list.size()); - std::sort(list.begin(), list.end()); - - maxLabelsize_ = 0; - - for (std::size_t i = 0; i < list.size(); ++i) { - if (list[i].labelsize > maxLabelsize_) - maxLabelsize_ = list[i].labelsize; - } -} - -static void writeSnapShot(std::ofstream &file, const Gambatte::uint_least32_t *pixels, const unsigned pitch) { - put24(file, pixels ? StateSaver::SS_WIDTH * StateSaver::SS_HEIGHT * sizeof(Gambatte::uint_least32_t) : 0); - - if (pixels) { - Gambatte::uint_least32_t buf[StateSaver::SS_WIDTH]; - - for (unsigned h = StateSaver::SS_HEIGHT; h--;) { - for (unsigned x = 0; x < StateSaver::SS_WIDTH; ++x) { - unsigned long rb = 0; - unsigned long g = 0; - - static const unsigned w[StateSaver::SS_DIV] = { 3, 5, 5, 3 }; - - for (unsigned y = 0; y < StateSaver::SS_DIV; ++y) - for (unsigned xx = 0; xx < StateSaver::SS_DIV; ++xx) { - rb += (pixels[x * StateSaver::SS_DIV + y * pitch + xx] & 0xFF00FF) * w[y] * w[xx]; - g += (pixels[x * StateSaver::SS_DIV + y * pitch + xx] & 0x00FF00) * w[y] * w[xx]; - } - - buf[x] = (rb >> 8 & 0xFF00FF) | (g >> 8 & 0x00FF00); - } - - file.write(reinterpret_cast(buf), sizeof(buf)); - pixels += pitch * StateSaver::SS_DIV; - } - } -} - -static SaverList list; - -void StateSaver::saveState(const SaveState &state, const char *filename) { - std::ofstream file(filename, std::ios_base::binary); - - if (file.fail()) - return; - - { static const char ver[] = { 0, 0 }; file.write(ver, sizeof(ver)); } - - writeSnapShot(file, state.ppu.drawBuffer.get(), state.ppu.drawBuffer.getSz() / 144); - - for (SaverList::const_iterator it = list.begin(); it != list.end(); ++it) { - file.write(it->label, it->labelsize); - (*it->save)(file, state); - } -} - -bool StateSaver::loadState(SaveState &state, const char *filename) { - std::ifstream file(filename, std::ios_base::binary); - - if (file.fail() || file.get() != 0) - return false; - - file.ignore(); - file.ignore(get24(file)); - - Array labelbuf(list.maxLabelsize()); - const Saver labelbufSaver = { label: labelbuf, save: 0, load: 0, labelsize: (unsigned char)list.maxLabelsize() }; - - SaverList::const_iterator done = list.begin(); - - while (file.good() && done != list.end()) { - file.getline(labelbuf, list.maxLabelsize(), NUL); - - SaverList::const_iterator it = done; - - if (std::strcmp(labelbuf, it->label)) { - it = std::lower_bound(it + 1, list.end(), labelbufSaver); - - if (it == list.end() || std::strcmp(labelbuf, it->label)) { - file.ignore(get24(file)); - continue; - } - } else - ++done; - - (*it->load)(file, state); - } - - state.cpu.cycleCounter &= 0x7FFFFFFF; - state.spu.cycleCounter &= 0x7FFFFFFF; - - return true; -} diff --git a/supergameboy/libgambatte/src/statesaver.h b/supergameboy/libgambatte/src/statesaver.h deleted file mode 100644 index ea9ce8b3..00000000 --- a/supergameboy/libgambatte/src/statesaver.h +++ /dev/null @@ -1,37 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2008 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef STATESAVER_H -#define STATESAVER_H - -class SaveState; - -class StateSaver { - StateSaver(); - -public: - enum { SS_SHIFT = 2 }; - enum { SS_DIV = 1 << 2 }; - enum { SS_WIDTH = 160 >> SS_SHIFT }; - enum { SS_HEIGHT = 144 >> SS_SHIFT }; - - static void saveState(const SaveState &state, const char *filename); - static bool loadState(SaveState &state, const char *filename); -}; - -#endif diff --git a/supergameboy/libgambatte/src/video.cpp b/supergameboy/libgambatte/src/video.cpp deleted file mode 100644 index 875afa43..00000000 --- a/supergameboy/libgambatte/src/video.cpp +++ /dev/null @@ -1,1474 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aam�s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "video.h" -#include "videoblitter.h" -#include "video/filters/filter.h" -#include "video/filters/catrom2x.h" -#include "video/filters/catrom3x.h" -#include "video/filters/kreed2xsai.h" -#include "video/filters/maxsthq2x.h" -#include "video/filters/maxsthq3x.h" -#include "filterinfo.h" -#include "savestate.h" -#include "video/basic_add_event.h" -#include -#include - -static void addEventIfActivated(event_queue &q, VideoEvent *const e, const unsigned long newTime) { - e->setTime(newTime); - - if (newTime != VideoEvent::DISABLED_TIME) - q.push(e); -} - -void LCD::setDmgPalette(unsigned long *const palette, const unsigned long *const dmgColors, const unsigned data) { - palette[0] = dmgColors[data & 3]; - palette[1] = dmgColors[data >> 2 & 3]; - palette[2] = dmgColors[data >> 4 & 3]; - palette[3] = dmgColors[data >> 6 & 3]; -} - -unsigned long LCD::gbcToRgb32(const unsigned bgr15) { - const unsigned long r = bgr15 & 0x1F; - const unsigned long g = bgr15 >> 5 & 0x1F; - const unsigned long b = bgr15 >> 10 & 0x1F; - - return ((r * 13 + g * 2 + b) >> 1) << 16 | ((g * 3 + b) << 9) | ((r * 3 + g * 2 + b * 11) >> 1); -} - -unsigned long LCD::gbcToRgb16(const unsigned bgr15) { - const unsigned r = bgr15 & 0x1F; - const unsigned g = bgr15 >> 5 & 0x1F; - const unsigned b = bgr15 >> 10 & 0x1F; - - return (((r * 13 + g * 2 + b + 8) << 7) & 0xF800) | ((g * 3 + b + 1) >> 1) << 5 | ((r * 3 + g * 2 + b * 11 + 8) >> 4); -} - -unsigned long LCD::gbcToUyvy(const unsigned bgr15) { - const unsigned r5 = bgr15 & 0x1F; - const unsigned g5 = bgr15 >> 5 & 0x1F; - const unsigned b5 = bgr15 >> 10 & 0x1F; - - // y = (r5 * 926151 + g5 * 1723530 + b5 * 854319) / 510000 + 16; - // u = (b5 * 397544 - r5 * 68824 - g5 * 328720) / 225930 + 128; - // v = (r5 * 491176 - g5 * 328720 - b5 * 162456) / 178755 + 128; - - const unsigned long y = (r5 * 116 + g5 * 216 + b5 * 107 + 16 * 64 + 32) >> 6; - const unsigned long u = (b5 * 225 - r5 * 39 - g5 * 186 + 128 * 128 + 64) >> 7; - const unsigned long v = (r5 * 176 - g5 * 118 - b5 * 58 + 128 * 64 + 32) >> 6; - -#ifdef WORDS_BIGENDIAN - return u << 24 | y << 16 | v << 8 | y; -#else - return y << 24 | v << 16 | y << 8 | u; -#endif -} - -LCD::LCD(const unsigned char *const oamram, const unsigned char *const vram_in) : - vram(vram_in), - bgTileData(vram), - bgTileMap(vram + 0x1800), - wdTileMap(bgTileMap), - vBlitter(NULL), - filter(NULL), - dbuffer(NULL), - draw(NULL), - gbcToFormat(gbcToRgb32), - dmgColors(dmgColorsRgb32), - lastUpdate(0), - videoCycles(0), - dpitch(0), - winYPos(0), - m3EventQueue(11, VideoEventComparer()), - irqEventQueue(4, VideoEventComparer()), - vEventQueue(5, VideoEventComparer()), - win(m3EventQueue, lyCounter, m3ExtraCycles), - scxReader(m3EventQueue, /*wyReg.reader3(),*/ win.wxReader, win.we.enableChecker(), win.we.disableChecker(), m3ExtraCycles), - spriteMapper(m3ExtraCycles, lyCounter, oamram), - m3ExtraCycles(spriteMapper, scxReader, win), - breakEvent(drawStartCycle, scReadOffset), - mode3Event(m3EventQueue, vEventQueue, mode0Irq, irqEvent), - lycIrq(ifReg), - mode0Irq(lyCounter, lycIrq, m3ExtraCycles, ifReg), - mode1Irq(ifReg), - mode2Irq(lyCounter, lycIrq, ifReg), - irqEvent(irqEventQueue), - drawStartCycle(90), - scReadOffset(90), - ifReg(0), - tileIndexSign(0), - statReg(0), - doubleSpeed(false), - enabled(false), - cgb(false), - bgEnable(false), - spriteEnable(false) -{ - std::memset(bgpData, 0, sizeof(bgpData)); - std::memset(objpData, 0, sizeof(objpData)); - - for (unsigned i = 0; i < sizeof(dmgColorsRgb32) / sizeof(unsigned long); ++i) { - setDmgPaletteColor(i, (3 - (i & 3)) * 85 * 0x010101); - } - - filters.push_back(NULL); - filters.push_back(new Catrom2x); - filters.push_back(new Catrom3x); - filters.push_back(new Kreed_2xSaI); - filters.push_back(new MaxSt_Hq2x); - filters.push_back(new MaxSt_Hq3x); - - reset(oamram, false); - setDoubleSpeed(false); - - setVideoFilter(0); -} - -LCD::~LCD() { -// delete []filter_buffer; - for (std::size_t i = 0; i < filters.size(); ++i) - delete filters[i]; -} - -void LCD::reset(const unsigned char *const oamram, const bool cgb_in) { - cgb = cgb_in; - spriteMapper.reset(oamram, cgb_in); - setDBuffer(); -} - -void LCD::resetVideoState(const unsigned long cycleCounter) { - vEventQueue.clear(); - m3EventQueue.clear(); - irqEventQueue.clear(); - - lyCounter.reset(videoCycles, lastUpdate); - vEventQueue.push(&lyCounter); - - spriteMapper.resetVideoState(); - m3ExtraCycles.invalidateCache(); - - addEventIfActivated(m3EventQueue, &scxReader, ScxReader::schedule(lyCounter, cycleCounter)); - addEventIfActivated(m3EventQueue, &win.wxReader, WxReader::schedule(scxReader.scxAnd7(), lyCounter, win.wxReader, cycleCounter)); - addEventIfActivated(m3EventQueue, &win.wyReg.reader1(), Wy::WyReader1::schedule(lyCounter, cycleCounter)); - addEventIfActivated(m3EventQueue, &win.wyReg.reader2(), Wy::WyReader2::schedule(lyCounter, cycleCounter)); - addEventIfActivated(m3EventQueue, &win.wyReg.reader3(), Wy::WyReader3::schedule(win.wxReader.getSource(), scxReader, lyCounter, cycleCounter)); - addEventIfActivated(m3EventQueue, &win.wyReg.reader4(), Wy::WyReader4::schedule(lyCounter, cycleCounter)); - addEventIfActivated(m3EventQueue, &spriteMapper, SpriteMapper::schedule(lyCounter, cycleCounter)); - addEventIfActivated(m3EventQueue, &win.we.enableChecker(), We::WeEnableChecker::schedule(scxReader.scxAnd7(), win.wxReader.wx(), lyCounter, cycleCounter)); - addEventIfActivated(m3EventQueue, &win.we.disableChecker(), We::WeDisableChecker::schedule(scxReader.scxAnd7(), win.wxReader.wx(), lyCounter, cycleCounter)); - addEventIfActivated(m3EventQueue, &win.weMasterChecker, WeMasterChecker::schedule(win.wyReg.getSource(), win.we.getSource(), lyCounter, cycleCounter)); - - addEventIfActivated(irqEventQueue, &lycIrq, LycIrq::schedule(statReg, lycIrq.lycReg(), lyCounter, cycleCounter)); - addEventIfActivated(irqEventQueue, &mode0Irq, Mode0Irq::schedule(statReg, m3ExtraCycles, lyCounter, cycleCounter)); - addEventIfActivated(irqEventQueue, &mode1Irq, Mode1Irq::schedule(lyCounter, cycleCounter)); - addEventIfActivated(irqEventQueue, &mode2Irq, Mode2Irq::schedule(statReg, lyCounter, cycleCounter)); - - addEventIfActivated(vEventQueue, &mode3Event, Mode3Event::schedule(m3EventQueue)); - addEventIfActivated(vEventQueue, &irqEvent, IrqEvent::schedule(irqEventQueue)); - addEventIfActivated(vEventQueue, &scReader, ScReader::schedule(lastUpdate, videoCycles, scReadOffset, doubleSpeed)); - addEventIfActivated(vEventQueue, &breakEvent, BreakEvent::schedule(lyCounter)); -} - -void LCD::setDoubleSpeed(const bool ds) { - doubleSpeed = ds; - lyCounter.setDoubleSpeed(doubleSpeed); - scxReader.setDoubleSpeed(doubleSpeed); - win.wxReader.setDoubleSpeed(doubleSpeed); - scReader.setDoubleSpeed(doubleSpeed); - breakEvent.setDoubleSpeed(doubleSpeed); - lycIrq.setDoubleSpeed(doubleSpeed); - mode1Irq.setDoubleSpeed(doubleSpeed); -} - -void LCD::setStatePtrs(SaveState &state) { - state.ppu.drawBuffer.set(static_cast(dbuffer), dpitch * 144); - state.ppu.bgpData.set(bgpData, sizeof bgpData); - state.ppu.objpData.set(objpData, sizeof objpData); - spriteMapper.setStatePtrs(state); -} - -void LCD::saveState(SaveState &state) const { - state.ppu.videoCycles = videoCycles; - state.ppu.winYPos = winYPos; - state.ppu.drawStartCycle = drawStartCycle; - state.ppu.scReadOffset = scReadOffset; - state.ppu.lcdc = enabled << 7 | ((wdTileMap - vram - 0x1800) >> 4) | (tileIndexSign ^ 0x80) >> 3 | ((bgTileMap - vram - 0x1800) >> 7) | spriteEnable << 1 | bgEnable; - state.ppu.lycIrqSkip = lycIrq.skips(); - - spriteMapper.saveState(state); - scReader.saveState(state); - scxReader.saveState(state); - win.weMasterChecker.saveState(state); - win.wxReader.saveState(state); - win.wyReg.saveState(state); - win.we.saveState(state); -} - -void LCD::loadState(const SaveState &state, const unsigned char *oamram) { - statReg = state.mem.ioamhram.get()[0x141]; - ifReg = 0; - - setDoubleSpeed(cgb & state.mem.ioamhram.get()[0x14D] >> 7); - - lastUpdate = state.cpu.cycleCounter; - videoCycles = std::min(state.ppu.videoCycles, 70223ul); - winYPos = state.ppu.winYPos > 143 ? 0xFF : state.ppu.winYPos; - drawStartCycle = state.ppu.drawStartCycle; - scReadOffset = state.ppu.scReadOffset; - enabled = state.ppu.lcdc >> 7 & 1; - wdTileMap = vram + 0x1800 + (state.ppu.lcdc >> 6 & 1) * 0x400; - tileIndexSign = ((state.ppu.lcdc >> 4 & 1) ^ 1) * 0x80; - bgTileData = vram + ((state.ppu.lcdc >> 4 & 1) ^ 1) * 0x1000; - bgTileMap = vram + 0x1800 + (state.ppu.lcdc >> 3 & 1) * 0x400; - spriteEnable = state.ppu.lcdc >> 1 & 1; - bgEnable = state.ppu.lcdc & 1; - - lycIrq.setM2IrqEnabled(statReg >> 5 & 1); - lycIrq.setLycReg(state.mem.ioamhram.get()[0x145]); - lycIrq.setSkip(state.ppu.lycIrqSkip); - mode1Irq.setM1StatIrqEnabled(statReg >> 4 & 1); - - win.we.setSource(state.mem.ioamhram.get()[0x140] >> 5 & 1); - spriteMapper.setLargeSpritesSource(state.mem.ioamhram.get()[0x140] >> 2 & 1); - scReader.setScySource(state.mem.ioamhram.get()[0x142]); - scxReader.setSource(state.mem.ioamhram.get()[0x143]); - breakEvent.setScxSource(state.mem.ioamhram.get()[0x143]); - scReader.setScxSource(state.mem.ioamhram.get()[0x143]); - win.wyReg.setSource(state.mem.ioamhram.get()[0x14A]); - win.wxReader.setSource(state.mem.ioamhram.get()[0x14B]); - - spriteMapper.loadState(state); - scReader.loadState(state); - scxReader.loadState(state); - win.weMasterChecker.loadState(state); - win.wxReader.loadState(state); - win.wyReg.loadState(state); - win.we.loadState(state); - - resetVideoState(lastUpdate); - spriteMapper.oamChange(oamram, lastUpdate); - refreshPalettes(); -} - -void LCD::refreshPalettes() { - if (cgb) { - for (unsigned i = 0; i < 8 * 8; i += 2) { - bgPalette[i >> 1] = (*gbcToFormat)(bgpData[i] | bgpData[i + 1] << 8); - spPalette[i >> 1] = (*gbcToFormat)(objpData[i] | objpData[i + 1] << 8); - } - } else { - setDmgPalette(bgPalette, dmgColors, bgpData[0]); - setDmgPalette(spPalette, dmgColors + 4, objpData[0]); - setDmgPalette(spPalette + 4, dmgColors + 8, objpData[1]); - } -} - -void LCD::setVideoBlitter(Gambatte::VideoBlitter *vb) { - vBlitter = vb; - - if (vBlitter) { - vBlitter->setBufferDimensions(videoWidth(), videoHeight()); - pb = vBlitter->inBuffer(); - } - - setDBuffer(); -} - -void LCD::videoBufferChange() { - if (vBlitter) { - pb = vBlitter->inBuffer(); - setDBuffer(); - } -} - -void LCD::setVideoFilter(const unsigned n) { - const unsigned oldw = videoWidth(); - const unsigned oldh = videoHeight(); - - if (filter) - filter->outit(); - - filter = filters.at(n < filters.size() ? n : 0); - - if (filter) { - filter->init(); - } - - if (vBlitter && (oldw != videoWidth() || oldh != videoHeight())) { - vBlitter->setBufferDimensions(videoWidth(), videoHeight()); - pb = vBlitter->inBuffer(); - } - - setDBuffer(); -} - -std::vector LCD::filterInfo() const { - std::vector v; - - static Gambatte::FilterInfo noInfo = { "None", 160, 144 }; - v.push_back(&noInfo); - - for (std::size_t i = 1; i < filters.size(); ++i) - v.push_back(&filters[i]->info()); - - return v; -} - -unsigned int LCD::videoWidth() const { - return filter ? filter->info().outWidth : 160; -} - -unsigned int LCD::videoHeight() const { - return filter ? filter->info().outHeight : 144; -} - -template -static void blitOsdElement(Gambatte::uint_least32_t *d, const Gambatte::uint_least32_t *s, const unsigned width, unsigned h, const unsigned dpitch, Blend blend) { - while (h--) { - for (unsigned w = width; w--;) { - if (*s != 0xFFFFFFFF) - *d = blend(*s, *d); - - ++d; - ++s; - } - - d += dpitch - width; - } -} - -template -struct Blend { - enum { SW = weight - 1 }; - enum { LOWMASK = SW * 0x010101ul }; - Gambatte::uint_least32_t operator()(const Gambatte::uint_least32_t s, const Gambatte::uint_least32_t d) const { - return (s * SW + d - (((s & LOWMASK) * SW + (d & LOWMASK)) & LOWMASK)) / weight; - } -}; - -void LCD::updateScreen(const unsigned long cycleCounter) { - update(cycleCounter); - - if (pb.pixels) { - if (dbuffer && osdElement.get()) { - const Gambatte::uint_least32_t *s = osdElement->update(); - - if (s) { - Gambatte::uint_least32_t *d = static_cast(dbuffer) + osdElement->y() * dpitch + osdElement->x(); - - switch (osdElement->opacity()) { - case OsdElement::SEVEN_EIGHTHS: blitOsdElement(d, s, osdElement->w(), osdElement->h(), dpitch, Blend<8>()); break; - case OsdElement::THREE_FOURTHS: blitOsdElement(d, s, osdElement->w(), osdElement->h(), dpitch, Blend<4>()); break; - } - } else - osdElement.reset(); - } - - if (filter) { - filter->filter(static_cast(tmpbuf ? tmpbuf : pb.pixels), (tmpbuf ? videoWidth() : pb.pitch)); - } - - if (tmpbuf) { - switch (pb.format) { - case Gambatte::PixelBuffer::RGB16: - rgb32ToRgb16(tmpbuf, static_cast(pb.pixels), videoWidth(), videoHeight(), pb.pitch); - break; - case Gambatte::PixelBuffer::UYVY: - rgb32ToUyvy(tmpbuf, static_cast(pb.pixels), videoWidth(), videoHeight(), pb.pitch); - break; - default: break; - } - } - - if (vBlitter) - vBlitter->blit(); - } -} - -template -static void clear(T *buf, const unsigned long color, const unsigned dpitch) { - unsigned lines = 144; - - while (lines--) { - std::fill_n(buf, 160, color); - buf += dpitch; - } -} - -void LCD::enableChange(const unsigned long cycleCounter) { - update(cycleCounter); - enabled = !enabled; - - if (enabled) { - lycIrq.setSkip(false); - videoCycles = 0; - lastUpdate = cycleCounter; - winYPos = 0xFF; - win.weMasterChecker.unset(); - spriteMapper.enableDisplay(cycleCounter); - resetVideoState(cycleCounter); - } - - if (!enabled && dbuffer) { - const unsigned long color = cgb ? (*gbcToFormat)(0xFFFF) : dmgColors[0]; - - clear(static_cast(dbuffer), color, dpitch); - -// updateScreen(cycleCounter); - } -} - -//FIXME: needs testing -void LCD::lyWrite(const unsigned long cycleCounter) { - update(cycleCounter); - lycIrq.setSkip(false); - videoCycles = 0; - lastUpdate = cycleCounter; - winYPos = 0xFF; - win.weMasterChecker.unset(); - resetVideoState(cycleCounter); - -// if ((statReg & 0x40) && lycIrq.lycReg() == 0) -// ifReg |= 2; -} - -void LCD::preResetCounter(const unsigned long cycleCounter) { - preSpeedChange(cycleCounter); -} - -void LCD::postResetCounter(const unsigned long oldCC, const unsigned long cycleCounter) { - lastUpdate = cycleCounter - (oldCC - lastUpdate); - spriteMapper.resetCycleCounter(oldCC, cycleCounter); - resetVideoState(cycleCounter); -} - -void LCD::preSpeedChange(const unsigned long cycleCounter) { - update(cycleCounter); - spriteMapper.preCounterChange(cycleCounter); -} - -void LCD::postSpeedChange(const unsigned long cycleCounter) { - setDoubleSpeed(!doubleSpeed); - - resetVideoState(cycleCounter); -} - -bool LCD::isMode0IrqPeriod(const unsigned long cycleCounter) { - if (cycleCounter >= vEventQueue.top()->time()) - update(cycleCounter); - - const unsigned timeToNextLy = lyCounter.time() - cycleCounter; - - return /*memory.enable_display && */lyCounter.ly() < 144 && timeToNextLy <= (456U - (169 + doubleSpeed * 3U + 80 + m3ExtraCycles(lyCounter.ly()) + 1 - doubleSpeed)) << doubleSpeed && timeToNextLy > 4; -} - -bool LCD::isMode2IrqPeriod(const unsigned long cycleCounter) { - if (cycleCounter >= lyCounter.time()) - update(cycleCounter); - - const unsigned nextLy = lyCounter.time() - cycleCounter; - - return /*memory.enable_display && */lyCounter.ly() < 143 && nextLy <= 4; -} - -bool LCD::isLycIrqPeriod(const unsigned lycReg, const unsigned endCycles, const unsigned long cycleCounter) { - if (cycleCounter >= lyCounter.time()) - update(cycleCounter); - - const unsigned timeToNextLy = lyCounter.time() - cycleCounter; - - return (lyCounter.ly() == lycReg && timeToNextLy > endCycles) || (lycReg == 0 && lyCounter.ly() == 153 && timeToNextLy <= (456U - 8U) << doubleSpeed); -} - -bool LCD::isMode1IrqPeriod(const unsigned long cycleCounter) { - if (cycleCounter >= lyCounter.time()) - update(cycleCounter); - - const unsigned timeToNextLy = lyCounter.time() - cycleCounter; - - return lyCounter.ly() > 143 && (lyCounter.ly() < 153 || timeToNextLy > 4U - doubleSpeed * 4U); -} - -bool LCD::isHdmaPeriod(const unsigned long cycleCounter) { - if (cycleCounter >= vEventQueue.top()->time()) - update(cycleCounter); - - const unsigned timeToNextLy = lyCounter.time() - cycleCounter; - - return /*memory.enable_display && */lyCounter.ly() < 144 && timeToNextLy <= ((456U - (169U + doubleSpeed * 3U + 80U + m3ExtraCycles(lyCounter.ly()) + 2 - doubleSpeed)) << doubleSpeed) && timeToNextLy > 4; -} - -unsigned long LCD::nextHdmaTime(const unsigned long cycleCounter) { - if (cycleCounter >= vEventQueue.top()->time()) - update(cycleCounter); - - unsigned line = lyCounter.ly(); - int next = static_cast(169 + doubleSpeed * 3U + 80 + 2 - doubleSpeed) - static_cast(lyCounter.lineCycles(cycleCounter)); - - if (line < 144 && next + static_cast(m3ExtraCycles(line)) <= 0) { - next += 456; - ++line; - } - - if (line > 143) { - next += (154 - line) * 456; - line = 0; - } - - next += m3ExtraCycles(line); - - return cycleCounter + (static_cast(next) << doubleSpeed); -} - -bool LCD::vramAccessible(const unsigned long cycleCounter) { - if (cycleCounter >= vEventQueue.top()->time()) - update(cycleCounter); - - bool accessible = true; - - if (enabled && lyCounter.ly() < 144) { - const unsigned lineCycles = lyCounter.lineCycles(cycleCounter); - - if (lineCycles > 79 && lineCycles < 80 + 169 + doubleSpeed * 3U + m3ExtraCycles(lyCounter.ly())) - accessible = false; - } - - return accessible; -} - -bool LCD::cgbpAccessible(const unsigned long cycleCounter) { - if (cycleCounter >= vEventQueue.top()->time()) - update(cycleCounter); - - bool accessible = true; - - if (enabled && lyCounter.ly() < 144) { - const unsigned lineCycles = lyCounter.lineCycles(cycleCounter); - - if (lineCycles > 79U + doubleSpeed && lineCycles < 80U + 169U + doubleSpeed * 3U + m3ExtraCycles(lyCounter.ly()) + 4U - doubleSpeed * 2U) - accessible = false; - } - - return accessible; -} - -bool LCD::oamAccessible(const unsigned long cycleCounter) { - bool accessible = true; - - if (enabled) { - if (cycleCounter >= vEventQueue.top()->time()) - update(cycleCounter); - - accessible = spriteMapper.oamAccessible(cycleCounter); - } - - return accessible; -} - -void LCD::weChange(const bool newValue, const unsigned long cycleCounter) { - if (cycleCounter >= vEventQueue.top()->time()) - update(cycleCounter); - - win.we.setSource(newValue); - addFixedtimeEvent(m3EventQueue, &win.weMasterChecker, WeMasterChecker::schedule(win.wyReg.getSource(), newValue, lyCounter, cycleCounter)); - addFixedtimeEvent(m3EventQueue, &win.we.disableChecker(), We::WeDisableChecker::schedule(scxReader.scxAnd7(), win.wxReader.wx(), lyCounter, cycleCounter)); - addFixedtimeEvent(m3EventQueue, &win.we.enableChecker(), We::WeEnableChecker::schedule(scxReader.scxAnd7(), win.wxReader.wx(), lyCounter, cycleCounter)); - addUnconditionalEvent(vEventQueue, &mode3Event, Mode3Event::schedule(m3EventQueue)); -} - -void LCD::wxChange(const unsigned newValue, const unsigned long cycleCounter) { - if (cycleCounter >= vEventQueue.top()->time()) - update(cycleCounter); - - win.wxReader.setSource(newValue); - addEvent(m3EventQueue, &win.wxReader, WxReader::schedule(scxReader.scxAnd7(), lyCounter, win.wxReader, cycleCounter)); - - if (win.wyReg.reader3().time() != VideoEvent::DISABLED_TIME) - addEvent(m3EventQueue, &win.wyReg.reader3(), Wy::WyReader3::schedule(win.wxReader.getSource(), scxReader, lyCounter, cycleCounter)); - - addUnconditionalEvent(vEventQueue, &mode3Event, Mode3Event::schedule(m3EventQueue)); -} - -void LCD::wyChange(const unsigned newValue, const unsigned long cycleCounter) { - if (cycleCounter >= vEventQueue.top()->time()) - update(cycleCounter); - - win.wyReg.setSource(newValue); - addFixedtimeEvent(m3EventQueue, &win.wyReg.reader1(), Wy::WyReader1::schedule(lyCounter, cycleCounter)); - addFixedtimeEvent(m3EventQueue, &win.wyReg.reader2(), Wy::WyReader2::schedule(lyCounter, cycleCounter)); - addFixedtimeEvent(m3EventQueue, &win.wyReg.reader3(), Wy::WyReader3::schedule(win.wxReader.getSource(), scxReader, lyCounter, cycleCounter)); - addFixedtimeEvent(m3EventQueue, &win.wyReg.reader4(), Wy::WyReader4::schedule(lyCounter, cycleCounter)); - addEvent(m3EventQueue, &win.weMasterChecker, WeMasterChecker::schedule(win.wyReg.getSource(), win.we.getSource(), lyCounter, cycleCounter)); - addUnconditionalEvent(vEventQueue, &mode3Event, Mode3Event::schedule(m3EventQueue)); -} - -void LCD::scxChange(const unsigned newScx, const unsigned long cycleCounter) { - update(cycleCounter); - - scxReader.setSource(newScx); - breakEvent.setScxSource(newScx); - scReader.setScxSource(newScx); - - addFixedtimeEvent(m3EventQueue, &scxReader, ScxReader::schedule(lyCounter, cycleCounter)); - - if (win.wyReg.reader3().time() != VideoEvent::DISABLED_TIME) - addEvent(m3EventQueue, &win.wyReg.reader3(), Wy::WyReader3::schedule(win.wxReader.getSource(), scxReader, lyCounter, cycleCounter)); - - addUnconditionalEvent(vEventQueue, &mode3Event, Mode3Event::schedule(m3EventQueue)); - - const unsigned lineCycles = lyCounter.lineCycles(cycleCounter); - - if (lineCycles < 82U + doubleSpeed * 4U) - drawStartCycle = 90 + doubleSpeed * 4U + (newScx & 7); - else - addFixedtimeEvent(vEventQueue, &breakEvent, BreakEvent::schedule(lyCounter)); - - if (lineCycles < 86U + doubleSpeed * 2U) - scReadOffset = std::max(drawStartCycle - (newScx & 7), 90U + doubleSpeed * 4U); - - addEvent(vEventQueue, &scReader, ScReader::schedule(lastUpdate, videoCycles, scReadOffset, doubleSpeed)); -} - -void LCD::scyChange(const unsigned newValue, const unsigned long cycleCounter) { - update(cycleCounter); - - scReader.setScySource(newValue); - addFixedtimeEvent(vEventQueue, &scReader, ScReader::schedule(lastUpdate, videoCycles, scReadOffset, doubleSpeed)); -} - -void LCD::spriteSizeChange(const bool newLarge, const unsigned long cycleCounter) { - update(cycleCounter); - - spriteMapper.oamChange(cycleCounter); - spriteMapper.setLargeSpritesSource(newLarge); - addFixedtimeEvent(m3EventQueue, &spriteMapper, SpriteMapper::schedule(lyCounter, cycleCounter)); - addUnconditionalEvent(vEventQueue, &mode3Event, Mode3Event::schedule(m3EventQueue)); -} - -void LCD::oamChange(const unsigned long cycleCounter) { - update(cycleCounter); - - spriteMapper.oamChange(cycleCounter); - addFixedtimeEvent(m3EventQueue, &spriteMapper, SpriteMapper::schedule(lyCounter, cycleCounter)); - addUnconditionalEvent(vEventQueue, &mode3Event, Mode3Event::schedule(m3EventQueue)); -} - -void LCD::oamChange(const unsigned char *const oamram, const unsigned long cycleCounter) { - update(cycleCounter); - - spriteMapper.oamChange(oamram, cycleCounter); - addFixedtimeEvent(m3EventQueue, &spriteMapper, SpriteMapper::schedule(lyCounter, cycleCounter)); - addUnconditionalEvent(vEventQueue, &mode3Event, Mode3Event::schedule(m3EventQueue)); -} - -void LCD::wdTileMapSelectChange(const bool newValue, const unsigned long cycleCounter) { - update(cycleCounter); - - wdTileMap = vram + 0x1800 + newValue * 0x400; -} - -void LCD::bgTileMapSelectChange(const bool newValue, const unsigned long cycleCounter) { - update(cycleCounter); - - bgTileMap = vram + 0x1800 + newValue * 0x400; -} - -void LCD::bgTileDataSelectChange(const bool newValue, const unsigned long cycleCounter) { - update(cycleCounter); - - tileIndexSign = (newValue ^ 1) * 0x80; - bgTileData = vram + (newValue ^ 1) * 0x1000; -} - -void LCD::spriteEnableChange(const bool newValue, const unsigned long cycleCounter) { - update(cycleCounter); - - spriteEnable = newValue; -} - -void LCD::bgEnableChange(const bool newValue, const unsigned long cycleCounter) { - update(cycleCounter); - - bgEnable = newValue; -} - -void LCD::lcdstatChange(const unsigned data, const unsigned long cycleCounter) { - if (cycleCounter >= vEventQueue.top()->time()) - update(cycleCounter); - - const unsigned old = statReg; - statReg = data; - mode1Irq.setM1StatIrqEnabled(data & 0x10); - lycIrq.setM2IrqEnabled(data & 0x20); - - if (!enabled) - return; - - const bool lycIrqPeriod = isLycIrqPeriod(lycIrq.lycReg(), lycIrq.lycReg() == 153 ? lyCounter.lineTime() - (4 << (doubleSpeed*2)) : 4 - doubleSpeed * 4U, cycleCounter); - - if (lycIrq.lycReg() < 154 && ((data ^ old) & 0x40)) { - if (data & 0x40) { - if (lycIrqPeriod) - ifReg |= 2; - } else { - if (!doubleSpeed && lycIrq.time() - cycleCounter < 5 && (!(old & 0x20) || lycIrq.lycReg() > 143 || lycIrq.lycReg() == 0)) - ifReg |= 2; - } - - addFixedtimeEvent(irqEventQueue, &lycIrq, LycIrq::schedule(data, lycIrq.lycReg(), lyCounter, cycleCounter)); - } - - if ((((data & 0x10) && !(old & 0x10)) || !cgb) && !((old & 0x40) && lycIrqPeriod) && isMode1IrqPeriod(cycleCounter)) - ifReg |= 2; - - if ((data ^ old) & 0x08) { - if (data & 0x08) { - if (!((old & 0x40) && lycIrqPeriod) && isMode0IrqPeriod(cycleCounter)) - ifReg |= 2; - } else { - if (mode0Irq.time() - cycleCounter < 3 && (lycIrq.time() == VideoEvent::DISABLED_TIME || lyCounter.ly() != lycIrq.lycReg())) - ifReg |= 2; - } - - addFixedtimeEvent(irqEventQueue, &mode0Irq, Mode0Irq::schedule(data, m3ExtraCycles, lyCounter, cycleCounter)); - } - - if ((data & 0x28) == 0x20 && (old & 0x28) != 0x20 && isMode2IrqPeriod(cycleCounter)) { - ifReg |= 2; - } - - addFixedtimeEvent(irqEventQueue, &mode2Irq, Mode2Irq::schedule(data, lyCounter, cycleCounter)); - - addEvent(vEventQueue, &irqEvent, IrqEvent::schedule(irqEventQueue)); -} - -void LCD::lycRegChange(const unsigned data, const unsigned long cycleCounter) { - if (data == lycIrq.lycReg()) - return; - - if (cycleCounter >= vEventQueue.top()->time()) - update(cycleCounter); - - const unsigned old = lycIrq.lycReg(); - lycIrq.setLycReg(data); - - if (!(enabled && (statReg & 0x40))) - return; - - if (!doubleSpeed && lycIrq.time() - cycleCounter < 5 && (!(statReg & 0x20) || old > 143 || old == 0)) - ifReg |= 2; - - addEvent(irqEventQueue, &lycIrq, LycIrq::schedule(statReg, lycIrq.lycReg(), lyCounter, cycleCounter)); - - if (data < 154) { - if (isLycIrqPeriod(data, data == 153 ? lyCounter.lineTime() - doubleSpeed * 8U : 8, cycleCounter)) - ifReg |= 2; - - if (lycIrq.isSkipPeriod(cycleCounter, doubleSpeed)) - lycIrq.setSkip(true); - } - - addEvent(vEventQueue, &irqEvent, IrqEvent::schedule(irqEventQueue)); -} - -unsigned long LCD::nextIrqEvent() const { - if (!enabled) - return VideoEvent::DISABLED_TIME; - - if (mode0Irq.time() != VideoEvent::DISABLED_TIME && mode3Event.time() < irqEvent.time()) - return mode3Event.time(); - - return irqEvent.time(); -} - -unsigned LCD::getIfReg(const unsigned long cycleCounter) { - if (cycleCounter >= vEventQueue.top()->time()) - update(cycleCounter); - - return ifReg; -} - -void LCD::setIfReg(const unsigned ifReg_in, const unsigned long cycleCounter) { - if (cycleCounter >= vEventQueue.top()->time()) - update(cycleCounter); - - ifReg = ifReg_in; -} - -unsigned LCD::get_stat(const unsigned lycReg, const unsigned long cycleCounter) { - unsigned stat = 0; - - if (enabled) { - if (cycleCounter >= vEventQueue.top()->time()) - update(cycleCounter); - - const unsigned timeToNextLy = lyCounter.time() - cycleCounter; - - if (lyCounter.ly() > 143) { - if (lyCounter.ly() < 153 || timeToNextLy > 4 - doubleSpeed * 4U) - stat = 1; - } else { - const unsigned lineCycles = 456 - (timeToNextLy >> doubleSpeed); - - if (lineCycles < 80) { - if (!spriteMapper.inactivePeriodAfterDisplayEnable(cycleCounter)) - stat = 2; - } else if (lineCycles < 80 + 169 + doubleSpeed * 3U + m3ExtraCycles(lyCounter.ly())) - stat = 3; - } - - if ((lyCounter.ly() == lycReg && timeToNextLy > 4 - doubleSpeed * 4U) || - (lycReg == 0 && lyCounter.ly() == 153 && timeToNextLy >> doubleSpeed <= 456 - 8)) { - stat |= 4; - } - } - - return stat; -} - -void LCD::do_update(unsigned cycles) { - if (lyCounter.ly() < 144) { - const unsigned lineCycles = lyCounter.lineCycles(lastUpdate); - const unsigned xpos = lineCycles < drawStartCycle ? 0 : lineCycles - drawStartCycle; - - const unsigned endLineCycles = lineCycles + cycles; - unsigned endX = endLineCycles < drawStartCycle ? 0 : endLineCycles - drawStartCycle; - - if (endX > 160) - endX = 160; - - if (xpos < endX) - (this->*draw)(xpos, lyCounter.ly(), endX); - } else if (lyCounter.ly() == 144) { - winYPos = 0xFF; - //scy[0] = scy[1] = memory.fastread(0xFF42); - //scx[0] = scx[1] = memory.fastread(0xFF43); - win.weMasterChecker.unset(); - } - - videoCycles += cycles; - - if (videoCycles >= 70224U) - videoCycles -= 70224U; -} - -inline void LCD::event() { - vEventQueue.top()->doEvent(); - - if (vEventQueue.top()->time() == VideoEvent::DISABLED_TIME) - vEventQueue.pop(); - else - vEventQueue.modify_root(vEventQueue.top()); -} - -void LCD::update(const unsigned long cycleCounter) { - if (!enabled) - return; - - for (;;) { - const unsigned cycles = (std::max(std::min(cycleCounter, static_cast(vEventQueue.top()->time())), lastUpdate) - lastUpdate) >> doubleSpeed; - do_update(cycles); - lastUpdate += cycles << doubleSpeed; - - if (cycleCounter >= vEventQueue.top()->time()) - event(); - else - break; - } -} - -void LCD::setDBuffer() { - tmpbuf.reset(pb.format == Gambatte::PixelBuffer::RGB32 ? 0 : videoWidth() * videoHeight()); - - if (cgb) - draw = &LCD::cgb_draw; - else - draw = &LCD::dmg_draw; - - gbcToFormat = &gbcToRgb32; - dmgColors = dmgColorsRgb32; - - if (filter) { - dbuffer = filter->inBuffer(); - dpitch = filter->inPitch(); - } else if (pb.format == Gambatte::PixelBuffer::RGB32) { - dbuffer = pb.pixels; - dpitch = pb.pitch; - } else { - dbuffer = tmpbuf; - dpitch = 160; - } - - if (dbuffer == NULL) - draw = &LCD::null_draw; - - refreshPalettes(); -} - -void LCD::setDmgPaletteColor(const unsigned index, const unsigned long rgb32) { - dmgColorsRgb32[index] = rgb32; - dmgColorsRgb16[index] = rgb32ToRgb16(rgb32); - dmgColorsUyvy[index] = ::rgb32ToUyvy(rgb32); -} - -void LCD::setDmgPaletteColor(const unsigned palNum, const unsigned colorNum, const unsigned long rgb32) { - if (palNum > 2 || colorNum > 3) - return; - - setDmgPaletteColor((palNum * 4) | colorNum, rgb32); - refreshPalettes(); -} - -void LCD::null_draw(unsigned /*xpos*/, const unsigned ypos, const unsigned endX) { - const bool enableWindow = win.enabled(ypos); - - if (enableWindow && winYPos == 0xFF) - winYPos = /*ypos - wyReg.value()*/ 0; - - if (endX == 160) { - if (enableWindow) - ++winYPos; - } -} - -template -void LCD::cgb_draw(unsigned xpos, const unsigned ypos, const unsigned endX) { - const unsigned effectiveScx = scReader.scx(); - - const bool enableWindow = win.enabled(ypos); - - if (enableWindow && winYPos == 0xFF) - winYPos = /*ypos - wyReg.value()*/ 0; - - T *const bufLine = static_cast(dbuffer) + ypos * static_cast(dpitch); - - if (!(enableWindow && win.wxReader.wx() <= xpos + 7)) { - const unsigned fby = scReader.scy() + ypos /*& 0xFF*/; - const unsigned end = std::min(enableWindow ? win.wxReader.wx() - 7 : 160U, endX); - - cgb_bg_drawPixels(bufLine, xpos, end, scxReader.scxAnd7(), ((xpos + effectiveScx) & ~7) + ((xpos + drawStartCycle - scReadOffset) & 7), - bgTileMap + (fby & 0xF8) * 4, bgTileData, fby & 7); - } - - if (enableWindow && endX + 7 > win.wxReader.wx()) { - const unsigned start = std::max(win.wxReader.wx() < 7 ? 0U : (win.wxReader.wx() - 7), xpos); - - cgb_bg_drawPixels(bufLine, start, endX, 7u - win.wxReader.wx(), start + (7u - win.wxReader.wx()), - wdTileMap + (winYPos & 0xF8) * 4, bgTileData, winYPos & 7); - } - - if (endX == 160) { - if (spriteEnable) - cgb_drawSprites(bufLine, ypos); - - if (enableWindow) - ++winYPos; - } -} - -template -void LCD::dmg_draw(unsigned xpos, const unsigned ypos, const unsigned endX) { - const unsigned effectiveScx = scReader.scx(); - - const bool enableWindow = win.enabled(ypos); - - if (enableWindow && winYPos == 0xFF) - winYPos = /*ypos - wyReg.value()*/ 0; - - T *const bufLine = static_cast(dbuffer) + ypos * static_cast(dpitch); - - if (bgEnable) { - if (!(enableWindow && win.wxReader.wx() <= xpos + 7)) { - const unsigned fby = scReader.scy() + ypos /*& 0xFF*/; - const unsigned end = std::min(enableWindow ? win.wxReader.wx() - 7 : 160U, endX); - - bg_drawPixels(bufLine, xpos, end, scxReader.scxAnd7(), ((xpos + effectiveScx) & ~7) + ((xpos + drawStartCycle - scReadOffset) & 7), - bgTileMap + (fby & 0xF8) * 4, bgTileData + (fby & 7) * 2); - } - - if (enableWindow && endX + 7 > win.wxReader.wx()) { - const unsigned start = std::max(win.wxReader.wx() < 7 ? 0U : (win.wxReader.wx() - 7), xpos); - - bg_drawPixels(bufLine, start, endX, 7u - win.wxReader.wx(), start + (7u - win.wxReader.wx()), - wdTileMap + (winYPos & 0xF8) * 4, bgTileData + (winYPos & 7) * 2); - } - } else - std::fill_n(bufLine + xpos, endX - xpos, bgPalette[0]); - - if (endX == 160) { - if (spriteEnable) - drawSprites(bufLine, ypos); - - if (enableWindow) - ++winYPos; - } -} - -#define FLIP(u8) ( (((u8) & 0x01) << 7) | (((u8) & 0x02) << 5) | (((u8) & 0x04) << 3) | (((u8) & 0x08) << 1) | \ -(((u8) & 0x10) >> 1) | (((u8) & 0x20) >> 3) | (((u8) & 0x40) >> 5) | (((u8) & 0x80) >> 7) ) - -#define FLIP_ROW(n) FLIP((n)|0x0), FLIP((n)|0x1), FLIP((n)|0x2), FLIP((n)|0x3), FLIP((n)|0x4), FLIP((n)|0x5), FLIP((n)|0x6), FLIP((n)|0x7), \ -FLIP((n)|0x8), FLIP((n)|0x9), FLIP((n)|0xA), FLIP((n)|0xB), FLIP((n)|0xC), FLIP((n)|0xD), FLIP((n)|0xE), FLIP((n)|0xF) - -static const unsigned char xflipt[0x100] = { - FLIP_ROW(0x00), FLIP_ROW(0x10), FLIP_ROW(0x20), FLIP_ROW(0x30), - FLIP_ROW(0x40), FLIP_ROW(0x50), FLIP_ROW(0x60), FLIP_ROW(0x70), - FLIP_ROW(0x80), FLIP_ROW(0x90), FLIP_ROW(0xA0), FLIP_ROW(0xB0), - FLIP_ROW(0xC0), FLIP_ROW(0xD0), FLIP_ROW(0xE0), FLIP_ROW(0xF0) -}; - -#undef FLIP_ROW -#undef FLIP - -#define PREP(u8) (u8) - -#define EXPAND(u8) ((PREP(u8) << 7 & 0x4000) | (PREP(u8) << 6 & 0x1000) | (PREP(u8) << 5 & 0x0400) | (PREP(u8) << 4 & 0x0100) | \ - (PREP(u8) << 3 & 0x0040) | (PREP(u8) << 2 & 0x0010) | (PREP(u8) << 1 & 0x0004) | (PREP(u8) & 0x0001)) - -#define EXPAND_ROW(n) EXPAND((n)|0x0), EXPAND((n)|0x1), EXPAND((n)|0x2), EXPAND((n)|0x3), \ - EXPAND((n)|0x4), EXPAND((n)|0x5), EXPAND((n)|0x6), EXPAND((n)|0x7), \ - EXPAND((n)|0x8), EXPAND((n)|0x9), EXPAND((n)|0xA), EXPAND((n)|0xB), \ - EXPAND((n)|0xC), EXPAND((n)|0xD), EXPAND((n)|0xE), EXPAND((n)|0xF) - -#define EXPAND_TABLE EXPAND_ROW(0x00), EXPAND_ROW(0x10), EXPAND_ROW(0x20), EXPAND_ROW(0x30), \ - EXPAND_ROW(0x40), EXPAND_ROW(0x50), EXPAND_ROW(0x60), EXPAND_ROW(0x70), \ - EXPAND_ROW(0x80), EXPAND_ROW(0x90), EXPAND_ROW(0xA0), EXPAND_ROW(0xB0), \ - EXPAND_ROW(0xC0), EXPAND_ROW(0xD0), EXPAND_ROW(0xE0), EXPAND_ROW(0xF0) - -static const unsigned short expand_lut[0x200] = { - EXPAND_TABLE, - -#undef PREP -#define PREP(u8) (((u8) << 7 & 0x80) | ((u8) << 5 & 0x40) | ((u8) << 3 & 0x20) | ((u8) << 1 & 0x10) | \ - ((u8) >> 1 & 0x08) | ((u8) >> 3 & 0x04) | ((u8) >> 5 & 0x02) | ((u8) >> 7 & 0x01)) - - EXPAND_TABLE -}; - -#undef EXPAND_TABLE -#undef EXPAND_ROW -#undef EXPAND -#undef PREP - -//shoud work for the window too, if -wx is passed as scx. -//tilemap and tiledata must point to the areas in the first vram bank -//the second vram bank has to be placed immediately after the first one in memory (0x4000 continous bytes that cover both). -//tilemap needs to be offset to the right line -template -void LCD::cgb_bg_drawPixels(T * const buffer_line, unsigned xpos, const unsigned end, const unsigned scx, unsigned tilemappos, - const unsigned char *const tilemap, const unsigned char *const tiledata, const unsigned tileline) -{ - const unsigned sign = tileIndexSign; - unsigned shift = (7 - ((scx + xpos) & 7)) * 2; - T *buf = buffer_line + xpos; - T *const bufend = buffer_line + end; - - while (buf < bufend) { - if ((tilemappos & 7) || bufend - buf < 8) { - const unsigned char *const maptmp = tilemap + (tilemappos >> 3 & 0x1F); - const unsigned attributes = maptmp[0x2000]; - const unsigned char *const dataptr = tiledata + (attributes << 10 & 0x2000) + - maptmp[0] * 16 - (maptmp[0] & sign) * 32 + ((attributes & 0x40) ? 7 - tileline : tileline) * 2; - const unsigned short *const exp_lut = expand_lut + (attributes << 3 & 0x100); - - const unsigned data = exp_lut[dataptr[0]] + exp_lut[dataptr[1]] * 2; - const unsigned long *const palette = bgPalette + (attributes & 7) * 4; - - do { - *buf++ = palette[data >> shift & 3]; - shift = (shift - 2) & 15; - } while ((++tilemappos & 7) && buf < bufend); - } - - while (bufend - buf > 7) { - const unsigned char *const maptmp = tilemap + (tilemappos >> 3 & 0x1F); - const unsigned attributes = maptmp[0x2000]; - const unsigned char *const dataptr = tiledata + (attributes << 10 & 0x2000) + - maptmp[0] * 16 - (maptmp[0] & sign) * 32 + ((attributes & 0x40) ? 7 - tileline : tileline) * 2; - const unsigned short *const exp_lut = expand_lut + (attributes << 3 & 0x100); - - const unsigned data = exp_lut[dataptr[0]] + exp_lut[dataptr[1]] * 2; - const unsigned long *const palette = bgPalette + (attributes & 7) * 4; - - buf[0] = palette[data >> shift & 3]; - buf[1] = palette[data >> ((shift - 2) & 15) & 3]; - buf[2] = palette[data >> ((shift - 4) & 15) & 3]; - buf[3] = palette[data >> ((shift - 6) & 15) & 3]; - buf[4] = palette[data >> ((shift - 8) & 15) & 3]; - buf[5] = palette[data >> ((shift - 10) & 15) & 3]; - buf[6] = palette[data >> ((shift - 12) & 15) & 3]; - buf[7] = palette[data >> ((shift - 14) & 15) & 3]; - - buf += 8; - tilemappos += 8; - } - } -} - -static unsigned cgb_prioritizedBG_mask(const unsigned spx, const unsigned bgStart, const unsigned bgEnd, const unsigned scx, - const unsigned char *const tilemap, const unsigned char *const tiledata, const unsigned tileline, const unsigned sign) { - const unsigned spStart = spx < bgStart + 8 ? bgStart + 8 - spx : 0; - - unsigned bgbyte; - - { - const unsigned pos = scx + spx - 8 + spStart; - const unsigned char *maptmp = tilemap + (pos >> 3 & 0x1F); - unsigned tile = maptmp[0]; - unsigned attributes = maptmp[0x2000]; - - const unsigned char *const data = tiledata + (attributes << 10 & 0x2000) + - tile * 16 - (tile & sign) * 32 + ((attributes & 0x40) ? 7 - tileline : tileline) * 2; - - bgbyte = (attributes & 0x20) ? xflipt[data[0] | data[1]] : (data[0] | data[1]); - - const unsigned offset = pos & 7; - - if (offset) { - bgbyte <<= offset; - maptmp = tilemap + (((pos >> 3) + 1) & 0x1F); - tile = maptmp[0]; - attributes = maptmp[0x2000]; - - const unsigned char *const data = tiledata + (attributes << 10 & 0x2000) + - tile * 16 - (tile & sign) * 32 + ((attributes & 0x40) ? 7 - tileline : tileline) * 2; - - bgbyte |= ((attributes & 0x20) ? xflipt[data[0] | data[1]] : (data[0] | data[1])) >> (8 - offset); - } - } - - bgbyte >>= spStart; - const unsigned spEnd = spx > bgEnd ? bgEnd + 8 - spx : 8; - const unsigned mask = ~bgbyte | 0xFF >> spEnd; - - return mask; -} - -static unsigned cgb_toplayerBG_mask(const unsigned spx, const unsigned bgStart, const unsigned bgEnd, const unsigned scx, - const unsigned char *const tilemap, const unsigned char *const tiledata, const unsigned tileline, const unsigned sign) { - const unsigned spStart = spx < bgStart + 8 ? bgStart + 8 - spx : 0; - - unsigned bgbyte = 0; - - { - const unsigned pos = scx + spx - 8 + spStart; - const unsigned char *maptmp = tilemap + (pos >> 3 & 0x1F); - unsigned attributes = maptmp[0x2000]; - - if (attributes & 0x80) { - const unsigned tile = maptmp[0]; - - const unsigned char *const data = tiledata + (attributes << 10 & 0x2000) + - tile * 16 - (tile & sign) * 32 + ((attributes & 0x40) ? 7 - tileline : tileline) * 2; - - bgbyte = (attributes & 0x20) ? xflipt[data[0] | data[1]] : (data[0] | data[1]); - } - - const unsigned offset = pos & 7; - - if (offset) { - bgbyte <<= offset; - maptmp = tilemap + (((pos >> 3) + 1) & 0x1F); - attributes = maptmp[0x2000]; - - if (attributes & 0x80) { - const unsigned tile = maptmp[0]; - - const unsigned char *const data = tiledata + (attributes << 10 & 0x2000) + - tile * 16 - (tile & sign) * 32 + ((attributes & 0x40) ? 7 - tileline : tileline) * 2; - - bgbyte |= ((attributes & 0x20) ? xflipt[data[0] | data[1]] : (data[0] | data[1])) >> (8 - offset); - } - } - } - - bgbyte >>= spStart; - const unsigned spEnd = spx > bgEnd ? bgEnd + 8 - spx : 8; - const unsigned mask = ~bgbyte | 0xFF >> spEnd; - - return mask; -} - -template -void LCD::cgb_drawSprites(T * const buffer_line, const unsigned ypos) { - const unsigned scy = scReader.scy() + ypos /*& 0xFF*/; - const unsigned wx = win.wxReader.wx() < 7 ? 0 : win.wxReader.wx() - 7; - const bool enableWindow = win.enabled(ypos); - const unsigned char *const spriteMapLine = spriteMapper.sprites(ypos); - - for (int i = spriteMapper.numSprites(ypos) - 1; i >= 0; --i) { - const unsigned spNrX2 = spriteMapLine[i]; - const unsigned spx = spriteMapper.posbuf()[spNrX2 + 1]; - - if (spx < 168 && spx) { - unsigned spLine = ypos + 16 - spriteMapper.posbuf()[spNrX2]; - unsigned spTile = spriteMapper.oamram()[spNrX2 * 2 + 2]; - const unsigned attributes = spriteMapper.oamram()[spNrX2 * 2 + 3]; - - if (spriteMapper.largeSprites(spNrX2 >> 1)) { - if (attributes & 0x40) //yflip - spLine = 15 - spLine; - - if (spLine < 8) - spTile &= 0xFE; - else { - spLine -= 8; - spTile |= 0x01; - } - } else { - if (attributes & 0x40) //yflip - spLine = 7 - spLine; - } - - const unsigned char *const data = vram + ((attributes * 0x400) & 0x2000) + spTile * 16 + spLine * 2; - - unsigned byte1 = data[0]; - unsigned byte2 = data[1]; - - if (attributes & 0x20) { - byte1 = xflipt[byte1]; - byte2 = xflipt[byte2]; - } - - //(Sprites with priority-bit are still allowed to cover other sprites according to GBdev-faq.) - if (bgEnable) { - unsigned mask = 0xFF; - - if (attributes & 0x80) { - if (!(enableWindow && (wx == 0 || spx >= wx + 8u))) - mask = cgb_prioritizedBG_mask(spx, 0, enableWindow ? wx : 160, scReader.scx(), - bgTileMap + ((scy & 0xF8) << 2), bgTileData, scy & 7, tileIndexSign); - if (enableWindow && spx > wx) - mask &= cgb_prioritizedBG_mask(spx, wx, 160, 0u - wx, wdTileMap + ((winYPos & 0xF8) << 2), bgTileData, winYPos & 7, tileIndexSign); - } else { - if (!(enableWindow && (wx == 0 || spx >= wx + 8u))) - mask = cgb_toplayerBG_mask(spx, 0, enableWindow ? wx : 160, scReader.scx(), - bgTileMap + ((scy & 0xF8) << 2), bgTileData, scy & 7, tileIndexSign); - if (enableWindow && spx > wx) - mask &= cgb_toplayerBG_mask(spx, wx, 160, 0u - wx, wdTileMap + ((winYPos & 0xF8) << 2), bgTileData, winYPos & 7, tileIndexSign); - } - - byte1 &= mask; - byte2 &= mask; - } - - const unsigned bytes = expand_lut[byte1] + expand_lut[byte2] * 2; - const unsigned long *const palette = spPalette + (attributes & 7) * 4; - - if (spx > 7 && spx < 161) { - T * const buf = buffer_line + spx - 8; - unsigned color; - - if ((color = bytes >> 14 )) - buf[0] = palette[color]; - if ((color = bytes >> 12 & 3)) - buf[1] = palette[color]; - if ((color = bytes >> 10 & 3)) - buf[2] = palette[color]; - if ((color = bytes >> 8 & 3)) - buf[3] = palette[color]; - if ((color = bytes >> 6 & 3)) - buf[4] = palette[color]; - if ((color = bytes >> 4 & 3)) - buf[5] = palette[color]; - if ((color = bytes >> 2 & 3)) - buf[6] = palette[color]; - if ((color = bytes & 3)) - buf[7] = palette[color]; - } else { - const unsigned end = spx >= 160 ? 160 : spx; - unsigned xpos = spx <= 8 ? 0 : (spx - 8); - unsigned shift = (7 - (xpos + 8 - spx)) * 2; - - while (xpos < end) { - if (const unsigned color = bytes >> shift & 3) - buffer_line[xpos] = palette[color]; - - shift -= 2; - ++xpos; - } - } - } - } -} - - -//shoud work for the window too, if -wx is passed as scx. -//tilemap and tiledata need to be offset to the right line -template -void LCD::bg_drawPixels(T * const buffer_line, unsigned xpos, const unsigned end, const unsigned scx, unsigned tilemappos, - const unsigned char *const tilemap, const unsigned char *const tiledata) -{ - const unsigned sign = tileIndexSign; - unsigned shift = (7 - ((scx + xpos) & 7)) * 2; - T *buf = buffer_line + xpos; - T *const bufend = buffer_line + end; - - while (buf < bufend) { - if ((tilemappos & 7) || bufend - buf < 8) { - const unsigned tile = tilemap[tilemappos >> 3 & 0x1F]; - const unsigned char *const dataptr = tiledata + tile * 16 - (tile & sign) * 32; - const unsigned data = expand_lut[dataptr[0]] + expand_lut[dataptr[1]] * 2; - - do { - *buf++ = bgPalette[data >> shift & 3]; - shift = (shift - 2) & 15; - } while ((++tilemappos & 7) && buf < bufend); - } - - while (bufend - buf > 7) { - const unsigned tile = tilemap[tilemappos >> 3 & 0x1F]; - const unsigned char *const dataptr = tiledata + tile * 16 - (tile & sign) * 32; - const unsigned data = expand_lut[dataptr[0]] + expand_lut[dataptr[1]] * 2; - buf[0] = bgPalette[data >> shift & 3]; - buf[1] = bgPalette[data >> ((shift - 2) & 15) & 3]; - buf[2] = bgPalette[data >> ((shift - 4) & 15) & 3]; - buf[3] = bgPalette[data >> ((shift - 6) & 15) & 3]; - buf[4] = bgPalette[data >> ((shift - 8) & 15) & 3]; - buf[5] = bgPalette[data >> ((shift - 10) & 15) & 3]; - buf[6] = bgPalette[data >> ((shift - 12) & 15) & 3]; - buf[7] = bgPalette[data >> ((shift - 14) & 15) & 3]; - buf += 8; - tilemappos += 8; - } - } -} - -static unsigned prioritizedBG_mask(const unsigned spx, const unsigned bgStart, const unsigned bgEnd, const unsigned scx, - const unsigned char *const tilemap, const unsigned char *const tiledata, const unsigned sign) { - const unsigned spStart = spx < bgStart + 8 ? bgStart + 8 - spx : 0; - - unsigned bgbyte; - - { - const unsigned pos = scx + spx - 8 + spStart; - unsigned tile = tilemap[pos >> 3 & 0x1F]; - const unsigned char *data = tiledata + tile * 16 - (tile & sign) * 32; - bgbyte = data[0] | data[1]; - const unsigned offset = pos & 7; - - if (offset) { - bgbyte <<= offset; - tile = tilemap[((pos >> 3) + 1) & 0x1F]; - data = tiledata + tile * 16 - (tile & sign) * 32; - bgbyte |= (data[0] | data[1]) >> (8 - offset); - } - } - - bgbyte >>= spStart; - const unsigned spEnd = spx > bgEnd ? bgEnd + 8 - spx : 8; - const unsigned mask = ~bgbyte | 0xFF >> spEnd; - - return mask; -} - -template -void LCD::drawSprites(T * const buffer_line, const unsigned ypos) { - const unsigned scy = scReader.scy() + ypos /*& 0xFF*/; - const unsigned wx = win.wxReader.wx() < 7 ? 0 : win.wxReader.wx() - 7; - const bool enableWindow = win.enabled(ypos); - const unsigned char *const spriteMapLine = spriteMapper.sprites(ypos); - - for (int i = spriteMapper.numSprites(ypos) - 1; i >= 0; --i) { - const unsigned spNrX2 = spriteMapLine[i]; - const unsigned spx = spriteMapper.posbuf()[spNrX2 + 1]; - - if (spx < 168 && spx) { - unsigned spLine = ypos + 16 - spriteMapper.posbuf()[spNrX2]; - unsigned spTile = spriteMapper.oamram()[spNrX2 * 2 + 2]; - const unsigned attributes = spriteMapper.oamram()[spNrX2 * 2 + 3]; - - if (spriteMapper.largeSprites(spNrX2 >> 1)) { - if (attributes & 0x40) //yflip - spLine = 15 - spLine; - - if (spLine < 8) - spTile &= 0xFE; - else { - spLine -= 8; - spTile |= 0x01; - } - } else { - if (attributes & 0x40) //yflip - spLine = 7 - spLine; - } - - const unsigned char *const data = vram + spTile * 16 + spLine * 2; - - unsigned byte1 = data[0]; - unsigned byte2 = data[1]; - - if (attributes & 0x20) { - byte1 = xflipt[byte1]; - byte2 = xflipt[byte2]; - } - - //(Sprites with priority-bit are still allowed to cover other sprites according to GBdev-faq.) - if (attributes & 0x80) { - unsigned mask = 0xFF; - - if (bgEnable && !(enableWindow && (wx == 0 || spx >= wx + 8u))) - mask = prioritizedBG_mask(spx, 0, enableWindow ? wx : 160, scReader.scx(), - bgTileMap + ((scy & 0xF8) << 2), bgTileData + ((scy & 7) << 1), tileIndexSign); - if (enableWindow && spx > wx) - mask &= prioritizedBG_mask(spx, wx, 160, 0u - wx, wdTileMap + ((winYPos & 0xF8) << 2), bgTileData + ((winYPos & 7) << 1), tileIndexSign); - - byte1 &= mask; - byte2 &= mask; - } - - const unsigned bytes = expand_lut[byte1] + expand_lut[byte2] * 2; - const unsigned long *const palette = spPalette + ((attributes >> 2) & 4); - - if (spx > 7 && spx < 161) { - T * const buf = buffer_line + spx - 8; - unsigned color; - - if ((color = bytes >> 14 )) - buf[0] = palette[color]; - if ((color = bytes >> 12 & 3)) - buf[1] = palette[color]; - if ((color = bytes >> 10 & 3)) - buf[2] = palette[color]; - if ((color = bytes >> 8 & 3)) - buf[3] = palette[color]; - if ((color = bytes >> 6 & 3)) - buf[4] = palette[color]; - if ((color = bytes >> 4 & 3)) - buf[5] = palette[color]; - if ((color = bytes >> 2 & 3)) - buf[6] = palette[color]; - if ((color = bytes & 3)) - buf[7] = palette[color]; - } else { - const unsigned end = spx >= 160 ? 160 : spx; - unsigned xpos = spx <= 8 ? 0 : (spx - 8); - unsigned shift = (7 - (xpos + 8 - spx)) * 2; - - while (xpos < end) { - if (const unsigned color = bytes >> shift & 3) - buffer_line[xpos] = palette[color]; - - shift -= 2; - ++xpos; - } - } - } - } -} diff --git a/supergameboy/libgambatte/src/video.h b/supergameboy/libgambatte/src/video.h deleted file mode 100644 index 7271d1b1..00000000 --- a/supergameboy/libgambatte/src/video.h +++ /dev/null @@ -1,293 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aam�s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef VIDEO_H -#define VIDEO_H - -namespace Gambatte { -class VideoBlitter; -struct FilterInfo; -} - -class Filter; -class SaveState; - -#include -#include -#include "event_queue.h" -#include "videoblitter.h" -#include "array.h" -#include "int.h" -#include "colorconversion.h" -#include "osd_element.h" - -#include "video/video_event_comparer.h" -#include "video/ly_counter.h" -#include "video/window.h" -#include "video/scx_reader.h" -#include "video/sprite_mapper.h" -#include "video/sc_reader.h" -#include "video/break_event.h" -#include "video/mode3_event.h" - -#include "video/lyc_irq.h" -#include "video/mode0_irq.h" -#include "video/mode1_irq.h" -#include "video/mode2_irq.h" -#include "video/irq_event.h" -#include "video/m3_extra_cycles.h" - -class LCD { - //static const uint8_t xflipt[0x100]; - unsigned long dmgColorsRgb32[3 * 4]; - unsigned long dmgColorsRgb16[3 * 4]; - unsigned long dmgColorsUyvy[3 * 4]; - - unsigned long bgPalette[8 * 4]; - unsigned long spPalette[8 * 4]; - - unsigned char bgpData[8 * 8]; - unsigned char objpData[8 * 8]; - - const unsigned char *const vram; - const unsigned char *bgTileData; - const unsigned char *bgTileMap; - const unsigned char *wdTileMap; - - Gambatte::VideoBlitter *vBlitter; - Filter *filter; - - void *dbuffer; - void (LCD::*draw)(unsigned xpos, unsigned ypos, unsigned endX); - unsigned long (*gbcToFormat)(unsigned bgr15); - const unsigned long *dmgColors; - - unsigned long lastUpdate; - unsigned long videoCycles; - - unsigned dpitch; - unsigned winYPos; - - event_queue m3EventQueue; - event_queue irqEventQueue; - event_queue vEventQueue; - - LyCounter lyCounter; - Window win; - ScxReader scxReader; - SpriteMapper spriteMapper; - M3ExtraCycles m3ExtraCycles; - ScReader scReader; - BreakEvent breakEvent; - Mode3Event mode3Event; - - LycIrq lycIrq; - Mode0Irq mode0Irq; - Mode1Irq mode1Irq; - Mode2Irq mode2Irq; - IrqEvent irqEvent; - - Gambatte::PixelBuffer pb; - Array tmpbuf; - Rgb32ToUyvy rgb32ToUyvy; - std::auto_ptr osdElement; - - std::vector filters; - - unsigned char drawStartCycle; - unsigned char scReadOffset; - unsigned char ifReg; - unsigned char tileIndexSign; - unsigned char statReg; - - bool doubleSpeed; - bool enabled; - bool cgb; - bool bgEnable; - bool spriteEnable; - - static void setDmgPalette(unsigned long *palette, const unsigned long *dmgColors, unsigned data); - void setDmgPaletteColor(unsigned index, unsigned long rgb32); - static unsigned long gbcToRgb32(unsigned bgr15); - static unsigned long gbcToRgb16(unsigned bgr15); - static unsigned long gbcToUyvy(unsigned bgr15); - - void refreshPalettes(); - void setDBuffer(); - void resetVideoState(unsigned long cycleCounter); - - void setDoubleSpeed(bool enabled); - - void event(); - - bool cgbpAccessible(unsigned long cycleCounter); - bool isMode0IrqPeriod(unsigned long cycleCounter); - bool isMode2IrqPeriod(unsigned long cycleCounter); - bool isLycIrqPeriod(unsigned lycReg, unsigned endCycles, unsigned long cycleCounter); - bool isMode1IrqPeriod(unsigned long cycleCounter); - - template void bg_drawPixels(T *buffer_line, unsigned xpos, unsigned end, unsigned scx, unsigned tilemappos, - const unsigned char *tilemap, const unsigned char *tiledata); - template void drawSprites(T *buffer_line, unsigned ypos); - - template void cgb_bg_drawPixels(T *buffer_line, unsigned xpos, unsigned end, unsigned scx, unsigned tilemappos, - const unsigned char *tilemap, const unsigned char *tiledata, unsigned tileline); - template void cgb_drawSprites(T *buffer_line, unsigned ypos); - - void null_draw(unsigned xpos, unsigned ypos, unsigned endX); - template void dmg_draw(unsigned xpos, unsigned ypos, unsigned endX); - template void cgb_draw(unsigned xpos, unsigned ypos, unsigned endX); - - void do_update(unsigned cycles); - -public: - void update(unsigned long cycleCounter); - - LCD(const unsigned char *oamram, const unsigned char *vram_in); - ~LCD(); - void reset(const unsigned char *oamram, bool cgb); - void setStatePtrs(SaveState &state); - void saveState(SaveState &state) const; - void loadState(const SaveState &state, const unsigned char *oamram); - void setVideoBlitter(Gambatte::VideoBlitter *vb); - void videoBufferChange(); - void setVideoFilter(unsigned n); - std::vector filterInfo() const; - unsigned videoWidth() const; - unsigned videoHeight() const; - void setDmgPaletteColor(unsigned palNum, unsigned colorNum, unsigned long rgb32); - - void setOsdElement(std::auto_ptr osdElement) { - this->osdElement = osdElement; - } - - void wdTileMapSelectChange(bool newValue, unsigned long cycleCounter); - void bgTileMapSelectChange(bool newValue, unsigned long cycleCounter); - void bgTileDataSelectChange(bool newValue, unsigned long cycleCounter); - void bgEnableChange(bool newValue, unsigned long cycleCounter); - void spriteEnableChange(bool newValue, unsigned long cycleCounter); - - void dmgBgPaletteChange(const unsigned data, const unsigned long cycleCounter) { - update(cycleCounter); - bgpData[0] = data; - setDmgPalette(bgPalette, dmgColors, data); - } - - void dmgSpPalette1Change(const unsigned data, const unsigned long cycleCounter) { - update(cycleCounter); - objpData[0] = data; - setDmgPalette(spPalette, dmgColors + 4, data); - } - - void dmgSpPalette2Change(const unsigned data, const unsigned long cycleCounter) { - update(cycleCounter); - objpData[1] = data; - setDmgPalette(spPalette + 4, dmgColors + 8, data); - } - - void cgbBgColorChange(unsigned index, const unsigned data, const unsigned long cycleCounter) { - if (bgpData[index] != data && cgbpAccessible(cycleCounter)) { - update(cycleCounter); - bgpData[index] = data; - index >>= 1; - bgPalette[index] = (*gbcToFormat)(bgpData[index << 1] | bgpData[(index << 1) + 1] << 8); - } - } - - void cgbSpColorChange(unsigned index, const unsigned data, const unsigned long cycleCounter) { - if (objpData[index] != data && cgbpAccessible(cycleCounter)) { - update(cycleCounter); - objpData[index] = data; - index >>= 1; - spPalette[index] = (*gbcToFormat)(objpData[index << 1] | objpData[(index << 1) + 1] << 8); - } - } - - unsigned cgbBgColorRead(const unsigned index, const unsigned long cycleCounter) { - return cgb & cgbpAccessible(cycleCounter) ? bgpData[index] : 0xFF; - } - - unsigned cgbSpColorRead(const unsigned index, const unsigned long cycleCounter) { - return cgb & cgbpAccessible(cycleCounter) ? objpData[index] : 0xFF; - } - - void updateScreen(unsigned long cc); - void enableChange(unsigned long cycleCounter); - void preResetCounter(unsigned long cycleCounter); - void postResetCounter(unsigned long oldCC, unsigned long cycleCounter); - void preSpeedChange(unsigned long cycleCounter); - void postSpeedChange(unsigned long cycleCounter); -// unsigned get_mode(unsigned cycleCounter) /*const*/; - bool vramAccessible(unsigned long cycleCounter); - bool oamAccessible(unsigned long cycleCounter); - void weChange(bool newValue, unsigned long cycleCounter); - void wxChange(unsigned newValue, unsigned long cycleCounter); - void wyChange(unsigned newValue, unsigned long cycleCounter); - void oamChange(unsigned long cycleCounter); - void oamChange(const unsigned char *oamram, unsigned long cycleCounter); - void scxChange(unsigned newScx, unsigned long cycleCounter); - void scyChange(unsigned newValue, unsigned long cycleCounter); - void spriteSizeChange(bool newLarge, unsigned long cycleCounter); - - void vramChange(const unsigned long cycleCounter) { - update(cycleCounter); - } - - unsigned get_stat(unsigned lycReg, unsigned long cycleCounter); - - unsigned getLyReg(const unsigned long cycleCounter) { - unsigned lyReg = 0; - - if (enabled) { - if (cycleCounter >= lyCounter.time()) - update(cycleCounter); - - lyReg = lyCounter.ly(); - - if (lyCounter.time() - cycleCounter <= 4) { - if (lyReg == 153) - lyReg = 0; - else - ++lyReg; - } else if (lyReg == 153) - lyReg = 0; - } - - return lyReg; - } - - unsigned long nextMode1IrqTime() const { - return mode1Irq.time(); - } - - void lyWrite(unsigned long cycleCounter); - void lcdstatChange(unsigned data, unsigned long cycleCounter); - void lycRegChange(unsigned data, unsigned long cycleCounter); - unsigned long nextIrqEvent() const; - unsigned getIfReg(unsigned long cycleCounter); - void setIfReg(unsigned ifReg_in, unsigned long cycleCounter); - - unsigned long nextHdmaTime(unsigned long cycleCounter); - bool isHdmaPeriod(unsigned long cycleCounter); - - unsigned long nextHdmaTimeInvalid() const { - return mode3Event.time(); - } -}; - -#endif diff --git a/supergameboy/libgambatte/src/video/basic_add_event.cpp b/supergameboy/libgambatte/src/video/basic_add_event.cpp deleted file mode 100644 index 4bc57a09..00000000 --- a/supergameboy/libgambatte/src/video/basic_add_event.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2008 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "basic_add_event.h" -#include "../event_queue.h" - -void addEvent(event_queue &q, VideoEvent *const e, const unsigned long newTime) { - const unsigned long oldTime = e->time(); - - if (oldTime != newTime) { - e->setTime(newTime); - - if (newTime < oldTime) { - if (oldTime == VideoEvent::DISABLED_TIME) - q.push(e); - else - q.dec(e, e); - } else { - if (newTime == VideoEvent::DISABLED_TIME) - q.remove(e); - else - q.inc(e, e); - } - } -} - -void addUnconditionalEvent(event_queue &q, VideoEvent *const e, const unsigned long newTime) { - const unsigned long oldTime = e->time(); - - e->setTime(newTime); - - if (newTime < oldTime) { - if (oldTime == VideoEvent::DISABLED_TIME) - q.push(e); - else - q.dec(e, e); - } else if (oldTime != newTime) { - q.inc(e, e); - } -} - -void addFixedtimeEvent(event_queue &q, VideoEvent *const e, const unsigned long newTime) { - const unsigned long oldTime = e->time(); - - if (oldTime != newTime) { - e->setTime(newTime); - - if (oldTime == VideoEvent::DISABLED_TIME) - q.push(e); - else - q.remove(e); - } -} - -void addUnconditionalFixedtimeEvent(event_queue &q, VideoEvent *const e, const unsigned long newTime) { - if (e->time() == VideoEvent::DISABLED_TIME) { - e->setTime(newTime); - q.push(e); - } -} diff --git a/supergameboy/libgambatte/src/video/basic_add_event.h b/supergameboy/libgambatte/src/video/basic_add_event.h deleted file mode 100644 index 780d7191..00000000 --- a/supergameboy/libgambatte/src/video/basic_add_event.h +++ /dev/null @@ -1,56 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef BASIC_ADD_EVENT_H -#define BASIC_ADD_EVENT_H - -template class event_queue; - -#include "video_event.h" -#include "video_event_comparer.h" - -/*template -static inline void addEvent(T &event, const LyCounter &lyCounter, const unsigned long cycleCounter, event_queue &queue) { - if (event.time() == VideoEvent::DISABLED_TIME) { - event.schedule(lyCounter, cycleCounter); - queue.push(&event); - } -} - -template -static inline void addEvent(T &event, const unsigned data, const LyCounter &lyCounter, const unsigned long cycleCounter, event_queue &queue) { - if (event.time() == VideoEvent::DISABLED_TIME) { - event.schedule(data, lyCounter, cycleCounter); - queue.push(&event); - } -} - -template -static inline void addEvent(T &event, const unsigned data1, const unsigned data2, const LyCounter &lyCounter, const unsigned long cycleCounter, event_queue &queue) { - if (event.time() == VideoEvent::DISABLED_TIME) { - event.schedule(data1, data2, lyCounter, cycleCounter); - queue.push(&event); - } -}*/ - -void addEvent(event_queue &q, VideoEvent *e, unsigned long newTime); -void addUnconditionalEvent(event_queue &q, VideoEvent *e, unsigned long newTime); -void addFixedtimeEvent(event_queue &q, VideoEvent *e, unsigned long newTime); -void addUnconditionalFixedtimeEvent(event_queue &q, VideoEvent *e, unsigned long newTime); - -#endif diff --git a/supergameboy/libgambatte/src/video/break_event.cpp b/supergameboy/libgambatte/src/video/break_event.cpp deleted file mode 100644 index e6e7ffbf..00000000 --- a/supergameboy/libgambatte/src/video/break_event.cpp +++ /dev/null @@ -1,35 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "break_event.h" - -BreakEvent::BreakEvent(unsigned char &drawStartCycle_in, unsigned char &scReadOffset_in) : - VideoEvent(3), - drawStartCycle(drawStartCycle_in), - scReadOffset(scReadOffset_in) -{ - setDoubleSpeed(false); - setScxSource(0); -} - -void BreakEvent::doEvent() { - scReadOffset = baseCycle; - drawStartCycle = baseCycle + (scxSrc & 7); - - setTime(DISABLED_TIME); -} diff --git a/supergameboy/libgambatte/src/video/break_event.h b/supergameboy/libgambatte/src/video/break_event.h deleted file mode 100644 index 9e7dcb82..00000000 --- a/supergameboy/libgambatte/src/video/break_event.h +++ /dev/null @@ -1,59 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef BREAK_EVENT_H -#define BREAK_EVENT_H - -#include "video_event.h" -#include "ly_counter.h" -#include "basic_add_event.h" - -class BreakEvent : public VideoEvent { - unsigned char &drawStartCycle; - unsigned char &scReadOffset; - - unsigned char scxSrc; - unsigned char baseCycle; - -public: - BreakEvent(unsigned char &drawStartCycle_in, unsigned char &scReadOffset_in); - - void doEvent(); - - static unsigned long schedule(const LyCounter &lyCounter) { - return lyCounter.time(); - } - - void setDoubleSpeed(const bool dS) { - baseCycle = 90 + dS * 4; - } - - void setScxSource(const unsigned scxSrc_in) { - scxSrc = scxSrc_in; - } -}; - -static inline void addEvent(event_queue &q, BreakEvent *const e, const unsigned long newTime) { - addUnconditionalEvent(q, e, newTime); -} - -static inline void addFixedtimeEvent(event_queue &q, BreakEvent *const e, const unsigned long newTime) { - addUnconditionalFixedtimeEvent(q, e, newTime); -} - -#endif diff --git a/supergameboy/libgambatte/src/video/filters/catrom2x.cpp b/supergameboy/libgambatte/src/video/filters/catrom2x.cpp deleted file mode 100644 index 53a4c931..00000000 --- a/supergameboy/libgambatte/src/video/filters/catrom2x.cpp +++ /dev/null @@ -1,194 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "catrom2x.h" -#include "filterinfo.h" -#include - -struct Colorsum { - Gambatte::uint_least32_t r, g, b; -}; - -static void merge_columns(Gambatte::uint_least32_t *dest, const Colorsum *sums) { - unsigned w = 160; - - while (w--) { - { - Gambatte::uint_least32_t rsum = sums[1].r; - Gambatte::uint_least32_t gsum = sums[1].g; - Gambatte::uint_least32_t bsum = sums[1].b; - - if (rsum & 0x80000000) rsum = 0; - if (gsum & 0x80000000) gsum = 0; - if (bsum & 0x80000000) bsum = 0; - - rsum <<= 12; - rsum += 0x008000; - gsum >>= 4; - gsum += 0x0080; - bsum += 0x0008; - bsum >>= 4; - - if (rsum > 0xFF0000) rsum = 0xFF0000; - if (gsum > 0x00FF00) gsum = 0x00FF00; - if (bsum > 0x0000FF) bsum = 0x0000FF; - - *dest++ = (rsum & 0xFF0000) | (gsum & 0x00FF00) | bsum; - } - - { - Gambatte::uint_least32_t rsum = sums[1].r * 9; - Gambatte::uint_least32_t gsum = sums[1].g * 9; - Gambatte::uint_least32_t bsum = sums[1].b * 9; - - rsum -= sums[0].r; - gsum -= sums[0].g; - bsum -= sums[0].b; - - rsum += sums[2].r * 9; - gsum += sums[2].g * 9; - bsum += sums[2].b * 9; - - rsum -= sums[3].r; - gsum -= sums[3].g; - bsum -= sums[3].b; - - if (rsum & 0x80000000) rsum = 0; - if (gsum & 0x80000000) gsum = 0; - if (bsum & 0x80000000) bsum = 0; - - rsum <<= 8; - rsum += 0x008000; - gsum >>= 8; - gsum += 0x000080; - bsum += 0x000080; - bsum >>= 8; - - if (rsum > 0xFF0000) rsum = 0xFF0000; - if (gsum > 0x00FF00) gsum = 0x00FF00; - if (bsum > 0x0000FF) bsum = 0x0000FF; - - *dest++ = (rsum & 0xFF0000) | (gsum & 0x00FF00) | bsum; - } - - ++sums; - } -} - -static void filter(Gambatte::uint_least32_t *dline, const unsigned pitch, const Gambatte::uint_least32_t *sline) { - Colorsum sums[163]; - - for (unsigned h = 144; h--;) { - { - const Gambatte::uint_least32_t *s = sline; - Colorsum *sum = sums; - unsigned n = 163; - - while (n--) { - unsigned long pixel = *s; - sum->r = pixel >> 12 & 0x000FF0 ; - pixel <<= 4; - sum->g = pixel & 0x0FF000; - sum->b = pixel & 0x000FF0; - - ++s; - ++sum; - } - } - - merge_columns(dline, sums); - dline += pitch; - - { - const Gambatte::uint_least32_t *s = sline; - Colorsum *sum = sums; - unsigned n = 163; - - while (n--) { - unsigned long pixel = *s; - unsigned long rsum = (pixel >> 16) * 9; - unsigned long gsum = (pixel & 0x00FF00) * 9; - unsigned long bsum = (pixel & 0x0000FF) * 9; - - pixel = s[-1*163]; - rsum -= pixel >> 16; - gsum -= pixel & 0x00FF00; - bsum -= pixel & 0x0000FF; - - pixel = s[1*163]; - rsum += (pixel >> 16) * 9; - gsum += (pixel & 0x00FF00) * 9; - bsum += (pixel & 0x0000FF) * 9; - - pixel = s[2*163]; - rsum -= pixel >> 16; - gsum -= pixel & 0x00FF00; - bsum -= pixel & 0x0000FF; - - sum->r = rsum; - sum->g = gsum; - sum->b = bsum; - - ++s; - ++sum; - } - } - - merge_columns(dline, sums); - dline += pitch; - sline += 163; - } -} - -Catrom2x::Catrom2x() { - buffer = NULL; -} - -Catrom2x::~Catrom2x() { - delete []buffer; -} - -void Catrom2x::init() { - delete []buffer; - - buffer = new Gambatte::uint_least32_t[147 * 163]; - std::memset(buffer, 0, 147ul * 163 * sizeof(Gambatte::uint_least32_t)); -} - -void Catrom2x::outit() { - delete []buffer; - buffer = NULL; -} - -const Gambatte::FilterInfo& Catrom2x::info() { - static Gambatte::FilterInfo fInfo = { "Bicubic Catmull-Rom Spline 2x", 160 * 2, 144 * 2 }; - - return fInfo; -} - -Gambatte::uint_least32_t* Catrom2x::inBuffer() { - return buffer + 164; -} - -unsigned Catrom2x::inPitch() { - return 163; -} - -void Catrom2x::filter(Gambatte::uint_least32_t *const dbuffer, const unsigned pitch) { - ::filter(dbuffer, pitch, buffer + 163); -} diff --git a/supergameboy/libgambatte/src/video/filters/catrom2x.h b/supergameboy/libgambatte/src/video/filters/catrom2x.h deleted file mode 100644 index df657f04..00000000 --- a/supergameboy/libgambatte/src/video/filters/catrom2x.h +++ /dev/null @@ -1,40 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef CATROM2X_H -#define CATROM2X_H - -#include "filter.h" - -struct FilterInfo; - -class Catrom2x : public Filter { - Gambatte::uint_least32_t *buffer; - -public: - Catrom2x(); - ~Catrom2x(); - void init(); - void outit(); - const Gambatte::FilterInfo& info(); - void filter(Gambatte::uint_least32_t *dbuffer, unsigned pitch); - Gambatte::uint_least32_t* inBuffer(); - unsigned inPitch(); -}; - -#endif diff --git a/supergameboy/libgambatte/src/video/filters/catrom3x.cpp b/supergameboy/libgambatte/src/video/filters/catrom3x.cpp deleted file mode 100644 index 09a03f6a..00000000 --- a/supergameboy/libgambatte/src/video/filters/catrom3x.cpp +++ /dev/null @@ -1,360 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aam�s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "catrom3x.h" -#include "filterinfo.h" -#include - -struct Colorsum { - Gambatte::uint_least32_t r, g, b; -}; - -static void merge_columns(Gambatte::uint_least32_t *dest, const Colorsum *sums) { - unsigned w = 160; - - while (w--) { - { - Gambatte::uint_least32_t rsum = sums[1].r; - Gambatte::uint_least32_t gsum = sums[1].g; - Gambatte::uint_least32_t bsum = sums[1].b; - - if (rsum & 0x80000000) - rsum = 0; - else if (rsum > 6869) - rsum = 0xFF0000; - else { - rsum *= 607; - rsum <<= 2; - rsum += 0x008000; - rsum &= 0xFF0000; - } - - if (gsum & 0x80000000) - gsum = 0; - else if (gsum > 1758567) - gsum = 0xFF00; - else { - gsum *= 607; - gsum >>= 14; - gsum += 0x000080; - gsum &= 0x00FF00; - } - - if (bsum & 0x80000000) - bsum = 0; - else if (bsum > 6869) - bsum = 0xFF; - else { - bsum *= 607; - bsum += 8192; - bsum >>= 14; - } - - /*rsum/=27; - rsum<<=8; - gsum/=27; - gsum<<=5; - bsum<<=4; - bsum+=27; - bsum/=54; - rsum+=0x008000; - gsum+=0x000080; - - if(rsum>0xFF0000) rsum=0xFF0000; - if(gsum>0x00FF00) gsum=0x00FF00; - if(bsum>0x0000FF) bsum=0x0000FF;*/ - - *dest++ = rsum/*&0xFF0000*/ | gsum/*&0x00FF00*/ | bsum; - } - { - Gambatte::uint_least32_t rsum = sums[1].r * 21; - Gambatte::uint_least32_t gsum = sums[1].g * 21; - Gambatte::uint_least32_t bsum = sums[1].b * 21; - - rsum -= sums[0].r << 1; - gsum -= sums[0].g << 1; - bsum -= sums[0].b << 1; - - rsum += sums[2].r * 9; - gsum += sums[2].g * 9; - bsum += sums[2].b * 9; - - rsum -= sums[3].r; - gsum -= sums[3].g; - bsum -= sums[3].b; - - if (rsum & 0x80000000) - rsum = 0; - else if (rsum > 185578) - rsum = 0xFF0000; - else { - rsum *= 719; - rsum >>= 3; - rsum += 0x008000; - rsum &= 0xFF0000; - } - - if (gsum & 0x80000000) - gsum = 0; - else if (gsum > 47508223) - gsum = 0x00FF00; - else { - gsum >>= 8; - gsum *= 719; - gsum >>= 11; - gsum += 0x000080; - gsum &= 0x00FF00; - } - - if (bsum & 0x80000000) - bsum = 0; - else if (bsum > 185578) - bsum = 0x0000FF; - else { - bsum *= 719; - bsum += 0x040000; - bsum >>= 19; - } - - /*rsum/=729; - rsum<<=8; - gsum/=729; - gsum<<=5; - bsum<<=4; - bsum+=729; - bsum/=1458; - rsum+=0x008000; - gsum+=0x000080; - - if(rsum>0xFF0000) rsum=0xFF0000; - if(gsum>0x00FF00) gsum=0x00FF00; - if(bsum>0x0000FF) bsum=0x0000FF;*/ - - *dest++ = rsum/*&0xFF0000*/ | gsum/*&0x00FF00*/ | bsum; - } - { - Gambatte::uint_least32_t rsum = sums[1].r * 9; - Gambatte::uint_least32_t gsum = sums[1].g * 9; - Gambatte::uint_least32_t bsum = sums[1].b * 9; - - rsum -= sums[0].r; - gsum -= sums[0].g; - bsum -= sums[0].b; - - rsum += sums[2].r * 21; - gsum += sums[2].g * 21; - bsum += sums[2].b * 21; - - rsum -= sums[3].r << 1; - gsum -= sums[3].g << 1; - bsum -= sums[3].b << 1; - - if (rsum & 0x80000000) - rsum = 0; - else if (rsum > 185578) - rsum = 0xFF0000; - else { - rsum *= 719; - rsum >>= 3; - rsum += 0x008000; - rsum &= 0xFF0000; - } - - if (gsum & 0x80000000) - gsum = 0; - else if (gsum > 47508223) - gsum = 0xFF00; - else { - gsum >>= 8; - gsum *= 719; - gsum >>= 11; - gsum += 0x000080; - gsum &= 0x00FF00; - } - - if (bsum & 0x80000000) - bsum = 0; - else if (bsum > 185578) - bsum = 0x0000FF; - else { - bsum *= 719; - bsum += 0x040000; - bsum >>= 19; - } - - /*rsum/=729; - rsum<<=8; - gsum/=729; - gsum<<=5; - bsum<<=4; - bsum+=729; - bsum/=1458; - rsum+=0x008000; - gsum+=0x000080; - - if(rsum>0xFF0000) rsum=0xFF0000; - if(gsum>0x00FF00) gsum=0x00FF00; - if(bsum>0x0000FF) bsum=0x0000FF;*/ - - *dest++ = rsum/*&0xFF0000*/ | gsum/*&0x00FF00*/ | bsum; - } - ++sums; - } -} - -static void filter(Gambatte::uint_least32_t *dline, const unsigned pitch, const Gambatte::uint_least32_t *sline) { - Colorsum sums[163]; - - for (unsigned h = 144; h--;) { - { - const Gambatte::uint_least32_t *s = sline; - Colorsum *sum = sums; - unsigned n = 163; - - while (n--) { - const unsigned long pixel = *s; - sum->r = (pixel >> 16) * 27; - sum->g = (pixel & 0x00FF00) * 27; - sum->b = (pixel & 0x0000FF) * 27; - - ++s; - ++sum; - } - } - - merge_columns(dline, sums); - dline += pitch; - - { - const Gambatte::uint_least32_t *s = sline; - Colorsum *sum = sums; - unsigned n = 163; - - while (n--) { - unsigned long pixel = *s; - unsigned long rsum = (pixel >> 16) * 21; - unsigned long gsum = (pixel & 0x00FF00) * 21; - unsigned long bsum = (pixel & 0x0000FF) * 21; - - pixel = s[-1 * 163]; - rsum -= (pixel >> 16) << 1; - pixel <<= 1; - gsum -= pixel & 0x01FE00; - bsum -= pixel & 0x0001FE; - - pixel = s[1 * 163]; - rsum += (pixel >> 16) * 9; - gsum += (pixel & 0x00FF00) * 9; - bsum += (pixel & 0x0000FF) * 9; - - pixel = s[2 * 163]; - rsum -= pixel >> 16; - gsum -= pixel & 0x00FF00; - bsum -= pixel & 0x0000FF; - - sum->r = rsum; - sum->g = gsum; - sum->b = bsum; - - ++s; - ++sum; - } - } - - merge_columns(dline, sums); - dline += pitch; - - { - const Gambatte::uint_least32_t *s = sline; - Colorsum *sum = sums; - unsigned n = 163; - - while (n--) { - unsigned long pixel = *s; - unsigned long rsum = (pixel >> 16) * 9; - unsigned long gsum = (pixel & 0x00FF00) * 9; - unsigned long bsum = (pixel & 0x0000FF) * 9; - - pixel = s[-1 * 163]; - rsum -= pixel >> 16; - gsum -= pixel & 0x00FF00; - bsum -= pixel & 0x0000FF; - - pixel = s[1 * 163]; - rsum += (pixel >> 16) * 21; - gsum += (pixel & 0x00FF00) * 21; - bsum += (pixel & 0x0000FF) * 21; - - pixel = s[2 * 163]; - rsum -= (pixel >> 16) << 1; - pixel <<= 1; - gsum -= pixel & 0x01FE00; - bsum -= pixel & 0x0001FE; - - sum->r = rsum; - sum->g = gsum; - sum->b = bsum; - - ++s; - ++sum; - } - } - - merge_columns(dline, sums); - dline += pitch; - sline += 163; - } -} - -Catrom3x::Catrom3x() { - buffer = NULL; -} - -Catrom3x::~Catrom3x() { - delete []buffer; -} - -void Catrom3x::init() { - delete []buffer; - - buffer = new Gambatte::uint_least32_t[147 * 163]; - std::memset(buffer, 0, 147ul * 163 * sizeof(Gambatte::uint_least32_t)); -} - -void Catrom3x::outit() { - delete []buffer; - buffer = NULL; -} - -const Gambatte::FilterInfo& Catrom3x::info() { - static Gambatte::FilterInfo fInfo = { "Bicubic Catmull-Rom Spline 3x", 160 * 3, 144 * 3 }; - - return fInfo; -} - -Gambatte::uint_least32_t* Catrom3x::inBuffer() { - return buffer + 164; -} - -unsigned Catrom3x::inPitch() { - return 163; -} - -void Catrom3x::filter(Gambatte::uint_least32_t *const dbuffer, const unsigned pitch) { - ::filter(dbuffer, pitch, buffer + 163); -} diff --git a/supergameboy/libgambatte/src/video/filters/catrom3x.h b/supergameboy/libgambatte/src/video/filters/catrom3x.h deleted file mode 100644 index 64f47827..00000000 --- a/supergameboy/libgambatte/src/video/filters/catrom3x.h +++ /dev/null @@ -1,40 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef CATROM3X_H -#define CATROM3X_H - -#include "filter.h" - -struct FilterInfo; - -class Catrom3x : public Filter { - Gambatte::uint_least32_t *buffer; - -public: - Catrom3x(); - ~Catrom3x(); - void init(); - void outit(); - const Gambatte::FilterInfo& info(); - void filter(Gambatte::uint_least32_t *dbuffer, unsigned pitch); - Gambatte::uint_least32_t* inBuffer(); - unsigned inPitch(); -}; - -#endif diff --git a/supergameboy/libgambatte/src/video/filters/filter.h b/supergameboy/libgambatte/src/video/filters/filter.h deleted file mode 100644 index 72e3bf7d..00000000 --- a/supergameboy/libgambatte/src/video/filters/filter.h +++ /dev/null @@ -1,39 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef FILTER_H -#define FILTER_H - -#include "int.h" - -namespace Gambatte { -struct FilterInfo; -} - -class Filter { -public: - virtual ~Filter() {} - virtual void init() {}; - virtual void outit() {}; - virtual const Gambatte::FilterInfo& info() = 0; - virtual void filter(Gambatte::uint_least32_t *dbuffer, unsigned pitch) = 0; - virtual Gambatte::uint_least32_t* inBuffer() = 0; - virtual unsigned inPitch() = 0; -}; - -#endif diff --git a/supergameboy/libgambatte/src/video/filters/kreed2xsai.cpp b/supergameboy/libgambatte/src/video/filters/kreed2xsai.cpp deleted file mode 100644 index 70c261b3..00000000 --- a/supergameboy/libgambatte/src/video/filters/kreed2xsai.cpp +++ /dev/null @@ -1,243 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aam�s * - * aamas@stud.ntnu.no * - * * - * Copyright (C) 1999 Derek Liauw Kie Fa (Kreed) * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "kreed2xsai.h" -#include "filterinfo.h" -#include - -static inline int getResult1(const unsigned long a, const unsigned long b, const unsigned long c, const unsigned long d) { - int x = 0; - int y = 0; - int r = 0; - - if (a == c) ++x; - else if (b == c) ++y; - - if (a == d) ++x; - else if (b == d) ++y; - - if (x <= 1) ++r; - - if (y <= 1) --r; - - return r; -} - -static inline int getResult2(const unsigned long a, const unsigned long b, const unsigned long c, const unsigned long d) { - int x = 0; - int y = 0; - int r = 0; - - if (a == c) ++x; - else if (b == c) ++y; - - if (a == d) ++x; - else if (b == d) ++y; - - if (x <= 1) --r; - - if (y <= 1) ++r; - - return r; -} - -static inline unsigned long interpolate(const unsigned long a, const unsigned long b) { - return (a + b - ((a ^ b) & 0x010101)) >> 1; -} - -static inline unsigned long qInterpolate(const unsigned long a, const unsigned long b, const unsigned long c, const unsigned long d) { - const unsigned long lowBits = ((a & 0x030303) + (b & 0x030303) + (c & 0x030303) + (d & 0x030303)) & 0x030303; - - return (a + b + c + d - lowBits) >> 2; -} - -static void filter(Gambatte::uint_least32_t *dstPtr, const unsigned dstPitch, - const Gambatte::uint_least32_t *srcPtr, const unsigned srcPitch, const unsigned width, unsigned height) -{ - while (height--) { - const Gambatte::uint_least32_t *bP = srcPtr; - Gambatte::uint_least32_t *dP = dstPtr; - - for (unsigned finish = width; finish--;) { - register unsigned long colorA, colorB; - unsigned long colorC, colorD, - colorE, colorF, colorG, colorH, - colorI, colorJ, colorK, colorL, - - colorM, colorN, colorO, colorP; - unsigned long product, product1, product2; - - //--------------------------------------- - // Map of the pixels: I|E F|J - // G|A B|K - // H|C D|L - // M|N O|P - colorI = *(bP - srcPitch - 1); - colorE = *(bP - srcPitch); - colorF = *(bP - srcPitch + 1); - colorJ = *(bP - srcPitch + 2); - - colorG = *(bP - 1); - colorA = *(bP); - colorB = *(bP + 1); - colorK = *(bP + 2); - - colorH = *(bP + srcPitch - 1); - colorC = *(bP + srcPitch); - colorD = *(bP + srcPitch + 1); - colorL = *(bP + srcPitch + 2); - - colorM = *(bP + srcPitch * 2 - 1); - colorN = *(bP + srcPitch * 2); - colorO = *(bP + srcPitch * 2 + 1); - colorP = *(bP + srcPitch * 2 + 2); - - if (colorA == colorD && colorB != colorC) { - if ((colorA == colorE && colorB == colorL) || - (colorA == colorC && colorA == colorF - && colorB != colorE && colorB == colorJ)) { - product = colorA; - } else { - product = interpolate(colorA, colorB); - } - - if ((colorA == colorG && colorC == colorO) || - (colorA == colorB && colorA == colorH - && colorG != colorC && colorC == colorM)) { - product1 = colorA; - } else { - product1 = interpolate(colorA, colorC); - } - product2 = colorA; - } else if (colorB == colorC && colorA != colorD) { - if ((colorB == colorF && colorA == colorH) || - (colorB == colorE && colorB == colorD - && colorA != colorF && colorA == colorI)) { - product = colorB; - } else { - product = interpolate(colorA, colorB); - } - - if ((colorC == colorH && colorA == colorF) || - (colorC == colorG && colorC == colorD - && colorA != colorH && colorA == colorI)) { - product1 = colorC; - } else { - product1 = interpolate(colorA, colorC); - } - product2 = colorB; - } else if (colorA == colorD && colorB == colorC) { - if (colorA == colorB) { - product = colorA; - product1 = colorA; - product2 = colorA; - } else { - register int r = 0; - - product1 = interpolate(colorA, colorC); - product = interpolate(colorA, colorB); - - r += getResult1(colorA, colorB, colorG, colorE); - r += getResult2(colorB, colorA, colorK, colorF); - r += getResult2(colorB, colorA, colorH, colorN); - r += getResult1(colorA, colorB, colorL, colorO); - - if (r > 0) - product2 = colorA; - else if (r < 0) - product2 = colorB; - else { - product2 = qInterpolate(colorA, colorB, colorC, colorD); - } - } - } else { - product2 = qInterpolate(colorA, colorB, colorC, colorD); - - if (colorA == colorC && colorA == colorF - && colorB != colorE && colorB == colorJ) { - product = colorA; - } else if (colorB == colorE && colorB == colorD - && colorA != colorF && colorA == colorI) { - product = colorB; - } else { - product = interpolate(colorA, colorB); - } - - if (colorA == colorB && colorA == colorH - && colorG != colorC && colorC == colorM) { - product1 = colorA; - } else if (colorC == colorG && colorC == colorD - && colorA != colorH && colorA == colorI) { - product1 = colorC; - } else { - product1 = interpolate(colorA, colorC); - } - } - *dP = colorA; - *(dP + 1) = product; - *(dP + dstPitch) = product1; - *(dP + dstPitch + 1) = product2; - - ++bP; - dP += 2; - } - - srcPtr += srcPitch; - dstPtr += dstPitch * 2; - } -} - -Kreed_2xSaI::Kreed_2xSaI() { - buffer = NULL; -} - -Kreed_2xSaI::~Kreed_2xSaI() { - delete []buffer; -} - -void Kreed_2xSaI::init() { - delete []buffer; - - buffer = new Gambatte::uint_least32_t[145 * 161]; - std::memset(buffer, 0, 145ul * 161 * sizeof(Gambatte::uint_least32_t)); -} - -void Kreed_2xSaI::outit() { - delete []buffer; - buffer = NULL; -} - -const Gambatte::FilterInfo& Kreed_2xSaI::info() { - static Gambatte::FilterInfo fInfo = { "Kreed's 2xSaI", 160 * 2, 144 * 2 }; - - return fInfo; -} - -Gambatte::uint_least32_t* Kreed_2xSaI::inBuffer() { - return buffer; -} - -unsigned Kreed_2xSaI::inPitch() { - return 161; -} - -void Kreed_2xSaI::filter(Gambatte::uint_least32_t *const dbuffer, const unsigned pitch) { - ::filter(dbuffer, pitch, buffer, 161, 160, 144); -} diff --git a/supergameboy/libgambatte/src/video/filters/kreed2xsai.h b/supergameboy/libgambatte/src/video/filters/kreed2xsai.h deleted file mode 100644 index f2feffc0..00000000 --- a/supergameboy/libgambatte/src/video/filters/kreed2xsai.h +++ /dev/null @@ -1,40 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef KREED2XSAI_H -#define KREED2XSAI_H - -#include "filter.h" - -struct FilterInfo; - -class Kreed_2xSaI : public Filter { - Gambatte::uint_least32_t *buffer; - -public: - Kreed_2xSaI(); - ~Kreed_2xSaI(); - void init(); - void outit(); - const Gambatte::FilterInfo& info(); - void filter(Gambatte::uint_least32_t *dbuffer, unsigned pitch); - Gambatte::uint_least32_t* inBuffer(); - unsigned inPitch(); -}; - -#endif diff --git a/supergameboy/libgambatte/src/video/filters/maxsthq2x.cpp b/supergameboy/libgambatte/src/video/filters/maxsthq2x.cpp deleted file mode 100644 index a818d62a..00000000 --- a/supergameboy/libgambatte/src/video/filters/maxsthq2x.cpp +++ /dev/null @@ -1,2875 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aam�s * - * aamas@stud.ntnu.no * - * * - * 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 General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * -***************************************************************************/ -#include "maxsthq2x.h" -#include "filterinfo.h" -#include - -static /*inline*/ unsigned long Interp1(const unsigned long c1, const unsigned long c2) { - const unsigned long lowbits = ((c1 & 0x030303) * 3 + (c2 & 0x030303)) & 0x030303; - - return (c1 * 3 + c2 - lowbits) >> 2; -} - -static /*inline*/ unsigned long Interp2(const unsigned long c1, const unsigned long c2, const unsigned long c3) { - const unsigned long lowbits = ((c1 * 2 & 0x020202) + (c2 & 0x030303) + (c3 & 0x030303)) & 0x030303; - - return (c1 * 2 + c2 + c3 - lowbits) >> 2; -} - -static /*inline*/ unsigned long Interp6(const unsigned long c1, const unsigned long c2, const unsigned long c3) { - const unsigned long lowbits = ((c1 & 0x070707) * 5 + (c2 * 2 & 0x060606) + (c3 & 0x070707)) & 0x070707; - - return ((c1 * 5 + c2 * 2 + c3) - lowbits) >> 3; -} - -static /*inline*/ unsigned long Interp7(const unsigned long c1, const unsigned long c2, const unsigned long c3) { - const unsigned long lowbits = ((c1 & 0x070707) * 6 + (c2 & 0x070707) + (c3 & 0x070707)) & 0x070707; - - return ((c1 * 6 + c2 + c3) - lowbits) >> 3; -} - -static /*inline*/ unsigned long Interp9(unsigned long c1, const unsigned long c2, const unsigned long c3) { - const unsigned lowbits = ((c1 * 2 & 0x070707) + ((c2 & 0x070707) + (c3 & 0x070707)) * 3) & 0x070707; - - return (c1 * 2 + (c2 + c3) * 3 - lowbits) >> 3; -} - -static /*inline*/ unsigned long Interp10(const unsigned long c1, const unsigned long c2, const unsigned long c3) { - const unsigned lowbits = ((c1 & 0x0F0F0F) * 14 + (c2 & 0x0F0F0F) + (c3 & 0x0F0F0F)) & 0x0F0F0F; - - return (c1 * 14 + c2 + c3 - lowbits) >> 4; -} - -#define PIXEL00_0 *pOut = w[5]; -#define PIXEL00_10 *pOut = Interp1(w[5], w[1]); -#define PIXEL00_11 *pOut = Interp1(w[5], w[4]); -#define PIXEL00_12 *pOut = Interp1(w[5], w[2]); -#define PIXEL00_20 *pOut = Interp2(w[5], w[4], w[2]); -#define PIXEL00_21 *pOut = Interp2(w[5], w[1], w[2]); -#define PIXEL00_22 *pOut = Interp2(w[5], w[1], w[4]); -#define PIXEL00_60 *pOut = Interp6(w[5], w[2], w[4]); -#define PIXEL00_61 *pOut = Interp6(w[5], w[4], w[2]); -#define PIXEL00_70 *pOut = Interp7(w[5], w[4], w[2]); -#define PIXEL00_90 *pOut = Interp9(w[5], w[4], w[2]); -#define PIXEL00_100 *pOut = Interp10(w[5], w[4], w[2]); -#define PIXEL01_0 *(pOut+1) = w[5]; -#define PIXEL01_10 *(pOut+1) = Interp1(w[5], w[3]); -#define PIXEL01_11 *(pOut+1) = Interp1(w[5], w[2]); -#define PIXEL01_12 *(pOut+1) = Interp1(w[5], w[6]); -#define PIXEL01_20 *(pOut+1) = Interp2(w[5], w[2], w[6]); -#define PIXEL01_21 *(pOut+1) = Interp2(w[5], w[3], w[6]); -#define PIXEL01_22 *(pOut+1) = Interp2(w[5], w[3], w[2]); -#define PIXEL01_60 *(pOut+1) = Interp6(w[5], w[6], w[2]); -#define PIXEL01_61 *(pOut+1) = Interp6(w[5], w[2], w[6]); -#define PIXEL01_70 *(pOut+1) = Interp7(w[5], w[2], w[6]); -#define PIXEL01_90 *(pOut+1) = Interp9(w[5], w[2], w[6]); -#define PIXEL01_100 *(pOut+1) = Interp10(w[5], w[2], w[6]); -#define PIXEL10_0 *(pOut+dstPitch) = w[5]; -#define PIXEL10_10 *(pOut+dstPitch) = Interp1(w[5], w[7]); -#define PIXEL10_11 *(pOut+dstPitch) = Interp1(w[5], w[8]); -#define PIXEL10_12 *(pOut+dstPitch) = Interp1(w[5], w[4]); -#define PIXEL10_20 *(pOut+dstPitch) = Interp2(w[5], w[8], w[4]); -#define PIXEL10_21 *(pOut+dstPitch) = Interp2(w[5], w[7], w[4]); -#define PIXEL10_22 *(pOut+dstPitch) = Interp2(w[5], w[7], w[8]); -#define PIXEL10_60 *(pOut+dstPitch) = Interp6(w[5], w[4], w[8]); -#define PIXEL10_61 *(pOut+dstPitch) = Interp6(w[5], w[8], w[4]); -#define PIXEL10_70 *(pOut+dstPitch) = Interp7(w[5], w[8], w[4]); -#define PIXEL10_90 *(pOut+dstPitch) = Interp9(w[5], w[8], w[4]); -#define PIXEL10_100 *(pOut+dstPitch) = Interp10(w[5], w[8], w[4]); -#define PIXEL11_0 *(pOut+dstPitch+1) = w[5]; -#define PIXEL11_10 *(pOut+dstPitch+1) = Interp1(w[5], w[9]); -#define PIXEL11_11 *(pOut+dstPitch+1) = Interp1(w[5], w[6]); -#define PIXEL11_12 *(pOut+dstPitch+1) = Interp1(w[5], w[8]); -#define PIXEL11_20 *(pOut+dstPitch+1) = Interp2(w[5], w[6], w[8]); -#define PIXEL11_21 *(pOut+dstPitch+1) = Interp2(w[5], w[9], w[8]); -#define PIXEL11_22 *(pOut+dstPitch+1) = Interp2(w[5], w[9], w[6]); -#define PIXEL11_60 *(pOut+dstPitch+1) = Interp6(w[5], w[8], w[6]); -#define PIXEL11_61 *(pOut+dstPitch+1) = Interp6(w[5], w[6], w[8]); -#define PIXEL11_70 *(pOut+dstPitch+1) = Interp7(w[5], w[6], w[8]); -#define PIXEL11_90 *(pOut+dstPitch+1) = Interp9(w[5], w[6], w[8]); -#define PIXEL11_100 *(pOut+dstPitch+1) = Interp10(w[5], w[6], w[8]); - -static /*inline*/ bool Diff(const unsigned long w1, const unsigned long w2) { - const unsigned rdiff = (w1 >> 16) - (w2 >> 16); - const unsigned gdiff = (w1 >> 8 & 0xFF) - (w2 >> 8 & 0xFF); - const unsigned bdiff = (w1 & 0xFF) - (w2 & 0xFF); - - return rdiff + gdiff + bdiff + 0xC0U > 0xC0U * 2 || - rdiff - bdiff + 0x1CU > 0x1CU * 2 || - gdiff * 2 - rdiff - bdiff + 0x30U > 0x30U * 2; -} - -static void filter(Gambatte::uint_least32_t *pOut, const unsigned dstPitch, - const Gambatte::uint_least32_t *pIn, const unsigned Xres, const unsigned Yres) -{ - unsigned long w[10]; - - // +----+----+----+ - // | | | | - // | w1 | w2 | w3 | - // +----+----+----+ - // | | | | - // | w4 | w5 | w6 | - // +----+----+----+ - // | | | | - // | w7 | w8 | w9 | - // +----+----+----+ - - for (unsigned j = 0; j < Yres; j++) { - const unsigned prevline = j > 0 ? Xres : 0; - const unsigned nextline = j < Yres - 1 ? Xres : 0; - - for (unsigned i = 0; i < Xres; i++) { - w[2] = *(pIn - prevline); - w[5] = *(pIn); - w[8] = *(pIn + nextline); - - if (i > 0) { - w[1] = *(pIn - prevline - 1); - w[4] = *(pIn - 1); - w[7] = *(pIn + nextline - 1); - } else { - w[1] = w[2]; - w[4] = w[5]; - w[7] = w[8]; - } - - if (i < Xres - 1) { - w[3] = *(pIn - prevline + 1); - w[6] = *(pIn + 1); - w[9] = *(pIn + nextline + 1); - } else { - w[3] = w[2]; - w[6] = w[5]; - w[9] = w[8]; - } - - unsigned pattern = 0; - - { - unsigned flag = 1; - - const unsigned r1 = w[5] >> 16; - const unsigned g1 = w[5] >> 8 & 0xFF; - const unsigned b1 = w[5] & 0xFF; - - for (unsigned k = 1; k < 10; ++k) { - if (k == 5) continue; - - if (w[k] != w[5]) { - const unsigned rdiff = r1 - (w[k] >> 16); - const unsigned gdiff = g1 - (w[k] >> 8 & 0xFF); - const unsigned bdiff = b1 - (w[k] & 0xFF); - - if (rdiff + gdiff + bdiff + 0xC0U > 0xC0U * 2 || - rdiff - bdiff + 0x1CU > 0x1CU * 2 || - gdiff * 2 - rdiff - bdiff + 0x30U > 0x30U * 2) - pattern |= flag; - } - - flag <<= 1; - } - } - - 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; - pOut += 2; - } - pOut += dstPitch * 2 - Xres * 2; - } -} - -MaxSt_Hq2x::MaxSt_Hq2x() { - buffer = NULL; -} - -MaxSt_Hq2x::~MaxSt_Hq2x() { - outit(); -} - -void MaxSt_Hq2x::init() { - delete []buffer; - buffer = new Gambatte::uint_least32_t[144 * 160]; -} - -void MaxSt_Hq2x::outit() { - delete []buffer; - buffer = NULL; -} - -const Gambatte::FilterInfo& MaxSt_Hq2x::info() { - static const Gambatte::FilterInfo fInfo = { "MaxSt's Hq2x", 160 * 2, 144 * 2 }; - return fInfo; -} - -Gambatte::uint_least32_t* MaxSt_Hq2x::inBuffer() { - return buffer; -} - -unsigned MaxSt_Hq2x::inPitch() { - return 160; -} - -void MaxSt_Hq2x::filter(Gambatte::uint_least32_t *const dbuffer, const unsigned pitch) { - ::filter(dbuffer, pitch, buffer, 160, 144); -} diff --git a/supergameboy/libgambatte/src/video/filters/maxsthq2x.h b/supergameboy/libgambatte/src/video/filters/maxsthq2x.h deleted file mode 100644 index ca2cf411..00000000 --- a/supergameboy/libgambatte/src/video/filters/maxsthq2x.h +++ /dev/null @@ -1,41 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aam�s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef MAXSTHQ2X_H -#define MAXSTHQ2X_H - -#include "filter.h" - -struct FilterInfo; - -class MaxSt_Hq2x : public Filter { - Gambatte::uint_least32_t *buffer; - -public: - MaxSt_Hq2x(); - ~MaxSt_Hq2x(); - void init(); - void outit(); - const Gambatte::FilterInfo& info(); - void filter(Gambatte::uint_least32_t *dbuffer, unsigned pitch); - Gambatte::uint_least32_t* inBuffer(); - unsigned inPitch(); -}; - - -#endif diff --git a/supergameboy/libgambatte/src/video/filters/maxsthq3x.cpp b/supergameboy/libgambatte/src/video/filters/maxsthq3x.cpp deleted file mode 100644 index 996a221e..00000000 --- a/supergameboy/libgambatte/src/video/filters/maxsthq3x.cpp +++ /dev/null @@ -1,3845 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre AamÃ¥s * - * aamas@stud.ntnu.no * - * * - * 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 General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "maxsthq3x.h" -#include "filterinfo.h" -#include - -static /*inline*/ unsigned long Interp1(const unsigned long c1, const unsigned long c2) { - const unsigned long lowbits = ((c1 & 0x030303) * 3 + (c2 & 0x030303)) & 0x030303; - - return (c1 * 3 + c2 - lowbits) >> 2; -} - -static /*inline*/ unsigned long Interp2(const unsigned long c1, const unsigned long c2, const unsigned long c3) { - const unsigned long lowbits = ((c1 * 2 & 0x020202) + (c2 & 0x030303) + (c3 & 0x030303)) & 0x030303; - - return (c1 * 2 + c2 + c3 - lowbits) >> 2; -} - -static /*inline*/ unsigned long Interp3(const unsigned long c1, const unsigned long c2) { - const unsigned long lowbits = ((c1 & 0x070707) * 7 + (c2 & 0x070707)) & 0x070707; - - return (c1 * 7 + c2 - lowbits) >> 3; -} - -static /*inline*/ unsigned long Interp4(const unsigned long c1, const unsigned long c2, const unsigned long c3) { - const unsigned long lowbits = ((c1 * 2 & 0x0E0E0E) + ((c2 & 0x0F0F0F) + (c3 & 0x0F0F0F)) * 7) & 0x0F0F0F; - - return (c1 * 2 + (c2 + c3) * 7 - lowbits) >> 4; -} - -static /*inline*/ unsigned long Interp5(const unsigned long c1, const unsigned long c2) { - return (c1 + c2 - ((c1 ^ c2) & 0x010101)) >> 1; -} - -#define PIXEL00_1M *pOut = Interp1(w[5], w[1]); -#define PIXEL00_1U *pOut = Interp1(w[5], w[2]); -#define PIXEL00_1L *pOut = Interp1(w[5], w[4]); -#define PIXEL00_2 *pOut = Interp2(w[5], w[4], w[2]); -#define PIXEL00_4 *pOut = Interp4(w[5], w[4], w[2]); -#define PIXEL00_5 *pOut = Interp5(w[4], w[2]); -#define PIXEL00_C *pOut = w[5]; - -#define PIXEL01_1 *(pOut+1) = Interp1(w[5], w[2]); -#define PIXEL01_3 *(pOut+1) = Interp3(w[5], w[2]); -#define PIXEL01_6 *(pOut+1) = Interp1(w[2], w[5]); -#define PIXEL01_C *(pOut+1) = w[5]; - -#define PIXEL02_1M *(pOut+2) = Interp1(w[5], w[3]); -#define PIXEL02_1U *(pOut+2) = Interp1(w[5], w[2]); -#define PIXEL02_1R *(pOut+2) = Interp1(w[5], w[6]); -#define PIXEL02_2 *(pOut+2) = Interp2(w[5], w[2], w[6]); -#define PIXEL02_4 *(pOut+2) = Interp4(w[5], w[2], w[6]); -#define PIXEL02_5 *(pOut+2) = Interp5(w[2], w[6]); -#define PIXEL02_C *(pOut+2) = w[5]; - -#define PIXEL10_1 *(pOut+dstPitch) = Interp1(w[5], w[4]); -#define PIXEL10_3 *(pOut+dstPitch) = Interp3(w[5], w[4]); -#define PIXEL10_6 *(pOut+dstPitch) = Interp1(w[4], w[5]); -#define PIXEL10_C *(pOut+dstPitch) = w[5]; - -#define PIXEL11 *(pOut+dstPitch+1) = w[5]; - -#define PIXEL12_1 *(pOut+dstPitch+2) = Interp1(w[5], w[6]); -#define PIXEL12_3 *(pOut+dstPitch+2) = Interp3(w[5], w[6]); -#define PIXEL12_6 *(pOut+dstPitch+2) = Interp1(w[6], w[5]); -#define PIXEL12_C *(pOut+dstPitch+2) = w[5]; - -#define PIXEL20_1M *(pOut+dstPitch*2) = Interp1(w[5], w[7]); -#define PIXEL20_1D *(pOut+dstPitch*2) = Interp1(w[5], w[8]); -#define PIXEL20_1L *(pOut+dstPitch*2) = Interp1(w[5], w[4]); -#define PIXEL20_2 *(pOut+dstPitch*2) = Interp2(w[5], w[8], w[4]); -#define PIXEL20_4 *(pOut+dstPitch*2) = Interp4(w[5], w[8], w[4]); -#define PIXEL20_5 *(pOut+dstPitch*2) = Interp5(w[8], w[4]); -#define PIXEL20_C *(pOut+dstPitch*2) = w[5]; - -#define PIXEL21_1 *(pOut+dstPitch*2+1) = Interp1(w[5], w[8]); -#define PIXEL21_3 *(pOut+dstPitch*2+1) = Interp3(w[5], w[8]); -#define PIXEL21_6 *(pOut+dstPitch*2+1) = Interp1(w[8], w[5]); -#define PIXEL21_C *(pOut+dstPitch*2+1) = w[5]; - -#define PIXEL22_1M *(pOut+dstPitch*2+2) = Interp1(w[5], w[9]); -#define PIXEL22_1D *(pOut+dstPitch*2+2) = Interp1(w[5], w[8]); -#define PIXEL22_1R *(pOut+dstPitch*2+2) = Interp1(w[5], w[6]); -#define PIXEL22_2 *(pOut+dstPitch*2+2) = Interp2(w[5], w[6], w[8]); -#define PIXEL22_4 *(pOut+dstPitch*2+2) = Interp4(w[5], w[6], w[8]); -#define PIXEL22_5 *(pOut+dstPitch*2+2) = Interp5(w[6], w[8]); -#define PIXEL22_C *(pOut+dstPitch*2+2) = w[5]; - -static /*inline*/ bool Diff(const unsigned long w1, const unsigned long w2) { - const unsigned rdiff = (w1 >> 16) - (w2 >> 16); - const unsigned gdiff = (w1 >> 8 & 0xFF) - (w2 >> 8 & 0xFF); - const unsigned bdiff = (w1 & 0xFF) - (w2 & 0xFF); - - return rdiff + gdiff + bdiff + 0xC0U > 0xC0U * 2 || - rdiff - bdiff + 0x1CU > 0x1CU * 2 || - gdiff * 2 - rdiff - bdiff + 0x30U > 0x30U * 2; -} - -static void filter(Gambatte::uint_least32_t *pOut, const unsigned dstPitch, - const Gambatte::uint_least32_t *pIn, const unsigned Xres, const unsigned Yres) -{ - unsigned long w[10]; - - // +----+----+----+ - // | | | | - // | w1 | w2 | w3 | - // +----+----+----+ - // | | | | - // | w4 | w5 | w6 | - // +----+----+----+ - // | | | | - // | w7 | w8 | w9 | - // +----+----+----+ - - for (unsigned j = 0; j < Yres; j++) { - const unsigned prevline = j > 0 ? Xres : 0; - const unsigned nextline = j < Yres - 1 ? Xres : 0; - - for (unsigned i = 0; i < Xres; i++) { - w[2] = *(pIn - prevline); - w[5] = *(pIn); - w[8] = *(pIn + nextline); - - if (i > 0) { - w[1] = *(pIn - prevline - 1); - w[4] = *(pIn - 1); - w[7] = *(pIn + nextline - 1); - } else { - w[1] = w[2]; - w[4] = w[5]; - w[7] = w[8]; - } - - if (i < Xres - 1) { - w[3] = *(pIn - prevline + 1); - w[6] = *(pIn + 1); - w[9] = *(pIn + nextline + 1); - } else { - w[3] = w[2]; - w[6] = w[5]; - w[9] = w[8]; - } - - unsigned pattern = 0; - - { - unsigned flag = 1; - - const unsigned r1 = w[5] >> 16; - const unsigned g1 = w[5] >> 8 & 0xFF; - const unsigned b1 = w[5] & 0xFF; - - for (unsigned k = 1; k < 10; ++k) { - if (k == 5) continue; - - if (w[k] != w[5]) { - const unsigned rdiff = r1 - (w[k] >> 16); - const unsigned gdiff = g1 - (w[k] >> 8 & 0xFF); - const unsigned bdiff = b1 - (w[k] & 0xFF); - - if (rdiff + gdiff + bdiff + 0xC0U > 0xC0U * 2 || - rdiff - bdiff + 0x1CU > 0x1CU * 2 || - gdiff * 2 - rdiff - bdiff + 0x30U > 0x30U * 2) - pattern |= flag; - } - - flag <<= 1; - } - } - - 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; - pOut += 3; - } - pOut += dstPitch * 3 - Xres * 3; - } -} - -MaxSt_Hq3x::MaxSt_Hq3x() { - buffer = NULL; -} - -MaxSt_Hq3x::~MaxSt_Hq3x() { - outit(); -} - -void MaxSt_Hq3x::init() { - delete []buffer; - buffer = new Gambatte::uint_least32_t[144 * 160]; -} - -void MaxSt_Hq3x::outit() { - delete []buffer; - buffer = NULL; -} - -const Gambatte::FilterInfo& MaxSt_Hq3x::info() { - static const Gambatte::FilterInfo fInfo = { "MaxSt's Hq3x", 160 * 3, 144 * 3 }; - return fInfo; -} - -Gambatte::uint_least32_t* MaxSt_Hq3x::inBuffer() { - return buffer; -} - -unsigned MaxSt_Hq3x::inPitch() { - return 160; -} - -void MaxSt_Hq3x::filter(Gambatte::uint_least32_t *const dbuffer, const unsigned pitch) { - ::filter(dbuffer, pitch, buffer, 160, 144); -} diff --git a/supergameboy/libgambatte/src/video/filters/maxsthq3x.h b/supergameboy/libgambatte/src/video/filters/maxsthq3x.h deleted file mode 100644 index 9e1f51d6..00000000 --- a/supergameboy/libgambatte/src/video/filters/maxsthq3x.h +++ /dev/null @@ -1,40 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre AamÃ¥s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef MAXSTHQ3X_H -#define MAXSTHQ3X_H - -#include "filter.h" - -struct FilterInfo; - -class MaxSt_Hq3x : public Filter { - Gambatte::uint_least32_t *buffer; - -public: - MaxSt_Hq3x(); - ~MaxSt_Hq3x(); - void init(); - void outit(); - const Gambatte::FilterInfo& info(); - void filter(Gambatte::uint_least32_t *dbuffer, unsigned pitch); - Gambatte::uint_least32_t* inBuffer(); - unsigned inPitch(); -}; - -#endif diff --git a/supergameboy/libgambatte/src/video/irq_event.cpp b/supergameboy/libgambatte/src/video/irq_event.cpp deleted file mode 100644 index 358f1daf..00000000 --- a/supergameboy/libgambatte/src/video/irq_event.cpp +++ /dev/null @@ -1,36 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "irq_event.h" - -IrqEvent::IrqEvent(event_queue &irqEventQueue_in) : - VideoEvent(11), - irqEventQueue(irqEventQueue_in) -{ -} - -void IrqEvent::doEvent() { - irqEventQueue.top()->doEvent(); - - if (irqEventQueue.top()->time() == DISABLED_TIME) - irqEventQueue.pop(); - else - irqEventQueue.modify_root(irqEventQueue.top()); - - setTime(schedule(irqEventQueue)); -} diff --git a/supergameboy/libgambatte/src/video/irq_event.h b/supergameboy/libgambatte/src/video/irq_event.h deleted file mode 100644 index c8a5b991..00000000 --- a/supergameboy/libgambatte/src/video/irq_event.h +++ /dev/null @@ -1,52 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * -***************************************************************************/ -#ifndef VIDEO_IRQ_EVENT_H -#define VIDEO_IRQ_EVENT_H - -#include "../event_queue.h" -#include "video_event.h" -#include "video_event_comparer.h" -#include "basic_add_event.h" - -class IrqEvent : public VideoEvent { - event_queue &irqEventQueue; - -public: - IrqEvent(event_queue &irqEventQueue_in); - - void doEvent(); - - static unsigned long schedule(const event_queue &irqEventQueue) { - return irqEventQueue.top()->time(); - } - - void schedule() { - setTime(irqEventQueue.top()->time()); - } -}; - -static inline void addEvent(event_queue &q, IrqEvent *const e, const unsigned long newTime) { - addUnconditionalEvent(q, e, newTime); -} - -static inline void addFixedtimeEvent(event_queue &q, IrqEvent *const e, const unsigned long newTime) { - addUnconditionalFixedtimeEvent(q, e, newTime); -} - -#endif diff --git a/supergameboy/libgambatte/src/video/ly_counter.cpp b/supergameboy/libgambatte/src/video/ly_counter.cpp deleted file mode 100644 index 5d5b6d98..00000000 --- a/supergameboy/libgambatte/src/video/ly_counter.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aam�s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "ly_counter.h" -#include "../savestate.h" - -LyCounter::LyCounter() : VideoEvent(0) { - setDoubleSpeed(false); - reset(0, 0); -} - -void LyCounter::doEvent() { - ++ly_; - - if (ly_ == 154) - ly_ = 0; - - setTime(time() + lineTime_); -} - -unsigned long LyCounter::nextLineCycle(const unsigned lineCycle, const unsigned long cycleCounter) const { - unsigned long tmp = time() + (lineCycle << ds); - - if (tmp - cycleCounter > lineTime_) - tmp -= lineTime_; - - return tmp; -} - -unsigned long LyCounter::nextFrameCycle(const unsigned long frameCycle, const unsigned long cycleCounter) const { - unsigned long tmp = time() + (((153U - ly()) * 456U + frameCycle) << ds); - - if (tmp - cycleCounter > 70224U << ds) - tmp -= 70224U << ds; - - return tmp; -} - -void LyCounter::reset(const unsigned long videoCycles, const unsigned long lastUpdate) { - ly_ = videoCycles / 456; - setTime(lastUpdate + ((456 - (videoCycles - ly_ * 456ul)) << isDoubleSpeed())); -} - -void LyCounter::setDoubleSpeed(const bool ds_in) { - ds = ds_in; - lineTime_ = 456U << ds_in; -} diff --git a/supergameboy/libgambatte/src/video/ly_counter.h b/supergameboy/libgambatte/src/video/ly_counter.h deleted file mode 100644 index 2b795fb8..00000000 --- a/supergameboy/libgambatte/src/video/ly_counter.h +++ /dev/null @@ -1,69 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef LY_COUNTER_H -#define LY_COUNTER_H - -class SaveState; - -#include "video_event.h" -#include "basic_add_event.h" - -class LyCounter : public VideoEvent { - unsigned short lineTime_; - unsigned char ly_; - bool ds; - -public: - LyCounter(); - - void doEvent(); - - bool isDoubleSpeed() const { - return ds; - } - - unsigned lineCycles(const unsigned long cc) const { - return 456u - ((time() - cc) >> isDoubleSpeed()); - } - - unsigned lineTime() const { - return lineTime_; - } - - unsigned ly() const { - return ly_; - } - - unsigned long nextLineCycle(unsigned lineCycle, unsigned long cycleCounter) const; - unsigned long nextFrameCycle(unsigned long frameCycle, unsigned long cycleCounter) const; - - void reset(unsigned long videoCycles, unsigned long lastUpdate); - - void setDoubleSpeed(bool ds_in); -}; - -static inline void addEvent(event_queue &q, LyCounter *const e, const unsigned long newTime) { - addUnconditionalEvent(q, e, newTime); -} - -static inline void addFixedtimeEvent(event_queue &q, LyCounter *const e, const unsigned long newTime) { - addUnconditionalFixedtimeEvent(q, e, newTime); -} - -#endif diff --git a/supergameboy/libgambatte/src/video/lyc_irq.cpp b/supergameboy/libgambatte/src/video/lyc_irq.cpp deleted file mode 100644 index eb81d41b..00000000 --- a/supergameboy/libgambatte/src/video/lyc_irq.cpp +++ /dev/null @@ -1,42 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "lyc_irq.h" - -LycIrq::LycIrq(unsigned char &ifReg_in) : - VideoEvent(1), - ifReg(ifReg_in) -{ - setDoubleSpeed(false); - setM2IrqEnabled(false); - setLycReg(0); - setSkip(false); -} - -void LycIrq::doEvent() { - if (!skip && (!m2IrqEnabled || lycReg_ > 143 || lycReg_ == 0)) - ifReg |= 0x2; - - skip = false; - - setTime(time() + frameTime); -} - -unsigned long LycIrq::schedule(const unsigned statReg, const unsigned lycReg, const LyCounter &lyCounter, const unsigned long cycleCounter) { - return ((statReg & 0x40) && lycReg < 154) ? lyCounter.nextFrameCycle(lycReg ? lycReg * 456 : 153 * 456 + 8, cycleCounter) : static_cast(DISABLED_TIME); -} diff --git a/supergameboy/libgambatte/src/video/lyc_irq.h b/supergameboy/libgambatte/src/video/lyc_irq.h deleted file mode 100644 index ed93fdda..00000000 --- a/supergameboy/libgambatte/src/video/lyc_irq.h +++ /dev/null @@ -1,67 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef VIDEO_LYC_IRQ_H -#define VIDEO_LYC_IRQ_H - -#include "ly_counter.h" - -class LycIrq : public VideoEvent { - unsigned char &ifReg; - unsigned long frameTime; - unsigned char lycReg_; - bool m2IrqEnabled; - bool skip; - -public: - LycIrq(unsigned char &ifReg_in); - - void doEvent(); - - unsigned lycReg() const { - return lycReg_; - } - - static unsigned long schedule(unsigned statReg, unsigned lycReg, const LyCounter &lyCounter, unsigned long cycleCounter); - - void setDoubleSpeed(const bool ds) { - frameTime = 70224 << ds; - } - - void setLycReg(const unsigned lycReg_in) { - lycReg_ = lycReg_in; - } - - void setM2IrqEnabled(const bool enabled) { - m2IrqEnabled = enabled; - } - - void setSkip(const bool skip) { - this->skip = skip; - } - - bool skips() const { - return skip; - } - - bool isSkipPeriod(const unsigned long cycleCounter, const bool doubleSpeed) const { - return lycReg_ > 0 && time() - cycleCounter > 4U >> doubleSpeed && time() - cycleCounter < 9; - } -}; - -#endif diff --git a/supergameboy/libgambatte/src/video/m3_extra_cycles.cpp b/supergameboy/libgambatte/src/video/m3_extra_cycles.cpp deleted file mode 100644 index de4eadb7..00000000 --- a/supergameboy/libgambatte/src/video/m3_extra_cycles.cpp +++ /dev/null @@ -1,101 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "m3_extra_cycles.h" -#include "scx_reader.h" -#include "window.h" -#include "sprite_mapper.h" -#include "../insertion_sort.h" - -M3ExtraCycles::M3ExtraCycles(const SpriteMapper &spriteMapper, - const ScxReader &scxReader, - const Window &win) : - spriteMapper(spriteMapper), - scxReader(scxReader), - win(win) -{ - invalidateCache(); -} - -static const unsigned char* addLineCycles(const unsigned char *const start, const unsigned char *const end, - const unsigned maxSpx, const unsigned scwxAnd7, const unsigned char *const posbuf_plus1, unsigned char *cycles_out) { - unsigned sum = 0; - - const unsigned char *a = start; - - for (; a < end; ++a) { - const unsigned spx = posbuf_plus1[*a]; - - if (spx > maxSpx) - break; - - unsigned cycles = 6; - const unsigned posAnd7 = (scwxAnd7 + spx) & 7; - - if (posAnd7 < 5) { - cycles = 11 - posAnd7; - - for (const unsigned char *b = a; b > start;) { - const unsigned bSpx = posbuf_plus1[*--b]; - - if (spx - bSpx > 4U) - break; - - if (((scwxAnd7 + bSpx) & 7) < 4 || spx == bSpx) { - cycles = 6; - break; - } - } - } - - sum += cycles; - } - - *cycles_out += sum; - - return a; -} - -void M3ExtraCycles::updateLine(const unsigned ly) const { - const bool windowEnabled = win.enabled(ly); - - cycles[ly] = windowEnabled ? scxReader.scxAnd7() + 6 : scxReader.scxAnd7(); - - const unsigned numSprites = spriteMapper.numSprites(ly); - - if (numSprites == 0) - return; - - unsigned char sortBuf[10]; - const unsigned char *tmp = spriteMapper.sprites(ly); - - if (spriteMapper.isCgb()) { - std::memcpy(sortBuf, tmp, sizeof(sortBuf)); - insertionSort(sortBuf, sortBuf + numSprites, SpriteMapper::SpxLess(spriteMapper.posbuf())); - tmp = sortBuf; - } - - const unsigned char *const tmpend = tmp + numSprites; - const unsigned char *const posbuf_plus1 = spriteMapper.posbuf() + 1; - - if (windowEnabled) { - addLineCycles(addLineCycles(tmp, tmpend, win.wxReader.wx(), scxReader.scxAnd7(), posbuf_plus1, cycles + ly), - tmpend, 167, 7 - win.wxReader.wx(), posbuf_plus1, cycles + ly); - } else - addLineCycles(tmp, tmpend, 167, scxReader.scxAnd7(), posbuf_plus1, cycles + ly); -} diff --git a/supergameboy/libgambatte/src/video/m3_extra_cycles.h b/supergameboy/libgambatte/src/video/m3_extra_cycles.h deleted file mode 100644 index 8a7f1470..00000000 --- a/supergameboy/libgambatte/src/video/m3_extra_cycles.h +++ /dev/null @@ -1,56 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef VIDEO_M3_EXTRA_CYCLES_H -#define VIDEO_M3_EXTRA_CYCLES_H - -class ScxReader; -class Window; -class SpriteMapper; - -#include - -class M3ExtraCycles { - enum { CYCLES_INVALID = 0xFF }; - - mutable unsigned char cycles[144]; - - const SpriteMapper &spriteMapper; - const ScxReader &scxReader; - const Window &win; - - void updateLine(unsigned ly) const; - -public: - M3ExtraCycles(const SpriteMapper &spriteMapper, - const ScxReader &scxReader_in, - const Window &win); - - void invalidateCache() { - std::memset(cycles, CYCLES_INVALID, sizeof(cycles)); - } - - unsigned operator()(const unsigned ly) const { - if (cycles[ly] == CYCLES_INVALID) - updateLine(ly); - - return cycles[ly]; - } -}; - -#endif diff --git a/supergameboy/libgambatte/src/video/mode0_irq.cpp b/supergameboy/libgambatte/src/video/mode0_irq.cpp deleted file mode 100644 index 041d3db1..00000000 --- a/supergameboy/libgambatte/src/video/mode0_irq.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aam�s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * -***************************************************************************/ -#include "mode0_irq.h" - -#include "ly_counter.h" -#include "lyc_irq.h" -#include "m3_extra_cycles.h" - -Mode0Irq::Mode0Irq(const LyCounter &lyCounter_in, const LycIrq &lycIrq_in, - const M3ExtraCycles &m3ExtraCycles_in, unsigned char &ifReg_in) : - VideoEvent(0), - lyCounter(lyCounter_in), - lycIrq(lycIrq_in), - m3ExtraCycles(m3ExtraCycles_in), - ifReg(ifReg_in) -{ -} - -static unsigned baseCycle(const bool ds) { - return 80 + 169 + ds * 3 + 1 - ds; -} - -void Mode0Irq::doEvent() { - if (lycIrq.time() == DISABLED_TIME || lyCounter.ly() != lycIrq.lycReg()) - ifReg |= 2; - - unsigned long nextTime = lyCounter.time(); - unsigned nextLy = lyCounter.ly() + 1; - - if (nextLy == 144) { - nextLy = 0; - nextTime += lyCounter.lineTime() * 10; - } - - nextTime += (baseCycle(lyCounter.isDoubleSpeed()) + m3ExtraCycles(nextLy)) << lyCounter.isDoubleSpeed(); - - setTime(nextTime); -} - -void Mode0Irq::mode3CyclesChange() { - unsigned long nextTime = lyCounter.time() - lyCounter.lineTime(); - unsigned nextLy = lyCounter.ly(); - - if (time() > lyCounter.time()) { - nextTime += lyCounter.lineTime(); - ++nextLy; - - if (nextLy > 143) { - nextTime += lyCounter.lineTime() * (154 - nextLy); - nextLy = 0; - } - } - - nextTime += (baseCycle(lyCounter.isDoubleSpeed()) + m3ExtraCycles(nextLy)) << lyCounter.isDoubleSpeed(); - - setTime(nextTime); -} - -unsigned long Mode0Irq::schedule(const unsigned statReg, const M3ExtraCycles &m3ExtraCycles, const LyCounter &lyCounter, const unsigned long cycleCounter) { - if (!(statReg & 0x08)) - return DISABLED_TIME; - - unsigned line = lyCounter.ly(); - int next = static_cast(baseCycle(lyCounter.isDoubleSpeed())) - static_cast(lyCounter.lineCycles(cycleCounter)); - - if (line < 144 && next + static_cast(m3ExtraCycles(line)) <= 0) { - next += 456; - ++line; - } - - if (line > 143) { - next += (154 - line) * 456; - line = 0; - } - - next += m3ExtraCycles(line); - - return cycleCounter + (static_cast(next) << lyCounter.isDoubleSpeed()); -} diff --git a/supergameboy/libgambatte/src/video/mode0_irq.h b/supergameboy/libgambatte/src/video/mode0_irq.h deleted file mode 100644 index bc5f1540..00000000 --- a/supergameboy/libgambatte/src/video/mode0_irq.h +++ /dev/null @@ -1,42 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef VIDEO_MODE0_IRQ_H -#define VIDEO_MODE0_IRQ_H - -class LycIrq; -class M3ExtraCycles; - -#include "ly_counter.h" - -class Mode0Irq : public VideoEvent { - const LyCounter &lyCounter; - const LycIrq &lycIrq; - const M3ExtraCycles &m3ExtraCycles; - unsigned char &ifReg; - -public: - Mode0Irq(const LyCounter &lyCounter_in, const LycIrq &lycIrq_in, - const M3ExtraCycles &m3ExtraCycles_in, unsigned char &ifReg_in); - - void doEvent(); - void mode3CyclesChange(); - static unsigned long schedule(unsigned statReg, const M3ExtraCycles &m3ExtraCycles, const LyCounter &lyCounter, unsigned long cycleCounter); -}; - -#endif diff --git a/supergameboy/libgambatte/src/video/mode1_irq.cpp b/supergameboy/libgambatte/src/video/mode1_irq.cpp deleted file mode 100644 index ddafe25c..00000000 --- a/supergameboy/libgambatte/src/video/mode1_irq.cpp +++ /dev/null @@ -1,33 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "mode1_irq.h" - -Mode1Irq::Mode1Irq(unsigned char &ifReg_in) : - VideoEvent(0), - ifReg(ifReg_in) -{ - setDoubleSpeed(false); - setM1StatIrqEnabled(false); -} - -void Mode1Irq::doEvent() { - ifReg |= flags; - - setTime(time() + frameTime); -} diff --git a/supergameboy/libgambatte/src/video/mode1_irq.h b/supergameboy/libgambatte/src/video/mode1_irq.h deleted file mode 100644 index f4e6270f..00000000 --- a/supergameboy/libgambatte/src/video/mode1_irq.h +++ /dev/null @@ -1,56 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef VIDEO_MODE1_IRQ_H -#define VIDEO_MODE1_IRQ_H - -#include "ly_counter.h" -#include "basic_add_event.h" - -class Mode1Irq : public VideoEvent { - unsigned char &ifReg; - unsigned long frameTime; - unsigned char flags; - -public: - Mode1Irq(unsigned char &ifReg_in); - - void doEvent(); - - static unsigned long schedule(const LyCounter &lyCounter, unsigned long cycleCounter) { - return lyCounter.nextFrameCycle(144 * 456, cycleCounter); - } - - void setDoubleSpeed(const bool ds) { - frameTime = 70224 << ds; - } - - void setM1StatIrqEnabled(const bool enabled) { - flags = (enabled * 2) | 1; - } -}; - -static inline void addEvent(event_queue &q, Mode1Irq *const e, const unsigned long newTime) { - addUnconditionalEvent(q, e, newTime); -} - -static inline void addFixedtimeEvent(event_queue &q, Mode1Irq *const e, const unsigned long newTime) { - addUnconditionalFixedtimeEvent(q, e, newTime); -} - -#endif diff --git a/supergameboy/libgambatte/src/video/mode2_irq.cpp b/supergameboy/libgambatte/src/video/mode2_irq.cpp deleted file mode 100644 index b1a419ea..00000000 --- a/supergameboy/libgambatte/src/video/mode2_irq.cpp +++ /dev/null @@ -1,63 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "mode2_irq.h" - -#include "ly_counter.h" -#include "lyc_irq.h" - -Mode2Irq::Mode2Irq(const LyCounter &lyCounter_in, const LycIrq &lycIrq_in, - unsigned char &ifReg_in) : - VideoEvent(0), - lyCounter(lyCounter_in), - lycIrq(lycIrq_in), - ifReg(ifReg_in) -{ -} - -void Mode2Irq::doEvent() { - const unsigned ly = lyCounter.time() - time() < 8 ? (lyCounter.ly() == 153 ? 0 : lyCounter.ly() + 1) : lyCounter.ly(); - - if (lycIrq.time() == DISABLED_TIME || (lycIrq.lycReg() != 0 && ly != (lycIrq.lycReg() + 1U)) || (lycIrq.lycReg() == 0 && ly > 1)) - ifReg |= 2; - - setTime(time() + lyCounter.lineTime()); - - if (ly == 0) - setTime(time() - 4); - else if (ly == 143) - setTime(time() + lyCounter.lineTime() * 10 + 4); -} - -unsigned long Mode2Irq::schedule(const unsigned statReg, const LyCounter &lyCounter, const unsigned long cycleCounter) { - if ((statReg & 0x28) != 0x20) - return DISABLED_TIME; - - unsigned next = lyCounter.time() - cycleCounter; - - if (lyCounter.ly() >= 143 || (lyCounter.ly() == 142 && next <= 4)) { - next += (153u - lyCounter.ly()) * lyCounter.lineTime(); - } else { - if (next <= 4) - next += lyCounter.lineTime(); - - next -= 4; - } - - return cycleCounter + next; -} diff --git a/supergameboy/libgambatte/src/video/mode2_irq.h b/supergameboy/libgambatte/src/video/mode2_irq.h deleted file mode 100644 index 2ea86055..00000000 --- a/supergameboy/libgambatte/src/video/mode2_irq.h +++ /dev/null @@ -1,40 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef VIDEO_MODE2_IRQ_H -#define VIDEO_MODE2_IRQ_H - -class LycIrq; - -#include "ly_counter.h" -#include "basic_add_event.h" - -class Mode2Irq : public VideoEvent { - const LyCounter &lyCounter; - const LycIrq &lycIrq; - unsigned char &ifReg; - -public: - Mode2Irq(const LyCounter &lyCounter_in, const LycIrq &lycIrq_in, - unsigned char &ifReg_in); - - void doEvent(); - static unsigned long schedule(unsigned statReg, const LyCounter &lyCounter, unsigned long cycleCounter); -}; - -#endif diff --git a/supergameboy/libgambatte/src/video/mode3_event.cpp b/supergameboy/libgambatte/src/video/mode3_event.cpp deleted file mode 100644 index 84502315..00000000 --- a/supergameboy/libgambatte/src/video/mode3_event.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "mode3_event.h" -#include "mode0_irq.h" -#include "irq_event.h" - -Mode3Event::Mode3Event(event_queue &m3EventQueue_in, - event_queue &vEventQueue_in, - Mode0Irq &mode0Irq_in, IrqEvent &irqEvent_in) : - VideoEvent(1), - m3EventQueue(m3EventQueue_in), - vEventQueue(vEventQueue_in), - mode0Irq(mode0Irq_in), - irqEvent(irqEvent_in) -{ -} - -void Mode3Event::doEvent() { - m3EventQueue.top()->doEvent(); - - if (m3EventQueue.top()->time() == DISABLED_TIME) - m3EventQueue.pop(); - else - m3EventQueue.modify_root(m3EventQueue.top()); - - if (mode0Irq.time() != DISABLED_TIME) { - const unsigned long oldTime = mode0Irq.time(); - mode0Irq.mode3CyclesChange(); - - if (mode0Irq.time() != oldTime) { - // position in irqEventQueue should remain the same. - // The same may be possible for vEventQueue, with some precautions. - if (irqEvent.time() == oldTime) { - irqEvent.schedule(); - - if (mode0Irq.time() > oldTime) - vEventQueue.inc(&irqEvent, &irqEvent); - else - vEventQueue.dec(&irqEvent, &irqEvent); - } - - } - } - - setTime(schedule(m3EventQueue)); -} diff --git a/supergameboy/libgambatte/src/video/mode3_event.h b/supergameboy/libgambatte/src/video/mode3_event.h deleted file mode 100644 index 7f9aedc6..00000000 --- a/supergameboy/libgambatte/src/video/mode3_event.h +++ /dev/null @@ -1,47 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef MODE3_EVENT_H -#define MODE3_EVENT_H - -class Mode0Irq; -class IrqEvent; - -#include "video_event.h" -#include "video_event_comparer.h" -#include "../event_queue.h" - -class Mode3Event : public VideoEvent { - event_queue &m3EventQueue; - event_queue &vEventQueue; - Mode0Irq &mode0Irq; - IrqEvent &irqEvent; - -public: - Mode3Event(event_queue &m3EventQueue_in, - event_queue &vEventQueue_in, - Mode0Irq &mode0Irq_in, IrqEvent &irqEvent_in); - - void doEvent(); - - static unsigned long schedule(const event_queue &m3EventQueue) { - return m3EventQueue.empty() ? static_cast(DISABLED_TIME) : m3EventQueue.top()->time(); - } -}; - -#endif diff --git a/supergameboy/libgambatte/src/video/sc_reader.cpp b/supergameboy/libgambatte/src/video/sc_reader.cpp deleted file mode 100644 index fff2f66c..00000000 --- a/supergameboy/libgambatte/src/video/sc_reader.cpp +++ /dev/null @@ -1,62 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "sc_reader.h" - -#include "../event_queue.h" -#include "../savestate.h" - -ScReader::ScReader() : VideoEvent(2) { - setDoubleSpeed(false); - setScxSource(0); - setScySource(0); - scx_[1] = scx_[0] = scxSrc; - scy_[1] = scy_[0] = scySrc; -} - -void ScReader::doEvent() { - scy_[0] = scy_[1]; - scy_[1] = scySrc; - scx_[0] = scx_[1]; - scx_[1] = scxSrc; - - if ((scy_[0] ^ scy_[1]) | (scx_[0] ^ scx_[1])) - setTime(time() + incCycles); - else - setTime(DISABLED_TIME); - -} - -void ScReader::saveState(SaveState &state) const { - state.ppu.scx[0] = scx_[0]; - state.ppu.scx[1] = scx_[1]; - state.ppu.scy[0] = scy_[0]; - state.ppu.scy[1] = scy_[1]; -} - -void ScReader::loadState(const SaveState &state) { - scx_[0] = state.ppu.scx[0]; - scx_[1] = state.ppu.scx[1]; - scy_[0] = state.ppu.scy[0]; - scy_[1] = state.ppu.scy[1]; -} - -void ScReader::setDoubleSpeed(const bool dS_in) { - dS = dS_in; - incCycles = 8u << dS_in; -} diff --git a/supergameboy/libgambatte/src/video/sc_reader.h b/supergameboy/libgambatte/src/video/sc_reader.h deleted file mode 100644 index 0d7ef7d1..00000000 --- a/supergameboy/libgambatte/src/video/sc_reader.h +++ /dev/null @@ -1,77 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aam�s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef SC_READER_H -#define SC_READER_H - -class SaveState; -template class event_queue; - -#include "video_event.h" -#include "video_event_comparer.h" -#include "basic_add_event.h" - -class ScReader : public VideoEvent { - unsigned char scx_[2]; - unsigned char scy_[2]; - - unsigned char scxSrc; - unsigned char scySrc; - unsigned char incCycles; - bool dS; - -public: - ScReader(); - - void doEvent(); - - unsigned scx() const { - return /*(*/scx_[0]/* & ~0x7) | (scxSrc & 0x7)*/; - } - - unsigned scy() const { - return scy_[0]; - } - - static unsigned long schedule(const unsigned long lastUpdate, const unsigned long videoCycles, const unsigned scReadOffset, const bool dS) { - return lastUpdate + ((8u - ((videoCycles - scReadOffset) & 7)) << dS); - } - - void setDoubleSpeed(bool dS_in); - - void setScxSource(const unsigned scxSrc_in) { - scxSrc = scxSrc_in; - } - - void setScySource(const unsigned scySrc_in) { - scySrc = scySrc_in; - } - - void saveState(SaveState &state) const; - void loadState(const SaveState &state); -}; - -static inline void addEvent(event_queue &q, ScReader *const e, const unsigned long newTime) { - addUnconditionalEvent(q, e, newTime); -} - -static inline void addFixedtimeEvent(event_queue &q, ScReader *const e, const unsigned long newTime) { - addUnconditionalFixedtimeEvent(q, e, newTime); -} - -#endif diff --git a/supergameboy/libgambatte/src/video/scx_reader.cpp b/supergameboy/libgambatte/src/video/scx_reader.cpp deleted file mode 100644 index 6baa97f9..00000000 --- a/supergameboy/libgambatte/src/video/scx_reader.cpp +++ /dev/null @@ -1,71 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aam�s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "scx_reader.h" - -#include "../event_queue.h" -#include "m3_extra_cycles.h" -#include "../savestate.h" - -ScxReader::ScxReader(event_queue &m3EventQueue_in, -// VideoEvent &wyReader3_in, - VideoEvent &wxReader_in, - VideoEvent &weEnableChecker_in, - VideoEvent &weDisableChecker_in, - M3ExtraCycles &m3ExtraCycles) : - VideoEvent(1), - m3EventQueue(m3EventQueue_in), -// wyReader3(wyReader3_in), - wxReader(wxReader_in), - weEnableChecker(weEnableChecker_in), - weDisableChecker(weDisableChecker_in), - m3ExtraCycles(m3ExtraCycles) -{ - setDoubleSpeed(false); - setSource(0); - scxAnd7_ = src; -} - -static void rescheduleEvent(event_queue &m3EventQueue, VideoEvent& event, const unsigned long diff) { - if (event.time() != VideoEvent::DISABLED_TIME) { - event.setTime(event.time() + diff); - (diff & 0x10) ? m3EventQueue.dec(&event, &event) : m3EventQueue.inc(&event, &event); - } -} - -void ScxReader::doEvent() { - const unsigned long diff = (static_cast(src) - static_cast(scxAnd7_)) << dS; - scxAnd7_ = src; - -// rescheduleEvent(m3EventQueue, wyReader3, diff); - rescheduleEvent(m3EventQueue, wxReader, diff); - rescheduleEvent(m3EventQueue, weEnableChecker, diff); - rescheduleEvent(m3EventQueue, weDisableChecker, diff); - - m3ExtraCycles.invalidateCache(); - - setTime(DISABLED_TIME); -} - -void ScxReader::saveState(SaveState &state) const { - state.ppu.scxAnd7 = scxAnd7_; -} - -void ScxReader::loadState(const SaveState &state) { - scxAnd7_ = state.ppu.scxAnd7; -} diff --git a/supergameboy/libgambatte/src/video/scx_reader.h b/supergameboy/libgambatte/src/video/scx_reader.h deleted file mode 100644 index f92f8b2b..00000000 --- a/supergameboy/libgambatte/src/video/scx_reader.h +++ /dev/null @@ -1,85 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef SCX_READER_H -#define SCX_READER_H - -template class event_queue; -class M3ExtraCycles; -class SaveState; - -#include "video_event.h" -#include "video_event_comparer.h" -#include "ly_counter.h" -#include "basic_add_event.h" - -class ScxReader : public VideoEvent { - event_queue &m3EventQueue; -// VideoEvent &wyReader3; - VideoEvent &wxReader; - VideoEvent &weEnableChecker; - VideoEvent &weDisableChecker; - M3ExtraCycles &m3ExtraCycles; - - unsigned char scxAnd7_; - unsigned char src; - bool dS; - -public: - ScxReader(event_queue &m3EventQueue_in, -// VideoEvent &wyReader3_in, - VideoEvent &wxReader_in, - VideoEvent &weEnableChecker_in, - VideoEvent &weDisableChecker_in, - M3ExtraCycles &m3ExtraCycles); - - void doEvent(); - - unsigned getSource() const { - return src; - } - - static unsigned long schedule(const LyCounter &lyCounter, const unsigned long cycleCounter) { - return lyCounter.nextLineCycle(82 + lyCounter.isDoubleSpeed() * 3, cycleCounter); - } - - unsigned scxAnd7() const { - return scxAnd7_; - } - - void setDoubleSpeed(const bool dS_in) { - dS = dS_in; - } - - void setSource(const unsigned scxSrc) { - src = scxSrc & 7; - } - - void saveState(SaveState &state) const; - void loadState(const SaveState &state); -}; - -static inline void addEvent(event_queue &q, ScxReader *const e, const unsigned long newTime) { - addUnconditionalEvent(q, e, newTime); -} - -static inline void addFixedtimeEvent(event_queue &q, ScxReader *const e, const unsigned long newTime) { - addUnconditionalFixedtimeEvent(q, e, newTime); -} - -#endif diff --git a/supergameboy/libgambatte/src/video/sprite_mapper.cpp b/supergameboy/libgambatte/src/video/sprite_mapper.cpp deleted file mode 100644 index f1e9cd97..00000000 --- a/supergameboy/libgambatte/src/video/sprite_mapper.cpp +++ /dev/null @@ -1,187 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre AamÃ¥s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "sprite_mapper.h" -#include "m3_extra_cycles.h" -#include "../insertion_sort.h" -#include - -#include - -SpriteMapper::OamReader::OamReader(const LyCounter &lyCounter, const unsigned char *oamram) -: lyCounter(lyCounter), oamram(oamram) { - reset(oamram); -} - -void SpriteMapper::OamReader::reset(const unsigned char *const oamram) { - this->oamram = oamram; - setLargeSpritesSrc(false); - lu = 0; - lastChange = 0xFF; - std::fill_n(szbuf, 40, largeSpritesSrc); - - unsigned pos = 0; - unsigned distance = 80; - - while (distance--) { - buf[pos] = oamram[((pos * 2) & ~3) | (pos & 1)]; - ++pos; - } -} - -static unsigned toPosCycles(const unsigned long cc, const LyCounter &lyCounter) { - unsigned lc = lyCounter.lineCycles(cc) + 4 - lyCounter.isDoubleSpeed() * 3u; - - if (lc >= 456) - lc -= 456; - - return lc >> 1; -} - -void SpriteMapper::OamReader::update(const unsigned long cc) { - if (cc > lu) { - if (changed()) { - const unsigned lulc = toPosCycles(lu, lyCounter); - - unsigned pos = std::min(lulc, 40u); - unsigned distance = 40; - - if ((cc - lu) >> lyCounter.isDoubleSpeed() < 456) { - const unsigned cclc = toPosCycles(cc, lyCounter); - - distance = std::min(cclc, 40u) - pos + (cclc < lulc ? 40 : 0); - } - - { - const unsigned targetDistance = lastChange - pos + (lastChange <= pos ? 40 : 0); - - if (targetDistance <= distance) { - distance = targetDistance; - lastChange = 0xFF; - } - } - - while (distance--) { - if (pos >= 40) - pos = 0; - - szbuf[pos] = largeSpritesSrc; - buf[pos * 2] = oamram[pos * 4]; - buf[pos * 2 + 1] = oamram[pos * 4 + 1]; - - ++pos; - } - } - - lu = cc; - } -} - -void SpriteMapper::OamReader::change(const unsigned long cc) { - update(cc); - lastChange = std::min(toPosCycles(lu, lyCounter), 40u); -} - -void SpriteMapper::OamReader::setStatePtrs(SaveState &state) { - state.ppu.oamReaderBuf.set(buf, sizeof buf); - state.ppu.oamReaderSzbuf.set(szbuf, sizeof(szbuf) / sizeof(bool)); -} - -void SpriteMapper::OamReader::enableDisplay(const unsigned long cc) { - std::memset(buf, 0x00, sizeof(buf)); - std::fill(szbuf, szbuf + 40, false); - lu = cc + 160; - lastChange = 40; -} - -bool SpriteMapper::OamReader::oamAccessible(const unsigned long cycleCounter, const M3ExtraCycles &m3ExtraCycles) const { - unsigned ly = lyCounter.ly(); - unsigned lc = lyCounter.lineCycles(cycleCounter) + 4 - lyCounter.isDoubleSpeed() * 3u; - - if (lc >= 456) { - lc -= 456; - ++ly; - } - - return cycleCounter < lu || ly >= 144 || lc >= 80 + 173 + m3ExtraCycles(ly); -} - -SpriteMapper::SpriteMapper(M3ExtraCycles &m3ExtraCycles, - const LyCounter &lyCounter, - const unsigned char *const oamram) : - VideoEvent(2), - m3ExtraCycles(m3ExtraCycles), - oamReader(lyCounter, oamram), - cgb(false) -{ - clearMap(); -} - -void SpriteMapper::reset(const unsigned char *const oamram, const bool cgb_in) { - oamReader.reset(oamram); - cgb = cgb_in; - clearMap(); -} - -void SpriteMapper::clearMap() { - std::memset(num, cgb ? 0 : NEED_SORTING_MASK, sizeof(num)); -} - -void SpriteMapper::mapSprites() { - clearMap(); - - for (unsigned i = 0x00; i < 0x50; i += 2) { - const unsigned spriteHeight = 8u << largeSprites(i >> 1); - const unsigned bottom_pos = posbuf()[i] - (17u - spriteHeight); - - if (bottom_pos >= 143 + spriteHeight) - continue; - - unsigned char *map = spritemap; - unsigned char *n = num; - - if (bottom_pos >= spriteHeight) { - const unsigned startly = bottom_pos + 1 - spriteHeight; - n += startly; - map += startly * 10; - } - - unsigned char *const end = num + (bottom_pos >= 143 ? 143 : bottom_pos); - - do { - if ((*n & ~NEED_SORTING_MASK) < 10) - map[(*n)++ & ~NEED_SORTING_MASK] = i; - - map += 10; - ++n; - } while (n <= end); - } - - m3ExtraCycles.invalidateCache(); -} - -void SpriteMapper::sortLine(const unsigned ly) const { - num[ly] &= ~NEED_SORTING_MASK; - insertionSort(spritemap + ly * 10, spritemap + ly * 10 + num[ly], SpxLess(posbuf())); -} - -void SpriteMapper::doEvent() { - oamReader.update(time()); - mapSprites(); - setTime(oamReader.changed() ? time() + oamReader.lyCounter.lineTime() : static_cast(DISABLED_TIME)); -} diff --git a/supergameboy/libgambatte/src/video/sprite_mapper.h b/supergameboy/libgambatte/src/video/sprite_mapper.h deleted file mode 100644 index 25b8090b..00000000 --- a/supergameboy/libgambatte/src/video/sprite_mapper.h +++ /dev/null @@ -1,148 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aam�s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef SPRITE_MAPPER_H -#define SPRITE_MAPPER_H - -#include "video_event.h" -//#include "video_event_comparer.h" -#include "ly_counter.h" -#include "basic_add_event.h" -#include "../savestate.h" - -class M3ExtraCycles; -class SaveState; - -class SpriteMapper : public VideoEvent { - class OamReader { - unsigned char buf[80]; - bool szbuf[40]; - - public: - const LyCounter &lyCounter; - - private: - const unsigned char *oamram; - unsigned long lu; - unsigned char lastChange; - bool largeSpritesSrc; - - public: - OamReader(const LyCounter &lyCounter, const unsigned char *oamram); - void reset(const unsigned char *oamram); - void change(unsigned long cc); - void change(const unsigned char *oamram, unsigned long cc) { change(cc); this->oamram = oamram; } - bool changed() const { return lastChange != 0xFF; } - bool largeSprites(unsigned spNr) const { return szbuf[spNr]; } - const unsigned char *oam() const { return oamram; } - void resetCycleCounter(const unsigned long oldCc, const unsigned long newCc) { lu = lu + newCc - oldCc; } - void setLargeSpritesSrc(const bool src) { largeSpritesSrc = src; } - void update(unsigned long cc); - const unsigned char *spritePosBuf() const { return buf; } - void setStatePtrs(SaveState &state); - void enableDisplay(unsigned long cc); - void saveState(SaveState &state) const { state.ppu.enableDisplayM0Time = lu; } - void loadState(const SaveState &state) { lu = state.ppu.enableDisplayM0Time; } - void resetVideoState() { change(lu); } - bool oamAccessible(unsigned long cycleCounter, const M3ExtraCycles &m3ExtraCycles) const; - bool inactivePeriodAfterDisplayEnable(const unsigned long cc) const { return cc < lu; } - }; - - enum { NEED_SORTING_MASK = 0x80 }; - -public: - class SpxLess { - const unsigned char *const posbuf_plus1; - - public: - SpxLess(const unsigned char *const posbuf) : posbuf_plus1(posbuf + 1) {} - - bool operator()(const unsigned char l, const unsigned char r) const { - return posbuf_plus1[l] < posbuf_plus1[r]; - } - }; - -private: - mutable unsigned char spritemap[144*10]; - mutable unsigned char num[144]; - - M3ExtraCycles &m3ExtraCycles; - OamReader oamReader; - - bool cgb; - - void clearMap(); - void mapSprites(); - void sortLine(unsigned ly) const; - -public: - SpriteMapper(M3ExtraCycles &m3ExtraCycles, - const LyCounter &lyCounter, - const unsigned char *oamram_in); - void reset(const unsigned char *oamram, bool cgb_in); - void doEvent(); - bool isCgb() const { return cgb; } - bool largeSprites(unsigned spNr) const { return oamReader.largeSprites(spNr); } - unsigned numSprites(const unsigned ly) const { return num[ly] & ~NEED_SORTING_MASK; } - void oamChange(const unsigned long cc) { oamReader.change(cc); } - void oamChange(const unsigned char *oamram, const unsigned long cc) { oamReader.change(oamram, cc); } - const unsigned char *oamram() const { return oamReader.oam(); } - const unsigned char *posbuf() const { return oamReader.spritePosBuf(); } - void preCounterChange(const unsigned long cc) { oamReader.update(cc); } - - void resetCycleCounter(const unsigned long oldCc, const unsigned long newCc) { - oamReader.resetCycleCounter(oldCc, newCc); - } - - static unsigned long schedule(const LyCounter &lyCounter, const unsigned long cycleCounter) { - return lyCounter.nextLineCycle(80, cycleCounter); - } - - void setLargeSpritesSource(const bool src) { oamReader.setLargeSpritesSrc(src); } - - const unsigned char* sprites(const unsigned ly) const { - if (num[ly] & NEED_SORTING_MASK) - sortLine(ly); - - return spritemap + ly * 10; - } - - void setStatePtrs(SaveState &state) { oamReader.setStatePtrs(state); } - void enableDisplay(unsigned long cc) { oamReader.enableDisplay(cc); } - void saveState(SaveState &state) const { oamReader.saveState(state); } - void loadState(const SaveState &state) { oamReader.loadState(state); } - void resetVideoState() { oamReader.resetVideoState(); } - - bool oamAccessible(unsigned long cycleCounter) const { - return oamReader.oamAccessible(cycleCounter, m3ExtraCycles); - } - - bool inactivePeriodAfterDisplayEnable(const unsigned long cc) const { - return oamReader.inactivePeriodAfterDisplayEnable(cc); - } -}; - -static inline void addEvent(event_queue &q, SpriteMapper *const e, const unsigned long newTime) { - addUnconditionalEvent(q, e, newTime); -} - -static inline void addFixedtimeEvent(event_queue &q, SpriteMapper *const e, const unsigned long newTime) { - addUnconditionalFixedtimeEvent(q, e, newTime); -} - -#endif diff --git a/supergameboy/libgambatte/src/video/video_event.h b/supergameboy/libgambatte/src/video/video_event.h deleted file mode 100644 index fb64d5b2..00000000 --- a/supergameboy/libgambatte/src/video/video_event.h +++ /dev/null @@ -1,50 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef VIDEO_EVENT_H -#define VIDEO_EVENT_H - -class VideoEvent { - unsigned long time_; - const unsigned char priority_; - -public: - enum { DISABLED_TIME = 0xFFFFFFFFu }; - - VideoEvent(const unsigned priority_in) : - time_(DISABLED_TIME), - priority_(priority_in) - {} - - virtual ~VideoEvent() {} - virtual void doEvent() = 0; - - unsigned priority() const { - return priority_; - } - - unsigned long time() const { - return time_; - } - - void setTime(const unsigned long time_in) { - time_ = time_in; - } -}; - -#endif diff --git a/supergameboy/libgambatte/src/video/video_event_comparer.h b/supergameboy/libgambatte/src/video/video_event_comparer.h deleted file mode 100644 index 4eb25969..00000000 --- a/supergameboy/libgambatte/src/video/video_event_comparer.h +++ /dev/null @@ -1,31 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef VIDEO_EVENT_COMPARER_H -#define VIDEO_EVENT_COMPARER_H - -#include "video_event.h" - -class VideoEventComparer { -public: - bool less(const VideoEvent *const a, const VideoEvent *const b) const { - return a->time() < b->time() || (a->time() == b->time() && a->priority() < b->priority()); - } -}; - -#endif diff --git a/supergameboy/libgambatte/src/video/we.cpp b/supergameboy/libgambatte/src/video/we.cpp deleted file mode 100644 index d5e66c47..00000000 --- a/supergameboy/libgambatte/src/video/we.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "we.h" -#include "../savestate.h" - -We::WeEnableChecker::WeEnableChecker(We &we) : - VideoEvent(8), - we(we) -{} - -void We::WeEnableChecker::doEvent() { - we.set(we.src_); - - setTime(DISABLED_TIME); -} - -We::WeDisableChecker::WeDisableChecker(We &we) : - VideoEvent(9), - we(we) -{} - -void We::WeDisableChecker::doEvent() { - we.set(we.we_ & we.src_); - - setTime(DISABLED_TIME); -} - -We::We(M3ExtraCycles &m3ExtraCycles) : - m3ExtraCycles_(m3ExtraCycles), - enableChecker_(*this), - disableChecker_(*this) -{ - setSource(false); - we_ = src_; -} - -void We::saveState(SaveState &state) const { - state.ppu.lcdc = (state.ppu.lcdc & ~0x20) | we_ << 5; -} - -void We::loadState(const SaveState &state) { - we_ = state.ppu.lcdc >> 5 & 1; -} diff --git a/supergameboy/libgambatte/src/video/we.h b/supergameboy/libgambatte/src/video/we.h deleted file mode 100644 index d800ca11..00000000 --- a/supergameboy/libgambatte/src/video/we.h +++ /dev/null @@ -1,118 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef WE_H -#define WE_H - -class SaveState; - -#include "video_event.h" -#include "ly_counter.h" -#include "m3_extra_cycles.h" -#include "basic_add_event.h" - -class We { -public: - class WeEnableChecker : public VideoEvent { - We &we; - - public: - WeEnableChecker(We &we); - - void doEvent(); - - static unsigned long schedule(const unsigned scxAnd7, const unsigned wx, const LyCounter &lyCounter, const unsigned long cycleCounter) { - return lyCounter.nextLineCycle(scxAnd7 + 82 + wx + lyCounter.isDoubleSpeed() * 3, cycleCounter); - } - }; - - class WeDisableChecker : public VideoEvent { - We &we; - - public: - WeDisableChecker(We &we); - - void doEvent(); - - static unsigned long schedule(const unsigned scxAnd7, const unsigned wx, const LyCounter &lyCounter, const unsigned long cycleCounter) { - return lyCounter.nextLineCycle(scxAnd7 + 88 + wx + lyCounter.isDoubleSpeed() * 3, cycleCounter); - } - }; - - friend class WeEnableChecker; - friend class WeDisableChecker; - -private: - M3ExtraCycles &m3ExtraCycles_; - WeEnableChecker enableChecker_; - WeDisableChecker disableChecker_; - - bool we_; - bool src_; - - void set(const bool value) { - if (we_ != value) - m3ExtraCycles_.invalidateCache(); - - we_ = value; - } - -public: - We(M3ExtraCycles &m3ExtraCycles); - - WeDisableChecker& disableChecker() { - return disableChecker_; - } - - WeEnableChecker& enableChecker() { - return enableChecker_; - } - - bool getSource() const { - return src_; - } - - void setSource(const bool src) { - src_ = src; - } - - bool value() const { - return we_; - } - - void saveState(SaveState &state) const; - void loadState(const SaveState &state); -}; - -static inline void addEvent(event_queue &q, We::WeEnableChecker *const e, const unsigned long newTime) { - addUnconditionalEvent(q, e, newTime); -} - -static inline void addFixedtimeEvent(event_queue &q, We::WeEnableChecker *const e, const unsigned long newTime) { - addUnconditionalFixedtimeEvent(q, e, newTime); -} - -static inline void addEvent(event_queue &q, We::WeDisableChecker *const e, const unsigned long newTime) { - addUnconditionalEvent(q, e, newTime); -} - -static inline void addFixedtimeEvent(event_queue &q, We::WeDisableChecker *const e, const unsigned long newTime) { - addUnconditionalFixedtimeEvent(q, e, newTime); -} - -#endif diff --git a/supergameboy/libgambatte/src/video/we_master_checker.cpp b/supergameboy/libgambatte/src/video/we_master_checker.cpp deleted file mode 100644 index bff81585..00000000 --- a/supergameboy/libgambatte/src/video/we_master_checker.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "we_master_checker.h" - -#include "event_queue.h" -#include "wy.h" -#include "basic_add_event.h" -#include "../savestate.h" - -WeMasterChecker::WeMasterChecker(event_queue &m3EventQueue_in, - Wy &wy_in, - const LyCounter &lyCounter_in, - M3ExtraCycles &m3ExtraCycles) : - VideoEvent(10), - m3EventQueue(m3EventQueue_in), - wy(wy_in), - lyCounter(lyCounter_in), - m3ExtraCycles(m3ExtraCycles) -{ - weMaster_ = false; -} - -void WeMasterChecker::doEvent() { -// if (wy.value() >= lyCounter.ly()) { - if (!weMaster_ /*&& src */&& wy.value() == lyCounter.ly()) { - wy.weirdAssWeMasterEnableOnWyLineCase(); - addEvent(m3EventQueue, &wy.reader4(), Wy::WyReader4::schedule(lyCounter, time())); - } - - set(true); -// } - - setTime(time() + (70224U << lyCounter.isDoubleSpeed())); -} - -void WeMasterChecker::saveState(SaveState &state) const { - state.ppu.weMaster = weMaster_; -} - -void WeMasterChecker::loadState(const SaveState &state) { - weMaster_ = state.ppu.weMaster; -} diff --git a/supergameboy/libgambatte/src/video/we_master_checker.h b/supergameboy/libgambatte/src/video/we_master_checker.h deleted file mode 100644 index cf1f1209..00000000 --- a/supergameboy/libgambatte/src/video/we_master_checker.h +++ /dev/null @@ -1,73 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef WE_MASTER_CHECKER_H -#define WE_MASTER_CHECKER_H - -template class event_queue; -class Wy; -class SaveState; - -#include "video_event.h" -#include "video_event_comparer.h" -#include "ly_counter.h" -#include "m3_extra_cycles.h" - -class WeMasterChecker : public VideoEvent { - event_queue &m3EventQueue; - Wy &wy; - const LyCounter &lyCounter; - M3ExtraCycles &m3ExtraCycles; - - bool weMaster_; - - void set(const bool value) { - if (weMaster_ != value) - m3ExtraCycles.invalidateCache(); - - weMaster_ = value; - } - -public: - WeMasterChecker(event_queue &m3EventQueue_in, - Wy &wy_in, - const LyCounter &lyCounter_in, - M3ExtraCycles &m3ExtraCycles); - - void doEvent(); - - static unsigned long schedule(const unsigned wySrc, const bool weSrc, const LyCounter &lyCounter, const unsigned long cycleCounter) { - if (weSrc && wySrc < 143) - return lyCounter.nextFrameCycle(wySrc * 456ul + 448 + lyCounter.isDoubleSpeed() * 4, cycleCounter); - else - return DISABLED_TIME; - } - - void unset() { - set(false); - } - - bool weMaster() const { - return weMaster_; - } - - void saveState(SaveState &state) const; - void loadState(const SaveState &state); -}; - -#endif diff --git a/supergameboy/libgambatte/src/video/window.h b/supergameboy/libgambatte/src/video/window.h deleted file mode 100644 index 790d612c..00000000 --- a/supergameboy/libgambatte/src/video/window.h +++ /dev/null @@ -1,47 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef WINDOW_H -#define WINDOW_H - -#include "we.h" -#include "we_master_checker.h" -#include "wy.h" -#include "wx_reader.h" - -struct Window { - We we; - WeMasterChecker weMasterChecker; - Wy wyReg; - WxReader wxReader; - - Window(event_queue &m3EventQueue, - const LyCounter &lyCounter, - M3ExtraCycles &m3ExtraCycles) : - we(m3ExtraCycles), - weMasterChecker(m3EventQueue, wyReg, lyCounter, m3ExtraCycles), - wyReg(lyCounter, weMasterChecker, m3ExtraCycles), - wxReader(m3EventQueue, we.enableChecker(), we.disableChecker(), m3ExtraCycles) - {} - - bool enabled(const unsigned ly) const { - return we.value() && wxReader.wx() < 0xA7 && ly >= wyReg.value() && (weMasterChecker.weMaster() || ly == wyReg.value()); - } -}; - -#endif /*WINDOW_H*/ diff --git a/supergameboy/libgambatte/src/video/wx_reader.cpp b/supergameboy/libgambatte/src/video/wx_reader.cpp deleted file mode 100644 index 80a6b640..00000000 --- a/supergameboy/libgambatte/src/video/wx_reader.cpp +++ /dev/null @@ -1,65 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aam�s * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "wx_reader.h" - -#include "../event_queue.h" -#include "m3_extra_cycles.h" -#include "../savestate.h" - -WxReader::WxReader(event_queue &m3EventQueue, - VideoEvent &weEnableChecker, - VideoEvent &weDisableChecker, - M3ExtraCycles &m3ExtraCycles) : -VideoEvent(7), -m3EventQueue(m3EventQueue), -weEnableChecker(weEnableChecker), -weDisableChecker(weDisableChecker), -m3ExtraCycles(m3ExtraCycles) -{ - setDoubleSpeed(false); - setSource(0); - wx_ = src_; -} - -static void rescheduleEvent(event_queue &m3EventQueue, VideoEvent& event, const unsigned long diff) { - if (event.time() != VideoEvent::DISABLED_TIME) { - event.setTime(event.time() + diff); - (diff & 0x200) ? m3EventQueue.dec(&event, &event) : m3EventQueue.inc(&event, &event); - } -} - -void WxReader::doEvent() { - const unsigned long diff = (static_cast(src_) - static_cast(wx_)) << dS; - wx_ = src_; - - rescheduleEvent(m3EventQueue, weEnableChecker, diff); - rescheduleEvent(m3EventQueue, weDisableChecker, diff); - - m3ExtraCycles.invalidateCache(); - - setTime(DISABLED_TIME); -} - -void WxReader::saveState(SaveState &state) const { - state.ppu.wx = wx_; -} - -void WxReader::loadState(const SaveState &state) { - wx_ = state.ppu.wx; -} diff --git a/supergameboy/libgambatte/src/video/wx_reader.h b/supergameboy/libgambatte/src/video/wx_reader.h deleted file mode 100644 index 1681f8a4..00000000 --- a/supergameboy/libgambatte/src/video/wx_reader.h +++ /dev/null @@ -1,83 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef WX_READER_H -#define WX_READER_H - -template class event_queue; -class M3ExtraCycles; -class SaveState; - -#include "video_event.h" -#include "video_event_comparer.h" -#include "ly_counter.h" -#include "basic_add_event.h" -#include - -class WxReader : public VideoEvent { - event_queue &m3EventQueue; - VideoEvent &weEnableChecker; - VideoEvent &weDisableChecker; - M3ExtraCycles &m3ExtraCycles; - - unsigned char wx_; - unsigned char src_; - bool dS; - -public: - WxReader(event_queue &m3EventQueue_in, - VideoEvent &weEnableChecker_in, - VideoEvent &weDisableChecker_in, - M3ExtraCycles &m3ExtraCycles); - - void doEvent(); - - unsigned getSource() const { - return src_; - } - - unsigned wx() const { - return wx_; - } - - void setDoubleSpeed(const bool dS_in) { - dS = dS_in; - } - - void setSource(const unsigned src) { - src_ = src; - } - - static unsigned long schedule(const unsigned scxAnd7, const LyCounter &lyCounter, const WxReader &wxReader, const unsigned long cycleCounter) { - return lyCounter.nextLineCycle(scxAnd7 + 82 + lyCounter.isDoubleSpeed() * 3 + std::min(wxReader.getSource(), wxReader.wx()), cycleCounter); - //setTime(lyCounter.nextLineCycle(scxAnd7 + 89 + lyCounter.isDoubleSpeed() * 3, cycleCounter)); - } - - void saveState(SaveState &state) const; - void loadState(const SaveState &state); -}; - -static inline void addEvent(event_queue &q, WxReader *const e, const unsigned long newTime) { - addUnconditionalEvent(q, e, newTime); -} - -static inline void addFixedtimeEvent(event_queue &q, WxReader *const e, const unsigned long newTime) { - addUnconditionalFixedtimeEvent(q, e, newTime); -} - -#endif diff --git a/supergameboy/libgambatte/src/video/wy.cpp b/supergameboy/libgambatte/src/video/wy.cpp deleted file mode 100644 index 64a5f725..00000000 --- a/supergameboy/libgambatte/src/video/wy.cpp +++ /dev/null @@ -1,105 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#include "wy.h" - -#include "we_master_checker.h" -#include "scx_reader.h" -#include "../event_queue.h" -#include "../savestate.h" - -Wy::WyReader1::WyReader1(Wy &wy, const WeMasterChecker &weMasterChecker) : - VideoEvent(3), - wy(wy), - weMasterChecker(weMasterChecker) -{} - -void Wy::WyReader1::doEvent() { - if (wy.src_ >= wy.lyCounter.ly() && /*wy >= lyCounter.ly()*/ !weMasterChecker.weMaster()) - wy.set(wy.src_); - - setTime(DISABLED_TIME); -} - -Wy::WyReader2::WyReader2(Wy &wy) : - VideoEvent(4), - wy(wy) -{} - -void Wy::WyReader2::doEvent() { - if (wy.wy_ == wy.lyCounter.ly() + 1 - wy.lyCounter.isDoubleSpeed() && wy.src_ > wy.wy_) - wy.set(wy.src_); - - setTime(DISABLED_TIME); -} - -Wy::WyReader3::WyReader3(Wy &wy) : - VideoEvent(5), - wy(wy) -{} - -void Wy::WyReader3::doEvent() { - if (wy.src_ == wy.lyCounter.ly() && wy.wy_ > wy.lyCounter.ly()) - wy.set(wy.src_); - - setTime(DISABLED_TIME); -} - -unsigned long Wy::WyReader3::schedule(const unsigned wxSrc, const ScxReader &scxReader, const LyCounter &lyCounter, const unsigned long cycleCounter) { - const unsigned curLineCycle = 456 - ((lyCounter.time() - cycleCounter) >> lyCounter.isDoubleSpeed()); - const unsigned baseTime = 78 + lyCounter.isDoubleSpeed() * 6 + wxSrc; - - if (curLineCycle >= 82U + lyCounter.isDoubleSpeed() * 3) { - if (baseTime + scxReader.scxAnd7() > curLineCycle) - return lyCounter.time() + ((baseTime + scxReader.scxAnd7()) << lyCounter.isDoubleSpeed()) - lyCounter.lineTime(); - else - return lyCounter.time() + ((baseTime + scxReader.getSource()) << lyCounter.isDoubleSpeed()); - } else - return lyCounter.nextLineCycle(baseTime + scxReader.getSource(), cycleCounter); -} - -Wy::WyReader4::WyReader4(Wy &wy) : - VideoEvent(6), - wy(wy) -{} - -void Wy::WyReader4::doEvent() { - wy.set(wy.src_); - - setTime(DISABLED_TIME); -} - -Wy::Wy(const LyCounter &lyCounter, const WeMasterChecker &weMasterChecker, M3ExtraCycles &m3ExtraCycles) : - lyCounter(lyCounter), - m3ExtraCycles(m3ExtraCycles), - reader1_(*this, weMasterChecker), - reader2_(*this), - reader3_(*this), - reader4_(*this) -{ - setSource(0); - wy_ = src_; -} - -void Wy::saveState(SaveState &state) const { - state.ppu.wy = wy_; -} - -void Wy::loadState(const SaveState &state) { - wy_ = state.ppu.wy; -} diff --git a/supergameboy/libgambatte/src/video/wy.h b/supergameboy/libgambatte/src/video/wy.h deleted file mode 100644 index 2a1033f9..00000000 --- a/supergameboy/libgambatte/src/video/wy.h +++ /dev/null @@ -1,187 +0,0 @@ -/*************************************************************************** - * Copyright (C) 2007 by Sindre Aamås * - * aamas@stud.ntnu.no * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License version 2 as * - * published by the Free Software Foundation. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License version 2 for more details. * - * * - * You should have received a copy of the GNU General Public License * - * version 2 along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * - ***************************************************************************/ -#ifndef WY_H -#define WY_H - -class WeMasterChecker; -class ScxReader; -template class event_queue; -class SaveState; - -#include "video_event.h" -#include "video_event_comparer.h" -#include "ly_counter.h" -#include "m3_extra_cycles.h" -#include "basic_add_event.h" - -class Wy { -public: - class WyReader1 : public VideoEvent { - Wy &wy; - const WeMasterChecker &weMasterChecker; - - public: - WyReader1(Wy &wy, const WeMasterChecker &weMasterChecker); - - void doEvent(); - - static unsigned long schedule(const LyCounter &lyCounter, const unsigned long cycleCounter) { - return lyCounter.nextLineCycle(448 + lyCounter.isDoubleSpeed() * 4, cycleCounter); - } - }; - - class WyReader2 : public VideoEvent { - Wy &wy; - - public: - WyReader2(Wy &wy); - - void doEvent(); - - static unsigned long schedule(const LyCounter &lyCounter, const unsigned long cycleCounter) { - return lyCounter.isDoubleSpeed() ? lyCounter.time() : lyCounter.nextLineCycle(452, cycleCounter); - } - }; - - class WyReader3 : public VideoEvent { - Wy &wy; - - public: - WyReader3(Wy &wy); - - void doEvent(); - static unsigned long schedule(unsigned wxSrc, const ScxReader &scxReader, const LyCounter &lyCounter, unsigned long cycleCounter); - - //void schedule(const unsigned scxAnd7, const LyCounter &lyCounter, const unsigned cycleCounter) { - // setTime(lyCounter.nextLineCycle(scxAnd7 + 85 + lyCounter.isDoubleSpeed() * 6, cycleCounter)); - //} - }; - - class WyReader4 : public VideoEvent { - Wy &wy; - - public: - WyReader4(Wy &wy); - - void doEvent(); - - static unsigned long schedule(const LyCounter &lyCounter, const unsigned long cycleCounter) { - return lyCounter.nextFrameCycle(lyCounter.isDoubleSpeed() * 4, cycleCounter); - } - }; - - friend class WyReader1; - friend class WyReader2; - friend class WyReader3; - friend class WyReader4; - -private: - const LyCounter &lyCounter; - M3ExtraCycles &m3ExtraCycles; - WyReader1 reader1_; - WyReader2 reader2_; - WyReader3 reader3_; - WyReader4 reader4_; - - unsigned char wy_; - unsigned char src_; - - void set(const unsigned char value) { - if (wy_ != value) - m3ExtraCycles.invalidateCache(); - - wy_ = value; - } - -public: - Wy(const LyCounter &lyCounter, const WeMasterChecker &weMasterChecker, M3ExtraCycles &m3ExtraCycles); - - WyReader1& reader1() { - return reader1_; - } - - WyReader2& reader2() { - return reader2_; - } - - WyReader3& reader3() { - return reader3_; - } - - WyReader4& reader4() { - return reader4_; - } - - unsigned getSource() const { - return src_; - } - - void setSource(const unsigned src) { - src_ = src; - } - - //void setValue(const unsigned val) { - // wy_ = val; - //} - - unsigned value() const { - return wy_; - } - - void weirdAssWeMasterEnableOnWyLineCase() { - set(wy_ + 1); - } - - void saveState(SaveState &state) const; - void loadState(const SaveState &state); -}; - -static inline void addEvent(event_queue &q, Wy::WyReader1 *const e, const unsigned long newTime) { - addUnconditionalEvent(q, e, newTime); -} - -static inline void addFixedtimeEvent(event_queue &q, Wy::WyReader1 *const e, const unsigned long newTime) { - addUnconditionalFixedtimeEvent(q, e, newTime); -} - -static inline void addEvent(event_queue &q, Wy::WyReader2 *const e, const unsigned long newTime) { - addUnconditionalEvent(q, e, newTime); -} - -static inline void addFixedtimeEvent(event_queue &q, Wy::WyReader2 *const e, const unsigned long newTime) { - addUnconditionalFixedtimeEvent(q, e, newTime); -} - -static inline void addEvent(event_queue &q, Wy::WyReader3 *const e, const unsigned long newTime) { - addUnconditionalEvent(q, e, newTime); -} - -static inline void addFixedtimeEvent(event_queue &q, Wy::WyReader3 *const e, const unsigned long newTime) { - addUnconditionalFixedtimeEvent(q, e, newTime); -} - -static inline void addEvent(event_queue &q, Wy::WyReader4 *const e, const unsigned long newTime) { - addUnconditionalEvent(q, e, newTime); -} - -static inline void addFixedtimeEvent(event_queue &q, Wy::WyReader4 *const e, const unsigned long newTime) { - addUnconditionalFixedtimeEvent(q, e, newTime); -} - -#endif diff --git a/supergameboy/nall/Makefile b/supergameboy/nall/Makefile deleted file mode 100644 index 8149bf15..00000000 --- a/supergameboy/nall/Makefile +++ /dev/null @@ -1,107 +0,0 @@ -# Makefile -# author: byuu -# license: public domain - -[A-Z] = A B C D E F G H I J K L M N O P Q R S T U V W X Y Z -[a-z] = a b c d e f g h i j k l m n o p q r s t u v w x y z -[0-9] = 0 1 2 3 4 5 6 7 8 9 -[markup] = ` ~ ! @ \# $$ % ^ & * ( ) - _ = + [ { ] } \ | ; : ' " , < . > / ? -[all] = $([A-Z]) $([a-z]) $([0-9]) $([markup]) -[space] := -[space] += - -##### -# platform detection -##### - -ifeq ($(platform),) - uname := $(shell uname -a) - ifeq ($(uname),) - platform := win - delete = del $(subst /,\,$1) - else ifneq ($(findstring Darwin,$(uname)),) - platform := osx - delete = rm -f $1 - else - platform := x - delete = rm -f $1 - endif -endif - -ifeq ($(compiler),) - ifeq ($(platform),osx) - compiler := gcc-4.2 - else - compiler := gcc - endif -endif - -ifeq ($(prefix),) - prefix := /usr/local -endif - -##### -# function rwildcard(directory, pattern) -##### -rwildcard = \ - $(strip \ - $(filter $(if $2,$2,%), \ - $(foreach f, \ - $(wildcard $1*), \ - $(eval t = $(call rwildcard,$f/)) \ - $(if $t,$t,$f) \ - ) \ - ) \ - ) - -##### -# function strtr(source, from, to) -##### -strtr = \ - $(eval __temp := $1) \ - $(strip \ - $(foreach c, \ - $(join $(addsuffix :,$2),$3), \ - $(eval __temp := \ - $(subst $(word 1,$(subst :, ,$c)),$(word 2,$(subst :, ,$c)),$(__temp)) \ - ) \ - ) \ - $(__temp) \ - ) - -##### -# function strupper(source) -##### -strupper = $(call strtr,$1,$([a-z]),$([A-Z])) - -##### -# function strlower(source) -##### -strlower = $(call strtr,$1,$([A-Z]),$([a-z])) - -##### -# function strlen(source) -##### -strlen = \ - $(eval __temp := $(subst $([space]),_,$1)) \ - $(words \ - $(strip \ - $(foreach c, \ - $([all]), \ - $(eval __temp := \ - $(subst $c,$c ,$(__temp)) \ - ) \ - ) \ - $(__temp) \ - ) \ - ) - -##### -# function streq(source) -##### -streq = $(if $(filter-out xx,x$(subst $1,,$2)$(subst $2,,$1)x),,1) - -##### -# function strne(source) -##### -strne = $(if $(filter-out xx,x$(subst $1,,$2)$(subst $2,,$1)x),1,) diff --git a/supergameboy/nall/algorithm.hpp b/supergameboy/nall/algorithm.hpp deleted file mode 100644 index cdc48dcf..00000000 --- a/supergameboy/nall/algorithm.hpp +++ /dev/null @@ -1,23 +0,0 @@ -#ifndef NALL_ALGORITHM_HPP -#define NALL_ALGORITHM_HPP - -#undef min -#undef max - -namespace nall { - template T min(const T &t, const U &u) { - return t < u ? t : u; - } - - template T max(const T &t, const U &u) { - return t > u ? t : u; - } - - //pseudo-random number generator - inline unsigned prng() { - static unsigned n = 0; - return n = (n >> 1) ^ (((n & 1) - 1) & 0xedb88320); - } -} - -#endif diff --git a/supergameboy/nall/any.hpp b/supergameboy/nall/any.hpp deleted file mode 100644 index b31cff3c..00000000 --- a/supergameboy/nall/any.hpp +++ /dev/null @@ -1,74 +0,0 @@ -#ifndef NALL_ANY_HPP -#define NALL_ANY_HPP - -#include -#include -#include - -namespace nall { - class any { - public: - bool empty() const { return container; } - const std::type_info& type() const { return container ? container->type() : typeid(void); } - - template any& operator=(const T& value_) { - typedef typename static_if< - std::is_array::value, - typename std::remove_extent::type>::type*, - T - >::type auto_t; - - if(type() == typeid(auto_t)) { - static_cast*>(container)->value = (auto_t)value_; - } else { - if(container) delete container; - container = new holder((auto_t)value_); - } - - return *this; - } - - any() : container(0) {} - template any(const T& value_) : container(0) { operator=(value_); } - - private: - struct placeholder { - virtual const std::type_info& type() const = 0; - } *container; - - template struct holder : placeholder { - T value; - const std::type_info& type() const { return typeid(T); } - holder(const T& value_) : value(value_) {} - }; - - template friend T any_cast(any&); - template friend T any_cast(const any&); - template friend T* any_cast(any*); - template friend const T* any_cast(const any*); - }; - - template T any_cast(any &value) { - typedef typename std::remove_reference::type nonref; - if(value.type() != typeid(nonref)) throw; - return static_cast*>(value.container)->value; - } - - template T any_cast(const any &value) { - typedef const typename std::remove_reference::type nonref; - if(value.type() != typeid(nonref)) throw; - return static_cast*>(value.container)->value; - } - - template T* any_cast(any *value) { - if(!value || value->type() != typeid(T)) return 0; - return &static_cast*>(value->container)->value; - } - - template const T* any_cast(const any *value) { - if(!value || value->type() != typeid(T)) return 0; - return &static_cast*>(value->container)->value; - } -} - -#endif diff --git a/supergameboy/nall/array.hpp b/supergameboy/nall/array.hpp deleted file mode 100644 index c1d33fd1..00000000 --- a/supergameboy/nall/array.hpp +++ /dev/null @@ -1,120 +0,0 @@ -#ifndef NALL_ARRAY_HPP -#define NALL_ARRAY_HPP - -#include -#include -#include -#include -#include -#include -#include - -namespace nall { - //dynamic vector array - //neither constructor nor destructor is ever invoked; - //thus, this should only be used for POD objects. - template class array { - protected: - T *pool; - unsigned poolsize, buffersize; - - public: - unsigned size() const { return buffersize; } - unsigned capacity() const { return poolsize; } - - void reset() { - if(pool) free(pool); - pool = 0; - poolsize = 0; - buffersize = 0; - } - - void reserve(unsigned newsize) { - if(newsize == poolsize) return; - - pool = (T*)realloc(pool, newsize * sizeof(T)); - poolsize = newsize; - buffersize = min(buffersize, newsize); - } - - void resize(unsigned newsize) { - if(newsize > poolsize) reserve(bit::round(newsize)); //round reserve size up to power of 2 - buffersize = newsize; - } - - T* get(unsigned minsize = 0) { - if(minsize > buffersize) resize(minsize); - if(minsize > buffersize) throw "array[] out of bounds"; - return pool; - } - - void add(const T data) { - operator[](buffersize) = data; - } - - signed find(const T data) { - for(unsigned i = 0; i < size(); i++) if(pool[i] == data) return i; - return -1; //not found - } - - void clear() { - memset(pool, 0, buffersize * sizeof(T)); - } - - array() : pool(0), poolsize(0), buffersize(0) { - } - - array(std::initializer_list list) : pool(0), poolsize(0), buffersize(0) { - for(const T *p = list.begin(); p != list.end(); ++p) add(*p); - } - - ~array() { - reset(); - } - - //copy - array& operator=(const array &source) { - if(pool) free(pool); - buffersize = source.buffersize; - poolsize = source.poolsize; - pool = (T*)malloc(sizeof(T) * poolsize); //allocate entire pool size, - memcpy(pool, source.pool, sizeof(T) * buffersize); //... but only copy used pool objects - return *this; - } - - array(const array &source) : pool(0), poolsize(0), buffersize(0) { - operator=(source); - } - - //move - array& operator=(array &&source) { - if(pool) free(pool); - pool = source.pool; - poolsize = source.poolsize; - buffersize = source.buffersize; - source.pool = 0; - source.reset(); - return *this; - } - - array(array &&source) : pool(0), poolsize(0), buffersize(0) { - operator=(std::move(source)); - } - - //index - inline T& operator[](unsigned index) { - if(index >= buffersize) resize(index + 1); - if(index >= buffersize) throw "array[] out of bounds"; - return pool[index]; - } - - inline const T& operator[](unsigned index) const { - if(index >= buffersize) throw "array[] out of bounds"; - return pool[index]; - } - }; - - template struct has_size> { enum { value = true }; }; -} - -#endif diff --git a/supergameboy/nall/base64.hpp b/supergameboy/nall/base64.hpp deleted file mode 100644 index e41c87b7..00000000 --- a/supergameboy/nall/base64.hpp +++ /dev/null @@ -1,90 +0,0 @@ -#ifndef NALL_BASE64_HPP -#define NALL_BASE64_HPP - -#include -#include - -namespace nall { - class base64 { - public: - static bool encode(char *&output, const uint8_t* input, unsigned inlength) { - output = new char[inlength * 8 / 6 + 6](); - - unsigned i = 0, o = 0; - while(i < inlength) { - switch(i % 3) { - case 0: { - output[o++] = enc(input[i] >> 2); - output[o] = enc((input[i] & 3) << 4); - } break; - - case 1: { - uint8_t prev = dec(output[o]); - output[o++] = enc(prev + (input[i] >> 4)); - output[o] = enc((input[i] & 15) << 2); - } break; - - case 2: { - uint8_t prev = dec(output[o]); - output[o++] = enc(prev + (input[i] >> 6)); - output[o++] = enc(input[i] & 63); - } break; - } - - i++; - } - - return true; - } - - static bool decode(uint8_t *&output, unsigned &outlength, const char *input) { - unsigned inlength = strlen(input), infix = 0; - output = new uint8_t[inlength](); - - unsigned i = 0, o = 0; - while(i < inlength) { - uint8_t x = dec(input[i]); - - switch(i++ & 3) { - case 0: { - output[o] = x << 2; - } break; - - case 1: { - output[o++] |= x >> 4; - output[o] = (x & 15) << 4; - } break; - - case 2: { - output[o++] |= x >> 2; - output[o] = (x & 3) << 6; - } break; - - case 3: { - output[o++] |= x; - } break; - } - } - - outlength = o; - return true; - } - - private: - static char enc(uint8_t n) { - static char lookup_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; - return lookup_table[n & 63]; - } - - static uint8_t dec(char n) { - if(n >= 'A' && n <= 'Z') return n - 'A'; - if(n >= 'a' && n <= 'z') return n - 'a' + 26; - if(n >= '0' && n <= '9') return n - '0' + 52; - if(n == '-') return 62; - if(n == '_') return 63; - return 0; - } - }; -} - -#endif diff --git a/supergameboy/nall/bit.hpp b/supergameboy/nall/bit.hpp deleted file mode 100644 index 169fc144..00000000 --- a/supergameboy/nall/bit.hpp +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef NALL_BIT_HPP -#define NALL_BIT_HPP - -namespace nall { - template inline unsigned uclamp(const unsigned x) { - enum { y = (1U << bits) - 1 }; - return y + ((x - y) & -(x < y)); //min(x, y); - } - - template inline unsigned uclip(const unsigned x) { - enum { m = (1U << bits) - 1 }; - return (x & m); - } - - template inline signed sclamp(const signed x) { - enum { b = 1U << (bits - 1), m = (1U << (bits - 1)) - 1 }; - return (x > m) ? m : (x < -b) ? -b : x; - } - - template inline signed sclip(const signed x) { - enum { b = 1U << (bits - 1), m = (1U << bits) - 1 }; - return ((x & m) ^ b) - b; - } - - namespace bit { - //lowest(0b1110) == 0b0010 - template inline T lowest(const T x) { - return x & -x; - } - - //clear_lowest(0b1110) == 0b1100 - template inline T clear_lowest(const T x) { - return x & (x - 1); - } - - //set_lowest(0b0101) == 0b0111 - template inline T set_lowest(const T x) { - return x | (x + 1); - } - - //round up to next highest single bit: - //round(15) == 16, round(16) == 16, round(17) == 32 - inline unsigned round(unsigned x) { - if((x & (x - 1)) == 0) return x; - while(x & (x - 1)) x &= x - 1; - return x << 1; - } - } -} - -#endif diff --git a/supergameboy/nall/concept.hpp b/supergameboy/nall/concept.hpp deleted file mode 100644 index 2949cd5e..00000000 --- a/supergameboy/nall/concept.hpp +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef NALL_CONCEPT_HPP -#define NALL_CONCEPT_HPP - -namespace nall { - //unsigned count() const; - template struct has_count { enum { value = false }; }; - - //unsigned length() const; - template struct has_length { enum { value = false }; }; - - //unsigned size() const; - template struct has_size { enum { value = false }; }; -} - -#endif diff --git a/supergameboy/nall/config.hpp b/supergameboy/nall/config.hpp deleted file mode 100644 index 31ae4e00..00000000 --- a/supergameboy/nall/config.hpp +++ /dev/null @@ -1,124 +0,0 @@ -#ifndef NALL_CONFIG_HPP -#define NALL_CONFIG_HPP - -#include -#include -#include - -namespace nall { - namespace configuration_traits { - template struct is_boolean { enum { value = false }; }; - template<> struct is_boolean { enum { value = true }; }; - - template struct is_signed { enum { value = false }; }; - template<> struct is_signed { enum { value = true }; }; - - template struct is_unsigned { enum { value = false }; }; - template<> struct is_unsigned { enum { value = true }; }; - - template struct is_double { enum { value = false }; }; - template<> struct is_double { enum { value = true }; }; - - template struct is_string { enum { value = false }; }; - template<> struct is_string { enum { value = true }; }; - } - - class configuration { - public: - enum type_t { boolean_t, signed_t, unsigned_t, double_t, string_t, unknown_t }; - struct item_t { - uintptr_t data; - string name; - string desc; - type_t type; - - string get() const { - switch(type) { - case boolean_t: return string() << *(bool*)data; - case signed_t: return string() << *(signed*)data; - case unsigned_t: return string() << *(unsigned*)data; - case double_t: return string() << *(double*)data; - case string_t: return string() << "\"" << *(string*)data << "\""; - } - return "???"; - } - - void set(string s) { - switch(type) { - case boolean_t: *(bool*)data = (s == "true"); break; - case signed_t: *(signed*)data = strsigned(s); break; - case unsigned_t: *(unsigned*)data = strunsigned(s); break; - case double_t: *(double*)data = strdouble(s); break; - case string_t: trim(s, "\""); *(string*)data = s; break; - } - } - }; - linear_vector list; - - template - void attach(T &data, const char *name, const char *desc = "") { - unsigned n = list.size(); - list[n].data = (uintptr_t)&data; - list[n].name = name; - list[n].desc = desc; - - if(configuration_traits::is_boolean::value) list[n].type = boolean_t; - else if(configuration_traits::is_signed::value) list[n].type = signed_t; - else if(configuration_traits::is_unsigned::value) list[n].type = unsigned_t; - else if(configuration_traits::is_double::value) list[n].type = double_t; - else if(configuration_traits::is_string::value) list[n].type = string_t; - else list[n].type = unknown_t; - } - - virtual bool load(const char *filename) { - string data; - if(data.readfile(filename) == true) { - data.replace("\r", ""); - lstring line; - line.split("\n", data); - - for(unsigned i = 0; i < line.size(); i++) { - int position = qstrpos(line[i], "#"); - if(position >= 0) line[i][position] = 0; - if(qstrpos(line[i], " = ") < 0) continue; - - lstring part; - part.qsplit(" = ", line[i]); - trim(part[0]); - trim(part[1]); - - for(unsigned n = 0; n < list.size(); n++) { - if(part[0] == list[n].name) { - list[n].set(part[1]); - break; - } - } - } - - return true; - } else { - return false; - } - } - - virtual bool save(const char *filename) const { - file fp; - if(fp.open(filename, file::mode_write)) { - for(unsigned i = 0; i < list.size(); i++) { - string output; - output << list[i].name << " = " << list[i].get(); - if(list[i].desc != "") output << " # " << list[i].desc; - output << "\r\n"; - fp.print(output); - } - - fp.close(); - return true; - } else { - return false; - } - } - }; -} - -#endif diff --git a/supergameboy/nall/crc32.hpp b/supergameboy/nall/crc32.hpp deleted file mode 100644 index ad36fbf6..00000000 --- a/supergameboy/nall/crc32.hpp +++ /dev/null @@ -1,66 +0,0 @@ -#ifndef NALL_CRC32_HPP -#define NALL_CRC32_HPP - -#include - -namespace nall { - const uint32_t crc32_table[256] = { - 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, - 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, - 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, - 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, - 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, - 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, - 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, - 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, - 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, - 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, - 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, - 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, - 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, - 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, - 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, - 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, - 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, - 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, - 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, - 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, - 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, - 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, - 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, - 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, - 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, - 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, - 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, - 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, - 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, - 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, - 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, - 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, - 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, - 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, - 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, - 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, - 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, - 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, - 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, - 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, - 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, - 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, - 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d - }; - - inline uint32_t crc32_adjust(uint32_t crc32, uint8_t input) { - return ((crc32 >> 8) & 0x00ffffff) ^ crc32_table[(crc32 ^ input) & 0xff]; - } - - inline uint32_t crc32_calculate(const uint8_t *data, unsigned length) { - uint32_t crc32 = ~0; - for(unsigned i = 0; i < length; i++) { - crc32 = crc32_adjust(crc32, data[i]); - } - return ~crc32; - } -} - -#endif diff --git a/supergameboy/nall/detect.hpp b/supergameboy/nall/detect.hpp deleted file mode 100644 index b4991aaf..00000000 --- a/supergameboy/nall/detect.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef NALL_DETECT_HPP -#define NALL_DETECT_HPP - -/* Compiler detection */ - -#if defined(__GNUC__) - #define COMPILER_GCC -#elif defined(_MSC_VER) - #define COMPILER_VISUALC -#endif - -/* Platform detection */ - -#if defined(_WIN32) - #define PLATFORM_WIN -#elif defined(__APPLE__) - #define PLATFORM_OSX -#elif defined(linux) || defined(__sun__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) - #define PLATFORM_X -#endif - -/* Endian detection */ - -#if defined(__i386__) || defined(__amd64__) || defined(_M_IX86) || defined(_M_AMD64) - #define ARCH_LSB -#elif defined(__powerpc__) || defined(_M_PPC) || defined(__BIG_ENDIAN__) - #define ARCH_MSB -#endif - -#endif diff --git a/supergameboy/nall/dictionary.hpp b/supergameboy/nall/dictionary.hpp deleted file mode 100644 index f14e2095..00000000 --- a/supergameboy/nall/dictionary.hpp +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef NALL_DICTIONARY_HPP -#define NALL_DICTIONARY_HPP - -#include -#include -#include - -namespace nall { - class dictionary { - public: - string operator[](const char *input) { - for(unsigned i = 0; i < index_input.size(); i++) { - if(index_input[i] == input) return index_output[i]; - } - - //no match, use input; remove input identifier, if one exists - if(strbegin(input, "{{")) { - int pos = strpos(input, "}}"); - if(pos >= 0) { - string temp = substr(input, pos + 2); - return temp; - } - } - - return input; - } - - bool import(const char *filename) { - string data; - if(data.readfile(filename) == false) return false; - ltrim_once(data, "\xef\xbb\xbf"); //remove UTF-8 marker, if it exists - data.replace("\r", ""); - - lstring line; - line.split("\n", data); - for(unsigned i = 0; i < line.size(); i++) { - lstring part; - //format: "Input" = "Output" - part.qsplit("=", line[i]); - if(part.size() != 2) continue; - - //remove whitespace - trim(part[0]); - trim(part[1]); - - //remove quotes - trim_once(part[0], "\""); - trim_once(part[1], "\""); - - unsigned n = index_input.size(); - index_input[n] = part[0]; - index_output[n] = part[1]; - } - - return true; - } - - void reset() { - index_input.reset(); - index_output.reset(); - } - - ~dictionary() { - reset(); - } - - dictionary& operator=(const dictionary&) = delete; - dictionary(const dictionary&) = delete; - - protected: - lstring index_input; - lstring index_output; - }; -} - -#endif diff --git a/supergameboy/nall/dl.hpp b/supergameboy/nall/dl.hpp deleted file mode 100644 index 22acf51f..00000000 --- a/supergameboy/nall/dl.hpp +++ /dev/null @@ -1,119 +0,0 @@ -#ifndef NALL_DL_HPP -#define NALL_DL_HPP - -//dynamic linking support - -#include -#include -#include -#include - -#if defined(PLATFORM_X) || defined(PLATFORM_OSX) - #include -#elif defined(PLATFORM_WIN) - #include - #include -#endif - -namespace nall { - struct library { - bool opened() const { return handle; } - bool open(const char*); - void* sym(const char*); - void close(); - - library() : handle(0) {} - ~library() { close(); } - - library& operator=(const library&) = delete; - library(const library&) = delete; - - private: - uintptr_t handle; - }; - - #if defined(PLATFORM_X) - inline bool library::open(const char *name) { - if(handle) close(); - char *t = new char[strlen(name) + 256]; - strcpy(t, "lib"); - strcat(t, name); - strcat(t, ".so"); - handle = (uintptr_t)dlopen(t, RTLD_LAZY); - if(!handle) { - strcpy(t, "/usr/local/lib/lib"); - strcat(t, name); - strcat(t, ".so"); - handle = (uintptr_t)dlopen(t, RTLD_LAZY); - } - delete[] t; - return handle; - } - - inline void* library::sym(const char *name) { - if(!handle) return 0; - return dlsym((void*)handle, name); - } - - inline void library::close() { - if(!handle) return; - dlclose((void*)handle); - handle = 0; - } - #elif defined(PLATFORM_OSX) - inline bool library::open(const char *name) { - if(handle) close(); - char *t = new char[strlen(name) + 256]; - strcpy(t, "lib"); - strcat(t, name); - strcat(t, ".dylib"); - handle = (uintptr_t)dlopen(t, RTLD_LAZY); - if(!handle) { - strcpy(t, "/usr/local/lib/lib"); - strcat(t, name); - strcat(t, ".dylib"); - handle = (uintptr_t)dlopen(t, RTLD_LAZY); - } - delete[] t; - return handle; - } - - inline void* library::sym(const char *name) { - if(!handle) return 0; - return dlsym((void*)handle, name); - } - - inline void library::close() { - if(!handle) return; - dlclose((void*)handle); - handle = 0; - } - #elif defined(PLATFORM_WIN) - inline bool library::open(const char *name) { - if(handle) close(); - char *t = new char[strlen(name) + 8]; - strcpy(t, name); - strcat(t, ".dll"); - handle = (uintptr_t)LoadLibraryW(utf16_t(t)); - delete[] t; - return handle; - } - - inline void* library::sym(const char *name) { - if(!handle) return 0; - return (void*)GetProcAddress((HMODULE)handle, name); - } - - inline void library::close() { - if(!handle) return; - FreeLibrary((HMODULE)handle); - handle = 0; - } - #else - inline bool library::open(const char*) { return false; } - inline void* library::sym(const char*) { return 0; } - inline void library::close() {} - #endif -}; - -#endif diff --git a/supergameboy/nall/endian.hpp b/supergameboy/nall/endian.hpp deleted file mode 100644 index 40d15633..00000000 --- a/supergameboy/nall/endian.hpp +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef NALL_ENDIAN_HPP -#define NALL_ENDIAN_HPP - -#if !defined(ARCH_MSB) - //little-endian: uint8_t[] { 0x01, 0x02, 0x03, 0x04 } == 0x04030201 - #define order_lsb2(a,b) a,b - #define order_lsb3(a,b,c) a,b,c - #define order_lsb4(a,b,c,d) a,b,c,d - #define order_lsb5(a,b,c,d,e) a,b,c,d,e - #define order_lsb6(a,b,c,d,e,f) a,b,c,d,e,f - #define order_lsb7(a,b,c,d,e,f,g) a,b,c,d,e,f,g - #define order_lsb8(a,b,c,d,e,f,g,h) a,b,c,d,e,f,g,h - #define order_msb2(a,b) b,a - #define order_msb3(a,b,c) c,b,a - #define order_msb4(a,b,c,d) d,c,b,a - #define order_msb5(a,b,c,d,e) e,d,c,b,a - #define order_msb6(a,b,c,d,e,f) f,e,d,c,b,a - #define order_msb7(a,b,c,d,e,f,g) g,f,e,d,c,b,a - #define order_msb8(a,b,c,d,e,f,g,h) h,g,f,e,d,c,b,a -#else - //big-endian: uint8_t[] { 0x01, 0x02, 0x03, 0x04 } == 0x01020304 - #define order_lsb2(a,b) b,a - #define order_lsb3(a,b,c) c,b,a - #define order_lsb4(a,b,c,d) d,c,b,a - #define order_lsb5(a,b,c,d,e) e,d,c,b,a - #define order_lsb6(a,b,c,d,e,f) f,e,d,c,b,a - #define order_lsb7(a,b,c,d,e,f,g) g,f,e,d,c,b,a - #define order_lsb8(a,b,c,d,e,f,g,h) h,g,f,e,d,c,b,a - #define order_msb2(a,b) a,b - #define order_msb3(a,b,c) a,b,c - #define order_msb4(a,b,c,d) a,b,c,d - #define order_msb5(a,b,c,d,e) a,b,c,d,e - #define order_msb6(a,b,c,d,e,f) a,b,c,d,e,f - #define order_msb7(a,b,c,d,e,f,g) a,b,c,d,e,f,g - #define order_msb8(a,b,c,d,e,f,g,h) a,b,c,d,e,f,g,h -#endif - -#endif diff --git a/supergameboy/nall/file.hpp b/supergameboy/nall/file.hpp deleted file mode 100644 index 4c8ca8ee..00000000 --- a/supergameboy/nall/file.hpp +++ /dev/null @@ -1,259 +0,0 @@ -#ifndef NALL_FILE_HPP -#define NALL_FILE_HPP - -#include -#include - -#if !defined(_WIN32) - #include -#else - #include -#endif - -#include -#include -#include - -namespace nall { - inline FILE* fopen_utf8(const char *utf8_filename, const char *mode) { - #if !defined(_WIN32) - return fopen(utf8_filename, mode); - #else - return _wfopen(utf16_t(utf8_filename), utf16_t(mode)); - #endif - } - - class file { - public: - enum FileMode { mode_read, mode_write, mode_readwrite, mode_writeread }; - enum SeekMode { seek_absolute, seek_relative }; - - uint8_t read() { - if(!fp) return 0xff; //file not open - if(file_mode == mode_write) return 0xff; //reads not permitted - if(file_offset >= file_size) return 0xff; //cannot read past end of file - buffer_sync(); - return buffer[(file_offset++) & buffer_mask]; - } - - uintmax_t readl(unsigned length = 1) { - uintmax_t data = 0; - for(int i = 0; i < length; i++) { - data |= (uintmax_t)read() << (i << 3); - } - return data; - } - - uintmax_t readm(unsigned length = 1) { - uintmax_t data = 0; - while(length--) { - data <<= 8; - data |= read(); - } - return data; - } - - void read(uint8_t *buffer, unsigned length) { - while(length--) *buffer++ = read(); - } - - void write(uint8_t data) { - if(!fp) return; //file not open - if(file_mode == mode_read) return; //writes not permitted - buffer_sync(); - buffer[(file_offset++) & buffer_mask] = data; - buffer_dirty = true; - if(file_offset > file_size) file_size = file_offset; - } - - void writel(uintmax_t data, unsigned length = 1) { - while(length--) { - write(data); - data >>= 8; - } - } - - void writem(uintmax_t data, unsigned length = 1) { - for(int i = length - 1; i >= 0; i--) { - write(data >> (i << 3)); - } - } - - void write(const uint8_t *buffer, unsigned length) { - while(length--) write(*buffer++); - } - - void print(const char *string) { - if(!string) return; - while(*string) write(*string++); - } - - void flush() { - buffer_flush(); - fflush(fp); - } - - void seek(int offset, SeekMode mode = seek_absolute) { - if(!fp) return; //file not open - buffer_flush(); - - uintmax_t req_offset = file_offset; - switch(mode) { - case seek_absolute: req_offset = offset; break; - case seek_relative: req_offset += offset; break; - } - - if(req_offset < 0) req_offset = 0; //cannot seek before start of file - if(req_offset > file_size) { - if(file_mode == mode_read) { //cannot seek past end of file - req_offset = file_size; - } else { //pad file to requested location - file_offset = file_size; - while(file_size < req_offset) write(0x00); - } - } - - file_offset = req_offset; - } - - int offset() { - if(!fp) return -1; //file not open - return file_offset; - } - - int size() { - if(!fp) return -1; //file not open - return file_size; - } - - bool truncate(unsigned size) { - if(!fp) return false; //file not open - #if !defined(_WIN32) - return ftruncate(fileno(fp), size) == 0; - #else - return _chsize(fileno(fp), size) == 0; - #endif - } - - bool end() { - if(!fp) return true; //file not open - return file_offset >= file_size; - } - - static bool exists(const char *fn) { - #if !defined(_WIN32) - FILE *fp = fopen(fn, "rb"); - #else - FILE *fp = _wfopen(utf16_t(fn), L"rb"); - #endif - if(fp) { - fclose(fp); - return true; - } - return false; - } - - static unsigned size(const char *fn) { - #if !defined(_WIN32) - FILE *fp = fopen(fn, "rb"); - #else - FILE *fp = _wfopen(utf16_t(fn), L"rb"); - #endif - unsigned filesize = 0; - if(fp) { - fseek(fp, 0, SEEK_END); - filesize = ftell(fp); - fclose(fp); - } - return filesize; - } - - bool open() { - return fp; - } - - bool open(const char *fn, FileMode mode) { - if(fp) return false; - - switch(file_mode = mode) { - #if !defined(_WIN32) - case mode_read: fp = fopen(fn, "rb"); break; - case mode_write: fp = fopen(fn, "wb+"); break; //need read permission for buffering - case mode_readwrite: fp = fopen(fn, "rb+"); break; - case mode_writeread: fp = fopen(fn, "wb+"); break; - #else - case mode_read: fp = _wfopen(utf16_t(fn), L"rb"); break; - case mode_write: fp = _wfopen(utf16_t(fn), L"wb+"); break; - case mode_readwrite: fp = _wfopen(utf16_t(fn), L"rb+"); break; - case mode_writeread: fp = _wfopen(utf16_t(fn), L"wb+"); break; - #endif - } - if(!fp) return false; - buffer_offset = -1; //invalidate buffer - file_offset = 0; - fseek(fp, 0, SEEK_END); - file_size = ftell(fp); - fseek(fp, 0, SEEK_SET); - return true; - } - - void close() { - if(!fp) return; - buffer_flush(); - fclose(fp); - fp = 0; - } - - file() { - memset(buffer, 0, sizeof buffer); - buffer_offset = -1; - buffer_dirty = false; - fp = 0; - file_offset = 0; - file_size = 0; - file_mode = mode_read; - } - - ~file() { - close(); - } - - file& operator=(const file&) = delete; - file(const file&) = delete; - - private: - enum { buffer_size = 1 << 12, buffer_mask = buffer_size - 1 }; - char buffer[buffer_size]; - int buffer_offset; - bool buffer_dirty; - FILE *fp; - unsigned file_offset; - unsigned file_size; - FileMode file_mode; - - void buffer_sync() { - if(!fp) return; //file not open - if(buffer_offset != (file_offset & ~buffer_mask)) { - buffer_flush(); - buffer_offset = file_offset & ~buffer_mask; - fseek(fp, buffer_offset, SEEK_SET); - unsigned length = (buffer_offset + buffer_size) <= file_size ? buffer_size : (file_size & buffer_mask); - if(length) unsigned unused = fread(buffer, 1, length, fp); - } - } - - void buffer_flush() { - if(!fp) return; //file not open - if(file_mode == mode_read) return; //buffer cannot be written to - if(buffer_offset < 0) return; //buffer unused - if(buffer_dirty == false) return; //buffer unmodified since read - fseek(fp, buffer_offset, SEEK_SET); - unsigned length = (buffer_offset + buffer_size) <= file_size ? buffer_size : (file_size & buffer_mask); - if(length) unsigned unused = fwrite(buffer, 1, length, fp); - buffer_offset = -1; //invalidate buffer - buffer_dirty = false; - } - }; -} - -#endif diff --git a/supergameboy/nall/filemap.hpp b/supergameboy/nall/filemap.hpp deleted file mode 100644 index a05f0eb7..00000000 --- a/supergameboy/nall/filemap.hpp +++ /dev/null @@ -1,190 +0,0 @@ -#ifndef NALL_FILEMAP_HPP -#define NALL_FILEMAP_HPP - -#include -#include - -#include -#include -#if defined(_WIN32) - #include -#else - #include - #include - #include - #include - #include -#endif - -namespace nall { - class filemap { - public: - enum filemode { mode_read, mode_write, mode_readwrite, mode_writeread }; - - bool open(const char *filename, filemode mode) { return p_open(filename, mode); } - void close() { return p_close(); } - unsigned size() const { return p_size; } - uint8_t* handle() { return p_handle; } - const uint8_t* handle() const { return p_handle; } - filemap() : p_size(0), p_handle(0) { p_ctor(); } - ~filemap() { p_dtor(); } - - private: - unsigned p_size; - uint8_t *p_handle; - - #if defined(_WIN32) - //============= - //MapViewOfFile - //============= - - HANDLE p_filehandle, p_maphandle; - - bool p_open(const char *filename, filemode mode) { - int desired_access, creation_disposition, flprotect, map_access; - - switch(mode) { - default: return false; - case mode_read: - desired_access = GENERIC_READ; - creation_disposition = OPEN_EXISTING; - flprotect = PAGE_READONLY; - map_access = FILE_MAP_READ; - break; - case mode_write: - //write access requires read access - desired_access = GENERIC_WRITE; - creation_disposition = CREATE_ALWAYS; - flprotect = PAGE_READWRITE; - map_access = FILE_MAP_ALL_ACCESS; - break; - case mode_readwrite: - desired_access = GENERIC_READ | GENERIC_WRITE; - creation_disposition = OPEN_EXISTING; - flprotect = PAGE_READWRITE; - map_access = FILE_MAP_ALL_ACCESS; - break; - case mode_writeread: - desired_access = GENERIC_READ | GENERIC_WRITE; - creation_disposition = CREATE_NEW; - flprotect = PAGE_READWRITE; - map_access = FILE_MAP_ALL_ACCESS; - break; - } - - p_filehandle = CreateFileW(utf16_t(filename), desired_access, FILE_SHARE_READ, NULL, - creation_disposition, FILE_ATTRIBUTE_NORMAL, NULL); - if(p_filehandle == INVALID_HANDLE_VALUE) return false; - - p_size = GetFileSize(p_filehandle, NULL); - - p_maphandle = CreateFileMapping(p_filehandle, NULL, flprotect, 0, p_size, NULL); - if(p_maphandle == INVALID_HANDLE_VALUE) { - CloseHandle(p_filehandle); - p_filehandle = INVALID_HANDLE_VALUE; - return false; - } - - p_handle = (uint8_t*)MapViewOfFile(p_maphandle, map_access, 0, 0, p_size); - return p_handle; - } - - void p_close() { - if(p_handle) { - UnmapViewOfFile(p_handle); - p_handle = 0; - } - - if(p_maphandle != INVALID_HANDLE_VALUE) { - CloseHandle(p_maphandle); - p_maphandle = INVALID_HANDLE_VALUE; - } - - if(p_filehandle != INVALID_HANDLE_VALUE) { - CloseHandle(p_filehandle); - p_filehandle = INVALID_HANDLE_VALUE; - } - } - - void p_ctor() { - p_filehandle = INVALID_HANDLE_VALUE; - p_maphandle = INVALID_HANDLE_VALUE; - } - - void p_dtor() { - close(); - } - - #else - //==== - //mmap - //==== - - int p_fd; - - bool p_open(const char *filename, filemode mode) { - int open_flags, mmap_flags; - - switch(mode) { - default: return false; - case mode_read: - open_flags = O_RDONLY; - mmap_flags = PROT_READ; - break; - case mode_write: - open_flags = O_RDWR | O_CREAT; //mmap() requires read access - mmap_flags = PROT_WRITE; - break; - case mode_readwrite: - open_flags = O_RDWR; - mmap_flags = PROT_READ | PROT_WRITE; - break; - case mode_writeread: - open_flags = O_RDWR | O_CREAT; - mmap_flags = PROT_READ | PROT_WRITE; - break; - } - - p_fd = ::open(filename, open_flags); - if(p_fd < 0) return false; - - struct stat p_stat; - fstat(p_fd, &p_stat); - p_size = p_stat.st_size; - - p_handle = (uint8_t*)mmap(0, p_size, mmap_flags, MAP_SHARED, p_fd, 0); - if(p_handle == MAP_FAILED) { - p_handle = 0; - ::close(p_fd); - p_fd = -1; - return false; - } - - return p_handle; - } - - void p_close() { - if(p_handle) { - munmap(p_handle, p_size); - p_handle = 0; - } - - if(p_fd >= 0) { - ::close(p_fd); - p_fd = -1; - } - } - - void p_ctor() { - p_fd = -1; - } - - void p_dtor() { - p_close(); - } - - #endif - }; -} - -#endif diff --git a/supergameboy/nall/foreach.hpp b/supergameboy/nall/foreach.hpp deleted file mode 100644 index ea975b84..00000000 --- a/supergameboy/nall/foreach.hpp +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef NALL_FOREACH_HPP -#define NALL_FOREACH_HPP - -#undef foreach -#define foreach(iter, object) \ - for(unsigned foreach_counter = 0, foreach_limit = foreach_size(object), foreach_once = 0, foreach_broken = 0; foreach_counter < foreach_limit && foreach_broken == 0; foreach_counter++, foreach_once = 0) \ - for(auto &iter = object[foreach_counter]; foreach_once == 0 && (foreach_broken = 1); foreach_once++, foreach_broken = 0) - -#include -#include -#include - -namespace nall { - template unsigned foreach_size(const T& object, typename mp_enable_if>::type = 0) { - return object.count(); - } - - template unsigned foreach_size(const T& object, typename mp_enable_if>::type = 0) { - return object.length(); - } - - template unsigned foreach_size(const T& object, typename mp_enable_if>::type = 0) { - return object.size(); - } - - template unsigned foreach_size(const T& object, typename mp_enable_if>::type = 0) { - return sizeof(T) / sizeof(typename std::remove_extent::type); - } -} - -#endif diff --git a/supergameboy/nall/function.hpp b/supergameboy/nall/function.hpp deleted file mode 100644 index 3f0f704e..00000000 --- a/supergameboy/nall/function.hpp +++ /dev/null @@ -1,102 +0,0 @@ -#ifndef NALL_FUNCTION_HPP -#define NALL_FUNCTION_HPP - -#include -#include - -namespace nall { - template class function; - - template - class function { - private: - struct base1 { virtual void func1(P...) {} }; - struct base2 { virtual void func2(P...) {} }; - struct derived : base1, virtual base2 {}; - - struct data_t { - R (*callback)(const data_t&, P...); - union { - R (*callback_global)(P...); - struct { - R (derived::*callback_member)(P...); - void *object; - }; - }; - } data; - - static R callback_global(const data_t &data, P... p) { - return data.callback_global(p...); - } - - template - static R callback_member(const data_t &data, P... p) { - return (((C*)data.object)->*((R (C::*&)(P...))data.callback_member))(p...); - } - - public: - R operator()(P... p) const { return data.callback(data, p...); } - operator bool() const { return data.callback; } - void reset() { data.callback = 0; } - - function& operator=(const function &source) { memcpy(&data, &source.data, sizeof(data_t)); return *this; } - function(const function &source) { operator=(source); } - - //no pointer - function() { - data.callback = 0; - } - - //symbolic link pointer (nall/dl.hpp::sym, etc) - function(void *callback) { - data.callback = callback ? &callback_global : 0; - data.callback_global = (R (*)(P...))callback; - } - - //global function pointer - function(R (*callback)(P...)) { - data.callback = &callback_global; - data.callback_global = callback; - } - - //member function pointer - template - function(R (C::*callback)(P...), C *object) { - static_assert(sizeof data.callback_member >= sizeof callback, "callback_member is too small"); - data.callback = &callback_member; - (R (C::*&)(P...))data.callback_member = callback; - data.object = object; - } - - //const member function pointer - template - function(R (C::*callback)(P...) const, C *object) { - static_assert(sizeof data.callback_member >= sizeof callback, "callback_member is too small"); - data.callback = &callback_member; - (R (C::*&)(P...))data.callback_member = (R (C::*&)(P...))callback; - data.object = object; - } - - //lambda function pointer - template - function(T callback) { - static_assert(std::is_same::type>::value, "lambda mismatch"); - data.callback = &callback_global; - data.callback_global = (R (*)(P...))callback; - } - }; - - //bind functions to ease construction and assignment of function() with more than one argument - - template - function bind(R (C::*callback)(P...), C *object) { - return function(callback, object); - } - - template - function bind(R (C::*callback)(P...) const, C *object) { - return function(callback, object); - } -} - -#endif diff --git a/supergameboy/nall/input.hpp b/supergameboy/nall/input.hpp deleted file mode 100644 index b3ce9ebf..00000000 --- a/supergameboy/nall/input.hpp +++ /dev/null @@ -1,386 +0,0 @@ -#ifndef NALL_INPUT_HPP -#define NALL_INPUT_HPP - -#include -#include -#include - -#include -#include - -namespace nall { - -struct Keyboard; -Keyboard& keyboard(unsigned = 0); - -static const char KeyboardScancodeName[][64] = { - "Escape", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", - "PrintScreen", "ScrollLock", "Pause", "Tilde", - "Num1", "Num2", "Num3", "Num4", "Num5", "Num6", "Num7", "Num8", "Num9", "Num0", - "Dash", "Equal", "Backspace", - "Insert", "Delete", "Home", "End", "PageUp", "PageDown", - "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", - "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "Z", - "LeftBracket", "RightBracket", "Backslash", "Semicolon", "Apostrophe", "Comma", "Period", "Slash", - "Keypad1", "Keypad2", "Keypad3", "Keypad4", "Keypad5", "Keypad6", "Keypad7", "Keypad8", "Keypad9", "Keypad0", - "Point", "Enter", "Add", "Subtract", "Multiply", "Divide", - "NumLock", "CapsLock", - "Up", "Down", "Left", "Right", - "Tab", "Return", "Spacebar", "Menu", - "Shift", "Control", "Alt", "Super", -}; - -struct Keyboard { - const unsigned ID; - enum { Base = 1 }; - enum { Count = 8, Size = 128 }; - - enum Scancode { - Escape, F1, F2, F3, F4, F5, F6, F7, F8, F9, F10, F11, F12, - PrintScreen, ScrollLock, Pause, Tilde, - Num1, Num2, Num3, Num4, Num5, Num6, Num7, Num8, Num9, Num0, - Dash, Equal, Backspace, - Insert, Delete, Home, End, PageUp, PageDown, - A, B, C, D, E, F, G, H, I, J, K, L, M, - N, O, P, Q, R, S, T, U, V, W, X, Y, Z, - LeftBracket, RightBracket, Backslash, Semicolon, Apostrophe, Comma, Period, Slash, - Keypad1, Keypad2, Keypad3, Keypad4, Keypad5, Keypad6, Keypad7, Keypad8, Keypad9, Keypad0, - Point, Enter, Add, Subtract, Multiply, Divide, - NumLock, CapsLock, - Up, Down, Left, Right, - Tab, Return, Spacebar, Menu, - Shift, Control, Alt, Super, - Limit, - }; - - static signed numberDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(keyboard(i).belongsTo(scancode)) return i; - } - return -1; - } - - static signed keyDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(keyboard(i).isKey(scancode)) return scancode - keyboard(i).key(Escape); - } - return -1; - } - - static signed modifierDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(keyboard(i).isModifier(scancode)) return scancode - keyboard(i).key(Shift); - } - return -1; - } - - static bool isAnyKey(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(keyboard(i).isKey(scancode)) return true; - } - return false; - } - - static bool isAnyModifier(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(keyboard(i).isModifier(scancode)) return true; - } - return false; - } - - static uint16_t decode(const char *name) { - string s(name); - if(!strbegin(name, "KB")) return 0; - ltrim(s, "KB"); - unsigned id = strunsigned(s); - int pos = strpos(s, "::"); - if(pos < 0) return 0; - s = substr(s, pos + 2); - for(unsigned i = 0; i < Limit; i++) { - if(s == KeyboardScancodeName[i]) return Base + Size * id + i; - } - return 0; - } - - string encode(uint16_t code) const { - unsigned index = 0; - for(unsigned i = 0; i < Count; i++) { - if(code >= Base + Size * i && code < Base + Size * (i + 1)) { - index = code - (Base + Size * i); - break; - } - } - return string() << "KB" << ID << "::" << KeyboardScancodeName[index]; - } - - uint16_t operator[](Scancode code) const { return Base + ID * Size + code; } - uint16_t key(unsigned id) const { return Base + Size * ID + id; } - bool isKey(unsigned id) const { return id >= key(Escape) && id <= key(Menu); } - bool isModifier(unsigned id) const { return id >= key(Shift) && id <= key(Super); } - bool belongsTo(uint16_t scancode) const { return isKey(scancode) || isModifier(scancode); } - - Keyboard(unsigned ID_) : ID(ID_) {} -}; - -inline Keyboard& keyboard(unsigned id) { - static Keyboard kb0(0), kb1(1), kb2(2), kb3(3), kb4(4), kb5(5), kb6(6), kb7(7); - switch(id) { default: - case 0: return kb0; case 1: return kb1; case 2: return kb2; case 3: return kb3; - case 4: return kb4; case 5: return kb5; case 6: return kb6; case 7: return kb7; - } -} - -static const char MouseScancodeName[][64] = { - "Xaxis", "Yaxis", "Zaxis", - "Button0", "Button1", "Button2", "Button3", "Button4", "Button5", "Button6", "Button7", -}; - -struct Mouse; -Mouse& mouse(unsigned = 0); - -struct Mouse { - const unsigned ID; - enum { Base = Keyboard::Base + Keyboard::Size * Keyboard::Count }; - enum { Count = 8, Size = 16 }; - enum { Axes = 3, Buttons = 8 }; - - enum Scancode { - Xaxis, Yaxis, Zaxis, - Button0, Button1, Button2, Button3, Button4, Button5, Button6, Button7, - Limit, - }; - - static signed numberDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(mouse(i).belongsTo(scancode)) return i; - } - return -1; - } - - static signed axisDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(mouse(i).isAxis(scancode)) return scancode - mouse(i).axis(0); - } - return -1; - } - - static signed buttonDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(mouse(i).isButton(scancode)) return scancode - mouse(i).button(0); - } - return -1; - } - - static bool isAnyAxis(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(mouse(i).isAxis(scancode)) return true; - } - return false; - } - - static bool isAnyButton(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(mouse(i).isButton(scancode)) return true; - } - return false; - } - - static uint16_t decode(const char *name) { - string s(name); - if(!strbegin(name, "MS")) return 0; - ltrim(s, "MS"); - unsigned id = strunsigned(s); - int pos = strpos(s, "::"); - if(pos < 0) return 0; - s = substr(s, pos + 2); - for(unsigned i = 0; i < Limit; i++) { - if(s == MouseScancodeName[i]) return Base + Size * id + i; - } - return 0; - } - - string encode(uint16_t code) const { - unsigned index = 0; - for(unsigned i = 0; i < Count; i++) { - if(code >= Base + Size * i && code < Base + Size * (i + 1)) { - index = code - (Base + Size * i); - break; - } - } - return string() << "MS" << ID << "::" << MouseScancodeName[index]; - } - - uint16_t operator[](Scancode code) const { return Base + ID * Size + code; } - uint16_t axis(unsigned id) const { return Base + Size * ID + Xaxis + id; } - uint16_t button(unsigned id) const { return Base + Size * ID + Button0 + id; } - bool isAxis(unsigned id) const { return id >= axis(0) && id <= axis(2); } - bool isButton(unsigned id) const { return id >= button(0) && id <= button(7); } - bool belongsTo(uint16_t scancode) const { return isAxis(scancode) || isButton(scancode); } - - Mouse(unsigned ID_) : ID(ID_) {} -}; - -inline Mouse& mouse(unsigned id) { - static Mouse ms0(0), ms1(1), ms2(2), ms3(3), ms4(4), ms5(5), ms6(6), ms7(7); - switch(id) { default: - case 0: return ms0; case 1: return ms1; case 2: return ms2; case 3: return ms3; - case 4: return ms4; case 5: return ms5; case 6: return ms6; case 7: return ms7; - } -} - -static const char JoypadScancodeName[][64] = { - "Hat0", "Hat1", "Hat2", "Hat3", "Hat4", "Hat5", "Hat6", "Hat7", - "Axis0", "Axis1", "Axis2", "Axis3", "Axis4", "Axis5", "Axis6", "Axis7", - "Axis8", "Axis9", "Axis10", "Axis11", "Axis12", "Axis13", "Axis14", "Axis15", - "Button0", "Button1", "Button2", "Button3", "Button4", "Button5", "Button6", "Button7", - "Button8", "Button9", "Button10", "Button11", "Button12", "Button13", "Button14", "Button15", - "Button16", "Button17", "Button18", "Button19", "Button20", "Button21", "Button22", "Button23", - "Button24", "Button25", "Button26", "Button27", "Button28", "Button29", "Button30", "Button31", -}; - -struct Joypad; -Joypad& joypad(unsigned = 0); - -struct Joypad { - const unsigned ID; - enum { Base = Mouse::Base + Mouse::Size * Mouse::Count }; - enum { Count = 8, Size = 64 }; - enum { Hats = 8, Axes = 16, Buttons = 32 }; - - enum Scancode { - Hat0, Hat1, Hat2, Hat3, Hat4, Hat5, Hat6, Hat7, - Axis0, Axis1, Axis2, Axis3, Axis4, Axis5, Axis6, Axis7, - Axis8, Axis9, Axis10, Axis11, Axis12, Axis13, Axis14, Axis15, - Button0, Button1, Button2, Button3, Button4, Button5, Button6, Button7, - Button8, Button9, Button10, Button11, Button12, Button13, Button14, Button15, - Button16, Button17, Button18, Button19, Button20, Button21, Button22, Button23, - Button24, Button25, Button26, Button27, Button28, Button29, Button30, Button31, - Limit, - }; - - enum Hat { HatCenter = 0, HatUp = 1, HatRight = 2, HatDown = 4, HatLeft = 8 }; - - static signed numberDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(joypad(i).belongsTo(scancode)) return i; - } - return -1; - } - - static signed hatDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(joypad(i).isHat(scancode)) return scancode - joypad(i).hat(0); - } - return -1; - } - - static signed axisDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(joypad(i).isAxis(scancode)) return scancode - joypad(i).axis(0); - } - return -1; - } - - static signed buttonDecode(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(joypad(i).isButton(scancode)) return scancode - joypad(i).button(0); - } - return -1; - } - - static bool isAnyHat(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(joypad(i).isHat(scancode)) return true; - } - return false; - } - - static bool isAnyAxis(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(joypad(i).isAxis(scancode)) return true; - } - return false; - } - - static bool isAnyButton(uint16_t scancode) { - for(unsigned i = 0; i < Count; i++) { - if(joypad(i).isButton(scancode)) return true; - } - return false; - } - - static uint16_t decode(const char *name) { - string s(name); - if(!strbegin(name, "JP")) return 0; - ltrim(s, "JP"); - unsigned id = strunsigned(s); - int pos = strpos(s, "::"); - if(pos < 0) return 0; - s = substr(s, pos + 2); - for(unsigned i = 0; i < Limit; i++) { - if(s == JoypadScancodeName[i]) return Base + Size * id + i; - } - return 0; - } - - string encode(uint16_t code) const { - unsigned index = 0; - for(unsigned i = 0; i < Count; i++) { - if(code >= Base + Size * i && code < Base + Size * (i + 1)) { - index = code - (Base + Size * i); - } - } - return string() << "JP" << ID << "::" << JoypadScancodeName[index]; - } - - uint16_t operator[](Scancode code) const { return Base + ID * Size + code; } - uint16_t hat(unsigned id) const { return Base + Size * ID + Hat0 + id; } - uint16_t axis(unsigned id) const { return Base + Size * ID + Axis0 + id; } - uint16_t button(unsigned id) const { return Base + Size * ID + Button0 + id; } - bool isHat(unsigned id) const { return id >= hat(0) && id <= hat(7); } - bool isAxis(unsigned id) const { return id >= axis(0) && id <= axis(15); } - bool isButton(unsigned id) const { return id >= button(0) && id <= button(31); } - bool belongsTo(uint16_t scancode) const { return isHat(scancode) || isAxis(scancode) || isButton(scancode); } - - Joypad(unsigned ID_) : ID(ID_) {} -}; - -inline Joypad& joypad(unsigned id) { - static Joypad jp0(0), jp1(1), jp2(2), jp3(3), jp4(4), jp5(5), jp6(6), jp7(7); - switch(id) { default: - case 0: return jp0; case 1: return jp1; case 2: return jp2; case 3: return jp3; - case 4: return jp4; case 5: return jp5; case 6: return jp6; case 7: return jp7; - } -} - -struct Scancode { - enum { None = 0, Limit = Joypad::Base + Joypad::Size * Joypad::Count }; - - static uint16_t decode(const char *name) { - uint16_t code; - code = Keyboard::decode(name); - if(code) return code; - code = Mouse::decode(name); - if(code) return code; - code = Joypad::decode(name); - if(code) return code; - return None; - } - - static string encode(uint16_t code) { - for(unsigned i = 0; i < Keyboard::Count; i++) { - if(keyboard(i).belongsTo(code)) return keyboard(i).encode(code); - } - for(unsigned i = 0; i < Mouse::Count; i++) { - if(mouse(i).belongsTo(code)) return mouse(i).encode(code); - } - for(unsigned i = 0; i < Joypad::Count; i++) { - if(joypad(i).belongsTo(code)) return joypad(i).encode(code); - } - return "None"; - } -}; - -} - -#endif diff --git a/supergameboy/nall/lzss.hpp b/supergameboy/nall/lzss.hpp deleted file mode 100644 index 202bc814..00000000 --- a/supergameboy/nall/lzss.hpp +++ /dev/null @@ -1,81 +0,0 @@ -#ifndef NALL_LZSS_HPP -#define NALL_LZSS_HPP - -#include -#include -#include - -namespace nall { - class lzss { - public: - static bool encode(uint8_t *&output, unsigned &outlength, const uint8_t *input, unsigned inlength) { - output = new(zeromemory) uint8_t[inlength * 9 / 8 + 9]; - - unsigned i = 0, o = 0; - while(i < inlength) { - unsigned flagoffset = o++; - uint8_t flag = 0x00; - - for(unsigned b = 0; b < 8 && i < inlength; b++) { - unsigned longest = 0, pointer; - for(unsigned index = 1; index < 4096; index++) { - unsigned count = 0; - while(true) { - if(count >= 15 + 3) break; //verify pattern match is not longer than max length - if(i + count >= inlength) break; //verify pattern match does not read past end of input - if(i + count < index) break; //verify read is not before start of input - if(input[i + count] != input[i + count - index]) break; //verify pattern still matches - count++; - } - - if(count > longest) { - longest = count; - pointer = index; - } - } - - if(longest < 3) output[o++] = input[i++]; - else { - flag |= 1 << b; - uint16_t x = ((longest - 3) << 12) + pointer; - output[o++] = x; - output[o++] = x >> 8; - i += longest; - } - } - - output[flagoffset] = flag; - } - - outlength = o; - return true; - } - - static bool decode(uint8_t *&output, const uint8_t *input, unsigned length) { - output = new(zeromemory) uint8_t[length]; - - unsigned i = 0, o = 0; - while(o < length) { - uint8_t flag = input[i++]; - - for(unsigned b = 0; b < 8 && o < length; b++) { - if(!(flag & (1 << b))) output[o++] = input[i++]; - else { - uint16_t offset = input[i++]; - offset += input[i++] << 8; - uint16_t lookuplength = (offset >> 12) + 3; - offset &= 4095; - for(unsigned index = 0; index < lookuplength && o + index < length; index++) { - output[o + index] = output[o + index - offset]; - } - o += lookuplength; - } - } - } - - return true; - } - }; -} - -#endif diff --git a/supergameboy/nall/moduloarray.hpp b/supergameboy/nall/moduloarray.hpp deleted file mode 100644 index be549ae9..00000000 --- a/supergameboy/nall/moduloarray.hpp +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef NALL_MODULO_HPP -#define NALL_MODULO_HPP - -#include - -namespace nall { - template class modulo_array { - public: - inline T operator[](int index) const { - return buffer[size + index]; - } - - inline T read(int index) const { - return buffer[size + index]; - } - - inline void write(unsigned index, const T value) { - buffer[index] = - buffer[index + size] = - buffer[index + size + size] = value; - } - - void serialize(serializer &s) { - s.array(buffer, size * 3); - } - - modulo_array() { - buffer = new T[size * 3](); - } - - ~modulo_array() { - delete[] buffer; - } - - private: - T *buffer; - }; -} - -#endif diff --git a/supergameboy/nall/platform.hpp b/supergameboy/nall/platform.hpp deleted file mode 100644 index 68ed37ce..00000000 --- a/supergameboy/nall/platform.hpp +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef NALL_PLATFORM_HPP -#define NALL_PLATFORM_HPP - -#include - -//========================= -//standard platform headers -//========================= - -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(_WIN32) - #include - #include - #include - #undef interface -#else - #include - #include - #include -#endif - -//================== -//warning supression -//================== - -//Visual C++ -#if defined(_MSC_VER) - //disable libc "deprecation" warnings - #pragma warning(disable:4996) -#endif - -//================ -//POSIX compliance -//================ - -#if defined(_MSC_VER) - #define PATH_MAX _MAX_PATH - #define va_copy(dest, src) ((dest) = (src)) -#endif - -#if defined(_WIN32) - #define getcwd _getcwd - #define ftruncate _chsize - #define putenv _putenv - #define mkdir(n, m) _wmkdir(nall::utf16_t(n)) - #define rmdir _rmdir - #define vsnprintf _vsnprintf - #define usleep(n) Sleep(n / 1000) -#endif - -//================ -//inline expansion -//================ - -#if defined(__GNUC__) - #define noinline __attribute__((noinline)) - #define inline inline - #define alwaysinline inline __attribute__((always_inline)) -#elif defined(_MSC_VER) - #define noinline __declspec(noinline) - #define inline inline - #define alwaysinline inline __forceinline -#else - #define noinline - #define inline inline - #define alwaysinline inline -#endif - -#endif - diff --git a/supergameboy/nall/priorityqueue.hpp b/supergameboy/nall/priorityqueue.hpp deleted file mode 100644 index 7104e791..00000000 --- a/supergameboy/nall/priorityqueue.hpp +++ /dev/null @@ -1,109 +0,0 @@ -#ifndef NALL_PRIORITYQUEUE_HPP -#define NALL_PRIORITYQUEUE_HPP - -#include -#include -#include -#include - -namespace nall { - template void priority_queue_nocallback(type_t) {} - - //priority queue implementation using binary min-heap array; - //does not require normalize() function. - //O(1) find (tick) - //O(log n) insert (enqueue) - //O(log n) remove (dequeue) - template class priority_queue { - public: - inline void tick(unsigned ticks) { - basecounter += ticks; - while(heapsize && gte(basecounter, heap[0].counter)) callback(dequeue()); - } - - //counter is relative to current time (eg enqueue(64, ...) fires in 64 ticks); - //counter cannot exceed std::numeric_limits::max() >> 1. - void enqueue(unsigned counter, type_t event) { - unsigned child = heapsize++; - counter += basecounter; - - while(child) { - unsigned parent = (child - 1) >> 1; - if(gte(counter, heap[parent].counter)) break; - - heap[child].counter = heap[parent].counter; - heap[child].event = heap[parent].event; - child = parent; - } - - heap[child].counter = counter; - heap[child].event = event; - } - - type_t dequeue() { - type_t event(heap[0].event); - unsigned parent = 0; - unsigned counter = heap[--heapsize].counter; - - while(true) { - unsigned child = (parent << 1) + 1; - if(child >= heapsize) break; - if(child + 1 < heapsize && gte(heap[child].counter, heap[child + 1].counter)) child++; - if(gte(heap[child].counter, counter)) break; - - heap[parent].counter = heap[child].counter; - heap[parent].event = heap[child].event; - parent = child; - } - - heap[parent].counter = counter; - heap[parent].event = heap[heapsize].event; - return event; - } - - void reset() { - basecounter = 0; - heapsize = 0; - } - - void serialize(serializer &s) { - s.integer(basecounter); - s.integer(heapsize); - for(unsigned n = 0; n < heapcapacity; n++) { - s.integer(heap[n].counter); - s.integer(heap[n].event); - } - } - - priority_queue(unsigned size, function callback_ = &priority_queue_nocallback) - : callback(callback_) { - heap = new heap_t[size]; - heapcapacity = size; - reset(); - } - - ~priority_queue() { - delete[] heap; - } - - priority_queue& operator=(const priority_queue&) = delete; - priority_queue(const priority_queue&) = delete; - - private: - function callback; - unsigned basecounter; - unsigned heapsize; - unsigned heapcapacity; - struct heap_t { - unsigned counter; - type_t event; - } *heap; - - //return true if x is greater than or equal to y - inline bool gte(unsigned x, unsigned y) { - return x - y < (std::numeric_limits::max() >> 1); - } - }; -} - -#endif diff --git a/supergameboy/nall/property.hpp b/supergameboy/nall/property.hpp deleted file mode 100644 index 6fd33acd..00000000 --- a/supergameboy/nall/property.hpp +++ /dev/null @@ -1,91 +0,0 @@ -#ifndef NALL_PROPERTY_HPP -#define NALL_PROPERTY_HPP - -//nall::property implements ownership semantics into container classes -//example: property::readonly implies that only owner has full -//access to type; and all other code has readonly access. -// -//this code relies on extended friend semantics from C++0x to work, as it -//declares a friend class via a template paramter. it also exploits a bug in -//G++ 4.x to work even in C++98 mode. -// -//if compiling elsewhere, simply remove the friend class and private semantics - -//property can be used either of two ways: -//struct foo { -// property::readonly x; -// property::readwrite y; -//}; -//-or- -//struct foo : property { -// readonly x; -// readwrite y; -//}; - -//return types are const T& (byref) instead fo T (byval) to avoid major speed -//penalties for objects with expensive copy constructors - -//operator-> provides access to underlying object type: -//readonly foo; -//foo->bar(); -//... will call Object::bar(); - -//operator='s reference is constant so as to avoid leaking a reference handle -//that could bypass access restrictions - -//both constant and non-constant operators are provided, though it may be -//necessary to cast first, for instance: -//struct foo : property { readonly bar; } object; -//int main() { int value = const_cast(object); } - -//writeonly is useful for objects that have non-const reads, but const writes. -//however, to avoid leaking handles, the interface is very restricted. the only -//way to write is via operator=, which requires conversion via eg copy -//constructor. example: -//struct foo { -// foo(bool value) { ... } -//}; -//writeonly bar; -//bar = true; - -namespace nall { - template struct property { - template struct traits { typedef T type; }; - - template struct readonly { - const T* operator->() const { return &value; } - const T& operator()() const { return value; } - operator const T&() const { return value; } - private: - T* operator->() { return &value; } - operator T&() { return value; } - const T& operator=(const T& value_) { return value = value_; } - T value; - friend class traits::type; - }; - - template struct writeonly { - void operator=(const T& value_) { value = value_; } - private: - const T* operator->() const { return &value; } - const T& operator()() const { return value; } - operator const T&() const { return value; } - T* operator->() { return &value; } - operator T&() { return value; } - T value; - friend class traits::type; - }; - - template struct readwrite { - const T* operator->() const { return &value; } - const T& operator()() const { return value; } - operator const T&() const { return value; } - T* operator->() { return &value; } - operator T&() { return value; } - const T& operator=(const T& value_) { return value = value_; } - T value; - }; - }; -} - -#endif diff --git a/supergameboy/nall/qt/Makefile b/supergameboy/nall/qt/Makefile deleted file mode 100644 index 69e84960..00000000 --- a/supergameboy/nall/qt/Makefile +++ /dev/null @@ -1,55 +0,0 @@ -# requires nall/Makefile - -# imports: -# $(qtlibs) -- list of Qt components to link against - -# exports the following symbols: -# $(moc) -- meta-object compiler -# $(rcc) -- resource compiler -# $(qtinc) -- includes for compiling -# $(qtlib) -- libraries for linking - -ifeq ($(moc),) -moc := moc -endif - -ifeq ($(rcc),) -rcc := rcc -endif - -ifeq ($(platform),x) - qtinc := `pkg-config --cflags $(qtlibs)` - qtlib := `pkg-config --libs $(qtlibs)` -else ifeq ($(platform),osx) - qtinc := $(foreach lib,$(qtlibs),-I/Library/Frameworks/$(lib).framework/Versions/4/Headers) - - qtlib := -L/Library/Frameworks - qtlib += $(foreach lib,$(qtlibs),-framework $(lib)) - qtlib += -framework Carbon - qtlib += -framework Cocoa - qtlib += -framework OpenGL - qtlib += -framework AppKit - qtlib += -framework ApplicationServices -else ifeq ($(platform),win) - ifeq ($(qtpath),) - # find Qt install directory from PATH environment variable - qtpath := $(foreach path,$(subst ;, ,$(PATH)),$(if $(wildcard $(path)/$(moc).exe),$(path))) - qtpath := $(strip $(qtpath)) - qtpath := $(subst \,/,$(qtpath)) - qtpath := $(patsubst %/bin,%,$(qtpath)) - endif - - qtinc := -I$(qtpath)/include - qtinc += $(foreach lib,$(qtlibs),-I$(qtpath)/include/$(lib)) - - qtlib := -L$(qtpath)/lib - qtlib += -L$(qtpath)/plugins/imageformats - - qtlib += $(foreach lib,$(qtlibs),-l$(lib)4) - qtlib += -lmingw32 -lqtmain -lcomdlg32 -loleaut32 -limm32 -lwinmm - qtlib += -lwinspool -lmsimg32 -lole32 -ladvapi32 -lws2_32 -luuid -lgdi32 - qtlib += $(foreach lib,$(qtlibs),-l$(lib)4) - - # optional image-file support: - # qtlib += -lqjpeg -lqmng -endif diff --git a/supergameboy/nall/qt/check-action.moc.hpp b/supergameboy/nall/qt/check-action.moc.hpp deleted file mode 100644 index db378fe9..00000000 --- a/supergameboy/nall/qt/check-action.moc.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef NALL_QT_CHECKACTION_HPP -#define NALL_QT_CHECKACTION_HPP - -namespace nall { - -class CheckAction : public QAction { - Q_OBJECT - -public: - bool isChecked() const; - void setChecked(bool); - void toggleChecked(); - CheckAction(const QString&, QObject*); - -protected slots: - -protected: - bool checked; -}; - -inline bool CheckAction::isChecked() const { - return checked; -} - -inline void CheckAction::setChecked(bool checked_) { - checked = checked_; - if(checked) setIcon(QIcon(":/16x16/item-check-on.png")); - else setIcon(QIcon(":/16x16/item-check-off.png")); -} - -inline void CheckAction::toggleChecked() { - setChecked(!isChecked()); -} - -inline CheckAction::CheckAction(const QString &text, QObject *parent) : QAction(text, parent) { - setChecked(false); -} - -} - -#endif diff --git a/supergameboy/nall/qt/concept.hpp b/supergameboy/nall/qt/concept.hpp deleted file mode 100644 index 51cacef4..00000000 --- a/supergameboy/nall/qt/concept.hpp +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef NALL_QT_CONCEPT_HPP -#define NALL_QT_CONCEPT_HPP - -#include - -namespace nall { - template struct has_count> { enum { value = true }; }; -} - -#endif diff --git a/supergameboy/nall/qt/file-dialog.moc.hpp b/supergameboy/nall/qt/file-dialog.moc.hpp deleted file mode 100644 index bcccfaf5..00000000 --- a/supergameboy/nall/qt/file-dialog.moc.hpp +++ /dev/null @@ -1,392 +0,0 @@ -#ifndef NALL_QT_FILEDIALOG_HPP -#define NALL_QT_FILEDIALOG_HPP - -#include -#include -#include - -namespace nall { - -class FileDialog; - -class NewFolderDialog : public Window { - Q_OBJECT - -public: - void show(); - NewFolderDialog(FileDialog*); - -protected slots: - void createFolderAction(); - -protected: - FileDialog *parent; - QVBoxLayout *layout; - QLineEdit *folderNameEdit; - QHBoxLayout *controlLayout; - QPushButton *okButton; - QPushButton *cancelButton; -}; - -class FileView : public QListView { - Q_OBJECT - -protected: - void keyPressEvent(QKeyEvent*); - -signals: - void changed(const QModelIndex&); - void browseUp(); - -protected slots: - void currentChanged(const QModelIndex&, const QModelIndex&); -}; - -class FileDialog : public Window { - Q_OBJECT - -public: - void showLoad(); - void showSave(); - void showFolder(); - - void setPath(string path); - void setNameFilters(const string &filters); - FileDialog(); - -signals: - void changed(const string&); - void activated(const string&); - void accepted(const string&); - void rejected(); - -protected slots: - void fileViewChange(const QModelIndex&); - void fileViewActivate(const QModelIndex&); - void pathBoxChanged(); - void filterBoxChanged(); - void createNewFolder(); - void browseUp(); - void acceptAction(); - void rejectAction(); - -protected: - NewFolderDialog *newFolderDialog; - QVBoxLayout *layout; - QHBoxLayout *navigationLayout; - QComboBox *pathBox; - QPushButton *newFolderButton; - QPushButton *upFolderButton; - QHBoxLayout *browseLayout; - QFileSystemModel *fileSystemModel; - FileView *fileView; - QGroupBox *previewFrame; - QLineEdit *fileNameEdit; - QHBoxLayout *controlLayout; - QComboBox *filterBox; - QPushButton *optionsButton; - QPushButton *acceptButton; - QPushButton *rejectButton; - bool lock; - void createFolderAction(const string &name); - void closeEvent(QCloseEvent*); - - friend class NewFolderDialog; -}; - -inline void NewFolderDialog::show() { - folderNameEdit->setText(""); - Window::show(); - folderNameEdit->setFocus(); -} - -inline void NewFolderDialog::createFolderAction() { - string name = folderNameEdit->text().toUtf8().constData(); - if(name == "") { - folderNameEdit->setFocus(); - } else { - parent->createFolderAction(name); - close(); - } -} - -inline NewFolderDialog::NewFolderDialog(FileDialog *fileDialog) : parent(fileDialog) { - setMinimumWidth(240); - setWindowTitle("Create New Folder"); - - layout = new QVBoxLayout; - layout->setAlignment(Qt::AlignTop); - layout->setMargin(5); - layout->setSpacing(5); - setLayout(layout); - - folderNameEdit = new QLineEdit; - layout->addWidget(folderNameEdit); - - controlLayout = new QHBoxLayout; - controlLayout->setAlignment(Qt::AlignRight); - layout->addLayout(controlLayout); - - okButton = new QPushButton("Ok"); - controlLayout->addWidget(okButton); - - cancelButton = new QPushButton("Cancel"); - controlLayout->addWidget(cancelButton); - - connect(folderNameEdit, SIGNAL(returnPressed()), this, SLOT(createFolderAction())); - connect(okButton, SIGNAL(released()), this, SLOT(createFolderAction())); - connect(cancelButton, SIGNAL(released()), this, SLOT(close())); -} - -inline void FileView::currentChanged(const QModelIndex ¤t, const QModelIndex &previous) { - QAbstractItemView::currentChanged(current, previous); - emit changed(current); -} - -inline void FileView::keyPressEvent(QKeyEvent *event) { - //enhance consistency: force OS X to act like Windows and Linux; enter = activate item - if(event->key() == Qt::Key_Return || event->key() == Qt::Key_Enter) { - emit activated(currentIndex()); - return; - } - - //simulate popular file manager behavior; backspace = go up one directory - if(event->key() == Qt::Key_Backspace) { - emit browseUp(); - return; - } - - //fallback: unrecognized keypresses get handled by the widget itself - QListView::keyPressEvent(event); -} - -inline void FileDialog::showLoad() { - acceptButton->setText("Load"); - fileNameEdit->hide(); - filterBox->show(); - show(); -} - -inline void FileDialog::showSave() { - acceptButton->setText("Save"); - fileNameEdit->show(); - filterBox->show(); - show(); -} - -inline void FileDialog::showFolder() { - acceptButton->setText("Choose"); - fileNameEdit->hide(); - filterBox->hide(); - setNameFilters("Folders ()"); - show(); -} - -inline void FileDialog::fileViewChange(const QModelIndex &index) { - string path = fileSystemModel->filePath(index).toUtf8().constData(); - if(path == fileSystemModel->rootPath().toUtf8().constData()) path = ""; - fileNameEdit->setText(notdir(path)); - emit changed(path); -} - -inline void FileDialog::fileViewActivate(const QModelIndex &index) { - string path = fileSystemModel->filePath(index).toUtf8().constData(); - if(fileSystemModel->isDir(index)) { - emit activated(path); - setPath(path); - } else { - emit activated(path); - close(); - } -} - -inline void FileDialog::pathBoxChanged() { - if(lock) return; - setPath(pathBox->currentText().toUtf8().constData()); -} - -inline void FileDialog::filterBoxChanged() { - if(lock) return; - string filters = filterBox->currentText().toUtf8().constData(); - if(filters.length() == 0) { - fileSystemModel->setNameFilters(QStringList() << "*"); - } else { - filters = substr(filters, strpos(filters, "(")); - ltrim(filters, "("); - rtrim(filters, ")"); - lstring part; - part.split(" ", filters); - QStringList list; - for(unsigned i = 0; i < part.size(); i++) list << part[i]; - fileSystemModel->setNameFilters(list); - } -} - -inline void FileDialog::createNewFolder() { - newFolderDialog->show(); -} - -inline void FileDialog::browseUp() { - if(pathBox->count() > 1) pathBox->setCurrentIndex(1); -} - -inline void FileDialog::setPath(string path) { - lock = true; - newFolderDialog->close(); - - if(QDir(path).exists()) { - newFolderButton->setEnabled(true); - } else { - newFolderButton->setEnabled(false); - path = ""; - } - - fileSystemModel->setRootPath(path); - fileView->setRootIndex(fileSystemModel->index(path)); - fileView->setCurrentIndex(fileView->rootIndex()); - fileView->setFocus(); - - pathBox->clear(); - if(path.length() > 0) { - QDir directory(path); - while(true) { - pathBox->addItem(directory.absolutePath()); - if(directory.isRoot()) break; - directory.cdUp(); - } - } - pathBox->addItem(""); - fileNameEdit->setText(""); - - lock = false; -} - -inline void FileDialog::setNameFilters(const string &filters) { - lock = true; - - lstring list; - list.split("\n", filters); - - filterBox->clear(); - for(unsigned i = 0; i < list.size(); i++) { - filterBox->addItem(list[i]); - } - - lock = false; - filterBoxChanged(); -} - -inline void FileDialog::acceptAction() { - string path = fileSystemModel->rootPath().toUtf8().constData(); - path << "/" << notdir(fileNameEdit->text().toUtf8().constData()); - rtrim(path, "/"); - if(QDir(path).exists()) { - emit accepted(path); - setPath(path); - } else { - emit accepted(path); - close(); - } -} - -inline void FileDialog::rejectAction() { - emit rejected(); - close(); -} - -inline void FileDialog::createFolderAction(const string &name) { - string path = fileSystemModel->rootPath().toUtf8().constData(); - path << "/" << notdir(name); - mkdir(path, 0755); -} - -inline void FileDialog::closeEvent(QCloseEvent *event) { - newFolderDialog->close(); - Window::closeEvent(event); -} - -inline FileDialog::FileDialog() { - newFolderDialog = new NewFolderDialog(this); - resize(640, 360); - - layout = new QVBoxLayout; - layout->setMargin(5); - layout->setSpacing(5); - setLayout(layout); - - navigationLayout = new QHBoxLayout; - layout->addLayout(navigationLayout); - - pathBox = new QComboBox; - pathBox->setEditable(true); - pathBox->setMinimumContentsLength(16); - pathBox->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLength); - pathBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); - navigationLayout->addWidget(pathBox); - - newFolderButton = new QPushButton; - newFolderButton->setIconSize(QSize(16, 16)); - newFolderButton->setIcon(QIcon(":/16x16/folder-new.png")); - navigationLayout->addWidget(newFolderButton); - - upFolderButton = new QPushButton; - upFolderButton->setIconSize(QSize(16, 16)); - upFolderButton->setIcon(QIcon(":/16x16/go-up.png")); - navigationLayout->addWidget(upFolderButton); - - browseLayout = new QHBoxLayout; - layout->addLayout(browseLayout); - - fileSystemModel = new QFileSystemModel; - fileSystemModel->setFilter(QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot); - fileSystemModel->setNameFilterDisables(false); - - fileView = new FileView; - fileView->setMinimumWidth(320); - fileView->setModel(fileSystemModel); - fileView->setIconSize(QSize(16, 16)); - browseLayout->addWidget(fileView); - - previewFrame = new QGroupBox; - previewFrame->hide(); - browseLayout->addWidget(previewFrame); - - fileNameEdit = new QLineEdit; - layout->addWidget(fileNameEdit); - - controlLayout = new QHBoxLayout; - controlLayout->setAlignment(Qt::AlignRight); - layout->addLayout(controlLayout); - - filterBox = new QComboBox; - filterBox->setMinimumContentsLength(16); - filterBox->setSizeAdjustPolicy(QComboBox::AdjustToMinimumContentsLength); - filterBox->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); - controlLayout->addWidget(filterBox); - - optionsButton = new QPushButton("Options"); - optionsButton->hide(); - controlLayout->addWidget(optionsButton); - - acceptButton = new QPushButton("Ok"); - controlLayout->addWidget(acceptButton); - - rejectButton = new QPushButton("Cancel"); - controlLayout->addWidget(rejectButton); - - lock = false; - connect(pathBox, SIGNAL(currentIndexChanged(int)), this, SLOT(pathBoxChanged())); - connect(newFolderButton, SIGNAL(released()), this, SLOT(createNewFolder())); - connect(upFolderButton, SIGNAL(released()), this, SLOT(browseUp())); - connect(fileView, SIGNAL(changed(const QModelIndex&)), this, SLOT(fileViewChange(const QModelIndex&))); - connect(fileView, SIGNAL(activated(const QModelIndex&)), this, SLOT(fileViewActivate(const QModelIndex&))); - connect(fileView, SIGNAL(browseUp()), this, SLOT(browseUp())); - connect(fileNameEdit, SIGNAL(returnPressed()), this, SLOT(acceptAction())); - connect(filterBox, SIGNAL(currentIndexChanged(int)), this, SLOT(filterBoxChanged())); - connect(acceptButton, SIGNAL(released()), this, SLOT(acceptAction())); - connect(rejectButton, SIGNAL(released()), this, SLOT(rejectAction())); -} - -} - -#endif diff --git a/supergameboy/nall/qt/hex-editor.moc.hpp b/supergameboy/nall/qt/hex-editor.moc.hpp deleted file mode 100644 index d59f4be9..00000000 --- a/supergameboy/nall/qt/hex-editor.moc.hpp +++ /dev/null @@ -1,173 +0,0 @@ -#ifndef NALL_QT_HEXEDITOR_HPP -#define NALL_QT_HEXEDITOR_HPP - -#include -#include -#include - -namespace nall { - -class HexEditor : public QTextEdit { - Q_OBJECT - -public: - function reader; - function writer; - - void setColumns(unsigned columns); - void setRows(unsigned rows); - void setOffset(unsigned offset); - void setSize(unsigned size); - unsigned lineWidth() const; - void refresh(); - - HexEditor(); - -protected slots: - void scrolled(); - -protected: - QHBoxLayout *layout; - QScrollBar *scrollBar; - unsigned editorColumns; - unsigned editorRows; - unsigned editorOffset; - unsigned editorSize; - bool lock; - - void keyPressEvent(QKeyEvent*); -}; - -inline void HexEditor::keyPressEvent(QKeyEvent *event) { - QTextCursor cursor = textCursor(); - unsigned x = cursor.position() % lineWidth(); - unsigned y = cursor.position() / lineWidth(); - - int hexCode = -1; - switch(event->key()) { - case Qt::Key_0: hexCode = 0; break; - case Qt::Key_1: hexCode = 1; break; - case Qt::Key_2: hexCode = 2; break; - case Qt::Key_3: hexCode = 3; break; - case Qt::Key_4: hexCode = 4; break; - case Qt::Key_5: hexCode = 5; break; - case Qt::Key_6: hexCode = 6; break; - case Qt::Key_7: hexCode = 7; break; - case Qt::Key_8: hexCode = 8; break; - case Qt::Key_9: hexCode = 9; break; - case Qt::Key_A: hexCode = 10; break; - case Qt::Key_B: hexCode = 11; break; - case Qt::Key_C: hexCode = 12; break; - case Qt::Key_D: hexCode = 13; break; - case Qt::Key_E: hexCode = 14; break; - case Qt::Key_F: hexCode = 15; break; - } - - if(cursor.hasSelection() == false && hexCode != -1) { - bool cursorOffsetValid = (x >= 11 && ((x - 11) % 3) != 2); - if(cursorOffsetValid) { - bool nibble = (x - 11) % 3; //0 = top nibble, 1 = bottom nibble - unsigned cursorOffset = y * editorColumns + ((x - 11) / 3); - unsigned effectiveOffset = editorOffset + cursorOffset; - if(effectiveOffset >= editorSize) effectiveOffset %= editorSize; - - uint8_t data = reader ? reader(effectiveOffset) : 0x00; - data &= (nibble == 0 ? 0x0f : 0xf0); - data |= (nibble == 0 ? (hexCode << 4) : (hexCode << 0)); - if(writer) writer(effectiveOffset, data); - refresh(); - - cursor.setPosition(y * lineWidth() + x + 1); //advance cursor - setTextCursor(cursor); - } - } else { - //allow navigation keys to move cursor, but block text input - setTextInteractionFlags(Qt::TextSelectableByKeyboard | Qt::TextSelectableByMouse); - QTextEdit::keyPressEvent(event); - setTextInteractionFlags(Qt::TextEditorInteraction); - } -} - -inline void HexEditor::setColumns(unsigned columns) { - editorColumns = columns; -} - -inline void HexEditor::setRows(unsigned rows) { - editorRows = rows; - scrollBar->setPageStep(editorRows); -} - -inline void HexEditor::setOffset(unsigned offset) { - lock = true; - editorOffset = offset; - scrollBar->setSliderPosition(editorOffset / editorColumns); - lock = false; -} - -inline void HexEditor::setSize(unsigned size) { - editorSize = size; - bool indivisible = (editorSize % editorColumns) != 0; //add one for incomplete row - scrollBar->setRange(0, editorSize / editorColumns + indivisible - editorRows); -} - -inline unsigned HexEditor::lineWidth() const { - return 11 + 3 * editorColumns; -} - -inline void HexEditor::refresh() { - string output; - char temp[256]; - unsigned offset = editorOffset; - - for(unsigned y = 0; y < editorRows; y++) { - if(offset >= editorSize) break; - sprintf(temp, "%.4x:%.4x", (offset >> 16) & 0xffff, (offset >> 0) & 0xffff); - output << "" << temp << "  "; - - for(unsigned x = 0; x < editorColumns; x++) { - if(offset >= editorSize) break; - sprintf(temp, "%.2x", reader ? reader(offset) : 0x00); - offset++; - output << "" << temp << ""; - if(x != (editorColumns - 1)) output << " "; - } - - if(y != (editorRows - 1)) output << "
"; - } - - setHtml(output); -} - -inline void HexEditor::scrolled() { - if(lock) return; - unsigned offset = scrollBar->sliderPosition(); - editorOffset = offset * editorColumns; - refresh(); -} - -inline HexEditor::HexEditor() { - setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); - - layout = new QHBoxLayout; - layout->setAlignment(Qt::AlignRight); - layout->setMargin(0); - layout->setSpacing(0); - setLayout(layout); - - scrollBar = new QScrollBar(Qt::Vertical); - scrollBar->setSingleStep(1); - layout->addWidget(scrollBar); - - lock = false; - connect(scrollBar, SIGNAL(actionTriggered(int)), this, SLOT(scrolled())); - - setColumns(16); - setRows(16); - setSize(0); - setOffset(0); -} - -} - -#endif diff --git a/supergameboy/nall/qt/radio-action.moc.hpp b/supergameboy/nall/qt/radio-action.moc.hpp deleted file mode 100644 index a2bbca48..00000000 --- a/supergameboy/nall/qt/radio-action.moc.hpp +++ /dev/null @@ -1,41 +0,0 @@ -#ifndef NALL_QT_RADIOACTION_HPP -#define NALL_QT_RADIOACTION_HPP - -namespace nall { - -class RadioAction : public QAction { - Q_OBJECT - -public: - bool isChecked() const; - void setChecked(bool); - void toggleChecked(); - RadioAction(const QString&, QObject*); - -protected slots: - -protected: - bool checked; -}; - -inline bool RadioAction::isChecked() const { - return checked; -} - -inline void RadioAction::setChecked(bool checked_) { - checked = checked_; - if(checked) setIcon(QIcon(":/16x16/item-radio-on.png")); - else setIcon(QIcon(":/16x16/item-radio-off.png")); -} - -inline void RadioAction::toggleChecked() { - setChecked(!isChecked()); -} - -inline RadioAction::RadioAction(const QString &text, QObject *parent) : QAction(text, parent) { - setChecked(false); -} - -} - -#endif diff --git a/supergameboy/nall/qt/window.moc.hpp b/supergameboy/nall/qt/window.moc.hpp deleted file mode 100644 index 0d3bf390..00000000 --- a/supergameboy/nall/qt/window.moc.hpp +++ /dev/null @@ -1,105 +0,0 @@ -#ifndef NALL_QT_WINDOW_HPP -#define NALL_QT_WINDOW_HPP - -#include -#include - -namespace nall { - -class Window : public QWidget { - Q_OBJECT - -public: - void setGeometryString(string *geometryString); - void setCloseOnEscape(bool); - void show(); - void hide(); - void shrink(); - - Window(); - -protected slots: - -protected: - string *geometryString; - bool closeOnEscape; - void keyReleaseEvent(QKeyEvent *event); - void closeEvent(QCloseEvent *event); -}; - -inline void Window::setGeometryString(string *geometryString_) { - geometryString = geometryString_; - if(geometryString && isVisible() == false) { - uint8_t *data; - unsigned length; - base64::decode(data, length, *geometryString); - QByteArray array((const char*)data, length); - delete[] data; - restoreGeometry(array); - } -} - -inline void Window::setCloseOnEscape(bool value) { - closeOnEscape = value; -} - -inline void Window::show() { - if(geometryString && isVisible() == false) { - uint8_t *data; - unsigned length; - base64::decode(data, length, *geometryString); - QByteArray array((const char*)data, length); - delete[] data; - restoreGeometry(array); - } - QWidget::show(); - QApplication::processEvents(); - activateWindow(); - raise(); -} - -inline void Window::hide() { - if(geometryString && isVisible() == true) { - char *data; - QByteArray geometry = saveGeometry(); - base64::encode(data, (const uint8_t*)geometry.data(), geometry.length()); - *geometryString = data; - delete[] data; - } - QWidget::hide(); -} - -inline void Window::shrink() { - if(isFullScreen()) return; - - for(unsigned i = 0; i < 2; i++) { - resize(0, 0); - usleep(2000); - QApplication::processEvents(); - } -} - -inline void Window::keyReleaseEvent(QKeyEvent *event) { - if(closeOnEscape && (event->key() == Qt::Key_Escape)) close(); - QWidget::keyReleaseEvent(event); -} - -inline void Window::closeEvent(QCloseEvent *event) { - if(geometryString) { - char *data; - QByteArray geometry = saveGeometry(); - base64::encode(data, (const uint8_t*)geometry.data(), geometry.length()); - *geometryString = data; - delete[] data; - } - QWidget::closeEvent(event); -} - -inline Window::Window() { - geometryString = 0; - closeOnEscape = true; -} - -} - -#endif diff --git a/supergameboy/nall/serial.hpp b/supergameboy/nall/serial.hpp deleted file mode 100644 index 6f5cf6d6..00000000 --- a/supergameboy/nall/serial.hpp +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef NALL_SERIAL_HPP -#define NALL_SERIAL_HPP - -#include -#include -#include -#include - -#include - -namespace nall { - class serial { - public: - //-1 on error, otherwise return bytes read - int read(uint8_t *data, unsigned length) { - if(port_open == false) return -1; - return ::read(port, (void*)data, length); - } - - //-1 on error, otherwise return bytes written - int write(const uint8_t *data, unsigned length) { - if(port_open == false) return -1; - return ::write(port, (void*)data, length); - } - - bool open(const char *portname, unsigned rate) { - close(); - - port = ::open(portname, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK); - if(port == -1) return false; - - if(ioctl(port, TIOCEXCL) == -1) { close(); return false; } - if(fcntl(port, F_SETFL, 0) == -1) { close(); return false; } - if(tcgetattr(port, &original_attr) == -1) { close(); return false; } - - termios attr = original_attr; - cfmakeraw(&attr); - cfsetspeed(&attr, rate); - - attr.c_lflag &=~ (ECHO | ECHONL | ISIG | ICANON | IEXTEN); - attr.c_iflag &=~ (BRKINT | PARMRK | INPCK | ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXOFF | IXANY); - attr.c_iflag |= (IGNBRK | IGNPAR); - attr.c_oflag &=~ (OPOST); - attr.c_cflag &=~ (CSIZE | CSTOPB | PARENB); - attr.c_cflag |= (CS8 | CREAD | CLOCAL); - attr.c_cc[VTIME] = attr.c_cc[VMIN] = 0; - - if(tcsetattr(port, TCSANOW, &attr) == -1) { close(); return false; } - return port_open = true; - } - - void close() { - if(port != -1) { - tcdrain(port); - if(port_open == true) { - tcsetattr(port, TCSANOW, &original_attr); - port_open = false; - } - ::close(port); - port = -1; - } - } - - serial() { - port = -1; - port_open = false; - } - - ~serial() { - close(); - } - - private: - int port; - bool port_open; - termios original_attr; - }; -} - -#endif diff --git a/supergameboy/nall/serializer.hpp b/supergameboy/nall/serializer.hpp deleted file mode 100644 index 9f816dfe..00000000 --- a/supergameboy/nall/serializer.hpp +++ /dev/null @@ -1,145 +0,0 @@ -#ifndef NALL_SERIALIZER_HPP -#define NALL_SERIALIZER_HPP - -#include -#include -#include -#include - -namespace nall { - //serializer: a class designed to save and restore the state of classes. - // - //benefits: - //- data() will be portable in size (it is not necessary to specify type sizes.) - //- data() will be portable in endianness (always stored internally as little-endian.) - //- one serialize function can both save and restore class states. - // - //caveats: - //- only plain-old-data can be stored. complex classes must provide serialize(serializer&); - //- floating-point usage is not portable across platforms - - class serializer { - public: - enum mode_t { Load, Save, Size }; - - mode_t mode() const { - return imode; - } - - const uint8_t* data() const { - return idata; - } - - unsigned size() const { - return isize; - } - - unsigned capacity() const { - return icapacity; - } - - template void floatingpoint(T &value) { - enum { size = sizeof(T) }; - //this is rather dangerous, and not cross-platform safe; - //but there is no standardized way to export FP-values - uint8_t *p = (uint8_t*)&value; - if(imode == Save) { - for(unsigned n = 0; n < size; n++) idata[isize++] = p[n]; - } else if(imode == Load) { - for(unsigned n = 0; n < size; n++) p[n] = idata[isize++]; - } else { - isize += size; - } - } - - template void integer(T &value) { - enum { size = std::is_same::value ? 1 : sizeof(T) }; - if(imode == Save) { - for(unsigned n = 0; n < size; n++) idata[isize++] = value >> (n << 3); - } else if(imode == Load) { - value = 0; - for(unsigned n = 0; n < size; n++) value |= idata[isize++] << (n << 3); - } else if(imode == Size) { - isize += size; - } - } - - template void array(T &array) { - enum { size = sizeof(T) / sizeof(typename std::remove_extent::type) }; - for(unsigned n = 0; n < size; n++) integer(array[n]); - } - - template void array(T array, unsigned size) { - for(unsigned n = 0; n < size; n++) integer(array[n]); - } - - //copy - serializer& operator=(const serializer &s) { - if(idata) delete[] idata; - - imode = s.imode; - idata = new uint8_t[s.icapacity]; - isize = s.isize; - icapacity = s.icapacity; - - memcpy(idata, s.idata, s.icapacity); - return *this; - } - - serializer(const serializer &s) : idata(0) { - operator=(s); - } - - //move - serializer& operator=(serializer &&s) { - if(idata) delete[] idata; - - imode = s.imode; - idata = s.idata; - isize = s.isize; - icapacity = s.icapacity; - - s.idata = 0; - return *this; - } - - serializer(serializer &&s) { - operator=(std::move(s)); - } - - //construction - serializer() { - imode = Size; - idata = 0; - isize = 0; - } - - serializer(unsigned capacity) { - imode = Save; - idata = new uint8_t[capacity](); - isize = 0; - icapacity = capacity; - } - - serializer(const uint8_t *data, unsigned capacity) { - imode = Load; - idata = new uint8_t[capacity]; - isize = 0; - icapacity = capacity; - memcpy(idata, data, capacity); - } - - ~serializer() { - if(idata) delete[] idata; - } - - private: - mode_t imode; - uint8_t *idata; - unsigned isize; - unsigned icapacity; - }; - -}; - -#endif diff --git a/supergameboy/nall/sha256.hpp b/supergameboy/nall/sha256.hpp deleted file mode 100644 index 7f41f04e..00000000 --- a/supergameboy/nall/sha256.hpp +++ /dev/null @@ -1,143 +0,0 @@ -#ifndef NALL_SHA256_HPP -#define NALL_SHA256_HPP - -//author: vladitx - -namespace nall { - #define PTR(t, a) ((t*)(a)) - - #define SWAP32(x) ((uint32_t)( \ - (((uint32_t)(x) & 0x000000ff) << 24) | \ - (((uint32_t)(x) & 0x0000ff00) << 8) | \ - (((uint32_t)(x) & 0x00ff0000) >> 8) | \ - (((uint32_t)(x) & 0xff000000) >> 24) \ - )) - - #define ST32(a, d) *PTR(uint32_t, a) = (d) - #define ST32BE(a, d) ST32(a, SWAP32(d)) - - #define LD32(a) *PTR(uint32_t, a) - #define LD32BE(a) SWAP32(LD32(a)) - - #define LSL32(x, n) ((uint32_t)(x) << (n)) - #define LSR32(x, n) ((uint32_t)(x) >> (n)) - #define ROR32(x, n) (LSR32(x, n) | LSL32(x, 32 - (n))) - - //first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19 - static const uint32_t T_H[8] = { - 0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19, - }; - - //first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311 - static const uint32_t T_K[64] = { - 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, - 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, - 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, - 0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967, - 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, - 0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070, - 0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3, - 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2, - }; - - struct sha256_ctx { - uint8_t in[64]; - unsigned inlen; - - uint32_t w[64]; - uint32_t h[8]; - uint64_t len; - }; - - void sha256_init(sha256_ctx *p) { - memset(p, 0, sizeof(sha256_ctx)); - memcpy(p->h, T_H, sizeof(T_H)); - } - - static void sha256_block(sha256_ctx *p) { - unsigned i; - uint32_t s0, s1; - uint32_t a, b, c, d, e, f, g, h; - uint32_t t1, t2, maj, ch; - - for(i = 0; i < 16; i++) p->w[i] = LD32BE(p->in + i * 4); - - for(i = 16; i < 64; i++) { - s0 = ROR32(p->w[i - 15], 7) ^ ROR32(p->w[i - 15], 18) ^ LSR32(p->w[i - 15], 3); - s1 = ROR32(p->w[i - 2], 17) ^ ROR32(p->w[i - 2], 19) ^ LSR32(p->w[i - 2], 10); - p->w[i] = p->w[i - 16] + s0 + p->w[i - 7] + s1; - } - - a = p->h[0]; b = p->h[1]; c = p->h[2]; d = p->h[3]; - e = p->h[4]; f = p->h[5]; g = p->h[6]; h = p->h[7]; - - for(i = 0; i < 64; i++) { - s0 = ROR32(a, 2) ^ ROR32(a, 13) ^ ROR32(a, 22); - maj = (a & b) ^ (a & c) ^ (b & c); - t2 = s0 + maj; - s1 = ROR32(e, 6) ^ ROR32(e, 11) ^ ROR32(e, 25); - ch = (e & f) ^ (~e & g); - t1 = h + s1 + ch + T_K[i] + p->w[i]; - - h = g; g = f; f = e; e = d + t1; - d = c; c = b; b = a; a = t1 + t2; - } - - p->h[0] += a; p->h[1] += b; p->h[2] += c; p->h[3] += d; - p->h[4] += e; p->h[5] += f; p->h[6] += g; p->h[7] += h; - - //next block - p->inlen = 0; - } - - void sha256_chunk(sha256_ctx *p, const uint8_t *s, unsigned len) { - unsigned l; - p->len += len; - - while(len) { - l = 64 - p->inlen; - l = (len < l) ? len : l; - - memcpy(p->in + p->inlen, s, l); - s += l; - p->inlen += l; - len -= l; - - if(p->inlen == 64) sha256_block(p); - } - } - - void sha256_final(sha256_ctx *p) { - uint64_t len; - p->in[p->inlen++] = 0x80; - - if(p->inlen > 56) { - memset(p->in + p->inlen, 0, 64 - p->inlen); - sha256_block(p); - } - - memset(p->in + p->inlen, 0, 56 - p->inlen); - - len = p->len << 3; - ST32BE(p->in + 56, len >> 32); - ST32BE(p->in + 60, len); - sha256_block(p); - } - - void sha256_hash(sha256_ctx *p, uint8_t *s) { - uint32_t *t = (uint32_t*)s; - for(unsigned i = 0; i < 8; i++) ST32BE(t++, p->h[i]); - } - - #undef PTR - #undef SWAP32 - #undef ST32 - #undef ST32BE - #undef LD32 - #undef LD32BE - #undef LSL32 - #undef LSR32 - #undef ROR32 -} - -#endif diff --git a/supergameboy/nall/sort.hpp b/supergameboy/nall/sort.hpp deleted file mode 100644 index 23c317a5..00000000 --- a/supergameboy/nall/sort.hpp +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef NALL_SORT_HPP -#define NALL_SORT_HPP - -#include - -//class: merge sort -//average: O(n log n) -//worst: O(n log n) -//memory: O(n) -//stack: O(log n) -//stable?: yes - -//notes: -//there are two primary reasons for choosing merge sort -//over the (usually) faster quick sort*: -//1: it is a stable sort. -//2: it lacks O(n^2) worst-case overhead. -//(* which is also O(n log n) in the average case.) - -namespace nall { - template - void sort(T list[], unsigned length) { - if(length <= 1) return; //nothing to sort - - //use insertion sort to quickly sort smaller blocks - if(length < 64) { - for(unsigned i = 0; i < length; i++) { - unsigned min = i; - for(unsigned j = i + 1; j < length; j++) { - if(list[j] < list[min]) min = j; - } - if(min != i) swap(list[i], list[min]); - } - return; - } - - //split list in half and recursively sort both - unsigned middle = length / 2; - sort(list, middle); - sort(list + middle, length - middle); - - //left and right are sorted here; perform merge sort - T *buffer = new T[length]; - unsigned offset = 0; - unsigned left = 0; - unsigned right = middle; - while(left < middle && right < length) { - if(list[left] < list[right]) { - buffer[offset++] = list[left++]; - } else { - buffer[offset++] = list[right++]; - } - } - while(left < middle) buffer[offset++] = list[left++]; - while(right < length) buffer[offset++] = list[right++]; - - for(unsigned i = 0; i < length; i++) list[i] = buffer[i]; - delete[] buffer; - } -} - -#endif diff --git a/supergameboy/nall/static.hpp b/supergameboy/nall/static.hpp deleted file mode 100644 index 4acb9fd0..00000000 --- a/supergameboy/nall/static.hpp +++ /dev/null @@ -1,20 +0,0 @@ -#ifndef NALL_STATIC_HPP -#define NALL_STATIC_HPP - -namespace nall { - template struct static_if { typedef T type; }; - template struct static_if { typedef F type; }; - template struct mp_static_if { typedef typename static_if::type type; }; - - template struct static_and { enum { value = false }; }; - template<> struct static_and { enum { value = true }; }; - template struct mp_static_and { enum { value = static_and::value }; }; - - template struct static_or { enum { value = false }; }; - template<> struct static_or { enum { value = true }; }; - template<> struct static_or { enum { value = true }; }; - template<> struct static_or { enum { value = true }; }; - template struct mp_static_or { enum { value = static_or::value }; }; -} - -#endif diff --git a/supergameboy/nall/stdint.hpp b/supergameboy/nall/stdint.hpp deleted file mode 100644 index d8b6c788..00000000 --- a/supergameboy/nall/stdint.hpp +++ /dev/null @@ -1,44 +0,0 @@ -#ifndef NALL_STDINT_HPP -#define NALL_STDINT_HPP - -#include - -#if defined(_MSC_VER) - typedef signed char int8_t; - typedef signed short int16_t; - typedef signed int int32_t; - typedef signed long long int64_t; - typedef int64_t intmax_t; - #if defined(_WIN64) - typedef int64_t intptr_t; - #else - typedef int32_t intptr_t; - #endif - - typedef unsigned char uint8_t; - typedef unsigned short uint16_t; - typedef unsigned int uint32_t; - typedef unsigned long long uint64_t; - typedef uint64_t uintmax_t; - #if defined(_WIN64) - typedef uint64_t uintptr_t; - #else - typedef uint32_t uintptr_t; - #endif -#else - #include -#endif - -namespace nall { - static_assert(sizeof(int8_t) == 1, "int8_t is not of the correct size" ); - static_assert(sizeof(int16_t) == 2, "int16_t is not of the correct size"); - static_assert(sizeof(int32_t) == 4, "int32_t is not of the correct size"); - static_assert(sizeof(int64_t) == 8, "int64_t is not of the correct size"); - - static_assert(sizeof(uint8_t) == 1, "int8_t is not of the correct size" ); - static_assert(sizeof(uint16_t) == 2, "int16_t is not of the correct size"); - static_assert(sizeof(uint32_t) == 4, "int32_t is not of the correct size"); - static_assert(sizeof(uint64_t) == 8, "int64_t is not of the correct size"); -} - -#endif diff --git a/supergameboy/nall/string.hpp b/supergameboy/nall/string.hpp deleted file mode 100644 index 65a4a4b8..00000000 --- a/supergameboy/nall/string.hpp +++ /dev/null @@ -1,26 +0,0 @@ -#ifndef NALL_STRING_HPP -#define NALL_STRING_HPP - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -namespace nall { - template<> struct has_length { enum { value = true }; }; - template<> struct has_size { enum { value = true }; }; -} - -#endif diff --git a/supergameboy/nall/string/base.hpp b/supergameboy/nall/string/base.hpp deleted file mode 100644 index 179a7dd4..00000000 --- a/supergameboy/nall/string/base.hpp +++ /dev/null @@ -1,137 +0,0 @@ -#ifndef NALL_STRING_BASE_HPP -#define NALL_STRING_BASE_HPP - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace nall { - class string; - template inline string to_string(T); - - class string { - public: - inline void reserve(unsigned); - inline unsigned length() const; - - inline string& assign(const char*); - inline string& append(const char*); - template inline string& operator= (T value); - template inline string& operator<<(T value); - - inline operator const char*() const; - inline char* operator()(); - inline char& operator[](int); - - inline bool operator==(const char*) const; - inline bool operator!=(const char*) const; - inline bool operator< (const char*) const; - inline bool operator<=(const char*) const; - inline bool operator> (const char*) const; - inline bool operator>=(const char*) const; - - inline string(); - inline string(const char*); - inline string(const string&); - inline string(string&&); - inline string& operator=(const string&); - inline string& operator=(string&&); - inline ~string(); - - inline bool readfile(const char*); - inline string& replace (const char*, const char*); - inline string& qreplace(const char*, const char*); - - protected: - char *data; - unsigned size; - - #if defined(QT_CORE_LIB) - public: - inline operator QString() const; - #endif - }; - - class lstring : public linear_vector { - public: - template inline lstring& operator<<(T value); - - inline int find(const char*); - inline void split (const char*, const char*, unsigned = 0); - inline void qsplit(const char*, const char*, unsigned = 0); - - lstring(); - lstring(std::initializer_list); - }; - - //compare.hpp - inline char chrlower(char c); - inline char chrupper(char c); - inline int stricmp(const char *dest, const char *src); - inline int strpos (const char *str, const char *key); - inline int qstrpos(const char *str, const char *key); - inline bool strbegin (const char *str, const char *key); - inline bool stribegin(const char *str, const char *key); - inline bool strend (const char *str, const char *key); - inline bool striend(const char *str, const char *key); - - //convert.hpp - inline char* strlower(char *str); - inline char* strupper(char *str); - inline char* strtr(char *dest, const char *before, const char *after); - inline uintmax_t strhex (const char *str); - inline intmax_t strsigned (const char *str); - inline uintmax_t strunsigned(const char *str); - inline uintmax_t strbin (const char *str); - inline double strdouble (const char *str); - - //match.hpp - inline bool match(const char *pattern, const char *str); - - //math.hpp - inline bool strint (const char *str, int &result); - inline bool strmath(const char *str, int &result); - - //strl.hpp - inline unsigned strlcpy(char *dest, const char *src, unsigned length); - inline unsigned strlcat(char *dest, const char *src, unsigned length); - - //trim.hpp - inline char* ltrim(char *str, const char *key = " "); - inline char* rtrim(char *str, const char *key = " "); - inline char* trim (char *str, const char *key = " "); - inline char* ltrim_once(char *str, const char *key = " "); - inline char* rtrim_once(char *str, const char *key = " "); - inline char* trim_once (char *str, const char *key = " "); - - //utility.hpp - inline unsigned strlcpy(string &dest, const char *src, unsigned length); - inline unsigned strlcat(string &dest, const char *src, unsigned length); - inline string substr(const char *src, unsigned start = 0, unsigned length = 0); - inline string& strlower(string &str); - inline string& strupper(string &str); - inline string& strtr(string &dest, const char *before, const char *after); - inline string& ltrim(string &str, const char *key = " "); - inline string& rtrim(string &str, const char *key = " "); - inline string& trim (string &str, const char *key = " "); - inline string& ltrim_once(string &str, const char *key = " "); - inline string& rtrim_once(string &str, const char *key = " "); - inline string& trim_once (string &str, const char *key = " "); - template inline string strhex(uintmax_t value); - template inline string strsigned(intmax_t value); - template inline string strunsigned(uintmax_t value); - template inline string strbin(uintmax_t value); - inline unsigned strdouble(char *str, double value); - inline string strdouble(double value); - - //variadic.hpp - template inline string sprint(Args... args); - template inline void print(Args... args); -}; - -#endif diff --git a/supergameboy/nall/string/cast.hpp b/supergameboy/nall/string/cast.hpp deleted file mode 100644 index 7b48eda0..00000000 --- a/supergameboy/nall/string/cast.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef NALL_STRING_CAST_HPP -#define NALL_STRING_CAST_HPP - -namespace nall { - -//this is needed, as C++0x does not support explicit template specialization inside classes -template<> inline string to_string (bool v) { return v ? "true" : "false"; } -template<> inline string to_string (signed int v) { return strsigned(v); } -template<> inline string to_string (unsigned int v) { return strunsigned(v); } -template<> inline string to_string (double v) { return strdouble(v); } -template<> inline string to_string (char *v) { return v; } -template<> inline string to_string (const char *v) { return v; } -template<> inline string to_string (string v) { return v; } -template<> inline string to_string(const string &v) { return v; } - -template string& string::operator= (T value) { return assign(to_string(value)); } -template string& string::operator<<(T value) { return append(to_string(value)); } - -template lstring& lstring::operator<<(T value) { - operator[](size()).assign(to_string(value)); - return *this; -} - -#if defined(QT_CORE_LIB) -template<> inline string to_string(QString v) { return v.toUtf8().constData(); } -template<> inline string to_string(const QString &v) { return v.toUtf8().constData(); } -string::operator QString() const { return QString::fromUtf8(*this); } -#endif - -} - -#endif diff --git a/supergameboy/nall/string/compare.hpp b/supergameboy/nall/string/compare.hpp deleted file mode 100644 index e1173de4..00000000 --- a/supergameboy/nall/string/compare.hpp +++ /dev/null @@ -1,104 +0,0 @@ -#ifndef NALL_STRING_COMPARE_HPP -#define NALL_STRING_COMPARE_HPP - -namespace nall { - -char chrlower(char c) { - return (c >= 'A' && c <= 'Z') ? c + ('a' - 'A') : c; -} - -char chrupper(char c) { - return (c >= 'a' && c <= 'z') ? c - ('a' - 'A') : c; -} - -int stricmp(const char *dest, const char *src) { - while(*dest) { - if(chrlower(*dest) != chrlower(*src)) break; - dest++; - src++; - } - - return (int)chrlower(*dest) - (int)chrlower(*src); -} - -int strpos(const char *str, const char *key) { - int ssl = strlen(str), ksl = strlen(key); - - if(ksl > ssl) return -1; - for(int i = 0; i <= ssl - ksl; i++) { - if(!memcmp(str + i, key, ksl)) { - return i; - } - } - return -1; -} - -int qstrpos(const char *str, const char *key) { - int ssl = strlen(str), ksl = strlen(key); - - if(ksl > ssl) return -1; - for(int i = 0; i <= ssl - ksl;) { - uint8_t x = str[i]; - if(x == '\"' || x == '\'') { - uint8_t z = i++; - while(str[i] != x && i < ssl) i++; - if(i >= ssl) i = z; - } - if(!memcmp(str + i, key, ksl)) { - return i; - } else { - i++; - } - } - return -1; -} - -bool strbegin(const char *str, const char *key) { - int i, ssl = strlen(str), ksl = strlen(key); - - if(ksl > ssl) return false; - return (!memcmp(str, key, ksl)); -} - -bool stribegin(const char *str, const char *key) { - int ssl = strlen(str), ksl = strlen(key); - - if(ksl > ssl) return false; - for(int i = 0; i < ksl; i++) { - if(str[i] >= 'A' && str[i] <= 'Z') { - if(str[i] != key[i] && str[i]+0x20 != key[i])return false; - } else if(str[i] >= 'a' && str[i] <= 'z') { - if(str[i] != key[i] && str[i]-0x20 != key[i])return false; - } else { - if(str[i] != key[i])return false; - } - } - return true; -} - -bool strend(const char *str, const char *key) { - int ssl = strlen(str), ksl = strlen(key); - - if(ksl > ssl) return false; - return (!memcmp(str + ssl - ksl, key, ksl)); -} - -bool striend(const char *str, const char *key) { - int ssl = strlen(str), ksl = strlen(key); - - if(ksl > ssl) return false; - for(int i = ssl - ksl, z = 0; i < ssl; i++, z++) { - if(str[i] >= 'A' && str[i] <= 'Z') { - if(str[i] != key[z] && str[i]+0x20 != key[z])return false; - } else if(str[i] >= 'a' && str[i] <= 'z') { - if(str[i] != key[z] && str[i]-0x20 != key[z])return false; - } else { - if(str[i] != key[z])return false; - } - } - return true; -} - -} - -#endif diff --git a/supergameboy/nall/string/convert.hpp b/supergameboy/nall/string/convert.hpp deleted file mode 100644 index 3ff134be..00000000 --- a/supergameboy/nall/string/convert.hpp +++ /dev/null @@ -1,153 +0,0 @@ -#ifndef NALL_STRING_CONVERT_HPP -#define NALL_STRING_CONVERT_HPP - -namespace nall { - -char* strlower(char *str) { - if(!str) return 0; - int i = 0; - while(str[i]) { - str[i] = chrlower(str[i]); - i++; - } - return str; -} - -char* strupper(char *str) { - if(!str) return 0; - int i = 0; - while(str[i]) { - str[i] = chrupper(str[i]); - i++; - } - return str; -} - -char* strtr(char *dest, const char *before, const char *after) { - if(!dest || !before || !after) return dest; - int sl = strlen(dest), bsl = strlen(before), asl = strlen(after); - - if(bsl != asl || bsl == 0) return dest; //patterns must be the same length for 1:1 replace - for(unsigned i = 0; i < sl; i++) { - for(unsigned l = 0; l < bsl; l++) { - if(dest[i] == before[l]) { - dest[i] = after[l]; - break; - } - } - } - - return dest; -} - -uintmax_t strhex(const char *str) { - if(!str) return 0; - uintmax_t result = 0; - - //skip hex identifiers 0x and $, if present - if(*str == '0' && (*(str + 1) == 'X' || *(str + 1) == 'x')) str += 2; - else if(*str == '$') str++; - - while(*str) { - uint8_t x = *str++; - if(x >= '0' && x <= '9') x -= '0'; - else if(x >= 'A' && x <= 'F') x -= 'A' - 10; - else if(x >= 'a' && x <= 'f') x -= 'a' - 10; - else break; //stop at first invalid character - result = result * 16 + x; - } - - return result; -} - -intmax_t strsigned(const char *str) { - if(!str) return 0; - intmax_t result = 0; - bool negate = false; - - //check for negation - if(*str == '-') { - negate = true; - str++; - } - - while(*str) { - uint8_t x = *str++; - if(x >= '0' && x <= '9') x -= '0'; - else break; //stop at first invalid character - result = result * 10 + x; - } - - return !negate ? result : -result; -} - -uintmax_t strunsigned(const char *str) { - if(!str) return 0; - uintmax_t result = 0; - - while(*str) { - uint8_t x = *str++; - if(x >= '0' && x <= '9') x -= '0'; - else break; //stop at first invalid character - result = result * 10 + x; - } - - return result; -} - -uintmax_t strbin(const char *str) { - if(!str) return 0; - uintmax_t result = 0; - - //skip bin identifiers 0b and %, if present - if(*str == '0' && (*(str + 1) == 'B' || *(str + 1) == 'b')) str += 2; - else if(*str == '%') str++; - - while(*str) { - uint8_t x = *str++; - if(x == '0' || x == '1') x -= '0'; - else break; //stop at first invalid character - result = result * 2 + x; - } - - return result; -} - -double strdouble(const char *str) { - if(!str) return 0.0; - bool negate = false; - - //check for negation - if(*str == '-') { - negate = true; - str++; - } - - intmax_t result_integral = 0; - while(*str) { - uint8_t x = *str++; - if(x >= '0' && x <= '9') x -= '0'; - else if(x == '.') break; //break loop and read fractional part - else return (double)result_integral; //invalid value, assume no fractional part - result_integral = result_integral * 10 + x; - } - - intmax_t result_fractional = 0; - while(*str) { - uint8_t x = *str++; - if(x >= '0' && x <= '9') x -= '0'; - else break; //stop at first invalid character - result_fractional = result_fractional * 10 + x; - } - - //calculate fractional portion - double result = (double)result_fractional; - while((uintmax_t)result > 0) result /= 10.0; - result += (double)result_integral; - - return !negate ? result : -result; -} - -} - -#endif diff --git a/supergameboy/nall/string/core.hpp b/supergameboy/nall/string/core.hpp deleted file mode 100644 index d13bfc38..00000000 --- a/supergameboy/nall/string/core.hpp +++ /dev/null @@ -1,133 +0,0 @@ -#ifndef NALL_STRING_CORE_HPP -#define NALL_STRING_CORE_HPP - -namespace nall { - -void string::reserve(unsigned size_) { - if(size_ > size) { - size = size_; - data = (char*)realloc(data, size + 1); - data[size] = 0; - } -} - -unsigned string::length() const { - return strlen(data); -} - -string& string::assign(const char *s) { - unsigned length = strlen(s); - reserve(length); - strcpy(data, s); - return *this; -} - -string& string::append(const char *s) { - unsigned length = strlen(data) + strlen(s); - reserve(length); - strcat(data, s); - return *this; -} - -string::operator const char*() const { - return data; -} - -char* string::operator()() { - return data; -} - -char& string::operator[](int index) { - reserve(index); - return data[index]; -} - -bool string::operator==(const char *str) const { return strcmp(data, str) == 0; } -bool string::operator!=(const char *str) const { return strcmp(data, str) != 0; } -bool string::operator< (const char *str) const { return strcmp(data, str) < 0; } -bool string::operator<=(const char *str) const { return strcmp(data, str) <= 0; } -bool string::operator> (const char *str) const { return strcmp(data, str) > 0; } -bool string::operator>=(const char *str) const { return strcmp(data, str) >= 0; } - -string::string() { - size = 64; - data = (char*)malloc(size + 1); - *data = 0; -} - -string::string(const char *value) { - size = strlen(value); - data = strdup(value); -} - -string::string(const string &value) { - size = strlen(value); - data = strdup(value); -} - -string::string(string &&source) { - size = source.size; - data = source.data; - source.data = 0; -} - -string& string::operator=(const string &value) { - assign(value); - return *this; -} - -string& string::operator=(string &&source) { - if(data) free(data); - size = source.size; - data = source.data; - source.data = 0; - source.size = 0; - return *this; -} - -string::~string() { - free(data); -} - -bool string::readfile(const char *filename) { - assign(""); - - #if !defined(_WIN32) - FILE *fp = fopen(filename, "rb"); - #else - FILE *fp = _wfopen(utf16_t(filename), L"rb"); - #endif - if(!fp) return false; - - fseek(fp, 0, SEEK_END); - unsigned size = ftell(fp); - rewind(fp); - char *fdata = new char[size + 1]; - unsigned unused = fread(fdata, 1, size, fp); - fclose(fp); - fdata[size] = 0; - assign(fdata); - delete[] fdata; - - return true; -} - -int lstring::find(const char *key) { - for(unsigned i = 0; i < size(); i++) { - if(operator[](i) == key) return i; - } - return -1; -} - -inline lstring::lstring() { -} - -inline lstring::lstring(std::initializer_list list) { - for(const string *s = list.begin(); s != list.end(); ++s) { - operator<<(*s); - } -} - -} - -#endif diff --git a/supergameboy/nall/string/filename.hpp b/supergameboy/nall/string/filename.hpp deleted file mode 100644 index f3750760..00000000 --- a/supergameboy/nall/string/filename.hpp +++ /dev/null @@ -1,61 +0,0 @@ -#ifndef NALL_FILENAME_HPP -#define NALL_FILENAME_HPP - -namespace nall { - -// "foo/bar.c" -> "foo/", "bar.c" -> "./" -inline string dir(char const *name) { - string result = name; - for(signed i = strlen(result); i >= 0; i--) { - if(result[i] == '/' || result[i] == '\\') { - result[i + 1] = 0; - break; - } - if(i == 0) result = "./"; - } - return result; -} - -// "foo/bar.c" -> "bar.c" -inline string notdir(char const *name) { - for(signed i = strlen(name); i >= 0; i--) { - if(name[i] == '/' || name[i] == '\\') { - name += i + 1; - break; - } - } - string result = name; - return result; -} - -// "foo/bar.c" -> "foo/bar" -inline string basename(char const *name) { - string result = name; - for(signed i = strlen(result); i >= 0; i--) { - if(result[i] == '/' || result[i] == '\\') { - //file has no extension - break; - } - if(result[i] == '.') { - result[i] = 0; - break; - } - } - return result; -} - -// "foo/bar.c" -> "c" -inline string extension(char const *name) { - for(signed i = strlen(name); i >= 0; i--) { - if(name[i] == '.') { - name += i + 1; - break; - } - } - string result = name; - return result; -} - -} - -#endif diff --git a/supergameboy/nall/string/match.hpp b/supergameboy/nall/string/match.hpp deleted file mode 100644 index d8cf702d..00000000 --- a/supergameboy/nall/string/match.hpp +++ /dev/null @@ -1,76 +0,0 @@ -#ifndef NALL_STRING_MATCH_HPP -#define NALL_STRING_MATCH_HPP - -namespace nall { - -bool match(const char *p, const char *s) { - const char *p_ = 0, *s_ = 0; - - for(;;) { - if(!*s) { - while(*p == '*') p++; - return !*p; - } - - //wildcard match - if(*p == '*') { - p_ = p++, s_ = s; - continue; - } - - //any match - if(*p == '?') { - p++, s++; - continue; - } - - //ranged match - if(*p == '{') { - #define pattern(name_, rule_) \ - if(strbegin(p, name_)) { \ - if(rule_) { \ - p += sizeof(name_) - 1, s++; \ - continue; \ - } \ - goto failure; \ - } - - pattern("{alpha}", (*s >= 'A' && *s <= 'Z') || (*s >= 'a' && *s <= 'z')) - pattern("{alphanumeric}", (*s >= 'A' && *s <= 'Z') || (*s >= 'a' && *s <= 'z') || (*s >= '0' && *s <= '9')) - pattern("{binary}", (*s == '0' || *s == '1')) - pattern("{hex}", (*s >= '0' && *s <= '9') || (*s >= 'A' && *s <= 'F') || (*s >= 'a' && *s <= 'f')) - pattern("{lowercase}", (*s >= 'a' && *s <= 'z')) - pattern("{numeric}", (*s >= '0' && *s <= '9')) - pattern("{uppercase}", (*s >= 'A' && *s <= 'Z')) - pattern("{whitespace}", (*s == ' ' || *s == '\t')) - - #undef pattern - goto failure; - } - - //reserved character match - if(*p == '\\') { - p++; - //fallthrough - } - - //literal match - if(*p == *s) { - p++, *s++; - continue; - } - - //attempt wildcard rematch - failure: - if(p_) { - p = p_, s = s_ + 1; - continue; - } - - return false; - } -} - -} - -#endif diff --git a/supergameboy/nall/string/math.hpp b/supergameboy/nall/string/math.hpp deleted file mode 100644 index ea8b99c8..00000000 --- a/supergameboy/nall/string/math.hpp +++ /dev/null @@ -1,164 +0,0 @@ -#ifndef NALL_STRING_MATH_HPP -#define NALL_STRING_MATH_HPP - -namespace nall { - -static int eval_integer(const char *&s) { - if(!*s) throw "unrecognized_integer"; - int value = 0, x = *s, y = *(s + 1); - - //hexadecimal - if(x == '0' && (y == 'X' || y == 'x')) { - s += 2; - while(true) { - if(*s >= '0' && *s <= '9') { value = value * 16 + (*s++ - '0'); continue; } - if(*s >= 'A' && *s <= 'F') { value = value * 16 + (*s++ - 'A' + 10); continue; } - if(*s >= 'a' && *s <= 'f') { value = value * 16 + (*s++ - 'a' + 10); continue; } - return value; - } - } - - //binary - if(x == '0' && (y == 'B' || y == 'b')) { - s += 2; - while(true) { - if(*s == '0' || *s == '1') { value = value * 2 + (*s++ - '0'); continue; } - return value; - } - } - - //octal (or decimal '0') - if(x == '0') { - s += 1; - while(true) { - if(*s >= '0' && *s <= '7') { value = value * 8 + (*s++ - '0'); continue; } - return value; - } - } - - //decimal - if(x >= '0' && x <= '9') { - while(true) { - if(*s >= '0' && *s <= '9') { value = value * 10 + (*s++ - '0'); continue; } - return value; - } - } - - //char - if(x == '\'' && y != '\'') { - s += 1; - while(true) { - value = value * 256 + *s++; - if(*s == '\'') { s += 1; return value; } - if(!*s) throw "mismatched_char"; - } - } - - throw "unrecognized_integer"; -} - -static int eval(const char *&s, int depth = 0) { - while(*s == ' ' || *s == '\t') s++; //trim whitespace - if(!*s) throw "unrecognized_token"; - int value = 0, x = *s, y = *(s + 1); - - if(*s == '(') { - value = eval(++s, 1); - if(*s++ != ')') throw "mismatched_group"; - } - - else if(x == '!') value = !eval(++s, 13); - else if(x == '~') value = ~eval(++s, 13); - else if(x == '+') value = +eval(++s, 13); - else if(x == '-') value = -eval(++s, 13); - - else if((x >= '0' && x <= '9') || x == '\'') value = eval_integer(s); - - else throw "unrecognized_token"; - - while(true) { - while(*s == ' ' || *s == '\t') s++; //trim whitespace - if(!*s) break; - x = *s, y = *(s + 1); - - if(depth >= 13) break; - if(x == '*') { value *= eval(++s, 13); continue; } - if(x == '/') { value /= eval(++s, 13); continue; } - if(x == '%') { value %= eval(++s, 13); continue; } - - if(depth >= 12) break; - if(x == '+') { value += eval(++s, 12); continue; } - if(x == '-') { value -= eval(++s, 12); continue; } - - if(depth >= 11) break; - if(x == '<' && y == '<') { value <<= eval(++++s, 11); continue; } - if(x == '>' && y == '>') { value >>= eval(++++s, 11); continue; } - - if(depth >= 10) break; - if(x == '<' && y == '=') { value = value <= eval(++++s, 10); continue; } - if(x == '>' && y == '=') { value = value >= eval(++++s, 10); continue; } - if(x == '<') { value = value < eval(++s, 10); continue; } - if(x == '>') { value = value > eval(++s, 10); continue; } - - if(depth >= 9) break; - if(x == '=' && y == '=') { value = value == eval(++++s, 9); continue; } - if(x == '!' && y == '=') { value = value != eval(++++s, 9); continue; } - - if(depth >= 8) break; - if(x == '&' && y != '&') { value = value & eval(++s, 8); continue; } - - if(depth >= 7) break; - if(x == '^' && y != '^') { value = value ^ eval(++s, 7); continue; } - - if(depth >= 6) break; - if(x == '|' && y != '|') { value = value | eval(++s, 6); continue; } - - if(depth >= 5) break; - if(x == '&' && y == '&') { value = eval(++++s, 5) && value; continue; } - - if(depth >= 4) break; - if(x == '^' && y == '^') { value = (!eval(++++s, 4) != !value); continue; } - - if(depth >= 3) break; - if(x == '|' && y == '|') { value = eval(++++s, 3) || value; continue; } - - if(x == '?') { - int lhs = eval(++s, 2); - if(*s != ':') throw "mismatched_ternary"; - int rhs = eval(++s, 2); - value = value ? lhs : rhs; - continue; - } - if(depth >= 2) break; - - if(depth > 0 && x == ')') break; - - throw "unrecognized_token"; - } - - return value; -} - -bool strint(const char *s, int &result) { - try { - result = eval_integer(s); - return true; - } catch(const char*) { - result = 0; - return false; - } -} - -bool strmath(const char *s, int &result) { - try { - result = eval(s); - return true; - } catch(const char*) { - result = 0; - return false; - } -} - -} - -#endif diff --git a/supergameboy/nall/string/replace.hpp b/supergameboy/nall/string/replace.hpp deleted file mode 100644 index db405a9b..00000000 --- a/supergameboy/nall/string/replace.hpp +++ /dev/null @@ -1,103 +0,0 @@ -#ifndef NALL_STRING_REPLACE_HPP -#define NALL_STRING_REPLACE_HPP - -namespace nall { - -string& string::replace(const char *key, const char *token) { - int i, z, ksl = strlen(key), tsl = strlen(token), ssl = length(); - unsigned int replace_count = 0, size = ssl; - char *buffer; - - if(ksl <= ssl) { - if(tsl > ksl) { //the new string may be longer than the old string... - for(i = 0; i <= ssl - ksl;) { //so let's find out how big of a string we'll need... - if(!memcmp(data + i, key, ksl)) { - replace_count++; - i += ksl; - } else i++; - } - size = ssl + ((tsl - ksl) * replace_count); - reserve(size); - } - - buffer = new char[size + 1]; - for(i = z = 0; i < ssl;) { - if(i <= ssl - ksl) { - if(!memcmp(data + i, key, ksl)) { - memcpy(buffer + z, token, tsl); - z += tsl; - i += ksl; - } else buffer[z++] = data[i++]; - } else buffer[z++] = data[i++]; - } - buffer[z] = 0; - - assign(buffer); - delete[] buffer; - } - - return *this; -} - -string& string::qreplace(const char *key, const char *token) { - int i, l, z, ksl = strlen(key), tsl = strlen(token), ssl = length(); - unsigned int replace_count = 0, size = ssl; - uint8_t x; - char *buffer; - - if(ksl <= ssl) { - if(tsl > ksl) { - for(i = 0; i <= ssl - ksl;) { - x = data[i]; - if(x == '\"' || x == '\'') { - l = i; - i++; - while(data[i++] != x) { - if(i == ssl) { - i = l; - break; - } - } - } - if(!memcmp(data + i, key, ksl)) { - replace_count++; - i += ksl; - } else i++; - } - size = ssl + ((tsl - ksl) * replace_count); - reserve(size); - } - - buffer = new char[size + 1]; - for(i = z = 0; i < ssl;) { - x = data[i]; - if(x == '\"' || x == '\'') { - l = i++; - while(data[i] != x && i < ssl)i++; - if(i >= ssl)i = l; - else { - memcpy(buffer + z, data + l, i - l); - z += i - l; - } - } - if(i <= ssl - ksl) { - if(!memcmp(data + i, key, ksl)) { - memcpy(buffer + z, token, tsl); - z += tsl; - i += ksl; - replace_count++; - } else buffer[z++] = data[i++]; - } else buffer[z++] = data[i++]; - } - buffer[z] = 0; - - assign(buffer); - delete[] buffer; - } - - return *this; -} - -}; - -#endif diff --git a/supergameboy/nall/string/split.hpp b/supergameboy/nall/string/split.hpp deleted file mode 100644 index bb77dfcd..00000000 --- a/supergameboy/nall/string/split.hpp +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef NALL_STRING_SPLIT_HPP -#define NALL_STRING_SPLIT_HPP - -namespace nall { - -void lstring::split(const char *key, const char *src, unsigned limit) { - reset(); - - int ssl = strlen(src), ksl = strlen(key); - int lp = 0, split_count = 0; - - for(int i = 0; i <= ssl - ksl;) { - if(!memcmp(src + i, key, ksl)) { - strlcpy(operator[](split_count++), src + lp, i - lp + 1); - i += ksl; - lp = i; - if(!--limit) break; - } else i++; - } - - operator[](split_count++) = src + lp; -} - -void lstring::qsplit(const char *key, const char *src, unsigned limit) { - reset(); - - int ssl = strlen(src), ksl = strlen(key); - int lp = 0, split_count = 0; - - for(int i = 0; i <= ssl - ksl;) { - uint8_t x = src[i]; - - if(x == '\"' || x == '\'') { - int z = i++; //skip opening quote - while(i < ssl && src[i] != x) i++; - if(i >= ssl) i = z; //failed match, rewind i - else { - i++; //skip closing quote - continue; //restart in case next char is also a quote - } - } - - if(!memcmp(src + i, key, ksl)) { - strlcpy(operator[](split_count++), src + lp, i - lp + 1); - i += ksl; - lp = i; - if(!--limit) break; - } else i++; - } - - operator[](split_count++) = src + lp; -} - -}; - -#endif diff --git a/supergameboy/nall/string/strl.hpp b/supergameboy/nall/string/strl.hpp deleted file mode 100644 index 84c841fa..00000000 --- a/supergameboy/nall/string/strl.hpp +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef NALL_STRING_STRL_HPP -#define NALL_STRING_STRL_HPP - -namespace nall { - -//strlcpy, strlcat based on OpenBSD implementation by Todd C. Miller - -//return = strlen(src) -unsigned strlcpy(char *dest, const char *src, unsigned length) { - char *d = dest; - const char *s = src; - unsigned n = length; - - if(n) { - while(--n && (*d++ = *s++)); //copy as many bytes as possible, or until null terminator reached - } - - if(!n) { - if(length) *d = 0; - while(*s++); //traverse rest of s, so that s - src == strlen(src) - } - - return (s - src - 1); //return length of copied string, sans null terminator -} - -//return = strlen(src) + min(length, strlen(dest)) -unsigned strlcat(char *dest, const char *src, unsigned length) { - char *d = dest; - const char *s = src; - unsigned n = length; - - while(n-- && *d) d++; //find end of dest - unsigned dlength = d - dest; - n = length - dlength; //subtract length of dest from maximum string length - - if(!n) return dlength + strlen(s); - - while(*s) { - if(n != 1) { - *d++ = *s; - n--; - } - s++; - } - *d = 0; - - return dlength + (s - src); //return length of resulting string, sans null terminator -} - -} - -#endif diff --git a/supergameboy/nall/string/trim.hpp b/supergameboy/nall/string/trim.hpp deleted file mode 100644 index b13ab9ba..00000000 --- a/supergameboy/nall/string/trim.hpp +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef NALL_STRING_TRIM_HPP -#define NALL_STRING_TRIM_HPP - -namespace nall { - -char* ltrim(char *str, const char *key) { - if(!key || !*key) return str; - while(strbegin(str, key)) { - char *dest = str, *src = str + strlen(key); - while(true) { - *dest = *src++; - if(!*dest) break; - dest++; - } - } - return str; -} - -char* rtrim(char *str, const char *key) { - if(!key || !*key) return str; - while(strend(str, key)) str[strlen(str) - strlen(key)] = 0; - return str; -} - -char* trim(char *str, const char *key) { - return ltrim(rtrim(str, key), key); -} - -char* ltrim_once(char *str, const char *key) { - if(!key || !*key) return str; - if(strbegin(str, key)) { - char *dest = str, *src = str + strlen(key); - while(true) { - *dest = *src++; - if(!*dest) break; - dest++; - } - } - return str; -} - -char* rtrim_once(char *str, const char *key) { - if(!key || !*key) return str; - if(strend(str, key)) str[strlen(str) - strlen(key)] = 0; - return str; -} - -char* trim_once(char *str, const char *key) { - return ltrim_once(rtrim_once(str, key), key); -} - -} - -#endif diff --git a/supergameboy/nall/string/utility.hpp b/supergameboy/nall/string/utility.hpp deleted file mode 100644 index 2da2762b..00000000 --- a/supergameboy/nall/string/utility.hpp +++ /dev/null @@ -1,169 +0,0 @@ -#ifndef NALL_STRING_UTILITY_HPP -#define NALL_STRING_UTILITY_HPP - -namespace nall { - -unsigned strlcpy(string &dest, const char *src, unsigned length) { - dest.reserve(length); - return strlcpy(dest(), src, length); -} - -unsigned strlcat(string &dest, const char *src, unsigned length) { - dest.reserve(length); - return strlcat(dest(), src, length); -} - -string substr(const char *src, unsigned start, unsigned length) { - string dest; - if(length == 0) { - //copy entire string - dest = src + start; - } else { - //copy partial string - strlcpy(dest, src + start, length + 1); - } - return dest; -} - -/* very simplistic wrappers to return string& instead of char* type */ - -string& strlower(string &str) { strlower(str()); return str; } -string& strupper(string &str) { strupper(str()); return str; } -string& strtr(string &dest, const char *before, const char *after) { strtr(dest(), before, after); return dest; } -string& ltrim(string &str, const char *key) { ltrim(str(), key); return str; } -string& rtrim(string &str, const char *key) { rtrim(str(), key); return str; } -string& trim (string &str, const char *key) { trim (str(), key); return str; } -string& ltrim_once(string &str, const char *key) { ltrim_once(str(), key); return str; } -string& rtrim_once(string &str, const char *key) { rtrim_once(str(), key); return str; } -string& trim_once (string &str, const char *key) { trim_once (str(), key); return str; } - -/* arithmetic <> string */ - -template string strhex(uintmax_t value) { - string output; - unsigned offset = 0; - - //render string backwards, as we do not know its length yet - do { - unsigned n = value & 15; - output[offset++] = n < 10 ? '0' + n : 'a' + n - 10; - value >>= 4; - } while(value); - - while(offset < length) output[offset++] = padding; - output[offset--] = 0; - - //reverse the string in-place - for(unsigned i = 0; i < (offset + 1) >> 1; i++) { - char temp = output[i]; - output[i] = output[offset - i]; - output[offset - i] = temp; - } - - return output; -} - -template string strsigned(intmax_t value) { - string output; - unsigned offset = 0; - - bool negative = value < 0; - if(negative) value = abs(value); - - do { - unsigned n = value % 10; - output[offset++] = '0' + n; - value /= 10; - } while(value); - - while(offset < length) output[offset++] = padding; - if(negative) output[offset++] = '-'; - output[offset--] = 0; - - for(unsigned i = 0; i < (offset + 1) >> 1; i++) { - char temp = output[i]; - output[i] = output[offset - i]; - output[offset - i] = temp; - } - - return output; -} - -template string strunsigned(uintmax_t value) { - string output; - unsigned offset = 0; - - do { - unsigned n = value % 10; - output[offset++] = '0' + n; - value /= 10; - } while(value); - - while(offset < length) output[offset++] = padding; - output[offset--] = 0; - - for(unsigned i = 0; i < (offset + 1) >> 1; i++) { - char temp = output[i]; - output[i] = output[offset - i]; - output[offset - i] = temp; - } - - return output; -} - -template string strbin(uintmax_t value) { - string output; - unsigned offset = 0; - - do { - unsigned n = value & 1; - output[offset++] = '0' + n; - value >>= 1; - } while(value); - - while(offset < length) output[offset++] = padding; - output[offset--] = 0; - - for(unsigned i = 0; i < (offset + 1) >> 1; i++) { - char temp = output[i]; - output[i] = output[offset - i]; - output[offset - i] = temp; - } - - return output; -} - -//using sprintf is certainly not the most ideal method to convert -//a double to a string ... but attempting to parse a double by -//hand, digit-by-digit, results in subtle rounding errors. -unsigned strdouble(char *str, double value) { - char buffer[256]; - sprintf(buffer, "%f", value); - - //remove excess 0's in fraction (2.500000 -> 2.5) - for(char *p = buffer; *p; p++) { - if(*p == '.') { - char *p = buffer + strlen(buffer) - 1; - while(*p == '0') { - if(*(p - 1) != '.') *p = 0; //... but not for eg 1.0 -> 1. - p--; - } - break; - } - } - - unsigned length = strlen(buffer); - if(str) strcpy(str, buffer); - return length + 1; -} - -string strdouble(double value) { - string temp; - temp.reserve(strdouble(0, value)); - strdouble(temp(), value); - return temp; -} - -} - -#endif diff --git a/supergameboy/nall/string/variadic.hpp b/supergameboy/nall/string/variadic.hpp deleted file mode 100644 index 13c477a8..00000000 --- a/supergameboy/nall/string/variadic.hpp +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef NALL_STRING_VARIADIC_HPP -#define NALL_STRING_VARIADIC_HPP - -namespace nall { - -static void isprint(string &output) { -} - -template -static void isprint(string &output, T value, Args... args) { - output << to_string(value); - isprint(output, args...); -} - -template inline string sprint(Args... args) { - string output; - isprint(output, args...); - return output; -} - -template inline void print(Args... args) { - printf("%s", (const char*)sprint(args...)); -} - -} - -#endif diff --git a/supergameboy/nall/string/xml.hpp b/supergameboy/nall/string/xml.hpp deleted file mode 100644 index d423f87f..00000000 --- a/supergameboy/nall/string/xml.hpp +++ /dev/null @@ -1,257 +0,0 @@ -#ifndef NALL_STRING_XML_HPP -#define NALL_STRING_XML_HPP - -//XML subset parser -//version 0.05 - -namespace nall { - -struct xml_attribute { - string name; - string content; - virtual string parse() const; -}; - -struct xml_element : xml_attribute { - string parse() const; - linear_vector attribute; - linear_vector element; - -protected: - void parse_doctype(const char *&data); - bool parse_head(string data); - bool parse_body(const char *&data); - friend xml_element xml_parse(const char *data); -}; - -inline string xml_attribute::parse() const { - string data; - unsigned offset = 0; - - const char *source = content; - while(*source) { - if(*source == '&') { - if(strbegin(source, "<")) { data[offset++] = '<'; source += 4; continue; } - if(strbegin(source, ">")) { data[offset++] = '>'; source += 4; continue; } - if(strbegin(source, "&")) { data[offset++] = '&'; source += 5; continue; } - if(strbegin(source, "'")) { data[offset++] = '\''; source += 6; continue; } - if(strbegin(source, """)) { data[offset++] = '"'; source += 6; continue; } - } - - //reject illegal characters - if(*source == '&') return ""; - if(*source == '<') return ""; - if(*source == '>') return ""; - - data[offset++] = *source++; - } - - data[offset] = 0; - return data; -} - -inline string xml_element::parse() const { - string data; - unsigned offset = 0; - - const char *source = content; - while(*source) { - if(*source == '&') { - if(strbegin(source, "<")) { data[offset++] = '<'; source += 4; continue; } - if(strbegin(source, ">")) { data[offset++] = '>'; source += 4; continue; } - if(strbegin(source, "&")) { data[offset++] = '&'; source += 5; continue; } - if(strbegin(source, "'")) { data[offset++] = '\''; source += 6; continue; } - if(strbegin(source, """)) { data[offset++] = '"'; source += 6; continue; } - } - - if(strbegin(source, ""); - if(pos == -1) return ""; - source += pos + 3; - continue; - } - - if(strbegin(source, ""); - if(pos == -1) return ""; - string cdata = substr(source, 9, pos - 9); - data << cdata; - offset += strlen(cdata); - - source += offset + 3; - continue; - } - - //reject illegal characters - if(*source == '&') return ""; - if(*source == '<') return ""; - if(*source == '>') return ""; - - data[offset++] = *source++; - } - - data[offset] = 0; - return data; -} - -inline void xml_element::parse_doctype(const char *&data) { - name = "!DOCTYPE"; - const char *content_begin = data; - - signed counter = 0; - while(*data) { - char value = *data++; - if(value == '<') counter++; - if(value == '>') counter--; - if(counter < 0) { - content = substr(content_begin, 0, data - content_begin - 1); - return; - } - } - throw "..."; -} - -inline bool xml_element::parse_head(string data) { - data.qreplace("\t", " "); - data.qreplace("\r", " "); - data.qreplace("\n", " "); - while(qstrpos(data, " ") >= 0) data.qreplace(" ", " "); - data.qreplace(" =", "="); - data.qreplace("= ", "="); - rtrim(data); - - lstring part; - part.qsplit(" ", data); - - name = part[0]; - if(name == "") throw "..."; - - for(unsigned i = 1; i < part.size(); i++) { - lstring side; - side.qsplit("=", part[i]); - if(side.size() != 2) throw "..."; - - xml_attribute attr; - attr.name = side[0]; - attr.content = side[1]; - if(strbegin(attr.content, "\"") && strend(attr.content, "\"")) trim_once(attr.content, "\""); - else if(strbegin(attr.content, "'") && strend(attr.content, "'")) trim_once(attr.content, "'"); - else throw "..."; - attribute.add(attr); - } -} - -inline bool xml_element::parse_body(const char *&data) { - while(true) { - if(!*data) return false; - if(*data++ != '<') continue; - if(*data == '/') return false; - - if(strbegin(data, "!DOCTYPE") == true) { - parse_doctype(data); - return true; - } - - if(strbegin(data, "!--")) { - signed offset = strpos(data, "-->"); - if(offset == -1) throw "..."; - data += offset + 3; - continue; - } - - if(strbegin(data, "![CDATA[")) { - signed offset = strpos(data, "]]>"); - if(offset == -1) throw "..."; - data += offset + 3; - continue; - } - - signed offset = strpos(data, ">"); - if(offset == -1) throw "..."; - - string tag = substr(data, 0, offset); - data += offset + 1; - const char *content_begin = data; - - bool self_terminating = false; - - if(strend(tag, "?") == true) { - self_terminating = true; - rtrim_once(tag, "?"); - } else if(strend(tag, "/") == true) { - self_terminating = true; - rtrim_once(tag, "/"); - } - - parse_head(tag); - if(self_terminating) return true; - - while(*data) { - unsigned index = element.size(); - xml_element node; - if(node.parse_body(data) == false) { - if(*data == '/') { - signed length = data - content_begin - 1; - if(length > 0) content = substr(content_begin, 0, length); - - data++; - offset = strpos(data, ">"); - if(offset == -1) throw "..."; - - tag = substr(data, 0, offset); - data += offset + 1; - - tag.replace("\t", " "); - tag.replace("\r", " "); - tag.replace("\n", " "); - while(strpos(tag, " ") >= 0) tag.replace(" ", " "); - rtrim(tag); - - if(name != tag) throw "..."; - return true; - } - } else { - element.add(node); - } - } - } -} - -//ensure there is only one root element -inline bool xml_validate(xml_element &document) { - unsigned root_counter = 0; - - for(unsigned i = 0; i < document.element.size(); i++) { - string &name = document.element[i].name; - if(strbegin(name, "?")) continue; - if(strbegin(name, "!")) continue; - if(++root_counter > 1) return false; - } - - return true; -} - -inline xml_element xml_parse(const char *data) { - xml_element self; - - try { - while(*data) { - xml_element node; - if(node.parse_body(data) == false) { - break; - } else { - self.element.add(node); - } - } - - if(xml_validate(self) == false) throw "..."; - return self; - } catch(const char*) { - xml_element empty; - return empty; - } -} - -} - -#endif diff --git a/supergameboy/nall/ups.hpp b/supergameboy/nall/ups.hpp deleted file mode 100644 index f255ecb3..00000000 --- a/supergameboy/nall/ups.hpp +++ /dev/null @@ -1,190 +0,0 @@ -#ifndef NALL_UPS_HPP -#define NALL_UPS_HPP - -#include - -#include -#include -#include -#include - -namespace nall { - class ups { - public: - enum result { - ok, - patch_unreadable, - patch_unwritable, - patch_invalid, - input_invalid, - output_invalid, - patch_crc32_invalid, - input_crc32_invalid, - output_crc32_invalid, - }; - - ups::result create(const char *patch_fn, const uint8_t *x_data, unsigned x_size, const uint8_t *y_data, unsigned y_size) { - if(!fp.open(patch_fn, file::mode_write)) return patch_unwritable; - - crc32 = ~0; - uint32_t x_crc32 = crc32_calculate(x_data, x_size); - uint32_t y_crc32 = crc32_calculate(y_data, y_size); - - //header - write('U'); - write('P'); - write('S'); - write('1'); - encptr(x_size); - encptr(y_size); - - //body - unsigned max_size = max(x_size, y_size); - unsigned relative = 0; - for(unsigned i = 0; i < max_size;) { - uint8_t x = i < x_size ? x_data[i] : 0x00; - uint8_t y = i < y_size ? y_data[i] : 0x00; - - if(x == y) { - i++; - continue; - } - - encptr(i++ - relative); - write(x ^ y); - - while(true) { - if(i >= max_size) { - write(0x00); - break; - } - - x = i < x_size ? x_data[i] : 0x00; - y = i < y_size ? y_data[i] : 0x00; - i++; - write(x ^ y); - if(x == y) break; - } - - relative = i; - } - - //footer - for(unsigned i = 0; i < 4; i++) write(x_crc32 >> (i << 3)); - for(unsigned i = 0; i < 4; i++) write(y_crc32 >> (i << 3)); - uint32_t p_crc32 = ~crc32; - for(unsigned i = 0; i < 4; i++) write(p_crc32 >> (i << 3)); - - fp.close(); - return ok; - } - - ups::result apply(const uint8_t *p_data, unsigned p_size, const uint8_t *x_data, unsigned x_size, uint8_t *&y_data, unsigned &y_size) { - if(p_size < 18) return patch_invalid; - p_buffer = p_data; - - crc32 = ~0; - - //header - if(read() != 'U') return patch_invalid; - if(read() != 'P') return patch_invalid; - if(read() != 'S') return patch_invalid; - if(read() != '1') return patch_invalid; - - unsigned px_size = decptr(); - unsigned py_size = decptr(); - - //mirror - if(x_size != px_size && x_size != py_size) return input_invalid; - y_size = (x_size == px_size) ? py_size : px_size; - y_data = new uint8_t[y_size](); - - for(unsigned i = 0; i < x_size && i < y_size; i++) y_data[i] = x_data[i]; - for(unsigned i = x_size; i < y_size; i++) y_data[i] = 0x00; - - //body - unsigned relative = 0; - while(p_buffer < p_data + p_size - 12) { - relative += decptr(); - - while(true) { - uint8_t x = read(); - if(x && relative < y_size) { - uint8_t y = relative < x_size ? x_data[relative] : 0x00; - y_data[relative] = x ^ y; - } - relative++; - if(!x) break; - } - } - - //footer - unsigned px_crc32 = 0, py_crc32 = 0, pp_crc32 = 0; - for(unsigned i = 0; i < 4; i++) px_crc32 |= read() << (i << 3); - for(unsigned i = 0; i < 4; i++) py_crc32 |= read() << (i << 3); - uint32_t p_crc32 = ~crc32; - for(unsigned i = 0; i < 4; i++) pp_crc32 |= read() << (i << 3); - - uint32_t x_crc32 = crc32_calculate(x_data, x_size); - uint32_t y_crc32 = crc32_calculate(y_data, y_size); - - if(px_size != py_size) { - if(x_size == px_size && x_crc32 != px_crc32) return input_crc32_invalid; - if(x_size == py_size && x_crc32 != py_crc32) return input_crc32_invalid; - if(y_size == px_size && y_crc32 != px_crc32) return output_crc32_invalid; - if(y_size == py_size && y_crc32 != py_crc32) return output_crc32_invalid; - } else { - if(x_crc32 != px_crc32 && x_crc32 != py_crc32) return input_crc32_invalid; - if(y_crc32 != px_crc32 && y_crc32 != py_crc32) return output_crc32_invalid; - if(x_crc32 == y_crc32 && px_crc32 != py_crc32) return output_crc32_invalid; - if(x_crc32 != y_crc32 && px_crc32 == py_crc32) return output_crc32_invalid; - } - - if(p_crc32 != pp_crc32) return patch_crc32_invalid; - return ok; - } - - private: - file fp; - uint32_t crc32; - const uint8_t *p_buffer; - - uint8_t read() { - uint8_t n = *p_buffer++; - crc32 = crc32_adjust(crc32, n); - return n; - } - - void write(uint8_t n) { - fp.write(n); - crc32 = crc32_adjust(crc32, n); - } - - void encptr(uint64_t offset) { - while(true) { - uint64_t x = offset & 0x7f; - offset >>= 7; - if(offset == 0) { - write(0x80 | x); - break; - } - write(x); - offset--; - } - } - - uint64_t decptr() { - uint64_t offset = 0, shift = 1; - while(true) { - uint8_t x = read(); - offset += (x & 0x7f) * shift; - if(x & 0x80) break; - shift <<= 7; - offset += shift; - } - return offset; - } - }; -} - -#endif diff --git a/supergameboy/nall/utf8.hpp b/supergameboy/nall/utf8.hpp deleted file mode 100644 index c66c341a..00000000 --- a/supergameboy/nall/utf8.hpp +++ /dev/null @@ -1,72 +0,0 @@ -#ifndef NALL_UTF8_HPP -#define NALL_UTF8_HPP - -//UTF-8 <> UTF-16 conversion -//used only for Win32; Linux, etc use UTF-8 internally - -#if defined(_WIN32) - -#undef _WIN32_WINNT -#define _WIN32_WINNT 0x0501 -#undef NOMINMAX -#define NOMINMAX -#include -#undef interface - -namespace nall { - //UTF-8 to UTF-16 - class utf16_t { - public: - operator wchar_t*() { - return buffer; - } - - operator const wchar_t*() const { - return buffer; - } - - utf16_t(const char *s = "") { - if(!s) s = ""; - unsigned length = MultiByteToWideChar(CP_UTF8, 0, s, -1, 0, 0); - buffer = new wchar_t[length + 1](); - MultiByteToWideChar(CP_UTF8, 0, s, -1, buffer, length); - } - - ~utf16_t() { - delete[] buffer; - } - - private: - wchar_t *buffer; - }; - - //UTF-16 to UTF-8 - class utf8_t { - public: - operator char*() { - return buffer; - } - - operator const char*() const { - return buffer; - } - - utf8_t(const wchar_t *s = L"") { - if(!s) s = L""; - unsigned length = WideCharToMultiByte(CP_UTF8, 0, s, -1, 0, 0, (const char*)0, (BOOL*)0); - buffer = new char[length + 1](); - WideCharToMultiByte(CP_UTF8, 0, s, -1, buffer, length, (const char*)0, (BOOL*)0); - } - - ~utf8_t() { - delete[] buffer; - } - - private: - char *buffer; - }; -} - -#endif //if defined(_WIN32) - -#endif diff --git a/supergameboy/nall/utility.hpp b/supergameboy/nall/utility.hpp deleted file mode 100644 index 2a63f515..00000000 --- a/supergameboy/nall/utility.hpp +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef NALL_UTILITY_HPP -#define NALL_UTILITY_HPP - -#include -#include - -namespace nall { - template struct enable_if { typedef T type; }; - template struct enable_if {}; - template struct mp_enable_if : enable_if {}; - - template inline void swap(T &x, T &y) { - T temp(std::move(x)); - x = std::move(y); - y = std::move(temp); - } - - template struct base_from_member { - T value; - base_from_member(T value_) : value(value_) {} - }; - - template inline T* allocate(size_t size, const T &value) { - T *array = new T[size]; - for(size_t i = 0; i < size; i++) array[i] = value; - return array; - } -} - -#endif diff --git a/supergameboy/nall/varint.hpp b/supergameboy/nall/varint.hpp deleted file mode 100644 index cc3bb17c..00000000 --- a/supergameboy/nall/varint.hpp +++ /dev/null @@ -1,92 +0,0 @@ -#ifndef NALL_VARINT_HPP -#define NALL_VARINT_HPP - -#include -#include -#include - -namespace nall { - template class uint_t { - private: - enum { bytes = (bits + 7) >> 3 }; //minimum number of bytes needed to store value - typedef typename static_if< - sizeof(int) >= bytes, - unsigned int, - typename static_if< - sizeof(long) >= bytes, - unsigned long, - typename static_if< - sizeof(long long) >= bytes, - unsigned long long, - void - >::type - >::type - >::type T; - static_assert::value> uint_assert; - T data; - - public: - inline operator T() const { return data; } - inline T operator ++(int) { T r = data; data = uclip(data + 1); return r; } - inline T operator --(int) { T r = data; data = uclip(data - 1); return r; } - inline T operator ++() { return data = uclip(data + 1); } - inline T operator --() { return data = uclip(data - 1); } - inline T operator =(const T i) { return data = uclip(i); } - inline T operator |=(const T i) { return data = uclip(data | i); } - inline T operator ^=(const T i) { return data = uclip(data ^ i); } - inline T operator &=(const T i) { return data = uclip(data & i); } - inline T operator<<=(const T i) { return data = uclip(data << i); } - inline T operator>>=(const T i) { return data = uclip(data >> i); } - inline T operator +=(const T i) { return data = uclip(data + i); } - inline T operator -=(const T i) { return data = uclip(data - i); } - inline T operator *=(const T i) { return data = uclip(data * i); } - inline T operator /=(const T i) { return data = uclip(data / i); } - inline T operator %=(const T i) { return data = uclip(data % i); } - - inline uint_t() : data(0) {} - inline uint_t(const T i) : data(uclip(i)) {} - }; - - template class int_t { - private: - enum { bytes = (bits + 7) >> 3 }; //minimum number of bytes needed to store value - typedef typename static_if< - sizeof(int) >= bytes, - signed int, - typename static_if< - sizeof(long) >= bytes, - signed long, - typename static_if< - sizeof(long long) >= bytes, - signed long long, - void - >::type - >::type - >::type T; - static_assert::value> int_assert; - T data; - - public: - inline operator T() const { return data; } - inline T operator ++(int) { T r = data; data = sclip(data + 1); return r; } - inline T operator --(int) { T r = data; data = sclip(data - 1); return r; } - inline T operator ++() { return data = sclip(data + 1); } - inline T operator --() { return data = sclip(data - 1); } - inline T operator =(const T i) { return data = sclip(i); } - inline T operator |=(const T i) { return data = sclip(data | i); } - inline T operator ^=(const T i) { return data = sclip(data ^ i); } - inline T operator &=(const T i) { return data = sclip(data & i); } - inline T operator<<=(const T i) { return data = sclip(data << i); } - inline T operator>>=(const T i) { return data = sclip(data >> i); } - inline T operator +=(const T i) { return data = sclip(data + i); } - inline T operator -=(const T i) { return data = sclip(data - i); } - inline T operator *=(const T i) { return data = sclip(data * i); } - inline T operator /=(const T i) { return data = sclip(data / i); } - inline T operator %=(const T i) { return data = sclip(data % i); } - - inline int_t() : data(0) {} - inline int_t(const T i) : data(sclip(i)) {} - }; -} - -#endif diff --git a/supergameboy/nall/vector.hpp b/supergameboy/nall/vector.hpp deleted file mode 100644 index 3d69d4d5..00000000 --- a/supergameboy/nall/vector.hpp +++ /dev/null @@ -1,240 +0,0 @@ -#ifndef NALL_VECTOR_HPP -#define NALL_VECTOR_HPP - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace nall { - //linear_vector - //memory: O(capacity * 2) - // - //linear_vector uses placement new + manual destructor calls to create a - //contiguous block of memory for all objects. accessing individual elements - //is fast, though resizing the array incurs significant overhead. - //reserve() overhead is reduced from quadratic time to amortized constant time - //by resizing twice as much as requested. - // - //if objects hold memory address references to themselves (introspection), a - //valid copy constructor will be needed to keep pointers valid. - - template class linear_vector { - protected: - T *pool; - unsigned poolsize, objectsize; - - public: - unsigned size() const { return objectsize; } - unsigned capacity() const { return poolsize; } - - void reset() { - if(pool) { - for(unsigned i = 0; i < objectsize; i++) pool[i].~T(); - free(pool); - } - pool = 0; - poolsize = 0; - objectsize = 0; - } - - void reserve(unsigned newsize) { - newsize = bit::round(newsize); //round to nearest power of two (for amortized growth) - - T *poolcopy = (T*)malloc(newsize * sizeof(T)); - for(unsigned i = 0; i < min(objectsize, newsize); i++) new(poolcopy + i) T(pool[i]); - for(unsigned i = 0; i < objectsize; i++) pool[i].~T(); - free(pool); - pool = poolcopy; - poolsize = newsize; - objectsize = min(objectsize, newsize); - } - - void resize(unsigned newsize) { - if(newsize > poolsize) reserve(newsize); - - if(newsize < objectsize) { - //vector is shrinking; destroy excess objects - for(unsigned i = newsize; i < objectsize; i++) pool[i].~T(); - } else if(newsize > objectsize) { - //vector is expanding; allocate new objects - for(unsigned i = objectsize; i < newsize; i++) new(pool + i) T; - } - - objectsize = newsize; - } - - void add(const T data) { - if(objectsize + 1 > poolsize) reserve(objectsize + 1); - new(pool + objectsize++) T(data); - } - - inline T& operator[](unsigned index) { - if(index >= objectsize) resize(index + 1); - return pool[index]; - } - - inline const T& operator[](unsigned index) const { - if(index >= objectsize) throw "vector[] out of bounds"; - return pool[index]; - } - - //copy - inline linear_vector& operator=(const linear_vector &source) { - reset(); - reserve(source.capacity()); - resize(source.size()); - for(unsigned i = 0; i < source.size(); i++) operator[](i) = source.operator[](i); - return *this; - } - - linear_vector(const linear_vector &source) : pool(0), poolsize(0), objectsize(0) { - operator=(source); - } - - //move - inline linear_vector& operator=(linear_vector &&source) { - reset(); - pool = source.pool; - poolsize = source.poolsize; - objectsize = source.objectsize; - source.pool = 0; - source.reset(); - return *this; - } - - linear_vector(linear_vector &&source) : pool(0), poolsize(0), objectsize(0) { - operator=(std::move(source)); - } - - //construction - linear_vector() : pool(0), poolsize(0), objectsize(0) { - } - - linear_vector(std::initializer_list list) : pool(0), poolsize(0), objectsize(0) { - for(const T *p = list.begin(); p != list.end(); ++p) add(*p); - } - - ~linear_vector() { - reset(); - } - }; - - //pointer_vector - //memory: O(1) - // - //pointer_vector keeps an array of pointers to each vector object. this adds - //significant overhead to individual accesses, but allows for optimal memory - //utilization. - // - //by guaranteeing that the base memory address of each objects never changes, - //this avoids the need for an object to have a valid copy constructor. - - template class pointer_vector { - protected: - T **pool; - unsigned poolsize, objectsize; - - public: - unsigned size() const { return objectsize; } - unsigned capacity() const { return poolsize; } - - void reset() { - if(pool) { - for(unsigned i = 0; i < objectsize; i++) { if(pool[i]) delete pool[i]; } - free(pool); - } - pool = 0; - poolsize = 0; - objectsize = 0; - } - - void reserve(unsigned newsize) { - newsize = bit::round(newsize); //round to nearest power of two (for amortized growth) - - for(unsigned i = newsize; i < objectsize; i++) { - if(pool[i]) { delete pool[i]; pool[i] = 0; } - } - - pool = (T**)realloc(pool, newsize * sizeof(T*)); - for(unsigned i = poolsize; i < newsize; i++) pool[i] = 0; - poolsize = newsize; - objectsize = min(objectsize, newsize); - } - - void resize(unsigned newsize) { - if(newsize > poolsize) reserve(newsize); - - for(unsigned i = newsize; i < objectsize; i++) { - if(pool[i]) { delete pool[i]; pool[i] = 0; } - } - - objectsize = newsize; - } - - void add(const T data) { - if(objectsize + 1 > poolsize) reserve(objectsize + 1); - pool[objectsize++] = new T(data); - } - - inline T& operator[](unsigned index) { - if(index >= objectsize) resize(index + 1); - if(!pool[index]) pool[index] = new T; - return *pool[index]; - } - - inline const T& operator[](unsigned index) const { - if(index >= objectsize || !pool[index]) throw "vector[] out of bounds"; - return *pool[index]; - } - - //copy - inline pointer_vector& operator=(const pointer_vector &source) { - reset(); - reserve(source.capacity()); - resize(source.size()); - for(unsigned i = 0; i < source.size(); i++) operator[](i) = source.operator[](i); - return *this; - } - - pointer_vector(const pointer_vector &source) : pool(0), poolsize(0), objectsize(0) { - operator=(source); - } - - //move - inline pointer_vector& operator=(pointer_vector &&source) { - reset(); - pool = source.pool; - poolsize = source.poolsize; - objectsize = source.objectsize; - source.pool = 0; - source.reset(); - return *this; - } - - pointer_vector(pointer_vector &&source) : pool(0), poolsize(0), objectsize(0) { - operator=(std::move(source)); - } - - //construction - pointer_vector() : pool(0), poolsize(0), objectsize(0) { - } - - pointer_vector(std::initializer_list list) : pool(0), poolsize(0), objectsize(0) { - for(const T *p = list.begin(); p != list.end(); ++p) add(*p); - } - - ~pointer_vector() { - reset(); - } - }; - - template struct has_size> { enum { value = true }; }; - template struct has_size> { enum { value = true }; }; -} - -#endif diff --git a/supergameboy/supergameboy.cpp b/supergameboy/supergameboy.cpp deleted file mode 100644 index 0c011af7..00000000 --- a/supergameboy/supergameboy.cpp +++ /dev/null @@ -1,68 +0,0 @@ -#include "supergameboy.hpp" - -#ifdef _WIN32 - #define dllexport __declspec(dllexport) -#else - #define dllexport -#endif - -#include -#include -#include - -#include - -dllexport void sgb_rom(uint8_t *data, unsigned size) { - supergameboy.romdata = data; - supergameboy.romsize = size; -} - -dllexport void sgb_ram(uint8_t *data, unsigned size) { - supergameboy.ramdata = data; - supergameboy.ramsize = size; -} - -dllexport void sgb_rtc(uint8_t *data, unsigned size) { - supergameboy.rtcdata = data; - supergameboy.rtcsize = size; -} - -dllexport bool sgb_init(bool version) { - return supergameboy.init(version); -} - -dllexport void sgb_term() { - supergameboy.term(); -} - -dllexport void sgb_power() { - supergameboy.power(); -} - -dllexport void sgb_reset() { - supergameboy.reset(); -} - -dllexport void sgb_row(unsigned row) { - supergameboy.row(row); -} - -dllexport uint8_t sgb_read(uint16_t addr) { - return supergameboy.read(addr); -} - -dllexport void sgb_write(uint16_t addr, uint8_t data) { - supergameboy.write(addr, data); -} - -dllexport unsigned sgb_run(uint32_t *samplebuffer, unsigned clocks) { - return supergameboy.run(samplebuffer, clocks); -} - -dllexport void sgb_save() { - supergameboy.save(); -} - -dllexport void sgb_serialize(nall::serializer &s) { - supergameboy.serialize(s); -} diff --git a/supergameboy/supergameboy.hpp b/supergameboy/supergameboy.hpp deleted file mode 100644 index 715e4893..00000000 --- a/supergameboy/supergameboy.hpp +++ /dev/null @@ -1,32 +0,0 @@ -#ifndef SUPERGAMEBOY_HPP -#define SUPERGAMEBOY_HPP - -#include -#include -#include -#include - -#include -#include -using namespace nall; - -#include -#include - -extern "C" { - void sgb_rom(uint8_t *data, unsigned size); - void sgb_ram(uint8_t *data, unsigned size); - void sgb_rtc(uint8_t *data, unsigned size); - bool sgb_init(bool version); - void sgb_term(); - void sgb_power(); - void sgb_reset(); - void sgb_row(unsigned row); - uint8_t sgb_read(uint16_t addr); - void sgb_write(uint16_t addr, uint8_t data); - unsigned sgb_run(uint32_t *samplebuffer, unsigned clocks); - void sgb_save(); - void sgb_serialize(nall::serializer &s); -} - -#endif diff --git a/supergameboy/sync.sh b/supergameboy/sync.sh deleted file mode 100644 index 4bbaf34f..00000000 --- a/supergameboy/sync.sh +++ /dev/null @@ -1,2 +0,0 @@ -rm -r nall -cp -r ../nall ./nall