From cc1de3a7a80f7b11c8070eed774aa4bae6333265 Mon Sep 17 00:00:00 2001 From: n-a-c-h <> Date: Sun, 21 Nov 2004 00:10:55 +0000 Subject: [PATCH] JMA Support. --- zsnes/src/Makefile.in | 32 ++- zsnes/src/initc.c | 11 + zsnes/src/jma/7z.h | 26 +++ zsnes/src/jma/7zlzma.cpp | 46 ++++ zsnes/src/jma/aribitcd.cpp | 40 ++++ zsnes/src/jma/aribitcd.h | 101 +++++++++ zsnes/src/jma/ariconst.h | 33 +++ zsnes/src/jma/ariprice.h | 12 + zsnes/src/jma/btreecd.h | 309 +++++++++++++++++++++++++ zsnes/src/jma/crc32.cpp | 82 +++++++ zsnes/src/jma/crc32.h | 29 +++ zsnes/src/jma/iiostrm.cpp | 44 ++++ zsnes/src/jma/iiostrm.h | 50 +++++ zsnes/src/jma/inbyte.cpp | 60 +++++ zsnes/src/jma/inbyte.h | 77 +++++++ zsnes/src/jma/jma.cpp | 447 +++++++++++++++++++++++++++++++++++++ zsnes/src/jma/jma.h | 88 ++++++++ zsnes/src/jma/lencoder.h | 93 ++++++++ zsnes/src/jma/litcoder.h | 123 ++++++++++ zsnes/src/jma/lzma.cpp | 42 ++++ zsnes/src/jma/lzma.h | 124 ++++++++++ zsnes/src/jma/lzmadec.cpp | 299 +++++++++++++++++++++++++ zsnes/src/jma/lzmadec.h | 83 +++++++ zsnes/src/jma/outbyte.cpp | 64 ++++++ zsnes/src/jma/outbyte.h | 61 +++++ zsnes/src/jma/portable.h | 76 +++++++ zsnes/src/jma/rcdefs.h | 61 +++++ zsnes/src/jma/rngcoder.h | 251 +++++++++++++++++++++ zsnes/src/jma/winout.cpp | 90 ++++++++ zsnes/src/jma/winout.h | 90 ++++++++ zsnes/src/jma/zsnesjma.cpp | 64 ++++++ zsnes/src/jma/zsnesjma.h | 27 +++ 32 files changed, 3028 insertions(+), 7 deletions(-) create mode 100644 zsnes/src/jma/7z.h create mode 100644 zsnes/src/jma/7zlzma.cpp create mode 100644 zsnes/src/jma/aribitcd.cpp create mode 100644 zsnes/src/jma/aribitcd.h create mode 100644 zsnes/src/jma/ariconst.h create mode 100644 zsnes/src/jma/ariprice.h create mode 100644 zsnes/src/jma/btreecd.h create mode 100644 zsnes/src/jma/crc32.cpp create mode 100644 zsnes/src/jma/crc32.h create mode 100644 zsnes/src/jma/iiostrm.cpp create mode 100644 zsnes/src/jma/iiostrm.h create mode 100644 zsnes/src/jma/inbyte.cpp create mode 100644 zsnes/src/jma/inbyte.h create mode 100644 zsnes/src/jma/jma.cpp create mode 100644 zsnes/src/jma/jma.h create mode 100644 zsnes/src/jma/lencoder.h create mode 100644 zsnes/src/jma/litcoder.h create mode 100644 zsnes/src/jma/lzma.cpp create mode 100644 zsnes/src/jma/lzma.h create mode 100644 zsnes/src/jma/lzmadec.cpp create mode 100644 zsnes/src/jma/lzmadec.h create mode 100644 zsnes/src/jma/outbyte.cpp create mode 100644 zsnes/src/jma/outbyte.h create mode 100644 zsnes/src/jma/portable.h create mode 100644 zsnes/src/jma/rcdefs.h create mode 100644 zsnes/src/jma/rngcoder.h create mode 100644 zsnes/src/jma/winout.cpp create mode 100644 zsnes/src/jma/winout.h create mode 100644 zsnes/src/jma/zsnesjma.cpp create mode 100644 zsnes/src/jma/zsnesjma.h diff --git a/zsnes/src/Makefile.in b/zsnes/src/Makefile.in index 2daad197..6527a119 100644 --- a/zsnes/src/Makefile.in +++ b/zsnes/src/Makefile.in @@ -24,6 +24,7 @@ WINDIR=linux OBJDIR=obj ZIPDIR=zip EFFECTSDIR=effects +JMADIR=jma CHIPSOBJ=${CHIPDIR}/sfxproc.o ${CHIPDIR}/fxemu2.o ${CHIPDIR}/dsp1proc.o\ ${CHIPDIR}/fxemu2b.o ${CHIPDIR}/fxemu2c.o ${CHIPDIR}/fxtable.o\ @@ -57,7 +58,9 @@ WINOBJ=${WINDIR}/copyvwin.o \ WINDOSOBJ=${DOSDIR}/debug.o ${DOSDIR}/joy.o ${DOSDIR}/modemrtn.o ${DOSDIR}/vesa2.o\ ${DOSDIR}/initvid.o ${DOSDIR}/sw.o ${DOSDIR}/gppro.o ${DOSDIR}/vesa12.o -#PREOBJ=${OBJDIR}/unzip.o ${DOSDIR}/zsipx.o +JMAOBJ=${JMADIR}/7zlzma.o ${JMADIR}/aribitcd.o ${JMADIR}/crc32.o ${JMADIR}/iiostrm.o\ + ${JMADIR}/inbyte.o ${JMADIR}/jma.o ${JMADIR}/lzma.o ${JMADIR}/lzmadec.o\ + ${JMADIR}/outbyte.o ${JMADIR}/winout.o ${JMADIR}/zsnesjma.o ZIPOBJ=${ZIPDIR}/unzip.o ${ZIPDIR}/zpng.o @@ -65,9 +68,12 @@ EFFECTSOBJ=${EFFECTSDIR}/burn.o ${EFFECTSDIR}/water.o ${EFFECTSDIR}/smoke.o MAINOBJ=cfgload.o endmem.o init.o initc.o uic.o patch.o ui.o vcache.o version.o -OBJS=${CHIPSOBJ} ${CPUOBJ} ${WINOBJ} ${WINDOSOBJ} ${GUIOBJ} ${VIDEOBJ} ${MAINOBJ} ${ZIPOBJ} ${EFFECTSOBJ} +OBJS=${CHIPSOBJ} ${CPUOBJ} ${WINOBJ} ${WINDOSOBJ} ${GUIOBJ} ${VIDEOBJ} ${MAINOBJ} ${ZIPOBJ} ${EFFECTSOBJ} ${JMAOBJ} -.SUFFIXES: .c .asm +.SUFFIXES: .cpp .c .asm + +%.o: %.cpp + g++ @CFLAGS@ -o $@ -c $< %.o: %.c @CC@ @CFLAGS@ -o $@ -c $< @@ -78,7 +84,7 @@ OBJS=${CHIPSOBJ} ${CPUOBJ} ${WINOBJ} ${WINDOSOBJ} ${GUIOBJ} ${VIDEOBJ} ${MAINOBJ ALL: @ZSNESEXE@ @ZSNESEXE@: ${OBJS} - @CC@ -o @ZSNESEXE@ ${OBJS} @CFLAGS@ @LDFLAGS@ + g++ -o @ZSNESEXE@ ${OBJS} @CFLAGS@ @LDFLAGS@ ${ZIPDIR}/zpng.o: ${ZIPDIR}/zpng.c ${ZIPDIR}/zpng.h ${ZIPDIR}/unzip.o: ${ZIPDIR}/unzip.c ${ZIPDIR}/zunzip.h @@ -104,7 +110,7 @@ ${CHIPDIR}/dsp1emu.o: ${CHIPDIR}/dsp1emu.c ui.o: ui.asm macros.mac cfgload.o:cfgload.asm macros.mac init.o:init.asm macros.mac -initc.o:initc.c +initc.o:initc.c ${JMADIR}/zsnesjma.h uic.o:uic.c patch.o:patch.c @@ -189,6 +195,18 @@ ${CHIPDIR}/sa1proc.o: ${CHIPDIR}/sa1proc.asm macros.mac endmem.o: endmem.asm macros.mac ${DOSDIR}/modemrtn.o: ${DOSDIR}/modemrtn.asm macros.mac +${JMADIR}/7zlzma.o: ${JMADIR}/7zlzma.cpp +${JMADIR}/aribitcd.o: ${JMADIR}/aribitcd.cpp +${JMADIR}/crc32.o: ${JMADIR}/crc32.cpp ${JMADIR}/crc32.h +${JMADIR}/iiostrm.o: ${JMADIR}/iiostrm.cpp +${JMADIR}/inbyte.o: ${JMADIR}/inbyte.cpp +${JMADIR}/jma.o: ${JMADIR}/jma.cpp ${JMADIR}/jma.h ${JMADIR}/crc32.h ${JMADIR}/portable.h +${JMADIR}/lzma.o: ${JMADIR}/lzma.cpp +${JMADIR}/lzmadec.o: ${JMADIR}/lzmadec.cpp +${JMADIR}/outbyte.o: ${JMADIR}/outbyte.cpp +${JMADIR}/winout.o: ${JMADIR}/winout.cpp +${JMADIR}/zsnesjma.o: ${JMADIR}/zsnesjma.cpp ${JMADIR}/zsnesjma.h ${JMADIR}/jma.h + install: @INSTALL@ -m 0755 @ZSNESEXE@ @prefix@/bin @INSTALL@ -m 0644 linux/zsnes.1 @prefix@/man/man1 @@ -197,10 +215,10 @@ uninstall: rm -f @prefix@/bin/$(notdir @ZSNESEXE@) @prefix@/man/man5/zsnes.5 clean: - rm -f ${CHIPDIR}/*.o ${CPUDIR}/*.o ${VIDEODIR}/*.o ${GUIDIR}/*.o ${DOSDIR}/*.o ${WINDIR}/*.o ${ZIPDIR}/*.o ${EFFECTSDIR}/*.o *.o @ZSNESEXE@ + rm -f ${CHIPDIR}/*.o ${CPUDIR}/*.o ${VIDEODIR}/*.o ${GUIDIR}/*.o ${DOSDIR}/*.o ${WINDIR}/*.o ${ZIPDIR}/*.o ${EFFECTSDIR}/*.o ${JMADIR}/*.o *.o @ZSNESEXE@ distclean: - rm -f ${CHIPDIR}/*.o ${CPUDIR}/*.o ${VIDEODIR}/*.o ${GUIDIR}/*.o ${DOSDIR}/*.o ${WINDIR}/*.o ${ZIPDIR}/*.o ${EFFECTSDIR}/*.o *.o @ZSNESEXE@ Makefile config.cache config.log config.status config.h + rm -f ${CHIPDIR}/*.o ${CPUDIR}/*.o ${VIDEODIR}/*.o ${GUIDIR}/*.o ${DOSDIR}/*.o ${WINDIR}/*.o ${ZIPDIR}/*.o ${EFFECTSDIR}/*.o ${JMADIR}/*.o *.o @ZSNESEXE@ Makefile config.cache config.log config.status config.h diff --git a/zsnes/src/initc.c b/zsnes/src/initc.c index acb30900..4178a6f3 100755 --- a/zsnes/src/initc.c +++ b/zsnes/src/initc.c @@ -28,6 +28,7 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. #define DIR_SLASH "\\" #endif #include "zip/zunzip.h" +#include "jma/zsnesjma.h" #ifndef __GNUC__ #define strcasecmp stricmp @@ -783,6 +784,16 @@ void loadROM() lastROMFileName = ZOpenFileName; + if (strlen(ZOpenFileName) >= 5) //Char + ".jma" + { + char *ext = ZOpenFileName+strlen(ZOpenFileName)-4; + if (!strcasecmp(ext, ".jma")) + { + isCompressed = true; + load_jma_file(ZOpenFileName); + } + } + if (strlen(ZOpenFileName) >= 5) //Char + ".zip" { char *ext = ZOpenFileName+strlen(ZOpenFileName)-4; diff --git a/zsnes/src/jma/7z.h b/zsnes/src/jma/7z.h new file mode 100644 index 00000000..7415acfd --- /dev/null +++ b/zsnes/src/jma/7z.h @@ -0,0 +1,26 @@ +/* +Copyright (C) 2004 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 as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +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 + +bool decompress_lzma_7z(const unsigned char* in_data, unsigned in_size, unsigned char* out_data, unsigned out_size) throw (); + +#endif + diff --git a/zsnes/src/jma/7zlzma.cpp b/zsnes/src/jma/7zlzma.cpp new file mode 100644 index 00000000..24cb9c52 --- /dev/null +++ b/zsnes/src/jma/7zlzma.cpp @@ -0,0 +1,46 @@ +/* +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 as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +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(const unsigned char* in_data, unsigned in_size, unsigned char* out_data, unsigned out_size) throw () { + try { + NCompress::NLZMA::CDecoder cc; + + ISequentialInStream in(reinterpret_cast(in_data), in_size); + ISequentialOutStream out(reinterpret_cast(out_data), out_size); + + 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; + } +} diff --git a/zsnes/src/jma/aribitcd.cpp b/zsnes/src/jma/aribitcd.cpp new file mode 100644 index 00000000..b89f8345 --- /dev/null +++ b/zsnes/src/jma/aribitcd.cpp @@ -0,0 +1,40 @@ +/* +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 as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +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 "aribitcd.h" +#include "ariprice.h" + +#include + +namespace NCompression { +namespace NArithmetic { + +static const double kDummyMultMid = (1.0 / kBitPrice) / 2; + +CPriceTables::CPriceTables() +{ + double aLn2 = log(2); + double aLnAll = log(kBitModelTotal >> kNumMoveReducingBits); + for(UINT32 i = 1; i < (kBitModelTotal >> kNumMoveReducingBits) - 1; i++) + m_StatePrices[i] = UINT32((fabs(aLnAll - log(i)) / aLn2 + kDummyMultMid) * kBitPrice); +} + +CPriceTables g_PriceTables; + +}} diff --git a/zsnes/src/jma/aribitcd.h b/zsnes/src/jma/aribitcd.h new file mode 100644 index 00000000..482dd74a --- /dev/null +++ b/zsnes/src/jma/aribitcd.h @@ -0,0 +1,101 @@ +#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; + + +class CPriceTables +{ +public: + UINT32 m_StatePrices[kBitModelTotal >> kNumMoveReducingBits]; + CPriceTables(); +}; + +extern CPriceTables g_PriceTables; + + +///////////////////////////// +// 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 CBitEncoder: public CBitModel +{ +public: + void Encode(CRangeEncoder *aRangeEncoder, UINT32 aSymbol) + { + aRangeEncoder->EncodeBit(CBitModel::m_Probability, kNumBitModelTotalBits, aSymbol); + CBitModel::UpdateModel(aSymbol); + } + UINT32 GetPrice(UINT32 aSymbol) const + { + return g_PriceTables.m_StatePrices[ + (((CBitModel::m_Probability - aSymbol) ^ ((-(int)aSymbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; + } +}; + + +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/zsnes/src/jma/ariconst.h b/zsnes/src/jma/ariconst.h new file mode 100644 index 00000000..d4153bad --- /dev/null +++ b/zsnes/src/jma/ariconst.h @@ -0,0 +1,33 @@ +/* +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 as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +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::CRangeEncoder CMyRangeEncoder; +typedef NCompression::NArithmetic::CRangeDecoder CMyRangeDecoder; + +template class CMyBitEncoder: + public NCompression::NArithmetic::CBitEncoder {}; +template class CMyBitDecoder: + public NCompression::NArithmetic::CBitDecoder {}; + +#endif diff --git a/zsnes/src/jma/ariprice.h b/zsnes/src/jma/ariprice.h new file mode 100644 index 00000000..ccc398e1 --- /dev/null +++ b/zsnes/src/jma/ariprice.h @@ -0,0 +1,12 @@ +#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/zsnes/src/jma/btreecd.h b/zsnes/src/jma/btreecd.h new file mode 100644 index 00000000..24ae5849 --- /dev/null +++ b/zsnes/src/jma/btreecd.h @@ -0,0 +1,309 @@ +/* +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 as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +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" + +////////////////////////// +// CBitTreeEncoder + +template +class CBitTreeEncoder +{ + CMyBitEncoder m_Models[1 << m_NumBitLevels]; +public: + void Init() + { + for(UINT32 i = 1; i < (1 << m_NumBitLevels); i++) + m_Models[i].Init(); + } + void Encode(CMyRangeEncoder *aRangeEncoder, UINT32 aSymbol) + { + UINT32 aModelIndex = 1; + for (UINT32 aBitIndex = m_NumBitLevels; aBitIndex > 0 ;) + { + aBitIndex--; + UINT32 aBit = (aSymbol >> aBitIndex ) & 1; + m_Models[aModelIndex].Encode(aRangeEncoder, aBit); + aModelIndex = (aModelIndex << 1) | aBit; + } + }; + UINT32 GetPrice(UINT32 aSymbol) const + { + UINT32 aPrice = 0; + UINT32 aModelIndex = 1; + for (UINT32 aBitIndex = m_NumBitLevels; aBitIndex > 0 ;) + { + aBitIndex--; + UINT32 aBit = (aSymbol >> aBitIndex ) & 1; + aPrice += m_Models[aModelIndex].GetPrice(aBit); + aModelIndex = (aModelIndex << 1) + aBit; + } + return aPrice; + } +}; + +////////////////////////// +// 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); + }; +}; + + + +//////////////////////////////// +// CReverseBitTreeEncoder + +template +class CReverseBitTreeEncoder2 +{ + CMyBitEncoder *m_Models; + UINT32 m_NumBitLevels; +public: + CReverseBitTreeEncoder2(): m_Models(0) { } + ~CReverseBitTreeEncoder2() { delete []m_Models; } + bool Create(UINT32 aNumBitLevels) + { + m_NumBitLevels = aNumBitLevels; + m_Models = new CMyBitEncoder[1 << aNumBitLevels]; + return (m_Models != 0); + } + void Init() + { + UINT32 aNumModels = 1 << m_NumBitLevels; + for(UINT32 i = 1; i < aNumModels; i++) + m_Models[i].Init(); + } + void Encode(CMyRangeEncoder *aRangeEncoder, UINT32 aSymbol) + { + UINT32 aModelIndex = 1; + for (UINT32 i = 0; i < m_NumBitLevels; i++) + { + UINT32 aBit = aSymbol & 1; + m_Models[aModelIndex].Encode(aRangeEncoder, aBit); + aModelIndex = (aModelIndex << 1) | aBit; + aSymbol >>= 1; + } + } + UINT32 GetPrice(UINT32 aSymbol) const + { + UINT32 aPrice = 0; + UINT32 aModelIndex = 1; + for (UINT32 i = m_NumBitLevels; i > 0; i--) + { + UINT32 aBit = aSymbol & 1; + aSymbol >>= 1; + aPrice += m_Models[aModelIndex].GetPrice(aBit); + aModelIndex = (aModelIndex << 1) | aBit; + } + return aPrice; + } +}; + +/* +template +class CReverseBitTreeEncoder: public CReverseBitTreeEncoder2 +{ +public: + CReverseBitTreeEncoder() + { Create(aNumBitLevels); } +}; +*/ +//////////////////////////////// +// 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; + } +}; + +/* +////////////////////////// +// CBitTreeEncoder2 + +template +class CBitTreeEncoder2 +{ + NCompression::NArithmetic::CBitEncoder *m_Models; + UINT32 m_NumBitLevels; +public: + bool Create(UINT32 aNumBitLevels) + { + m_NumBitLevels = aNumBitLevels; + m_Models = new NCompression::NArithmetic::CBitEncoder[1 << aNumBitLevels]; + return (m_Models != 0); + } + void Init() + { + UINT32 aNumModels = 1 << m_NumBitLevels; + for(UINT32 i = 1; i < aNumModels; i++) + m_Models[i].Init(); + } + void Encode(CMyRangeEncoder *aRangeEncoder, UINT32 aSymbol) + { + UINT32 aModelIndex = 1; + for (UINT32 aBitIndex = m_NumBitLevels; aBitIndex > 0 ;) + { + aBitIndex--; + UINT32 aBit = (aSymbol >> aBitIndex ) & 1; + m_Models[aModelIndex].Encode(aRangeEncoder, aBit); + aModelIndex = (aModelIndex << 1) | aBit; + } + } + UINT32 GetPrice(UINT32 aSymbol) const + { + UINT32 aPrice = 0; + UINT32 aModelIndex = 1; + for (UINT32 aBitIndex = m_NumBitLevels; aBitIndex > 0 ;) + { + aBitIndex--; + UINT32 aBit = (aSymbol >> aBitIndex ) & 1; + aPrice += m_Models[aModelIndex].GetPrice(aBit); + aModelIndex = (aModelIndex << 1) + aBit; + } + return aPrice; + } +}; + + +////////////////////////// +// CBitTreeDecoder2 + +template +class CBitTreeDecoder2 +{ + NCompression::NArithmetic::CBitDecoder *m_Models; + UINT32 m_NumBitLevels; +public: + bool Create(UINT32 aNumBitLevels) + { + m_NumBitLevels = aNumBitLevels; + m_Models = new NCompression::NArithmetic::CBitDecoder[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; + 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); + } +}; +*/ + + +#endif diff --git a/zsnes/src/jma/crc32.cpp b/zsnes/src/jma/crc32.cpp new file mode 100644 index 00000000..ef0bcae0 --- /dev/null +++ b/zsnes/src/jma/crc32.cpp @@ -0,0 +1,82 @@ +/* +Copyright (C) 2004 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 +as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You 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/zsnes/src/jma/crc32.h b/zsnes/src/jma/crc32.h new file mode 100644 index 00000000..c760dc7b --- /dev/null +++ b/zsnes/src/jma/crc32.h @@ -0,0 +1,29 @@ +/* +Copyright (C) 2004 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 +as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You 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); + unsigned short SUM_CRC32(const unsigned char *, size_t, unsigned int &crc32); +} + +#endif diff --git a/zsnes/src/jma/iiostrm.cpp b/zsnes/src/jma/iiostrm.cpp new file mode 100644 index 00000000..c9fec54d --- /dev/null +++ b/zsnes/src/jma/iiostrm.cpp @@ -0,0 +1,44 @@ +/* +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 as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +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" + +HRESULT ISequentialInStream::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::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; +} diff --git a/zsnes/src/jma/iiostrm.h b/zsnes/src/jma/iiostrm.h new file mode 100644 index 00000000..7cb94744 --- /dev/null +++ b/zsnes/src/jma/iiostrm.h @@ -0,0 +1,50 @@ +/* +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 as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +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 "portable.h" + +class ISequentialInStream +{ + const char* data; + unsigned size; +public: + ISequentialInStream(const char* Adata, unsigned Asize) : data(Adata), size(Asize) { } + + HRESULT Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize); +}; + +class ISequentialOutStream +{ + char* data; + unsigned size; + bool overflow; + unsigned total; +public: + ISequentialOutStream(char* Adata, unsigned Asize) : data(Adata), size(Asize), overflow(false), total(0) { } + + bool overflow_get() const { return overflow; } + unsigned size_get() const { return total; } + + HRESULT Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize); +}; + +#endif diff --git a/zsnes/src/jma/inbyte.cpp b/zsnes/src/jma/inbyte.cpp new file mode 100644 index 00000000..b46d5535 --- /dev/null +++ b/zsnes/src/jma/inbyte.cpp @@ -0,0 +1,60 @@ +/* +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 as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +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_BufferSize(aBufferSize), + m_BufferBase(0) +{ + 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/zsnes/src/jma/inbyte.h b/zsnes/src/jma/inbyte.h new file mode 100644 index 00000000..ece23501 --- /dev/null +++ b/zsnes/src/jma/inbyte.h @@ -0,0 +1,77 @@ +/* +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 as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +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/zsnes/src/jma/jma.cpp b/zsnes/src/jma/jma.cpp new file mode 100644 index 00000000..c7479cb9 --- /dev/null +++ b/zsnes/src/jma/jma.cpp @@ -0,0 +1,447 @@ +/* +Copyright (C) 2004 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 +as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You 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 +#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 char jma_version = 0; + const unsigned char jma_null = 0; + + //Convert zip/JMA integer time to to time_t + time_t uint_to_time(unsigned int date, unsigned int 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]; + + //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. + //This if can probably be improved + if (file_block_size >= jma_file_size) + { + throw(JMA_BAD_FILE); + } + + //Seek to before file block so we can read the file block + stream.seekg(-(file_block_size+UINT_SIZE),ios::end); + + jma_file_info file_info; + char byte; + + while (file_block_size) + { + //First stored in the file block is the file name null terminated + file_info.name = ""; + + stream.get(byte); + while (byte) + { + file_info.name += byte; + 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 = ""; + + stream.get(byte); + while (byte) + { + file_info.comment += byte; + stream.get(byte); + } + + //Next is a UINT representing the file's size + stream.read((char *)uint_buffer, UINT_SIZE); + file_info.size = charp_to_uint(uint_buffer); + + //Followed by CRC32 + stream.read((char *)uint_buffer, UINT_SIZE); + file_info.crc32 = charp_to_uint(uint_buffer); + + //Special UINT representation of file's date + stream.read((char *)uint_buffer, UINT_SIZE); + file_info.date = charp_to_uint(uint_buffer); + + //Special UINT representation of file's time + stream.read((char *)uint_buffer, UINT_SIZE); + file_info.time = charp_to_uint(uint_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*4; + } + } + + //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) + { + throw(JMA_NO_OPEN); + } + + //Header is "JMA\0N" + unsigned char header[5]; + stream.read((char *)header, 5); + if (memcmp(jma_magic, header, 5)) + { + throw(JMA_BAD_FILE); + } + + //Not the cleanest code but logical + stream.read((char *)header, 5); + if (*header == 0) //Version 0 + { + 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) + { + 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) + { + throw(JMA_NO_OPEN); + } + + //Move forward over header + stream.seekg(10, 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) + { + 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; + } + } + 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); + + //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) + { + 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 (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); + } + else + { + size_t copy_amount = our_file_size-i > chunk_size ? chunk_size : our_file_size-i; + copy_amount -= first_chunk_offset; + memcpy(buffer+i, decomp_buffer+first_chunk_offset, copy_amount); + first_chunk_offset = 0; + 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; + } + } + +} + + diff --git a/zsnes/src/jma/jma.h b/zsnes/src/jma/jma.h new file mode 100644 index 00000000..0034071d --- /dev/null +++ b/zsnes/src/jma/jma.h @@ -0,0 +1,88 @@ +/* +Copyright (C) 2004 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 +as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You 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 int date; + unsigned int 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); + + 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); + }; + +} +#endif diff --git a/zsnes/src/jma/lencoder.h b/zsnes/src/jma/lencoder.h new file mode 100644 index 00000000..699c13bb --- /dev/null +++ b/zsnes/src/jma/lencoder.h @@ -0,0 +1,93 @@ +/* +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 as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +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 int 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/zsnes/src/jma/litcoder.h b/zsnes/src/jma/litcoder.h new file mode 100644 index 00000000..d0e71e26 --- /dev/null +++ b/zsnes/src/jma/litcoder.h @@ -0,0 +1,123 @@ +/* +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 as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +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/zsnes/src/jma/lzma.cpp b/zsnes/src/jma/lzma.cpp new file mode 100644 index 00000000..d994be5f --- /dev/null +++ b/zsnes/src/jma/lzma.cpp @@ -0,0 +1,42 @@ +/* +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 as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +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/zsnes/src/jma/lzma.h b/zsnes/src/jma/lzma.h new file mode 100644 index 00000000..e84b5d0f --- /dev/null +++ b/zsnes/src/jma/lzma.h @@ -0,0 +1,124 @@ +/* +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 as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +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(int 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/zsnes/src/jma/lzmadec.cpp b/zsnes/src/jma/lzmadec.cpp new file mode 100644 index 00000000..ff323cc4 --- /dev/null +++ b/zsnes/src/jma/lzmadec.cpp @@ -0,0 +1,299 @@ +/* +Copyright (C) 2004 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 as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +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; 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(int 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) == 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) == + 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 >= kStartPosModelIndex) + { + aDistance = kDistStart[aPosSlot]; + if (aPosSlot < 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/zsnes/src/jma/lzmadec.h b/zsnes/src/jma/lzmadec.h new file mode 100644 index 00000000..90799f36 --- /dev/null +++ b/zsnes/src/jma/lzmadec.h @@ -0,0 +1,83 @@ +/* +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 as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +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/zsnes/src/jma/outbyte.cpp b/zsnes/src/jma/outbyte.cpp new file mode 100644 index 00000000..a66003d0 --- /dev/null +++ b/zsnes/src/jma/outbyte.cpp @@ -0,0 +1,64 @@ +/* +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 as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +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 "outbyte.h" + +namespace NStream { + +COutByte::COutByte(UINT32 aBufferSize): + m_BufferSize(aBufferSize) +{ + m_Buffer = new BYTE[m_BufferSize]; +} + +COutByte::~COutByte() +{ + delete []m_Buffer; +} + +void COutByte::Init(ISequentialOutStream *aStream) +{ + m_Stream = aStream; + m_ProcessedSize = 0; + m_Pos = 0; +} + +HRESULT COutByte::Flush() +{ + if (m_Pos == 0) + return S_OK; + UINT32 aProcessedSize; + HRESULT aResult = m_Stream->Write(m_Buffer, m_Pos, &aProcessedSize); + if (aResult != S_OK) + return aResult; + if (m_Pos != aProcessedSize) + return E_FAIL; + m_ProcessedSize += aProcessedSize; + m_Pos = 0; + return S_OK; +} + +void COutByte::WriteBlock() +{ + HRESULT aResult = Flush(); + if (aResult != S_OK) + throw aResult; +} + +} diff --git a/zsnes/src/jma/outbyte.h b/zsnes/src/jma/outbyte.h new file mode 100644 index 00000000..5944fe21 --- /dev/null +++ b/zsnes/src/jma/outbyte.h @@ -0,0 +1,61 @@ +/* +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 as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +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_OUTBYTE_H +#define __STREAM_OUTBYTE_H + +#include "portable.h" +#include "iiostrm.h" + +namespace NStream { + +class COutByte +{ + BYTE *m_Buffer; + UINT32 m_Pos; + UINT32 m_BufferSize; + ISequentialOutStream* m_Stream; + UINT64 m_ProcessedSize; + + void WriteBlock(); +public: + COutByte(UINT32 aBufferSize = (1 << 20)); + ~COutByte(); + + void Init(ISequentialOutStream *aStream); + HRESULT Flush(); + + void WriteByte(BYTE aByte) + { + m_Buffer[m_Pos++] = aByte; + if(m_Pos >= m_BufferSize) + WriteBlock(); + } + void WriteBytes(const void *aBytes, UINT32 aSize) + { + for (UINT32 i = 0; i < aSize; i++) + WriteByte(((const BYTE *)aBytes)[i]); + } + + UINT64 GetProcessedSize() const { return m_ProcessedSize + m_Pos; } +}; + +} + +#endif diff --git a/zsnes/src/jma/portable.h b/zsnes/src/jma/portable.h new file mode 100644 index 00000000..623c5c2b --- /dev/null +++ b/zsnes/src/jma/portable.h @@ -0,0 +1,76 @@ +/* +Copyright (C) 2004 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 +as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You 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) + +//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); +} + +#endif diff --git a/zsnes/src/jma/rcdefs.h b/zsnes/src/jma/rcdefs.h new file mode 100644 index 00000000..0383460e --- /dev/null +++ b/zsnes/src/jma/rcdefs.h @@ -0,0 +1,61 @@ +/* +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 as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +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/zsnes/src/jma/rngcoder.h b/zsnes/src/jma/rngcoder.h new file mode 100644 index 00000000..0d8a2754 --- /dev/null +++ b/zsnes/src/jma/rngcoder.h @@ -0,0 +1,251 @@ +/* +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 as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +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" +#include "outbyte.h" + +namespace NCompression { +namespace NArithmetic { + +const UINT32 kNumTopBits = 24; +const UINT32 kTopValue = (1 << kNumTopBits); + +class CRangeEncoder +{ + NStream::COutByte m_Stream; + UINT64 m_Low; + UINT32 m_Range; + UINT32 m_FFNum; + BYTE m_Cache; + +public: + void Init(ISequentialOutStream *aStream) + { + m_Stream.Init(aStream); + m_Low = 0; + m_Range = UINT32(-1); + m_FFNum = 0; + m_Cache = 0; + } + + void FlushData() + { + // m_Low += 1; + for(int i = 0; i < 5; i++) + ShiftLow(); + } + + HRESULT FlushStream() + { return m_Stream.Flush(); } + + void Encode(UINT32 aStart, UINT32 aSize, UINT32 aTotal) + { + m_Low += aStart * (m_Range /= aTotal); + m_Range *= aSize; + while (m_Range < kTopValue) + { + m_Range <<= 8; + ShiftLow(); + } + } + + /* + void EncodeDirectBitsDiv(UINT32 aValue, UINT32 aNumTotalBits) + { + m_Low += aValue * (m_Range >>= aNumTotalBits); + Normalize(); + } + + void EncodeDirectBitsDiv2(UINT32 aValue, UINT32 aNumTotalBits) + { + if (aNumTotalBits <= kNumBottomBits) + EncodeDirectBitsDiv(aValue, aNumTotalBits); + else + { + EncodeDirectBitsDiv(aValue >> kNumBottomBits, (aNumTotalBits - kNumBottomBits)); + EncodeDirectBitsDiv(aValue & ((1 << kBottomValueBits) - 1), kNumBottomBits); + } + } + */ + void ShiftLow() + { + if (m_Low < (UINT32)0xFF000000 || UINT32(m_Low >> 32) == 1) + { + m_Stream.WriteByte(m_Cache + BYTE(m_Low >> 32)); + for (;m_FFNum != 0; m_FFNum--) + m_Stream.WriteByte(0xFF + BYTE(m_Low >> 32)); + m_Cache = BYTE(UINT32(m_Low) >> 24); + } + else + m_FFNum++; + m_Low = UINT32(m_Low) << 8; + } + + void EncodeDirectBits(UINT32 aValue, UINT32 aNumTotalBits) + { + for (int i = aNumTotalBits - 1; i >= 0; i--) + { + m_Range >>= 1; + if (((aValue >> i) & 1) == 1) + m_Low += m_Range; + if (m_Range < kTopValue) + { + m_Range <<= 8; + ShiftLow(); + } + } + } + + void EncodeBit(UINT32 aSize0, UINT32 aNumTotalBits, UINT32 aSymbol) + { + UINT32 aNewBound = (m_Range >> aNumTotalBits) * aSize0; + if (aSymbol == 0) + m_Range = aNewBound; + else + { + m_Low += aNewBound; + m_Range -= aNewBound; + } + while (m_Range < kTopValue) + { + m_Range <<= 8; + ShiftLow(); + } + } + + UINT64 GetProcessedSize() { return m_Stream.GetProcessedSize() + m_FFNum; } +}; + +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/zsnes/src/jma/winout.cpp b/zsnes/src/jma/winout.cpp new file mode 100644 index 00000000..61e9a652 --- /dev/null +++ b/zsnes/src/jma/winout.cpp @@ -0,0 +1,90 @@ +/* +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 as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +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/zsnes/src/jma/winout.h b/zsnes/src/jma/winout.h new file mode 100644 index 00000000..240ee891 --- /dev/null +++ b/zsnes/src/jma/winout.h @@ -0,0 +1,90 @@ +/* +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 as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +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++; + for(UINT32 i = 0; i < aLen; i++) + p[i] = p[i - aDistance]; + 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/zsnes/src/jma/zsnesjma.cpp b/zsnes/src/jma/zsnesjma.cpp new file mode 100644 index 00000000..5bb2a1f8 --- /dev/null +++ b/zsnes/src/jma/zsnesjma.cpp @@ -0,0 +1,64 @@ +/* +Copyright (C) 2004 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 +as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You 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 +using namespace std; + +#include "zsnesjma.h" +#include "jma.h" + +extern unsigned char *romdata; +extern unsigned int curromspace; +extern unsigned int maxromspace; + +void load_jma_file(const char *filename) +{ + try + { + JMA::jma_open JMAFile(filename); + vector file_info = JMAFile.get_files_info(); + + string our_file_name; + size_t our_file_size = 0; + + for (vector::iterator i = file_info.begin(); i != file_info.end(); i++) + { + //Check for valid ROM based on size + if ((i->size <= maxromspace+512) && (i->size > our_file_size)) + { + our_file_name = i->name; + our_file_size = i->size; + } + } + + if (!our_file_size) + { + return; + } + + JMAFile.extract_file(our_file_name, romdata); + + curromspace = our_file_size; + } + catch (JMA::jma_errors jma_error) + { + //No need to do anything + } +} + diff --git a/zsnes/src/jma/zsnesjma.h b/zsnes/src/jma/zsnesjma.h new file mode 100644 index 00000000..5b0ee927 --- /dev/null +++ b/zsnes/src/jma/zsnesjma.h @@ -0,0 +1,27 @@ +/* +Copyright (C) 2004 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 +as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You 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. +*/ + +#ifdef __cplusplus +extern "C" { +#endif +void load_jma_file(const char *filename); +#ifdef __cplusplus +} +#endif +