mirror of https://github.com/bsnes-emu/bsnes.git
Update to v074 release.
byuu says (since v073): This release adds full low-level emulation of the NEC uPD96050 coprocessor, used by the ST-0010 (F1 Race of Champions II) and the ST-0011 (Hayazashi Nidan Morita Shougi). The former was already playable with HLE, but lacked timing emulation. The latter has never been playable through emulation before now. But as with SD Gundam GX before, you really weren't missing much. [...] Also new in this release is my own Game Boy emulator. It is being used to provide native Super Game Boy support, built directly into bsnes. This core is released under the GPLv2, but I am willing to grant a more permissive license for other SNES emulators, if anyone is interested. Of course I cannot compete with the quality of gambatte, and certainly not from only a weeks' worth of work. Currently, there is no Game Boy-side sound output and there are quite a few bugs remaining in its emulation core. I would appreciate any help on this, the Game Boy is not my forte. So yes, we are taking a step back today, so that we may take two steps forward in the future. [...] Lastly, the debugger is still Linux-only, but it is now stable enough to be considered usable. Check it out if you like, compile with -DDEBUGGER to enable it.
This commit is contained in:
parent
92da6bde26
commit
20afa076ef
|
@ -1,7 +1,7 @@
|
|||
include nall/Makefile
|
||||
snes := snes
|
||||
gameboy := gameboy
|
||||
profile := compatibility
|
||||
profile := accuracy
|
||||
ui := ui
|
||||
|
||||
# compiler
|
||||
|
|
|
@ -3,12 +3,12 @@
|
|||
|
||||
namespace nall {
|
||||
template<int bits> inline unsigned uclamp(const unsigned x) {
|
||||
enum { y = (1U << bits) - 1 };
|
||||
enum { y = (1U << (bits - 1)) + ((1U << (bits - 1)) - 1) };
|
||||
return y + ((x - y) & -(x < y)); //min(x, y);
|
||||
}
|
||||
|
||||
template<int bits> inline unsigned uclip(const unsigned x) {
|
||||
enum { m = (1U << bits) - 1 };
|
||||
enum { m = (1U << (bits - 1)) + ((1U << (bits - 1)) - 1) };
|
||||
return (x & m);
|
||||
}
|
||||
|
||||
|
|
|
@ -400,75 +400,51 @@ SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) {
|
|||
}
|
||||
|
||||
if(has_dsp1) {
|
||||
xml << " <upd7725 program='dsp1b.bin' sha256='4d42db0f36faef263d6b93f508e8c1c4ae8fc2605fd35e3390ecc02905cd420c'>\n";
|
||||
xml << " <necdsp revision='upd7725' frequency='8000000' program='dsp1b.bin' sha256='4d42db0f36faef263d6b93f508e8c1c4ae8fc2605fd35e3390ecc02905cd420c'>\n";
|
||||
if(dsp1_mapper == DSP1LoROM1MB) {
|
||||
xml << " <dr>\n";
|
||||
xml << " <map address='20-3f:8000-bfff'/>\n";
|
||||
xml << " <map address='a0-bf:8000-bfff'/>\n";
|
||||
xml << " </dr>\n";
|
||||
xml << " <sr>\n";
|
||||
xml << " <map address='20-3f:c000-ffff'/>\n";
|
||||
xml << " <map address='a0-bf:c000-ffff'/>\n";
|
||||
xml << " </sr>\n";
|
||||
xml << " <dr mask='004000' test='000000'/>\n";
|
||||
xml << " <sr mask='004000' test='004000'/>\n";
|
||||
xml << " <map address='20-3f:8000-ffff'/>\n";
|
||||
xml << " <map address='a0-bf:8000-ffff'/>\n";
|
||||
} else if(dsp1_mapper == DSP1LoROM2MB) {
|
||||
xml << " <dr>\n";
|
||||
xml << " <map address='60-6f:0000-3fff'/>\n";
|
||||
xml << " <map address='e0-ef:0000-3fff'/>\n";
|
||||
xml << " </dr>\n";
|
||||
xml << " <sr>\n";
|
||||
xml << " <map address='60-6f:4000-7fff'/>\n";
|
||||
xml << " <map address='e0-ef:4000-7fff'/>\n";
|
||||
xml << " </sr>\n";
|
||||
xml << " <dr mask='004000' test='000000'/>\n";
|
||||
xml << " <sr mask='004000' test='004000'/>\n";
|
||||
xml << " <map address='60-6f:0000-7fff'/>\n";
|
||||
xml << " <map address='e0-ef:0000-7fff'/>\n";
|
||||
} else if(dsp1_mapper == DSP1HiROM) {
|
||||
xml << " <dr>\n";
|
||||
xml << " <map address='00-1f:6000-6fff'/>\n";
|
||||
xml << " <map address='80-9f:6000-6fff'/>\n";
|
||||
xml << " </dr>\n";
|
||||
xml << " <sr>\n";
|
||||
xml << " <map address='00-1f:7000-7fff'/>\n";
|
||||
xml << " <map address='80-9f:7000-7fff'/>\n";
|
||||
xml << " </sr>\n";
|
||||
xml << " <dr mask='001000' test='000000'/>\n";
|
||||
xml << " <sr mask='001000' test='001000'/>\n";
|
||||
xml << " <map address='00-1f:6000-7fff'/>\n";
|
||||
xml << " <map address='80-9f:6000-7fff'/>\n";
|
||||
}
|
||||
xml << " </upd7725>\n";
|
||||
xml << " </necdsp>\n";
|
||||
}
|
||||
|
||||
if(has_dsp2) {
|
||||
xml << " <upd7725 program='dsp2.bin' sha256='5efbdf96ed0652790855225964f3e90e6a4d466cfa64df25b110933c6cf94ea1'>\n";
|
||||
xml << " <dr>\n";
|
||||
xml << " <map address='20-3f:8000-bfff'/>\n";
|
||||
xml << " <map address='a0-bf:8000-bfff'/>\n";
|
||||
xml << " </dr>\n";
|
||||
xml << " <sr>\n";
|
||||
xml << " <map address='20-3f:c000-ffff'/>\n";
|
||||
xml << " <map address='a0-bf:c000-ffff'/>\n";
|
||||
xml << " </sr>\n";
|
||||
xml << " </upd7725>\n";
|
||||
xml << " <necdsp revision='upd7725' frequency='8000000' program='dsp2.bin' sha256='5efbdf96ed0652790855225964f3e90e6a4d466cfa64df25b110933c6cf94ea1'>\n";
|
||||
xml << " <dr mask='004000' test='000000'/>\n";
|
||||
xml << " <sr mask='004000' test='004000'/>\n";
|
||||
xml << " <map address='20-3f:8000-ffff'/>\n";
|
||||
xml << " <map address='a0-bf:8000-ffff'/>\n";
|
||||
xml << " </necdsp>\n";
|
||||
}
|
||||
|
||||
if(has_dsp3) {
|
||||
xml << " <upd7725 program='dsp3.bin' sha256='2e635f72e4d4681148bc35429421c9b946e4f407590e74e31b93b8987b63ba90'>\n";
|
||||
xml << " <dr>\n";
|
||||
xml << " <map address='20-3f:8000-bfff'/>\n";
|
||||
xml << " <map address='a0-bf:8000-bfff'/>\n";
|
||||
xml << " </dr>\n";
|
||||
xml << " <sr>\n";
|
||||
xml << " <map address='20-3f:c000-ffff'/>\n";
|
||||
xml << " <map address='a0-bf:c000-ffff'/>\n";
|
||||
xml << " </sr>\n";
|
||||
xml << " </upd7725>\n";
|
||||
xml << " <necdsp revision='upd7725' frequency='8000000' program='dsp3.bin' sha256='2e635f72e4d4681148bc35429421c9b946e4f407590e74e31b93b8987b63ba90'>\n";
|
||||
xml << " <dr mask='004000' test='000000'/>\n";
|
||||
xml << " <sr mask='004000' test='004000'/>\n";
|
||||
xml << " <map address='20-3f:8000-ffff'/>\n";
|
||||
xml << " <map address='a0-bf:8000-ffff'/>\n";
|
||||
xml << " </necdsp>\n";
|
||||
}
|
||||
|
||||
if(has_dsp4) {
|
||||
xml << " <upd7725 program='dsp4.bin' sha256='63ede17322541c191ed1fdf683872554a0a57306496afc43c59de7c01a6e764a'>\n";
|
||||
xml << " <dr>\n";
|
||||
xml << " <map address='30-3f:8000-bfff'/>\n";
|
||||
xml << " <map address='b0-bf:8000-bfff'/>\n";
|
||||
xml << " </dr>\n";
|
||||
xml << " <sr>\n";
|
||||
xml << " <map address='30-3f:c000-ffff'/>\n";
|
||||
xml << " <map address='b0-bf:c000-ffff'/>\n";
|
||||
xml << " </sr>\n";
|
||||
xml << " </upd7725>\n";
|
||||
xml << " <necdsp revision='upd7725' frequency='8000000' program='dsp4.bin' sha256='63ede17322541c191ed1fdf683872554a0a57306496afc43c59de7c01a6e764a'>\n";
|
||||
xml << " <dr mask='004000' test='000000'/>\n";
|
||||
xml << " <sr mask='004000' test='004000'/>\n";
|
||||
xml << " <map address='30-3f:8000-ffff'/>\n";
|
||||
xml << " <map address='b0-bf:8000-ffff'/>\n";
|
||||
xml << " </necdsp>\n";
|
||||
}
|
||||
|
||||
if(has_obc1) {
|
||||
|
@ -479,17 +455,23 @@ SNESCartridge::SNESCartridge(const uint8_t *data, unsigned size) {
|
|||
}
|
||||
|
||||
if(has_st010) {
|
||||
xml << " <upd96050 program='st0010.bin' frequency='10000000' sha256='55c697e864562445621cdf8a7bf6e84ae91361e393d382a3704e9aa55559041e'>\n";
|
||||
xml << " <necdsp revision='upd96050' frequency='10000000' program='st0010.bin' sha256='55c697e864562445621cdf8a7bf6e84ae91361e393d382a3704e9aa55559041e'>\n";
|
||||
xml << " <dr mask='080001' test='000000'/>\n";
|
||||
xml << " <sr mask='080001' test='000001'/>\n";
|
||||
xml << " <dp mask='080000' test='080000'/>\n";
|
||||
xml << " <map address='60-6f:0000-0fff'/>\n";
|
||||
xml << " <map address='e0-ef:0000-0fff'/>\n";
|
||||
xml << " </upd96050>\n";
|
||||
xml << " </necdsp>\n";
|
||||
}
|
||||
|
||||
if(has_st011) {
|
||||
xml << " <upd96050 program='st0011.bin' frequency='15000000' sha256='448e0deb0f580833ea878f4894a56124da18453d2d78e821388b6545909ba00a'>\n";
|
||||
xml << " <necdsp revision='upd96050' frequency='15000000' program='st0011.bin' sha256='b71d71fa5f18ff39b2b3688e914a04d1286b613002ddde827529fdc54650a130'>\n";
|
||||
xml << " <dr mask='080001' test='000000'/>\n";
|
||||
xml << " <sr mask='080001' test='000001'/>\n";
|
||||
xml << " <dp mask='080000' test='080000'/>\n";
|
||||
xml << " <map address='60-6f:0000-0fff'/>\n";
|
||||
xml << " <map address='e0-ef:0000-0fff'/>\n";
|
||||
xml << " </upd96050>\n";
|
||||
xml << " </necdsp>\n";
|
||||
}
|
||||
|
||||
if(has_st018) {
|
||||
|
|
|
@ -8,84 +8,110 @@
|
|||
namespace nall {
|
||||
template<unsigned bits> class uint_t {
|
||||
private:
|
||||
enum { bytes = (bits + 7) >> 3 }; //minimum number of bytes needed to store value
|
||||
typedef typename static_if<
|
||||
sizeof(int) >= bytes,
|
||||
unsigned int,
|
||||
typename static_if<
|
||||
sizeof(long) >= bytes,
|
||||
unsigned long,
|
||||
typename static_if<
|
||||
sizeof(long long) >= bytes,
|
||||
unsigned long long,
|
||||
void
|
||||
>::type
|
||||
>::type
|
||||
>::type T;
|
||||
static_assert(!std::is_same<T, void>::value, "");
|
||||
T data;
|
||||
unsigned data;
|
||||
|
||||
public:
|
||||
inline operator T() const { return data; }
|
||||
inline T operator ++(int) { T r = data; data = uclip<bits>(data + 1); return r; }
|
||||
inline T operator --(int) { T r = data; data = uclip<bits>(data - 1); return r; }
|
||||
inline T operator ++() { return data = uclip<bits>(data + 1); }
|
||||
inline T operator --() { return data = uclip<bits>(data - 1); }
|
||||
inline T operator =(const T i) { return data = uclip<bits>(i); }
|
||||
inline T operator |=(const T i) { return data = uclip<bits>(data | i); }
|
||||
inline T operator ^=(const T i) { return data = uclip<bits>(data ^ i); }
|
||||
inline T operator &=(const T i) { return data = uclip<bits>(data & i); }
|
||||
inline T operator<<=(const T i) { return data = uclip<bits>(data << i); }
|
||||
inline T operator>>=(const T i) { return data = uclip<bits>(data >> i); }
|
||||
inline T operator +=(const T i) { return data = uclip<bits>(data + i); }
|
||||
inline T operator -=(const T i) { return data = uclip<bits>(data - i); }
|
||||
inline T operator *=(const T i) { return data = uclip<bits>(data * i); }
|
||||
inline T operator /=(const T i) { return data = uclip<bits>(data / i); }
|
||||
inline T operator %=(const T i) { return data = uclip<bits>(data % i); }
|
||||
inline operator unsigned() const { return data; }
|
||||
inline unsigned operator ++(int) { unsigned r = data; data = uclip<bits>(data + 1); return r; }
|
||||
inline unsigned operator --(int) { unsigned r = data; data = uclip<bits>(data - 1); return r; }
|
||||
inline unsigned operator ++() { return data = uclip<bits>(data + 1); }
|
||||
inline unsigned operator --() { return data = uclip<bits>(data - 1); }
|
||||
inline unsigned operator =(const unsigned i) { return data = uclip<bits>(i); }
|
||||
inline unsigned operator |=(const unsigned i) { return data = uclip<bits>(data | i); }
|
||||
inline unsigned operator ^=(const unsigned i) { return data = uclip<bits>(data ^ i); }
|
||||
inline unsigned operator &=(const unsigned i) { return data = uclip<bits>(data & i); }
|
||||
inline unsigned operator<<=(const unsigned i) { return data = uclip<bits>(data << i); }
|
||||
inline unsigned operator>>=(const unsigned i) { return data = uclip<bits>(data >> i); }
|
||||
inline unsigned operator +=(const unsigned i) { return data = uclip<bits>(data + i); }
|
||||
inline unsigned operator -=(const unsigned i) { return data = uclip<bits>(data - i); }
|
||||
inline unsigned operator *=(const unsigned i) { return data = uclip<bits>(data * i); }
|
||||
inline unsigned operator /=(const unsigned i) { return data = uclip<bits>(data / i); }
|
||||
inline unsigned operator %=(const unsigned i) { return data = uclip<bits>(data % i); }
|
||||
|
||||
inline uint_t() : data(0) {}
|
||||
inline uint_t(const T i) : data(uclip<bits>(i)) {}
|
||||
inline uint_t(const unsigned i) : data(uclip<bits>(i)) {}
|
||||
};
|
||||
|
||||
template<unsigned bits> class int_t {
|
||||
private:
|
||||
enum { bytes = (bits + 7) >> 3 }; //minimum number of bytes needed to store value
|
||||
typedef typename static_if<
|
||||
sizeof(int) >= bytes,
|
||||
signed int,
|
||||
typename static_if<
|
||||
sizeof(long) >= bytes,
|
||||
signed long,
|
||||
typename static_if<
|
||||
sizeof(long long) >= bytes,
|
||||
signed long long,
|
||||
void
|
||||
>::type
|
||||
>::type
|
||||
>::type T;
|
||||
static_assert(!std::is_same<T, void>::value, "");
|
||||
T data;
|
||||
signed data;
|
||||
|
||||
public:
|
||||
inline operator T() const { return data; }
|
||||
inline T operator ++(int) { T r = data; data = sclip<bits>(data + 1); return r; }
|
||||
inline T operator --(int) { T r = data; data = sclip<bits>(data - 1); return r; }
|
||||
inline T operator ++() { return data = sclip<bits>(data + 1); }
|
||||
inline T operator --() { return data = sclip<bits>(data - 1); }
|
||||
inline T operator =(const T i) { return data = sclip<bits>(i); }
|
||||
inline T operator |=(const T i) { return data = sclip<bits>(data | i); }
|
||||
inline T operator ^=(const T i) { return data = sclip<bits>(data ^ i); }
|
||||
inline T operator &=(const T i) { return data = sclip<bits>(data & i); }
|
||||
inline T operator<<=(const T i) { return data = sclip<bits>(data << i); }
|
||||
inline T operator>>=(const T i) { return data = sclip<bits>(data >> i); }
|
||||
inline T operator +=(const T i) { return data = sclip<bits>(data + i); }
|
||||
inline T operator -=(const T i) { return data = sclip<bits>(data - i); }
|
||||
inline T operator *=(const T i) { return data = sclip<bits>(data * i); }
|
||||
inline T operator /=(const T i) { return data = sclip<bits>(data / i); }
|
||||
inline T operator %=(const T i) { return data = sclip<bits>(data % i); }
|
||||
inline operator signed() const { return data; }
|
||||
inline signed operator ++(int) { signed r = data; data = sclip<bits>(data + 1); return r; }
|
||||
inline signed operator --(int) { signed r = data; data = sclip<bits>(data - 1); return r; }
|
||||
inline signed operator ++() { return data = sclip<bits>(data + 1); }
|
||||
inline signed operator --() { return data = sclip<bits>(data - 1); }
|
||||
inline signed operator =(const signed i) { return data = sclip<bits>(i); }
|
||||
inline signed operator |=(const signed i) { return data = sclip<bits>(data | i); }
|
||||
inline signed operator ^=(const signed i) { return data = sclip<bits>(data ^ i); }
|
||||
inline signed operator &=(const signed i) { return data = sclip<bits>(data & i); }
|
||||
inline signed operator<<=(const signed i) { return data = sclip<bits>(data << i); }
|
||||
inline signed operator>>=(const signed i) { return data = sclip<bits>(data >> i); }
|
||||
inline signed operator +=(const signed i) { return data = sclip<bits>(data + i); }
|
||||
inline signed operator -=(const signed i) { return data = sclip<bits>(data - i); }
|
||||
inline signed operator *=(const signed i) { return data = sclip<bits>(data * i); }
|
||||
inline signed operator /=(const signed i) { return data = sclip<bits>(data / i); }
|
||||
inline signed operator %=(const signed i) { return data = sclip<bits>(data % i); }
|
||||
|
||||
inline int_t() : data(0) {}
|
||||
inline int_t(const T i) : data(sclip<bits>(i)) {}
|
||||
inline int_t(const signed i) : data(sclip<bits>(i)) {}
|
||||
};
|
||||
|
||||
class varuint_t {
|
||||
private:
|
||||
unsigned data;
|
||||
unsigned mask;
|
||||
|
||||
public:
|
||||
inline operator unsigned() const { return data; }
|
||||
inline unsigned operator ++(int) { unsigned r = data; data = (data + 1) & mask; return r; }
|
||||
inline unsigned operator --(int) { unsigned r = data; data = (data - 1) & mask; return r; }
|
||||
inline unsigned operator ++() { return data = (data + 1) & mask; }
|
||||
inline unsigned operator --() { return data = (data - 1) & mask; }
|
||||
inline unsigned operator =(const unsigned i) { return data = (i) & mask; }
|
||||
inline unsigned operator |=(const unsigned i) { return data = (data | i) & mask; }
|
||||
inline unsigned operator ^=(const unsigned i) { return data = (data ^ i) & mask; }
|
||||
inline unsigned operator &=(const unsigned i) { return data = (data & i) & mask; }
|
||||
inline unsigned operator<<=(const unsigned i) { return data = (data << i) & mask; }
|
||||
inline unsigned operator>>=(const unsigned i) { return data = (data >> i) & mask; }
|
||||
inline unsigned operator +=(const unsigned i) { return data = (data + i) & mask; }
|
||||
inline unsigned operator -=(const unsigned i) { return data = (data - i) & mask; }
|
||||
inline unsigned operator *=(const unsigned i) { return data = (data * i) & mask; }
|
||||
inline unsigned operator /=(const unsigned i) { return data = (data / i) & mask; }
|
||||
inline unsigned operator %=(const unsigned i) { return data = (data % i) & mask; }
|
||||
|
||||
inline void bits(unsigned bits) { mask = (1U << (bits - 1)) + ((1U << (bits - 1)) - 1); data &= mask; }
|
||||
inline varuint_t() : data(0), mask(~0U) {}
|
||||
inline varuint_t(const unsigned i) : data(i), mask(~0U) {}
|
||||
};
|
||||
|
||||
class varuintmax_t {
|
||||
private:
|
||||
uintmax_t data;
|
||||
uintmax_t mask;
|
||||
|
||||
public:
|
||||
inline operator uintmax_t() const { return data; }
|
||||
inline uintmax_t operator ++(int) { uintmax_t r = data; data = (data + 1) & mask; return r; }
|
||||
inline uintmax_t operator --(int) { uintmax_t r = data; data = (data - 1) & mask; return r; }
|
||||
inline uintmax_t operator ++() { return data = (data + 1) & mask; }
|
||||
inline uintmax_t operator --() { return data = (data - 1) & mask; }
|
||||
inline uintmax_t operator =(const uintmax_t i) { return data = (i) & mask; }
|
||||
inline uintmax_t operator |=(const uintmax_t i) { return data = (data | i) & mask; }
|
||||
inline uintmax_t operator ^=(const uintmax_t i) { return data = (data ^ i) & mask; }
|
||||
inline uintmax_t operator &=(const uintmax_t i) { return data = (data & i) & mask; }
|
||||
inline uintmax_t operator<<=(const uintmax_t i) { return data = (data << i) & mask; }
|
||||
inline uintmax_t operator>>=(const uintmax_t i) { return data = (data >> i) & mask; }
|
||||
inline uintmax_t operator +=(const uintmax_t i) { return data = (data + i) & mask; }
|
||||
inline uintmax_t operator -=(const uintmax_t i) { return data = (data - i) & mask; }
|
||||
inline uintmax_t operator *=(const uintmax_t i) { return data = (data * i) & mask; }
|
||||
inline uintmax_t operator /=(const uintmax_t i) { return data = (data / i) & mask; }
|
||||
inline uintmax_t operator %=(const uintmax_t i) { return data = (data % i) & mask; }
|
||||
|
||||
inline void bits(unsigned bits) { mask = (1ULL << (bits - 1)) + ((1ULL << (bits - 1)) - 1); data &= mask; }
|
||||
inline varuintmax_t() : data(0), mask(~0ULL) {}
|
||||
inline varuintmax_t(const uintmax_t i) : data(i), mask(~0ULL) {}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -2,10 +2,9 @@ snes_objects := snes-system
|
|||
snes_objects += snes-cartridge snes-cheat
|
||||
snes_objects += snes-memory snes-cpucore snes-smpcore
|
||||
snes_objects += snes-cpu snes-smp snes-dsp snes-ppu
|
||||
snes_objects += snes-icd2 snes-superfx snes-sa1
|
||||
snes_objects += snes-necdsp snes-upd7725 snes-upd96050
|
||||
snes_objects += snes-icd2 snes-superfx snes-sa1 snes-necdsp
|
||||
snes_objects += snes-bsx snes-srtc snes-sdd1 snes-spc7110 snes-cx4
|
||||
snes_objects += snes-obc1 snes-st0010 snes-st0011 snes-st0018
|
||||
snes_objects += snes-obc1 snes-st0018
|
||||
snes_objects += snes-msu1 snes-serial
|
||||
objects += $(snes_objects)
|
||||
|
||||
|
@ -39,23 +38,19 @@ obj/snes-cpu.o : $(snescpu)/cpu.cpp $(call rwildcard,$(snescpu)/)
|
|||
obj/snes-smp.o : $(snessmp)/smp.cpp $(call rwildcard,$(snessmp)/)
|
||||
obj/snes-dsp.o : $(snesdsp)/dsp.cpp $(call rwildcard,$(snesdsp)/)
|
||||
obj/snes-ppu.o : $(snesppu)/ppu.cpp $(call rwildcard,$(snesppu)/)
|
||||
obj/snes-cartridge.o: $(snes)/cartridge/cartridge.cpp $(call rwilddcard,$(snes)/cartridge/)
|
||||
obj/snes-cheat.o : $(snes)/cheat/cheat.cpp $(call rwildcard,$(snes)/cheat/)
|
||||
obj/snes-cartridge.o: $(snes)/cartridge/cartridge.cpp $(snes)/cartridge/*
|
||||
obj/snes-cheat.o : $(snes)/cheat/cheat.cpp $(snes)/cheat/*
|
||||
|
||||
obj/snes-icd2.o : $(snes)/chip/icd2/icd2.cpp $(call rwildcard,$(snes)/chip/icd2/)
|
||||
obj/snes-superfx.o : $(snes)/chip/superfx/superfx.cpp $(call rwildcard,$(snes)/chip/superfx/)
|
||||
obj/snes-sa1.o : $(snes)/chip/sa1/sa1.cpp $(call rwildcard,$(snes)/chip/sa1/)
|
||||
obj/snes-necdsp.o : $(snes)/chip/necdsp/core/core.cpp $(call rwildcard,$(snes)/chip/necdsp/core/)
|
||||
obj/snes-upd7725.o : $(snes)/chip/necdsp/upd7725/upd7725.cpp $(call rwildcard,$(snes)/chip/necdsp/)
|
||||
obj/snes-upd96050.o: $(snes)/chip/necdsp/upd96050/upd96050.cpp $(call rwildcard,$(snes)/chip/necdsp/)
|
||||
obj/snes-necdsp.o : $(snes)/chip/necdsp/necdsp.cpp $(call rwildcard,$(snes)/chip/necdsp/)
|
||||
obj/snes-bsx.o : $(snes)/chip/bsx/bsx.cpp $(snes)/chip/bsx/*
|
||||
obj/snes-srtc.o : $(snes)/chip/srtc/srtc.cpp $(snes)/chip/srtc/*
|
||||
obj/snes-sdd1.o : $(snes)/chip/sdd1/sdd1.cpp $(snes)/chip/sdd1/*
|
||||
obj/snes-spc7110.o : $(snes)/chip/spc7110/spc7110.cpp $(snes)/chip/spc7110/*
|
||||
obj/snes-cx4.o : $(snes)/chip/cx4/cx4.cpp $(snes)/chip/cx4/*
|
||||
obj/snes-obc1.o : $(snes)/chip/obc1/obc1.cpp $(snes)/chip/obc1/*
|
||||
obj/snes-st0010.o : $(snes)/chip/st0010/st0010.cpp $(snes)/chip/st0010/*
|
||||
obj/snes-st0011.o : $(snes)/chip/st0011/st0011.cpp $(snes)/chip/st0011/*
|
||||
obj/snes-st0018.o : $(snes)/chip/st0018/st0018.cpp $(snes)/chip/st0018/*
|
||||
obj/snes-msu1.o : $(snes)/chip/msu1/msu1.cpp $(snes)/chip/msu1/*
|
||||
obj/snes-serial.o : $(snes)/chip/serial/serial.cpp $(snes)/chip/serial/*
|
||||
|
|
|
@ -22,22 +22,17 @@ void Cartridge::load(Mode cartridge_mode, const lstring &xml_list) {
|
|||
mode = cartridge_mode;
|
||||
region = Region::NTSC;
|
||||
ram_size = 0;
|
||||
spc7110_data_rom_offset = 0x100000;
|
||||
supergameboy_version = SuperGameBoyVersion::Version1;
|
||||
|
||||
has_bsx_slot = false;
|
||||
has_superfx = false;
|
||||
has_sa1 = false;
|
||||
has_upd7725 = false;
|
||||
has_upd96050 = false;
|
||||
has_necdsp = false;
|
||||
has_srtc = false;
|
||||
has_sdd1 = false;
|
||||
has_spc7110 = false;
|
||||
has_spc7110rtc = false;
|
||||
has_cx4 = false;
|
||||
has_obc1 = false;
|
||||
has_st0010 = false;
|
||||
has_st0011 = false;
|
||||
has_st0018 = false;
|
||||
has_msu1 = false;
|
||||
has_serial = false;
|
||||
|
|
|
@ -13,11 +13,6 @@ public:
|
|||
PAL,
|
||||
};
|
||||
|
||||
enum class SuperGameBoyVersion : unsigned {
|
||||
Version1,
|
||||
Version2,
|
||||
};
|
||||
|
||||
//assigned externally to point to file-system datafiles (msu1 and serial)
|
||||
//example: "/path/to/filename.sfc" would set this to "/path/to/filename"
|
||||
readwrite<string> basename;
|
||||
|
@ -29,22 +24,17 @@ public:
|
|||
readonly<Mode> mode;
|
||||
readonly<Region> region;
|
||||
readonly<unsigned> ram_size;
|
||||
readonly<unsigned> spc7110_data_rom_offset;
|
||||
readonly<SuperGameBoyVersion> supergameboy_version;
|
||||
|
||||
readonly<bool> has_bsx_slot;
|
||||
readonly<bool> has_superfx;
|
||||
readonly<bool> has_sa1;
|
||||
readonly<bool> has_upd7725;
|
||||
readonly<bool> has_upd96050;
|
||||
readonly<bool> has_necdsp;
|
||||
readonly<bool> has_srtc;
|
||||
readonly<bool> has_sdd1;
|
||||
readonly<bool> has_spc7110;
|
||||
readonly<bool> has_spc7110rtc;
|
||||
readonly<bool> has_cx4;
|
||||
readonly<bool> has_obc1;
|
||||
readonly<bool> has_st0010;
|
||||
readonly<bool> has_st0011;
|
||||
readonly<bool> has_st0018;
|
||||
readonly<bool> has_msu1;
|
||||
readonly<bool> has_serial;
|
||||
|
@ -85,8 +75,7 @@ private:
|
|||
void xml_parse_icd2(xml_element&);
|
||||
void xml_parse_superfx(xml_element&);
|
||||
void xml_parse_sa1(xml_element&);
|
||||
void xml_parse_upd7725(xml_element&);
|
||||
void xml_parse_upd96050(xml_element&);
|
||||
void xml_parse_necdsp(xml_element&);
|
||||
void xml_parse_bsx(xml_element&);
|
||||
void xml_parse_sufamiturbo(xml_element&);
|
||||
void xml_parse_supergameboy(xml_element&);
|
||||
|
@ -94,9 +83,7 @@ private:
|
|||
void xml_parse_sdd1(xml_element&);
|
||||
void xml_parse_spc7110(xml_element&);
|
||||
void xml_parse_cx4(xml_element&);
|
||||
void xml_parse_necdsp(xml_element&);
|
||||
void xml_parse_obc1(xml_element&);
|
||||
void xml_parse_setadsp(xml_element&);
|
||||
void xml_parse_setarisc(xml_element&);
|
||||
void xml_parse_msu1(xml_element&);
|
||||
void xml_parse_serial(xml_element&);
|
||||
|
|
|
@ -35,8 +35,7 @@ void Cartridge::parse_xml_cartridge(const char *data) {
|
|||
if(node.name == "icd2") xml_parse_icd2(node);
|
||||
if(node.name == "superfx") xml_parse_superfx(node);
|
||||
if(node.name == "sa1") xml_parse_sa1(node);
|
||||
if(node.name == "upd7725") xml_parse_upd7725(node);
|
||||
if(node.name == "upd96050") xml_parse_upd96050(node);
|
||||
if(node.name == "necdsp") xml_parse_necdsp(node);
|
||||
if(node.name == "bsx") xml_parse_bsx(node);
|
||||
if(node.name == "sufamiturbo") xml_parse_sufamiturbo(node);
|
||||
if(node.name == "srtc") xml_parse_srtc(node);
|
||||
|
@ -44,7 +43,6 @@ void Cartridge::parse_xml_cartridge(const char *data) {
|
|||
if(node.name == "spc7110") xml_parse_spc7110(node);
|
||||
if(node.name == "cx4") xml_parse_cx4(node);
|
||||
if(node.name == "obc1") xml_parse_obc1(node);
|
||||
if(node.name == "setadsp") xml_parse_setadsp(node);
|
||||
if(node.name == "setarisc") xml_parse_setarisc(node);
|
||||
if(node.name == "msu1") xml_parse_msu1(node);
|
||||
if(node.name == "serial") xml_parse_serial(node);
|
||||
|
@ -98,11 +96,12 @@ void Cartridge::xml_parse_ram(xml_element &root) {
|
|||
|
||||
void Cartridge::xml_parse_icd2(xml_element &root) {
|
||||
if(mode != Mode::SuperGameBoy) return;
|
||||
icd2.revision = 1;
|
||||
|
||||
foreach(attr, root.attribute) {
|
||||
if(attr.name == "revision") {
|
||||
if(attr.content == "1") supergameboy_version = SuperGameBoyVersion::Version1;
|
||||
if(attr.content == "2") supergameboy_version = SuperGameBoyVersion::Version2;
|
||||
if(attr.content == "1") icd2.revision = 1;
|
||||
if(attr.content == "2") icd2.revision = 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -226,132 +225,79 @@ void Cartridge::xml_parse_sa1(xml_element &root) {
|
|||
}
|
||||
}
|
||||
|
||||
void Cartridge::xml_parse_upd7725(xml_element &root) {
|
||||
has_upd7725 = true;
|
||||
void Cartridge::xml_parse_necdsp(xml_element &root) {
|
||||
has_necdsp = true;
|
||||
necdsp.revision = NECDSP::Revision::uPD7725;
|
||||
necdsp.frequency = 8000000;
|
||||
|
||||
bool program = false;
|
||||
bool sha256 = false;
|
||||
string xml_hash;
|
||||
string rom_hash;
|
||||
for(unsigned n = 0; n < 16384; n++) necdsp.programROM[n] = 0x000000;
|
||||
for(unsigned n = 0; n < 2048; n++) necdsp.dataROM[n] = 0x0000;
|
||||
|
||||
for(unsigned n = 0; n < 2048; n++) upd7725.programROM[n] = 0;
|
||||
for(unsigned n = 0; n < 1024; n++) upd7725.dataROM[n] = 0;
|
||||
string program, programhash;
|
||||
string sha256;
|
||||
|
||||
foreach(attr, root.attribute) {
|
||||
if(attr.name == "program") {
|
||||
file fp;
|
||||
fp.open(string(dir(basename()), attr.content), file::mode::read);
|
||||
if(fp.open() && fp.size() == 8192) {
|
||||
program = true;
|
||||
if(attr.name == "revision") {
|
||||
if(attr.content == "upd7725" ) necdsp.revision = NECDSP::Revision::uPD7725;
|
||||
if(attr.content == "upd96050") necdsp.revision = NECDSP::Revision::uPD96050;
|
||||
} else if(attr.name == "frequency") {
|
||||
necdsp.frequency = decimal(attr.content);
|
||||
} else if(attr.name == "program") {
|
||||
program = attr.content;
|
||||
} else if(attr.name == "sha256") {
|
||||
sha256 = attr.content;
|
||||
}
|
||||
}
|
||||
|
||||
for(unsigned n = 0; n < 2048; n++) {
|
||||
upd7725.programROM[n] = fp.readm(3);
|
||||
}
|
||||
for(unsigned n = 0; n < 1024; n++) {
|
||||
upd7725.dataROM[n] = fp.readm(2);
|
||||
}
|
||||
unsigned promsize = (necdsp.revision == NECDSP::Revision::uPD7725 ? 2048 : 16384);
|
||||
unsigned dromsize = (necdsp.revision == NECDSP::Revision::uPD7725 ? 1024 : 2048);
|
||||
unsigned filesize = promsize * 3 + dromsize * 2;
|
||||
|
||||
file fp;
|
||||
if(fp.open(string(dir(basename()), program), file::mode::read)) {
|
||||
if(fp.size() == filesize) {
|
||||
for(unsigned n = 0; n < promsize; n++) necdsp.programROM[n] = fp.readm(3);
|
||||
for(unsigned n = 0; n < dromsize; n++) necdsp.dataROM[n] = fp.readm(2);
|
||||
|
||||
fp.seek(0);
|
||||
uint8 data[8192];
|
||||
fp.read(data, 8192);
|
||||
fp.close();
|
||||
uint8_t data[filesize];
|
||||
fp.read(data, filesize);
|
||||
|
||||
sha256_ctx sha;
|
||||
uint8 shahash[32];
|
||||
sha256_init(&sha);
|
||||
sha256_chunk(&sha, data, 8192);
|
||||
sha256_chunk(&sha, data, filesize);
|
||||
sha256_final(&sha);
|
||||
sha256_hash(&sha, shahash);
|
||||
foreach(n, shahash) rom_hash.append(hex<2>(n));
|
||||
}
|
||||
} else if(attr.name == "sha256") {
|
||||
sha256 = true;
|
||||
xml_hash = attr.content;
|
||||
foreach(n, shahash) programhash.append(hex<2>(n));
|
||||
}
|
||||
fp.close();
|
||||
}
|
||||
|
||||
foreach(node, root.element) {
|
||||
if(node.name == "dr") {
|
||||
foreach(leaf, node.element) {
|
||||
if(leaf.name == "map") {
|
||||
Mapping m(upd7725dr);
|
||||
foreach(attr, leaf.attribute) {
|
||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||
}
|
||||
mapping.append(m);
|
||||
}
|
||||
}
|
||||
} else if(node.name == "sr") {
|
||||
foreach(leaf, node.element) {
|
||||
if(leaf.name == "map") {
|
||||
Mapping m(upd7725sr);
|
||||
foreach(attr, leaf.attribute) {
|
||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||
}
|
||||
mapping.append(m);
|
||||
}
|
||||
}
|
||||
foreach(attr, node.attribute) {
|
||||
if(attr.name == "mask") necdsp.drmask = hex(attr.content);
|
||||
if(attr.name == "test") necdsp.drtest = hex(attr.content);
|
||||
}
|
||||
}
|
||||
|
||||
if(program == false) {
|
||||
system.interface->message("Warning: uPD7725 program is missing.");
|
||||
} else if(sha256 == true && xml_hash != rom_hash) {
|
||||
system.interface->message({
|
||||
"Warning: uPD7725 program SHA256 is incorrect.\n\n"
|
||||
"Expected:\n", xml_hash, "\n\n"
|
||||
"Actual:\n", rom_hash
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void Cartridge::xml_parse_upd96050(xml_element &root) {
|
||||
has_upd96050 = true;
|
||||
|
||||
bool program = false;
|
||||
bool sha256 = false;
|
||||
string xml_hash;
|
||||
string rom_hash;
|
||||
|
||||
for(unsigned n = 0; n < 16384; n++) upd96050.programROM[n] = 0;
|
||||
for(unsigned n = 0; n < 2048; n++) upd96050.dataROM[n] = 0;
|
||||
|
||||
foreach(attr, root.attribute) {
|
||||
if(attr.name == "program") {
|
||||
file fp;
|
||||
fp.open(string(dir(basename()), attr.content), file::mode::read);
|
||||
if(fp.open() && fp.size() == 52 * 1024) {
|
||||
program = true;
|
||||
|
||||
for(unsigned n = 0; n < 16384; n++) {
|
||||
upd96050.programROM[n] = fp.readm(3);
|
||||
}
|
||||
for(unsigned n = 0; n < 2048; n++) {
|
||||
upd96050.dataROM[n] = fp.readm(2);
|
||||
}
|
||||
|
||||
fp.seek(0);
|
||||
uint8 data[52 * 1024];
|
||||
fp.read(data, 52 * 1024);
|
||||
fp.close();
|
||||
|
||||
sha256_ctx sha;
|
||||
uint8 shahash[32];
|
||||
sha256_init(&sha);
|
||||
sha256_chunk(&sha, data, 52 * 1024);
|
||||
sha256_final(&sha);
|
||||
sha256_hash(&sha, shahash);
|
||||
foreach(n, shahash) rom_hash.append(hex<2>(n));
|
||||
}
|
||||
} else if(attr.name == "sha256") {
|
||||
sha256 = true;
|
||||
xml_hash = attr.content;
|
||||
if(node.name == "sr") {
|
||||
foreach(attr, node.attribute) {
|
||||
if(attr.name == "mask") necdsp.srmask = hex(attr.content);
|
||||
if(attr.name == "test") necdsp.srtest = hex(attr.content);
|
||||
}
|
||||
}
|
||||
|
||||
if(node.name == "dp") {
|
||||
foreach(attr, node.attribute) {
|
||||
if(attr.name == "mask") necdsp.dpmask = hex(attr.content);
|
||||
if(attr.name == "test") necdsp.dptest = hex(attr.content);
|
||||
}
|
||||
}
|
||||
|
||||
foreach(node, root.element) {
|
||||
if(node.name == "map") {
|
||||
Mapping m(upd96050);
|
||||
Mapping m(necdsp);
|
||||
foreach(attr, node.attribute) {
|
||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||
}
|
||||
|
@ -359,13 +305,13 @@ void Cartridge::xml_parse_upd96050(xml_element &root) {
|
|||
}
|
||||
}
|
||||
|
||||
if(program == false) {
|
||||
system.interface->message("Warning: uPD96050 program is missing.");
|
||||
} else if(sha256 == true && xml_hash != rom_hash) {
|
||||
if(program == "") {
|
||||
system.interface->message({ "Warning: NEC DSP program ", program, " is missing." });
|
||||
} else if(sha256 != "" && sha256 != programhash) {
|
||||
system.interface->message({
|
||||
"Warning: uPD96050 program SHA256 is incorrect.\n\n"
|
||||
"Expected:\n", xml_hash, "\n\n"
|
||||
"Actual:\n", rom_hash
|
||||
"Warning: NEC DSP program ", program, " SHA256 is incorrect.\n\n"
|
||||
"Expected:\n", sha256, "\n\n"
|
||||
"Actual:\n", programhash
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -491,6 +437,7 @@ void Cartridge::xml_parse_sdd1(xml_element &root) {
|
|||
|
||||
void Cartridge::xml_parse_spc7110(xml_element &root) {
|
||||
has_spc7110 = true;
|
||||
spc7110.data_rom_offset = 0x100000;
|
||||
|
||||
foreach(node, root.element) {
|
||||
if(node.name == "dcu") {
|
||||
|
@ -509,7 +456,7 @@ void Cartridge::xml_parse_spc7110(xml_element &root) {
|
|||
Mapping m(spc7110mcu);
|
||||
foreach(attr, leaf.attribute) {
|
||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||
if(attr.name == "offset") spc7110_data_rom_offset = hex(attr.content);
|
||||
if(attr.name == "offset") spc7110.data_rom_offset = hex(attr.content);
|
||||
}
|
||||
mapping.append(m);
|
||||
}
|
||||
|
@ -585,34 +532,6 @@ void Cartridge::xml_parse_obc1(xml_element &root) {
|
|||
}
|
||||
}
|
||||
|
||||
void Cartridge::xml_parse_setadsp(xml_element &root) {
|
||||
unsigned program = 0;
|
||||
|
||||
foreach(attr, root.attribute) {
|
||||
if(attr.name == "program") {
|
||||
if(attr.content == "ST-0010") {
|
||||
program = 1;
|
||||
has_st0010 = true;
|
||||
} else if(attr.content == "ST-0011") {
|
||||
program = 2;
|
||||
has_st0011 = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Memory *map[3] = { 0, &st0010, 0 };
|
||||
|
||||
foreach(node, root.element) {
|
||||
if(node.name == "map" && map[program]) {
|
||||
Mapping m(*map[program]);
|
||||
foreach(attr, node.attribute) {
|
||||
if(attr.name == "address") xml_parse_address(m, attr.content);
|
||||
}
|
||||
mapping.append(m);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Cartridge::xml_parse_setarisc(xml_element &root) {
|
||||
unsigned program = 0;
|
||||
|
||||
|
|
|
@ -6,17 +6,13 @@ struct Coprocessor : Processor {
|
|||
#include <snes/chip/icd2/icd2.hpp>
|
||||
#include <snes/chip/superfx/superfx.hpp>
|
||||
#include <snes/chip/sa1/sa1.hpp>
|
||||
#include <snes/chip/necdsp/core/core.hpp>
|
||||
#include <snes/chip/necdsp/upd7725/upd7725.hpp>
|
||||
#include <snes/chip/necdsp/upd96050/upd96050.hpp>
|
||||
#include <snes/chip/necdsp/necdsp.hpp>
|
||||
#include <snes/chip/bsx/bsx.hpp>
|
||||
#include <snes/chip/srtc/srtc.hpp>
|
||||
#include <snes/chip/sdd1/sdd1.hpp>
|
||||
#include <snes/chip/spc7110/spc7110.hpp>
|
||||
#include <snes/chip/cx4/cx4.hpp>
|
||||
#include <snes/chip/obc1/obc1.hpp>
|
||||
#include <snes/chip/st0010/st0010.hpp>
|
||||
#include <snes/chip/st0011/st0011.hpp>
|
||||
#include <snes/chip/st0018/st0018.hpp>
|
||||
#include <snes/chip/msu1/msu1.hpp>
|
||||
#include <snes/chip/serial/serial.hpp>
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
class ICD2 : public GameBoy::Interface, public Coprocessor, public MMIO, public Memory {
|
||||
public:
|
||||
unsigned revision;
|
||||
|
||||
static void Enter();
|
||||
void enter();
|
||||
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
class uPDcore {
|
||||
public:
|
||||
#include "registers.hpp"
|
||||
|
||||
uint24 *programROM;
|
||||
uint16 *dataROM;
|
||||
uint16 *dataRAM;
|
||||
|
||||
unsigned programROMSize;
|
||||
unsigned dataROMSize;
|
||||
unsigned dataRAMSize;
|
||||
|
||||
void exec();
|
||||
void exec_op(uint24 opcode);
|
||||
void exec_rt(uint24 opcode);
|
||||
void exec_jp(uint24 opcode);
|
||||
void exec_ld(uint24 opcode);
|
||||
void stack_push();
|
||||
void stack_pull();
|
||||
|
||||
string disassemble(uint14 ip);
|
||||
|
||||
void serialize(serializer&);
|
||||
uPDcore(unsigned pcbits, unsigned rpbits, unsigned dpbits);
|
||||
~uPDcore();
|
||||
};
|
|
@ -1,7 +1,7 @@
|
|||
#ifdef UPDCORE_CPP
|
||||
#ifdef NECDSP_CPP
|
||||
|
||||
string uPDcore::disassemble(uint14 ip) {
|
||||
string output = { hex<3>(ip), " " };
|
||||
string NECDSP::disassemble(uint14 ip) {
|
||||
string output = { hex<4>(ip), " " };
|
||||
uint24 opcode = programROM[ip];
|
||||
uint2 type = opcode >> 22;
|
||||
|
||||
|
@ -134,6 +134,7 @@ string uPDcore::disassemble(uint14 ip) {
|
|||
uint11 na = opcode >> 2;
|
||||
|
||||
switch(brch) {
|
||||
case 0x000: output << "jmpso "; break;
|
||||
case 0x080: output << "jnca "; break;
|
||||
case 0x082: output << "jca "; break;
|
||||
case 0x084: output << "jncb "; break;
|
||||
|
@ -168,12 +169,14 @@ string uPDcore::disassemble(uint14 ip) {
|
|||
case 0x0ba: output << "jsoak "; break;
|
||||
case 0x0bc: output << "jnrqm "; break;
|
||||
case 0x0be: output << "jrqm "; break;
|
||||
case 0x100: output << "jmp "; break;
|
||||
case 0x140: output << "call "; break;
|
||||
case 0x100: output << "ljmp "; break;
|
||||
case 0x101: output << "hjmp "; break;
|
||||
case 0x140: output << "lcall "; break;
|
||||
case 0x141: output << "hcall "; break;
|
||||
default: output << "?????? "; break;
|
||||
}
|
||||
|
||||
output << "$" << hex<3>(na);
|
||||
output << "$" << hex<4>(na);
|
||||
}
|
||||
|
||||
if(type == 3) { //LD
|
|
@ -0,0 +1,83 @@
|
|||
#ifdef NECDSP_CPP
|
||||
|
||||
uint8 NECDSP::read(unsigned addr) {
|
||||
cpu.synchronize_coprocessor();
|
||||
if((addr & srmask) == srtest) return sr_read();
|
||||
if((addr & drmask) == drtest) return dr_read();
|
||||
if((addr & dpmask) == dptest) return dp_read(addr);
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
void NECDSP::write(unsigned addr, uint8 data) {
|
||||
cpu.synchronize_coprocessor();
|
||||
if((addr & srmask) == srtest) return sr_write(data);
|
||||
if((addr & drmask) == drtest) return dr_write(data);
|
||||
if((addr & dpmask) == dptest) return dp_write(addr, data);
|
||||
}
|
||||
|
||||
uint8 NECDSP::sr_read() {
|
||||
return regs.sr >> 8;
|
||||
}
|
||||
|
||||
void NECDSP::sr_write(uint8 data) {
|
||||
}
|
||||
|
||||
uint8 NECDSP::dr_read() {
|
||||
if(regs.sr.drc == 0) {
|
||||
//16-bit
|
||||
if(regs.sr.drs == 0) {
|
||||
regs.sr.drs = 1;
|
||||
return regs.dr >> 0;
|
||||
} else {
|
||||
regs.sr.rqm = 0;
|
||||
regs.sr.drs = 0;
|
||||
return regs.dr >> 8;
|
||||
}
|
||||
} else {
|
||||
//8-bit
|
||||
regs.sr.rqm = 0;
|
||||
return regs.dr >> 0;
|
||||
}
|
||||
}
|
||||
|
||||
void NECDSP::dr_write(uint8 data) {
|
||||
if(regs.sr.drc == 0) {
|
||||
//16-bit
|
||||
if(regs.sr.drs == 0) {
|
||||
regs.sr.drs = 1;
|
||||
regs.dr = (regs.dr & 0xff00) | (data << 0);
|
||||
} else {
|
||||
regs.sr.rqm = 0;
|
||||
regs.sr.drs = 0;
|
||||
regs.dr = (data << 8) | (regs.dr & 0x00ff);
|
||||
}
|
||||
} else {
|
||||
//8-bit
|
||||
regs.sr.rqm = 0;
|
||||
regs.dr = (regs.dr & 0xff00) | (data << 0);
|
||||
}
|
||||
}
|
||||
|
||||
uint8 NECDSP::dp_read(unsigned addr) {
|
||||
bool hi = addr & 1;
|
||||
addr = (addr >> 1) & 2047;
|
||||
|
||||
if(hi == false) {
|
||||
return dataRAM[addr] >> 0;
|
||||
} else {
|
||||
return dataRAM[addr] >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
void NECDSP::dp_write(unsigned addr, uint8 data) {
|
||||
bool hi = addr & 1;
|
||||
addr = (addr >> 1) & 2047;
|
||||
|
||||
if(hi == false) {
|
||||
dataRAM[addr] = (dataRAM[addr] & 0xff00) | (data << 0);
|
||||
} else {
|
||||
dataRAM[addr] = (dataRAM[addr] & 0x00ff) | (data << 8);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,30 +1,29 @@
|
|||
#include <snes/snes.hpp>
|
||||
|
||||
#define UPDCORE_CPP
|
||||
#define NECDSP_CPP
|
||||
namespace SNES {
|
||||
|
||||
#include "memory.cpp"
|
||||
#include "disassembler.cpp"
|
||||
#include "serialization.cpp"
|
||||
NECDSP necdsp;
|
||||
|
||||
void uPDcore::exec() {
|
||||
#if 0
|
||||
static uint16 lastpc = 0xffff;
|
||||
if(lastpc != regs.pc) {
|
||||
print(
|
||||
"A:", hex<4>((uint16)regs.a), " B:", hex<4>((uint16)regs.b),
|
||||
" DR:", hex<4>(regs.dr), " SR:", hex<4>(regs.sr),
|
||||
" FA:", hex<2>(regs.flaga), " FB:", hex<2>(regs.flagb),
|
||||
" RP:", hex<4>(regs.rp), " DP:", hex<4>(regs.dp), " SO:", hex<4>(regs.so), "\n",
|
||||
"K: ", hex<4>((uint16)regs.k), " L:", hex<4>((uint16)regs.l),
|
||||
" M:", hex<4>((uint16)regs.m), " N:", hex<4>((uint16)regs.n),
|
||||
" TR:", hex<4>(regs.tr), " TRB:", hex<4>(regs.trb), " [DP15]:", hex<4>(dataRAM[0x15]), "\n"
|
||||
);
|
||||
print(disassemble(lastpc = regs.pc), "\n");
|
||||
void NECDSP::Enter() { necdsp.enter(); }
|
||||
|
||||
void NECDSP::enter() {
|
||||
while(true) {
|
||||
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
|
||||
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
|
||||
}
|
||||
|
||||
exec();
|
||||
step(1);
|
||||
synchronize_cpu();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
uint24 opcode = programROM[regs.pc];
|
||||
regs.pc = regs.pc + 1;
|
||||
void NECDSP::exec() {
|
||||
uint24 opcode = programROM[regs.pc++];
|
||||
switch(opcode >> 22) {
|
||||
case 0: exec_op(opcode); break;
|
||||
case 1: exec_rt(opcode); break;
|
||||
|
@ -37,7 +36,7 @@ if(lastpc != regs.pc) {
|
|||
regs.n = result << 1; //store low 15-bits + zero
|
||||
}
|
||||
|
||||
void uPDcore::exec_op(uint24 opcode) {
|
||||
void NECDSP::exec_op(uint24 opcode) {
|
||||
uint2 pselect = opcode >> 20; //P select
|
||||
uint4 alu = opcode >> 16; //ALU operation mode
|
||||
uint1 asl = opcode >> 15; //accumulator select
|
||||
|
@ -155,25 +154,27 @@ void uPDcore::exec_op(uint24 opcode) {
|
|||
case 3: regs.dp = (regs.dp & 0xf0); break; //DPCLR
|
||||
}
|
||||
|
||||
regs.dp = regs.dp ^ (dphm << 4);
|
||||
regs.dp ^= dphm << 4;
|
||||
|
||||
if(rpdcr) regs.rp = regs.rp - 1;
|
||||
if(rpdcr) regs.rp--;
|
||||
}
|
||||
|
||||
void uPDcore::exec_rt(uint24 opcode) {
|
||||
void NECDSP::exec_rt(uint24 opcode) {
|
||||
exec_op(opcode);
|
||||
stack_pull();
|
||||
regs.pc = regs.stack[--regs.sp];
|
||||
}
|
||||
|
||||
void uPDcore::exec_jp(uint24 opcode) {
|
||||
void NECDSP::exec_jp(uint24 opcode) {
|
||||
uint9 brch = opcode >> 13; //branch
|
||||
uint11 na = opcode >> 2; //next address
|
||||
uint2 bank = opcode >> 0; //bank address
|
||||
|
||||
uint16 jps = (regs.pc & 0x3800) | (na << 0);
|
||||
uint16 jpl = (regs.pc & 0x2000) | (bank << 11) | (na << 0);
|
||||
uint16 jps = (regs.pc & 0x2000) | (bank << 11) | (na << 0);
|
||||
uint16 jpl = (bank << 11) | (na << 0);
|
||||
|
||||
switch(brch) {
|
||||
case 0x000: regs.pc = regs.so; return; //JMPSO
|
||||
|
||||
case 0x080: if(regs.flaga.c == 0) regs.pc = jps; return; //JNCA
|
||||
case 0x082: if(regs.flaga.c == 1) regs.pc = jps; return; //JCA
|
||||
case 0x084: if(regs.flagb.c == 0) regs.pc = jps; return; //JNCB
|
||||
|
@ -212,59 +213,15 @@ void uPDcore::exec_jp(uint24 opcode) {
|
|||
case 0x0bc: if(regs.sr.rqm == 0) regs.pc = jps; return; //JNRQM
|
||||
case 0x0be: if(regs.sr.rqm == 1) regs.pc = jps; return; //JRQM
|
||||
|
||||
case 0x100: regs.pc = jps; return; //JMP
|
||||
case 0x140: stack_push(); regs.pc = jps; return; //CALL
|
||||
case 0x100: regs.pc = 0x0000 | jpl; return; //LJMP
|
||||
case 0x101: regs.pc = 0x2000 | jpl; return; //HJMP
|
||||
|
||||
case 0x140: regs.stack[regs.sp++] = regs.pc; regs.pc = 0x0000 | jpl; return; //LCALL
|
||||
case 0x141: regs.stack[regs.sp++] = regs.pc; regs.pc = 0x2000 | jpl; return; //HCALL
|
||||
}
|
||||
|
||||
switch(brch) {
|
||||
case 0x000: regs.pc = regs.so; return;
|
||||
|
||||
case 0x081: if(regs.flaga.c == 1) regs.pc = jpl; return;
|
||||
|
||||
case 0x0bf: if(regs.sr.rqm == 1) regs.pc = jpl; return;
|
||||
}
|
||||
|
||||
print(hex<4>(regs.pc - 1), ": unknown jump ", hex<3>(brch), "\n");
|
||||
|
||||
/*bool r = false;
|
||||
switch(brch) {
|
||||
case 0x080: r = (regs.flaga.c == 0); break; //JNCA
|
||||
case 0x082: r = (regs.flaga.c == 1); break; //JCA
|
||||
case 0x084: r = (regs.flagb.c == 0); break; //JNCB
|
||||
case 0x086: r = (regs.flagb.c == 1); break; //JCB
|
||||
case 0x088: r = (regs.flaga.z == 0); break; //JNZA
|
||||
case 0x08a: r = (regs.flaga.z == 1); break; //JZA
|
||||
case 0x08c: r = (regs.flagb.z == 0); break; //JNZB
|
||||
case 0x08e: r = (regs.flagb.z == 1); break; //JZB
|
||||
case 0x090: r = (regs.flaga.ov0 == 0); break; //JNOVA0
|
||||
case 0x092: r = (regs.flaga.ov0 == 1); break; //JOVA0
|
||||
case 0x094: r = (regs.flagb.ov0 == 0); break; //JNOVB0
|
||||
case 0x096: r = (regs.flagb.ov0 == 1); break; //JOVB0
|
||||
case 0x098: r = (regs.flaga.ov1 == 0); break; //JNOVA1
|
||||
case 0x09a: r = (regs.flaga.ov1 == 1); break; //JOVA1
|
||||
case 0x09c: r = (regs.flagb.ov1 == 0); break; //JNOVB1
|
||||
case 0x09e: r = (regs.flagb.ov1 == 1); break; //JOVB1
|
||||
case 0x0a0: r = (regs.flaga.s0 == 0); break; //JNSA0
|
||||
case 0x0a2: r = (regs.flaga.s0 == 1); break; //JSA0
|
||||
case 0x0a4: r = (regs.flagb.s0 == 0); break; //JNSB0
|
||||
case 0x0a6: r = (regs.flagb.s0 == 1); break; //JSB0
|
||||
case 0x0a8: r = (regs.flaga.s1 == 0); break; //JNSA1
|
||||
case 0x0aa: r = (regs.flaga.s1 == 1); break; //JSA1
|
||||
case 0x0ac: r = (regs.flagb.s1 == 0); break; //JNSB1
|
||||
case 0x0ae: r = (regs.flagb.s1 == 1); break; //JSB1
|
||||
case 0x0b0: r = (regs.dp & 0x0f) == 0x00; break; //JDPL0
|
||||
case 0x0b1: r = (regs.dp & 0x0f) != 0x00; break; //JDPLN0
|
||||
case 0x0b2: r = (regs.dp & 0x0f) == 0x0f; break; //JDPLF
|
||||
case 0x0b3: r = (regs.dp & 0x0f) != 0x0f; break; //JDPLNF
|
||||
case 0x0bc: r = (regs.sr.rqm == 0); break; //JNRQM
|
||||
case 0x0be: r = (regs.sr.rqm == 1); break; //JRQM
|
||||
case 0x100: r = true; break; //JMP
|
||||
case 0x140: r = true; stack_push(); break; //CALL
|
||||
}
|
||||
if(r) regs.pc = na;*/
|
||||
}
|
||||
|
||||
void uPDcore::exec_ld(uint24 opcode) {
|
||||
void NECDSP::exec_ld(uint24 opcode) {
|
||||
uint16 id = opcode >> 6; //immediate data
|
||||
uint4 dst = opcode >> 0; //destination
|
||||
|
||||
|
@ -290,35 +247,58 @@ void uPDcore::exec_ld(uint24 opcode) {
|
|||
}
|
||||
}
|
||||
|
||||
void uPDcore::stack_push() {
|
||||
for(unsigned r = 63; r >= 1; r--) regs.stack[r] = regs.stack[r - 1];
|
||||
regs.stack[0] = regs.pc;
|
||||
void NECDSP::init() {
|
||||
}
|
||||
|
||||
void uPDcore::stack_pull() {
|
||||
regs.pc = regs.stack[0];
|
||||
for(unsigned r = 0; r <= 62; r++) regs.stack[r] = regs.stack[r + 1];
|
||||
regs.stack[63] = 0x0000;
|
||||
void NECDSP::enable() {
|
||||
}
|
||||
|
||||
uPDcore::uPDcore(unsigned pcbits, unsigned rpbits, unsigned dpbits) {
|
||||
programROMSize = 1 << pcbits;
|
||||
dataROMSize = 1 << rpbits;
|
||||
dataRAMSize = 1 << dpbits;
|
||||
void NECDSP::power() {
|
||||
if(revision == Revision::uPD7725) {
|
||||
regs.pc.bits(11);
|
||||
regs.rp.bits(10);
|
||||
regs.dp.bits( 8);
|
||||
dpmask = 0x000000, dptest = 0xffffff; //uPD7725 not mapped to SNES bus
|
||||
}
|
||||
|
||||
programROM = new uint24[programROMSize];
|
||||
dataROM = new uint16[dataROMSize];
|
||||
dataRAM = new uint16[dataRAMSize];
|
||||
if(revision == Revision::uPD96050) {
|
||||
regs.pc.bits(14);
|
||||
regs.rp.bits(11);
|
||||
regs.dp.bits(11);
|
||||
}
|
||||
|
||||
regs.pc.mask = programROMSize - 1;
|
||||
regs.rp.mask = dataROMSize - 1;
|
||||
regs.dp.mask = dataRAMSize - 1;
|
||||
reset();
|
||||
}
|
||||
|
||||
uPDcore::~uPDcore() {
|
||||
delete[] programROM;
|
||||
delete[] dataROM;
|
||||
delete[] dataRAM;
|
||||
void NECDSP::reset() {
|
||||
create(NECDSP::Enter, frequency);
|
||||
|
||||
for(unsigned n = 0; n < 16; n++) regs.stack[n] = 0x0000;
|
||||
regs.pc = 0x0000;
|
||||
regs.rp = 0x0000;
|
||||
regs.dp = 0x0000;
|
||||
regs.sp = 0x0;
|
||||
regs.k = 0x0000;
|
||||
regs.l = 0x0000;
|
||||
regs.m = 0x0000;
|
||||
regs.n = 0x0000;
|
||||
regs.a = 0x0000;
|
||||
regs.b = 0x0000;
|
||||
regs.flaga = 0x00;
|
||||
regs.flagb = 0x00;
|
||||
regs.tr = 0x0000;
|
||||
regs.trb = 0x0000;
|
||||
regs.sr = 0x0000;
|
||||
regs.dr = 0x0000;
|
||||
regs.si = 0x0000;
|
||||
regs.so = 0x0000;
|
||||
regs.idb = 0x0000;
|
||||
}
|
||||
|
||||
NECDSP::NECDSP() {
|
||||
}
|
||||
|
||||
NECDSP::~NECDSP() {
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
class NECDSP : public Coprocessor, public Memory {
|
||||
public:
|
||||
enum class Revision : unsigned { uPD7725, uPD96050 } revision;
|
||||
unsigned frequency;
|
||||
unsigned drmask, drtest;
|
||||
unsigned srmask, srtest;
|
||||
unsigned dpmask, dptest;
|
||||
|
||||
#include "registers.hpp"
|
||||
|
||||
uint24 programROM[16384];
|
||||
uint16 dataROM[2048];
|
||||
uint16 dataRAM[2048];
|
||||
|
||||
unsigned programROMSize;
|
||||
unsigned dataROMSize;
|
||||
unsigned dataRAMSize;
|
||||
|
||||
static void Enter();
|
||||
void enter();
|
||||
|
||||
void exec();
|
||||
void exec_op(uint24 opcode);
|
||||
void exec_rt(uint24 opcode);
|
||||
void exec_jp(uint24 opcode);
|
||||
void exec_ld(uint24 opcode);
|
||||
|
||||
string disassemble(uint14 ip);
|
||||
|
||||
uint8 read(unsigned addr);
|
||||
void write(unsigned addr, uint8 data);
|
||||
|
||||
uint8 sr_read();
|
||||
void sr_write(uint8 data);
|
||||
|
||||
uint8 dr_read();
|
||||
void dr_write(uint8 data);
|
||||
|
||||
uint8 dp_read(unsigned addr);
|
||||
void dp_write(unsigned addr, uint8 data);
|
||||
|
||||
void init();
|
||||
void enable();
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
void serialize(serializer&);
|
||||
NECDSP();
|
||||
~NECDSP();
|
||||
};
|
||||
|
||||
extern NECDSP necdsp;
|
|
@ -1,16 +1,3 @@
|
|||
struct Pointer {
|
||||
uint16 data;
|
||||
uint16 mask;
|
||||
|
||||
inline operator unsigned() const {
|
||||
return data;
|
||||
}
|
||||
|
||||
inline unsigned operator=(unsigned d) {
|
||||
return data = d & mask;
|
||||
}
|
||||
};
|
||||
|
||||
struct Flag {
|
||||
bool s1, s0, c, z, ov1, ov0;
|
||||
|
||||
|
@ -42,10 +29,11 @@ struct Status {
|
|||
};
|
||||
|
||||
struct Regs {
|
||||
Pointer pc; //program counter
|
||||
Pointer rp; //ROM pointer
|
||||
Pointer dp; //data pointer
|
||||
uint16 stack[64]; //LIFO
|
||||
uint16 stack[16]; //LIFO
|
||||
varuint pc; //program counter
|
||||
varuint rp; //ROM pointer
|
||||
varuint dp; //data pointer
|
||||
uint4 sp; //stack pointer
|
||||
int16 k;
|
||||
int16 l;
|
||||
int16 m;
|
|
@ -1,18 +1,13 @@
|
|||
#ifdef UPDCORE_CPP
|
||||
#ifdef NECDSP_CPP
|
||||
|
||||
void uPDcore::serialize(serializer &s) {
|
||||
s.array(dataRAM, dataRAMSize);
|
||||
|
||||
s.integer(regs.pc.data);
|
||||
s.integer(regs.pc.mask);
|
||||
|
||||
s.integer(regs.rp.data);
|
||||
s.integer(regs.rp.mask);
|
||||
|
||||
s.integer(regs.dp.data);
|
||||
s.integer(regs.dp.mask);
|
||||
void NECDSP::serialize(serializer &s) {
|
||||
s.array(dataRAM);
|
||||
|
||||
s.array(regs.stack);
|
||||
s.integer(regs.pc);
|
||||
s.integer(regs.rp);
|
||||
s.integer(regs.dp);
|
||||
s.integer(regs.sp);
|
||||
|
||||
s.integer(regs.k);
|
||||
s.integer(regs.l);
|
||||
|
@ -51,6 +46,8 @@ void uPDcore::serialize(serializer &s) {
|
|||
s.integer(regs.sr.p0);
|
||||
|
||||
s.integer(regs.dr);
|
||||
s.integer(regs.si);
|
||||
s.integer(regs.so);
|
||||
s.integer(regs.idb);
|
||||
}
|
||||
|
|
@ -1,109 +0,0 @@
|
|||
#include <snes/snes.hpp>
|
||||
|
||||
#define UPD7725_CPP
|
||||
namespace SNES {
|
||||
|
||||
uPD7725 upd7725;
|
||||
uPD7725SR upd7725sr;
|
||||
uPD7725DR upd7725dr;
|
||||
|
||||
void uPD7725::Enter() { upd7725.enter(); }
|
||||
|
||||
void uPD7725::enter() {
|
||||
while(true) {
|
||||
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
|
||||
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
|
||||
}
|
||||
|
||||
uPDcore::exec();
|
||||
step(1);
|
||||
synchronize_cpu();
|
||||
}
|
||||
}
|
||||
|
||||
uint8 uPD7725::read(bool mode) {
|
||||
cpu.synchronize_coprocessor();
|
||||
if(mode == 0) return regs.sr >> 8;
|
||||
|
||||
if(regs.sr.drc == 0) {
|
||||
//16-bit
|
||||
if(regs.sr.drs == 0) {
|
||||
regs.sr.drs = 1;
|
||||
return regs.dr >> 0;
|
||||
} else {
|
||||
regs.sr.rqm = 0;
|
||||
regs.sr.drs = 0;
|
||||
return regs.dr >> 8;
|
||||
}
|
||||
} else {
|
||||
//8-bit
|
||||
regs.sr.rqm = 0;
|
||||
return regs.dr >> 0;
|
||||
}
|
||||
}
|
||||
|
||||
void uPD7725::write(bool mode, uint8 data) {
|
||||
cpu.synchronize_coprocessor();
|
||||
if(mode == 0) return;
|
||||
|
||||
if(regs.sr.drc == 0) {
|
||||
//16-bit
|
||||
if(regs.sr.drs == 0) {
|
||||
regs.sr.drs = 1;
|
||||
regs.dr = (regs.dr & 0xff00) | (data << 0);
|
||||
} else {
|
||||
regs.sr.rqm = 0;
|
||||
regs.sr.drs = 0;
|
||||
regs.dr = (data << 8) | (regs.dr & 0x00ff);
|
||||
}
|
||||
} else {
|
||||
//8-bit
|
||||
regs.sr.rqm = 0;
|
||||
regs.dr = (regs.dr & 0xff00) | (data << 0);
|
||||
}
|
||||
}
|
||||
|
||||
void uPD7725::init() {
|
||||
}
|
||||
|
||||
void uPD7725::enable() {
|
||||
}
|
||||
|
||||
void uPD7725::power() {
|
||||
for(unsigned i = 0; i < 256; i++) dataRAM[i] = 0x0000;
|
||||
reset();
|
||||
}
|
||||
|
||||
void uPD7725::reset() {
|
||||
create(uPD7725::Enter, 8 * 1024 * 1024); //8.192MHz
|
||||
|
||||
regs.pc = 0x000;
|
||||
regs.stack[0] = 0x000;
|
||||
regs.stack[1] = 0x000;
|
||||
regs.stack[2] = 0x000;
|
||||
regs.stack[3] = 0x000;
|
||||
regs.flaga = 0x00;
|
||||
regs.flagb = 0x00;
|
||||
regs.sr = 0x0000;
|
||||
regs.rp = 0x3ff;
|
||||
}
|
||||
|
||||
void uPD7725::serialize(serializer &s) {
|
||||
Coprocessor::serialize(s);
|
||||
uPDcore::serialize(s);
|
||||
}
|
||||
|
||||
uPD7725::uPD7725() : uPDcore(11, 10, 8) {
|
||||
//NEC uPD7725:
|
||||
//11-bit ProgramROM (2048 x 24-bit) w/4-level stack
|
||||
//10-bit DataROM (1024 x 16-bit)
|
||||
// 8-bit DataRAM ( 256 x 16-bit)
|
||||
}
|
||||
|
||||
uint8 uPD7725SR::read(unsigned) { return upd7725.read(0); }
|
||||
void uPD7725SR::write(unsigned, uint8 data) { upd7725.write(0, data); }
|
||||
|
||||
uint8 uPD7725DR::read(unsigned) { return upd7725.read(1); }
|
||||
void uPD7725DR::write(unsigned, uint8 data) { upd7725.write(1, data); }
|
||||
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
class uPD7725 : public Coprocessor, public uPDcore {
|
||||
public:
|
||||
static void Enter();
|
||||
void enter();
|
||||
void init();
|
||||
void enable();
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
void serialize(serializer&);
|
||||
uPD7725();
|
||||
|
||||
private:
|
||||
uint8 read(bool mode);
|
||||
void write(bool mode, uint8 data);
|
||||
|
||||
friend class uPD7725SR;
|
||||
friend class uPD7725DR;
|
||||
};
|
||||
|
||||
class uPD7725SR : public Memory {
|
||||
uint8 read(unsigned addr);
|
||||
void write(unsigned addr, uint8 data);
|
||||
};
|
||||
|
||||
class uPD7725DR : public Memory {
|
||||
uint8 read(unsigned addr);
|
||||
void write(unsigned addr, uint8 data);
|
||||
};
|
||||
|
||||
extern uPD7725 upd7725;
|
||||
extern uPD7725SR upd7725sr;
|
||||
extern uPD7725DR upd7725dr;
|
|
@ -1,142 +0,0 @@
|
|||
#include <snes/snes.hpp>
|
||||
|
||||
#define UPD96050_CPP
|
||||
namespace SNES {
|
||||
|
||||
uPD96050 upd96050;
|
||||
|
||||
void uPD96050::Enter() { upd96050.enter(); }
|
||||
|
||||
void uPD96050::enter() {
|
||||
while(true) {
|
||||
if(scheduler.sync == Scheduler::SynchronizeMode::All) {
|
||||
scheduler.exit(Scheduler::ExitReason::SynchronizeEvent);
|
||||
}
|
||||
|
||||
uPDcore::exec();
|
||||
step(1);
|
||||
synchronize_cpu();
|
||||
}
|
||||
}
|
||||
|
||||
uint8 uPD96050::read(unsigned addr) {
|
||||
cpu.synchronize_coprocessor();
|
||||
addr &= 0x8ffff;
|
||||
|
||||
if(addr == 0x00000) {
|
||||
if(regs.sr.drc == 0) {
|
||||
//16-bit
|
||||
if(regs.sr.drs == 0) {
|
||||
regs.sr.drs = 1;
|
||||
return regs.dr >> 0;
|
||||
} else {
|
||||
regs.sr.rqm = 0;
|
||||
regs.sr.drs = 0;
|
||||
return regs.dr >> 8;
|
||||
}
|
||||
} else {
|
||||
//8-bit
|
||||
regs.sr.rqm = 0;
|
||||
return regs.dr >> 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(addr == 0x00001) {
|
||||
return regs.sr >> 8;
|
||||
}
|
||||
|
||||
if(addr & 0x80000) {
|
||||
bool hi = addr & 1;
|
||||
addr = (addr >> 1) & 2047;
|
||||
|
||||
if(hi == false) {
|
||||
return dataRAM[addr] >> 0;
|
||||
} else {
|
||||
return dataRAM[addr] >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
void uPD96050::write(unsigned addr, uint8 data) {
|
||||
cpu.synchronize_coprocessor();
|
||||
addr &= 0x8ffff;
|
||||
|
||||
if(addr == 0x00000) {
|
||||
//print("DR = ", hex<2>(data), " @ ", hex<6>(cpu.regs.pc), "\n");
|
||||
if(regs.sr.drc == 0) {
|
||||
//16-bit
|
||||
if(regs.sr.drs == 0) {
|
||||
regs.sr.drs = 1;
|
||||
regs.dr = (regs.dr & 0xff00) | (data << 0);
|
||||
} else {
|
||||
regs.sr.rqm = 0;
|
||||
regs.sr.drs = 0;
|
||||
regs.dr = (data << 8) | (regs.dr & 0x00ff);
|
||||
}
|
||||
} else {
|
||||
//8-bit
|
||||
regs.sr.rqm = 0;
|
||||
regs.dr = (regs.dr & 0xff00) | (data << 0);
|
||||
}
|
||||
}
|
||||
|
||||
if(addr == 0x00001) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(addr & 0x80000) {
|
||||
bool hi = addr & 1;
|
||||
addr = (addr >> 1) & 2047;
|
||||
|
||||
if(hi == false) {
|
||||
dataRAM[addr] = (dataRAM[addr] & 0xff00) | (data << 0);
|
||||
} else {
|
||||
dataRAM[addr] = (dataRAM[addr] & 0x00ff) | (data << 8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void uPD96050::init() {
|
||||
}
|
||||
|
||||
void uPD96050::enable() {
|
||||
}
|
||||
|
||||
void uPD96050::power() {
|
||||
for(unsigned i = 0; i < 2048; i++) dataRAM[i] = 0x0000;
|
||||
reset();
|
||||
}
|
||||
|
||||
void uPD96050::reset() {
|
||||
create(uPD96050::Enter, 15 * 1000 * 1000);
|
||||
|
||||
regs.pc = 0x0000;
|
||||
regs.stack[0] = 0x0000;
|
||||
regs.stack[1] = 0x0000;
|
||||
regs.stack[2] = 0x0000;
|
||||
regs.stack[3] = 0x0000;
|
||||
regs.stack[4] = 0x0000;
|
||||
regs.stack[5] = 0x0000;
|
||||
regs.stack[6] = 0x0000;
|
||||
regs.stack[7] = 0x0000;
|
||||
regs.flaga = 0x00;
|
||||
regs.flagb = 0x00;
|
||||
regs.sr = 0x0000;
|
||||
regs.rp = 0x03ff;
|
||||
}
|
||||
|
||||
void uPD96050::serialize(serializer &s) {
|
||||
Coprocessor::serialize(s);
|
||||
uPDcore::serialize(s);
|
||||
}
|
||||
|
||||
uPD96050::uPD96050() : uPDcore(14, 11, 11) {
|
||||
//NEC uPD96050:
|
||||
//14-bit ProgramROM (16384 x 24-bit) w/8-level stack
|
||||
//11-bit DataROM ( 2048 x 16-bit)
|
||||
//11-bit DataRAM ( 2048 x 16-bit) w/battery backup
|
||||
}
|
||||
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
class uPD96050 : public Coprocessor, public uPDcore, public Memory {
|
||||
public:
|
||||
static void Enter();
|
||||
void enter();
|
||||
void init();
|
||||
void enable();
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
uint8 read(unsigned addr);
|
||||
void write(unsigned addr, uint8 data);
|
||||
|
||||
void serialize(serializer&);
|
||||
uPD96050();
|
||||
};
|
||||
|
||||
extern uPD96050 upd96050;
|
|
@ -24,9 +24,9 @@ void SPC7110Decomp::write(uint8 data) {
|
|||
}
|
||||
|
||||
uint8 SPC7110Decomp::dataread() {
|
||||
unsigned size = memory::cartrom.size() - cartridge.spc7110_data_rom_offset();
|
||||
unsigned size = memory::cartrom.size() - spc7110.data_rom_offset;
|
||||
while(decomp_offset >= size) decomp_offset -= size;
|
||||
return memory::cartrom.read(cartridge.spc7110_data_rom_offset() + decomp_offset++);
|
||||
return memory::cartrom.read(spc7110.data_rom_offset + decomp_offset++);
|
||||
}
|
||||
|
||||
void SPC7110Decomp::init(unsigned mode, unsigned offset, unsigned index) {
|
||||
|
|
|
@ -84,9 +84,9 @@ void SPC7110::reset() {
|
|||
}
|
||||
|
||||
unsigned SPC7110::datarom_addr(unsigned addr) {
|
||||
unsigned size = memory::cartrom.size() - cartridge.spc7110_data_rom_offset();
|
||||
unsigned size = memory::cartrom.size() - data_rom_offset;
|
||||
while(addr >= size) addr -= size;
|
||||
return cartridge.spc7110_data_rom_offset() + addr;
|
||||
return data_rom_offset + addr;
|
||||
}
|
||||
|
||||
unsigned SPC7110::data_pointer() { return r4811 + (r4812 << 8) + (r4813 << 16); }
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
class SPC7110 : public MMIO {
|
||||
public:
|
||||
unsigned data_rom_offset;
|
||||
|
||||
void init();
|
||||
void enable();
|
||||
void power();
|
||||
|
|
|
@ -1,130 +0,0 @@
|
|||
#ifdef ST0010_CPP
|
||||
|
||||
const int16 ST0010::sin_table[256] = {
|
||||
0x0000, 0x0324, 0x0648, 0x096a, 0x0c8c, 0x0fab, 0x12c8, 0x15e2,
|
||||
0x18f9, 0x1c0b, 0x1f1a, 0x2223, 0x2528, 0x2826, 0x2b1f, 0x2e11,
|
||||
0x30fb, 0x33df, 0x36ba, 0x398c, 0x3c56, 0x3f17, 0x41ce, 0x447a,
|
||||
0x471c, 0x49b4, 0x4c3f, 0x4ebf, 0x5133, 0x539b, 0x55f5, 0x5842,
|
||||
0x5a82, 0x5cb3, 0x5ed7, 0x60eb, 0x62f1, 0x64e8, 0x66cf, 0x68a6,
|
||||
0x6a6d, 0x6c23, 0x6dc9, 0x6f5e, 0x70e2, 0x7254, 0x73b5, 0x7504,
|
||||
0x7641, 0x776b, 0x7884, 0x7989, 0x7a7c, 0x7b5c, 0x7c29, 0x7ce3,
|
||||
0x7d89, 0x7e1d, 0x7e9c, 0x7f09, 0x7f61, 0x7fa6, 0x7fd8, 0x7ff5,
|
||||
0x7fff, 0x7ff5, 0x7fd8, 0x7fa6, 0x7f61, 0x7f09, 0x7e9c, 0x7e1d,
|
||||
0x7d89, 0x7ce3, 0x7c29, 0x7b5c, 0x7a7c, 0x7989, 0x7884, 0x776b,
|
||||
0x7641, 0x7504, 0x73b5, 0x7254, 0x70e2, 0x6f5e, 0x6dc9, 0x6c23,
|
||||
0x6a6d, 0x68a6, 0x66cf, 0x64e8, 0x62f1, 0x60eb, 0x5ed7, 0x5cb3,
|
||||
0x5a82, 0x5842, 0x55f5, 0x539b, 0x5133, 0x4ebf, 0x4c3f, 0x49b4,
|
||||
0x471c, 0x447a, 0x41ce, 0x3f17, 0x3c56, 0x398c, 0x36ba, 0x33df,
|
||||
0x30fb, 0x2e11, 0x2b1f, 0x2826, 0x2528, 0x2223, 0x1f1a, 0x1c0b,
|
||||
0x18f8, 0x15e2, 0x12c8, 0x0fab, 0x0c8c, 0x096a, 0x0648, 0x0324,
|
||||
0x0000, -0x0324, -0x0648, -0x096b, -0x0c8c, -0x0fab, -0x12c8, -0x15e2,
|
||||
-0x18f9, -0x1c0b, -0x1f1a, -0x2223, -0x2528, -0x2826, -0x2b1f, -0x2e11,
|
||||
-0x30fb, -0x33df, -0x36ba, -0x398d, -0x3c56, -0x3f17, -0x41ce, -0x447a,
|
||||
-0x471c, -0x49b4, -0x4c3f, -0x4ebf, -0x5133, -0x539b, -0x55f5, -0x5842,
|
||||
-0x5a82, -0x5cb3, -0x5ed7, -0x60ec, -0x62f1, -0x64e8, -0x66cf, -0x68a6,
|
||||
-0x6a6d, -0x6c23, -0x6dc9, -0x6f5e, -0x70e2, -0x7254, -0x73b5, -0x7504,
|
||||
-0x7641, -0x776b, -0x7884, -0x7989, -0x7a7c, -0x7b5c, -0x7c29, -0x7ce3,
|
||||
-0x7d89, -0x7e1d, -0x7e9c, -0x7f09, -0x7f61, -0x7fa6, -0x7fd8, -0x7ff5,
|
||||
-0x7fff, -0x7ff5, -0x7fd8, -0x7fa6, -0x7f61, -0x7f09, -0x7e9c, -0x7e1d,
|
||||
-0x7d89, -0x7ce3, -0x7c29, -0x7b5c, -0x7a7c, -0x7989, -0x7883, -0x776b,
|
||||
-0x7641, -0x7504, -0x73b5, -0x7254, -0x70e2, -0x6f5e, -0x6dc9, -0x6c23,
|
||||
-0x6a6d, -0x68a6, -0x66cf, -0x64e8, -0x62f1, -0x60eb, -0x5ed7, -0x5cb3,
|
||||
-0x5a82, -0x5842, -0x55f5, -0x539a, -0x5133, -0x4ebf, -0x4c3f, -0x49b3,
|
||||
-0x471c, -0x447a, -0x41cd, -0x3f17, -0x3c56, -0x398c, -0x36b9, -0x33de,
|
||||
-0x30fb, -0x2e10, -0x2b1f, -0x2826, -0x2527, -0x2223, -0x1f19, -0x1c0b,
|
||||
-0x18f8, -0x15e2, -0x12c8, -0x0fab, -0x0c8b, -0x096a, -0x0647, -0x0324
|
||||
};
|
||||
|
||||
const int16 ST0010::mode7_scale[176] = {
|
||||
0x0380, 0x0325, 0x02da, 0x029c, 0x0268, 0x023b, 0x0215, 0x01f3,
|
||||
0x01d5, 0x01bb, 0x01a3, 0x018e, 0x017b, 0x016a, 0x015a, 0x014b,
|
||||
0x013e, 0x0132, 0x0126, 0x011c, 0x0112, 0x0109, 0x0100, 0x00f8,
|
||||
0x00f0, 0x00e9, 0x00e3, 0x00dc, 0x00d6, 0x00d1, 0x00cb, 0x00c6,
|
||||
0x00c1, 0x00bd, 0x00b8, 0x00b4, 0x00b0, 0x00ac, 0x00a8, 0x00a5,
|
||||
0x00a2, 0x009e, 0x009b, 0x0098, 0x0095, 0x0093, 0x0090, 0x008d,
|
||||
0x008b, 0x0088, 0x0086, 0x0084, 0x0082, 0x0080, 0x007e, 0x007c,
|
||||
0x007a, 0x0078, 0x0076, 0x0074, 0x0073, 0x0071, 0x006f, 0x006e,
|
||||
0x006c, 0x006b, 0x0069, 0x0068, 0x0067, 0x0065, 0x0064, 0x0063,
|
||||
0x0062, 0x0060, 0x005f, 0x005e, 0x005d, 0x005c, 0x005b, 0x005a,
|
||||
0x0059, 0x0058, 0x0057, 0x0056, 0x0055, 0x0054, 0x0053, 0x0052,
|
||||
0x0051, 0x0051, 0x0050, 0x004f, 0x004e, 0x004d, 0x004d, 0x004c,
|
||||
0x004b, 0x004b, 0x004a, 0x0049, 0x0048, 0x0048, 0x0047, 0x0047,
|
||||
0x0046, 0x0045, 0x0045, 0x0044, 0x0044, 0x0043, 0x0042, 0x0042,
|
||||
0x0041, 0x0041, 0x0040, 0x0040, 0x003f, 0x003f, 0x003e, 0x003e,
|
||||
0x003d, 0x003d, 0x003c, 0x003c, 0x003b, 0x003b, 0x003a, 0x003a,
|
||||
0x003a, 0x0039, 0x0039, 0x0038, 0x0038, 0x0038, 0x0037, 0x0037,
|
||||
0x0036, 0x0036, 0x0036, 0x0035, 0x0035, 0x0035, 0x0034, 0x0034,
|
||||
0x0034, 0x0033, 0x0033, 0x0033, 0x0032, 0x0032, 0x0032, 0x0031,
|
||||
0x0031, 0x0031, 0x0030, 0x0030, 0x0030, 0x0030, 0x002f, 0x002f,
|
||||
0x002f, 0x002e, 0x002e, 0x002e, 0x002e, 0x002d, 0x002d, 0x002d,
|
||||
0x002d, 0x002c, 0x002c, 0x002c, 0x002c, 0x002b, 0x002b, 0x002b
|
||||
};
|
||||
|
||||
const uint8 ST0010::arctan[32][32] = {
|
||||
{ 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80 },
|
||||
{ 0x80, 0xa0, 0xad, 0xb3, 0xb6, 0xb8, 0xb9, 0xba, 0xbb, 0xbb, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd,
|
||||
0xbd, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbf, 0xbf, 0xbf, 0xbf },
|
||||
{ 0x80, 0x93, 0xa0, 0xa8, 0xad, 0xb0, 0xb3, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xbb,
|
||||
0xbb, 0xbb, 0xbb, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd },
|
||||
{ 0x80, 0x8d, 0x98, 0xa0, 0xa6, 0xaa, 0xad, 0xb0, 0xb1, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb7, 0xb8,
|
||||
0xb8, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbc, 0xbc, 0xbc, 0xbc },
|
||||
{ 0x80, 0x8a, 0x93, 0x9a, 0xa0, 0xa5, 0xa8, 0xab, 0xad, 0xaf, 0xb0, 0xb2, 0xb3, 0xb4, 0xb5, 0xb5,
|
||||
0xb6, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xba, 0xba, 0xba, 0xba, 0xba, 0xbb, 0xbb },
|
||||
{ 0x80, 0x88, 0x90, 0x96, 0x9b, 0xa0, 0xa4, 0xa7, 0xa9, 0xab, 0xad, 0xaf, 0xb0, 0xb1, 0xb2, 0xb3,
|
||||
0xb4, 0xb4, 0xb5, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9 },
|
||||
{ 0x80, 0x87, 0x8d, 0x93, 0x98, 0x9c, 0xa0, 0xa3, 0xa6, 0xa8, 0xaa, 0xac, 0xad, 0xae, 0xb0, 0xb0,
|
||||
0xb1, 0xb2, 0xb3, 0xb4, 0xb4, 0xb5, 0xb5, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7, 0xb7, 0xb8, 0xb8, 0xb8 },
|
||||
{ 0x80, 0x86, 0x8b, 0x90, 0x95, 0x99, 0x9d, 0xa0, 0xa3, 0xa5, 0xa7, 0xa9, 0xaa, 0xac, 0xad, 0xae,
|
||||
0xaf, 0xb0, 0xb1, 0xb2, 0xb2, 0xb3, 0xb3, 0xb4, 0xb4, 0xb5, 0xb5, 0xb6, 0xb6, 0xb6, 0xb7, 0xb7 },
|
||||
{ 0x80, 0x85, 0x8a, 0x8f, 0x93, 0x97, 0x9a, 0x9d, 0xa0, 0xa2, 0xa5, 0xa6, 0xa8, 0xaa, 0xab, 0xac,
|
||||
0xad, 0xae, 0xaf, 0xb0, 0xb0, 0xb1, 0xb2, 0xb2, 0xb3, 0xb3, 0xb4, 0xb4, 0xb5, 0xb5, 0xb5, 0xb5 },
|
||||
{ 0x80, 0x85, 0x89, 0x8d, 0x91, 0x95, 0x98, 0x9b, 0x9e, 0xa0, 0xa0, 0xa4, 0xa6, 0xa7, 0xa9, 0xaa,
|
||||
0xab, 0xac, 0xad, 0xae, 0xaf, 0xb0, 0xb0, 0xb1, 0xb1, 0xb2, 0xb2, 0xb3, 0xb3, 0xb4, 0xb4, 0xb4 },
|
||||
{ 0x80, 0x84, 0x88, 0x8c, 0x90, 0x93, 0x96, 0x99, 0x9b, 0x9e, 0xa0, 0xa2, 0xa4, 0xa5, 0xa7, 0xa8,
|
||||
0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, 0xaf, 0xb0, 0xb0, 0xb1, 0xb2, 0xb2, 0xb2, 0xb3, 0xb3 },
|
||||
{ 0x80, 0x84, 0x87, 0x8b, 0x8e, 0x91, 0x94, 0x97, 0x9a, 0x9c, 0x9e, 0xa0, 0xa2, 0xa3, 0xa5, 0xa6,
|
||||
0xa7, 0xa9, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xae, 0xae, 0xaf, 0xb0, 0xb0, 0xb1, 0xb1, 0xb2, 0xb2 },
|
||||
{ 0x80, 0x83, 0x87, 0x8a, 0x8d, 0x90, 0x93, 0x96, 0x98, 0x9a, 0x9c, 0x9e, 0xa0, 0xa2, 0xa3, 0xa5,
|
||||
0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xae, 0xae, 0xaf, 0xb0, 0xb0, 0xb0, 0xb1 },
|
||||
{ 0x80, 0x83, 0x86, 0x89, 0x8c, 0x8f, 0x92, 0x94, 0x96, 0x99, 0x9b, 0x9d, 0x9e, 0xa0, 0xa2, 0xa3,
|
||||
0xa4, 0xa5, 0xa7, 0xa8, 0xa9, 0xa9, 0xaa, 0xab, 0xac, 0xac, 0xad, 0xae, 0xae, 0xaf, 0xaf, 0xb0 },
|
||||
{ 0x80, 0x83, 0x86, 0x89, 0x8b, 0x8e, 0x90, 0x93, 0x95, 0x97, 0x99, 0x9b, 0x9d, 0x9e, 0xa0, 0xa1,
|
||||
0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xaa, 0xab, 0xac, 0xad, 0xad, 0xae, 0xae, 0xaf },
|
||||
{ 0x80, 0x83, 0x85, 0x88, 0x8b, 0x8d, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9b, 0x9d, 0x9f, 0xa0,
|
||||
0xa1, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa8, 0xa9, 0xaa, 0xab, 0xab, 0xac, 0xad, 0xad, 0xae },
|
||||
{ 0x80, 0x83, 0x85, 0x88, 0x8a, 0x8c, 0x8f, 0x91, 0x93, 0x95, 0x97, 0x99, 0x9a, 0x9c, 0x9d, 0x9f,
|
||||
0xa0, 0xa1, 0xa2, 0xa3, 0xa5, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xaa, 0xab, 0xab, 0xac, 0xad },
|
||||
{ 0x80, 0x82, 0x85, 0x87, 0x89, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x97, 0x99, 0x9b, 0x9c, 0x9d,
|
||||
0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa8, 0xa9, 0xaa, 0xaa, 0xab, 0xac },
|
||||
{ 0x80, 0x82, 0x85, 0x87, 0x89, 0x8b, 0x8d, 0x8f, 0x91, 0x93, 0x95, 0x96, 0x98, 0x99, 0x9b, 0x9c,
|
||||
0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa7, 0xa8, 0xa9, 0xa9, 0xaa, 0xab },
|
||||
{ 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x95, 0x97, 0x98, 0x9a, 0x9b,
|
||||
0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa6, 0xa7, 0xa8, 0xa8, 0xa9, 0xaa },
|
||||
{ 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x91, 0x93, 0x94, 0x96, 0x97, 0x99, 0x9a,
|
||||
0x9b, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa5, 0xa6, 0xa7, 0xa7, 0xa8, 0xa9 },
|
||||
{ 0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8b, 0x8d, 0x8f, 0x90, 0x92, 0x94, 0x95, 0x97, 0x98, 0x99,
|
||||
0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa4, 0xa5, 0xa6, 0xa6, 0xa7, 0xa8 },
|
||||
{ 0x80, 0x82, 0x84, 0x86, 0x87, 0x89, 0x8b, 0x8d, 0x8e, 0x90, 0x91, 0x93, 0x94, 0x96, 0x97, 0x98,
|
||||
0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa3, 0xa3, 0xa4, 0xa5, 0xa6, 0xa6, 0xa7 },
|
||||
{ 0x80, 0x82, 0x84, 0x85, 0x87, 0x89, 0x8a, 0x8c, 0x8e, 0x8f, 0x91, 0x92, 0x94, 0x95, 0x96, 0x98,
|
||||
0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa3, 0xa4, 0xa5, 0xa5, 0xa6 },
|
||||
{ 0x80, 0x82, 0x83, 0x85, 0x87, 0x88, 0x8a, 0x8c, 0x8d, 0x8f, 0x90, 0x92, 0x93, 0x94, 0x96, 0x97,
|
||||
0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa3, 0xa4, 0xa5, 0xa5 },
|
||||
{ 0x80, 0x82, 0x83, 0x85, 0x86, 0x88, 0x8a, 0x8b, 0x8d, 0x8e, 0x90, 0x91, 0x92, 0x94, 0x95, 0x96,
|
||||
0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa3, 0xa4, 0xa4 },
|
||||
{ 0x80, 0x82, 0x83, 0x85, 0x86, 0x88, 0x89, 0x8b, 0x8c, 0x8e, 0x8f, 0x90, 0x92, 0x93, 0x94, 0x95,
|
||||
0x96, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9e, 0x9f, 0xa0, 0xa1, 0xa2, 0xa2, 0xa3, 0xa4 },
|
||||
{ 0x80, 0x82, 0x83, 0x85, 0x86, 0x87, 0x89, 0x8a, 0x8c, 0x8d, 0x8e, 0x90, 0x91, 0x92, 0x93, 0x95,
|
||||
0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9e, 0x9f, 0xa0, 0xa1, 0xa1, 0xa2, 0xa3 },
|
||||
{ 0x80, 0x81, 0x83, 0x84, 0x86, 0x87, 0x89, 0x8a, 0x8b, 0x8d, 0x8e, 0x8f, 0x90, 0x92, 0x93, 0x94,
|
||||
0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9e, 0x9f, 0xa0, 0xa1, 0xa1, 0xa2 },
|
||||
{ 0x80, 0x81, 0x83, 0x84, 0x86, 0x87, 0x88, 0x8a, 0x8b, 0x8c, 0x8e, 0x8f, 0x90, 0x91, 0x92, 0x93,
|
||||
0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0x9f, 0xa0, 0xa1, 0xa1 },
|
||||
{ 0x80, 0x81, 0x83, 0x84, 0x85, 0x87, 0x88, 0x89, 0x8b, 0x8c, 0x8d, 0x8e, 0x90, 0x91, 0x92, 0x93,
|
||||
0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, 0x9f, 0xa0, 0xa1 },
|
||||
{ 0x80, 0x81, 0x83, 0x84, 0x85, 0x87, 0x88, 0x89, 0x8a, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91, 0x92,
|
||||
0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9c, 0x9d, 0x9e, 0x9f, 0x9f, 0xa0 }
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,261 +0,0 @@
|
|||
#ifdef ST0010_CPP
|
||||
|
||||
//ST-0010 emulation code - Copyright (C) 2003 The Dumper, Matthew Kendora, Overload, Feather
|
||||
//bsnes port - Copyright (C) 2007 byuu
|
||||
|
||||
void ST0010::op_01(int16 x0, int16 y0, int16 &x1, int16 &y1, int16 &quadrant, int16 &theta) {
|
||||
if((x0 < 0) && (y0 < 0)) {
|
||||
x1 = -x0;
|
||||
y1 = -y0;
|
||||
quadrant = -0x8000;
|
||||
} else if(x0 < 0) {
|
||||
x1 = y0;
|
||||
y1 = -x0;
|
||||
quadrant = -0x4000;
|
||||
} else if(y0 < 0) {
|
||||
x1 = -y0;
|
||||
y1 = x0;
|
||||
quadrant = 0x4000;
|
||||
} else {
|
||||
x1 = x0;
|
||||
y1 = y0;
|
||||
quadrant = 0x0000;
|
||||
}
|
||||
|
||||
while((x1 > 0x1f) || (y1 > 0x1f)) {
|
||||
if(x1 > 1) { x1 >>= 1; }
|
||||
if(y1 > 1) { y1 >>= 1; }
|
||||
}
|
||||
|
||||
if(y1 == 0) { quadrant += 0x4000; }
|
||||
|
||||
theta = (arctan[y1][x1] << 8) ^ quadrant;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
void ST0010::op_01() {
|
||||
int16 x0 = readw(0x0000);
|
||||
int16 y0 = readw(0x0002);
|
||||
int16 x1, y1, quadrant, theta;
|
||||
|
||||
op_01(x0, y0, x1, y1, quadrant, theta);
|
||||
|
||||
writew(0x0000, x1);
|
||||
writew(0x0002, y1);
|
||||
writew(0x0004, quadrant);
|
||||
//writew(0x0006, y0); //Overload's docs note this write occurs, SNES9x disagrees
|
||||
writew(0x0010, theta);
|
||||
}
|
||||
|
||||
void ST0010::op_02() {
|
||||
int16 positions = readw(0x0024);
|
||||
uint16 *places = (uint16*)(ram + 0x0040);
|
||||
uint16 *drivers = (uint16*)(ram + 0x0080);
|
||||
|
||||
bool sorted;
|
||||
uint16 temp;
|
||||
if(positions > 1) {
|
||||
do {
|
||||
sorted = true;
|
||||
for(int i = 0; i < positions - 1; i++) {
|
||||
if(places[i] < places[i + 1]) {
|
||||
temp = places[i + 1];
|
||||
places[i + 1] = places[i];
|
||||
places[i] = temp;
|
||||
|
||||
temp = drivers[i + 1];
|
||||
drivers[i + 1] = drivers[i];
|
||||
drivers[i] = temp;
|
||||
|
||||
sorted = false;
|
||||
}
|
||||
}
|
||||
positions--;
|
||||
} while(!sorted);
|
||||
}
|
||||
}
|
||||
|
||||
void ST0010::op_03() {
|
||||
int16 x0 = readw(0x0000);
|
||||
int16 y0 = readw(0x0002);
|
||||
int16 multiplier = readw(0x0004);
|
||||
int32 x1, y1;
|
||||
|
||||
x1 = x0 * multiplier << 1;
|
||||
y1 = y0 * multiplier << 1;
|
||||
|
||||
writed(0x0010, x1);
|
||||
writed(0x0014, y1);
|
||||
}
|
||||
|
||||
void ST0010::op_04() {
|
||||
int16 x = readw(0x0000);
|
||||
int16 y = readw(0x0002);
|
||||
int16 square;
|
||||
//calculate the vector length of (x,y)
|
||||
square = (int16)sqrt((double)(y * y + x * x));
|
||||
|
||||
writew(0x0010, square);
|
||||
}
|
||||
|
||||
void ST0010::op_05() {
|
||||
int32 dx, dy;
|
||||
int16 a1, b1, c1;
|
||||
uint16 o1;
|
||||
bool wrap = false;
|
||||
|
||||
//target (x,y) coordinates
|
||||
int16 ypos_max = readw(0x00c0);
|
||||
int16 xpos_max = readw(0x00c2);
|
||||
|
||||
//current coordinates and direction
|
||||
int32 ypos = readd(0x00c4);
|
||||
int32 xpos = readd(0x00c8);
|
||||
uint16 rot = readw(0x00cc);
|
||||
|
||||
//physics
|
||||
uint16 speed = readw(0x00d4);
|
||||
uint16 accel = readw(0x00d6);
|
||||
uint16 speed_max = readw(0x00d8);
|
||||
|
||||
//special condition acknowledgement
|
||||
int16 system = readw(0x00da);
|
||||
int16 flags = readw(0x00dc);
|
||||
|
||||
//new target coordinates
|
||||
int16 ypos_new = readw(0x00de);
|
||||
int16 xpos_new = readw(0x00e0);
|
||||
|
||||
//mask upper bit
|
||||
xpos_new &= 0x7fff;
|
||||
|
||||
//get the current distance
|
||||
dx = xpos_max - (xpos >> 16);
|
||||
dy = ypos_max - (ypos >> 16);
|
||||
|
||||
//quirk: clear and move in9
|
||||
writew(0x00d2, 0xffff);
|
||||
writew(0x00da, 0x0000);
|
||||
|
||||
//grab the target angle
|
||||
op_01(dy, dx, a1, b1, c1, (int16&)o1);
|
||||
|
||||
//check for wrapping
|
||||
if(abs(o1 - rot) > 0x8000) {
|
||||
o1 += 0x8000;
|
||||
rot += 0x8000;
|
||||
wrap = true;
|
||||
}
|
||||
|
||||
uint16 old_speed = speed;
|
||||
|
||||
//special case
|
||||
if(abs(o1 - rot) == 0x8000) {
|
||||
speed = 0x100;
|
||||
}
|
||||
|
||||
//slow down for sharp curves
|
||||
else if(abs(o1 - rot) >= 0x1000) {
|
||||
uint32 slow = abs(o1 - rot);
|
||||
slow >>= 4; //scaling
|
||||
speed -= slow;
|
||||
}
|
||||
|
||||
//otherwise accelerate
|
||||
else {
|
||||
speed += accel;
|
||||
if(speed > speed_max) {
|
||||
speed = speed_max; //clip speed
|
||||
}
|
||||
}
|
||||
|
||||
//prevent negative/positive overflow
|
||||
if(abs(old_speed - speed) > 0x8000) {
|
||||
if(old_speed < speed) { speed = 0; }
|
||||
else speed = 0xff00;
|
||||
}
|
||||
|
||||
//adjust direction by so many degrees
|
||||
//be careful of negative adjustments
|
||||
if((o1 > rot && (o1 - rot) > 0x80) || (o1 < rot && (rot - o1) >= 0x80)) {
|
||||
if(o1 < rot) { rot -= 0x280; }
|
||||
else if(o1 > rot) { rot += 0x280; }
|
||||
}
|
||||
|
||||
//turn off wrapping
|
||||
if(wrap) { rot -= 0x8000; }
|
||||
|
||||
//now check the distances (store for later)
|
||||
dx = (xpos_max << 16) - xpos;
|
||||
dy = (ypos_max << 16) - ypos;
|
||||
dx >>= 16;
|
||||
dy >>= 16;
|
||||
|
||||
//if we're in so many units of the target, signal it
|
||||
if((system && (dy <= 6 && dy >= -8) && (dx <= 126 && dx >= -128)) || (!system && (dx <= 6 && dx >= -8) && (dy <= 126 && dy >= -128))) {
|
||||
//announce our new destination and flag it
|
||||
xpos_max = xpos_new & 0x7fff;
|
||||
ypos_max = ypos_new;
|
||||
flags |= 0x08;
|
||||
}
|
||||
|
||||
//update position
|
||||
xpos -= (cos(rot) * 0x400 >> 15) * (speed >> 8) << 1;
|
||||
ypos -= (sin(rot) * 0x400 >> 15) * (speed >> 8) << 1;
|
||||
|
||||
//quirk: mask upper byte
|
||||
xpos &= 0x1fffffff;
|
||||
ypos &= 0x1fffffff;
|
||||
|
||||
writew(0x00c0, ypos_max);
|
||||
writew(0x00c2, xpos_max);
|
||||
writed(0x00c4, ypos);
|
||||
writed(0x00c8, xpos);
|
||||
writew(0x00cc, rot);
|
||||
writew(0x00d4, speed);
|
||||
writew(0x00dc, flags);
|
||||
}
|
||||
|
||||
void ST0010::op_06() {
|
||||
int16 multiplicand = readw(0x0000);
|
||||
int16 multiplier = readw(0x0002);
|
||||
int32 product;
|
||||
|
||||
product = multiplicand * multiplier << 1;
|
||||
|
||||
writed(0x0010, product);
|
||||
}
|
||||
|
||||
void ST0010::op_07() {
|
||||
int16 theta = readw(0x0000);
|
||||
|
||||
int16 data;
|
||||
for(int i = 0, offset = 0; i < 176; i++) {
|
||||
data = mode7_scale[i] * cos(theta) >> 15;
|
||||
writew(0x00f0 + offset, data);
|
||||
writew(0x0510 + offset, data);
|
||||
|
||||
data = mode7_scale[i] * sin(theta) >> 15;
|
||||
writew(0x0250 + offset, data);
|
||||
if(data) { data = ~data; }
|
||||
writew(0x03b0 + offset, data);
|
||||
|
||||
offset += 2;
|
||||
}
|
||||
}
|
||||
|
||||
void ST0010::op_08() {
|
||||
int16 x0 = readw(0x0000);
|
||||
int16 y0 = readw(0x0002);
|
||||
int16 theta = readw(0x0004);
|
||||
int16 x1, y1;
|
||||
|
||||
x1 = (y0 * sin(theta) >> 15) + (x0 * cos(theta) >> 15);
|
||||
y1 = (y0 * cos(theta) >> 15) - (x0 * sin(theta) >> 15);
|
||||
|
||||
writew(0x0010, x1);
|
||||
writew(0x0012, y1);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,7 +0,0 @@
|
|||
#ifdef ST0010_CPP
|
||||
|
||||
void ST0010::serialize(serializer &s) {
|
||||
s.array(ram);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,93 +0,0 @@
|
|||
#include <snes/snes.hpp>
|
||||
|
||||
#define ST0010_CPP
|
||||
namespace SNES {
|
||||
|
||||
ST0010 st0010;
|
||||
|
||||
#include "data.hpp"
|
||||
#include "opcodes.cpp"
|
||||
#include "serialization.cpp"
|
||||
|
||||
void ST0010::init() {
|
||||
}
|
||||
|
||||
void ST0010::enable() {
|
||||
}
|
||||
|
||||
int16 ST0010::sin(int16 theta) {
|
||||
return sin_table[(theta >> 8) & 0xff];
|
||||
}
|
||||
|
||||
int16 ST0010::cos(int16 theta) {
|
||||
return sin_table[((theta + 0x4000) >> 8) & 0xff];
|
||||
}
|
||||
|
||||
uint8 ST0010::readb(uint16 addr) {
|
||||
return ram[addr & 0xfff];
|
||||
}
|
||||
|
||||
uint16 ST0010::readw(uint16 addr) {
|
||||
return (readb(addr + 0) << 0) |
|
||||
(readb(addr + 1) << 8);
|
||||
}
|
||||
|
||||
uint32 ST0010::readd(uint16 addr) {
|
||||
return (readb(addr + 0) << 0) |
|
||||
(readb(addr + 1) << 8) |
|
||||
(readb(addr + 2) << 16) |
|
||||
(readb(addr + 3) << 24);
|
||||
}
|
||||
|
||||
void ST0010::writeb(uint16 addr, uint8 data) {
|
||||
ram[addr & 0xfff] = data;
|
||||
}
|
||||
|
||||
void ST0010::writew(uint16 addr, uint16 data) {
|
||||
writeb(addr + 0, data >> 0);
|
||||
writeb(addr + 1, data >> 8);
|
||||
}
|
||||
|
||||
void ST0010::writed(uint16 addr, uint32 data) {
|
||||
writeb(addr + 0, data >> 0);
|
||||
writeb(addr + 1, data >> 8);
|
||||
writeb(addr + 2, data >> 16);
|
||||
writeb(addr + 3, data >> 24);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
void ST0010::power() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void ST0010::reset() {
|
||||
memset(ram, 0x00, sizeof ram);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
uint8 ST0010::read(unsigned addr) {
|
||||
return readb(addr);
|
||||
}
|
||||
|
||||
void ST0010::write(unsigned addr, uint8 data) {
|
||||
writeb(addr, data);
|
||||
|
||||
if((addr & 0xfff) == 0x0021 && (data & 0x80)) {
|
||||
switch(ram[0x0020]) {
|
||||
case 0x01: op_01(); break;
|
||||
case 0x02: op_02(); break;
|
||||
case 0x03: op_03(); break;
|
||||
case 0x04: op_04(); break;
|
||||
case 0x05: op_05(); break;
|
||||
case 0x06: op_06(); break;
|
||||
case 0x07: op_07(); break;
|
||||
case 0x08: op_08(); break;
|
||||
}
|
||||
|
||||
ram[0x0021] &= ~0x80;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
class ST0010 : public Memory {
|
||||
public:
|
||||
void init();
|
||||
void enable();
|
||||
void power();
|
||||
void reset();
|
||||
|
||||
uint8 read(unsigned addr);
|
||||
void write(unsigned addr, uint8 data);
|
||||
|
||||
void serialize(serializer&);
|
||||
|
||||
private:
|
||||
uint8 ram[0x1000];
|
||||
static const int16 sin_table[256];
|
||||
static const int16 mode7_scale[176];
|
||||
static const uint8 arctan[32][32];
|
||||
|
||||
//interfaces to sin table
|
||||
int16 sin(int16 theta);
|
||||
int16 cos(int16 theta);
|
||||
|
||||
//interfaces to ram buffer
|
||||
uint8 readb (uint16 addr);
|
||||
uint16 readw (uint16 addr);
|
||||
uint32 readd (uint16 addr);
|
||||
void writeb(uint16 addr, uint8 data);
|
||||
void writew(uint16 addr, uint16 data);
|
||||
void writed(uint16 addr, uint32 data);
|
||||
|
||||
//opcodes
|
||||
void op_01();
|
||||
void op_02();
|
||||
void op_03();
|
||||
void op_04();
|
||||
void op_05();
|
||||
void op_06();
|
||||
void op_07();
|
||||
void op_08();
|
||||
|
||||
void op_01(int16 x0, int16 y0, int16 &x1, int16 &y1, int16 &quadrant, int16 &theta);
|
||||
};
|
||||
|
||||
extern ST0010 st0010;
|
|
@ -1,20 +0,0 @@
|
|||
#include <snes/snes.hpp>
|
||||
|
||||
#define ST0011_CPP
|
||||
namespace SNES {
|
||||
|
||||
ST0011 st0011;
|
||||
|
||||
void ST0011::init() {
|
||||
}
|
||||
|
||||
void ST0011::enable() {
|
||||
}
|
||||
|
||||
void ST0011::power() {
|
||||
}
|
||||
|
||||
void ST0011::reset() {
|
||||
}
|
||||
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
class ST0011 {
|
||||
public:
|
||||
void init();
|
||||
void enable();
|
||||
void power();
|
||||
void reset();
|
||||
};
|
||||
|
||||
extern ST0011 st0011;
|
|
@ -1,12 +1,12 @@
|
|||
namespace SNES {
|
||||
namespace Info {
|
||||
static const char Name[] = "bsnes";
|
||||
static const char Version[] = "073.07";
|
||||
static const char Version[] = "074";
|
||||
static const unsigned SerializerVersion = 16;
|
||||
}
|
||||
}
|
||||
|
||||
#define DEBUGGER
|
||||
//#define DEBUGGER
|
||||
#define CHEAT_SYSTEM
|
||||
|
||||
#include <libco/libco.h>
|
||||
|
@ -84,9 +84,7 @@ namespace SNES {
|
|||
typedef uint_t<30> uint30;
|
||||
typedef uint_t<31> uint31;
|
||||
|
||||
typedef uint_t<40> uint40;
|
||||
typedef uint_t<48> uint48;
|
||||
typedef uint_t<56> uint56;
|
||||
typedef varuint_t varuint;
|
||||
|
||||
struct Processor {
|
||||
cothread_t thread;
|
||||
|
|
|
@ -60,14 +60,12 @@ void System::serialize_all(serializer &s) {
|
|||
if(cartridge.mode() == Cartridge::Mode::SuperGameBoy) icd2.serialize(s);
|
||||
if(cartridge.has_superfx()) superfx.serialize(s);
|
||||
if(cartridge.has_sa1()) sa1.serialize(s);
|
||||
if(cartridge.has_upd7725()) upd7725.serialize(s);
|
||||
if(cartridge.has_upd96050()) upd96050.serialize(s);
|
||||
if(cartridge.has_necdsp()) necdsp.serialize(s);
|
||||
if(cartridge.has_srtc()) srtc.serialize(s);
|
||||
if(cartridge.has_sdd1()) sdd1.serialize(s);
|
||||
if(cartridge.has_spc7110()) spc7110.serialize(s);
|
||||
if(cartridge.has_cx4()) cx4.serialize(s);
|
||||
if(cartridge.has_obc1()) obc1.serialize(s);
|
||||
if(cartridge.has_st0010()) st0010.serialize(s);
|
||||
if(cartridge.has_msu1()) msu1.serialize(s);
|
||||
if(cartridge.has_serial()) serial.serialize(s);
|
||||
}
|
||||
|
|
|
@ -71,8 +71,7 @@ void System::init(Interface *interface_) {
|
|||
icd2.init();
|
||||
superfx.init();
|
||||
sa1.init();
|
||||
upd7725.init();
|
||||
upd96050.init();
|
||||
necdsp.init();
|
||||
bsxbase.init();
|
||||
bsxcart.init();
|
||||
bsxflash.init();
|
||||
|
@ -81,8 +80,6 @@ void System::init(Interface *interface_) {
|
|||
spc7110.init();
|
||||
cx4.init();
|
||||
obc1.init();
|
||||
st0010.init();
|
||||
st0011.init();
|
||||
st0018.init();
|
||||
msu1.init();
|
||||
serial.init();
|
||||
|
@ -124,15 +121,12 @@ void System::power() {
|
|||
|
||||
if(cartridge.has_superfx()) superfx.enable();
|
||||
if(cartridge.has_sa1()) sa1.enable();
|
||||
if(cartridge.has_upd7725()) upd7725.enable();
|
||||
if(cartridge.has_upd96050()) upd96050.enable();
|
||||
if(cartridge.has_necdsp()) necdsp.enable();
|
||||
if(cartridge.has_srtc()) srtc.enable();
|
||||
if(cartridge.has_sdd1()) sdd1.enable();
|
||||
if(cartridge.has_spc7110()) spc7110.enable();
|
||||
if(cartridge.has_cx4()) cx4.enable();
|
||||
if(cartridge.has_obc1()) obc1.enable();
|
||||
if(cartridge.has_st0010()) st0010.enable();
|
||||
if(cartridge.has_st0011()) st0011.enable();
|
||||
if(cartridge.has_st0018()) st0018.enable();
|
||||
if(cartridge.has_msu1()) msu1.enable();
|
||||
if(cartridge.has_serial()) serial.enable();
|
||||
|
@ -149,15 +143,12 @@ void System::power() {
|
|||
|
||||
if(cartridge.has_superfx()) superfx.power();
|
||||
if(cartridge.has_sa1()) sa1.power();
|
||||
if(cartridge.has_upd7725()) upd7725.power();
|
||||
if(cartridge.has_upd96050()) upd96050.power();
|
||||
if(cartridge.has_necdsp()) necdsp.power();
|
||||
if(cartridge.has_srtc()) srtc.power();
|
||||
if(cartridge.has_sdd1()) sdd1.power();
|
||||
if(cartridge.has_spc7110()) spc7110.power();
|
||||
if(cartridge.has_cx4()) cx4.power();
|
||||
if(cartridge.has_obc1()) obc1.power();
|
||||
if(cartridge.has_st0010()) st0010.power();
|
||||
if(cartridge.has_st0011()) st0011.power();
|
||||
if(cartridge.has_st0018()) st0018.power();
|
||||
if(cartridge.has_msu1()) msu1.power();
|
||||
if(cartridge.has_serial()) serial.power();
|
||||
|
@ -165,8 +156,7 @@ void System::power() {
|
|||
if(cartridge.mode() == Cartridge::Mode::SuperGameBoy) cpu.coprocessors.append(&icd2);
|
||||
if(cartridge.has_superfx()) cpu.coprocessors.append(&superfx);
|
||||
if(cartridge.has_sa1()) cpu.coprocessors.append(&sa1);
|
||||
if(cartridge.has_upd7725()) cpu.coprocessors.append(&upd7725);
|
||||
if(cartridge.has_upd96050()) cpu.coprocessors.append(&upd96050);
|
||||
if(cartridge.has_necdsp()) cpu.coprocessors.append(&necdsp);
|
||||
if(cartridge.has_msu1()) cpu.coprocessors.append(&msu1);
|
||||
if(cartridge.has_serial()) cpu.coprocessors.append(&serial);
|
||||
|
||||
|
@ -191,15 +181,12 @@ void System::reset() {
|
|||
|
||||
if(cartridge.has_superfx()) superfx.reset();
|
||||
if(cartridge.has_sa1()) sa1.reset();
|
||||
if(cartridge.has_upd7725()) upd7725.reset();
|
||||
if(cartridge.has_upd96050()) upd96050.reset();
|
||||
if(cartridge.has_necdsp()) necdsp.reset();
|
||||
if(cartridge.has_srtc()) srtc.reset();
|
||||
if(cartridge.has_sdd1()) sdd1.reset();
|
||||
if(cartridge.has_spc7110()) spc7110.reset();
|
||||
if(cartridge.has_cx4()) cx4.reset();
|
||||
if(cartridge.has_obc1()) obc1.reset();
|
||||
if(cartridge.has_st0010()) st0010.reset();
|
||||
if(cartridge.has_st0011()) st0011.reset();
|
||||
if(cartridge.has_st0018()) st0018.reset();
|
||||
if(cartridge.has_msu1()) msu1.reset();
|
||||
if(cartridge.has_serial()) serial.reset();
|
||||
|
@ -207,8 +194,7 @@ void System::reset() {
|
|||
if(cartridge.mode() == Cartridge::Mode::SuperGameBoy) cpu.coprocessors.append(&icd2);
|
||||
if(cartridge.has_superfx()) cpu.coprocessors.append(&superfx);
|
||||
if(cartridge.has_sa1()) cpu.coprocessors.append(&sa1);
|
||||
if(cartridge.has_upd7725()) cpu.coprocessors.append(&upd7725);
|
||||
if(cartridge.has_upd96050()) cpu.coprocessors.append(&upd96050);
|
||||
if(cartridge.has_necdsp()) cpu.coprocessors.append(&necdsp);
|
||||
if(cartridge.has_msu1()) cpu.coprocessors.append(&msu1);
|
||||
if(cartridge.has_serial()) cpu.coprocessors.append(&serial);
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ include nall/Makefile
|
|||
|
||||
c := $(compiler) -std=gnu99
|
||||
cpp := $(subst cc,++,$(compiler)) -std=gnu++0x
|
||||
flags := -O3 -I. -Iobj -fomit-frame-pointer -fPIC
|
||||
flags := -O3 -I. -Iobj -fomit-frame-pointer
|
||||
link := -s
|
||||
objects :=
|
||||
|
||||
|
|
|
@ -1,77 +0,0 @@
|
|||
/* 7zAlloc.c -- Allocation functions
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "7zAlloc.h"
|
||||
|
||||
/* #define _SZ_ALLOC_DEBUG */
|
||||
/* use _SZ_ALLOC_DEBUG to debug alloc/free operations */
|
||||
|
||||
#ifdef _SZ_ALLOC_DEBUG
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
int g_allocCount = 0;
|
||||
int g_allocCountTemp = 0;
|
||||
|
||||
#endif
|
||||
|
||||
void *SzAlloc(void *p, size_t size)
|
||||
{
|
||||
p = p;
|
||||
if (size == 0)
|
||||
return 0;
|
||||
#ifdef _SZ_ALLOC_DEBUG
|
||||
fprintf(stderr, "\nAlloc %10d bytes; count = %10d", size, g_allocCount);
|
||||
g_allocCount++;
|
||||
#endif
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void SzFree(void *p, void *address)
|
||||
{
|
||||
p = p;
|
||||
#ifdef _SZ_ALLOC_DEBUG
|
||||
if (address != 0)
|
||||
{
|
||||
g_allocCount--;
|
||||
fprintf(stderr, "\nFree; count = %10d", g_allocCount);
|
||||
}
|
||||
#endif
|
||||
free(address);
|
||||
}
|
||||
|
||||
void *SzAllocTemp(void *p, size_t size)
|
||||
{
|
||||
p = p;
|
||||
if (size == 0)
|
||||
return 0;
|
||||
#ifdef _SZ_ALLOC_DEBUG
|
||||
fprintf(stderr, "\nAlloc_temp %10d bytes; count = %10d", size, g_allocCountTemp);
|
||||
g_allocCountTemp++;
|
||||
#ifdef _WIN32
|
||||
return HeapAlloc(GetProcessHeap(), 0, size);
|
||||
#endif
|
||||
#endif
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
void SzFreeTemp(void *p, void *address)
|
||||
{
|
||||
p = p;
|
||||
#ifdef _SZ_ALLOC_DEBUG
|
||||
if (address != 0)
|
||||
{
|
||||
g_allocCountTemp--;
|
||||
fprintf(stderr, "\nFree_temp; count = %10d", g_allocCountTemp);
|
||||
}
|
||||
#ifdef _WIN32
|
||||
HeapFree(GetProcessHeap(), 0, address);
|
||||
return;
|
||||
#endif
|
||||
#endif
|
||||
free(address);
|
||||
}
|
|
@ -1,23 +0,0 @@
|
|||
/* 7zAlloc.h -- Allocation functions
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_ALLOC_H
|
||||
#define __7Z_ALLOC_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void *SzAlloc(void *p, size_t size);
|
||||
void SzFree(void *p, void *address);
|
||||
|
||||
void *SzAllocTemp(void *p, size_t size);
|
||||
void SzFreeTemp(void *p, void *address);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,36 +0,0 @@
|
|||
/* 7zBuf.c -- Byte Buffer
|
||||
2008-03-28
|
||||
Igor Pavlov
|
||||
Public domain */
|
||||
|
||||
#include "7zBuf.h"
|
||||
|
||||
void Buf_Init(CBuf *p)
|
||||
{
|
||||
p->data = 0;
|
||||
p->size = 0;
|
||||
}
|
||||
|
||||
int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc)
|
||||
{
|
||||
p->size = 0;
|
||||
if (size == 0)
|
||||
{
|
||||
p->data = 0;
|
||||
return 1;
|
||||
}
|
||||
p->data = (Byte *)alloc->Alloc(alloc, size);
|
||||
if (p->data != 0)
|
||||
{
|
||||
p->size = size;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Buf_Free(CBuf *p, ISzAlloc *alloc)
|
||||
{
|
||||
alloc->Free(alloc, p->data);
|
||||
p->data = 0;
|
||||
p->size = 0;
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
/* 7zBuf.h -- Byte Buffer
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_BUF_H
|
||||
#define __7Z_BUF_H
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Byte *data;
|
||||
size_t size;
|
||||
} CBuf;
|
||||
|
||||
void Buf_Init(CBuf *p);
|
||||
int Buf_Create(CBuf *p, size_t size, ISzAlloc *alloc);
|
||||
void Buf_Free(CBuf *p, ISzAlloc *alloc);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
Byte *data;
|
||||
size_t size;
|
||||
size_t pos;
|
||||
} CDynBuf;
|
||||
|
||||
void DynBuf_Construct(CDynBuf *p);
|
||||
void DynBuf_SeekToBeg(CDynBuf *p);
|
||||
int DynBuf_Write(CDynBuf *p, const Byte *buf, size_t size, ISzAlloc *alloc);
|
||||
void DynBuf_Free(CDynBuf *p, ISzAlloc *alloc);
|
||||
|
||||
#endif
|
|
@ -1,194 +0,0 @@
|
|||
7z ANSI-C Decoder 4.62
|
||||
----------------------
|
||||
|
||||
7z ANSI-C provides 7z/LZMA decoding.
|
||||
7z ANSI-C version is simplified version ported from C++ code.
|
||||
|
||||
LZMA is default and general compression method of 7z format
|
||||
in 7-Zip compression program (www.7-zip.org). LZMA provides high
|
||||
compression ratio and very fast decompression.
|
||||
|
||||
|
||||
LICENSE
|
||||
-------
|
||||
|
||||
7z ANSI-C Decoder is part of the LZMA SDK.
|
||||
LZMA SDK is written and placed in the public domain by Igor Pavlov.
|
||||
|
||||
Files
|
||||
---------------------
|
||||
|
||||
7zDecode.* - Low level 7z decoding
|
||||
7zExtract.* - High level 7z decoding
|
||||
7zHeader.* - .7z format constants
|
||||
7zIn.* - .7z archive opening
|
||||
7zItem.* - .7z structures
|
||||
7zMain.c - Test application
|
||||
|
||||
|
||||
How To Use
|
||||
----------
|
||||
|
||||
You must download 7-Zip program from www.7-zip.org.
|
||||
|
||||
You can create .7z archive with 7z.exe or 7za.exe:
|
||||
|
||||
7za.exe a archive.7z *.htm -r -mx -m0fb=255
|
||||
|
||||
If you have big number of files in archive, and you need fast extracting,
|
||||
you can use partly-solid archives:
|
||||
|
||||
7za.exe a archive.7z *.htm -ms=512K -r -mx -m0fb=255 -m0d=512K
|
||||
|
||||
In that example 7-Zip will use 512KB solid blocks. So it needs to decompress only
|
||||
512KB for extracting one file from such archive.
|
||||
|
||||
|
||||
Limitations of current version of 7z ANSI-C Decoder
|
||||
---------------------------------------------------
|
||||
|
||||
- It reads only "FileName", "Size", "LastWriteTime" and "CRC" information for each file in archive.
|
||||
- It supports only LZMA and Copy (no compression) methods with BCJ or BCJ2 filters.
|
||||
- It converts original UTF-16 Unicode file names to UTF-8 Unicode file names.
|
||||
|
||||
These limitations will be fixed in future versions.
|
||||
|
||||
|
||||
Using 7z ANSI-C Decoder Test application:
|
||||
-----------------------------------------
|
||||
|
||||
Usage: 7zDec <command> <archive_name>
|
||||
|
||||
<Command>:
|
||||
e: Extract files from archive
|
||||
l: List contents of archive
|
||||
t: Test integrity of archive
|
||||
|
||||
Example:
|
||||
|
||||
7zDec l archive.7z
|
||||
|
||||
lists contents of archive.7z
|
||||
|
||||
7zDec e archive.7z
|
||||
|
||||
extracts files from archive.7z to current folder.
|
||||
|
||||
|
||||
How to use .7z Decoder
|
||||
----------------------
|
||||
|
||||
Memory allocation
|
||||
~~~~~~~~~~~~~~~~~
|
||||
|
||||
7z Decoder uses two memory pools:
|
||||
1) Temporary pool
|
||||
2) Main pool
|
||||
Such scheme can allow you to avoid fragmentation of allocated blocks.
|
||||
|
||||
|
||||
Steps for using 7z decoder
|
||||
--------------------------
|
||||
|
||||
Use code at 7zMain.c as example.
|
||||
|
||||
1) Declare variables:
|
||||
inStream /* implements ILookInStream interface */
|
||||
CSzArEx db; /* 7z archive database structure */
|
||||
ISzAlloc allocImp; /* memory functions for main pool */
|
||||
ISzAlloc allocTempImp; /* memory functions for temporary pool */
|
||||
|
||||
2) call CrcGenerateTable(); function to initialize CRC structures.
|
||||
|
||||
3) call SzArEx_Init(&db); function to initialize db structures.
|
||||
|
||||
4) call SzArEx_Open(&db, inStream, &allocMain, &allocTemp) to open archive
|
||||
|
||||
This function opens archive "inStream" and reads headers to "db".
|
||||
All items in "db" will be allocated with "allocMain" functions.
|
||||
SzArEx_Open function allocates and frees temporary structures by "allocTemp" functions.
|
||||
|
||||
5) List items or Extract items
|
||||
|
||||
Listing code:
|
||||
~~~~~~~~~~~~~
|
||||
{
|
||||
UInt32 i;
|
||||
for (i = 0; i < db.db.NumFiles; i++)
|
||||
{
|
||||
CFileItem *f = db.db.Files + i;
|
||||
printf("%10d %s\n", (int)f->Size, f->Name);
|
||||
}
|
||||
}
|
||||
|
||||
Extracting code:
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
SZ_RESULT SzAr_Extract(
|
||||
CArchiveDatabaseEx *db,
|
||||
ILookInStream *inStream,
|
||||
UInt32 fileIndex, /* index of file */
|
||||
UInt32 *blockIndex, /* index of solid block */
|
||||
Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */
|
||||
size_t *outBufferSize, /* buffer size for output buffer */
|
||||
size_t *offset, /* offset of stream for required file in *outBuffer */
|
||||
size_t *outSizeProcessed, /* size of file in *outBuffer */
|
||||
ISzAlloc *allocMain,
|
||||
ISzAlloc *allocTemp);
|
||||
|
||||
If you need to decompress more than one file, you can send these values from previous call:
|
||||
blockIndex,
|
||||
outBuffer,
|
||||
outBufferSize,
|
||||
You can consider "outBuffer" as cache of solid block. If your archive is solid,
|
||||
it will increase decompression speed.
|
||||
|
||||
After decompressing you must free "outBuffer":
|
||||
allocImp.Free(outBuffer);
|
||||
|
||||
6) call SzArEx_Free(&db, allocImp.Free) to free allocated items in "db".
|
||||
|
||||
|
||||
|
||||
|
||||
Memory requirements for .7z decoding
|
||||
------------------------------------
|
||||
|
||||
Memory usage for Archive opening:
|
||||
- Temporary pool:
|
||||
- Memory for uncompressed .7z headers
|
||||
- some other temporary blocks
|
||||
- Main pool:
|
||||
- Memory for database:
|
||||
Estimated size of one file structures in solid archive:
|
||||
- Size (4 or 8 Bytes)
|
||||
- CRC32 (4 bytes)
|
||||
- LastWriteTime (8 bytes)
|
||||
- Some file information (4 bytes)
|
||||
- File Name (variable length) + pointer + allocation structures
|
||||
|
||||
Memory usage for archive Decompressing:
|
||||
- Temporary pool:
|
||||
- Memory for LZMA decompressing structures
|
||||
- Main pool:
|
||||
- Memory for decompressed solid block
|
||||
- Memory for temprorary buffers, if BCJ2 fileter is used. Usually these
|
||||
temprorary buffers can be about 15% of solid block size.
|
||||
|
||||
|
||||
7z Decoder doesn't allocate memory for compressed blocks.
|
||||
Instead of this, you must allocate buffer with desired
|
||||
size before calling 7z Decoder. Use 7zMain.c as example.
|
||||
|
||||
|
||||
Defines
|
||||
-------
|
||||
|
||||
_SZ_ALLOC_DEBUG - define it if you want to debug alloc/free operations to stderr.
|
||||
|
||||
|
||||
---
|
||||
|
||||
http://www.7-zip.org
|
||||
http://www.7-zip.org/sdk.html
|
||||
http://www.7-zip.org/support.html
|
|
@ -1,35 +0,0 @@
|
|||
/* 7zCrc.c -- CRC32 calculation
|
||||
2008-08-05
|
||||
Igor Pavlov
|
||||
Public domain */
|
||||
|
||||
#include "7zCrc.h"
|
||||
|
||||
#define kCrcPoly 0xEDB88320
|
||||
UInt32 g_CrcTable[256];
|
||||
|
||||
void MY_FAST_CALL CrcGenerateTable(void)
|
||||
{
|
||||
UInt32 i;
|
||||
for (i = 0; i < 256; i++)
|
||||
{
|
||||
UInt32 r = i;
|
||||
int j;
|
||||
for (j = 0; j < 8; j++)
|
||||
r = (r >> 1) ^ (kCrcPoly & ~((r & 1) - 1));
|
||||
g_CrcTable[i] = r;
|
||||
}
|
||||
}
|
||||
|
||||
UInt32 MY_FAST_CALL CrcUpdate(UInt32 v, const void *data, size_t size)
|
||||
{
|
||||
const Byte *p = (const Byte *)data;
|
||||
for (; size > 0 ; size--, p++)
|
||||
v = CRC_UPDATE_BYTE(v, *p);
|
||||
return v;
|
||||
}
|
||||
|
||||
UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size)
|
||||
{
|
||||
return CrcUpdate(CRC_INIT_VAL, data, size) ^ 0xFFFFFFFF;
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
/* 7zCrc.h -- CRC32 calculation
|
||||
2008-03-13
|
||||
Igor Pavlov
|
||||
Public domain */
|
||||
|
||||
#ifndef __7Z_CRC_H
|
||||
#define __7Z_CRC_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
extern UInt32 g_CrcTable[];
|
||||
|
||||
void MY_FAST_CALL CrcGenerateTable(void);
|
||||
|
||||
#define CRC_INIT_VAL 0xFFFFFFFF
|
||||
#define CRC_GET_DIGEST(crc) ((crc) ^ 0xFFFFFFFF)
|
||||
#define CRC_UPDATE_BYTE(crc, b) (g_CrcTable[((crc) ^ (b)) & 0xFF] ^ ((crc) >> 8))
|
||||
|
||||
UInt32 MY_FAST_CALL CrcUpdate(UInt32 crc, const void *data, size_t size);
|
||||
UInt32 MY_FAST_CALL CrcCalc(const void *data, size_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,257 +0,0 @@
|
|||
/* 7zDecode.c -- Decoding from 7z folder
|
||||
2008-11-23 : Igor Pavlov : Public domain */
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "Bcj2.h"
|
||||
#include "Bra.h"
|
||||
#include "LzmaDec.h"
|
||||
#include "7zDecode.h"
|
||||
|
||||
#define k_Copy 0
|
||||
#define k_LZMA 0x30101
|
||||
#define k_BCJ 0x03030103
|
||||
#define k_BCJ2 0x0303011B
|
||||
|
||||
static SRes SzDecodeLzma(CSzCoderInfo *coder, UInt64 inSize, ILookInStream *inStream,
|
||||
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain)
|
||||
{
|
||||
CLzmaDec state;
|
||||
SRes res = SZ_OK;
|
||||
|
||||
LzmaDec_Construct(&state);
|
||||
RINOK(LzmaDec_AllocateProbs(&state, coder->Props.data, (unsigned)coder->Props.size, allocMain));
|
||||
state.dic = outBuffer;
|
||||
state.dicBufSize = outSize;
|
||||
LzmaDec_Init(&state);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
Byte *inBuf = NULL;
|
||||
size_t lookahead = (1 << 18);
|
||||
if (lookahead > inSize)
|
||||
lookahead = (size_t)inSize;
|
||||
res = inStream->Look((void *)inStream, (void **)&inBuf, &lookahead);
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
|
||||
{
|
||||
SizeT inProcessed = (SizeT)lookahead, dicPos = state.dicPos;
|
||||
ELzmaStatus status;
|
||||
res = LzmaDec_DecodeToDic(&state, outSize, inBuf, &inProcessed, LZMA_FINISH_END, &status);
|
||||
lookahead -= inProcessed;
|
||||
inSize -= inProcessed;
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
if (state.dicPos == state.dicBufSize || (inProcessed == 0 && dicPos == state.dicPos))
|
||||
{
|
||||
if (state.dicBufSize != outSize || lookahead != 0 ||
|
||||
(status != LZMA_STATUS_FINISHED_WITH_MARK &&
|
||||
status != LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK))
|
||||
res = SZ_ERROR_DATA;
|
||||
break;
|
||||
}
|
||||
res = inStream->Skip((void *)inStream, inProcessed);
|
||||
if (res != SZ_OK)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
LzmaDec_FreeProbs(&state, allocMain);
|
||||
return res;
|
||||
}
|
||||
|
||||
static SRes SzDecodeCopy(UInt64 inSize, ILookInStream *inStream, Byte *outBuffer)
|
||||
{
|
||||
while (inSize > 0)
|
||||
{
|
||||
void *inBuf;
|
||||
size_t curSize = (1 << 18);
|
||||
if (curSize > inSize)
|
||||
curSize = (size_t)inSize;
|
||||
RINOK(inStream->Look((void *)inStream, (void **)&inBuf, &curSize));
|
||||
if (curSize == 0)
|
||||
return SZ_ERROR_INPUT_EOF;
|
||||
memcpy(outBuffer, inBuf, curSize);
|
||||
outBuffer += curSize;
|
||||
inSize -= curSize;
|
||||
RINOK(inStream->Skip((void *)inStream, curSize));
|
||||
}
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
#define IS_UNSUPPORTED_METHOD(m) ((m) != k_Copy && (m) != k_LZMA)
|
||||
#define IS_UNSUPPORTED_CODER(c) (IS_UNSUPPORTED_METHOD(c.MethodID) || c.NumInStreams != 1 || c.NumOutStreams != 1)
|
||||
#define IS_NO_BCJ(c) (c.MethodID != k_BCJ || c.NumInStreams != 1 || c.NumOutStreams != 1)
|
||||
#define IS_NO_BCJ2(c) (c.MethodID != k_BCJ2 || c.NumInStreams != 4 || c.NumOutStreams != 1)
|
||||
|
||||
static
|
||||
SRes CheckSupportedFolder(const CSzFolder *f)
|
||||
{
|
||||
if (f->NumCoders < 1 || f->NumCoders > 4)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
if (IS_UNSUPPORTED_CODER(f->Coders[0]))
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
if (f->NumCoders == 1)
|
||||
{
|
||||
if (f->NumPackStreams != 1 || f->PackStreams[0] != 0 || f->NumBindPairs != 0)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
return SZ_OK;
|
||||
}
|
||||
if (f->NumCoders == 2)
|
||||
{
|
||||
if (IS_NO_BCJ(f->Coders[1]) ||
|
||||
f->NumPackStreams != 1 || f->PackStreams[0] != 0 ||
|
||||
f->NumBindPairs != 1 ||
|
||||
f->BindPairs[0].InIndex != 1 || f->BindPairs[0].OutIndex != 0)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
return SZ_OK;
|
||||
}
|
||||
if (f->NumCoders == 4)
|
||||
{
|
||||
if (IS_UNSUPPORTED_CODER(f->Coders[1]) ||
|
||||
IS_UNSUPPORTED_CODER(f->Coders[2]) ||
|
||||
IS_NO_BCJ2(f->Coders[3]))
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
if (f->NumPackStreams != 4 ||
|
||||
f->PackStreams[0] != 2 ||
|
||||
f->PackStreams[1] != 6 ||
|
||||
f->PackStreams[2] != 1 ||
|
||||
f->PackStreams[3] != 0 ||
|
||||
f->NumBindPairs != 3 ||
|
||||
f->BindPairs[0].InIndex != 5 || f->BindPairs[0].OutIndex != 0 ||
|
||||
f->BindPairs[1].InIndex != 4 || f->BindPairs[1].OutIndex != 1 ||
|
||||
f->BindPairs[2].InIndex != 3 || f->BindPairs[2].OutIndex != 2)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
return SZ_OK;
|
||||
}
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static
|
||||
UInt64 GetSum(const UInt64 *values, UInt32 index)
|
||||
{
|
||||
UInt64 sum = 0;
|
||||
UInt32 i;
|
||||
for (i = 0; i < index; i++)
|
||||
sum += values[i];
|
||||
return sum;
|
||||
}
|
||||
|
||||
static
|
||||
SRes SzDecode2(const UInt64 *packSizes, const CSzFolder *folder,
|
||||
ILookInStream *inStream, UInt64 startPos,
|
||||
Byte *outBuffer, SizeT outSize, ISzAlloc *allocMain,
|
||||
Byte *tempBuf[])
|
||||
{
|
||||
UInt32 ci;
|
||||
SizeT tempSizes[3] = { 0, 0, 0};
|
||||
SizeT tempSize3 = 0;
|
||||
Byte *tempBuf3 = 0;
|
||||
|
||||
RINOK(CheckSupportedFolder(folder));
|
||||
|
||||
for (ci = 0; ci < folder->NumCoders; ci++)
|
||||
{
|
||||
CSzCoderInfo *coder = &folder->Coders[ci];
|
||||
|
||||
if (coder->MethodID == k_Copy || coder->MethodID == k_LZMA)
|
||||
{
|
||||
UInt32 si = 0;
|
||||
UInt64 offset;
|
||||
UInt64 inSize;
|
||||
Byte *outBufCur = outBuffer;
|
||||
SizeT outSizeCur = outSize;
|
||||
if (folder->NumCoders == 4)
|
||||
{
|
||||
UInt32 indices[] = { 3, 2, 0 };
|
||||
UInt64 unpackSize = folder->UnpackSizes[ci];
|
||||
si = indices[ci];
|
||||
if (ci < 2)
|
||||
{
|
||||
Byte *temp;
|
||||
outSizeCur = (SizeT)unpackSize;
|
||||
if (outSizeCur != unpackSize)
|
||||
return SZ_ERROR_MEM;
|
||||
temp = (Byte *)IAlloc_Alloc(allocMain, outSizeCur);
|
||||
if (temp == 0 && outSizeCur != 0)
|
||||
return SZ_ERROR_MEM;
|
||||
outBufCur = tempBuf[1 - ci] = temp;
|
||||
tempSizes[1 - ci] = outSizeCur;
|
||||
}
|
||||
else if (ci == 2)
|
||||
{
|
||||
if (unpackSize > outSize) /* check it */
|
||||
return SZ_ERROR_PARAM;
|
||||
tempBuf3 = outBufCur = outBuffer + (outSize - (size_t)unpackSize);
|
||||
tempSize3 = outSizeCur = (SizeT)unpackSize;
|
||||
}
|
||||
else
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
}
|
||||
offset = GetSum(packSizes, si);
|
||||
inSize = packSizes[si];
|
||||
RINOK(LookInStream_SeekTo(inStream, startPos + offset));
|
||||
|
||||
if (coder->MethodID == k_Copy)
|
||||
{
|
||||
if (inSize != outSizeCur) /* check it */
|
||||
return SZ_ERROR_DATA;
|
||||
RINOK(SzDecodeCopy(inSize, inStream, outBufCur));
|
||||
}
|
||||
else
|
||||
{
|
||||
RINOK(SzDecodeLzma(coder, inSize, inStream, outBufCur, outSizeCur, allocMain));
|
||||
}
|
||||
}
|
||||
else if (coder->MethodID == k_BCJ)
|
||||
{
|
||||
UInt32 state;
|
||||
if (ci != 1)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
x86_Convert_Init(state);
|
||||
x86_Convert(outBuffer, outSize, 0, &state, 0);
|
||||
}
|
||||
else if (coder->MethodID == k_BCJ2)
|
||||
{
|
||||
UInt64 offset = GetSum(packSizes, 1);
|
||||
UInt64 s3Size = packSizes[1];
|
||||
SRes res;
|
||||
if (ci != 3)
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
RINOK(LookInStream_SeekTo(inStream, startPos + offset));
|
||||
tempSizes[2] = (SizeT)s3Size;
|
||||
if (tempSizes[2] != s3Size)
|
||||
return SZ_ERROR_MEM;
|
||||
tempBuf[2] = (Byte *)IAlloc_Alloc(allocMain, tempSizes[2]);
|
||||
if (tempBuf[2] == 0 && tempSizes[2] != 0)
|
||||
return SZ_ERROR_MEM;
|
||||
res = SzDecodeCopy(s3Size, inStream, tempBuf[2]);
|
||||
RINOK(res)
|
||||
|
||||
res = Bcj2_Decode(
|
||||
tempBuf3, tempSize3,
|
||||
tempBuf[0], tempSizes[0],
|
||||
tempBuf[1], tempSizes[1],
|
||||
tempBuf[2], tempSizes[2],
|
||||
outBuffer, outSize);
|
||||
RINOK(res)
|
||||
}
|
||||
else
|
||||
return SZ_ERROR_UNSUPPORTED;
|
||||
}
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
SRes SzDecode(const UInt64 *packSizes, const CSzFolder *folder,
|
||||
ILookInStream *inStream, UInt64 startPos,
|
||||
Byte *outBuffer, size_t outSize, ISzAlloc *allocMain)
|
||||
{
|
||||
Byte *tempBuf[3] = { 0, 0, 0};
|
||||
int i;
|
||||
SRes res = SzDecode2(packSizes, folder, inStream, startPos,
|
||||
outBuffer, (SizeT)outSize, allocMain, tempBuf);
|
||||
for (i = 0; i < 3; i++)
|
||||
IAlloc_Free(allocMain, tempBuf[i]);
|
||||
return res;
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
/* 7zDecode.h -- Decoding from 7z folder
|
||||
2008-11-23 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_DECODE_H
|
||||
#define __7Z_DECODE_H
|
||||
|
||||
#include "7zItem.h"
|
||||
|
||||
SRes SzDecode(const UInt64 *packSizes, const CSzFolder *folder,
|
||||
ILookInStream *stream, UInt64 startPos,
|
||||
Byte *outBuffer, size_t outSize, ISzAlloc *allocMain);
|
||||
|
||||
#endif
|
|
@ -1,93 +0,0 @@
|
|||
/* 7zExtract.c -- Extracting from 7z archive
|
||||
2008-11-23 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "7zCrc.h"
|
||||
#include "7zDecode.h"
|
||||
#include "7zExtract.h"
|
||||
|
||||
SRes SzAr_Extract(
|
||||
const CSzArEx *p,
|
||||
ILookInStream *inStream,
|
||||
UInt32 fileIndex,
|
||||
UInt32 *blockIndex,
|
||||
Byte **outBuffer,
|
||||
size_t *outBufferSize,
|
||||
size_t *offset,
|
||||
size_t *outSizeProcessed,
|
||||
ISzAlloc *allocMain,
|
||||
ISzAlloc *allocTemp)
|
||||
{
|
||||
UInt32 folderIndex = p->FileIndexToFolderIndexMap[fileIndex];
|
||||
SRes res = SZ_OK;
|
||||
*offset = 0;
|
||||
*outSizeProcessed = 0;
|
||||
if (folderIndex == (UInt32)-1)
|
||||
{
|
||||
IAlloc_Free(allocMain, *outBuffer);
|
||||
*blockIndex = folderIndex;
|
||||
*outBuffer = 0;
|
||||
*outBufferSize = 0;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
if (*outBuffer == 0 || *blockIndex != folderIndex)
|
||||
{
|
||||
CSzFolder *folder = p->db.Folders + folderIndex;
|
||||
UInt64 unpackSizeSpec = SzFolder_GetUnpackSize(folder);
|
||||
size_t unpackSize = (size_t)unpackSizeSpec;
|
||||
UInt64 startOffset = SzArEx_GetFolderStreamPos(p, folderIndex, 0);
|
||||
|
||||
if (unpackSize != unpackSizeSpec)
|
||||
return SZ_ERROR_MEM;
|
||||
*blockIndex = folderIndex;
|
||||
IAlloc_Free(allocMain, *outBuffer);
|
||||
*outBuffer = 0;
|
||||
|
||||
RINOK(LookInStream_SeekTo(inStream, startOffset));
|
||||
|
||||
if (res == SZ_OK)
|
||||
{
|
||||
*outBufferSize = unpackSize;
|
||||
if (unpackSize != 0)
|
||||
{
|
||||
*outBuffer = (Byte *)IAlloc_Alloc(allocMain, unpackSize);
|
||||
if (*outBuffer == 0)
|
||||
res = SZ_ERROR_MEM;
|
||||
}
|
||||
if (res == SZ_OK)
|
||||
{
|
||||
res = SzDecode(p->db.PackSizes +
|
||||
p->FolderStartPackStreamIndex[folderIndex], folder,
|
||||
inStream, startOffset,
|
||||
*outBuffer, unpackSize, allocTemp);
|
||||
if (res == SZ_OK)
|
||||
{
|
||||
if (folder->UnpackCRCDefined)
|
||||
{
|
||||
if (CrcCalc(*outBuffer, unpackSize) != folder->UnpackCRC)
|
||||
res = SZ_ERROR_CRC;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res == SZ_OK)
|
||||
{
|
||||
UInt32 i;
|
||||
CSzFileItem *fileItem = p->db.Files + fileIndex;
|
||||
*offset = 0;
|
||||
for (i = p->FolderStartFileIndex[folderIndex]; i < fileIndex; i++)
|
||||
*offset += (UInt32)p->db.Files[i].Size;
|
||||
*outSizeProcessed = (size_t)fileItem->Size;
|
||||
if (*offset + *outSizeProcessed > *outBufferSize)
|
||||
return SZ_ERROR_FAIL;
|
||||
{
|
||||
if (fileItem->FileCRCDefined)
|
||||
{
|
||||
if (CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->FileCRC)
|
||||
res = SZ_ERROR_CRC;
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
|
@ -1,49 +0,0 @@
|
|||
/* 7zExtract.h -- Extracting from 7z archive
|
||||
2008-11-23 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_EXTRACT_H
|
||||
#define __7Z_EXTRACT_H
|
||||
|
||||
#include "7zIn.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
SzExtract extracts file from archive
|
||||
|
||||
*outBuffer must be 0 before first call for each new archive.
|
||||
|
||||
Extracting cache:
|
||||
If you need to decompress more than one file, you can send
|
||||
these values from previous call:
|
||||
*blockIndex,
|
||||
*outBuffer,
|
||||
*outBufferSize
|
||||
You can consider "*outBuffer" as cache of solid block. If your archive is solid,
|
||||
it will increase decompression speed.
|
||||
|
||||
If you use external function, you can declare these 3 cache variables
|
||||
(blockIndex, outBuffer, outBufferSize) as static in that external function.
|
||||
|
||||
Free *outBuffer and set *outBuffer to 0, if you want to flush cache.
|
||||
*/
|
||||
|
||||
SRes SzAr_Extract(
|
||||
const CSzArEx *db,
|
||||
ILookInStream *inStream,
|
||||
UInt32 fileIndex, /* index of file */
|
||||
UInt32 *blockIndex, /* index of solid block */
|
||||
Byte **outBuffer, /* pointer to pointer to output buffer (allocated with allocMain) */
|
||||
size_t *outBufferSize, /* buffer size for output buffer */
|
||||
size_t *offset, /* offset of stream for required file in *outBuffer */
|
||||
size_t *outSizeProcessed, /* size of file in *outBuffer */
|
||||
ISzAlloc *allocMain,
|
||||
ISzAlloc *allocTemp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,6 +0,0 @@
|
|||
/* 7zHeader.c -- 7z Headers
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "7zHeader.h"
|
||||
|
||||
Byte k7zSignature[k7zSignatureSize] = {'7', 'z', 0xBC, 0xAF, 0x27, 0x1C};
|
|
@ -1,57 +0,0 @@
|
|||
/* 7zHeader.h -- 7z Headers
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_HEADER_H
|
||||
#define __7Z_HEADER_H
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
#define k7zSignatureSize 6
|
||||
extern Byte k7zSignature[k7zSignatureSize];
|
||||
|
||||
#define k7zMajorVersion 0
|
||||
|
||||
#define k7zStartHeaderSize 0x20
|
||||
|
||||
enum EIdEnum
|
||||
{
|
||||
k7zIdEnd,
|
||||
|
||||
k7zIdHeader,
|
||||
|
||||
k7zIdArchiveProperties,
|
||||
|
||||
k7zIdAdditionalStreamsInfo,
|
||||
k7zIdMainStreamsInfo,
|
||||
k7zIdFilesInfo,
|
||||
|
||||
k7zIdPackInfo,
|
||||
k7zIdUnpackInfo,
|
||||
k7zIdSubStreamsInfo,
|
||||
|
||||
k7zIdSize,
|
||||
k7zIdCRC,
|
||||
|
||||
k7zIdFolder,
|
||||
|
||||
k7zIdCodersUnpackSize,
|
||||
k7zIdNumUnpackStream,
|
||||
|
||||
k7zIdEmptyStream,
|
||||
k7zIdEmptyFile,
|
||||
k7zIdAnti,
|
||||
|
||||
k7zIdName,
|
||||
k7zIdCTime,
|
||||
k7zIdATime,
|
||||
k7zIdMTime,
|
||||
k7zIdWinAttributes,
|
||||
k7zIdComment,
|
||||
|
||||
k7zIdEncodedHeader,
|
||||
|
||||
k7zIdStartPos,
|
||||
k7zIdDummy
|
||||
};
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -1,49 +0,0 @@
|
|||
/* 7zIn.h -- 7z Input functions
|
||||
2008-11-23 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_IN_H
|
||||
#define __7Z_IN_H
|
||||
|
||||
#include "7zHeader.h"
|
||||
#include "7zItem.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CSzAr db;
|
||||
|
||||
UInt64 startPosAfterHeader;
|
||||
UInt64 dataPos;
|
||||
|
||||
UInt32 *FolderStartPackStreamIndex;
|
||||
UInt64 *PackStreamStartPositions;
|
||||
UInt32 *FolderStartFileIndex;
|
||||
UInt32 *FileIndexToFolderIndexMap;
|
||||
} CSzArEx;
|
||||
|
||||
void SzArEx_Init(CSzArEx *p);
|
||||
void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc);
|
||||
UInt64 SzArEx_GetFolderStreamPos(const CSzArEx *p, UInt32 folderIndex, UInt32 indexInFolder);
|
||||
int SzArEx_GetFolderFullPackSize(const CSzArEx *p, UInt32 folderIndex, UInt64 *resSize);
|
||||
|
||||
/*
|
||||
Errors:
|
||||
SZ_ERROR_NO_ARCHIVE
|
||||
SZ_ERROR_ARCHIVE
|
||||
SZ_ERROR_UNSUPPORTED
|
||||
SZ_ERROR_MEM
|
||||
SZ_ERROR_CRC
|
||||
SZ_ERROR_INPUT_EOF
|
||||
SZ_ERROR_FAIL
|
||||
*/
|
||||
|
||||
SRes SzArEx_Open(CSzArEx *p, ILookInStream *inStream, ISzAlloc *allocMain, ISzAlloc *allocTemp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,129 +0,0 @@
|
|||
/* 7zItem.c -- 7z Items
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "7zItem.h"
|
||||
|
||||
void SzCoderInfo_Init(CSzCoderInfo *p)
|
||||
{
|
||||
Buf_Init(&p->Props);
|
||||
}
|
||||
|
||||
void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc)
|
||||
{
|
||||
Buf_Free(&p->Props, alloc);
|
||||
SzCoderInfo_Init(p);
|
||||
}
|
||||
|
||||
void SzFolder_Init(CSzFolder *p)
|
||||
{
|
||||
p->Coders = 0;
|
||||
p->BindPairs = 0;
|
||||
p->PackStreams = 0;
|
||||
p->UnpackSizes = 0;
|
||||
p->NumCoders = 0;
|
||||
p->NumBindPairs = 0;
|
||||
p->NumPackStreams = 0;
|
||||
p->UnpackCRCDefined = 0;
|
||||
p->UnpackCRC = 0;
|
||||
p->NumUnpackStreams = 0;
|
||||
}
|
||||
|
||||
static
|
||||
void SzFolder_Free(CSzFolder *p, ISzAlloc *alloc)
|
||||
{
|
||||
UInt32 i;
|
||||
if (p->Coders)
|
||||
for (i = 0; i < p->NumCoders; i++)
|
||||
SzCoderInfo_Free(&p->Coders[i], alloc);
|
||||
IAlloc_Free(alloc, p->Coders);
|
||||
IAlloc_Free(alloc, p->BindPairs);
|
||||
IAlloc_Free(alloc, p->PackStreams);
|
||||
IAlloc_Free(alloc, p->UnpackSizes);
|
||||
SzFolder_Init(p);
|
||||
}
|
||||
|
||||
UInt32 SzFolder_GetNumOutStreams(CSzFolder *p)
|
||||
{
|
||||
UInt32 result = 0;
|
||||
UInt32 i;
|
||||
for (i = 0; i < p->NumCoders; i++)
|
||||
result += p->Coders[i].NumOutStreams;
|
||||
return result;
|
||||
}
|
||||
|
||||
int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex)
|
||||
{
|
||||
UInt32 i;
|
||||
for (i = 0; i < p->NumBindPairs; i++)
|
||||
if (p->BindPairs[i].InIndex == inStreamIndex)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
static
|
||||
int SzFolder_FindBindPairForOutStream(CSzFolder *p, UInt32 outStreamIndex)
|
||||
{
|
||||
UInt32 i;
|
||||
for (i = 0; i < p->NumBindPairs; i++)
|
||||
if (p->BindPairs[i].OutIndex == outStreamIndex)
|
||||
return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
UInt64 SzFolder_GetUnpackSize(CSzFolder *p)
|
||||
{
|
||||
int i = (int)SzFolder_GetNumOutStreams(p);
|
||||
if (i == 0)
|
||||
return 0;
|
||||
for (i--; i >= 0; i--)
|
||||
if (SzFolder_FindBindPairForOutStream(p, i) < 0)
|
||||
return p->UnpackSizes[i];
|
||||
/* throw 1; */
|
||||
return 0;
|
||||
}
|
||||
|
||||
void SzFile_Init(CSzFileItem *p)
|
||||
{
|
||||
p->HasStream = 1;
|
||||
p->IsDir = 0;
|
||||
p->IsAnti = 0;
|
||||
p->FileCRCDefined = 0;
|
||||
p->MTimeDefined = 0;
|
||||
p->Name = 0;
|
||||
}
|
||||
|
||||
static void SzFile_Free(CSzFileItem *p, ISzAlloc *alloc)
|
||||
{
|
||||
IAlloc_Free(alloc, p->Name);
|
||||
SzFile_Init(p);
|
||||
}
|
||||
|
||||
void SzAr_Init(CSzAr *p)
|
||||
{
|
||||
p->PackSizes = 0;
|
||||
p->PackCRCsDefined = 0;
|
||||
p->PackCRCs = 0;
|
||||
p->Folders = 0;
|
||||
p->Files = 0;
|
||||
p->NumPackStreams = 0;
|
||||
p->NumFolders = 0;
|
||||
p->NumFiles = 0;
|
||||
}
|
||||
|
||||
void SzAr_Free(CSzAr *p, ISzAlloc *alloc)
|
||||
{
|
||||
UInt32 i;
|
||||
if (p->Folders)
|
||||
for (i = 0; i < p->NumFolders; i++)
|
||||
SzFolder_Free(&p->Folders[i], alloc);
|
||||
if (p->Files)
|
||||
for (i = 0; i < p->NumFiles; i++)
|
||||
SzFile_Free(&p->Files[i], alloc);
|
||||
IAlloc_Free(alloc, p->PackSizes);
|
||||
IAlloc_Free(alloc, p->PackCRCsDefined);
|
||||
IAlloc_Free(alloc, p->PackCRCs);
|
||||
IAlloc_Free(alloc, p->Folders);
|
||||
IAlloc_Free(alloc, p->Files);
|
||||
SzAr_Init(p);
|
||||
}
|
|
@ -1,83 +0,0 @@
|
|||
/* 7zItem.h -- 7z Items
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_ITEM_H
|
||||
#define __7Z_ITEM_H
|
||||
|
||||
#include "7zBuf.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt32 NumInStreams;
|
||||
UInt32 NumOutStreams;
|
||||
UInt64 MethodID;
|
||||
CBuf Props;
|
||||
} CSzCoderInfo;
|
||||
|
||||
void SzCoderInfo_Init(CSzCoderInfo *p);
|
||||
void SzCoderInfo_Free(CSzCoderInfo *p, ISzAlloc *alloc);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt32 InIndex;
|
||||
UInt32 OutIndex;
|
||||
} CBindPair;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CSzCoderInfo *Coders;
|
||||
CBindPair *BindPairs;
|
||||
UInt32 *PackStreams;
|
||||
UInt64 *UnpackSizes;
|
||||
UInt32 NumCoders;
|
||||
UInt32 NumBindPairs;
|
||||
UInt32 NumPackStreams;
|
||||
int UnpackCRCDefined;
|
||||
UInt32 UnpackCRC;
|
||||
|
||||
UInt32 NumUnpackStreams;
|
||||
} CSzFolder;
|
||||
|
||||
void SzFolder_Init(CSzFolder *p);
|
||||
UInt64 SzFolder_GetUnpackSize(CSzFolder *p);
|
||||
int SzFolder_FindBindPairForInStream(CSzFolder *p, UInt32 inStreamIndex);
|
||||
UInt32 SzFolder_GetNumOutStreams(CSzFolder *p);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt32 Low;
|
||||
UInt32 High;
|
||||
} CNtfsFileTime;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CNtfsFileTime MTime;
|
||||
UInt64 Size;
|
||||
char *Name;
|
||||
UInt32 FileCRC;
|
||||
|
||||
Byte HasStream;
|
||||
Byte IsDir;
|
||||
Byte IsAnti;
|
||||
Byte FileCRCDefined;
|
||||
Byte MTimeDefined;
|
||||
} CSzFileItem;
|
||||
|
||||
void SzFile_Init(CSzFileItem *p);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
UInt64 *PackSizes;
|
||||
Byte *PackCRCsDefined;
|
||||
UInt32 *PackCRCs;
|
||||
CSzFolder *Folders;
|
||||
CSzFileItem *Files;
|
||||
UInt32 NumPackStreams;
|
||||
UInt32 NumFolders;
|
||||
UInt32 NumFiles;
|
||||
} CSzAr;
|
||||
|
||||
void SzAr_Init(CSzAr *p);
|
||||
void SzAr_Free(CSzAr *p, ISzAlloc *alloc);
|
||||
|
||||
#endif
|
|
@ -1,184 +0,0 @@
|
|||
/* 7zStream.c -- 7z Stream functions
|
||||
2008-11-23 : Igor Pavlov : Public domain */
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
#if NEVER_CALLED
|
||||
SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType)
|
||||
{
|
||||
while (size != 0)
|
||||
{
|
||||
size_t processed = size;
|
||||
RINOK(stream->Read(stream, buf, &processed));
|
||||
if (processed == 0)
|
||||
return errorType;
|
||||
buf = (void *)((Byte *)buf + processed);
|
||||
size -= processed;
|
||||
}
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size)
|
||||
{
|
||||
return SeqInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF);
|
||||
}
|
||||
|
||||
SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf)
|
||||
{
|
||||
size_t processed = 1;
|
||||
RINOK(stream->Read(stream, buf, &processed));
|
||||
return (processed == 1) ? SZ_OK : SZ_ERROR_INPUT_EOF;
|
||||
}
|
||||
#endif
|
||||
|
||||
SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset)
|
||||
{
|
||||
Int64 t = offset;
|
||||
return stream->Seek(stream, &t, SZ_SEEK_SET);
|
||||
}
|
||||
|
||||
#if NEVER_CALLED
|
||||
SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size)
|
||||
{
|
||||
void *lookBuf;
|
||||
if (*size == 0)
|
||||
return SZ_OK;
|
||||
RINOK(stream->Look(stream, &lookBuf, size));
|
||||
memcpy(buf, lookBuf, *size);
|
||||
return stream->Skip(stream, *size);
|
||||
}
|
||||
#endif
|
||||
|
||||
SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType)
|
||||
{
|
||||
while (size != 0)
|
||||
{
|
||||
size_t processed = size;
|
||||
RINOK(stream->Read(stream, buf, &processed));
|
||||
if (processed == 0)
|
||||
return errorType;
|
||||
buf = (void *)((Byte *)buf + processed);
|
||||
size -= processed;
|
||||
}
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size)
|
||||
{
|
||||
return LookInStream_Read2(stream, buf, size, SZ_ERROR_INPUT_EOF);
|
||||
}
|
||||
|
||||
static SRes LookToRead_Look_Lookahead(void *pp, void **buf, size_t *size)
|
||||
{
|
||||
SRes res = SZ_OK;
|
||||
#if !NEVER_CALLED
|
||||
(void)pp;
|
||||
(void)buf;
|
||||
(void)size;
|
||||
#else
|
||||
CLookToRead *p = (CLookToRead *)pp;
|
||||
size_t size2 = p->size - p->pos;
|
||||
if (size2 == 0 && *size > 0)
|
||||
{
|
||||
p->pos = 0;
|
||||
size2 = LookToRead_BUF_SIZE;
|
||||
res = p->realStream->Read(p->realStream, p->buf, &size2);
|
||||
p->size = size2;
|
||||
}
|
||||
if (size2 < *size)
|
||||
*size = size2;
|
||||
*buf = p->buf + p->pos;
|
||||
#endif
|
||||
return res;
|
||||
}
|
||||
|
||||
static SRes LookToRead_Look_Exact(void *pp, void **buf, size_t *size)
|
||||
{
|
||||
SRes res = SZ_OK;
|
||||
CLookToRead *p = (CLookToRead *)pp;
|
||||
size_t size2 = p->size - p->pos;
|
||||
if (size2 == 0 && *size > 0)
|
||||
{
|
||||
p->pos = 0;
|
||||
if (*size > LookToRead_BUF_SIZE)
|
||||
*size = LookToRead_BUF_SIZE;
|
||||
res = p->realStream->Read(p->realStream, p->buf, size);
|
||||
size2 = p->size = *size;
|
||||
}
|
||||
if (size2 < *size)
|
||||
*size = size2;
|
||||
*buf = p->buf + p->pos;
|
||||
return res;
|
||||
}
|
||||
|
||||
static SRes LookToRead_Skip(void *pp, size_t offset)
|
||||
{
|
||||
CLookToRead *p = (CLookToRead *)pp;
|
||||
p->pos += offset;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
static SRes LookToRead_Read(void *pp, void *buf, size_t *size)
|
||||
{
|
||||
CLookToRead *p = (CLookToRead *)pp;
|
||||
size_t rem = p->size - p->pos;
|
||||
if (rem == 0)
|
||||
return p->realStream->Read(p->realStream, buf, size);
|
||||
if (rem > *size)
|
||||
rem = *size;
|
||||
memcpy(buf, p->buf + p->pos, rem);
|
||||
p->pos += rem;
|
||||
*size = rem;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
static SRes LookToRead_Seek(void *pp, Int64 *pos, ESzSeek origin)
|
||||
{
|
||||
CLookToRead *p = (CLookToRead *)pp;
|
||||
p->pos = p->size = 0;
|
||||
return p->realStream->Seek(p->realStream, pos, origin);
|
||||
}
|
||||
|
||||
void LookToRead_CreateVTable(CLookToRead *p, int lookahead)
|
||||
{
|
||||
#if !NEVER_CALLED
|
||||
lookahead = 0;
|
||||
#endif
|
||||
p->s.Look = lookahead ?
|
||||
LookToRead_Look_Lookahead :
|
||||
LookToRead_Look_Exact;
|
||||
p->s.Skip = LookToRead_Skip;
|
||||
p->s.Read = LookToRead_Read;
|
||||
p->s.Seek = LookToRead_Seek;
|
||||
}
|
||||
|
||||
void LookToRead_Init(CLookToRead *p)
|
||||
{
|
||||
p->pos = p->size = 0;
|
||||
}
|
||||
|
||||
#if NEVER_CALLED
|
||||
static SRes SecToLook_Read(void *pp, void *buf, size_t *size)
|
||||
{
|
||||
CSecToLook *p = (CSecToLook *)pp;
|
||||
return LookInStream_LookRead(p->realStream, buf, size);
|
||||
}
|
||||
|
||||
void SecToLook_CreateVTable(CSecToLook *p)
|
||||
{
|
||||
p->s.Read = SecToLook_Read;
|
||||
}
|
||||
|
||||
static SRes SecToRead_Read(void *pp, void *buf, size_t *size)
|
||||
{
|
||||
CSecToRead *p = (CSecToRead *)pp;
|
||||
return p->realStream->Read(p->realStream, buf, size);
|
||||
}
|
||||
|
||||
void SecToRead_CreateVTable(CSecToRead *p)
|
||||
{
|
||||
p->s.Read = SecToRead_Read;
|
||||
}
|
||||
#endif
|
|
@ -1,132 +0,0 @@
|
|||
/* Bcj2.c -- Converter for x86 code (BCJ2)
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Bcj2.h"
|
||||
|
||||
#ifdef _LZMA_PROB32
|
||||
#define CProb UInt32
|
||||
#else
|
||||
#define CProb UInt16
|
||||
#endif
|
||||
|
||||
#define IsJcc(b0, b1) ((b0) == 0x0F && ((b1) & 0xF0) == 0x80)
|
||||
#define IsJ(b0, b1) ((b1 & 0xFE) == 0xE8 || IsJcc(b0, b1))
|
||||
|
||||
#define kNumTopBits 24
|
||||
#define kTopValue ((UInt32)1 << kNumTopBits)
|
||||
|
||||
#define kNumBitModelTotalBits 11
|
||||
#define kBitModelTotal (1 << kNumBitModelTotalBits)
|
||||
#define kNumMoveBits 5
|
||||
|
||||
#define RC_READ_BYTE (*buffer++)
|
||||
#define RC_TEST { if (buffer == bufferLim) return SZ_ERROR_DATA; }
|
||||
#define RC_INIT2 code = 0; range = 0xFFFFFFFF; \
|
||||
{ int i; for (i = 0; i < 5; i++) { RC_TEST; code = (code << 8) | RC_READ_BYTE; }}
|
||||
|
||||
#define NORMALIZE if (range < kTopValue) { RC_TEST; range <<= 8; code = (code << 8) | RC_READ_BYTE; }
|
||||
|
||||
#define IF_BIT_0(p) ttt = *(p); bound = (range >> kNumBitModelTotalBits) * ttt; if (code < bound)
|
||||
#define UPDATE_0(p) range = bound; *(p) = (CProb)(ttt + ((kBitModelTotal - ttt) >> kNumMoveBits)); NORMALIZE;
|
||||
#define UPDATE_1(p) range -= bound; code -= bound; *(p) = (CProb)(ttt - (ttt >> kNumMoveBits)); NORMALIZE;
|
||||
|
||||
int Bcj2_Decode(
|
||||
const Byte *buf0, SizeT size0,
|
||||
const Byte *buf1, SizeT size1,
|
||||
const Byte *buf2, SizeT size2,
|
||||
const Byte *buf3, SizeT size3,
|
||||
Byte *outBuf, SizeT outSize)
|
||||
{
|
||||
CProb p[256 + 2];
|
||||
SizeT inPos = 0, outPos = 0;
|
||||
|
||||
const Byte *buffer, *bufferLim;
|
||||
UInt32 range, code;
|
||||
Byte prevByte = 0;
|
||||
{
|
||||
unsigned int i;
|
||||
for (i = 0; i < sizeof(p) / sizeof(p[0]); i++)
|
||||
p[i] = kBitModelTotal >> 1;
|
||||
}
|
||||
buffer = buf3;
|
||||
bufferLim = buffer + size3;
|
||||
RC_INIT2
|
||||
|
||||
if (outSize == 0)
|
||||
return SZ_OK;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
Byte b;
|
||||
CProb *prob;
|
||||
UInt32 bound;
|
||||
UInt32 ttt;
|
||||
|
||||
SizeT limit = size0 - inPos;
|
||||
if (outSize - outPos < limit)
|
||||
limit = outSize - outPos;
|
||||
while (limit != 0)
|
||||
{
|
||||
Byte bb = buf0[inPos];
|
||||
outBuf[outPos++] = bb;
|
||||
if (IsJ(prevByte, bb))
|
||||
break;
|
||||
inPos++;
|
||||
prevByte = bb;
|
||||
limit--;
|
||||
}
|
||||
|
||||
if (limit == 0 || outPos == outSize)
|
||||
break;
|
||||
|
||||
b = buf0[inPos++];
|
||||
|
||||
if (b == 0xE8)
|
||||
prob = p + prevByte;
|
||||
else if (b == 0xE9)
|
||||
prob = p + 256;
|
||||
else
|
||||
prob = p + 257;
|
||||
|
||||
IF_BIT_0(prob)
|
||||
{
|
||||
UPDATE_0(prob)
|
||||
prevByte = b;
|
||||
}
|
||||
else
|
||||
{
|
||||
UInt32 dest;
|
||||
const Byte *v;
|
||||
UPDATE_1(prob)
|
||||
if (b == 0xE8)
|
||||
{
|
||||
v = buf1;
|
||||
if (size1 < 4)
|
||||
return SZ_ERROR_DATA;
|
||||
buf1 += 4;
|
||||
size1 -= 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
v = buf2;
|
||||
if (size2 < 4)
|
||||
return SZ_ERROR_DATA;
|
||||
buf2 += 4;
|
||||
size2 -= 4;
|
||||
}
|
||||
dest = (((UInt32)v[0] << 24) | ((UInt32)v[1] << 16) |
|
||||
((UInt32)v[2] << 8) | ((UInt32)v[3])) - ((UInt32)outPos + 4);
|
||||
outBuf[outPos++] = (Byte)dest;
|
||||
if (outPos == outSize)
|
||||
break;
|
||||
outBuf[outPos++] = (Byte)(dest >> 8);
|
||||
if (outPos == outSize)
|
||||
break;
|
||||
outBuf[outPos++] = (Byte)(dest >> 16);
|
||||
if (outPos == outSize)
|
||||
break;
|
||||
outBuf[outPos++] = prevByte = (Byte)(dest >> 24);
|
||||
}
|
||||
}
|
||||
return (outPos == outSize) ? SZ_OK : SZ_ERROR_DATA;
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
/* Bcj2.h -- Converter for x86 code (BCJ2)
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __BCJ2_H
|
||||
#define __BCJ2_H
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
/*
|
||||
Conditions:
|
||||
outSize <= FullOutputSize,
|
||||
where FullOutputSize is full size of output stream of x86_2 filter.
|
||||
|
||||
If buf0 overlaps outBuf, there are two required conditions:
|
||||
1) (buf0 >= outBuf)
|
||||
2) (buf0 + size0 >= outBuf + FullOutputSize).
|
||||
|
||||
Returns:
|
||||
SZ_OK
|
||||
SZ_ERROR_DATA - Data error
|
||||
*/
|
||||
|
||||
int Bcj2_Decode(
|
||||
const Byte *buf0, SizeT size0,
|
||||
const Byte *buf1, SizeT size1,
|
||||
const Byte *buf2, SizeT size2,
|
||||
const Byte *buf3, SizeT size3,
|
||||
Byte *outBuf, SizeT outSize);
|
||||
|
||||
#endif
|
|
@ -1,60 +0,0 @@
|
|||
/* Bra.h -- Branch converters for executables
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __BRA_H
|
||||
#define __BRA_H
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
/*
|
||||
These functions convert relative addresses to absolute addresses
|
||||
in CALL instructions to increase the compression ratio.
|
||||
|
||||
In:
|
||||
data - data buffer
|
||||
size - size of data
|
||||
ip - current virtual Instruction Pinter (IP) value
|
||||
state - state variable for x86 converter
|
||||
encoding - 0 (for decoding), 1 (for encoding)
|
||||
|
||||
Out:
|
||||
state - state variable for x86 converter
|
||||
|
||||
Returns:
|
||||
The number of processed bytes. If you call these functions with multiple calls,
|
||||
you must start next call with first byte after block of processed bytes.
|
||||
|
||||
Type Endian Alignment LookAhead
|
||||
|
||||
x86 little 1 4
|
||||
ARMT little 2 2
|
||||
ARM little 4 0
|
||||
PPC big 4 0
|
||||
SPARC big 4 0
|
||||
IA64 little 16 0
|
||||
|
||||
size must be >= Alignment + LookAhead, if it's not last block.
|
||||
If (size < Alignment + LookAhead), converter returns 0.
|
||||
|
||||
Example:
|
||||
|
||||
UInt32 ip = 0;
|
||||
for ()
|
||||
{
|
||||
; size must be >= Alignment + LookAhead, if it's not last block
|
||||
SizeT processed = Convert(data, size, ip, 1);
|
||||
data += processed;
|
||||
size -= processed;
|
||||
ip += processed;
|
||||
}
|
||||
*/
|
||||
|
||||
#define x86_Convert_Init(state) { state = 0; }
|
||||
SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding);
|
||||
SizeT ARM_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
|
||||
SizeT ARMT_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
|
||||
SizeT PPC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
|
||||
SizeT SPARC_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
|
||||
SizeT IA64_Convert(Byte *data, SizeT size, UInt32 ip, int encoding);
|
||||
|
||||
#endif
|
|
@ -1,85 +0,0 @@
|
|||
/* Bra86.c -- Converter for x86 code (BCJ)
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#include "Bra.h"
|
||||
|
||||
#define Test86MSByte(b) ((b) == 0 || (b) == 0xFF)
|
||||
|
||||
const Byte kMaskToAllowedStatus[8] = {1, 1, 1, 0, 1, 0, 0, 0};
|
||||
const Byte kMaskToBitNumber[8] = {0, 1, 2, 2, 3, 3, 3, 3};
|
||||
|
||||
SizeT x86_Convert(Byte *data, SizeT size, UInt32 ip, UInt32 *state, int encoding)
|
||||
{
|
||||
SizeT bufferPos = 0, prevPosT;
|
||||
UInt32 prevMask = *state & 0x7;
|
||||
if (size < 5)
|
||||
return 0;
|
||||
ip += 5;
|
||||
prevPosT = (SizeT)0 - 1;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
Byte *p = data + bufferPos;
|
||||
Byte *limit = data + size - 4;
|
||||
for (; p < limit; p++)
|
||||
if ((*p & 0xFE) == 0xE8)
|
||||
break;
|
||||
bufferPos = (SizeT)(p - data);
|
||||
if (p >= limit)
|
||||
break;
|
||||
prevPosT = bufferPos - prevPosT;
|
||||
if (prevPosT > 3)
|
||||
prevMask = 0;
|
||||
else
|
||||
{
|
||||
prevMask = (prevMask << ((int)prevPosT - 1)) & 0x7;
|
||||
if (prevMask != 0)
|
||||
{
|
||||
Byte b = p[4 - kMaskToBitNumber[prevMask]];
|
||||
if (!kMaskToAllowedStatus[prevMask] || Test86MSByte(b))
|
||||
{
|
||||
prevPosT = bufferPos;
|
||||
prevMask = ((prevMask << 1) & 0x7) | 1;
|
||||
bufferPos++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
prevPosT = bufferPos;
|
||||
|
||||
if (Test86MSByte(p[4]))
|
||||
{
|
||||
UInt32 src = ((UInt32)p[4] << 24) | ((UInt32)p[3] << 16) | ((UInt32)p[2] << 8) | ((UInt32)p[1]);
|
||||
UInt32 dest;
|
||||
for (;;)
|
||||
{
|
||||
Byte b;
|
||||
int index;
|
||||
if (encoding)
|
||||
dest = (ip + (UInt32)bufferPos) + src;
|
||||
else
|
||||
dest = src - (ip + (UInt32)bufferPos);
|
||||
if (prevMask == 0)
|
||||
break;
|
||||
index = kMaskToBitNumber[prevMask] * 8;
|
||||
b = (Byte)(dest >> (24 - index));
|
||||
if (!Test86MSByte(b))
|
||||
break;
|
||||
src = dest ^ ((1 << (32 - index)) - 1);
|
||||
}
|
||||
p[4] = (Byte)(~(((dest >> 24) & 1) - 1));
|
||||
p[3] = (Byte)(dest >> 16);
|
||||
p[2] = (Byte)(dest >> 8);
|
||||
p[1] = (Byte)dest;
|
||||
bufferPos += 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
prevMask = ((prevMask << 1) & 0x7) | 1;
|
||||
bufferPos++;
|
||||
}
|
||||
}
|
||||
prevPosT = bufferPos - prevPosT;
|
||||
*state = ((prevPosT > 3) ? 0 : ((prevMask << ((int)prevPosT - 1)) & 0x7));
|
||||
return bufferPos;
|
||||
}
|
|
@ -1,69 +0,0 @@
|
|||
/* CpuArch.h
|
||||
2008-08-05
|
||||
Igor Pavlov
|
||||
Public domain */
|
||||
|
||||
#ifndef __CPUARCH_H
|
||||
#define __CPUARCH_H
|
||||
|
||||
/*
|
||||
LITTLE_ENDIAN_UNALIGN means:
|
||||
1) CPU is LITTLE_ENDIAN
|
||||
2) it's allowed to make unaligned memory accesses
|
||||
if LITTLE_ENDIAN_UNALIGN is not defined, it means that we don't know
|
||||
about these properties of platform.
|
||||
*/
|
||||
|
||||
#if defined(_M_IX86) || defined(_M_X64) || defined(_M_AMD64) || defined(__i386__) || defined(__x86_64__)
|
||||
#define LITTLE_ENDIAN_UNALIGN
|
||||
#endif
|
||||
|
||||
#ifdef LITTLE_ENDIAN_UNALIGN
|
||||
|
||||
#define GetUi16(p) (*(const UInt16 *)(p))
|
||||
#define GetUi32(p) (*(const UInt32 *)(p))
|
||||
#define GetUi64(p) (*(const UInt64 *)(p))
|
||||
#define SetUi32(p, d) *(UInt32 *)(p) = (d);
|
||||
|
||||
#else
|
||||
|
||||
#define GetUi16(p) (((const Byte *)(p))[0] | ((UInt16)((const Byte *)(p))[1] << 8))
|
||||
|
||||
#define GetUi32(p) ( \
|
||||
((const Byte *)(p))[0] | \
|
||||
((UInt32)((const Byte *)(p))[1] << 8) | \
|
||||
((UInt32)((const Byte *)(p))[2] << 16) | \
|
||||
((UInt32)((const Byte *)(p))[3] << 24))
|
||||
|
||||
#define GetUi64(p) (GetUi32(p) | ((UInt64)GetUi32(((const Byte *)(p)) + 4) << 32))
|
||||
|
||||
#define SetUi32(p, d) { UInt32 _x_ = (d); \
|
||||
((Byte *)(p))[0] = (Byte)_x_; \
|
||||
((Byte *)(p))[1] = (Byte)(_x_ >> 8); \
|
||||
((Byte *)(p))[2] = (Byte)(_x_ >> 16); \
|
||||
((Byte *)(p))[3] = (Byte)(_x_ >> 24); }
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(LITTLE_ENDIAN_UNALIGN) && defined(_WIN64) && (_MSC_VER >= 1300)
|
||||
|
||||
#pragma intrinsic(_byteswap_ulong)
|
||||
#pragma intrinsic(_byteswap_uint64)
|
||||
#define GetBe32(p) _byteswap_ulong(*(const UInt32 *)(const Byte *)(p))
|
||||
#define GetBe64(p) _byteswap_uint64(*(const UInt64 *)(const Byte *)(p))
|
||||
|
||||
#else
|
||||
|
||||
#define GetBe32(p) ( \
|
||||
((UInt32)((const Byte *)(p))[0] << 24) | \
|
||||
((UInt32)((const Byte *)(p))[1] << 16) | \
|
||||
((UInt32)((const Byte *)(p))[2] << 8) | \
|
||||
((const Byte *)(p))[3] )
|
||||
|
||||
#define GetBe64(p) (((UInt64)GetBe32(p) << 32) | GetBe32(((const Byte *)(p)) + 4))
|
||||
|
||||
#endif
|
||||
|
||||
#define GetBe16(p) (((UInt16)((const Byte *)(p))[0] << 8) | ((const Byte *)(p))[1])
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -1,223 +0,0 @@
|
|||
/* LzmaDec.h -- LZMA Decoder
|
||||
2008-10-04 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __LZMADEC_H
|
||||
#define __LZMADEC_H
|
||||
|
||||
#include "Types.h"
|
||||
|
||||
/* #define _LZMA_PROB32 */
|
||||
/* _LZMA_PROB32 can increase the speed on some CPUs,
|
||||
but memory usage for CLzmaDec::probs will be doubled in that case */
|
||||
|
||||
#ifdef _LZMA_PROB32
|
||||
#define CLzmaProb UInt32
|
||||
#else
|
||||
#define CLzmaProb UInt16
|
||||
#endif
|
||||
|
||||
|
||||
/* ---------- LZMA Properties ---------- */
|
||||
|
||||
#define LZMA_PROPS_SIZE 5
|
||||
|
||||
typedef struct _CLzmaProps
|
||||
{
|
||||
unsigned lc, lp, pb;
|
||||
UInt32 dicSize;
|
||||
} CLzmaProps;
|
||||
|
||||
/* LzmaProps_Decode - decodes properties
|
||||
Returns:
|
||||
SZ_OK
|
||||
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
||||
*/
|
||||
|
||||
SRes LzmaProps_Decode(CLzmaProps *p, const Byte *data, unsigned size);
|
||||
|
||||
|
||||
/* ---------- LZMA Decoder state ---------- */
|
||||
|
||||
/* LZMA_REQUIRED_INPUT_MAX = number of required input bytes for worst case.
|
||||
Num bits = log2((2^11 / 31) ^ 22) + 26 < 134 + 26 = 160; */
|
||||
|
||||
#define LZMA_REQUIRED_INPUT_MAX 20
|
||||
|
||||
typedef struct
|
||||
{
|
||||
CLzmaProps prop;
|
||||
CLzmaProb *probs;
|
||||
Byte *dic;
|
||||
const Byte *buf;
|
||||
UInt32 range, code;
|
||||
SizeT dicPos;
|
||||
SizeT dicBufSize;
|
||||
UInt32 processedPos;
|
||||
UInt32 checkDicSize;
|
||||
unsigned state;
|
||||
UInt32 reps[4];
|
||||
unsigned remainLen;
|
||||
int needFlush;
|
||||
int needInitState;
|
||||
UInt32 numProbs;
|
||||
unsigned tempBufSize;
|
||||
Byte tempBuf[LZMA_REQUIRED_INPUT_MAX];
|
||||
} CLzmaDec;
|
||||
|
||||
#define LzmaDec_Construct(p) { (p)->dic = 0; (p)->probs = 0; }
|
||||
|
||||
void LzmaDec_Init(CLzmaDec *p);
|
||||
|
||||
/* There are two types of LZMA streams:
|
||||
0) Stream with end mark. That end mark adds about 6 bytes to compressed size.
|
||||
1) Stream without end mark. You must know exact uncompressed size to decompress such stream. */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
LZMA_FINISH_ANY, /* finish at any point */
|
||||
LZMA_FINISH_END /* block must be finished at the end */
|
||||
} ELzmaFinishMode;
|
||||
|
||||
/* ELzmaFinishMode has meaning only if the decoding reaches output limit !!!
|
||||
|
||||
You must use LZMA_FINISH_END, when you know that current output buffer
|
||||
covers last bytes of block. In other cases you must use LZMA_FINISH_ANY.
|
||||
|
||||
If LZMA decoder sees end marker before reaching output limit, it returns SZ_OK,
|
||||
and output value of destLen will be less than output buffer size limit.
|
||||
You can check status result also.
|
||||
|
||||
You can use multiple checks to test data integrity after full decompression:
|
||||
1) Check Result and "status" variable.
|
||||
2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.
|
||||
3) Check that output(srcLen) = compressedSize, if you know real compressedSize.
|
||||
You must use correct finish mode in that case. */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
LZMA_STATUS_NOT_SPECIFIED, /* use main error code instead */
|
||||
LZMA_STATUS_FINISHED_WITH_MARK, /* stream was finished with end mark. */
|
||||
LZMA_STATUS_NOT_FINISHED, /* stream was not finished */
|
||||
LZMA_STATUS_NEEDS_MORE_INPUT, /* you must provide more input bytes */
|
||||
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK /* there is probability that stream was finished without end mark */
|
||||
} ELzmaStatus;
|
||||
|
||||
/* ELzmaStatus is used only as output value for function call */
|
||||
|
||||
|
||||
/* ---------- Interfaces ---------- */
|
||||
|
||||
/* There are 3 levels of interfaces:
|
||||
1) Dictionary Interface
|
||||
2) Buffer Interface
|
||||
3) One Call Interface
|
||||
You can select any of these interfaces, but don't mix functions from different
|
||||
groups for same object. */
|
||||
|
||||
|
||||
/* There are two variants to allocate state for Dictionary Interface:
|
||||
1) LzmaDec_Allocate / LzmaDec_Free
|
||||
2) LzmaDec_AllocateProbs / LzmaDec_FreeProbs
|
||||
You can use variant 2, if you set dictionary buffer manually.
|
||||
For Buffer Interface you must always use variant 1.
|
||||
|
||||
LzmaDec_Allocate* can return:
|
||||
SZ_OK
|
||||
SZ_ERROR_MEM - Memory allocation error
|
||||
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
||||
*/
|
||||
|
||||
SRes LzmaDec_AllocateProbs(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAlloc *alloc);
|
||||
void LzmaDec_FreeProbs(CLzmaDec *p, ISzAlloc *alloc);
|
||||
|
||||
SRes LzmaDec_Allocate(CLzmaDec *state, const Byte *prop, unsigned propsSize, ISzAlloc *alloc);
|
||||
void LzmaDec_Free(CLzmaDec *state, ISzAlloc *alloc);
|
||||
|
||||
/* ---------- Dictionary Interface ---------- */
|
||||
|
||||
/* You can use it, if you want to eliminate the overhead for data copying from
|
||||
dictionary to some other external buffer.
|
||||
You must work with CLzmaDec variables directly in this interface.
|
||||
|
||||
STEPS:
|
||||
LzmaDec_Constr()
|
||||
LzmaDec_Allocate()
|
||||
for (each new stream)
|
||||
{
|
||||
LzmaDec_Init()
|
||||
while (it needs more decompression)
|
||||
{
|
||||
LzmaDec_DecodeToDic()
|
||||
use data from CLzmaDec::dic and update CLzmaDec::dicPos
|
||||
}
|
||||
}
|
||||
LzmaDec_Free()
|
||||
*/
|
||||
|
||||
/* LzmaDec_DecodeToDic
|
||||
|
||||
The decoding to internal dictionary buffer (CLzmaDec::dic).
|
||||
You must manually update CLzmaDec::dicPos, if it reaches CLzmaDec::dicBufSize !!!
|
||||
|
||||
finishMode:
|
||||
It has meaning only if the decoding reaches output limit (dicLimit).
|
||||
LZMA_FINISH_ANY - Decode just dicLimit bytes.
|
||||
LZMA_FINISH_END - Stream must be finished after dicLimit.
|
||||
|
||||
Returns:
|
||||
SZ_OK
|
||||
status:
|
||||
LZMA_STATUS_FINISHED_WITH_MARK
|
||||
LZMA_STATUS_NOT_FINISHED
|
||||
LZMA_STATUS_NEEDS_MORE_INPUT
|
||||
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
|
||||
SZ_ERROR_DATA - Data error
|
||||
*/
|
||||
|
||||
SRes LzmaDec_DecodeToDic(CLzmaDec *p, SizeT dicLimit,
|
||||
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
||||
|
||||
|
||||
/* ---------- Buffer Interface ---------- */
|
||||
|
||||
/* It's zlib-like interface.
|
||||
See LzmaDec_DecodeToDic description for information about STEPS and return results,
|
||||
but you must use LzmaDec_DecodeToBuf instead of LzmaDec_DecodeToDic and you don't need
|
||||
to work with CLzmaDec variables manually.
|
||||
|
||||
finishMode:
|
||||
It has meaning only if the decoding reaches output limit (*destLen).
|
||||
LZMA_FINISH_ANY - Decode just destLen bytes.
|
||||
LZMA_FINISH_END - Stream must be finished after (*destLen).
|
||||
*/
|
||||
|
||||
SRes LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen,
|
||||
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode, ELzmaStatus *status);
|
||||
|
||||
|
||||
/* ---------- One Call Interface ---------- */
|
||||
|
||||
/* LzmaDecode
|
||||
|
||||
finishMode:
|
||||
It has meaning only if the decoding reaches output limit (*destLen).
|
||||
LZMA_FINISH_ANY - Decode just destLen bytes.
|
||||
LZMA_FINISH_END - Stream must be finished after (*destLen).
|
||||
|
||||
Returns:
|
||||
SZ_OK
|
||||
status:
|
||||
LZMA_STATUS_FINISHED_WITH_MARK
|
||||
LZMA_STATUS_NOT_FINISHED
|
||||
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
|
||||
SZ_ERROR_DATA - Data error
|
||||
SZ_ERROR_MEM - Memory allocation error
|
||||
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
||||
SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
|
||||
*/
|
||||
|
||||
SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
|
||||
const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
|
||||
ELzmaStatus *status, ISzAlloc *alloc);
|
||||
|
||||
#endif
|
|
@ -1,206 +0,0 @@
|
|||
/* Types.h -- Basic types
|
||||
2008-11-23 : Igor Pavlov : Public domain */
|
||||
|
||||
#ifndef __7Z_TYPES_H
|
||||
#define __7Z_TYPES_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define SZ_OK 0
|
||||
|
||||
#define SZ_ERROR_DATA 1
|
||||
#define SZ_ERROR_MEM 2
|
||||
#define SZ_ERROR_CRC 3
|
||||
#define SZ_ERROR_UNSUPPORTED 4
|
||||
#define SZ_ERROR_PARAM 5
|
||||
#define SZ_ERROR_INPUT_EOF 6
|
||||
#define SZ_ERROR_OUTPUT_EOF 7
|
||||
#define SZ_ERROR_READ 8
|
||||
#define SZ_ERROR_WRITE 9
|
||||
#define SZ_ERROR_PROGRESS 10
|
||||
#define SZ_ERROR_FAIL 11
|
||||
#define SZ_ERROR_THREAD 12
|
||||
|
||||
#define SZ_ERROR_ARCHIVE 16
|
||||
#define SZ_ERROR_NO_ARCHIVE 17
|
||||
|
||||
typedef int SRes;
|
||||
|
||||
#ifndef RINOK
|
||||
#define RINOK(x) { int __result__ = (x); if (__result__ != 0) return __result__; }
|
||||
#endif
|
||||
|
||||
typedef unsigned char Byte;
|
||||
typedef short Int16;
|
||||
typedef unsigned short UInt16;
|
||||
|
||||
#ifdef _LZMA_UINT32_IS_ULONG
|
||||
typedef long Int32;
|
||||
typedef unsigned long UInt32;
|
||||
#else
|
||||
typedef int Int32;
|
||||
typedef unsigned int UInt32;
|
||||
#endif
|
||||
|
||||
#ifdef _SZ_NO_INT_64
|
||||
|
||||
/* define _SZ_NO_INT_64, if your compiler doesn't support 64-bit integers.
|
||||
NOTES: Some code will work incorrectly in that case! */
|
||||
|
||||
typedef long Int64;
|
||||
typedef unsigned long UInt64;
|
||||
|
||||
#else
|
||||
|
||||
#if defined(_MSC_VER) || defined(__BORLANDC__)
|
||||
typedef __int64 Int64;
|
||||
typedef unsigned __int64 UInt64;
|
||||
#else
|
||||
typedef long long int Int64;
|
||||
typedef unsigned long long int UInt64;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef _LZMA_NO_SYSTEM_SIZE_T
|
||||
typedef UInt32 SizeT;
|
||||
#else
|
||||
typedef size_t SizeT;
|
||||
#endif
|
||||
|
||||
typedef int Bool;
|
||||
#define True 1
|
||||
#define False 0
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
|
||||
#if _MSC_VER >= 1300
|
||||
#define MY_NO_INLINE __declspec(noinline)
|
||||
#else
|
||||
#define MY_NO_INLINE
|
||||
#endif
|
||||
|
||||
#define MY_CDECL __cdecl
|
||||
#define MY_STD_CALL __stdcall
|
||||
#define MY_FAST_CALL MY_NO_INLINE __fastcall
|
||||
|
||||
#else
|
||||
|
||||
#define MY_CDECL
|
||||
#define MY_STD_CALL
|
||||
#define MY_FAST_CALL
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* The following interfaces use first parameter as pointer to structure */
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SRes (*Read)(void *p, void *buf, size_t *size);
|
||||
/* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
|
||||
(output(*size) < input(*size)) is allowed */
|
||||
} ISeqInStream;
|
||||
|
||||
/* it can return SZ_ERROR_INPUT_EOF */
|
||||
SRes SeqInStream_Read(ISeqInStream *stream, void *buf, size_t size);
|
||||
SRes SeqInStream_Read2(ISeqInStream *stream, void *buf, size_t size, SRes errorType);
|
||||
SRes SeqInStream_ReadByte(ISeqInStream *stream, Byte *buf);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
size_t (*Write)(void *p, const void *buf, size_t size);
|
||||
/* Returns: result - the number of actually written bytes.
|
||||
(result < size) means error */
|
||||
} ISeqOutStream;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SZ_SEEK_SET = 0,
|
||||
SZ_SEEK_CUR = 1,
|
||||
SZ_SEEK_END = 2
|
||||
} ESzSeek;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SRes (*Read)(void *p, void *buf, size_t *size); /* same as ISeqInStream::Read */
|
||||
SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
|
||||
} ISeekInStream;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SRes (*Look)(void *p, void **buf, size_t *size);
|
||||
/* if (input(*size) != 0 && output(*size) == 0) means end_of_stream.
|
||||
(output(*size) > input(*size)) is not allowed
|
||||
(output(*size) < input(*size)) is allowed */
|
||||
SRes (*Skip)(void *p, size_t offset);
|
||||
/* offset must be <= output(*size) of Look */
|
||||
|
||||
SRes (*Read)(void *p, void *buf, size_t *size);
|
||||
/* reads directly (without buffer). It's same as ISeqInStream::Read */
|
||||
SRes (*Seek)(void *p, Int64 *pos, ESzSeek origin);
|
||||
} ILookInStream;
|
||||
|
||||
SRes LookInStream_LookRead(ILookInStream *stream, void *buf, size_t *size);
|
||||
SRes LookInStream_SeekTo(ILookInStream *stream, UInt64 offset);
|
||||
|
||||
/* reads via ILookInStream::Read */
|
||||
SRes LookInStream_Read2(ILookInStream *stream, void *buf, size_t size, SRes errorType);
|
||||
SRes LookInStream_Read(ILookInStream *stream, void *buf, size_t size);
|
||||
|
||||
#define LookToRead_BUF_SIZE (1 << 14)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ILookInStream s;
|
||||
ISeekInStream *realStream;
|
||||
size_t pos;
|
||||
size_t size;
|
||||
Byte buf[LookToRead_BUF_SIZE];
|
||||
} CLookToRead;
|
||||
|
||||
void LookToRead_CreateVTable(CLookToRead *p, int lookahead);
|
||||
void LookToRead_Init(CLookToRead *p);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ISeqInStream s;
|
||||
ILookInStream *realStream;
|
||||
} CSecToLook;
|
||||
|
||||
void SecToLook_CreateVTable(CSecToLook *p);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
ISeqInStream s;
|
||||
ILookInStream *realStream;
|
||||
} CSecToRead;
|
||||
|
||||
void SecToRead_CreateVTable(CSecToRead *p);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
SRes (*Progress)(void *p, UInt64 inSize, UInt64 outSize);
|
||||
/* Returns: result. (result != SZ_OK) means break.
|
||||
Value (UInt64)(Int64)-1 for size means unknown value. */
|
||||
} ICompressProgress;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
void *(*Alloc)(void *p, size_t size);
|
||||
void (*Free)(void *p, void *address); /* address can be 0 */
|
||||
} ISzAlloc;
|
||||
|
||||
#define IAlloc_Alloc(p, size) (p)->Alloc((p), size)
|
||||
#define IAlloc_Free(p, a) (p)->Free((p), a)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,594 +0,0 @@
|
|||
LZMA SDK 4.65
|
||||
-------------
|
||||
|
||||
LZMA SDK provides the documentation, samples, header files, libraries,
|
||||
and tools you need to develop applications that use LZMA compression.
|
||||
|
||||
LZMA is default and general compression method of 7z format
|
||||
in 7-Zip compression program (www.7-zip.org). LZMA provides high
|
||||
compression ratio and very fast decompression.
|
||||
|
||||
LZMA is an improved version of famous LZ77 compression algorithm.
|
||||
It was improved in way of maximum increasing of compression ratio,
|
||||
keeping high decompression speed and low memory requirements for
|
||||
decompressing.
|
||||
|
||||
|
||||
|
||||
LICENSE
|
||||
-------
|
||||
|
||||
LZMA SDK is written and placed in the public domain by Igor Pavlov.
|
||||
|
||||
|
||||
LZMA SDK Contents
|
||||
-----------------
|
||||
|
||||
LZMA SDK includes:
|
||||
|
||||
- ANSI-C/C++/C#/Java source code for LZMA compressing and decompressing
|
||||
- Compiled file->file LZMA compressing/decompressing program for Windows system
|
||||
|
||||
|
||||
UNIX/Linux version
|
||||
------------------
|
||||
To compile C++ version of file->file LZMA encoding, go to directory
|
||||
C++/7zip/Compress/LZMA_Alone
|
||||
and call make to recompile it:
|
||||
make -f makefile.gcc clean all
|
||||
|
||||
In some UNIX/Linux versions you must compile LZMA with static libraries.
|
||||
To compile with static libraries, you can use
|
||||
LIB = -lm -static
|
||||
|
||||
|
||||
Files
|
||||
---------------------
|
||||
lzma.txt - LZMA SDK description (this file)
|
||||
7zFormat.txt - 7z Format description
|
||||
7zC.txt - 7z ANSI-C Decoder description
|
||||
methods.txt - Compression method IDs for .7z
|
||||
lzma.exe - Compiled file->file LZMA encoder/decoder for Windows
|
||||
history.txt - history of the LZMA SDK
|
||||
|
||||
|
||||
Source code structure
|
||||
---------------------
|
||||
|
||||
C/ - C files
|
||||
7zCrc*.* - CRC code
|
||||
Alloc.* - Memory allocation functions
|
||||
Bra*.* - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code
|
||||
LzFind.* - Match finder for LZ (LZMA) encoders
|
||||
LzFindMt.* - Match finder for LZ (LZMA) encoders for multithreading encoding
|
||||
LzHash.h - Additional file for LZ match finder
|
||||
LzmaDec.* - LZMA decoding
|
||||
LzmaEnc.* - LZMA encoding
|
||||
LzmaLib.* - LZMA Library for DLL calling
|
||||
Types.h - Basic types for another .c files
|
||||
Threads.* - The code for multithreading.
|
||||
|
||||
LzmaLib - LZMA Library (.DLL for Windows)
|
||||
|
||||
LzmaUtil - LZMA Utility (file->file LZMA encoder/decoder).
|
||||
|
||||
Archive - files related to archiving
|
||||
7z - 7z ANSI-C Decoder
|
||||
|
||||
CPP/ -- CPP files
|
||||
|
||||
Common - common files for C++ projects
|
||||
Windows - common files for Windows related code
|
||||
|
||||
7zip - files related to 7-Zip Project
|
||||
|
||||
Common - common files for 7-Zip
|
||||
|
||||
Compress - files related to compression/decompression
|
||||
|
||||
Copy - Copy coder
|
||||
RangeCoder - Range Coder (special code of compression/decompression)
|
||||
LZMA - LZMA compression/decompression on C++
|
||||
LZMA_Alone - file->file LZMA compression/decompression
|
||||
Branch - Filters for x86, IA-64, ARM, ARM-Thumb, PowerPC and SPARC code
|
||||
|
||||
Archive - files related to archiving
|
||||
|
||||
Common - common files for archive handling
|
||||
7z - 7z C++ Encoder/Decoder
|
||||
|
||||
Bundles - Modules that are bundles of other modules
|
||||
|
||||
Alone7z - 7zr.exe: Standalone version of 7z.exe that supports only 7z/LZMA/BCJ/BCJ2
|
||||
Format7zR - 7zr.dll: Reduced version of 7za.dll: extracting/compressing to 7z/LZMA/BCJ/BCJ2
|
||||
Format7zExtractR - 7zxr.dll: Reduced version of 7zxa.dll: extracting from 7z/LZMA/BCJ/BCJ2.
|
||||
|
||||
UI - User Interface files
|
||||
|
||||
Client7z - Test application for 7za.dll, 7zr.dll, 7zxr.dll
|
||||
Common - Common UI files
|
||||
Console - Code for console archiver
|
||||
|
||||
|
||||
|
||||
CS/ - C# files
|
||||
7zip
|
||||
Common - some common files for 7-Zip
|
||||
Compress - files related to compression/decompression
|
||||
LZ - files related to LZ (Lempel-Ziv) compression algorithm
|
||||
LZMA - LZMA compression/decompression
|
||||
LzmaAlone - file->file LZMA compression/decompression
|
||||
RangeCoder - Range Coder (special code of compression/decompression)
|
||||
|
||||
Java/ - Java files
|
||||
SevenZip
|
||||
Compression - files related to compression/decompression
|
||||
LZ - files related to LZ (Lempel-Ziv) compression algorithm
|
||||
LZMA - LZMA compression/decompression
|
||||
RangeCoder - Range Coder (special code of compression/decompression)
|
||||
|
||||
|
||||
C/C++ source code of LZMA SDK is part of 7-Zip project.
|
||||
7-Zip source code can be downloaded from 7-Zip's SourceForge page:
|
||||
|
||||
http://sourceforge.net/projects/sevenzip/
|
||||
|
||||
|
||||
|
||||
LZMA features
|
||||
-------------
|
||||
- Variable dictionary size (up to 1 GB)
|
||||
- Estimated compressing speed: about 2 MB/s on 2 GHz CPU
|
||||
- Estimated decompressing speed:
|
||||
- 20-30 MB/s on 2 GHz Core 2 or AMD Athlon 64
|
||||
- 1-2 MB/s on 200 MHz ARM, MIPS, PowerPC or other simple RISC
|
||||
- Small memory requirements for decompressing (16 KB + DictionarySize)
|
||||
- Small code size for decompressing: 5-8 KB
|
||||
|
||||
LZMA decoder uses only integer operations and can be
|
||||
implemented in any modern 32-bit CPU (or on 16-bit CPU with some conditions).
|
||||
|
||||
Some critical operations that affect the speed of LZMA decompression:
|
||||
1) 32*16 bit integer multiply
|
||||
2) Misspredicted branches (penalty mostly depends from pipeline length)
|
||||
3) 32-bit shift and arithmetic operations
|
||||
|
||||
The speed of LZMA decompressing mostly depends from CPU speed.
|
||||
Memory speed has no big meaning. But if your CPU has small data cache,
|
||||
overall weight of memory speed will slightly increase.
|
||||
|
||||
|
||||
How To Use
|
||||
----------
|
||||
|
||||
Using LZMA encoder/decoder executable
|
||||
--------------------------------------
|
||||
|
||||
Usage: LZMA <e|d> inputFile outputFile [<switches>...]
|
||||
|
||||
e: encode file
|
||||
|
||||
d: decode file
|
||||
|
||||
b: Benchmark. There are two tests: compressing and decompressing
|
||||
with LZMA method. Benchmark shows rating in MIPS (million
|
||||
instructions per second). Rating value is calculated from
|
||||
measured speed and it is normalized with Intel's Core 2 results.
|
||||
Also Benchmark checks possible hardware errors (RAM
|
||||
errors in most cases). Benchmark uses these settings:
|
||||
(-a1, -d21, -fb32, -mfbt4). You can change only -d parameter.
|
||||
Also you can change the number of iterations. Example for 30 iterations:
|
||||
LZMA b 30
|
||||
Default number of iterations is 10.
|
||||
|
||||
<Switches>
|
||||
|
||||
|
||||
-a{N}: set compression mode 0 = fast, 1 = normal
|
||||
default: 1 (normal)
|
||||
|
||||
d{N}: Sets Dictionary size - [0, 30], default: 23 (8MB)
|
||||
The maximum value for dictionary size is 1 GB = 2^30 bytes.
|
||||
Dictionary size is calculated as DictionarySize = 2^N bytes.
|
||||
For decompressing file compressed by LZMA method with dictionary
|
||||
size D = 2^N you need about D bytes of memory (RAM).
|
||||
|
||||
-fb{N}: set number of fast bytes - [5, 273], default: 128
|
||||
Usually big number gives a little bit better compression ratio
|
||||
and slower compression process.
|
||||
|
||||
-lc{N}: set number of literal context bits - [0, 8], default: 3
|
||||
Sometimes lc=4 gives gain for big files.
|
||||
|
||||
-lp{N}: set number of literal pos bits - [0, 4], default: 0
|
||||
lp switch is intended for periodical data when period is
|
||||
equal 2^N. For example, for 32-bit (4 bytes)
|
||||
periodical data you can use lp=2. Often it's better to set lc0,
|
||||
if you change lp switch.
|
||||
|
||||
-pb{N}: set number of pos bits - [0, 4], default: 2
|
||||
pb switch is intended for periodical data
|
||||
when period is equal 2^N.
|
||||
|
||||
-mf{MF_ID}: set Match Finder. Default: bt4.
|
||||
Algorithms from hc* group doesn't provide good compression
|
||||
ratio, but they often works pretty fast in combination with
|
||||
fast mode (-a0).
|
||||
|
||||
Memory requirements depend from dictionary size
|
||||
(parameter "d" in table below).
|
||||
|
||||
MF_ID Memory Description
|
||||
|
||||
bt2 d * 9.5 + 4MB Binary Tree with 2 bytes hashing.
|
||||
bt3 d * 11.5 + 4MB Binary Tree with 3 bytes hashing.
|
||||
bt4 d * 11.5 + 4MB Binary Tree with 4 bytes hashing.
|
||||
hc4 d * 7.5 + 4MB Hash Chain with 4 bytes hashing.
|
||||
|
||||
-eos: write End Of Stream marker. By default LZMA doesn't write
|
||||
eos marker, since LZMA decoder knows uncompressed size
|
||||
stored in .lzma file header.
|
||||
|
||||
-si: Read data from stdin (it will write End Of Stream marker).
|
||||
-so: Write data to stdout
|
||||
|
||||
|
||||
Examples:
|
||||
|
||||
1) LZMA e file.bin file.lzma -d16 -lc0
|
||||
|
||||
compresses file.bin to file.lzma with 64 KB dictionary (2^16=64K)
|
||||
and 0 literal context bits. -lc0 allows to reduce memory requirements
|
||||
for decompression.
|
||||
|
||||
|
||||
2) LZMA e file.bin file.lzma -lc0 -lp2
|
||||
|
||||
compresses file.bin to file.lzma with settings suitable
|
||||
for 32-bit periodical data (for example, ARM or MIPS code).
|
||||
|
||||
3) LZMA d file.lzma file.bin
|
||||
|
||||
decompresses file.lzma to file.bin.
|
||||
|
||||
|
||||
Compression ratio hints
|
||||
-----------------------
|
||||
|
||||
Recommendations
|
||||
---------------
|
||||
|
||||
To increase the compression ratio for LZMA compressing it's desirable
|
||||
to have aligned data (if it's possible) and also it's desirable to locate
|
||||
data in such order, where code is grouped in one place and data is
|
||||
grouped in other place (it's better than such mixing: code, data, code,
|
||||
data, ...).
|
||||
|
||||
|
||||
Filters
|
||||
-------
|
||||
You can increase the compression ratio for some data types, using
|
||||
special filters before compressing. For example, it's possible to
|
||||
increase the compression ratio on 5-10% for code for those CPU ISAs:
|
||||
x86, IA-64, ARM, ARM-Thumb, PowerPC, SPARC.
|
||||
|
||||
You can find C source code of such filters in C/Bra*.* files
|
||||
|
||||
You can check the compression ratio gain of these filters with such
|
||||
7-Zip commands (example for ARM code):
|
||||
No filter:
|
||||
7z a a1.7z a.bin -m0=lzma
|
||||
|
||||
With filter for little-endian ARM code:
|
||||
7z a a2.7z a.bin -m0=arm -m1=lzma
|
||||
|
||||
It works in such manner:
|
||||
Compressing = Filter_encoding + LZMA_encoding
|
||||
Decompressing = LZMA_decoding + Filter_decoding
|
||||
|
||||
Compressing and decompressing speed of such filters is very high,
|
||||
so it will not increase decompressing time too much.
|
||||
Moreover, it reduces decompression time for LZMA_decoding,
|
||||
since compression ratio with filtering is higher.
|
||||
|
||||
These filters convert CALL (calling procedure) instructions
|
||||
from relative offsets to absolute addresses, so such data becomes more
|
||||
compressible.
|
||||
|
||||
For some ISAs (for example, for MIPS) it's impossible to get gain from such filter.
|
||||
|
||||
|
||||
LZMA compressed file format
|
||||
---------------------------
|
||||
Offset Size Description
|
||||
0 1 Special LZMA properties (lc,lp, pb in encoded form)
|
||||
1 4 Dictionary size (little endian)
|
||||
5 8 Uncompressed size (little endian). -1 means unknown size
|
||||
13 Compressed data
|
||||
|
||||
|
||||
ANSI-C LZMA Decoder
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Please note that interfaces for ANSI-C code were changed in LZMA SDK 4.58.
|
||||
If you want to use old interfaces you can download previous version of LZMA SDK
|
||||
from sourceforge.net site.
|
||||
|
||||
To use ANSI-C LZMA Decoder you need the following files:
|
||||
1) LzmaDec.h + LzmaDec.c + Types.h
|
||||
LzmaUtil/LzmaUtil.c is example application that uses these files.
|
||||
|
||||
|
||||
Memory requirements for LZMA decoding
|
||||
-------------------------------------
|
||||
|
||||
Stack usage of LZMA decoding function for local variables is not
|
||||
larger than 200-400 bytes.
|
||||
|
||||
LZMA Decoder uses dictionary buffer and internal state structure.
|
||||
Internal state structure consumes
|
||||
state_size = (4 + (1.5 << (lc + lp))) KB
|
||||
by default (lc=3, lp=0), state_size = 16 KB.
|
||||
|
||||
|
||||
How To decompress data
|
||||
----------------------
|
||||
|
||||
LZMA Decoder (ANSI-C version) now supports 2 interfaces:
|
||||
1) Single-call Decompressing
|
||||
2) Multi-call State Decompressing (zlib-like interface)
|
||||
|
||||
You must use external allocator:
|
||||
Example:
|
||||
void *SzAlloc(void *p, size_t size) { p = p; return malloc(size); }
|
||||
void SzFree(void *p, void *address) { p = p; free(address); }
|
||||
ISzAlloc alloc = { SzAlloc, SzFree };
|
||||
|
||||
You can use p = p; operator to disable compiler warnings.
|
||||
|
||||
|
||||
Single-call Decompressing
|
||||
-------------------------
|
||||
When to use: RAM->RAM decompressing
|
||||
Compile files: LzmaDec.h + LzmaDec.c + Types.h
|
||||
Compile defines: no defines
|
||||
Memory Requirements:
|
||||
- Input buffer: compressed size
|
||||
- Output buffer: uncompressed size
|
||||
- LZMA Internal Structures: state_size (16 KB for default settings)
|
||||
|
||||
Interface:
|
||||
int LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen,
|
||||
const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode,
|
||||
ELzmaStatus *status, ISzAlloc *alloc);
|
||||
In:
|
||||
dest - output data
|
||||
destLen - output data size
|
||||
src - input data
|
||||
srcLen - input data size
|
||||
propData - LZMA properties (5 bytes)
|
||||
propSize - size of propData buffer (5 bytes)
|
||||
finishMode - It has meaning only if the decoding reaches output limit (*destLen).
|
||||
LZMA_FINISH_ANY - Decode just destLen bytes.
|
||||
LZMA_FINISH_END - Stream must be finished after (*destLen).
|
||||
You can use LZMA_FINISH_END, when you know that
|
||||
current output buffer covers last bytes of stream.
|
||||
alloc - Memory allocator.
|
||||
|
||||
Out:
|
||||
destLen - processed output size
|
||||
srcLen - processed input size
|
||||
|
||||
Output:
|
||||
SZ_OK
|
||||
status:
|
||||
LZMA_STATUS_FINISHED_WITH_MARK
|
||||
LZMA_STATUS_NOT_FINISHED
|
||||
LZMA_STATUS_MAYBE_FINISHED_WITHOUT_MARK
|
||||
SZ_ERROR_DATA - Data error
|
||||
SZ_ERROR_MEM - Memory allocation error
|
||||
SZ_ERROR_UNSUPPORTED - Unsupported properties
|
||||
SZ_ERROR_INPUT_EOF - It needs more bytes in input buffer (src).
|
||||
|
||||
If LZMA decoder sees end_marker before reaching output limit, it returns OK result,
|
||||
and output value of destLen will be less than output buffer size limit.
|
||||
|
||||
You can use multiple checks to test data integrity after full decompression:
|
||||
1) Check Result and "status" variable.
|
||||
2) Check that output(destLen) = uncompressedSize, if you know real uncompressedSize.
|
||||
3) Check that output(srcLen) = compressedSize, if you know real compressedSize.
|
||||
You must use correct finish mode in that case. */
|
||||
|
||||
|
||||
Multi-call State Decompressing (zlib-like interface)
|
||||
----------------------------------------------------
|
||||
|
||||
When to use: file->file decompressing
|
||||
Compile files: LzmaDec.h + LzmaDec.c + Types.h
|
||||
|
||||
Memory Requirements:
|
||||
- Buffer for input stream: any size (for example, 16 KB)
|
||||
- Buffer for output stream: any size (for example, 16 KB)
|
||||
- LZMA Internal Structures: state_size (16 KB for default settings)
|
||||
- LZMA dictionary (dictionary size is encoded in LZMA properties header)
|
||||
|
||||
1) read LZMA properties (5 bytes) and uncompressed size (8 bytes, little-endian) to header:
|
||||
unsigned char header[LZMA_PROPS_SIZE + 8];
|
||||
ReadFile(inFile, header, sizeof(header)
|
||||
|
||||
2) Allocate CLzmaDec structures (state + dictionary) using LZMA properties
|
||||
|
||||
CLzmaDec state;
|
||||
LzmaDec_Constr(&state);
|
||||
res = LzmaDec_Allocate(&state, header, LZMA_PROPS_SIZE, &g_Alloc);
|
||||
if (res != SZ_OK)
|
||||
return res;
|
||||
|
||||
3) Init LzmaDec structure before any new LZMA stream. And call LzmaDec_DecodeToBuf in loop
|
||||
|
||||
LzmaDec_Init(&state);
|
||||
for (;;)
|
||||
{
|
||||
...
|
||||
int res = LzmaDec_DecodeToBuf(CLzmaDec *p, Byte *dest, SizeT *destLen,
|
||||
const Byte *src, SizeT *srcLen, ELzmaFinishMode finishMode);
|
||||
...
|
||||
}
|
||||
|
||||
|
||||
4) Free all allocated structures
|
||||
LzmaDec_Free(&state, &g_Alloc);
|
||||
|
||||
For full code example, look at C/LzmaUtil/LzmaUtil.c code.
|
||||
|
||||
|
||||
How To compress data
|
||||
--------------------
|
||||
|
||||
Compile files: LzmaEnc.h + LzmaEnc.c + Types.h +
|
||||
LzFind.c + LzFind.h + LzFindMt.c + LzFindMt.h + LzHash.h
|
||||
|
||||
Memory Requirements:
|
||||
- (dictSize * 11.5 + 6 MB) + state_size
|
||||
|
||||
Lzma Encoder can use two memory allocators:
|
||||
1) alloc - for small arrays.
|
||||
2) allocBig - for big arrays.
|
||||
|
||||
For example, you can use Large RAM Pages (2 MB) in allocBig allocator for
|
||||
better compression speed. Note that Windows has bad implementation for
|
||||
Large RAM Pages.
|
||||
It's OK to use same allocator for alloc and allocBig.
|
||||
|
||||
|
||||
Single-call Compression with callbacks
|
||||
--------------------------------------
|
||||
|
||||
Check C/LzmaUtil/LzmaUtil.c as example,
|
||||
|
||||
When to use: file->file decompressing
|
||||
|
||||
1) you must implement callback structures for interfaces:
|
||||
ISeqInStream
|
||||
ISeqOutStream
|
||||
ICompressProgress
|
||||
ISzAlloc
|
||||
|
||||
static void *SzAlloc(void *p, size_t size) { p = p; return MyAlloc(size); }
|
||||
static void SzFree(void *p, void *address) { p = p; MyFree(address); }
|
||||
static ISzAlloc g_Alloc = { SzAlloc, SzFree };
|
||||
|
||||
CFileSeqInStream inStream;
|
||||
CFileSeqOutStream outStream;
|
||||
|
||||
inStream.funcTable.Read = MyRead;
|
||||
inStream.file = inFile;
|
||||
outStream.funcTable.Write = MyWrite;
|
||||
outStream.file = outFile;
|
||||
|
||||
|
||||
2) Create CLzmaEncHandle object;
|
||||
|
||||
CLzmaEncHandle enc;
|
||||
|
||||
enc = LzmaEnc_Create(&g_Alloc);
|
||||
if (enc == 0)
|
||||
return SZ_ERROR_MEM;
|
||||
|
||||
|
||||
3) initialize CLzmaEncProps properties;
|
||||
|
||||
LzmaEncProps_Init(&props);
|
||||
|
||||
Then you can change some properties in that structure.
|
||||
|
||||
4) Send LZMA properties to LZMA Encoder
|
||||
|
||||
res = LzmaEnc_SetProps(enc, &props);
|
||||
|
||||
5) Write encoded properties to header
|
||||
|
||||
Byte header[LZMA_PROPS_SIZE + 8];
|
||||
size_t headerSize = LZMA_PROPS_SIZE;
|
||||
UInt64 fileSize;
|
||||
int i;
|
||||
|
||||
res = LzmaEnc_WriteProperties(enc, header, &headerSize);
|
||||
fileSize = MyGetFileLength(inFile);
|
||||
for (i = 0; i < 8; i++)
|
||||
header[headerSize++] = (Byte)(fileSize >> (8 * i));
|
||||
MyWriteFileAndCheck(outFile, header, headerSize)
|
||||
|
||||
6) Call encoding function:
|
||||
res = LzmaEnc_Encode(enc, &outStream.funcTable, &inStream.funcTable,
|
||||
NULL, &g_Alloc, &g_Alloc);
|
||||
|
||||
7) Destroy LZMA Encoder Object
|
||||
LzmaEnc_Destroy(enc, &g_Alloc, &g_Alloc);
|
||||
|
||||
|
||||
If callback function return some error code, LzmaEnc_Encode also returns that code.
|
||||
|
||||
|
||||
Single-call RAM->RAM Compression
|
||||
--------------------------------
|
||||
|
||||
Single-call RAM->RAM Compression is similar to Compression with callbacks,
|
||||
but you provide pointers to buffers instead of pointers to stream callbacks:
|
||||
|
||||
HRes LzmaEncode(Byte *dest, SizeT *destLen, const Byte *src, SizeT srcLen,
|
||||
CLzmaEncProps *props, Byte *propsEncoded, SizeT *propsSize, int writeEndMark,
|
||||
ICompressProgress *progress, ISzAlloc *alloc, ISzAlloc *allocBig);
|
||||
|
||||
Return code:
|
||||
SZ_OK - OK
|
||||
SZ_ERROR_MEM - Memory allocation error
|
||||
SZ_ERROR_PARAM - Incorrect paramater
|
||||
SZ_ERROR_OUTPUT_EOF - output buffer overflow
|
||||
SZ_ERROR_THREAD - errors in multithreading functions (only for Mt version)
|
||||
|
||||
|
||||
|
||||
LZMA Defines
|
||||
------------
|
||||
|
||||
_LZMA_SIZE_OPT - Enable some optimizations in LZMA Decoder to get smaller executable code.
|
||||
|
||||
_LZMA_PROB32 - It can increase the speed on some 32-bit CPUs, but memory usage for
|
||||
some structures will be doubled in that case.
|
||||
|
||||
_LZMA_UINT32_IS_ULONG - Define it if int is 16-bit on your compiler and long is 32-bit.
|
||||
|
||||
_LZMA_NO_SYSTEM_SIZE_T - Define it if you don't want to use size_t type.
|
||||
|
||||
|
||||
C++ LZMA Encoder/Decoder
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
C++ LZMA code use COM-like interfaces. So if you want to use it,
|
||||
you can study basics of COM/OLE.
|
||||
C++ LZMA code is just wrapper over ANSI-C code.
|
||||
|
||||
|
||||
C++ Notes
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
If you use some C++ code folders in 7-Zip (for example, C++ code for .7z handling),
|
||||
you must check that you correctly work with "new" operator.
|
||||
7-Zip can be compiled with MSVC 6.0 that doesn't throw "exception" from "new" operator.
|
||||
So 7-Zip uses "CPP\Common\NewHandler.cpp" that redefines "new" operator:
|
||||
operator new(size_t size)
|
||||
{
|
||||
void *p = ::malloc(size);
|
||||
if (p == 0)
|
||||
throw CNewException();
|
||||
return p;
|
||||
}
|
||||
If you use MSCV that throws exception for "new" operator, you can compile without
|
||||
"NewHandler.cpp". So standard exception will be used. Actually some code of
|
||||
7-Zip catches any exception in internal code and converts it to HRESULT code.
|
||||
So you don't need to catch CNewException, if you call COM interfaces of 7-Zip.
|
||||
|
||||
---
|
||||
|
||||
http://www.7-zip.org
|
||||
http://www.7-zip.org/sdk.html
|
||||
http://www.7-zip.org/support.html
|
|
@ -1,19 +0,0 @@
|
|||
Modified LZMA 4.65
|
||||
------------------
|
||||
This is just the ANSI C 7-zip extraction code from the LZMA 4.65 source
|
||||
code release, with unnecessary files removed. I've made minor changes to
|
||||
allow the code to compile with almost all warnings enabled in GCC.
|
||||
|
||||
* Made relevant functions extern "C" so that they can be called from
|
||||
C++.
|
||||
|
||||
* Put all files in same directory and removed "../../" from #includes.
|
||||
|
||||
* Made private (unprototyped) functions static.
|
||||
|
||||
* #if'd out code that is never called.
|
||||
|
||||
* Removed a couple of Windows references.
|
||||
|
||||
--
|
||||
Shay Green <gblargg@gmail.com>
|
|
@ -1,187 +0,0 @@
|
|||
include nall/Makefile
|
||||
|
||||
qtlibs := QtCore QtGui
|
||||
include nall/qt/Makefile
|
||||
|
||||
c := $(compiler) -std=gnu99
|
||||
cpp := $(subst cc,++,$(compiler)) -std=gnu++0x
|
||||
flags := -O3 -I. -Iobj -fomit-frame-pointer
|
||||
link :=
|
||||
|
||||
ifeq ($(platform),x)
|
||||
flags := -fPIC $(flags)
|
||||
link += -s
|
||||
else ifeq ($(platform),osx)
|
||||
flags := -fPIC $(flags)
|
||||
endif
|
||||
|
||||
objects := snesreader
|
||||
|
||||
# fex
|
||||
objects += Binary_Extractor blargg_common blargg_errors Data_Reader fex File_Extractor Gzip_Extractor Gzip_Reader Rar_Extractor Zip7_Extractor Zip_Extractor Zlib_Inflater
|
||||
# zlib
|
||||
objects += adler32 crc32 inffast inflate inftrees zutil
|
||||
# 7-zip
|
||||
objects += 7zAlloc 7zBuf 7zCrc 7zDecode 7zExtract 7zHeader 7zIn 7zItem 7zStream Bcj2 Bra86 LzmaDec
|
||||
# unrar
|
||||
objects += archive arcread coder crc encname extract getbits model rarvm rarvmtbl rawread suballoc unicode unpack unpack15 unpack20 unrar unrar_misc unrar_open
|
||||
# micro-bunzip
|
||||
objects += micro-bunzip
|
||||
# jma
|
||||
objects += jma jcrc32 lzmadecode 7zlzma iiostrm inbyte lzma winout
|
||||
|
||||
compile = \
|
||||
$(strip \
|
||||
$(if $(filter %.c,$<), \
|
||||
$(c) $(flags) $1 -c $< -o $@, \
|
||||
$(if $(filter %.cpp,$<), \
|
||||
$(cpp) $(flags) $1 -c $< -o $@ \
|
||||
) \
|
||||
) \
|
||||
)
|
||||
|
||||
%.o: $<; $(call compile)
|
||||
|
||||
all: build;
|
||||
|
||||
objects := $(patsubst %,obj/%.o,$(objects))
|
||||
moc_headers := $(call rwildcard,./,%.moc.hpp)
|
||||
moc_objects := $(foreach f,$(moc_headers),obj/$(notdir $(patsubst %.moc.hpp,%.moc,$f)))
|
||||
|
||||
# automatically run moc on all .moc.hpp (MOC header) files
|
||||
%.moc: $<; $(moc) -i $< -o $@
|
||||
|
||||
# automatically generate %.moc build rules
|
||||
__list = $(moc_headers)
|
||||
$(foreach f,$(moc_objects), \
|
||||
$(eval __file = $(word 1,$(__list))) \
|
||||
$(eval __list = $(wordlist 2,$(words $(__list)),$(__list))) \
|
||||
$(eval $f: $(__file)) \
|
||||
)
|
||||
|
||||
##################
|
||||
### snesreader ###
|
||||
##################
|
||||
|
||||
obj/snesreader.o: snesreader.cpp *
|
||||
$(call compile,$(qtinc))
|
||||
|
||||
###########
|
||||
### fex ###
|
||||
###########
|
||||
|
||||
obj/Binary_Extractor.o: fex/Binary_Extractor.cpp fex/*
|
||||
obj/blargg_common.o : fex/blargg_common.cpp fex/*
|
||||
obj/blargg_errors.o : fex/blargg_errors.cpp fex/*
|
||||
obj/Data_Reader.o : fex/Data_Reader.cpp fex/*
|
||||
obj/fex.o : fex/fex.cpp fex/*
|
||||
obj/File_Extractor.o : fex/File_Extractor.cpp fex/*
|
||||
obj/Gzip_Extractor.o : fex/Gzip_Extractor.cpp fex/*
|
||||
obj/Gzip_Reader.o : fex/Gzip_Reader.cpp fex/*
|
||||
obj/Rar_Extractor.o : fex/Rar_Extractor.cpp fex/*
|
||||
obj/Zip7_Extractor.o : fex/Zip7_Extractor.cpp fex/*
|
||||
obj/Zip_Extractor.o : fex/Zip_Extractor.cpp fex/*
|
||||
obj/Zlib_Inflater.o : fex/Zlib_Inflater.cpp fex/*
|
||||
|
||||
############
|
||||
### zlib ###
|
||||
############
|
||||
|
||||
obj/adler32.o : zlib/adler32.c zlib/*
|
||||
obj/crc32.o : zlib/crc32.c zlib/*
|
||||
obj/inffast.o : zlib/inffast.c zlib/*
|
||||
obj/inflate.o : zlib/inflate.c zlib/*
|
||||
obj/inftrees.o: zlib/inftrees.c zlib/*
|
||||
obj/zutil.o : zlib/zutil.c zlib/*
|
||||
|
||||
#############
|
||||
### 7-zip ###
|
||||
#############
|
||||
|
||||
obj/7zAlloc.o : 7z_C/7zAlloc.c 7z_C/*
|
||||
obj/7zBuf.o : 7z_C/7zBuf.c 7z_C/*
|
||||
obj/7zCrc.o : 7z_C/7zCrc.c 7z_C/*
|
||||
obj/7zDecode.o : 7z_C/7zDecode.c 7z_C/*
|
||||
obj/7zExtract.o: 7z_C/7zExtract.c 7z_C/*
|
||||
obj/7zHeader.o : 7z_C/7zHeader.c 7z_C/*
|
||||
obj/7zIn.o : 7z_C/7zIn.c 7z_C/*
|
||||
obj/7zItem.o : 7z_C/7zItem.c 7z_C/*
|
||||
obj/7zStream.o : 7z_C/7zStream.c 7z_C/*
|
||||
obj/Bcj2.o : 7z_C/Bcj2.c 7z_C/*
|
||||
obj/Bra86.o : 7z_C/Bra86.c 7z_C/*
|
||||
obj/LzmaDec.o : 7z_C/LzmaDec.c 7z_C/*
|
||||
|
||||
####################
|
||||
### micro-bunzip ###
|
||||
####################
|
||||
|
||||
obj/micro-bunzip.o: micro-bunzip/micro-bunzip.c micro-bunzip/*
|
||||
|
||||
#############
|
||||
### unrar ###
|
||||
#############
|
||||
|
||||
obj/archive.o : unrar/archive.cpp unrar/*
|
||||
obj/arcread.o : unrar/arcread.cpp unrar/*
|
||||
obj/coder.o : unrar/coder.cpp unrar/*
|
||||
obj/crc.o : unrar/crc.cpp unrar/*
|
||||
obj/encname.o : unrar/encname.cpp unrar/*
|
||||
obj/extract.o : unrar/extract.cpp unrar/*
|
||||
obj/getbits.o : unrar/getbits.cpp unrar/*
|
||||
obj/model.o : unrar/model.cpp unrar/*
|
||||
obj/rarvm.o : unrar/rarvm.cpp unrar/*
|
||||
obj/rarvmtbl.o : unrar/rarvmtbl.cpp unrar/*
|
||||
obj/rawread.o : unrar/rawread.cpp unrar/*
|
||||
obj/suballoc.o : unrar/suballoc.cpp unrar/*
|
||||
obj/unicode.o : unrar/unicode.cpp unrar/*
|
||||
obj/unpack.o : unrar/unpack.cpp unrar/*
|
||||
obj/unpack15.o : unrar/unpack15.cpp unrar/*
|
||||
obj/unpack20.o : unrar/unpack20.cpp unrar/*
|
||||
obj/unrar.o : unrar/unrar.cpp unrar/*
|
||||
obj/unrar_misc.o: unrar/unrar_misc.cpp unrar/*
|
||||
obj/unrar_open.o: unrar/unrar_open.cpp unrar/*
|
||||
|
||||
##############
|
||||
### libjma ###
|
||||
##############
|
||||
|
||||
obj/jma.o : libjma/jma.cpp libjma/*
|
||||
obj/jcrc32.o : libjma/jcrc32.cpp libjma/*
|
||||
obj/lzmadecode.o: libjma/lzmadecode.cpp libjma/*
|
||||
obj/7zlzma.o : libjma/7zlzma.cpp libjma/*
|
||||
obj/iiostrm.o : libjma/iiostrm.cpp libjma/*
|
||||
obj/inbyte.o : libjma/inbyte.cpp libjma/*
|
||||
obj/lzma.o : libjma/lzma.cpp libjma/*
|
||||
obj/winout.o : libjma/winout.cpp libjma/*
|
||||
|
||||
###############
|
||||
### targets ###
|
||||
###############
|
||||
|
||||
build: $(moc_objects) $(objects)
|
||||
ifeq ($(platform),x)
|
||||
ar rcs libsnesreader.a $(objects)
|
||||
$(cpp) $(link) -o libsnesreader.so -shared -Wl,-soname,libsnesreader.so.1 $(objects) $(qtlib)
|
||||
else ifeq ($(platform),osx)
|
||||
ar rcs libsnesreader.a $(objects)
|
||||
$(cpp) $(link) -o libsnesreader.dylib -shared -dynamiclib $(objects) $(qtlib)
|
||||
else ifeq ($(platform),win)
|
||||
$(cpp) $(link) -o snesreader.dll -shared -Wl,--out-implib,libsnesreader.a $(objects) $(qtlib)
|
||||
endif
|
||||
|
||||
install:
|
||||
ifeq ($(platform),x)
|
||||
install -D -m 755 libsnesreader.a $(DESTDIR)$(prefix)/lib
|
||||
install -D -m 755 libsnesreader.so $(DESTDIR)$(prefix)/lib
|
||||
ldconfig -n $(DESTDIR)$(prefix)/lib
|
||||
else ifeq ($(platform),osx)
|
||||
cp libsnesreader.dylib /usr/local/lib/libsnesreader.dylib
|
||||
endif
|
||||
|
||||
clean:
|
||||
-@$(call delete,obj/*.o)
|
||||
-@$(call delete,obj/*.moc)
|
||||
-@$(call delete,libsnesreader.a)
|
||||
-@$(call delete,libsnesreader.so)
|
||||
-@$(call delete,libsnesreader.dylib)
|
||||
-@$(call delete,snesreader.dll)
|
|
@ -1,2 +0,0 @@
|
|||
@mingw32-make
|
||||
@pause
|
|
@ -1 +0,0 @@
|
|||
@mingw32-make clean
|
|
@ -1,77 +0,0 @@
|
|||
// File_Extractor 1.0.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "Binary_Extractor.h"
|
||||
|
||||
/* Copyright (C) 2005-2009 Shay Green. This module is free software; you
|
||||
can redistribute it and/or modify it under the terms of the GNU Lesser
|
||||
General Public License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version. This
|
||||
module is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
details. You should have received a copy of the GNU Lesser General Public
|
||||
License along with this module; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
#include "blargg_source.h"
|
||||
|
||||
// TODO: could close file once data has been read into memory
|
||||
|
||||
static File_Extractor* new_binary()
|
||||
{
|
||||
return BLARGG_NEW Binary_Extractor;
|
||||
}
|
||||
|
||||
fex_type_t_ const fex_bin_type [1] = {{
|
||||
"",
|
||||
&new_binary,
|
||||
"file",
|
||||
NULL
|
||||
}};
|
||||
|
||||
Binary_Extractor::Binary_Extractor() :
|
||||
File_Extractor( fex_bin_type )
|
||||
{ }
|
||||
|
||||
Binary_Extractor::~Binary_Extractor()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
blargg_err_t Binary_Extractor::open_path_v()
|
||||
{
|
||||
set_name( arc_path() );
|
||||
return blargg_ok;
|
||||
}
|
||||
|
||||
blargg_err_t Binary_Extractor::open_v()
|
||||
{
|
||||
set_name( arc_path() );
|
||||
set_info( arc().remain(), 0, 0 );
|
||||
return blargg_ok;
|
||||
}
|
||||
|
||||
void Binary_Extractor::close_v()
|
||||
{ }
|
||||
|
||||
blargg_err_t Binary_Extractor::next_v()
|
||||
{
|
||||
return blargg_ok;
|
||||
}
|
||||
|
||||
blargg_err_t Binary_Extractor::rewind_v()
|
||||
{
|
||||
return open_path_v();
|
||||
}
|
||||
|
||||
blargg_err_t Binary_Extractor::stat_v()
|
||||
{
|
||||
RETURN_ERR( open_arc_file() );
|
||||
RETURN_ERR( arc().seek( 0 ) );
|
||||
return open_v();
|
||||
}
|
||||
|
||||
blargg_err_t Binary_Extractor::extract_v( void* p, int n )
|
||||
{
|
||||
return arc().read( p, n );
|
||||
}
|
|
@ -1,26 +0,0 @@
|
|||
// Presents a single file as an "archive" of just that file.
|
||||
|
||||
// File_Extractor 1.0.0
|
||||
#ifndef BINARY_EXTRACTOR_H
|
||||
#define BINARY_EXTRACTOR_H
|
||||
|
||||
#include "File_Extractor.h"
|
||||
|
||||
class Binary_Extractor : public File_Extractor {
|
||||
public:
|
||||
Binary_Extractor();
|
||||
virtual ~Binary_Extractor();
|
||||
|
||||
protected:
|
||||
virtual blargg_err_t open_path_v();
|
||||
virtual blargg_err_t open_v();
|
||||
virtual void close_v();
|
||||
|
||||
virtual blargg_err_t next_v();
|
||||
virtual blargg_err_t rewind_v();
|
||||
|
||||
virtual blargg_err_t stat_v();
|
||||
virtual blargg_err_t extract_v( void*, int );
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,551 +0,0 @@
|
|||
// File_Extractor 1.0.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "Data_Reader.h"
|
||||
|
||||
#include "blargg_endian.h"
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
|
||||
#if BLARGG_UTF8_PATHS
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
/* Copyright (C) 2005-2009 Shay Green. This module is free software; you
|
||||
can redistribute it and/or modify it under the terms of the GNU Lesser
|
||||
General Public License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version. This
|
||||
module is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
details. You should have received a copy of the GNU Lesser General Public
|
||||
License along with this module; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
#include "blargg_source.h"
|
||||
|
||||
// Data_Reader
|
||||
|
||||
blargg_err_t Data_Reader::read( void* p, int n )
|
||||
{
|
||||
assert( n >= 0 );
|
||||
|
||||
if ( n < 0 )
|
||||
return blargg_err_caller;
|
||||
|
||||
if ( n <= 0 )
|
||||
return blargg_ok;
|
||||
|
||||
if ( n > remain() )
|
||||
return blargg_err_file_eof;
|
||||
|
||||
blargg_err_t err = read_v( p, n );
|
||||
if ( !err )
|
||||
remain_ -= n;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
blargg_err_t Data_Reader::read_avail( void* p, int* n_ )
|
||||
{
|
||||
assert( *n_ >= 0 );
|
||||
|
||||
int n = min( *n_, remain() );
|
||||
*n_ = 0;
|
||||
|
||||
if ( n < 0 )
|
||||
return blargg_err_caller;
|
||||
|
||||
if ( n <= 0 )
|
||||
return blargg_ok;
|
||||
|
||||
blargg_err_t err = read_v( p, n );
|
||||
if ( !err )
|
||||
{
|
||||
remain_ -= n;
|
||||
*n_ = n;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
blargg_err_t Data_Reader::read_avail( void* p, long* n )
|
||||
{
|
||||
int i = STATIC_CAST(int, *n);
|
||||
blargg_err_t err = read_avail( p, &i );
|
||||
*n = i;
|
||||
return err;
|
||||
}
|
||||
|
||||
blargg_err_t Data_Reader::skip_v( int count )
|
||||
{
|
||||
char buf [512];
|
||||
while ( count )
|
||||
{
|
||||
int n = min( count, (int) sizeof buf );
|
||||
count -= n;
|
||||
RETURN_ERR( read_v( buf, n ) );
|
||||
}
|
||||
return blargg_ok;
|
||||
}
|
||||
|
||||
blargg_err_t Data_Reader::skip( int n )
|
||||
{
|
||||
assert( n >= 0 );
|
||||
|
||||
if ( n < 0 )
|
||||
return blargg_err_caller;
|
||||
|
||||
if ( n <= 0 )
|
||||
return blargg_ok;
|
||||
|
||||
if ( n > remain() )
|
||||
return blargg_err_file_eof;
|
||||
|
||||
blargg_err_t err = skip_v( n );
|
||||
if ( !err )
|
||||
remain_ -= n;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
// File_Reader
|
||||
|
||||
blargg_err_t File_Reader::seek( int n )
|
||||
{
|
||||
assert( n >= 0 );
|
||||
|
||||
if ( n < 0 )
|
||||
return blargg_err_caller;
|
||||
|
||||
if ( n == tell() )
|
||||
return blargg_ok;
|
||||
|
||||
if ( n > size() )
|
||||
return blargg_err_file_eof;
|
||||
|
||||
blargg_err_t err = seek_v( n );
|
||||
if ( !err )
|
||||
set_tell( n );
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
blargg_err_t File_Reader::skip_v( int n )
|
||||
{
|
||||
return seek_v( tell() + n );
|
||||
}
|
||||
|
||||
|
||||
// Subset_Reader
|
||||
|
||||
Subset_Reader::Subset_Reader( Data_Reader* dr, int size ) :
|
||||
in( dr )
|
||||
{
|
||||
set_remain( min( size, dr->remain() ) );
|
||||
}
|
||||
|
||||
blargg_err_t Subset_Reader::read_v( void* p, int s )
|
||||
{
|
||||
return in->read( p, s );
|
||||
}
|
||||
|
||||
|
||||
// Remaining_Reader
|
||||
|
||||
Remaining_Reader::Remaining_Reader( void const* h, int size, Data_Reader* r ) :
|
||||
in( r )
|
||||
{
|
||||
header = h;
|
||||
header_remain = size;
|
||||
|
||||
set_remain( size + r->remain() );
|
||||
}
|
||||
|
||||
blargg_err_t Remaining_Reader::read_v( void* out, int count )
|
||||
{
|
||||
int first = min( count, header_remain );
|
||||
if ( first )
|
||||
{
|
||||
memcpy( out, header, first );
|
||||
header = STATIC_CAST(char const*, header) + first;
|
||||
header_remain -= first;
|
||||
}
|
||||
|
||||
return in->read( STATIC_CAST(char*, out) + first, count - first );
|
||||
}
|
||||
|
||||
|
||||
// Mem_File_Reader
|
||||
|
||||
Mem_File_Reader::Mem_File_Reader( const void* p, long s ) :
|
||||
begin( STATIC_CAST(const char*, p) )
|
||||
{
|
||||
set_size( s );
|
||||
}
|
||||
|
||||
blargg_err_t Mem_File_Reader::read_v( void* p, int s )
|
||||
{
|
||||
memcpy( p, begin + tell(), s );
|
||||
return blargg_ok;
|
||||
}
|
||||
|
||||
blargg_err_t Mem_File_Reader::seek_v( int )
|
||||
{
|
||||
return blargg_ok;
|
||||
}
|
||||
|
||||
|
||||
// Callback_Reader
|
||||
|
||||
Callback_Reader::Callback_Reader( callback_t c, long s, void* d ) :
|
||||
callback( c ),
|
||||
user_data( d )
|
||||
{
|
||||
set_remain( s );
|
||||
}
|
||||
|
||||
blargg_err_t Callback_Reader::read_v( void* out, int count )
|
||||
{
|
||||
return callback( user_data, out, count );
|
||||
}
|
||||
|
||||
|
||||
// Callback_File_Reader
|
||||
|
||||
Callback_File_Reader::Callback_File_Reader( callback_t c, long s, void* d ) :
|
||||
callback( c ),
|
||||
user_data( d )
|
||||
{
|
||||
set_size( s );
|
||||
}
|
||||
|
||||
blargg_err_t Callback_File_Reader::read_v( void* out, int count )
|
||||
{
|
||||
return callback( user_data, out, count, tell() );
|
||||
}
|
||||
|
||||
blargg_err_t Callback_File_Reader::seek_v( int )
|
||||
{
|
||||
return blargg_ok;
|
||||
}
|
||||
|
||||
|
||||
// BLARGG_UTF8_PATHS
|
||||
|
||||
#if BLARGG_UTF8_PATHS
|
||||
|
||||
// Thanks to byuu for the idea for BLARGG_UTF8_PATHS and the implementations
|
||||
|
||||
// Converts wide-character path to UTF-8. Free result with free(). Only supported on Windows.
|
||||
char* blargg_to_utf8( const wchar_t* wpath )
|
||||
{
|
||||
if ( wpath == NULL )
|
||||
return NULL;
|
||||
|
||||
int needed = WideCharToMultiByte( CP_UTF8, 0, wpath, -1, NULL, 0, NULL, NULL );
|
||||
if ( needed <= 0 )
|
||||
return NULL;
|
||||
|
||||
char* path = (char*) malloc( needed );
|
||||
if ( path == NULL )
|
||||
return NULL;
|
||||
|
||||
int actual = WideCharToMultiByte( CP_UTF8, 0, wpath, -1, path, needed, NULL, NULL );
|
||||
if ( actual == 0 )
|
||||
{
|
||||
free( path );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
assert( actual == needed );
|
||||
return path;
|
||||
}
|
||||
|
||||
// Converts UTF-8 path to wide-character. Free result with free() Only supported on Windows.
|
||||
wchar_t* blargg_to_wide( const char* path )
|
||||
{
|
||||
if ( path == NULL )
|
||||
return NULL;
|
||||
|
||||
int needed = MultiByteToWideChar( CP_UTF8, 0, path, -1, NULL, 0 );
|
||||
if ( needed <= 0 )
|
||||
return NULL;
|
||||
|
||||
wchar_t* wpath = (wchar_t*) malloc( needed * sizeof *wpath );
|
||||
if ( wpath == NULL )
|
||||
return NULL;
|
||||
|
||||
int actual = MultiByteToWideChar( CP_UTF8, 0, path, -1, wpath, needed );
|
||||
if ( actual == 0 )
|
||||
{
|
||||
free( wpath );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
assert( actual == needed );
|
||||
return wpath;
|
||||
}
|
||||
|
||||
static FILE* blargg_fopen( const char path [], const char mode [] )
|
||||
{
|
||||
FILE* file = NULL;
|
||||
wchar_t* wmode = NULL;
|
||||
wchar_t* wpath = NULL;
|
||||
|
||||
wpath = blargg_to_wide( path );
|
||||
if ( wpath )
|
||||
{
|
||||
wmode = blargg_to_wide( mode );
|
||||
if ( wmode )
|
||||
file = _wfopen( wpath, wmode );
|
||||
}
|
||||
|
||||
// Save and restore errno in case free() clears it
|
||||
int saved_errno = errno;
|
||||
free( wmode );
|
||||
free( wpath );
|
||||
errno = saved_errno;
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static inline FILE* blargg_fopen( const char path [], const char mode [] )
|
||||
{
|
||||
return fopen( path, mode );
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
// Std_File_Reader
|
||||
|
||||
Std_File_Reader::Std_File_Reader()
|
||||
{
|
||||
file_ = NULL;
|
||||
}
|
||||
|
||||
Std_File_Reader::~Std_File_Reader()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
static blargg_err_t blargg_fopen( FILE** out, const char path [] )
|
||||
{
|
||||
errno = 0;
|
||||
*out = blargg_fopen( path, "rb" );
|
||||
if ( !*out )
|
||||
{
|
||||
#ifdef ENOENT
|
||||
if ( errno == ENOENT )
|
||||
return blargg_err_file_missing;
|
||||
#endif
|
||||
#ifdef ENOMEM
|
||||
if ( errno == ENOMEM )
|
||||
return blargg_err_memory;
|
||||
#endif
|
||||
return blargg_err_file_read;
|
||||
}
|
||||
|
||||
return blargg_ok;
|
||||
}
|
||||
|
||||
static blargg_err_t blargg_fsize( FILE* f, long* out )
|
||||
{
|
||||
if ( fseek( f, 0, SEEK_END ) )
|
||||
return blargg_err_file_io;
|
||||
|
||||
*out = ftell( f );
|
||||
if ( *out < 0 )
|
||||
return blargg_err_file_io;
|
||||
|
||||
if ( fseek( f, 0, SEEK_SET ) )
|
||||
return blargg_err_file_io;
|
||||
|
||||
return blargg_ok;
|
||||
}
|
||||
|
||||
blargg_err_t Std_File_Reader::open( const char path [] )
|
||||
{
|
||||
close();
|
||||
|
||||
FILE* f;
|
||||
RETURN_ERR( blargg_fopen( &f, path ) );
|
||||
|
||||
long s;
|
||||
blargg_err_t err = blargg_fsize( f, &s );
|
||||
if ( err )
|
||||
{
|
||||
fclose( f );
|
||||
return err;
|
||||
}
|
||||
|
||||
file_ = f;
|
||||
set_size( s );
|
||||
|
||||
return blargg_ok;
|
||||
}
|
||||
|
||||
void Std_File_Reader::make_unbuffered()
|
||||
{
|
||||
if ( setvbuf( STATIC_CAST(FILE*, file_), NULL, _IONBF, 0 ) )
|
||||
check( false ); // shouldn't fail, but OK if it does
|
||||
}
|
||||
|
||||
blargg_err_t Std_File_Reader::read_v( void* p, int s )
|
||||
{
|
||||
if ( (size_t) s != fread( p, 1, s, STATIC_CAST(FILE*, file_) ) )
|
||||
{
|
||||
// Data_Reader's wrapper should prevent EOF
|
||||
check( !feof( STATIC_CAST(FILE*, file_) ) );
|
||||
|
||||
return blargg_err_file_io;
|
||||
}
|
||||
|
||||
return blargg_ok;
|
||||
}
|
||||
|
||||
blargg_err_t Std_File_Reader::seek_v( int n )
|
||||
{
|
||||
if ( fseek( STATIC_CAST(FILE*, file_), n, SEEK_SET ) )
|
||||
{
|
||||
// Data_Reader's wrapper should prevent EOF
|
||||
check( !feof( STATIC_CAST(FILE*, file_) ) );
|
||||
|
||||
return blargg_err_file_io;
|
||||
}
|
||||
|
||||
return blargg_ok;
|
||||
}
|
||||
|
||||
void Std_File_Reader::close()
|
||||
{
|
||||
if ( file_ )
|
||||
{
|
||||
fclose( STATIC_CAST(FILE*, file_) );
|
||||
file_ = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Gzip_File_Reader
|
||||
|
||||
#ifdef HAVE_ZLIB_H
|
||||
|
||||
#include "zlib.h"
|
||||
|
||||
static const char* get_gzip_eof( const char path [], long* eof )
|
||||
{
|
||||
FILE* file;
|
||||
RETURN_ERR( blargg_fopen( &file, path ) );
|
||||
|
||||
int const h_size = 4;
|
||||
unsigned char h [h_size];
|
||||
|
||||
// read four bytes to ensure that we can seek to -4 later
|
||||
if ( fread( h, 1, h_size, file ) != (size_t) h_size || h[0] != 0x1F || h[1] != 0x8B )
|
||||
{
|
||||
// Not gzipped
|
||||
if ( ferror( file ) )
|
||||
return blargg_err_file_io;
|
||||
|
||||
if ( fseek( file, 0, SEEK_END ) )
|
||||
return blargg_err_file_io;
|
||||
|
||||
*eof = ftell( file );
|
||||
if ( *eof < 0 )
|
||||
return blargg_err_file_io;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Gzipped; get uncompressed size from end
|
||||
if ( fseek( file, -h_size, SEEK_END ) )
|
||||
return blargg_err_file_io;
|
||||
|
||||
if ( fread( h, 1, h_size, file ) != (size_t) h_size )
|
||||
return blargg_err_file_io;
|
||||
|
||||
*eof = get_le32( h );
|
||||
}
|
||||
|
||||
if ( fclose( file ) )
|
||||
check( false );
|
||||
|
||||
return blargg_ok;
|
||||
}
|
||||
|
||||
Gzip_File_Reader::Gzip_File_Reader()
|
||||
{
|
||||
file_ = NULL;
|
||||
}
|
||||
|
||||
Gzip_File_Reader::~Gzip_File_Reader()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
blargg_err_t Gzip_File_Reader::open( const char path [] )
|
||||
{
|
||||
close();
|
||||
|
||||
long s;
|
||||
RETURN_ERR( get_gzip_eof( path, &s ) );
|
||||
|
||||
file_ = gzopen( path, "rb" );
|
||||
if ( !file_ )
|
||||
return blargg_err_file_read;
|
||||
|
||||
set_size( s );
|
||||
return blargg_ok;
|
||||
}
|
||||
|
||||
static blargg_err_t convert_gz_error( gzFile file )
|
||||
{
|
||||
int err;
|
||||
gzerror( file, &err );
|
||||
|
||||
switch ( err )
|
||||
{
|
||||
case Z_STREAM_ERROR: break;
|
||||
case Z_DATA_ERROR: return blargg_err_file_corrupt;
|
||||
case Z_MEM_ERROR: return blargg_err_memory;
|
||||
case Z_BUF_ERROR: break;
|
||||
}
|
||||
return blargg_err_internal;
|
||||
}
|
||||
|
||||
blargg_err_t Gzip_File_Reader::read_v( void* p, int s )
|
||||
{
|
||||
int result = gzread( file_, p, s );
|
||||
if ( result != s )
|
||||
{
|
||||
if ( result < 0 )
|
||||
return convert_gz_error( file_ );
|
||||
|
||||
return blargg_err_file_corrupt;
|
||||
}
|
||||
|
||||
return blargg_ok;
|
||||
}
|
||||
|
||||
blargg_err_t Gzip_File_Reader::seek_v( int n )
|
||||
{
|
||||
if ( gzseek( file_, n, SEEK_SET ) < 0 )
|
||||
return convert_gz_error( file_ );
|
||||
|
||||
return blargg_ok;
|
||||
}
|
||||
|
||||
void Gzip_File_Reader::close()
|
||||
{
|
||||
if ( file_ )
|
||||
{
|
||||
if ( gzclose( file_ ) )
|
||||
check( false );
|
||||
file_ = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,264 +0,0 @@
|
|||
// Lightweight interface for reading data from byte stream
|
||||
|
||||
// File_Extractor 1.0.0
|
||||
#ifndef DATA_READER_H
|
||||
#define DATA_READER_H
|
||||
|
||||
#include "blargg_common.h"
|
||||
|
||||
/* Some functions accept a long instead of int for convenience where caller has
|
||||
a long due to some other interface, and would otherwise have to get a warning,
|
||||
or cast it (and verify that it wasn't outside the range of an int).
|
||||
|
||||
To really support huge (>2GB) files, long isn't a solution, since there's no
|
||||
guarantee it's more than 32 bits. We'd need to use long long (if available), or
|
||||
something compiler-specific, and change all places file sizes or offsets are
|
||||
used. */
|
||||
|
||||
// Supports reading and finding out how many bytes are remaining
|
||||
class Data_Reader {
|
||||
public:
|
||||
|
||||
// Reads min(*n,remain()) bytes and sets *n to this number, thus trying to read more
|
||||
// tham remain() bytes doesn't result in error, just *n being set to remain().
|
||||
blargg_err_t read_avail( void* p, int* n );
|
||||
blargg_err_t read_avail( void* p, long* n );
|
||||
|
||||
// Reads exactly n bytes, or returns error if they couldn't ALL be read.
|
||||
// Reading past end of file results in blargg_err_file_eof.
|
||||
blargg_err_t read( void* p, int n );
|
||||
|
||||
// Number of bytes remaining until end of file
|
||||
int remain() const { return remain_; }
|
||||
|
||||
// Reads and discards n bytes. Skipping past end of file results in blargg_err_file_eof.
|
||||
blargg_err_t skip( int n );
|
||||
|
||||
virtual ~Data_Reader() { }
|
||||
|
||||
private:
|
||||
// noncopyable
|
||||
Data_Reader( const Data_Reader& );
|
||||
Data_Reader& operator = ( const Data_Reader& );
|
||||
|
||||
// Derived interface
|
||||
protected:
|
||||
Data_Reader() : remain_( 0 ) { }
|
||||
|
||||
// Sets remain
|
||||
void set_remain( int n ) { assert( n >= 0 ); remain_ = n; }
|
||||
|
||||
// Do same as read(). Guaranteed that 0 < n <= remain(). Value of remain() is updated
|
||||
// AFTER this call succeeds, not before. set_remain() should NOT be called from this.
|
||||
virtual blargg_err_t read_v( void*, int n ) BLARGG_PURE( { (void)n; return blargg_ok; } )
|
||||
|
||||
// Do same as skip(). Guaranteed that 0 < n <= remain(). Default just reads data
|
||||
// and discards it. Value of remain() is updated AFTER this call succeeds, not
|
||||
// before. set_remain() should NOT be called from this.
|
||||
virtual blargg_err_t skip_v( int n );
|
||||
|
||||
// Implementation
|
||||
public:
|
||||
BLARGG_DISABLE_NOTHROW
|
||||
|
||||
private:
|
||||
int remain_;
|
||||
};
|
||||
|
||||
|
||||
// Supports seeking in addition to Data_Reader operations
|
||||
class File_Reader : public Data_Reader {
|
||||
public:
|
||||
|
||||
// Size of file
|
||||
int size() const { return size_; }
|
||||
|
||||
// Current position in file
|
||||
int tell() const { return size_ - remain(); }
|
||||
|
||||
// Goes to new position
|
||||
blargg_err_t seek( int );
|
||||
|
||||
// Derived interface
|
||||
protected:
|
||||
// Sets size and resets position
|
||||
void set_size( int n ) { size_ = n; Data_Reader::set_remain( n ); }
|
||||
void set_size( long n ) { set_size( STATIC_CAST(int, n) ); }
|
||||
|
||||
// Sets reported position
|
||||
void set_tell( int i ) { assert( 0 <= i && i <= size_ ); Data_Reader::set_remain( size_ - i ); }
|
||||
|
||||
// Do same as seek(). Guaranteed that 0 <= n <= size(). Value of tell() is updated
|
||||
// AFTER this call succeeds, not before. set_* functions should NOT be called from this.
|
||||
virtual blargg_err_t seek_v( int n ) BLARGG_PURE( { (void)n; return blargg_ok; } )
|
||||
|
||||
// Implementation
|
||||
protected:
|
||||
File_Reader() : size_( 0 ) { }
|
||||
|
||||
virtual blargg_err_t skip_v( int );
|
||||
|
||||
private:
|
||||
int size_;
|
||||
|
||||
void set_remain(); // avoid accidental use of set_remain
|
||||
};
|
||||
|
||||
|
||||
// Reads from file on disk
|
||||
class Std_File_Reader : public File_Reader {
|
||||
public:
|
||||
|
||||
// Opens file
|
||||
blargg_err_t open( const char path [] );
|
||||
|
||||
// Closes file if one was open
|
||||
void close();
|
||||
|
||||
// Switches to unbuffered mode. Useful if buffering is already being
|
||||
// done at a higher level.
|
||||
void make_unbuffered();
|
||||
|
||||
// Implementation
|
||||
public:
|
||||
Std_File_Reader();
|
||||
virtual ~Std_File_Reader();
|
||||
|
||||
protected:
|
||||
virtual blargg_err_t read_v( void*, int );
|
||||
virtual blargg_err_t seek_v( int );
|
||||
|
||||
private:
|
||||
void* file_;
|
||||
};
|
||||
|
||||
|
||||
// Treats range of memory as a file
|
||||
class Mem_File_Reader : public File_Reader {
|
||||
public:
|
||||
|
||||
Mem_File_Reader( const void* begin, long size );
|
||||
|
||||
// Implementation
|
||||
protected:
|
||||
virtual blargg_err_t read_v( void*, int );
|
||||
virtual blargg_err_t seek_v( int );
|
||||
|
||||
private:
|
||||
const char* const begin;
|
||||
};
|
||||
|
||||
|
||||
// Allows only count bytes to be read from reader passed
|
||||
class Subset_Reader : public Data_Reader {
|
||||
public:
|
||||
|
||||
Subset_Reader( Data_Reader*, int count );
|
||||
|
||||
// Implementation
|
||||
protected:
|
||||
virtual blargg_err_t read_v( void*, int );
|
||||
|
||||
private:
|
||||
Data_Reader* const in;
|
||||
};
|
||||
|
||||
|
||||
// Joins already-read header and remaining data into original file.
|
||||
// Meant for cases where you've already read header and don't want
|
||||
// to seek and re-read data (for efficiency).
|
||||
class Remaining_Reader : public Data_Reader {
|
||||
public:
|
||||
|
||||
Remaining_Reader( void const* header, int header_size, Data_Reader* );
|
||||
|
||||
// Implementation
|
||||
protected:
|
||||
virtual blargg_err_t read_v( void*, int );
|
||||
|
||||
private:
|
||||
Data_Reader* const in;
|
||||
void const* header;
|
||||
int header_remain;
|
||||
};
|
||||
|
||||
|
||||
// Invokes callback function to read data
|
||||
extern "C" { // necessary to be usable from C
|
||||
typedef const char* (*callback_reader_func_t)(
|
||||
void* user_data, // Same value passed to constructor
|
||||
void* out, // Buffer to place data into
|
||||
int count // Number of bytes to read
|
||||
);
|
||||
}
|
||||
class Callback_Reader : public Data_Reader {
|
||||
public:
|
||||
typedef callback_reader_func_t callback_t;
|
||||
Callback_Reader( callback_t, long size, void* user_data );
|
||||
|
||||
// Implementation
|
||||
protected:
|
||||
virtual blargg_err_t read_v( void*, int );
|
||||
|
||||
private:
|
||||
callback_t const callback;
|
||||
void* const user_data;
|
||||
};
|
||||
|
||||
|
||||
// Invokes callback function to read data
|
||||
extern "C" { // necessary to be usable from C
|
||||
typedef const char* (*callback_file_reader_func_t)(
|
||||
void* user_data, // Same value passed to constructor
|
||||
void* out, // Buffer to place data into
|
||||
int count, // Number of bytes to read
|
||||
int pos // Position in file to read from
|
||||
);
|
||||
}
|
||||
class Callback_File_Reader : public File_Reader {
|
||||
public:
|
||||
typedef callback_file_reader_func_t callback_t;
|
||||
Callback_File_Reader( callback_t, long size, void* user_data );
|
||||
|
||||
// Implementation
|
||||
protected:
|
||||
virtual blargg_err_t read_v( void*, int );
|
||||
virtual blargg_err_t seek_v( int );
|
||||
|
||||
private:
|
||||
callback_t const callback;
|
||||
void* const user_data;
|
||||
};
|
||||
|
||||
|
||||
#ifdef HAVE_ZLIB_H
|
||||
|
||||
// Reads file compressed with gzip (or uncompressed)
|
||||
class Gzip_File_Reader : public File_Reader {
|
||||
public:
|
||||
|
||||
// Opens possibly gzipped file
|
||||
blargg_err_t open( const char path [] );
|
||||
|
||||
// Closes file if one was open
|
||||
void close();
|
||||
|
||||
// Implementation
|
||||
public:
|
||||
Gzip_File_Reader();
|
||||
~Gzip_File_Reader();
|
||||
|
||||
protected:
|
||||
virtual blargg_err_t read_v( void*, int );
|
||||
virtual blargg_err_t seek_v( int );
|
||||
|
||||
private:
|
||||
// void* so "zlib.h" doesn't have to be included here
|
||||
void* file_;
|
||||
};
|
||||
#endif
|
||||
|
||||
char* blargg_to_utf8( const wchar_t* );
|
||||
wchar_t* blargg_to_wide( const char* );
|
||||
|
||||
#endif
|
|
@ -1,341 +0,0 @@
|
|||
// File_Extractor 1.0.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "File_Extractor.h"
|
||||
|
||||
/* Copyright (C) 2005-2009 Shay Green. This module is free software; you
|
||||
can redistribute it and/or modify it under the terms of the GNU Lesser
|
||||
General Public License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version. This
|
||||
module is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
details. You should have received a copy of the GNU Lesser General Public
|
||||
License along with this module; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
#include "blargg_source.h"
|
||||
|
||||
File_Extractor::fex_t( fex_type_t t ) :
|
||||
type_( t )
|
||||
{
|
||||
own_file_ = NULL;
|
||||
|
||||
close_();
|
||||
}
|
||||
|
||||
// Open
|
||||
|
||||
blargg_err_t File_Extractor::set_path( const char* path )
|
||||
{
|
||||
if ( !path )
|
||||
path = "";
|
||||
|
||||
RETURN_ERR( path_.resize( strlen( path ) + 1 ) );
|
||||
memcpy( path_.begin(), path, path_.size() );
|
||||
return blargg_ok;
|
||||
}
|
||||
|
||||
blargg_err_t File_Extractor::open( const char path [] )
|
||||
{
|
||||
close();
|
||||
|
||||
RETURN_ERR( set_path( path ) );
|
||||
|
||||
blargg_err_t err = open_path_v();
|
||||
if ( err )
|
||||
close();
|
||||
else
|
||||
opened_ = true;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
blargg_err_t File_Extractor::open_path_v()
|
||||
{
|
||||
RETURN_ERR( open_arc_file() );
|
||||
|
||||
return open_v();
|
||||
}
|
||||
|
||||
inline
|
||||
static void make_unbuffered( Std_File_Reader* r )
|
||||
{
|
||||
r->make_unbuffered();
|
||||
}
|
||||
|
||||
inline
|
||||
static void make_unbuffered( void* )
|
||||
{ }
|
||||
|
||||
blargg_err_t File_Extractor::open_arc_file( bool unbuffered )
|
||||
{
|
||||
if ( reader_ )
|
||||
return blargg_ok;
|
||||
|
||||
FEX_FILE_READER* in = BLARGG_NEW FEX_FILE_READER;
|
||||
CHECK_ALLOC( in );
|
||||
|
||||
blargg_err_t err = in->open( arc_path() );
|
||||
if ( err )
|
||||
{
|
||||
delete in;
|
||||
}
|
||||
else
|
||||
{
|
||||
reader_ = in;
|
||||
own_file();
|
||||
if ( unbuffered )
|
||||
make_unbuffered( in );
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
blargg_err_t File_Extractor::open( File_Reader* input, const char* path )
|
||||
{
|
||||
close();
|
||||
|
||||
RETURN_ERR( set_path( path ) );
|
||||
|
||||
RETURN_ERR( input->seek( 0 ) );
|
||||
|
||||
reader_ = input;
|
||||
blargg_err_t err = open_v();
|
||||
if ( err )
|
||||
close();
|
||||
else
|
||||
opened_ = true;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
// Close
|
||||
|
||||
void File_Extractor::close()
|
||||
{
|
||||
close_v();
|
||||
close_();
|
||||
}
|
||||
|
||||
void File_Extractor::close_()
|
||||
{
|
||||
delete own_file_;
|
||||
own_file_ = NULL;
|
||||
|
||||
tell_ = 0;
|
||||
reader_ = NULL;
|
||||
opened_ = false;
|
||||
|
||||
path_.clear();
|
||||
clear_file();
|
||||
}
|
||||
|
||||
File_Extractor::~fex_t()
|
||||
{
|
||||
check( !opened() ); // fails if derived destructor didn't call close()
|
||||
|
||||
delete own_file_;
|
||||
}
|
||||
|
||||
// Scanning
|
||||
|
||||
void File_Extractor::clear_file()
|
||||
{
|
||||
name_ = NULL;
|
||||
wname_ = NULL;
|
||||
done_ = true;
|
||||
stat_called = false;
|
||||
data_ptr_ = NULL;
|
||||
|
||||
set_info( 0 );
|
||||
own_data_.clear();
|
||||
clear_file_v();
|
||||
}
|
||||
|
||||
void File_Extractor::set_name( const char new_name [], const wchar_t* new_wname )
|
||||
{
|
||||
name_ = new_name;
|
||||
wname_ = new_wname;
|
||||
done_ = false;
|
||||
}
|
||||
|
||||
void File_Extractor::set_info( int new_size, unsigned date, unsigned crc )
|
||||
{
|
||||
size_ = new_size;
|
||||
date_ = (date != 0xFFFFFFFF ? date : 0);
|
||||
crc32_ = crc;
|
||||
set_remain( new_size );
|
||||
}
|
||||
|
||||
blargg_err_t File_Extractor::next_()
|
||||
{
|
||||
tell_++;
|
||||
clear_file();
|
||||
|
||||
blargg_err_t err = next_v();
|
||||
if ( err )
|
||||
clear_file();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
blargg_err_t File_Extractor::next()
|
||||
{
|
||||
assert( !done() );
|
||||
return next_();
|
||||
}
|
||||
|
||||
blargg_err_t File_Extractor::rewind()
|
||||
{
|
||||
assert( opened() );
|
||||
|
||||
tell_ = 0;
|
||||
clear_file();
|
||||
|
||||
blargg_err_t err = rewind_v();
|
||||
if ( err )
|
||||
clear_file();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
blargg_err_t File_Extractor::stat()
|
||||
{
|
||||
assert( !done() );
|
||||
|
||||
if ( !stat_called )
|
||||
{
|
||||
RETURN_ERR( stat_v() );
|
||||
stat_called = true;
|
||||
}
|
||||
return blargg_ok;
|
||||
}
|
||||
|
||||
// Tell/seek
|
||||
|
||||
int const pos_offset = 1;
|
||||
|
||||
fex_pos_t File_Extractor::tell_arc() const
|
||||
{
|
||||
assert( opened() );
|
||||
|
||||
fex_pos_t pos = tell_arc_v();
|
||||
assert( pos >= 0 );
|
||||
|
||||
return pos + pos_offset;
|
||||
}
|
||||
|
||||
blargg_err_t File_Extractor::seek_arc( fex_pos_t pos )
|
||||
{
|
||||
assert( opened() );
|
||||
assert( pos != 0 );
|
||||
|
||||
clear_file();
|
||||
|
||||
blargg_err_t err = seek_arc_v( pos - pos_offset );
|
||||
if ( err )
|
||||
clear_file();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
fex_pos_t File_Extractor::tell_arc_v() const
|
||||
{
|
||||
return tell_;
|
||||
}
|
||||
|
||||
blargg_err_t File_Extractor::seek_arc_v( fex_pos_t pos )
|
||||
{
|
||||
// >= because seeking to current file should always reset read pointer etc.
|
||||
if ( tell_ >= pos )
|
||||
RETURN_ERR( rewind() );
|
||||
|
||||
while ( tell_ < pos )
|
||||
{
|
||||
RETURN_ERR( next_() );
|
||||
|
||||
if ( done() )
|
||||
{
|
||||
assert( false );
|
||||
return blargg_err_caller;
|
||||
}
|
||||
}
|
||||
|
||||
assert( tell_ == pos );
|
||||
|
||||
return blargg_ok;
|
||||
}
|
||||
|
||||
// Extraction
|
||||
|
||||
blargg_err_t File_Extractor::rewind_file()
|
||||
{
|
||||
RETURN_ERR( stat() );
|
||||
|
||||
if ( tell() > 0 )
|
||||
{
|
||||
if ( data_ptr_ )
|
||||
{
|
||||
set_remain( size() );
|
||||
}
|
||||
else
|
||||
{
|
||||
RETURN_ERR( seek_arc( tell_arc() ) );
|
||||
RETURN_ERR( stat() );
|
||||
}
|
||||
}
|
||||
|
||||
return blargg_ok;
|
||||
}
|
||||
|
||||
blargg_err_t File_Extractor::data( const void** data_out )
|
||||
{
|
||||
assert( !done() );
|
||||
|
||||
*data_out = NULL;
|
||||
if ( !data_ptr_ )
|
||||
{
|
||||
int old_tell = tell();
|
||||
|
||||
RETURN_ERR( rewind_file() );
|
||||
|
||||
void const* ptr;
|
||||
RETURN_ERR( data_v( &ptr ) );
|
||||
data_ptr_ = ptr;
|
||||
|
||||
// Now that data is in memory, we can seek by simply setting remain
|
||||
set_remain( size() - old_tell );
|
||||
}
|
||||
|
||||
*data_out = data_ptr_;
|
||||
return blargg_ok;
|
||||
}
|
||||
|
||||
blargg_err_t File_Extractor::data_v( void const** out )
|
||||
{
|
||||
RETURN_ERR( own_data_.resize( size() ) );
|
||||
*out = own_data_.begin();
|
||||
|
||||
blargg_err_t err = extract_v( own_data_.begin(), own_data_.size() );
|
||||
if ( err )
|
||||
own_data_.clear();
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
blargg_err_t File_Extractor::extract_v( void* out, int count )
|
||||
{
|
||||
void const* p;
|
||||
RETURN_ERR( data( &p ) );
|
||||
memcpy( out, STATIC_CAST(char const*,p) + (size() - remain()), count );
|
||||
|
||||
return blargg_ok;
|
||||
}
|
||||
|
||||
blargg_err_t File_Extractor::read_v( void* out, int count )
|
||||
{
|
||||
if ( data_ptr_ )
|
||||
return File_Extractor::extract_v( out, count );
|
||||
|
||||
return extract_v( out, count );
|
||||
}
|
|
@ -1,191 +0,0 @@
|
|||
// Compressed file archive interface
|
||||
|
||||
// File_Extractor 1.0.0
|
||||
#ifndef FILE_EXTRACTOR_H
|
||||
#define FILE_EXTRACTOR_H
|
||||
|
||||
#include "blargg_common.h"
|
||||
#include "Data_Reader.h"
|
||||
#include "fex.h"
|
||||
|
||||
struct fex_t : private Data_Reader {
|
||||
public:
|
||||
virtual ~fex_t();
|
||||
|
||||
// Open/close
|
||||
|
||||
// Opens archive from custom data source. Keeps pointer until close().
|
||||
blargg_err_t open( File_Reader* input, const char* path = NULL );
|
||||
|
||||
// Takes ownership of File_Reader* passed to open(), so that close()
|
||||
// will delete it.
|
||||
void own_file() { own_file_ = reader_; }
|
||||
|
||||
// See fex.h
|
||||
blargg_err_t open( const char path [] );
|
||||
fex_type_t type() const { return type_; }
|
||||
void close();
|
||||
|
||||
// Scanning
|
||||
|
||||
// See fex.h
|
||||
bool done() const { return done_; }
|
||||
blargg_err_t next();
|
||||
blargg_err_t rewind();
|
||||
fex_pos_t tell_arc() const;
|
||||
blargg_err_t seek_arc( fex_pos_t );
|
||||
|
||||
// Info
|
||||
|
||||
// See fex.h
|
||||
const char* name() const { return name_; }
|
||||
const wchar_t* wname() const { return wname_; }
|
||||
blargg_err_t stat();
|
||||
int size() const { assert( stat_called ); return size_; }
|
||||
unsigned int dos_date() const { return date_; }
|
||||
unsigned int crc32() const { return crc32_; }
|
||||
|
||||
// Extraction
|
||||
|
||||
// Data_Reader to current file's data, so standard Data_Reader interface can
|
||||
// be used, rather than having to treat archives specially. stat() must have
|
||||
// been called.
|
||||
Data_Reader& reader() { assert( stat_called ); return *this; }
|
||||
|
||||
// See fex.h
|
||||
blargg_err_t data( const void** data_out );
|
||||
int tell() const { return size_ - remain(); }
|
||||
|
||||
// Derived interface
|
||||
protected:
|
||||
|
||||
// Sets type of object
|
||||
fex_t( fex_type_t );
|
||||
|
||||
// Path to archive file, or "" if none supplied
|
||||
const char* arc_path() const { return path_.begin(); }
|
||||
|
||||
// Opens archive file if it's not already. If unbuffered is true, opens file
|
||||
// without any buffering.
|
||||
blargg_err_t open_arc_file( bool unbuffered = false );
|
||||
|
||||
// Archive file
|
||||
File_Reader& arc() const { return *reader_; }
|
||||
|
||||
// Sets current file name
|
||||
void set_name( const char name [], const wchar_t* wname = NULL );
|
||||
|
||||
// Sets current file information
|
||||
void set_info( int size, unsigned date = 0, unsigned crc = 0 );
|
||||
|
||||
// User overrides
|
||||
|
||||
// Overrides must do indicated task. Non-pure functions have reasonable default
|
||||
// implementation. Overrides should avoid calling public functions like
|
||||
// next() and rewind().
|
||||
|
||||
// Open archive using file_path(). OK to delay actual file opening until later.
|
||||
// Default just calls open_arc_file(), then open_v().
|
||||
virtual blargg_err_t open_path_v();
|
||||
|
||||
// Open archive using file() for source data. If unsupported, return error.
|
||||
virtual blargg_err_t open_v() BLARGG_PURE( ; )
|
||||
|
||||
// Go to next file in archive and call set_name() and optionally set_info()
|
||||
virtual blargg_err_t next_v() BLARGG_PURE( ; )
|
||||
|
||||
// Go back to first file in archive
|
||||
virtual blargg_err_t rewind_v() BLARGG_PURE( ; )
|
||||
|
||||
// Close archive. Called even if open_path_v() or open_v() return unsuccessfully.
|
||||
virtual void close_v() BLARGG_PURE( ; )
|
||||
|
||||
// Clear any fields related to current file
|
||||
virtual void clear_file_v() { }
|
||||
|
||||
// Call set_info() if not already called by next_v()
|
||||
virtual blargg_err_t stat_v() { return blargg_ok; }
|
||||
|
||||
// Return value that allows later return to this file. Result must be >= 0.
|
||||
virtual fex_pos_t tell_arc_v() const;
|
||||
|
||||
// Return to previously saved position
|
||||
virtual blargg_err_t seek_arc_v( fex_pos_t );
|
||||
|
||||
// One or both of the following must be overridden
|
||||
|
||||
// Provide pointer to data for current file in archive
|
||||
virtual blargg_err_t data_v( const void** out );
|
||||
|
||||
// Extract next n bytes
|
||||
virtual blargg_err_t extract_v( void* out, int n );
|
||||
|
||||
// Implementation
|
||||
public:
|
||||
BLARGG_DISABLE_NOTHROW
|
||||
|
||||
private:
|
||||
fex_type_t const type_;
|
||||
|
||||
// Archive file
|
||||
blargg_vector<char> path_;
|
||||
File_Reader* reader_;
|
||||
File_Reader* own_file_;
|
||||
bool opened_;
|
||||
|
||||
// Position in archive
|
||||
fex_pos_t tell_; // only used by default implementation of tell/seek
|
||||
bool done_;
|
||||
|
||||
// Info for current file in archive
|
||||
const char* name_;
|
||||
const wchar_t* wname_;
|
||||
unsigned date_;
|
||||
unsigned crc32_;
|
||||
int size_;
|
||||
bool stat_called;
|
||||
|
||||
// Current file contents
|
||||
void const* data_ptr_; // NULL if not read into memory
|
||||
blargg_vector<char> own_data_;
|
||||
|
||||
bool opened() const { return opened_; }
|
||||
void clear_file();
|
||||
void close_();
|
||||
blargg_err_t set_path( const char* path );
|
||||
blargg_err_t rewind_file();
|
||||
blargg_err_t next_();
|
||||
|
||||
// Data_Reader overrides
|
||||
// TODO: override skip_v?
|
||||
virtual blargg_err_t read_v( void* out, int n );
|
||||
};
|
||||
|
||||
struct fex_type_t_
|
||||
{
|
||||
const char* extension;
|
||||
File_Extractor* (*new_fex)();
|
||||
const char* name;
|
||||
blargg_err_t (*init)(); // Called by fex_init(). Can be NULL.
|
||||
};
|
||||
|
||||
extern const fex_type_t_
|
||||
fex_7z_type [1],
|
||||
fex_gz_type [1],
|
||||
fex_rar_type [1],
|
||||
fex_zip_type [1],
|
||||
fex_bin_type [1];
|
||||
|
||||
inline blargg_err_t File_Extractor::open_v() { return blargg_ok; }
|
||||
inline blargg_err_t File_Extractor::next_v() { return blargg_ok; }
|
||||
inline blargg_err_t File_Extractor::rewind_v() { return blargg_ok; }
|
||||
inline void File_Extractor::close_v() { }
|
||||
|
||||
// Default to Std_File_Reader for archive access
|
||||
#ifndef FEX_FILE_READER
|
||||
#define FEX_FILE_READER Std_File_Reader
|
||||
#elif defined (FEX_FILE_READER_INCLUDE)
|
||||
#include FEX_FILE_READER_INCLUDE
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,98 +0,0 @@
|
|||
// File_Extractor 1.0.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "Gzip_Extractor.h"
|
||||
|
||||
/* Copyright (C) 2005-2009 Shay Green. This module is free software; you
|
||||
can redistribute it and/or modify it under the terms of the GNU Lesser
|
||||
General Public License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version. This
|
||||
module is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
details. You should have received a copy of the GNU Lesser General Public
|
||||
License along with this module; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
#include "blargg_source.h"
|
||||
|
||||
// TODO: could close file once data has been read into memory
|
||||
|
||||
static blargg_err_t init_gzip_file()
|
||||
{
|
||||
get_crc_table(); // initialize zlib's CRC-32 tables
|
||||
return blargg_ok;
|
||||
}
|
||||
|
||||
static File_Extractor* new_gzip()
|
||||
{
|
||||
return BLARGG_NEW Gzip_Extractor;
|
||||
}
|
||||
|
||||
fex_type_t_ const fex_gz_type [1] = {{
|
||||
".gz",
|
||||
&new_gzip,
|
||||
"gzipped file",
|
||||
&init_gzip_file
|
||||
}};
|
||||
|
||||
Gzip_Extractor::Gzip_Extractor() :
|
||||
File_Extractor( fex_gz_type )
|
||||
{ }
|
||||
|
||||
Gzip_Extractor::~Gzip_Extractor()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
blargg_err_t Gzip_Extractor::open_path_v()
|
||||
{
|
||||
// skip opening file
|
||||
return open_v();
|
||||
}
|
||||
|
||||
blargg_err_t Gzip_Extractor::stat_v()
|
||||
{
|
||||
RETURN_ERR( open_arc_file( true ) );
|
||||
if ( !gr.opened() || gr.tell() != 0 )
|
||||
RETURN_ERR( gr.open( &arc() ) );
|
||||
|
||||
set_info( gr.remain(), 0, gr.crc32() );
|
||||
return blargg_ok;
|
||||
}
|
||||
|
||||
blargg_err_t Gzip_Extractor::open_v()
|
||||
{
|
||||
// Remove .gz suffix
|
||||
size_t len = strlen( arc_path() );
|
||||
if ( fex_has_extension( arc_path(), ".gz" ) )
|
||||
len -= 3;
|
||||
|
||||
RETURN_ERR( name.resize( len + 1 ) );
|
||||
memcpy( name.begin(), arc_path(), name.size() );
|
||||
name [name.size() - 1] = '\0';
|
||||
|
||||
set_name( name.begin() );
|
||||
return blargg_ok;
|
||||
}
|
||||
|
||||
void Gzip_Extractor::close_v()
|
||||
{
|
||||
name.clear();
|
||||
gr.close();
|
||||
}
|
||||
|
||||
blargg_err_t Gzip_Extractor::next_v()
|
||||
{
|
||||
return blargg_ok;
|
||||
}
|
||||
|
||||
blargg_err_t Gzip_Extractor::rewind_v()
|
||||
{
|
||||
set_name( name.begin() );
|
||||
return blargg_ok;
|
||||
}
|
||||
|
||||
blargg_err_t Gzip_Extractor::extract_v( void* p, int n )
|
||||
{
|
||||
return gr.read( p, n );
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
// Presents a gzipped file as an "archive" of just that file.
|
||||
// Also handles non-gzipped files.
|
||||
|
||||
// File_Extractor 1.0.0
|
||||
#ifndef GZIP_EXTRACTOR_H
|
||||
#define GZIP_EXTRACTOR_H
|
||||
|
||||
#include "File_Extractor.h"
|
||||
#include "Gzip_Reader.h"
|
||||
|
||||
class Gzip_Extractor : public File_Extractor {
|
||||
public:
|
||||
Gzip_Extractor();
|
||||
virtual ~Gzip_Extractor();
|
||||
|
||||
protected:
|
||||
virtual blargg_err_t open_path_v();
|
||||
virtual blargg_err_t open_v();
|
||||
virtual void close_v();
|
||||
|
||||
virtual blargg_err_t next_v();
|
||||
virtual blargg_err_t rewind_v();
|
||||
|
||||
virtual blargg_err_t stat_v();
|
||||
virtual blargg_err_t extract_v( void*, int );
|
||||
|
||||
private:
|
||||
Gzip_Reader gr;
|
||||
blargg_vector<char> name;
|
||||
|
||||
void set_info_();
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,85 +0,0 @@
|
|||
// File_Extractor 1.0.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "Gzip_Reader.h"
|
||||
|
||||
#include "blargg_endian.h"
|
||||
|
||||
/* Copyright (C) 2006-2009 Shay Green. This module is free software; you
|
||||
can redistribute it and/or modify it under the terms of the GNU Lesser
|
||||
General Public License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version. This
|
||||
module is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
details. You should have received a copy of the GNU Lesser General Public
|
||||
License along with this module; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
#include "blargg_source.h"
|
||||
|
||||
Gzip_Reader::Gzip_Reader()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
Gzip_Reader::~Gzip_Reader()
|
||||
{ }
|
||||
|
||||
static blargg_err_t gzip_reader_read( void* file, void* out, int* count )
|
||||
{
|
||||
return STATIC_CAST(File_Reader*,file)->read_avail( out, count );
|
||||
}
|
||||
|
||||
blargg_err_t Gzip_Reader::calc_size()
|
||||
{
|
||||
size_ = in->size();
|
||||
crc32_ = 0;
|
||||
if ( inflater.deflated() )
|
||||
{
|
||||
byte trailer [8];
|
||||
int old_pos = in->tell();
|
||||
RETURN_ERR( in->seek( size_ - sizeof trailer ) );
|
||||
RETURN_ERR( in->read( trailer, sizeof trailer ) );
|
||||
RETURN_ERR( in->seek( old_pos ) );
|
||||
crc32_ = get_le32( trailer + 0 );
|
||||
|
||||
unsigned n = get_le32( trailer + 4 );
|
||||
if ( n > INT_MAX )
|
||||
return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "gzip larger than 2GB" );
|
||||
|
||||
size_ = n;
|
||||
}
|
||||
return blargg_ok;
|
||||
}
|
||||
|
||||
blargg_err_t Gzip_Reader::open( File_Reader* new_in )
|
||||
{
|
||||
close();
|
||||
|
||||
in = new_in;
|
||||
RETURN_ERR( in->seek( 0 ) );
|
||||
RETURN_ERR( inflater.begin( gzip_reader_read, new_in ) );
|
||||
RETURN_ERR( inflater.set_mode( inflater.mode_auto ) );
|
||||
RETURN_ERR( calc_size() );
|
||||
set_remain( size_ );
|
||||
|
||||
return blargg_ok;
|
||||
}
|
||||
|
||||
void Gzip_Reader::close()
|
||||
{
|
||||
in = NULL;
|
||||
inflater.end();
|
||||
}
|
||||
|
||||
blargg_err_t Gzip_Reader::read_v( void* out, int count )
|
||||
{
|
||||
assert( in );
|
||||
int actual = count;
|
||||
RETURN_ERR( inflater.read( out, &actual ) );
|
||||
|
||||
if ( actual != count )
|
||||
return blargg_err_file_corrupt;
|
||||
|
||||
return blargg_ok;
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
// Transparently decompresses gzip files, as well as uncompressed
|
||||
|
||||
// File_Extractor 1.0.0
|
||||
#ifndef GZIP_READER_H
|
||||
#define GZIP_READER_H
|
||||
|
||||
#include "Data_Reader.h"
|
||||
#include "Zlib_Inflater.h"
|
||||
|
||||
class Gzip_Reader : public Data_Reader {
|
||||
public:
|
||||
// Keeps pointer to reader until close(). If
|
||||
blargg_err_t open( File_Reader* );
|
||||
|
||||
// True if file is open
|
||||
bool opened() const { return in != NULL; }
|
||||
|
||||
// Frees memory
|
||||
void close();
|
||||
|
||||
// True if file is compressed
|
||||
bool deflated() const { return inflater.deflated(); }
|
||||
|
||||
// CRC-32 of data, of 0 if unavailable
|
||||
unsigned int crc32() const { return crc32_; }
|
||||
|
||||
// Number of bytes read since opening
|
||||
int tell() const { return size_ - remain(); }
|
||||
|
||||
public:
|
||||
Gzip_Reader();
|
||||
virtual ~Gzip_Reader();
|
||||
|
||||
protected:
|
||||
virtual blargg_err_t read_v( void*, int );
|
||||
|
||||
private:
|
||||
File_Reader* in;
|
||||
unsigned crc32_;
|
||||
int size_;
|
||||
Zlib_Inflater inflater;
|
||||
|
||||
blargg_err_t calc_size();
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,197 +0,0 @@
|
|||
// File_Extractor 1.0.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "blargg_common.h"
|
||||
|
||||
#if FEX_ENABLE_RAR
|
||||
|
||||
#include "Rar_Extractor.h"
|
||||
|
||||
/* Copyright (C) 2009 Shay Green. This module is free software; you
|
||||
can redistribute it and/or modify it under the terms of the GNU Lesser
|
||||
General Public License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version. This
|
||||
module is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
details. You should have received a copy of the GNU Lesser General Public
|
||||
License along with this module; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
#include "blargg_source.h"
|
||||
|
||||
static blargg_err_t init_rar()
|
||||
{
|
||||
unrar_init();
|
||||
return blargg_ok;
|
||||
}
|
||||
|
||||
static File_Extractor* new_rar()
|
||||
{
|
||||
return BLARGG_NEW Rar_Extractor;
|
||||
}
|
||||
|
||||
fex_type_t_ const fex_rar_type [1] = {{
|
||||
".rar",
|
||||
&new_rar,
|
||||
"RAR archive",
|
||||
&init_rar
|
||||
}};
|
||||
|
||||
blargg_err_t Rar_Extractor::convert_err( unrar_err_t err )
|
||||
{
|
||||
blargg_err_t reader_err = reader.err;
|
||||
reader.err = blargg_ok;
|
||||
if ( reader_err )
|
||||
check( err == unrar_next_err );
|
||||
|
||||
switch ( err )
|
||||
{
|
||||
case unrar_ok: return blargg_ok;
|
||||
case unrar_err_memory: return blargg_err_memory;
|
||||
case unrar_err_open: return blargg_err_file_read;
|
||||
case unrar_err_not_arc: return blargg_err_file_type;
|
||||
case unrar_err_corrupt: return blargg_err_file_corrupt;
|
||||
case unrar_err_io: return blargg_err_file_io;
|
||||
case unrar_err_arc_eof: return blargg_err_internal;
|
||||
case unrar_err_encrypted: return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "RAR encryption not supported" );
|
||||
case unrar_err_segmented: return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "RAR segmentation not supported" );
|
||||
case unrar_err_huge: return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "Huge RAR files not supported" );
|
||||
case unrar_err_old_algo: return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "Old RAR compression not supported" );
|
||||
case unrar_err_new_algo: return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "RAR uses unknown newer compression" );
|
||||
case unrar_next_err: break;
|
||||
default:
|
||||
check( false ); // unhandled RAR error
|
||||
}
|
||||
|
||||
if ( reader_err )
|
||||
return reader_err;
|
||||
|
||||
check( false );
|
||||
return BLARGG_ERR( BLARGG_ERR_INTERNAL, "RAR archive" );
|
||||
}
|
||||
|
||||
static inline unrar_err_t handle_err( Rar_Extractor::read_callback_t* h, blargg_err_t err )
|
||||
{
|
||||
if ( !err )
|
||||
return unrar_ok;
|
||||
|
||||
h->err = err;
|
||||
return unrar_next_err;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
{
|
||||
static unrar_err_t my_unrar_read( void* data, void* out, int* count, unrar_pos_t pos )
|
||||
{
|
||||
// TODO: 64-bit file support
|
||||
|
||||
Rar_Extractor::read_callback_t* h = STATIC_CAST(Rar_Extractor::read_callback_t*,data);
|
||||
if ( h->pos != pos )
|
||||
{
|
||||
blargg_err_t err = h->in->seek( pos );
|
||||
if ( err )
|
||||
return handle_err( h, err );
|
||||
|
||||
h->pos = pos;
|
||||
}
|
||||
|
||||
blargg_err_t err = h->in->read_avail( out, count );
|
||||
if ( err )
|
||||
return handle_err( h, err );
|
||||
|
||||
h->pos += *count;
|
||||
|
||||
return unrar_ok;
|
||||
}
|
||||
}
|
||||
|
||||
Rar_Extractor::Rar_Extractor() :
|
||||
File_Extractor( fex_rar_type )
|
||||
{
|
||||
unrar = NULL;
|
||||
}
|
||||
|
||||
Rar_Extractor::~Rar_Extractor()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
blargg_err_t Rar_Extractor::open_v()
|
||||
{
|
||||
reader.pos = 0;
|
||||
reader.in = &arc();
|
||||
reader.err = blargg_ok;
|
||||
|
||||
RETURN_ERR( arc().seek( 0 ) );
|
||||
RETURN_ERR( convert_err( unrar_open_custom( &unrar, &my_unrar_read, &reader ) ) );
|
||||
return skip_unextractables();
|
||||
}
|
||||
|
||||
void Rar_Extractor::close_v()
|
||||
{
|
||||
unrar_close( unrar );
|
||||
|
||||
unrar = NULL;
|
||||
reader.in = NULL;
|
||||
}
|
||||
|
||||
blargg_err_t Rar_Extractor::skip_unextractables()
|
||||
{
|
||||
while ( !unrar_done( unrar ) && unrar_try_extract( unrar ) )
|
||||
RETURN_ERR( next_raw() );
|
||||
|
||||
if ( !unrar_done( unrar ) )
|
||||
{
|
||||
unrar_info_t const* info = unrar_info( unrar );
|
||||
|
||||
set_name( info->name, (info->name_w && *info->name_w) ? info->name_w : NULL );
|
||||
set_info( info->size, info->dos_date, (info->is_crc32 ? info->crc : 0) );
|
||||
}
|
||||
|
||||
return blargg_ok;
|
||||
}
|
||||
|
||||
blargg_err_t Rar_Extractor::next_raw()
|
||||
{
|
||||
return convert_err( unrar_next( unrar ) );
|
||||
}
|
||||
|
||||
blargg_err_t Rar_Extractor::next_v()
|
||||
{
|
||||
RETURN_ERR( next_raw() );
|
||||
return skip_unextractables();
|
||||
}
|
||||
|
||||
blargg_err_t Rar_Extractor::rewind_v()
|
||||
{
|
||||
RETURN_ERR( convert_err( unrar_rewind( unrar ) ) );
|
||||
return skip_unextractables();
|
||||
}
|
||||
|
||||
fex_pos_t Rar_Extractor::tell_arc_v() const
|
||||
{
|
||||
return unrar_tell( unrar );
|
||||
}
|
||||
|
||||
blargg_err_t Rar_Extractor::seek_arc_v( fex_pos_t pos )
|
||||
{
|
||||
RETURN_ERR( convert_err( unrar_seek( unrar, pos ) ) );
|
||||
return skip_unextractables();
|
||||
}
|
||||
|
||||
blargg_err_t Rar_Extractor::data_v( void const** out )
|
||||
{
|
||||
return convert_err( unrar_extract_mem( unrar, out ) );
|
||||
}
|
||||
|
||||
blargg_err_t Rar_Extractor::extract_v( void* out, int count )
|
||||
{
|
||||
// We can read entire file directly into user buffer
|
||||
if ( count == size() )
|
||||
return convert_err( unrar_extract( unrar, out, count ) );
|
||||
|
||||
// This will call data_v() and copy from that buffer for us
|
||||
return File_Extractor::extract_v( out, count );
|
||||
}
|
||||
|
||||
#endif
|
|
@ -1,43 +0,0 @@
|
|||
// RAR archive extractor
|
||||
|
||||
// File_Extractor 1.0.0
|
||||
#ifndef RAR_EXTRACTOR_H
|
||||
#define RAR_EXTRACTOR_H
|
||||
|
||||
#include "File_Extractor.h"
|
||||
#include "unrar/unrar.h"
|
||||
|
||||
class Rar_Extractor : public File_Extractor {
|
||||
public:
|
||||
Rar_Extractor();
|
||||
virtual ~Rar_Extractor();
|
||||
|
||||
struct read_callback_t
|
||||
{
|
||||
const char* err;
|
||||
int pos;
|
||||
File_Reader* in;
|
||||
};
|
||||
|
||||
protected:
|
||||
virtual blargg_err_t open_v();
|
||||
virtual void close_v();
|
||||
|
||||
virtual blargg_err_t next_v();
|
||||
virtual blargg_err_t rewind_v();
|
||||
virtual fex_pos_t tell_arc_v() const;
|
||||
virtual blargg_err_t seek_arc_v( fex_pos_t );
|
||||
|
||||
virtual blargg_err_t data_v( void const** );
|
||||
virtual blargg_err_t extract_v( void*, int );
|
||||
|
||||
private:
|
||||
unrar_t* unrar;
|
||||
read_callback_t reader;
|
||||
|
||||
blargg_err_t convert_err( unrar_err_t );
|
||||
blargg_err_t skip_unextractables();
|
||||
blargg_err_t next_raw();
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,252 +0,0 @@
|
|||
// File_Extractor 1.0.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "Zip7_Extractor.h"
|
||||
|
||||
#include "7z_C/7zExtract.h"
|
||||
#include "7z_C/7zAlloc.h"
|
||||
#include "7z_C/7zCrc.h"
|
||||
|
||||
/* Copyright (C) 2005-2009 Shay Green. This module is free software; you
|
||||
can redistribute it and/or modify it under the terms of the GNU Lesser
|
||||
General Public License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version. This
|
||||
module is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
details. You should have received a copy of the GNU Lesser General Public
|
||||
License along with this module; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
#include "blargg_source.h"
|
||||
|
||||
static ISzAlloc zip7_alloc = { SzAlloc, SzFree };
|
||||
static ISzAlloc zip7_alloc_temp = { SzAllocTemp, SzFreeTemp };
|
||||
|
||||
struct Zip7_Extractor_Impl :
|
||||
ISeekInStream
|
||||
{
|
||||
CLookToRead look;
|
||||
CSzArEx db;
|
||||
|
||||
// SzExtract state
|
||||
UInt32 block_index;
|
||||
Byte* buf;
|
||||
size_t buf_size;
|
||||
|
||||
File_Reader* in;
|
||||
const char* in_err;
|
||||
};
|
||||
|
||||
extern "C"
|
||||
{
|
||||
// 7-zip callbacks pass an ISeekInStream* for data, so we must cast it
|
||||
// back to ISeekInStream* FIRST, then cast to our Impl structure
|
||||
|
||||
static SRes zip7_read_( void* vstream, void* out, size_t* size )
|
||||
{
|
||||
assert( out && size );
|
||||
ISeekInStream* stream = STATIC_CAST(ISeekInStream*,vstream);
|
||||
Zip7_Extractor_Impl* impl = STATIC_CAST(Zip7_Extractor_Impl*,stream);
|
||||
|
||||
long lsize = *size;
|
||||
blargg_err_t err = impl->in->read_avail( out, &lsize );
|
||||
if ( err )
|
||||
{
|
||||
*size = 0;
|
||||
impl->in_err = err;
|
||||
return SZ_ERROR_READ;
|
||||
}
|
||||
|
||||
*size = lsize;
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
static SRes zip7_seek_( void* vstream, Int64* pos, ESzSeek mode )
|
||||
{
|
||||
ISeekInStream* stream = STATIC_CAST(ISeekInStream*,vstream);
|
||||
Zip7_Extractor_Impl* impl = STATIC_CAST(Zip7_Extractor_Impl*,stream);
|
||||
|
||||
assert( mode != SZ_SEEK_CUR ); // never used
|
||||
|
||||
if ( mode == SZ_SEEK_END )
|
||||
{
|
||||
assert( *pos == 0 ); // only used to find file length
|
||||
*pos = impl->in->size();
|
||||
return SZ_OK;
|
||||
}
|
||||
|
||||
assert( mode == SZ_SEEK_SET );
|
||||
blargg_err_t err = impl->in->seek( *pos );
|
||||
if ( err )
|
||||
{
|
||||
// don't set in_err in this case, since it might be benign
|
||||
if ( err == blargg_err_file_eof )
|
||||
return SZ_ERROR_INPUT_EOF;
|
||||
|
||||
impl->in_err = err;
|
||||
return SZ_ERROR_READ;
|
||||
}
|
||||
|
||||
return SZ_OK;
|
||||
}
|
||||
}
|
||||
|
||||
blargg_err_t Zip7_Extractor::zip7_err( int err )
|
||||
{
|
||||
// TODO: ignore in_err in some cases? unsure about which error to use
|
||||
blargg_err_t in_err = impl->in_err;
|
||||
impl->in_err = NULL;
|
||||
if ( in_err )
|
||||
{
|
||||
check( err != SZ_OK );
|
||||
return in_err;
|
||||
}
|
||||
|
||||
switch ( err )
|
||||
{
|
||||
case SZ_OK: return blargg_ok;
|
||||
case SZ_ERROR_MEM: return blargg_err_memory;
|
||||
case SZ_ERROR_READ: return blargg_err_file_io;
|
||||
case SZ_ERROR_CRC:
|
||||
case SZ_ERROR_DATA:
|
||||
case SZ_ERROR_INPUT_EOF:
|
||||
case SZ_ERROR_ARCHIVE: return blargg_err_file_corrupt;
|
||||
case SZ_ERROR_UNSUPPORTED: return blargg_err_file_feature;
|
||||
case SZ_ERROR_NO_ARCHIVE: return blargg_err_file_type;
|
||||
}
|
||||
|
||||
return blargg_err_generic;
|
||||
}
|
||||
|
||||
static blargg_err_t init_7z()
|
||||
{
|
||||
static bool inited;
|
||||
if ( !inited )
|
||||
{
|
||||
inited = true;
|
||||
CrcGenerateTable();
|
||||
}
|
||||
return blargg_ok;
|
||||
}
|
||||
|
||||
static File_Extractor* new_7z()
|
||||
{
|
||||
return BLARGG_NEW Zip7_Extractor;
|
||||
}
|
||||
|
||||
fex_type_t_ const fex_7z_type [1] = {{
|
||||
".7z",
|
||||
&new_7z,
|
||||
"7-zip archive",
|
||||
&init_7z
|
||||
}};
|
||||
|
||||
Zip7_Extractor::Zip7_Extractor() :
|
||||
File_Extractor( fex_7z_type )
|
||||
{
|
||||
impl = NULL;
|
||||
}
|
||||
|
||||
Zip7_Extractor::~Zip7_Extractor()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
blargg_err_t Zip7_Extractor::open_v()
|
||||
{
|
||||
RETURN_ERR( init_7z() );
|
||||
|
||||
if ( !impl )
|
||||
{
|
||||
impl = (Zip7_Extractor_Impl*) malloc( sizeof *impl );
|
||||
CHECK_ALLOC( impl );
|
||||
}
|
||||
|
||||
impl->in = &arc();
|
||||
impl->block_index = (UInt32) -1;
|
||||
impl->buf = NULL;
|
||||
impl->buf_size = 0;
|
||||
|
||||
LookToRead_CreateVTable( &impl->look, false );
|
||||
impl->ISeekInStream::Read = zip7_read_;
|
||||
impl->ISeekInStream::Seek = zip7_seek_;
|
||||
impl->look.realStream = impl;
|
||||
LookToRead_Init( &impl->look );
|
||||
|
||||
SzArEx_Init( &impl->db );
|
||||
|
||||
impl->in_err = NULL;
|
||||
RETURN_ERR( zip7_err( SzArEx_Open( &impl->db, &impl->look.s,
|
||||
&zip7_alloc, &zip7_alloc_temp ) ) );
|
||||
|
||||
return seek_arc_v( 0 );
|
||||
}
|
||||
|
||||
void Zip7_Extractor::close_v()
|
||||
{
|
||||
if ( impl )
|
||||
{
|
||||
if ( impl->in )
|
||||
{
|
||||
impl->in = NULL;
|
||||
SzArEx_Free( &impl->db, &zip7_alloc );
|
||||
}
|
||||
IAlloc_Free( &zip7_alloc, impl->buf );
|
||||
free( impl );
|
||||
impl = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
blargg_err_t Zip7_Extractor::next_v()
|
||||
{
|
||||
while ( ++index < (int) impl->db.db.NumFiles )
|
||||
{
|
||||
CSzFileItem const& item = impl->db.db.Files [index];
|
||||
if ( !item.IsDir )
|
||||
{
|
||||
// TODO: Support date.
|
||||
// NTFS representation, stored as 64-bit value.
|
||||
// Divide by 10000000 (ten million) to get seconds
|
||||
//item.MTime.Low + (.High << 32)
|
||||
// How to convert to DOS style?
|
||||
|
||||
set_name( item.Name );
|
||||
set_info( item.Size, 0, (item.FileCRCDefined ? item.FileCRC : 0) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return blargg_ok;
|
||||
}
|
||||
|
||||
blargg_err_t Zip7_Extractor::rewind_v()
|
||||
{
|
||||
return seek_arc_v( 0 );
|
||||
}
|
||||
|
||||
fex_pos_t Zip7_Extractor::tell_arc_v() const
|
||||
{
|
||||
return index;
|
||||
}
|
||||
|
||||
blargg_err_t Zip7_Extractor::seek_arc_v( fex_pos_t pos )
|
||||
{
|
||||
assert( 0 <= pos && pos <= (int) impl->db.db.NumFiles );
|
||||
|
||||
index = pos - 1;
|
||||
return next_v();
|
||||
}
|
||||
|
||||
blargg_err_t Zip7_Extractor::data_v( void const** out )
|
||||
{
|
||||
impl->in_err = NULL;
|
||||
size_t offset = 0;
|
||||
size_t count = 0;
|
||||
RETURN_ERR( zip7_err( SzAr_Extract( &impl->db, &impl->look.s, index,
|
||||
&impl->block_index, &impl->buf, &impl->buf_size,
|
||||
&offset, &count, &zip7_alloc, &zip7_alloc_temp ) ) );
|
||||
assert( count == (size_t) size() );
|
||||
|
||||
*out = impl->buf + offset;
|
||||
return blargg_ok;
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
// 7-zip archive extractor
|
||||
|
||||
// File_Extractor 1.0.0
|
||||
#ifndef ZIP7_EXTRACTOR_H
|
||||
#define ZIP7_EXTRACTOR_H
|
||||
|
||||
#include "File_Extractor.h"
|
||||
|
||||
struct Zip7_Extractor_Impl;
|
||||
|
||||
class Zip7_Extractor : public File_Extractor {
|
||||
public:
|
||||
Zip7_Extractor();
|
||||
virtual ~Zip7_Extractor();
|
||||
|
||||
protected:
|
||||
virtual blargg_err_t open_v();
|
||||
virtual void close_v();
|
||||
|
||||
virtual blargg_err_t next_v();
|
||||
virtual blargg_err_t rewind_v();
|
||||
virtual fex_pos_t tell_arc_v() const;
|
||||
virtual blargg_err_t seek_arc_v( fex_pos_t );
|
||||
|
||||
virtual blargg_err_t data_v( void const** out );
|
||||
|
||||
private:
|
||||
Zip7_Extractor_Impl* impl;
|
||||
int index;
|
||||
|
||||
blargg_err_t zip7_err( int err );
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,390 +0,0 @@
|
|||
// File_Extractor 1.0.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "Zip_Extractor.h"
|
||||
|
||||
#include "blargg_endian.h"
|
||||
|
||||
/* Copyright (C) 2005-2009 Shay Green. This module is free software; you
|
||||
can redistribute it and/or modify it under the terms of the GNU Lesser
|
||||
General Public License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version. This
|
||||
module is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
details. You should have received a copy of the GNU Lesser General Public
|
||||
License along with this module; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
/* To avoid copying filename string from catalog, I terminate it by modifying
|
||||
catalog data. This potentially requires moving the first byte of the type
|
||||
of the next entry elsewhere; I move it to the first byte of made_by. Kind
|
||||
of hacky, but I'd rather not have to allocate memory for a copy of it. */
|
||||
|
||||
#include "blargg_source.h"
|
||||
|
||||
/* Reads this much from end of file when first opening. Only this much is
|
||||
searched for the end catalog entry. If whole catalog is within this data,
|
||||
nothing more needs to be read on open. */
|
||||
int const end_read_size = 8 * 1024;
|
||||
|
||||
/* Reads are are made using file offset that's a multiple of this,
|
||||
increasing performance. */
|
||||
int const disk_block_size = 4 * 1024;
|
||||
|
||||
// Read buffer used for extracting file data
|
||||
int const read_buf_size = 16 * 1024;
|
||||
|
||||
struct header_t
|
||||
{
|
||||
char type [4];
|
||||
byte vers [2];
|
||||
byte flags [2];
|
||||
byte method [2];
|
||||
byte date [4];
|
||||
byte crc [4];
|
||||
byte raw_size [4];
|
||||
byte size [4];
|
||||
byte filename_len [2];
|
||||
byte extra_len [2];
|
||||
char filename [2]; // [filename_len]
|
||||
//char extra [extra_len];
|
||||
};
|
||||
int const header_size = 30;
|
||||
|
||||
struct entry_t
|
||||
{
|
||||
char type [4];
|
||||
byte made_by [2];
|
||||
byte vers [2];
|
||||
byte flags [2];
|
||||
byte method [2];
|
||||
byte date [4];
|
||||
byte crc [4];
|
||||
byte raw_size [4];
|
||||
byte size [4];
|
||||
byte filename_len [2];
|
||||
byte extra_len [2];
|
||||
byte comment_len [2];
|
||||
byte disk [2];
|
||||
byte int_attrib [2];
|
||||
byte ext_attrib [4];
|
||||
byte file_offset [4];
|
||||
char filename [2]; // [filename_len]
|
||||
//char extra [extra_len];
|
||||
//char comment [comment_len];
|
||||
};
|
||||
int const entry_size = 46;
|
||||
|
||||
struct end_entry_t
|
||||
{
|
||||
char type [4];
|
||||
byte disk [2];
|
||||
byte first_disk [2];
|
||||
byte disk_entry_count [2];
|
||||
byte entry_count [2];
|
||||
byte dir_size [4];
|
||||
byte dir_offset [4];
|
||||
byte comment_len [2];
|
||||
char comment [2]; // [comment_len]
|
||||
};
|
||||
int const end_entry_size = 22;
|
||||
|
||||
static blargg_err_t init_zip()
|
||||
{
|
||||
get_crc_table(); // initialize zlib's CRC-32 tables
|
||||
return blargg_ok;
|
||||
}
|
||||
|
||||
static File_Extractor* new_zip()
|
||||
{
|
||||
return BLARGG_NEW Zip_Extractor;
|
||||
}
|
||||
|
||||
fex_type_t_ const fex_zip_type [1] = {{
|
||||
".zip",
|
||||
&new_zip,
|
||||
"ZIP archive",
|
||||
&init_zip
|
||||
}};
|
||||
|
||||
Zip_Extractor::Zip_Extractor() :
|
||||
File_Extractor( fex_zip_type )
|
||||
{
|
||||
Zip_Extractor::clear_file_v();
|
||||
|
||||
// If these fail, structures had extra padding inserted by compiler
|
||||
assert( offsetof (header_t,filename) == header_size );
|
||||
assert( offsetof (entry_t,filename) == entry_size );
|
||||
assert( offsetof (end_entry_t,comment) == end_entry_size );
|
||||
}
|
||||
|
||||
Zip_Extractor::~Zip_Extractor()
|
||||
{
|
||||
close();
|
||||
}
|
||||
|
||||
blargg_err_t Zip_Extractor::open_path_v()
|
||||
{
|
||||
RETURN_ERR( open_arc_file( true ) );
|
||||
return File_Extractor::open_path_v();
|
||||
}
|
||||
|
||||
inline
|
||||
void Zip_Extractor::reorder_entry_header( int offset )
|
||||
{
|
||||
catalog [offset + 0] = 0;
|
||||
catalog [offset + 4] = 'P';
|
||||
}
|
||||
|
||||
blargg_err_t Zip_Extractor::open_v()
|
||||
{
|
||||
if ( arc().size() < end_entry_size )
|
||||
return blargg_err_file_type;
|
||||
|
||||
// Read final end_read_size bytes of file
|
||||
int file_pos = max( 0, arc().size() - end_read_size );
|
||||
file_pos -= file_pos % disk_block_size;
|
||||
RETURN_ERR( catalog.resize( arc().size() - file_pos ) );
|
||||
RETURN_ERR( arc().seek( file_pos ) );
|
||||
RETURN_ERR( arc().read( catalog.begin(), catalog.size() ) );
|
||||
|
||||
// Find end-of-catalog entry
|
||||
int end_pos = catalog.size() - end_entry_size;
|
||||
while ( end_pos >= 0 && memcmp( &catalog [end_pos], "PK\5\6", 4 ) )
|
||||
end_pos--;
|
||||
if ( end_pos < 0 )
|
||||
return blargg_err_file_type;
|
||||
end_entry_t const& end_entry = (end_entry_t&) catalog [end_pos];
|
||||
end_pos += file_pos;
|
||||
|
||||
// some idiotic zip compressors add data to end of zip without setting comment len
|
||||
// check( arc().size() == end_pos + end_entry_size + get_le16( end_entry.comment_len ) );
|
||||
|
||||
// Find file offset of beginning of catalog
|
||||
catalog_begin = get_le32( end_entry.dir_offset );
|
||||
int catalog_size = end_pos - catalog_begin;
|
||||
if ( catalog_size < 0 )
|
||||
return blargg_err_file_corrupt;
|
||||
catalog_size += end_entry_size;
|
||||
|
||||
// See if catalog is entirely contained in bytes already read
|
||||
int begin_offset = catalog_begin - file_pos;
|
||||
if ( begin_offset >= 0 )
|
||||
memmove( catalog.begin(), &catalog [begin_offset], catalog_size );
|
||||
|
||||
RETURN_ERR( catalog.resize( catalog_size ) );
|
||||
if ( begin_offset < 0 )
|
||||
{
|
||||
// Catalog begins before bytes read, so it needs to be read
|
||||
RETURN_ERR( arc().seek( catalog_begin ) );
|
||||
RETURN_ERR( arc().read( catalog.begin(), catalog.size() ) );
|
||||
}
|
||||
|
||||
// First entry in catalog should be a file or end of archive
|
||||
if ( memcmp( catalog.begin(), "PK\1\2", 4 ) && memcmp( catalog.begin(), "PK\5\6", 4 ) )
|
||||
return blargg_err_file_type;
|
||||
|
||||
reorder_entry_header( 0 );
|
||||
return rewind_v();
|
||||
}
|
||||
|
||||
void Zip_Extractor::close_v()
|
||||
{
|
||||
catalog.clear();
|
||||
}
|
||||
|
||||
// Scanning
|
||||
|
||||
inline
|
||||
static bool is_normal_file( entry_t const& e, unsigned len )
|
||||
{
|
||||
int last_char = (len ? e.filename [len - 1] : '/');
|
||||
bool is_dir = (last_char == '/' || last_char == '\\');
|
||||
if ( is_dir && get_le32( e.size ) == 0 )
|
||||
return false;
|
||||
check( !is_dir );
|
||||
|
||||
// Mac OS X puts meta-information in separate files with normal extensions,
|
||||
// so they must be filtered out or caller will mistake them for normal files.
|
||||
if ( e.made_by[1] == 3 )
|
||||
{
|
||||
const char* dir = strrchr( e.filename, '/' );
|
||||
if ( dir )
|
||||
dir++;
|
||||
else
|
||||
dir = e.filename;
|
||||
|
||||
if ( *dir == '.' )
|
||||
return false;
|
||||
|
||||
if ( !strcmp( dir, "Icon\x0D" ) )
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
blargg_err_t Zip_Extractor::update_info( bool advance_first )
|
||||
{
|
||||
while ( 1 )
|
||||
{
|
||||
entry_t& e = (entry_t&) catalog [catalog_pos];
|
||||
|
||||
if ( memcmp( e.type, "\0K\1\2P", 5 ) && memcmp( e.type, "PK\1\2", 4 ) )
|
||||
{
|
||||
check( !memcmp( e.type, "\0K\5\6P", 5 ) );
|
||||
break;
|
||||
}
|
||||
|
||||
unsigned len = get_le16( e.filename_len );
|
||||
int next_offset = catalog_pos + entry_size + len + get_le16( e.extra_len ) +
|
||||
get_le16( e.comment_len );
|
||||
if ( (unsigned) next_offset > catalog.size() - end_entry_size )
|
||||
return blargg_err_file_corrupt;
|
||||
|
||||
if ( catalog [next_offset] == 'P' )
|
||||
reorder_entry_header( next_offset );
|
||||
|
||||
if ( !advance_first )
|
||||
{
|
||||
e.filename [len] = 0; // terminate name
|
||||
|
||||
if ( is_normal_file( e, len ) )
|
||||
{
|
||||
set_name( e.filename );
|
||||
set_info( get_le32( e.size ), get_le32( e.date ), get_le32( e.crc ) );
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
catalog_pos = next_offset;
|
||||
advance_first = false;
|
||||
}
|
||||
|
||||
return blargg_ok;
|
||||
}
|
||||
|
||||
blargg_err_t Zip_Extractor::next_v()
|
||||
{
|
||||
return update_info( true );
|
||||
}
|
||||
|
||||
blargg_err_t Zip_Extractor::rewind_v()
|
||||
{
|
||||
return seek_arc_v( 0 );
|
||||
}
|
||||
|
||||
fex_pos_t Zip_Extractor::tell_arc_v() const
|
||||
{
|
||||
return catalog_pos;
|
||||
}
|
||||
|
||||
blargg_err_t Zip_Extractor::seek_arc_v( fex_pos_t pos )
|
||||
{
|
||||
assert( 0 <= pos && (size_t) pos <= catalog.size() - end_entry_size );
|
||||
|
||||
catalog_pos = pos;
|
||||
return update_info( false );
|
||||
}
|
||||
|
||||
// Reading
|
||||
|
||||
void Zip_Extractor::clear_file_v()
|
||||
{
|
||||
buf.end();
|
||||
}
|
||||
|
||||
blargg_err_t Zip_Extractor::inflater_read( void* data, void* out, int* count )
|
||||
{
|
||||
Zip_Extractor& self = *STATIC_CAST(Zip_Extractor*,data);
|
||||
|
||||
if ( *count > self.raw_remain )
|
||||
*count = self.raw_remain;
|
||||
|
||||
self.raw_remain -= *count;
|
||||
|
||||
return self.arc().read( out, *count );
|
||||
}
|
||||
|
||||
blargg_err_t Zip_Extractor::fill_buf( int offset, int buf_size, int initial_read )
|
||||
{
|
||||
raw_remain = arc().size() - offset;
|
||||
RETURN_ERR( arc().seek( offset ) );
|
||||
return buf.begin( inflater_read, this, buf_size, initial_read );
|
||||
}
|
||||
|
||||
blargg_err_t Zip_Extractor::first_read( int count )
|
||||
{
|
||||
entry_t const& e = (entry_t&) catalog [catalog_pos];
|
||||
|
||||
// Determine compression
|
||||
{
|
||||
int method = get_le16( e.method );
|
||||
if ( (method && method != Z_DEFLATED) || get_le16( e.vers ) > 20 )
|
||||
return BLARGG_ERR( BLARGG_ERR_FILE_FEATURE, "compression method" );
|
||||
file_deflated = (method != 0);
|
||||
}
|
||||
|
||||
int raw_size = get_le32( e.raw_size );
|
||||
|
||||
int file_offset = get_le32( e.file_offset );
|
||||
int align = file_offset % disk_block_size;
|
||||
{
|
||||
// read header
|
||||
int buf_size = 3 * disk_block_size - 1 + raw_size; // space for all raw data
|
||||
buf_size -= buf_size % disk_block_size;
|
||||
int initial_read = buf_size;
|
||||
if ( !file_deflated || count < size() )
|
||||
{
|
||||
buf_size = read_buf_size;
|
||||
initial_read = disk_block_size * 2;
|
||||
}
|
||||
// TODO: avoid re-reading if buffer already has data we want?
|
||||
RETURN_ERR( fill_buf( file_offset - align, buf_size, initial_read ) );
|
||||
}
|
||||
header_t const& h = (header_t&) buf.data() [align];
|
||||
if ( buf.filled() < align + header_size || memcmp( h.type, "PK\3\4", 4 ) )
|
||||
return blargg_err_file_corrupt;
|
||||
|
||||
// CRCs of header and file data
|
||||
correct_crc = get_le32( h.crc );
|
||||
if ( !correct_crc )
|
||||
correct_crc = get_le32( e.crc );
|
||||
check( correct_crc == get_le32( e.crc ) ); // catalog CRC should match
|
||||
crc = ::crc32( 0, NULL, 0 );
|
||||
|
||||
// Data offset
|
||||
int data_offset = file_offset + header_size +
|
||||
get_le16( h.filename_len ) + get_le16( h.extra_len );
|
||||
if ( data_offset + raw_size > catalog_begin )
|
||||
return blargg_err_file_corrupt;
|
||||
|
||||
// Refill buffer if there's lots of extra data after header
|
||||
int buf_offset = data_offset - file_offset + align;
|
||||
if ( buf_offset > buf.filled() )
|
||||
{
|
||||
// TODO: this will almost never occur, making it a good place for bugs
|
||||
buf_offset = data_offset % disk_block_size;
|
||||
RETURN_ERR( fill_buf( data_offset - buf_offset, read_buf_size, disk_block_size ) );
|
||||
}
|
||||
|
||||
raw_remain = raw_size - (buf.filled() - buf_offset);
|
||||
return buf.set_mode( (file_deflated ? buf.mode_raw_deflate : buf.mode_copy), buf_offset );
|
||||
}
|
||||
|
||||
blargg_err_t Zip_Extractor::extract_v( void* out, int count )
|
||||
{
|
||||
if ( tell() == 0 )
|
||||
RETURN_ERR( first_read( count ) );
|
||||
|
||||
int actual = count;
|
||||
RETURN_ERR( buf.read( out, &actual ) );
|
||||
if ( actual < count )
|
||||
return blargg_err_file_corrupt;
|
||||
|
||||
crc = ::crc32( crc, (byte const*) out, count );
|
||||
if ( count == reader().remain() && crc != correct_crc )
|
||||
return blargg_err_file_corrupt;
|
||||
|
||||
return blargg_ok;
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
// ZIP archive extractor. Only supports deflation and store (no compression).
|
||||
|
||||
// File_Extractor 1.0.0
|
||||
#ifndef ZIP_EXTRACTOR_H
|
||||
#define ZIP_EXTRACTOR_H
|
||||
|
||||
#include "File_Extractor.h"
|
||||
#include "Zlib_Inflater.h"
|
||||
|
||||
class Zip_Extractor : public File_Extractor {
|
||||
public:
|
||||
Zip_Extractor();
|
||||
virtual ~Zip_Extractor();
|
||||
|
||||
protected:
|
||||
virtual blargg_err_t open_path_v();
|
||||
virtual blargg_err_t open_v();
|
||||
virtual void close_v();
|
||||
|
||||
virtual void clear_file_v();
|
||||
virtual blargg_err_t next_v();
|
||||
virtual blargg_err_t rewind_v();
|
||||
virtual fex_pos_t tell_arc_v() const;
|
||||
virtual blargg_err_t seek_arc_v( fex_pos_t );
|
||||
|
||||
virtual blargg_err_t extract_v( void*, int );
|
||||
|
||||
private:
|
||||
blargg_vector<char> catalog;
|
||||
int catalog_begin; // offset of first catalog entry in file (to detect corruption)
|
||||
int catalog_pos; // position of current entry in catalog
|
||||
int raw_remain; // bytes remaining to be read from zip file for current file
|
||||
unsigned crc; // ongoing CRC of extracted bytes
|
||||
unsigned correct_crc;
|
||||
bool file_deflated;
|
||||
Zlib_Inflater buf;
|
||||
|
||||
blargg_err_t fill_buf( int offset, int buf_size, int initial_read );
|
||||
blargg_err_t update_info( bool advance_first );
|
||||
blargg_err_t first_read( int count );
|
||||
void reorder_entry_header( int offset );
|
||||
static blargg_err_t inflater_read( void* data, void* out, int* count );
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,257 +0,0 @@
|
|||
// File_Extractor 1.0.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "Zlib_Inflater.h"
|
||||
|
||||
/* Copyright (C) 2006-2009 Shay Green. This module is free software; you
|
||||
can redistribute it and/or modify it under the terms of the GNU Lesser
|
||||
General Public License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version. This
|
||||
module is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
details. You should have received a copy of the GNU Lesser General Public
|
||||
License along with this module; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
#include "blargg_source.h"
|
||||
|
||||
int const block_size = 4096;
|
||||
|
||||
static const char* get_zlib_err( int code )
|
||||
{
|
||||
assert( code != Z_OK );
|
||||
switch ( code )
|
||||
{
|
||||
case Z_MEM_ERROR: return blargg_err_memory;
|
||||
case Z_DATA_ERROR: return blargg_err_file_corrupt;
|
||||
// TODO: handle more error codes
|
||||
}
|
||||
|
||||
const char* str = zError( code );
|
||||
if ( !str )
|
||||
str = BLARGG_ERR( BLARGG_ERR_GENERIC, "problem unzipping data" );
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
void Zlib_Inflater::end()
|
||||
{
|
||||
if ( deflated_ )
|
||||
{
|
||||
deflated_ = false;
|
||||
if ( inflateEnd( &zbuf ) )
|
||||
check( false );
|
||||
}
|
||||
buf.clear();
|
||||
|
||||
static z_stream const empty = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
memcpy( &zbuf, &empty, sizeof zbuf );
|
||||
}
|
||||
|
||||
Zlib_Inflater::Zlib_Inflater()
|
||||
{
|
||||
deflated_ = false;
|
||||
end(); // initialize things
|
||||
}
|
||||
|
||||
Zlib_Inflater::~Zlib_Inflater()
|
||||
{
|
||||
end();
|
||||
}
|
||||
|
||||
blargg_err_t Zlib_Inflater::fill_buf( int count )
|
||||
{
|
||||
byte* out = buf.end() - count;
|
||||
RETURN_ERR( callback( user_data, out, &count ) );
|
||||
zbuf.avail_in = count;
|
||||
zbuf.next_in = out;
|
||||
return blargg_ok;
|
||||
}
|
||||
|
||||
blargg_err_t Zlib_Inflater::begin( callback_t new_callback, void* new_user_data,
|
||||
int new_buf_size, int initial_read )
|
||||
{
|
||||
callback = new_callback;
|
||||
user_data = new_user_data;
|
||||
|
||||
end();
|
||||
|
||||
// TODO: decide whether using different size on alloc failure is a good idea
|
||||
//RETURN_ERR( buf.resize( new_buf_size ? new_buf_size : 4 * block_size ) );
|
||||
if ( new_buf_size && buf.resize( new_buf_size ) )
|
||||
{
|
||||
ACK_FAILURE();
|
||||
new_buf_size = 0;
|
||||
}
|
||||
|
||||
if ( !new_buf_size )
|
||||
{
|
||||
RETURN_ERR( buf.resize( 4 * block_size ) );
|
||||
initial_read = 0;
|
||||
}
|
||||
|
||||
// Fill buffer with some data, less than normal buffer size since caller might
|
||||
// just be examining beginning of file.
|
||||
return fill_buf( initial_read ? initial_read : block_size );
|
||||
}
|
||||
|
||||
blargg_err_t Zlib_Inflater::set_mode( mode_t mode, int data_offset )
|
||||
{
|
||||
zbuf.next_in += data_offset;
|
||||
zbuf.avail_in -= data_offset;
|
||||
|
||||
if ( mode == mode_auto )
|
||||
{
|
||||
// examine buffer for gzip header
|
||||
mode = mode_copy;
|
||||
unsigned const min_gzip_size = 2 + 8 + 8;
|
||||
if ( zbuf.avail_in >= min_gzip_size &&
|
||||
zbuf.next_in [0] == 0x1F && zbuf.next_in [1] == 0x8B )
|
||||
mode = mode_ungz;
|
||||
}
|
||||
|
||||
if ( mode != mode_copy )
|
||||
{
|
||||
int wb = MAX_WBITS + 16; // have zlib handle gzip header
|
||||
if ( mode == mode_raw_deflate )
|
||||
wb = -MAX_WBITS;
|
||||
|
||||
int zerr = inflateInit2( &zbuf, wb );
|
||||
if ( zerr )
|
||||
{
|
||||
zbuf.next_in = NULL;
|
||||
return get_zlib_err( zerr );
|
||||
}
|
||||
|
||||
deflated_ = true;
|
||||
}
|
||||
return blargg_ok;
|
||||
}
|
||||
|
||||
/*
|
||||
// Reads/inflates entire stream. All input must be in buffer, and count must be total
|
||||
// of all output.
|
||||
blargg_err_t read_all( void* out, int count );
|
||||
|
||||
|
||||
// zlib automatically applies this optimization (uses inflateFast)
|
||||
// TODO: remove
|
||||
blargg_err_t Zlib_Inflater::read_all( void* out, int count )
|
||||
{
|
||||
if ( deflated_ )
|
||||
{
|
||||
zbuf.next_out = (Bytef*) out;
|
||||
zbuf.avail_out = count;
|
||||
|
||||
int err = inflate( &zbuf, Z_FINISH );
|
||||
|
||||
if ( zbuf.avail_out || err != Z_STREAM_END )
|
||||
return blargg_err_file_corrupt;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( zbuf.avail_in < count )
|
||||
return blargg_err_file_corrupt;
|
||||
|
||||
memcpy( out, zbuf.next_in, count );
|
||||
|
||||
zbuf.next_in += count;
|
||||
zbuf.avail_in -= count;
|
||||
}
|
||||
|
||||
return blargg_ok;
|
||||
}
|
||||
*/
|
||||
|
||||
blargg_err_t Zlib_Inflater::read( void* out, int* count_io )
|
||||
{
|
||||
int remain = *count_io;
|
||||
if ( remain && zbuf.next_in )
|
||||
{
|
||||
if ( deflated_ )
|
||||
{
|
||||
zbuf.next_out = (Bytef*) out;
|
||||
zbuf.avail_out = remain;
|
||||
|
||||
while ( 1 )
|
||||
{
|
||||
uInt old_avail_in = zbuf.avail_in;
|
||||
int err = inflate( &zbuf, Z_NO_FLUSH );
|
||||
if ( err == Z_STREAM_END )
|
||||
{
|
||||
remain = zbuf.avail_out;
|
||||
end();
|
||||
break; // no more data to inflate
|
||||
}
|
||||
|
||||
if ( err && (err != Z_BUF_ERROR || old_avail_in) )
|
||||
return get_zlib_err( err );
|
||||
|
||||
if ( !zbuf.avail_out )
|
||||
{
|
||||
remain = 0;
|
||||
break; // requested number of bytes inflated
|
||||
}
|
||||
|
||||
if ( zbuf.avail_in )
|
||||
{
|
||||
// inflate() should never leave input if there's still space for output
|
||||
check( false );
|
||||
return blargg_err_file_corrupt;
|
||||
}
|
||||
|
||||
RETURN_ERR( fill_buf( buf.size() ) );
|
||||
if ( !zbuf.avail_in )
|
||||
return blargg_err_file_corrupt; // stream didn't end but there's no more data
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while ( 1 )
|
||||
{
|
||||
// copy buffered data
|
||||
if ( zbuf.avail_in )
|
||||
{
|
||||
long count = zbuf.avail_in;
|
||||
if ( count > remain )
|
||||
count = remain;
|
||||
memcpy( out, zbuf.next_in, count );
|
||||
zbuf.total_out += count;
|
||||
out = (char*) out + count;
|
||||
remain -= count;
|
||||
zbuf.next_in += count;
|
||||
zbuf.avail_in -= count;
|
||||
}
|
||||
|
||||
if ( !zbuf.avail_in && zbuf.next_in < buf.end() )
|
||||
{
|
||||
end();
|
||||
break;
|
||||
}
|
||||
|
||||
// read large request directly
|
||||
if ( remain + zbuf.total_out % block_size >= buf.size() )
|
||||
{
|
||||
int count = remain;
|
||||
RETURN_ERR( callback( user_data, out, &count ) );
|
||||
zbuf.total_out += count;
|
||||
out = (char*) out + count;
|
||||
remain -= count;
|
||||
|
||||
if ( remain )
|
||||
{
|
||||
end();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( !remain )
|
||||
break;
|
||||
|
||||
RETURN_ERR( fill_buf( buf.size() - zbuf.total_out % block_size ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
*count_io -= remain;
|
||||
return blargg_ok;
|
||||
}
|
|
@ -1,70 +0,0 @@
|
|||
// Simplifies use of zlib for inflating data
|
||||
|
||||
// File_Extractor 1.0.0
|
||||
#ifndef ZLIB_INFLATER_H
|
||||
#define ZLIB_INFLATER_H
|
||||
|
||||
#include "blargg_common.h"
|
||||
#include "Data_Reader.h"
|
||||
#include "zlib/zlib.h"
|
||||
|
||||
class Zlib_Inflater {
|
||||
public:
|
||||
|
||||
// Reads at most min(*count,bytes_until_eof()) bytes into *out and set *count
|
||||
// to that number, or returns error if that many can't be read.
|
||||
typedef blargg_err_t (*callback_t)( void* user_data, void* out, int* count );
|
||||
|
||||
// Begins by setting callback and filling buffer. Default buffer is 16K and
|
||||
// filled to 4K, or specify buf_size and initial_read for custom buffer size
|
||||
// and how much to read initially.
|
||||
blargg_err_t begin( callback_t, void* user_data,
|
||||
int buf_size = 0, int initial_read = 0 );
|
||||
|
||||
// Data read into buffer by begin()
|
||||
const unsigned char* data() const { return zbuf.next_in; }
|
||||
int filled() const { return zbuf.avail_in; }
|
||||
|
||||
// Begins inflation using specified mode. Using mode_auto selects between
|
||||
// mode_copy and mode_ungz by examining first two bytes of buffer. Use
|
||||
// buf_offset to specify where data begins in buffer, in case there is
|
||||
// header data that should be skipped.
|
||||
enum mode_t { mode_copy, mode_ungz, mode_raw_deflate, mode_auto };
|
||||
blargg_err_t set_mode( mode_t, int buf_offset = 0 );
|
||||
|
||||
// True if set_mode() has been called with mode_ungz or mode_raw_deflate
|
||||
bool deflated() const { return deflated_; }
|
||||
|
||||
// Reads/inflates at most *count_io bytes into *out and sets *count_io to actual
|
||||
// number of bytes read (less than requested if end of data was reached).
|
||||
// Buffers source data internally, even in copy mode, so input file can be
|
||||
// unbuffered without sacrificing performance.
|
||||
blargg_err_t read( void* out, int* count_io );
|
||||
|
||||
// Total number of bytes read since begin()
|
||||
int tell() const { return zbuf.total_out; }
|
||||
|
||||
// Ends inflation and frees memory
|
||||
void end();
|
||||
|
||||
private:
|
||||
// noncopyable
|
||||
Zlib_Inflater( const Zlib_Inflater& );
|
||||
Zlib_Inflater& operator = ( const Zlib_Inflater& );
|
||||
|
||||
// Implementation
|
||||
public:
|
||||
Zlib_Inflater();
|
||||
~Zlib_Inflater();
|
||||
|
||||
private:
|
||||
z_stream_s zbuf;
|
||||
blargg_vector<unsigned char> buf;
|
||||
bool deflated_;
|
||||
callback_t callback;
|
||||
void* user_data;
|
||||
|
||||
blargg_err_t fill_buf( int count );
|
||||
};
|
||||
|
||||
#endif
|
|
@ -1,51 +0,0 @@
|
|||
// File_Extractor 1.0.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "blargg_common.h"
|
||||
|
||||
/* Copyright (C) 2008-2009 Shay Green. This module is free software; you
|
||||
can redistribute it and/or modify it under the terms of the GNU Lesser
|
||||
General Public License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version. This
|
||||
module is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
details. You should have received a copy of the GNU Lesser General Public
|
||||
License along with this module; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
#include "blargg_source.h"
|
||||
|
||||
void blargg_vector_::init()
|
||||
{
|
||||
begin_ = NULL;
|
||||
size_ = 0;
|
||||
}
|
||||
|
||||
void blargg_vector_::clear()
|
||||
{
|
||||
void* p = begin_;
|
||||
begin_ = NULL;
|
||||
size_ = 0;
|
||||
free( p );
|
||||
}
|
||||
|
||||
blargg_err_t blargg_vector_::resize_( size_t n, size_t elem_size )
|
||||
{
|
||||
if ( n != size_ )
|
||||
{
|
||||
if ( n == 0 )
|
||||
{
|
||||
// Simpler to handle explicitly. Realloc will handle a size of 0,
|
||||
// but then we have to avoid raising an error for a NULL return.
|
||||
clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
void* p = realloc( begin_, n * elem_size );
|
||||
CHECK_ALLOC( p );
|
||||
begin_ = p;
|
||||
size_ = n;
|
||||
}
|
||||
}
|
||||
return blargg_ok;
|
||||
}
|
|
@ -1,206 +0,0 @@
|
|||
// Sets up common environment for Shay Green's libraries.
|
||||
// To change configuration options, modify blargg_config.h, not this file.
|
||||
|
||||
// File_Extractor 1.0.0
|
||||
#ifndef BLARGG_COMMON_H
|
||||
#define BLARGG_COMMON_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
|
||||
typedef const char* blargg_err_t; // 0 on success, otherwise error string
|
||||
|
||||
// Success; no error
|
||||
int const blargg_ok = 0;
|
||||
|
||||
// BLARGG_RESTRICT: equivalent to C99's restrict, where supported
|
||||
#if __GNUC__ >= 3 || _MSC_VER >= 1100
|
||||
#define BLARGG_RESTRICT __restrict
|
||||
#else
|
||||
#define BLARGG_RESTRICT
|
||||
#endif
|
||||
|
||||
#if __cplusplus >= 199711
|
||||
#define BLARGG_MUTABLE mutable
|
||||
#else
|
||||
#define BLARGG_MUTABLE
|
||||
#endif
|
||||
|
||||
/* BLARGG_4CHAR('a','b','c','d') = 'abcd' (four character integer constant).
|
||||
I don't just use 'abcd' because that's implementation-dependent. */
|
||||
#define BLARGG_4CHAR( a, b, c, d ) \
|
||||
((a&0xFF)*0x1000000 + (b&0xFF)*0x10000 + (c&0xFF)*0x100 + (d&0xFF))
|
||||
|
||||
/* BLARGG_STATIC_ASSERT( expr ): Generates compile error if expr is 0.
|
||||
Can be used at file, function, or class scope. */
|
||||
#ifdef _MSC_VER
|
||||
// MSVC6 (_MSC_VER < 1300) __LINE__ fails when /Zl is specified
|
||||
#define BLARGG_STATIC_ASSERT( expr ) \
|
||||
void blargg_failed_( int (*arg) [2 / (int) !!(expr) - 1] )
|
||||
#else
|
||||
// Others fail when declaring same function multiple times in class,
|
||||
// so differentiate them by line
|
||||
#define BLARGG_STATIC_ASSERT( expr ) \
|
||||
void blargg_failed_( int (*arg) [2 / !!(expr) - 1] [__LINE__] )
|
||||
#endif
|
||||
|
||||
/* Pure virtual functions cause a vtable entry to a "called pure virtual"
|
||||
error handler, requiring linkage to the C++ runtime library. This macro is
|
||||
used in place of the "= 0", and simply expands to its argument. During
|
||||
development, it expands to "= 0", allowing detection of missing overrides. */
|
||||
#define BLARGG_PURE( def ) def
|
||||
|
||||
/* My code depends on ASCII anywhere a character or string constant is
|
||||
compared with data read from a file, and anywhere file data is read and
|
||||
treated as a string. */
|
||||
#if '\n'!=0x0A || ' '!=0x20 || '0'!=0x30 || 'A'!=0x41 || 'a'!=0x61
|
||||
#error "ASCII character set required"
|
||||
#endif
|
||||
|
||||
/* My code depends on int being at least 32 bits. Almost everything these days
|
||||
uses at least 32-bit ints, so it's hard to even find a system with 16-bit ints
|
||||
to test with. The issue can't be gotten around by using a suitable blargg_int
|
||||
everywhere either, because int is often converted to implicitly when doing
|
||||
arithmetic on smaller types. */
|
||||
#if UINT_MAX < 0xFFFFFFFF
|
||||
#error "int must be at least 32 bits"
|
||||
#endif
|
||||
|
||||
// In case compiler doesn't support these properly. Used rarely.
|
||||
#define STATIC_CAST(T,expr) static_cast<T> (expr)
|
||||
#define CONST_CAST( T,expr) const_cast<T> (expr)
|
||||
|
||||
// User configuration can override the above macros if necessary
|
||||
#include "blargg_config.h"
|
||||
|
||||
/* BLARGG_DEPRECATED [_TEXT] for any declarations/text to be removed in a
|
||||
future version. In GCC, we can let the compiler warn. In other compilers,
|
||||
we strip it out unless BLARGG_LEGACY is true. */
|
||||
#if BLARGG_LEGACY
|
||||
// Allow old client code to work without warnings
|
||||
#define BLARGG_DEPRECATED_TEXT( text ) text
|
||||
#define BLARGG_DEPRECATED( text ) text
|
||||
#elif __GNUC__ >= 4
|
||||
// In GCC, we can mark declarations and let the compiler warn
|
||||
#define BLARGG_DEPRECATED_TEXT( text ) text
|
||||
#define BLARGG_DEPRECATED( text ) __attribute__ ((deprecated)) text
|
||||
#else
|
||||
// By default, deprecated items are removed, to avoid use in new code
|
||||
#define BLARGG_DEPRECATED_TEXT( text )
|
||||
#define BLARGG_DEPRECATED( text )
|
||||
#endif
|
||||
|
||||
/* BOOST::int8_t, BOOST::int32_t, etc.
|
||||
I used BOOST since I originally was going to allow use of the boost library
|
||||
for prividing the definitions. If I'm defining them, they must be scoped or
|
||||
else they could conflict with the standard ones at global scope. Even if
|
||||
HAVE_STDINT_H isn't defined, I can't assume the typedefs won't exist at
|
||||
global scope already. */
|
||||
#if defined (HAVE_STDINT_H) || \
|
||||
UCHAR_MAX != 0xFF || USHRT_MAX != 0xFFFF || UINT_MAX != 0xFFFFFFFF
|
||||
#include <stdint.h>
|
||||
#define BOOST
|
||||
#else
|
||||
struct BOOST
|
||||
{
|
||||
typedef signed char int8_t;
|
||||
typedef unsigned char uint8_t;
|
||||
typedef short int16_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef int int32_t;
|
||||
typedef unsigned int uint32_t;
|
||||
};
|
||||
#endif
|
||||
|
||||
/* My code is not written with exceptions in mind, so either uses new (nothrow)
|
||||
OR overrides operator new in my classes. The former is best since clients
|
||||
creating objects will get standard exceptions on failure, but that causes it
|
||||
to require the standard C++ library. So, when the client is using the C
|
||||
interface, I override operator new to use malloc. */
|
||||
|
||||
// BLARGG_DISABLE_NOTHROW is put inside classes
|
||||
#ifndef BLARGG_DISABLE_NOTHROW
|
||||
// throw spec mandatory in ISO C++ if NULL can be returned
|
||||
#if __cplusplus >= 199711 || __GNUC__ >= 3 || _MSC_VER >= 1300
|
||||
#define BLARGG_THROWS_NOTHING throw ()
|
||||
#else
|
||||
#define BLARGG_THROWS_NOTHING
|
||||
#endif
|
||||
|
||||
#define BLARGG_DISABLE_NOTHROW \
|
||||
void* operator new ( size_t s ) BLARGG_THROWS_NOTHING { return malloc( s ); }\
|
||||
void operator delete( void* p ) BLARGG_THROWS_NOTHING { free( p ); }
|
||||
|
||||
#define BLARGG_NEW new
|
||||
#else
|
||||
// BLARGG_NEW is used in place of new in library code
|
||||
#include <new>
|
||||
#define BLARGG_NEW new (std::nothrow)
|
||||
#endif
|
||||
|
||||
class blargg_vector_ {
|
||||
protected:
|
||||
void* begin_;
|
||||
size_t size_;
|
||||
void init();
|
||||
blargg_err_t resize_( size_t n, size_t elem_size );
|
||||
public:
|
||||
size_t size() const { return size_; }
|
||||
void clear();
|
||||
};
|
||||
|
||||
// Very lightweight vector for POD types (no constructor/destructor)
|
||||
template<class T>
|
||||
class blargg_vector : public blargg_vector_ {
|
||||
union T_must_be_pod { T t; }; // fails if T is not POD
|
||||
public:
|
||||
blargg_vector() { init(); }
|
||||
~blargg_vector() { clear(); }
|
||||
|
||||
blargg_err_t resize( size_t n ) { return resize_( n, sizeof (T) ); }
|
||||
|
||||
T* begin() { return static_cast<T*> (begin_); }
|
||||
const T* begin() const { return static_cast<T*> (begin_); }
|
||||
|
||||
T* end() { return static_cast<T*> (begin_) + size_; }
|
||||
const T* end() const { return static_cast<T*> (begin_) + size_; }
|
||||
|
||||
T& operator [] ( size_t n )
|
||||
{
|
||||
assert( n < size_ );
|
||||
return static_cast<T*> (begin_) [n];
|
||||
}
|
||||
|
||||
const T& operator [] ( size_t n ) const
|
||||
{
|
||||
assert( n < size_ );
|
||||
return static_cast<T*> (begin_) [n];
|
||||
}
|
||||
};
|
||||
|
||||
// Callback function with user data.
|
||||
// blargg_callback<T> set_callback; // for user, this acts like...
|
||||
// void set_callback( T func, void* user_data = NULL ); // ...this
|
||||
// To call function, do set_callback.f( .. set_callback.data ... );
|
||||
template<class T>
|
||||
struct blargg_callback
|
||||
{
|
||||
T f;
|
||||
void* data;
|
||||
blargg_callback() { f = NULL; }
|
||||
void operator () ( T callback, void* user_data = NULL ) { f = callback; data = user_data; }
|
||||
};
|
||||
|
||||
#ifndef _WIN32
|
||||
// Not supported on any other platforms
|
||||
#undef BLARGG_UTF8_PATHS
|
||||
#endif
|
||||
|
||||
BLARGG_DEPRECATED( typedef signed int blargg_long; )
|
||||
BLARGG_DEPRECATED( typedef unsigned int blargg_ulong; )
|
||||
#if BLARGG_LEGACY
|
||||
#define BOOST_STATIC_ASSERT BLARGG_STATIC_ASSERT
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,34 +0,0 @@
|
|||
// Library configuration. Modify this file as necessary.
|
||||
|
||||
// File_Extractor 1.0.0
|
||||
#ifndef BLARGG_CONFIG_H
|
||||
#define BLARGG_CONFIG_H
|
||||
|
||||
// Uncomment a #define line below to have effect described.
|
||||
|
||||
// Enable RAR archive support. Doing so adds extra licensing restrictions
|
||||
// to this library (see unrar/readme.txt for more information).
|
||||
#define FEX_ENABLE_RAR 1
|
||||
|
||||
// Accept file paths encoded as UTF-8. Currently only affects Windows,
|
||||
// as Unix/Linux/Mac OS X already use UTF-8 paths.
|
||||
#define BLARGG_UTF8_PATHS 1
|
||||
|
||||
// Enable support for as building DLL on Windows.
|
||||
//#define BLARGG_BUILD_DLL 1
|
||||
|
||||
// Support only the listed archive types. Remove any you don't need.
|
||||
/*
|
||||
#define FEX_TYPE_LIST \
|
||||
fex_7z_type,\
|
||||
fex_gz_type,\
|
||||
fex_rar_type,\
|
||||
fex_zip_type,
|
||||
*/
|
||||
|
||||
// Use standard config.h if present
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,185 +0,0 @@
|
|||
// CPU Byte Order Utilities
|
||||
|
||||
// File_Extractor 1.0.0
|
||||
#ifndef BLARGG_ENDIAN_H
|
||||
#define BLARGG_ENDIAN_H
|
||||
|
||||
#include "blargg_common.h"
|
||||
|
||||
// BLARGG_CPU_CISC: Defined if CPU has very few general-purpose registers (< 16)
|
||||
#if defined (__i386__) || defined (__x86_64__) || defined (_M_IX86) || defined (_M_X64)
|
||||
#define BLARGG_CPU_X86 1
|
||||
#define BLARGG_CPU_CISC 1
|
||||
#endif
|
||||
|
||||
#if defined (__powerpc__) || defined (__ppc__) || defined (__ppc64__) || \
|
||||
defined (__POWERPC__) || defined (__powerc)
|
||||
#define BLARGG_CPU_POWERPC 1
|
||||
#define BLARGG_CPU_RISC 1
|
||||
#endif
|
||||
|
||||
// BLARGG_BIG_ENDIAN, BLARGG_LITTLE_ENDIAN: Determined automatically, otherwise only
|
||||
// one may be #defined to 1. Only needed if something actually depends on byte order.
|
||||
#if !defined (BLARGG_BIG_ENDIAN) && !defined (BLARGG_LITTLE_ENDIAN)
|
||||
#ifdef __GLIBC__
|
||||
// GCC handles this for us
|
||||
#include <endian.h>
|
||||
#if __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#define BLARGG_LITTLE_ENDIAN 1
|
||||
#elif __BYTE_ORDER == __BIG_ENDIAN
|
||||
#define BLARGG_BIG_ENDIAN 1
|
||||
#endif
|
||||
#else
|
||||
|
||||
#if defined (LSB_FIRST) || defined (__LITTLE_ENDIAN__) || BLARGG_CPU_X86 || \
|
||||
(defined (LITTLE_ENDIAN) && LITTLE_ENDIAN+0 != 1234)
|
||||
#define BLARGG_LITTLE_ENDIAN 1
|
||||
#endif
|
||||
|
||||
#if defined (MSB_FIRST) || defined (__BIG_ENDIAN__) || defined (WORDS_BIGENDIAN) || \
|
||||
defined (__sparc__) || BLARGG_CPU_POWERPC || \
|
||||
(defined (BIG_ENDIAN) && BIG_ENDIAN+0 != 4321)
|
||||
#define BLARGG_BIG_ENDIAN 1
|
||||
#elif !defined (__mips__)
|
||||
// No endian specified; assume little-endian, since it's most common
|
||||
#define BLARGG_LITTLE_ENDIAN 1
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if BLARGG_LITTLE_ENDIAN && BLARGG_BIG_ENDIAN
|
||||
#undef BLARGG_LITTLE_ENDIAN
|
||||
#undef BLARGG_BIG_ENDIAN
|
||||
#endif
|
||||
|
||||
inline void blargg_verify_byte_order()
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
#if BLARGG_BIG_ENDIAN
|
||||
volatile int i = 1;
|
||||
assert( *(volatile char*) &i == 0 );
|
||||
#elif BLARGG_LITTLE_ENDIAN
|
||||
volatile int i = 1;
|
||||
assert( *(volatile char*) &i != 0 );
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
inline unsigned get_le16( void const* p )
|
||||
{
|
||||
return (unsigned) ((unsigned char const*) p) [1] << 8 |
|
||||
(unsigned) ((unsigned char const*) p) [0];
|
||||
}
|
||||
|
||||
inline unsigned get_be16( void const* p )
|
||||
{
|
||||
return (unsigned) ((unsigned char const*) p) [0] << 8 |
|
||||
(unsigned) ((unsigned char const*) p) [1];
|
||||
}
|
||||
|
||||
inline unsigned get_le32( void const* p )
|
||||
{
|
||||
return (unsigned) ((unsigned char const*) p) [3] << 24 |
|
||||
(unsigned) ((unsigned char const*) p) [2] << 16 |
|
||||
(unsigned) ((unsigned char const*) p) [1] << 8 |
|
||||
(unsigned) ((unsigned char const*) p) [0];
|
||||
}
|
||||
|
||||
inline unsigned get_be32( void const* p )
|
||||
{
|
||||
return (unsigned) ((unsigned char const*) p) [0] << 24 |
|
||||
(unsigned) ((unsigned char const*) p) [1] << 16 |
|
||||
(unsigned) ((unsigned char const*) p) [2] << 8 |
|
||||
(unsigned) ((unsigned char const*) p) [3];
|
||||
}
|
||||
|
||||
inline void set_le16( void* p, unsigned n )
|
||||
{
|
||||
((unsigned char*) p) [1] = (unsigned char) (n >> 8);
|
||||
((unsigned char*) p) [0] = (unsigned char) n;
|
||||
}
|
||||
|
||||
inline void set_be16( void* p, unsigned n )
|
||||
{
|
||||
((unsigned char*) p) [0] = (unsigned char) (n >> 8);
|
||||
((unsigned char*) p) [1] = (unsigned char) n;
|
||||
}
|
||||
|
||||
inline void set_le32( void* p, unsigned n )
|
||||
{
|
||||
((unsigned char*) p) [0] = (unsigned char) n;
|
||||
((unsigned char*) p) [1] = (unsigned char) (n >> 8);
|
||||
((unsigned char*) p) [2] = (unsigned char) (n >> 16);
|
||||
((unsigned char*) p) [3] = (unsigned char) (n >> 24);
|
||||
}
|
||||
|
||||
inline void set_be32( void* p, unsigned n )
|
||||
{
|
||||
((unsigned char*) p) [3] = (unsigned char) n;
|
||||
((unsigned char*) p) [2] = (unsigned char) (n >> 8);
|
||||
((unsigned char*) p) [1] = (unsigned char) (n >> 16);
|
||||
((unsigned char*) p) [0] = (unsigned char) (n >> 24);
|
||||
}
|
||||
|
||||
#if BLARGG_NONPORTABLE
|
||||
// Optimized implementation if byte order is known
|
||||
#if BLARGG_LITTLE_ENDIAN
|
||||
#define GET_LE16( addr ) (*(BOOST::uint16_t const*) (addr))
|
||||
#define GET_LE32( addr ) (*(BOOST::uint32_t const*) (addr))
|
||||
#define SET_LE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data))
|
||||
#define SET_LE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data))
|
||||
#elif BLARGG_BIG_ENDIAN
|
||||
#define GET_BE16( addr ) (*(BOOST::uint16_t const*) (addr))
|
||||
#define GET_BE32( addr ) (*(BOOST::uint32_t const*) (addr))
|
||||
#define SET_BE16( addr, data ) (void) (*(BOOST::uint16_t*) (addr) = (data))
|
||||
#define SET_BE32( addr, data ) (void) (*(BOOST::uint32_t*) (addr) = (data))
|
||||
|
||||
#if BLARGG_CPU_POWERPC
|
||||
// PowerPC has special byte-reversed instructions
|
||||
#if defined (__MWERKS__)
|
||||
#define GET_LE16( addr ) (__lhbrx( addr, 0 ))
|
||||
#define GET_LE32( addr ) (__lwbrx( addr, 0 ))
|
||||
#define SET_LE16( addr, in ) (__sthbrx( in, addr, 0 ))
|
||||
#define SET_LE32( addr, in ) (__stwbrx( in, addr, 0 ))
|
||||
#elif defined (__GNUC__)
|
||||
#define GET_LE16( addr ) ({unsigned short ppc_lhbrx_; __asm__ volatile( "lhbrx %0,0,%1" : "=r" (ppc_lhbrx_) : "r" (addr) : "memory" ); ppc_lhbrx_;})
|
||||
#define GET_LE32( addr ) ({unsigned short ppc_lwbrx_; __asm__ volatile( "lwbrx %0,0,%1" : "=r" (ppc_lwbrx_) : "r" (addr) : "memory" ); ppc_lwbrx_;})
|
||||
#define SET_LE16( addr, in ) ({__asm__ volatile( "sthbrx %0,0,%1" : : "r" (in), "r" (addr) : "memory" );})
|
||||
#define SET_LE32( addr, in ) ({__asm__ volatile( "stwbrx %0,0,%1" : : "r" (in), "r" (addr) : "memory" );})
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef GET_LE16
|
||||
#define GET_LE16( addr ) get_le16( addr )
|
||||
#define SET_LE16( addr, data ) set_le16( addr, data )
|
||||
#endif
|
||||
|
||||
#ifndef GET_LE32
|
||||
#define GET_LE32( addr ) get_le32( addr )
|
||||
#define SET_LE32( addr, data ) set_le32( addr, data )
|
||||
#endif
|
||||
|
||||
#ifndef GET_BE16
|
||||
#define GET_BE16( addr ) get_be16( addr )
|
||||
#define SET_BE16( addr, data ) set_be16( addr, data )
|
||||
#endif
|
||||
|
||||
#ifndef GET_BE32
|
||||
#define GET_BE32( addr ) get_be32( addr )
|
||||
#define SET_BE32( addr, data ) set_be32( addr, data )
|
||||
#endif
|
||||
|
||||
// auto-selecting versions
|
||||
|
||||
inline void set_le( BOOST::uint16_t* p, unsigned n ) { SET_LE16( p, n ); }
|
||||
inline void set_le( BOOST::uint32_t* p, unsigned n ) { SET_LE32( p, n ); }
|
||||
inline void set_be( BOOST::uint16_t* p, unsigned n ) { SET_BE16( p, n ); }
|
||||
inline void set_be( BOOST::uint32_t* p, unsigned n ) { SET_BE32( p, n ); }
|
||||
inline unsigned get_le( BOOST::uint16_t const* p ) { return GET_LE16( p ); }
|
||||
inline unsigned get_le( BOOST::uint32_t const* p ) { return GET_LE32( p ); }
|
||||
inline unsigned get_be( BOOST::uint16_t const* p ) { return GET_BE16( p ); }
|
||||
inline unsigned get_be( BOOST::uint32_t const* p ) { return GET_BE32( p ); }
|
||||
|
||||
#endif
|
|
@ -1,113 +0,0 @@
|
|||
// File_Extractor 1.0.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "blargg_errors.h"
|
||||
|
||||
/* Copyright (C) 2009 Shay Green. This module is free software; you
|
||||
can redistribute it and/or modify it under the terms of the GNU Lesser
|
||||
General Public License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version. This
|
||||
module is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
details. You should have received a copy of the GNU Lesser General Public
|
||||
License along with this module; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
#include "blargg_source.h"
|
||||
|
||||
blargg_err_def_t blargg_err_generic = BLARGG_ERR_GENERIC;
|
||||
blargg_err_def_t blargg_err_memory = BLARGG_ERR_MEMORY;
|
||||
blargg_err_def_t blargg_err_caller = BLARGG_ERR_CALLER;
|
||||
blargg_err_def_t blargg_err_internal = BLARGG_ERR_INTERNAL;
|
||||
blargg_err_def_t blargg_err_limitation = BLARGG_ERR_LIMITATION;
|
||||
|
||||
blargg_err_def_t blargg_err_file_missing = BLARGG_ERR_FILE_MISSING;
|
||||
blargg_err_def_t blargg_err_file_read = BLARGG_ERR_FILE_READ;
|
||||
blargg_err_def_t blargg_err_file_write = BLARGG_ERR_FILE_WRITE;
|
||||
blargg_err_def_t blargg_err_file_io = BLARGG_ERR_FILE_IO;
|
||||
blargg_err_def_t blargg_err_file_full = BLARGG_ERR_FILE_FULL;
|
||||
blargg_err_def_t blargg_err_file_eof = BLARGG_ERR_FILE_EOF;
|
||||
|
||||
blargg_err_def_t blargg_err_file_type = BLARGG_ERR_FILE_TYPE;
|
||||
blargg_err_def_t blargg_err_file_feature = BLARGG_ERR_FILE_FEATURE;
|
||||
blargg_err_def_t blargg_err_file_corrupt = BLARGG_ERR_FILE_CORRUPT;
|
||||
|
||||
const char* blargg_err_str( blargg_err_t err )
|
||||
{
|
||||
if ( !err )
|
||||
return "";
|
||||
|
||||
if ( *err == BLARGG_ERR_TYPE("")[0] )
|
||||
return err + 1;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
bool blargg_is_err_type( blargg_err_t err, const char type [] )
|
||||
{
|
||||
if ( err )
|
||||
{
|
||||
// True if first strlen(type) characters of err match type
|
||||
char const* p = err;
|
||||
while ( *type && *type == *p )
|
||||
{
|
||||
type++;
|
||||
p++;
|
||||
}
|
||||
|
||||
if ( !*type )
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
const char* blargg_err_details( blargg_err_t err )
|
||||
{
|
||||
const char* p = err;
|
||||
if ( !p )
|
||||
{
|
||||
p = "";
|
||||
}
|
||||
else if ( *p == BLARGG_ERR_TYPE("")[0] )
|
||||
{
|
||||
while ( *p && *p != ';' )
|
||||
p++;
|
||||
|
||||
// Skip ; and space after it
|
||||
if ( *p )
|
||||
{
|
||||
p++;
|
||||
|
||||
check( *p == ' ' );
|
||||
if ( *p )
|
||||
p++;
|
||||
}
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
int blargg_err_to_code( blargg_err_t err, blargg_err_to_code_t const codes [] )
|
||||
{
|
||||
if ( !err )
|
||||
return 0;
|
||||
|
||||
while ( codes->str && !blargg_is_err_type( err, codes->str ) )
|
||||
codes++;
|
||||
|
||||
return codes->code;
|
||||
}
|
||||
|
||||
blargg_err_t blargg_code_to_err( int code, blargg_err_to_code_t const codes [] )
|
||||
{
|
||||
if ( !code )
|
||||
return blargg_ok;
|
||||
|
||||
while ( codes->str && codes->code != code )
|
||||
codes++;
|
||||
|
||||
if ( !codes->str )
|
||||
return blargg_err_generic;
|
||||
|
||||
return codes->str;
|
||||
}
|
|
@ -1,80 +0,0 @@
|
|||
// Error strings and conversion functions
|
||||
|
||||
// File_Extractor 1.0.0
|
||||
#ifndef BLARGG_ERRORS_H
|
||||
#define BLARGG_ERRORS_H
|
||||
|
||||
#ifndef BLARGG_COMMON_H
|
||||
#include "blargg_common.h"
|
||||
#endif
|
||||
|
||||
typedef const char blargg_err_def_t [];
|
||||
|
||||
// Basic errors
|
||||
extern blargg_err_def_t blargg_err_generic;
|
||||
extern blargg_err_def_t blargg_err_memory;
|
||||
extern blargg_err_def_t blargg_err_caller;
|
||||
extern blargg_err_def_t blargg_err_internal;
|
||||
extern blargg_err_def_t blargg_err_limitation;
|
||||
|
||||
// File low-level
|
||||
extern blargg_err_def_t blargg_err_file_missing; // not found
|
||||
extern blargg_err_def_t blargg_err_file_read;
|
||||
extern blargg_err_def_t blargg_err_file_write;
|
||||
extern blargg_err_def_t blargg_err_file_io;
|
||||
extern blargg_err_def_t blargg_err_file_full;
|
||||
extern blargg_err_def_t blargg_err_file_eof;
|
||||
|
||||
// File high-level
|
||||
extern blargg_err_def_t blargg_err_file_type; // wrong file type
|
||||
extern blargg_err_def_t blargg_err_file_feature;
|
||||
extern blargg_err_def_t blargg_err_file_corrupt;
|
||||
|
||||
// C string describing error, or "" if err == NULL
|
||||
const char* blargg_err_str( blargg_err_t err );
|
||||
|
||||
// True iff error is of given type, or false if err == NULL
|
||||
bool blargg_is_err_type( blargg_err_t, const char type [] );
|
||||
|
||||
// Details of error without describing main cause, or "" if err == NULL
|
||||
const char* blargg_err_details( blargg_err_t err );
|
||||
|
||||
// Converts error string to integer code using mapping table. Calls blargg_is_err_type()
|
||||
// for each str and returns code on first match. Returns 0 if err == NULL.
|
||||
struct blargg_err_to_code_t {
|
||||
const char* str;
|
||||
int code;
|
||||
};
|
||||
int blargg_err_to_code( blargg_err_t err, blargg_err_to_code_t const [] );
|
||||
|
||||
// Converts error code back to string. If code == 0, returns NULL. If not in table,
|
||||
// returns blargg_err_generic.
|
||||
blargg_err_t blargg_code_to_err( int code, blargg_err_to_code_t const [] );
|
||||
|
||||
// Generates error string literal with details of cause
|
||||
#define BLARGG_ERR( type, str ) (type "; " str)
|
||||
|
||||
// Extra space to make it clear when blargg_err_str() isn't called to get
|
||||
// printable version of error. At some point, I might prefix error strings
|
||||
// with a code, to speed conversion to a code.
|
||||
#define BLARGG_ERR_TYPE( str ) " " str
|
||||
|
||||
// Error types to pass to BLARGG_ERR macro
|
||||
#define BLARGG_ERR_GENERIC BLARGG_ERR_TYPE( "operation failed" )
|
||||
#define BLARGG_ERR_MEMORY BLARGG_ERR_TYPE( "out of memory" )
|
||||
#define BLARGG_ERR_CALLER BLARGG_ERR_TYPE( "internal usage bug" )
|
||||
#define BLARGG_ERR_INTERNAL BLARGG_ERR_TYPE( "internal bug" )
|
||||
#define BLARGG_ERR_LIMITATION BLARGG_ERR_TYPE( "exceeded limitation" )
|
||||
|
||||
#define BLARGG_ERR_FILE_MISSING BLARGG_ERR_TYPE( "file not found" )
|
||||
#define BLARGG_ERR_FILE_READ BLARGG_ERR_TYPE( "couldn't open file" )
|
||||
#define BLARGG_ERR_FILE_WRITE BLARGG_ERR_TYPE( "couldn't modify file" )
|
||||
#define BLARGG_ERR_FILE_IO BLARGG_ERR_TYPE( "read/write error" )
|
||||
#define BLARGG_ERR_FILE_FULL BLARGG_ERR_TYPE( "disk full" )
|
||||
#define BLARGG_ERR_FILE_EOF BLARGG_ERR_TYPE( "truncated file" )
|
||||
|
||||
#define BLARGG_ERR_FILE_TYPE BLARGG_ERR_TYPE( "wrong file type" )
|
||||
#define BLARGG_ERR_FILE_FEATURE BLARGG_ERR_TYPE( "unsupported file feature" )
|
||||
#define BLARGG_ERR_FILE_CORRUPT BLARGG_ERR_TYPE( "corrupt file" )
|
||||
|
||||
#endif
|
|
@ -1,125 +0,0 @@
|
|||
/* Included at the beginning of library source files, AFTER all other #include
|
||||
lines. Sets up helpful macros and services used in my source code. Since this
|
||||
is only "active" in my source code, I don't have to worry about polluting the
|
||||
global namespace with unprefixed names. */
|
||||
|
||||
// File_Extractor 1.0.0
|
||||
#ifndef BLARGG_SOURCE_H
|
||||
#define BLARGG_SOURCE_H
|
||||
|
||||
#ifndef BLARGG_COMMON_H // optimization only
|
||||
#include "blargg_common.h"
|
||||
#endif
|
||||
#include "blargg_errors.h"
|
||||
|
||||
#include <string.h> /* memcpy(), memset(), memmove() */
|
||||
#include <stddef.h> /* offsetof() */
|
||||
|
||||
/* The following four macros are for debugging only. Some or all might be
|
||||
defined to do nothing, depending on the circumstances. Described is what
|
||||
happens when a particular macro is defined to do something. When defined to
|
||||
do nothing, the macros do NOT evaluate their argument(s). */
|
||||
|
||||
/* If expr is false, prints file and line number, then aborts program. Meant
|
||||
for checking internal state and consistency. A failed assertion indicates a bug
|
||||
in MY code.
|
||||
|
||||
void assert( bool expr ); */
|
||||
#include <assert.h>
|
||||
|
||||
/* If expr is false, prints file and line number, then aborts program. Meant
|
||||
for checking caller-supplied parameters and operations that are outside the
|
||||
control of the module. A failed requirement probably indicates a bug in YOUR
|
||||
code.
|
||||
|
||||
void require( bool expr ); */
|
||||
#undef require
|
||||
#define require( expr ) assert( expr )
|
||||
|
||||
/* Like printf() except output goes to debugging console/file.
|
||||
|
||||
void dprintf( const char format [], ... ); */
|
||||
static inline void blargg_dprintf_( const char [], ... ) { }
|
||||
#undef dprintf
|
||||
#define dprintf (1) ? (void) 0 : blargg_dprintf_
|
||||
|
||||
/* If expr is false, prints file and line number to debug console/log, then
|
||||
continues execution normally. Meant for flagging potential problems or things
|
||||
that should be looked into, but that aren't serious problems.
|
||||
|
||||
void check( bool expr ); */
|
||||
#undef check
|
||||
#define check( expr ) ((void) 0)
|
||||
|
||||
/* If expr yields non-NULL error string, returns it from current function,
|
||||
otherwise continues normally. */
|
||||
#undef RETURN_ERR
|
||||
#define RETURN_ERR( expr ) \
|
||||
do {\
|
||||
blargg_err_t blargg_return_err_ = (expr);\
|
||||
if ( blargg_return_err_ )\
|
||||
return blargg_return_err_;\
|
||||
} while ( 0 )
|
||||
|
||||
/* If ptr is NULL, returns out-of-memory error, otherwise continues normally. */
|
||||
#undef CHECK_ALLOC
|
||||
#define CHECK_ALLOC( ptr ) \
|
||||
do {\
|
||||
if ( !(ptr) )\
|
||||
return blargg_err_memory;\
|
||||
} while ( 0 )
|
||||
|
||||
/* The usual min/max functions for built-in types.
|
||||
|
||||
template<typename T> T min( T x, T y ) { return x < y ? x : y; }
|
||||
template<typename T> T max( T x, T y ) { return x > y ? x : y; } */
|
||||
#define BLARGG_DEF_MIN_MAX( type ) \
|
||||
static inline type blargg_min( type x, type y ) { if ( y < x ) x = y; return x; }\
|
||||
static inline type blargg_max( type x, type y ) { if ( x < y ) x = y; return x; }
|
||||
|
||||
BLARGG_DEF_MIN_MAX( int )
|
||||
BLARGG_DEF_MIN_MAX( unsigned )
|
||||
BLARGG_DEF_MIN_MAX( long )
|
||||
BLARGG_DEF_MIN_MAX( unsigned long )
|
||||
BLARGG_DEF_MIN_MAX( float )
|
||||
BLARGG_DEF_MIN_MAX( double )
|
||||
|
||||
#undef min
|
||||
#define min blargg_min
|
||||
|
||||
#undef max
|
||||
#define max blargg_max
|
||||
|
||||
// typedef unsigned char byte;
|
||||
typedef unsigned char blargg_byte;
|
||||
#undef byte
|
||||
#define byte blargg_byte
|
||||
|
||||
#ifndef BLARGG_EXPORT
|
||||
#if defined (_WIN32) && BLARGG_BUILD_DLL
|
||||
#define BLARGG_EXPORT __declspec(dllexport)
|
||||
#elif defined (__GNUC__)
|
||||
// can always set visibility, even when not building DLL
|
||||
#define BLARGG_EXPORT __attribute__ ((visibility ("default")))
|
||||
#else
|
||||
#define BLARGG_EXPORT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if BLARGG_LEGACY
|
||||
#define BLARGG_CHECK_ALLOC CHECK_ALLOC
|
||||
#define BLARGG_RETURN_ERR RETURN_ERR
|
||||
#endif
|
||||
|
||||
// Called after failed operation when overall operation may still complete OK.
|
||||
// Only used by unit testing framework.
|
||||
#undef ACK_FAILURE
|
||||
#define ACK_FAILURE() ((void)0)
|
||||
|
||||
/* BLARGG_SOURCE_BEGIN: If defined, #included, allowing redefition of dprintf etc.
|
||||
and check */
|
||||
#ifdef BLARGG_SOURCE_BEGIN
|
||||
#include BLARGG_SOURCE_BEGIN
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,323 +0,0 @@
|
|||
// File_Extractor 1.0.0. http://www.slack.net/~ant/
|
||||
|
||||
#include "fex.h"
|
||||
|
||||
#include "File_Extractor.h"
|
||||
#include "blargg_endian.h"
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
/* Copyright (C) 2005-2009 Shay Green. This module is free software; you
|
||||
can redistribute it and/or modify it under the terms of the GNU Lesser
|
||||
General Public License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version. This
|
||||
module is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
details. You should have received a copy of the GNU Lesser General Public
|
||||
License along with this module; if not, write to the Free Software Foundation,
|
||||
Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */
|
||||
|
||||
#include "blargg_source.h"
|
||||
|
||||
|
||||
//// Types
|
||||
|
||||
BLARGG_EXPORT const fex_type_t* fex_type_list( void )
|
||||
{
|
||||
static fex_type_t const fex_type_list_ [] =
|
||||
{
|
||||
#ifdef FEX_TYPE_LIST
|
||||
FEX_TYPE_LIST
|
||||
#else
|
||||
// Modify blargg_config.h to change type list, NOT this file
|
||||
fex_7z_type,
|
||||
fex_gz_type,
|
||||
#if FEX_ENABLE_RAR
|
||||
fex_rar_type,
|
||||
#endif
|
||||
fex_zip_type,
|
||||
#endif
|
||||
fex_bin_type,
|
||||
NULL
|
||||
};
|
||||
|
||||
return fex_type_list_;
|
||||
}
|
||||
|
||||
BLARGG_EXPORT fex_err_t fex_init( void )
|
||||
{
|
||||
static bool inited;
|
||||
if ( !inited )
|
||||
{
|
||||
for ( fex_type_t const* t = fex_type_list(); *t != NULL; ++t )
|
||||
{
|
||||
if ( (*t)->init )
|
||||
RETURN_ERR( (*t)->init() );
|
||||
}
|
||||
inited = true;
|
||||
}
|
||||
return blargg_ok;
|
||||
}
|
||||
|
||||
BLARGG_EXPORT const char* fex_identify_header( void const* header )
|
||||
{
|
||||
unsigned four = get_be32( header );
|
||||
switch ( four )
|
||||
{
|
||||
case 0x52457E5E:
|
||||
case 0x52617221: return ".rar";
|
||||
|
||||
case 0x377ABCAF: return ".7z";
|
||||
|
||||
case 0x504B0304:
|
||||
case 0x504B0506: return ".zip";
|
||||
|
||||
case 0x53495421: return ".sit";
|
||||
case 0x41724301: return ".arc";
|
||||
case 0x4D534346: return ".cab";
|
||||
case 0x5A4F4F20: return ".zoo";
|
||||
}
|
||||
|
||||
unsigned three = four >> 8;
|
||||
switch ( three )
|
||||
{
|
||||
case 0x425A68: return ".bz2";
|
||||
}
|
||||
|
||||
unsigned two = four >> 16;
|
||||
switch ( two )
|
||||
{
|
||||
case 0x1F8B: return ".gz";
|
||||
case 0x60EA: return ".arj";
|
||||
}
|
||||
|
||||
unsigned skip_first_two = four & 0xFFFF;
|
||||
if ( skip_first_two == 0x2D6C )
|
||||
return ".lha";
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
static int fex_has_extension_( const char str [], const char suffix [], size_t str_len )
|
||||
{
|
||||
size_t suffix_len = strlen( suffix );
|
||||
if ( str_len >= suffix_len )
|
||||
{
|
||||
str += str_len - suffix_len;
|
||||
while ( *str && tolower( (unsigned char) *str ) == *suffix )
|
||||
{
|
||||
str++;
|
||||
suffix++;
|
||||
}
|
||||
}
|
||||
return *suffix == 0;
|
||||
}
|
||||
|
||||
BLARGG_EXPORT int fex_has_extension( const char str [], const char suffix [] )
|
||||
{
|
||||
return fex_has_extension_( str, suffix, strlen( str ) );
|
||||
}
|
||||
|
||||
static int is_archive_extension( const char str [] )
|
||||
{
|
||||
static const char exts [] [6] = {
|
||||
".7z",
|
||||
".arc",
|
||||
".arj",
|
||||
".bz2",
|
||||
".cab",
|
||||
".dmg",
|
||||
".gz",
|
||||
".lha",
|
||||
".lz",
|
||||
".lzh",
|
||||
".lzma",
|
||||
".lzo",
|
||||
".lzx",
|
||||
".pea",
|
||||
".rar",
|
||||
".sit",
|
||||
".sitx",
|
||||
".tgz",
|
||||
".tlz",
|
||||
".z",
|
||||
".zip",
|
||||
".zoo",
|
||||
""
|
||||
};
|
||||
|
||||
size_t str_len = strlen( str );
|
||||
const char (*ext) [6] = exts;
|
||||
for ( ; **ext; ext++ )
|
||||
{
|
||||
if ( fex_has_extension_( str, *ext, str_len ) )
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
BLARGG_EXPORT fex_type_t fex_identify_extension( const char str [] )
|
||||
{
|
||||
size_t str_len = strlen( str );
|
||||
for ( fex_type_t const* types = fex_type_list(); *types; types++ )
|
||||
{
|
||||
if ( fex_has_extension_( str, (*types)->extension, str_len ) )
|
||||
{
|
||||
// Avoid treating known archive type as binary
|
||||
if ( *(*types)->extension || !is_archive_extension( str ) )
|
||||
return *types;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BLARGG_EXPORT fex_err_t fex_identify_file( fex_type_t* type_out, const char path [] )
|
||||
{
|
||||
*type_out = NULL;
|
||||
|
||||
fex_type_t type = fex_identify_extension( path );
|
||||
|
||||
// Unsupported extension?
|
||||
if ( !type )
|
||||
return blargg_ok; // reject
|
||||
|
||||
// Unknown/no extension?
|
||||
if ( !*(type->extension) )
|
||||
{
|
||||
// Examine header
|
||||
FEX_FILE_READER in;
|
||||
RETURN_ERR( in.open( path ) );
|
||||
if ( in.remain() >= fex_identify_header_size )
|
||||
{
|
||||
char h [fex_identify_header_size];
|
||||
RETURN_ERR( in.read( h, sizeof h ) );
|
||||
|
||||
type = fex_identify_extension( fex_identify_header( h ) );
|
||||
}
|
||||
}
|
||||
|
||||
*type_out = type;
|
||||
return blargg_ok;
|
||||
}
|
||||
|
||||
BLARGG_EXPORT fex_err_t fex_open_type( fex_t** fe_out, const char path [], fex_type_t type )
|
||||
{
|
||||
*fe_out = NULL;
|
||||
|
||||
if ( !type )
|
||||
return blargg_err_file_type;
|
||||
|
||||
fex_t* fe = type->new_fex();
|
||||
CHECK_ALLOC( fe );
|
||||
|
||||
fex_err_t err = fe->open( path );
|
||||
if ( err )
|
||||
{
|
||||
delete fe;
|
||||
return err;
|
||||
}
|
||||
|
||||
*fe_out = fe;
|
||||
return blargg_ok;
|
||||
}
|
||||
|
||||
BLARGG_EXPORT fex_err_t fex_open( fex_t** fe_out, const char path [] )
|
||||
{
|
||||
*fe_out = NULL;
|
||||
|
||||
fex_type_t type;
|
||||
RETURN_ERR( fex_identify_file( &type, path ) );
|
||||
|
||||
return fex_open_type( fe_out, path, type );
|
||||
}
|
||||
|
||||
|
||||
//// Wide paths
|
||||
|
||||
#if BLARGG_UTF8_PATHS
|
||||
char* fex_wide_to_path( const wchar_t* wide )
|
||||
{
|
||||
return blargg_to_utf8( wide );
|
||||
}
|
||||
|
||||
void fex_free_path( char* path )
|
||||
{
|
||||
free( path );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//// Errors
|
||||
|
||||
#define ENTRY( name ) { blargg_err_##name, fex_err_##name }
|
||||
static blargg_err_to_code_t const fex_codes [] =
|
||||
{
|
||||
ENTRY( generic ),
|
||||
ENTRY( memory ),
|
||||
ENTRY( caller ),
|
||||
ENTRY( internal ),
|
||||
ENTRY( limitation ),
|
||||
|
||||
ENTRY( file_missing ),
|
||||
ENTRY( file_read ),
|
||||
ENTRY( file_io ),
|
||||
ENTRY( file_eof ),
|
||||
|
||||
ENTRY( file_type ),
|
||||
ENTRY( file_feature ),
|
||||
ENTRY( file_corrupt ),
|
||||
|
||||
{ 0, -1 }
|
||||
};
|
||||
#undef ENTRY
|
||||
|
||||
static int err_code( fex_err_t err )
|
||||
{
|
||||
return blargg_err_to_code( err, fex_codes );
|
||||
}
|
||||
|
||||
BLARGG_EXPORT int fex_err_code( fex_err_t err )
|
||||
{
|
||||
int code = err_code( err );
|
||||
return (code >= 0 ? code : fex_err_generic);
|
||||
}
|
||||
|
||||
BLARGG_EXPORT fex_err_t fex_code_to_err( int code )
|
||||
{
|
||||
return blargg_code_to_err( code, fex_codes );
|
||||
}
|
||||
|
||||
BLARGG_EXPORT const char* fex_err_details( fex_err_t err )
|
||||
{
|
||||
// If we don't have error code assigned, return entire string
|
||||
return (err_code( err ) >= 0 ? blargg_err_details( err ) : blargg_err_str( err ));
|
||||
}
|
||||
|
||||
|
||||
//// Wrappers
|
||||
|
||||
BLARGG_EXPORT fex_err_t fex_read( fex_t* fe, void* out, int count )
|
||||
{
|
||||
RETURN_ERR( fe->stat() );
|
||||
return fe->reader().read( out, count );
|
||||
}
|
||||
|
||||
BLARGG_EXPORT void fex_close ( fex_t* fe ) { delete fe; }
|
||||
BLARGG_EXPORT fex_type_t fex_type ( const fex_t* fe ) { return fe->type(); }
|
||||
BLARGG_EXPORT int fex_done ( const fex_t* fe ) { return fe->done(); }
|
||||
BLARGG_EXPORT const char* fex_name ( const fex_t* fe ) { return fe->name(); }
|
||||
BLARGG_EXPORT const wchar_t* fex_wname ( const fex_t* fe ) { return fe->wname(); }
|
||||
BLARGG_EXPORT int fex_size ( const fex_t* fe ) { return fe->size(); }
|
||||
BLARGG_EXPORT unsigned fex_dos_date ( const fex_t* fe ) { return fe->dos_date(); }
|
||||
BLARGG_EXPORT unsigned fex_crc32 ( const fex_t* fe ) { return fe->crc32(); }
|
||||
BLARGG_EXPORT fex_err_t fex_stat ( fex_t* fe ) { return fe->stat(); }
|
||||
BLARGG_EXPORT fex_err_t fex_next ( fex_t* fe ) { return fe->next(); }
|
||||
BLARGG_EXPORT fex_err_t fex_rewind ( fex_t* fe ) { return fe->rewind(); }
|
||||
BLARGG_EXPORT int fex_tell ( const fex_t* fe ) { return fe->tell(); }
|
||||
BLARGG_EXPORT fex_pos_t fex_tell_arc ( const fex_t* fe ) { return fe->tell_arc(); }
|
||||
BLARGG_EXPORT fex_err_t fex_seek_arc ( fex_t* fe, fex_pos_t pos ) { return fe->seek_arc( pos ); }
|
||||
BLARGG_EXPORT const char* fex_type_extension ( fex_type_t t ) { return t->extension; }
|
||||
BLARGG_EXPORT const char* fex_type_name ( fex_type_t t ) { return t->name; }
|
||||
BLARGG_EXPORT fex_err_t fex_data ( fex_t* fe, const void** data_out ) { return fe->data( data_out ); }
|
||||
BLARGG_EXPORT const char* fex_err_str ( fex_err_t err ) { return blargg_err_str( err ); }
|
|
@ -1,206 +0,0 @@
|
|||
/** Uniform access to zip, gzip, 7-zip, and RAR compressed archives \file */
|
||||
|
||||
/* File_Extractor 1.0.0 */
|
||||
#ifndef FEX_H
|
||||
#define FEX_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/** First parameter of most functions is fex_t*, or const fex_t* if nothing is
|
||||
changed. Once one of these functions returns an error, the archive should not
|
||||
be used any further, other than to close it. One exception is
|
||||
fex_error_file_eof; the archive may still be used after this. */
|
||||
typedef struct fex_t fex_t;
|
||||
|
||||
/** Pointer to error, or NULL if function was successful. See error functions
|
||||
below. */
|
||||
#ifndef fex_err_t /* (#ifndef allows better testing of library) */
|
||||
typedef const char* fex_err_t;
|
||||
#endif
|
||||
|
||||
|
||||
/**** File types ****/
|
||||
|
||||
/** Archive file type identifier. Can also hold NULL. */
|
||||
typedef const struct fex_type_t_* fex_type_t;
|
||||
|
||||
/** Array of supported types, with NULL at end */
|
||||
const fex_type_t* fex_type_list( void );
|
||||
|
||||
/** Name of this archive type, e.g. "ZIP archive", "file" */
|
||||
const char* fex_type_name( fex_type_t );
|
||||
|
||||
/** Usual file extension for type, e.g. ".zip", ".7z". For binary file type,
|
||||
returns "", since it can open any file. */
|
||||
const char* fex_type_extension( fex_type_t );
|
||||
|
||||
|
||||
/**** Wide-character file paths (Windows only) ****/
|
||||
|
||||
/** Converts wide-character path to form suitable for use with fex functions.
|
||||
Only supported when BLARGG_UTF8_PATHS is defined and building on Windows. */
|
||||
char* fex_wide_to_path( const wchar_t* wide );
|
||||
|
||||
/** Frees converted path. OK to pass NULL. Only supported when BLARGG_UTF8_PATHS
|
||||
is defined and building on Windows */
|
||||
void fex_free_path( char* );
|
||||
|
||||
|
||||
/**** Identification ****/
|
||||
|
||||
/** True if str ends in extension. If extension is "", always returns true.
|
||||
Converts str to lowercase before comparison, so extension should ALREADY be
|
||||
lowercase (i.e. pass ".zip", NOT ".ZIP"). */
|
||||
int fex_has_extension( const char str [], const char extension [] );
|
||||
|
||||
/** Determines type based on first fex_identify_header_size bytes of file.
|
||||
Returns usual file extension this should have (e.g. ".zip", ".gz", etc.).
|
||||
Returns "" if file header is not recognized. */
|
||||
const char* fex_identify_header( const void* header );
|
||||
enum { fex_identify_header_size = 16 };
|
||||
|
||||
/** Determines type based on extension of a file path, or just a lone extension
|
||||
(must include '.', e.g. ".zip", NOT just "zip"). Returns NULL if extension is
|
||||
for an unsupported type (e.g. ".lzh"). */
|
||||
fex_type_t fex_identify_extension( const char path_or_extension [] );
|
||||
|
||||
/** Determines type based on filename extension and/or file header. Sets *out
|
||||
to determined type, or NULL if type is not supported. */
|
||||
fex_err_t fex_identify_file( fex_type_t* out, const char path [] );
|
||||
|
||||
/** Type of an already-opened archive */
|
||||
fex_type_t fex_type( const fex_t* );
|
||||
|
||||
|
||||
/**** Open/close ****/
|
||||
|
||||
/** Initializes static tables used by library. Automatically called by
|
||||
fex_open(). OK to call more than once. */
|
||||
fex_err_t fex_init( void );
|
||||
|
||||
/** Opens archive and points *out at it. If error, sets *out to NULL. */
|
||||
fex_err_t fex_open( fex_t** out, const char path [] );
|
||||
|
||||
/** Opens archive of specified type and sets *out. Returns error if file is not
|
||||
of that archive type. If error, sets *out to NULL. */
|
||||
fex_err_t fex_open_type( fex_t** out, const char path [], fex_type_t );
|
||||
|
||||
/** Closes archive and frees memory. OK to pass NULL. */
|
||||
void fex_close( fex_t* );
|
||||
|
||||
|
||||
/**** Scanning ****/
|
||||
|
||||
/** True if at end of archive. Must be called after fex_open() or fex_rewind(),
|
||||
as an archive might contain no files. */
|
||||
int fex_done( const fex_t* );
|
||||
|
||||
/** Goes to next file in archive. If there are no more files, fex_done() will
|
||||
now return true. */
|
||||
fex_err_t fex_next( fex_t* );
|
||||
|
||||
/** Goes back to first file in archive, as if it were just opened with
|
||||
fex_open() */
|
||||
fex_err_t fex_rewind( fex_t* );
|
||||
|
||||
/** Saved position in archive. Can also store zero. */
|
||||
typedef int fex_pos_t;
|
||||
|
||||
/** Position of current file in archive. Never returns zero. */
|
||||
fex_pos_t fex_tell_arc( const fex_t* );
|
||||
|
||||
/** Returns to file at previously-saved position */
|
||||
fex_err_t fex_seek_arc( fex_t*, fex_pos_t );
|
||||
|
||||
|
||||
/**** Info ****/
|
||||
|
||||
/** Name of current file */
|
||||
const char* fex_name( const fex_t* );
|
||||
|
||||
/** Wide-character name of current file, or NULL if unavailable */
|
||||
const wchar_t* fex_wname( const fex_t* );
|
||||
|
||||
/** Makes further information available for file */
|
||||
fex_err_t fex_stat( fex_t* );
|
||||
|
||||
/** Size of current file. fex_stat() or fex_data() must have been called. */
|
||||
int fex_size( const fex_t* );
|
||||
|
||||
/** Modification date of current file (MS-DOS format), or 0 if unavailable.
|
||||
fex_stat() must have been called. */
|
||||
unsigned int fex_dos_date( const fex_t* );
|
||||
|
||||
/** CRC-32 checksum of current file's contents, or 0 if unavailable. Doesn't
|
||||
require calculation; simply gets it from file's header. fex_stat() must have
|
||||
been called. */
|
||||
unsigned int fex_crc32( const fex_t* );
|
||||
|
||||
|
||||
/**** Extraction ****/
|
||||
|
||||
/** Reads n bytes from current file. Reading past end of file results in
|
||||
fex_err_file_eof. */
|
||||
fex_err_t fex_read( fex_t*, void* out, int n );
|
||||
|
||||
/** Number of bytes read from current file */
|
||||
int fex_tell( const fex_t* );
|
||||
|
||||
/** Points *out at current file's data in memory. Pointer is valid until
|
||||
fex_next(), fex_rewind(), fex_seek_arc(), or fex_close() is called. Pointer
|
||||
must NOT be freed(); library frees it automatically. If error, sets *out to
|
||||
NULL. */
|
||||
fex_err_t fex_data( fex_t*, const void** out );
|
||||
|
||||
|
||||
/**** Errors ****/
|
||||
|
||||
/** Error string associated with err. Returns "" if err is NULL. Returns err
|
||||
unchanged if it isn't a fex_err_t returned by library. */
|
||||
const char* fex_err_str( fex_err_t err );
|
||||
|
||||
/** Details of error beyond main cause, or "" if none or err is NULL. Returns
|
||||
err unchanged if it isn't a fex_err_t returned by library. */
|
||||
const char* fex_err_details( fex_err_t err );
|
||||
|
||||
/** Numeric code corresponding to err. Returns fex_ok if err is NULL. Returns
|
||||
fex_err_generic if err isn't a fex_err_t returned by library. */
|
||||
int fex_err_code( fex_err_t err );
|
||||
|
||||
enum {
|
||||
fex_ok = 0,/**< Successful call. Guaranteed to be zero. */
|
||||
fex_err_generic = 0x01,/**< Error of unspecified type */
|
||||
fex_err_memory = 0x02,/**< Out of memory */
|
||||
fex_err_caller = 0x03,/**< Caller called function with bad args */
|
||||
fex_err_internal = 0x04,/**< Internal problem, bug, etc. */
|
||||
fex_err_limitation = 0x05,/**< Exceeded program limit */
|
||||
|
||||
fex_err_file_missing = 0x20,/**< File not found at specified path */
|
||||
fex_err_file_read = 0x21,/**< Couldn't open file for reading */
|
||||
fex_err_file_io = 0x23,/**< Read/write error */
|
||||
fex_err_file_eof = 0x25,/**< Tried to read past end of file */
|
||||
|
||||
fex_err_file_type = 0x30,/**< File is of wrong type */
|
||||
fex_err_file_feature = 0x32,/**< File requires unsupported feature */
|
||||
fex_err_file_corrupt = 0x33 /**< File is corrupt */
|
||||
};
|
||||
|
||||
/** fex_err_t corresponding to numeric code. Note that this might not recover
|
||||
the original fex_err_t before it was converted to a numeric code; in
|
||||
particular, fex_err_details(fex_code_to_err(code)) will be "" in most cases. */
|
||||
fex_err_t fex_code_to_err( int code );
|
||||
|
||||
|
||||
/* Deprecated */
|
||||
typedef fex_t File_Extractor;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1,57 +0,0 @@
|
|||
#include "filechooser.moc.hpp"
|
||||
#include "filechooser.moc"
|
||||
|
||||
//FileChooser is implemented as a modal QWidget instead of a QDialog
|
||||
//due to a bug in Qt 4.6.0 (QTBUG-7188); which causes the FileChooser
|
||||
//to not refresh when a QTimer is active from the main application.
|
||||
string FileChooser::exec() {
|
||||
if(list.size() == 0) return "";
|
||||
if(list.size() == 1) return list[0];
|
||||
|
||||
listWidget->clear();
|
||||
for(unsigned i = 0; i < list.size(); i++) {
|
||||
listWidget->addItem(list[i]);
|
||||
}
|
||||
listWidget->sortItems(Qt::AscendingOrder);
|
||||
listWidget->setCurrentRow(0);
|
||||
listWidget->setFocus();
|
||||
|
||||
name = "";
|
||||
setWindowModality(Qt::ApplicationModal);
|
||||
show();
|
||||
while(isVisible()) QApplication::processEvents();
|
||||
setWindowModality(Qt::NonModal);
|
||||
return name;
|
||||
}
|
||||
|
||||
void FileChooser::load() {
|
||||
QListWidgetItem *item = listWidget->currentItem();
|
||||
if(item) name = item->text().toUtf8().constData();
|
||||
close();
|
||||
}
|
||||
|
||||
FileChooser::FileChooser() {
|
||||
setWindowTitle("Select Cartridge To Load");
|
||||
setMinimumWidth(480);
|
||||
setMinimumHeight(320);
|
||||
|
||||
layout = new QVBoxLayout;
|
||||
setLayout(layout);
|
||||
|
||||
listWidget = new QListWidget;
|
||||
layout->addWidget(listWidget);
|
||||
|
||||
controlLayout = new QHBoxLayout;
|
||||
controlLayout->setAlignment(Qt::AlignRight);
|
||||
layout->addLayout(controlLayout);
|
||||
|
||||
okButton = new QPushButton("Ok");
|
||||
controlLayout->addWidget(okButton);
|
||||
|
||||
cancelButton = new QPushButton("Cancel");
|
||||
controlLayout->addWidget(cancelButton);
|
||||
|
||||
connect(listWidget, SIGNAL(itemActivated(QListWidgetItem*)), this, SLOT(load()));
|
||||
connect(okButton, SIGNAL(released()), this, SLOT(load()));
|
||||
connect(cancelButton, SIGNAL(released()), this, SLOT(close()));
|
||||
}
|
|
@ -1,20 +0,0 @@
|
|||
class FileChooser : public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
lstring list;
|
||||
string name;
|
||||
string exec();
|
||||
|
||||
FileChooser();
|
||||
|
||||
private slots:
|
||||
void load();
|
||||
|
||||
private:
|
||||
QVBoxLayout *layout;
|
||||
QListWidget *listWidget;
|
||||
QHBoxLayout *controlLayout;
|
||||
QPushButton *okButton;
|
||||
QPushButton *cancelButton;
|
||||
} *fileChooser;
|
|
@ -1,28 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2005-2007 NSRT Team ( http://nsrt.edgeemu.com )
|
||||
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License version 2.1 as published by the Free Software Foundation.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __7Z_H
|
||||
#define __7Z_H
|
||||
|
||||
#include "iiostrm.h"
|
||||
|
||||
bool decompress_lzma_7z(ISequentialInStream& in, unsigned in_size, ISequentialOutStream& out, unsigned out_size) throw ();
|
||||
bool decompress_lzma_7z(const unsigned char* in_data, unsigned in_size, unsigned char* out_data, unsigned out_size) throw ();
|
||||
|
||||
#endif
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2005-2007 NSRT Team ( http://nsrt.edgeemu.com )
|
||||
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License version 2.1 as published by the Free Software Foundation.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include "7z.h"
|
||||
|
||||
#include "lzmadec.h"
|
||||
|
||||
bool decompress_lzma_7z(ISequentialInStream& in, unsigned in_size, ISequentialOutStream& out, unsigned out_size) throw ()
|
||||
{
|
||||
try
|
||||
{
|
||||
NCompress::NLZMA::CDecoder cc;
|
||||
|
||||
UINT64 in_size_l = in_size;
|
||||
UINT64 out_size_l = out_size;
|
||||
|
||||
if (cc.ReadCoderProperties(&in) != S_OK) { return(false); }
|
||||
if (cc.Code(&in, &out, &in_size_l, &out_size_l) != S_OK) { return(false); }
|
||||
if (out.size_get() != out_size || out.overflow_get()) { return(false); }
|
||||
|
||||
return(true);
|
||||
}
|
||||
catch (...)
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
|
||||
bool decompress_lzma_7z(const unsigned char* in_data, unsigned int in_size, unsigned char* out_data, unsigned int out_size) throw ()
|
||||
{
|
||||
ISequentialInStream_Array in(reinterpret_cast<const char*>(in_data), in_size);
|
||||
ISequentialOutStream_Array out(reinterpret_cast<char*>(out_data), out_size);
|
||||
|
||||
return(decompress_lzma_7z(in, in_size, out, out_size));
|
||||
}
|
|
@ -1,73 +0,0 @@
|
|||
#ifndef __COMPRESSION_BITCODER_H
|
||||
#define __COMPRESSION_BITCODER_H
|
||||
|
||||
#include "rngcoder.h"
|
||||
|
||||
namespace NCompression {
|
||||
namespace NArithmetic {
|
||||
|
||||
const int kNumBitModelTotalBits = 11;
|
||||
const UINT32 kBitModelTotal = (1 << kNumBitModelTotalBits);
|
||||
|
||||
const int kNumMoveReducingBits = 2;
|
||||
|
||||
/////////////////////////////
|
||||
// CBitModel
|
||||
|
||||
template <int aNumMoveBits>
|
||||
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 <int aNumMoveBits>
|
||||
class CBitDecoder: public CBitModel<aNumMoveBits>
|
||||
{
|
||||
public:
|
||||
UINT32 Decode(CRangeDecoder *aRangeDecoder)
|
||||
{
|
||||
UINT32 aNewBound = (aRangeDecoder->m_Range >> kNumBitModelTotalBits) * CBitModel<aNumMoveBits>::m_Probability;
|
||||
if (aRangeDecoder->m_Code < aNewBound)
|
||||
{
|
||||
aRangeDecoder->m_Range = aNewBound;
|
||||
CBitModel<aNumMoveBits>::m_Probability += (kBitModelTotal - CBitModel<aNumMoveBits>::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<aNumMoveBits>::m_Probability -= (CBitModel<aNumMoveBits>::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
|
|
@ -1,29 +0,0 @@
|
|||
/*
|
||||
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
|
||||
Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org )
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License version 2.1 as published by the Free Software Foundation.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef __ARICONST_H
|
||||
#define __ARICONST_H
|
||||
|
||||
#include "aribitcd.h"
|
||||
|
||||
|
||||
typedef NCompression::NArithmetic::CRangeDecoder CMyRangeDecoder;
|
||||
template <int aNumMoveBits> class CMyBitDecoder:
|
||||
public NCompression::NArithmetic::CBitDecoder<aNumMoveBits> {};
|
||||
|
||||
#endif
|
|
@ -1,12 +0,0 @@
|
|||
#ifndef __COMPRESSION_ARIPRICE_H
|
||||
#define __COMPRESSION_ARIPRICE_H
|
||||
|
||||
namespace NCompression {
|
||||
namespace NArithmetic {
|
||||
|
||||
const UINT32 kNumBitPriceShiftBits = 6;
|
||||
const UINT32 kBitPrice = 1 << kNumBitPriceShiftBits;
|
||||
|
||||
}}
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue