Compare commits

...
3 Commits
Author SHA1 Message Date
byuu 49c39e0e4d Update to bsnes v015 release.
- Added GZ / ZIP / JMA archive support [Nach, NSRT team]
    - Fixed bug in APU ADDW/SUBW opcode flags, thanks to DMV27, anomymous for info
    - Mosaic support is now (mostly) hardware accurate, thanks to TRAC for info
    - Fixed a bug in SC tilemap clipping, fixes Seiken Densetsu 3
    - Emulated pseudo-hires mode, uses a fairly poor color filter to simulate TV effect, the same one that SNES9x and Super Sleuth use
    - Rewrote the ROM loading code to be more port-friendly, and improved header detection
    - Added C4 emulation -- mostly correct. Only minor bugs remain, possibly not C4 related [Nach, byuu], also uses code from zsKnight, Overload, and anomie
    - Fixed noise channel generation for DSP, fixes Dual Orb 2 opening. Thanks to DMV27 for info
    - Fixed bug with DSP VxSRCN registers, fixes horrible sound corruption in Mortal Kombat 2/3
    - Modified DSP KON register reading to act according to anomie's research, while still allowing Der Langrisser, etc. to play sounds correctly
    - Fixed a bug in CPU BCD math, fixes numbers in SimEarth, thanks to DMV27 for info
    - Rewrote the windows port from scratch
    - -- Added triple buffering support (buggy)
    - -- Added DirectInput (joypad) support, allows both keyboard and joypad to be mapped to the same SNES controller button. Only one controller supported for this release, will be improved shortly
    - -- Added pause key (mapped to Pause/Break)
    - -- bsnes no longer consumes CPU time when paused or when no ROM is loaded
    - -- Updated DirectDraw to 7, and added video mode configuration options to configuration file
    - -- Video modes can specify screen width+height, refresh rate, and render width+height
    - -- Added CTRL+[1-0] hotkeys for swapping video modes
    - -- Added +/- hotkeys for adjusting frameskipping rate
    - -- Added adjustable speed regulation. There are five modes, all can be adjusted inside the configuration file. CTRL+[+/-] will adjust the speed mode.
    - -- Added PPU options to toggle any BG / OAM layers with any priority, HDMA effects, and offset per tile effects
    - -- Added option to accept invalid button combinations (up+down, left+right) to joypad config menu
    - -- bsnes now properly clears the main window when unloading games
    - [code] Made destructors for base classes virtual, so the correct destructors will be called now
2005-12-03 21:05:52 +00:00
byuu 7dec0b2a3c Update to bsnes v014 release.
This version adds speed regulation, greatly improves PPU rendering, and increases speed by ~30% over the previous version.
Changelog:
    - Rewrote offset-per-tile mode emulation, should be correct now. Fixes Chrono Trigger, Contra III, Tetris Attack, etc.
    - Fixed a bug with HDMA occuring during interrupts. Fixes Tales of Phantasia souond test screen
    - Updated compiler to Visual Studio 2005, and enabled profile guided optimizations
    - Added conditional compilation of debugging functions (faster without them)
    - Added conditional compilation of core classes as pointers (allowing polymorphism) or objects (allowing inlining). The latter results in a speed increase
    - Small fixes to BG and OAM rendering routines
    - Corrected sprite tile bounds wrapping
    - Corrected sprite rendering in hires video modes
    - Rewrote color add/sub routines, should be correct now. Fixes Illusion of Gaia menu, etc.
    - Optimized video blitting routines, will temporarilly break mixed video mode screenshots
    - Prevented selecting menu options via return key from being recognized as keypresses by the emulator
    - Added system speed regulation (60hz/NTSC or 50hz/PAL)! Many thanks to kode54, GIGO, and Richard Bannister for their assistance
I disabled the debugger and polymorphism, and enabled profile guided optimizations for this build, to maximize speed. The debugger and polymorphism can be re-enabled via uncommenting the respective #defines in src/base.h and recompiling, or bsnes v0.013 can be used. I may start releasing two separate builds in the future... not sure yet.
2005-11-12 16:49:26 +00:00
byuu f288280ceb Update to bsnes v013r02 release.
[No changelog available]
2005-10-25 23:25:28 +00:00
196 changed files with 24522 additions and 3602 deletions

No files matched your search

+127 -60
View File
@@ -13,123 +13,190 @@ snes.video_color_curve = true
snes.video_color_adjust_mode = 0
# Mutes SNES audio output when enabled
# (default = true)
snes.mute = true
# (default = false)
snes.mute = false
# Video mode
# 0 = 256x224w
# 1 = 512x448w
# 2 = 960x720w
# 3 = 640x480f
# 4 = 1024x768f
# (default = 1)
video.mode = 1
# Regulate speed to 60hz (NTSC) / 50hz (PAL)
# (default = true)
system.regulate_speed = true
# Slowest speed setting (in hz)
# (default = 16000)
system.speed_slowest = 16000
# Slow speed setting
# (default = 24000)
system.speed_slow = 24000
# Normal speed setting
# (default = 32000)
system.speed_normal = 32000
# Fast speed setting
# (default = 48000)
system.speed_fast = 48000
# Fastest speed setting
# (default = 64000)
system.speed_fastest = 64000
# Video mode at startup
# (default = 2)
video.mode = 2
# Video mode 0 (windowed)
# (default = "256x223")
video.mode_0 = "256x223"
# Video mode 1 (windowed)
# (default = "512x446")
video.mode_1 = "512x446"
# Video mode 2 (windowed)
# (default = "640x480")
video.mode_2 = "640x480"
# Video mode 3 (windowed)
# (default = "960x720")
video.mode_3 = "960x720"
# Video mode 4 (windowed)
# (default = "1152x864")
video.mode_4 = "1152x864"
# Video mode 5 (fullscreen)
# (default = "640x480@60:640x480")
video.mode_5 = "640x480@60:640x480"
# Video mode 6 (fullscreen)
# (default = "800x600@60:800x600")
video.mode_6 = "800x600@60:800x600"
# Video mode 7 (fullscreen)
# (default = "1024x768@60:1024x768")
video.mode_7 = "1024x768@60:1024x768"
# Video mode 8 (fullscreen)
# (default = "1280x960@60:1280x960")
video.mode_8 = "1280x960@60:1280x960"
# Video mode 9 (fullscreen)
# (default = "1600x1200@60:1600x1200")
video.mode_9 = "1600x1200@60:1600x1200"
# Use Video RAM instead of System RAM
# (default = true)
video.use_vram = true
# Wait for vertical retrace when updating screen
# Use triple buffering
# (default = false)
video.vblank = false
video.triple_buffering = false
# Show framerate in window title
# (default = true)
gui.show_fps = true
# Allow "impossible" key combinations for joypad 1 (not recommended)
# (default = false)
input.joypad1.allow_invalid_input = false
# Joypad1 up
# (default = 0x26)
input.joypad1.up = 0x26
# (default = 0x80c8)
input.joypad1.up = 0x80c8
# Joypad1 down
# (default = 0x28)
input.joypad1.down = 0x28
# (default = 0x81d0)
input.joypad1.down = 0x81d0
# Joypad1 left
# (default = 0x25)
input.joypad1.left = 0x25
# (default = 0x82cb)
input.joypad1.left = 0x82cb
# Joypad1 right
# (default = 0x27)
input.joypad1.right = 0x27
# (default = 0x83cd)
input.joypad1.right = 0x83cd
# Joypad1 A
# (default = 0x58)
input.joypad1.a = 0x58
# (default = 0x42d)
input.joypad1.a = 0x42d
# Joypad1 B
# (default = 0x5a)
input.joypad1.b = 0x5a
# (default = 0x32c)
input.joypad1.b = 0x32c
# Joypad1 X
# (default = 0x53)
input.joypad1.x = 0x53
# (default = 0x11f)
input.joypad1.x = 0x11f
# Joypad1 Y
# (default = 0x41)
input.joypad1.y = 0x41
# (default = 0x1e)
input.joypad1.y = 0x1e
# Joypad1 L
# (default = 0x44)
input.joypad1.l = 0x44
# (default = 0x620)
input.joypad1.l = 0x620
# Joypad1 R
# (default = 0x43)
input.joypad1.r = 0x43
# (default = 0x72e)
input.joypad1.r = 0x72e
# Joypad1 select
# (default = 0x10)
input.joypad1.select = 0x10
# (default = 0x836)
input.joypad1.select = 0x836
# Joypad1 start
# (default = 0xd)
input.joypad1.start = 0xd
# (default = 0x91c)
input.joypad1.start = 0x91c
# Allow "impossible" key combinations for joypad 2 (not recommended)
# (default = false)
input.joypad2.allow_invalid_input = false
# Joypad2 up
# (default = 0x54)
input.joypad2.up = 0x54
# (default = 0xff14)
input.joypad2.up = 0xff14
# Joypad2 down
# (default = 0x47)
input.joypad2.down = 0x47
# (default = 0xff22)
input.joypad2.down = 0xff22
# Joypad2 left
# (default = 0x46)
input.joypad2.left = 0x46
# (default = 0xff21)
input.joypad2.left = 0xff21
# Joypad2 right
# (default = 0x48)
input.joypad2.right = 0x48
# (default = 0xff23)
input.joypad2.right = 0xff23
# Joypad2 A
# (default = 0x4b)
input.joypad2.a = 0x4b
# (default = 0xff25)
input.joypad2.a = 0xff25
# Joypad2 B
# (default = 0x4a)
input.joypad2.b = 0x4a
# (default = 0xff24)
input.joypad2.b = 0xff24
# Joypad2 X
# (default = 0x49)
input.joypad2.x = 0x49
# (default = 0xff17)
input.joypad2.x = 0xff17
# Joypad2 Y
# (default = 0x55)
input.joypad2.y = 0x55
# (default = 0xff16)
input.joypad2.y = 0xff16
# Joypad2 L
# (default = 0x4f)
input.joypad2.l = 0x4f
# (default = 0xff18)
input.joypad2.l = 0xff18
# Joypad2 R
# (default = 0x4c)
input.joypad2.r = 0x4c
# (default = 0xff26)
input.joypad2.r = 0xff26
# Joypad2 select
# (default = 0x5b)
input.joypad2.select = 0x5b
# (default = 0xff1a)
input.joypad2.select = 0xff1a
# Joypad2 start
# (default = 0x5d)
input.joypad2.start = 0x5d
# (default = 0xff1b)
input.joypad2.start = 0xff1b
BIN
View File
Binary file not shown.
+3
View File
@@ -27,4 +27,7 @@ static const uint8 iplrom[64];
virtual bool in_opcode();
void disassemble_opcode(char *output);
inline uint16 __relb(int8 offset, int op_len);
APU() {}
virtual ~APU() {}
};
+13 -7
View File
@@ -24,13 +24,13 @@ uint8 r;
break;
case 0xf3: //DSPDATA
//0x80-0xff is a read-only mirror of 0x00-0x7f
r = dsp->read(status.dsp_addr & 0x7f);
r = r_dsp->read(status.dsp_addr & 0x7f);
break;
case 0xf4: //CPUIO0
case 0xf5: //CPUIO1
case 0xf6: //CPUIO2
case 0xf7: //CPUIO3
r = cpu->port_read(addr & 3);
r = r_cpu->port_read(addr & 3);
break;
case 0xf8: //???
case 0xf9: //??? -- Mapped to SPCRAM
@@ -63,7 +63,10 @@ uint8 r;
r = spcram[addr];
}
}
#ifdef DEBUGGER
snes->notify(SNES::SPCRAM_READ, addr, r);
#endif
return r;
}
@@ -78,12 +81,12 @@ void bAPU::spcram_write(uint16 addr, uint8 value) {
//one-time clearing of APU port read registers,
//emulated by simulating CPU writes of 0x00
if(value & 0x20) {
cpu->port_write(2, 0x00);
cpu->port_write(3, 0x00);
r_cpu->port_write(2, 0x00);
r_cpu->port_write(3, 0x00);
}
if(value & 0x10) {
cpu->port_write(0, 0x00);
cpu->port_write(1, 0x00);
r_cpu->port_write(0, 0x00);
r_cpu->port_write(1, 0x00);
}
//0->1 transistion resets timers
@@ -111,7 +114,7 @@ void bAPU::spcram_write(uint16 addr, uint8 value) {
case 0xf3: //DSPDATA
//0x80-0xff is a read-only mirror of 0x00-0x7f
if(status.dsp_addr < 0x80) {
dsp->write(status.dsp_addr & 0x7f, value);
r_dsp->write(status.dsp_addr & 0x7f, value);
}
break;
case 0xf4: //CPUIO0
@@ -143,7 +146,10 @@ void bAPU::spcram_write(uint16 addr, uint8 value) {
//even if the iplrom is enabled.
spcram[addr] = value;
}
#ifdef DEBUGGER
snes->notify(SNES::SPCRAM_WRITE, addr, value);
#endif
}
uint8 bAPU::port_read(uint8 port) {
+12 -8
View File
@@ -1,18 +1,22 @@
void bAPU::exec_cycle() {
uint8 op;
if(status.cycle_pos == 0) {
op = spcram_read(regs.pc);
snes->notify(SNES::APU_EXEC_OPCODE_BEGIN);
status.opcode = op_read();
status.cycle_pos = 1;
add_cycles(1);
} else {
if(status.cycle_pos) {
(this->*optbl[status.opcode])();
add_cycles(1);
if(status.cycle_pos == 0) {
#ifdef DEBUGGER
snes->notify(SNES::APU_EXEC_OPCODE_END);
#endif
}
return;
}
//on first cycle?
#ifdef DEBUGGER
snes->notify(SNES::APU_EXEC_OPCODE_BEGIN);
#endif
status.opcode = op_read();
status.cycle_pos = 1;
add_cycles(1);
}
//only return true when we are on an opcode edge
+8 -10
View File
@@ -9,12 +9,11 @@ int16 r = x + y + regs.p.c;
}
uint16 bAPU::op_addw(uint16 x, uint16 y) {
int32 r = x + y;
regs.p.n = !!(r & 0x8000);
regs.p.v = !!(~(x ^ y) & (y ^ (uint16)r) & 0x8000);
regs.p.h = !!((x ^ y ^ (uint16)r) & 0x10);
int16 r;
regs.p.c = 0;
r = op_adc(x, y);
r |= op_adc(x >> 8, y >> 8) << 8;
regs.p.z = ((uint16)r == 0);
regs.p.c = (r > 0xffff);
return r;
}
@@ -66,12 +65,11 @@ int16 r = x - y - !regs.p.c;
}
uint16 bAPU::op_subw(uint16 x, uint16 y) {
int32 r = x - y;
regs.p.n = !!(r & 0x8000);
regs.p.v = !!((x ^ y) & (x ^ (uint16)r) & 0x8000);
regs.p.h = !((x ^ y ^ (uint16)r) & 0x10);
int16 r;
regs.p.c = 1;
r = op_sbc(x, y);
r |= op_sbc(x >> 8, y >> 8) << 8;
regs.p.z = ((uint16)r == 0);
regs.p.c = (r >= 0);
return r;
}
-171
View File
@@ -1,171 +0,0 @@
#include "../../base.h"
uint8 bAPUSkip::spcram_read (uint16 addr) { return 0xff; }
void bAPUSkip::spcram_write(uint16 addr, uint8 value) {}
/*
This routine is very serious. It will eat holes through
the ROM to skip APU test conditions. Or in other words,
it will disable and/or force branches when neccesary.
It can very easily break or corrupt a game and prevent it
from being playable until the ROM is reloaded (ROM writes
are only performed in memory, of course).
However, this kind of brute force approach is required to
get many games playable without proper SPC700 emulation.
*/
uint8 bAPUSkip::port_read(uint8 port) {
port &= 3;
_apu_port *p = &apu_port[port];
int i, x, y, z, t;
uint32 addr;
addr = cpu->regs.pc.d;
p->read_addr[p->read_pos & 31] = addr;
//- lda $214x
// cmp $214x
// bne -
// cmp ???
// beq/bne -
__test1:
//look for an lda/cmp read pattern
if(addr == p->read_addr[(p->read_pos - 1) & 31])goto __test2;
if(addr != p->read_addr[(p->read_pos - 2) & 31])goto __test2;
if(addr == p->read_addr[(p->read_pos - 3) & 31])goto __test2;
if(addr != p->read_addr[(p->read_pos - 4) & 31])goto __test2;
if(p->read_addr[(p->read_pos - 1) & 31] != p->read_addr[(p->read_pos - 3) & 31])goto __test2;
//try and find compare opcode
for(i=0;i<24;i++) {
x = mem_bus->read(addr + i);
if(x == OP_CMP_CONST || x == OP_CPX_CONST || x == OP_CPY_CONST)break;
if(x == OP_CMP_ADDR || x == OP_CPX_ADDR || x == OP_CPY_ADDR) break;
if(x == OP_CMP_LONG)break;
}
if(i == 24)goto __test2;
//seek to next opcode
if(x == OP_CMP_CONST) {
i += (cpu->regs.p.m)?2:3;
} else if(x == OP_CPX_CONST || x == OP_CPY_CONST) {
i += (cpu->regs.p.x)?2:3;
} else if(x == OP_CMP_ADDR || x == OP_CPX_ADDR || x == OP_CPY_ADDR) {
i += 3;
} else { //(x == OP_CMP_LONG) {
i += 4;
}
x = mem_bus->read(addr + i);
if(x == OP_BNE) {
mem_bus->cart->write_protect(false);
mem_bus->write(addr + i, OP_NOP);
mem_bus->write(addr + i + 1, OP_NOP);
mem_bus->cart->write_protect(true);
} else if(x == OP_BEQ) {
mem_bus->cart->write_protect(false);
mem_bus->write(addr + i, OP_BRA);
mem_bus->cart->write_protect(true);
} else goto __test2;
goto __pass;
//- lda $214x
// cmp ???
// beq/bne -
__test2:
//look for a repeated read pattern
if(addr != p->read_addr[(p->read_pos - 1) & 31])goto __test3;
if(addr != p->read_addr[(p->read_pos - 2) & 31])goto __test3;
if(addr != p->read_addr[(p->read_pos - 3) & 31])goto __test3;
if(addr != p->read_addr[(p->read_pos - 4) & 31])goto __test3;
if(addr != p->read_addr[(p->read_pos - 5) & 31])goto __test3;
if(addr != p->read_addr[(p->read_pos - 6) & 31])goto __test3;
if(addr != p->read_addr[(p->read_pos - 7) & 31])goto __test3;
if(addr != p->read_addr[(p->read_pos - 8) & 31])goto __test3;
//try and find compare opcode
for(i=0;i<24;i++) {
x = mem_bus->read(addr + i);
if(x == OP_CMP_CONST || x == OP_CPX_CONST || x == OP_CPY_CONST)break;
if(x == OP_CMP_ADDR || x == OP_CPX_ADDR || x == OP_CPY_ADDR) break;
if(x == OP_CMP_LONG)break;
}
if(i == 24)goto __test3;
//seek to next opcode
if(x == OP_CMP_CONST) {
i += (cpu->regs.p.m)?2:3;
} else if(x == OP_CPX_CONST || x == OP_CPY_CONST) {
i += (cpu->regs.p.x)?2:3;
} else if(x == OP_CMP_ADDR || x == OP_CPX_ADDR || x == OP_CPY_ADDR) {
i += 3;
} else if(x == OP_CMP_LONG) {
i += 4;
}
x = mem_bus->read(addr + i);
if(x == OP_BNE) {
mem_bus->cart->write_protect(false);
mem_bus->write(addr + i, OP_NOP);
mem_bus->write(addr + i + 1, OP_NOP);
mem_bus->cart->write_protect(true);
} else if(x == OP_BEQ) {
mem_bus->cart->write_protect(false);
mem_bus->write(addr + i, OP_BRA);
mem_bus->cart->write_protect(true);
} else goto __test3;
goto __pass;
//fallback
__test3:
if(p->pos < 4) {
if(!(port & 1)) {
p->value = cpu->regs.a.l;
} else {
p->value = cpu->regs.a.h;
}
} else if(p->pos < 8) {
if(!(port & 1)) {
p->value = cpu->regs.x.l;
} else {
p->value = cpu->regs.x.h;
}
} else if(p->pos < 12) {
if(!(port & 1)) {
p->value = cpu->regs.y.l;
} else {
p->value = cpu->regs.y.h;
}
} else if(p->pos < 16) {
p->value = rand();
}
if(++p->pos == 16)p->pos = 0;
__pass:
p->read_pos++;
p->read_pos &= 31;
return p->value;
}
void bAPUSkip::port_write(uint8 port, uint8 value) {
port &= 3;
apu_port[port].value = value;
}
void bAPUSkip::run() {
snes->notify(SNES::APU_EXEC_OPCODE_BEGIN);
snes->notify(SNES::APU_EXEC_OPCODE_END);
}
void bAPUSkip::power() {
reset();
}
void bAPUSkip::reset() {
regs.a = 0x00;
regs.x = 0x00;
regs.y = 0x00;
regs.sp = 0x00;
regs.p = 0x02;
regs.pc = 0xffc0;
memset(&apu_port[0], 0, sizeof(_apu_port));
memset(&apu_port[1], 0, sizeof(_apu_port));
memset(&apu_port[2], 0, sizeof(_apu_port));
memset(&apu_port[3], 0, sizeof(_apu_port));
}
-37
View File
@@ -1,37 +0,0 @@
class bAPUSkip : public APU {
private:
uint8 spcram[65536];
public:
struct _apu_port {
uint8 value;
uint8 step, pos;
uint32 read_addr[32], read_pos;
}apu_port[4];
enum {
OP_CMP_CONST = 0xc9,
OP_CPX_CONST = 0xe0,
OP_CPY_CONST = 0xc0,
OP_CMP_ADDR = 0xcd,
OP_CPX_ADDR = 0xec,
OP_CPY_ADDR = 0xcc,
OP_CMP_LONG = 0xcf,
OP_BNE = 0xd0,
OP_BEQ = 0xf0,
OP_BRA = 0x80,
OP_NOP = 0xea
};
uint8 spcram_read (uint16 addr);
void spcram_write(uint16 addr, uint8 value);
uint8 port_read (uint8 port);
void port_write (uint8 port, uint8 value);
uint8 *get_spcram_handle() { return spcram; }
void run();
uint32 cycles_executed() { return 12 * 24; }
void power();
void reset();
};
+13
View File
@@ -1,3 +1,16 @@
//debugging extensions (~10% speed hit)
//#define DEBUGGER
//snes core polymorphism (allow mem/cpu/apu/ppu overriding,
//~10% speed hit)
//#define POLYMORPHISM
//enable GZ, ZIP format support
#define GZIP_SUPPORT
//enable JMA support
#define JMA_SUPPORT
//this should be declared in the port-specific makefiles
//#define ARCH_LSB
//#define ARCH_MSB
+243
View File
@@ -0,0 +1,243 @@
#include "../base.h"
void Cartridge::read_header() {
cart.srtc = false;
cart.sdd1 = false;
cart.c4 = false;
if(cart.header_index == 0x7fc0 && cart.rom_size >= 0x401000) {
cart.mapper = EXLOROM;
} else if(cart.header_index == 0x7fc0 && rom[cart.header_index + MAPPER] == 0x32) {
cart.mapper = EXLOROM;
} else if(cart.header_index == 0x7fc0) {
cart.mapper = LOROM;
} else if(cart.header_index == 0xffc0) {
cart.mapper = HIROM;
} else { //cart.header_index == 0x40ffc0
cart.mapper = EXHIROM;
}
uint8 mapper = rom[cart.header_index + MAPPER];
uint8 rom_type = rom[cart.header_index + ROM_TYPE];
if(mapper == 0x35 && rom_type == 0x55) {
cart.srtc = true;
}
if(mapper == 0x32 && (rom_type == 0x43 || rom_type == 0x45)) {
cart.sdd1 = true;
}
if(mapper == 0x20 && rom_type == 0xf3) {
cart.c4 = true;
}
if(rom[cart.header_index + SRAM_SIZE] & 7) {
cart.sram_size = 1024 << (rom[cart.header_index + SRAM_SIZE] & 7);
} else {
cart.sram_size = 0;
}
cart.region = (rom[cart.header_index + REGION] < 2) ? NTSC : PAL;
memcpy(&cart.name, &rom[cart.header_index + CART_NAME], 21);
cart.name[21] = 0;
for(int i=0;i<22;i++) {
if(cart.name[i] & 0x80) {
cart.name[i] = '?';
}
}
}
void Cartridge::find_header() {
int32 score_lo = 0,
score_hi = 0,
score_ex = 0;
if(rom_size < 0x010000) {
//cart too small to be anything else
cart.header_index = 0x007fc0;
return;
}
if((rom[0x7fc0 + MAPPER] & ~0x10) == 0x20)score_lo++;
if((rom[0xffc0 + MAPPER] & ~0x10) == 0x21)score_hi++;
if(rom[0x7fc0 + ROM_TYPE] < 0x08)score_lo++;
if(rom[0xffc0 + ROM_TYPE] < 0x08)score_hi++;
if(rom[0x7fc0 + ROM_SIZE] < 0x10)score_lo++;
if(rom[0xffc0 + ROM_SIZE] < 0x10)score_hi++;
if(rom[0x7fc0 + SRAM_SIZE] < 0x08)score_lo++;
if(rom[0xffc0 + SRAM_SIZE] < 0x08)score_hi++;
if(rom[0x7fc0 + REGION] < 14)score_lo++;
if(rom[0xffc0 + REGION] < 14)score_hi++;
if(rom[0x7fc0 + LICENSE] < 3)score_lo++;
if(rom[0xffc0 + LICENSE] < 3)score_hi++;
uint16 cksum, icksum;
cksum = rom[0x7fc0 + CKSUM] | (rom[0x7fc0 + CKSUM + 1] << 8);
icksum = rom[0x7fc0 + ICKSUM] | (rom[0x7fc0 + ICKSUM + 1] << 8);
if((cksum + icksum) == 0xffff)score_lo += 8;
cksum = rom[0xffc0 + CKSUM] | (rom[0xffc0 + CKSUM + 1] << 8);
icksum = rom[0xffc0 + ICKSUM] | (rom[0xffc0 + ICKSUM + 1] << 8);
if((cksum + icksum) == 0xffff)score_hi += 8;
if(rom_size < 0x401000) {
score_ex = 0;
} else {
if(rom[0x7fc0 + MAPPER] == 0x32)score_lo++;
else score_ex += 16;
}
if(score_lo >= score_hi && score_lo >= score_ex) {
cart.header_index = 0x007fc0;
} else if(score_hi >= score_ex) {
cart.header_index = 0x00ffc0;
} else {
cart.header_index = 0x40ffc0;
}
}
void Cartridge::load_sram() {
if(cart.sram_size == 0) {
sram = 0;
return;
}
FileReader ff;
if(!ff.open(sram_fn)) {
sram = (uint8*)malloc(cart.sram_size);
memset(sram, 0, cart.sram_size);
return;
}
sram = ff.read(cart.sram_size);
ff.close();
}
void Cartridge::save_sram() {
if(cart.sram_size == 0)return;
FileWriter ff;
if(!ff.open(sram_fn))return;
ff.write(sram, cart.sram_size);
ff.close();
}
void Cartridge::load_rom(Reader *rf) {
base_rom = rf->read();
rom_size = rf->size();
if((rom_size & 0x7fff) == 0x0200) {
rom = base_rom + 512;
rom_size -= 512;
} else {
rom = base_rom;
}
cart.rom_size = rom_size;
}
bool Cartridge::load(const char *fn) {
if(cart_loaded == true)return false;
if(strlen(fn) < 3)return false;
dprintf("* Loading \"%s\"...", fn);
strcpy(rom_fn, fn);
switch(Reader::detect(rom_fn)) {
case Reader::RF_NORMAL: {
FileReader ff;
if(!ff.open(rom_fn)) {
alert("Error loading image file (%s)!", rom_fn);
return false;
}
load_rom(static_cast<Reader*>(&ff));
ff.close();
break;
}
#ifdef GZIP_SUPPORT
case Reader::RF_GZ: {
GZReader gf;
if(!gf.open(rom_fn)) {
alert("Error loading image file (%s)!", rom_fn);
return false;
}
load_rom(static_cast<Reader*>(&gf));
gf.close();
break;
}
case Reader::RF_ZIP: {
ZipReader zf(rom_fn);
load_rom(static_cast<Reader*>(&zf));
break;
}
#endif
#ifdef JMA_SUPPORT
case Reader::RF_JMA: {
try {
JMAReader jf(rom_fn);
load_rom(static_cast<Reader*>(&jf));
} catch(JMA::jma_errors jma_error) {
alert("Error loading image file (%s)!", rom_fn);
return false;
}
break;
}
#endif
}
int i;
strcpy(sram_fn, fn);
for(i=strlen(fn)-1;i>=0;i--) {
if(fn[i] == '.')break;
}
if(i != 0)sram_fn[i] = 0;
strcat(sram_fn, ".srm");
find_header();
read_header();
load_sram();
cart_loaded = true;
r_mem->load_cart();
return true;
}
bool Cartridge::unload() {
if(cart_loaded == false)return false;
r_mem->unload_cart();
if(base_rom) {
zerofree(base_rom);
}
if(sram) {
save_sram();
zerofree(sram);
}
cart_loaded = false;
return true;
}
Cartridge::Cartridge() {
cart_loaded = false;
base_rom = 0;
rom = 0;
sram = 0;
rom_size = 0;
}
Cartridge::~Cartridge() {
if(cart_loaded == true) {
unload();
}
}
+59
View File
@@ -0,0 +1,59 @@
class Cartridge {
public:
bool cart_loaded;
char rom_fn[4096], sram_fn[4096];
uint8 *base_rom, *rom, *sram;
uint32 rom_size;
enum {
//header fields
CART_NAME = 0x00,
MAPPER = 0x15,
ROM_TYPE = 0x16,
ROM_SIZE = 0x17,
SRAM_SIZE = 0x18,
REGION = 0x19,
LICENSE = 0x1a,
VERSION = 0x1b,
ICKSUM = 0x1c,
CKSUM = 0x1e,
//regions
NTSC = 0,
PAL = 1,
//memory mappers
LOROM = 0x20,
HIROM = 0x21,
EXLOROM = 0x22,
EXHIROM = 0x25,
};
struct {
uint32 header_index;
char name[32];
uint32 rom_size;
uint32 sram_size;
bool region;
uint32 mapper;
bool srtc;
bool sdd1;
bool c4;
} cart;
void load_rom(Reader *rf);
void load_sram();
void save_sram();
void find_header();
void read_header();
bool load(const char *fn);
bool unload();
Cartridge();
~Cartridge();
};
extern Cartridge cartridge;
+197
View File
@@ -0,0 +1,197 @@
/*
C4 emulation
Used in Rockman X2/X3 (Megaman X2/X3)
Portions (c) anomie, Overload, zsKnight, Nach, byuu
*/
#include "../../base.h"
#include "c4data.cpp"
#include "c4fn.cpp"
#include "c4oam.cpp"
#include "c4ops.cpp"
void C4::init() {}
void C4::enable() {}
uint32 C4::ldr(uint8 r) {
uint16 addr = 0x0080 + (r * 3);
return (reg[addr]) | (reg[addr + 1] << 8) | (reg[addr + 2] << 16);
}
void C4::str(uint8 r, uint32 data) {
uint16 addr = 0x0080 + (r * 3);
reg[addr ] = (data);
reg[addr + 1] = (data >> 8);
reg[addr + 2] = (data >> 16);
}
void C4::mul(uint32 x, uint32 y, uint32 &rl, uint32 &rh) {
int64 rx = x & 0xffffff;
int64 ry = y & 0xffffff;
if(rx & 0x800000)rx |= ~0x7fffff;
if(ry & 0x800000)ry |= ~0x7fffff;
rx *= ry;
rl = (rx) & 0xffffff;
rh = (rx >> 24) & 0xffffff;
}
uint32 C4::sin(uint32 rx) {
r0 = rx & 0x1ff;
if(r0 & 0x100)r0 ^= 0x1ff;
if(r0 & 0x080)r0 ^= 0x0ff;
if(rx & 0x100) {
return sin_table[r0 + 0x80];
} else {
return sin_table[r0];
}
}
uint32 C4::cos(uint32 rx) {
return sin(rx + 0x080);
}
void C4::immediate_reg(uint32 start) {
r0 = ldr(0);
for(uint32 i=start;i<48;i++) {
if((r0 & 0x0fff) < 0x0c00) {
ram[r0 & 0x0fff] = immediate_data[i];
}
r0++;
}
str(0, r0);
}
void C4::transfer_data() {
uint32 src;
uint16 dest, count;
src = (reg[0x40]) | (reg[0x41] << 8) | (reg[0x42] << 16);
count = (reg[0x43]) | (reg[0x44] << 8);
dest = (reg[0x45]) | (reg[0x46] << 8);
for(uint32 i=0;i<count;i++) {
write(dest++, r_mem->read(src++));
}
}
void C4::write(uint16 addr, uint8 data) {
addr &= 0x1fff;
if(addr < 0x0c00) {
//ram
ram[addr] = data;
return;
}
if(addr < 0x1f00) {
//unmapped
return;
}
//command register
reg[addr & 0xff] = data;
if(addr == 0x1f47) {
//memory transfer
transfer_data();
return;
}
if(addr == 0x1f4f) {
//c4 command
if(reg[0x4d] == 0x0e && !(data & 0xc3)) {
//c4 test command
reg[0x80] = data >> 2;
return;
}
switch(data) {
case 0x00:op00();break;
case 0x01:op01();break;
case 0x05:op05();break;
case 0x0d:op0d();break;
case 0x10:op10();break;
case 0x13:op13();break;
case 0x15:op15();break;
case 0x1f:op1f();break;
case 0x22:op22();break;
case 0x25:op25();break;
case 0x2d:op2d();break;
case 0x40:op40();break;
case 0x54:op54();break;
case 0x5c:op5c();break;
case 0x5e:op5e();break;
case 0x60:op60();break;
case 0x62:op62();break;
case 0x64:op64();break;
case 0x66:op66();break;
case 0x68:op68();break;
case 0x6a:op6a();break;
case 0x6c:op6c();break;
case 0x6e:op6e();break;
case 0x70:op70();break;
case 0x72:op72();break;
case 0x74:op74();break;
case 0x76:op76();break;
case 0x78:op78();break;
case 0x7a:op7a();break;
case 0x7c:op7c();break;
case 0x89:op89();break;
}
}
}
void C4::writeb(uint16 addr, uint8 data) {
write(addr, data);
}
void C4::writew(uint16 addr, uint16 data) {
write(addr, data);
write(addr + 1, data >> 8);
}
void C4::writel(uint16 addr, uint32 data) {
write(addr, data);
write(addr + 1, data >> 8);
write(addr + 2, data >> 16);
}
uint8 C4::read(uint16 addr) {
addr &= 0x1fff;
if(addr < 0x0c00) {
return ram[addr];
}
if(addr >= 0x1f00) {
return reg[addr & 0xff];
}
return r_cpu->regs.mdr;
}
uint8 C4::readb(uint16 addr) {
return read(addr);
}
uint16 C4::readw(uint16 addr) {
return read(addr) | (read(addr + 1) << 8);
}
uint32 C4::readl(uint16 addr) {
return read(addr) | (read(addr + 1) << 8) + (read(addr + 2) << 16);
}
void C4::power() {
reset();
}
void C4::reset() {
memset(ram, 0, 0x0c00);
memset(reg, 0, 0x0100);
}
C4::C4() {}
+94
View File
@@ -0,0 +1,94 @@
class C4 {
private:
uint8 ram[0x0c00];
uint8 reg[0x0100];
uint32 r0, r1, r2, r3, r4, r5, r6, r7,
r8, r9, r10, r11, r12, r13, r14, r15;
static const uint8 immediate_data[48];
static const uint16 wave_data[40];
static const uint32 sin_table[256];
static const int16 SinTable[512];
static const int16 CosTable[512];
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();
void C4DrawLine(int32 X1, int32 Y1, int16 Z1, int32 X2, int32 Y2, int16 Z2, uint8 Color);
void C4DrawWireFrame();
void C4DoScaleRotate(int row_padding);
public:
uint32 ldr(uint8 r);
void str(uint8 r, uint32 data);
void mul(uint32 x, uint32 y, uint32 &rl, uint32 &rh);
uint32 sin(uint32 rx);
uint32 cos(uint32 rx);
void transfer_data();
void immediate_reg(uint32 num);
void op00_00();
void op00_03();
void op00_05();
void op00_07();
void op00_08();
void op00_0b();
void op00_0c();
void op00();
void op01();
void op05();
void op0d();
void op10();
void op13();
void op15();
void op1f();
void op22();
void op25();
void op2d();
void op40();
void op54();
void op5c();
void op5e();
void op60();
void op62();
void op64();
void op66();
void op68();
void op6a();
void op6c();
void op6e();
void op70();
void op72();
void op74();
void op76();
void op78();
void op7a();
void op7c();
void op89();
void init();
void enable();
void power();
void reset();
void write (uint16 addr, uint8 data);
void writeb(uint16 addr, uint8 data);
void writew(uint16 addr, uint16 data);
void writel(uint16 addr, uint32 data);
uint8 read (uint16 addr);
uint8 readb(uint16 addr);
uint16 readw(uint16 addr);
uint32 readl(uint16 addr);
C4();
};
+183
View File
@@ -0,0 +1,183 @@
const uint8 C4::immediate_data[48] = {
0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff,
0xff, 0xff, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x80, 0xff, 0xff, 0x7f,
0x00, 0x80, 0x00, 0xff, 0x7f, 0x00, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0xff,
0x00, 0x00, 0x01, 0xff, 0xff, 0xfe, 0x00, 0x01, 0x00, 0xff, 0xfe, 0x00
};
const uint16 C4::wave_data[40] = {
0x0000, 0x0002, 0x0004, 0x0006, 0x0008, 0x000a, 0x000c, 0x000e,
0x0200, 0x0202, 0x0204, 0x0206, 0x0208, 0x020a, 0x020c, 0x020e,
0x0400, 0x0402, 0x0404, 0x0406, 0x0408, 0x040a, 0x040c, 0x040e,
0x0600, 0x0602, 0x0604, 0x0606, 0x0608, 0x060a, 0x060c, 0x060e,
0x0800, 0x0802, 0x0804, 0x0806, 0x0808, 0x080a, 0x080c, 0x080e
};
const uint32 C4::sin_table[256] = {
0x000000, 0x000324, 0x000648, 0x00096c, 0x000c8f, 0x000fb2, 0x0012d5, 0x0015f6,
0x001917, 0x001c37, 0x001f56, 0x002273, 0x002590, 0x0028aa, 0x002bc4, 0x002edb,
0x0031f1, 0x003505, 0x003817, 0x003b26, 0x003e33, 0x00413e, 0x004447, 0x00474d,
0x004a50, 0x004d50, 0x00504d, 0x005347, 0x00563e, 0x005931, 0x005c22, 0x005f0e,
0x0061f7, 0x0064dc, 0x0067bd, 0x006a9b, 0x006d74, 0x007049, 0x007319, 0x0075e5,
0x0078ad, 0x007b70, 0x007e2e, 0x0080e7, 0x00839c, 0x00864b, 0x0088f5, 0x008b9a,
0x008e39, 0x0090d3, 0x009368, 0x0095f6, 0x00987f, 0x009b02, 0x009d7f, 0x009ff6,
0x00a267, 0x00a4d2, 0x00a736, 0x00a994, 0x00abeb, 0x00ae3b, 0x00b085, 0x00b2c8,
0x00b504, 0x00b73a, 0x00b968, 0x00bb8f, 0x00bdae, 0x00bfc7, 0x00c1d8, 0x00c3e2,
0x00c5e4, 0x00c7de, 0x00c9d1, 0x00cbbb, 0x00cd9f, 0x00cf7a, 0x00d14d, 0x00d318,
0x00d4db, 0x00d695, 0x00d848, 0x00d9f2, 0x00db94, 0x00dd2d, 0x00debe, 0x00e046,
0x00e1c5, 0x00e33c, 0x00e4aa, 0x00e60f, 0x00e76b, 0x00e8bf, 0x00ea09, 0x00eb4b,
0x00ec83, 0x00edb2, 0x00eed8, 0x00eff5, 0x00f109, 0x00f213, 0x00f314, 0x00f40b,
0x00f4fa, 0x00f5de, 0x00f6ba, 0x00f78b, 0x00f853, 0x00f912, 0x00f9c7, 0x00fa73,
0x00fb14, 0x00fbac, 0x00fc3b, 0x00fcbf, 0x00fd3a, 0x00fdab, 0x00fe13, 0x00fe70,
0x00fec4, 0x00ff0e, 0x00ff4e, 0x00ff84, 0x00ffb1, 0x00ffd3, 0x00ffec, 0x00fffb,
0x000000, 0xfffcdb, 0xfff9b7, 0xfff693, 0xfff370, 0xfff04d, 0xffed2a, 0xffea09,
0xffe6e8, 0xffe3c8, 0xffe0a9, 0xffdd8c, 0xffda6f, 0xffd755, 0xffd43b, 0xffd124,
0xffce0e, 0xffcafa, 0xffc7e8, 0xffc4d9, 0xffc1cc, 0xffbec1, 0xffbbb8, 0xffb8b2,
0xffb5af, 0xffb2af, 0xffafb2, 0xffacb8, 0xffa9c1, 0xffa6ce, 0xffa3dd, 0xffa0f1,
0xff9e08, 0xff9b23, 0xff9842, 0xff9564, 0xff928b, 0xff8fb6, 0xff8ce6, 0xff8a1a,
0xff8752, 0xff848f, 0xff81d1, 0xff7f18, 0xff7c63, 0xff79b4, 0xff770a, 0xff7465,
0xff71c6, 0xff6f2c, 0xff6c97, 0xff6a09, 0xff6780, 0xff64fd, 0xff6280, 0xff6009,
0xff5d98, 0xff5b2d, 0xff58c9, 0xff566b, 0xff5414, 0xff51c4, 0xff4f7a, 0xff4d37,
0xff4afb, 0xff48c5, 0xff4697, 0xff4470, 0xff4251, 0xff4038, 0xff3e27, 0xff3c1e,
0xff3a1b, 0xff3821, 0xff362e, 0xff3444, 0xff3260, 0xff3085, 0xff2eb2, 0xff2ce7,
0xff2b24, 0xff296a, 0xff27b7, 0xff260d, 0xff246b, 0xff22d2, 0xff2141, 0xff1fb9,
0xff1e3a, 0xff1cc3, 0xff1b55, 0xff19f0, 0xff1894, 0xff1740, 0xff15f6, 0xff14b4,
0xff137c, 0xff124d, 0xff1127, 0xff100a, 0xff0ef6, 0xff0dec, 0xff0ceb, 0xff0bf4,
0xff0b05, 0xff0a21, 0xff0945, 0xff0874, 0xff07ac, 0xff06ed, 0xff0638, 0xff058d,
0xff04eb, 0xff0453, 0xff03c4, 0xff0340, 0xff02c5, 0xff0254, 0xff01ec, 0xff018f,
0xff013b, 0xff00f1, 0xff00b1, 0xff007b, 0xff004e, 0xff002c, 0xff0013, 0xff0004
};
const int16 C4::SinTable[512] = {
0, 402, 804, 1206, 1607, 2009, 2410, 2811,
3211, 3611, 4011, 4409, 4808, 5205, 5602, 5997,
6392, 6786, 7179, 7571, 7961, 8351, 8739, 9126,
9512, 9896, 10278, 10659, 11039, 11416, 11793, 12167,
12539, 12910, 13278, 13645, 14010, 14372, 14732, 15090,
15446, 15800, 16151, 16499, 16846, 17189, 17530, 17869,
18204, 18537, 18868, 19195, 19519, 19841, 20159, 20475,
20787, 21097, 21403, 21706, 22005, 22301, 22594, 22884,
23170, 23453, 23732, 24007, 24279, 24547, 24812, 25073,
25330, 25583, 25832, 26077, 26319, 26557, 26790, 27020,
27245, 27466, 27684, 27897, 28106, 28310, 28511, 28707,
28898, 29086, 29269, 29447, 29621, 29791, 29956, 30117,
30273, 30425, 30572, 30714, 30852, 30985, 31114, 31237,
31357, 31471, 31581, 31685, 31785, 31881, 31971, 32057,
32138, 32214, 32285, 32351, 32413, 32469, 32521, 32568,
32610, 32647, 32679, 32706, 32728, 32745, 32758, 32765,
32767, 32765, 32758, 32745, 32728, 32706, 32679, 32647,
32610, 32568, 32521, 32469, 32413, 32351, 32285, 32214,
32138, 32057, 31971, 31881, 31785, 31685, 31581, 31471,
31357, 31237, 31114, 30985, 30852, 30714, 30572, 30425,
30273, 30117, 29956, 29791, 29621, 29447, 29269, 29086,
28898, 28707, 28511, 28310, 28106, 27897, 27684, 27466,
27245, 27020, 26790, 26557, 26319, 26077, 25832, 25583,
25330, 25073, 24812, 24547, 24279, 24007, 23732, 23453,
23170, 22884, 22594, 22301, 22005, 21706, 21403, 21097,
20787, 20475, 20159, 19841, 19519, 19195, 18868, 18537,
18204, 17869, 17530, 17189, 16846, 16499, 16151, 15800,
15446, 15090, 14732, 14372, 14010, 13645, 13278, 12910,
12539, 12167, 11793, 11416, 11039, 10659, 10278, 9896,
9512, 9126, 8739, 8351, 7961, 7571, 7179, 6786,
6392, 5997, 5602, 5205, 4808, 4409, 4011, 3611,
3211, 2811, 2410, 2009, 1607, 1206, 804, 402,
0, -402, -804, -1206, -1607, -2009, -2410, -2811,
-3211, -3611, -4011, -4409, -4808, -5205, -5602, -5997,
-6392, -6786, -7179, -7571, -7961, -8351, -8739, -9126,
-9512, -9896, -10278, -10659, -11039, -11416, -11793, -12167,
-12539, -12910, -13278, -13645, -14010, -14372, -14732, -15090,
-15446, -15800, -16151, -16499, -16846, -17189, -17530, -17869,
-18204, -18537, -18868, -19195, -19519, -19841, -20159, -20475,
-20787, -21097, -21403, -21706, -22005, -22301, -22594, -22884,
-23170, -23453, -23732, -24007, -24279, -24547, -24812, -25073,
-25330, -25583, -25832, -26077, -26319, -26557, -26790, -27020,
-27245, -27466, -27684, -27897, -28106, -28310, -28511, -28707,
-28898, -29086, -29269, -29447, -29621, -29791, -29956, -30117,
-30273, -30425, -30572, -30714, -30852, -30985, -31114, -31237,
-31357, -31471, -31581, -31685, -31785, -31881, -31971, -32057,
-32138, -32214, -32285, -32351, -32413, -32469, -32521, -32568,
-32610, -32647, -32679, -32706, -32728, -32745, -32758, -32765,
-32767, -32765, -32758, -32745, -32728, -32706, -32679, -32647,
-32610, -32568, -32521, -32469, -32413, -32351, -32285, -32214,
-32138, -32057, -31971, -31881, -31785, -31685, -31581, -31471,
-31357, -31237, -31114, -30985, -30852, -30714, -30572, -30425,
-30273, -30117, -29956, -29791, -29621, -29447, -29269, -29086,
-28898, -28707, -28511, -28310, -28106, -27897, -27684, -27466,
-27245, -27020, -26790, -26557, -26319, -26077, -25832, -25583,
-25330, -25073, -24812, -24547, -24279, -24007, -23732, -23453,
-23170, -22884, -22594, -22301, -22005, -21706, -21403, -21097,
-20787, -20475, -20159, -19841, -19519, -19195, -18868, -18537,
-18204, -17869, -17530, -17189, -16846, -16499, -16151, -15800,
-15446, -15090, -14732, -14372, -14010, -13645, -13278, -12910,
-12539, -12167, -11793, -11416, -11039, -10659, -10278, -9896,
-9512, -9126, -8739, -8351, -7961, -7571, -7179, -6786,
-6392, -5997, -5602, -5205, -4808, -4409, -4011, -3611,
-3211, -2811, -2410, -2009, -1607, -1206, -804, -402
};
const int16 C4::CosTable[512] = {
32767, 32765, 32758, 32745, 32728, 32706, 32679, 32647,
32610, 32568, 32521, 32469, 32413, 32351, 32285, 32214,
32138, 32057, 31971, 31881, 31785, 31685, 31581, 31471,
31357, 31237, 31114, 30985, 30852, 30714, 30572, 30425,
30273, 30117, 29956, 29791, 29621, 29447, 29269, 29086,
28898, 28707, 28511, 28310, 28106, 27897, 27684, 27466,
27245, 27020, 26790, 26557, 26319, 26077, 25832, 25583,
25330, 25073, 24812, 24547, 24279, 24007, 23732, 23453,
23170, 22884, 22594, 22301, 22005, 21706, 21403, 21097,
20787, 20475, 20159, 19841, 19519, 19195, 18868, 18537,
18204, 17869, 17530, 17189, 16846, 16499, 16151, 15800,
15446, 15090, 14732, 14372, 14010, 13645, 13278, 12910,
12539, 12167, 11793, 11416, 11039, 10659, 10278, 9896,
9512, 9126, 8739, 8351, 7961, 7571, 7179, 6786,
6392, 5997, 5602, 5205, 4808, 4409, 4011, 3611,
3211, 2811, 2410, 2009, 1607, 1206, 804, 402,
0, -402, -804, -1206, -1607, -2009, -2410, -2811,
-3211, -3611, -4011, -4409, -4808, -5205, -5602, -5997,
-6392, -6786, -7179, -7571, -7961, -8351, -8739, -9126,
-9512, -9896, -10278, -10659, -11039, -11416, -11793, -12167,
-12539, -12910, -13278, -13645, -14010, -14372, -14732, -15090,
-15446, -15800, -16151, -16499, -16846, -17189, -17530, -17869,
-18204, -18537, -18868, -19195, -19519, -19841, -20159, -20475,
-20787, -21097, -21403, -21706, -22005, -22301, -22594, -22884,
-23170, -23453, -23732, -24007, -24279, -24547, -24812, -25073,
-25330, -25583, -25832, -26077, -26319, -26557, -26790, -27020,
-27245, -27466, -27684, -27897, -28106, -28310, -28511, -28707,
-28898, -29086, -29269, -29447, -29621, -29791, -29956, -30117,
-30273, -30425, -30572, -30714, -30852, -30985, -31114, -31237,
-31357, -31471, -31581, -31685, -31785, -31881, -31971, -32057,
-32138, -32214, -32285, -32351, -32413, -32469, -32521, -32568,
-32610, -32647, -32679, -32706, -32728, -32745, -32758, -32765,
-32767, -32765, -32758, -32745, -32728, -32706, -32679, -32647,
-32610, -32568, -32521, -32469, -32413, -32351, -32285, -32214,
-32138, -32057, -31971, -31881, -31785, -31685, -31581, -31471,
-31357, -31237, -31114, -30985, -30852, -30714, -30572, -30425,
-30273, -30117, -29956, -29791, -29621, -29447, -29269, -29086,
-28898, -28707, -28511, -28310, -28106, -27897, -27684, -27466,
-27245, -27020, -26790, -26557, -26319, -26077, -25832, -25583,
-25330, -25073, -24812, -24547, -24279, -24007, -23732, -23453,
-23170, -22884, -22594, -22301, -22005, -21706, -21403, -21097,
-20787, -20475, -20159, -19841, -19519, -19195, -18868, -18537,
-18204, -17869, -17530, -17189, -16846, -16499, -16151, -15800,
-15446, -15090, -14732, -14372, -14010, -13645, -13278, -12910,
-12539, -12167, -11793, -11416, -11039, -10659, -10278, -9896,
-9512, -9126, -8739, -8351, -7961, -7571, -7179, -6786,
-6392, -5997, -5602, -5205, -4808, -4409, -4011, -3611,
-3211, -2811, -2410, -2009, -1607, -1206, -804, -402,
0, 402, 804, 1206, 1607, 2009, 2410, 2811,
3211, 3611, 4011, 4409, 4808, 5205, 5602, 5997,
6392, 6786, 7179, 7571, 7961, 8351, 8739, 9126,
9512, 9896, 10278, 10659, 11039, 11416, 11793, 12167,
12539, 12910, 13278, 13645, 14010, 14372, 14732, 15090,
15446, 15800, 16151, 16499, 16846, 17189, 17530, 17869,
18204, 18537, 18868, 19195, 19519, 19841, 20159, 20475,
20787, 21097, 21403, 21706, 22005, 22301, 22594, 22884,
23170, 23453, 23732, 24007, 24279, 24547, 24812, 25073,
25330, 25583, 25832, 26077, 26319, 26557, 26790, 27020,
27245, 27466, 27684, 27897, 28106, 28310, 28511, 28707,
28898, 29086, 29269, 29447, 29621, 29791, 29956, 30117,
30273, 30425, 30572, 30714, 30852, 30985, 31114, 31237,
31357, 31471, 31581, 31685, 31785, 31881, 31971, 32057,
32138, 32214, 32285, 32351, 32413, 32469, 32521, 32568,
32610, 32647, 32679, 32706, 32728, 32745, 32758, 32765
};
+242
View File
@@ -0,0 +1,242 @@
#include <math.h>
#define Tan(a) (CosTable[a] ? ((((int32)SinTable[a]) << 16) / CosTable[a]) : 0x80000000)
#define sar(b, n) ((b) >> (n))
#ifdef PI
#undef PI
#endif
#define PI 3.1415926535897932384626433832795
//Wireframe Helpers
void C4::C4TransfWireFrame() {
c4x = (double)C4WFXVal;
c4y = (double)C4WFYVal;
c4z = (double)C4WFZVal - 0x95;
//Rotate X
tanval = -(double)C4WFX2Val * PI * 2 / 128;
c4y2 = c4y * ::cos(tanval) - c4z * ::sin(tanval);
c4z2 = c4y * ::sin(tanval) + c4z * ::cos(tanval);
//Rotate Y
tanval = -(double)C4WFY2Val * PI * 2 / 128;
c4x2 = c4x * ::cos(tanval) + c4z2 * ::sin(tanval);
c4z = c4x * -::sin(tanval) + c4z2 * ::cos(tanval);
//Rotate Z
tanval = -(double)C4WFDist * PI * 2 / 128;
c4x = c4x2 * ::cos(tanval) - c4y2 * ::sin(tanval);
c4y = c4x2 * ::sin(tanval) + c4y2 * ::cos(tanval);
//Scale
C4WFXVal = (int16)(c4x * C4WFScale / (0x90 * (c4z + 0x95)) * 0x95);
C4WFYVal = (int16)(c4y * C4WFScale / (0x90 * (c4z + 0x95)) * 0x95);
}
void C4::C4CalcWireFrame() {
C4WFXVal = C4WFX2Val - C4WFXVal;
C4WFYVal = C4WFY2Val - C4WFYVal;
if(abs(C4WFXVal) > abs(C4WFYVal)) {
C4WFDist = abs(C4WFXVal) + 1;
C4WFYVal = (256 * (long)C4WFYVal) / abs(C4WFXVal);
C4WFXVal = (C4WFXVal < 0) ? -256 : 256;
} else if(C4WFYVal != 0) {
C4WFDist = abs(C4WFYVal) + 1;
C4WFXVal = (256 * (long)C4WFXVal) / abs(C4WFYVal);
C4WFYVal = (C4WFYVal < 0) ? -256 : 256;
} else {
C4WFDist = 0;
}
}
void C4::C4TransfWireFrame2() {
c4x = (double)C4WFXVal;
c4y = (double)C4WFYVal;
c4z = (double)C4WFZVal;
//Rotate X
tanval = -(double)C4WFX2Val * PI * 2 / 128;
c4y2 = c4y * ::cos(tanval) - c4z * ::sin(tanval);
c4z2 = c4y * ::sin(tanval) + c4z * ::cos(tanval);
//Rotate Y
tanval = -(double)C4WFY2Val * PI * 2 / 128;
c4x2 = c4x * ::cos(tanval) + c4z2 * ::sin(tanval);
c4z = c4x * -::sin(tanval) + c4z2 * ::cos(tanval);
//Rotate Z
tanval = -(double)C4WFDist * PI * 2 / 128;
c4x = c4x2 * ::cos(tanval) - c4y2 * ::sin(tanval);
c4y = c4x2 * ::sin(tanval) + c4y2 * ::cos(tanval);
//Scale
C4WFXVal = (int16)(c4x * C4WFScale / 0x100);
C4WFYVal = (int16)(c4y * C4WFScale / 0x100);
}
void C4::C4DrawWireFrame() {
uint32 line = readl(0x1f80);
uint32 point1, point2;
int16 X1, Y1, Z1;
int16 X2, Y2, Z2;
uint8 Color;
for(int32 i = ram[0x0295]; i > 0; i--, line += 5) {
if(r_mem->read(line) == 0xff && r_mem->read(line + 1) == 0xff) {
int32 tmp = line - 5;
while(r_mem->read(tmp + 2) == 0xff && r_mem->read(tmp + 3) == 0xff && (tmp + 2) >= 0) { tmp -= 5; }
point1 = (read(0x1f82) << 16) | (r_mem->read(tmp + 2) << 8) | r_mem->read(tmp + 3);
} else {
point1 = (read(0x1f82) << 16) | (r_mem->read(line) << 8) | r_mem->read(line + 1);
}
point2 = (read(0x1f82) << 16) | (r_mem->read(line + 2) << 8) | r_mem->read(line + 3);
X1=(r_mem->read(point1 + 0) << 8) | r_mem->read(point1 + 1);
Y1=(r_mem->read(point1 + 2) << 8) | r_mem->read(point1 + 3);
Z1=(r_mem->read(point1 + 4) << 8) | r_mem->read(point1 + 5);
X2=(r_mem->read(point2 + 0) << 8) | r_mem->read(point2 + 1);
Y2=(r_mem->read(point2 + 2) << 8) | r_mem->read(point2 + 3);
Z2=(r_mem->read(point2 + 4) << 8) | r_mem->read(point2 + 5);
Color = r_mem->read(line + 4);
C4DrawLine(X1, Y1, Z1, X2, Y2, Z2, Color);
}
}
void C4::C4DrawLine(int32 X1, int32 Y1, int16 Z1, int32 X2, int32 Y2, int16 Z2, uint8 Color) {
//Transform coordinates
C4WFXVal = (int16)X1;
C4WFYVal = (int16)Y1;
C4WFZVal = Z1;
C4WFScale = read(0x1f90);
C4WFX2Val = read(0x1f86);
C4WFY2Val = read(0x1f87);
C4WFDist = read(0x1f88);
C4TransfWireFrame2();
X1 = (C4WFXVal + 48) << 8;
Y1 = (C4WFYVal + 48) << 8;
C4WFXVal = (int16)X2;
C4WFYVal = (int16)Y2;
C4WFZVal = Z2;
C4TransfWireFrame2();
X2 = (C4WFXVal + 48) << 8;
Y2 = (C4WFYVal + 48) << 8;
//Get line info
C4WFXVal = (int16)(X1 >> 8);
C4WFYVal = (int16)(Y1 >> 8);
C4WFX2Val = (int16)(X2 >> 8);
C4WFY2Val = (int16)(Y2 >> 8);
C4CalcWireFrame();
X2 = (int16)C4WFXVal;
Y2 = (int16)C4WFYVal;
//Render line
for(int32 i = C4WFDist ? C4WFDist : 1; i > 0; i--) {
if(X1 > 0xff && Y1 > 0xff && X1 < 0x6000 && Y1 < 0x6000) {
uint16 addr = (((Y1 >> 8) >> 3) << 8) - (((Y1 >> 8) >> 3) << 6) + (((X1 >> 8) >> 3) << 4) + ((Y1 >> 8) & 7) * 2;
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; }
}
X1 += X2;
Y1 += Y2;
}
}
void C4::C4DoScaleRotate(int row_padding) {
int16 A, B, C, D;
//Calculate matrix
int32 XScale = readw(0x1f8f);
int32 YScale = readw(0x1f92);
if(XScale & 0x8000)XScale = 0x7fff;
if(YScale & 0x8000)YScale = 0x7fff;
if(readw(0x1f80) == 0) { //no rotation
A = (int16)XScale;
B = 0;
C = 0;
D = (int16)YScale;
} 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
A = (int16)(-XScale);
B = 0;
C = 0;
D = (int16)(-YScale);
} else if(readw(0x1f80) == 384) { //270 degree rotation
A = 0;
B = (int16)YScale;
C = (int16)(-XScale);
D = 0;
} else {
A = (int16) sar(CosTable[readw(0x1f80) & 0x1ff] * XScale, 15);
B = (int16)(-sar(SinTable[readw(0x1f80) & 0x1ff] * YScale, 15));
C = (int16) sar(SinTable[readw(0x1f80) & 0x1ff] * XScale, 15);
D = (int16) sar(CosTable[readw(0x1f80) & 0x1ff] * YScale, 15);
}
//Calculate Pixel Resolution
uint8 w = read(0x1f89) & ~7;
uint8 h = read(0x1f8c) & ~7;
//Clear the output RAM
memset(ram, 0, (w + row_padding / 4) * h / 2);
int32 Cx = (int16)readw(0x1f83);
int32 Cy = (int16)readw(0x1f86);
//Calculate start position (i.e. (Ox, Oy) = (0, 0))
//The low 12 bits are fractional, so (Cx<<12) gives us the Cx we want in
//the function. We do Cx*A etc normally because the matrix parameters
//already have the fractional parts.
int32 LineX = (Cx << 12) - Cx * A - Cx * B;
int32 LineY = (Cy << 12) - Cy * C - Cy * D;
//Start loop
uint32 X, Y;
uint8 byte;
int32 outidx = 0;
uint8 bit = 0x80;
for(int32 y = 0; y < h; y++) {
X = LineX;
Y = LineY;
for(int32 x = 0; x < w; x++) {
if((X >> 12) >= w || (Y >> 12) >= h) {
byte = 0;
} else {
uint32 addr = (Y >> 12) * w + (X >> 12);
byte = read(0x600 + (addr >> 1));
if(addr & 1) { byte >>= 4; }
}
//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; }
bit >>= 1;
if(!bit) {
bit = 0x80;
outidx += 32;
}
X += A; //Add 1 to output x => add an A and a C
Y += C;
}
outidx += 2 + row_padding;
if(outidx & 0x10) {
outidx &= ~0x10;
} else {
outidx -= w * 4 + row_padding;
}
LineX += B; //Add 1 to output y => add a B and a D
LineY += D;
}
}
+224
View File
@@ -0,0 +1,224 @@
//Build OAM
void C4::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;
}
uint16 globalx, globaly;
uint32 oamptr2;
int16 sprx, spry;
uint8 sprname, sprattr;
uint8 sprcount;
globalx = readw(0x621);
globaly = readw(0x623);
oamptr2 = 0x200 + (ram[0x626] >> 2);
if(!ram[0x620])return;
sprcount = 128 - ram[0x626];
uint8 offset = (ram[0x626] & 3) * 2;
for(int pri=0x30;pri>=0;pri-=0x10) {
uint32 srcptr = 0x220;
for(int i=ram[0x620];i>0 && sprcount>0;i--, srcptr+=16) {
if((ram[srcptr + 4] & 0x30) != pri)continue;
sprx = readw(srcptr) - globalx;
spry = readw(srcptr + 2) - globaly;
sprname = ram[srcptr + 5];
sprattr = ram[srcptr + 4] | ram[srcptr + 6];
uint32 spraddr = readl(srcptr + 7);
if(r_mem->read(spraddr)) {
int16 x, y;
for(int sprcnt=r_mem->read(spraddr++);sprcnt>0 && sprcount>0;sprcnt--, spraddr+=4) {
x = (int8)r_mem->read(spraddr + 1);
if(sprattr & 0x40) {
x = -x - ((r_mem->read(spraddr) & 0x20) ? 16 : 8);
}
x += sprx;
if(x >= -16 && x <= 272) {
y = (int8)r_mem->read(spraddr + 2);
if(sprattr & 0x80) {
y = -y - ((r_mem->read(spraddr) & 0x20) ? 16 : 8);
}
y += spry;
if(y >= -16 && y <= 224) {
ram[oamptr ] = (uint8)x;
ram[oamptr + 1] = (uint8)y;
ram[oamptr + 2] = sprname + r_mem->read(spraddr + 3);
ram[oamptr + 3] = sprattr ^ (r_mem->read(spraddr) & 0xc0);
ram[oamptr2] &= ~(3 << offset);
if(x & 0x100)ram[oamptr2] |= 1 << offset;
if(r_mem->read(spraddr) & 0x20)ram[oamptr2] |= 2 << offset;
oamptr += 4;
sprcount--;
offset = (offset + 2) & 6;
if(!offset)oamptr2++;
}
}
}
} else if(sprcount > 0) {
ram[oamptr ] = (uint8)sprx;
ram[oamptr + 1] = (uint8)spry;
ram[oamptr + 2] = sprname;
ram[oamptr + 3] = sprattr;
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++;
}
}
}
}
//Scale and Rotate
void C4::op00_03() {
C4DoScaleRotate(0);
}
//Transform Lines
void C4::op00_05() {
C4WFX2Val = read(0x1f83);
C4WFY2Val = read(0x1f86);
C4WFDist = read(0x1f89);
C4WFScale = read(0x1f8c);
//Transform Vertices
uint32 ptr = 0;
for(int32 i = readw(0x1f80); i > 0; i--, ptr += 0x10) {
C4WFXVal = readw(ptr + 1);
C4WFYVal = readw(ptr + 5);
C4WFZVal = readw(ptr + 9);
C4TransfWireFrame();
//Displace
writew(ptr + 1, C4WFXVal + 0x80);
writew(ptr + 5, C4WFYVal + 0x50);
}
writew(0x600, 23);
writew(0x602, 0x60);
writew(0x605, 0x40);
writew(0x600 + 8, 23);
writew(0x602 + 8, 0x60);
writew(0x605 + 8, 0x40);
ptr = 0xb02;
uint32 ptr2 = 0;
for(int32 i = readw(0xb00); i > 0; i--, ptr += 2, ptr2 += 8) {
C4WFXVal = readw((read(ptr + 0) << 4) + 1);
C4WFYVal = readw((read(ptr + 0) << 4) + 5);
C4WFX2Val = readw((read(ptr + 1) << 4) + 1);
C4WFY2Val = readw((read(ptr + 1) << 4) + 5);
C4CalcWireFrame();
writew(ptr2 + 0x600, C4WFDist ? C4WFDist : 1);
writew(ptr2 + 0x602, C4WFXVal);
writew(ptr2 + 0x605, C4WFYVal);
}
}
//Scale and Rotate
void C4::op00_07() {
C4DoScaleRotate(64);
}
//Draw Wireframe
void C4::op00_08() {
C4DrawWireFrame();
}
//Disintegrate
void C4::op00_0b() {
uint8 width, height;
uint32 startx, starty;
uint32 srcptr;
uint32 x, y;
int32 scalex, scaley;
int32 cx, cy;
int32 i, j;
width = read(0x1f89);
height = read(0x1f8c);
cx = readw(0x1f80);
cy = readw(0x1f83);
scalex = (int16)readw(0x1f86);
scaley = (int16)readw(0x1f8f);
startx = -cx * scalex + (cx << 8);
starty = -cy * scaley + (cy << 8);
srcptr = 0x600;
for(i = 0; i < (width * height) >> 1; i++) {
write(i, 0);
}
for(y = starty, i = 0;i < height; i++, y += scaley) {
for(x = startx, j = 0;j < width; j++, x += scalex) {
if((x >> 8) < width && (y >> 8) < height && (y >> 8) * width + (x >> 8) < 0x2000) {
uint8 pixel = (j & 1) ? (ram[srcptr] >> 4) : (ram[srcptr]);
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(j & 1)srcptr++;
}
}
}
//Bitplane Wave
void C4::op00_0c() {
uint32 destptr = 0;
uint32 waveptr = read(0x1f83);
uint16 mask1 = 0xc0c0;
uint16 mask2 = 0x3f3f;
int32 i, j;
int16 height, temp;
for(j = 0; j < 0x10; j++) {
do {
height = -((int8)ram[waveptr + 0xb00]) - 16;
for(i = 0; i < 40; i++) {
temp = readw(destptr + wave_data[i]) & mask2;
if(height >= 0) {
if(height < 8) {
temp |= mask1 & readw(0xa00 + height * 2);
} else {
temp |= mask1 & 0xff00;
}
}
writew(destptr + wave_data[i], temp);
height++;
}
waveptr = (waveptr + 1) & 0x7f;
mask1 = (mask1 >> 2) | (mask1 << 6);
mask2 = (mask2 >> 2) | (mask2 << 6);
} while(mask1 != 0xc0c0);
destptr += 16;
do {
height = -((int8)ram[waveptr + 0xb00]) - 16;
for(i = 0; i < 40; i++) {
temp = readw(destptr + wave_data[i]) & mask2;
if(height >= 0) {
if(height < 8) {
temp |= mask1 & readw(0xa10 + height * 2);
} else {
temp |= mask1 & 0xff00;
}
writew(destptr + wave_data[i], temp);
height++;
}
waveptr = (waveptr + 1) & 0x7f;
mask1 = (mask1 >> 2) | (mask1 << 6);
mask2 = (mask2 >> 2) | (mask2 << 6);
}
} while(mask1 != 0xc0c0);
destptr += 16;
}
}
+222
View File
@@ -0,0 +1,222 @@
//Sprite Functions
void C4::op00() {
switch(reg[0x4d]) {
case 0x00:op00_00();break;
case 0x03:op00_03();break;
case 0x05:op00_05();break;
case 0x07:op00_07();break;
case 0x08:op00_08();break;
case 0x0b:op00_0b();break;
case 0x0c:op00_0c();break;
}
}
//Draw Wireframe
void C4::op01() {
memset(ram + 0x300, 0, 2304);
C4DrawWireFrame();
}
//Propulsion
void C4::op05() {
int32 temp = 0x10000;
if(readw(0x1f83)) {
temp = sar((temp / readw(0x1f83)) * readw(0x1f81), 8);
}
writew(0x1f80, temp);
}
//Set Vector length
void C4::op0d() {
C41FXVal = readw(0x1f80);
C41FYVal = readw(0x1f83);
C41FDistVal = readw(0x1f86);
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);
writew(0x1f89, C41FXVal);
writew(0x1f8c, C41FYVal);
}
//Triangle
void C4::op10() {
r0 = ldr(0);
r1 = ldr(1);
r4 = r0 & 0x1ff;
if(r1 & 0x8000)r1 |= ~0x7fff;
mul(cos(r4), r1, r5, r2);
r5 = (r5 >> 16) & 0xff;
r2 = (r2 << 8) + r5;
mul(sin(r4), r1, r5, r3);
r5 = (r5 >> 16) & 0xff;
r3 = (r3 << 8) + r5;
str(0, r0);
str(1, r1);
str(2, r2);
str(3, r3);
str(4, r4);
str(5, r5);
}
//Triangle
void C4::op13() {
r0 = ldr(0);
r1 = ldr(1);
r4 = r0 & 0x1ff;
mul(cos(r4), r1, r5, r2);
r5 = (r5 >> 8) & 0xffff;
r2 = (r2 << 16) + r5;
mul(sin(r4), r1, r5, r3);
r5 = (r5 >> 8) & 0xffff;
r3 = (r3 << 16) + r5;
str(0, r0);
str(1, r1);
str(2, r2);
str(3, r3);
str(4, r4);
str(5, r5);
}
//Pythagorean
void C4::op15() {
C41FXVal = readw(0x1f80);
C41FYVal = readw(0x1f83);
C41FDist = (int16)sqrt((double)C41FXVal * (double)C41FXVal + (double)C41FYVal * (double)C41FYVal);
writew(0x1f80, C41FDist);
}
//Calculate distance
void C4::op1f() {
C41FXVal = readw(0x1f80);
C41FYVal = readw(0x1f83);
if(!C41FXVal) {
C41FAngleRes = (C41FYVal > 0) ? 0x080 : 0x180;
} else {
tanval = ((double)C41FYVal) / ((double)C41FXVal);
C41FAngleRes = (short)(atan(tanval) / (PI * 2) * 512);
C41FAngleRes = C41FAngleRes;
if(C41FXVal < 0) {
C41FAngleRes += 0x100;
}
C41FAngleRes &= 0x1ff;
}
writew(0x1f86, C41FAngleRes);
}
//Trapezoid
void C4::op22() {
int16 angle1 = readw(0x1f8c) & 0x1ff;
int16 angle2 = readw(0x1f8f) & 0x1ff;
int32 tan1 = Tan(angle1);
int32 tan2 = Tan(angle2);
int16 y = readw(0x1f83) - readw(0x1f89);
int16 left, right;
for(int32 j = 0; j < 225; j++, y++) {
if(y >= 0) {
left = sar((int32)tan1 * y, 16) - readw(0x1f80) + readw(0x1f86);
right = sar((int32)tan2 * y, 16) - readw(0x1f80) + readw(0x1f86) + readw(0x1f93);
if(left < 0 && right < 0) {
left = 1;
right = 0;
} else if(left < 0) {
left = 0;
} else if(right < 0) {
right = 0;
}
if(left > 255 && right > 255) {
left = 255;
right = 254;
} else if(left > 255) {
left = 255;
} else if(right > 255) {
right = 255;
}
} else {
left = 1;
right = 0;
}
ram[j + 0x800] = (uint8)left;
ram[j + 0x900] = (uint8)right;
}
}
//Multiply
void C4::op25() {
r0 = ldr(0);
r1 = ldr(1);
mul(r0, r1, r0, r1);
str(0, r0);
str(1, r1);
}
//Transform Coords
void C4::op2d() {
C4WFXVal = readw(0x1f81);
C4WFYVal = readw(0x1f84);
C4WFZVal = readw(0x1f87);
C4WFX2Val = read (0x1f89);
C4WFY2Val = read (0x1f8a);
C4WFDist = read (0x1f8b);
C4WFScale = readw(0x1f90);
C4TransfWireFrame2();
writew(0x1f80, C4WFXVal);
writew(0x1f83, C4WFYVal);
}
//Sum
void C4::op40() {
r0 = 0;
for(uint32 i=0;i<0x800;i++) {
r0 += ram[i];
}
str(0, r0);
}
//Square
void C4::op54() {
r0 = ldr(0);
mul(r0, r0, r1, r2);
str(1, r1);
str(2, r2);
}
//Immediate Register
void C4::op5c() {
str(0, 0x000000);
immediate_reg(0);
}
//Immediate Register (Multiple)
void C4::op5e() { immediate_reg( 0); }
void C4::op60() { immediate_reg( 3); }
void C4::op62() { immediate_reg( 6); }
void C4::op64() { immediate_reg( 9); }
void C4::op66() { immediate_reg(12); }
void C4::op68() { immediate_reg(15); }
void C4::op6a() { immediate_reg(18); }
void C4::op6c() { immediate_reg(21); }
void C4::op6e() { immediate_reg(24); }
void C4::op70() { immediate_reg(27); }
void C4::op72() { immediate_reg(30); }
void C4::op74() { immediate_reg(33); }
void C4::op76() { immediate_reg(36); }
void C4::op78() { immediate_reg(39); }
void C4::op7a() { immediate_reg(42); }
void C4::op7c() { immediate_reg(45); }
//Immediate ROM
void C4::op89() {
str(0, 0x054336);
str(1, 0xffffff);
}
+3 -4
View File
@@ -1,12 +1,11 @@
#include "../../base.h"
#include "sdd1emu.cpp"
void SDD1::init() {
}
void SDD1::init() {}
void SDD1::enable() {
for(int i=0x4800;i<=0x4807;i++) {
mem_bus->set_mmio_mapper(i, mmio);
r_mem->set_mmio_mapper(i, mmio);
}
}
@@ -47,7 +46,7 @@ uint8 SDD1::mmio_read(uint16 addr) {
case 0x4807:return (sdd1.index[3] >> 20) & 7;
}
return cpu->regs.mdr;
return r_cpu->regs.mdr;
}
void SDD1::mmio_write(uint16 addr, uint8 data) {
+1 -1
View File
@@ -28,7 +28,7 @@ understood.
************************************************************************/
#define SDD1_read(__addr) (mem_bus->read(__addr))
#define SDD1_read(__addr) (r_mem->read(__addr))
////////////////////////////////////////////////////
+4 -5
View File
@@ -74,12 +74,11 @@ tm *t;
srtc.data[12] = t->tm_wday;
}
void SRTC::init() {
}
void SRTC::init() {}
void SRTC::enable() {
mem_bus->set_mmio_mapper(0x2800, mmio);
mem_bus->set_mmio_mapper(0x2801, mmio);
r_mem->set_mmio_mapper(0x2800, mmio);
r_mem->set_mmio_mapper(0x2801, mmio);
}
void SRTC::power() {
@@ -176,7 +175,7 @@ uint8 SRTCMMIO::read(uint32 addr) {
case 0x2800:return srtc->read();
}
return cpu->regs.mdr;
return r_cpu->regs.mdr;
}
void SRTCMMIO::write(uint32 addr, uint8 value) {
+19 -3
View File
@@ -21,8 +21,24 @@ void SNES::VideoColorAdjust::set(uint32 _data) {
::snes->update_color_lookup_table();
}
Setting SNES::mute(&config_file, "snes.mute",
"Mutes SNES audio output when enabled",
true, Setting::TRUE_FALSE);
Setting SNES::mute(&config_file, "snes.mute", "Mutes SNES audio output when enabled",
false, Setting::TRUE_FALSE);
//do not save these settings to config_file
Setting CPU::hdma_enable(0, "cpu.hdma_enable", "Enable HDMA effects", true, Setting::TRUE_FALSE);
Setting PPU::opt_enable(0, "ppu.opt_enable", "Enable offset-per-tile effects", true, Setting::TRUE_FALSE);
Setting PPU::bg1_pri0_enable(0, "ppu.bg1_pri0_enable", "Enable BG1 Priority 0", true, Setting::TRUE_FALSE);
Setting PPU::bg1_pri1_enable(0, "ppu.bg1_pri1_enable", "Enable BG1 Priority 1", true, Setting::TRUE_FALSE);
Setting PPU::bg2_pri0_enable(0, "ppu.bg2_pri0_enable", "Enable BG2 Priority 0", true, Setting::TRUE_FALSE);
Setting PPU::bg2_pri1_enable(0, "ppu.bg2_pri1_enable", "Enable BG2 Priority 1", true, Setting::TRUE_FALSE);
Setting PPU::bg3_pri0_enable(0, "ppu.bg3_pri0_enable", "Enable BG3 Priority 0", true, Setting::TRUE_FALSE);
Setting PPU::bg3_pri1_enable(0, "ppu.bg3_pri1_enable", "Enable BG3 Priority 1", true, Setting::TRUE_FALSE);
Setting PPU::bg4_pri0_enable(0, "ppu.bg4_pri0_enable", "Enable BG4 Priority 0", true, Setting::TRUE_FALSE);
Setting PPU::bg4_pri1_enable(0, "ppu.bg4_pri1_enable", "Enable BG4 Priority 1", true, Setting::TRUE_FALSE);
Setting PPU::oam_pri0_enable(0, "ppu.oam_pri0_enable", "Enable OAM Priority 0", true, Setting::TRUE_FALSE);
Setting PPU::oam_pri1_enable(0, "ppu.oam_pri1_enable", "Enable OAM Priority 1", true, Setting::TRUE_FALSE);
Setting PPU::oam_pri2_enable(0, "ppu.oam_pri2_enable", "Enable OAM Priority 2", true, Setting::TRUE_FALSE);
Setting PPU::oam_pri3_enable(0, "ppu.oam_pri3_enable", "Enable OAM Priority 3", true, Setting::TRUE_FALSE);
};
+15
View File
@@ -12,4 +12,19 @@ extern struct SNES {
static Setting mute;
} snes;
extern struct CPU {
static Setting hdma_enable;
} cpu;
extern struct PPU {
static Setting opt_enable;
static Setting bg1_pri0_enable, bg1_pri1_enable;
static Setting bg2_pri0_enable, bg2_pri1_enable;
static Setting bg3_pri0_enable, bg3_pri1_enable;
static Setting bg4_pri0_enable, bg4_pri1_enable;
static Setting oam_pri0_enable, oam_pri1_enable;
static Setting oam_pri2_enable, oam_pri3_enable;
} ppu;
};
+18 -26
View File
@@ -28,29 +28,18 @@ void bCPU::run() {
return;
}
if(run_state.irq) {
irq_run();
return;
}
if(run_state.stp) {
exec_cycle();
return;
}
if(status.cycle_pos == 0) {
//interrupts only trigger on opcode edges
if(time.nmi_pending == true) {
time.nmi_pending = false;
aa.w = 0xffea;
run_state.irq = true;
return;
}
if(time.irq_pending == true) {
time.irq_pending = false;
aa.w = 0xffee;
run_state.irq = true;
return;
if(!run_state.irq && !run_state.stp) {
if(time.nmi_pending == true) {
time.nmi_pending = false;
aa.w = 0xffea;
run_state.irq = true;
} else if(time.irq_pending == true) {
time.irq_pending = false;
aa.w = 0xffee;
run_state.irq = true;
}
}
}
@@ -96,7 +85,7 @@ void bCPU::power() {
void bCPU::reset() {
//reset vector location
regs.pc = mem_bus->read(0xfffc) | (mem_bus->read(0xfffd) << 8);
regs.pc = r_mem->read(0xfffc) | (r_mem->read(0xfffd) << 8);
//registers are not fully reset by SNES
regs.x.h = 0x00;
@@ -172,22 +161,25 @@ void bCPU::cpu_io() {
status.cycle_count = 6;
pre_exec_cycle();
add_cycles(6);
cycle_edge();
}
uint8 bCPU::mem_read(uint32 addr) {
status.cycle_count = mem_bus->speed(addr);
status.cycle_count = r_mem->speed(addr);
pre_exec_cycle();
add_cycles(status.cycle_count - 4);
regs.mdr = mem_bus->read(addr);
regs.mdr = r_mem->read(addr);
add_cycles(4);
cycle_edge();
return regs.mdr;
}
void bCPU::mem_write(uint32 addr, uint8 value) {
status.cycle_count = mem_bus->speed(addr);
status.cycle_count = r_mem->speed(addr);
pre_exec_cycle();
add_cycles(status.cycle_count);
mem_bus->write(addr, value);
r_mem->write(addr, value);
cycle_edge();
}
uint32 bCPU::op_addr(uint8 mode, uint32 addr) {
+18 -13
View File
@@ -25,10 +25,10 @@ uint8 x;
if(sdd1->dma_active() == true) {
x = sdd1->dma_read();
} else {
x = mem_bus->read(dma_addr(i));
x = r_mem->read(dma_addr(i));
}
mem_bus->write(0x2100 | ((channel[i].destaddr + index) & 0xff), x);
r_mem->write(0x2100 | ((channel[i].destaddr + index) & 0xff), x);
add_cycles(8);
channel[i].xfersize--;
@@ -36,8 +36,8 @@ uint8 x;
void bCPU::dma_mmiotocpu(uint8 i, uint8 index) {
uint8 x;
x = mem_bus->read(0x2100 | ((channel[i].destaddr + index) & 0xff));
mem_bus->write(dma_addr(i), x);
x = r_mem->read(0x2100 | ((channel[i].destaddr + index) & 0xff));
r_mem->write(dma_addr(i), x);
add_cycles(8);
channel[i].xfersize--;
@@ -113,21 +113,26 @@ uint16 index;
uint8 bCPU::hdma_read(uint8 i) {
if(channel[i].direction == DMA_MMIOTOCPU) {
return mem_bus->read(hdma_mmio(i));
return r_mem->read(hdma_mmio(i));
} else if(!channel[i].hdma_indirect) {
return mem_bus->read(hdma_addr(i));
return r_mem->read(hdma_addr(i));
} else {
return mem_bus->read(hdma_iaddr(i));
return r_mem->read(hdma_iaddr(i));
}
}
void bCPU::hdma_write(uint8 i, uint8 x) {
uint32 addr;
if(channel[i].direction == DMA_CPUTOMMIO) {
mem_bus->write(hdma_mmio(i), x);
addr = hdma_mmio(i);
} else if(!channel[i].hdma_indirect) {
mem_bus->write(hdma_addr(i), x);
addr = hdma_addr(i);
} else {
mem_bus->write(hdma_iaddr(i), x);
addr = hdma_iaddr(i);
}
if((bool)config::cpu.hdma_enable == true) {
r_mem->write(addr, x);
}
add_cycles(8);
@@ -135,12 +140,12 @@ void bCPU::hdma_write(uint8 i, uint8 x) {
}
void bCPU::hdma_update(uint8 i) {
channel[i].hdma_line_counter = mem_bus->read(hdma_addr(i));
channel[i].hdma_line_counter = r_mem->read(hdma_addr(i));
add_cycles(8);
hdma_add_cycles(8);
if(channel[i].hdma_indirect) {
channel[i].hdma_iaddr = mem_bus->read(hdma_addr(i)) << 8;
channel[i].hdma_iaddr = r_mem->read(hdma_addr(i)) << 8;
add_cycles(8);
hdma_add_cycles(8);
}
@@ -155,7 +160,7 @@ void bCPU::hdma_update(uint8 i) {
if(channel[i].hdma_indirect) {
channel[i].hdma_iaddr >>= 8;
channel[i].hdma_iaddr |= mem_bus->read(hdma_addr(i)) << 8;
channel[i].hdma_iaddr |= r_mem->read(hdma_addr(i)) << 8;
add_cycles(8);
hdma_add_cycles(8);
}
+19 -8
View File
@@ -133,6 +133,7 @@ static int z;
break;
case DMASTATE_RUN:
dma_run(); //updates status.dma_cycle_count
cycle_edge();
break;
case DMASTATE_CPUSYNC:
exec_cycle();
@@ -141,18 +142,28 @@ static int z;
}
void bCPU::exec_cycle() {
//on first cycle?
if(status.cycle_pos == 0) {
snes->notify(SNES::CPU_EXEC_OPCODE_BEGIN);
status.opcode = op_read();
status.cycle_pos = 1;
//irq active? run one bus cycle of the irq event and return
if(run_state.irq) {
irq_run();
return;
}
(this->*optbl[status.opcode])();
if(status.cycle_pos == 0) {
snes->notify(SNES::CPU_EXEC_OPCODE_END);
if(status.cycle_pos) {
(this->*optbl[status.opcode])();
#ifdef DEBUGGER
if(status.cycle_pos == 0) {
snes->notify(SNES::CPU_EXEC_OPCODE_END);
}
#endif
return;
}
//on first cycle?
#ifdef DEBUGGER
snes->notify(SNES::CPU_EXEC_OPCODE_BEGIN);
#endif
status.opcode = op_read();
status.cycle_pos = 1;
}
//only return true when we are on an opcode edge
+3 -1
View File
@@ -13,7 +13,7 @@ void bCPU::irq_run() {
//WDC documentation is incorrect, first cycle
//is a memory read fetch from PBR:PC
switch(status.cycle_pos++) {
case 0: add_cycles(mem_bus->speed(regs.pc.d)); break;
case 0: add_cycles(r_mem->speed(regs.pc.d)); break;
case 1: add_cycles(6); break;
case 2: stack_write(regs.pc.b); break;
case 3: stack_write(regs.pc.h); break;
@@ -25,8 +25,10 @@ void bCPU::irq_run() {
regs.pc.w = rd.w;
regs.p.i = 1;
regs.p.d = 0;
#ifdef DEBUGGER
//let debugger know the new IRQ opcode address
snes->notify(SNES::CPU_EXEC_OPCODE_END);
#endif
status.cycle_pos = 0;
run_state.irq = false;
break;
+5 -5
View File
@@ -37,7 +37,7 @@ void bCPU::mmio_reset() {
//WMDATA
uint8 bCPU::mmio_r2180() {
uint8 r;
r = mem_bus->read(0x7e0000 | status.wram_addr);
r = r_mem->read(0x7e0000 | status.wram_addr);
status.wram_addr++;
status.wram_addr &= 0x01ffff;
return r;
@@ -324,7 +324,7 @@ uint8 bCPUMMIO::read(uint32 addr) {
uint i;
//APU
if(addr >= 0x2140 && addr <= 0x217f) {
return apu->port_read(addr & 3);
return r_apu->port_read(addr & 3);
}
//HDMA
@@ -374,7 +374,7 @@ uint i;
//WMDATA
void bCPU::mmio_w2180(uint8 value) {
mem_bus->write(0x7e0000 | status.wram_addr, value);
r_mem->write(0x7e0000 | status.wram_addr, value);
status.wram_addr++;
status.wram_addr &= 0x01ffff;
}
@@ -441,7 +441,7 @@ void bCPU::mmio_w4200(uint8 value) {
//WRIO
void bCPU::mmio_w4201(uint8 value) {
if((status.pio & 0x80) && !(value & 0x80)) {
ppu->latch_counters();
r_ppu->latch_counters();
}
status.pio = value;
}
@@ -525,7 +525,7 @@ void bCPU::mmio_w420c(uint8 value) {
//MEMSEL
void bCPU::mmio_w420d(uint8 value) {
mem_bus->set_speed(value & 1);
r_mem->set_speed(value & 1);
}
//DMAPx
+107 -25
View File
@@ -1,31 +1,75 @@
//op_read
inline void bCPU::op_adc_b() {
int32 r = regs.a.l + rd.l + regs.p.c;
//bcd
if(regs.p.d) {
if(((r ) & 15) > 9)r += 6;
if(((r >> 4) & 15) > 9)r += 6 << 4;
uint8 n0 = (regs.a.l ) & 15;
uint8 n1 = (regs.a.l >> 4) & 15;
n0 += ((rd.l) & 15) + regs.p.c;
if(n0 > 9) {
n0 -= 10;
n0 &= 15;
n1++;
}
n1 += ((rd.l >> 4) & 15);
if(n1 > 9) {
n1 -= 10;
n1 &= 15;
regs.p.c = 1;
} else {
regs.p.c = 0;
}
r = (n1 << 4) | (n0);
} else {
r = regs.a.l + rd.l + regs.p.c;
regs.p.c = (r > 0xff);
}
regs.p.n = !!(r & 0x80);
regs.p.v = !!(~(regs.a.l ^ rd.l) & (regs.a.l ^ r) & 0x80);
regs.p.z = ((uint8)r == 0);
regs.p.c = (r > 0xff);
regs.a.l = r;
}
inline void bCPU::op_adc_w() {
int32 r = regs.a.w + rd.w + regs.p.c;
//bcd
int32 r;
if(regs.p.d) {
if(((r ) & 15) > 9)r += 6;
if(((r >> 4) & 15) > 9)r += 6 << 4;
if(((r >> 8) & 15) > 9)r += 6 << 8;
if(((r >> 12) & 15) > 9)r += 6 << 12;
uint8 n0 = (regs.a.w ) & 15;
uint8 n1 = (regs.a.w >> 4) & 15;
uint8 n2 = (regs.a.w >> 8) & 15;
uint8 n3 = (regs.a.w >> 12) & 15;
n0 += ((rd.w) & 15) + regs.p.c;
if(n0 > 9) {
n0 -= 10;
n0 &= 15;
n1++;
}
n1 += ((rd.w >> 4) & 15);
if(n1 > 9) {
n1 -= 10;
n1 &= 15;
n2++;
}
n2 += ((rd.w >> 8) & 15);
if(n2 > 9) {
n2 -= 10;
n2 &= 15;
n3++;
}
n3 += ((rd.w >> 12) & 15);
if(n3 > 9) {
n3 -= 10;
n3 &= 15;
regs.p.c = 1;
} else {
regs.p.c = 0;
}
r = (n3 << 12) | (n2 << 8) | (n1 << 4) | (n0);
} else {
r = regs.a.w + rd.w + regs.p.c;
regs.p.c = (r > 0xffff);
}
regs.p.n = !!(r & 0x8000);
regs.p.v = !!(~(regs.a.w ^ rd.w) & (regs.a.w ^ r) & 0x8000);
regs.p.z = ((uint16)r == 0);
regs.p.c = (r > 0xffff);
regs.a.w = r;
}
@@ -156,32 +200,70 @@ inline void bCPU::op_ora_w() {
}
inline void bCPU::op_sbc_b() {
int32 r = regs.a.l - rd.l - !regs.p.c;
//bcd
int32 r;
if(regs.p.d) {
if(((r ) & 15) > 9)r -= 6;
if(((r >> 4) & 15) > 9)r -= 6 << 4;
uint8 n0 = (regs.a.l ) & 15;
uint8 n1 = (regs.a.l >> 4) & 15;
n0 -= ((rd.l ) & 15) + !regs.p.c;
n1 -= ((rd.l >> 4) & 15);
if(n0 > 9) {
n0 += 10;
n1--;
}
if(n1 > 9) {
n1 += 10;
regs.p.c = 0;
} else {
regs.p.c = 1;
}
r = (n1 << 4) | (n0);
} else {
r = regs.a.l - rd.l - !regs.p.c;
regs.p.c = (r >= 0);
}
regs.p.n = !!(r & 0x80);
regs.p.v = !!((regs.a.l ^ rd.l) & (regs.a.l ^ r) & 0x80);
regs.p.z = ((byte)r == 0);
regs.p.c = (r >= 0);
regs.p.z = ((uint8)r == 0);
regs.a.l = r;
}
inline void bCPU::op_sbc_w() {
int32 r = regs.a.w - rd.w - !regs.p.c;
//bcd
int32 r;
if(regs.p.d) {
if(((r ) & 15) > 9)r -= 6;
if(((r >> 4) & 15) > 9)r -= 6 << 4;
if(((r >> 8) & 15) > 9)r -= 6 << 8;
if(((r >> 12) & 15) > 9)r -= 6 << 12;
uint8 n0 = (regs.a.w ) & 15;
uint8 n1 = (regs.a.w >> 4) & 15;
uint8 n2 = (regs.a.w >> 8) & 15;
uint8 n3 = (regs.a.w >> 12) & 15;
n0 -= ((rd.w ) & 15) + !regs.p.c;
n1 -= ((rd.w >> 4) & 15);
n2 -= ((rd.w >> 8) & 15);
n3 -= ((rd.w >> 12) & 15);
if(n0 > 9) {
n0 += 10;
n1--;
}
if(n1 > 9) {
n1 += 10;
n2--;
}
if(n2 > 9) {
n2 += 10;
n3--;
}
if(n3 > 9) {
n3 += 10;
regs.p.c = 0;
} else {
regs.p.c = 1;
}
r = (n3 << 12) | (n2 << 8) | (n1 << 4) | (n0);
} else {
r = regs.a.w - rd.w - !regs.p.c;
regs.p.c = (r >= 0);
}
regs.p.n = !!(r & 0x8000);
regs.p.v = !!((regs.a.w ^ rd.w) & (regs.a.w ^ r) & 0x8000);
regs.p.z = ((word)r == 0);
regs.p.c = (r >= 0);
regs.p.z = ((uint16)r == 0);
regs.a.w = r;
}
+21 -19
View File
@@ -239,6 +239,24 @@ uint32 r = status.cycles_executed;
return r;
}
void bCPU::cycle_edge() {
if(time.hdmainit_triggered == false) {
if(time.hc >= time.hdmainit_trigger_pos || time.v) {
time.hdmainit_triggered = true;
hdmainit_activate();
}
}
if(time.hdma_triggered == false) {
if(time.v <= (overscan() ? 239 : 224)) {
if(time.hc >= 1106) {
time.hdma_triggered = true;
hdma_activate();
}
}
}
}
void bCPU::add_cycles(int cycles) {
status.cycles_executed += cycles;
@@ -253,23 +271,16 @@ void bCPU::add_cycles(int cycles) {
if(time.v == 0) {
frame();
ppu->frame();
r_ppu->frame();
snes->frame();
}
scanline();
ppu->scanline();
r_ppu->scanline();
snes->scanline();
time.line_rendered = false;
}
if(time.hdmainit_triggered == false) {
if(time.hc + cycles >= time.hdmainit_trigger_pos || time.v) {
time.hdmainit_triggered = true;
hdmainit_activate();
}
}
if(time.dram_refreshed == false) {
if(time.hc + cycles >= time.dram_refresh_pos) {
time.dram_refreshed = true;
@@ -296,16 +307,7 @@ void bCPU::add_cycles(int cycles) {
//therefore, wait a few dots before rendering the scanline
if(time.hc + cycles >= (48 * 4)) {
time.line_rendered = true;
ppu->render_scanline();
}
}
if(time.hdma_triggered == false) {
if(time.v <= (overscan() ? 239 : 224)) {
if(time.hc + cycles >= 1106) {
time.hdma_triggered = true;
hdma_activate();
}
r_ppu->render_scanline();
}
}
+1
View File
@@ -69,5 +69,6 @@ inline uint8 dma_counter();
inline void inc_vcounter();
inline uint16 get_hcounter();
inline void cycle_edge();
inline void add_cycles(int cycles);
inline void time_reset();
+1
View File
@@ -70,4 +70,5 @@ enum {
uint16 __relw(int16 offset);
CPU();
virtual ~CPU() {}
};
+1 -1
View File
@@ -41,7 +41,7 @@ union {
struct { uint8 l, h; };
#else
struct { uint8 h, l; };
#endif;
#endif
};
CPUReg16() { w = 0; }
+11 -11
View File
@@ -38,23 +38,23 @@ uint32 r = 0;
break;
case OPTYPE_IDP:
addr = (regs.d + (addr & 0xffff)) & 0xffff;
r = (regs.db << 16) + mem_bus->read_word(addr);
r = (regs.db << 16) + r_mem->read_word(addr);
break;
case OPTYPE_IDPX:
addr = (regs.d + regs.x + (addr & 0xffff)) & 0xffff;
r = (regs.db << 16) + mem_bus->read_word(addr);
r = (regs.db << 16) + r_mem->read_word(addr);
break;
case OPTYPE_IDPY:
addr = (regs.d + (addr & 0xffff)) & 0xffff;
r = (regs.db << 16) + mem_bus->read_word(addr) + regs.y;
r = (regs.db << 16) + r_mem->read_word(addr) + regs.y;
break;
case OPTYPE_ILDP:
addr = (regs.d + (addr & 0xffff)) & 0xffff;
r = mem_bus->read_long(addr);
r = r_mem->read_long(addr);
break;
case OPTYPE_ILDPY:
addr = (regs.d + (addr & 0xffff)) & 0xffff;
r = mem_bus->read_long(addr) + regs.y;
r = r_mem->read_long(addr) + regs.y;
break;
case OPTYPE_ADDR:
r = (regs.db << 16) + (addr & 0xffff);
@@ -88,7 +88,7 @@ uint32 r = 0;
break;
case OPTYPE_ISRY:
addr = (regs.s + (addr & 0xff)) & 0xffff;
r = (regs.db << 16) + mem_bus->read_word(addr) + regs.y;
r = (regs.db << 16) + r_mem->read_word(addr) + regs.y;
break;
}
return r;
@@ -109,10 +109,10 @@ static CPUReg24 pc;
pc.d = regs.pc.d;
sprintf(s, "%0.6x ", pc.d);
op = mem_bus->read(pc.d); pc.w++;
op0 = mem_bus->read(pc.d); pc.w++;
op1 = mem_bus->read(pc.d); pc.w++;
op2 = mem_bus->read(pc.d);
op = r_mem->read(pc.d); pc.w++;
op0 = r_mem->read(pc.d); pc.w++;
op1 = r_mem->read(pc.d); pc.w++;
op2 = r_mem->read(pc.d);
switch(op) {
case 0x00:sprintf(t, "brk #$%0.2x ", op0);break;
@@ -457,7 +457,7 @@ static uint8 op_len_tbl[256] = {
return 0;
}
op = mem_bus->read(regs.pc.d);
op = r_mem->read(regs.pc.d);
len = op_len_tbl[op];
if(len == 5)return (regs.p.m)?2:3;
if(len == 6)return (regs.p.x)?2:3;
+54 -35
View File
@@ -1,10 +1,22 @@
#include "../../base.h"
#include "bdsp_tables.cpp"
uint8 bDSP::read_8 (uint16 addr) { return (spcram[addr]); }
uint16 bDSP::read_16 (uint16 addr) { return (spcram[(addr + 1) & 0xffff] << 8) + (spcram[addr]); }
void bDSP::write_8 (uint16 addr, uint8 data) { spcram[addr] = data; }
void bDSP::write_16(uint16 addr, uint16 data) { spcram[addr++] = data; spcram[addr] = data >> 8; }
uint8 bDSP::readb(uint16 addr) {
return spcram[addr];
}
void bDSP::writeb(uint16 addr, uint8 data) {
spcram[addr] = data;
}
uint16 bDSP::readw(uint16 addr) {
return (readb(addr)) | (readb(addr + 1) << 8);
}
void bDSP::writew(uint16 addr, uint16 data) {
writeb(addr, data);
writeb(addr + 1, data >> 8);
}
uint8 bDSP::read(uint8 addr) {
int i, v, n;
@@ -98,12 +110,14 @@ int i, v, n;
break;
case 0x04:case 0x14:case 0x24:case 0x34:
case 0x44:case 0x54:case 0x64:case 0x74:
//voice[v].SRCN = data;
voice[v].SRCN = data;
break;
//below is anomie's code, but TRAC says writing SRCN doesn't affect anything until a
//BRR-with-end block is encountered, where it loads the loop address from the new SRCN
//anomie's code breaks MK2 sound completely...
if(voice[v].SRCN != data) {
voice[v].SRCN = data;
voice[v].brr_ptr = read_16((status.DIR << 8) + (voice[v].SRCN << 2) + ((voice[v].brr_looped)?2:0));
voice[v].SRCN = data;
voice[v].brr_ptr = readw((status.DIR << 8) + (voice[v].SRCN << 2) + ((voice[v].brr_looped) ? 2 : 0));
voice[v].brr_index = 0;
}
break;
@@ -144,18 +158,18 @@ int i, v, n;
case 0x3c:status.EVOLR = data;break;
case 0x4c:
status.KON = data;
// status.kon = data;
status.KON = data;
status.kon = data;
status.key_flag = true;
break;
case 0x5c:
status.KOFF = data;
status.KOFF = data;
status.key_flag = true;
break;
case 0x6c:
status.FLG = data;
status.FLG = data;
status.key_flag = true;
status.noise_rate = RateTable[data & 0x1f];
break;
@@ -165,15 +179,15 @@ int i, v, n;
status.ENDX = 0;
break;
case 0x0d:status.EFB = data;break;
case 0x2d:status.PMON = data;break;
case 0x3d:status.NON = data;break;
case 0x4d:status.EON = data;break;
case 0x5d:status.DIR = data;break;
case 0x6d:status.ESA = data;break;
case 0x0d:status.EFB = data;break;
case 0x2d:status.PMON = data;break;
case 0x3d:status.NON = data;break;
case 0x4d:status.EON = data;break;
case 0x5d:status.DIR = data;break;
case 0x6d:status.ESA = data;break;
case 0x7d:
status.EDL = data;
status.EDL = data;
status.echo_size = (data & 0x0f) << 11;
break;
}
@@ -183,7 +197,7 @@ int i, v, n;
void bDSP::power() {
int v;
spcram = apu->get_spcram_handle();
spcram = r_apu->get_spcram_handle();
memset(dspram, 0x00, 128);
for(v=0;v<8;v++) {
@@ -221,7 +235,7 @@ int v;
status.KOFF = 0x00;
status.FLG |= 0xe0;
//status.kon = 0x00;
status.kon = 0x00;
status.key_flag = false;
status.noise_ctr = 0;
@@ -238,7 +252,7 @@ int v;
voice[v].pitch_ctr = 0;
voice[v].brr_index = 0;
voice[v].brr_ptr = read_16((status.DIR << 8) + (voice[v].SRCN << 2));
voice[v].brr_ptr = readw((status.DIR << 8) + (voice[v].SRCN << 2));
voice[v].brr_looped = false;
voice[v].brr_data[0] = 0;
voice[v].brr_data[1] = 0;
@@ -288,7 +302,9 @@ int32 esamplel, esampler;
int32 fir_samplel, fir_sampler;
pmon = status.PMON & ~status.NON & ~1;
if(!(dsp_counter++ & 1) && status.key_flag) {
//if(!(dsp_counter++ & 1) && status.key_flag) {
//TRAC believes KON/KOFF is polled every sample. further testing is needed
if(status.key_flag) {
for(v=0;v<8;v++) {
uint8 mask = 1 << v;
if(status.soft_reset()) {
@@ -301,10 +317,12 @@ int32 fir_samplel, fir_sampler;
voice[v].env_state = RELEASE;
voice[v].AdjustEnvelope();
}
} else if(status.KON & mask) { //status.kon
status.KON &= ~mask; //new code
status.ENDX &= ~mask; //new code
voice[v].brr_ptr = read_16((status.DIR << 8) + (voice[v].SRCN << 2));
} else if(status.kon & mask) {
//new KON code
status.ENDX &= ~mask;
status.kon &= ~mask;
voice[v].brr_ptr = readw((status.DIR << 8) + (voice[v].SRCN << 2));
voice[v].brr_index = -9;
voice[v].brr_looped = false;
voice[v].brr_data[0] = 0;
@@ -316,7 +334,8 @@ int32 fir_samplel, fir_sampler;
voice[v].AdjustEnvelope();
}
}
// status.ENDX &= ~status.kon;
//old KON code, breaks sound effects in DL / SFA2
// status.ENDX &= ~status.kon;
// status.kon = 0;
status.key_flag = false;
}
@@ -359,7 +378,7 @@ int32 fir_samplel, fir_sampler;
voice[v].brr_data_index &= 3;
if(voice[v].brr_index == 0) {
voice[v].brr_header = read_8(voice[v].brr_ptr);
voice[v].brr_header = readb(voice[v].brr_ptr);
if(voice[v].brr_header_flags() & BRR_END) {
status.ENDX |= (1 << v);
@@ -373,7 +392,7 @@ int32 fir_samplel, fir_sampler;
#define S(x) voice[v].brr_data[(voice[v].brr_data_index + (x)) & 3]
if(voice[v].env_state != SILENCE) {
sample = read_8(voice[v].brr_ptr + 1 + (voice[v].brr_index >> 1));
sample = readb(voice[v].brr_ptr + 1 + (voice[v].brr_index >> 1));
if(voice[v].brr_index & 1) {
sample = clip(4, sample);
} else {
@@ -410,7 +429,7 @@ int32 fir_samplel, fir_sampler;
if(++voice[v].brr_index > 15) {
voice[v].brr_index = 0;
if(voice[v].brr_header_flags() & BRR_END) {
voice[v].brr_ptr = read_16((status.DIR << 8) + (voice[v].SRCN << 2) + 2);
voice[v].brr_ptr = readw((status.DIR << 8) + (voice[v].SRCN << 2) + 2);
voice[v].brr_looped = true;
} else {
voice[v].brr_ptr += 9;
@@ -496,7 +515,7 @@ int32 fir_samplel, fir_sampler;
//gaussian interpolation / noise
if(status.NON & (1 << v)) {
sample = status.noise_sample;
sample = clip(15, status.noise_sample);
} else {
d = voice[v].pitch_ctr >> 4; //-256 <= sample <= -1
sample = ((GaussTable[ -1-d] * S(-3)) >> 11);
@@ -527,8 +546,8 @@ int32 fir_samplel, fir_sampler;
//echo (FIR) adjust
#define F(c,x) status.fir_buffer[c][(status.fir_buffer_index+(x)) & 7]
status.fir_buffer_index++;
F(0,0) = read_16((status.ESA << 8) + status.echo_index);
F(1,0) = read_16((status.ESA << 8) + status.echo_index + 2);
F(0,0) = readw((status.ESA << 8) + status.echo_index);
F(1,0) = readw((status.ESA << 8) + status.echo_index + 2);
fir_samplel = (F(0,-0) * status.FIR[7] +
F(0,-1) * status.FIR[6] +
@@ -557,8 +576,8 @@ int32 fir_samplel, fir_sampler;
esamplel = clamp(16, esamplel);
esampler = clamp(16, esampler);
write_16((status.ESA << 8) + status.echo_index, esamplel);
write_16((status.ESA << 8) + status.echo_index + 2, esampler);
writew((status.ESA << 8) + status.echo_index, esamplel);
writew((status.ESA << 8) + status.echo_index + 2, esampler);
}
status.echo_index += 4;
+5 -5
View File
@@ -10,10 +10,10 @@ enum {
BRR_LOOP = 2
};
uint8 read_8 (uint16 addr);
uint16 read_16 (uint16 addr);
void write_8 (uint16 addr, uint8 data);
void write_16(uint16 addr, uint16 data);
uint8 readb (uint16 addr);
uint16 readw (uint16 addr);
void writeb(uint16 addr, uint8 data);
void writew(uint16 addr, uint16 data);
public:
static const uint16 RateTable[32];
@@ -63,7 +63,7 @@ struct Status {
int8 FIR[8];
//internal variables
//uint8 kon;
uint8 kon;
bool key_flag;
int16 noise_ctr, noise_rate;
+3
View File
@@ -6,4 +6,7 @@ public:
virtual void power() = 0;
virtual void reset() = 0;
virtual uint32 run() = 0;
DSP() {}
virtual ~DSP() {}
};
+54 -17
View File
@@ -1,49 +1,86 @@
#define BSNES_VERSION "0.013"
#define BSNES_VERSION "0.015"
#define BSNES_TITLE "bsnes v" BSNES_VERSION
#ifdef POLYMORPHISM
#define ref(x) x
#else
#define ref(x) (&x)
#endif
#define deref(x) __##x
#define r_mem ref(deref(mem))
#define r_cpu ref(deref(cpu))
#define r_apu ref(deref(apu))
#define r_dsp ref(deref(dsp))
#define r_ppu ref(deref(ppu))
#include "reader/reader.h"
#include "cart/cart.h"
#include "memory/memory.h"
#include "memory/bmemory/bmemory.h"
extern MMIO mmio_unmapped;
extern MemBus *mem_bus;
#include "cpu/cpu.h"
#include "cpu/bcpu/bcpu.h"
extern CPU *cpu;
#include "apu/apu.h"
#include "apu/bapu/bapu.h"
#include "apu/bapuskip/bapuskip.h"
extern APU *apu;
#include "dsp/dsp.h"
#include "dsp/bdsp/bdsp.h"
extern DSP *dsp;
#include "ppu/ppu.h"
#include "ppu/bppu/bppu.h"
extern PPU *ppu;
#include "snes/snes.h"
extern SNES *snes;
#include "chip/srtc/srtc.h"
#include "chip/sdd1/sdd1.h"
#include "chip/c4/c4.h"
extern MMIO mmio_unmapped;
#ifdef POLYMORPHISM
extern MemBus *deref(mem);
extern CPU *deref(cpu);
extern APU *deref(apu);
extern DSP *deref(dsp);
extern PPU *deref(ppu);
#else
extern bMemBus deref(mem);
extern bCPU deref(cpu);
extern bAPU deref(apu);
extern bDSP deref(dsp);
extern bPPU deref(ppu);
#endif
extern SNES *snes;
extern SRTC *srtc;
extern SDD1 *sdd1;
extern C4 *c4;
#include "config/config.h"
#ifdef INTERFACE_MAIN
Cartridge cartridge;
#include "config/config.cpp"
MemBus *mem_bus;
CPU *cpu;
APU *apu;
DSP *dsp;
PPU *ppu;
SNES *snes;
#ifdef POLYMORPHISM
MemBus *deref(mem);
CPU *deref(cpu);
APU *deref(apu);
DSP *deref(dsp);
PPU *deref(ppu);
#else
bMemBus deref(mem);
bCPU deref(cpu);
bAPU deref(apu);
bDSP deref(dsp);
bPPU deref(ppu);
#endif
SNES *snes;
SRTC *srtc;
SDD1 *sdd1;
C4 *c4;
SRTC *srtc;
SDD1 *sdd1;
#endif
+14 -11
View File
@@ -20,20 +20,23 @@
#define zerofree(__n) if(__n) { free(__n); __n = 0; }
typedef unsigned int uint;
typedef unsigned int uint;
typedef unsigned char byte;
typedef unsigned short word;
typedef unsigned long ulong;
typedef unsigned char byte;
typedef unsigned short word;
typedef unsigned long ulong;
typedef unsigned long long uquad;
typedef unsigned char bool8;
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned long uint32;
typedef unsigned char bool8;
typedef unsigned char uint8;
typedef unsigned short uint16;
typedef unsigned long uint32;
typedef unsigned long long uint64;
typedef signed char int8;
typedef signed short int16;
typedef signed long int32;
typedef signed char int8;
typedef signed short int16;
typedef signed long int32;
typedef signed long long int64;
#ifdef null
#undef null
+65 -23
View File
@@ -11,7 +11,6 @@ uint Setting::get() {
}
void Setting::set(uint _data) {
printf("%s %d\n", name, _data);
data = _data;
if(type != DEC && type != HEX) {
@@ -20,6 +19,15 @@ printf("%s %d\n", name, _data);
}
}
char *Setting::sget() {
return strptr(char_data);
}
void Setting::sset(const char *_data) {
strcpy(char_data, _data);
strunquote(char_data);
}
Setting::Setting(Config *_parent, char *_name, char *_desc, uint _data, uint _type) {
int s;
if(_parent) {
@@ -44,28 +52,53 @@ int s;
type = _type;
}
Setting::Setting(Config *_parent, char *_name, char *_desc, char *_data) {
int s;
if(_parent) {
_parent->add(this);
}
s = strlen(_name);
name = (char*)malloc(s + 1);
strcpy(name, _name);
if(_desc) {
s = strlen(_desc);
desc = (char*)malloc(s + 1);
strcpy(desc, _desc);
} else {
desc = (char*)malloc(1);
*desc = 0;
}
strcpy(char_data, _data);
strcpy(char_def, _data);
type = STR;
}
void Config::add(Setting *setting) {
list[list_count++] = setting;
}
uint Config::string_to_uint(uint type, char *input) {
if(!strcmp(input, "true") ||
!strcmp(input, "enabled") ||
!strcmp(input, "on") ||
!strcmp(input, "yes")
if(strmatch(input, "true") ||
strmatch(input, "enabled") ||
strmatch(input, "on") ||
strmatch(input, "yes")
) {
return (uint)true;
}
if(!strcmp(input, "false") ||
!strcmp(input, "disabled") ||
!strcmp(input, "off") ||
!strcmp(input, "no")
if(strmatch(input, "false") ||
strmatch(input, "disabled") ||
strmatch(input, "off") ||
strmatch(input, "no")
) {
return (uint)false;
}
if(!strbegin(input, "0x")) {
if(strbegin(input, "0x")) {
return strhex(input + 2);
}
@@ -76,16 +109,16 @@ char *Config::uint_to_string(uint type, uint input) {
static char output[512];
switch(type) {
case Setting::TRUE_FALSE:
sprintf(output, "%s", (input & 1)?"true":"false");
sprintf(output, "%s", (input & 1) ? "true" : "false");
break;
case Setting::ENABLED_DISABLED:
sprintf(output, "%s", (input & 1)?"enabled":"disabled");
sprintf(output, "%s", (input & 1) ? "enabled" : "disabled");
break;
case Setting::ON_OFF:
sprintf(output, "%s", (input & 1)?"on":"off");
sprintf(output, "%s", (input & 1) ? "on" : "off");
break;
case Setting::YES_NO:
sprintf(output, "%s", (input & 1)?"yes":"no");
sprintf(output, "%s", (input & 1) ? "yes" : "no");
break;
case Setting::DEC:
sprintf(output, "%d", input);
@@ -120,14 +153,18 @@ char *buffer = (char*)malloc(fsize + 1);
qreplace(data, " ", "");
split(line, "\n", data);
for(int i=0;i<count(line);i++) {
for(int i = 0; i < count(line); i++) {
if(strlen(line[i]) == 0)continue;
if(*strptr(line[i]) == '#')continue;
split(part, "=", line[i]);
for(int l=0;l<list_count;l++) {
if(!strcmp(list[l]->name, part[0])) {
list[l]->set(string_to_uint(list[l]->type, strptr(part[1])));
qsplit(part, "=", line[i]);
for(int l = 0; l < list_count; l++) {
if(strmatch(list[l]->name, part[0])) {
if(list[l]->type != Setting::STR) {
list[l]->set(string_to_uint(list[l]->type, strptr(part[1])));
} else {
list[l]->sset(strptr(part[1]));
}
}
}
}
@@ -141,15 +178,20 @@ FILE *fp;
fp = fopen(fn, "wb");
if(!fp)return false;
for(int i=0;i<list_count;i++) {
for(int i = 0; i < list_count; i++) {
strcpy(data, list[i]->desc);
replace(data, "\r\n", "\n");
split(line, "\n", data);
for(int l=0;l<count(line);l++) {
for(int l = 0; l < count(line); l++) {
fprintf(fp, "# %s\r\n", strptr(line[l]));
}
fprintf(fp, "# (default = %s)\r\n", uint_to_string(list[i]->type, list[i]->def));
fprintf(fp, "%s = %s\r\n\r\n", list[i]->name, uint_to_string(list[i]->type, list[i]->data));
if(list[i]->type != Setting::STR) {
fprintf(fp, "# (default = %s)\r\n", uint_to_string(list[i]->type, list[i]->def));
fprintf(fp, "%s = %s\r\n\r\n", list[i]->name, uint_to_string(list[i]->type, list[i]->data));
} else {
fprintf(fp, "# (default = \"%s\")\r\n", strptr(list[i]->char_def));
fprintf(fp, "%s = \"%s\"\r\n\r\n", list[i]->name, strptr(list[i]->char_data));
}
}
return true;
+18 -6
View File
@@ -1,5 +1,5 @@
/*
libconfig : version 0.05 ~byuu (09/13/05)
libconfig : version 0.05 ~byuu (10/30/05)
*/
#ifndef __LIBCONFIG
@@ -28,6 +28,8 @@ class Config;
inline __name &operator=(const int8 _data) { set(_data); return *this; } \
inline __name &operator=(const int16 _data) { set(_data); return *this; } \
inline __name &operator=(const int32 _data) { set(_data); return *this; } \
inline __name &operator=(const float _data) { set((uint)_data); return *this; } \
inline __name &operator=(const double _data) { set((uint)_data); return *this; } \
void toggle() { data ^= 1; set(data); } \
__name(Config *_parent, char *_name, char *_desc = 0, uint _data = 0, uint _type = Setting::DEC) : \
Setting(_parent, _name, _desc, _data, _type) {}
@@ -46,14 +48,20 @@ enum {
YES_NO,
BOOL,
DEC,
HEX
HEX,
STR
};
char *name, *desc;
virtual void toggle();
virtual uint get();
virtual void set(uint _data);
substring char_data, char_def;
virtual void toggle();
virtual uint get();
virtual void set(uint _data);
Setting(Config *_parent, char *_name, char *_desc = 0, uint _data = 0, uint _type = DEC);
virtual char *sget();
virtual void sset(const char *_data);
Setting(Config *_parent, char *_name, char *_desc, uint _data, uint _type);
Setting(Config *_parent, char *_name, char *_desc, char *_data);
inline operator bool() { return (bool)get(); }
inline operator uint() { return get(); }
@@ -64,6 +72,8 @@ char *name, *desc;
inline operator int8() { return get(); }
inline operator int16() { return get(); }
inline operator int32() { return get(); }
inline operator float() { return (float) get(); }
inline operator double() { return (double)get(); }
inline Setting &operator=(const bool _data) { set((uint)_data); return *this; }
inline Setting &operator=(const uint _data) { set(_data); return *this; }
@@ -74,6 +84,8 @@ char *name, *desc;
inline Setting &operator=(const int8 _data) { set(_data); return *this; }
inline Setting &operator=(const int16 _data) { set(_data); return *this; }
inline Setting &operator=(const int32 _data) { set(_data); return *this; }
inline Setting &operator=(const float _data) { set((uint)_data); return *this; }
inline Setting &operator=(const double _data) { set((uint)_data); return *this; }
};
class Config {
+65 -53
View File
@@ -64,6 +64,28 @@ int strcmp(substring &dest, const char *src) { return strcmp(strptr(dest), src);
int strcmp(const char *dest, substring &src) { return strcmp(dest, strptr(src)); }
int strcmp(substring &dest, substring &src) { return strcmp(strptr(dest), strptr(src)); }
int __stricmp(const char *dest, const char *src) {
while(*dest && *src) {
if(chrlower(*dest) != chrlower(*src))break;
dest++;
src++;
}
return (int)chrlower(*dest) - (int)chrlower(*src);
}
int stricmp(substring &dest, const char *src) { return __stricmp(strptr(dest), src); }
int stricmp(const char *dest, substring &src) { return __stricmp(dest, strptr(src)); }
int stricmp(substring &dest, substring &src) { return __stricmp(strptr(dest), strptr(src)); }
bool strmatch(const char *dest, const char *src) { return !strcmp(dest, src); }
bool strmatch(substring &dest, const char *src) { return strmatch(strptr(dest), src); }
bool strmatch(const char *dest, substring &src) { return strmatch(dest, strptr(src)); }
bool strmatch(substring &dest, substring &src) { return strmatch(strptr(dest), strptr(src)); }
bool strimatch(const char *dest, const char *src) { return !stricmp(dest, src); }
bool strimatch(substring &dest, const char *src) { return strimatch(strptr(dest), src); }
bool strimatch(const char *dest, substring &src) { return strimatch(dest, strptr(src)); }
bool strimatch(substring &dest, substring &src) { return strimatch(strptr(dest), strptr(src)); }
void strcpy(substring &dest, const char *src) {
int srclen = strlen(src);
if(srclen > dest.size) { strresize(dest, srclen); }
@@ -109,18 +131,6 @@ int i, sl = strlen(dest.s);
s[i] = 0;
}
int __stricmp(const char *dest, const char *src) {
while(*dest && *src) {
if(chrlower(*dest) != chrlower(*src))break;
dest++;
src++;
}
return (int)chrlower(*dest) - (int)chrlower(*src);
}
int stricmp(substring &dest, const char *src) { return __stricmp(strptr(dest), src); }
int stricmp(const char *dest, substring &src) { return __stricmp(dest, strptr(src)); }
int stricmp(substring &dest, substring &src) { return __stricmp(strptr(dest), strptr(src)); }
void strlower(char *str) {
while(*str) {
*str = chrlower(*str);
@@ -137,40 +147,44 @@ void strupper(char *str) {
}
void strupper(substring &str) { strupper(strptr(str)); }
uint strpos(const char *str, const char *key) {
bool strpos(const char *str, const char *key, uint &pos) {
int i, ssl = strlen(str), ksl = strlen(key);
if(ksl > ssl)return null;
for(i=0;i<=ssl-ksl;i++) {
if(!memcmp(str+i, key, ksl))return i;
if(ksl > ssl)return false;
for(i = 0; i <= ssl - ksl; i++) {
if(!memcmp(str + i, key, ksl)) {
pos = i;
return true;
}
}
return null;
return false;
}
uint strpos(substring &str, const char *key) { return strpos(strptr(str), key); }
uint strpos(const char *str, substring &key) { return strpos(str, strptr(key)); }
uint strpos(substring &str, substring &key) { return strpos(strptr(str), strptr(key)); }
bool strpos(substring &str, const char *key, uint &pos) { return strpos(strptr(str), key, pos); }
bool strpos(const char *str, substring &key, uint &pos) { return strpos(str, strptr(key), pos); }
bool strpos(substring &str, substring &key, uint &pos) { return strpos(strptr(str), strptr(key), pos); }
uint qstrpos(const char *str, const char *key) {
bool qstrpos(const char *str, const char *key, uint &pos) {
int i, z, ssl = strlen(str), ksl = strlen(key);
uint8 x;
if(ksl > ssl)return null;
for(i=0;i<=ssl-ksl;) {
if(ksl > ssl)return false;
for(i = 0; i <= ssl - ksl;) {
x = str[i];
if(x == '\"' || x == '\'') {
z = i++;
while(str[i] != x && i < ssl)i++;
if(i >= ssl)i = z;
}
if(!memcmp(str+i, key, ksl)) {
return i;
if(!memcmp(str + i, key, ksl)) {
pos = i;
return true;
} else {
i++;
}
}
return null;
return false;
}
uint qstrpos(substring &str, const char *key) { return qstrpos(strptr(str), key); }
uint qstrpos(const char *str, substring &key) { return qstrpos(str, strptr(key)); }
uint qstrpos(substring &str, substring &key) { return qstrpos(strptr(str), strptr(key)); }
bool qstrpos(substring &str, const char *key, uint &pos) { return qstrpos(strptr(str), key, pos); }
bool qstrpos(const char *str, substring &key, uint &pos) { return qstrpos(str, strptr(key), pos); }
bool qstrpos(substring &str, substring &key, uint &pos) { return qstrpos(strptr(str), strptr(key), pos); }
void strtr(char *dest, const char *before, const char *after) {
int i, l, sl = strlen(dest), bsl = strlen(before), asl = strlen(after);
@@ -183,53 +197,51 @@ int i, l, sl = strlen(dest), bsl = strlen(before), asl = strlen(after);
}
void strtr(substring &dest, const char *before, const char *after) { strtr(strptr(dest), before, after); }
uint strbegin(const char *str, const char *key) {
bool strbegin(const char *str, const char *key) {
int i, ssl = strlen(str), ksl = strlen(key);
if(ksl > ssl)return 1;
if(!memcmp(str, key, ksl))return 0;
return 1;
if(ksl > ssl)return false;
return (!memcmp(str, key, ksl));
}
uint strbegin(substring &str, const char *key) { return strbegin(strptr(str), key); }
bool strbegin(substring &str, const char *key) { return strbegin(strptr(str), key); }
uint stribegin(const char *str, const char *key) {
bool stribegin(const char *str, const char *key) {
int i, ssl = strlen(str), ksl = strlen(key);
if(ksl > ssl)return 1;
if(ksl > ssl)return false;
for(i=0;i<ksl;i++) {
if(str[i] >= 'A' && str[i] <= 'Z') {
if(str[i] != key[i] && str[i]+0x20 != key[i])return 1;
if(str[i] != key[i] && str[i]+0x20 != key[i])return false;
} else if(str[i] >= 'a' && str[i] <= 'z') {
if(str[i] != key[i] && str[i]-0x20 != key[i])return 1;
if(str[i] != key[i] && str[i]-0x20 != key[i])return false;
} else {
if(str[i] != key[i])return 1;
if(str[i] != key[i])return false;
}
}
return 0;
return true;
}
uint stribegin(substring &str, const char *key) { return stribegin(strptr(str), key); }
bool stribegin(substring &str, const char *key) { return stribegin(strptr(str), key); }
uint strend(const char *str, const char *key) {
bool strend(const char *str, const char *key) {
int i, ssl = strlen(str), ksl = strlen(key);
if(ksl > ssl)return 1;
if(!memcmp(str + ssl - ksl, key, ksl))return 0;
return 1;
if(ksl > ssl)return false;
return (!memcmp(str + ssl - ksl, key, ksl));
}
uint strend(substring &str, const char *key) { return strend(strptr(str), key); }
bool strend(substring &str, const char *key) { return strend(strptr(str), key); }
uint striend(const char *str, const char *key) {
bool striend(const char *str, const char *key) {
int i, z, ssl = strlen(str), ksl = strlen(key);
if(ksl > ssl)return 1;
if(ksl > ssl)return false;
for(i=ssl-ksl, z=0;i<ssl;i++, z++) {
if(str[i] >= 'A' && str[i] <= 'Z') {
if(str[i] != key[z] && str[i]+0x20 != key[z])return 1;
if(str[i] != key[z] && str[i]+0x20 != key[z])return false;
} else if(str[i] >= 'a' && str[i] <= 'z') {
if(str[i] != key[z] && str[i]-0x20 != key[z])return 1;
if(str[i] != key[z] && str[i]-0x20 != key[z])return false;
} else {
if(str[i] != key[z])return 1;
if(str[i] != key[z])return false;
}
}
return 0;
return true;
}
uint striend(substring &str, const char *key) { return striend(strptr(str), key); }
bool striend(substring &str, const char *key) { return striend(strptr(str), key); }
void strltrim(char *str, const char *key) {
int i, ssl = strlen(str), ksl = strlen(key);
+36 -26
View File
@@ -1,5 +1,5 @@
/*
libstring : version 0.06a ~byuu (08/22/05)
libstring : version 0.07 ~byuu (11/30/05)
*/
#ifndef __LIBSTRING
@@ -25,6 +25,25 @@ int strcmp(substring &dest, const char *src);
int strcmp(const char *dest, substring &src);
int strcmp(substring &dest, substring &src);
//vc6/win32 and gcc/dos only support stricmp, whereas
//gcc/unix only supports strcasecmp. this is an attempt
//to avoid platform-specific defines...
#define stricmp __stricmp
int __stricmp(const char *dest, const char *src);
int stricmp(substring &dest, const char *src);
int stricmp(const char *dest, substring &src);
int stricmp(substring &dest, substring &src);
bool strmatch(const char *dest, const char *src);
bool strmatch(substring &dest, const char *src);
bool strmatch(const char *dest, substring &src);
bool strmatch(substring &dest, substring &src);
bool strimatch(const char *dest, const char *src);
bool strimatch(substring &dest, const char *src);
bool strimatch(const char *dest, substring &src);
bool strimatch(substring &dest, substring &src);
void strcpy(substring &dest, const char *src);
void strcpy(substring &dest, substring &src);
@@ -38,45 +57,36 @@ void strinsert(substring &dest, substring &src, uint pos);
void strremove(substring &dest, uint start, uint length = 0);
//vc6/win32 and gcc/dos only support stricmp, whereas
//gcc/unix only supports strcasecmp. this is an attempt
//to avoid platform-specific defines...
#define stricmp __stricmp
int __stricmp(const char *dest, const char *src);
int stricmp(substring &dest, const char *src);
int stricmp(const char *dest, substring &src);
int stricmp(substring &dest, substring &src);
void strlower(char *str);
void strlower(substring &str);
void strupper(char *str);
void strupper(substring &str);
uint strpos(const char *str, const char *key);
uint strpos(substring &str, const char *key);
uint strpos(const char *str, substring &key);
uint strpos(substring &str, substring &key);
bool strpos(const char *str, const char *key, uint &pos);
bool strpos(substring &str, const char *key, uint &pos);
bool strpos(const char *str, substring &key, uint &pos);
bool strpos(substring &str, substring &key, uint &pos);
uint qstrpos(const char *str, const char *key);
uint qstrpos(substring &str, const char *key);
uint qstrpos(const char *str, substring &key);
uint qstrpos(substring &str, substring &key);
bool qstrpos(const char *str, const char *key, uint &pos);
bool qstrpos(substring &str, const char *key, uint &pos);
bool qstrpos(const char *str, substring &key, uint &pos);
bool qstrpos(substring &str, substring &key, uint &pos);
void strtr(char *dest, const char *before, const char *after);
void strtr(substring &dest, const char *before, const char *after);
uint strbegin(const char *str, const char *key);
uint strbegin(substring &str, const char *key);
bool strbegin(const char *str, const char *key);
bool strbegin(substring &str, const char *key);
uint stribegin(const char *str, const char *key);
uint stribegin(substring &str, const char *key);
bool stribegin(const char *str, const char *key);
bool stribegin(substring &str, const char *key);
uint strend(const char *str, const char *key);
uint strend(substring &str, const char *key);
bool strend(const char *str, const char *key);
bool strend(substring &str, const char *key);
uint striend(const char *str, const char *key);
uint striend(substring &str, const char *key);
bool striend(const char *str, const char *key);
bool striend(substring &str, const char *key);
void strltrim(char *str, const char *key);
void strltrim(substring &str, const char *key);
+13
View File
@@ -6,6 +6,12 @@ uint32 b, w;
b = (addr >> 16);
w = (addr & 0xffff);
if(cartridge.cart.c4) {
if(!(b & 0x40) && w >= 0x6000 && w <= 0x7fff) {
return c4->read(w);
}
}
//SRAM Region A
if((b & 0x7f) >= 0x30 && (b & 0x7f) <= 0x3f && (w & 0xe000) == 0x6000) {
b &= 0x7f;
@@ -57,6 +63,13 @@ uint32 b, w;
b = (addr >> 16);
w = (addr & 0xffff);
if(cartridge.cart.c4) {
if(!(b & 0x40) && w >= 0x6000 && w <= 0x7fff) {
c4->write(w, value);
return;
}
}
//SRAM Region A
if((b & 0x7f) >= 0x30 && (b & 0x7f) <= 0x3f && (w & 0xe000) == 0x6000) {
b &= 0x7f;
+29 -116
View File
@@ -4,82 +4,15 @@
#include "bcart_exlorom.cpp"
#include "bcart_exhirom.cpp"
bool bMemBus::load_cart(Reader *rf) {
uint32 cksum, icksum, index;
char cart_title[24];
uint8 mapper, region;
if(rom_loaded == true)return false;
void bMemBus::load_cart() {
if(rom_loaded == true)return;
rf->read(&rom_image);
rom = rom_image;
rom_size = rf->size();
if(rom_size < 32768) {
free(rom_image);
return false;
}
//check for ROM header (currently unused)
if((rom_size & 0x1fff) == 0x0200) {
rom_size -= 512;
rom += 512;
}
if(rom_size >= 0x410000) {
if(rom[0x7fd5] == 0x32) {
mapper = EXLOROM;
} else {
mapper = EXHIROM;
}
goto end;
}
if(rom_size < 65536) {
mapper = LOROM;
goto end;
}
cksum = rom[0xffdc] | (rom[0xffdd] << 8);
icksum = rom[0xffde] | (rom[0xffdf] << 8);
if(cksum + icksum == 0xffff) {
mapper = HIROM;
} else {
mapper = LOROM;
}
if(rom[0x7fd5] == 0x32 && rom[0xffd5] == 0x32) {
//SFA2 detected
mapper = EXLOROM;
goto end;
}
end:
switch(mapper) {
case LOROM: index = 0x007fc0;break;
case HIROM: index = 0x00ffc0;break;
case EXLOROM:index = 0x007fc0;break;
case EXHIROM:index = 0x40ffc0;break;
}
memcpy(cart_title, (char*)rom + index, 21);
cart_title[21] = 0;
switch(rom[index + 0x18] & 7) {
case 0:sram_size = 0; break;
case 1:sram_size = 2 * 1024;break;
case 2:sram_size = 4 * 1024;break;
case 3:sram_size = 8 * 1024;break;
case 4:sram_size = 16 * 1024;break;
case 5:sram_size = 32 * 1024;break;
case 6:sram_size = 64 * 1024;break;
case 7:sram_size = 128 * 1024;break;
}
region = rom[index + 0x19];
dprintf("* Image Name : \"%s\"", cart_title);
dprintf("* Region : %s", (region <= 1)?"NTSC":"PAL");
dprintf("* MAD : %0.2x", mapper);
dprintf("* SRAM Size : %dkb", sram_size / 1024);
uint8 *rom = cartridge.rom;
uint16 index = cartridge.cart.header_index;
dprintf("* Image Name : \"%s\"", cartridge.cart.name);
dprintf("* Region : %s", (cartridge.cart.region == Cartridge::NTSC) ? "NTSC" : "PAL");
dprintf("* MAD : %0.2x", cartridge.cart.mapper);
dprintf("* SRAM Size : %dkb", cartridge.cart.sram_size / 1024);
dprintf("* Reset:%0.4x NMI:%0.4x IRQ:%0.4x BRK[n]:%0.4x COP[n]:%0.4x BRK[e]:%0.4x COP[e]:%0.4x",
rom[index + 0x3c] | (rom[index + 0x3d] << 8), //Reset
rom[index + 0x2a] | (rom[index + 0x2b] << 8), //NMI
@@ -92,66 +25,42 @@ end:
dprintf("");
CartInfo ci;
ci.rom = rom;
ci.sram = sram;
ci.rom_size = rom_size;
ci.sram_size = sram_size;
ci.rom = cartridge.rom;
ci.sram = cartridge.sram;
ci.rom_size = cartridge.cart.rom_size;
ci.sram_size = cartridge.cart.sram_size;
switch(mapper) {
case LOROM: cart = new bCartLoROM(); break;
case HIROM: cart = new bCartHiROM(); break;
case EXLOROM:cart = new bCartExLoROM();break;
case EXHIROM:cart = new bCartExHiROM();break;
default:return false;
switch(cartridge.cart.mapper) {
case Cartridge::LOROM: cart = new bCartLoROM(); break;
case Cartridge::HIROM: cart = new bCartHiROM(); break;
case Cartridge::EXLOROM:cart = new bCartExLoROM();break;
case Cartridge::EXHIROM:cart = new bCartExHiROM();break;
default:return;
}
cart->set_cartinfo(&ci);
rom_loaded = true;
if(region == 0 || region == 1) {
if(cartridge.cart.region == Cartridge::NTSC) {
snes->set_region(SNES::NTSC);
} else {
snes->set_region(SNES::PAL);
}
return true;
}
bool bMemBus::load_sram(Reader *rf) {
if(rom_loaded == false || sram_size == 0)return false;
rf->read(&sram, sram_size);
CartInfo ci;
ci.rom = rom;
ci.sram = sram;
ci.rom_size = rom_size;
ci.sram_size = sram_size;
cart->set_cartinfo(&ci);
return true;
}
bool bMemBus::save_sram(Writer *wf) {
if(rom_loaded == false || sram_size == 0)return false;
wf->write(sram, sram_size);
return true;
rom_loaded = true;
}
void bMemBus::unload_cart() {
if(rom_loaded == false)return;
if(rom_image)free(rom_image);
if(sram)free(sram);
delete(cart);
rom_loaded = false;
}
void bMemBus::get_cartinfo(CartInfo *ci) {
ci->rom = rom;
ci->sram = sram;
ci->rom_size = rom_size;
ci->sram_size = sram_size;
ci->rom = cartridge.rom;
ci->sram = cartridge.sram;
ci->rom_size = cartridge.cart.rom_size;
ci->sram_size = cartridge.cart.sram_size;
}
/***********************
@@ -171,7 +80,7 @@ void bMemBus::get_cartinfo(CartInfo *ci) {
***************************************/
uint8 bMemBus::read(uint32 addr) {
static uint32 r;
uint8 r;
switch(addr & 0xc00000) {
case 0x400000:
if((addr & 0xfe0000) == 0x7e0000) {
@@ -206,7 +115,9 @@ static uint32 r;
break;
}
#ifdef DEBUGGER
snes->notify(SNES::MEM_READ, addr, r);
#endif
return r;
}
@@ -245,7 +156,9 @@ void bMemBus::write(uint32 addr, uint8 value) {
break;
}
#ifdef DEBUGGER
snes->notify(SNES::MEM_WRITE, addr, value);
#endif
}
void bMemBus::power() {
+3 -5
View File
@@ -11,8 +11,7 @@ public:
//just a pointer to rom_image (with no header), or
//rom_image + 512 (if a header is present).
//rom should never be allocated or released directly.
uint8 *rom_image, *rom, *sram, *wram;
uint32 rom_size, sram_size;
uint8 *wram;
bool rom_loaded;
enum { LOROM = 0x20, HIROM = 0x21, EXLOROM = 0x22, EXHIROM = 0x25 };
@@ -20,10 +19,9 @@ enum { LOROM = 0x20, HIROM = 0x21, EXLOROM = 0x22, EXHIROM = 0x25 };
uint8 read (uint32 addr);
void write(uint32 addr, uint8 value);
bool load_cart(Reader *rf);
bool load_sram(Reader *rf);
bool save_sram(Writer *wf);
void load_cart();
void unload_cart();
bool cart_loaded() { return rom_loaded; }
void get_cartinfo(CartInfo *ci);
void power();
+1 -7
View File
@@ -79,7 +79,7 @@ void Memory::write_long(uint32 addr, uint32 data, uint wrap) {
}
MMIO mmio_unmapped;
uint8 MMIO::read (uint32 addr) { return cpu->regs.mdr; }
uint8 MMIO::read (uint32 addr) { return r_cpu->regs.mdr; }
void MMIO::write(uint32 addr, uint8 value) {}
uint8 MemBus::calc_speed(uint32 addr, bool fast) {
@@ -92,10 +92,6 @@ uint8 MemBus::calc_speed(uint32 addr, bool fast) {
return 8;
}
uint8 MemBus::speed(uint32 addr) {
return speed_table[addr >> 9];
}
void MemBus::set_speed(bool fast) {
fastROM = fast;
@@ -131,5 +127,3 @@ int i;
}
speed_table = (uint8*)speed_table_slowrom;
}
MemBus::~MemBus() {}
+7 -6
View File
@@ -43,18 +43,19 @@ uint8 *speed_table,
speed_table_fastrom[32768];
inline uint8 calc_speed(uint32 addr, bool fast);
public:
uint8 speed(uint32 addr);
void set_speed(bool fast);
inline uint8 speed(uint32 addr) {
return speed_table[addr >> 9];
}
void set_speed(bool fast);
virtual bool load_cart(Reader *rf) = 0;
virtual bool load_sram(Reader *rf) = 0;
virtual bool save_sram(Writer *wf) = 0;
virtual void load_cart() = 0;
virtual void unload_cart() = 0;
virtual bool cart_loaded() = 0;
virtual void get_cartinfo(CartInfo *ci) = 0;
virtual void power() = 0;
virtual void reset() = 0;
MemBus();
~MemBus();
virtual ~MemBus() {}
};
+69 -23
View File
@@ -5,18 +5,40 @@
void bPPU::run() {}
void bPPU::scanline() {
_y = cpu->vcounter();
_screen_width = (regs.bg_mode == 5 || regs.bg_mode == 6) ? 512 : 256;
_interlace = cpu->interlace();
_interlace_field = cpu->interlace_field();
line.y = r_cpu->vcounter();
line.width = (regs.hires) ? 512 : 256;
line.interlace = r_cpu->interlace();
line.interlace_field = r_cpu->interlace_field();
if(_y == 0) {
if(line.y == 0) {
//RTO flag reset
regs.time_over = false;
regs.range_over = false;
}
if(_y == 1) {
int32 bg;
if(line.y == 1) {
//mosaic reset
for(bg=BG1;bg<=BG4;bg++) {
regs.bg_y[bg] = 1;
}
regs.mosaic_countdown = regs.mosaic_size + 1;
regs.mosaic_countdown--;
} else {
for(bg=BG1;bg<=BG4;bg++) {
if(!regs.mosaic_enabled[bg] || !regs.mosaic_countdown) {
regs.bg_y[bg] = line.y;
}
}
if(!regs.mosaic_countdown) {
regs.mosaic_countdown = regs.mosaic_size + 1;
}
regs.mosaic_countdown--;
}
if(line.y == 1) {
//OAM FirstSprite priority set
if(regs.oam_priority == true) {
regs.oam_firstsprite = (regs.oam_addr & 0xfe) >> 1;
@@ -25,7 +47,7 @@ void bPPU::scanline() {
}
}
if(_y == (cpu->overscan() ? 239 : 224) && regs.display_disabled == false) {
if(line.y == (r_cpu->overscan() ? 239 : 224) && regs.display_disabled == false) {
//OAM address reset
regs.oam_addr = ((regs.oam_addrh << 8) | regs.oam_addrl) << 1;
}
@@ -34,17 +56,18 @@ void bPPU::scanline() {
void bPPU::render_scanline() {
if(status.render_output == false)return;
if(_y > 0 && _y < (cpu->overscan() ? 239 : 224)) {
if(line.y > 0 && line.y < (r_cpu->overscan() ? 239 : 224)) {
render_line();
}
}
void bPPU::frame() {
PPU::frame();
snes->notify(SNES::RENDER_FRAME);
}
void bPPU::power() {
PPU::power();
memset(vram, 0, 65536);
memset(oam, 0, 544);
memset(cgram, 0, 512);
@@ -55,6 +78,7 @@ void bPPU::power() {
}
void bPPU::reset() {
PPU::reset();
frame();
memset(sprite_list, 0, sizeof(sprite_list));
@@ -63,6 +87,12 @@ void bPPU::reset() {
regs.ppu1_mdr = 0xff;
regs.ppu2_mdr = 0xff;
//bg line counters
regs.bg_y[0] = 0;
regs.bg_y[1] = 0;
regs.bg_y[2] = 0;
regs.bg_y[3] = 0;
//$2100
regs.display_disabled = 0;
regs.display_brightness = 0;
@@ -87,13 +117,15 @@ void bPPU::reset() {
regs.bg_tilesize[BG4] = 0;
regs.bg3_priority = 0;
regs.bg_mode = 0;
regs.hires = false;
//$2106
regs.mosaic_size = 0;
regs.mosaic_enabled[BG1] = false;
regs.mosaic_enabled[BG2] = false;
regs.mosaic_enabled[BG3] = false;
regs.mosaic_enabled[BG4] = false;
regs.mosaic_size = 0;
regs.mosaic_enabled[BG1] = false;
regs.mosaic_enabled[BG2] = false;
regs.mosaic_enabled[BG3] = false;
regs.mosaic_enabled[BG4] = false;
regs.mosaic_countdown = 0;
//$2107-$210a
regs.bg_scaddr[BG1] = 0x0000;
@@ -227,16 +259,18 @@ void bPPU::reset() {
regs.color_enabled[BG1] = false;
//$2132
regs.color_r = 0x00;
regs.color_g = 0x00;
regs.color_b = 0x00;
regs.color_r = 0x00;
regs.color_g = 0x00;
regs.color_b = 0x00;
regs.color_rgb = 0x0000;
//$2133
regs.mode7_extbg = false;
regs.overscan = false;
regs.scanlines = 224;
regs.oam_halve = false;
regs.interlace = false;
regs.mode7_extbg = false;
regs.pseudo_hires = false;
regs.overscan = false;
regs.scanlines = 224;
regs.oam_halve = false;
regs.interlace = false;
//$2137
regs.hcounter = 0;
@@ -252,7 +286,7 @@ void bPPU::reset() {
regs.time_over = false;
regs.range_over = false;
_screen_width = 256; //needed for clear_window_cache()
line.width = 256; //needed for clear_window_cache()
update_sprite_list_sizes();
clear_tiledata_cache();
clear_window_cache();
@@ -261,20 +295,26 @@ void bPPU::reset() {
uint8 bPPU::vram_read(uint16 addr) {
uint8 r;
r = vram[addr];
#ifdef DEBUGGER
snes->notify(SNES::VRAM_READ, addr, r);
#endif
return r;
}
void bPPU::vram_write(uint16 addr, uint8 value) {
vram[addr] = value;
#ifdef DEBUGGER
snes->notify(SNES::VRAM_WRITE, addr, value);
#endif
}
uint8 bPPU::oam_read(uint16 addr) {
uint8 r;
if(addr >= 0x0200)addr = 0x0200 | (addr & 31);
r = oam[addr];
#ifdef DEBUGGER
snes->notify(SNES::OAM_READ, addr, r);
#endif
return r;
}
@@ -282,7 +322,9 @@ void bPPU::oam_write(uint16 addr, uint8 value) {
if(addr >= 0x0200)addr = 0x0200 | (addr & 31);
oam[addr] = value;
update_sprite_list(addr);
#ifdef DEBUGGER
snes->notify(SNES::OAM_WRITE, addr, value);
#endif
}
uint8 bPPU::cgram_read(uint16 addr) {
@@ -292,7 +334,9 @@ uint8 r;
if(addr & 1) {
r &= 0x7f;
}
#ifdef DEBUGGER
snes->notify(SNES::CGRAM_READ, addr, r);
#endif
return r;
}
@@ -302,7 +346,9 @@ void bPPU::cgram_write(uint16 addr, uint8 value) {
value &= 0x7f;
}
cgram[addr] = value;
#ifdef DEBUGGER
snes->notify(SNES::CGRAM_WRITE, addr, value);
#endif
}
bPPU::bPPU() {
+16 -2
View File
@@ -15,7 +15,14 @@ uint8 region;
enum { NTSC = 0, PAL = 1 };
enum { BG1 = 0, BG2 = 1, BG3 = 2, BG4 = 3, OAM = 4, BACK = 5, COL = 5 };
enum { SC_32x32 = 0, SC_32x64 = 1, SC_64x32 = 2, SC_64x64 = 3 };
enum { SC_32x32 = 0, SC_64x32 = 1, SC_32x64 = 2, SC_64x64 = 3 };
struct {
uint32 y;
uint32 width;
bool interlace;
bool interlace_field;
} line;
struct sprite_item {
uint8 width, height;
@@ -31,6 +38,9 @@ struct {
//open bus support
uint8 ppu1_mdr, ppu2_mdr;
//bg line counters
uint16 bg_y[4];
//$2100
bool display_disabled;
uint8 display_brightness;
@@ -51,10 +61,12 @@ struct {
bool bg_tilesize[4];
bool bg3_priority;
uint8 bg_mode;
bool hires;
//$2106
uint8 mosaic_size;
bool mosaic_enabled[4];
uint16 mosaic_countdown;
//$2107-$210a
uint16 bg_scaddr[4];
@@ -119,9 +131,11 @@ struct {
//$2132
uint8 color_r, color_g, color_b;
uint16 color_rgb;
//$2133
bool mode7_extbg;
bool pseudo_hires;
bool overscan;
uint16 scanlines;
bool oam_halve;
@@ -237,7 +251,7 @@ uint16 *mosaic_table[16];
void power();
void reset();
bool scanline_is_hires() { return (regs.bg_mode == 5 || regs.bg_mode == 6); }
bool scanline_is_hires() { return (regs.hires); }
bPPU();
~bPPU();
+30 -26
View File
@@ -1,6 +1,6 @@
void bPPU::latch_counters() {
regs.hcounter = cpu->hcounter();
regs.vcounter = cpu->vcounter();
regs.hcounter = r_cpu->hcounter();
regs.vcounter = r_cpu->vcounter();
regs.counters_latched = true;
}
@@ -21,20 +21,20 @@ bool bPPU::vram_can_read() {
return true;
}
uint16 v = cpu->vcounter();
uint16 hc = cpu->hcycles();
uint16 v = r_cpu->vcounter();
uint16 hc = r_cpu->hcycles();
uint16 ls;
if(cpu->interlace() && !cpu->interlace_field()) {
ls = cpu->region_scanlines();
if(r_cpu->interlace() && !r_cpu->interlace_field()) {
ls = r_cpu->region_scanlines();
} else {
ls = cpu->region_scanlines() - 1;
ls = r_cpu->region_scanlines() - 1;
}
if(v == ls && hc == 1362)return false;
if(v < (cpu->overscan() ? 239 : 224))return false;
if(v < (r_cpu->overscan() ? 239 : 224))return false;
if(v == (cpu->overscan() ? 239 : 224)) {
if(v == (r_cpu->overscan() ? 239 : 224)) {
if(hc == 1362)return true;
return false;
}
@@ -47,17 +47,17 @@ bool bPPU::vram_can_write(uint8 &value) {
return true;
}
uint16 v = cpu->vcounter();
uint16 hc = cpu->hcycles();
uint16 v = r_cpu->vcounter();
uint16 hc = r_cpu->hcycles();
if(v == 0) {
if(hc <= 4)return true;
if(hc == 6) { value = cpu->regs.mdr; return true; }
if(hc == 6) { value = r_cpu->regs.mdr; return true; }
return false;
}
if(v < (cpu->overscan() ? 240 : 225))return false;
if(v < (r_cpu->overscan() ? 240 : 225))return false;
if(v == (cpu->overscan() ? 240 : 225)) {
if(v == (r_cpu->overscan() ? 240 : 225)) {
if(hc <= 4)return false;
return true;
}
@@ -117,6 +117,7 @@ void bPPU::mmio_w2105(uint8 value) {
regs.bg_tilesize[BG1] = !!(value & 0x10);
regs.bg3_priority = !!(value & 0x08);
regs.bg_mode = (value & 7);
regs.hires = (regs.bg_mode == 5 || regs.bg_mode == 6);
window_cache[BG1].main_dirty = window_cache[BG1].sub_dirty = true;
window_cache[BG2].main_dirty = window_cache[BG2].sub_dirty = true;
@@ -542,18 +543,21 @@ void bPPU::mmio_w2132(uint8 value) {
if(value & 0x80)regs.color_b = value & 0x1f;
if(value & 0x40)regs.color_g = value & 0x1f;
if(value & 0x20)regs.color_r = value & 0x1f;
regs.color_rgb = (regs.color_r) | (regs.color_g << 5) | (regs.color_b << 10);
}
//SETINI
void bPPU::mmio_w2133(uint8 value) {
regs.mode7_extbg = !!(value & 0x40);
regs.overscan = !!(value & 0x04);
regs.scanlines = (value & 0x04)?239:224;
regs.oam_halve = !!(value & 0x02);
regs.interlace = !!(value & 0x01);
regs.mode7_extbg = !!(value & 0x40);
regs.pseudo_hires = !!(value & 0x08);
regs.overscan = !!(value & 0x04);
regs.scanlines = (value & 0x04)?239:224;
regs.oam_halve = !!(value & 0x02);
regs.interlace = !!(value & 0x01);
cpu->set_overscan(regs.overscan);
cpu->set_interlace(regs.interlace);
r_cpu->set_overscan(regs.overscan);
r_cpu->set_interlace(regs.interlace);
}
//MPYL
@@ -582,10 +586,10 @@ uint32 r;
//SLHV
uint8 bPPU::mmio_r2137() {
if(cpu->pio_status() & 0x80) {
if(r_cpu->pio_status() & 0x80) {
latch_counters();
}
return cpu->regs.mdr;
return r_cpu->regs.mdr;
}
//OAMDATAREAD
@@ -689,8 +693,8 @@ uint8 r = 0x00;
regs.latch_hcounter = 0;
regs.latch_vcounter = 0;
r |= cpu->interlace_field() << 7;
if(!(cpu->pio_status() & 0x80)) {
r |= r_cpu->interlace_field() << 7;
if(!(r_cpu->pio_status() & 0x80)) {
r |= 0x40;
} else if(regs.counters_latched == true) {
r |= 0x40;
@@ -738,7 +742,7 @@ uint8 bPPUMMIO::read(uint32 addr) {
case 0x213f:return ppu->mmio_r213f(); //STAT78
}
return cpu->regs.mdr;
return r_cpu->regs.mdr;
}
void bPPUMMIO::write(uint32 addr, uint8 value) {
+46 -14
View File
@@ -6,6 +6,40 @@
#include "bppu_render_addsub.cpp"
#include "bppu_render_line.cpp"
bool bPPU::render_enabled(uint8 bg, uint8 pri) {
switch(bg) {
case BG1:
switch(pri) {
case 0: return config::ppu.bg1_pri0_enable;
case 1: return config::ppu.bg1_pri1_enable;
} break;
case BG2:
switch(pri) {
case 0: return config::ppu.bg2_pri0_enable;
case 1: return config::ppu.bg2_pri1_enable;
} break;
case BG3:
switch(pri) {
case 0: return config::ppu.bg3_pri0_enable;
case 1: return config::ppu.bg3_pri1_enable;
} break;
case BG4:
switch(pri) {
case 0: return config::ppu.bg4_pri0_enable;
case 1: return config::ppu.bg4_pri1_enable;
} break;
case OAM:
switch(pri) {
case 0: return config::ppu.oam_pri0_enable;
case 1: return config::ppu.oam_pri1_enable;
case 2: return config::ppu.oam_pri2_enable;
case 3: return config::ppu.oam_pri3_enable;
} break;
}
return true;
}
/*
Mode 0: ->
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12
@@ -20,28 +54,25 @@ inline void bPPU::render_line_mode0() {
}
/*
Mode 1 (pri=0): ->
1, 2, 3, 4, 5, 6, 7, 8, 9, 10
BG3B, OAM0, BG3A, OAM1, BG2B, BG1B, OAM2, BG2A, BG1A, OAM3
Mode 1 (pri=1): ->
1, 2, 3, 4, 5, 6, 7, 8, 9, 10
BG3B, OAM0, OAM1, BG2B, BG1B, OAM2, BG2A, BG1A, OAM3, BG3A
Mode 1 (pri=0): ->
1, 2, 3, 4, 5, 6, 7, 8, 9, 10
BG3B, OAM0, BG3A, OAM1, BG2B, BG1B, OAM2, BG2A, BG1A, OAM3
*/
inline void bPPU::render_line_mode1() {
switch(regs.bg3_priority) {
case 0:
render_line_bg(BG1, COLORDEPTH_16, 6, 9);
render_line_bg(BG2, COLORDEPTH_16, 5, 8);
render_line_bg(BG3, COLORDEPTH_4, 1, 3);
render_line_oam(2, 4, 7, 10);
break;
case 1:
if(regs.bg3_priority) {
render_line_bg(BG1, COLORDEPTH_16, 5, 8);
render_line_bg(BG2, COLORDEPTH_16, 4, 7);
render_line_bg(BG3, COLORDEPTH_4, 1, 10);
render_line_oam(2, 3, 6, 9);
break;
} else {
render_line_bg(BG1, COLORDEPTH_16, 6, 9);
render_line_bg(BG2, COLORDEPTH_16, 5, 8);
render_line_bg(BG3, COLORDEPTH_4, 1, 3);
render_line_oam(2, 4, 7, 10);
}
}
@@ -121,12 +152,13 @@ inline void bPPU::render_line_mode7() {
void bPPU::render_line() {
if(regs.display_disabled == true) {
memset(snes->get_ppu_output_handle(), 0, 1024);
memset(output + (line.y * 1024), 0, 1024);
return;
}
clear_pixel_cache();
build_window_tables(COL);
update_bg_info();
switch(regs.bg_mode) {
case 0:render_line_mode0();break;
+19 -13
View File
@@ -1,8 +1,5 @@
//bppu_render.cpp
int _screen_width;
bool _interlace;
int _interlace_field;
inline bool render_enabled(uint8 bg, uint8 pri);
inline void render_line_mode0();
inline void render_line_mode1();
inline void render_line_mode2();
@@ -16,19 +13,18 @@ inline void render_line_mode7();
enum { COLORDEPTH_4 = 0, COLORDEPTH_16 = 1, COLORDEPTH_256 = 2 };
enum { TILE_2BIT = 0, TILE_4BIT = 1, TILE_8BIT = 2 };
enum { PC_BG1 = 0x80, PC_BG2 = 0x81, PC_BG3 = 0x82, PC_BG4 = 0x83, PC_OAM = 0x84, PC_BACK = 0x00 };
struct _pixel {
//bgr555 color data for main/subscreen pixels: 0x0000 = transparent / use palette color # 0
//needs to be bgr555 instead of palette index for direct color mode ($2130 bit 0) to work
uint16 src_main, src_sub;
//indicates source of palette # for main/subscreen (BG1-4, OAM, or back)
uint8 bg_main, bg_sub;
//true when bg_main == OAM && palette index >= 192, disables color add/sub effects
uint8 color_exempt;
//color_exemption -- true when bg == OAM && palette index >= 192, disables color add/sub effects
uint8 ce_main, ce_sub;
//priority level of src_n. to set src_n,
//the priority of the pixel must be >pri_n
uint8 pri_main, pri_sub;
} pixel_cache[512];
} pixel_cache[256];
uint8 *bg_tiledata[3];
uint8 *bg_tiledata_state[3];
@@ -41,7 +37,7 @@ inline void clear_tiledata_cache();
//bppu_render_windows.cpp
struct _window {
bool main_dirty, sub_dirty;
uint8 main[512], sub[512];
uint8 main[256], sub[256];
} window_cache[6];
void build_window_table(uint8 bg, bool mainscreen);
@@ -49,6 +45,13 @@ void build_window_tables(uint8 bg);
inline void clear_window_cache();
//bppu_render_bg.cpp
struct {
uint16 tw, th; //tile width, height
uint16 mx, my; //screen mask x, y
} bg_info[4];
inline void update_bg_info();
inline uint16 bg_get_tile(uint8 bg, uint16 x, uint16 y);
void render_line_bg(uint8 bg, uint8 color_depth, uint8 pri0_pos, uint8 pri1_pos);
//bppu_render_oam.cpp
@@ -61,24 +64,27 @@ struct oam_tileitem {
} oam_tilelist[34];
enum { OAM_PRI_NONE = 4 };
uint8 oam_line_pal[512], oam_line_pri[512];
uint8 oam_line_pal[256], oam_line_pri[256];
bool is_sprite_on_scanline();
void load_oam_tiles();
void render_oam_tile(int tile_num);
void render_line_oam(uint8 pri0_pos, uint8 pri1_pos, uint8 pri2_pos, uint8 pri3_pos);
void render_line_oam_lores(uint8 pri0_pos, uint8 pri1_pos, uint8 pri2_pos, uint8 pri3_pos);
//bppu_render_mode7.cpp
void render_line_mode7(uint8 bg, uint8 pri0_pos, uint8 pri1_pos);
//bppu_render_addsub.cpp
inline uint16 addsub_pixels(uint32 cdest, uint32 csrc);
inline uint16 addsub_pixel (uint32 cdest);
inline uint16 addsub_pixels(uint32 x, uint32 cdest, uint32 csrc, bool halve);
//bppu_render_line.cpp
enum { BLENDTYPE_BACK = 0, BLENDTYPE_MAIN = 1, BLENDTYPE_SUB = 2, BLENDTYPE_COMBINE = 3 };
inline uint16 get_palette(uint8 index);
inline uint16 get_direct_color(uint8 p, uint8 t);
inline uint16 get_pixel(int x);
inline uint16 get_pixel_normal(uint32 x);
inline uint16 get_pixel_swap(uint32 x);
inline uint16 get_pixel_lores(uint32 x);
inline uint16 get_pixel_hires(uint32 x);
inline void render_line_output();
+21 -84
View File
@@ -1,92 +1,29 @@
inline uint16 bPPU::addsub_pixels(uint32 cdest, uint32 csrc) {
int r, g, b;
uint16 res;
switch(regs.color_mode) {
case 0: //COLORMODE_ADD:
if(regs.color_halve == true) {
cdest = ((cdest << 16) | cdest) & 0x03e07c1f;
csrc = ((csrc << 16) | csrc) & 0x03e07c1f;
cdest += csrc;
cdest >>= 1;
cdest &= 0x03e07c1f;
return (cdest >> 16) | cdest;
} else {
cdest = ((cdest << 16) | cdest) & 0x03e07c1f;
csrc = ((csrc << 16) | csrc) & 0x03e07c1f;
cdest += csrc;
if(cdest & 0x04000000)cdest |= 0x03e00000;
if(cdest & 0x00008000)cdest |= 0x00007c00;
if(cdest & 0x00000020)cdest |= 0x0000001f;
cdest &= 0x03e07c1f;
return (cdest >> 16) | cdest;
}
break;
case 1: //COLORMODE_SUB:
if(regs.color_halve == true) {
if((cdest & 0x7c00) < (csrc & 0x7c00))cdest &= ~0x7c00;
else cdest -= (csrc & 0x7c00);
if((cdest & 0x03e0) < (csrc & 0x03e0))cdest &= ~0x03e0;
else cdest -= (csrc & 0x03e0);
if((cdest & 0x001f) < (csrc & 0x001f))cdest &= ~0x001f;
else cdest -= (csrc & 0x001f);
return (cdest & 0x7bde) >> 1;
} else {
if((cdest & 0x7c00) < (csrc & 0x7c00))cdest &= ~0x7c00;
else cdest -= (csrc & 0x7c00);
if((cdest & 0x03e0) < (csrc & 0x03e0))cdest &= ~0x03e0;
else cdest -= (csrc & 0x03e0);
if((cdest & 0x001f) < (csrc & 0x001f))cdest &= ~0x001f;
else cdest -= (csrc & 0x001f);
return cdest;
}
break;
}
return 0x0000; //prevent annoying warning message
}
inline uint16 bPPU::addsub_pixels(uint32 x, uint32 cdest, uint32 csrc, bool halve) {
if(!regs.color_mode) {
//add
cdest = ((cdest << 16) | cdest) & 0x03e07c1f;
csrc = ((csrc << 16) | csrc) & 0x03e07c1f;
cdest += csrc;
inline uint16 bPPU::addsub_pixel(uint32 cdest) {
int r, g, b;
uint32 csrc = (regs.color_r) | (regs.color_g << 5) | (regs.color_b << 10);
uint16 res;
switch(regs.color_mode) {
case 0: //COLORMODE_ADD:
if(regs.color_halve == true && regs.addsub_mode == 0) {
cdest = ((cdest << 16) | cdest) & 0x03e07c1f;
csrc = ((csrc << 16) | csrc) & 0x03e07c1f;
cdest += csrc;
cdest >>= 1;
cdest &= 0x03e07c1f;
return (cdest >> 16) | cdest;
} else {
cdest = ((cdest << 16) | cdest) & 0x03e07c1f;
csrc = ((csrc << 16) | csrc) & 0x03e07c1f;
cdest += csrc;
if(!halve) {
if(cdest & 0x04000000)cdest |= 0x03e00000;
if(cdest & 0x00008000)cdest |= 0x00007c00;
if(cdest & 0x00000020)cdest |= 0x0000001f;
cdest &= 0x03e07c1f;
return (cdest >> 16) | cdest;
}
break;
case 1: //COLORMODE_SUB:
if(regs.color_halve == true && regs.addsub_mode == 0) {
if((cdest & 0x7c00) < (csrc & 0x7c00))cdest &= ~0x7c00;
else cdest -= (csrc & 0x7c00);
if((cdest & 0x03e0) < (csrc & 0x03e0))cdest &= ~0x03e0;
else cdest -= (csrc & 0x03e0);
if((cdest & 0x001f) < (csrc & 0x001f))cdest &= ~0x001f;
else cdest -= (csrc & 0x001f);
return (cdest & 0x7bde) >> 1;
} else {
if((cdest & 0x7c00) < (csrc & 0x7c00))cdest &= ~0x7c00;
else cdest -= (csrc & 0x7c00);
if((cdest & 0x03e0) < (csrc & 0x03e0))cdest &= ~0x03e0;
else cdest -= (csrc & 0x03e0);
if((cdest & 0x001f) < (csrc & 0x001f))cdest &= ~0x001f;
else cdest -= (csrc & 0x001f);
return cdest;
cdest >>= 1;
}
break;
cdest &= 0x03e07c1f;
return (cdest >> 16) | cdest;
} else {
//subtract
if((cdest & 0x7c00) < (csrc & 0x7c00))cdest &= ~0x7c00;
else cdest -= (csrc & 0x7c00);
if((cdest & 0x03e0) < (csrc & 0x03e0))cdest &= ~0x03e0;
else cdest -= (csrc & 0x03e0);
if((cdest & 0x001f) < (csrc & 0x001f))cdest &= ~0x001f;
else cdest -= (csrc & 0x001f);
return (!halve) ? cdest : ((cdest & 0x7bde) >> 1);
}
return 0x0000; //prevent annoying warning message
}
+160 -217
View File
@@ -1,263 +1,206 @@
//called once at the start of every rendered scanline
void bPPU::update_bg_info() {
for(int bg = 0; bg < 4; bg++) {
bg_info[bg].th = (regs.bg_tilesize[bg]) ? 4 : 3;
bg_info[bg].tw = (regs.hires) ? 4 : bg_info[bg].th;
bg_info[bg].mx = (bg_info[bg].th == 4) ? (line.width << 1) : line.width;
bg_info[bg].my = bg_info[bg].mx;
if(regs.bg_scsize[bg] & 0x01)bg_info[bg].mx <<= 1;
if(regs.bg_scsize[bg] & 0x02)bg_info[bg].my <<= 1;
bg_info[bg].mx--;
bg_info[bg].my--;
}
}
uint16 bPPU::bg_get_tile(uint8 bg, uint16 x, uint16 y) {
uint16 pos;
x &= bg_info[bg].mx;
y &= bg_info[bg].my;
x >>= bg_info[bg].tw;
y >>= bg_info[bg].th;
pos = (regs.bg_scsize[bg] & 2) ? ((y & 0x20) << ((regs.bg_scsize[bg] & 1) ? 6 : 5)) : 0;
pos += (regs.bg_scsize[bg] & 1) ? ((x & 0x20) << 5) : 0;
pos += ((y & 31) << 5) + (x & 31);
return read16(vram, regs.bg_scaddr[bg] + (pos << 1));
}
void bPPU::render_line_bg(uint8 bg, uint8 color_depth, uint8 pri0_pos, uint8 pri1_pos) {
if(regs.bg_enabled[bg] == false && regs.bgsub_enabled[bg] == false) {
return;
}
int x;
int _scaddr = regs.bg_scaddr[bg];
int _tdaddr = regs.bg_tdaddr[bg];
bool _bg_enabled = regs.bg_enabled[bg];
bool _bgsub_enabled = regs.bgsub_enabled[bg];
//are layers disabled by user?
if(render_enabled(bg, 0) == false)pri0_pos = 0;
if(render_enabled(bg, 1) == false)pri1_pos = 0;
//nothing to render?
if(!pri0_pos && !pri1_pos)return;
uint16 opt_valid_bit; //offset-per-tile valid flag bit
if(bg == BG1) {
opt_valid_bit = 0x2000;
} else if(bg == BG2) {
opt_valid_bit = 0x4000;
} else {
opt_valid_bit = 0x0000;
bool bg_enabled = regs.bg_enabled[bg];
bool bgsub_enabled = regs.bgsub_enabled[bg];
uint16 opt_valid_bit = (bg == BG1) ? 0x2000 : ((bg == BG2) ? 0x4000 : 0x0000);
uint8 bgpal_index = (regs.bg_mode == 0) ? (bg << 5) : 0;
uint8 pal_size = (color_depth == 2) ? 256 : ((color_depth == 1) ? 16 : 4);
uint16 tile_mask = (color_depth == 2) ? 0x03ff : ((color_depth == 1) ? 0x07ff : 0x0fff);
//4 + color_depth = >>(4-6) -- / {16, 32, 64 } bytes/tile
//index is a tile number count to add to base tile number
uint tiledata_index = regs.bg_tdaddr[bg] >> (4 + color_depth);
uint8 *bg_td = (uint8*)bg_tiledata[color_depth];
uint8 *bg_td_state = (uint8*)bg_tiledata_state[color_depth];
uint8 tile_width = bg_info[bg].tw;
uint8 tile_height = bg_info[bg].th;
uint16 mask_x = bg_info[bg].mx; //screen width mask
uint16 mask_y = bg_info[bg].my; //screen height mask
uint x = 0;
uint y = regs.bg_y[bg];
if(line.interlace && regs.hires) {
y = (y << 1) + line.interlace_field;
}
//Mode 0 uses a special palette-indexing mode.
//Since there are 8 selectable palettes per tile,
//and there are 4 colors per palette on all four
//BGs for Mode 0, each BG has a unique palette
//entry point. This allows all 256 palette colors
//to be used, instead of just the first 32.
//entry = bg * 32, where 32 is from 8 * 4
uint8 bgpal_index = (regs.bg_mode == 0) ? (bg << 5) : 0;
uint16 hscroll = (regs.hires) ? (regs.bg_hofs[bg] << 1) : regs.bg_hofs[bg];
uint16 vscroll = (line.interlace && regs.hires) ? (regs.bg_vofs[bg] << 1) : regs.bg_vofs[bg];
hscroll &= mask_x;
vscroll &= mask_y;
uint8 pal_size, tiledata_size;
switch(color_depth) {
case COLORDEPTH_4:
pal_size = 4;
tiledata_size = 4; //<<4=*16
break;
case COLORDEPTH_16:
pal_size = 16;
tiledata_size = 5; //<<5=*32
break;
case COLORDEPTH_256:
pal_size = 256;
tiledata_size = 6; //<<6=*64
break;
}
uint16 *mtable = (uint16*)mosaic_table[(regs.mosaic_enabled[bg]) ? regs.mosaic_size : 0];
uint16 mosaic_x;
uint16 mosaic_y;
uint8 *bg_td, *bg_td_state;
bg_td = (uint8*)bg_tiledata[color_depth];
bg_td_state = (uint8*)bg_tiledata_state[color_depth];
uint16 screen_width, screen_height;
screen_width = _screen_width;
screen_height = _screen_width; //this is correct -- ppu tilemap is a perfect square
uint8 tile_size, tile_width, tile_height;
tile_size = (regs.bg_tilesize[bg])?4:3; //<<4=*16, <<3=*8
tile_width = tile_size;
tile_height = tile_size;
int screen_x, screen_y;
if(_interlace == true && _screen_width == 512) {
screen_y = (_y << 1) + _interlace_field;
} else {
screen_y = _y;
}
//Modes 5 and 6 seem to force 16-width tiles due to having twice the resolution.
//The tile size attribute in $2105 has no effect on tile width.
if(_screen_width == 512) {
tile_width = 4; //<<4=*16
}
if(tile_size == 4) { //16x16 tile size
screen_width <<= 1;
screen_height <<= 1;
}
if(regs.bg_scsize[bg] & 0x01)screen_width <<= 1;
if(regs.bg_scsize[bg] & 0x02)screen_height <<= 1;
uint16 screen_width_mask, screen_height_mask;
screen_width_mask = screen_width - 1;
screen_height_mask = screen_height - 1;
int bg_x, bg_y;
uint16 vscroll, hscroll;
if(_screen_width == 512) {
hscroll = (regs.bg_hofs[bg] << 1) & screen_width_mask;
} else {
hscroll = regs.bg_hofs[bg] & screen_width_mask;
}
bg_x = hscroll;
if(_screen_width == 512 && _interlace == true) {
vscroll = (regs.bg_vofs[bg] << 1) & screen_height_mask;
} else {
vscroll = regs.bg_vofs[bg] & screen_height_mask;
}
bg_y = (screen_y + vscroll) & screen_height_mask;
uint16 *mtable;
int mosaic_x, mosaic_y;
if(regs.mosaic_enabled[bg] == true) {
mtable = (uint16*)mosaic_table[regs.mosaic_size];
} else {
mtable = (uint16*)mosaic_table[0];
}
mosaic_x = mtable[bg_x];
mosaic_y = mtable[bg_y];
uint8 tile_x;
uint16 t, base_xpos, base_pos, pos;
uint16 tile_num;
int mirror_x, mirror_y;
uint16 hval, vval;
uint16 t, tile_pri, tile_num;
uint8 pal_index, pal_num;
uint8 *tile_ptr;
int xpos, ypos;
uint16 map_index, hoffset, voffset, col;
uint xpos, ypos;
uint16 hoffset, voffset, opt_x, col;
bool mirror_x, mirror_y;
bool is_opt_mode = (config::ppu.opt_enable) && (regs.bg_mode == 2 || regs.bg_mode == 4 || regs.bg_mode == 6);
build_window_tables(bg);
uint8 *wt_main = window_cache[bg].main;
uint8 *wt_sub = window_cache[bg].sub;
screen_x = 0;
do { //for(screen_x=0;screen_x<_screen_width;screen_x++) {
if(regs.bg_mode == 2 || regs.bg_mode == 4 || regs.bg_mode == 6) {
if(regs.bg_mode == 6) {
//hires adjust
tile_x = (mtable[screen_x + (hscroll & 15)] >> 4);
} else {
tile_x = (mtable[screen_x + (hscroll & 7)] >> 3);
}
int32 prev_x = -1, prev_y = -1;
for(x = 0; x < line.width; x++) {
hoffset = x + hscroll;
voffset = y + vscroll;
hoffset = hscroll;
voffset = vscroll;
if(is_opt_mode) {
opt_x = (x + (hscroll & 7));
//tile 0 is unaffected by OPT mode...
if(tile_x != 0) {
//multiply by two to index into 16-bit table entries
tile_x = ((tile_x - 1) & 31) << 1;
if(opt_x >= 8) {
hval = bg_get_tile(BG3,
(opt_x - 8) + (regs.bg_hofs[BG3] & ~7),
regs.bg_vofs[BG3]);
vval = bg_get_tile(BG3,
(opt_x - 8) + (regs.bg_hofs[BG3] & ~7),
regs.bg_vofs[BG3] + 8);
if(regs.bg_mode == 4) {
pos = regs.bg_scaddr[BG3] + tile_x;
t = read16(vram, pos);
if(t & opt_valid_bit) {
if(!(t & 0x8000)) {
hoffset = ((t & 0x1ff8) | (hscroll & 7)) & screen_width_mask;
if(hval & opt_valid_bit) {
if(!(hval & 0x8000)) {
hoffset = opt_x + (hval & ~7);
} else {
voffset = (t & 0x1fff) & screen_height_mask;
voffset = y + hval;
}
}
} else {
pos = regs.bg_scaddr[BG3] + tile_x;
t = read16(vram, pos);
if(t & opt_valid_bit) {
hoffset = ((t & 0x1ff8) | (hscroll & 7)) & screen_width_mask;
if(hval & opt_valid_bit) {
hoffset = opt_x + (hval & ~7);
}
pos = regs.bg_scaddr[BG3] + 64 + tile_x;
t = read16(vram, pos);
if(t & opt_valid_bit) {
voffset = (t & 0x1fff) & screen_height_mask;
if(vval & opt_valid_bit) {
voffset = y + vval;
}
}
}
mosaic_x = mtable[(screen_x + hoffset) & screen_width_mask ];
mosaic_y = mtable[(screen_y + voffset) & screen_height_mask];
}
switch(regs.bg_scsize[bg]) {
case 0:
map_index = 0;
break;
case 1:
map_index = ((mosaic_x >> tile_size) >> 5) << 11;
break;
case 2:
map_index = ((mosaic_y >> tile_size) >> 5) << 11;
break;
case 3:
map_index = ((mosaic_x >> tile_size) >> 5) << 11 |
((mosaic_y >> tile_size) >> 5) << 12;
break;
}
mosaic_x = mtable[hoffset & mask_x];
mosaic_y = voffset & mask_y;
base_xpos = ((mosaic_x >> 3) & 31);
base_pos = (((mosaic_y >> tile_height) & 31) << 5) + ((mosaic_x >> tile_width) & 31);
pos = _scaddr + map_index + (base_pos << 1);
t = read16(vram, pos);
mirror_y = !!(t & 0x8000);
mirror_x = !!(t & 0x4000);
if((mosaic_x >> 3) != prev_x || (mosaic_y >> 3) != prev_y) {
prev_x = (mosaic_x >> 3);
prev_y = (mosaic_y >> 3);
int _pri;
_pri = (t & 0x2000) ? pri1_pos : pri0_pos;
t = bg_get_tile(bg, mosaic_x, mosaic_y);
tile_num = t & 0x03ff;
mirror_y = !!(t & 0x8000);
mirror_x = !!(t & 0x4000);
tile_pri = (t & 0x2000) ? pri1_pos : pri0_pos;
tile_num = t;
if(tile_width == 4) { //16x16 horizontal tile mirroring
if(!!(mosaic_x & 8) != mirror_x)tile_num++;
}
if(tile_height == 4) { //16x16 vertical tile mirroring
if(!!(mosaic_y & 8) != mirror_y)tile_num += 16;
}
//16x16 horizontal tile mirroring
if(tile_width == 4) {
if(((mosaic_x & 15) >= 8 && !mirror_x) ||
((mosaic_x & 15) < 8 && mirror_x))tile_num++;
tile_num &= 0x03ff;
tile_num += tiledata_index;
tile_num &= tile_mask;
if(bg_td_state[tile_num] == 1) {
render_bg_tile(color_depth, tile_num);
}
pal_num = ((t >> 10) & 7);
pal_index = (pal_num * pal_size) + bgpal_index;
ypos = mosaic_y & 7;
if(mirror_y)ypos ^= 7; //invert y tile pos
tile_ptr = (uint8*)bg_td + (tile_num * 64) + (ypos * 8);
}
//16x16 vertical tile mirroring
if(tile_height == 4) {
if(((mosaic_y & 15) >= 8 && !mirror_y) ||
((mosaic_y & 15) < 8 && mirror_y))tile_num += 16;
tile_num &= 0x03ff;
}
xpos = mosaic_x & 7;
if(mirror_x)xpos ^= 7; //invert x tile pos
col = *(tile_ptr + xpos);
if(col) {
if(regs.direct_color == true && bg == BG1 && (regs.bg_mode == 3 || regs.bg_mode == 4)) {
col = get_direct_color(pal_num, col);
} else {
col = get_palette(col + pal_index);
}
tile_num += (_tdaddr >> tiledata_size);
#define setpixel_main(x) \
if(pixel_cache[x].pri_main < tile_pri) { \
pixel_cache[x].pri_main = tile_pri; \
pixel_cache[x].bg_main = bg; \
pixel_cache[x].src_main = col; \
pixel_cache[x].ce_main = false; \
}
#define setpixel_sub(x) \
if(pixel_cache[x].pri_sub < tile_pri) { \
pixel_cache[x].pri_sub = tile_pri; \
pixel_cache[x].bg_sub = bg; \
pixel_cache[x].src_sub = col; \
pixel_cache[x].ce_sub = false; \
}
if(bg_td_state[tile_num] == 1) {
render_bg_tile(color_depth, tile_num);
}
pal_num = ((t >> 10) & 7);
pal_index = pal_num * pal_size + bgpal_index;
if(mirror_y) { ypos = (7 - (mosaic_y & 7)); }
else { ypos = ( (mosaic_y & 7)); }
//loop while we are rendering from the same tile, as there's no need to do all of the above work
//unless we have rendered all of the visible tile, taking mosaic into account.
tile_ptr = (uint8*)bg_td + (tile_num << 6) + (ypos << 3);
do {
if(mirror_x) { xpos = (7 - (mosaic_x & 7)); }
else { xpos = ( (mosaic_x & 7)); }
col = *(tile_ptr + xpos);
if(col && window_cache[COL].main[screen_x]) {
if(regs.direct_color == true && bg == BG1 && (regs.bg_mode == 3 || regs.bg_mode == 4)) {
col = get_direct_color(pal_num, col);
if(!regs.hires) {
if(bg_enabled == true && !wt_main[x]) { setpixel_main(x); }
if(bgsub_enabled == true && !wt_sub[x]) { setpixel_sub(x); }
} else {
int hx = x >> 1;
if(x & 1) {
if(bg_enabled == true && !wt_main[hx]) { setpixel_main(hx); }
} else {
col = get_palette(col + pal_index);
}
if(_bg_enabled == true && !wt_main[screen_x]) {
if(pixel_cache[screen_x].pri_main < _pri) {
pixel_cache[screen_x].pri_main = _pri;
pixel_cache[screen_x].bg_main = 0x80 | bg;
pixel_cache[screen_x].src_main = col;
pixel_cache[screen_x].color_exempt = false;
}
}
if(_bgsub_enabled == true && !wt_sub[screen_x]) {
if(pixel_cache[screen_x].pri_sub < _pri) {
pixel_cache[screen_x].pri_sub = _pri;
pixel_cache[screen_x].bg_sub = 0x80 | bg;
pixel_cache[screen_x].src_sub = col;
}
if(bgsub_enabled == true && !wt_sub[hx]) { setpixel_sub(hx); }
}
}
bg_x++;
bg_x &= screen_width_mask;
mosaic_x = mtable[bg_x];
if(base_xpos != ((mosaic_x >> 3) & 31))break;
if(++screen_x >= _screen_width)break;
} while(1);
} while(++screen_x < _screen_width);
#undef setpixel_main
#undef setpixel_sub
}
}
}
+20 -2
View File
@@ -3,6 +3,7 @@
if(d0 & __m)col += 1; \
if(d1 & __m)col += 2; \
*dest++ = col
#define render_bg_tile_line_16(__m) \
col = 0; \
if(d0 & __m)col += 1; \
@@ -10,6 +11,7 @@
if(d2 & __m)col += 4; \
if(d3 & __m)col += 8; \
*dest++ = col
#define render_bg_tile_line_256(__m) \
col = 0; \
if(d0 & __m)col += 1; \
@@ -96,8 +98,24 @@ uint8 *dest;
}
}
#undef render_bg_tile_line_4
#undef render_bg_tile_line_16
#undef render_bg_tile_line_256
inline void bPPU::clear_pixel_cache() {
memset(pixel_cache, 0, sizeof(pixel_cache));
uint16 main = get_palette(0);
uint16 sub = (regs.pseudo_hires || regs.hires) ? main : regs.color_rgb;
uint32 i = 255;
do {
pixel_cache[i].src_main = main;
pixel_cache[i].src_sub = sub;
pixel_cache[i].bg_main = BACK;
pixel_cache[i].bg_sub = BACK;
pixel_cache[i].ce_main = false;
pixel_cache[i].ce_sub = false;
pixel_cache[i].pri_main = 0;
pixel_cache[i].pri_sub = 0;
} while(i--);
}
void bPPU::init_tiledata_cache() {
@@ -112,7 +130,7 @@ void bPPU::init_tiledata_cache() {
void bPPU::clear_tiledata_cache() {
memset(bg_tiledata[TILE_2BIT], 0, 262144);
memset(bg_tiledata[TILE_4BIT], 0, 131072);
memset(bg_tiledata[TILE_4BIT], 0, 65536);
memset(bg_tiledata[TILE_8BIT], 0, 65536);
memset(bg_tiledata_state[TILE_2BIT], 0, 4096);
memset(bg_tiledata_state[TILE_4BIT], 0, 2048);
memset(bg_tiledata_state[TILE_8BIT], 0, 1024);
+90 -52
View File
@@ -11,71 +11,109 @@ inline uint16 bPPU::get_direct_color(uint8 p, uint8 t) {
((t >> 6) << 13) | ((p >> 2) << 12);
}
inline uint16 bPPU::get_pixel(int x) {
inline uint16 bPPU::get_pixel_normal(uint32 x) {
_pixel *p = &pixel_cache[x];
uint16 _r, src_back = get_palette(0);
if(p->bg_main && p->bg_sub) {
if(p->color_exempt == false && regs.color_enabled[p->bg_main & 0x7f] && window_cache[COL].sub[x]) {
if(regs.addsub_mode) {
_r = addsub_pixels(p->src_main, p->src_sub);
} else {
_r = addsub_pixel(p->src_main);
}
} else {
_r = p->src_main;
}
} else if(p->bg_main) {
if(p->color_exempt == false && regs.color_enabled[p->bg_main & 0x7f] && window_cache[COL].sub[x]) {
_r = addsub_pixel(p->src_main);
} else {
_r = p->src_main;
}
} else if(p->bg_sub) {
if(regs.color_enabled[BACK]) {
if(window_cache[COL].sub[x]) {
if(regs.addsub_mode) {
_r = addsub_pixels(src_back, p->src_sub);
} else {
_r = addsub_pixel(src_back);
}
} else {
_r = src_back;
}
} else {
_r = src_back; //was 0x0000 -- possibly another condition here?
}
uint16 src_main, src_sub;
uint8 bg_sub;
src_main = p->src_main;
if(!regs.addsub_mode) {
bg_sub = BACK;
src_sub = regs.color_rgb;
} else {
if(window_cache[COL].main[x]) {
if(regs.color_enabled[BACK] && window_cache[COL].sub[x]) {
_r = addsub_pixel(src_back);
} else {
_r = src_back;
bg_sub = p->bg_sub;
src_sub = p->src_sub;
}
if(!window_cache[COL].main[x]) {
if(!window_cache[COL].sub[x]) {
return 0x0000;
}
src_main = 0x0000;
}
if(!p->ce_main && regs.color_enabled[p->bg_main] && window_cache[COL].sub[x]) {
bool halve = false;
if(regs.color_halve && window_cache[COL].main[x]) {
if(regs.addsub_mode && bg_sub == BACK);
else {
halve = true;
}
}
return addsub_pixels(x, src_main, src_sub, halve);
}
return src_main;
}
inline uint16 bPPU::get_pixel_swap(uint32 x) {
_pixel *p = &pixel_cache[x];
uint16 src_main, src_sub;
uint8 bg_sub;
src_main = p->src_sub;
if(!regs.addsub_mode) {
bg_sub = BACK;
src_sub = regs.color_rgb;
} else {
bg_sub = p->bg_main;
src_sub = p->src_main;
}
if(!window_cache[COL].main[x]) {
if(!window_cache[COL].sub[x]) {
return 0x0000;
}
src_main = 0x0000;
}
if(!p->ce_sub && regs.color_enabled[p->bg_sub] && window_cache[COL].sub[x]) {
bool halve = false;
if(regs.color_halve && window_cache[COL].main[x]) {
if(regs.addsub_mode && bg_sub == BACK);
else {
halve = true;
}
} else {
_r = 0x0000;
}
return addsub_pixels(x, src_main, src_sub, halve);
}
return src_main;
}
inline uint16 bPPU::get_pixel_lores(uint32 x) {
return get_pixel_normal(x);
}
inline uint16 bPPU::get_pixel_hires(uint32 x) {
if(x & 1) {
return get_pixel_normal(x >> 1);
} else {
return get_pixel_swap(x >> 1);
}
return _r;
}
inline void bPPU::render_line_output() {
int x;
uint16 _r;
uint16 *ptr;
ptr = (uint16*)snes->get_ppu_output_handle();
uint32 r, x;
uint16 *ptr = (uint16*)output + (line.y * 1024) +
((line.interlace && line.interlace_field) ? 512 : 0);
uint16 *ltable = (uint16*)light_table + (regs.display_brightness << 15);
uint16 *ltable;
ltable = (uint16*)light_table + (regs.display_brightness << 15);
if(_screen_width == 256) {
if(!regs.pseudo_hires && !regs.hires) {
for(x=0;x<256;x++) {
_r = get_pixel(x);
*ptr++ = *(ltable + _r);
r = get_pixel_lores(x);
*ptr++ = *(ltable + r);
}
} else {
for(x=0;x<512;x++) {
_r = get_pixel(x);
*ptr++ = *(ltable + _r);
r = get_pixel_hires(x);
*ptr++ = *(ltable + r);
}
if(regs.pseudo_hires && !regs.hires) {
ptr -= 512;
for(x=0;x<256;x++) {
*(ptr + x) = ((ptr[x << 1] & 0x7bde) >> 1) + ((ptr[(x << 1) + 1] & 0x7bde) >> 1);
}
}
}
}
+28 -23
View File
@@ -17,6 +17,12 @@
void bPPU::render_line_mode7(uint8 bg, uint8 pri0_pos, uint8 pri1_pos) {
if(regs.bg_enabled[bg] == false && regs.bgsub_enabled[bg] == false)return;
//are layers disabled by user?
if(render_enabled(bg, 0) == false)pri0_pos = 0;
if(render_enabled(bg, 1) == false)pri1_pos = 0;
//nothing to render?
if(!pri0_pos && !pri1_pos);
int32 x, y;
int32 a, b, c, d, cx, cy;
int32 hofs, vofs;
@@ -43,9 +49,9 @@ uint8 *wt_main = window_cache[bg].main;
uint8 *wt_sub = window_cache[bg].sub;
if(regs.mode7_vflip == true) {
y = 255 - _y;
y = 255 - line.y;
} else {
y = _y;
y = line.y;
}
uint16 *mtable_x, *mtable_y;
@@ -120,29 +126,28 @@ int32 psy = ((c * CLIP(hofs - cx)) & ~63) + ((d * CLIP(vofs - cy)) & ~63) + ((d
_x = x;
}
if(window_cache[COL].main[_x]) {
uint32 col;
if(regs.direct_color == true && bg == BG1) {
//direct color mode does not apply to bg2, as it is only 128 colors...
col = get_direct_color(0, palette);
} else {
col = get_palette(palette);
}
uint32 col;
if(regs.direct_color == true && bg == BG1) {
//direct color mode does not apply to bg2, as it is only 128 colors...
col = get_direct_color(0, palette);
} else {
col = get_palette(palette);
}
if(regs.bg_enabled[bg] == true && !wt_main[_x]) {
if(pixel_cache[_x].pri_main < _pri) {
pixel_cache[_x].pri_main = _pri;
pixel_cache[_x].bg_main = 0x80 | bg;
pixel_cache[_x].src_main = col;
pixel_cache[_x].color_exempt = false;
}
if(regs.bg_enabled[bg] == true && !wt_main[_x]) {
if(pixel_cache[_x].pri_main < _pri) {
pixel_cache[_x].pri_main = _pri;
pixel_cache[_x].bg_main = bg;
pixel_cache[_x].src_main = col;
pixel_cache[_x].ce_main = false;
}
if(regs.bgsub_enabled[bg] == true && !wt_sub[_x]) {
if(pixel_cache[_x].pri_sub < _pri) {
pixel_cache[_x].pri_sub = _pri;
pixel_cache[_x].bg_sub = 0x80 | bg;
pixel_cache[_x].src_sub = col;
}
}
if(regs.bgsub_enabled[bg] == true && !wt_sub[_x]) {
if(pixel_cache[_x].pri_sub < _pri) {
pixel_cache[_x].pri_sub = _pri;
pixel_cache[_x].bg_sub = bg;
pixel_cache[_x].src_sub = col;
pixel_cache[_x].ce_sub = false;
}
}
}
+83 -82
View File
@@ -63,10 +63,10 @@ uint16 width, height;
addr &= 0x001f;
z = oam[0x0200 + addr];
i = addr << 2;
sprite_list[i ].x = ((z & 0x01)?0x0100:0x0000) + (sprite_list[i ].x & 0xff);
sprite_list[i + 1].x = ((z & 0x04)?0x0100:0x0000) + (sprite_list[i + 1].x & 0xff);
sprite_list[i + 2].x = ((z & 0x10)?0x0100:0x0000) + (sprite_list[i + 2].x & 0xff);
sprite_list[i + 3].x = ((z & 0x40)?0x0100:0x0000) + (sprite_list[i + 3].x & 0xff);
sprite_list[i ].x = ((z & 0x01) ? 256 : 0) + (sprite_list[i ].x & 255);
sprite_list[i + 1].x = ((z & 0x04) ? 256 : 0) + (sprite_list[i + 1].x & 255);
sprite_list[i + 2].x = ((z & 0x10) ? 256 : 0) + (sprite_list[i + 2].x & 255);
sprite_list[i + 3].x = ((z & 0x40) ? 256 : 0) + (sprite_list[i + 3].x & 255);
get_sprite_size(i, !!(z & 0x02));
get_sprite_size(i + 1, !!(z & 0x08));
get_sprite_size(i + 2, !!(z & 0x20));
@@ -90,18 +90,18 @@ uint16 addr = 0x0200;
bool bPPU::is_sprite_on_scanline() {
//if sprite is entirely offscreen and doesn't wrap around to the left side of the screen,
//then it is not counted. 256 is correct, and not 255 -- as one might first expect
if(spr->x > 256 && (spr->x + spr->width) < 512 && _screen_width != 512)return false;
if(spr->x > 256 && (spr->x + spr->width) < 512)return false;
if(regs.oam_halve == false) {
if(_y >= spr->y && _y < (spr->y + spr->height)) {
if(line.y >= spr->y && line.y < (spr->y + spr->height)) {
return true;
} else if((spr->y + spr->height) >= 256 && _y < ((spr->y + spr->height) & 255)) {
} else if((spr->y + spr->height) >= 256 && line.y < ((spr->y + spr->height) & 255)) {
return true;
}
} else {
if(_y >= spr->y && _y < (spr->y + (spr->height >> 1))) {
if(line.y >= spr->y && line.y < (spr->y + (spr->height >> 1))) {
return true;
} else if((spr->y + (spr->height >> 1)) >= 256 && _y < ((spr->y + (spr->height >> 1)) & 255)) {
} else if((spr->y + (spr->height >> 1)) >= 256 && line.y < ((spr->y + (spr->height >> 1)) & 255)) {
return true;
}
}
@@ -110,62 +110,53 @@ bool bPPU::is_sprite_on_scanline() {
}
void bPPU::load_oam_tiles() {
uint16 tile_width;
tile_width = spr->width >> 3;
uint16 tile_width = spr->width >> 3;
int x = spr->x;
int y = (spr->vflip) ? ((spr->height - 1) - (line.y - spr->y)) : (line.y - spr->y);
int x, y, chr, nameselect_index;
x = spr->x;
if(_screen_width == 512)x <<= 1;
x &= 511;
if(spr->vflip) {
y = ((spr->height - 1) - (_y - spr->y));
} else {
y = (_y - spr->y);
}
//todo: double-check code below. seems that interlace_field
//should be added to hires 512x448 sprites as well, and not
//just when oam_halve is enabled...
if(regs.oam_halve == true) {
y <<= 1;
if(_interlace == true && _screen_width == 512) {
y += _interlace_field;
if(line.interlace && line.width == 512) {
y += line.interlace_field;
}
}
x &= 511;
y &= 255;
chr = spr->character;
uint16 tdaddr = regs.oam_tdaddr;
uint16 chrx = (spr->character ) & 15;
uint16 chry = (spr->character >> 4) & 15;
if(spr->use_nameselect == true) {
chr += 256;
nameselect_index = regs.oam_nameselect << 13;
} else {
nameselect_index = 0x0000;
tdaddr += (256 * 32) + (regs.oam_nameselect << 13);
}
chr += (y >> 3) << 4;
chry += (y >> 3);
chry &= 15;
chry <<= 4;
int i, n, mx, pos, z;
int i, n, sx, mx, pos;
for(i=0;i<tile_width;i++) {
z = x;
z += (i << ((_screen_width == 512)?4:3));
z &= 511;
sx = x;
sx += i << 3;
sx &= 511;
//ignore sprites that are offscreen
//sprites at 256 are still counted, even though they aren't visible onscreen
if(z >= 257 && (z + 7) < 512 && _screen_width != 512)continue;
if(sx >= 257 && (sx + 7) < 512)continue;
if(regs.oam_tilecount++ > 34)break;
n = regs.oam_tilecount - 1;
oam_tilelist[n].x = z;
oam_tilelist[n].x = sx;
oam_tilelist[n].y = y;
oam_tilelist[n].pri = spr->priority;
oam_tilelist[n].pal = (spr->palette << 4) + 128;
oam_tilelist[n].hflip = spr->hflip;
if(oam_tilelist[n].hflip) {
mx = (tile_width - 1) - i;
} else {
mx = i;
}
pos = regs.oam_tdaddr + ((chr + mx) << 5) + ((y & 7) << 1) + nameselect_index;
mx = (oam_tilelist[n].hflip) ? ((tile_width - 1) - i) : i;
pos = tdaddr + ((chry + ((chrx + mx) & 15)) << 5);
oam_tilelist[n].tile = (pos >> 5) & 0x07ff;
}
}
@@ -182,38 +173,26 @@ oam_tileitem *t = &oam_tilelist[tile_num];
int x, sx, col;
sx = t->x;
//tile_ptr = tiledata + (tile * (8_width * 8_height)) + ((y & 7_height_mask) * 8_width);
tile_ptr = (uint8*)oam_td + (t->tile << 6) + ((t->y & 7) << 3);
for(x=0;x<8;x++) {
sx &= 511;
if(sx < _screen_width) {
col = *(tile_ptr + ((t->hflip)?7-x:x));
if(sx < 256) {
col = *(tile_ptr + ((t->hflip) ? (7 - x) : x));
if(col) {
col += t->pal;
oam_line_pal[sx] = col;
oam_line_pri[sx] = t->pri;
if(_screen_width == 512) {
oam_line_pal[sx + 1] = col;
oam_line_pri[sx + 1] = t->pri;
}
}
}
sx += (_screen_width == 512)?2:1;
sx++;
}
}
void bPPU::render_line_oam(uint8 pri0_pos, uint8 pri1_pos, uint8 pri2_pos, uint8 pri3_pos) {
int s, x;
bool _bg_enabled = regs.bg_enabled[OAM];
bool _bgsub_enabled = regs.bgsub_enabled[OAM];
build_window_tables(OAM);
uint8 *wt_main = window_cache[OAM].main;
uint8 *wt_sub = window_cache[OAM].sub;
int s;
regs.oam_itemcount = 0;
regs.oam_tilecount = 0;
memset(oam_line_pri, OAM_PRI_NONE, 512);
memset(oam_line_pri, OAM_PRI_NONE, 256);
memset(oam_itemlist, 0xff, 32);
for(s=0;s<128;s++) {
@@ -239,35 +218,57 @@ uint8 *wt_sub = window_cache[OAM].sub;
regs.time_over |= (regs.oam_tilecount > 34);
regs.range_over |= (regs.oam_itemcount > 32);
if(_bg_enabled == false && _bgsub_enabled == false)return;
if(regs.bg_enabled[OAM] == false && regs.bgsub_enabled[OAM] == false)return;
int _pri;
for(x=0;x<_screen_width;x++) {
//are layers disabled by user?
if(render_enabled(OAM, 0) == false)pri0_pos = 0;
if(render_enabled(OAM, 1) == false)pri1_pos = 0;
if(render_enabled(OAM, 2) == false)pri2_pos = 0;
if(render_enabled(OAM, 3) == false)pri3_pos = 0;
//nothing to render?
if(!pri0_pos && !pri1_pos && !pri2_pos && !pri3_pos)return;
render_line_oam_lores(pri0_pos, pri1_pos, pri2_pos, pri3_pos);
}
#define setpixel_main(x) \
if(pixel_cache[x].pri_main < pri) { \
pixel_cache[x].pri_main = pri; \
pixel_cache[x].bg_main = OAM; \
pixel_cache[x].src_main = get_palette(oam_line_pal[x]); \
pixel_cache[x].ce_main = (oam_line_pal[x] < 192); \
}
#define setpixel_sub(x) \
if(pixel_cache[x].pri_sub < pri) { \
pixel_cache[x].pri_sub = pri; \
pixel_cache[x].bg_sub = OAM; \
pixel_cache[x].src_sub = get_palette(oam_line_pal[x]); \
pixel_cache[x].ce_sub = (oam_line_pal[x] < 192); \
}
void bPPU::render_line_oam_lores(uint8 pri0_pos, uint8 pri1_pos, uint8 pri2_pos, uint8 pri3_pos) {
bool bg_enabled = regs.bg_enabled[OAM];
bool bgsub_enabled = regs.bgsub_enabled[OAM];
build_window_tables(OAM);
uint8 *wt_main = window_cache[OAM].main;
uint8 *wt_sub = window_cache[OAM].sub;
int pri;
for(int x=0;x<256;x++) {
if(oam_line_pri[x] == OAM_PRI_NONE)continue;
switch(oam_line_pri[x]) {
case 0:_pri = pri0_pos;break;
case 1:_pri = pri1_pos;break;
case 2:_pri = pri2_pos;break;
case 3:_pri = pri3_pos;break;
case 0:pri = pri0_pos;break;
case 1:pri = pri1_pos;break;
case 2:pri = pri2_pos;break;
case 3:pri = pri3_pos;break;
}
if(window_cache[COL].main[x]) {
if(_bg_enabled == true && !wt_main[x]) {
if(pixel_cache[x].pri_main < _pri) {
pixel_cache[x].pri_main = _pri;
pixel_cache[x].bg_main = PC_OAM;
pixel_cache[x].src_main = get_palette(oam_line_pal[x]);
pixel_cache[x].color_exempt = (oam_line_pal[x] < 192);
}
}
if(_bgsub_enabled == true && !wt_sub[x]) {
if(pixel_cache[x].pri_sub < _pri) {
pixel_cache[x].pri_sub = _pri;
pixel_cache[x].bg_sub = PC_OAM;
pixel_cache[x].src_sub = get_palette(oam_line_pal[x]);
}
}
}
if(bg_enabled == true && !wt_main[x]) { setpixel_main(x); }
if(bgsub_enabled == true && !wt_sub[x]) { setpixel_sub(x); }
}
}
#undef setpixel_main
#undef setpixel_sub
+10 -17
View File
@@ -9,11 +9,11 @@ uint8 *wtbl;
if(bg != COL) {
if(mainscreen == true && regs.window_enabled[bg] == false) {
memset(wtbl, 0, _screen_width);
memset(wtbl, 0, 256);
return;
}
if(mainscreen == false && regs.sub_window_enabled[bg] == false) {
memset(wtbl, 0, _screen_width);
memset(wtbl, 0, 256);
return;
}
} else {
@@ -26,13 +26,13 @@ uint8 *wtbl;
if(mask == 0) {
//always
memset(wtbl, 1, _screen_width);
memset(wtbl, 1, 256);
return;
}
if(mask == 3) {
//never
memset(wtbl, 0, _screen_width);
memset(wtbl, 0, 256);
return;
}
@@ -56,37 +56,30 @@ bool r;
window2_left = regs.window2_left;
window2_right = regs.window2_right;
if(_screen_width == 512) {
window1_left <<= 1;
window1_right <<= 1;
window2_left <<= 1;
window2_right <<= 1;
}
if(regs.window1_enabled[bg] == false && regs.window2_enabled[bg] == false) {
memset(wtbl, clr, _screen_width);
memset(wtbl, clr, 256);
} else if(regs.window1_enabled[bg] == true && regs.window2_enabled[bg] == false) {
if(regs.window1_invert[bg] == false) {
for(x=0;x<_screen_width;x++) {
for(x = 0; x < 256; x++) {
wtbl[x] = (x >= window1_left && x <= window1_right) ? set : clr;
}
} else {
for(x=0;x<_screen_width;x++) {
for(x = 0; x < 256; x++) {
wtbl[x] = (x < window1_left || x > window1_right) ? set : clr;
}
}
} else if(regs.window1_enabled[bg] == false && regs.window2_enabled[bg] == true) {
if(regs.window2_invert[bg] == false) {
for(x=0;x<_screen_width;x++) {
for(x = 0; x < 256; x++) {
wtbl[x] = (x >= window2_left && x <= window2_right) ? set : clr;
}
} else {
for(x=0;x<_screen_width;x++) {
for(x = 0; x < 256; x++) {
wtbl[x] = (x < window2_left || x > window2_right) ? set : clr;
}
}
} else { //if(regs.window1_enabled[bg] == true && regs.window2_enabled[bg] == true) {
for(x=0;x<_screen_width;x++) {
for(x = 0; x < 256; x++) {
if(regs.window1_invert[bg] == false) {
w1_mask = (x >= window1_left && x <= window1_right);
} else {
+16 -3
View File
@@ -2,14 +2,16 @@
void PPU::get_scanline_info(scanline_info *info) {
info->hires = scanline_is_hires();
info->interlace = cpu->interlace();
info->interlace = r_cpu->interlace();
}
void PPU::enable_renderer(bool r) { status.render_output = r; }
bool PPU::renderer_enabled() { return status.render_output; }
void PPU::frame() {
static fr = 0, fe = 0;
status.frame_executed = true;
static int32 fr = 0, fe = 0;
static time_t prev, curr;
fe++;
if(status.render_output)fr++;
@@ -24,7 +26,16 @@ static time_t prev, curr;
prev = curr;
}
void PPU::power() {}
void PPU::reset() {
memset(output, 0, 512 * 480 * sizeof(uint16));
}
PPU::PPU() {
output = (uint16*)malloc(512 * 480 * sizeof(uint16));
memset(output, 0, 512 * 480 * sizeof(uint16));
status.render_output = true;
status.frames_updated = false;
status.frames_rendered = 0;
@@ -35,4 +46,6 @@ PPU::PPU() {
mmio = &mmio_unmapped;
}
PPU::~PPU() {}
PPU::~PPU() {
zerofree(output);
}
+5 -4
View File
@@ -1,11 +1,13 @@
class PPU {
public:
uint16 *output;
//this struct should be read-only to
//functions outside of this class
struct {
bool render_output;
bool frame_executed;
bool frames_updated;
uint32 frames_rendered;
uint32 frames_executed;
@@ -21,7 +23,6 @@ uint8 ppu1_version;
//* reported by $213f
uint8 ppu2_version;
int _y;
MMIO *mmio;
struct scanline_info {
@@ -44,11 +45,11 @@ struct scanline_info {
virtual void scanline() = 0;
virtual void render_scanline() = 0;
virtual void frame();
virtual void power() = 0;
virtual void reset() = 0;
virtual void power();
virtual void reset();
virtual void enable_renderer(bool r);
virtual bool renderer_enabled();
PPU();
~PPU();
virtual ~PPU();
};
+2 -2
View File
@@ -6,7 +6,7 @@ uint32 FileReader::size() {
//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.
void FileReader::read(uint8 **buffer, uint32 length) {
uint8 *FileReader::read(uint32 length) {
uint8 *data;
if(length == 0) {
//read the entire file into RAM
@@ -24,7 +24,7 @@ uint8 *data;
memset(data, 0, length);
if(fp)fread(data, 1, length, fp);
}
*buffer = data;
return data;
}
bool FileReader::open(char *fn) {
+1 -1
View File
@@ -5,7 +5,7 @@ uint32 fsize;
public:
uint32 size();
void read(uint8 **buffer, uint32 length = 0);
uint8 *read(uint32 length = 0);
bool open(char *fn);
void close();
+76
View File
@@ -0,0 +1,76 @@
uint32 GZReader::size() {
return fsize;
}
//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 *GZReader::read(uint32 length) {
uint8 *data;
if(length == 0) {
//read the entire file into RAM
data = (uint8*)memalloc(fsize);
memset(data, 0, fsize);
if(gp)gzread(gp, data, fsize);
} else if(length > fsize) {
//read the entire file into RAM, pad the rest with 0x00s
data = (uint8*)memalloc(length);
memset(data, 0, length);
if(gp)gzread(gp, data, fsize);
} else { //fsize >= length
//read only what was requested
data = (uint8*)memalloc(length);
memset(data, 0, length);
if(gp)gzread(gp, data, length);
}
return data;
}
bool GZReader::open(char *fn) {
FILE *fp;
fp = fopen(fn, "rb");
if(!fp)return false;
fseek(fp, 0, SEEK_END);
fsize = ftell(fp);
if(fsize < 4) {
fclose(fp);
fp = 0;
return false;
}
uint32 gzsize;
fseek(fp, -4, SEEK_END); //jump to 4 bytes before end
gzsize = fgetc(fp);
gzsize |= fgetc(fp) << 8;
gzsize |= fgetc(fp) << 16;
gzsize |= fgetc(fp) << 24;
fclose(fp);
fp = 0;
gp = gzopen(fn, "rb");
if(!gp)return false;
if(!gzdirect(gp)) {
fsize = gzsize;
}
//empty file?
if(fsize == 0) {
gzclose(gp);
gp = 0;
return false;
}
return true;
}
void GZReader::close() {
if(gp) {
gzclose(gp);
gp = 0;
}
}
+16
View File
@@ -0,0 +1,16 @@
#include "zlib/zlib.h"
class GZReader : public Reader {
private:
gzFile gp;
uint32 fsize;
public:
uint32 size();
uint8 *read(uint32 length = 0);
bool open(char *fn);
void close();
GZReader() { gp = 0; fsize = 0; }
~GZReader() { if(gp)gzclose(gp); }
};
+29
View File
@@ -0,0 +1,29 @@
/*
Copyright (C) 2005 NSRT Team ( http://nsrt.edgeemu.com )
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __7Z_H
#define __7Z_H
#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
+51
View File
@@ -0,0 +1,51 @@
/*
Copyright (C) 2005 NSRT Team ( http://nsrt.edgeemu.com )
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#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));
}
+73
View File
@@ -0,0 +1,73 @@
#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
+30
View File
@@ -0,0 +1,30 @@
/*
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org )
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __ARICONST_H
#define __ARICONST_H
#include "aribitcd.h"
typedef NCompression::NArithmetic::CRangeDecoder CMyRangeDecoder;
template <int aNumMoveBits> class CMyBitDecoder:
public NCompression::NArithmetic::CBitDecoder<aNumMoveBits> {};
#endif
+12
View File
@@ -0,0 +1,12 @@
#ifndef __COMPRESSION_ARIPRICE_H
#define __COMPRESSION_ARIPRICE_H
namespace NCompression {
namespace NArithmetic {
const UINT32 kNumBitPriceShiftBits = 6;
const UINT32 kBitPrice = 1 << kNumBitPriceShiftBits;
}}
#endif
+127
View File
@@ -0,0 +1,127 @@
/*
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org )
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __BITTREECODER_H
#define __BITTREECODER_H
#include "aribitcd.h"
#include "rcdefs.h"
//////////////////////////
// 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
+29
View File
@@ -0,0 +1,29 @@
/*
Copyright (C) 2004 NSRT Team ( http://nsrt.edgeemu.com )
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef CRC32_H
#define CRC32_H
namespace CRC32lib
{
unsigned int CRC32(const unsigned char *, size_t, register unsigned int crc32 = 0xFFFFFFFF);
unsigned short SUM_CRC32(const unsigned char *, size_t, unsigned int &crc32);
}
#endif
+133
View File
@@ -0,0 +1,133 @@
/*
Copyright (C) 2005 NSRT Team ( http://nsrt.edgeemu.com )
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org )
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "portable.h"
#include "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);
}
+211
View File
@@ -0,0 +1,211 @@
/*
Copyright (C) 2005 NSRT Team ( http://nsrt.edgeemu.com )
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org )
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#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
+61
View File
@@ -0,0 +1,61 @@
/*
Copyright (C) 2005 NSRT Team ( http://nsrt.edgeemu.com )
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org )
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "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);
}
}
+77
View File
@@ -0,0 +1,77 @@
/*
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org )
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __STREAM_INBYTE_H
#define __STREAM_INBYTE_H
#include "iiostrm.h"
namespace NStream {
class CInByte
{
UINT64 m_ProcessedSize;
BYTE *m_BufferBase;
UINT32 m_BufferSize;
BYTE *m_Buffer;
BYTE *m_BufferLimit;
ISequentialInStream* m_Stream;
bool m_StreamWasExhausted;
bool ReadBlock();
public:
CInByte(UINT32 aBufferSize = 0x100000);
~CInByte();
void Init(ISequentialInStream *aStream);
bool ReadByte(BYTE &aByte)
{
if(m_Buffer >= m_BufferLimit)
if(!ReadBlock())
return false;
aByte = *m_Buffer++;
return true;
}
BYTE ReadByte()
{
if(m_Buffer >= m_BufferLimit)
if(!ReadBlock())
return 0x0;
return *m_Buffer++;
}
void ReadBytes(void *aData, UINT32 aSize, UINT32 &aProcessedSize)
{
for(aProcessedSize = 0; aProcessedSize < aSize; aProcessedSize++)
if (!ReadByte(((BYTE *)aData)[aProcessedSize]))
return;
}
bool ReadBytes(void *aData, UINT32 aSize)
{
UINT32 aProcessedSize;
ReadBytes(aData, aSize, aProcessedSize);
return (aProcessedSize == aSize);
}
UINT64 GetProcessedSize() const { return m_ProcessedSize + (m_Buffer - m_BufferBase); }
};
}
#endif
+82
View File
@@ -0,0 +1,82 @@
/*
Copyright (C) 2004 NSRT Team ( http://nsrt.edgeemu.com )
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <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);
}
}
+552
View File
@@ -0,0 +1,552 @@
/*
Copyright (C) 2005 NSRT Team ( http://nsrt.edgeemu.com )
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <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");
}
}
+90
View File
@@ -0,0 +1,90 @@
/*
Copyright (C) 2005 NSRT Team ( http://nsrt.edgeemu.com )
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef JMA_H
#define JMA_H
#include <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
+94
View File
@@ -0,0 +1,94 @@
/*
Copyright (C) 2005 NSRT Team ( http://nsrt.edgeemu.com )
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org )
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#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
+123
View File
@@ -0,0 +1,123 @@
/*
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org )
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __LITERALCODER_H
#define __LITERALCODER_H
#include "aribitcd.h"
#include "rcdefs.h"
namespace NLiteral {
const int kNumMoveBits = 5;
class CDecoder2
{
CMyBitDecoder<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
+42
View File
@@ -0,0 +1,42 @@
/*
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org )
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "lzma.h"
namespace NCompress {
namespace NLZMA {
UINT32 kDistStart[kDistTableSizeMax];
static class CConstInit
{
public:
CConstInit()
{
UINT32 aStartValue = 0;
int i;
for (i = 0; i < kDistTableSizeMax; i++)
{
kDistStart[i] = aStartValue;
aStartValue += (1 << kDistDirectBits[i]);
}
}
} g_ConstInit;
}}
+125
View File
@@ -0,0 +1,125 @@
/*
Copyright (C) 2005 NSRT Team ( http://nsrt.edgeemu.com )
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org )
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "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
+299
View File
@@ -0,0 +1,299 @@
/*
Copyright (C) 2005 NSRT Team ( http://nsrt.edgeemu.com )
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org )
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "portable.h"
#include "lzmadec.h"
#define RETURN_E_OUTOFMEMORY_IF_FALSE(x) { if (!(x)) return E_OUTOFMEMORY; }
namespace NCompress {
namespace NLZMA {
HRESULT CDecoder::SetDictionarySize(UINT32 aDictionarySize)
{
if (aDictionarySize > (1 << kDicLogSizeMax))
return E_INVALIDARG;
UINT32 aWindowReservSize = MyMax(aDictionarySize, UINT32(1 << 21));
if (m_DictionarySize != aDictionarySize)
{
m_OutWindowStream.Create(aDictionarySize, kMatchMaxLen, aWindowReservSize);
m_DictionarySize = aDictionarySize;
}
return S_OK;
}
HRESULT CDecoder::SetLiteralProperties(
UINT32 aLiteralPosStateBits, UINT32 aLiteralContextBits)
{
if (aLiteralPosStateBits > 8)
return E_INVALIDARG;
if (aLiteralContextBits > 8)
return E_INVALIDARG;
m_LiteralDecoder.Create(aLiteralPosStateBits, aLiteralContextBits);
return S_OK;
}
HRESULT CDecoder::SetPosBitsProperties(UINT32 aNumPosStateBits)
{
if (aNumPosStateBits > NLength::kNumPosStatesBitsMax)
return E_INVALIDARG;
UINT32 aNumPosStates = 1 << aNumPosStateBits;
m_LenDecoder.Create(aNumPosStates);
m_RepMatchLenDecoder.Create(aNumPosStates);
m_PosStateMask = aNumPosStates - 1;
return S_OK;
}
CDecoder::CDecoder():
m_DictionarySize((UINT32)-1)
{
Create();
}
HRESULT CDecoder::Create()
{
for(int i = 0; i < kNumPosModels; i++)
{
RETURN_E_OUTOFMEMORY_IF_FALSE(
m_PosDecoders[i].Create(kDistDirectBits[kStartPosModelIndex + i]));
}
return S_OK;
}
HRESULT CDecoder::Init(ISequentialInStream *anInStream,
ISequentialOutStream *anOutStream)
{
m_RangeDecoder.Init(anInStream);
m_OutWindowStream.Init(anOutStream);
int i;
for(i = 0; i < kNumStates; i++)
{
for (UINT32 j = 0; j <= m_PosStateMask; j++)
{
m_MainChoiceDecoders[i][j].Init();
m_MatchRepShortChoiceDecoders[i][j].Init();
}
m_MatchChoiceDecoders[i].Init();
m_MatchRepChoiceDecoders[i].Init();
m_MatchRep1ChoiceDecoders[i].Init();
m_MatchRep2ChoiceDecoders[i].Init();
}
m_LiteralDecoder.Init();
// m_RepMatchLenDecoder.Init();
for (i = 0; (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;
}
}}
+83
View File
@@ -0,0 +1,83 @@
/*
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org )
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __LZARITHMETIC_DECODER_H
#define __LZARITHMETIC_DECODER_H
#include "winout.h"
#include "lzma.h"
#include "lencoder.h"
#include "litcoder.h"
namespace NCompress {
namespace NLZMA {
typedef CMyBitDecoder<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
+85
View File
@@ -0,0 +1,85 @@
/*
Copyright (C) 2004 NSRT Team ( http://nsrt.edgeemu.com )
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#ifndef __PORTABLE_H
#define __PORTABLE_H
#include <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
+61
View File
@@ -0,0 +1,61 @@
/*
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org )
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __RCDEFS_H
#define __RCDEFS_H
#include "aribitcd.h"
#include "ariconst.h"
#define RC_INIT_VAR \
UINT32 aRange = aRangeDecoder->m_Range; \
UINT32 aCode = aRangeDecoder->m_Code;
#define RC_FLUSH_VAR \
aRangeDecoder->m_Range = aRange; \
aRangeDecoder->m_Code = aCode;
#define RC_NORMALIZE \
if (aRange < NCompression::NArithmetic::kTopValue) \
{ \
aCode = (aCode << 8) | aRangeDecoder->m_Stream.ReadByte(); \
aRange <<= 8; }
#define RC_GETBIT2(aNumMoveBits, aProb, aModelIndex, Action0, Action1) \
{UINT32 aNewBound = (aRange >> NCompression::NArithmetic::kNumBitModelTotalBits) * aProb; \
if (aCode < aNewBound) \
{ \
Action0; \
aRange = aNewBound; \
aProb += (NCompression::NArithmetic::kBitModelTotal - aProb) >> aNumMoveBits; \
aModelIndex <<= 1; \
} \
else \
{ \
Action1; \
aRange -= aNewBound; \
aCode -= aNewBound; \
aProb -= (aProb) >> aNumMoveBits; \
aModelIndex = (aModelIndex << 1) + 1; \
}} \
RC_NORMALIZE
#define RC_GETBIT(aNumMoveBits, aProb, aModelIndex) RC_GETBIT2(aNumMoveBits, aProb, aModelIndex, ; , ;)
#endif
+144
View File
@@ -0,0 +1,144 @@
/*
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org )
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __COMPRESSION_RANGECODER_H
#define __COMPRESSION_RANGECODER_H
#include "inbyte.h"
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
+90
View File
@@ -0,0 +1,90 @@
/*
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org )
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "winout.h"
namespace NStream {
namespace NWindow {
void COut::Create(UINT32 aKeepSizeBefore, UINT32 aKeepSizeAfter, UINT32 aKeepSizeReserv)
{
m_Pos = 0;
m_PosLimit = aKeepSizeReserv + aKeepSizeBefore;
m_KeepSizeBefore = aKeepSizeBefore;
m_KeepSizeAfter = aKeepSizeAfter;
m_KeepSizeReserv = aKeepSizeReserv;
m_StreamPos = 0;
m_MoveFrom = m_KeepSizeReserv;
m_WindowSize = aKeepSizeBefore;
UINT32 aBlockSize = m_KeepSizeBefore + m_KeepSizeAfter + m_KeepSizeReserv;
delete []m_Buffer;
m_Buffer = new BYTE[aBlockSize];
}
COut::~COut()
{
delete []m_Buffer;
}
void COut::SetWindowSize(UINT32 aWindowSize)
{
m_WindowSize = aWindowSize;
m_MoveFrom = m_KeepSizeReserv + m_KeepSizeBefore - aWindowSize;
}
void COut::Init(ISequentialOutStream *aStream, bool aSolid)
{
m_Stream = aStream;
if(aSolid)
m_StreamPos = m_Pos;
else
{
m_Pos = 0;
m_PosLimit = m_KeepSizeReserv + m_KeepSizeBefore;
m_StreamPos = 0;
}
}
HRESULT COut::Flush()
{
UINT32 aSize = m_Pos - m_StreamPos;
if(aSize == 0)
return S_OK;
UINT32 aProcessedSize;
HRESULT aResult = m_Stream->Write(m_Buffer + m_StreamPos, aSize, &aProcessedSize);
if (aResult != S_OK)
return aResult;
if (aSize != aProcessedSize)
return E_FAIL;
m_StreamPos = m_Pos;
return S_OK;
}
void COut::MoveBlockBackward()
{
HRESULT aResult = Flush();
if (aResult != S_OK)
throw aResult;
memmove(m_Buffer, m_Buffer + m_MoveFrom, m_WindowSize + m_KeepSizeAfter);
m_Pos -= m_MoveFrom;
m_StreamPos -= m_MoveFrom;
}
}}
+90
View File
@@ -0,0 +1,90 @@
/*
Copyright (C) 2002 Andrea Mazzoleni ( http://advancemame.sf.net )
Copyright (C) 2001-4 Igor Pavlov ( http://www.7-zip.org )
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __STREAM_WINDOWOUT_H
#define __STREAM_WINDOWOUT_H
#include "iiostrm.h"
namespace NStream {
namespace NWindow {
// m_KeepSizeBefore: how mach BYTEs must be in buffer before m_Pos;
// m_KeepSizeAfter: how mach BYTEs must be in buffer after m_Pos;
// m_KeepSizeReserv: how mach BYTEs must be in buffer for Moving Reserv;
// must be >= aKeepSizeAfter; // test it
class COut
{
BYTE *m_Buffer;
UINT32 m_Pos;
UINT32 m_PosLimit;
UINT32 m_KeepSizeBefore;
UINT32 m_KeepSizeAfter;
UINT32 m_KeepSizeReserv;
UINT32 m_StreamPos;
UINT32 m_WindowSize;
UINT32 m_MoveFrom;
ISequentialOutStream *m_Stream;
virtual void MoveBlockBackward();
public:
COut(): m_Buffer(0), m_Stream(0) {}
virtual ~COut();
void Create(UINT32 aKeepSizeBefore,
UINT32 aKeepSizeAfter, UINT32 aKeepSizeReserv = (1<<17));
void SetWindowSize(UINT32 aWindowSize);
void Init(ISequentialOutStream *aStream, bool aSolid = false);
HRESULT Flush();
UINT32 GetCurPos() const { return m_Pos; }
const BYTE *GetPointerToCurrentPos() const { return m_Buffer + m_Pos;};
void CopyBackBlock(UINT32 aDistance, UINT32 aLen)
{
if (m_Pos >= m_PosLimit)
MoveBlockBackward();
BYTE *p = m_Buffer + m_Pos;
aDistance++;
for(UINT32 i = 0; i < aLen; i++)
p[i] = p[i - aDistance];
m_Pos += aLen;
}
void PutOneByte(BYTE aByte)
{
if (m_Pos >= m_PosLimit)
MoveBlockBackward();
m_Buffer[m_Pos++] = aByte;
}
BYTE GetOneByte(UINT32 anIndex) const
{
return m_Buffer[m_Pos + anIndex];
}
BYTE *GetBuffer() const { return m_Buffer; }
};
}}
#endif
+43
View File
@@ -0,0 +1,43 @@
//created by Nach
//#include "jma/jma.h"
uint32 JMAReader::size() {
return fsize;
}
#define MAXROM 0x800000
uint8 *JMAReader::read(uint32 length)
{
uint8 *data;
if (!fsize) { return 0; }
if (length <= fsize)
{
//read the entire file into RAM
data = (uint8*)memalloc(fsize);
JMAFile.extract_file(cname, data);
}
else if (length > fsize)
{
//read the entire file into RAM, pad the rest with 0x00s
data = (uint8*)memalloc(length);
memset(data, 0, length);
JMAFile.extract_file(cname, data);
}
return data;
}
JMAReader::JMAReader(char *fn) : JMAFile(fn), fsize(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 <= MAXROM+512) && (i->size > fsize))
{
cname = i->name;
fsize = i->size;
}
}
}
+17
View File
@@ -0,0 +1,17 @@
//created by Nach
#include "jma/jma.h"
class JMAReader : public Reader {
private:
JMA::jma_open JMAFile;
uint32 fsize;
std::string cname;
public:
uint32 size();
uint8 *read(uint32 length = 0);
JMAReader(char *fn);
~JMAReader() { }
};
+20
View File
@@ -1,2 +1,22 @@
#include "../base.h"
#include "filereader.cpp"
#ifdef GZIP_SUPPORT
#include "gzreader.cpp"
#include "zipreader.cpp"
#endif
#ifdef JMA_SUPPORT
#include "jmareader.cpp"
#endif
uint32 Reader::detect(char *fn) {
int len = strlen(fn);
if(len >= 4 && !stricmp(fn + len - 3, ".gz")) {
return RF_GZ;
} else if(len >= 5 && !stricmp(fn + len - 4, ".zip")) {
return RF_ZIP;
} else if(len >= 5 && !stricmp(fn + len - 4, ".jma")) {
return RF_JMA;
} else {
return RF_NORMAL;
}
}
+18 -1
View File
@@ -1,7 +1,17 @@
class Reader {
public:
enum {
RF_NORMAL = 0,
RF_GZ = 1,
RF_ZIP = 2,
RF_JMA = 3
};
//attemps to determine filetype by extension,
//RF_NORMAL is returned on failure as a failsafe
static uint32 detect(char *fn);
virtual uint32 size() = 0;
virtual void read(uint8 **buffer, uint32 length = 0) = 0;
//return is 0 on failure, caller must deallocate memory manually
virtual uint8 *read(uint32 length = 0) = 0;
};
class Writer {
@@ -10,3 +20,10 @@ public:
};
#include "filereader.h"
#ifdef GZIP_SUPPORT
#include "gzreader.h"
#include "zipreader.h"
#endif
#ifdef JMA_SUPPORT
#include "jmareader.h"
#endif
+54
View File
@@ -0,0 +1,54 @@
//created by Nach
uint32 ZipReader::size() {
return fsize;
}
#define MAXROM 0x800000
uint8 *ZipReader::read(uint32 length)
{
uint8 *data;
if (!fsize) { return 0; }
if (length <= fsize)
{
//read the entire file into RAM
data = (uint8*)memalloc(fsize);
unzReadCurrentFile(zipfile, data, fsize);
}
else if (length > fsize)
{
//read the entire file into RAM, pad the rest with 0x00s
data = (uint8*)memalloc(length);
memset(data, 0, length);
unzReadCurrentFile(zipfile, data, fsize);
}
return data;
}
ZipReader::ZipReader(char *fn) : fsize(0)
{
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);
if ((cFileInfo.uncompressed_size <= MAXROM+512) && (cFileInfo.uncompressed_size > fsize))
{
strcpy(cname, cFileName);
fsize = cFileInfo.uncompressed_size;
}
}
if (fsize)
{
unzLocateFile(zipfile, cname, 1);
unzOpenCurrentFile(zipfile);
}
}
}
+27
View File
@@ -0,0 +1,27 @@
//created by Nach
#include "zlib/unzip.h"
//Could be up to 65536
#define ZIP_MAX_FILE_NAME 4096
class ZipReader : public Reader {
private:
unzFile zipfile;
uint32 fsize;
char cname[4096];
public:
uint32 size();
uint8 *read(uint32 length = 0);
ZipReader(char *fn);
~ZipReader()
{
if (zipfile)
{
unzCloseCurrentFile(zipfile);
unzClose(zipfile);
}
}
};
+149
View File
@@ -0,0 +1,149 @@
/* adler32.c -- compute the Adler-32 checksum of a data stream
* Copyright (C) 1995-2004 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* @(#) $Id: adler32.c,v 1.3 2005/07/27 18:15:11 nach Exp $ */
#define ZLIB_INTERNAL
#include "zlib.h"
#define BASE 65521UL /* largest prime smaller than 65536 */
#define NMAX 5552
/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;}
#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1);
#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2);
#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4);
#define DO16(buf) DO8(buf,0); DO8(buf,8);
/* use NO_DIVIDE if your processor does not do division in hardware */
#ifdef NO_DIVIDE
# define MOD(a) \
do { \
if (a >= (BASE << 16)) a -= (BASE << 16); \
if (a >= (BASE << 15)) a -= (BASE << 15); \
if (a >= (BASE << 14)) a -= (BASE << 14); \
if (a >= (BASE << 13)) a -= (BASE << 13); \
if (a >= (BASE << 12)) a -= (BASE << 12); \
if (a >= (BASE << 11)) a -= (BASE << 11); \
if (a >= (BASE << 10)) a -= (BASE << 10); \
if (a >= (BASE << 9)) a -= (BASE << 9); \
if (a >= (BASE << 8)) a -= (BASE << 8); \
if (a >= (BASE << 7)) a -= (BASE << 7); \
if (a >= (BASE << 6)) a -= (BASE << 6); \
if (a >= (BASE << 5)) a -= (BASE << 5); \
if (a >= (BASE << 4)) a -= (BASE << 4); \
if (a >= (BASE << 3)) a -= (BASE << 3); \
if (a >= (BASE << 2)) a -= (BASE << 2); \
if (a >= (BASE << 1)) a -= (BASE << 1); \
if (a >= BASE) a -= BASE; \
} while (0)
# define MOD4(a) \
do { \
if (a >= (BASE << 4)) a -= (BASE << 4); \
if (a >= (BASE << 3)) a -= (BASE << 3); \
if (a >= (BASE << 2)) a -= (BASE << 2); \
if (a >= (BASE << 1)) a -= (BASE << 1); \
if (a >= BASE) a -= BASE; \
} while (0)
#else
# define MOD(a) a %= BASE
# define MOD4(a) a %= BASE
#endif
/* ========================================================================= */
uLong ZEXPORT adler32(adler, buf, len)
uLong adler;
const Bytef *buf;
uInt len;
{
unsigned long sum2;
unsigned n;
/* split Adler-32 into component sums */
sum2 = (adler >> 16) & 0xffff;
adler &= 0xffff;
/* in case user likes doing a byte at a time, keep it fast */
if (len == 1) {
adler += buf[0];
if (adler >= BASE)
adler -= BASE;
sum2 += adler;
if (sum2 >= BASE)
sum2 -= BASE;
return adler | (sum2 << 16);
}
/* initial Adler-32 value (deferred check for len == 1 speed) */
if (buf == Z_NULL)
return 1L;
/* in case short lengths are provided, keep it somewhat fast */
if (len < 16) {
while (len--) {
adler += *buf++;
sum2 += adler;
}
if (adler >= BASE)
adler -= BASE;
MOD4(sum2); /* only added so many BASE's */
return adler | (sum2 << 16);
}
/* do length NMAX blocks -- requires just one modulo operation */
while (len >= NMAX) {
len -= NMAX;
n = NMAX / 16; /* NMAX is divisible by 16 */
do {
DO16(buf); /* 16 sums unrolled */
buf += 16;
} while (--n);
MOD(adler);
MOD(sum2);
}
/* do remaining bytes (less than NMAX, still just one modulo) */
if (len) { /* avoid modulos if none remaining */
while (len >= 16) {
len -= 16;
DO16(buf);
buf += 16;
}
while (len--) {
adler += *buf++;
sum2 += adler;
}
MOD(adler);
MOD(sum2);
}
/* return recombined sums */
return adler | (sum2 << 16);
}
/* ========================================================================= */
uLong ZEXPORT adler32_combine(adler1, adler2, len2)
uLong adler1;
uLong adler2;
z_off_t len2;
{
unsigned long sum1;
unsigned long sum2;
unsigned rem;
/* the derivation of this formula is left as an exercise for the reader */
rem = (unsigned)(len2 % BASE);
sum1 = adler1 & 0xffff;
sum2 = rem * sum1;
MOD(sum2);
sum1 += (adler2 & 0xffff) + BASE - 1;
sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem;
if (sum1 > BASE) sum1 -= BASE;
if (sum1 > BASE) sum1 -= BASE;
if (sum2 > (BASE << 1)) sum2 -= (BASE << 1);
if (sum2 > BASE) sum2 -= BASE;
return sum1 | (sum2 << 16);
}
+79
View File
@@ -0,0 +1,79 @@
/* compress.c -- compress a memory buffer
* Copyright (C) 1995-2003 Jean-loup Gailly.
* For conditions of distribution and use, see copyright notice in zlib.h
*/
/* @(#) $Id: compress.c,v 1.3 2005/07/27 18:15:11 nach Exp $ */
#define ZLIB_INTERNAL
#include "zlib.h"
/* ===========================================================================
Compresses the source buffer into the destination buffer. The level
parameter has the same meaning as in deflateInit. sourceLen is the byte
length of the source buffer. Upon entry, destLen is the total size of the
destination buffer, which must be at least 0.1% larger than sourceLen plus
12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
memory, Z_BUF_ERROR if there was not enough room in the output buffer,
Z_STREAM_ERROR if the level parameter is invalid.
*/
int ZEXPORT compress2 (dest, destLen, source, sourceLen, level)
Bytef *dest;
uLongf *destLen;
const Bytef *source;
uLong sourceLen;
int level;
{
z_stream stream;
int err;
stream.next_in = (Bytef*)source;
stream.avail_in = (uInt)sourceLen;
#ifdef MAXSEG_64K
/* Check for source > 64K on 16-bit machine: */
if ((uLong)stream.avail_in != sourceLen) return Z_BUF_ERROR;
#endif
stream.next_out = dest;
stream.avail_out = (uInt)*destLen;
if ((uLong)stream.avail_out != *destLen) return Z_BUF_ERROR;
stream.zalloc = (alloc_func)0;
stream.zfree = (free_func)0;
stream.opaque = (voidpf)0;
err = deflateInit(&stream, level);
if (err != Z_OK) return err;
err = deflate(&stream, Z_FINISH);
if (err != Z_STREAM_END) {
deflateEnd(&stream);
return err == Z_OK ? Z_BUF_ERROR : err;
}
*destLen = stream.total_out;
err = deflateEnd(&stream);
return err;
}
/* ===========================================================================
*/
int ZEXPORT compress (dest, destLen, source, sourceLen)
Bytef *dest;
uLongf *destLen;
const Bytef *source;
uLong sourceLen;
{
return compress2(dest, destLen, source, sourceLen, Z_DEFAULT_COMPRESSION);
}
/* ===========================================================================
If the default memLevel or windowBits for deflateInit() is changed, then
this function needs to be updated.
*/
uLong ZEXPORT compressBound (sourceLen)
uLong sourceLen;
{
return sourceLen + (sourceLen >> 12) + (sourceLen >> 14) + 11;
}
+423
View File
@@ -0,0 +1,423 @@
/* crc32.c -- compute the CRC-32 of a data stream
* Copyright (C) 1995-2005 Mark Adler
* For conditions of distribution and use, see copyright notice in zlib.h
*
* Thanks to Rodney Brown <[email protected]> for his contribution of faster
* CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing
* tables for updating the shift register in one step with three exclusive-ors
* instead of four steps with four exclusive-ors. This results in about a
* factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
*/
/* @(#) $Id: crc32.c,v 1.3 2005/07/27 18:15:11 nach Exp $ */
/*
Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
protection on the static variables used to control the first-use generation
of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should
first call get_crc_table() to initialize the tables before allowing more than
one thread to use crc32().
*/
#ifdef MAKECRCH
# include <stdio.h>
# ifndef DYNAMIC_CRC_TABLE
# define DYNAMIC_CRC_TABLE
# endif /* !DYNAMIC_CRC_TABLE */
#endif /* MAKECRCH */
#include "zutil.h" /* for STDC and FAR definitions */
#define local static
/* Find a four-byte integer type for crc32_little() and crc32_big(). */
#ifndef NOBYFOUR
# ifdef STDC /* need ANSI C limits.h to determine sizes */
# include <limits.h>
# define BYFOUR
# if (UINT_MAX == 0xffffffffUL)
typedef unsigned int u4;
# else
# if (ULONG_MAX == 0xffffffffUL)
typedef unsigned long u4;
# else
# if (USHRT_MAX == 0xffffffffUL)
typedef unsigned short u4;
# else
# undef BYFOUR /* can't find a four-byte integer type! */
# endif
# endif
# endif
# endif /* STDC */
#endif /* !NOBYFOUR */
/* Definitions for doing the crc four data bytes at a time. */
#ifdef BYFOUR
# define REV(w) (((w)>>24)+(((w)>>8)&0xff00)+ \
(((w)&0xff00)<<8)+(((w)&0xff)<<24))
local unsigned long crc32_little OF((unsigned long,
const unsigned char FAR *, unsigned));
local unsigned long crc32_big OF((unsigned long,
const unsigned char FAR *, unsigned));
# define TBLS 8
#else
# define TBLS 1
#endif /* BYFOUR */
/* Local functions for crc concatenation */
local unsigned long gf2_matrix_times OF((unsigned long *mat,
unsigned long vec));
local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat));
#ifdef DYNAMIC_CRC_TABLE
local volatile int crc_table_empty = 1;
local unsigned long FAR crc_table[TBLS][256];
local void make_crc_table OF((void));
#ifdef MAKECRCH
local void write_table OF((FILE *, const unsigned long FAR *));
#endif /* MAKECRCH */
/*
Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
Polynomials over GF(2) are represented in binary, one bit per coefficient,
with the lowest powers in the most significant bit. Then adding polynomials
is just exclusive-or, and multiplying a polynomial by x is a right shift by
one. If we call the above polynomial p, and represent a byte as the
polynomial q, also with the lowest power in the most significant bit (so the
byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
where a mod b means the remainder after dividing a by b.
This calculation is done using the shift-register method of multiplying and
taking the remainder. The register is initialized to zero, and for each
incoming bit, x^32 is added mod p to the register if the bit is a one (where
x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
x (which is shifting right by one and adding x^32 mod p if the bit shifted
out is a one). We start with the highest power (least significant bit) of
q and repeat for all eight bits of q.
The first table is simply the CRC of all possible eight bit values. This is
all the information needed to generate CRCs on data a byte at a time for all
combinations of CRC register values and incoming bytes. The remaining tables
allow for word-at-a-time CRC calculation for both big-endian and little-
endian machines, where a word is four bytes.
*/
local void make_crc_table()
{
unsigned long c;
int n, k;
unsigned long poly; /* polynomial exclusive-or pattern */
/* terms of polynomial defining this crc (except x^32): */
static volatile int first = 1; /* flag to limit concurrent making */
static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
/* See if another task is already doing this (not thread-safe, but better
than nothing -- significantly reduces duration of vulnerability in
case the advice about DYNAMIC_CRC_TABLE is ignored) */
if (first) {
first = 0;
/* make exclusive-or pattern from polynomial (0xedb88320UL) */
poly = 0UL;
for (n = 0; n < sizeof(p)/sizeof(unsigned char); n++)
poly |= 1UL << (31 - p[n]);
/* generate a crc for every 8-bit value */
for (n = 0; n < 256; n++) {
c = (unsigned long)n;
for (k = 0; k < 8; k++)
c = c & 1 ? poly ^ (c >> 1) : c >> 1;
crc_table[0][n] = c;
}
#ifdef BYFOUR
/* generate crc for each value followed by one, two, and three zeros,
and then the byte reversal of those as well as the first table */
for (n = 0; n < 256; n++) {
c = crc_table[0][n];
crc_table[4][n] = REV(c);
for (k = 1; k < 4; k++) {
c = crc_table[0][c & 0xff] ^ (c >> 8);
crc_table[k][n] = c;
crc_table[k + 4][n] = REV(c);
}
}
#endif /* BYFOUR */
crc_table_empty = 0;
}
else { /* not first */
/* wait for the other guy to finish (not efficient, but rare) */
while (crc_table_empty)
;
}
#ifdef MAKECRCH
/* write out CRC tables to crc32.h */
{
FILE *out;
out = fopen("crc32.h", "w");
if (out == NULL) return;
fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n");
fprintf(out, " * Generated automatically by crc32.c\n */\n\n");
fprintf(out, "local const unsigned long FAR ");
fprintf(out, "crc_table[TBLS][256] =\n{\n {\n");
write_table(out, crc_table[0]);
# ifdef BYFOUR
fprintf(out, "#ifdef BYFOUR\n");
for (k = 1; k < 8; k++) {
fprintf(out, " },\n {\n");
write_table(out, crc_table[k]);
}
fprintf(out, "#endif\n");
# endif /* BYFOUR */
fprintf(out, " }\n};\n");
fclose(out);
}
#endif /* MAKECRCH */
}
#ifdef MAKECRCH
local void write_table(out, table)
FILE *out;
const unsigned long FAR *table;
{
int n;
for (n = 0; n < 256; n++)
fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", table[n],
n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", "));
}
#endif /* MAKECRCH */
#else /* !DYNAMIC_CRC_TABLE */
/* ========================================================================
* Tables of CRC-32s of all single-byte values, made by make_crc_table().
*/
#include "crc32.h"
#endif /* DYNAMIC_CRC_TABLE */
/* =========================================================================
* This function can be used by asm versions of crc32()
*/
const unsigned long FAR * ZEXPORT get_crc_table()
{
#ifdef DYNAMIC_CRC_TABLE
if (crc_table_empty)
make_crc_table();
#endif /* DYNAMIC_CRC_TABLE */
return (const unsigned long FAR *)crc_table;
}
/* ========================================================================= */
#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8)
#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1
/* ========================================================================= */
unsigned long ZEXPORT crc32(crc, buf, len)
unsigned long crc;
const unsigned char FAR *buf;
unsigned len;
{
if (buf == Z_NULL) return 0UL;
#ifdef DYNAMIC_CRC_TABLE
if (crc_table_empty)
make_crc_table();
#endif /* DYNAMIC_CRC_TABLE */
#ifdef BYFOUR
if (sizeof(void *) == sizeof(ptrdiff_t)) {
u4 endian;
endian = 1;
if (*((unsigned char *)(&endian)))
return crc32_little(crc, buf, len);
else
return crc32_big(crc, buf, len);
}
#endif /* BYFOUR */
crc = crc ^ 0xffffffffUL;
while (len >= 8) {
DO8;
len -= 8;
}
if (len) do {
DO1;
} while (--len);
return crc ^ 0xffffffffUL;
}
#ifdef BYFOUR
/* ========================================================================= */
#define DOLIT4 c ^= *buf4++; \
c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \
crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24]
#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4
/* ========================================================================= */
local unsigned long crc32_little(crc, buf, len)
unsigned long crc;
const unsigned char FAR *buf;
unsigned len;
{
register u4 c;
register const u4 FAR *buf4;
c = (u4)crc;
c = ~c;
while (len && ((ptrdiff_t)buf & 3)) {
c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
len--;
}
buf4 = (const u4 FAR *)(const void FAR *)buf;
while (len >= 32) {
DOLIT32;
len -= 32;
}
while (len >= 4) {
DOLIT4;
len -= 4;
}
buf = (const unsigned char FAR *)buf4;
if (len) do {
c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8);
} while (--len);
c = ~c;
return (unsigned long)c;
}
/* ========================================================================= */
#define DOBIG4 c ^= *++buf4; \
c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \
crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24]
#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4
/* ========================================================================= */
local unsigned long crc32_big(crc, buf, len)
unsigned long crc;
const unsigned char FAR *buf;
unsigned len;
{
register u4 c;
register const u4 FAR *buf4;
c = REV((u4)crc);
c = ~c;
while (len && ((ptrdiff_t)buf & 3)) {
c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
len--;
}
buf4 = (const u4 FAR *)(const void FAR *)buf;
buf4--;
while (len >= 32) {
DOBIG32;
len -= 32;
}
while (len >= 4) {
DOBIG4;
len -= 4;
}
buf4++;
buf = (const unsigned char FAR *)buf4;
if (len) do {
c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8);
} while (--len);
c = ~c;
return (unsigned long)(REV(c));
}
#endif /* BYFOUR */
#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */
/* ========================================================================= */
local unsigned long gf2_matrix_times(mat, vec)
unsigned long *mat;
unsigned long vec;
{
unsigned long sum;
sum = 0;
while (vec) {
if (vec & 1)
sum ^= *mat;
vec >>= 1;
mat++;
}
return sum;
}
/* ========================================================================= */
local void gf2_matrix_square(square, mat)
unsigned long *square;
unsigned long *mat;
{
int n;
for (n = 0; n < GF2_DIM; n++)
square[n] = gf2_matrix_times(mat, mat[n]);
}
/* ========================================================================= */
uLong ZEXPORT crc32_combine(crc1, crc2, len2)
uLong crc1;
uLong crc2;
z_off_t len2;
{
int n;
unsigned long row;
unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */
unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */
/* degenerate case */
if (len2 == 0)
return crc1;
/* put operator for one zero bit in odd */
odd[0] = 0xedb88320L; /* CRC-32 polynomial */
row = 1;
for (n = 1; n < GF2_DIM; n++) {
odd[n] = row;
row <<= 1;
}
/* put operator for two zero bits in even */
gf2_matrix_square(even, odd);
/* put operator for four zero bits in odd */
gf2_matrix_square(odd, even);
/* apply len2 zeros to crc1 (first square will put the operator for one
zero byte, eight zero bits, in even) */
do {
/* apply zeros operator for this bit of len2 */
gf2_matrix_square(even, odd);
if (len2 & 1)
crc1 = gf2_matrix_times(even, crc1);
len2 >>= 1;
/* if no more bits set, then done */
if (len2 == 0)
break;
/* another iteration of the loop with odd and even swapped */
gf2_matrix_square(odd, even);
if (len2 & 1)
crc1 = gf2_matrix_times(odd, crc1);
len2 >>= 1;
/* if no more bits set, then done */
} while (len2 != 0);
/* return combined crc */
crc1 ^= crc2;
return crc1;
}
+441
View File
@@ -0,0 +1,441 @@
/* crc32.h -- tables for rapid CRC calculation
* Generated automatically by crc32.c
*/
local const unsigned long FAR crc_table[TBLS][256] =
{
{
0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL,
0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL,
0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL,
0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL,
0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL,
0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL,
0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL,
0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL,
0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL,
0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL,
0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL,
0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL,
0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL,
0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL,
0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL,
0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL,
0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL,
0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL,
0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL,
0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL,
0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL,
0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL,
0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL,
0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL,
0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL,
0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL,
0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL,
0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL,
0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL,
0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL,
0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL,
0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL,
0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL,
0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL,
0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL,
0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL,
0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL,
0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL,
0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL,
0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL,
0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL,
0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL,
0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL,
0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL,
0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL,
0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL,
0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL,
0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL,
0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL,
0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL,
0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL,
0x2d02ef8dUL
#ifdef BYFOUR
},
{
0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL,
0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL,
0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL,
0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL,
0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL,
0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL,
0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL,
0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL,
0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL,
0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL,
0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL,
0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL,
0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL,
0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL,
0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL,
0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL,
0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL,
0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL,
0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL,
0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL,
0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL,
0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL,
0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL,
0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL,
0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL,
0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL,
0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL,
0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL,
0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL,
0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL,
0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL,
0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL,
0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL,
0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL,
0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL,
0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL,
0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL,
0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL,
0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL,
0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL,
0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL,
0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL,
0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL,
0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL,
0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL,
0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL,
0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL,
0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL,
0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL,
0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL,
0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL,
0x9324fd72UL
},
{
0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL,
0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL,
0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL,
0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL,
0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL,
0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL,
0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL,
0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL,
0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL,
0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL,
0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL,
0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL,
0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL,
0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL,
0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL,
0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL,
0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL,
0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL,
0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL,
0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL,
0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL,
0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL,
0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL,
0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL,
0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL,
0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL,
0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL,
0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL,
0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL,
0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL,
0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL,
0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL,
0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL,
0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL,
0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL,
0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL,
0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL,
0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL,
0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL,
0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL,
0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL,
0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL,
0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL,
0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL,
0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL,
0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL,
0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL,
0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL,
0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL,
0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL,
0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL,
0xbe9834edUL
},
{
0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL,
0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL,
0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL,
0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL,
0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL,
0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL,
0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL,
0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL,
0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL,
0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL,
0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL,
0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL,
0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL,
0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL,
0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL,
0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL,
0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL,
0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL,
0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL,
0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL,
0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL,
0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL,
0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL,
0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL,
0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL,
0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL,
0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL,
0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL,
0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL,
0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL,
0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL,
0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL,
0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL,
0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL,
0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL,
0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL,
0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL,
0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL,
0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL,
0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL,
0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL,
0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL,
0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL,
0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL,
0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL,
0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL,
0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL,
0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL,
0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL,
0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL,
0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL,
0xde0506f1UL
},
{
0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL,
0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL,
0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL,
0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL,
0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL,
0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL,
0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL,
0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL,
0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL,
0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL,
0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL,
0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL,
0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL,
0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL,
0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL,
0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL,
0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL,
0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL,
0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL,
0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL,
0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL,
0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL,
0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL,
0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL,
0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL,
0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL,
0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL,
0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL,
0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL,
0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL,
0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL,
0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL,
0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL,
0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL,
0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL,
0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL,
0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL,
0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL,
0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL,
0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL,
0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL,
0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL,
0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL,
0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL,
0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL,
0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL,
0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL,
0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL,
0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL,
0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL,
0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL,
0x8def022dUL
},
{
0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL,
0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL,
0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL,
0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL,
0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL,
0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL,
0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL,
0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL,
0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL,
0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL,
0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL,
0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL,
0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL,
0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL,
0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL,
0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL,
0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL,
0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL,
0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL,
0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL,
0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL,
0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL,
0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL,
0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL,
0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL,
0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL,
0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL,
0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL,
0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL,
0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL,
0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL,
0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL,
0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL,
0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL,
0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL,
0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL,
0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL,
0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL,
0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL,
0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL,
0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL,
0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL,
0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL,
0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL,
0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL,
0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL,
0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL,
0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL,
0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL,
0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL,
0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL,
0x72fd2493UL
},
{
0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL,
0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL,
0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL,
0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL,
0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL,
0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL,
0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL,
0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL,
0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL,
0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL,
0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL,
0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL,
0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL,
0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL,
0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL,
0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL,
0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL,
0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL,
0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL,
0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL,
0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL,
0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL,
0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL,
0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL,
0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL,
0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL,
0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL,
0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL,
0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL,
0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL,
0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL,
0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL,
0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL,
0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL,
0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL,
0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL,
0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL,
0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL,
0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL,
0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL,
0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL,
0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL,
0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL,
0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL,
0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL,
0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL,
0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL,
0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL,
0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL,
0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL,
0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL,
0xed3498beUL
},
{
0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL,
0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL,
0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL,
0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL,
0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL,
0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL,
0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL,
0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL,
0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL,
0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL,
0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL,
0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL,
0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL,
0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL,
0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL,
0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL,
0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL,
0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL,
0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL,
0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL,
0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL,
0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL,
0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL,
0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL,
0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL,
0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL,
0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL,
0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL,
0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL,
0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL,
0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL,
0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL,
0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL,
0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL,
0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL,
0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL,
0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL,
0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL,
0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL,
0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL,
0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL,
0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL,
0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL,
0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL,
0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL,
0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL,
0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL,
0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL,
0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL,
0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL,
0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL,
0xf10605deUL
#endif
}
};
Loaded 100 of 196 files, more files were not shown because too many files have changed in this diff. Show more