Compare commits

..

3 Commits
v048 ... v051

Author SHA1 Message Date
byuu
b6a85353bf Update to bsnes v051 release.
Starting with this release, I wish to take bsnes in a new direction. It has always excelled in accuracy, as the only SNES emulator to offer a full 100% compatibility rate with all known commercial software. But over the years, it has also gained an impressive array of features and enhancements not found anywhere else. It is also the only actively developed SNES emulator with rapid, periodic releases. Its only achilles heel is the steep system requirements, which is quickly being overcome by aggressive new optimizations and steadily-increasing hardware speeds.
In an effort to make bsnes even more accessible to everyone, starting with this release, bsnes is now fully open source software, licensed under the terms of the GNU General Public License. I would like to work toward positioning bsnes as a truly general use emulator, and would welcome any help with this.
Specifically, I am looking for an interested Debian maintainer to package bsnes for Linux users; as well as for anyone interested in helping to optimize and improve bsnes as a whole. It also seems that many still do not know about bsnes, I'd appreciate advice and help on spreading the word. Please leave a message on my forum if you are interested.
I would also welcome and support any forks that target specific areas: a speed-oriented version, a tool-assisted speedrun version, netplay bindings, and so on. As part of this targeting, I've also released a custom debugger-enabled version, which trades a bit of speed in turn for best-in-class debugging capabilities.
Please check back here over the following few days, I'll be writing up documentation explaining all of the various unique features of bsnes, as well as detailed compilation instructions for programmers.
Changelog:
    - corrected a small bug in HDMA processing; fixes College Football '97 flickering
    - corrected ROMBR and PBR SuperFX register masking; fixes Voxel demo [MooglyGuy]
    - DSP-4 driver AI bug fixed [Jonas Quinn]
    - added save state support to the S-DD1, S-RTC, DSP-1, DSP-2 and ST-0010 co-processors
    - fixed a freeze issue when the S-SMP encounters STOP and SLEEP opcodes
    - Cx4 save states no longer need floating-point values, and are thus fully portable now
    - added new custom file loading dialog; allows non-modal usage, screenshot previews and ROM info summary, among many other benefits
    - added support for IPS soft-patching
    - added blargg's File_Extractor library
    - added support for archives compressed using 7-zip, RAR and BZip2; which is in addition to existing support for Gzip, ZIP and JMA
    - state manager now properly updates the timestamp column on saves [FitzRoy]
    - added OpenGL renderer to OS X port
    - fixed system beep issue with keyboard input on OS X port
    - fixed menubar visibility issue on OS X port
    - fixed a Display handle leak on Linux port [snzzbk]
    - X-video driver now releases SHM memory properly upon exit [emon]
    - fixed Direct3D rendering issue that was blurring video on some cards [Fes]
    - enhanced window positioning code for all platforms
    - debugger is now GUI-driven instead of via command-line
    - memory hex editor is now fully usable
    - added PPU video RAM viewer to debugger
    - added S-CPU and S-SMP tracing capabilities to debugger
    - Qt version upgraded to 4.5.2, and compiled with optimizations enabled; runs faster but makes the binary slightly larger
    - too many code cleanups to list
2009-09-27 11:40:16 +00:00
byuu
c2453cb634 Update to bsnes v050 release.
I always regret having to post new releases so quickly, but a semi-major bug crept into v049. I'd rather fix it now, before I start making major changes that will need testing again. The problem was that the S-PPU was not being synchronized as often as it should have been, resulting in titles such as F-Zero and Super Mario Kart showing flickering lines here and there. This release fixes that.
This release also adds savestate support for Mega Man X2 and Mega Man X3, which utilize the Cx4 coprocessor; and it fixes a bug where input was still accepted even when the main window was minimized.
2009-08-25 16:00:26 +00:00
byuu
59b86cd3a8 Update to bsnes v049 release.
This is a maintenance release, but it offers a lot of bug-fixes and speed-ups, so it should be well worth the update. The debugger is not finished yet, so use it at your own risk. It is disabled in the binary release because breakpoint testing impacts performance. Once it is ready, I will release a separate binary with the debugger enabled.
Changelog:
    - Optimized S-PPU emulation, provides a ~10-15% speedup in normal games
    - Cleaned up cheat editor user interface
    - Added save state and export data path selections
    - Added workaround for a strange issue that caused PAL games to run at 60 fps sometimes
    - Fixed sprite caching issue; fixes SD F-1 Grand Prix
    - Fixed PPUcounter reset issue; fixes Bishoujo Janshi Suchie-Pai [Jonas Quinn]
    - Fixed scaling on scanline, Scale2x, LQ2x and HQ2x filters on hires and interlace screens
    - Fixed sizeof(bool) serialization issue for PowerPC architecture [Richard Bannister]
    - Fixed cheat code sort ordering
    - Fixed a bug with centering in fullscreen mode
    - Fixed an audio pitch bug when changing frequency
    - Fixed a volume adjust bug when frequency was exactly 32000hz
    - Fixed X-video RGB rendering bugs [thanks to tukuyomi for testing]
    - Fixed a file open dialog issue on Linux when using QGtkStyle [jensbw]
    - Fixed a memory corruption issue involving QApplication::main() [giovannibajo]
    - Added a preliminary debugger (disabled in binary releases due to associated speed hit)
    - Added S-CPU and S-SMP stepping and tracing support
    - Added read/write/execute breakpoint support
    - Added memory editor (currently it can only view memory)
    - Added screenshot capture support [kode54]
    - Save state archives are now ~60% smaller than before
    - Various code cleanup work, as usual (note: the debugger code is messy, as it is in-progress)
2009-08-22 12:09:19 +00:00
238 changed files with 4347 additions and 20207 deletions

View File

@@ -25,13 +25,13 @@ link :=
ifeq ($(platform),x)
link += -s
ruby := video.glx video.xv video.sdl video.qtimage
ruby := video.glx video.xv video.qtraster video.sdl
ruby += audio.alsa audio.openal audio.oss audio.pulseaudio audio.ao
ruby += input.sdl input.x
link += $(if $(findstring audio.openal,$(ruby)),-lopenal)
else ifeq ($(platform),osx)
ruby := video.qtimage
ruby := video.qtopengl video.qtraster
ruby += audio.openal
ruby += input.carbon
@@ -43,7 +43,7 @@ else ifeq ($(platform),win)
# statically link Qt for Windows build
link += -enable-stdcall-fixup -Wl,-enable-auto-import -Wl,-enable-runtime-pseudo-reloc
ruby := video.direct3d video.wgl video.directdraw video.gdi video.qtimage
ruby := video.direct3d video.wgl video.directdraw video.gdi video.qtraster
ruby += audio.directsound
ruby += input.rawinput input.directinput
@@ -72,26 +72,16 @@ link += $(call ifhas,audio.pulseaudio,$(ruby),-lpulse-simple)
link += $(call ifhas,input.directinput,$(ruby),-ldinput8 -ldxguid)
link += $(call ifhas,input.rawinput,$(ruby),-ldinput8 -ldxguid)
####################
### core objects ###
####################
###############
### objects ###
###############
objects := libco ruby libreader libfilter
objects := libco ruby libfilter
objects += system cartridge cheat
objects += memory smemory cpu cpucore scpu smp smpcore ssmp sdsp ppu bppu
objects += sgb superfx sa1
objects += bsx srtc sdd1 spc7110 cx4 dsp1 dsp2 dsp3 dsp4 obc1 st010 st011 st018
ifeq ($(enable_gzip),true)
objects += adler32 compress crc32 deflate gzio inffast inflate inftrees ioapi trees unzip zip zutil
flags += -DGZIP_SUPPORT
endif
ifeq ($(enable_jma),true)
objects += jma jcrc32 lzmadec 7zlzma iiostrm inbyte lzma winout
flags += -DJMA_SUPPORT
endif
######################
### implicit rules ###
######################
@@ -122,7 +112,6 @@ obj/ruby.o: lib/ruby/ruby.cpp $(call rwildcard,lib/ruby/*)
$(call compile,$(rubydef) $(rubyflags))
obj/libco.o: lib/libco/libco.c lib/libco/*
$(c) -O3 -fomit-frame-pointer -static -Ilib -c $< -o $@
obj/libreader.o: lib/libreader/libreader.cpp lib/libreader/*
obj/libfilter.o: lib/libfilter/libfilter.cpp lib/libfilter/*
#################
@@ -167,7 +156,7 @@ obj/sdsp.o: dsp/sdsp/sdsp.cpp dsp/sdsp/*
###########
obj/ppu.o : ppu/ppu.cpp ppu/*
obj/bppu.o: ppu/bppu/bppu.cpp ppu/bppu/*
obj/bppu.o: ppu/bppu/bppu.cpp $(call rwildcard,ppu/bppu/)
##############
### system ###
@@ -196,37 +185,6 @@ obj/st010.o : chip/st010/st010.cpp chip/st010/*
obj/st011.o : chip/st011/st011.cpp chip/st011/*
obj/st018.o : chip/st018/st018.cpp chip/st018/*
############
### zlib ###
############
obj/adler32.o : lib/zlib/adler32.c lib/zlib/*
obj/compress.o: lib/zlib/compress.c lib/zlib/*
obj/crc32.o : lib/zlib/crc32.c lib/zlib/*
obj/deflate.o : lib/zlib/deflate.c lib/zlib/*
obj/gzio.o : lib/zlib/gzio.c lib/zlib/*
obj/inffast.o : lib/zlib/inffast.c lib/zlib/*
obj/inflate.o : lib/zlib/inflate.c lib/zlib/*
obj/inftrees.o: lib/zlib/inftrees.c lib/zlib/*
obj/ioapi.o : lib/zlib/ioapi.c lib/zlib/*
obj/trees.o : lib/zlib/trees.c lib/zlib/*
obj/unzip.o : lib/zlib/unzip.c lib/zlib/*
obj/zip.o : lib/zlib/zip.c lib/zlib/*
obj/zutil.o : lib/zlib/zutil.c lib/zlib/*
##############
### libjma ###
##############
obj/jma.o : lib/libjma/jma.cpp lib/libjma/*
obj/jcrc32.o : lib/libjma/jcrc32.cpp lib/libjma/*
obj/lzmadec.o: lib/libjma/lzmadec.cpp lib/libjma/*
obj/7zlzma.o : lib/libjma/7zlzma.cpp lib/libjma/*
obj/iiostrm.o: lib/libjma/iiostrm.cpp lib/libjma/*
obj/inbyte.o : lib/libjma/inbyte.cpp lib/libjma/*
obj/lzma.o : lib/libjma/lzma.cpp lib/libjma/*
obj/winout.o : lib/libjma/winout.cpp lib/libjma/*
###############
### targets ###
###############
@@ -265,9 +223,5 @@ help:
@echo " mingw32-gcc - MinGW compiler"
@echo " i586-mingw32-gcc - MinGW cross compiler"
@echo ""
@echo "Available options:"
@echo " enable_gzip=[true|false] - Enable ZIP / GZ support (default=false)"
@echo " enable_jma=[true|false] - Enable JMA support (default=false)"
@echo ""
@echo "Example: $(MAKE) platform=x compiler=gcc enable_gzip=true"
@echo "Example: $(MAKE) platform=x compiler=gcc"
@echo ""

View File

@@ -1,11 +1,6 @@
static const char bsnesVersion[] = "0.048";
static const char bsnesVersion[] = "0.051";
static const char bsnesTitle[] = "bsnes";
#define BUSCORE sBus
#define CPUCORE sCPU
#define SMPCORE sSMP
#define DSPCORE sDSP
#define PPUCORE bPPU
static const unsigned bsnesSaveStateVersion = 3;
//S-DSP can be encapsulated into a state machine using #define magic
//this avoids ~2.048m co_switch() calls per second (~5% speedup)
@@ -14,6 +9,9 @@ static const char bsnesTitle[] = "bsnes";
//game genie + pro action replay code support (~2% speed hit)
#define CHEAT_SYSTEM
//enable debugging extensions (~15% speed hit)
//#define DEBUGGER
#include <libco/libco.h>
#include <nall/algorithm.hpp>

View File

@@ -71,6 +71,7 @@ void Cartridge::load(Mode cartridge_mode) {
set(crc32, ~checksum);
bus.load_cart();
system.serialize_init();
set(loaded, true);
}

View File

@@ -1,5 +1,3 @@
@mingw32-make
::@mingw32-make enable_gzip=true enable_jma=true
@pause

View File

@@ -186,7 +186,7 @@ void Cheat::disable(unsigned i) {
//===============================
void Cheat::load(string data) {
data.replace("\r\n", "\n");
data.replace("\r", "");
data.qreplace(" ", "");
lstring line;
@@ -195,17 +195,17 @@ void Cheat::load(string data) {
lstring part;
part.qsplit(",", line[i]);
if(part.size() != 3) continue;
trim(part[0], "\"");
add(part[1] == "enabled", /* code = */ part[2], /* desc = */ part[0]);
trim(part[2], "\"");
add(part[0] == "enabled", /* code = */ part[1], /* desc = */ part[2]);
}
}
string Cheat::save() const {
string data;
for(unsigned i = 0; i < code.size(); i++) {
data << "\"" << code[i].desc << "\", "
<< (code[i].enabled ? "enabled, " : "disabled, ")
<< code[i].code << "\r\n";
data << (code[i].enabled ? "enabled," : "disabled,")
<< code[i].code << ","
<< "\"" << code[i].desc << "\"\r\n";
}
return data;
}

View File

@@ -11,10 +11,11 @@ namespace SNES {
Cx4 cx4;
#include "cx4data.cpp"
#include "cx4fn.cpp"
#include "cx4oam.cpp"
#include "cx4ops.cpp"
#include "serialization.cpp"
#include "data.cpp"
#include "functions.cpp"
#include "oam.cpp"
#include "opcodes.cpp"
void Cx4::init() {
}

View File

@@ -1,4 +1,15 @@
class Cx4 : 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[0x0c00];
uint8 reg[0x0100];
@@ -15,9 +26,6 @@ private:
int16 C4WFXVal, C4WFYVal, C4WFZVal, C4WFX2Val, C4WFY2Val, C4WFDist, C4WFScale;
int16 C41FXVal, C41FYVal, C41FAngleRes, C41FDist, C41FDistVal;
double tanval;
double c4x,c4y,c4z, c4x2,c4y2,c4z2;
void C4TransfWireFrame();
void C4TransfWireFrame2();
void C4CalcWireFrame();
@@ -82,16 +90,6 @@ public:
void writeb(uint16 addr, uint8 data);
void writew(uint16 addr, uint16 data);
void writel(uint16 addr, uint32 data);
//
void init();
void enable();
void power();
void reset();
uint8 read (unsigned addr);
void write(unsigned addr, uint8 data);
};
extern Cx4 cx4;

View File

@@ -10,9 +10,10 @@
//Wireframe Helpers
void Cx4::C4TransfWireFrame() {
c4x = (double)C4WFXVal;
c4y = (double)C4WFYVal;
c4z = (double)C4WFZVal - 0x95;
double c4x = (double)C4WFXVal;
double c4y = (double)C4WFYVal;
double c4z = (double)C4WFZVal - 0x95;
double tanval, c4x2, c4y2, c4z2;
//Rotate X
tanval = -(double)C4WFX2Val * PI * 2 / 128;
@@ -52,9 +53,10 @@ void Cx4::C4CalcWireFrame() {
}
void Cx4::C4TransfWireFrame2() {
c4x = (double)C4WFXVal;
c4y = (double)C4WFYVal;
c4z = (double)C4WFZVal;
double c4x = (double)C4WFXVal;
double c4y = (double)C4WFYVal;
double c4z = (double)C4WFZVal;
double tanval, c4x2, c4y2, c4z2;
//Rotate X
tanval = -(double)C4WFX2Val * PI * 2 / 128;
@@ -140,8 +142,8 @@ void Cx4::C4DrawLine(int32 X1, int32 Y1, int16 Z1, int32 X2, int32 Y2, int16 Z2,
uint8 bit = 0x80 >> ((X1 >> 8) & 7);
ram[addr + 0x300] &= ~bit;
ram[addr + 0x301] &= ~bit;
if(Color & 1) { ram[addr + 0x300] |= bit; }
if(Color & 2) { ram[addr + 0x301] |= bit; }
if(Color & 1) ram[addr + 0x300] |= bit;
if(Color & 2) ram[addr + 0x301] |= bit;
}
X1 += X2;
Y1 += Y2;
@@ -158,22 +160,22 @@ void Cx4::C4DoScaleRotate(int row_padding) {
if(XScale & 0x8000)XScale = 0x7fff;
if(YScale & 0x8000)YScale = 0x7fff;
if(readw(0x1f80) == 0) { //no rotation
if(readw(0x1f80) == 0) { //no rotation
A = (int16)XScale;
B = 0;
C = 0;
D = (int16)YScale;
} else if(readw(0x1f80) == 128) { //90 degree rotation
} else if(readw(0x1f80) == 128) { //90 degree rotation
A = 0;
B = (int16)(-YScale);
C = (int16)XScale;
D = 0;
} else if(readw(0x1f80) == 256) { //180 degree rotation
} else if(readw(0x1f80) == 256) { //180 degree rotation
A = (int16)(-XScale);
B = 0;
C = 0;
D = (int16)(-YScale);
} else if(readw(0x1f80) == 384) { //270 degree rotation
} else if(readw(0x1f80) == 384) { //270 degree rotation
A = 0;
B = (int16)YScale;
C = (int16)(-XScale);
@@ -221,10 +223,10 @@ void Cx4::C4DoScaleRotate(int row_padding) {
}
//De-bitplanify
if(byte & 1) { ram[outidx ] |= bit; }
if(byte & 2) { ram[outidx + 1] |= bit; }
if(byte & 4) { ram[outidx + 16] |= bit; }
if(byte & 8) { ram[outidx + 17] |= bit; }
if(byte & 1) ram[outidx ] |= bit;
if(byte & 2) ram[outidx + 1] |= bit;
if(byte & 4) ram[outidx + 16] |= bit;
if(byte & 8) ram[outidx + 17] |= bit;
bit >>= 1;
if(!bit) {
@@ -232,7 +234,7 @@ void Cx4::C4DoScaleRotate(int row_padding) {
outidx += 32;
}
X += A; //Add 1 to output x => add an A and a C
X += A; //Add 1 to output x => add an A and a C
Y += C;
}
outidx += 2 + row_padding;
@@ -241,7 +243,7 @@ void Cx4::C4DoScaleRotate(int row_padding) {
} else {
outidx -= w * 4 + row_padding;
}
LineX += B; //Add 1 to output y => add a B and a D
LineX += B; //Add 1 to output y => add a B and a D
LineY += D;
}
}

View File

@@ -5,7 +5,7 @@ void Cx4::op00_00() {
uint32 oamptr = ram[0x626] << 2;
for(int32 i = 0x1fd; i > oamptr && i >= 0; i -= 4) {
//clear oam-to-be
if(i >= 0)ram[i] = 0xe0;
if(i >= 0) ram[i] = 0xe0;
}
uint16 globalx, globaly;
@@ -18,7 +18,7 @@ void Cx4::op00_00() {
globaly = readw(0x623);
oamptr2 = 0x200 + (ram[0x626] >> 2);
if(!ram[0x620])return;
if(!ram[0x620]) return;
sprcount = 128 - ram[0x626];
uint8 offset = (ram[0x626] & 3) * 2;
@@ -51,8 +51,8 @@ void Cx4::op00_00() {
ram[oamptr + 2] = sprname + bus.read(spraddr + 3);
ram[oamptr + 3] = sprattr ^ (bus.read(spraddr) & 0xc0);
ram[oamptr2] &= ~(3 << offset);
if(x & 0x100)ram[oamptr2] |= 1 << offset;
if(bus.read(spraddr) & 0x20)ram[oamptr2] |= 2 << offset;
if(x & 0x100) ram[oamptr2] |= 1 << offset;
if(bus.read(spraddr) & 0x20) ram[oamptr2] |= 2 << offset;
oamptr += 4;
sprcount--;
offset = (offset + 2) & 6;
@@ -66,12 +66,12 @@ void Cx4::op00_00() {
ram[oamptr + 2] = sprname;
ram[oamptr + 3] = sprattr;
ram[oamptr2] &= ~(3 << offset);
if(sprx & 0x100)ram[oamptr2] |= 3 << offset;
if(sprx & 0x100) ram[oamptr2] |= 3 << offset;
else ram[oamptr2] |= 2 << offset;
oamptr += 4;
sprcount--;
offset = (offset + 2) & 6;
if(!offset)oamptr2++;
if(!offset) oamptr2++;
}
}
}
@@ -165,12 +165,12 @@ void Cx4::op00_0b() {
int32 index = (y >> 11) * width * 4 + (x >> 11) * 32 + ((y >> 8) & 7) * 2;
uint8 mask = 0x80 >> ((x >> 8) & 7);
if(pixel & 1)ram[index ] |= mask;
if(pixel & 2)ram[index + 1] |= mask;
if(pixel & 4)ram[index + 16] |= mask;
if(pixel & 8)ram[index + 17] |= mask;
if(pixel & 1) ram[index ] |= mask;
if(pixel & 2) ram[index + 1] |= mask;
if(pixel & 4) ram[index + 16] |= mask;
if(pixel & 8) ram[index + 17] |= mask;
}
if(j & 1)srcptr++;
if(j & 1) srcptr++;
}
}
}

View File

@@ -33,7 +33,7 @@ void Cx4::op0d() {
C41FXVal = readw(0x1f80);
C41FYVal = readw(0x1f83);
C41FDistVal = readw(0x1f86);
tanval = sqrt(((double)C41FYVal) * ((double)C41FYVal) + ((double)C41FXVal) * ((double)C41FXVal));
double tanval = sqrt(((double)C41FYVal) * ((double)C41FYVal) + ((double)C41FXVal) * ((double)C41FXVal));
tanval = (double)C41FDistVal / tanval;
C41FYVal = (int16)(((double)C41FYVal * tanval) * 0.99);
C41FXVal = (int16)(((double)C41FXVal * tanval) * 0.98);
@@ -103,7 +103,7 @@ void Cx4::op1f() {
if(!C41FXVal) {
C41FAngleRes = (C41FYVal > 0) ? 0x080 : 0x180;
} else {
tanval = ((double)C41FYVal) / ((double)C41FXVal);
double tanval = ((double)C41FYVal) / ((double)C41FXVal);
C41FAngleRes = (short)(atan(tanval) / (PI * 2) * 512);
C41FAngleRes = C41FAngleRes;
if(C41FXVal < 0) {

View File

@@ -0,0 +1,39 @@
#ifdef CX4_CPP
void Cx4::serialize(serializer &s) {
s.array(ram);
s.array(reg);
s.integer(r0);
s.integer(r1);
s.integer(r2);
s.integer(r3);
s.integer(r4);
s.integer(r5);
s.integer(r6);
s.integer(r7);
s.integer(r8);
s.integer(r9);
s.integer(r10);
s.integer(r11);
s.integer(r12);
s.integer(r13);
s.integer(r14);
s.integer(r15);
s.integer(C4WFXVal);
s.integer(C4WFYVal);
s.integer(C4WFZVal);
s.integer(C4WFX2Val);
s.integer(C4WFY2Val);
s.integer(C4WFDist);
s.integer(C4WFScale);
s.integer(C41FXVal);
s.integer(C41FYVal);
s.integer(C41FAngleRes);
s.integer(C41FDist);
s.integer(C41FDistVal);
}
#endif

View File

@@ -5,6 +5,7 @@ namespace SNES {
DSP1 dsp1;
#include "serialization.cpp"
#include "dsp1emu.cpp"
void DSP1::init() {
@@ -78,5 +79,5 @@ void DSP1::write(unsigned addr, uint8 data) {
dsp1.setDr(data);
}
}
};
};

View File

@@ -1,10 +1,6 @@
#include "dsp1emu.hpp"
class DSP1 : public Memory {
private:
Dsp1 dsp1;
bool addr_decode(uint16 addr);
public:
void init();
void enable();
@@ -13,6 +9,12 @@ public:
uint8 read(unsigned addr);
void write(unsigned addr, uint8 data);
void serialize(serializer&);
private:
Dsp1 dsp1;
bool addr_decode(uint16 addr);
};
extern DSP1 dsp1;

View File

@@ -33,6 +33,8 @@ class Dsp1
void setDr(uint8 iDr);
void reset();
void serialize(serializer&);
private:
enum FsmMajorState {WAIT_COMMAND, READ_DATA, WRITE_DATA};
enum MaxDataAccesses {MAX_READS=7, MAX_WRITES=1024};
@@ -72,7 +74,7 @@ class Dsp1
uint8 mSr; // status register
int mSrLowByteAccess;
uint16 mDr; // "internal" representation of the data register
FsmMajorState mFsmMajorState; // current major state of the FSM
unsigned mFsmMajorState; // current major state of the FSM
uint8 mCommand; // current command processed by the FSM
uint8 mDataCounter; // #uint16 read/writes counter used by the FSM
int16 mReadBuffer[MAX_READS];

View File

@@ -0,0 +1,56 @@
#ifdef DSP1_CPP
void DSP1::serialize(serializer &s) {
dsp1.serialize(s);
}
void Dsp1::serialize(serializer &s) {
for(unsigned i = 0; i < 3; i++) {
s.array(shared.MatrixA[i]);
s.array(shared.MatrixB[i]);
s.array(shared.MatrixC[i]);
}
s.integer(shared.CentreX);
s.integer(shared.CentreY);
s.integer(shared.CentreZ);
s.integer(shared.CentreZ_C);
s.integer(shared.CentreZ_E);
s.integer(shared.VOffset);
s.integer(shared.Les);
s.integer(shared.C_Les);
s.integer(shared.E_Les);
s.integer(shared.SinAas);
s.integer(shared.CosAas);
s.integer(shared.SinAzs);
s.integer(shared.CosAzs);
s.integer(shared.SinAZS);
s.integer(shared.CosAZS);
s.integer(shared.SecAZS_C1);
s.integer(shared.SecAZS_E1);
s.integer(shared.SecAZS_C2);
s.integer(shared.SecAZS_E2);
s.integer(shared.Nx);
s.integer(shared.Ny);
s.integer(shared.Nz);
s.integer(shared.Gx);
s.integer(shared.Gy);
s.integer(shared.Gz);
s.integer(shared.Hx);
s.integer(shared.Hy);
s.integer(shared.Vx);
s.integer(shared.Vy);
s.integer(shared.Vz);
s.integer(mSr);
s.integer(mSrLowByteAccess);
s.integer(mDr);
s.integer(mFsmMajorState);
s.integer(mCommand);
s.integer(mDataCounter);
s.array(mReadBuffer);
s.array(mWriteBuffer);
s.integer(mFreeze);
}
#endif

View File

@@ -5,7 +5,8 @@ namespace SNES {
DSP2 dsp2;
#include "dsp2_op.cpp"
#include "serialization.cpp"
#include "opcodes.cpp"
void DSP2::init() {
}

View File

@@ -29,6 +29,7 @@ public:
uint8 read(unsigned addr);
void write(unsigned addr, uint8 data);
void serialize(serializer&);
DSP2();
~DSP2();

View File

@@ -0,0 +1,26 @@
#ifdef DSP2_CPP
void DSP2::serialize(serializer &s) {
s.integer(status.waiting_for_command);
s.integer(status.command);
s.integer(status.in_count);
s.integer(status.in_index);
s.integer(status.out_count);
s.integer(status.out_index);
s.array(status.parameters);
s.array(status.output);
s.integer(status.op05transparent);
s.integer(status.op05haslen);
s.integer(status.op05len);
s.integer(status.op06haslen);
s.integer(status.op06len);
s.integer(status.op09word1);
s.integer(status.op09word2);
s.integer(status.op0dhaslen);
s.integer(status.op0doutlen);
s.integer(status.op0dinlen);
}
#endif

View File

@@ -2062,9 +2062,9 @@ void DSP4SetByte()
// unknown
case 0x000A:
{
//int16 in1a = DSP4_READ_WORD();
int16 in1a = DSP4_READ_WORD();
int16 in2a = DSP4_READ_WORD();
//int16 in3a = DSP4_READ_WORD();
int16 in3a = DSP4_READ_WORD();
int16 out1a, out2a, out3a, out4a;
DSP4_OP0A(in2a, &out2a, &out1a, &out4a, &out3a);

View File

@@ -5,6 +5,7 @@ namespace SNES {
SDD1 sdd1;
#include "serialization.cpp"
#include "sdd1emu.cpp"
void SDD1::init() {}
@@ -152,11 +153,9 @@ void SDD1::write(unsigned addr, uint8 data) {
}
SDD1::SDD1() {
buffer.data = new uint8[65536];
}
SDD1::~SDD1() {
delete[] buffer.data;
}
};

View File

@@ -13,6 +13,7 @@ public:
uint8 read(unsigned addr);
void write(unsigned addr, uint8 data);
void serialize(serializer&);
SDD1();
~SDD1();
@@ -30,7 +31,7 @@ private:
SDD1emu sdd1emu;
struct {
uint8 *data; //pointer to decompressed S-DD1 data (65536 bytes)
uint8 data[65536]; //pointer to decompressed S-DD1 data
uint16 offset; //read index into S-DD1 decompression buffer
unsigned size; //length of data buffer; reads decrement counter, set ready to false at 0
bool ready; //true when data[] is valid; false to invoke sdd1emu.decompress()

View File

@@ -0,0 +1,19 @@
#ifdef SDD1_CPP
void SDD1::serialize(serializer &s) {
s.integer(sdd1_enable);
s.integer(xfer_enable);
s.array(mmc);
for(unsigned n = 0; n < 8; n++) {
s.integer(dma[n].addr);
s.integer(dma[n].size);
}
s.array(buffer.data);
s.integer(buffer.offset);
s.integer(buffer.size);
s.integer(buffer.ready);
}
#endif

View File

@@ -0,0 +1,8 @@
#ifdef SRTC_CPP
void SRTC::serialize(serializer &s) {
s.integer(rtc_mode);
s.integer(rtc_index);
}
#endif

View File

@@ -5,6 +5,8 @@ namespace SNES {
SRTC srtc;
#include "serialization.cpp"
const unsigned SRTC::months[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
void SRTC::init() {
@@ -20,7 +22,7 @@ void SRTC::power() {
}
void SRTC::reset() {
rtc_mode = RTCM_Read;
rtc_mode = RtcRead;
rtc_index = -1;
update_time();
}
@@ -159,7 +161,7 @@ uint8 SRTC::mmio_read(unsigned addr) {
addr &= 0xffff;
if(addr == 0x2800) {
if(rtc_mode != RTCM_Read) return 0x00;
if(rtc_mode != RtcRead) return 0x00;
if(rtc_index < 0) {
update_time();
@@ -183,19 +185,19 @@ void SRTC::mmio_write(unsigned addr, uint8 data) {
data &= 0x0f; //only the low four bits are used
if(data == 0x0d) {
rtc_mode = RTCM_Read;
rtc_mode = RtcRead;
rtc_index = -1;
return;
}
if(data == 0x0e) {
rtc_mode = RTCM_Command;
rtc_mode = RtcCommand;
return;
}
if(data == 0x0f) return; //unknown behavior
if(rtc_mode == RTCM_Write) {
if(rtc_mode == RtcWrite) {
if(rtc_index >= 0 && rtc_index < 12) {
memory::cartrtc.write(rtc_index++, data);
@@ -209,17 +211,17 @@ void SRTC::mmio_write(unsigned addr, uint8 data) {
memory::cartrtc.write(rtc_index++, weekday(year, month, day));
}
}
} else if(rtc_mode == RTCM_Command) {
} else if(rtc_mode == RtcCommand) {
if(data == 0) {
rtc_mode = RTCM_Write;
rtc_mode = RtcWrite;
rtc_index = 0;
} else if(data == 4) {
rtc_mode = RTCM_Ready;
rtc_mode = RtcReady;
rtc_index = -1;
for(unsigned i = 0; i < 13; i++) memory::cartrtc.write(i, 0);
} else {
//unknown behavior
rtc_mode = RTCM_Ready;
rtc_mode = RtcReady;
}
}
}

View File

@@ -1,22 +1,24 @@
class SRTC : public MMIO {
public:
void update_time();
unsigned weekday(unsigned year, unsigned month, unsigned day);
void init();
void enable();
void power();
void reset();
uint8 mmio_read (unsigned addr);
void mmio_write(unsigned addr, uint8 data);
uint8 mmio_read(unsigned addr);
void mmio_write(unsigned addr, uint8 data);
void serialize(serializer&);
SRTC();
private:
static const unsigned months[12];
enum RTC_Mode { RTCM_Ready, RTCM_Command, RTCM_Read, RTCM_Write } rtc_mode;
enum RtcMode { RtcReady, RtcCommand, RtcRead, RtcWrite };
unsigned rtc_mode;
signed rtc_index;
void update_time();
unsigned weekday(unsigned year, unsigned month, unsigned day);
};
extern SRTC srtc;

View File

@@ -0,0 +1,7 @@
#ifdef ST010_CPP
void ST010::serialize(serializer &s) {
s.array(ram);
}
#endif

View File

@@ -5,6 +5,10 @@ namespace SNES {
ST010 st010;
#include "st010_data.hpp"
#include "serialization.cpp"
#include "st010_op.cpp"
void ST010::init() {
}
@@ -13,9 +17,6 @@ void ST010::enable() {
bus.map(Bus::MapDirect, 0xe8, 0xef, 0x0000, 0x0fff, *this);
}
#include "st010_data.hpp"
#include "st010_op.cpp"
int16 ST010::sin(int16 theta) {
return sin_table[(theta >> 8) & 0xff];
}

View File

@@ -8,6 +8,8 @@ public:
uint8 read(unsigned addr);
void write(unsigned addr, uint8 data);
void serialize(serializer&);
private:
uint8 ram[0x1000];
static const int16 sin_table[256];

View File

@@ -453,7 +453,7 @@ template<int n> void SuperFX::op_jmp_r() {
//$98-9d(alt1): ljmp rN
template<int n> void SuperFX::op_ljmp_r() {
regs.pbr = regs.r[n];
regs.pbr = regs.r[n] & 0x7f;
regs.r[15] = regs.sr();
regs.cbr = regs.r[15] & 0xfff0;
cache_flush();
@@ -593,7 +593,7 @@ void SuperFX::op_ramb() {
//$df(alt3): romb
void SuperFX::op_romb() {
rombuffer_sync();
regs.rombr = regs.sr();
regs.rombr = regs.sr() & 0x7f;
regs.reset();
}

View File

@@ -91,7 +91,7 @@ void SuperFX::mmio_write(unsigned addr, uint8 data) {
} break;
case 0x3034: {
regs.pbr = data;
regs.pbr = data & 0x7f;
cache_flush();
} break;

View File

@@ -127,274 +127,274 @@ void CPUcore::disassemble_opcode(char *output) {
#define x8 (regs.e || regs.p.x)
switch(op) {
case 0x00: sprintf(t, "brk #$%.2x ", op8); break;
case 0x01: sprintf(t, "ora ($%.2x,x) [$%.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0x02: sprintf(t, "cop #$%.2x ", op8); break;
case 0x03: sprintf(t, "ora $%.2x,s [$%.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0x04: sprintf(t, "tsb $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x05: sprintf(t, "ora $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x06: sprintf(t, "asl $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x07: sprintf(t, "ora [$%.2x] [$%.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0x08: sprintf(t, "php "); break;
case 0x09: if(a8)sprintf(t, "ora #$%.2x ", op8);
else sprintf(t, "ora #$%.4x ", op16); break;
case 0x0a: sprintf(t, "asl a "); break;
case 0x0b: sprintf(t, "phd "); break;
case 0x0c: sprintf(t, "tsb $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x0d: sprintf(t, "ora $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x0e: sprintf(t, "asl $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x0f: sprintf(t, "ora $%.6x [$%.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x10: sprintf(t, "bpl $%.4x [$%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x11: sprintf(t, "ora ($%.2x),y [$%.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0x12: sprintf(t, "ora ($%.2x) [$%.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0x13: sprintf(t, "ora ($%.2x,s),y [$%.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0x14: sprintf(t, "trb $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x15: sprintf(t, "ora $%.2x,x [$%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x16: sprintf(t, "asl $%.2x,x [$%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x17: sprintf(t, "ora [$%.2x],y [$%.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0x18: sprintf(t, "clc "); break;
case 0x19: sprintf(t, "ora $%.4x,y [$%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0x1a: sprintf(t, "inc "); break;
case 0x1b: sprintf(t, "tcs "); break;
case 0x1c: sprintf(t, "trb $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x1d: sprintf(t, "ora $%.4x,x [$%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x1e: sprintf(t, "asl $%.4x,x [$%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x1f: sprintf(t, "ora $%.6x,x [$%.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0x20: sprintf(t, "jsr $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR_PC, op16)); break;
case 0x21: sprintf(t, "and ($%.2x,x) [$%.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0x22: sprintf(t, "jsl $%.6x [$%.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x23: sprintf(t, "and $%.2x,s [$%.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0x24: sprintf(t, "bit $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x25: sprintf(t, "and $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x26: sprintf(t, "rol $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x27: sprintf(t, "and [$%.2x] [$%.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0x28: sprintf(t, "plp "); break;
case 0x29: if(a8)sprintf(t, "and #$%.2x ", op8);
else sprintf(t, "and #$%.4x ", op16); break;
case 0x2a: sprintf(t, "rol a "); break;
case 0x2b: sprintf(t, "pld "); break;
case 0x2c: sprintf(t, "bit $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x2d: sprintf(t, "and $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x2e: sprintf(t, "rol $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x2f: sprintf(t, "and $%.6x [$%.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x30: sprintf(t, "bmi $%.4x [$%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x31: sprintf(t, "and ($%.2x),y [$%.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0x32: sprintf(t, "and ($%.2x) [$%.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0x33: sprintf(t, "and ($%.2x,s),y [$%.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0x34: sprintf(t, "bit $%.2x,x [$%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x35: sprintf(t, "and $%.2x,x [$%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x36: sprintf(t, "rol $%.2x,x [$%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x37: sprintf(t, "and [$%.2x],y [$%.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0x38: sprintf(t, "sec "); break;
case 0x39: sprintf(t, "and $%.4x,y [$%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0x3a: sprintf(t, "dec "); break;
case 0x3b: sprintf(t, "tsc "); break;
case 0x3c: sprintf(t, "bit $%.4x,x [$%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x3d: sprintf(t, "and $%.4x,x [$%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x3e: sprintf(t, "rol $%.4x,x [$%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x3f: sprintf(t, "and $%.6x,x [$%.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0x40: sprintf(t, "rti "); break;
case 0x41: sprintf(t, "eor ($%.2x,x) [$%.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0x42: sprintf(t, "wdm "); break;
case 0x43: sprintf(t, "eor $%.2x,s [$%.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0x44: sprintf(t, "mvp $%.2x,$%.2x ", op1, op8); break;
case 0x45: sprintf(t, "eor $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x46: sprintf(t, "lsr $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x47: sprintf(t, "eor [$%.2x] [$%.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0x48: sprintf(t, "pha "); break;
case 0x49: if(a8)sprintf(t, "eor #$%.2x ", op8);
else sprintf(t, "eor #$%.4x ", op16); break;
case 0x4a: sprintf(t, "lsr a "); break;
case 0x4b: sprintf(t, "phk "); break;
case 0x4c: sprintf(t, "jmp $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR_PC, op16)); break;
case 0x4d: sprintf(t, "eor $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x4e: sprintf(t, "lsr $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x4f: sprintf(t, "eor $%.6x [$%.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x50: sprintf(t, "bvc $%.4x [$%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x51: sprintf(t, "eor ($%.2x),y [$%.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0x52: sprintf(t, "eor ($%.2x) [$%.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0x53: sprintf(t, "eor ($%.2x,s),y [$%.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0x54: sprintf(t, "mvn $%.2x,$%.2x ", op1, op8); break;
case 0x55: sprintf(t, "eor $%.2x,x [$%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x56: sprintf(t, "lsr $%.2x,x [$%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x57: sprintf(t, "eor [$%.2x],y [$%.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0x58: sprintf(t, "cli "); break;
case 0x59: sprintf(t, "eor $%.4x,y [$%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0x5a: sprintf(t, "phy "); break;
case 0x5b: sprintf(t, "tcd "); break;
case 0x5c: sprintf(t, "jml $%.6x [$%.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x5d: sprintf(t, "eor $%.4x,x [$%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x5e: sprintf(t, "lsr $%.4x,x [$%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x5f: sprintf(t, "eor $%.6x,x [$%.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0x60: sprintf(t, "rts "); break;
case 0x61: sprintf(t, "adc ($%.2x,x) [$%.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0x62: sprintf(t, "per $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x63: sprintf(t, "adc $%.2x,s [$%.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0x64: sprintf(t, "stz $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x65: sprintf(t, "adc $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x66: sprintf(t, "ror $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x67: sprintf(t, "adc [$%.2x] [$%.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0x68: sprintf(t, "pla "); break;
case 0x69: if(a8)sprintf(t, "adc #$%.2x ", op8);
else sprintf(t, "adc #$%.4x ", op16); break;
case 0x6a: sprintf(t, "ror a "); break;
case 0x6b: sprintf(t, "rtl "); break;
case 0x6c: sprintf(t, "jmp ($%.4x) [$%.6x]", op16, decode(OPTYPE_IADDR_PC, op16)); break;
case 0x6d: sprintf(t, "adc $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x6e: sprintf(t, "ror $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x6f: sprintf(t, "adc $%.6x [$%.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x70: sprintf(t, "bvs $%.4x [$%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x71: sprintf(t, "adc ($%.2x),y [$%.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0x72: sprintf(t, "adc ($%.2x) [$%.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0x73: sprintf(t, "adc ($%.2x,s),y [$%.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0x74: sprintf(t, "stz $%.2x,x [$%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x75: sprintf(t, "adc $%.2x,x [$%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x76: sprintf(t, "ror $%.2x,x [$%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x77: sprintf(t, "adc [$%.2x],y [$%.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0x78: sprintf(t, "sei "); break;
case 0x79: sprintf(t, "adc $%.4x,y [$%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0x7a: sprintf(t, "ply "); break;
case 0x7b: sprintf(t, "tdc "); break;
case 0x7c: sprintf(t, "jmp ($%.4x,x) [$%.6x]", op16, decode(OPTYPE_IADDRX, op16)); break;
case 0x7d: sprintf(t, "adc $%.4x,x [$%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x7e: sprintf(t, "ror $%.4x,x [$%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x7f: sprintf(t, "adc $%.6x,x [$%.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0x80: sprintf(t, "bra $%.4x [$%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x81: sprintf(t, "sta ($%.2x,x) [$%.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0x82: sprintf(t, "brl $%.4x [$%.6x]", uint16(decode(OPTYPE_RELW, op16)), decode(OPTYPE_RELW, op16)); break;
case 0x83: sprintf(t, "sta $%.2x,s [$%.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0x84: sprintf(t, "sty $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x85: sprintf(t, "sta $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x86: sprintf(t, "stx $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x87: sprintf(t, "sta [$%.2x] [$%.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0x88: sprintf(t, "dey "); break;
case 0x89: if(a8)sprintf(t, "bit #$%.2x ", op8);
else sprintf(t, "bit #$%.4x ", op16); break;
case 0x8a: sprintf(t, "txa "); break;
case 0x8b: sprintf(t, "phb "); break;
case 0x8c: sprintf(t, "sty $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x8d: sprintf(t, "sta $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x8e: sprintf(t, "stx $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x8f: sprintf(t, "sta $%.6x [$%.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x90: sprintf(t, "bcc $%.4x [$%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x91: sprintf(t, "sta ($%.2x),y [$%.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0x92: sprintf(t, "sta ($%.2x) [$%.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0x93: sprintf(t, "sta ($%.2x,s),y [$%.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0x94: sprintf(t, "sty $%.2x,x [$%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x95: sprintf(t, "sta $%.2x,x [$%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x96: sprintf(t, "stx $%.2x,y [$%.6x]", op8, decode(OPTYPE_DPY, op8)); break;
case 0x97: sprintf(t, "sta [$%.2x],y [$%.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0x98: sprintf(t, "tya "); break;
case 0x99: sprintf(t, "sta $%.4x,y [$%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0x9a: sprintf(t, "txs "); break;
case 0x9b: sprintf(t, "txy "); break;
case 0x9c: sprintf(t, "stz $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x9d: sprintf(t, "sta $%.4x,x [$%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x9e: sprintf(t, "stz $%.4x,x [$%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x9f: sprintf(t, "sta $%.6x,x [$%.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0xa0: if(x8)sprintf(t, "ldy #$%.2x ", op8);
else sprintf(t, "ldy #$%.4x ", op16); break;
case 0xa1: sprintf(t, "lda ($%.2x,x) [$%.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0xa2: if(x8)sprintf(t, "ldx #$%.2x ", op8);
else sprintf(t, "ldx #$%.4x ", op16); break;
case 0xa3: sprintf(t, "lda $%.2x,s [$%.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0xa4: sprintf(t, "ldy $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xa5: sprintf(t, "lda $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xa6: sprintf(t, "ldx $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xa7: sprintf(t, "lda [$%.2x] [$%.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0xa8: sprintf(t, "tay "); break;
case 0xa9: if(a8)sprintf(t, "lda #$%.2x ", op8);
else sprintf(t, "lda #$%.4x ", op16); break;
case 0xaa: sprintf(t, "tax "); break;
case 0xab: sprintf(t, "plb "); break;
case 0xac: sprintf(t, "ldy $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xad: sprintf(t, "lda $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xae: sprintf(t, "ldx $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xaf: sprintf(t, "lda $%.6x [$%.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0xb0: sprintf(t, "bcs $%.4x [$%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0xb1: sprintf(t, "lda ($%.2x),y [$%.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0xb2: sprintf(t, "lda ($%.2x) [$%.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0xb3: sprintf(t, "lda ($%.2x,s),y [$%.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0xb4: sprintf(t, "ldy $%.2x,x [$%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xb5: sprintf(t, "lda $%.2x,x [$%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xb6: sprintf(t, "ldx $%.2x,y [$%.6x]", op8, decode(OPTYPE_DPY, op8)); break;
case 0xb7: sprintf(t, "lda [$%.2x],y [$%.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0xb8: sprintf(t, "clv "); break;
case 0xb9: sprintf(t, "lda $%.4x,y [$%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0xba: sprintf(t, "tsx "); break;
case 0xbb: sprintf(t, "tyx "); break;
case 0xbc: sprintf(t, "ldy $%.4x,x [$%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xbd: sprintf(t, "lda $%.4x,x [$%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xbe: sprintf(t, "ldx $%.4x,y [$%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0xbf: sprintf(t, "lda $%.6x,x [$%.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0xc0: if(x8)sprintf(t, "cpy #$%.2x ", op8);
else sprintf(t, "cpy #$%.4x ", op16); break;
case 0xc1: sprintf(t, "cmp ($%.2x,x) [$%.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0xc2: sprintf(t, "rep #$%.2x ", op8); break;
case 0xc3: sprintf(t, "cmp $%.2x,s [$%.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0xc4: sprintf(t, "cpy $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xc5: sprintf(t, "cmp $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xc6: sprintf(t, "dec $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xc7: sprintf(t, "cmp [$%.2x] [$%.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0xc8: sprintf(t, "iny "); break;
case 0xc9: if(a8)sprintf(t, "cmp #$%.2x ", op8);
else sprintf(t, "cmp #$%.4x ", op16); break;
case 0xca: sprintf(t, "dex "); break;
case 0xcb: sprintf(t, "wai "); break;
case 0xcc: sprintf(t, "cpy $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xcd: sprintf(t, "cmp $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xce: sprintf(t, "dec $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xcf: sprintf(t, "cmp $%.6x [$%.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0xd0: sprintf(t, "bne $%.4x [$%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0xd1: sprintf(t, "cmp ($%.2x),y [$%.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0xd2: sprintf(t, "cmp ($%.2x) [$%.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0xd3: sprintf(t, "cmp ($%.2x,s),y [$%.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0xd4: sprintf(t, "pei ($%.2x) [$%.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0xd5: sprintf(t, "cmp $%.2x,x [$%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xd6: sprintf(t, "dec $%.2x,x [$%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xd7: sprintf(t, "cmp [$%.2x],y [$%.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0xd8: sprintf(t, "cld "); break;
case 0xd9: sprintf(t, "cmp $%.4x,y [$%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0xda: sprintf(t, "phx "); break;
case 0xdb: sprintf(t, "stp "); break;
case 0xdc: sprintf(t, "jmp [$%.4x] [$%.6x]", op16, decode(OPTYPE_ILADDR, op16)); break;
case 0xdd: sprintf(t, "cmp $%.4x,x [$%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xde: sprintf(t, "dec $%.4x,x [$%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xdf: sprintf(t, "cmp $%.6x,x [$%.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0xe0: if(x8)sprintf(t, "cpx #$%.2x ", op8);
else sprintf(t, "cpx #$%.4x ", op16); break;
case 0xe1: sprintf(t, "sbc ($%.2x,x) [$%.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0xe2: sprintf(t, "sep #$%.2x ", op8); break;
case 0xe3: sprintf(t, "sbc $%.2x,s [$%.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0xe4: sprintf(t, "cpx $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xe5: sprintf(t, "sbc $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xe6: sprintf(t, "inc $%.2x [$%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xe7: sprintf(t, "sbc [$%.2x] [$%.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0xe8: sprintf(t, "inx "); break;
case 0xe9: if(a8)sprintf(t, "sbc #$%.2x ", op8);
else sprintf(t, "sbc #$%.4x ", op16); break;
case 0xea: sprintf(t, "nop "); break;
case 0xeb: sprintf(t, "xba "); break;
case 0xec: sprintf(t, "cpx $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xed: sprintf(t, "sbc $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xee: sprintf(t, "inc $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xef: sprintf(t, "sbc $%.6x [$%.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0xf0: sprintf(t, "beq $%.4x [$%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0xf1: sprintf(t, "sbc ($%.2x),y [$%.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0xf2: sprintf(t, "sbc ($%.2x) [$%.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0xf3: sprintf(t, "sbc ($%.2x,s),y [$%.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0xf4: sprintf(t, "pea $%.4x [$%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xf5: sprintf(t, "sbc $%.2x,x [$%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xf6: sprintf(t, "inc $%.2x,x [$%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xf7: sprintf(t, "sbc [$%.2x],y [$%.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0xf8: sprintf(t, "sed "); break;
case 0xf9: sprintf(t, "sbc $%.4x,y [$%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0xfa: sprintf(t, "plx "); break;
case 0xfb: sprintf(t, "xce "); break;
case 0xfc: sprintf(t, "jsr ($%.4x,x) [$%.6x]", op16, decode(OPTYPE_IADDRX, op16)); break;
case 0xfd: sprintf(t, "sbc $%.4x,x [$%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xfe: sprintf(t, "inc $%.4x,x [$%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xff: sprintf(t, "sbc $%.6x,x [$%.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0x00: sprintf(t, "brk #$%.2x ", op8); break;
case 0x01: sprintf(t, "ora ($%.2x,x) [%.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0x02: sprintf(t, "cop #$%.2x ", op8); break;
case 0x03: sprintf(t, "ora $%.2x,s [%.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0x04: sprintf(t, "tsb $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x05: sprintf(t, "ora $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x06: sprintf(t, "asl $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x07: sprintf(t, "ora [$%.2x] [%.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0x08: sprintf(t, "php "); break;
case 0x09: if(a8)sprintf(t, "ora #$%.2x ", op8);
else sprintf(t, "ora #$%.4x ", op16); break;
case 0x0a: sprintf(t, "asl a "); break;
case 0x0b: sprintf(t, "phd "); break;
case 0x0c: sprintf(t, "tsb $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x0d: sprintf(t, "ora $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x0e: sprintf(t, "asl $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x0f: sprintf(t, "ora $%.6x [%.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x10: sprintf(t, "bpl $%.4x [%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x11: sprintf(t, "ora ($%.2x),y [%.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0x12: sprintf(t, "ora ($%.2x) [%.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0x13: sprintf(t, "ora ($%.2x,s),y [%.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0x14: sprintf(t, "trb $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x15: sprintf(t, "ora $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x16: sprintf(t, "asl $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x17: sprintf(t, "ora [$%.2x],y [%.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0x18: sprintf(t, "clc "); break;
case 0x19: sprintf(t, "ora $%.4x,y [%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0x1a: sprintf(t, "inc "); break;
case 0x1b: sprintf(t, "tcs "); break;
case 0x1c: sprintf(t, "trb $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x1d: sprintf(t, "ora $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x1e: sprintf(t, "asl $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x1f: sprintf(t, "ora $%.6x,x [%.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0x20: sprintf(t, "jsr $%.4x [%.6x]", op16, decode(OPTYPE_ADDR_PC, op16)); break;
case 0x21: sprintf(t, "and ($%.2x,x) [%.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0x22: sprintf(t, "jsl $%.6x [%.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x23: sprintf(t, "and $%.2x,s [%.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0x24: sprintf(t, "bit $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x25: sprintf(t, "and $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x26: sprintf(t, "rol $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x27: sprintf(t, "and [$%.2x] [%.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0x28: sprintf(t, "plp "); break;
case 0x29: if(a8)sprintf(t, "and #$%.2x ", op8);
else sprintf(t, "and #$%.4x ", op16); break;
case 0x2a: sprintf(t, "rol a "); break;
case 0x2b: sprintf(t, "pld "); break;
case 0x2c: sprintf(t, "bit $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x2d: sprintf(t, "and $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x2e: sprintf(t, "rol $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x2f: sprintf(t, "and $%.6x [%.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x30: sprintf(t, "bmi $%.4x [%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x31: sprintf(t, "and ($%.2x),y [%.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0x32: sprintf(t, "and ($%.2x) [%.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0x33: sprintf(t, "and ($%.2x,s),y [%.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0x34: sprintf(t, "bit $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x35: sprintf(t, "and $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x36: sprintf(t, "rol $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x37: sprintf(t, "and [$%.2x],y [%.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0x38: sprintf(t, "sec "); break;
case 0x39: sprintf(t, "and $%.4x,y [%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0x3a: sprintf(t, "dec "); break;
case 0x3b: sprintf(t, "tsc "); break;
case 0x3c: sprintf(t, "bit $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x3d: sprintf(t, "and $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x3e: sprintf(t, "rol $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x3f: sprintf(t, "and $%.6x,x [%.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0x40: sprintf(t, "rti "); break;
case 0x41: sprintf(t, "eor ($%.2x,x) [%.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0x42: sprintf(t, "wdm "); break;
case 0x43: sprintf(t, "eor $%.2x,s [%.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0x44: sprintf(t, "mvp $%.2x,$%.2x ", op1, op8); break;
case 0x45: sprintf(t, "eor $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x46: sprintf(t, "lsr $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x47: sprintf(t, "eor [$%.2x] [%.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0x48: sprintf(t, "pha "); break;
case 0x49: if(a8)sprintf(t, "eor #$%.2x ", op8);
else sprintf(t, "eor #$%.4x ", op16); break;
case 0x4a: sprintf(t, "lsr a "); break;
case 0x4b: sprintf(t, "phk "); break;
case 0x4c: sprintf(t, "jmp $%.4x [%.6x]", op16, decode(OPTYPE_ADDR_PC, op16)); break;
case 0x4d: sprintf(t, "eor $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x4e: sprintf(t, "lsr $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x4f: sprintf(t, "eor $%.6x [%.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x50: sprintf(t, "bvc $%.4x [%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x51: sprintf(t, "eor ($%.2x),y [%.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0x52: sprintf(t, "eor ($%.2x) [%.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0x53: sprintf(t, "eor ($%.2x,s),y [%.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0x54: sprintf(t, "mvn $%.2x,$%.2x ", op1, op8); break;
case 0x55: sprintf(t, "eor $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x56: sprintf(t, "lsr $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x57: sprintf(t, "eor [$%.2x],y [%.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0x58: sprintf(t, "cli "); break;
case 0x59: sprintf(t, "eor $%.4x,y [%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0x5a: sprintf(t, "phy "); break;
case 0x5b: sprintf(t, "tcd "); break;
case 0x5c: sprintf(t, "jml $%.6x [%.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x5d: sprintf(t, "eor $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x5e: sprintf(t, "lsr $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x5f: sprintf(t, "eor $%.6x,x [%.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0x60: sprintf(t, "rts "); break;
case 0x61: sprintf(t, "adc ($%.2x,x) [%.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0x62: sprintf(t, "per $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x63: sprintf(t, "adc $%.2x,s [%.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0x64: sprintf(t, "stz $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x65: sprintf(t, "adc $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x66: sprintf(t, "ror $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x67: sprintf(t, "adc [$%.2x] [%.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0x68: sprintf(t, "pla "); break;
case 0x69: if(a8)sprintf(t, "adc #$%.2x ", op8);
else sprintf(t, "adc #$%.4x ", op16); break;
case 0x6a: sprintf(t, "ror a "); break;
case 0x6b: sprintf(t, "rtl "); break;
case 0x6c: sprintf(t, "jmp ($%.4x) [%.6x]", op16, decode(OPTYPE_IADDR_PC, op16)); break;
case 0x6d: sprintf(t, "adc $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x6e: sprintf(t, "ror $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x6f: sprintf(t, "adc $%.6x [%.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x70: sprintf(t, "bvs $%.4x [%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x71: sprintf(t, "adc ($%.2x),y [%.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0x72: sprintf(t, "adc ($%.2x) [%.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0x73: sprintf(t, "adc ($%.2x,s),y [%.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0x74: sprintf(t, "stz $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x75: sprintf(t, "adc $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x76: sprintf(t, "ror $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x77: sprintf(t, "adc [$%.2x],y [%.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0x78: sprintf(t, "sei "); break;
case 0x79: sprintf(t, "adc $%.4x,y [%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0x7a: sprintf(t, "ply "); break;
case 0x7b: sprintf(t, "tdc "); break;
case 0x7c: sprintf(t, "jmp ($%.4x,x) [%.6x]", op16, decode(OPTYPE_IADDRX, op16)); break;
case 0x7d: sprintf(t, "adc $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x7e: sprintf(t, "ror $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x7f: sprintf(t, "adc $%.6x,x [%.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0x80: sprintf(t, "bra $%.4x [%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x81: sprintf(t, "sta ($%.2x,x) [%.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0x82: sprintf(t, "brl $%.4x [%.6x]", uint16(decode(OPTYPE_RELW, op16)), decode(OPTYPE_RELW, op16)); break;
case 0x83: sprintf(t, "sta $%.2x,s [%.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0x84: sprintf(t, "sty $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x85: sprintf(t, "sta $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x86: sprintf(t, "stx $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0x87: sprintf(t, "sta [$%.2x] [%.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0x88: sprintf(t, "dey "); break;
case 0x89: if(a8)sprintf(t, "bit #$%.2x ", op8);
else sprintf(t, "bit #$%.4x ", op16); break;
case 0x8a: sprintf(t, "txa "); break;
case 0x8b: sprintf(t, "phb "); break;
case 0x8c: sprintf(t, "sty $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x8d: sprintf(t, "sta $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x8e: sprintf(t, "stx $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x8f: sprintf(t, "sta $%.6x [%.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0x90: sprintf(t, "bcc $%.4x [%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0x91: sprintf(t, "sta ($%.2x),y [%.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0x92: sprintf(t, "sta ($%.2x) [%.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0x93: sprintf(t, "sta ($%.2x,s),y [%.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0x94: sprintf(t, "sty $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x95: sprintf(t, "sta $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0x96: sprintf(t, "stx $%.2x,y [%.6x]", op8, decode(OPTYPE_DPY, op8)); break;
case 0x97: sprintf(t, "sta [$%.2x],y [%.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0x98: sprintf(t, "tya "); break;
case 0x99: sprintf(t, "sta $%.4x,y [%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0x9a: sprintf(t, "txs "); break;
case 0x9b: sprintf(t, "txy "); break;
case 0x9c: sprintf(t, "stz $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0x9d: sprintf(t, "sta $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x9e: sprintf(t, "stz $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0x9f: sprintf(t, "sta $%.6x,x [%.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0xa0: if(x8)sprintf(t, "ldy #$%.2x ", op8);
else sprintf(t, "ldy #$%.4x ", op16); break;
case 0xa1: sprintf(t, "lda ($%.2x,x) [%.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0xa2: if(x8)sprintf(t, "ldx #$%.2x ", op8);
else sprintf(t, "ldx #$%.4x ", op16); break;
case 0xa3: sprintf(t, "lda $%.2x,s [%.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0xa4: sprintf(t, "ldy $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xa5: sprintf(t, "lda $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xa6: sprintf(t, "ldx $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xa7: sprintf(t, "lda [$%.2x] [%.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0xa8: sprintf(t, "tay "); break;
case 0xa9: if(a8)sprintf(t, "lda #$%.2x ", op8);
else sprintf(t, "lda #$%.4x ", op16); break;
case 0xaa: sprintf(t, "tax "); break;
case 0xab: sprintf(t, "plb "); break;
case 0xac: sprintf(t, "ldy $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xad: sprintf(t, "lda $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xae: sprintf(t, "ldx $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xaf: sprintf(t, "lda $%.6x [%.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0xb0: sprintf(t, "bcs $%.4x [%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0xb1: sprintf(t, "lda ($%.2x),y [%.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0xb2: sprintf(t, "lda ($%.2x) [%.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0xb3: sprintf(t, "lda ($%.2x,s),y [%.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0xb4: sprintf(t, "ldy $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xb5: sprintf(t, "lda $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xb6: sprintf(t, "ldx $%.2x,y [%.6x]", op8, decode(OPTYPE_DPY, op8)); break;
case 0xb7: sprintf(t, "lda [$%.2x],y [%.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0xb8: sprintf(t, "clv "); break;
case 0xb9: sprintf(t, "lda $%.4x,y [%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0xba: sprintf(t, "tsx "); break;
case 0xbb: sprintf(t, "tyx "); break;
case 0xbc: sprintf(t, "ldy $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xbd: sprintf(t, "lda $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xbe: sprintf(t, "ldx $%.4x,y [%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0xbf: sprintf(t, "lda $%.6x,x [%.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0xc0: if(x8)sprintf(t, "cpy #$%.2x ", op8);
else sprintf(t, "cpy #$%.4x ", op16); break;
case 0xc1: sprintf(t, "cmp ($%.2x,x) [%.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0xc2: sprintf(t, "rep #$%.2x ", op8); break;
case 0xc3: sprintf(t, "cmp $%.2x,s [%.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0xc4: sprintf(t, "cpy $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xc5: sprintf(t, "cmp $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xc6: sprintf(t, "dec $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xc7: sprintf(t, "cmp [$%.2x] [%.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0xc8: sprintf(t, "iny "); break;
case 0xc9: if(a8)sprintf(t, "cmp #$%.2x ", op8);
else sprintf(t, "cmp #$%.4x ", op16); break;
case 0xca: sprintf(t, "dex "); break;
case 0xcb: sprintf(t, "wai "); break;
case 0xcc: sprintf(t, "cpy $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xcd: sprintf(t, "cmp $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xce: sprintf(t, "dec $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xcf: sprintf(t, "cmp $%.6x [%.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0xd0: sprintf(t, "bne $%.4x [%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0xd1: sprintf(t, "cmp ($%.2x),y [%.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0xd2: sprintf(t, "cmp ($%.2x) [%.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0xd3: sprintf(t, "cmp ($%.2x,s),y [%.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0xd4: sprintf(t, "pei ($%.2x) [%.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0xd5: sprintf(t, "cmp $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xd6: sprintf(t, "dec $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xd7: sprintf(t, "cmp [$%.2x],y [%.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0xd8: sprintf(t, "cld "); break;
case 0xd9: sprintf(t, "cmp $%.4x,y [%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0xda: sprintf(t, "phx "); break;
case 0xdb: sprintf(t, "stp "); break;
case 0xdc: sprintf(t, "jmp [$%.4x] [%.6x]", op16, decode(OPTYPE_ILADDR, op16)); break;
case 0xdd: sprintf(t, "cmp $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xde: sprintf(t, "dec $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xdf: sprintf(t, "cmp $%.6x,x [%.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
case 0xe0: if(x8)sprintf(t, "cpx #$%.2x ", op8);
else sprintf(t, "cpx #$%.4x ", op16); break;
case 0xe1: sprintf(t, "sbc ($%.2x,x) [%.6x]", op8, decode(OPTYPE_IDPX, op8)); break;
case 0xe2: sprintf(t, "sep #$%.2x ", op8); break;
case 0xe3: sprintf(t, "sbc $%.2x,s [%.6x]", op8, decode(OPTYPE_SR, op8)); break;
case 0xe4: sprintf(t, "cpx $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xe5: sprintf(t, "sbc $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xe6: sprintf(t, "inc $%.2x [%.6x]", op8, decode(OPTYPE_DP, op8)); break;
case 0xe7: sprintf(t, "sbc [$%.2x] [%.6x]", op8, decode(OPTYPE_ILDP, op8)); break;
case 0xe8: sprintf(t, "inx "); break;
case 0xe9: if(a8)sprintf(t, "sbc #$%.2x ", op8);
else sprintf(t, "sbc #$%.4x ", op16); break;
case 0xea: sprintf(t, "nop "); break;
case 0xeb: sprintf(t, "xba "); break;
case 0xec: sprintf(t, "cpx $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xed: sprintf(t, "sbc $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xee: sprintf(t, "inc $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xef: sprintf(t, "sbc $%.6x [%.6x]", op24, decode(OPTYPE_LONG, op24)); break;
case 0xf0: sprintf(t, "beq $%.4x [%.6x]", uint16(decode(OPTYPE_RELB, op8)), decode(OPTYPE_RELB, op8)); break;
case 0xf1: sprintf(t, "sbc ($%.2x),y [%.6x]", op8, decode(OPTYPE_IDPY, op8)); break;
case 0xf2: sprintf(t, "sbc ($%.2x) [%.6x]", op8, decode(OPTYPE_IDP, op8)); break;
case 0xf3: sprintf(t, "sbc ($%.2x,s),y [%.6x]", op8, decode(OPTYPE_ISRY, op8)); break;
case 0xf4: sprintf(t, "pea $%.4x [%.6x]", op16, decode(OPTYPE_ADDR, op16)); break;
case 0xf5: sprintf(t, "sbc $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xf6: sprintf(t, "inc $%.2x,x [%.6x]", op8, decode(OPTYPE_DPX, op8)); break;
case 0xf7: sprintf(t, "sbc [$%.2x],y [%.6x]", op8, decode(OPTYPE_ILDPY, op8)); break;
case 0xf8: sprintf(t, "sed "); break;
case 0xf9: sprintf(t, "sbc $%.4x,y [%.6x]", op16, decode(OPTYPE_ADDRY, op16)); break;
case 0xfa: sprintf(t, "plx "); break;
case 0xfb: sprintf(t, "xce "); break;
case 0xfc: sprintf(t, "jsr ($%.4x,x) [%.6x]", op16, decode(OPTYPE_IADDRX, op16)); break;
case 0xfd: sprintf(t, "sbc $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xfe: sprintf(t, "inc $%.4x,x [%.6x]", op16, decode(OPTYPE_ADDRX, op16)); break;
case 0xff: sprintf(t, "sbc $%.6x,x [%.6x]", op24, decode(OPTYPE_LONGX, op24)); break;
}
#undef op8
@@ -427,7 +427,7 @@ void CPUcore::disassemble_opcode(char *output) {
strcat(s, t);
strcat(s, " ");
sprintf(t, "V:%3d H:%4d", ppu.vcounter(), ppu.hcounter());
sprintf(t, "V:%3d H:%4d", cpu.vcounter(), cpu.hcounter());
strcat(s, t);
}

View File

@@ -0,0 +1,34 @@
#ifdef SCPU_CPP
void sCPUDebug::op_step() {
bool break_event = false;
if(debugger.step_cpu) {
debugger.break_event = Debugger::CPUStep;
scheduler.exit();
} else {
debugger.breakpoint_test(Debugger::Breakpoint::CPUBus, Debugger::Breakpoint::Exec, regs.pc, 0x00);
}
if(debugger.trace_cpu) {
char t[256];
disassemble_opcode(t);
debugger.tracefile.print(string() << t << "\n");
}
sCPU::op_step();
scheduler.sync_cpusmp();
}
uint8 sCPUDebug::op_read(uint32 addr) {
uint8 data = sCPU::op_read(addr);
debugger.breakpoint_test(Debugger::Breakpoint::CPUBus, Debugger::Breakpoint::Read, addr, data);
return data;
}
void sCPUDebug::op_write(uint32 addr, uint8 data) {
sCPU::op_write(addr, data);
debugger.breakpoint_test(Debugger::Breakpoint::CPUBus, Debugger::Breakpoint::Write, addr, data);
}
#endif

View File

@@ -0,0 +1,6 @@
class sCPUDebug : public sCPU {
public:
void op_step();
uint8 op_read(uint32 addr);
void op_write(uint32 addr, uint8 data);
};

View File

@@ -51,8 +51,6 @@ void sCPU::dma_transfer(bool direction, uint8 bbus, uint32 abus) {
}
}
}
cycle_edge();
}
/*****
@@ -118,6 +116,7 @@ void sCPU::dma_run() {
unsigned index = 0;
do {
dma_transfer(channel[i].direction, dma_bbus(i, index++), dma_addr(i));
cycle_edge();
} while(channel[i].dma_enabled && --channel[i].xfersize);
channel[i].dma_enabled = false;

View File

@@ -11,6 +11,6 @@ void port_write(uint8 port, uint8 data) { apu_port[port & 3] = data; }
//======================
void op_io();
uint8 op_read(uint32 addr);
void op_write(uint32 addr, uint8 data);
debugvirtual uint8 op_read(uint32 addr);
debugvirtual void op_write(uint32 addr, uint8 data);
alwaysinline unsigned speed(unsigned addr) const;

View File

@@ -3,8 +3,14 @@
#define SCPU_CPP
namespace SNES {
#include "serialization.cpp"
#if defined(DEBUGGER)
#include "debugger/debugger.cpp"
sCPUDebug cpu;
#else
sCPU cpu;
#endif
#include "serialization.cpp"
#include "dma/dma.cpp"
#include "memory/memory.cpp"
#include "mmio/mmio.cpp"
@@ -22,18 +28,27 @@ void sCPU::enter() {
if(status.nmi_pending) {
status.nmi_pending = false;
status.interrupt_vector = (regs.e == false ? 0xffea : 0xfffa);
op_irq();
} else if(status.irq_pending) {
status.irq_pending = false;
status.interrupt_vector = (regs.e == false ? 0xffee : 0xfffe);
op_irq();
} else if(status.reset_pending) {
status.reset_pending = false;
add_clocks(186);
regs.pc.l = bus.read(0xfffc);
regs.pc.h = bus.read(0xfffd);
}
op_irq();
}
tracer.trace_cpuop(); //traces CPU opcode (only if tracer is enabled)
(this->*opcode_table[op_readpc()])();
op_step();
}
}
void sCPU::op_step() {
(this->*opcode_table[op_readpc()])();
}
void sCPU::op_irq() {
op_read(regs.pc.d);
op_io();
@@ -78,9 +93,6 @@ void sCPU::reset() {
regs.wai = false;
update_table();
status.interrupt_pending = false;
status.interrupt_vector = 0xfffc; //reset vector address
mmio_reset();
dma_reset();
timing_reset();
@@ -89,9 +101,6 @@ void sCPU::reset() {
apu_port[1] = 0x00;
apu_port[2] = 0x00;
apu_port[3] = 0x00;
regs.pc.l = bus.read(0xfffc);
regs.pc.h = bus.read(0xfffd);
}
sCPU::sCPU() : event(512, bind(&sCPU::queue_event, this)) {

View File

@@ -1,6 +1,7 @@
class sCPU : public CPU, public CPUcore {
public:
void enter();
debugvirtual void op_step();
void op_irq();
bool interrupt_pending() { return status.interrupt_pending; }
@@ -35,6 +36,8 @@ public:
bool irq_pending;
bool irq_hold;
bool reset_pending;
//DMA
bool dma_active;
unsigned dma_counter;
@@ -91,4 +94,13 @@ public:
void serialize(serializer&);
sCPU();
~sCPU();
friend class sCPUDebug;
};
#if defined(DEBUGGER)
#include "debugger/debugger.hpp"
extern sCPUDebug cpu;
#else
extern sCPU cpu;
#endif

View File

@@ -28,6 +28,8 @@ void sCPU::serialize(serializer &s) {
s.integer(status.irq_pending);
s.integer(status.irq_hold);
s.integer(status.reset_pending);
s.integer(status.dma_active);
s.integer(status.dma_counter);
s.integer(status.dma_clocks);

View File

@@ -155,6 +155,10 @@ void sCPU::timing_reset() {
status.irq_pending = false;
status.irq_hold = false;
status.reset_pending = true;
status.interrupt_pending = true;
status.interrupt_vector = 0xfffc; //reset vector address
status.dma_active = false;
status.dma_counter = 0;
status.dma_clocks = 0;

View File

@@ -3,7 +3,7 @@
<head></head>
<body>
<h1>bsnes&trade; Usage Documentation</h1><br>
<h2>bsnes Usage Documentation</h2><br>
bsnes is a Super Nintendo / Super Famicom emulator that strives to provide the
most faithful hardware emulation possible. It focuses on accuracy and clean
@@ -12,49 +12,49 @@ emulator to document how the underlying hardware works. It is thus very useful
for development and research. And while it can be used for general purpose
gaming, it will require significantly more powerful hardware than a typical
emulator.
<hr>
<br>
<h2><u>Modes of Operation</u></h2><br>
<h3>Modes of Operation</h3><br>
bsnes is capable of running both in its default multi-user mode, as well as in
single-user mode.<br>
<br>
single-user mode.
<br><br>
In multi-user mode, configuration data is stored inside the user's home
directory. On Windows, this is located at "%APPDATA%/.bsnes". On other operating
systems, this is located at "~/.bsnes".<br>
<br>
systems, this is located at "~/.bsnes".
<br><br>
To enable single-user mode, create a blank "bsnes.cfg" file inside the same
folder as the bsnes executable. bsnes will then use this file to store
configuration data.
<hr>
<br>
<h2><u>Supported Filetypes</u></h2><br>
<h3>Supported Filetypes</h3><br>
<b>SFC, SMC, SWC, FIG:</b> SNES cartridge &mdash; ROM image.<br>
<b>SFC, SMC:</b> SNES cartridge &mdash; ROM image.<br>
<b>BS:</b> Satellaview BS-X flash cartridge &mdash; EEPROM image.<br>
<b>ST:</b> Sufami Turbo cartridge &mdash; ROM image.<br>
<b>SRM, PSR:</b> non-volatile memory, often used to save game data &mdash; (P)SRAM image.<br>
<b>RTC:</b> real-time clock non-volatile memory.<br>
<b>UPS:</b> patch data, used to dynamically modify cartridge of same base filename upon load.<br>
<b>CHT:</b> plain-text list of "Game Genie" / "Pro Action Replay" codes.
<hr>
<br>
<h2><u>Known Limitations</u></h2><br>
<h3>Known Limitations</h3><br>
<b>Satellaview BS-X emulation:</b> this hardware is only partially supported.
This is mostly because the satellite network it used (St. GIGA) has been shut
down. Access to this network would be required to properly reverse engineer much
of the hardware. Working around this would require game-specific hacks, which
are contrary to the design goals of this emulator. As a result, most BS-X
software will not function correctly.<br>
<br>
software will not function correctly.
<br><br>
<b>Netplay:</b> internet multiplay is not currently supported nor planned.
<hr>
<br>
<h2><u>Contributors</u></h2>
<h3>Contributors</h3><br>
&bull; Andreas Naive<br>
&bull; anomie<br>
&bull; _Demo_<br>

View File

@@ -3,85 +3,75 @@
<head></head>
<body>
<h1>bsnes&trade; Reference License</h1><br>
<b>Copyright &copy; 2004&ndash;2009 byuu<br>
All rights reserved</b>
<hr>
<h2><u>1. Definitions</u></h2><br>
The terms "reproduce", "reproduction", "distribute" and "distribution" have the
same meaning here as under U.S. copyright law.<br><br>
"The software" means this software package as a whole, including, but not
limited to, this license, binaries, source code, documentation, and data.<br><br>
"You" means the licensee of the software.<br><br>
"The licensor" means the copyright holder of the software, byuu.
<hr>
<h2><u>2. Grant of Rights</u></h2><br>
Subject to the terms of this license, the licensor grants you a
non-transferable, non-exclusive, worldwide, royalty-free copyright license to
reproduce the software for non-commercial use only, provided the software
remains unmodified, and there is no charge for the software itself, nor for the
medium upon which the software is distributed. The reproduction of modified or
derivative works of the software is strictly prohibited without the express
consent of the licensor.
<hr>
<h2><u>3. Limitations</u></h2><br>
This license does not grant you any rights to use the licensor's name, logo or
trademarks.<br>
<h2>GNU GENERAL PUBLIC LICENSE<br>
<small>Version 2, June 1991</small></h2>
<br>
The software is provided "as is", and any express or implied warranties,
including, but not limited to, the implied warranties of merchantability and
fitness for a particular purpose are disclaimed. In no event shall the licensor
be liable for any direct, indirect, incidental, special, exemplary, or
consequential damages (including, but not limited to, procurement of sbustitute
goods or services; loss of use, data, or profits; or business interruption)
however caused and on any theory of liability, whether in contract, strict
liability, or tort (including negligence or otherwise) arising in any way out of
the use of the software, even if advised of the possibility of such damage.<br>
<br>
<h3>TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION</h3><br>
In the event that this license is determined to be invalid or unenforceable, the
Grant of Rights will become null and void, and no rights shall be granted to the
licensee, within the scope of U.S. copyright law.
<hr>
<b>0.</b>
This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you".<br><br>
Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does.<br><br>
<h2><u>4. Exemptions</u></h2><br>
<b>1.</b>
You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program.<br><br>
You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee.<br><br>
The software includes the work of other copyrights holders, which is licensed
under different agreements, and exempt from this license. Below is a complete
list of all such software, and their respective copyright holders and licenses.
Note that explicit permission has been granted to the licensor to use included
software which is ordinarily not compatible with this license, such as the GPL.
<br>
<b>2.</b>
You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions:<br><br>
<ul>
<li>a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change.</li>
<li>b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License.</li>
<li>c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.)</li>
</ul>
These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it.<br><br>
Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program.<br><br>
In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License.<br><br>
<table border="1" cellpadding="3">
<tr><td><b>Name</b></td><td><b>License</b></td><td><b>Author(s)</b></td></tr>
<b>3.</b>
You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following:
<ul>
<li>a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,</li>
<li>b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or,</li>
<li>c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.)</li>
</ul>
The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable.<br><br>
If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code.<br><br>
<tr><td>Cx4 emulator</td><td></td><td>anomie, Kris Bleakley, Nach, zsKnight</td></tr>
<tr><td>DSP-1 emulator</td><td></td><td>Andreas Naive, John Weidman, Kris Bleakley, neviksti</td></tr>
<tr><td>DSP-2 emulator</td><td></td><td>Kris Bleakley</td></tr>
<tr><td>DSP-3 emulator</td><td></td><td>John Weidman, Kris Bleakley, Lancer, z80 gaiden</td></tr>
<tr><td>DSP-4 emulator</td><td></td><td>Dreamer Nom, John Weidman, Kris Bleakley, Nach, z80 gaiden</td></tr>
<tr><td>S-DD1 decompressor</td><td>Public Domain</td><td>Andreas Naive</td></tr>
<tr><td>S-DSP emulator</td><td>LGPL 2.1</td><td>Shay Green</td></tr>
<tr><td>SPC7110 decompressor</td><td>Public Domain</td><td>neviksti</td></tr>
<tr><td>ST-0010 emulator</td><td></td><td>Feather, John Weidman, Kris Bleakley, Matthew Kendora</td></tr>
<b>4.</b>
You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance.<br><br>
<tr><td>Qt toolkit</td><td>LGPL 2.1</td><td>Nokia</td></tr>
<tr><td>HQ2x filter</td><td>LGPL 2.1</td><td>MaxST</td></tr>
<tr><td>JMA decompressor</td><td>GPL 2</td><td>NSRT team</td></tr>
<tr><td>NTSC filter</td><td>LGPL 2.1</td><td>Shay Green</td></tr>
<tr><td>zlib decompressor</td><td>zlib license</td><td>zlib team</td></tr>
</table>
<b>5.</b>
You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it.<br><br>
<b>6.</b>
Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License.<br><br>
<b>7.</b>
If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program.<br><br>
If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances.<br><br>
It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice.<br><br>
This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License.<br><br>
<b>8.</b>
If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License.<br><br>
<b>9.</b>
The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns.<br><br>
Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation.<br><br>
<b>10.</b>
If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally.<br><br>
<b>NO WARRANTY</b><br><br>
<b>11.</b>
BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.<br><br>
<b>12.</b>
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.<br>
<h3>END OF TERMS AND CONDITIONS</h3>
</body>
</html>

View File

@@ -3,6 +3,8 @@
#define ADSP_CPP
namespaec SNES {
aDSP dsp;
#include "adsp_tables.cpp"
void aDSP::enter() { loop:

View File

@@ -170,3 +170,5 @@ public:
aDSP();
~aDSP();
};
extern aDSP dsp;

View File

@@ -0,0 +1,3 @@
#ifdef SDSP_CPP
#endif

View File

@@ -0,0 +1,3 @@
class sDSPDebug : public sDSP {
public:
};

View File

@@ -7,6 +7,13 @@
#define SDSP_CPP
namespace SNES {
#if defined(DEBUGGER)
#include "debugger/debugger.cpp"
sDSPDebug dsp;
#else
sDSP dsp;
#endif
#include "serialization.cpp"
#define REG(n) state.regs[r_##n]

View File

@@ -164,4 +164,13 @@ private:
void echo_28();
void echo_29();
void echo_30();
friend class sDSPDebug;
};
#if defined(DEBUGGER)
#include "debugger/debugger.hpp"
extern sDSPDebug dsp;
#else
extern sDSP dsp;
#endif

View File

@@ -1,3 +1,9 @@
#ifdef DEBUGGER
#define debugvirtual virtual
#else
#define debugvirtual
#endif
namespace SNES {
#include "memory/memory.hpp"
#include "memory/smemory/smemory.hpp"
@@ -16,12 +22,6 @@ namespace SNES {
#include "dsp/dsp.hpp"
#include "dsp/sdsp/sdsp.hpp"
extern BUSCORE bus;
extern CPUCORE cpu;
extern SMPCORE smp;
extern PPUCORE ppu;
extern DSPCORE dsp;
#include "system/system.hpp"
#include "chip/chip.hpp"
#include "cartridge/cartridge.hpp"
@@ -31,3 +31,5 @@ namespace SNES {
#include "ppu/ppu-inline.hpp"
#include "cheat/cheat-inline.hpp"
};
#undef debugvirtual

View File

@@ -1,3 +1,10 @@
//HQ2x filter
//authors: byuu and blargg
//license: public domain
//
//note: this is a clean reimplementation of the original HQ2x filter, which was
//written by Maxim Stepin (MaxSt). it is not 100% identical, but very similar.
HQ2xFilter filter_hq2x;
const uint8_t HQ2xFilter::hqTable[256] = {
@@ -87,8 +94,13 @@ alwaysinline uint16_t HQ2xFilter::blend(unsigned rule, uint16_t E, uint16_t A, u
}
void HQ2xFilter::size(unsigned &outwidth, unsigned &outheight, unsigned width, unsigned height) {
outwidth = width * 2;
outheight = height * 2;
outwidth = width;
outheight = height;
if(width <= 256 && height <= 240) {
outwidth *= 2;
outheight *= 2;
}
}
void HQ2xFilter::render(

View File

@@ -1,8 +1,13 @@
LQ2xFilter filter_lq2x;
void LQ2xFilter::size(unsigned &outwidth, unsigned &outheight, unsigned width, unsigned height) {
outwidth = width * 2;
outheight = height * 2;
outwidth = width;
outheight = height;
if(width <= 256 && height <= 240) {
outwidth *= 2;
outheight *= 2;
}
}
void LQ2xFilter::render(

View File

@@ -1,8 +1,13 @@
Scale2xFilter filter_scale2x;
void Scale2xFilter::size(unsigned &outwidth, unsigned &outheight, unsigned width, unsigned height) {
outwidth = width * 2;
outheight = height * 2;
outwidth = width;
outheight = height;
if(width <= 256 && height <= 240) {
outwidth *= 2;
outheight *= 2;
}
}
void Scale2xFilter::render(

View File

@@ -2,7 +2,7 @@ ScanlineFilter filter_scanline;
void ScanlineFilter::size(unsigned &outwidth, unsigned &outheight, unsigned width, unsigned height) {
outwidth = width;
outheight = height * 2;
outheight = height > 240 ? height : height * 2;
}
void ScanlineFilter::render(

View File

@@ -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

View File

@@ -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));
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -1,126 +0,0 @@
/*
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org )
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License version 2.1 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __BITTREECODER_H
#define __BITTREECODER_H
#include "aribitcd.h"
#include "rcdefs.h"
//////////////////////////
// CBitTreeDecoder
template <int aNumMoveBits, UINT32 m_NumBitLevels>
class CBitTreeDecoder
{
CMyBitDecoder<aNumMoveBits> m_Models[1 << m_NumBitLevels];
public:
void Init()
{
for(UINT32 i = 1; i < (1 << m_NumBitLevels); i++)
m_Models[i].Init();
}
UINT32 Decode(CMyRangeDecoder *aRangeDecoder)
{
UINT32 aModelIndex = 1;
RC_INIT_VAR
for(UINT32 aBitIndex = m_NumBitLevels; aBitIndex > 0; aBitIndex--)
{
// aModelIndex = (aModelIndex << 1) + m_Models[aModelIndex].Decode(aRangeDecoder);
RC_GETBIT(aNumMoveBits, m_Models[aModelIndex].m_Probability, aModelIndex)
}
RC_FLUSH_VAR
return aModelIndex - (1 << m_NumBitLevels);
};
};
////////////////////////////////
// CReverseBitTreeDecoder
template <int aNumMoveBits>
class CReverseBitTreeDecoder2
{
CMyBitDecoder<aNumMoveBits> *m_Models;
UINT32 m_NumBitLevels;
public:
CReverseBitTreeDecoder2(): m_Models(0) { }
~CReverseBitTreeDecoder2() { delete []m_Models; }
bool Create(UINT32 aNumBitLevels)
{
m_NumBitLevels = aNumBitLevels;
m_Models = new CMyBitDecoder<aNumMoveBits>[1 << aNumBitLevels];
return (m_Models != 0);
}
void Init()
{
UINT32 aNumModels = 1 << m_NumBitLevels;
for(UINT32 i = 1; i < aNumModels; i++)
m_Models[i].Init();
}
UINT32 Decode(CMyRangeDecoder *aRangeDecoder)
{
UINT32 aModelIndex = 1;
UINT32 aSymbol = 0;
RC_INIT_VAR
for(UINT32 aBitIndex = 0; aBitIndex < m_NumBitLevels; aBitIndex++)
{
// UINT32 aBit = m_Models[aModelIndex].Decode(aRangeDecoder);
// aModelIndex <<= 1;
// aModelIndex += aBit;
// aSymbol |= (aBit << aBitIndex);
RC_GETBIT2(aNumMoveBits, m_Models[aModelIndex].m_Probability, aModelIndex, ; , aSymbol |= (1 << aBitIndex))
}
RC_FLUSH_VAR
return aSymbol;
};
};
////////////////////////////
// CReverseBitTreeDecoder2
template <int aNumMoveBits, UINT32 m_NumBitLevels>
class CReverseBitTreeDecoder
{
CMyBitDecoder<aNumMoveBits> m_Models[1 << m_NumBitLevels];
public:
void Init()
{
for(UINT32 i = 1; i < (1 << m_NumBitLevels); i++)
m_Models[i].Init();
}
UINT32 Decode(CMyRangeDecoder *aRangeDecoder)
{
UINT32 aModelIndex = 1;
UINT32 aSymbol = 0;
RC_INIT_VAR
for(UINT32 aBitIndex = 0; aBitIndex < m_NumBitLevels; aBitIndex++)
{
// UINT32 aBit = m_Models[aModelIndex].Decode(aRangeDecoder);
// aModelIndex <<= 1;
// aModelIndex += aBit;
// aSymbol |= (aBit << aBitIndex);
RC_GETBIT2(aNumMoveBits, m_Models[aModelIndex].m_Probability, aModelIndex, ; , aSymbol |= (1 << aBitIndex))
}
RC_FLUSH_VAR
return aSymbol;
}
};
#endif

View File

@@ -1,26 +0,0 @@
/*
Copyright (C) 2004-2007 NSRT Team ( http://nsrt.edgeemu.com )
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef CRC32_H
#define CRC32_H
namespace CRC32lib
{
unsigned int CRC32(const unsigned char *, size_t, register unsigned int crc32 = 0xFFFFFFFF);
}
#endif

View File

@@ -1,132 +0,0 @@
/*
Copyright (C) 2005-2007 NSRT Team ( http://nsrt.edgeemu.com )
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org )
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License version 2.1 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "portable.h"
#include "iiostrm.h"
#include "crc32.h"
HRESULT ISequentialInStream_Array::Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize)
{
if (aSize > size)
{
aSize = size;
}
*aProcessedSize = aSize;
memcpy(aData, data, aSize);
size -= aSize;
data += aSize;
return(S_OK);
}
HRESULT ISequentialOutStream_Array::Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize)
{
if (aSize > size)
{
overflow = true;
aSize = size;
}
*aProcessedSize = aSize;
memcpy(data, aData, aSize);
size -= aSize;
data += aSize;
total += aSize;
return(S_OK);
}
HRESULT ISequentialInStream_String::Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize)
{
if (aSize > data.size())
{
aSize = data.size();
}
*aProcessedSize = aSize;
memcpy(aData, data.c_str(), aSize);
data.erase(0, aSize);
return(S_OK);
}
HRESULT ISequentialOutStream_String::Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize)
{
*aProcessedSize = aSize;
data.append((const char *)aData, aSize);
total += aSize;
return(S_OK);
}
HRESULT ISequentialInStream_Istream::Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize)
{
data.read((char *)aData, aSize);
*aProcessedSize = data.gcount();
return(S_OK);
}
HRESULT ISequentialOutStream_Ostream::Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize)
{
*aProcessedSize = aSize;
data.write((char *)aData, aSize);
total += aSize;
return(S_OK);
}
HRESULT ISequentialInStreamCRC32_Array::Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize)
{
ISequentialInStream_Array::Read(aData, aSize, aProcessedSize);
crc32 = CRC32lib::CRC32((const unsigned char *)aData, *aProcessedSize, ~crc32);
return(S_OK);
}
HRESULT ISequentialOutStreamCRC32_Array::Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize)
{
ISequentialOutStream_Array::Write(aData, aSize, aProcessedSize);
crc32 = CRC32lib::CRC32((const unsigned char *)aData, *aProcessedSize, ~crc32);
return(S_OK);
}
HRESULT ISequentialInStreamCRC32_String::Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize)
{
ISequentialInStream_String::Read(aData, aSize, aProcessedSize);
crc32 = CRC32lib::CRC32((const unsigned char *)aData, *aProcessedSize, ~crc32);
return(S_OK);
}
HRESULT ISequentialOutStreamCRC32_String::Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize)
{
ISequentialOutStream_String::Write(aData, aSize, aProcessedSize);
crc32 = CRC32lib::CRC32((const unsigned char *)aData, *aProcessedSize, ~crc32);
return(S_OK);
}
HRESULT ISequentialInStreamCRC32_Istream::Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize)
{
ISequentialInStream_Istream::Read(aData, aSize, aProcessedSize);
crc32 = CRC32lib::CRC32((const unsigned char *)aData, *aProcessedSize, ~crc32);
return(S_OK);
}
HRESULT ISequentialOutStreamCRC32_Ostream::Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize)
{
ISequentialOutStream_Ostream::Write(aData, aSize, aProcessedSize);
crc32 = CRC32lib::CRC32((const unsigned char *)aData, *aProcessedSize, ~crc32);
return(S_OK);
}

View File

@@ -1,210 +0,0 @@
/*
Copyright (C) 2005-2007 NSRT Team ( http://nsrt.edgeemu.com )
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org )
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License version 2.1 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __IINOUTSTREAMS_H
#define __IINOUTSTREAMS_H
#include <string>
#include <fstream>
#include "portable.h"
class ISequentialInStream
{
public:
virtual HRESULT Read(void *, UINT32, UINT32 *) = 0;
virtual ~ISequentialInStream() {}
};
class ISequentialInStream_Array : public ISequentialInStream
{
const char *data;
unsigned int size;
public:
ISequentialInStream_Array(const char *Adata, unsigned Asize) : data(Adata), size(Asize) { }
HRESULT Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize);
virtual ~ISequentialInStream_Array() {}
};
class ISequentialInStream_String : public ISequentialInStream
{
std::string& data;
public:
ISequentialInStream_String(std::string& Adata) : data(Adata) { }
HRESULT Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize);
virtual ~ISequentialInStream_String() {}
};
class ISequentialInStream_Istream : public ISequentialInStream
{
std::istream& data;
public:
ISequentialInStream_Istream(std::istream& Adata) : data(Adata) { }
HRESULT Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize);
virtual ~ISequentialInStream_Istream() {}
};
class ISequentialOutStream
{
public:
virtual bool overflow_get() const = 0;
virtual unsigned int size_get() const = 0;
virtual HRESULT Write(const void *, UINT32, UINT32 *) = 0;
virtual ~ISequentialOutStream() {}
};
class ISequentialOutStream_Array : public ISequentialOutStream
{
char *data;
unsigned int size;
bool overflow;
unsigned int total;
public:
ISequentialOutStream_Array(char *Adata, unsigned Asize) : data(Adata), size(Asize), overflow(false), total(0) { }
bool overflow_get() const { return(overflow); }
unsigned int size_get() const { return(total); }
HRESULT Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize);
virtual ~ISequentialOutStream_Array() {}
};
class ISequentialOutStream_String : public ISequentialOutStream
{
std::string& data;
unsigned int total;
public:
ISequentialOutStream_String(std::string& Adata) : data(Adata), total(0) { }
bool overflow_get() const { return(false); }
unsigned int size_get() const { return(total); }
HRESULT Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize);
virtual ~ISequentialOutStream_String() {}
};
class ISequentialOutStream_Ostream : public ISequentialOutStream
{
std::ostream& data;
unsigned int total;
public:
ISequentialOutStream_Ostream(std::ostream& Adata) : data(Adata), total(0) { }
bool overflow_get() const { return(false); }
unsigned int size_get() const { return(total); }
HRESULT Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize);
virtual ~ISequentialOutStream_Ostream() {}
};
class ISequentialStreamCRC32
{
protected:
unsigned int crc32;
public:
ISequentialStreamCRC32() : crc32(0) {}
unsigned int crc32_get() const { return(crc32); }
virtual ~ISequentialStreamCRC32() {}
};
class ISequentialInStreamCRC32_Array : public ISequentialInStream_Array, public ISequentialStreamCRC32
{
public:
ISequentialInStreamCRC32_Array(const char *Adata, unsigned Asize) : ISequentialInStream_Array(Adata, Asize) { }
HRESULT Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize);
virtual ~ISequentialInStreamCRC32_Array() {}
};
class ISequentialInStreamCRC32_String : public ISequentialInStream_String, public ISequentialStreamCRC32
{
public:
ISequentialInStreamCRC32_String(std::string& Adata) : ISequentialInStream_String(Adata) { }
HRESULT Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize);
virtual ~ISequentialInStreamCRC32_String() {}
};
class ISequentialInStreamCRC32_Istream : public ISequentialInStream_Istream, public ISequentialStreamCRC32
{
public:
ISequentialInStreamCRC32_Istream(std::istream& Adata) : ISequentialInStream_Istream(Adata) { }
HRESULT Read(void *aData, UINT32 aSize, UINT32 *aProcessedSize);
virtual ~ISequentialInStreamCRC32_Istream() {}
};
class ISequentialOutStreamCRC32_Array : public ISequentialOutStream_Array, public ISequentialStreamCRC32
{
public:
ISequentialOutStreamCRC32_Array(char *Adata, unsigned Asize) : ISequentialOutStream_Array(Adata, Asize) { }
HRESULT Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize);
virtual ~ISequentialOutStreamCRC32_Array() {}
};
class ISequentialOutStreamCRC32_String : public ISequentialOutStream_String, public ISequentialStreamCRC32
{
public:
ISequentialOutStreamCRC32_String(std::string& Adata) : ISequentialOutStream_String(Adata) { }
HRESULT Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize);
virtual ~ISequentialOutStreamCRC32_String() {}
};
class ISequentialOutStreamCRC32_Ostream : public ISequentialOutStream_Ostream, public ISequentialStreamCRC32
{
public:
ISequentialOutStreamCRC32_Ostream(std::ostream& Adata) : ISequentialOutStream_Ostream(Adata) { }
HRESULT Write(const void *aData, UINT32 aSize, UINT32 *aProcessedSize);
virtual ~ISequentialOutStreamCRC32_Ostream() {}
};
#endif

View File

@@ -1,60 +0,0 @@
/*
Copyright (C) 2005-2007 NSRT Team ( http://nsrt.edgeemu.com )
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org )
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License version 2.1 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "inbyte.h"
namespace NStream{
CInByte::CInByte(UINT32 aBufferSize):
m_BufferBase(0),
m_BufferSize(aBufferSize)
{
m_BufferBase = new BYTE[m_BufferSize];
}
CInByte::~CInByte()
{
delete []m_BufferBase;
}
void CInByte::Init(ISequentialInStream *aStream)
{
m_Stream = aStream;
m_ProcessedSize = 0;
m_Buffer = m_BufferBase;
m_BufferLimit = m_Buffer;
m_StreamWasExhausted = false;
}
bool CInByte::ReadBlock()
{
if (m_StreamWasExhausted)
return false;
m_ProcessedSize += (m_Buffer - m_BufferBase);
UINT32 aNumProcessedBytes;
HRESULT aResult = m_Stream->Read(m_BufferBase, m_BufferSize, &aNumProcessedBytes);
if (aResult != S_OK)
throw aResult;
m_Buffer = m_BufferBase;
m_BufferLimit = m_Buffer + aNumProcessedBytes;
m_StreamWasExhausted = (aNumProcessedBytes == 0);
return (!m_StreamWasExhausted);
}
}

View File

@@ -1,76 +0,0 @@
/*
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org )
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License version 2.1 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __STREAM_INBYTE_H
#define __STREAM_INBYTE_H
#include "iiostrm.h"
namespace NStream {
class CInByte
{
UINT64 m_ProcessedSize;
BYTE *m_BufferBase;
UINT32 m_BufferSize;
BYTE *m_Buffer;
BYTE *m_BufferLimit;
ISequentialInStream* m_Stream;
bool m_StreamWasExhausted;
bool ReadBlock();
public:
CInByte(UINT32 aBufferSize = 0x100000);
~CInByte();
void Init(ISequentialInStream *aStream);
bool ReadByte(BYTE &aByte)
{
if(m_Buffer >= m_BufferLimit)
if(!ReadBlock())
return false;
aByte = *m_Buffer++;
return true;
}
BYTE ReadByte()
{
if(m_Buffer >= m_BufferLimit)
if(!ReadBlock())
return 0x0;
return *m_Buffer++;
}
void ReadBytes(void *aData, UINT32 aSize, UINT32 &aProcessedSize)
{
for(aProcessedSize = 0; aProcessedSize < aSize; aProcessedSize++)
if (!ReadByte(((BYTE *)aData)[aProcessedSize]))
return;
}
bool ReadBytes(void *aData, UINT32 aSize)
{
UINT32 aProcessedSize;
ReadBytes(aData, aSize, aProcessedSize);
return (aProcessedSize == aSize);
}
UINT64 GetProcessedSize() const { return m_ProcessedSize + (m_Buffer - m_BufferBase); }
};
}
#endif

View File

@@ -1,80 +0,0 @@
/*
Copyright (C) 2004-2007 NSRT Team ( http://nsrt.edgeemu.com )
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdlib.h>
namespace CRC32lib
{
//Don't ask questions, this is the PKZip CRC32 table
const unsigned int crc32Table[256] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d };
//CRC32 for char arrays
unsigned int CRC32(const unsigned char *array, size_t size, register unsigned int crc32)
{
const unsigned char *end_p = array+size;
for (register const unsigned char *p = array; p < end_p; p++)
{
crc32 = ((crc32 >> 8) & 0x00FFFFFF) ^ crc32Table[(crc32 ^ *p) & 0xFF];
}
return(~crc32);
}
}

View File

@@ -1,550 +0,0 @@
/*
Copyright (C) 2005-2007 NSRT Team ( http://nsrt.edgeemu.com )
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <sstream>
#include "jma.h"
using namespace std;
#include "portable.h"
#include "7z.h"
#include "crc32.h"
namespace JMA
{
const char jma_magic[] = { 'J', 'M', 'A', 0, 'N' };
const unsigned int jma_header_length = 5;
const unsigned char jma_version = 1;
const unsigned int jma_version_length = 1;
const unsigned int jma_total_header_length = jma_header_length + jma_version_length + UINT_SIZE;
//Convert DOS/zip/JMA integer time to to time_t
time_t uint_to_time(unsigned short date, unsigned short time)
{
tm formatted_time;
formatted_time.tm_mday = date & 0x1F;
formatted_time.tm_mon = ((date >> 5) & 0xF) - 1;
formatted_time.tm_year = ((date >> 9) & 0x7f) + 80;
formatted_time.tm_sec = (time & 0x1F) * 2;
formatted_time.tm_min = (time >> 5) & 0x3F;
formatted_time.tm_hour = (time >> 11) & 0x1F;
return(mktime(&formatted_time));
}
//Retreive the file block, what else?
void jma_open::retrieve_file_block() throw(jma_errors)
{
unsigned char uint_buffer[UINT_SIZE];
unsigned char ushort_buffer[USHORT_SIZE];
//File block size is the last UINT in the file
stream.seekg(-UINT_SIZE,ios::end);
stream.read((char *)uint_buffer, UINT_SIZE);
size_t file_block_size = charp_to_uint(uint_buffer);
//Currently at the end of the file, so that's the file size
size_t jma_file_size = stream.tellg();
//The file block can't be larger than the JMA file without it's header.
//This if can probably be improved
if (file_block_size >= jma_file_size-jma_total_header_length)
{
throw(JMA_BAD_FILE);
}
//Seek to before file block so we can read the file block
stream.seekg(-((int)file_block_size+UINT_SIZE),ios::end);
//This is needed if the file block is compressed
stringstream decompressed_file_block;
//Pointer to where to read file block from (file or decompressed buffer)
istream *file_block_stream;
//Setup file info buffer and byte to read with
jma_file_info file_info;
char byte;
stream.get(byte);
if (!byte) //If file block is compressed
{
//Compressed size isn't counting the byte we just read or the UINT for compressed size
size_t compressed_size = file_block_size - (1+UINT_SIZE);
//Read decompressed size / true file block size
stream.read((char *)uint_buffer, UINT_SIZE);
file_block_size = charp_to_uint(uint_buffer);
//Setup access methods for decompression
ISequentialInStream_Istream compressed_data(stream);
ISequentialOutStream_Ostream decompressed_data(decompressed_file_block);
//Decompress the data
if (!decompress_lzma_7z(compressed_data, compressed_size, decompressed_data, file_block_size))
{
throw(JMA_DECOMPRESS_FAILED);
}
//Go to beginning, setup pointer to buffer
decompressed_file_block.seekg(0, ios::beg);
file_block_stream = &decompressed_file_block;
}
else
{
stream.putback(byte); //Putback byte, byte is part of filename, not compressed indicator
file_block_stream = &stream;
}
//Minimum file name length is 2 bytes, a char and a null
//Minimum comment length is 1 byte, a null
//There are currently 2 UINTs and 2 USHORTs per file
while (file_block_size >= 2+1+UINT_SIZE*2+USHORT_SIZE*2) //This does allow for a gap, but that's okay
{
//First stored in the file block is the file name null terminated
file_info.name = "";
file_block_stream->get(byte);
while (byte)
{
file_info.name += byte;
file_block_stream->get(byte);
}
//There must be a file name or the file is bad
if (!file_info.name.length())
{
throw(JMA_BAD_FILE);
}
//Same trick as above for the comment
file_info.comment = "";
file_block_stream->get(byte);
while (byte)
{
file_info.comment += byte;
file_block_stream->get(byte);
}
//Next is a UINT representing the file's size
file_block_stream->read((char *)uint_buffer, UINT_SIZE);
file_info.size = charp_to_uint(uint_buffer);
//Followed by CRC32
file_block_stream->read((char *)uint_buffer, UINT_SIZE);
file_info.crc32 = charp_to_uint(uint_buffer);
//Special USHORT representation of file's date
file_block_stream->read((char *)ushort_buffer, USHORT_SIZE);
file_info.date = charp_to_ushort(ushort_buffer);
//Special USHORT representation of file's time
file_block_stream->read((char *)ushort_buffer, USHORT_SIZE);
file_info.time = charp_to_ushort(ushort_buffer);
file_info.buffer = 0; //Pointing to null till we decompress files
files.push_back(file_info); //Put file info into our structure
//Subtract size of the file info we just read
file_block_size -= file_info.name.length()+file_info.comment.length()+2+UINT_SIZE*2+USHORT_SIZE*2;
}
}
//Constructor for opening JMA files for reading
jma_open::jma_open(const char *compressed_file_name) throw (jma_errors)
{
decompressed_buffer = 0;
compressed_buffer = 0;
stream.open(compressed_file_name, ios::in | ios::binary);
if (!stream.is_open())
{
throw(JMA_NO_OPEN);
}
//Header is "JMA\0N"
unsigned char header[jma_header_length];
stream.read((char *)header, jma_header_length);
if (memcmp(jma_magic, header, jma_header_length))
{
throw(JMA_BAD_FILE);
}
//Not the cleanest code but logical
stream.read((char *)header, 5);
if (*header <= jma_version)
{
chunk_size = charp_to_uint(header+1); //Chunk size is a UINT that follows version #
retrieve_file_block();
}
else
{
throw(JMA_UNSUPPORTED_VERSION);
}
}
//Destructor only has to close the stream if neccesary
jma_open::~jma_open()
{
if (stream.is_open())
{
stream.close();
}
}
//Return a vector containing useful info about the files in the JMA
vector<jma_public_file_info> jma_open::get_files_info()
{
vector<jma_public_file_info> file_info_vector;
jma_public_file_info file_info;
for (vector<jma_file_info>::iterator i = files.begin(); i != files.end(); i++)
{
file_info.name = i->name;
file_info.comment = i->comment;
file_info.size = i->size;
file_info.datetime = uint_to_time(i->date, i->time);
file_info.crc32 = i->crc32;
file_info_vector.push_back(file_info);
}
return(file_info_vector);
}
//Skip forward a given number of chunks
void jma_open::chunk_seek(unsigned int chunk_num) throw(jma_errors)
{
//Check the stream is open
if (!stream.is_open())
{
throw(JMA_NO_OPEN);
}
//Clear possible errors so the seek will work
stream.clear();
//Move forward over header
stream.seekg(jma_total_header_length, ios::beg);
unsigned char int4_buffer[UINT_SIZE];
while (chunk_num--)
{
//Read in size of chunk
stream.read((char *)int4_buffer, UINT_SIZE);
//Skip chunk plus it's CRC32
stream.seekg(charp_to_uint(int4_buffer)+UINT_SIZE, ios::cur);
}
}
//Return a vector of pointers to each file in the JMA, the buffer to hold all the files
//must be initilized outside.
vector<unsigned char *> jma_open::get_all_files(unsigned char *buffer) throw(jma_errors)
{
//If there's no stream we can't read from it, so exit
if (!stream.is_open())
{
throw(JMA_NO_OPEN);
}
//Seek to the first chunk
chunk_seek(0);
//Set the buffer that decompressed data goes to
decompressed_buffer = buffer;
//If the JMA is not solid
if (chunk_size)
{
unsigned char int4_buffer[UINT_SIZE];
size_t size = get_total_size(files);
//For each chunk in the file...
for (size_t remaining_size = size; remaining_size; remaining_size -= chunk_size)
{
//Read the compressed size
stream.read((char *)int4_buffer, UINT_SIZE);
size_t compressed_size = charp_to_uint(int4_buffer);
//Allocate memory of the correct size to hold the compressed data in the JMA
//Throw error on failure as that is unrecoverable from
try
{
compressed_buffer = new unsigned char[compressed_size];
}
catch (bad_alloc xa)
{
throw(JMA_NO_MEM_ALLOC);
}
//Read all the compressed data in
stream.read((char *)compressed_buffer, compressed_size);
//Read the expected CRC of compressed data from the file
stream.read((char *)int4_buffer, UINT_SIZE);
//If it doesn't match, throw error and cleanup memory
if (CRC32lib::CRC32(compressed_buffer, compressed_size) != charp_to_uint(int4_buffer))
{
delete[] compressed_buffer;
throw(JMA_BAD_FILE);
}
//Decompress the data, cleanup memory on failure
if (!decompress_lzma_7z(compressed_buffer, compressed_size,
decompressed_buffer+size-remaining_size,
(remaining_size > chunk_size) ? chunk_size : remaining_size))
{
delete[] compressed_buffer;
throw(JMA_DECOMPRESS_FAILED);
}
delete[] compressed_buffer;
if (remaining_size <= chunk_size) //If we just decompressed the remainder
{
break;
}
}
}
else //Solidly compressed JMA
{
unsigned char int4_buffer[UINT_SIZE];
//Read the size of the compressed data
stream.read((char *)int4_buffer, UINT_SIZE);
size_t compressed_size = charp_to_uint(int4_buffer);
//Get decompressed size
size_t size = get_total_size(files);
//Setup access methods for decompression
ISequentialInStream_Istream compressed_data(stream);
ISequentialOutStream_Array decompressed_data(reinterpret_cast<char*>(decompressed_buffer), size);
//Decompress the data
if (!decompress_lzma_7z(compressed_data, compressed_size, decompressed_data, size))
{
throw(JMA_DECOMPRESS_FAILED);
}
/*
//Allocate memory of the right size to hold the compressed data in the JMA
try
{
compressed_buffer = new unsigned char[compressed_size];
}
catch (bad_alloc xa)
{
throw(JMA_NO_MEM_ALLOC);
}
//Copy the compressed data into memory
stream.read((char *)compressed_buffer, compressed_size);
size_t size = get_total_size(files);
//Read the CRC of the compressed data
stream.read((char *)int4_buffer, UINT_SIZE);
//If it doesn't match, complain
if (CRC32lib::CRC32(compressed_buffer, compressed_size) != charp_to_uint(int4_buffer))
{
delete[] compressed_buffer;
throw(JMA_BAD_FILE);
}
//Decompress the data
if (!decompress_lzma_7z(compressed_buffer, compressed_size, decompressed_buffer, size))
{
delete[] compressed_buffer;
throw(JMA_DECOMPRESS_FAILED);
}
delete[] compressed_buffer;
*/
}
vector<unsigned char *> file_pointers;
size_t size = 0;
//For each file, add it's pointer to the vector, size is pointer offset in the buffer
for (vector<jma_file_info>::iterator i = files.begin(); i != files.end(); i++)
{
i->buffer = decompressed_buffer+size;
file_pointers.push_back(decompressed_buffer+size);
size += i->size;
}
//Return the vector of pointers
return(file_pointers);
}
//Extracts the file with a given name found in the archive to the given buffer
void jma_open::extract_file(string& name, unsigned char *buffer) throw(jma_errors)
{
if (!stream.is_open())
{
throw(JMA_NO_OPEN);
}
size_t size_to_skip = 0;
size_t our_file_size = 0;
//Search through the vector of file information
for (vector<jma_file_info>::iterator i = files.begin(); i != files.end(); i++)
{
if (i->name == name)
{
//Set the variable so we can tell we found it
our_file_size = i->size;
break;
}
//Keep a running total of size
size_to_skip += i->size;
}
if (!our_file_size) //File with the specified name was not found in the archive
{
throw(JMA_FILE_NOT_FOUND);
}
//If the JMA only contains one file, we can skip a lot of overhead
if (files.size() == 1)
{
get_all_files(buffer);
return;
}
if (chunk_size) //we are using non-solid archive..
{
unsigned int chunks_to_skip = size_to_skip / chunk_size;
//skip over requisite number of chunks
chunk_seek(chunks_to_skip);
//Allocate memory for compressed and decompressed data
unsigned char *comp_buffer = 0, *decomp_buffer = 0;
try
{
//Compressed data size is <= non compressed size
unsigned char *combined_buffer = new unsigned char[chunk_size*2];
comp_buffer = combined_buffer;
decomp_buffer = combined_buffer+chunk_size;
}
catch (bad_alloc xa)
{
throw(JMA_NO_MEM_ALLOC);
}
size_t first_chunk_offset = size_to_skip % chunk_size;
unsigned char int4_buffer[UINT_SIZE];
for (size_t i = 0; i < our_file_size;)
{
//Get size
stream.read((char *)int4_buffer, UINT_SIZE);
size_t compressed_size = charp_to_uint(int4_buffer);
//Read all the compressed data in
stream.read((char *)comp_buffer, compressed_size);
//Read the CRC of the compressed data
stream.read((char *)int4_buffer, UINT_SIZE);
//If it doesn't match, complain
if (CRC32lib::CRC32(comp_buffer, compressed_size) != charp_to_uint(int4_buffer))
{
delete[] comp_buffer;
throw(JMA_BAD_FILE);
}
//Decompress chunk
if (!decompress_lzma_7z(comp_buffer, compressed_size, decomp_buffer, chunk_size))
{
delete[] comp_buffer;
throw(JMA_DECOMPRESS_FAILED);
}
size_t copy_amount = our_file_size-i > chunk_size-first_chunk_offset ? chunk_size-first_chunk_offset : our_file_size-i;
memcpy(buffer+i, decomp_buffer+first_chunk_offset, copy_amount);
first_chunk_offset = 0; //Set to zero since this is only for the first iteration
i += copy_amount;
}
delete[] comp_buffer;
}
else //Solid JMA
{
unsigned char *decomp_buffer = 0;
try
{
decomp_buffer = new unsigned char[get_total_size(files)];
}
catch (bad_alloc xa)
{
throw(JMA_NO_MEM_ALLOC);
}
get_all_files(decomp_buffer);
memcpy(buffer, decomp_buffer+size_to_skip, our_file_size);
delete[] decomp_buffer;
}
}
bool jma_open::is_solid()
{
return(chunk_size ? false : true);
}
const char *jma_error_text(jma_errors error)
{
switch (error)
{
case JMA_NO_CREATE:
return("JMA could not be created");
case JMA_NO_MEM_ALLOC:
return("Memory for JMA could be allocated");
case JMA_NO_OPEN:
return("JMA could not be opened");
case JMA_BAD_FILE:
return("Invalid/Corrupt JMA");
case JMA_UNSUPPORTED_VERSION:
return("JMA version not supported");
case JMA_COMPRESS_FAILED:
return("JMA compression failed");
case JMA_DECOMPRESS_FAILED:
return("JMA decompression failed");
case JMA_FILE_NOT_FOUND:
return("File not found in JMA");
}
return("Unknown error");
}
}

View File

@@ -1,88 +0,0 @@
/*
Copyright (C) 2005-2007 NSRT Team ( http://nsrt.edgeemu.com )
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef JMA_H
#define JMA_H
#include <string>
#include <fstream>
#include <vector>
#include <time.h>
namespace JMA
{
enum jma_errors { JMA_NO_CREATE, JMA_NO_MEM_ALLOC, JMA_NO_OPEN, JMA_BAD_FILE,
JMA_UNSUPPORTED_VERSION, JMA_COMPRESS_FAILED, JMA_DECOMPRESS_FAILED,
JMA_FILE_NOT_FOUND };
struct jma_file_info_base
{
std::string name;
std::string comment;
size_t size;
unsigned int crc32;
};
struct jma_public_file_info : jma_file_info_base
{
time_t datetime;
};
struct jma_file_info : jma_file_info_base
{
unsigned short date;
unsigned short time;
const unsigned char *buffer;
};
template<class jma_file_type>
inline size_t get_total_size(std::vector<jma_file_type>& files)
{
size_t size = 0;
for (typename std::vector<jma_file_type>::iterator i = files.begin(); i != files.end(); i++)
{
size += i->size; //We do have a problem if this wraps around
}
return(size);
}
class jma_open
{
public:
jma_open(const char *) throw(jma_errors);
~jma_open();
std::vector<jma_public_file_info> get_files_info();
std::vector<unsigned char *> get_all_files(unsigned char *) throw(jma_errors);
void extract_file(std::string& name, unsigned char *) throw(jma_errors);
bool is_solid();
private:
std::ifstream stream;
std::vector<jma_file_info> files;
size_t chunk_size;
unsigned char *decompressed_buffer;
unsigned char *compressed_buffer;
void chunk_seek(unsigned int) throw(jma_errors);
void retrieve_file_block() throw(jma_errors);
};
const char *jma_error_text(jma_errors);
}
#endif

View File

@@ -1,93 +0,0 @@
/*
Copyright (C) 2005-2007 NSRT Team ( http://nsrt.edgeemu.com )
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org )
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License version 2.1 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __LENCODER_H
#define __LENCODER_H
#include "btreecd.h"
namespace NLength {
const UINT32 kNumPosStatesBitsMax = 4;
const int kNumPosStatesMax = (1 << kNumPosStatesBitsMax);
const int kNumPosStatesBitsEncodingMax = 4;
const int kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax);
const int kNumMoveBits = 5;
const int kNumLenBits = 3;
const int kNumLowSymbols = 1 << kNumLenBits;
const int kNumMidBits = 3;
const int kNumMidSymbols = 1 << kNumMidBits;
const int kNumHighBits = 8;
const int kNumSymbolsTotal = kNumLowSymbols + kNumMidSymbols + (1 << kNumHighBits);
const int kNumSpecSymbols = kNumLowSymbols + kNumMidSymbols;
class CDecoder
{
CMyBitDecoder<kNumMoveBits> m_Choice;
CBitTreeDecoder<kNumMoveBits, kNumLenBits> m_LowCoder[kNumPosStatesMax];
CMyBitDecoder<kNumMoveBits> m_Choice2;
CBitTreeDecoder<kNumMoveBits, kNumMidBits> m_MidCoder[kNumPosStatesMax];
CBitTreeDecoder<kNumMoveBits, kNumHighBits> m_HighCoder;
UINT32 m_NumPosStates;
public:
void Create(UINT32 aNumPosStates)
{ m_NumPosStates = aNumPosStates; }
void Init()
{
m_Choice.Init();
for (UINT32 aPosState = 0; aPosState < m_NumPosStates; aPosState++)
{
m_LowCoder[aPosState].Init();
m_MidCoder[aPosState].Init();
}
m_Choice2.Init();
m_HighCoder.Init();
}
UINT32 Decode(CMyRangeDecoder *aRangeDecoder, UINT32 aPosState)
{
if(m_Choice.Decode(aRangeDecoder) == 0)
return m_LowCoder[aPosState].Decode(aRangeDecoder);
else
{
UINT32 aSymbol = kNumLowSymbols;
if(m_Choice2.Decode(aRangeDecoder) == 0)
aSymbol += m_MidCoder[aPosState].Decode(aRangeDecoder);
else
{
aSymbol += kNumMidSymbols;
aSymbol += m_HighCoder.Decode(aRangeDecoder);
}
return aSymbol;
}
}
};
}
#endif

View File

@@ -1,122 +0,0 @@
/*
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org )
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License version 2.1 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __LITERALCODER_H
#define __LITERALCODER_H
#include "aribitcd.h"
#include "rcdefs.h"
namespace NLiteral {
const int kNumMoveBits = 5;
class CDecoder2
{
CMyBitDecoder<kNumMoveBits> m_Decoders[3][1 << 8];
public:
void Init()
{
for (int i = 0; i < 3; i++)
for (int j = 1; j < (1 << 8); j++)
m_Decoders[i][j].Init();
}
BYTE DecodeNormal(CMyRangeDecoder *aRangeDecoder)
{
UINT32 aSymbol = 1;
RC_INIT_VAR
do
{
// aSymbol = (aSymbol << 1) | m_Decoders[0][aSymbol].Decode(aRangeDecoder);
RC_GETBIT(kNumMoveBits, m_Decoders[0][aSymbol].m_Probability, aSymbol)
}
while (aSymbol < 0x100);
RC_FLUSH_VAR
return aSymbol;
}
BYTE DecodeWithMatchByte(CMyRangeDecoder *aRangeDecoder, BYTE aMatchByte)
{
UINT32 aSymbol = 1;
RC_INIT_VAR
do
{
UINT32 aMatchBit = (aMatchByte >> 7) & 1;
aMatchByte <<= 1;
// UINT32 aBit = m_Decoders[1 + aMatchBit][aSymbol].Decode(aRangeDecoder);
// aSymbol = (aSymbol << 1) | aBit;
UINT32 aBit;
RC_GETBIT2(kNumMoveBits, m_Decoders[1 + aMatchBit][aSymbol].m_Probability, aSymbol,
aBit = 0, aBit = 1)
if (aMatchBit != aBit)
{
while (aSymbol < 0x100)
{
// aSymbol = (aSymbol << 1) | m_Decoders[0][aSymbol].Decode(aRangeDecoder);
RC_GETBIT(kNumMoveBits, m_Decoders[0][aSymbol].m_Probability, aSymbol)
}
break;
}
}
while (aSymbol < 0x100);
RC_FLUSH_VAR
return aSymbol;
}
};
class CDecoder
{
CDecoder2 *m_Coders;
UINT32 m_NumPrevBits;
UINT32 m_NumPosBits;
UINT32 m_PosMask;
public:
CDecoder(): m_Coders(0) {}
~CDecoder() { Free(); }
void Free()
{
delete []m_Coders;
m_Coders = 0;
}
void Create(UINT32 aNumPosBits, UINT32 aNumPrevBits)
{
Free();
m_NumPosBits = aNumPosBits;
m_PosMask = (1 << aNumPosBits) - 1;
m_NumPrevBits = aNumPrevBits;
UINT32 aNumStates = 1 << (m_NumPrevBits + m_NumPosBits);
m_Coders = new CDecoder2[aNumStates];
}
void Init()
{
UINT32 aNumStates = 1 << (m_NumPrevBits + m_NumPosBits);
for (UINT32 i = 0; i < aNumStates; i++)
m_Coders[i].Init();
}
UINT32 GetState(UINT32 aPos, BYTE aPrevByte) const
{ return ((aPos & m_PosMask) << m_NumPrevBits) + (aPrevByte >> (8 - m_NumPrevBits)); }
BYTE DecodeNormal(CMyRangeDecoder *aRangeDecoder, UINT32 aPos, BYTE aPrevByte)
{ return m_Coders[GetState(aPos, aPrevByte)].DecodeNormal(aRangeDecoder); }
BYTE DecodeWithMatchByte(CMyRangeDecoder *aRangeDecoder, UINT32 aPos, BYTE aPrevByte, BYTE aMatchByte)
{ return m_Coders[GetState(aPos, aPrevByte)].DecodeWithMatchByte(aRangeDecoder, aMatchByte); }
};
}
#endif

View File

@@ -1,41 +0,0 @@
/*
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org )
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License version 2.1 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "lzma.h"
namespace NCompress {
namespace NLZMA {
UINT32 kDistStart[kDistTableSizeMax];
static class CConstInit
{
public:
CConstInit()
{
UINT32 aStartValue = 0;
int i;
for (i = 0; i < kDistTableSizeMax; i++)
{
kDistStart[i] = aStartValue;
aStartValue += (1 << kDistDirectBits[i]);
}
}
} g_ConstInit;
}}

View File

@@ -1,124 +0,0 @@
/*
Copyright (C) 2005-2007 NSRT Team ( http://nsrt.edgeemu.com )
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org )
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License version 2.1 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "lencoder.h"
#ifndef __LZMA_H
#define __LZMA_H
namespace NCompress {
namespace NLZMA {
const UINT32 kNumRepDistances = 4;
const BYTE kNumStates = 12;
const BYTE kLiteralNextStates[kNumStates] = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5};
const BYTE kMatchNextStates[kNumStates] = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10};
const BYTE kRepNextStates[kNumStates] = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11};
const BYTE kShortRepNextStates[kNumStates]= {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11};
class CState
{
public:
BYTE m_Index;
void Init()
{ m_Index = 0; }
void UpdateChar()
{ m_Index = kLiteralNextStates[m_Index]; }
void UpdateMatch()
{ m_Index = kMatchNextStates[m_Index]; }
void UpdateRep()
{ m_Index = kRepNextStates[m_Index]; }
void UpdateShortRep()
{ m_Index = kShortRepNextStates[m_Index]; }
};
class CBaseCoder
{
protected:
CState m_State;
BYTE m_PreviousByte;
bool m_PeviousIsMatch;
UINT32 m_RepDistances[kNumRepDistances];
void Init()
{
m_State.Init();
m_PreviousByte = 0;
m_PeviousIsMatch = false;
for(UINT32 i = 0 ; i < kNumRepDistances; i++)
m_RepDistances[i] = 0;
}
};
const int kNumPosSlotBits = 6;
const int kDicLogSizeMax = 28;
const int kDistTableSizeMax = kDicLogSizeMax * 2;
extern UINT32 kDistStart[kDistTableSizeMax];
const BYTE kDistDirectBits[kDistTableSizeMax] =
{
0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9,
10, 10, 11, 11, 12, 12, 13, 13, 14, 14, 15, 15, 16, 16, 17, 17, 18, 18, 19, 19,
20, 20, 21, 21, 22, 22, 23, 23, 24, 24, 25, 25, 26, 26
};
const UINT32 kNumLenToPosStates = 4;
inline UINT32 GetLenToPosState(UINT32 aLen)
{
aLen -= 2;
if (aLen < kNumLenToPosStates)
return aLen;
return kNumLenToPosStates - 1;
}
const int kMatchMinLen = 2;
const int kMatchMaxLen = kMatchMinLen + NLength::kNumSymbolsTotal - 1;
const int kNumAlignBits = 4;
const int kAlignTableSize = 1 << kNumAlignBits;
const UINT32 kAlignMask = (kAlignTableSize - 1);
const int kStartPosModelIndex = 4;
const int kEndPosModelIndex = 14;
const int kNumPosModels = kEndPosModelIndex - kStartPosModelIndex;
const int kNumFullDistances = 1 << (kEndPosModelIndex / 2);
const int kMainChoiceLiteralIndex = 0;
const int kMainChoiceMatchIndex = 1;
const int kMatchChoiceDistanceIndex= 0;
const int kMatchChoiceRepetitionIndex = 1;
const int kNumMoveBitsForMainChoice = 5;
const int kNumMoveBitsForPosCoders = 5;
const int kNumMoveBitsForAlignCoders = 5;
const int kNumMoveBitsForPosSlotCoder = 5;
const int kNumLitPosStatesBitsEncodingMax = 4;
const int kNumLitContextBitsMax = 8;
}}
#endif

View File

@@ -1,298 +0,0 @@
/*
Copyright (C) 2005-2007 NSRT Team ( http://nsrt.edgeemu.com )
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org )
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License version 2.1 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "portable.h"
#include "lzmadec.h"
#define RETURN_E_OUTOFMEMORY_IF_FALSE(x) { if (!(x)) return E_OUTOFMEMORY; }
namespace NCompress {
namespace NLZMA {
HRESULT CDecoder::SetDictionarySize(UINT32 aDictionarySize)
{
if (aDictionarySize > (1 << kDicLogSizeMax))
return E_INVALIDARG;
UINT32 aWindowReservSize = MyMax(aDictionarySize, UINT32(1 << 21));
if (m_DictionarySize != aDictionarySize)
{
m_OutWindowStream.Create(aDictionarySize, kMatchMaxLen, aWindowReservSize);
m_DictionarySize = aDictionarySize;
}
return S_OK;
}
HRESULT CDecoder::SetLiteralProperties(
UINT32 aLiteralPosStateBits, UINT32 aLiteralContextBits)
{
if (aLiteralPosStateBits > 8)
return E_INVALIDARG;
if (aLiteralContextBits > 8)
return E_INVALIDARG;
m_LiteralDecoder.Create(aLiteralPosStateBits, aLiteralContextBits);
return S_OK;
}
HRESULT CDecoder::SetPosBitsProperties(UINT32 aNumPosStateBits)
{
if (aNumPosStateBits > NLength::kNumPosStatesBitsMax)
return E_INVALIDARG;
UINT32 aNumPosStates = 1 << aNumPosStateBits;
m_LenDecoder.Create(aNumPosStates);
m_RepMatchLenDecoder.Create(aNumPosStates);
m_PosStateMask = aNumPosStates - 1;
return S_OK;
}
CDecoder::CDecoder():
m_DictionarySize((UINT32)-1)
{
Create();
}
HRESULT CDecoder::Create()
{
for(int i = 0; i < kNumPosModels; i++)
{
RETURN_E_OUTOFMEMORY_IF_FALSE(
m_PosDecoders[i].Create(kDistDirectBits[kStartPosModelIndex + i]));
}
return S_OK;
}
HRESULT CDecoder::Init(ISequentialInStream *anInStream,
ISequentialOutStream *anOutStream)
{
m_RangeDecoder.Init(anInStream);
m_OutWindowStream.Init(anOutStream);
int i;
for(i = 0; i < kNumStates; i++)
{
for (UINT32 j = 0; j <= m_PosStateMask; j++)
{
m_MainChoiceDecoders[i][j].Init();
m_MatchRepShortChoiceDecoders[i][j].Init();
}
m_MatchChoiceDecoders[i].Init();
m_MatchRepChoiceDecoders[i].Init();
m_MatchRep1ChoiceDecoders[i].Init();
m_MatchRep2ChoiceDecoders[i].Init();
}
m_LiteralDecoder.Init();
// m_RepMatchLenDecoder.Init();
for (i = 0; (UINT32) i < kNumLenToPosStates; i++)
m_PosSlotDecoder[i].Init();
for(i = 0; i < kNumPosModels; i++)
m_PosDecoders[i].Init();
m_LenDecoder.Init();
m_RepMatchLenDecoder.Init();
m_PosAlignDecoder.Init();
return S_OK;
}
HRESULT CDecoder::CodeReal(ISequentialInStream *anInStream,
ISequentialOutStream *anOutStream,
const UINT64 *anInSize, const UINT64 *anOutSize)
{
if (anOutSize == NULL)
return E_INVALIDARG;
Init(anInStream, anOutStream);
CState aState;
aState.Init();
bool aPeviousIsMatch = false;
BYTE aPreviousByte = 0;
UINT32 aRepDistances[kNumRepDistances];
for(UINT32 i = 0 ; i < kNumRepDistances; i++)
aRepDistances[i] = 0;
UINT64 aNowPos64 = 0;
UINT64 aSize = *anOutSize;
while(aNowPos64 < aSize)
{
UINT64 aNext = MyMin(aNowPos64 + (1 << 18), aSize);
while(aNowPos64 < aNext)
{
UINT32 aPosState = UINT32(aNowPos64) & m_PosStateMask;
if (m_MainChoiceDecoders[aState.m_Index][aPosState].Decode(&m_RangeDecoder) == (UINT32) kMainChoiceLiteralIndex)
{
// aCounts[0]++;
aState.UpdateChar();
if(aPeviousIsMatch)
{
BYTE aMatchByte = m_OutWindowStream.GetOneByte(0 - aRepDistances[0] - 1);
aPreviousByte = m_LiteralDecoder.DecodeWithMatchByte(&m_RangeDecoder,
UINT32(aNowPos64), aPreviousByte, aMatchByte);
aPeviousIsMatch = false;
}
else
aPreviousByte = m_LiteralDecoder.DecodeNormal(&m_RangeDecoder,
UINT32(aNowPos64), aPreviousByte);
m_OutWindowStream.PutOneByte(aPreviousByte);
aNowPos64++;
}
else
{
aPeviousIsMatch = true;
UINT32 aDistance, aLen;
if(m_MatchChoiceDecoders[aState.m_Index].Decode(&m_RangeDecoder) ==
(UINT32) kMatchChoiceRepetitionIndex)
{
if(m_MatchRepChoiceDecoders[aState.m_Index].Decode(&m_RangeDecoder) == 0)
{
if(m_MatchRepShortChoiceDecoders[aState.m_Index][aPosState].Decode(&m_RangeDecoder) == 0)
{
aState.UpdateShortRep();
aPreviousByte = m_OutWindowStream.GetOneByte(0 - aRepDistances[0] - 1);
m_OutWindowStream.PutOneByte(aPreviousByte);
aNowPos64++;
// aCounts[3 + 4]++;
continue;
}
// aCounts[3 + 0]++;
aDistance = aRepDistances[0];
}
else
{
if(m_MatchRep1ChoiceDecoders[aState.m_Index].Decode(&m_RangeDecoder) == 0)
{
aDistance = aRepDistances[1];
aRepDistances[1] = aRepDistances[0];
// aCounts[3 + 1]++;
}
else
{
if (m_MatchRep2ChoiceDecoders[aState.m_Index].Decode(&m_RangeDecoder) == 0)
{
// aCounts[3 + 2]++;
aDistance = aRepDistances[2];
}
else
{
// aCounts[3 + 3]++;
aDistance = aRepDistances[3];
aRepDistances[3] = aRepDistances[2];
}
aRepDistances[2] = aRepDistances[1];
aRepDistances[1] = aRepDistances[0];
}
aRepDistances[0] = aDistance;
}
aLen = m_RepMatchLenDecoder.Decode(&m_RangeDecoder, aPosState) + kMatchMinLen;
// aCounts[aLen]++;
aState.UpdateRep();
}
else
{
aLen = kMatchMinLen + m_LenDecoder.Decode(&m_RangeDecoder, aPosState);
aState.UpdateMatch();
UINT32 aPosSlot = m_PosSlotDecoder[GetLenToPosState(aLen)].Decode(&m_RangeDecoder);
// aCounts[aPosSlot]++;
if (aPosSlot >= (UINT32) kStartPosModelIndex)
{
aDistance = kDistStart[aPosSlot];
if (aPosSlot < (UINT32) kEndPosModelIndex)
aDistance += m_PosDecoders[aPosSlot - kStartPosModelIndex].Decode(&m_RangeDecoder);
else
{
aDistance += (m_RangeDecoder.DecodeDirectBits(kDistDirectBits[aPosSlot] -
kNumAlignBits) << kNumAlignBits);
aDistance += m_PosAlignDecoder.Decode(&m_RangeDecoder);
}
}
else
aDistance = aPosSlot;
aRepDistances[3] = aRepDistances[2];
aRepDistances[2] = aRepDistances[1];
aRepDistances[1] = aRepDistances[0];
aRepDistances[0] = aDistance;
// UpdateStat(aLen, aPosSlot);
}
if (aDistance >= aNowPos64)
throw E_INVALIDDATA;
m_OutWindowStream.CopyBackBlock(aDistance, aLen);
aNowPos64 += aLen;
aPreviousByte = m_OutWindowStream.GetOneByte(0 - 1);
}
}
}
return Flush();
}
HRESULT CDecoder::Code(ISequentialInStream *anInStream, ISequentialOutStream *anOutStream, const UINT64 *anInSize, const UINT64 *anOutSize)
{
try {
return CodeReal(anInStream, anOutStream, anInSize, anOutSize);
} catch (HRESULT& e) {
return e;
} catch (...) {
return E_FAIL;
}
}
HRESULT CDecoder::ReadCoderProperties(ISequentialInStream *anInStream)
{
UINT32 aNumPosStateBits;
UINT32 aLiteralPosStateBits;
UINT32 aLiteralContextBits;
UINT32 aDictionarySize;
UINT32 aProcessesedSize;
BYTE aByte;
RETURN_IF_NOT_S_OK(anInStream->Read(&aByte, sizeof(aByte), &aProcessesedSize));
if (aProcessesedSize != sizeof(aByte))
return E_INVALIDARG;
aLiteralContextBits = aByte % 9;
BYTE aRemainder = aByte / 9;
aLiteralPosStateBits = aRemainder % 5;
aNumPosStateBits = aRemainder / 5;
UINT8 uint_buffer[UINT_SIZE];
RETURN_IF_NOT_S_OK(anInStream->Read(uint_buffer, sizeof(aDictionarySize), &aProcessesedSize));
aDictionarySize = charp_to_uint(uint_buffer);
if (aProcessesedSize != sizeof(aDictionarySize))
return E_INVALIDARG;
RETURN_IF_NOT_S_OK(SetDictionarySize(aDictionarySize));
RETURN_IF_NOT_S_OK(SetLiteralProperties(aLiteralPosStateBits, aLiteralContextBits));
RETURN_IF_NOT_S_OK(SetPosBitsProperties(aNumPosStateBits));
return S_OK;
}
}}

View File

@@ -1,82 +0,0 @@
/*
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org )
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License version 2.1 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __LZARITHMETIC_DECODER_H
#define __LZARITHMETIC_DECODER_H
#include "winout.h"
#include "lzma.h"
#include "lencoder.h"
#include "litcoder.h"
namespace NCompress {
namespace NLZMA {
typedef CMyBitDecoder<kNumMoveBitsForMainChoice> CMyBitDecoder2;
class CDecoder
{
NStream::NWindow::COut m_OutWindowStream;
CMyRangeDecoder m_RangeDecoder;
CMyBitDecoder2 m_MainChoiceDecoders[kNumStates][NLength::kNumPosStatesMax];
CMyBitDecoder2 m_MatchChoiceDecoders[kNumStates];
CMyBitDecoder2 m_MatchRepChoiceDecoders[kNumStates];
CMyBitDecoder2 m_MatchRep1ChoiceDecoders[kNumStates];
CMyBitDecoder2 m_MatchRep2ChoiceDecoders[kNumStates];
CMyBitDecoder2 m_MatchRepShortChoiceDecoders[kNumStates][NLength::kNumPosStatesMax];
CBitTreeDecoder<kNumMoveBitsForPosSlotCoder, kNumPosSlotBits> m_PosSlotDecoder[kNumLenToPosStates];
CReverseBitTreeDecoder2<kNumMoveBitsForPosCoders> m_PosDecoders[kNumPosModels];
CReverseBitTreeDecoder<kNumMoveBitsForAlignCoders, kNumAlignBits> m_PosAlignDecoder;
// CBitTreeDecoder2<kNumMoveBitsForPosCoders> m_PosDecoders[kNumPosModels];
// CBitTreeDecoder<kNumMoveBitsForAlignCoders, kNumAlignBits> m_PosAlignDecoder;
NLength::CDecoder m_LenDecoder;
NLength::CDecoder m_RepMatchLenDecoder;
NLiteral::CDecoder m_LiteralDecoder;
UINT32 m_DictionarySize;
UINT32 m_PosStateMask;
HRESULT Create();
HRESULT Init(ISequentialInStream *anInStream, ISequentialOutStream *anOutStream);
HRESULT Flush() { return m_OutWindowStream.Flush(); }
HRESULT CodeReal(ISequentialInStream *anInStream, ISequentialOutStream *anOutStream, const UINT64 *anInSize, const UINT64 *anOutSize);
public:
CDecoder();
HRESULT Code(ISequentialInStream *anInStream, ISequentialOutStream *anOutStream, const UINT64 *anInSize, const UINT64 *anOutSize);
HRESULT ReadCoderProperties(ISequentialInStream *anInStream);
HRESULT SetDictionarySize(UINT32 aDictionarySize);
HRESULT SetLiteralProperties(UINT32 aLiteralPosStateBits, UINT32 aLiteralContextBits);
HRESULT SetPosBitsProperties(UINT32 aNumPosStateBits);
};
}}
#endif

View File

@@ -1,83 +0,0 @@
/*
Copyright (C) 2004-2007 NSRT Team ( http://nsrt.edgeemu.com )
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
version 2 as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __PORTABLE_H
#define __PORTABLE_H
#include <string.h>
typedef signed char INT8;
typedef unsigned char UINT8;
typedef short INT16;
typedef unsigned short UINT16;
typedef long INT32;
typedef unsigned long UINT32;
typedef long long INT64;
typedef unsigned long long UINT64;
typedef UINT8 BYTE;
typedef UINT16 WORD;
typedef UINT32 DWORD;
typedef unsigned UINT_PTR;
typedef int BOOL;
#define FALSE 0
#define TRUE 1
#define HRESULT int
#define S_OK 0
#define E_INVALIDARG -1
#define E_OUTOFMEMORY -2
#define E_FAIL -3
#define E_INTERNAL_ERROR -4
#define E_INVALIDDATA -5
template <class T> inline T MyMin(T a, T b) {
return a < b ? a : b;
}
template <class T> inline T MyMax(T a, T b) {
return a > b ? a : b;
}
#define RETURN_IF_NOT_S_OK(x) { HRESULT __aResult_ = (x); if(__aResult_ != S_OK) return __aResult_; }
#define UINT_SIZE (4)
#define USHORT_SIZE (2)
//Convert an array of 4 bytes back into an integer
inline unsigned int charp_to_uint(const unsigned char buffer[UINT_SIZE])
{
unsigned int num = (unsigned int)buffer[3];
num |= ((unsigned int)buffer[2]) << 8;
num |= ((unsigned int)buffer[1]) << 16;
num |= ((unsigned int)buffer[0]) << 24;
return(num);
}
//Convert an array of 2 bytes back into a short integer
inline unsigned short charp_to_ushort(const unsigned char buffer[USHORT_SIZE])
{
unsigned short num = (unsigned short)buffer[1];
num |= ((unsigned short)buffer[0]) << 8;
return(num);
}
#endif

View File

@@ -1,60 +0,0 @@
/*
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org )
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License version 2.1 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __RCDEFS_H
#define __RCDEFS_H
#include "aribitcd.h"
#include "ariconst.h"
#define RC_INIT_VAR \
UINT32 aRange = aRangeDecoder->m_Range; \
UINT32 aCode = aRangeDecoder->m_Code;
#define RC_FLUSH_VAR \
aRangeDecoder->m_Range = aRange; \
aRangeDecoder->m_Code = aCode;
#define RC_NORMALIZE \
if (aRange < NCompression::NArithmetic::kTopValue) \
{ \
aCode = (aCode << 8) | aRangeDecoder->m_Stream.ReadByte(); \
aRange <<= 8; }
#define RC_GETBIT2(aNumMoveBits, aProb, aModelIndex, Action0, Action1) \
{UINT32 aNewBound = (aRange >> NCompression::NArithmetic::kNumBitModelTotalBits) * aProb; \
if (aCode < aNewBound) \
{ \
Action0; \
aRange = aNewBound; \
aProb += (NCompression::NArithmetic::kBitModelTotal - aProb) >> aNumMoveBits; \
aModelIndex <<= 1; \
} \
else \
{ \
Action1; \
aRange -= aNewBound; \
aCode -= aNewBound; \
aProb -= (aProb) >> aNumMoveBits; \
aModelIndex = (aModelIndex << 1) + 1; \
}} \
RC_NORMALIZE
#define RC_GETBIT(aNumMoveBits, aProb, aModelIndex) RC_GETBIT2(aNumMoveBits, aProb, aModelIndex, ; , ;)
#endif

View File

@@ -1,143 +0,0 @@
/*
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org )
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License version 2.1 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __COMPRESSION_RANGECODER_H
#define __COMPRESSION_RANGECODER_H
#include "inbyte.h"
namespace NCompression {
namespace NArithmetic {
const UINT32 kNumTopBits = 24;
const UINT32 kTopValue = (1 << kNumTopBits);
class CRangeDecoder
{
public:
NStream::CInByte m_Stream;
UINT32 m_Range;
UINT32 m_Code;
UINT32 m_Word;
void Normalize()
{
while (m_Range < kTopValue)
{
m_Code = (m_Code << 8) | m_Stream.ReadByte();
m_Range <<= 8;
}
}
void Init(ISequentialInStream *aStream)
{
m_Stream.Init(aStream);
m_Code = 0;
m_Range = UINT32(-1);
for(int i = 0; i < 5; i++)
m_Code = (m_Code << 8) | m_Stream.ReadByte();
}
UINT32 GetThreshold(UINT32 aTotal)
{
return (m_Code) / ( m_Range /= aTotal);
}
void Decode(UINT32 aStart, UINT32 aSize, UINT32 aTotal)
{
m_Code -= aStart * m_Range;
m_Range *= aSize;
Normalize();
}
/*
UINT32 DecodeDirectBitsDiv(UINT32 aNumTotalBits)
{
m_Range >>= aNumTotalBits;
UINT32 aThreshold = m_Code / m_Range;
m_Code -= aThreshold * m_Range;
Normalize();
return aThreshold;
}
UINT32 DecodeDirectBitsDiv2(UINT32 aNumTotalBits)
{
if (aNumTotalBits <= kNumBottomBits)
return DecodeDirectBitsDiv(aNumTotalBits);
UINT32 aResult = DecodeDirectBitsDiv(aNumTotalBits - kNumBottomBits) << kNumBottomBits;
return (aResult | DecodeDirectBitsDiv(kNumBottomBits));
}
*/
UINT32 DecodeDirectBits(UINT32 aNumTotalBits)
{
UINT32 aRange = m_Range;
UINT32 aCode = m_Code;
UINT32 aResult = 0;
for (UINT32 i = aNumTotalBits; i > 0; i--)
{
aRange >>= 1;
/*
aResult <<= 1;
if (aCode >= aRange)
{
aCode -= aRange;
aResult |= 1;
}
*/
UINT32 t = (aCode - aRange) >> 31;
aCode -= aRange & (t - 1);
// aRange = aRangeTmp + ((aRange & 1) & (1 - t));
aResult = (aResult << 1) | (1 - t);
if (aRange < kTopValue)
{
aCode = (aCode << 8) | m_Stream.ReadByte();
aRange <<= 8;
}
}
m_Range = aRange;
m_Code = aCode;
return aResult;
}
UINT32 DecodeBit(UINT32 aSize0, UINT32 aNumTotalBits)
{
UINT32 aNewBound = (m_Range >> aNumTotalBits) * aSize0;
UINT32 aSymbol;
if (m_Code < aNewBound)
{
aSymbol = 0;
m_Range = aNewBound;
}
else
{
aSymbol = 1;
m_Code -= aNewBound;
m_Range -= aNewBound;
}
Normalize();
return aSymbol;
}
UINT64 GetProcessedSize() {return m_Stream.GetProcessedSize(); }
};
}}
#endif

View File

@@ -1,89 +0,0 @@
/*
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org )
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License version 2.1 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "winout.h"
namespace NStream {
namespace NWindow {
void COut::Create(UINT32 aKeepSizeBefore, UINT32 aKeepSizeAfter, UINT32 aKeepSizeReserv)
{
m_Pos = 0;
m_PosLimit = aKeepSizeReserv + aKeepSizeBefore;
m_KeepSizeBefore = aKeepSizeBefore;
m_KeepSizeAfter = aKeepSizeAfter;
m_KeepSizeReserv = aKeepSizeReserv;
m_StreamPos = 0;
m_MoveFrom = m_KeepSizeReserv;
m_WindowSize = aKeepSizeBefore;
UINT32 aBlockSize = m_KeepSizeBefore + m_KeepSizeAfter + m_KeepSizeReserv;
delete []m_Buffer;
m_Buffer = new BYTE[aBlockSize];
}
COut::~COut()
{
delete []m_Buffer;
}
void COut::SetWindowSize(UINT32 aWindowSize)
{
m_WindowSize = aWindowSize;
m_MoveFrom = m_KeepSizeReserv + m_KeepSizeBefore - aWindowSize;
}
void COut::Init(ISequentialOutStream *aStream, bool aSolid)
{
m_Stream = aStream;
if(aSolid)
m_StreamPos = m_Pos;
else
{
m_Pos = 0;
m_PosLimit = m_KeepSizeReserv + m_KeepSizeBefore;
m_StreamPos = 0;
}
}
HRESULT COut::Flush()
{
UINT32 aSize = m_Pos - m_StreamPos;
if(aSize == 0)
return S_OK;
UINT32 aProcessedSize;
HRESULT aResult = m_Stream->Write(m_Buffer + m_StreamPos, aSize, &aProcessedSize);
if (aResult != S_OK)
return aResult;
if (aSize != aProcessedSize)
return E_FAIL;
m_StreamPos = m_Pos;
return S_OK;
}
void COut::MoveBlockBackward()
{
HRESULT aResult = Flush();
if (aResult != S_OK)
throw aResult;
memmove(m_Buffer, m_Buffer + m_MoveFrom, m_WindowSize + m_KeepSizeAfter);
m_Pos -= m_MoveFrom;
m_StreamPos -= m_MoveFrom;
}
}}

View File

@@ -1,89 +0,0 @@
/*
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org )
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License version 2.1 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __STREAM_WINDOWOUT_H
#define __STREAM_WINDOWOUT_H
#include "iiostrm.h"
namespace NStream {
namespace NWindow {
// m_KeepSizeBefore: how mach BYTEs must be in buffer before m_Pos;
// m_KeepSizeAfter: how mach BYTEs must be in buffer after m_Pos;
// m_KeepSizeReserv: how mach BYTEs must be in buffer for Moving Reserv;
// must be >= aKeepSizeAfter; // test it
class COut
{
BYTE *m_Buffer;
UINT32 m_Pos;
UINT32 m_PosLimit;
UINT32 m_KeepSizeBefore;
UINT32 m_KeepSizeAfter;
UINT32 m_KeepSizeReserv;
UINT32 m_StreamPos;
UINT32 m_WindowSize;
UINT32 m_MoveFrom;
ISequentialOutStream *m_Stream;
virtual void MoveBlockBackward();
public:
COut(): m_Buffer(0), m_Stream(0) {}
virtual ~COut();
void Create(UINT32 aKeepSizeBefore,
UINT32 aKeepSizeAfter, UINT32 aKeepSizeReserv = (1<<17));
void SetWindowSize(UINT32 aWindowSize);
void Init(ISequentialOutStream *aStream, bool aSolid = false);
HRESULT Flush();
UINT32 GetCurPos() const { return m_Pos; }
const BYTE *GetPointerToCurrentPos() const { return m_Buffer + m_Pos;};
void CopyBackBlock(UINT32 aDistance, UINT32 aLen)
{
if (m_Pos >= m_PosLimit)
MoveBlockBackward();
BYTE *p = m_Buffer + m_Pos;
aDistance++;
for(UINT32 i = 0; i < aLen; i++)
p[i] = p[i - aDistance];
m_Pos += aLen;
}
void PutOneByte(BYTE aByte)
{
if (m_Pos >= m_PosLimit)
MoveBlockBackward();
m_Buffer[m_Pos++] = aByte;
}
BYTE GetOneByte(UINT32 anIndex) const
{
return m_Buffer[m_Pos + anIndex];
}
BYTE *GetBuffer() const { return m_Buffer; }
};
}}
#endif

View File

@@ -1,49 +0,0 @@
#ifdef READER_CPP
#include "filereader.hpp"
unsigned FileReader::size() {
return fp.size();
}
//This function will allocate memory even if open() fails.
//This is needed so that when SRAM files do not exist, the
//memory for the SRAM data will be allocated still.
//The memory is flushed to 0x00 when no file is opened.
uint8_t* FileReader::read(unsigned length) {
uint8_t *data = 0;
if(length == 0) {
//read the entire file into RAM
data = new(zeromemory) uint8_t[fp.size()];
if(fp.open()) fp.read(data, fp.size());
} else if(length > fp.size()) {
//read the entire file into RAM, pad the rest with 0x00s
data = new(zeromemory) uint8_t[length];
if(fp.open()) fp.read(data, fp.size());
} else { //filesize >= length
//read only what was requested
data = new(zeromemory) uint8_t[length];
if(fp.open()) fp.read(data, length);
}
return data;
}
bool FileReader::ready() {
return fp.open();
}
FileReader::FileReader(const char *fn) {
if(!fp.open(fn, file::mode_read)) return;
if(fp.size() == 0) {
//empty file
fp.close();
}
}
FileReader::~FileReader() {
if(fp.open()) fp.close();
}
#endif //ifdef READER_CPP

View File

@@ -1,12 +0,0 @@
class FileReader : public Reader {
public:
unsigned size();
uint8_t* read(unsigned length = 0);
bool ready();
FileReader(const char *fn);
~FileReader();
private:
file fp;
};

View File

@@ -1,84 +0,0 @@
#ifdef READER_CPP
#include "gzreader.hpp"
unsigned GZReader::size() {
return filesize;
}
//This function will allocate memory even if open() fails.
//This is needed so that when SRAM files do not exist, the
//memory for the SRAM data will be allocated still.
//The memory is flushed to 0x00 when no file is opened.
uint8_t* GZReader::read(unsigned length) {
uint8_t *data = 0;
if(length == 0) {
//read the entire file into RAM
data = new(zeromemory) uint8_t[filesize];
if(gp) gzread(gp, data, filesize);
} else if(length > filesize) {
//read the entire file into RAM, pad the rest with 0x00s
data = new(zeromemory) uint8_t[length];
if(gp) gzread(gp, data, filesize);
} else { //filesize >= length
//read only what was requested
data = new(zeromemory) uint8_t[length];
if(gp) gzread(gp, data, length);
}
return data;
}
bool GZReader::ready() {
return (gp != 0);
}
GZReader::GZReader(const char *fn) : gp(0) {
#if !defined(_WIN32)
fp = fopen(fn, "rb");
#else
fp = _wfopen(utf16_t(fn), L"rb");
#endif
if(!fp) return;
fseek(fp, 0, SEEK_END);
filesize = ftell(fp);
if(filesize < 4) {
//too small to be a valid GZ archive
fclose(fp);
fp = 0;
return;
}
fseek(fp, -4, SEEK_END);
unsigned gzsize;
gzsize = fgetc(fp);
gzsize |= fgetc(fp) << 8;
gzsize |= fgetc(fp) << 16;
gzsize |= fgetc(fp) << 24;
fseek(fp, 0, SEEK_SET);
//zlib does not support UTF-8 filenames on Windows,
//thus _wfopen() wrapper above + fileno() wrapper here.
gp = gzdopen(fileno(fp), "rb");
if(!gp) return;
if(gzdirect(gp) == false) filesize = gzsize;
if(filesize == 0) {
//archive is empty
gzclose(gp);
gp = 0;
return;
}
}
GZReader::~GZReader() {
if(gp) {
gzclose(gp);
gp = 0;
}
}
#endif //ifdef READER_CPP

View File

@@ -1,16 +0,0 @@
#include <zlib/zlib.h>
class GZReader : public Reader {
private:
FILE *fp;
gzFile gp;
unsigned filesize;
public:
unsigned size();
uint8_t* read(unsigned length = 0);
bool ready();
GZReader(const char *fn);
~GZReader();
};

View File

@@ -1,36 +0,0 @@
#ifdef READER_CPP
#include "jmareader.hpp"
unsigned JMAReader::size() {
return filesize;
}
uint8_t* JMAReader::read(unsigned length) {
uint8_t *data = 0;
if(!filesize) return 0;
if(length <= filesize) {
//read the entire file into RAM
data = new(zeromemory) uint8_t[filesize];
JMAFile.extract_file(cname, data);
} else if(length > filesize) {
//read the entire file into RAM, pad the rest with 0x00s
data = new(zeromemory) uint8_t[length];
JMAFile.extract_file(cname, data);
}
return data;
}
JMAReader::JMAReader(const char *fn) : JMAFile(fn), filesize(0) {
std::vector<JMA::jma_public_file_info> file_info = JMAFile.get_files_info();
for(std::vector<JMA::jma_public_file_info>::iterator i = file_info.begin(); i != file_info.end(); i++) {
//Check for valid ROM based on size
if((i->size <= 0x1000000 + 512) && (i->size > filesize)) {
cname = i->name;
filesize = i->size;
}
}
}
#endif //ifdef READER_CPP

View File

@@ -1,14 +0,0 @@
#include <libjma/jma.h>
class JMAReader : public Reader {
public:
unsigned size();
uint8_t* read(unsigned length = 0);
JMAReader(const char *fn);
private:
JMA::jma_open JMAFile;
unsigned filesize;
std::string cname;
};

View File

@@ -1,36 +0,0 @@
#include "libreader.hpp"
#define READER_CPP
#include "filereader.cpp"
#if defined(GZIP_SUPPORT)
#include "gzreader.cpp"
#include "zipreader.cpp"
#endif
#if defined(JMA_SUPPORT)
#include "jmareader.cpp"
#endif
Reader::Type Reader::detect(const char *fn, bool inspectheader) {
file fp;
if(!fp.open(fn, file::mode_read)) return Unknown;
uint8_t p[8];
memset(p, 0, sizeof p);
fp.read(p, 8);
fp.close();
if(inspectheader == true) {
//inspect file header to determine type
if(p[0] == 0x1f && p[1] == 0x8b && p[2] == 0x08 && p[3] <= 0x1f) return GZIP;
if(p[0] == 0x50 && p[1] == 0x4b && p[2] == 0x03 && p[3] == 0x04) return ZIP;
if(p[0] == 0x4a && p[1] == 0x4d && p[2] == 0x41 && p[3] == 0x00 && p[4] == 0x4e) return JMA;
} else {
//check file extension to determine type
if(striend(fn, ".gz")) return GZIP;
if(striend(fn, ".zip") || striend(fn, ".z")) return ZIP;
if(striend(fn, ".jma")) return JMA;
}
return Normal;
}

View File

@@ -1,21 +0,0 @@
#include <nall/file.hpp>
#include <nall/platform.hpp>
#include <nall/stdint.hpp>
#include <nall/string.hpp>
using namespace nall;
class Reader {
public:
enum Type {
Unknown,
Normal,
GZIP,
ZIP,
JMA,
};
static Type detect(const char *fn, bool inspectheader);
virtual unsigned size() = 0;
virtual uint8_t* read(unsigned length = 0) = 0;
virtual bool ready() { return true; } //can only call read() when ready() returns true
};

View File

@@ -1,60 +0,0 @@
#ifdef READER_CPP
#include "zipreader.hpp"
unsigned ZipReader::size() {
return filesize;
}
uint8_t* ZipReader::read(unsigned length) {
if(!filesize) return 0;
uint8_t *data = 0;
if(length <= filesize) {
//read the entire file into RAM
data = new(zeromemory) uint8_t[filesize];
unzReadCurrentFile(zipfile, data, filesize);
} else { /* length > filesize */
//read the entire file into RAM, pad the rest with 0x00s
data = new(zeromemory) uint8_t[length];
unzReadCurrentFile(zipfile, data, filesize);
}
return data;
}
bool ZipReader::ready() {
return zipready;
}
ZipReader::ZipReader(const char *fn) : filesize(0), zipready(false) {
unz_file_info cFileInfo; //Create variable to hold info for a compressed file
char cFileName[sizeof(cname)];
if(zipfile = unzOpen(fn)) { //Open zip file
for(int cFile = unzGoToFirstFile(zipfile); cFile == UNZ_OK; cFile = unzGoToNextFile(zipfile)) {
//Gets info on current file, and places it in cFileInfo
unzGetCurrentFileInfo(zipfile, &cFileInfo, cFileName, sizeof(cname), 0, 0, 0, 0);
//verify uncompressed file is not bigger than max ROM size
if((cFileInfo.uncompressed_size <= 0x1000000 + 512) && (cFileInfo.uncompressed_size > filesize)) {
strcpy(cname, cFileName);
filesize = cFileInfo.uncompressed_size;
}
}
if(filesize) {
unzLocateFile(zipfile, cname, 1);
unzOpenCurrentFile(zipfile);
zipready = true;
}
}
}
ZipReader::~ZipReader() {
if(zipfile) {
unzCloseCurrentFile(zipfile);
unzClose(zipfile);
}
}
#endif //ifdef READER_CPP

View File

@@ -1,19 +0,0 @@
#include <zlib/unzip.h>
#define ZIP_MAX_FILE_NAME PATH_MAX
class ZipReader : public Reader {
public:
unsigned size();
uint8_t* read(unsigned length = 0);
bool ready();
ZipReader(const char *fn);
~ZipReader();
private:
unzFile zipfile;
unsigned filesize;
bool zipready;
char cname[PATH_MAX];
};

View File

@@ -18,16 +18,17 @@ ifeq ($(platform),x)
qtinc := `pkg-config --cflags QtCore QtGui`
qtlib := `pkg-config --libs QtCore QtGui`
else ifeq ($(platform),osx)
qtinc := -I/usr/include/QtCore
qtinc += -I/usr/include/QtGui
qtinc += -I/Library/Frameworks/QtCore.framework/Versions/4/Headers
qtinc := -I/Library/Frameworks/QtCore.framework/Versions/4/Headers
qtinc += -I/Library/Frameworks/QtGui.framework/Versions/4/Headers
qtinc += -I/Library/Frameworks/QtOpenGL.framework/Versions/4/Headers
qtlib := -L/Library/Frameworks
qtlib += -framework QtCore
qtlib += -framework QtGui
qtlib += -framework QtOpenGL
qtlib += -framework Carbon
qtlib += -framework Cocoa
qtlib += -framework OpenGL
qtlib += -framework AppKit
qtlib += -framework ApplicationServices
else ifeq ($(platform),win)

View File

@@ -31,11 +31,17 @@ namespace nall {
#if defined(PLATFORM_X)
inline bool library::open(const char *name) {
if(handle) close();
char *t = new char[strlen(name) + 8];
char *t = new char[strlen(name) + 256];
strcpy(t, "lib");
strcat(t, name);
strcat(t, ".so");
handle = (uintptr_t)dlopen(t, RTLD_LAZY);
if(!handle) {
strcpy(t, "/usr/local/lib/lib");
strcat(t, name);
strcat(t, ".so");
handle = (uintptr_t)dlopen(t, RTLD_LAZY);
}
delete[] t;
return handle;
}

View File

@@ -17,7 +17,7 @@ namespace nall {
//
//caveats:
//- only plain-old-data can be stored. complex classes must provide serialize(serializer&);
//- floating-point values are not supported.
//- floating-point usage is not portable across platforms
class serializer {
public:
@@ -33,12 +33,29 @@ namespace nall {
return icapacity;
}
template<typename T> void integer(T &value) {
if(save) {
for(unsigned n = 0; n < sizeof(T); n++) idata[isize++] = value >> (n << 3);
template<typename T> void floatingpoint(T &value) {
enum { size = sizeof(T) };
//this is rather dangerous, and not cross-platform safe;
//but there is no standardized way to export FP-values
uint8_t *p = (uint8_t*)&value;
if(mode == Save) {
for(unsigned n = 0; n < size; n++) idata[isize++] = p[n];
} else if(mode == Load) {
for(unsigned n = 0; n < size; n++) p[n] = idata[isize++];
} else {
isize += size;
}
}
template<typename T> void integer(T &value) {
enum { size = is_bool<T>::value ? 1 : sizeof(T) };
if(mode == Save) {
for(unsigned n = 0; n < size; n++) idata[isize++] = value >> (n << 3);
} else if(mode == Load) {
value = 0;
for(unsigned n = 0; n < sizeof(T); n++) value |= idata[isize++] << (n << 3);
for(unsigned n = 0; n < size; n++) value |= idata[isize++] << (n << 3);
} else if(mode == Size) {
isize += size;
}
}
@@ -54,7 +71,7 @@ namespace nall {
serializer& operator=(const serializer &s) {
if(idata) delete[] idata;
save = s.save;
mode = s.mode;
idata = new uint8_t[s.icapacity];
isize = s.isize;
icapacity = s.icapacity;
@@ -67,15 +84,21 @@ namespace nall {
operator=(s);
}
serializer() {
mode = Size;
idata = 0;
isize = 0;
}
serializer(unsigned capacity) {
save = true;
mode = Save;
idata = new(zeromemory) uint8_t[capacity];
isize = 0;
icapacity = capacity;
}
serializer(const uint8_t *data, unsigned capacity) {
save = false;
mode = Load;
idata = new uint8_t[capacity];
isize = 0;
icapacity = capacity;
@@ -83,11 +106,11 @@ namespace nall {
}
~serializer() {
delete[] idata;
if(idata) delete[] idata;
}
private:
bool save;
enum mode_t { Load, Save, Size } mode;
uint8_t *idata;
unsigned isize;
unsigned icapacity;

View File

@@ -26,6 +26,9 @@ namespace nall {
template<> struct is_floating_point<double> { enum { value = true }; };
template<> struct is_floating_point<long double> { enum { value = true }; };
template<typename T> struct is_bool { enum { value = false }; };
template<> struct is_bool<bool> { enum { value = true }; };
template<typename T> struct is_void { enum { value = false }; };
template<> struct is_void<void> { enum { value = true }; };

View File

@@ -224,6 +224,7 @@ struct pInputSDL {
}
SDL_QuitSubSystem(SDL_INIT_JOYSTICK);
XCloseDisplay(device.display);
}
pInputSDL() {

View File

@@ -50,6 +50,7 @@ public:
}
void term() {
XCloseDisplay(display);
}
};

View File

@@ -38,8 +38,12 @@ void VideoInterface::driver(const char *driver) {
else if(!strcmp(driver, "OpenGL")) p = new VideoGLX();
#endif
#ifdef VIDEO_QTIMAGE
else if(!strcmp(driver, "QtImage")) p = new VideoQtImage();
#ifdef VIDEO_QTOPENGL
else if(!strcmp(driver, "Qt-OpenGL")) p = new VideoQtOpenGL();
#endif
#ifdef VIDEO_QTRASTER
else if(!strcmp(driver, "Qt-Raster")) p = new VideoQtRaster();
#endif
#ifdef VIDEO_SDL
@@ -67,10 +71,12 @@ const char* VideoInterface::default_driver() {
return "DirectDraw";
#elif defined(VIDEO_GDI)
return "GDI";
#elif defined(VIDEO_QTOPENGL)
return "Qt-OpenGL";
#elif defined(VIDEO_QTRASTER)
return "Qt-Raster";
#elif defined(VIDEO_SDL)
return "SDL";
#elif defined(VIDEO_QTIMAGE)
return "QtImage";
#elif defined(VIDEO_XV)
return "X-Video";
#elif defined(VIDEO_GLX)
@@ -108,16 +114,20 @@ const char* VideoInterface::driver_list() {
"OpenGL;"
#endif
#if defined(VIDEO_QTOPENGL)
"Qt-OpenGL;"
#endif
#if defined(VIDEO_XV)
"X-Video;"
#endif
#if defined(VIDEO_SDL)
"SDL;"
#if defined(VIDEO_QTRASTER)
"Qt-Raster;"
#endif
#if defined(VIDEO_QTIMAGE)
"QtImage;"
#if defined(VIDEO_SDL)
"SDL;"
#endif
"None";

View File

@@ -1,10 +1,17 @@
/* Global Headers */
#if defined(VIDEO_QTIMAGE)
#if defined(VIDEO_QTOPENGL) || defined(VIDEO_QTRASTER)
#include <QApplication>
#include <QtGui>
#endif
#if defined(VIDEO_QTOPENGL)
#include <QGLWidget>
#if defined(PLATFORM_WIN)
#include <GL/glext.h>
#endif
#endif
#if defined(PLATFORM_X)
#include <X11/Xlib.h>
#include <X11/Xutil.h>
@@ -56,8 +63,12 @@
#include <ruby/video/glx.cpp>
#endif
#ifdef VIDEO_QTIMAGE
#include <ruby/video/qtimage.cpp>
#ifdef VIDEO_QTOPENGL
#include <ruby/video/qtopengl.cpp>
#endif
#ifdef VIDEO_QTRASTER
#include <ruby/video/qtraster.cpp>
#endif
#ifdef VIDEO_SDL

View File

@@ -191,10 +191,10 @@ public:
uint32_t x, uint32_t y, uint32_t w, uint32_t h
) {
d3dvertex vertex[4];
vertex[0].x = vertex[2].x = (double)(x );
vertex[1].x = vertex[3].x = (double)(x + w);
vertex[0].y = vertex[1].y = (double)(y );
vertex[2].y = vertex[3].y = (double)(y + h);
vertex[0].x = vertex[2].x = (double)(x - 0.5);
vertex[1].x = vertex[3].x = (double)(x + w - 0.5);
vertex[0].y = vertex[1].y = (double)(y - 0.5);
vertex[2].y = vertex[3].y = (double)(y + h - 0.5);
//Z-buffer and RHW are unused for 2D blit, set to normal values
vertex[0].z = vertex[1].z = vertex[2].z = vertex[3].z = 0.0;

View File

@@ -0,0 +1,152 @@
namespace ruby {
class pVideoQtOpenGL {
public:
QWidget *parent;
QVBoxLayout *layout;
class RubyGLWidget : public QGLWidget {
public:
GLuint texture;
unsigned textureWidth, textureHeight;
uint32_t *buffer;
unsigned rasterWidth, rasterHeight;
unsigned filter;
void resize(unsigned width, unsigned height) {
if(width > textureWidth || height > textureHeight) {
textureWidth = max(width, textureWidth);
textureHeight = max(height, textureHeight);
if(buffer) {
delete[] buffer;
glDeleteTextures(1, &texture);
}
buffer = new uint32_t[textureWidth * textureHeight];
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
glPixelStorei(GL_UNPACK_ROW_LENGTH, textureWidth);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, textureWidth, textureHeight, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, buffer);
}
}
void paintGL() {
unsigned outputWidth = width();
unsigned outputHeight = height();
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, outputWidth, 0, outputHeight, -1.0, 1.0);
glViewport(0, 0, outputWidth, outputHeight);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, (filter == Video::FilterPoint) ? GL_NEAREST : GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, (filter == Video::FilterPoint) ? GL_NEAREST : GL_LINEAR);
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, rasterWidth, rasterHeight, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, buffer);
double w = (double)rasterWidth / (double)textureWidth;
double h = (double)rasterHeight / (double)textureHeight;
unsigned u = outputWidth;
unsigned v = outputHeight;
glBegin(GL_TRIANGLE_STRIP);
glTexCoord2f(0, 0); glVertex3i(0, v, 0);
glTexCoord2f(w, 0); glVertex3i(u, v, 0);
glTexCoord2f(0, h); glVertex3i(0, 0, 0);
glTexCoord2f(w, h); glVertex3i(u, 0, 0);
glEnd();
}
void initializeGL() {
format().setDoubleBuffer(true);
texture = 0;
textureWidth = 0;
textureHeight = 0;
buffer = 0;
resize(rasterWidth = 256, rasterHeight = 256);
glDisable(GL_ALPHA_TEST);
glDisable(GL_BLEND);
glDisable(GL_DEPTH_TEST);
glDisable(GL_POLYGON_SMOOTH);
glDisable(GL_STENCIL_TEST);
glEnable(GL_DITHER);
glEnable(GL_TEXTURE_2D);
glClearColor(0.0, 0.0, 0.0, 0.0);
}
} *widget;
bool cap(const string& name) {
if(name == Video::Filter) return true;
if(name == "QWidget") return true;
return false;
}
any get(const string& name) {
if(name == Video::Filter) return widget->filter;
if(name == "QWidget") return parent;
return false;
}
bool set(const string& name, const any& value) {
if(name == Video::Filter) {
widget->filter = any_cast<unsigned>(value);
return true;
}
if(name == "QWidget") {
parent = any_cast<QWidget*>(value);
return true;
}
return false;
}
bool lock(uint32_t *&data, unsigned &pitch, unsigned width, unsigned height) {
widget->resize(width, height);
widget->rasterWidth = width;
widget->rasterHeight = height;
pitch = widget->textureWidth * sizeof(uint32_t);
return data = widget->buffer;
}
void unlock() {
}
void clear() {
memset(widget->buffer, 0, widget->textureWidth * widget->textureHeight * sizeof(uint32_t));
widget->updateGL();
}
void refresh() {
widget->updateGL();
}
bool init() {
layout = new QVBoxLayout;
layout->setMargin(0);
widget = new RubyGLWidget;
widget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
layout->addWidget(widget);
parent->setLayout(layout);
return true;
}
void term() {
}
};
DeclareVideo(QtOpenGL)
};

View File

@@ -1,22 +1,18 @@
namespace ruby {
//variables needed by both pVideoQtImage and pVideoQtImage::QtImage
//external as one cannot reference parent class from ::QtImage
struct VideoQtImageContext {
struct VideoQtRasterContext {
QImage *image;
unsigned width, height;
unsigned filter;
};
} context;
class pVideoQtImage {
class pVideoQtRaster {
public:
VideoQtImageContext context;
QWidget *parent;
QVBoxLayout *layout;
struct QtImage : public QWidget {
VideoQtImageContext &context;
VideoQtRasterContext &context;
void paintEvent(QPaintEvent*) {
if(context.image == 0) return;
@@ -31,7 +27,7 @@ public:
}
}
QtImage(QWidget *parent, VideoQtImageContext &context_) : QWidget(parent), context(context_) {}
QtImage(QWidget *parent, VideoQtRasterContext &context_) : QWidget(parent), context(context_) {}
} *widget;
bool cap(const string& name) {
@@ -118,13 +114,13 @@ public:
layout = 0;
}
pVideoQtImage() {
pVideoQtRaster() {
context.image = 0;
widget = 0;
layout = 0;
}
};
DeclareVideo(QtImage)
DeclareVideo(QtRaster)
};

Some files were not shown because too many files have changed in this diff Show More