mirror of https://github.com/bsnes-emu/bsnes.git
Update to bsnes v019 release.
I´m releasing bsnes v0.019 today. This version contains Bandai Sufami Turbo support, new IRQ emulation code, and some various bugfixes. Unfortunately, this release is not entirely cause for celebration. Due to fatal errors in Microsoft´s "enterprise class" c++ compiler package, I am no longer able to compile bsnes with profile guided optimizations. I have tested v0.018 with and without these optimizations, and the difference is a 40% speedup when PGO is used, even more significant than I had previously believed. However, bsnes has now become too complex for Visual C++ to handle. Unfortunately, there is nothing I can do about this, except wait for Microsoft to fix their compiler. (Warning: this paragraph contains personal opinions, skip it if you can´t handle that) As if this wasn´t enough, I´m now doing my best to wean my dependence from Microsoft´s line of operating systems, as I´m particularly concerned about the black box nature of Vista and its´ DRM control mechanisms. This isn´t a road I wish to begin traveling down, and thusly have no interest in upgrading to future versions of Windows. Therefore, as of late, I´ve been writing a UI wrapper that will allow me to code applications that are truly platform independent. The biggest goal for this library is to design a GUI for bsnes that runs virtually identically on both Windows and Linux/BSD. This is mostly complete, however there were many tricks I used in bsnes using the win32 API that I simply cannot do with GTK+ on Linux/BSD, such as the memory editor window subclassing. I will be porting bsnes to use this new UI wrapper, and in turn this will lessen the attractiveness / functionality of the bsnes UI to a certain degree. Perhaps the most devastating news is that I am still contemplating the idea of designing a dot-based PPU renderer for bsnes. As if the loss of PGO wasn´t bad enough, this will likely eat away an unimaginable level of performance as well. I can only estimate the speed loss being between 100-500%. Yes, it will be that bad. And despite weeks of planning, I cannot think of a way to allow a scanline-based and dot-based renderer to coexist as selectable options, given their massive differences in implementation. And let´s not even joke about SA-1 or SuperFX support ... those processors are each four to eight times more powerful than the SNES´ main CPU. All of these speed losses will basically make bsnes mostly irrelevant as an alternative to ZSNES, SNES9x et al. Although I believe I really came close to a viable alternative with v0.018, I know that I cannot both create a mainstream emulator, as well as keep with my original goal to emulate the SNES as accurately as possible. The past few months have been very tough for me; trying to decide which of the above two goals to pursue. I´ve still not absolutely made up my mind. But for now, I´ve been sitting on a mostly untouched version of bsnes for the last few months, and have decided to release it to the public, profile guided optimizations be damned. I´m once again asking for help, if anyone can figure out why bsnes won´t compile with PGO support, please let me know. I´d very much like to get one last PGO build of bsnes released before starting on a dot-based PPU renderer. But given the usual response I get from these requests for help, I´d suggest no one getting their hopes up that bsnes will ever be as fast as it once was again. The new version can be downloaded at the usual place. I´m leaving v0.018 up, as it may very well be the last stable, fast version of bsnes ever released.
This commit is contained in:
parent
add0f74387
commit
1ebdb69516
Binary file not shown.
BIN
bsnes_fast.exe
BIN
bsnes_fast.exe
Binary file not shown.
28
readme.txt
28
readme.txt
|
@ -1,5 +1,5 @@
|
|||
bsnes
|
||||
Version 0.018
|
||||
Version 0.019
|
||||
Author: byuu
|
||||
|
||||
|
||||
|
@ -14,29 +14,6 @@ http://byuu.org/
|
|||
Please see license.txt for important licensing information.
|
||||
|
||||
|
||||
Known Bugs
|
||||
----------
|
||||
Koushien 2 (J):
|
||||
- Severity: critical
|
||||
- Issue: game periodically crashes
|
||||
- Cause: unknown, possibly S-SMP related
|
||||
|
||||
Mega lo Mania (J):
|
||||
- Severity: minor
|
||||
- Issue: horizontal line flickering during intro
|
||||
- Cause: caching of OAM occurs too early. Not fixable without dot-based PPU core
|
||||
|
||||
Street Racer (J):
|
||||
- Severity: minor
|
||||
- Issue: track sometimes flickers every several frames
|
||||
- Cause: unknown, possibly timing related
|
||||
|
||||
Unirally (J), Uniracers (U, E):
|
||||
- Severity: critical
|
||||
- Issue: 2-player mode sprites do not display at the correct positions
|
||||
- Cause: mid-frame OAM writes. Not fixable without dot-based PPU core
|
||||
|
||||
|
||||
Known Limitations
|
||||
-----------------
|
||||
S-CPU
|
||||
|
@ -108,9 +85,6 @@ BS-X Flashcart
|
|||
Flash cartridge used by BS-X, as well as some standalone games by
|
||||
Asciisoft
|
||||
|
||||
Bandai Sufami Turbo
|
||||
Special cartloader to play some Bandai games
|
||||
|
||||
Super Gameboy
|
||||
Cartridge passthrough used for playing Gameboy games
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#define BSNES_VERSION "0.018.04"
|
||||
#define BSNES_VERSION "0.019"
|
||||
#define BSNES_TITLE "bsnes v" BSNES_VERSION
|
||||
|
||||
#define MEMCORE bMemBus
|
||||
|
@ -34,6 +34,7 @@
|
|||
#endif
|
||||
|
||||
#include "lib/libbase.h"
|
||||
#include "lib/libsort.h"
|
||||
#include "lib/libco_x86.h"
|
||||
#include "lib/libarray.h"
|
||||
#include "lib/libvector.h"
|
||||
|
|
|
@ -1,9 +1,20 @@
|
|||
#include "../base.h"
|
||||
#include "database.cpp"
|
||||
|
||||
#include "cart_file.cpp"
|
||||
#include "cart_header.cpp"
|
||||
|
||||
Cartridge cartridge;
|
||||
|
||||
void Cartridge::read_dbi() {
|
||||
#include "cart_normal.cpp"
|
||||
#include "cart_st.cpp"
|
||||
#include "cart_stdual.cpp"
|
||||
|
||||
void Cartridge::load_begin(uint cart_type) {
|
||||
if(loaded() == true)return;
|
||||
|
||||
info.type = cart_type;
|
||||
|
||||
info.srtc = false;
|
||||
info.sdd1 = false;
|
||||
info.c4 = false;
|
||||
|
@ -13,372 +24,89 @@ void Cartridge::read_dbi() {
|
|||
|
||||
info.dsp1_mapper = 0;
|
||||
|
||||
info.header_index = 0x7fc0;
|
||||
info.header_index = 0xffc0;
|
||||
info.mapper = PCB;
|
||||
strcpy(info.name, dbi.name);
|
||||
strcpy(info.pcb, dbi.pcb);
|
||||
strcpy(info.name, "");
|
||||
strcpy(info.pcb, "");
|
||||
info.region = NTSC;
|
||||
info.cart_mmio = false;
|
||||
|
||||
info.rom_size = dbi.rom;
|
||||
info.ram_size = dbi.ram;
|
||||
}
|
||||
info.rom_size = 0;
|
||||
info.ram_size = 0;
|
||||
|
||||
void Cartridge::read_header() {
|
||||
info.srtc = false;
|
||||
info.sdd1 = false;
|
||||
info.c4 = false;
|
||||
info.dsp1 = false;
|
||||
info.dsp2 = false;
|
||||
info.obc1 = false;
|
||||
|
||||
info.dsp1_mapper = 0;
|
||||
|
||||
if(info.header_index == 0x7fc0 && info.rom_size >= 0x401000) {
|
||||
info.mapper = EXLOROM;
|
||||
strcpy(info.pcb, "UNL-EXLOROM");
|
||||
} else if(info.header_index == 0x7fc0 && rom[info.header_index + MAPPER] == 0x32) {
|
||||
info.mapper = EXLOROM;
|
||||
strcpy(info.pcb, "UNL-EXLOROM");
|
||||
} else if(info.header_index == 0x7fc0) {
|
||||
info.mapper = LOROM;
|
||||
strcpy(info.pcb, "UNL-LOROM");
|
||||
} else if(info.header_index == 0xffc0) {
|
||||
info.mapper = HIROM;
|
||||
strcpy(info.pcb, "UNL-HIROM");
|
||||
} else { //info.header_index == 0x40ffc0
|
||||
info.mapper = EXHIROM;
|
||||
strcpy(info.pcb, "UNL-EXHIROM");
|
||||
}
|
||||
|
||||
uint8 mapper = rom[info.header_index + MAPPER];
|
||||
uint8 rom_type = rom[info.header_index + ROM_TYPE];
|
||||
if(mapper == 0x35 && rom_type == 0x55) {
|
||||
info.srtc = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x32 && (rom_type == 0x43 || rom_type == 0x45)) {
|
||||
info.sdd1 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x20 && rom_type == 0xf3) {
|
||||
info.c4 = true;
|
||||
}
|
||||
|
||||
if((mapper == 0x20 || mapper == 0x21) && rom_type == 0x03) {
|
||||
info.dsp1 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x30 && rom_type == 0x05) {
|
||||
info.dsp1 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x31 && (rom_type == 0x03 || rom_type == 0x05)) {
|
||||
info.dsp1 = true;
|
||||
}
|
||||
|
||||
if(info.dsp1 == true) {
|
||||
if((mapper & 0x2f) == 0x20 && info.rom_size <= 0x100000) {
|
||||
info.dsp1_mapper = DSP1_LOROM_1MB;
|
||||
} else if((mapper & 0x2f) == 0x20) {
|
||||
info.dsp1_mapper = DSP1_LOROM_2MB;
|
||||
} else if((mapper & 0x2f) == 0x21) {
|
||||
info.dsp1_mapper = DSP1_HIROM;
|
||||
}
|
||||
}
|
||||
|
||||
if(mapper == 0x20 && rom_type == 0x05) {
|
||||
info.dsp2 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x30 && rom_type == 0x25) {
|
||||
info.obc1 = true;
|
||||
}
|
||||
|
||||
info.cart_mmio = info.c4 | info.dsp1 | info.dsp2 | info.obc1;
|
||||
|
||||
if(rom[info.header_index + SRAM_SIZE] & 7) {
|
||||
info.ram_size = 1024 << (rom[info.header_index + SRAM_SIZE] & 7);
|
||||
} else {
|
||||
info.ram_size = 0;
|
||||
}
|
||||
|
||||
memcpy(&info.name, &rom[info.header_index + CART_NAME], 21);
|
||||
info.name[21] = 0;
|
||||
|
||||
for(int i = 0; i < 22; i++) {
|
||||
if(info.name[i] & 0x80) {
|
||||
info.name[i] = '?';
|
||||
}
|
||||
file.count = 0;
|
||||
for(int i = 0; i < 8; i++) {
|
||||
strcpy(file.rom_name[i], "");
|
||||
strcpy(file.ram_name[i], "");
|
||||
file.rom_size[i] = 0;
|
||||
file.ram_size[i] = 0;
|
||||
file.rom_data[i] = 0;
|
||||
file.ram_data[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void Cartridge::find_header() {
|
||||
int32 score_lo = 0,
|
||||
score_hi = 0,
|
||||
score_ex = 0;
|
||||
void Cartridge::load(const char *rom_fn) {
|
||||
if(!rom_fn || !*rom_fn)return;
|
||||
|
||||
if(info.rom_size < 0x010000) {
|
||||
//cart too small to be anything but lorom
|
||||
info.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++;
|
||||
|
||||
if(rom[0x7fc0 + RESH] & 0x80)score_lo += 2;
|
||||
if(rom[0xffc0 + RESH] & 0x80)score_hi += 2;
|
||||
|
||||
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 && (cksum != 0) && (icksum != 0)) {
|
||||
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 && (cksum != 0) && (icksum != 0)) {
|
||||
score_hi += 8;
|
||||
}
|
||||
|
||||
if(info.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) {
|
||||
info.header_index = 0x007fc0;
|
||||
} else if(score_hi >= score_ex) {
|
||||
info.header_index = 0x00ffc0;
|
||||
} else {
|
||||
info.header_index = 0x40ffc0;
|
||||
}
|
||||
}
|
||||
|
||||
void Cartridge::load_sram() {
|
||||
if(info.ram_size == 0) {
|
||||
sram = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
FileReader ff(sram_fn);
|
||||
if(!ff.ready()) {
|
||||
sram = (uint8*)malloc(info.ram_size);
|
||||
memset(sram, 0xff, info.ram_size);
|
||||
return;
|
||||
}
|
||||
|
||||
sram = ff.read(info.ram_size);
|
||||
}
|
||||
|
||||
void Cartridge::save_sram() {
|
||||
if(info.ram_size == 0)return;
|
||||
|
||||
FileWriter ff(sram_fn);
|
||||
if(!ff.ready())return;
|
||||
|
||||
ff.write(sram, info.ram_size);
|
||||
}
|
||||
|
||||
void Cartridge::load_rom(Reader &rf) {
|
||||
uint size = rf.size();
|
||||
bool header = ((size & 0x7fff) == 512);
|
||||
info.rom_size = size - (header ? 512 : 0);
|
||||
if(info.rom_size & 0x7fff) {
|
||||
info.rom_size += 0x8000 - (info.rom_size & 0x7fff);
|
||||
}
|
||||
|
||||
uint8 *base_rom = rf.read(info.rom_size + (header ? 512 : 0));
|
||||
if(header) {
|
||||
memcpy(rom_header, base_rom, 512);
|
||||
} else {
|
||||
memset(rom_header, 0x00, 512);
|
||||
}
|
||||
|
||||
rom = (uint8*)malloc(info.rom_size);
|
||||
memcpy(rom, base_rom + (header ? 512 : 0), info.rom_size);
|
||||
SafeFree(base_rom);
|
||||
|
||||
info.crc32 = 0xffffffff;
|
||||
for(int32 i = 0; i < info.rom_size; i++) {
|
||||
info.crc32 = crc32_adjust(info.crc32, rom[i]);
|
||||
}
|
||||
info.crc32 = ~info.crc32;
|
||||
}
|
||||
|
||||
void Cartridge::patch_rom(Reader &rf) {
|
||||
UPS<ramfile, ramfile, ramfile> ups;
|
||||
uint patchsize = rf.size();
|
||||
uint8 *patchdata = rf.read();
|
||||
|
||||
fopen(ups.original, 0, file::mode_writeread);
|
||||
fopen(ups.modified, 0, file::mode_writeread);
|
||||
fopen(ups.patch.fp, 0, file::mode_writeread);
|
||||
|
||||
fwrite(ups.original, rom, info.rom_size);
|
||||
fwrite(ups.patch.fp, patchdata, patchsize);
|
||||
|
||||
if(ups.apply() == true) {
|
||||
info.crc32 = ups.modified_crc32;
|
||||
info.rom_size = ups.modified_filesize;
|
||||
rom = (uint8*)realloc(rom, info.rom_size);
|
||||
fseek(ups.modified, 0, file::seek_start);
|
||||
fread(ups.modified, rom, info.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(rom_fn);
|
||||
if(!ff.ready()) {
|
||||
alert("Error loading image file (%s)!", rom_fn);
|
||||
return false;
|
||||
}
|
||||
load_rom(ff);
|
||||
} break;
|
||||
|
||||
#ifdef GZIP_SUPPORT
|
||||
case Reader::RF_GZ: {
|
||||
GZReader gf(rom_fn);
|
||||
if(!gf.ready()) {
|
||||
alert("Error loading image file (%s)!", rom_fn);
|
||||
return false;
|
||||
}
|
||||
load_rom(gf);
|
||||
} break;
|
||||
|
||||
case Reader::RF_ZIP: {
|
||||
ZipReader zf(rom_fn);
|
||||
load_rom(zf);
|
||||
} break;
|
||||
#endif
|
||||
|
||||
#ifdef JMA_SUPPORT
|
||||
case Reader::RF_JMA: {
|
||||
try {
|
||||
JMAReader jf(rom_fn);
|
||||
load_rom(jf);
|
||||
} catch(JMA::jma_errors jma_error) {
|
||||
alert("Error loading image file (%s)!", rom_fn);
|
||||
return false;
|
||||
}
|
||||
} break;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
//remove ROM extension
|
||||
strcpy(sram_fn, fn);
|
||||
char fn[4096], ram_fn[4096];
|
||||
strcpy(fn, rom_fn);
|
||||
//correct folder slashes
|
||||
for(int i = strlen(fn) - 1; i >= 0; i--) {
|
||||
if(sram_fn[i] == '.') {
|
||||
sram_fn[i] = 0;
|
||||
if(fn[i] == '\\')fn[i] = '/';
|
||||
}
|
||||
|
||||
uint i = file.count++;
|
||||
strcpy(file.rom_name[i], fn);
|
||||
|
||||
strcpy(fn, rom_fn);
|
||||
//remove ROM extension
|
||||
for(int i = strlen(fn) - 1; i >= 0; i--) {
|
||||
if(fn[i] == '.') {
|
||||
fn[i] = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//add SRAM extension
|
||||
strcat(sram_fn, ".");
|
||||
strcat(sram_fn, config::fs.save_ext.sget());
|
||||
if(i == 0) {
|
||||
strcpy(file.patch_name, fn);
|
||||
strcat(file.patch_name, ".ups");
|
||||
}
|
||||
strcpy(fn, strptr(config::file_updatepath(fn, config::path.save)));
|
||||
if(i == 0) {
|
||||
strcpy(file.cheat_name, fn);
|
||||
strcat(file.cheat_name, ".cht");
|
||||
}
|
||||
strcpy(file.ram_name[i], fn);
|
||||
strcat(file.ram_name[i], ".");
|
||||
strcat(file.ram_name[i], config::path.save_ext);
|
||||
}
|
||||
|
||||
stringarray save_path;
|
||||
strcpy(save_path, config::fs.save_path.sget());
|
||||
replace(save_path, "\\", "/");
|
||||
if(strlen(save_path) && !strend(save_path, "/")) { strcat(save_path, "/"); }
|
||||
|
||||
if(strlen(save_path) != 0) {
|
||||
//override default path (current directory)
|
||||
stringarray new_fn, parts;
|
||||
strcpy(new_fn, sram_fn);
|
||||
replace(new_fn, "\\", "/");
|
||||
split(parts, "/", new_fn);
|
||||
|
||||
//add new SRAM path
|
||||
strcpy(new_fn, save_path);
|
||||
|
||||
//append fs.base_path if fs.sram_path is not fully-qualified path
|
||||
if(strbegin(new_fn, "./") == true) {
|
||||
strltrim(new_fn, "./");
|
||||
strcpy(new_fn[1], new_fn[0]);
|
||||
strcpy(new_fn[0], config::fs.base_path.sget());
|
||||
strcat(new_fn[0], new_fn[1]);
|
||||
}
|
||||
|
||||
//finally, append SRAM file name
|
||||
strcat(new_fn, parts[count(parts) - 1]);
|
||||
strcpy(sram_fn, strptr(new_fn));
|
||||
bool Cartridge::load_end() {
|
||||
for(int i = 0; i < file.count; i++) {
|
||||
load_file(file.rom_name[i], file.rom_data[i], file.rom_size[i]);
|
||||
}
|
||||
|
||||
//load cheat file if it exists
|
||||
strcpy(cheat_fn, sram_fn);
|
||||
strrtrim(cheat_fn, config::fs.save_ext.sget());
|
||||
strrtrim(cheat_fn, ".");
|
||||
strcat(cheat_fn, ".cht");
|
||||
|
||||
if(fexists(cheat_fn) == true) {
|
||||
FileReader ff(cheat_fn);
|
||||
cheat.load(ff);
|
||||
if(fexists(file.cheat_name) == true) {
|
||||
cheat.clear();
|
||||
cheat.load(file.cheat_name);
|
||||
}
|
||||
|
||||
//load patch file if it exists
|
||||
strcpy(patch_fn, sram_fn);
|
||||
strrtrim(patch_fn, config::fs.save_ext.sget());
|
||||
strrtrim(patch_fn, ".");
|
||||
strcat(patch_fn, ".ups");
|
||||
|
||||
if(fexists(patch_fn) == true) {
|
||||
FileReader ff(patch_fn);
|
||||
patch_rom(ff);
|
||||
switch(info.type) {
|
||||
case CART_NORMAL: {
|
||||
load_rom_normal();
|
||||
load_ram_normal();
|
||||
} break;
|
||||
case CART_ST: {
|
||||
load_rom_st();
|
||||
load_ram_st();
|
||||
} break;
|
||||
case CART_STDUAL: {
|
||||
load_rom_stdual();
|
||||
load_ram_stdual();
|
||||
} break;
|
||||
}
|
||||
|
||||
#ifdef GZIP_SUPPORT
|
||||
else {
|
||||
strrtrim(patch_fn, ".ups");
|
||||
strcat(patch_fn, ".upz");
|
||||
if(fexists(patch_fn) == true) {
|
||||
ZipReader zf(patch_fn);
|
||||
patch_rom(zf);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if(read_database() == true) {
|
||||
read_dbi();
|
||||
} else {
|
||||
find_header();
|
||||
read_header();
|
||||
}
|
||||
|
||||
load_sram();
|
||||
cart_loaded = true;
|
||||
|
||||
r_mem->load_cart();
|
||||
return true;
|
||||
}
|
||||
|
@ -388,13 +116,23 @@ bool Cartridge::unload() {
|
|||
|
||||
r_mem->unload_cart();
|
||||
|
||||
if(sram) { save_sram(); }
|
||||
SafeFree(rom);
|
||||
SafeFree(sram);
|
||||
switch(info.type) {
|
||||
case CART_NORMAL: {
|
||||
save_ram_normal();
|
||||
} break;
|
||||
case CART_ST: {
|
||||
save_ram_st();
|
||||
} break;
|
||||
case CART_STDUAL: {
|
||||
save_ram_stdual();
|
||||
} break;
|
||||
}
|
||||
|
||||
if(cheat.count() > 0 || fexists(cheat_fn)) {
|
||||
FileWriter ff(cheat_fn);
|
||||
cheat.save(ff);
|
||||
SafeFree(rom);
|
||||
SafeFree(ram);
|
||||
|
||||
if(cheat.count() > 0 || fexists(file.cheat_name) == true) {
|
||||
cheat.save(file.cheat_name);
|
||||
cheat.clear();
|
||||
}
|
||||
|
||||
|
@ -407,8 +145,8 @@ Cartridge::Cartridge() {
|
|||
|
||||
cart_loaded = false;
|
||||
|
||||
rom = 0;
|
||||
sram = 0;
|
||||
rom = 0;
|
||||
ram = 0;
|
||||
}
|
||||
|
||||
Cartridge::~Cartridge() {
|
||||
|
|
|
@ -15,10 +15,15 @@ db_item dbi;
|
|||
|
||||
//
|
||||
|
||||
bool cart_loaded;
|
||||
char rom_fn[4096], sram_fn[4096], cheat_fn[4096], patch_fn[4096];
|
||||
enum {
|
||||
CART_NORMAL,
|
||||
CART_ST,
|
||||
CART_STDUAL,
|
||||
};
|
||||
|
||||
uint8 rom_header[512], *rom, *sram;
|
||||
bool cart_loaded;
|
||||
|
||||
uint8 rom_header[512], *rom, *ram;
|
||||
|
||||
enum {
|
||||
//header fields
|
||||
|
@ -26,7 +31,7 @@ enum {
|
|||
MAPPER = 0x15,
|
||||
ROM_TYPE = 0x16,
|
||||
ROM_SIZE = 0x17,
|
||||
SRAM_SIZE = 0x18,
|
||||
RAM_SIZE = 0x18,
|
||||
REGION = 0x19,
|
||||
LICENSE = 0x1a,
|
||||
VERSION = 0x1b,
|
||||
|
@ -53,6 +58,17 @@ enum {
|
|||
};
|
||||
|
||||
struct {
|
||||
uint count;
|
||||
char cheat_name[4096], patch_name[4096];
|
||||
char rom_name[8][4096], ram_name[8][4096];
|
||||
uint rom_size[8], ram_size[8];
|
||||
uint8 *rom_data[8], *ram_data[8];
|
||||
} file;
|
||||
|
||||
struct {
|
||||
uint type;
|
||||
|
||||
//cart information
|
||||
uint32 crc32;
|
||||
char name[128];
|
||||
char pcb[32];
|
||||
|
@ -78,15 +94,28 @@ struct {
|
|||
uint header_index;
|
||||
} info;
|
||||
|
||||
void load_rom(Reader &rf);
|
||||
void patch_rom(Reader &rf);
|
||||
void load_sram();
|
||||
void save_sram();
|
||||
void read_dbi();
|
||||
bool load_file(const char *fn, uint8 *&data, uint &size);
|
||||
bool save_file(const char *fn, uint8 *data, uint size);
|
||||
|
||||
void load_rom_normal();
|
||||
void load_ram_normal();
|
||||
void save_ram_normal();
|
||||
|
||||
void load_rom_st();
|
||||
void load_ram_st();
|
||||
void save_ram_st();
|
||||
|
||||
void load_rom_stdual();
|
||||
void load_ram_stdual();
|
||||
void save_ram_stdual();
|
||||
|
||||
void find_header();
|
||||
void read_header();
|
||||
|
||||
bool loaded() { return cart_loaded; }
|
||||
bool load(const char *fn);
|
||||
void load_begin(uint cart_type);
|
||||
void load(const char *rom_fn);
|
||||
bool load_end();
|
||||
bool unload();
|
||||
|
||||
Cartridge();
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
bool Cartridge::load_file(const char *fn, uint8 *&data, uint &size) {
|
||||
dprintf("* Loading \"%s\"...", fn);
|
||||
|
||||
if(fexists(fn) == false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch(Reader::detect(fn)) {
|
||||
|
||||
case Reader::RF_NORMAL: {
|
||||
FileReader ff(fn);
|
||||
if(!ff.ready()) {
|
||||
alert("Error loading image file (%s)!", fn);
|
||||
return false;
|
||||
}
|
||||
size = ff.size();
|
||||
data = ff.read();
|
||||
} break;
|
||||
|
||||
#ifdef GZIP_SUPPORT
|
||||
case Reader::RF_GZ: {
|
||||
GZReader gf(fn);
|
||||
if(!gf.ready()) {
|
||||
alert("Error loading image file (%s)!", fn);
|
||||
return false;
|
||||
}
|
||||
size = gf.size();
|
||||
data = gf.read();
|
||||
} break;
|
||||
|
||||
case Reader::RF_ZIP: {
|
||||
ZipReader zf(fn);
|
||||
size = zf.size();
|
||||
data = zf.read();
|
||||
} break;
|
||||
#endif
|
||||
|
||||
#ifdef JMA_SUPPORT
|
||||
case Reader::RF_JMA: {
|
||||
try {
|
||||
JMAReader jf(fn);
|
||||
size = jf.size();
|
||||
data = jf.read();
|
||||
} catch(JMA::jma_errors jma_error) {
|
||||
alert("Error loading image file (%s)!", fn);
|
||||
return false;
|
||||
}
|
||||
} break;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Cartridge::save_file(const char *fn, uint8 *data, uint size) {
|
||||
FileWriter ff(fn);
|
||||
if(!ff.ready())return false;
|
||||
ff.write(data, size);
|
||||
return true;
|
||||
}
|
|
@ -0,0 +1,149 @@
|
|||
void Cartridge::read_header() {
|
||||
info.srtc = false;
|
||||
info.sdd1 = false;
|
||||
info.c4 = false;
|
||||
info.dsp1 = false;
|
||||
info.dsp2 = false;
|
||||
info.obc1 = false;
|
||||
|
||||
info.dsp1_mapper = 0;
|
||||
|
||||
if(info.header_index == 0x7fc0 && info.rom_size >= 0x401000) {
|
||||
info.mapper = EXLOROM;
|
||||
strcpy(info.pcb, "UNL-EXLOROM");
|
||||
} else if(info.header_index == 0x7fc0 && rom[info.header_index + MAPPER] == 0x32) {
|
||||
info.mapper = EXLOROM;
|
||||
strcpy(info.pcb, "UNL-EXLOROM");
|
||||
} else if(info.header_index == 0x7fc0) {
|
||||
info.mapper = LOROM;
|
||||
strcpy(info.pcb, "UNL-LOROM");
|
||||
} else if(info.header_index == 0xffc0) {
|
||||
info.mapper = HIROM;
|
||||
strcpy(info.pcb, "UNL-HIROM");
|
||||
} else { //info.header_index == 0x40ffc0
|
||||
info.mapper = EXHIROM;
|
||||
strcpy(info.pcb, "UNL-EXHIROM");
|
||||
}
|
||||
|
||||
uint8 mapper = rom[info.header_index + MAPPER];
|
||||
uint8 rom_type = rom[info.header_index + ROM_TYPE];
|
||||
if(mapper == 0x35 && rom_type == 0x55) {
|
||||
info.srtc = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x32 && (rom_type == 0x43 || rom_type == 0x45)) {
|
||||
info.sdd1 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x20 && rom_type == 0xf3) {
|
||||
info.c4 = true;
|
||||
}
|
||||
|
||||
if((mapper == 0x20 || mapper == 0x21) && rom_type == 0x03) {
|
||||
info.dsp1 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x30 && rom_type == 0x05) {
|
||||
info.dsp1 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x31 && (rom_type == 0x03 || rom_type == 0x05)) {
|
||||
info.dsp1 = true;
|
||||
}
|
||||
|
||||
if(info.dsp1 == true) {
|
||||
if((mapper & 0x2f) == 0x20 && info.rom_size <= 0x100000) {
|
||||
info.dsp1_mapper = DSP1_LOROM_1MB;
|
||||
} else if((mapper & 0x2f) == 0x20) {
|
||||
info.dsp1_mapper = DSP1_LOROM_2MB;
|
||||
} else if((mapper & 0x2f) == 0x21) {
|
||||
info.dsp1_mapper = DSP1_HIROM;
|
||||
}
|
||||
}
|
||||
|
||||
if(mapper == 0x20 && rom_type == 0x05) {
|
||||
info.dsp2 = true;
|
||||
}
|
||||
|
||||
if(mapper == 0x30 && rom_type == 0x25) {
|
||||
info.obc1 = true;
|
||||
}
|
||||
|
||||
info.cart_mmio = info.c4 | info.dsp1 | info.dsp2 | info.obc1;
|
||||
|
||||
if(rom[info.header_index + RAM_SIZE] & 7) {
|
||||
info.ram_size = 1024 << (rom[info.header_index + RAM_SIZE] & 7);
|
||||
} else {
|
||||
info.ram_size = 0;
|
||||
}
|
||||
|
||||
memcpy(&info.name, &rom[info.header_index + CART_NAME], 21);
|
||||
info.name[21] = 0;
|
||||
|
||||
for(int i = 0; i < 22; i++) {
|
||||
if(info.name[i] & 0x80) {
|
||||
info.name[i] = '?';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Cartridge::find_header() {
|
||||
int32 score_lo = 0,
|
||||
score_hi = 0,
|
||||
score_ex = 0;
|
||||
|
||||
if(info.rom_size < 0x010000) {
|
||||
//cart too small to be anything but lorom
|
||||
info.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 + RAM_SIZE] < 0x08)score_lo++;
|
||||
if(rom[0xffc0 + RAM_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++;
|
||||
|
||||
if(rom[0x7fc0 + RESH] & 0x80)score_lo += 2;
|
||||
if(rom[0xffc0 + RESH] & 0x80)score_hi += 2;
|
||||
|
||||
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 && (cksum != 0) && (icksum != 0)) {
|
||||
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 && (cksum != 0) && (icksum != 0)) {
|
||||
score_hi += 8;
|
||||
}
|
||||
|
||||
if(info.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) {
|
||||
info.header_index = 0x007fc0;
|
||||
} else if(score_hi >= score_ex) {
|
||||
info.header_index = 0x00ffc0;
|
||||
} else {
|
||||
info.header_index = 0x40ffc0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
void Cartridge::load_rom_normal() {
|
||||
uint size = 0;
|
||||
for(int i = 0; i < file.count; i++) {
|
||||
size += file.rom_size[i] - (((file.rom_size[i] & 0x7fff) == 512) ? 512 : 0);
|
||||
}
|
||||
|
||||
info.rom_size = size;
|
||||
rom = (uint8*)malloc(info.rom_size);
|
||||
memset(rom, 0, info.rom_size);
|
||||
|
||||
uint offset = 0;
|
||||
for(int i = 0; i < file.count; i++) {
|
||||
uint8 *data = file.rom_data[i] + (((file.rom_size[i] & 0x7fff) == 512) ? 512 : 0);
|
||||
uint size = file.rom_size[i] - (((file.rom_size[i] & 0x7fff) == 512) ? 512 : 0);
|
||||
memcpy(rom + offset, data, size);
|
||||
offset += size;
|
||||
safe_free(file.rom_data[i]);
|
||||
}
|
||||
|
||||
info.crc32 = crc32_calculate(rom, info.rom_size);
|
||||
|
||||
if(read_database() == true) {
|
||||
info.srtc = false;
|
||||
info.sdd1 = false;
|
||||
info.c4 = false;
|
||||
info.dsp1 = false;
|
||||
info.dsp2 = false;
|
||||
info.obc1 = false;
|
||||
|
||||
info.dsp1_mapper = 0;
|
||||
|
||||
info.header_index = 0xffc0;
|
||||
info.mapper = PCB;
|
||||
strcpy(info.name, dbi.name);
|
||||
strcpy(info.pcb, dbi.pcb);
|
||||
info.region = NTSC;
|
||||
info.cart_mmio = false;
|
||||
|
||||
info.rom_size = dbi.rom;
|
||||
info.ram_size = dbi.ram;
|
||||
} else {
|
||||
find_header();
|
||||
read_header();
|
||||
}
|
||||
}
|
||||
|
||||
void Cartridge::load_ram_normal() {
|
||||
if(info.ram_size == 0) {
|
||||
ram = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
ram = (uint8*)malloc(info.ram_size);
|
||||
memset(ram, 0xff, info.ram_size);
|
||||
|
||||
if(load_file(file.ram_name[0], file.ram_data[0], file.ram_size[0]) == true) {
|
||||
memcpy(ram, file.ram_data[0], min(info.ram_size, file.ram_size[0]));
|
||||
safe_free(file.ram_data[0]);
|
||||
}
|
||||
}
|
||||
|
||||
void Cartridge::save_ram_normal() {
|
||||
if(info.ram_size == 0)return;
|
||||
|
||||
save_file(file.ram_name[0], ram, info.ram_size);
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
void Cartridge::load_rom_st() {
|
||||
uint8 *data;
|
||||
uint size;
|
||||
string bios = config::file_updatepath("stbios.bin", config::path.bios);
|
||||
info.rom_size = 0x200000;
|
||||
rom = (uint8*)malloc(info.rom_size);
|
||||
memset(rom, 0, info.rom_size);
|
||||
|
||||
load_file(strptr(bios), data, size);
|
||||
memcpy(rom, data, min(size, 0x040000));
|
||||
safe_free(data);
|
||||
|
||||
memcpy(rom + 0x100000, file.rom_data[0], min(file.rom_size[0], 0x100000));
|
||||
safe_free(file.rom_data[0]);
|
||||
|
||||
//
|
||||
strcpy(info.name, "???");
|
||||
strcpy(info.pcb, "STC-SOLO");
|
||||
|
||||
info.mapper = PCB;
|
||||
info.region = NTSC;
|
||||
|
||||
info.rom_size = 0x200000;
|
||||
info.ram_size = 0x020000;
|
||||
//
|
||||
|
||||
info.crc32 = crc32_calculate(rom + 0x100000, file.rom_size[0]);
|
||||
if(read_database() == true) {
|
||||
strcpy(info.name, dbi.name);
|
||||
}
|
||||
}
|
||||
|
||||
void Cartridge::load_ram_st() {
|
||||
ram = (uint8*)malloc(info.ram_size);
|
||||
memset(ram, 0xff, info.ram_size);
|
||||
|
||||
if(load_file(file.ram_name[0], file.ram_data[0], file.ram_size[0]) == true) {
|
||||
memcpy(ram, file.ram_data[0], min(file.ram_size[0], 0x020000));
|
||||
safe_free(file.ram_data[0]);
|
||||
}
|
||||
}
|
||||
|
||||
void Cartridge::save_ram_st() {
|
||||
save_file(file.ram_name[0], ram, 0x020000);
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
void Cartridge::load_rom_stdual() {
|
||||
uint8 *data;
|
||||
uint size;
|
||||
string bios = config::file_updatepath("stbios.bin", config::path.bios);
|
||||
info.rom_size = 0x300000;
|
||||
rom = (uint8*)malloc(info.rom_size);
|
||||
memset(rom, 0, info.rom_size);
|
||||
|
||||
load_file(strptr(bios), data, size);
|
||||
memcpy(rom, data, min(size, 0x040000));
|
||||
safe_free(data);
|
||||
|
||||
memcpy(rom + 0x100000, file.rom_data[0], min(file.rom_size[0], 0x100000));
|
||||
safe_free(file.rom_data[0]);
|
||||
|
||||
memcpy(rom + 0x200000, file.rom_data[1], min(file.rom_size[1], 0x100000));
|
||||
safe_free(file.rom_data[1]);
|
||||
|
||||
char name_a[4096], name_b[4096];
|
||||
strcpy(name_a, "???");
|
||||
strcpy(name_b, "???");
|
||||
//
|
||||
info.mapper = PCB;
|
||||
info.region = NTSC;
|
||||
|
||||
info.rom_size = 0x300000;
|
||||
info.ram_size = 0x040000;
|
||||
//
|
||||
|
||||
info.crc32 = crc32_calculate(rom + 0x100000, file.rom_size[0]);
|
||||
if(read_database() == true) {
|
||||
strcpy(name_a, dbi.name);
|
||||
}
|
||||
|
||||
info.crc32 = crc32_calculate(rom + 0x200000, file.rom_size[1]);
|
||||
if(read_database() == true) {
|
||||
strcpy(name_b, dbi.name);
|
||||
}
|
||||
|
||||
//
|
||||
info.crc32 = 0;
|
||||
strcpy(info.name, name_a);
|
||||
strcat(info.name, " + ");
|
||||
strcat(info.name, name_b);
|
||||
strcpy(info.pcb, "STC-DUAL");
|
||||
}
|
||||
|
||||
void Cartridge::load_ram_stdual() {
|
||||
ram = (uint8*)malloc(info.ram_size);
|
||||
memset(ram, 0xff, info.ram_size);
|
||||
|
||||
if(load_file(file.ram_name[0], file.ram_data[0], file.ram_size[0]) == true) {
|
||||
memcpy(ram + 0x000000, file.ram_data[0], min(file.ram_size[0], 0x020000));
|
||||
safe_free(file.ram_data[0]);
|
||||
}
|
||||
|
||||
if(load_file(file.ram_name[1], file.ram_data[1], file.ram_size[1]) == true) {
|
||||
memcpy(ram + 0x020000, file.ram_data[1], min(file.ram_size[1], 0x020000));
|
||||
safe_free(file.ram_data[1]);
|
||||
}
|
||||
}
|
||||
|
||||
void Cartridge::save_ram_stdual() {
|
||||
save_file(file.ram_name[0], ram + 0x000000, 0x020000);
|
||||
save_file(file.ram_name[1], ram + 0x020000, 0x020000);
|
||||
}
|
Binary file not shown.
|
@ -1,32 +1,98 @@
|
|||
[0xbb5c4238]
|
||||
name = "Bishoujo Senshi Sailor Moon Sailor Stars - Fuwa Fuwa Panic 2 (Japan)"
|
||||
pcb = "STC-????"
|
||||
rom = 8mbit
|
||||
ram = 32kbit
|
||||
|
||||
[0x8eb753f3]
|
||||
name = "Crayon Shin-chan - Nagagutsu Dobon!! (Japan)"
|
||||
pcb = "STC-????"
|
||||
rom = 4mbit
|
||||
ram = 8kbit
|
||||
|
||||
[0x7aedd703]
|
||||
name = "Der Langrisser (Japan) [!]"
|
||||
pcb = "SHVC-1A3M-30"
|
||||
rom = 16mbit
|
||||
ram = 64kbit
|
||||
|
||||
[0x35f9eecc]
|
||||
name = "Der Langrisser (Japan) (V1.1)"
|
||||
pcb = "SHVC-1A3M-30" ;unverified (guess)
|
||||
rom = 16mbit
|
||||
ram = 64kbit
|
||||
|
||||
[0x19bdcb19]
|
||||
name = "Derby Stallion '96 (Japan) [!]"
|
||||
pcb = "BSC-1A5M-01"
|
||||
rom = 24mbit
|
||||
ram = 256kbit
|
||||
|
||||
[0x4296500d]
|
||||
name = "Gegege no Kitarou - Youkai Donjara (Japan)"
|
||||
pcb = "STC-????"
|
||||
rom = 4mbit
|
||||
ram = 16kbit
|
||||
|
||||
[0x14c66fca]
|
||||
name = "Gekisou Sentai Car Rangers (Japan)"
|
||||
pcb = "STC-????"
|
||||
rom = 4mbit
|
||||
ram = 8kbit
|
||||
|
||||
[0x32b2b3dd]
|
||||
name = "Poi Poi Ninja World (Japan)"
|
||||
pcb = "STC-????"
|
||||
rom = 4mbit
|
||||
ram = 8kbit
|
||||
|
||||
[0x9684526d]
|
||||
name = "Romancing SaGa (Japan) (V1.1) [!]"
|
||||
pcb = "SHVC-1A3B-12"
|
||||
rom = 8mbit
|
||||
ram = 64kbit
|
||||
|
||||
[0x675b6382]
|
||||
name = "RPG Tsukuru 2 (Japan)"
|
||||
pcb = "BSC-1A7M-01" ;unverified
|
||||
rom = 16mbit
|
||||
ram = 512kbit
|
||||
[0xafd74dcb]
|
||||
name = "SD Gundam Generation A - Ichinen Sensouki (Japan)"
|
||||
pcb = "STC-????"
|
||||
rom = 4mbit
|
||||
ram = 8kbit
|
||||
|
||||
[0x48ecae44]
|
||||
name = "SD Gundam Generation B - Grips Senki (Japan)"
|
||||
pcb = "STC-????"
|
||||
rom = 4mbit
|
||||
ram = 8kbit
|
||||
|
||||
[0x72b4235f]
|
||||
name = "SD Gundam Generation C - Axis Senki (Japan)"
|
||||
pcb = "STC-????"
|
||||
rom = 4mbit
|
||||
ram = 8kbit
|
||||
|
||||
[0x792d884c]
|
||||
name = "SD Gundam Generation D - Babylonia Kenkoku Senki (Japan)"
|
||||
pcb = "STC-????"
|
||||
rom = 4mbit
|
||||
ram = 8kbit
|
||||
|
||||
[0xefd3a865]
|
||||
name = "SD Gundam Generation E - Zanskar Senki (Japan)"
|
||||
pcb = "STC-????"
|
||||
rom = 4mbit
|
||||
ram = 8kbit
|
||||
|
||||
[0xc5dfa8fd]
|
||||
name = "SD Gundam Generation F - Colony Kakutouki (Japan)"
|
||||
pcb = "STC-????"
|
||||
rom = 4mbit
|
||||
ram = 8kbit
|
||||
|
||||
[0x43ad5a45]
|
||||
name = "SD Ultra Battle - Seven Densetsu (Japan)"
|
||||
pcb = "STC-????"
|
||||
rom = 4mbit
|
||||
ram = 8kbit
|
||||
|
||||
[0x04939d14]
|
||||
name = "SD Ultra Battle - Ultra Densetsu (Japan)"
|
||||
pcb = "STC-????"
|
||||
rom = 4mbit
|
||||
ram = 8kbit
|
||||
|
||||
[0xa5c0045e]
|
||||
name = "Secret of Evermore (USA) [!]"
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
FILE *fp;
|
||||
|
||||
uint decode_size(substring &str) {
|
||||
uint decode_size(string &str) {
|
||||
//hex encoding
|
||||
if(strbegin(str, "0x")) {
|
||||
strltrim(str, "0x");
|
||||
|
@ -31,8 +31,8 @@ uint decode_size(substring &str) {
|
|||
return strdec(str);
|
||||
}
|
||||
|
||||
void build_block(substring &block) {
|
||||
string line, hashpart, part;
|
||||
void build_block(string &block) {
|
||||
stringarray line, hashpart, part;
|
||||
split(line, "\n", block);
|
||||
|
||||
if(strbegin(line[0], "[") == false) {
|
||||
|
@ -58,26 +58,26 @@ db_item dbi;
|
|||
strset(line[i], pos, 0);
|
||||
}
|
||||
|
||||
if(strmatch(line[i], ""))continue;
|
||||
if(line[i] == "")continue;
|
||||
|
||||
split(part, "=", line[i]);
|
||||
strunquote(part[1]);
|
||||
|
||||
if(strmatch(part[0], "name")) {
|
||||
if(part[0] == "name") {
|
||||
strncpy(dbi.name, strptr(part[1]), 128);
|
||||
dbi.name[128] = 0;
|
||||
}
|
||||
|
||||
if(strmatch(part[0], "pcb")) {
|
||||
if(part[0] == "pcb") {
|
||||
strncpy(dbi.pcb, strptr(part[1]), 32);
|
||||
dbi.pcb[31] = 0;
|
||||
}
|
||||
|
||||
if(strmatch(part[0], "rom")) {
|
||||
if(part[0] == "rom") {
|
||||
dbi.rom = decode_size(part[1]);
|
||||
}
|
||||
|
||||
if(strmatch(part[0], "ram")) {
|
||||
if(part[0] == "ram") {
|
||||
dbi.ram = decode_size(part[1]);
|
||||
}
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ db_item dbi;
|
|||
}
|
||||
|
||||
void build_database() {
|
||||
string data, block;
|
||||
stringarray data, block;
|
||||
if(strfread(data, "cartdb.txt") == false)return;
|
||||
|
||||
fp = fopen("cart.db", "wb");
|
||||
|
|
|
@ -268,7 +268,8 @@ void Cheat::disable(uint32 n) {
|
|||
* cheat file manipulation routines
|
||||
*****/
|
||||
|
||||
bool Cheat::load(Reader &rf) {
|
||||
bool Cheat::load(const char *fn) {
|
||||
FileReader rf(fn);
|
||||
if(!rf.ready())return false;
|
||||
|
||||
uint8 *raw_data = rf.read();
|
||||
|
@ -299,7 +300,8 @@ stringarray data, line;
|
|||
return true;
|
||||
}
|
||||
|
||||
bool Cheat::save(Writer &wf) {
|
||||
bool Cheat::save(const char *fn) {
|
||||
FileWriter wf(fn);
|
||||
if(!wf.ready())return false;
|
||||
|
||||
string data;
|
||||
|
|
|
@ -38,8 +38,8 @@ public:
|
|||
bool enabled(uint32 n);
|
||||
void enable (uint32 n);
|
||||
void disable(uint32 n);
|
||||
bool load(Reader &rf);
|
||||
bool save(Writer &wf);
|
||||
bool load(const char *fn);
|
||||
bool save(const char *fn);
|
||||
void clear();
|
||||
|
||||
Cheat();
|
||||
|
|
|
@ -10,34 +10,34 @@ void OBC1::power() {
|
|||
}
|
||||
|
||||
void OBC1::reset() {
|
||||
memset(cartridge.sram, 0xff, 0x2000);
|
||||
status.baseptr = (cartridge.sram[0x1ff5] & 1) ? 0x1800 : 0x1c00;
|
||||
status.address = (cartridge.sram[0x1ff6] & 0x7f);
|
||||
status.shift = (cartridge.sram[0x1ff6] & 3) << 1;
|
||||
memset(cartridge.ram, 0xff, 0x2000);
|
||||
status.baseptr = (cartridge.ram[0x1ff5] & 1) ? 0x1800 : 0x1c00;
|
||||
status.address = (cartridge.ram[0x1ff6] & 0x7f);
|
||||
status.shift = (cartridge.ram[0x1ff6] & 3) << 1;
|
||||
}
|
||||
|
||||
uint8 OBC1::read(uint16 addr) {
|
||||
addr &= 0x1fff;
|
||||
|
||||
if((addr & 0x1ff8) != 0x1ff0) {
|
||||
return cartridge.sram[addr];
|
||||
return cartridge.ram[addr];
|
||||
}
|
||||
|
||||
switch(addr) {
|
||||
case 0x1ff0:
|
||||
return cartridge.sram[status.baseptr + (status.address << 2) + 0];
|
||||
return cartridge.ram[status.baseptr + (status.address << 2) + 0];
|
||||
case 0x1ff1:
|
||||
return cartridge.sram[status.baseptr + (status.address << 2) + 1];
|
||||
return cartridge.ram[status.baseptr + (status.address << 2) + 1];
|
||||
case 0x1ff2:
|
||||
return cartridge.sram[status.baseptr + (status.address << 2) + 2];
|
||||
return cartridge.ram[status.baseptr + (status.address << 2) + 2];
|
||||
case 0x1ff3:
|
||||
return cartridge.sram[status.baseptr + (status.address << 2) + 3];
|
||||
return cartridge.ram[status.baseptr + (status.address << 2) + 3];
|
||||
case 0x1ff4:
|
||||
return cartridge.sram[status.baseptr + (status.address >> 2) + 0x200];
|
||||
return cartridge.ram[status.baseptr + (status.address >> 2) + 0x200];
|
||||
case 0x1ff5:
|
||||
case 0x1ff6:
|
||||
case 0x1ff7:
|
||||
return cartridge.sram[addr];
|
||||
return cartridge.ram[addr];
|
||||
}
|
||||
|
||||
//never used, blocks compiler warning
|
||||
|
@ -48,40 +48,40 @@ void OBC1::write(uint16 addr, uint8 data) {
|
|||
addr &= 0x1fff;
|
||||
|
||||
if((addr & 0x1ff8) != 0x1ff0) {
|
||||
cartridge.sram[addr] = data;
|
||||
cartridge.ram[addr] = data;
|
||||
return;
|
||||
}
|
||||
|
||||
switch(addr) {
|
||||
case 0x1ff0:
|
||||
cartridge.sram[status.baseptr + (status.address << 2) + 0] = data;
|
||||
cartridge.ram[status.baseptr + (status.address << 2) + 0] = data;
|
||||
break;
|
||||
case 0x1ff1:
|
||||
cartridge.sram[status.baseptr + (status.address << 2) + 1] = data;
|
||||
cartridge.ram[status.baseptr + (status.address << 2) + 1] = data;
|
||||
break;
|
||||
case 0x1ff2:
|
||||
cartridge.sram[status.baseptr + (status.address << 2) + 2] = data;
|
||||
cartridge.ram[status.baseptr + (status.address << 2) + 2] = data;
|
||||
break;
|
||||
case 0x1ff3:
|
||||
cartridge.sram[status.baseptr + (status.address << 2) + 3] = data;
|
||||
cartridge.ram[status.baseptr + (status.address << 2) + 3] = data;
|
||||
break;
|
||||
case 0x1ff4: {
|
||||
uint8 temp;
|
||||
temp = cartridge.sram[status.baseptr + (status.address >> 2) + 0x200];
|
||||
temp = cartridge.ram[status.baseptr + (status.address >> 2) + 0x200];
|
||||
temp = (temp & ~(3 << status.shift)) | ((data & 3) << status.shift);
|
||||
cartridge.sram[status.baseptr + (status.address >> 2) + 0x200] = temp;
|
||||
cartridge.ram[status.baseptr + (status.address >> 2) + 0x200] = temp;
|
||||
} break;
|
||||
case 0x1ff5:
|
||||
status.baseptr = (data & 1) ? 0x1800 : 0x1c00;
|
||||
cartridge.sram[addr] = data;
|
||||
cartridge.ram[addr] = data;
|
||||
break;
|
||||
case 0x1ff6:
|
||||
status.address = (data & 0x7f);
|
||||
status.shift = (data & 3) << 1;
|
||||
cartridge.sram[addr] = data;
|
||||
cartridge.ram[addr] = data;
|
||||
break;
|
||||
case 0x1ff7:
|
||||
cartridge.sram[addr] = data;
|
||||
cartridge.ram[addr] = data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,24 +2,52 @@ Config config_file;
|
|||
|
||||
namespace config {
|
||||
|
||||
Setting FS::base_path(0, "fs.base_path",
|
||||
"Directory that bsnes resides in", "");
|
||||
Setting FS::rom_path(&config_file, "fs.rom_path",
|
||||
"Default path to look for ROM files in (\"\" = use default directory)", "");
|
||||
Setting FS::save_path(&config_file, "fs.save_path",
|
||||
"Default path for all save RAM and cheat files (\"\" = use current directory)", "");
|
||||
string file_updatepath(const char *req_file, const char *req_path) {
|
||||
string file(req_file);
|
||||
replace(file, "\\", "/");
|
||||
if(!req_path || strlen(req_path) == 0) { return file; }
|
||||
|
||||
Setting FS::save_ext(&config_file, "fs.save_ext",
|
||||
string path(req_path);
|
||||
replace(path, "\\", "/");
|
||||
if(!strend(path, "/")) { strcat(path, "/"); }
|
||||
|
||||
if(strbegin(path, "./")) {
|
||||
strltrim(path, "./");
|
||||
string temp;
|
||||
strcpy(temp, config::path.base);
|
||||
strcat(temp, path);
|
||||
strcpy(path, temp);
|
||||
}
|
||||
|
||||
stringarray part;
|
||||
split(part, "/", file);
|
||||
strcat(path, part[count(part) - 1]);
|
||||
return path;
|
||||
}
|
||||
|
||||
Setting Path::base(0, "fs.base_path",
|
||||
"Path that bsnes resides in", "");
|
||||
Setting Path::rom(&config_file, "path.rom",
|
||||
"Default path to look for ROM files in (\"\" = use default directory)", "");
|
||||
Setting Path::save(&config_file, "path.save",
|
||||
"Default path for all save RAM and cheat files (\"\" = use current directory)", "");
|
||||
Setting Path::bios(&config_file, "path.bios",
|
||||
"Path where BIOS file(s) are located\n"
|
||||
"Supported BIOS files:\n"
|
||||
"stbios.bin - Bandai Sufami Turbo"
|
||||
"", "./bios");
|
||||
|
||||
Setting Path::save_ext(&config_file, "path.save_ext",
|
||||
"Extension to be used for all save RAM files", "srm");
|
||||
|
||||
Setting SNES::gamma_ramp(&config_file, "snes.colorfilter.gamma_ramp",
|
||||
"Use precalculated TV-style gamma ramp", true, Setting::TRUE_FALSE);
|
||||
"Use precalculated TV-style gamma ramp", true, Setting::BOOL);
|
||||
Setting SNES::sepia(&config_file, "snes.colorfilter.sepia",
|
||||
"Convert color to sepia tone", false, Setting::TRUE_FALSE);
|
||||
"Convert color to sepia tone", false, Setting::BOOL);
|
||||
Setting SNES::grayscale(&config_file, "snes.colorfilter.grayscale",
|
||||
"Convert color to grayscale tone", false, Setting::TRUE_FALSE);
|
||||
"Convert color to grayscale tone", false, Setting::BOOL);
|
||||
Setting SNES::invert(&config_file, "snes.colorfilter.invert",
|
||||
"Invert output image colors", false, Setting::TRUE_FALSE);
|
||||
"Invert output image colors", false, Setting::BOOL);
|
||||
Setting SNES::contrast(&config_file, "snes.colorfilter.contrast",
|
||||
"Contrast", 0, Setting::DEC);
|
||||
Setting SNES::brightness(&config_file, "snes.colorfilter.brightness",
|
||||
|
@ -30,10 +58,10 @@ Setting SNES::gamma(&config_file, "snes.colorfilter.gamma",
|
|||
Setting SNES::ntsc_merge_fields(&config_file, "snes.ntsc_merge_fields",
|
||||
"Merge fields in NTSC video filter\n"
|
||||
"Set to true if using filter at any refresh rate other than 60hz\n"
|
||||
"", true, Setting::TRUE_FALSE);
|
||||
"", true, Setting::BOOL);
|
||||
|
||||
Setting SNES::mute(&config_file, "snes.mute", "Mutes SNES audio output when enabled",
|
||||
false, Setting::TRUE_FALSE);
|
||||
false, Setting::BOOL);
|
||||
|
||||
Setting SNES::controller_port0(&config_file, "snes.controller_port_1",
|
||||
"Controller attached to SNES port 1", ::SNES::DEVICEID_JOYPAD1, Setting::DEC);
|
||||
|
@ -43,31 +71,37 @@ Setting SNES::controller_port1(&config_file, "snes.controller_port_2",
|
|||
Setting CPU::ntsc_clock_rate(&config_file, "cpu.ntsc_clock_rate",
|
||||
"NTSC S-CPU clock rate (in hz)", 21477272, Setting::DEC);
|
||||
Setting CPU::pal_clock_rate(&config_file, "cpu.pal_clock_rate",
|
||||
"PAL S-CPU clock rate (in hz)", 21241370, Setting::DEC);
|
||||
"PAL S-CPU clock rate (in hz)", 21281370, Setting::DEC);
|
||||
|
||||
Setting CPU::hdma_enable(0, "cpu.hdma_enable",
|
||||
"Enable HDMA effects", true, Setting::TRUE_FALSE);
|
||||
"Enable HDMA effects", true, Setting::BOOL);
|
||||
|
||||
Setting SMP::ntsc_clock_rate(&config_file, "smp.ntsc_clock_rate",
|
||||
"NTSC S-SMP clock rate (in hz)", 24576000, Setting::DEC);
|
||||
"NTSC S-SMP clock rate (in hz)", 24606720, Setting::DEC);
|
||||
Setting SMP::pal_clock_rate(&config_file, "smp.pal_clock_rate",
|
||||
"PAL S-SMP clock rate (in hz)", 24576000, Setting::DEC);
|
||||
"PAL S-SMP clock rate (in hz)", 24606720, Setting::DEC);
|
||||
|
||||
Setting PPU::render_scanline_position(&config_file, "ppu.render_scanline_position",
|
||||
Setting PPU::Hack::render_scanline_position(&config_file, "ppu.hack.render_scanline_position",
|
||||
"Approximate HCLOCK position to render at for scanline-based renderers",
|
||||
256, Setting::DEC);
|
||||
Setting PPU::opt_enable(0, "ppu.opt_enable", "Enable offset-per-tile effects", true, Setting::TRUE_FALSE);
|
||||
512, Setting::DEC);
|
||||
Setting PPU::Hack::obj_cache(&config_file, "ppu.hack.obj_cache",
|
||||
"Cache OAM OBJ attributes one scanline before rendering\n"
|
||||
"This is technically closer to the actual operation of the SNES,\n"
|
||||
"but can cause problems in many games if enabled",
|
||||
false, Setting::BOOL);
|
||||
|
||||
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);
|
||||
Setting PPU::opt_enable(0, "ppu.opt_enable", "Enable offset-per-tile effects", true, Setting::BOOL);
|
||||
Setting PPU::bg1_pri0_enable(0, "ppu.bg1_pri0_enable", "Enable BG1 Priority 0", true, Setting::BOOL);
|
||||
Setting PPU::bg1_pri1_enable(0, "ppu.bg1_pri1_enable", "Enable BG1 Priority 1", true, Setting::BOOL);
|
||||
Setting PPU::bg2_pri0_enable(0, "ppu.bg2_pri0_enable", "Enable BG2 Priority 0", true, Setting::BOOL);
|
||||
Setting PPU::bg2_pri1_enable(0, "ppu.bg2_pri1_enable", "Enable BG2 Priority 1", true, Setting::BOOL);
|
||||
Setting PPU::bg3_pri0_enable(0, "ppu.bg3_pri0_enable", "Enable BG3 Priority 0", true, Setting::BOOL);
|
||||
Setting PPU::bg3_pri1_enable(0, "ppu.bg3_pri1_enable", "Enable BG3 Priority 1", true, Setting::BOOL);
|
||||
Setting PPU::bg4_pri0_enable(0, "ppu.bg4_pri0_enable", "Enable BG4 Priority 0", true, Setting::BOOL);
|
||||
Setting PPU::bg4_pri1_enable(0, "ppu.bg4_pri1_enable", "Enable BG4 Priority 1", true, Setting::BOOL);
|
||||
Setting PPU::oam_pri0_enable(0, "ppu.oam_pri0_enable", "Enable OAM Priority 0", true, Setting::BOOL);
|
||||
Setting PPU::oam_pri1_enable(0, "ppu.oam_pri1_enable", "Enable OAM Priority 1", true, Setting::BOOL);
|
||||
Setting PPU::oam_pri2_enable(0, "ppu.oam_pri2_enable", "Enable OAM Priority 2", true, Setting::BOOL);
|
||||
Setting PPU::oam_pri3_enable(0, "ppu.oam_pri3_enable", "Enable OAM Priority 3", true, Setting::BOOL);
|
||||
|
||||
};
|
||||
|
|
|
@ -2,10 +2,12 @@ extern Config config_file;
|
|||
|
||||
namespace config {
|
||||
|
||||
extern struct FS {
|
||||
static Setting base_path, rom_path, save_path;
|
||||
string file_updatepath(const char *, const char *);
|
||||
|
||||
extern struct Path {
|
||||
static Setting base, rom, save, bios;
|
||||
static Setting save_ext;
|
||||
} fs;
|
||||
} path;
|
||||
|
||||
extern struct SNES {
|
||||
static Setting gamma_ramp, sepia, grayscale, invert, contrast, brightness, gamma;
|
||||
|
@ -25,9 +27,12 @@ extern struct SMP {
|
|||
} smp;
|
||||
|
||||
extern struct PPU {
|
||||
static Setting render_scanline_position;
|
||||
static Setting opt_enable;
|
||||
struct Hack {
|
||||
static Setting render_scanline_position;
|
||||
static Setting obj_cache;
|
||||
} hack;
|
||||
|
||||
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;
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
class CPU : public MMIO {
|
||||
public:
|
||||
thread_t thread;
|
||||
virtual void enter() = 0;
|
||||
|
||||
public:
|
||||
|
|
|
@ -58,9 +58,7 @@ cop(0x02, 0xfff4, 0xfff5, 0xffe4, 0xffe5) {
|
|||
stp(0xdb) {
|
||||
1:op_io();
|
||||
2:last_cycle();
|
||||
while(1) {
|
||||
op_io();
|
||||
}
|
||||
while(1) { op_io(); }
|
||||
}
|
||||
|
||||
wai(0xcb) {
|
||||
|
@ -77,9 +75,9 @@ wai(0xcb) {
|
|||
xce(0xfb) {
|
||||
1:last_cycle();
|
||||
op_io();
|
||||
bool c = regs.p.c;
|
||||
bool carry = regs.p.c;
|
||||
regs.p.c = regs.e;
|
||||
regs.e = c;
|
||||
regs.e = carry;
|
||||
if(regs.e) {
|
||||
regs.p |= 0x30;
|
||||
regs.s.h = 0x01;
|
||||
|
|
|
@ -98,9 +98,7 @@ case 0x02: {
|
|||
case 0xdb: {
|
||||
op_io();
|
||||
last_cycle();
|
||||
while(1) {
|
||||
op_io();
|
||||
}
|
||||
while(1) { op_io(); }
|
||||
} break;
|
||||
|
||||
//wai
|
||||
|
@ -119,9 +117,9 @@ case 0xcb: {
|
|||
case 0xfb: {
|
||||
last_cycle();
|
||||
op_io();
|
||||
bool c = regs.p.c;
|
||||
bool carry = regs.p.c;
|
||||
regs.p.c = regs.e;
|
||||
regs.e = c;
|
||||
regs.e = carry;
|
||||
if(regs.e) {
|
||||
regs.p |= 0x30;
|
||||
regs.s.h = 0x01;
|
||||
|
|
|
@ -5,11 +5,11 @@ iny(0xc8, regs.p.x, y) {
|
|||
op_io();
|
||||
if($1) {
|
||||
regs.$2.l++;
|
||||
regs.p.n = bool(regs.$2.l & 0x80);
|
||||
regs.p.n = !!(regs.$2.l & 0x80);
|
||||
regs.p.z = (regs.$2.l == 0);
|
||||
} else {
|
||||
regs.$2.w++;
|
||||
regs.p.n = bool(regs.$2.w & 0x8000);
|
||||
regs.p.n = !!(regs.$2.w & 0x8000);
|
||||
regs.p.z = (regs.$2.w == 0);
|
||||
}
|
||||
}
|
||||
|
@ -21,11 +21,11 @@ dey(0x88, regs.p.x, y) {
|
|||
op_io();
|
||||
if($1) {
|
||||
regs.$2.l--;
|
||||
regs.p.n = bool(regs.$2.l & 0x80);
|
||||
regs.p.n = !!(regs.$2.l & 0x80);
|
||||
regs.p.z = (regs.$2.l == 0);
|
||||
} else {
|
||||
regs.$2.w--;
|
||||
regs.p.n = bool(regs.$2.w & 0x8000);
|
||||
regs.p.n = !!(regs.$2.w & 0x8000);
|
||||
regs.p.z = (regs.$2.w == 0);
|
||||
}
|
||||
}
|
||||
|
@ -34,14 +34,14 @@ asl(0x0a) {
|
|||
1:last_cycle();
|
||||
op_io();
|
||||
if(regs.p.m) {
|
||||
regs.p.c = bool(regs.a.l & 0x80);
|
||||
regs.p.c = !!(regs.a.l & 0x80);
|
||||
regs.a.l <<= 1;
|
||||
regs.p.n = bool(regs.a.l & 0x80);
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.p.c = bool(regs.a.w & 0x8000);
|
||||
regs.p.c = !!(regs.a.w & 0x8000);
|
||||
regs.a.w <<= 1;
|
||||
regs.p.n = bool(regs.a.w & 0x8000);
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
}
|
||||
|
@ -52,12 +52,12 @@ lsr(0x4a) {
|
|||
if(regs.p.m) {
|
||||
regs.p.c = regs.a.l & 1;
|
||||
regs.a.l >>= 1;
|
||||
regs.p.n = bool(regs.a.l & 0x80);
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.p.c = regs.a.w & 1;
|
||||
regs.a.w >>= 1;
|
||||
regs.p.n = bool(regs.a.w & 0x8000);
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
}
|
||||
|
@ -67,16 +67,16 @@ rol(0x2a) {
|
|||
op_io();
|
||||
uint16 c = regs.p.c;
|
||||
if(regs.p.m) {
|
||||
regs.p.c = bool(regs.a.l & 0x80);
|
||||
regs.p.c = !!(regs.a.l & 0x80);
|
||||
regs.a.l <<= 1;
|
||||
regs.a.l |= c;
|
||||
regs.p.n = bool(regs.a.l & 0x80);
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.p.c = bool(regs.a.w & 0x8000);
|
||||
regs.p.c = !!(regs.a.w & 0x8000);
|
||||
regs.a.w <<= 1;
|
||||
regs.a.w |= c;
|
||||
regs.p.n = bool(regs.a.w & 0x8000);
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
}
|
||||
|
@ -90,14 +90,14 @@ ror(0x6a) {
|
|||
regs.p.c = regs.a.l & 1;
|
||||
regs.a.l >>= 1;
|
||||
regs.a.l |= c;
|
||||
regs.p.n = bool(regs.a.l & 0x80);
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
c = (regs.p.c)?0x8000:0;
|
||||
regs.p.c = regs.a.w & 1;
|
||||
regs.a.w >>= 1;
|
||||
regs.a.w |= c;
|
||||
regs.p.n = bool(regs.a.w & 0x8000);
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,11 +4,11 @@ case 0x1a: {
|
|||
op_io();
|
||||
if(regs.p.m) {
|
||||
regs.a.l++;
|
||||
regs.p.n = bool(regs.a.l & 0x80);
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.a.w++;
|
||||
regs.p.n = bool(regs.a.w & 0x8000);
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
@ -19,11 +19,11 @@ case 0xe8: {
|
|||
op_io();
|
||||
if(regs.p.x) {
|
||||
regs.x.l++;
|
||||
regs.p.n = bool(regs.x.l & 0x80);
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
} else {
|
||||
regs.x.w++;
|
||||
regs.p.n = bool(regs.x.w & 0x8000);
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
@ -34,11 +34,11 @@ case 0xc8: {
|
|||
op_io();
|
||||
if(regs.p.x) {
|
||||
regs.y.l++;
|
||||
regs.p.n = bool(regs.y.l & 0x80);
|
||||
regs.p.n = !!(regs.y.l & 0x80);
|
||||
regs.p.z = (regs.y.l == 0);
|
||||
} else {
|
||||
regs.y.w++;
|
||||
regs.p.n = bool(regs.y.w & 0x8000);
|
||||
regs.p.n = !!(regs.y.w & 0x8000);
|
||||
regs.p.z = (regs.y.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
@ -49,11 +49,11 @@ case 0x3a: {
|
|||
op_io();
|
||||
if(regs.p.m) {
|
||||
regs.a.l--;
|
||||
regs.p.n = bool(regs.a.l & 0x80);
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.a.w--;
|
||||
regs.p.n = bool(regs.a.w & 0x8000);
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
@ -64,11 +64,11 @@ case 0xca: {
|
|||
op_io();
|
||||
if(regs.p.x) {
|
||||
regs.x.l--;
|
||||
regs.p.n = bool(regs.x.l & 0x80);
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
} else {
|
||||
regs.x.w--;
|
||||
regs.p.n = bool(regs.x.w & 0x8000);
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
@ -79,11 +79,11 @@ case 0x88: {
|
|||
op_io();
|
||||
if(regs.p.x) {
|
||||
regs.y.l--;
|
||||
regs.p.n = bool(regs.y.l & 0x80);
|
||||
regs.p.n = !!(regs.y.l & 0x80);
|
||||
regs.p.z = (regs.y.l == 0);
|
||||
} else {
|
||||
regs.y.w--;
|
||||
regs.p.n = bool(regs.y.w & 0x8000);
|
||||
regs.p.n = !!(regs.y.w & 0x8000);
|
||||
regs.p.z = (regs.y.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
@ -93,14 +93,14 @@ case 0x0a: {
|
|||
last_cycle();
|
||||
op_io();
|
||||
if(regs.p.m) {
|
||||
regs.p.c = bool(regs.a.l & 0x80);
|
||||
regs.p.c = !!(regs.a.l & 0x80);
|
||||
regs.a.l <<= 1;
|
||||
regs.p.n = bool(regs.a.l & 0x80);
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.p.c = bool(regs.a.w & 0x8000);
|
||||
regs.p.c = !!(regs.a.w & 0x8000);
|
||||
regs.a.w <<= 1;
|
||||
regs.p.n = bool(regs.a.w & 0x8000);
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
@ -112,12 +112,12 @@ case 0x4a: {
|
|||
if(regs.p.m) {
|
||||
regs.p.c = regs.a.l & 1;
|
||||
regs.a.l >>= 1;
|
||||
regs.p.n = bool(regs.a.l & 0x80);
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.p.c = regs.a.w & 1;
|
||||
regs.a.w >>= 1;
|
||||
regs.p.n = bool(regs.a.w & 0x8000);
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
@ -128,16 +128,16 @@ case 0x2a: {
|
|||
op_io();
|
||||
uint16 c = regs.p.c;
|
||||
if(regs.p.m) {
|
||||
regs.p.c = bool(regs.a.l & 0x80);
|
||||
regs.p.c = !!(regs.a.l & 0x80);
|
||||
regs.a.l <<= 1;
|
||||
regs.a.l |= c;
|
||||
regs.p.n = bool(regs.a.l & 0x80);
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
regs.p.c = bool(regs.a.w & 0x8000);
|
||||
regs.p.c = !!(regs.a.w & 0x8000);
|
||||
regs.a.w <<= 1;
|
||||
regs.a.w |= c;
|
||||
regs.p.n = bool(regs.a.w & 0x8000);
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
@ -152,14 +152,14 @@ case 0x6a: {
|
|||
regs.p.c = regs.a.l & 1;
|
||||
regs.a.l >>= 1;
|
||||
regs.a.l |= c;
|
||||
regs.p.n = bool(regs.a.l & 0x80);
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
} else {
|
||||
c = (regs.p.c)?0x8000:0;
|
||||
regs.p.c = regs.a.w & 1;
|
||||
regs.a.w >>= 1;
|
||||
regs.a.w |= c;
|
||||
regs.p.n = bool(regs.a.w & 0x8000);
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
} break;
|
||||
|
|
|
@ -23,8 +23,8 @@ int32 r = regs.a.l + rd.l + regs.p.c;
|
|||
r = regs.a.l + rd.l + regs.p.c;
|
||||
regs.p.c = (r > 0xff);
|
||||
}
|
||||
regs.p.n = bool(r & 0x80);
|
||||
regs.p.v = bool(~(regs.a.l ^ rd.l) & (regs.a.l ^ r) & 0x80);
|
||||
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.a.l = r;
|
||||
}
|
||||
|
@ -67,135 +67,135 @@ int32 r;
|
|||
r = regs.a.w + rd.w + regs.p.c;
|
||||
regs.p.c = (r > 0xffff);
|
||||
}
|
||||
regs.p.n = bool(r & 0x8000);
|
||||
regs.p.v = bool(~(regs.a.w ^ rd.w) & (regs.a.w ^ r) & 0x8000);
|
||||
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.a.w = r;
|
||||
}
|
||||
|
||||
inline void sCPU::op_and_b() {
|
||||
regs.a.l &= rd.l;
|
||||
regs.p.n = bool(regs.a.l & 0x80);
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_and_w() {
|
||||
regs.a.w &= rd.w;
|
||||
regs.p.n = bool(regs.a.w & 0x8000);
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_bit_b() {
|
||||
regs.p.n = bool(rd.l & 0x80);
|
||||
regs.p.v = bool(rd.l & 0x40);
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.v = !!(rd.l & 0x40);
|
||||
regs.p.z = ((rd.l & regs.a.l) == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_bit_w() {
|
||||
regs.p.n = bool(rd.w & 0x8000);
|
||||
regs.p.v = bool(rd.w & 0x4000);
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.v = !!(rd.w & 0x4000);
|
||||
regs.p.z = ((rd.w & regs.a.w) == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_cmp_b() {
|
||||
int32 r = regs.a.l - rd.l;
|
||||
regs.p.n = bool(r & 0x80);
|
||||
regs.p.n = !!(r & 0x80);
|
||||
regs.p.z = ((uint8)r == 0);
|
||||
regs.p.c = (r >= 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_cmp_w() {
|
||||
int32 r = regs.a.w - rd.w;
|
||||
regs.p.n = bool(r & 0x8000);
|
||||
regs.p.n = !!(r & 0x8000);
|
||||
regs.p.z = ((uint16)r == 0);
|
||||
regs.p.c = (r >= 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_cpx_b() {
|
||||
int32 r = regs.x.l - rd.l;
|
||||
regs.p.n = bool(r & 0x80);
|
||||
regs.p.n = !!(r & 0x80);
|
||||
regs.p.z = ((uint8)r == 0);
|
||||
regs.p.c = (r >= 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_cpx_w() {
|
||||
int32 r = regs.x.w - rd.w;
|
||||
regs.p.n = bool(r & 0x8000);
|
||||
regs.p.n = !!(r & 0x8000);
|
||||
regs.p.z = ((uint16)r == 0);
|
||||
regs.p.c = (r >= 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_cpy_b() {
|
||||
int32 r = regs.y.l - rd.l;
|
||||
regs.p.n = bool(r & 0x80);
|
||||
regs.p.n = !!(r & 0x80);
|
||||
regs.p.z = ((uint8)r == 0);
|
||||
regs.p.c = (r >= 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_cpy_w() {
|
||||
int32 r = regs.y.w - rd.w;
|
||||
regs.p.n = bool(r & 0x8000);
|
||||
regs.p.n = !!(r & 0x8000);
|
||||
regs.p.z = ((uint16)r == 0);
|
||||
regs.p.c = (r >= 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_eor_b() {
|
||||
regs.a.l ^= rd.l;
|
||||
regs.p.n = bool(regs.a.l & 0x80);
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_eor_w() {
|
||||
regs.a.w ^= rd.w;
|
||||
regs.p.n = bool(regs.a.w & 0x8000);
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_lda_b() {
|
||||
regs.a.l = rd.l;
|
||||
regs.p.n = bool(regs.a.l & 0x80);
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_lda_w() {
|
||||
regs.a.w = rd.w;
|
||||
regs.p.n = bool(regs.a.w & 0x8000);
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_ldx_b() {
|
||||
regs.x.l = rd.l;
|
||||
regs.p.n = bool(regs.x.l & 0x80);
|
||||
regs.p.n = !!(regs.x.l & 0x80);
|
||||
regs.p.z = (regs.x.l == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_ldx_w() {
|
||||
regs.x.w = rd.w;
|
||||
regs.p.n = bool(regs.x.w & 0x8000);
|
||||
regs.p.n = !!(regs.x.w & 0x8000);
|
||||
regs.p.z = (regs.x.w == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_ldy_b() {
|
||||
regs.y.l = rd.l;
|
||||
regs.p.n = bool(regs.y.l & 0x80);
|
||||
regs.p.n = !!(regs.y.l & 0x80);
|
||||
regs.p.z = (regs.y.l == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_ldy_w() {
|
||||
regs.y.w = rd.w;
|
||||
regs.p.n = bool(regs.y.w & 0x8000);
|
||||
regs.p.n = !!(regs.y.w & 0x8000);
|
||||
regs.p.z = (regs.y.w == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_ora_b() {
|
||||
regs.a.l |= rd.l;
|
||||
regs.p.n = bool(regs.a.l & 0x80);
|
||||
regs.p.n = !!(regs.a.l & 0x80);
|
||||
regs.p.z = (regs.a.l == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_ora_w() {
|
||||
regs.a.w |= rd.w;
|
||||
regs.p.n = bool(regs.a.w & 0x8000);
|
||||
regs.p.n = !!(regs.a.w & 0x8000);
|
||||
regs.p.z = (regs.a.w == 0);
|
||||
}
|
||||
|
||||
|
@ -221,8 +221,8 @@ int32 r;
|
|||
r = regs.a.l - rd.l - !regs.p.c;
|
||||
regs.p.c = (r >= 0);
|
||||
}
|
||||
regs.p.n = bool(r & 0x80);
|
||||
regs.p.v = bool((regs.a.l ^ rd.l) & (regs.a.l ^ r) & 0x80);
|
||||
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.a.l = r;
|
||||
}
|
||||
|
@ -261,8 +261,8 @@ int32 r;
|
|||
r = regs.a.w - rd.w - !regs.p.c;
|
||||
regs.p.c = (r >= 0);
|
||||
}
|
||||
regs.p.n = bool(r & 0x8000);
|
||||
regs.p.v = bool((regs.a.w ^ rd.w) & (regs.a.w ^ r) & 0x8000);
|
||||
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.a.w = r;
|
||||
}
|
||||
|
@ -270,89 +270,85 @@ int32 r;
|
|||
//op_rmw
|
||||
inline void sCPU::op_inc_b() {
|
||||
rd.l++;
|
||||
regs.p.n = bool(rd.l & 0x80);
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_inc_w() {
|
||||
rd.w++;
|
||||
regs.p.n = bool(rd.w & 0x8000);
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_dec_b() {
|
||||
rd.l--;
|
||||
regs.p.n = bool(rd.l & 0x80);
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_dec_w() {
|
||||
rd.w--;
|
||||
regs.p.n = bool(rd.w & 0x8000);
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_asl_b() {
|
||||
regs.p.c = bool(rd.l & 0x80);
|
||||
regs.p.c = !!(rd.l & 0x80);
|
||||
rd.l <<= 1;
|
||||
regs.p.n = bool(rd.l & 0x80);
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_asl_w() {
|
||||
regs.p.c = bool(rd.w & 0x8000);
|
||||
regs.p.c = !!(rd.w & 0x8000);
|
||||
rd.w <<= 1;
|
||||
regs.p.n = bool(rd.w & 0x8000);
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_lsr_b() {
|
||||
regs.p.c = rd.l & 1;
|
||||
rd.l >>= 1;
|
||||
regs.p.n = bool(rd.l & 0x80);
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_lsr_w() {
|
||||
regs.p.c = rd.w & 1;
|
||||
rd.w >>= 1;
|
||||
regs.p.n = bool(rd.w & 0x8000);
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_rol_b() {
|
||||
uint16 c = regs.p.c;
|
||||
regs.p.c = bool(rd.l & 0x80);
|
||||
rd.l <<= 1;
|
||||
rd.l |= c;
|
||||
regs.p.n = bool(rd.l & 0x80);
|
||||
uint16 carry = (uint16)regs.p.c;
|
||||
regs.p.c = !!(rd.l & 0x80);
|
||||
rd.l = (rd.l << 1) | carry;
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_rol_w() {
|
||||
uint16 c = regs.p.c;
|
||||
regs.p.c = bool(rd.w & 0x8000);
|
||||
rd.w <<= 1;
|
||||
rd.w |= c;
|
||||
regs.p.n = bool(rd.w & 0x8000);
|
||||
uint16 carry = (uint16)regs.p.c;
|
||||
regs.p.c = !!(rd.w & 0x8000);
|
||||
rd.w = (rd.w << 1) | carry;
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_ror_b() {
|
||||
uint16 c = (regs.p.c)?0x80:0;
|
||||
uint16 carry = (uint16)regs.p.c << 7;
|
||||
regs.p.c = rd.l & 1;
|
||||
rd.l >>= 1;
|
||||
rd.l |= c;
|
||||
regs.p.n = bool(rd.l & 0x80);
|
||||
rd.l = carry | (rd.l >> 1);
|
||||
regs.p.n = !!(rd.l & 0x80);
|
||||
regs.p.z = (rd.l == 0);
|
||||
}
|
||||
|
||||
inline void sCPU::op_ror_w() {
|
||||
uint16 c = (regs.p.c)?0x8000:0;
|
||||
uint16 carry = (uint16)regs.p.c << 15;
|
||||
regs.p.c = rd.w & 1;
|
||||
rd.w >>= 1;
|
||||
rd.w |= c;
|
||||
regs.p.n = bool(rd.w & 0x8000);
|
||||
rd.w = carry | (rd.w >> 1);
|
||||
regs.p.n = !!(rd.w & 0x8000);
|
||||
regs.p.z = (rd.w == 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
void sCPU::dma_add_clocks(uint clocks) {
|
||||
status.dma_clocks += clocks;
|
||||
add_clocks(clocks);
|
||||
}
|
||||
|
||||
/*****
|
||||
* used by both DMA and HDMA
|
||||
*
|
||||
|
@ -29,8 +34,7 @@ uint8 r;
|
|||
r_mem->write(abus, r);
|
||||
}
|
||||
|
||||
status.dma_clocks += 8;
|
||||
add_clocks(8);
|
||||
dma_add_clocks(8);
|
||||
cycle_edge();
|
||||
}
|
||||
|
||||
|
@ -104,8 +108,7 @@ inline void sCPU::dma_write(uint8 i, uint8 index) {
|
|||
void sCPU::dma_run() {
|
||||
for(int i = 0; i < 8; i++) {
|
||||
if(channel[i].dma_enabled == false)continue;
|
||||
status.dma_clocks += 8;
|
||||
add_clocks(8);
|
||||
dma_add_clocks(8);
|
||||
|
||||
if(cartridge.info.sdd1 == true) {
|
||||
sdd1->dma_begin(i, (channel[i].srcbank << 16) | (channel[i].srcaddr),
|
||||
|
@ -129,7 +132,7 @@ void sCPU::dma_run() {
|
|||
channel[i].dma_enabled = false;
|
||||
}
|
||||
|
||||
counter.set(counter.irq_delay, 24);
|
||||
counter.set(counter.irq_delay, 2);
|
||||
}
|
||||
|
||||
/*****
|
||||
|
@ -166,19 +169,19 @@ uint8 r = 0;
|
|||
|
||||
void sCPU::hdma_update(uint8 i) {
|
||||
channel[i].hdma_line_counter = r_mem->read(hdma_addr(i));
|
||||
add_clocks(8);
|
||||
dma_add_clocks(8);
|
||||
|
||||
channel[i].hdma_completed = (channel[i].hdma_line_counter == 0);
|
||||
channel[i].hdma_do_transfer = !channel[i].hdma_completed;
|
||||
|
||||
if(channel[i].hdma_indirect) {
|
||||
channel[i].hdma_iaddr = r_mem->read(hdma_addr(i)) << 8;
|
||||
add_clocks(8);
|
||||
dma_add_clocks(8);
|
||||
|
||||
if(!channel[i].hdma_completed || hdma_active_after(i)) {
|
||||
channel[i].hdma_iaddr >>= 8;
|
||||
channel[i].hdma_iaddr |= r_mem->read(hdma_addr(i)) << 8;
|
||||
add_clocks(8);
|
||||
dma_add_clocks(8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -188,7 +191,7 @@ static uint8 hdma_xferlen[8] = { 1, 2, 2, 4, 4, 4, 2, 4 };
|
|||
for(int i = 0; i < 8; i++) {
|
||||
if(hdma_active(i) == false)continue;
|
||||
channel[i].dma_enabled = false; //HDMA run during DMA will stop DMA mid-transfer
|
||||
add_clocks(8);
|
||||
dma_add_clocks(8);
|
||||
|
||||
if(channel[i].hdma_do_transfer) {
|
||||
int xferlen = hdma_xferlen[channel[i].xfermode];
|
||||
|
@ -197,7 +200,7 @@ static uint8 hdma_xferlen[8] = { 1, 2, 2, 4, 4, 4, 2, 4 };
|
|||
dma_transfer(channel[i].direction, dma_bbus(i, index),
|
||||
!channel[i].hdma_indirect ? hdma_addr(i) : hdma_iaddr(i));
|
||||
} else {
|
||||
add_clocks(8);
|
||||
dma_add_clocks(8);
|
||||
cycle_edge();
|
||||
}
|
||||
}
|
||||
|
@ -210,7 +213,7 @@ static uint8 hdma_xferlen[8] = { 1, 2, 2, 4, 4, 4, 2, 4 };
|
|||
}
|
||||
}
|
||||
|
||||
counter.set(counter.irq_delay, 24);
|
||||
counter.set(counter.irq_delay, 2);
|
||||
}
|
||||
|
||||
void sCPU::hdma_init_reset() {
|
||||
|
@ -229,7 +232,7 @@ void sCPU::hdma_init() {
|
|||
hdma_update(i);
|
||||
}
|
||||
|
||||
counter.set(counter.irq_delay, 24);
|
||||
counter.set(counter.irq_delay, 2);
|
||||
}
|
||||
|
||||
/*****
|
||||
|
|
|
@ -45,6 +45,7 @@ struct {
|
|||
bool hdma_do_transfer;
|
||||
} channel[8];
|
||||
|
||||
void dma_add_clocks(uint clocks);
|
||||
void dma_transfer(bool direction, uint8 bbus, uint32 abus);
|
||||
|
||||
uint8 dma_bbus(uint8 i, uint8 index);
|
||||
|
|
|
@ -41,7 +41,7 @@ void sCPU::mmio_w4016(uint8 data) {
|
|||
status.joypad_strobe_latch = !!(data & 1);
|
||||
|
||||
if(status.joypad_strobe_latch == 1) {
|
||||
snes->poll_input();
|
||||
snes.poll_input();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,7 @@ void sCPU::mmio_w4016(uint8 data) {
|
|||
//realtime or buffered status of joypadN.b
|
||||
uint8 sCPU::mmio_r4016() {
|
||||
uint8 r = regs.mdr & 0xfc;
|
||||
r |= (uint8)snes->port_read(0);
|
||||
r |= (uint8)snes.port_read(0);
|
||||
return r;
|
||||
}
|
||||
|
||||
|
@ -63,43 +63,14 @@ uint8 r = regs.mdr & 0xfc;
|
|||
//1-0 = Joypad serial data
|
||||
uint8 sCPU::mmio_r4017() {
|
||||
uint8 r = (regs.mdr & 0xe0) | 0x1c;
|
||||
r |= (uint8)snes->port_read(1);
|
||||
r |= (uint8)snes.port_read(1);
|
||||
return r;
|
||||
}
|
||||
|
||||
//NMITIMEN
|
||||
void sCPU::mmio_w4200(uint8 data) {
|
||||
status.nmi_enabled = !!(data & 0x80);
|
||||
status.virq_enabled = !!(data & 0x20);
|
||||
status.hirq_enabled = !!(data & 0x10);
|
||||
status.auto_joypad_poll = !!(data & 0x01);
|
||||
|
||||
if(status.nmi_read == 0) {
|
||||
if(status.nmi_line == 1 && status.nmi_enabled == 1) {
|
||||
status.nmi_transition = 1;
|
||||
}
|
||||
status.nmi_line = !status.nmi_enabled;
|
||||
}
|
||||
|
||||
if(status.irq_read == 0) {
|
||||
if(status.irq_line == 1 && (status.virq_enabled || status.hirq_enabled)) {
|
||||
status.irq_transition = 1;
|
||||
}
|
||||
status.irq_line = !(status.virq_enabled || status.hirq_enabled);
|
||||
}
|
||||
|
||||
if(status.virq_enabled == true && status.hirq_enabled == false) {
|
||||
status.irq_lock = false;
|
||||
}
|
||||
|
||||
if(status.virq_enabled == false && status.hirq_enabled == false) {
|
||||
status.irq_line = 1;
|
||||
status.irq_read = 1;
|
||||
status.irq_transition = 0;
|
||||
}
|
||||
|
||||
update_interrupts();
|
||||
counter.set(counter.irq_delay, 2);
|
||||
nmitimen_update(data);
|
||||
}
|
||||
|
||||
//WRIO
|
||||
|
@ -144,32 +115,28 @@ void sCPU::mmio_w4206(uint8 data) {
|
|||
void sCPU::mmio_w4207(uint8 data) {
|
||||
status.hirq_pos = (status.hirq_pos & ~0xff) | (data);
|
||||
status.hirq_pos &= 0x01ff;
|
||||
update_interrupts();
|
||||
irqpos_update(0x4207);
|
||||
hvtime_update(0x4207);
|
||||
}
|
||||
|
||||
//HTIMEH
|
||||
void sCPU::mmio_w4208(uint8 data) {
|
||||
status.hirq_pos = (status.hirq_pos & 0xff) | (data << 8);
|
||||
status.hirq_pos &= 0x01ff;
|
||||
update_interrupts();
|
||||
irqpos_update(0x4208);
|
||||
hvtime_update(0x4208);
|
||||
}
|
||||
|
||||
//VTIMEL
|
||||
void sCPU::mmio_w4209(uint8 data) {
|
||||
status.virq_pos = (status.virq_pos & ~0xff) | (data);
|
||||
status.virq_pos &= 0x01ff;
|
||||
update_interrupts();
|
||||
irqpos_update(0x4209);
|
||||
hvtime_update(0x4209);
|
||||
}
|
||||
|
||||
//VTIMEH
|
||||
void sCPU::mmio_w420a(uint8 data) {
|
||||
status.virq_pos = (status.virq_pos & 0xff) | (data << 8);
|
||||
status.virq_pos &= 0x01ff;
|
||||
update_interrupts();
|
||||
irqpos_update(0x420a);
|
||||
hvtime_update(0x420a);
|
||||
}
|
||||
|
||||
//DMAEN
|
||||
|
@ -201,12 +168,7 @@ void sCPU::mmio_w420d(uint8 data) {
|
|||
//3-0 = CPU (5a22) version
|
||||
uint8 sCPU::mmio_r4210() {
|
||||
uint8 r = (regs.mdr & 0x70);
|
||||
r |= (uint8)(!status.nmi_read) << 7;
|
||||
|
||||
if(!nmi_edge()) {
|
||||
status.nmi_read = 1;
|
||||
}
|
||||
|
||||
r |= (uint8)(rdnmi()) << 7;
|
||||
r |= (cpu_version & 0x0f);
|
||||
return r;
|
||||
}
|
||||
|
@ -216,14 +178,7 @@ uint8 r = (regs.mdr & 0x70);
|
|||
//6-0 = MDR
|
||||
uint8 sCPU::mmio_r4211() {
|
||||
uint8 r = (regs.mdr & 0x7f);
|
||||
r |= (uint8)(!status.irq_read) << 7;
|
||||
|
||||
if(!irq_edge()) {
|
||||
status.irq_read = 1;
|
||||
status.irq_line = 1;
|
||||
status.irq_transition = 0;
|
||||
}
|
||||
|
||||
r |= (uint8)(timeup()) << 7;
|
||||
return r;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
#include "timing/timing.cpp"
|
||||
|
||||
void sCPU::power() {
|
||||
status.region = (bool)snes->region();
|
||||
status.region = (bool)snes.region();
|
||||
|
||||
regs.a = regs.x = regs.y = 0x0000;
|
||||
regs.s = 0x01ff;
|
||||
|
|
|
@ -16,6 +16,9 @@ struct {
|
|||
} event;
|
||||
|
||||
struct {
|
||||
uint nmi_hold;
|
||||
uint irq_hold;
|
||||
|
||||
uint nmi_fire;
|
||||
uint irq_fire;
|
||||
uint irq_delay;
|
||||
|
@ -55,6 +58,7 @@ struct {
|
|||
bool interlace, interlace_field;
|
||||
bool overscan;
|
||||
uint16 field_lines, line_clocks;
|
||||
uint16 prev_field_lines, prev_line_clocks;
|
||||
uint16 vblstart;
|
||||
|
||||
bool line_rendered;
|
||||
|
@ -70,15 +74,17 @@ struct {
|
|||
|
||||
uint16 irq_delay;
|
||||
|
||||
uint16 nmi_trigger_pos;
|
||||
uint16 nmi_read_pos, nmi_line_pos;
|
||||
bool nmi_read, nmi_line, nmi_transition;
|
||||
bool nmi_lock, nmi_pending;
|
||||
uint16 vnmi_trigger_pos;
|
||||
bool nmi_valid;
|
||||
bool nmi_line;
|
||||
bool nmi_transition;
|
||||
bool nmi_pending;
|
||||
|
||||
uint16 virq_trigger_pos, hirq_trigger_pos;
|
||||
uint16 irq_read_pos, irq_line_pos;
|
||||
bool irq_read, irq_line, irq_transition;
|
||||
bool irq_lock, irq_pending;
|
||||
bool irq_valid;
|
||||
bool irq_line;
|
||||
bool irq_transition;
|
||||
bool irq_pending;
|
||||
|
||||
//dma
|
||||
uint dma_counter;
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
#if defined(FAVOR_ACCURACY)
|
||||
#include "irqtiming_accurate.cpp"
|
||||
#elif defined(FAVOR_SPEED)
|
||||
#include "irqtiming_fast.cpp"
|
||||
#endif
|
||||
#include "irqtiming.cpp"
|
||||
|
||||
bool sCPU::irq_pos_valid() {
|
||||
uint vpos = status.virq_pos;
|
||||
|
@ -21,15 +17,25 @@ uint vlimit = region_scanlines() >> 1;
|
|||
return true;
|
||||
}
|
||||
|
||||
alwaysinline bool sCPU::nmi_test() {
|
||||
if(status.nmi_transition == 0)return false;
|
||||
alwaysinline
|
||||
bool sCPU::nmi_test() {
|
||||
if(status.nmi_transition == false) { return false; }
|
||||
status.nmi_transition = false;
|
||||
|
||||
status.nmi_transition = 0;
|
||||
event.wai = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
alwaysinline bool sCPU::irq_test() {
|
||||
alwaysinline
|
||||
bool sCPU::irq_test() {
|
||||
if(status.irq_transition == false) { return false; }
|
||||
status.irq_transition = false;
|
||||
|
||||
event.wai = false;
|
||||
return (regs.p.i) ? false : true;
|
||||
}
|
||||
|
||||
/*
|
||||
if(status.irq_transition == 1)goto irq_trigger;
|
||||
|
||||
if(status.irq_read == 0) {
|
||||
|
@ -51,3 +57,4 @@ irq_trigger:
|
|||
event.wai = false;
|
||||
return (regs.p.i) ? false : true;
|
||||
}
|
||||
*/
|
||||
|
|
|
@ -0,0 +1,105 @@
|
|||
void sCPU::update_interrupts() {
|
||||
status.vnmi_trigger_pos = status.vblstart;
|
||||
|
||||
if(irq_pos_valid() == true) {
|
||||
status.virq_trigger_pos = status.virq_pos;
|
||||
status.hirq_trigger_pos = 4 * ((status.hirq_enabled) ? (status.hirq_pos + 1) : 0);
|
||||
} else {
|
||||
status.virq_trigger_pos = IRQ_TRIGGER_NEVER;
|
||||
status.hirq_trigger_pos = IRQ_TRIGGER_NEVER;
|
||||
}
|
||||
}
|
||||
|
||||
alwaysinline
|
||||
void sCPU::poll_interrupts() {
|
||||
uint vpos = status.vcounter, hpos = status.hclock;
|
||||
|
||||
//NMI test
|
||||
timeshift_backward(2, vpos, hpos);
|
||||
bool nmi_valid = (vpos >= status.vnmi_trigger_pos);
|
||||
if(status.nmi_valid == false && nmi_valid == true) {
|
||||
//0->1 edge sensitive transition
|
||||
status.nmi_line = true;
|
||||
counter.nmi_hold = 6;
|
||||
} else if(status.nmi_valid == true && nmi_valid == false) {
|
||||
//1->0 edge sensitive transition
|
||||
status.nmi_line = false;
|
||||
}
|
||||
status.nmi_valid = nmi_valid;
|
||||
|
||||
//NMI hold
|
||||
if(counter.nmi_hold) {
|
||||
counter.nmi_hold -= 2;
|
||||
if(counter.nmi_hold == 0) {
|
||||
if(status.nmi_enabled == true) { status.nmi_transition = true; }
|
||||
}
|
||||
}
|
||||
|
||||
//IRQ test
|
||||
timeshift_backward(8, vpos, hpos);
|
||||
bool irq_valid = (status.virq_enabled == true || status.hirq_enabled == true);
|
||||
if(irq_valid == true) {
|
||||
if(status.virq_enabled == true && vpos != status.virq_trigger_pos) { irq_valid = false; }
|
||||
if(status.hirq_enabled == true && hpos != status.hirq_trigger_pos) { irq_valid = false; }
|
||||
}
|
||||
if(status.irq_valid == false && irq_valid == true) {
|
||||
//0->1 edge sensitive transition
|
||||
status.irq_line = true;
|
||||
counter.irq_hold = 6;
|
||||
}
|
||||
status.irq_valid = irq_valid;
|
||||
|
||||
//IRQ hold
|
||||
if(counter.irq_hold) { counter.irq_hold -= 2; }
|
||||
if(status.irq_line == true && counter.irq_hold == 0) {
|
||||
if(status.virq_enabled == true || status.hirq_enabled == true) { status.irq_transition = true; }
|
||||
}
|
||||
}
|
||||
|
||||
void sCPU::nmitimen_update(uint8 data) {
|
||||
bool nmi_enabled = status.nmi_enabled;
|
||||
bool virq_enabled = status.virq_enabled;
|
||||
bool hirq_enabled = status.hirq_enabled;
|
||||
status.nmi_enabled = !!(data & 0x80);
|
||||
status.virq_enabled = !!(data & 0x20);
|
||||
status.hirq_enabled = !!(data & 0x10);
|
||||
|
||||
//0->1 edge sensitive transition
|
||||
if(nmi_enabled == false && status.nmi_enabled == true && status.nmi_line == true) {
|
||||
status.nmi_transition = true;
|
||||
}
|
||||
|
||||
//?->1 level sensitive transition
|
||||
if(status.virq_enabled == true && status.hirq_enabled == false && status.irq_line == true) {
|
||||
status.irq_transition = true;
|
||||
}
|
||||
|
||||
if(status.virq_enabled == false && status.hirq_enabled == false) {
|
||||
status.irq_line = false;
|
||||
status.irq_transition = false;
|
||||
}
|
||||
|
||||
update_interrupts();
|
||||
counter.set(counter.irq_delay, 2);
|
||||
}
|
||||
|
||||
void sCPU::hvtime_update(uint16 addr) {
|
||||
update_interrupts();
|
||||
}
|
||||
|
||||
bool sCPU::rdnmi() {
|
||||
bool result = status.nmi_line;
|
||||
if(counter.nmi_hold == 0) {
|
||||
status.nmi_line = false;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool sCPU::timeup() {
|
||||
bool result = status.irq_line;
|
||||
if(counter.irq_hold == 0) {
|
||||
status.irq_line = false;
|
||||
status.irq_transition = false;
|
||||
}
|
||||
return result;
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
void sCPU::update_interrupts() {
|
||||
status.nmi_trigger_pos = (status.vcounter == status.vblstart) ? 2 : IRQ_TRIGGER_NEVER;
|
||||
|
||||
if(irq_pos_valid() == true) {
|
||||
status.virq_trigger_pos = status.virq_pos;
|
||||
status.hirq_trigger_pos = 4 * ((status.hirq_enabled) ? (status.hirq_pos + 1) : 0);
|
||||
} else {
|
||||
status.virq_trigger_pos = IRQ_TRIGGER_NEVER;
|
||||
status.hirq_trigger_pos = IRQ_TRIGGER_NEVER;
|
||||
}
|
||||
}
|
||||
|
||||
alwaysinline void sCPU::poll_interrupts(uint clocks) {
|
||||
clocks >>= 1;
|
||||
while(clocks--) {
|
||||
status.hclock += 2;
|
||||
if(status.hclock >= status.line_clocks) { scanline(); }
|
||||
|
||||
//NMI tick
|
||||
if(counter.nmi_fire) {
|
||||
counter.nmi_fire -= 2;
|
||||
if(counter.nmi_fire == 0) {
|
||||
if(status.nmi_enabled == true && status.nmi_line == 1) {
|
||||
status.nmi_line = 0;
|
||||
status.nmi_transition = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//IRQ tick
|
||||
if(counter.irq_fire) {
|
||||
counter.irq_fire -= 2;
|
||||
if(counter.irq_fire == 0) {
|
||||
if(status.virq_enabled == true || status.hirq_enabled == true) {
|
||||
status.irq_line = 0;
|
||||
status.irq_transition = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//NMI test
|
||||
if(status.hclock == status.nmi_trigger_pos) {
|
||||
status.nmi_read = 0;
|
||||
counter.nmi_fire = 4;
|
||||
}
|
||||
|
||||
//IRQ test
|
||||
if(status.hclock == 10) { status.irq_lock = false; }
|
||||
|
||||
if(status.hirq_trigger_pos == IRQ_TRIGGER_NEVER) { continue; }
|
||||
if(status.virq_enabled == false && status.hirq_enabled == false) { continue; }
|
||||
if(status.irq_lock == true) { continue; }
|
||||
|
||||
uint vpos = status.vcounter, hpos = status.hclock;
|
||||
timeshift_backward(10, vpos, hpos);
|
||||
|
||||
bool trigger_irq = true;
|
||||
if(status.virq_enabled == true && vpos != status.virq_trigger_pos)trigger_irq = false;
|
||||
if(status.hirq_enabled == true && hpos != status.hirq_trigger_pos)trigger_irq = false;
|
||||
|
||||
if(trigger_irq == true) {
|
||||
status.irq_lock = true;
|
||||
status.irq_read = 0;
|
||||
counter.irq_fire = 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool sCPU::nmi_edge() { return (counter.nmi_fire != 0); }
|
||||
bool sCPU::irq_edge() { return (counter.irq_fire != 0); }
|
||||
|
||||
void sCPU::irqpos_update(uint16 addr) {
|
||||
uint vpos = status.vcounter, hpos = status.hclock;
|
||||
timeshift_backward(10, vpos, hpos);
|
||||
if(hpos < status.hirq_trigger_pos) { status.irq_lock = false; }
|
||||
}
|
|
@ -1,111 +0,0 @@
|
|||
void sCPU::update_interrupts() {
|
||||
status.nmi_read_pos = (status.vcounter == status.vblstart) ? 2 : IRQ_TRIGGER_NEVER;
|
||||
status.nmi_line_pos = (status.vcounter == status.vblstart) ? 6 : IRQ_TRIGGER_NEVER;
|
||||
|
||||
if(irq_pos_valid() == false) {
|
||||
status.irq_read_pos = IRQ_TRIGGER_NEVER;
|
||||
status.irq_line_pos = IRQ_TRIGGER_NEVER;
|
||||
return;
|
||||
}
|
||||
|
||||
uint vpos = status.virq_pos;
|
||||
uint hpos = 4 * ((status.hirq_enabled) ? (status.hirq_pos + 1) : 0);
|
||||
timeshift_forward(10, vpos, hpos);
|
||||
if(!status.virq_enabled || (status.virq_enabled && status.vcounter == vpos)) {
|
||||
status.irq_read_pos = hpos;
|
||||
} else {
|
||||
status.irq_read_pos = IRQ_TRIGGER_NEVER;
|
||||
}
|
||||
|
||||
timeshift_forward(4, vpos, hpos);
|
||||
if(!status.virq_enabled || (status.virq_enabled && status.vcounter == vpos)) {
|
||||
status.irq_line_pos = hpos;
|
||||
} else {
|
||||
status.irq_line_pos = IRQ_TRIGGER_NEVER;
|
||||
}
|
||||
}
|
||||
|
||||
alwaysinline void sCPU::poll_interrupts(uint clocks) {
|
||||
if(status.hclock + clocks >= status.line_clocks) {
|
||||
clocks = (status.hclock + clocks) - status.line_clocks;
|
||||
poll_interrupts_range(status.line_clocks - status.hclock);
|
||||
scanline();
|
||||
status.irq_lock = false;
|
||||
if(clocks == 0) { return; }
|
||||
}
|
||||
|
||||
poll_interrupts_range(clocks);
|
||||
status.hclock += clocks;
|
||||
}
|
||||
|
||||
alwaysinline void sCPU::poll_interrupts_range(uint clocks) {
|
||||
int start, end;
|
||||
if(status.hclock == 0) {
|
||||
start = -1;
|
||||
end = clocks;
|
||||
} else {
|
||||
start = status.hclock;
|
||||
end = status.hclock + clocks;
|
||||
}
|
||||
|
||||
if(start < status.nmi_read_pos && status.nmi_read_pos <= end) {
|
||||
status.nmi_read = 0;
|
||||
}
|
||||
|
||||
if(start < status.nmi_line_pos && status.nmi_line_pos <= end) {
|
||||
if(status.nmi_enabled == true) {
|
||||
if(status.nmi_line == 1) {
|
||||
status.nmi_transition = 1;
|
||||
}
|
||||
status.nmi_line = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(status.virq_enabled == false && status.hirq_enabled == false) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(status.hirq_enabled == false) {
|
||||
if(status.irq_lock == false) {
|
||||
if(end >= status.irq_read_pos) {
|
||||
status.irq_read = 0;
|
||||
}
|
||||
|
||||
if(end >= status.irq_line_pos) {
|
||||
status.irq_lock = true;
|
||||
status.irq_line = 0;
|
||||
status.irq_transition = 1;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if(start < status.irq_read_pos && status.irq_read_pos <= end) {
|
||||
status.irq_read = 0;
|
||||
}
|
||||
|
||||
if(start < status.irq_line_pos && status.irq_line_pos <= end) {
|
||||
status.irq_lock = true;
|
||||
status.irq_line = 0;
|
||||
status.irq_transition = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool sCPU::nmi_edge() {
|
||||
uint vpos = status.vcounter, hpos = status.hclock;
|
||||
if(hpos == status.nmi_read_pos)return true;
|
||||
timeshift_backward(2, vpos, hpos);
|
||||
if(hpos == status.nmi_read_pos)return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool sCPU::irq_edge() {
|
||||
uint vpos = status.vcounter, hpos = status.hclock;
|
||||
if(hpos == status.irq_read_pos)return true;
|
||||
timeshift_backward(2, vpos, hpos);
|
||||
if(hpos == status.irq_read_pos)return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void sCPU::irqpos_update(uint16 addr) {
|
||||
if(status.hclock < status.irq_line_pos) { status.irq_lock = false; }
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
void sCPU::run_auto_joypad_poll() {
|
||||
uint16 joy1 = 0, joy2 = 0;
|
||||
for(int i = 0; i < 16; i++) {
|
||||
joy1 |= (uint16)snes->port_read(0) ? (0x8000 >> i) : 0;
|
||||
joy2 |= (uint16)snes->port_read(1) ? (0x8000 >> i) : 0;
|
||||
joy1 |= (uint16)snes.port_read(0) ? (0x8000 >> i) : 0;
|
||||
joy2 |= (uint16)snes.port_read(1) ? (0x8000 >> i) : 0;
|
||||
}
|
||||
|
||||
status.joy1l = joy1;
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
alwaysinline void sCPU::timeshift_forward(uint clocks, uint &vtime, uint &htime) {
|
||||
htime += clocks;
|
||||
|
||||
if(htime >= status.line_clocks) {
|
||||
htime -= status.line_clocks;
|
||||
if(++vtime >= status.field_lines) {
|
||||
|
@ -13,14 +12,11 @@ alwaysinline void sCPU::timeshift_backward(uint clocks, uint &vtime, uint &htime
|
|||
if(htime >= clocks) {
|
||||
htime -= clocks;
|
||||
} else {
|
||||
htime += 1364 - clocks;
|
||||
if(status.region == SNES::NTSC && status.vcounter == 241 &&
|
||||
status.interlace == false && status.interlace_field == 1)htime -= 4;
|
||||
htime += status.prev_line_clocks - clocks;
|
||||
if(vtime > 0) {
|
||||
vtime--;
|
||||
} else {
|
||||
vtime = status.region_scanlines;
|
||||
if(status.interlace == true && status.interlace_field == 1)vtime++;
|
||||
vtime = status.prev_field_lines - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,11 +55,12 @@ void sCPU::add_clocks(uint clocks) {
|
|||
counter.sub(counter.irq_delay, clocks);
|
||||
scheduler.addclocks_cpu(clocks);
|
||||
|
||||
//TODO: rename function to more descriptive term
|
||||
//below function is responsible for incrementing status.hclock
|
||||
//by clocks, calling scanline() when a new line is reached, and
|
||||
//testing for and triggering NMIs and IRQs
|
||||
poll_interrupts(clocks);
|
||||
clocks >>= 1;
|
||||
while(clocks--) {
|
||||
status.hclock += 2;
|
||||
if(status.hclock >= status.line_clocks) { scanline(); }
|
||||
poll_interrupts();
|
||||
}
|
||||
}
|
||||
|
||||
void sCPU::scanline() {
|
||||
|
@ -70,6 +71,7 @@ void sCPU::scanline() {
|
|||
frame();
|
||||
}
|
||||
|
||||
status.prev_line_clocks = status.line_clocks;
|
||||
status.line_clocks = (ntsc_color_burst_phase_shift_scanline() == false) ? 1364 : 1360;
|
||||
|
||||
//dram refresh occurs once every scanline
|
||||
|
@ -89,23 +91,20 @@ void sCPU::scanline() {
|
|||
status.hdma_triggered = (status.vcounter <= (!overscan() ? 224 : 239)) ? false : true;
|
||||
|
||||
r_ppu->scanline();
|
||||
snes->scanline();
|
||||
snes.scanline();
|
||||
|
||||
update_interrupts();
|
||||
|
||||
if(status.auto_joypad_poll == true && status.vcounter == (!overscan() ? 227 : 242)) {
|
||||
snes->poll_input();
|
||||
snes.poll_input();
|
||||
run_auto_joypad_poll();
|
||||
}
|
||||
}
|
||||
|
||||
void sCPU::frame() {
|
||||
status.nmi_read = 1;
|
||||
status.nmi_line = 1;
|
||||
status.nmi_transition = 0;
|
||||
|
||||
status.vcounter = 0;
|
||||
status.interlace_field ^= 1;
|
||||
status.prev_field_lines = status.field_lines;
|
||||
status.field_lines = (status.region_scanlines >> 1);
|
||||
//interlaced even fields have one extra scanline
|
||||
//(263+262=525 NTSC, 313+312=625 PAL)
|
||||
|
@ -119,7 +118,7 @@ void sCPU::frame() {
|
|||
}
|
||||
|
||||
r_ppu->frame();
|
||||
snes->frame();
|
||||
snes.frame();
|
||||
}
|
||||
|
||||
/*****
|
||||
|
@ -171,15 +170,16 @@ void sCPU::cycle_edge() {
|
|||
if(status.hdmainit_triggered == false) {
|
||||
if(status.hclock >= status.hdmainit_trigger_position || status.vcounter) {
|
||||
status.hdmainit_triggered = true;
|
||||
|
||||
hdma_init_reset();
|
||||
if(hdma_enabled_channels()) {
|
||||
if(status.dma_state == DMASTATE_INACTIVE) {
|
||||
status.dma_state = DMASTATE_DMASYNC;
|
||||
status.hdmainit_pending = true;
|
||||
} else {
|
||||
hdma_init();
|
||||
}
|
||||
add_clocks(12);
|
||||
hdma_init();
|
||||
//if(status.dma_state == DMASTATE_INACTIVE) {
|
||||
// status.dma_state = DMASTATE_DMASYNC;
|
||||
// status.hdmainit_pending = true;
|
||||
//} else {
|
||||
// hdma_init();
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -188,12 +188,14 @@ void sCPU::cycle_edge() {
|
|||
if(status.hclock >= 1106) {
|
||||
status.hdma_triggered = true;
|
||||
if(hdma_active_channels()) {
|
||||
if(status.dma_state == DMASTATE_INACTIVE) {
|
||||
status.dma_state = DMASTATE_DMASYNC;
|
||||
status.hdma_pending = true;
|
||||
} else {
|
||||
hdma_run();
|
||||
}
|
||||
add_clocks(12);
|
||||
hdma_run();
|
||||
//if(status.dma_state == DMASTATE_INACTIVE) {
|
||||
// status.dma_state = DMASTATE_DMASYNC;
|
||||
// status.hdma_pending = true;
|
||||
//} else {
|
||||
// hdma_run();
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -221,6 +223,9 @@ void sCPU::timing_power() {
|
|||
}
|
||||
|
||||
void sCPU::timing_reset() {
|
||||
counter.nmi_hold = 0;
|
||||
counter.irq_hold = 0;
|
||||
|
||||
counter.nmi_fire = 0;
|
||||
counter.irq_fire = 0;
|
||||
counter.irq_delay = 0;
|
||||
|
@ -241,8 +246,11 @@ void sCPU::timing_reset() {
|
|||
status.field_lines = status.region_scanlines >> 1;
|
||||
status.line_clocks = 1364;
|
||||
|
||||
status.prev_field_lines = status.region_scanlines >> 1;
|
||||
status.prev_line_clocks = 1364;
|
||||
|
||||
status.line_rendered = false;
|
||||
status.line_render_position = minmax<0, 1112>((uint16)config::ppu.render_scanline_position);
|
||||
status.line_render_position = minmax<0, 1112>((uint16)config::ppu.hack.render_scanline_position);
|
||||
|
||||
status.dram_refreshed = false;
|
||||
status.dram_refresh_position = (cpu_version == 1) ? 530 : 538;
|
||||
|
@ -254,16 +262,14 @@ void sCPU::timing_reset() {
|
|||
|
||||
status.irq_delay = 0;
|
||||
|
||||
status.nmi_read = 1;
|
||||
status.nmi_line = 1;
|
||||
status.nmi_transition = 0;
|
||||
status.nmi_lock = false;
|
||||
status.nmi_valid = false;
|
||||
status.nmi_line = false;
|
||||
status.nmi_transition = false;
|
||||
status.nmi_pending = false;
|
||||
|
||||
status.irq_read = 1;
|
||||
status.irq_line = 1;
|
||||
status.irq_transition = 0;
|
||||
status.irq_lock = false;
|
||||
status.irq_valid = false;
|
||||
status.irq_line = false;
|
||||
status.irq_transition = false;
|
||||
status.irq_pending = false;
|
||||
|
||||
update_interrupts();
|
||||
|
|
|
@ -31,13 +31,12 @@
|
|||
//irq.cpp
|
||||
enum { IRQ_TRIGGER_NEVER = 0x3fff };
|
||||
void update_interrupts();
|
||||
void poll_interrupts(uint clocks);
|
||||
#ifdef FAVOR_SPEED
|
||||
void poll_interrupts_range(uint clocks);
|
||||
#endif
|
||||
bool nmi_edge();
|
||||
bool irq_edge();
|
||||
void irqpos_update(uint16 addr);
|
||||
void poll_interrupts();
|
||||
void nmitimen_update(uint8 data);
|
||||
void hvtime_update(uint16 addr);
|
||||
bool rdnmi();
|
||||
bool timeup();
|
||||
|
||||
bool irq_pos_valid();
|
||||
bool nmi_test();
|
||||
bool irq_test();
|
||||
|
|
|
@ -558,7 +558,7 @@ int32 fir_samplel, fir_sampler;
|
|||
msampler = sclamp<16>(msampler);
|
||||
}
|
||||
|
||||
return uint32( uint16(msamplel) | (uint16(msampler) << 16) );
|
||||
return (uint32)( (uint16)msamplel | ((uint16)msampler << 16) );
|
||||
}
|
||||
|
||||
bDSP::bDSP() {}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
libbase : version 0.08c ~byuu (09/28/06)
|
||||
libbase : version 0.08f ~byuu (2006-11-07)
|
||||
*/
|
||||
|
||||
#ifndef __LIBBASE
|
||||
|
@ -9,6 +9,7 @@
|
|||
//disable libc deprecation warnings in MSVC 2k5+
|
||||
#pragma warning(disable:4996)
|
||||
|
||||
#define NOMINMAX
|
||||
#define ftruncate _chsize
|
||||
#define vsnprintf _vsnprintf
|
||||
#endif
|
||||
|
@ -28,7 +29,10 @@
|
|||
#define alwaysinline inline
|
||||
#define fastcall __attribute__((fastcall))
|
||||
#else
|
||||
#error "unsupported compiler"
|
||||
#define noinline
|
||||
#define inline inline
|
||||
#define alwaysinline inline
|
||||
#define fastcall
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
@ -47,6 +51,7 @@
|
|||
#define TRUE !FALSE
|
||||
#endif
|
||||
|
||||
//deprecated
|
||||
#define SafeFree(__n) if(__n) { free(__n); __n = 0; }
|
||||
#define SafeDelete(__n) if(__n) { delete(__n); __n = 0; }
|
||||
#define SafeRelease(__n) if(__n) { __n->Release(); __n = 0; }
|
||||
|
@ -78,14 +83,45 @@ typedef signed long long int64;
|
|||
* templates
|
||||
*****/
|
||||
|
||||
template<typename T> inline void safe_free(T &handle) {
|
||||
if(handle) {
|
||||
free(handle);
|
||||
handle = 0;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> inline void safe_delete(T &handle) {
|
||||
if(handle) {
|
||||
delete handle;
|
||||
handle = 0;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> inline void safe_release(T &handle) {
|
||||
if(handle) {
|
||||
handle->Release();
|
||||
handle = 0;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T> inline void swap(T &x, T &y) {
|
||||
T z = x;
|
||||
x = y;
|
||||
y = z;
|
||||
}
|
||||
|
||||
#ifdef min
|
||||
#undef min
|
||||
#endif
|
||||
#define min(x, y) ((x < y) ? x : y)
|
||||
|
||||
#ifdef max
|
||||
#undef max
|
||||
#endif
|
||||
#define max(x, y) ((x > y) ? x : y)
|
||||
|
||||
template<int min, int max, typename T> inline T minmax(const T x) {
|
||||
return (x < T(min)) ? T(min) : (x > T(max)) ? T(max) : x;
|
||||
return (x < (T)min) ? (T)min : (x > (T)max) ? (T)max : x;
|
||||
}
|
||||
|
||||
template<int bits> inline unsigned uclamp(const unsigned x) {
|
||||
|
@ -243,6 +279,90 @@ typedef int_t<48, int64> int48;
|
|||
* libc extensions
|
||||
*****/
|
||||
|
||||
static uint8 fgetb(FILE *fp) { return fgetc(fp); }
|
||||
static uint8 fgetlb(FILE *fp) { return fgetc(fp); }
|
||||
static uint8 fgetmb(FILE *fp) { return fgetc(fp); }
|
||||
|
||||
static uint16 fgetlw(FILE *fp) {
|
||||
return (fgetc(fp)) | (fgetc(fp) << 8);
|
||||
}
|
||||
|
||||
static uint16 fgetmw(FILE *fp) {
|
||||
return (fgetc(fp) << 8) | (fgetc(fp) << 8);
|
||||
}
|
||||
|
||||
static uint32 fgetld(FILE *fp) {
|
||||
return (fgetc(fp)) | (fgetc(fp) << 8) | (fgetc(fp) << 16) | (fgetc(fp) << 24);
|
||||
}
|
||||
|
||||
static uint32 fgetmd(FILE *fp) {
|
||||
return (fgetc(fp) << 24) | (fgetc(fp) << 16) | (fgetc(fp) << 8) | (fgetc(fp));
|
||||
}
|
||||
|
||||
static uint64 fgetlq(FILE *fp) {
|
||||
return ((uint64)fgetc(fp) << 0) | ((uint64)fgetc(fp) << 8) |
|
||||
((uint64)fgetc(fp) << 16) | ((uint64)fgetc(fp) << 24) |
|
||||
((uint64)fgetc(fp) << 32) | ((uint64)fgetc(fp) << 40) |
|
||||
((uint64)fgetc(fp) << 48) | ((uint64)fgetc(fp) << 56);
|
||||
}
|
||||
|
||||
static uint64 fgetmq(FILE *fp) {
|
||||
return ((uint64)fgetc(fp) << 56) | ((uint64)fgetc(fp) << 48) |
|
||||
((uint64)fgetc(fp) << 40) | ((uint64)fgetc(fp) << 32) |
|
||||
((uint64)fgetc(fp) << 24) | ((uint64)fgetc(fp) << 16) |
|
||||
((uint64)fgetc(fp) << 8) | ((uint64)fgetc(fp) << 0);
|
||||
}
|
||||
|
||||
static void fputb(FILE *fp, uint8 data) { fputc(data, fp); }
|
||||
static void fputlb(FILE *fp, uint8 data) { fputc(data, fp); }
|
||||
static void fputmb(FILE *fp, uint8 data) { fputc(data, fp); }
|
||||
|
||||
static void fputlw(FILE *fp, uint16 data) {
|
||||
fputc(data >> 0, fp);
|
||||
fputc(data >> 8, fp);
|
||||
}
|
||||
|
||||
static void fputmw(FILE *fp, uint16 data) {
|
||||
fputc(data >> 8, fp);
|
||||
fputc(data >> 0, fp);
|
||||
}
|
||||
|
||||
static void fputld(FILE *fp, uint32 data) {
|
||||
fputc(data >> 0, fp);
|
||||
fputc(data >> 8, fp);
|
||||
fputc(data >> 16, fp);
|
||||
fputc(data >> 24, fp);
|
||||
}
|
||||
|
||||
static void fputmd(FILE *fp, uint32 data) {
|
||||
fputc(data >> 24, fp);
|
||||
fputc(data >> 16, fp);
|
||||
fputc(data >> 8, fp);
|
||||
fputc(data >> 0, fp);
|
||||
}
|
||||
|
||||
static void fputlq(FILE *fp, uint64 data) {
|
||||
fputc(data >> 0, fp);
|
||||
fputc(data >> 8, fp);
|
||||
fputc(data >> 16, fp);
|
||||
fputc(data >> 24, fp);
|
||||
fputc(data >> 32, fp);
|
||||
fputc(data >> 40, fp);
|
||||
fputc(data >> 48, fp);
|
||||
fputc(data >> 56, fp);
|
||||
}
|
||||
|
||||
static void fputmq(FILE *fp, uint64 data) {
|
||||
fputc(data >> 56, fp);
|
||||
fputc(data >> 48, fp);
|
||||
fputc(data >> 40, fp);
|
||||
fputc(data >> 32, fp);
|
||||
fputc(data >> 24, fp);
|
||||
fputc(data >> 16, fp);
|
||||
fputc(data >> 8, fp);
|
||||
fputc(data >> 0, fp);
|
||||
}
|
||||
|
||||
static bool fexists(const char *fn) {
|
||||
FILE *fp = fopen(fn, "rb");
|
||||
if(!fp)return false;
|
||||
|
@ -270,7 +390,7 @@ uint32 size = ftell(fp);
|
|||
return size;
|
||||
}
|
||||
|
||||
inline int ftruncate(FILE *fp, long size) { return ftruncate(fileno(fp), size); }
|
||||
static int ftruncate(FILE *fp, long size) { return ftruncate(fileno(fp), size); }
|
||||
|
||||
/*****
|
||||
* crc32 calculation
|
||||
|
@ -327,4 +447,12 @@ inline uint32 crc32_adjust(uint32 crc32, uint8 input) {
|
|||
return ((crc32 >> 8) & 0x00ffffff) ^ crc32_table[(crc32 ^ input) & 0xff];
|
||||
}
|
||||
|
||||
inline uint32 crc32_calculate(uint8 *data, uint length) {
|
||||
uint32 crc32 = ~0;
|
||||
for(uint i = 0; i < length; i++) {
|
||||
crc32 = crc32_adjust(crc32, data[i]);
|
||||
}
|
||||
return ~crc32;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
libco_win32 : version 0.06 ~byuu (05/21/06)
|
||||
libco_win32 : version 0.08 ~byuu (10/21/06)
|
||||
win32-x86 implementation of libco
|
||||
*/
|
||||
|
||||
|
@ -9,60 +9,62 @@
|
|||
|
||||
#include "libco_win32.h"
|
||||
|
||||
namespace libco_win32 {
|
||||
bool co_enabled = false;
|
||||
int co_stackptr = 0;
|
||||
thread_t co_stack[4096];
|
||||
|
||||
void __stdcall coentry_proc(void *coentry) {
|
||||
thread_p main = (thread_p)coentry;
|
||||
main();
|
||||
}
|
||||
struct cothread_struct {
|
||||
void *cohandle;
|
||||
cothread_p coentry;
|
||||
cothread_t colink;
|
||||
};
|
||||
|
||||
void co_init() {
|
||||
if(libco_win32::co_enabled == true)return;
|
||||
libco_win32::co_enabled = true;
|
||||
cothread_t __co_active = 0, __co_primary = 0;
|
||||
|
||||
void __stdcall co_entryproc(void *coentry) {
|
||||
cothread_struct *s = static_cast<cothread_struct*>(coentry);
|
||||
s->coentry();
|
||||
co_exit(0);
|
||||
}
|
||||
|
||||
cothread_t co_init() {
|
||||
ConvertThreadToFiber(0);
|
||||
cothread_struct *s = static_cast<cothread_struct*>(malloc(sizeof(cothread_struct)));
|
||||
s->colink = 0;
|
||||
s->coentry = 0;
|
||||
s->cohandle = GetCurrentFiber();
|
||||
__co_active = __co_primary = static_cast<cothread_t>(s);
|
||||
return __co_active;
|
||||
}
|
||||
|
||||
void co_term() {
|
||||
/*****
|
||||
//ConverFiberToThread() only exists on WinXP+
|
||||
|
||||
if(libco_win32::co_enabled == false)return;
|
||||
libco_win32::co_enabled = false;
|
||||
|
||||
ConvertFiberToThread();
|
||||
*****/
|
||||
//primary fiber cannot be deleted; free memory used by handle to fiber only
|
||||
free(__co_primary);
|
||||
//ConvertFiberToThread(); //only exists on WinXP+
|
||||
}
|
||||
|
||||
thread_t co_active() {
|
||||
if(libco_win32::co_enabled == false)co_init();
|
||||
|
||||
return GetCurrentFiber();
|
||||
cothread_t co_active() {
|
||||
return __co_active;
|
||||
}
|
||||
|
||||
thread_t co_create(thread_p coentry, unsigned int heapsize) {
|
||||
if(libco_win32::co_enabled == false)co_init();
|
||||
|
||||
return CreateFiber(heapsize, libco_win32::coentry_proc, (void*)coentry);
|
||||
cothread_t co_create(cothread_p coentry, unsigned int heapsize) {
|
||||
cothread_struct *s = static_cast<cothread_struct*>(malloc(sizeof(cothread_struct)));
|
||||
s->colink = co_active();
|
||||
s->coentry = coentry;
|
||||
s->cohandle = CreateFiber(heapsize + 512, co_entryproc, static_cast<void*>(s));
|
||||
return static_cast<cothread_t>(s);
|
||||
}
|
||||
|
||||
void co_delete(thread_t cothread) {
|
||||
DeleteFiber(cothread);
|
||||
void co_delete(cothread_t cothread) {
|
||||
cothread_struct *s = static_cast<cothread_struct*>(cothread);
|
||||
DeleteFiber(s->cohandle);
|
||||
free(cothread);
|
||||
}
|
||||
|
||||
void co_jump(thread_t cothread) {
|
||||
SwitchToFiber(cothread);
|
||||
void co_switch(cothread_t cothread) {
|
||||
__co_active = cothread;
|
||||
cothread_struct *s = static_cast<cothread_struct*>(cothread);
|
||||
SwitchToFiber(s->cohandle);
|
||||
}
|
||||
|
||||
void co_call(thread_t cothread) {
|
||||
libco_win32::co_stack[libco_win32::co_stackptr++] = co_active();
|
||||
co_jump(cothread);
|
||||
}
|
||||
|
||||
void co_return() {
|
||||
co_jump(libco_win32::co_stack[--libco_win32::co_stackptr]);
|
||||
void co_exit(cothread_t cothread) {
|
||||
if(cothread != 0) { co_switch(cothread); }
|
||||
cothread_struct *s = static_cast<cothread_struct*>(__co_active);
|
||||
co_switch(s->colink);
|
||||
}
|
||||
|
|
|
@ -1,15 +1,20 @@
|
|||
/*
|
||||
libco_win32 : version 0.06 ~byuu (05/21/2006)
|
||||
libco_win32 : version 0.08 ~byuu (10/21/2006)
|
||||
*/
|
||||
|
||||
typedef void (*thread_t);
|
||||
typedef void (*thread_p)();
|
||||
#define COTHREAD_STACKSIZE_TINY 0x1000
|
||||
#define COTHREAD_STACKSIZE_SMALL 0x4000
|
||||
#define COTHREAD_STACKSIZE_NORMAL 0x10000
|
||||
#define COTHREAD_STACKSIZE_LARGE 0x40000
|
||||
#define COTHREAD_STACKSIZE_HUGE 0x100000
|
||||
|
||||
void co_init();
|
||||
void co_term();
|
||||
thread_t co_active();
|
||||
thread_t co_create(thread_p coentry, unsigned int heapsize);
|
||||
void co_delete(thread_t cothread);
|
||||
void co_jump(thread_t cothread);
|
||||
void co_call(thread_t cothread);
|
||||
void co_return();
|
||||
typedef void (*cothread_t);
|
||||
typedef void (*cothread_p)(void);
|
||||
|
||||
cothread_t co_init();
|
||||
void co_term();
|
||||
cothread_t co_active();
|
||||
cothread_t co_create(cothread_p coentry, unsigned int heapsize);
|
||||
void co_delete(cothread_t cothread);
|
||||
void co_switch(cothread_t cothread);
|
||||
void co_exit(cothread_t cothread);
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
;*****
|
||||
;libco_x86 : version 0.07 ~byuu (08/15/06)
|
||||
;libco_x86 : version 0.08 ~byuu (10/21/06)
|
||||
;cross-platform x86 implementation of libco
|
||||
;
|
||||
;context save/restore adheres to c/c++ ABI
|
||||
;for x86 windows, linux and freebsd
|
||||
;for x86 windows, osx, linux and freebsd
|
||||
;
|
||||
;context saves esp+ebp+esi+edi+ebx
|
||||
;context ignores eax+ecx+edx
|
||||
|
@ -14,8 +14,8 @@
|
|||
section .data
|
||||
|
||||
align 4
|
||||
co_initialized dd 0
|
||||
co_active_context dd 0
|
||||
co_primary_context dd 0
|
||||
|
||||
section .code
|
||||
|
||||
|
@ -31,9 +31,21 @@ section .code
|
|||
%define co_active @co_active@0
|
||||
%define co_create @co_create@8
|
||||
%define co_delete @co_delete@4
|
||||
%define co_jump @co_jump@4
|
||||
%define co_call @co_call@4
|
||||
%define co_return @co_return@0
|
||||
%define co_switch @co_switch@4
|
||||
%define co_exit @co_exit@4
|
||||
%endif
|
||||
|
||||
%ifdef OSX86
|
||||
%define malloc _malloc
|
||||
%define free _free
|
||||
|
||||
%define co_init _co_init
|
||||
%define co_term _co_term
|
||||
%define co_active _co_active
|
||||
%define co_create _co_create
|
||||
%define co_delete _co_delete
|
||||
%define co_switch _co_switch
|
||||
%define co_exit _co_exit
|
||||
%endif
|
||||
|
||||
extern malloc
|
||||
|
@ -44,26 +56,22 @@ global co_term
|
|||
global co_active
|
||||
global co_create
|
||||
global co_delete
|
||||
global co_jump
|
||||
global co_call
|
||||
global co_return
|
||||
global co_switch
|
||||
global co_exit
|
||||
|
||||
;*****
|
||||
;extern "C" void fastcall co_init();
|
||||
;extern "C" cothread_t fastcall co_init();
|
||||
;return = eax
|
||||
;*****
|
||||
|
||||
align 16
|
||||
co_init:
|
||||
cmp dword[co_initialized],0 ;only run co_init once
|
||||
jne .end
|
||||
inc dword[co_initialized]
|
||||
|
||||
;create context for main thread
|
||||
;create context for main cothread
|
||||
mov ecx,0 ;entry point for main thread is not needed
|
||||
mov edx,256 ;main thread uses default program stack
|
||||
mov edx,512 ;main cothread uses default program stack
|
||||
call co_create
|
||||
mov dword[co_active_context],eax
|
||||
.end
|
||||
mov dword[co_primary_context],eax
|
||||
ret
|
||||
|
||||
;*****
|
||||
|
@ -72,24 +80,22 @@ co_init:
|
|||
|
||||
align 16
|
||||
co_term:
|
||||
mov ecx,dword[co_primary_context]
|
||||
call co_delete
|
||||
ret
|
||||
|
||||
;*****
|
||||
;extern "C" thread_t fastcall co_active();
|
||||
;extern "C" cothread_t fastcall co_active();
|
||||
;return = eax
|
||||
;*****
|
||||
|
||||
align 16
|
||||
co_active:
|
||||
cmp dword[co_initialized],0 ;make sure co_init has been called
|
||||
jne .next
|
||||
call co_init
|
||||
.next:
|
||||
mov eax,dword[co_active_context]
|
||||
ret
|
||||
|
||||
;*****
|
||||
;extern "C" thread_t fastcall co_create(thread_p coentry, unsigned int heapsize);
|
||||
;extern "C" cothread_t fastcall co_create(cothread_p coentry, unsigned int heapsize);
|
||||
;ecx = coentry
|
||||
;edx = heapsize
|
||||
;return = eax
|
||||
|
@ -97,17 +103,8 @@ co_active:
|
|||
|
||||
align 16
|
||||
co_create:
|
||||
cmp dword[co_initialized],0 ;make sure co_init has been called
|
||||
jne .next
|
||||
push ecx
|
||||
push edx
|
||||
call co_init
|
||||
pop edx
|
||||
pop ecx
|
||||
.next:
|
||||
|
||||
;create heap space (stack + register storage)
|
||||
add edx,28 ;+8(esp+prev_call_context)+4(coentry)+16(stack_align)
|
||||
add edx,512 ;+4(esp)+4(coentry)+4(colink)+256(stack_align)
|
||||
push ecx
|
||||
push edx
|
||||
|
||||
|
@ -119,10 +116,10 @@ co_create:
|
|||
pop ecx
|
||||
|
||||
add edx,eax ;set edx to point to top of stack heap
|
||||
and edx,0xfffffff0 ;force 16-byte alignment of stack heap
|
||||
and edx,0xffffff00 ;force 256-byte alignment of stack heap
|
||||
|
||||
;store thread entry point + registers so that first call to co_jump will go to coentry
|
||||
mov dword[edx-4],ecx ;edx=*stack,ecx=coentry
|
||||
;store thread entry point + registers so that first call to co_switch will execute coentry
|
||||
mov dword[edx-4],co_entrypoint ;edx=*stack
|
||||
mov dword[edx-8],0
|
||||
mov dword[edx-12],0
|
||||
mov dword[edx-16],0
|
||||
|
@ -130,13 +127,15 @@ co_create:
|
|||
sub edx,20
|
||||
|
||||
;initialize context memory heap
|
||||
mov dword[eax],edx ;thread_t[0-3] = stack heap pointer (esp)
|
||||
mov dword[eax+4],0 ;thread_t[4-7] = (null) pointer to prev_call_context
|
||||
mov dword[eax],edx ;cothread_t[ 0- 3] = stack heap pointer (esp)
|
||||
mov dword[eax+4],ecx ;cothread_t[ 4- 7] = entry point
|
||||
mov ecx,dword[co_active_context]
|
||||
mov dword[eax+8],ecx ;cothread_t[ 8-11] = return context
|
||||
|
||||
ret ;return allocated memory block as thread handle
|
||||
|
||||
;*****
|
||||
;extern "C" void fastcall co_delete(thread_t cothread);
|
||||
;extern "C" void fastcall co_delete(cothread_t cothread);
|
||||
;ecx = cothread
|
||||
;*****
|
||||
|
||||
|
@ -148,12 +147,12 @@ co_delete:
|
|||
ret
|
||||
|
||||
;*****
|
||||
;extern "C" void fastcall co_jump(thread_t cothread);
|
||||
;extern "C" void fastcall co_switch(cothread_t cothread);
|
||||
;ecx = cothread
|
||||
;*****
|
||||
|
||||
align 16
|
||||
co_jump:
|
||||
co_switch:
|
||||
mov eax,dword[co_active_context] ;backup current context
|
||||
mov dword[co_active_context],ecx ;set new active context
|
||||
|
||||
|
@ -172,50 +171,27 @@ co_jump:
|
|||
ret
|
||||
|
||||
;*****
|
||||
;extern "C" void fastcall co_call(thread_t cothread);
|
||||
;extern "C" void fastcall co_exit(cothread_t cothread);
|
||||
;ecx = cothread
|
||||
;*****
|
||||
|
||||
align 16
|
||||
co_call:
|
||||
mov eax,dword[co_active_context] ;backup current context
|
||||
mov dword[co_active_context],ecx ;set new active context
|
||||
mov dword[ecx+4],eax
|
||||
co_exit:
|
||||
cmp ecx,0
|
||||
jne co_switch
|
||||
|
||||
push ebp
|
||||
push esi
|
||||
push edi
|
||||
push ebx
|
||||
mov dword[eax],esp
|
||||
|
||||
mov esp,dword[ecx]
|
||||
pop ebx
|
||||
pop edi
|
||||
pop esi
|
||||
pop ebp
|
||||
|
||||
ret
|
||||
;if cothread is null, switch to context that created current context
|
||||
mov eax,dword[co_active_context]
|
||||
mov ecx,dword[eax+8]
|
||||
jmp co_switch
|
||||
|
||||
;*****
|
||||
;extern "C" void fastcall co_return();
|
||||
;void fastcall co_entrypoint();
|
||||
;*****
|
||||
|
||||
align 16
|
||||
co_return:
|
||||
mov eax,dword[co_active_context] ;backup current context
|
||||
mov ecx,dword[eax+4] ;restore pre-call context
|
||||
mov dword[co_active_context],ecx ;set new active context
|
||||
|
||||
push ebp
|
||||
push esi
|
||||
push edi
|
||||
push ebx
|
||||
mov dword[eax],esp
|
||||
|
||||
mov esp,dword[ecx]
|
||||
pop ebx
|
||||
pop edi
|
||||
pop esi
|
||||
pop ebp
|
||||
|
||||
ret
|
||||
co_entrypoint:
|
||||
mov eax,dword[co_active_context]
|
||||
call dword[eax+4]
|
||||
xor ecx,ecx
|
||||
jmp co_exit
|
||||
|
|
|
@ -1,15 +1,20 @@
|
|||
/*
|
||||
libco_x86 : version 0.06 ~byuu (05/21/2006)
|
||||
libco_x86 : version 0.08 ~byuu (10/21/2006)
|
||||
*/
|
||||
|
||||
typedef void (*thread_t);
|
||||
typedef void (*thread_p)();
|
||||
#define COTHREAD_STACKSIZE_TINY 0x1000
|
||||
#define COTHREAD_STACKSIZE_SMALL 0x4000
|
||||
#define COTHREAD_STACKSIZE_NORMAL 0x10000
|
||||
#define COTHREAD_STACKSIZE_LARGE 0x40000
|
||||
#define COTHREAD_STACKSIZE_HUGE 0x100000
|
||||
|
||||
extern "C" void fastcall co_init();
|
||||
extern "C" void fastcall co_term();
|
||||
extern "C" thread_t fastcall co_active();
|
||||
extern "C" thread_t fastcall co_create(thread_p coentry, unsigned int heapsize);
|
||||
extern "C" void fastcall co_delete(thread_t cothread);
|
||||
extern "C" void fastcall co_jump(thread_t cothread);
|
||||
extern "C" void fastcall co_call(thread_t cothread);
|
||||
extern "C" void fastcall co_return();
|
||||
typedef void (*cothread_t);
|
||||
typedef void (*cothread_p)(void);
|
||||
|
||||
extern "C" cothread_t fastcall co_init();
|
||||
extern "C" void fastcall co_term();
|
||||
extern "C" cothread_t fastcall co_active();
|
||||
extern "C" cothread_t fastcall co_create(cothread_p coentry, unsigned int heapsize);
|
||||
extern "C" void fastcall co_delete(cothread_t cothread);
|
||||
extern "C" void fastcall co_switch(cothread_t cothread);
|
||||
extern "C" void fastcall co_exit(cothread_t cothread);
|
||||
|
|
|
@ -14,7 +14,7 @@ void Setting::set(uint _data) {
|
|||
data = _data;
|
||||
|
||||
switch(type) {
|
||||
case TRUE_FALSE:
|
||||
case BOOL:
|
||||
case ENABLED_DISABLED:
|
||||
case ON_OFF:
|
||||
case YES_NO:
|
||||
|
@ -32,22 +32,20 @@ void Setting::set(uint _data) {
|
|||
}
|
||||
}
|
||||
|
||||
char *Setting::sget() {
|
||||
char *Setting::strget() {
|
||||
return strptr(char_data);
|
||||
}
|
||||
|
||||
void Setting::sset(const char *_data) {
|
||||
void Setting::strset(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) {
|
||||
_parent->add(this);
|
||||
}
|
||||
|
||||
s = strlen(_name);
|
||||
uint s = strlen(_name);
|
||||
name = (char*)malloc(s + 1);
|
||||
strcpy(name, _name);
|
||||
|
||||
|
@ -66,12 +64,11 @@ int s;
|
|||
}
|
||||
|
||||
Setting::Setting(Config *_parent, char *_name, char *_desc, char *_data) {
|
||||
int s;
|
||||
if(_parent) {
|
||||
_parent->add(this);
|
||||
}
|
||||
|
||||
s = strlen(_name);
|
||||
uint s = strlen(_name);
|
||||
name = (char*)malloc(s + 1);
|
||||
strcpy(name, _name);
|
||||
|
||||
|
@ -87,7 +84,7 @@ int s;
|
|||
strcpy(char_data, _data);
|
||||
strcpy(char_def, _data);
|
||||
|
||||
type = STR;
|
||||
type = STRING;
|
||||
}
|
||||
|
||||
void Config::add(Setting *setting) {
|
||||
|
@ -95,18 +92,18 @@ void Config::add(Setting *setting) {
|
|||
}
|
||||
|
||||
uint Config::string_to_uint(uint type, char *input) {
|
||||
if(strmatch(input, "true") ||
|
||||
strmatch(input, "enabled") ||
|
||||
strmatch(input, "on") ||
|
||||
strmatch(input, "yes")
|
||||
if(!strcmp(input, "true") ||
|
||||
!strcmp(input, "enabled") ||
|
||||
!strcmp(input, "on") ||
|
||||
!strcmp(input, "yes")
|
||||
) {
|
||||
return (uint)true;
|
||||
}
|
||||
|
||||
if(strmatch(input, "false") ||
|
||||
strmatch(input, "disabled") ||
|
||||
strmatch(input, "off") ||
|
||||
strmatch(input, "no")
|
||||
if(!strcmp(input, "false") ||
|
||||
!strcmp(input, "disabled") ||
|
||||
!strcmp(input, "off") ||
|
||||
!strcmp(input, "no")
|
||||
) {
|
||||
return (uint)false;
|
||||
}
|
||||
|
@ -121,7 +118,7 @@ uint Config::string_to_uint(uint type, char *input) {
|
|||
char *Config::uint_to_string(uint type, uint input) {
|
||||
static char output[512];
|
||||
switch(type) {
|
||||
case Setting::TRUE_FALSE:
|
||||
case Setting::BOOL:
|
||||
sprintf(output, "%s", (input & 1) ? "true" : "false");
|
||||
break;
|
||||
case Setting::ENABLED_DISABLED:
|
||||
|
@ -144,7 +141,7 @@ static char output[512];
|
|||
return output;
|
||||
}
|
||||
|
||||
bool Config::load(char *fn) {
|
||||
bool Config::load(const char *fn) {
|
||||
FILE *fp;
|
||||
fp = fopen(fn, "rb");
|
||||
if(!fp)return false;
|
||||
|
@ -172,11 +169,12 @@ char *buffer = (char*)malloc(fsize + 1);
|
|||
|
||||
qsplit(part, "=", line[i]);
|
||||
for(int l = 0; l < list_count; l++) {
|
||||
if(strmatch(list[l]->name, part[0])) {
|
||||
if(!strcmp(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]));
|
||||
list[l]->strset(strptr(part[1]));
|
||||
strunquote(list[l]->char_data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -186,7 +184,7 @@ char *buffer = (char*)malloc(fsize + 1);
|
|||
}
|
||||
bool Config::load(string &fn) { return load(strptr(fn)); }
|
||||
|
||||
bool Config::save(char *fn) {
|
||||
bool Config::save(const char *fn) {
|
||||
FILE *fp;
|
||||
fp = fopen(fn, "wb");
|
||||
if(!fp)return false;
|
||||
|
@ -198,7 +196,7 @@ FILE *fp;
|
|||
for(int l = 0; l < count(line); l++) {
|
||||
fprintf(fp, "# %s\r\n", strptr(line[l]));
|
||||
}
|
||||
if(list[i]->type != Setting::STR) {
|
||||
if(list[i]->type != Setting::STRING) {
|
||||
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 {
|
||||
|
@ -207,6 +205,7 @@ FILE *fp;
|
|||
}
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
return true;
|
||||
}
|
||||
bool Config::save(string &fn) { return save(strptr(fn)); }
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
libconfig : version 0.10 ~byuu (10/10/06)
|
||||
libconfig : version 0.11 ~byuu (2006/11/12)
|
||||
*/
|
||||
|
||||
#ifndef __LIBCONFIG
|
||||
|
@ -30,16 +30,18 @@ enum {
|
|||
HEX16 = 7,
|
||||
HEX24 = 8,
|
||||
HEX32 = 9,
|
||||
STRING = 10,
|
||||
STR = 10,
|
||||
};
|
||||
|
||||
char *name, *desc;
|
||||
string char_data, char_def;
|
||||
virtual void toggle();
|
||||
virtual uint get();
|
||||
virtual void set(uint _data);
|
||||
|
||||
virtual char *sget();
|
||||
virtual void sset(const char *_data);
|
||||
virtual char *strget();
|
||||
virtual void strset(const char *_data);
|
||||
|
||||
Setting(Config *_parent, char *_name, char *_desc, uint _data, uint _type);
|
||||
Setting(Config *_parent, char *_name, char *_desc, char *_data);
|
||||
|
@ -52,6 +54,12 @@ string char_data, char_def;
|
|||
template<typename T> inline bool operator> (const T &x) { return (T)get() > x; }
|
||||
template<typename T> inline bool operator<=(const T &x) { return (T)get() <= x; }
|
||||
template<typename T> inline bool operator< (const T &x) { return (T)get() < x; }
|
||||
|
||||
inline operator char*() { return strget(); }
|
||||
inline Setting &operator=(char *x) { strset(x); return *this; }
|
||||
inline Setting &operator=(const char *x) { strset(x); return *this; }
|
||||
inline bool operator==(const char *x) { return !strcmp(strget(), x); }
|
||||
inline bool operator!=(const char *x) { return strcmp(strget(), x); }
|
||||
};
|
||||
|
||||
class Config {
|
||||
|
@ -67,9 +75,9 @@ char *uint_to_string(uint type, uint input);
|
|||
|
||||
public:
|
||||
void add(Setting *setting);
|
||||
bool load(char *fn);
|
||||
bool load(const char *fn);
|
||||
bool load(string &fn);
|
||||
bool save(char *fn);
|
||||
bool save(const char *fn);
|
||||
bool save(string &fn);
|
||||
Config();
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
libfile : version 0.05 ~byuu (10/12/06)
|
||||
libfile : version 0.05a ~byuu (10/26/06)
|
||||
*/
|
||||
|
||||
#ifndef __LIBFILE
|
||||
|
@ -51,10 +51,12 @@ uint32 crc32 = 0xffffffff;
|
|||
inline void fread(file &s, uint8 *data, uint length) { s.read(data, length); }
|
||||
inline uint8 fread(file &s) { return s.read(); }
|
||||
inline uint8 fgetc(file &s) { return s.read(); }
|
||||
inline uint fgetb(file &s) { return s.read(); }
|
||||
|
||||
inline void fwrite(file &s, uint8 *data, uint length) { s.write(data, length); }
|
||||
inline void fwrite(file &s, uint8 data) { s.write(data); }
|
||||
inline void fputc(file &s, uint8 data) { s.write(data); }
|
||||
inline void fputc(uint8 data, file &s) { s.write(data); }
|
||||
inline void fputb(file &s, uint8 data) { s.write(data); }
|
||||
|
||||
inline uint32 fcrc32(file &s) { return s.crc32(); }
|
||||
|
||||
|
@ -107,53 +109,53 @@ inline uint64 fgetmq(file &s) {
|
|||
((uint64)fgetc(s) << 8) | ((uint64)fgetc(s) << 0);
|
||||
}
|
||||
|
||||
inline void fputlb(file &s, uint8 data) { fputc(s, data); }
|
||||
inline void fputmb(file &s, uint8 data) { fputc(s, data); }
|
||||
inline void fputlb(file &s, uint8 data) { fputc(data, s); }
|
||||
inline void fputmb(file &s, uint8 data) { fputc(data, s); }
|
||||
|
||||
inline void fputlw(file &s, uint16 data) {
|
||||
fputc(s, data >> 0);
|
||||
fputc(s, data >> 8);
|
||||
fputc(data >> 0, s);
|
||||
fputc(data >> 8, s);
|
||||
}
|
||||
|
||||
inline void fputmw(file &s, uint16 data) {
|
||||
fputc(s, data >> 8);
|
||||
fputc(s, data >> 0);
|
||||
fputc(data >> 8, s);
|
||||
fputc(data >> 0, s);
|
||||
}
|
||||
|
||||
inline void fputld(file &s, uint32 data) {
|
||||
fputc(s, data >> 0);
|
||||
fputc(s, data >> 8);
|
||||
fputc(s, data >> 16);
|
||||
fputc(s, data >> 24);
|
||||
fputc(data >> 0, s);
|
||||
fputc(data >> 8, s);
|
||||
fputc(data >> 16, s);
|
||||
fputc(data >> 24, s);
|
||||
}
|
||||
|
||||
inline void fputmd(file &s, uint32 data) {
|
||||
fputc(s, data >> 24);
|
||||
fputc(s, data >> 16);
|
||||
fputc(s, data >> 8);
|
||||
fputc(s, data >> 0);
|
||||
fputc(data >> 24, s);
|
||||
fputc(data >> 16, s);
|
||||
fputc(data >> 8, s);
|
||||
fputc(data >> 0, s);
|
||||
}
|
||||
|
||||
inline void fputlq(file &s, uint64 data) {
|
||||
fputc(s, data >> 0);
|
||||
fputc(s, data >> 8);
|
||||
fputc(s, data >> 16);
|
||||
fputc(s, data >> 24);
|
||||
fputc(s, data >> 32);
|
||||
fputc(s, data >> 40);
|
||||
fputc(s, data >> 48);
|
||||
fputc(s, data >> 56);
|
||||
fputc(data >> 0, s);
|
||||
fputc(data >> 8, s);
|
||||
fputc(data >> 16, s);
|
||||
fputc(data >> 24, s);
|
||||
fputc(data >> 32, s);
|
||||
fputc(data >> 40, s);
|
||||
fputc(data >> 48, s);
|
||||
fputc(data >> 56, s);
|
||||
}
|
||||
|
||||
inline void fputmq(file &s, uint64 data) {
|
||||
fputc(s, data >> 56);
|
||||
fputc(s, data >> 48);
|
||||
fputc(s, data >> 40);
|
||||
fputc(s, data >> 32);
|
||||
fputc(s, data >> 24);
|
||||
fputc(s, data >> 16);
|
||||
fputc(s, data >> 8);
|
||||
fputc(s, data >> 0);
|
||||
fputc(data >> 56, s);
|
||||
fputc(data >> 48, s);
|
||||
fputc(data >> 40, s);
|
||||
fputc(data >> 32, s);
|
||||
fputc(data >> 24, s);
|
||||
fputc(data >> 16, s);
|
||||
fputc(data >> 8, s);
|
||||
fputc(data >> 0, s);
|
||||
}
|
||||
|
||||
/*****
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
libsort : version 0.01 ~byuu (2006-11-15)
|
||||
*/
|
||||
|
||||
#ifndef __LIBSORT
|
||||
#define __LIBSORT
|
||||
|
||||
template<typename T>
|
||||
void sort(T list[], uint length) {
|
||||
for(uint d = 0; d < length; d++) {
|
||||
uint min = d;
|
||||
for(uint s = d + 1; s < length; s++) {
|
||||
if(list[s] < list[min]) { min = s; }
|
||||
}
|
||||
if(min != d) {
|
||||
swap(list[d], list[min]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T, typename Tcmp>
|
||||
void sort(T list[], uint length, Tcmp comparator) {
|
||||
for(uint d = 0; d < length; d++) {
|
||||
uint min = d;
|
||||
for(uint s = d + 1; s < length; s++) {
|
||||
if(comparator(list[s], list[min]) == true) { min = s; }
|
||||
}
|
||||
if(min != d) {
|
||||
swap(list[d], list[min]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif __LIBSORT
|
|
@ -1,5 +1,6 @@
|
|||
#include "libbase.h"
|
||||
#include "libstring.h"
|
||||
#include "libstring_oo.cpp"
|
||||
|
||||
uint count(stringarray &str) { return str.size(); }
|
||||
|
||||
|
@ -13,12 +14,6 @@ char chrupper(char c) {
|
|||
return c;
|
||||
}
|
||||
|
||||
void strresize(string &str, uint size) {
|
||||
str.s = (char*)realloc(str.s, size + 1);
|
||||
str.s[size] = 0;
|
||||
str.size = size;
|
||||
}
|
||||
|
||||
char *strptr(string &str) { return str.s; }
|
||||
|
||||
uint strlen(string &str) { return strlen(strptr(str)); }
|
||||
|
@ -39,49 +34,41 @@ int stricmp(string &dest, const char *src) { return __stricmp(strptr(dest), src)
|
|||
int stricmp(const char *dest, string &src) { return __stricmp(dest, strptr(src)); }
|
||||
int stricmp(string &dest, string &src) { return __stricmp(strptr(dest), strptr(src)); }
|
||||
|
||||
bool strmatch(const char *dest, const char *src) { return !strcmp(dest, src); }
|
||||
bool strmatch(string &dest, const char *src) { return strmatch(strptr(dest), src); }
|
||||
bool strmatch(const char *dest, string &src) { return strmatch(dest, strptr(src)); }
|
||||
bool strmatch(string &dest, string &src) { return strmatch(strptr(dest), strptr(src)); }
|
||||
|
||||
bool strimatch(const char *dest, const char *src) { return !stricmp(dest, src); }
|
||||
bool strimatch(string &dest, const char *src) { return strimatch(strptr(dest), src); }
|
||||
bool strimatch(const char *dest, string &src) { return strimatch(dest, strptr(src)); }
|
||||
bool strimatch(string &dest, string &src) { return strimatch(strptr(dest), strptr(src)); }
|
||||
|
||||
void strcpy(string &dest, const char src) {
|
||||
if(1 > dest.size) { strresize(dest, 1); }
|
||||
dest.reserve(2);
|
||||
dest.s[0] = src;
|
||||
dest.s[1] = 0;
|
||||
}
|
||||
|
||||
void strcpy(string &dest, const char *src) {
|
||||
int srclen = strlen(src);
|
||||
if(srclen > dest.size) { strresize(dest, srclen); }
|
||||
dest.reserve(srclen);
|
||||
strcpy(dest.s, src);
|
||||
}
|
||||
void strcpy(string &dest, string &src) { strcpy(dest, strptr(src)); }
|
||||
|
||||
//this differs from libc's strncpy in that it always
|
||||
//appends a null terminator to the end of a copied string
|
||||
void strncpy(string &dest, const char *src, uint32 length) {
|
||||
int srclen = strlen(src);
|
||||
//never copy more text than is in the string
|
||||
if(srclen > length)srclen = length;
|
||||
if(srclen > dest.size) { strresize(dest, srclen); }
|
||||
strncpy(dest.s, src, srclen);
|
||||
dest.s[srclen] = 0;
|
||||
uint strlcpy(char *dest, const char *src, uint length) {
|
||||
uint srclen = strlen(src);
|
||||
length--;
|
||||
if(length > srclen)length = srclen;
|
||||
memcpy(dest, src, length);
|
||||
dest[length] = 0;
|
||||
return srclen;
|
||||
}
|
||||
void strncpy(string &dest, string &src, uint32 length) { strncpy(dest, strptr(src), length); }
|
||||
|
||||
void strset(string &dest, uint pos, uint8 c) {
|
||||
if(pos > dest.size) { strresize(dest, pos); }
|
||||
dest.s[pos] = c;
|
||||
uint strlcpy(string &dest, const char *src, uint length) {
|
||||
dest.reserve(length);
|
||||
return strlcpy(strptr(dest), src, length);
|
||||
}
|
||||
|
||||
uint strlcpy(string &dest, string &src, uint length) {
|
||||
dest.reserve(length);
|
||||
return strlcpy(strptr(dest), strptr(src), length);
|
||||
}
|
||||
|
||||
void strcat(string &dest, const char src) {
|
||||
int length = strlen(dest);
|
||||
if(length + 1 > dest.size) { strresize(dest, length + 1); }
|
||||
dest.reserve(length + 1);
|
||||
dest.s[length] = src;
|
||||
dest.s[length + 1] = 0;
|
||||
}
|
||||
|
@ -89,32 +76,62 @@ int length = strlen(dest);
|
|||
void strcat(string &dest, const char *src) {
|
||||
int srclen = strlen(src);
|
||||
int destlen = strlen(dest);
|
||||
if(srclen + destlen > dest.size) { strresize(dest, srclen + destlen); }
|
||||
dest.reserve(srclen + destlen);
|
||||
strcat(dest.s, src);
|
||||
}
|
||||
void strcat(string &dest, string &src) { strcat(dest, strptr(src)); }
|
||||
|
||||
uint strlcat(char *dest, const char *src, uint length) {
|
||||
uint destlen = strlen(dest), srclen = strlen(src);
|
||||
length--;
|
||||
if(length > destlen + srclen)length = destlen + srclen;
|
||||
memcpy(dest + destlen, src, length - destlen);
|
||||
dest[length] = 0;
|
||||
return destlen + srclen;
|
||||
}
|
||||
|
||||
uint strlcat(string &dest, const char *src, uint length) {
|
||||
dest.reserve(length);
|
||||
return strlcat(strptr(dest), src, length);
|
||||
}
|
||||
|
||||
uint strlcat(string &dest, string &src, uint length) {
|
||||
dest.reserve(length);
|
||||
return strlcat(strptr(dest), strptr(src), length);
|
||||
}
|
||||
|
||||
string substr(string &dest, const char *src, uint start, uint length) {
|
||||
string temp;
|
||||
if(length == 0) {
|
||||
//copy entire string
|
||||
strcpy(temp, src + start);
|
||||
} else {
|
||||
//copy partial string
|
||||
strlcpy(temp, src + start, length + 1);
|
||||
}
|
||||
return temp;
|
||||
}
|
||||
|
||||
string substr(string &dest, string &src, uint start, uint length) { return substr(dest, strptr(src), start, length); }
|
||||
|
||||
void strinsert(string &dest, const char *src, uint pos) {
|
||||
static string s;
|
||||
strcpy(s, strptr(dest) + pos);
|
||||
strset(dest, pos, 0);
|
||||
string temp;
|
||||
strcpy(temp, strptr(dest) + pos);
|
||||
dest[pos] = 0;
|
||||
strcat(dest, src);
|
||||
strcat(dest, s);
|
||||
strcat(dest, temp);
|
||||
}
|
||||
void strinsert(string &dest, string &src, uint pos) { strinsert(dest, strptr(src), pos); }
|
||||
|
||||
void strremove(string &dest, uint start, uint length) {
|
||||
int destlen;
|
||||
char *s;
|
||||
int i, sl = strlen(dest.s);
|
||||
if(start > dest.size) { strresize(dest, start); }
|
||||
int i, destlen = strlen(dest);
|
||||
dest.reserve(start);
|
||||
if(!length) {
|
||||
strset(dest, start, 0);
|
||||
dest[start] = 0;
|
||||
return;
|
||||
}
|
||||
s = dest.s;
|
||||
for(i=start;i<sl;i++) { s[i] = s[i+length]; }
|
||||
s[i] = 0;
|
||||
for(i = start; i < destlen; i++) { dest.s[i] = dest.s[i + length]; }
|
||||
dest.s[i] = 0;
|
||||
}
|
||||
|
||||
char *strlower(char *str) {
|
||||
|
@ -401,7 +418,7 @@ uint mask = 1000000000;
|
|||
}
|
||||
|
||||
string &utoa(string &str, uint num) {
|
||||
if(str.size < 16) { strresize(str, 16); }
|
||||
str.reserve(16);
|
||||
utoa(strptr(str), num);
|
||||
return str;
|
||||
}
|
||||
|
@ -418,7 +435,7 @@ char *pstr = str;
|
|||
}
|
||||
|
||||
string &itoa(string &str, uint num) {
|
||||
if(str.size < 16) { strresize(str, 16); }
|
||||
str.reserve(16);
|
||||
itoa(strptr(str), num);
|
||||
return str;
|
||||
}
|
||||
|
@ -441,7 +458,7 @@ uint mask = 28, r;
|
|||
}
|
||||
|
||||
string &htoa(string &str, uint num) {
|
||||
if(str.size < 16) { strresize(str, 16); }
|
||||
str.reserve(16);
|
||||
htoa(strptr(str), num);
|
||||
return str;
|
||||
}
|
||||
|
@ -464,7 +481,7 @@ uint mask = 28, r;
|
|||
}
|
||||
|
||||
string &uhtoa(string &str, uint num) {
|
||||
if(str.size < 16) { strresize(str, 16); }
|
||||
str.reserve(16);
|
||||
uhtoa(strptr(str), num);
|
||||
return str;
|
||||
}
|
||||
|
@ -485,7 +502,7 @@ uint mask = 0x80000000;
|
|||
}
|
||||
|
||||
string &btoa(string &str, uint num) {
|
||||
if(str.size < 48) { strresize(str, 48); }
|
||||
str.reserve(48);
|
||||
btoa(strptr(str), num);
|
||||
return str;
|
||||
}
|
||||
|
@ -507,6 +524,7 @@ char *fdata = (char*)malloc(size + 1);
|
|||
return true;
|
||||
}
|
||||
|
||||
#include "libstring_int.cpp"
|
||||
#include "libstring_math.cpp"
|
||||
#include "libstring_split.cpp"
|
||||
#include "libstring_replace.cpp"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
libstring : version 0.12 ~byuu (10/05/06)
|
||||
libstring : version 0.14b ~byuu (2006/11/17)
|
||||
*/
|
||||
|
||||
#ifndef __LIBSTRING
|
||||
|
@ -15,10 +15,7 @@ char chrupper(char c);
|
|||
|
||||
uint count(stringarray &str);
|
||||
|
||||
void strresize(string &str, uint size);
|
||||
|
||||
char* strptr(string &str);
|
||||
|
||||
char *strptr(string &str);
|
||||
uint strlen(string &str);
|
||||
|
||||
int strcmp(string &dest, const char *src);
|
||||
|
@ -34,26 +31,21 @@ int stricmp(string &dest, const char *src);
|
|||
int stricmp(const char *dest, string &src);
|
||||
int stricmp(string &dest, string &src);
|
||||
|
||||
bool strmatch(const char *dest, const char *src);
|
||||
bool strmatch(string &dest, const char *src);
|
||||
bool strmatch(const char *dest, string &src);
|
||||
bool strmatch(string &dest, string &src);
|
||||
|
||||
bool strimatch(const char *dest, const char *src);
|
||||
bool strimatch(string &dest, const char *src);
|
||||
bool strimatch(const char *dest, string &src);
|
||||
bool strimatch(string &dest, string &src);
|
||||
|
||||
void strcpy(string &dest, const char *src);
|
||||
void strcpy(string &dest, string &src);
|
||||
void strncpy(string &dest, const char *src, uint32 length);
|
||||
void strncpy(string &dest, string &src, uint32 length);
|
||||
|
||||
void strset(string &dest, uint pos, uint8 c);
|
||||
uint strlcpy(char *dest, const char *src, uint length);
|
||||
uint strlcpy(string &dest, const char *src, uint length);
|
||||
uint strlcpy(string &dest, string &src, uint length);
|
||||
|
||||
void strcat(string &dest, const char src);
|
||||
void strcat(string &dest, const char *src);
|
||||
void strcat(string &dest, string &src);
|
||||
uint strlcat(char *dest, const char *src, uint length);
|
||||
uint strlcat(string &dest, const char *src, uint length);
|
||||
uint strlcat(string &dest, string &src, uint length);
|
||||
|
||||
string substr(string &dest, const char *src, uint start = 0, uint length = 0);
|
||||
string substr(string &dest, string &src, uint start = 0, uint length = 0);
|
||||
|
||||
void strinsert(string &dest, const char *src, uint pos);
|
||||
void strinsert(string &dest, string &src, uint pos);
|
||||
|
@ -143,6 +135,8 @@ string &btoa(string &str, uint num);
|
|||
|
||||
bool strfread(string &str, const char *filename);
|
||||
|
||||
string strfmt(const char *fmt, int num);
|
||||
|
||||
int strmath(const char *in_str);
|
||||
int strmath(string &in_str);
|
||||
|
||||
|
@ -165,20 +159,68 @@ class string {
|
|||
public:
|
||||
char *s;
|
||||
uint size;
|
||||
void reserve(uint reqsize) {
|
||||
if(reqsize > size) {
|
||||
size = reqsize;
|
||||
s = (char*)realloc(s, size + 1);
|
||||
s[size] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void swap(string &str) {
|
||||
::swap(s, str.s);
|
||||
::swap(size, str.size);
|
||||
}
|
||||
|
||||
string() {
|
||||
size = 16;
|
||||
s = (char*)malloc(size + 1);
|
||||
*s = 0;
|
||||
s[0] = 0;
|
||||
}
|
||||
|
||||
~string() { SafeFree(s); }
|
||||
|
||||
void operator=(const string &p) {
|
||||
SafeFree(s);
|
||||
size = p.size;
|
||||
string(const char *str) {
|
||||
size = strlen(str);
|
||||
s = (char*)malloc(size + 1);
|
||||
strcpy(s, p.s);
|
||||
strcpy(s, str);
|
||||
}
|
||||
|
||||
string(string &str) {
|
||||
size = strlen(str);
|
||||
s = (char*)malloc(size + 1);
|
||||
strcpy(s, strptr(str));
|
||||
}
|
||||
|
||||
~string() { safe_free(s); }
|
||||
|
||||
const char *operator()();
|
||||
char &operator[](uint);
|
||||
string &operator=(int);
|
||||
string &operator=(const char *);
|
||||
string &operator=(string &);
|
||||
string &operator+=(int);
|
||||
string &operator+=(const char *);
|
||||
string &operator+=(string &);
|
||||
bool operator==(const char *);
|
||||
bool operator==(string &);
|
||||
bool operator!=(const char *);
|
||||
bool operator!=(string &);
|
||||
bool operator<(const char *);
|
||||
bool operator<(string &);
|
||||
bool operator<=(const char *);
|
||||
bool operator<=(string &);
|
||||
bool operator>(const char *);
|
||||
bool operator>(string &);
|
||||
bool operator>=(const char *);
|
||||
bool operator>=(string &);
|
||||
|
||||
string operator+(int);
|
||||
string operator+(const char *);
|
||||
string operator+(string &);
|
||||
};
|
||||
|
||||
string operator+(int, string &);
|
||||
string operator+(const char *, string &);
|
||||
|
||||
inline void swap(string &x, string &y) { x.swap(y); }
|
||||
|
||||
#endif //__LIBSTRING
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
string strfmt(const char *fmt, int num) {
|
||||
string temp;
|
||||
sprintf(temp, fmt, num);
|
||||
return temp;
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
const char *string::operator()() {
|
||||
return s;
|
||||
}
|
||||
|
||||
char &string::operator[](const uint index) {
|
||||
reserve(index);
|
||||
return s[index];
|
||||
}
|
||||
|
||||
string &string::operator=(int num) {
|
||||
strcpy(*this, strfmt("%d", num));
|
||||
return *this;
|
||||
}
|
||||
|
||||
string &string::operator=(const char *str) {
|
||||
strcpy(*this, str);
|
||||
return *this;
|
||||
}
|
||||
|
||||
string &string::operator=(string &str) {
|
||||
strcpy(*this, str);
|
||||
return *this;
|
||||
}
|
||||
|
||||
string &string::operator+=(int num) {
|
||||
strcat(*this, strfmt("%d", num));
|
||||
return *this;
|
||||
}
|
||||
|
||||
string &string::operator+=(const char *str) {
|
||||
strcat(*this, str);
|
||||
return *this;
|
||||
}
|
||||
|
||||
string &string::operator+=(string &str) {
|
||||
strcat(*this, str);
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool string::operator==(const char *str) { return strcmp(strptr(*this), str) == 0; }
|
||||
bool string::operator==(string &str) { return strcmp(strptr(*this), strptr(str)) == 0; }
|
||||
bool string::operator!=(const char *str) { return strcmp(strptr(*this), str) != 0; }
|
||||
bool string::operator!=(string &str) { return strcmp(strptr(*this), strptr(str)) != 0; }
|
||||
bool string::operator<(const char *str) { return strcmp(strptr(*this), str) < 0; }
|
||||
bool string::operator<(string &str) { return strcmp(strptr(*this), strptr(str)) < 0; }
|
||||
bool string::operator<=(const char *str) { return strcmp(strptr(*this), str) <= 0; }
|
||||
bool string::operator<=(string &str) { return strcmp(strptr(*this), strptr(str)) <= 0; }
|
||||
bool string::operator>(const char *str) { return strcmp(strptr(*this), str) > 0; }
|
||||
bool string::operator>(string &str) { return strcmp(strptr(*this), strptr(str)) > 0; }
|
||||
bool string::operator>=(const char *str) { return strcmp(strptr(*this), str) >= 0; }
|
||||
bool string::operator>=(string &str) { return strcmp(strptr(*this), strptr(str)) >= 0; }
|
||||
|
||||
string string::operator+(int num) {
|
||||
string temp(*this);
|
||||
strcat(temp, strfmt("%d", num));
|
||||
return temp;
|
||||
}
|
||||
|
||||
string string::operator+(const char *str) {
|
||||
string temp(*this);
|
||||
strcat(temp, str);
|
||||
return temp;
|
||||
}
|
||||
|
||||
string string::operator+(string &str) {
|
||||
string temp(*this);
|
||||
strcat(temp, str);
|
||||
return temp;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
string operator+(int x, string &y) {
|
||||
string temp(strfmt("%d", x));
|
||||
strcat(temp, y);
|
||||
return temp;
|
||||
}
|
||||
|
||||
string operator+(const char *x, string &y) {
|
||||
string temp(x);
|
||||
strcat(temp, y);
|
||||
return temp;
|
||||
}
|
|
@ -4,17 +4,17 @@ uint replace_count = 0, size = ssl;
|
|||
char *data;
|
||||
if(ksl > ssl)return str;
|
||||
if(tsl > ksl) { //the new string may be longer than the old string...
|
||||
for(i=0;i<=ssl-ksl;) { //so let's find out how big of a string we'll need...
|
||||
for(i = 0; i <= ssl - ksl;) { //so let's find out how big of a string we'll need...
|
||||
if(!memcmp(str.s + i, key, ksl)) {
|
||||
replace_count++;
|
||||
i += ksl;
|
||||
} else i++;
|
||||
}
|
||||
size = ssl + ((tsl - ksl) * replace_count);
|
||||
if(size > str.size)strresize(str, size);
|
||||
str.reserve(size);
|
||||
}
|
||||
data = (char*)malloc(size + 1);
|
||||
for(i=z=0;i<ssl;) {
|
||||
for(i = z = 0; i < ssl;) {
|
||||
if(i <= ssl - ksl) {
|
||||
if(!memcmp(str.s + i, key, ksl)) {
|
||||
memcpy(data + z, token, tsl);
|
||||
|
@ -37,7 +37,7 @@ uint8 x;
|
|||
char *data;
|
||||
if(ksl > ssl)return str;
|
||||
if(tsl > ksl) {
|
||||
for(i=0;i<=ssl-ksl;) {
|
||||
for(i = 0; i <= ssl - ksl;) {
|
||||
x = str.s[i];
|
||||
if(x == '\"' || x == '\'') {
|
||||
l = i;
|
||||
|
@ -55,10 +55,10 @@ char *data;
|
|||
} else i++;
|
||||
}
|
||||
size = ssl + ((tsl - ksl) * replace_count);
|
||||
if(size > str.size)strresize(str, size);
|
||||
str.reserve(size);
|
||||
}
|
||||
data = (char*)malloc(size + 1);
|
||||
for(i=z=0;i<ssl;) {
|
||||
for(i = z = 0; i < ssl;) {
|
||||
x = str.s[i];
|
||||
if(x == '\"' || x == '\'') {
|
||||
l = i++;
|
||||
|
|
|
@ -5,7 +5,7 @@ int ssl = strlen(src), ksl = strlen(key);
|
|||
int lp = 0, split_count = 0;
|
||||
for(int i = 0; i <= ssl - ksl;) {
|
||||
if(!memcmp(src + i, key, ksl)) {
|
||||
strncpy(dest[split_count++], src + lp, i - lp);
|
||||
strlcpy(dest[split_count++], src + lp, i - lp + 1);
|
||||
i += ksl;
|
||||
lp = i;
|
||||
} else i++;
|
||||
|
@ -27,7 +27,7 @@ int lp = 0, split_count = 0;
|
|||
if(i >= ssl)i = z;
|
||||
}
|
||||
if(!memcmp(src + i, key, ksl)) {
|
||||
strncpy(dest[split_count++], src + lp, i - lp);
|
||||
strlcpy(dest[split_count++], src + lp, i - lp + 1);
|
||||
i += ksl;
|
||||
lp = i;
|
||||
} else i++;
|
||||
|
|
|
@ -8,7 +8,7 @@ uint length = vsprintf(str, s, args);
|
|||
|
||||
uint vsprintf(string &str, const char *s, va_list args) {
|
||||
uint length = vsnprintf(0, 0, s, args);
|
||||
strresize(str, length + 1);
|
||||
str.reserve(length + 1);
|
||||
return vsprintf(strptr(str), s, args);
|
||||
}
|
||||
|
||||
|
|
|
@ -226,33 +226,33 @@ uint ptr = 0;
|
|||
template<typename FTO, typename FTM, typename FTP>
|
||||
void UPS<FTO, FTM, FTP>::ptr_write(uint ptr) {
|
||||
if(ptr <= 0xf7) {
|
||||
fputc(patch.fp, ptr);
|
||||
fputb(patch.fp, ptr);
|
||||
return;
|
||||
}
|
||||
|
||||
ptr -= 0xf8;
|
||||
if(ptr <= 0xffff) {
|
||||
fputc(patch.fp, 0xf8);
|
||||
fputc(patch.fp, ptr);
|
||||
fputc(patch.fp, ptr >> 8);
|
||||
fputb(patch.fp, 0xf8);
|
||||
fputb(patch.fp, ptr);
|
||||
fputb(patch.fp, ptr >> 8);
|
||||
return;
|
||||
}
|
||||
|
||||
ptr -= 0x10000;
|
||||
if(ptr <= 0xffffff) {
|
||||
fputc(patch.fp, 0xf9);
|
||||
fputc(patch.fp, ptr);
|
||||
fputc(patch.fp, ptr >> 8);
|
||||
fputc(patch.fp, ptr >> 16);
|
||||
fputb(patch.fp, 0xf9);
|
||||
fputb(patch.fp, ptr);
|
||||
fputb(patch.fp, ptr >> 8);
|
||||
fputb(patch.fp, ptr >> 16);
|
||||
return;
|
||||
}
|
||||
|
||||
ptr -= 0x1000000;
|
||||
fputc(patch.fp, 0xfa);
|
||||
fputc(patch.fp, ptr);
|
||||
fputc(patch.fp, ptr >> 8);
|
||||
fputc(patch.fp, ptr >> 16);
|
||||
fputc(patch.fp, ptr >> 24);
|
||||
fputb(patch.fp, 0xfa);
|
||||
fputb(patch.fp, ptr);
|
||||
fputb(patch.fp, ptr >> 8);
|
||||
fputb(patch.fp, ptr >> 16);
|
||||
fputb(patch.fp, ptr >> 24);
|
||||
}
|
||||
|
||||
template<typename FTO, typename FTM, typename FTP>
|
||||
|
@ -298,14 +298,14 @@ uint last_ptr = 0, rle_count, last_out, rep_count;
|
|||
ptr_write((i - 1) - last_ptr);
|
||||
|
||||
//data
|
||||
fputc(patch.fp, r);
|
||||
fputb(patch.fp, r);
|
||||
last_out = r;
|
||||
rep_count = 0;
|
||||
|
||||
do {
|
||||
r = fgetc(original) ^ fgetc(modified);
|
||||
i++;
|
||||
fputc(patch.fp, r);
|
||||
fputb(patch.fp, r);
|
||||
|
||||
if(last_out != r) {
|
||||
rep_count = 0;
|
||||
|
@ -319,7 +319,7 @@ uint last_ptr = 0, rle_count, last_out, rep_count;
|
|||
} while(i < largest_filesize);
|
||||
|
||||
ptr_write(rle_count);
|
||||
if(i < largest_filesize) { fputc(patch.fp, r); }
|
||||
if(i < largest_filesize) { fputb(patch.fp, r); }
|
||||
rep_count = 0;
|
||||
}
|
||||
}
|
||||
|
@ -331,7 +331,7 @@ uint last_ptr = 0, rle_count, last_out, rep_count;
|
|||
last_ptr = i;
|
||||
}
|
||||
|
||||
fputc(patch.fp, 0xff);
|
||||
fputb(patch.fp, 0xff);
|
||||
}
|
||||
|
||||
template<typename FTO, typename FTM, typename FTP>
|
||||
|
@ -385,7 +385,7 @@ void UPS<FTO, FTM, FTP>::apply_linear() {
|
|||
fseek(original, 0, file::seek_start);
|
||||
fseek(modified, 0, file::seek_start);
|
||||
for(uint i = 0; i < modified_filesize; i++) {
|
||||
fputc(modified, fgetc(original));
|
||||
fputb(modified, fgetc(original));
|
||||
}
|
||||
|
||||
fseek(original, 0, file::seek_start);
|
||||
|
@ -408,14 +408,14 @@ uint rle_count, last_in, rep_count;
|
|||
if(ftell(modified) >= modified_filesize) { break; }
|
||||
|
||||
uint8 r = fgetc(patch.fp);
|
||||
fputc(modified, r ^ fgetc(original));
|
||||
fputb(modified, r ^ fgetc(original));
|
||||
if(r != last_in) {
|
||||
rep_count = 0;
|
||||
} else {
|
||||
if(++rep_count == (3 - 1)) {
|
||||
rle_count = ptr_read();
|
||||
while(rle_count-- && ftell(modified) < modified_filesize) {
|
||||
fputc(modified, r ^ fgetc(original));
|
||||
fputb(modified, r ^ fgetc(original));
|
||||
}
|
||||
rep_count = 0;
|
||||
}
|
||||
|
|
|
@ -14,12 +14,12 @@ bool Button::Create(Window *parent_window, const char *style, int x, int y, int
|
|||
stringarray part;
|
||||
ParseStyleParam(style, part);
|
||||
for(int i = 0; i < count(part); i++) {
|
||||
if(strmatch(part[i], "visible"))state.ws |= WS_VISIBLE;
|
||||
if(strmatch(part[i], "disabled"))state.ws |= WS_DISABLED;
|
||||
if(!strcmp(part[i], "visible"))state.ws |= WS_VISIBLE;
|
||||
if(!strcmp(part[i], "disabled"))state.ws |= WS_DISABLED;
|
||||
|
||||
if(strmatch(part[i], "left"))state.ws |= BS_LEFT;
|
||||
if(strmatch(part[i], "center"))state.ws |= BS_CENTER;
|
||||
if(strmatch(part[i], "right"))state.ws |= BS_RIGHT;
|
||||
if(!strcmp(part[i], "left"))state.ws |= BS_LEFT;
|
||||
if(!strcmp(part[i], "center"))state.ws |= BS_CENTER;
|
||||
if(!strcmp(part[i], "right"))state.ws |= BS_RIGHT;
|
||||
}
|
||||
|
||||
hwnd = CreateWindowEx(state.es, "BUTTON", text, state.ws,
|
||||
|
|
|
@ -20,13 +20,13 @@ bool Checkbox::Create(Window *parent_window, const char *style, int x, int y, in
|
|||
stringarray part;
|
||||
ParseStyleParam(style, part);
|
||||
for(int i = 0; i < count(part); i++) {
|
||||
if(strmatch(part[i], "visible"))state.ws |= WS_VISIBLE;
|
||||
if(strmatch(part[i], "disabled"))state.ws |= WS_DISABLED;
|
||||
if(!strcmp(part[i], "visible"))state.ws |= WS_VISIBLE;
|
||||
if(!strcmp(part[i], "disabled"))state.ws |= WS_DISABLED;
|
||||
|
||||
if(strmatch(part[i], "left"))state.ws |= BS_LEFT;
|
||||
if(strmatch(part[i], "center"))state.ws |= BS_CENTER;
|
||||
if(strmatch(part[i], "right"))state.ws |= BS_RIGHT;
|
||||
if(strmatch(part[i], "auto"))state.ws |= BS_AUTOCHECKBOX;
|
||||
if(!strcmp(part[i], "left"))state.ws |= BS_LEFT;
|
||||
if(!strcmp(part[i], "center"))state.ws |= BS_CENTER;
|
||||
if(!strcmp(part[i], "right"))state.ws |= BS_RIGHT;
|
||||
if(!strcmp(part[i], "auto"))state.ws |= BS_AUTOCHECKBOX;
|
||||
}
|
||||
if(!(state.ws & BS_AUTOCHECKBOX))state.ws |= BS_CHECKBOX;
|
||||
|
||||
|
|
|
@ -38,13 +38,13 @@ bool Combobox::Create(Window *parent_window, const char *style, int x, int y, in
|
|||
stringarray part;
|
||||
ParseStyleParam(style, part);
|
||||
for(int i = 0; i < count(part); i++) {
|
||||
if(strmatch(part[i], "visible"))state.ws |= WS_VISIBLE;
|
||||
if(strmatch(part[i], "disabled"))state.ws |= WS_DISABLED;
|
||||
if(strmatch(part[i], "border"))state.ws |= WS_BORDER;
|
||||
if(strmatch(part[i], "raised"))state.ws |= WS_DLGFRAME;
|
||||
if(!strcmp(part[i], "visible"))state.ws |= WS_VISIBLE;
|
||||
if(!strcmp(part[i], "disabled"))state.ws |= WS_DISABLED;
|
||||
if(!strcmp(part[i], "border"))state.ws |= WS_BORDER;
|
||||
if(!strcmp(part[i], "raised"))state.ws |= WS_DLGFRAME;
|
||||
|
||||
if(strmatch(part[i], "sunken"))state.es |= WS_EX_STATICEDGE;
|
||||
if(strmatch(part[i], "edge"))state.es |= WS_EX_CLIENTEDGE;
|
||||
if(!strcmp(part[i], "sunken"))state.es |= WS_EX_STATICEDGE;
|
||||
if(!strcmp(part[i], "edge"))state.es |= WS_EX_CLIENTEDGE;
|
||||
}
|
||||
|
||||
hwnd = CreateWindowEx(state.es, "COMBOBOX", text, state.ws,
|
||||
|
@ -52,7 +52,7 @@ stringarray part;
|
|||
parent->hwnd, (HMENU)id, GetModuleHandle(0), 0);
|
||||
if(!hwnd)return false;
|
||||
|
||||
if(strmatch(text, "") == false) {
|
||||
if(!strcmp(text, "") == false) {
|
||||
stringarray t;
|
||||
split(t, "|", text);
|
||||
for(int i = 0; i < ::count(t); i++) {
|
||||
|
|
|
@ -74,12 +74,12 @@ void Control::GetText(char *text, uint length) {
|
|||
}
|
||||
|
||||
void Control::SetText(const char *text, ...) {
|
||||
char str[4096];
|
||||
string str;
|
||||
va_list args;
|
||||
va_start(args, text);
|
||||
vsprintf(str, text, args);
|
||||
va_end(args);
|
||||
SetWindowText(hwnd, str);
|
||||
SetWindowText(hwnd, strptr(str));
|
||||
}
|
||||
|
||||
Control::Control() {
|
||||
|
|
|
@ -19,18 +19,18 @@ bool Editbox::Create(Window *parent_window, const char *style, int x, int y, int
|
|||
stringarray part;
|
||||
ParseStyleParam(style, part);
|
||||
for(int i = 0; i < count(part); i++) {
|
||||
if(strmatch(part[i], "visible"))state.ws |= WS_VISIBLE;
|
||||
if(strmatch(part[i], "disabled"))state.ws |= WS_DISABLED;
|
||||
if(strmatch(part[i], "border"))state.ws |= WS_BORDER;
|
||||
if(strmatch(part[i], "raised"))state.ws |= WS_DLGFRAME;
|
||||
if(strmatch(part[i], "vscroll"))state.ws |= WS_VSCROLL;
|
||||
if(strmatch(part[i], "hscroll"))state.ws |= WS_HSCROLL;
|
||||
if(!strcmp(part[i], "visible"))state.ws |= WS_VISIBLE;
|
||||
if(!strcmp(part[i], "disabled"))state.ws |= WS_DISABLED;
|
||||
if(!strcmp(part[i], "border"))state.ws |= WS_BORDER;
|
||||
if(!strcmp(part[i], "raised"))state.ws |= WS_DLGFRAME;
|
||||
if(!strcmp(part[i], "vscroll"))state.ws |= WS_VSCROLL;
|
||||
if(!strcmp(part[i], "hscroll"))state.ws |= WS_HSCROLL;
|
||||
|
||||
if(strmatch(part[i], "multiline"))state.ws |= ES_MULTILINE;
|
||||
if(strmatch(part[i], "readonly"))state.ws |= ES_READONLY;
|
||||
if(!strcmp(part[i], "multiline"))state.ws |= ES_MULTILINE;
|
||||
if(!strcmp(part[i], "readonly"))state.ws |= ES_READONLY;
|
||||
|
||||
if(strmatch(part[i], "sunken"))state.es |= WS_EX_STATICEDGE;
|
||||
if(strmatch(part[i], "edge"))state.es |= WS_EX_CLIENTEDGE;
|
||||
if(!strcmp(part[i], "sunken"))state.es |= WS_EX_STATICEDGE;
|
||||
if(!strcmp(part[i], "edge"))state.es |= WS_EX_CLIENTEDGE;
|
||||
}
|
||||
|
||||
hwnd = CreateWindowEx(state.es, "EDIT", text, state.ws,
|
||||
|
|
|
@ -14,13 +14,13 @@ bool Groupbox::Create(Window *parent_window, const char *style, int x, int y, in
|
|||
stringarray part;
|
||||
ParseStyleParam(style, part);
|
||||
for(int i = 0; i < count(part); i++) {
|
||||
if(strmatch(part[i], "visible"))state.ws |= WS_VISIBLE;
|
||||
if(strmatch(part[i], "disabled"))state.ws |= WS_DISABLED;
|
||||
if(strmatch(part[i], "border"))state.ws |= WS_BORDER;
|
||||
if(strmatch(part[i], "raised"))state.ws |= WS_DLGFRAME;
|
||||
if(!strcmp(part[i], "visible"))state.ws |= WS_VISIBLE;
|
||||
if(!strcmp(part[i], "disabled"))state.ws |= WS_DISABLED;
|
||||
if(!strcmp(part[i], "border"))state.ws |= WS_BORDER;
|
||||
if(!strcmp(part[i], "raised"))state.ws |= WS_DLGFRAME;
|
||||
|
||||
if(strmatch(part[i], "sunken"))state.es |= WS_EX_STATICEDGE;
|
||||
if(strmatch(part[i], "edge"))state.es |= WS_EX_CLIENTEDGE;
|
||||
if(!strcmp(part[i], "sunken"))state.es |= WS_EX_STATICEDGE;
|
||||
if(!strcmp(part[i], "edge"))state.es |= WS_EX_CLIENTEDGE;
|
||||
}
|
||||
|
||||
hwnd = CreateWindowEx(state.es, "BUTTON", text, state.ws,
|
||||
|
|
|
@ -14,18 +14,18 @@ bool Label::Create(Window *parent_window, const char *style, int x, int y, int w
|
|||
stringarray part;
|
||||
ParseStyleParam(style, part);
|
||||
for(int i = 0; i < count(part); i++) {
|
||||
if(strmatch(part[i], "visible"))state.ws |= WS_VISIBLE;
|
||||
if(strmatch(part[i], "disabled"))state.ws |= WS_DISABLED;
|
||||
if(strmatch(part[i], "border"))state.ws |= WS_BORDER;
|
||||
if(strmatch(part[i], "raised"))state.ws |= WS_DLGFRAME;
|
||||
if(!strcmp(part[i], "visible"))state.ws |= WS_VISIBLE;
|
||||
if(!strcmp(part[i], "disabled"))state.ws |= WS_DISABLED;
|
||||
if(!strcmp(part[i], "border"))state.ws |= WS_BORDER;
|
||||
if(!strcmp(part[i], "raised"))state.ws |= WS_DLGFRAME;
|
||||
|
||||
if(strmatch(part[i], "left"))state.ws |= SS_LEFT;
|
||||
if(strmatch(part[i], "center"))state.ws |= SS_CENTER;
|
||||
if(strmatch(part[i], "right"))state.ws |= SS_RIGHT;
|
||||
if(strmatch(part[i], "etched"))state.ws |= SS_ETCHEDFRAME;
|
||||
if(!strcmp(part[i], "left"))state.ws |= SS_LEFT;
|
||||
if(!strcmp(part[i], "center"))state.ws |= SS_CENTER;
|
||||
if(!strcmp(part[i], "right"))state.ws |= SS_RIGHT;
|
||||
if(!strcmp(part[i], "etched"))state.ws |= SS_ETCHEDFRAME;
|
||||
|
||||
if(strmatch(part[i], "sunken"))state.es |= WS_EX_STATICEDGE;
|
||||
if(strmatch(part[i], "edge"))state.es |= WS_EX_CLIENTEDGE;
|
||||
if(!strcmp(part[i], "sunken"))state.es |= WS_EX_STATICEDGE;
|
||||
if(!strcmp(part[i], "edge"))state.es |= WS_EX_CLIENTEDGE;
|
||||
}
|
||||
|
||||
hwnd = CreateWindowEx(state.es, "STATIC", text, state.ws,
|
||||
|
|
|
@ -38,13 +38,13 @@ bool Listbox::Create(Window *parent_window, const char *style, int x, int y, int
|
|||
stringarray part;
|
||||
ParseStyleParam(style, part);
|
||||
for(int i = 0; i < count(part); i++) {
|
||||
if(strmatch(part[i], "visible"))state.ws |= WS_VISIBLE;
|
||||
if(strmatch(part[i], "disabled"))state.ws |= WS_DISABLED;
|
||||
if(strmatch(part[i], "border"))state.ws |= WS_BORDER;
|
||||
if(strmatch(part[i], "raised"))state.ws |= WS_DLGFRAME;
|
||||
if(!strcmp(part[i], "visible"))state.ws |= WS_VISIBLE;
|
||||
if(!strcmp(part[i], "disabled"))state.ws |= WS_DISABLED;
|
||||
if(!strcmp(part[i], "border"))state.ws |= WS_BORDER;
|
||||
if(!strcmp(part[i], "raised"))state.ws |= WS_DLGFRAME;
|
||||
|
||||
if(strmatch(part[i], "sunken"))state.es |= WS_EX_STATICEDGE;
|
||||
if(strmatch(part[i], "edge"))state.es |= WS_EX_CLIENTEDGE;
|
||||
if(!strcmp(part[i], "sunken"))state.es |= WS_EX_STATICEDGE;
|
||||
if(!strcmp(part[i], "edge"))state.es |= WS_EX_CLIENTEDGE;
|
||||
}
|
||||
|
||||
hwnd = CreateWindowEx(state.es, "LISTBOX", text, state.ws,
|
||||
|
@ -52,7 +52,7 @@ stringarray part;
|
|||
parent->hwnd, (HMENU)id, GetModuleHandle(0), 0);
|
||||
if(!hwnd)return false;
|
||||
|
||||
if(strmatch(text, "") == false) {
|
||||
if(!strcmp(text, "") == false) {
|
||||
stringarray t;
|
||||
split(t, "|", text);
|
||||
for(int i = 0; i < ::count(t); i++) {
|
||||
|
|
|
@ -75,13 +75,13 @@ bool Listview::Create(Window *parent_window, const char *style, int x, int y, in
|
|||
stringarray part;
|
||||
ParseStyleParam(style, part);
|
||||
for(int i = 0; i < count(part); i++) {
|
||||
if(strmatch(part[i], "visible"))state.ws |= WS_VISIBLE;
|
||||
if(strmatch(part[i], "disabled"))state.ws |= WS_DISABLED;
|
||||
if(strmatch(part[i], "border"))state.ws |= WS_BORDER;
|
||||
if(strmatch(part[i], "raised"))state.ws |= WS_DLGFRAME;
|
||||
if(!strcmp(part[i], "visible"))state.ws |= WS_VISIBLE;
|
||||
if(!strcmp(part[i], "disabled"))state.ws |= WS_DISABLED;
|
||||
if(!strcmp(part[i], "border"))state.ws |= WS_BORDER;
|
||||
if(!strcmp(part[i], "raised"))state.ws |= WS_DLGFRAME;
|
||||
|
||||
if(strmatch(part[i], "sunken"))state.es |= WS_EX_STATICEDGE;
|
||||
if(strmatch(part[i], "edge"))state.es |= WS_EX_CLIENTEDGE;
|
||||
if(!strcmp(part[i], "sunken"))state.es |= WS_EX_STATICEDGE;
|
||||
if(!strcmp(part[i], "edge"))state.es |= WS_EX_CLIENTEDGE;
|
||||
}
|
||||
|
||||
hwnd = CreateWindowEx(state.es, WC_LISTVIEW, text, state.ws,
|
||||
|
|
|
@ -20,12 +20,12 @@ bool Radiobox::Create(Window *parent_window, const char *style, int x, int y, in
|
|||
stringarray part;
|
||||
ParseStyleParam(style, part);
|
||||
for(int i = 0; i < count(part); i++) {
|
||||
if(strmatch(part[i], "visible"))state.ws |= WS_VISIBLE;
|
||||
if(strmatch(part[i], "disabled"))state.ws |= WS_DISABLED;
|
||||
if(!strcmp(part[i], "visible"))state.ws |= WS_VISIBLE;
|
||||
if(!strcmp(part[i], "disabled"))state.ws |= WS_DISABLED;
|
||||
|
||||
if(strmatch(part[i], "left"))state.ws |= BS_LEFT;
|
||||
if(strmatch(part[i], "center"))state.ws |= BS_CENTER;
|
||||
if(strmatch(part[i], "right"))state.ws |= BS_RIGHT;
|
||||
if(!strcmp(part[i], "left"))state.ws |= BS_LEFT;
|
||||
if(!strcmp(part[i], "center"))state.ws |= BS_CENTER;
|
||||
if(!strcmp(part[i], "right"))state.ws |= BS_RIGHT;
|
||||
}
|
||||
state.ws |= BS_RADIOBUTTON;
|
||||
|
||||
|
|
|
@ -28,13 +28,13 @@ bool Slider::Create(Window *parent_window, const char *style, int x, int y, int
|
|||
stringarray part;
|
||||
ParseStyleParam(style, part);
|
||||
for(int i = 0; i < count(part); i++) {
|
||||
if(strmatch(part[i], "visible"))state.ws |= WS_VISIBLE;
|
||||
if(strmatch(part[i], "disabled"))state.ws |= WS_DISABLED;
|
||||
if(strmatch(part[i], "border"))state.ws |= WS_BORDER;
|
||||
if(strmatch(part[i], "raised"))state.ws |= WS_DLGFRAME;
|
||||
if(!strcmp(part[i], "visible"))state.ws |= WS_VISIBLE;
|
||||
if(!strcmp(part[i], "disabled"))state.ws |= WS_DISABLED;
|
||||
if(!strcmp(part[i], "border"))state.ws |= WS_BORDER;
|
||||
if(!strcmp(part[i], "raised"))state.ws |= WS_DLGFRAME;
|
||||
|
||||
if(strmatch(part[i], "sunken"))state.es |= WS_EX_STATICEDGE;
|
||||
if(strmatch(part[i], "edge"))state.es |= WS_EX_CLIENTEDGE;
|
||||
if(!strcmp(part[i], "sunken"))state.es |= WS_EX_STATICEDGE;
|
||||
if(!strcmp(part[i], "edge"))state.es |= WS_EX_CLIENTEDGE;
|
||||
}
|
||||
|
||||
hwnd = CreateWindowEx(state.es, TRACKBAR_CLASS, text, state.ws,
|
||||
|
|
|
@ -257,20 +257,20 @@ void Window::SetStyle(const char *style) {
|
|||
stringarray part;
|
||||
ParseStyleParam(style, part);
|
||||
for(int i = 0; i < count(part); i++) {
|
||||
if(strmatch(part[i], "visible")) state.ws |= WS_VISIBLE;
|
||||
if(strmatch(part[i], "popup")) state.ws |= WS_POPUP;
|
||||
if(strmatch(part[i], "border")) state.ws |= WS_BORDER;
|
||||
if(strmatch(part[i], "frame")) state.ws |= WS_DLGFRAME;
|
||||
if(strmatch(part[i], "titlebar"))state.ws |= WS_CAPTION;
|
||||
if(strmatch(part[i], "minimize"))state.ws |= WS_MINIMIZEBOX;
|
||||
if(strmatch(part[i], "maximize"))state.ws |= WS_MAXIMIZEBOX;
|
||||
if(!strcmp(part[i], "visible")) state.ws |= WS_VISIBLE;
|
||||
if(!strcmp(part[i], "popup")) state.ws |= WS_POPUP;
|
||||
if(!strcmp(part[i], "border")) state.ws |= WS_BORDER;
|
||||
if(!strcmp(part[i], "frame")) state.ws |= WS_DLGFRAME;
|
||||
if(!strcmp(part[i], "titlebar"))state.ws |= WS_CAPTION;
|
||||
if(!strcmp(part[i], "minimize"))state.ws |= WS_MINIMIZEBOX;
|
||||
if(!strcmp(part[i], "maximize"))state.ws |= WS_MAXIMIZEBOX;
|
||||
|
||||
if(strmatch(part[i], "topmost")) state.es |= WS_EX_TOPMOST;
|
||||
if(strmatch(part[i], "layered")) state.es |= WS_EX_LAYERED;
|
||||
if(strmatch(part[i], "sunken")) state.es |= WS_EX_STATICEDGE;
|
||||
if(strmatch(part[i], "edge")) state.es |= WS_EX_CLIENTEDGE;
|
||||
if(!strcmp(part[i], "topmost")) state.es |= WS_EX_TOPMOST;
|
||||
if(!strcmp(part[i], "layered")) state.es |= WS_EX_LAYERED;
|
||||
if(!strcmp(part[i], "sunken")) state.es |= WS_EX_STATICEDGE;
|
||||
if(!strcmp(part[i], "edge")) state.es |= WS_EX_CLIENTEDGE;
|
||||
|
||||
if(strmatch(part[i], "dragmove"))state.dragmove = true;
|
||||
if(!strcmp(part[i], "dragmove"))state.dragmove = true;
|
||||
}
|
||||
|
||||
if(!hwnd)return;
|
||||
|
|
|
@ -71,7 +71,7 @@ char t[4096];
|
|||
|
||||
i++;
|
||||
while(1) {
|
||||
if(strptr(line[i])[1] == ':' || strptr(line[i])[2] == ':' || strmatch(line[i], "}"))break;
|
||||
if(strptr(line[i])[1] == ':' || strptr(line[i])[2] == ':' || line[i] == "}")break;
|
||||
|
||||
update_line(i);
|
||||
strcat(output_op, line[i]);
|
||||
|
|
|
@ -38,9 +38,9 @@ void bMemBus::load_cart() {
|
|||
uint region = read(0xffd9) & 0x7f;
|
||||
cartridge.info.region = (region <= 1 || region >= 13) ? Cartridge::NTSC : Cartridge::PAL;
|
||||
if(cartridge.info.region == Cartridge::NTSC) {
|
||||
snes->set_region(SNES::NTSC);
|
||||
snes.set_region(SNES::NTSC);
|
||||
} else {
|
||||
snes->set_region(SNES::PAL);
|
||||
snes.set_region(SNES::PAL);
|
||||
}
|
||||
|
||||
rom_loaded = true;
|
||||
|
|
|
@ -24,7 +24,7 @@ uint ram_size = cartridge.info.ram_size;
|
|||
uint addr = page << 8;
|
||||
uint bank = page >> 8;
|
||||
|
||||
//SRAM mapping is incorrect in several games, this is the most compatible
|
||||
//RAM mapping is incorrect in several games, this is the most compatible
|
||||
//layout I can create using only ROM header information. Additional accuracy
|
||||
//requires PCB identification.
|
||||
|
||||
|
@ -34,20 +34,20 @@ uint ram_size = cartridge.info.ram_size;
|
|||
continue;
|
||||
}
|
||||
|
||||
//HiROM SRAM region
|
||||
//HiROM RAM region
|
||||
//$[20-3f|a0-bf]:[6000-7fff]
|
||||
if((bank & 0x7f) >= 0x20 && (bank & 0x7f) <= 0x3f && (addr & 0xe000) == 0x6000) {
|
||||
if(ram_size == 0)continue;
|
||||
|
||||
addr = ((bank & 0x7f) - 0x20) * 0x2000 + ((addr & 0xffff) - 0x6000);
|
||||
addr %= ram_size;
|
||||
page_handle[page] = cartridge.sram + addr;
|
||||
page_handle[page] = cartridge.ram + addr;
|
||||
page_read [page] = &bMemBus::read_ram;
|
||||
page_write [page] = &bMemBus::write_ram;
|
||||
continue;
|
||||
}
|
||||
|
||||
//LoROM SRAM region
|
||||
//LoROM RAM region
|
||||
//$[70-7f|f0-ff]:[0000-7fff]
|
||||
//Note: WRAM is remapped over $[7e-7f]:[0000-ffff]
|
||||
if((bank & 0x7f) >= 0x70 && (bank & 0x7f) <= 0x7f && (addr & 0x8000) == 0x0000) {
|
||||
|
@ -57,7 +57,7 @@ uint ram_size = cartridge.info.ram_size;
|
|||
|
||||
addr = ((bank & 0x7f) - 0x70) * 0x8000 + (addr & 0x7fff);
|
||||
addr %= ram_size;
|
||||
page_handle[page] = cartridge.sram + addr;
|
||||
page_handle[page] = cartridge.ram + addr;
|
||||
page_read [page] = &bMemBus::read_ram;
|
||||
page_write [page] = &bMemBus::write_ram;
|
||||
continue;
|
||||
|
|
|
@ -1,16 +1,3 @@
|
|||
uint bMemBus::mirror(uint size, uint pos) {
|
||||
if(size == 0)return 0;
|
||||
if(pos < size)return pos;
|
||||
|
||||
uint mask = 1 << 31;
|
||||
while(!(pos & mask))mask >>= 1;
|
||||
if(size <= (pos & mask)) {
|
||||
return mirror(size, pos - mask);
|
||||
} else {
|
||||
return mask + mirror(size - mask, pos - mask);
|
||||
}
|
||||
}
|
||||
|
||||
bool bMemBus::cart_map_pcb(const char *pcb) {
|
||||
if(!strcmp(pcb, "SHVC-1A3B-01")) { cart_map_shvc_1a3b_13(); return true; }
|
||||
if(!strcmp(pcb, "SHVC-1A3B-11")) { cart_map_shvc_1a3b_13(); return true; }
|
||||
|
@ -35,9 +22,26 @@ bool bMemBus::cart_map_pcb(const char *pcb) {
|
|||
|
||||
if(!strcmp(pcb, "BSC-1A7M-10")) { cart_map_bsc_1a7m_10(); return true; }
|
||||
|
||||
if(!strcmp(pcb, "STC-SOLO")) { cart_map_stc_solo(); return true; }
|
||||
|
||||
if(!strcmp(pcb, "STC-DUAL")) { cart_map_stc_dual(); return true; }
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
uint bMemBus::mirror(uint size, uint pos) {
|
||||
if(size == 0)return 0;
|
||||
if(pos < size)return pos;
|
||||
|
||||
uint mask = 1 << 31;
|
||||
while(!(pos & mask))mask >>= 1;
|
||||
if(size <= (pos & mask)) {
|
||||
return mirror(size, pos - mask);
|
||||
} else {
|
||||
return mask + mirror(size - mask, pos - mask);
|
||||
}
|
||||
}
|
||||
|
||||
void bMemBus::cart_map_range(
|
||||
uint mode,
|
||||
uint8 bank_lo, uint8 bank_hi,
|
||||
|
@ -59,7 +63,7 @@ uint8 page_hi = (addr_hi >> 8) & 255;
|
|||
} break;
|
||||
|
||||
case MAP_RAM: {
|
||||
data = cartridge.sram;
|
||||
data = cartridge.ram;
|
||||
size = cartridge.info.ram_size;
|
||||
} break;
|
||||
|
||||
|
|
|
@ -26,4 +26,6 @@ enum {
|
|||
mapper(bsc_1a5m_01);
|
||||
mapper(bsc_1a7m_01);
|
||||
mapper(bsc_1a7m_10);
|
||||
mapper(stc_solo);
|
||||
mapper(stc_dual);
|
||||
#undef mapper
|
||||
|
|
|
@ -76,3 +76,27 @@ mapper(bsc_1a7m_10) {
|
|||
map(LINEAR, 0xa0, 0xbf, 0x8000, 0xffff, MAP_ROM, 0x100000);
|
||||
map(LINEAR, 0xf0, 0xff, 0x0000, 0x7fff, MAP_RAM);
|
||||
}
|
||||
|
||||
//STC-SOLO
|
||||
mapper(stc_solo) {
|
||||
map(LINEAR, 0x00, 0x1f, 0x8000, 0xffff, MAP_ROM, 0x000000);
|
||||
map(LINEAR, 0x20, 0x3f, 0x8000, 0xffff, MAP_ROM, 0x100000);
|
||||
map(LINEAR, 0x60, 0x63, 0x8000, 0xffff, MAP_RAM, 0x000000);
|
||||
map(LINEAR, 0x80, 0x9f, 0x8000, 0xffff, MAP_ROM, 0x000000);
|
||||
map(LINEAR, 0xa0, 0xbf, 0x8000, 0xffff, MAP_ROM, 0x100000);
|
||||
map(LINEAR, 0xe0, 0xe3, 0x8000, 0xffff, MAP_RAM, 0x000000);
|
||||
}
|
||||
|
||||
//STC-DUAL
|
||||
mapper(stc_dual) {
|
||||
map(LINEAR, 0x00, 0x1f, 0x8000, 0xffff, MAP_ROM, 0x000000);
|
||||
map(LINEAR, 0x20, 0x3f, 0x8000, 0xffff, MAP_ROM, 0x100000);
|
||||
map(LINEAR, 0x40, 0x5f, 0x8000, 0xffff, MAP_ROM, 0x200000);
|
||||
map(LINEAR, 0x60, 0x63, 0x8000, 0xffff, MAP_RAM, 0x000000);
|
||||
map(LINEAR, 0x70, 0x73, 0x8000, 0xffff, MAP_RAM, 0x020000);
|
||||
map(LINEAR, 0x80, 0x9f, 0x8000, 0xffff, MAP_ROM, 0x000000);
|
||||
map(LINEAR, 0xa0, 0xbf, 0x8000, 0xffff, MAP_ROM, 0x100000);
|
||||
map(LINEAR, 0xc0, 0xdf, 0x8000, 0xffff, MAP_ROM, 0x200000);
|
||||
map(LINEAR, 0xe0, 0xe3, 0x8000, 0xffff, MAP_RAM, 0x000000);
|
||||
map(LINEAR, 0xf0, 0xf3, 0x8000, 0xffff, MAP_RAM, 0x020000);
|
||||
}
|
||||
|
|
|
@ -65,8 +65,17 @@ void bPPU::render_scanline() {
|
|||
#endif
|
||||
|
||||
if(line.y >= 0 && line.y < (r_cpu->overscan() ? 240 : 225)) {
|
||||
if(status.render_output == true && line.y != 0) { render_line(); }
|
||||
render_line_oam_rto();
|
||||
if(config::ppu.hack.obj_cache == false) {
|
||||
if(line.y != 0) {
|
||||
render_line_oam_rto();
|
||||
render_line();
|
||||
}
|
||||
} else {
|
||||
if(line.y != 0) {
|
||||
render_line();
|
||||
}
|
||||
render_line_oam_rto();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -81,7 +90,7 @@ void bPPU::power() {
|
|||
memset(oam, 0, 544);
|
||||
memset(cgram, 0, 512);
|
||||
|
||||
region = snes->region();
|
||||
region = snes.region();
|
||||
|
||||
//$2100
|
||||
regs.display_disabled = 1;
|
||||
|
|
|
@ -189,7 +189,7 @@ void bPPU::mmio_w210d(uint8 value) {
|
|||
regs.m7_hofs = (value << 8) | regs.m7_latch;
|
||||
regs.m7_latch = value;
|
||||
|
||||
regs.bg_hofs[BG1] = (value << 8) | (regs.bg_ofslatch & 0xf8) | ((regs.bg_hofs[BG1] >> 8) & 7);
|
||||
regs.bg_hofs[BG1] = (value << 8) | (regs.bg_ofslatch & ~7) | ((regs.bg_hofs[BG1] >> 8) & 7);
|
||||
regs.bg_ofslatch = value;
|
||||
}
|
||||
|
||||
|
@ -198,43 +198,43 @@ void bPPU::mmio_w210e(uint8 value) {
|
|||
regs.m7_vofs = (value << 8) | regs.m7_latch;
|
||||
regs.m7_latch = value;
|
||||
|
||||
regs.bg_vofs[BG1] = (value << 8) | (regs.bg_ofslatch & 0xf8) | ((regs.bg_vofs[BG1] >> 8) & 7);
|
||||
regs.bg_vofs[BG1] = (value << 8) | (regs.bg_ofslatch);
|
||||
regs.bg_ofslatch = value;
|
||||
}
|
||||
|
||||
//BG2HOFS
|
||||
void bPPU::mmio_w210f(uint8 value) {
|
||||
regs.bg_hofs[BG2] = (value << 8) | (regs.bg_ofslatch & 0xf8) | ((regs.bg_hofs[BG2] >> 8) & 7);
|
||||
regs.bg_hofs[BG2] = (value << 8) | (regs.bg_ofslatch & ~7) | ((regs.bg_hofs[BG2] >> 8) & 7);
|
||||
regs.bg_ofslatch = value;
|
||||
}
|
||||
|
||||
//BG2VOFS
|
||||
void bPPU::mmio_w2110(uint8 value) {
|
||||
regs.bg_vofs[BG2] = (value << 8) | (regs.bg_ofslatch & 0xf8) | ((regs.bg_vofs[BG2] >> 8) & 7);
|
||||
regs.bg_vofs[BG2] = (value << 8) | (regs.bg_ofslatch);
|
||||
regs.bg_ofslatch = value;
|
||||
}
|
||||
|
||||
//BG3HOFS
|
||||
void bPPU::mmio_w2111(uint8 value) {
|
||||
regs.bg_hofs[BG3] = (value << 8) | (regs.bg_ofslatch & 0xf8) | ((regs.bg_hofs[BG3] >> 8) & 7);
|
||||
regs.bg_hofs[BG3] = (value << 8) | (regs.bg_ofslatch & ~7) | ((regs.bg_hofs[BG3] >> 8) & 7);
|
||||
regs.bg_ofslatch = value;
|
||||
}
|
||||
|
||||
//BG3VOFS
|
||||
void bPPU::mmio_w2112(uint8 value) {
|
||||
regs.bg_vofs[BG3] = (value << 8) | (regs.bg_ofslatch & 0xf8) | ((regs.bg_vofs[BG3] >> 8) & 7);
|
||||
regs.bg_vofs[BG3] = (value << 8) | (regs.bg_ofslatch);
|
||||
regs.bg_ofslatch = value;
|
||||
}
|
||||
|
||||
//BG4HOFS
|
||||
void bPPU::mmio_w2113(uint8 value) {
|
||||
regs.bg_hofs[BG4] = (value << 8) | (regs.bg_ofslatch & 0xf8) | ((regs.bg_hofs[BG4] >> 8) & 7);
|
||||
regs.bg_hofs[BG4] = (value << 8) | (regs.bg_ofslatch & ~7) | ((regs.bg_hofs[BG4] >> 8) & 7);
|
||||
regs.bg_ofslatch = value;
|
||||
}
|
||||
|
||||
//BG4VOFS
|
||||
void bPPU::mmio_w2114(uint8 value) {
|
||||
regs.bg_vofs[BG4] = (value << 8) | (regs.bg_ofslatch & 0xf8) | ((regs.bg_vofs[BG4] >> 8) & 7);
|
||||
regs.bg_vofs[BG4] = (value << 8) | (regs.bg_ofslatch);
|
||||
regs.bg_ofslatch = value;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
#define render_bg_tile_line_2bpp(mask) \
|
||||
col = bool(d0 & mask) << 0; \
|
||||
col += bool(d1 & mask) << 1; \
|
||||
col = !!(d0 & mask) << 0; \
|
||||
col += !!(d1 & mask) << 1; \
|
||||
*dest++ = col
|
||||
|
||||
#define render_bg_tile_line_4bpp(mask) \
|
||||
col = bool(d0 & mask) << 0; \
|
||||
col += bool(d1 & mask) << 1; \
|
||||
col += bool(d2 & mask) << 2; \
|
||||
col += bool(d3 & mask) << 3; \
|
||||
col = !!(d0 & mask) << 0; \
|
||||
col += !!(d1 & mask) << 1; \
|
||||
col += !!(d2 & mask) << 2; \
|
||||
col += !!(d3 & mask) << 3; \
|
||||
*dest++ = col
|
||||
|
||||
#define render_bg_tile_line_8bpp(mask) \
|
||||
col = bool(d0 & mask) << 0; \
|
||||
col += bool(d1 & mask) << 1; \
|
||||
col += bool(d2 & mask) << 2; \
|
||||
col += bool(d3 & mask) << 3; \
|
||||
col += bool(d4 & mask) << 4; \
|
||||
col += bool(d5 & mask) << 5; \
|
||||
col += bool(d6 & mask) << 6; \
|
||||
col += bool(d7 & mask) << 7; \
|
||||
col = !!(d0 & mask) << 0; \
|
||||
col += !!(d1 & mask) << 1; \
|
||||
col += !!(d2 & mask) << 2; \
|
||||
col += !!(d3 & mask) << 3; \
|
||||
col += !!(d4 & mask) << 4; \
|
||||
col += !!(d5 & mask) << 5; \
|
||||
col += !!(d6 & mask) << 6; \
|
||||
col += !!(d7 & mask) << 7; \
|
||||
*dest++ = col
|
||||
|
||||
void bPPU::render_bg_tile(uint8 color_depth, uint16 tile_num) {
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
void bPPU::build_sprite_list() {
|
||||
uint8 *tableA = oam, *tableB = oam + 512;
|
||||
uint8 y_offset = (config::ppu.hack.obj_cache == true) ? 0 : 1;
|
||||
|
||||
for(int i = 0; i < 128; i++) {
|
||||
uint x = bool(*tableB & (1 << ((i & 3) << 1))); //0x01, 0x04, 0x10, 0x40
|
||||
bool size = bool(*tableB & (2 << ((i & 3) << 1))); //0x02, 0x08, 0x20, 0x80
|
||||
uint x = !!(*tableB & (1 << ((i & 3) << 1))); //0x01, 0x04, 0x10, 0x40
|
||||
bool size = !!(*tableB & (2 << ((i & 3) << 1))); //0x02, 0x08, 0x20, 0x80
|
||||
|
||||
switch(regs.oam_basesize) {
|
||||
case 0: sprite_list[i].width = (!size) ? 8 : 16;
|
||||
|
@ -36,10 +37,10 @@ uint8 *tableA = oam, *tableB = oam + 512;
|
|||
}
|
||||
|
||||
sprite_list[i].x = (x << 8) + tableA[0];
|
||||
sprite_list[i].y = tableA[1];
|
||||
sprite_list[i].y = tableA[1] + y_offset;
|
||||
sprite_list[i].character = tableA[2];
|
||||
sprite_list[i].vflip = bool(tableA[3] & 0x80);
|
||||
sprite_list[i].hflip = bool(tableA[3] & 0x40);
|
||||
sprite_list[i].vflip = !!(tableA[3] & 0x80);
|
||||
sprite_list[i].hflip = !!(tableA[3] & 0x40);
|
||||
sprite_list[i].priority = (tableA[3] >> 4) & 3;
|
||||
sprite_list[i].palette = (tableA[3] >> 1) & 7;
|
||||
sprite_list[i].use_nameselect = tableA[3] & 1;
|
||||
|
|
|
@ -28,7 +28,7 @@ uint8 *JMAReader::read(uint32 length)
|
|||
return data;
|
||||
}
|
||||
|
||||
JMAReader::JMAReader(char *fn) : JMAFile(fn), fsize(0)
|
||||
JMAReader::JMAReader(const 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++)
|
||||
|
|
|
@ -12,6 +12,6 @@ public:
|
|||
uint32 size();
|
||||
uint8 *read(uint32 length = 0);
|
||||
|
||||
JMAReader(char *fn);
|
||||
JMAReader(const char *fn);
|
||||
~JMAReader() { }
|
||||
};
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
#include "jmareader.cpp"
|
||||
#endif
|
||||
|
||||
uint32 Reader::detect(char *fn) {
|
||||
uint Reader::detect(const char *fn) {
|
||||
int len = strlen(fn);
|
||||
if(len >= 4 && !stricmp(fn + len - 3, ".gz")) {
|
||||
return RF_GZ;
|
||||
|
|
|
@ -9,7 +9,7 @@ enum {
|
|||
|
||||
//attemps to determine filetype by extension,
|
||||
//RF_NORMAL is returned on failure as a failsafe
|
||||
static uint32 detect(char *fn);
|
||||
static uint detect(const char *fn);
|
||||
virtual uint32 size() = 0;
|
||||
|
||||
//return is 0 on failure, caller must deallocate memory manually
|
||||
|
|
|
@ -26,7 +26,7 @@ uint8 *ZipReader::read(uint32 length)
|
|||
return data;
|
||||
}
|
||||
|
||||
ZipReader::ZipReader(char *fn) : fsize(0)
|
||||
ZipReader::ZipReader(const char *fn) : fsize(0)
|
||||
{
|
||||
unz_file_info cFileInfo; //Create variable to hold info for a compressed file
|
||||
char cFileName[sizeof(cname)];
|
||||
|
|
|
@ -15,7 +15,7 @@ public:
|
|||
uint32 size();
|
||||
uint8 *read(uint32 length = 0);
|
||||
|
||||
ZipReader(char *fn);
|
||||
ZipReader(const char *fn);
|
||||
~ZipReader()
|
||||
{
|
||||
if (zipfile)
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
class SMP {
|
||||
public:
|
||||
thread_t thread;
|
||||
virtual void enter() = 0;
|
||||
|
||||
public:
|
||||
|
|
|
@ -106,13 +106,13 @@ mov_dp_dp(0xfa) {
|
|||
mov_dp_const(0x8f) {
|
||||
1:rd = op_readpc();
|
||||
2:dp = op_readpc();
|
||||
3:op_io();
|
||||
3:op_readdp(dp);
|
||||
4:op_writedp(dp, rd);
|
||||
}
|
||||
|
||||
mov_ix_a(0xc6) {
|
||||
1:op_io();
|
||||
2:op_io();
|
||||
2:op_readdp(regs.x);
|
||||
3:op_writedp(regs.x, regs.a);
|
||||
}
|
||||
|
||||
|
@ -126,17 +126,18 @@ mov_dp_a(0xc4, a),
|
|||
mov_dp_x(0xd8, x),
|
||||
mov_dp_y(0xcb, y) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io();
|
||||
2:op_readdp(dp);
|
||||
3:op_writedp(dp, regs.$1);
|
||||
}
|
||||
|
||||
mov_dpx_a(0xd4, x, a),
|
||||
mov_dpy_x(0xd9, y, x),
|
||||
mov_dpx_y(0xdb, x, y) {
|
||||
1:dp = op_readpc();
|
||||
1:dp = op_readpc();
|
||||
2:op_io();
|
||||
3:op_io();
|
||||
4:op_writedp(dp + regs.$1, regs.$2);
|
||||
dp += regs.$1;
|
||||
3:op_readdp(dp);
|
||||
4:op_writedp(dp, regs.$2);
|
||||
}
|
||||
|
||||
mov_addr_a(0xc5, a),
|
||||
|
@ -144,7 +145,7 @@ mov_addr_x(0xc9, x),
|
|||
mov_addr_y(0xcc, y) {
|
||||
1:dp = op_readpc();
|
||||
2:dp |= op_readpc() << 8;
|
||||
3:op_io();
|
||||
3:op_readaddr(dp);
|
||||
4:op_writeaddr(dp, regs.$1);
|
||||
}
|
||||
|
||||
|
@ -153,26 +154,29 @@ mov_addry_a(0xd6, y) {
|
|||
1:dp = op_readpc();
|
||||
2:dp |= op_readpc() << 8;
|
||||
3:op_io();
|
||||
4:op_io();
|
||||
5:op_writeaddr(dp + regs.$1, regs.a);
|
||||
dp += regs.$1;
|
||||
4:op_readaddr(dp);
|
||||
5:op_writeaddr(dp, regs.a);
|
||||
}
|
||||
|
||||
mov_idpx_a(0xc7) {
|
||||
1:sp = op_readpc() + regs.x;
|
||||
1:sp = op_readpc();
|
||||
2:op_io();
|
||||
sp += regs.x;
|
||||
3:dp = op_readdp(sp);
|
||||
4:dp |= op_readdp(sp + 1) << 8;
|
||||
5:op_io();
|
||||
5:op_readaddr(dp);
|
||||
6:op_writeaddr(dp, regs.a);
|
||||
}
|
||||
|
||||
mov_idpy_a(0xd7) {
|
||||
1:sp = op_readpc();
|
||||
2:op_io();
|
||||
3:dp = op_readdp(sp);
|
||||
4:dp |= op_readdp(sp + 1) << 8;
|
||||
5:op_io();
|
||||
6:op_writeaddr(dp + regs.y, regs.a);
|
||||
1:sp = op_readpc();
|
||||
2:dp = op_readdp(sp);
|
||||
3:dp |= op_readdp(sp + 1) << 8;
|
||||
4:op_io();
|
||||
dp += regs.y;
|
||||
5:op_readaddr(dp);
|
||||
6:op_writeaddr(dp, regs.a);
|
||||
}
|
||||
|
||||
movw_ya_dp(0xba) {
|
||||
|
@ -186,7 +190,7 @@ movw_ya_dp(0xba) {
|
|||
|
||||
movw_dp_ya(0xda) {
|
||||
1:dp = op_readpc();
|
||||
2:op_io();
|
||||
2:op_readdp(dp);
|
||||
3:op_writedp(dp, regs.a);
|
||||
4:op_writedp(dp + 1, regs.y);
|
||||
}
|
||||
|
|
|
@ -214,14 +214,14 @@ case 0xfa: {
|
|||
case 0x8f: {
|
||||
rd = op_readpc();
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
op_readdp(dp);
|
||||
op_writedp(dp, rd);
|
||||
} break;
|
||||
|
||||
//mov_ix_a
|
||||
case 0xc6: {
|
||||
op_io();
|
||||
op_io();
|
||||
op_readdp(regs.x);
|
||||
op_writedp(regs.x, regs.a);
|
||||
} break;
|
||||
|
||||
|
@ -235,53 +235,56 @@ case 0xaf: {
|
|||
//mov_dp_a
|
||||
case 0xc4: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
op_readdp(dp);
|
||||
op_writedp(dp, regs.a);
|
||||
} break;
|
||||
|
||||
//mov_dp_x
|
||||
case 0xd8: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
op_readdp(dp);
|
||||
op_writedp(dp, regs.x);
|
||||
} break;
|
||||
|
||||
//mov_dp_y
|
||||
case 0xcb: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
op_readdp(dp);
|
||||
op_writedp(dp, regs.y);
|
||||
} break;
|
||||
|
||||
//mov_dpx_a
|
||||
case 0xd4: {
|
||||
dp = op_readpc();
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
op_io();
|
||||
op_writedp(dp + regs.x, regs.a);
|
||||
dp += regs.x;
|
||||
op_readdp(dp);
|
||||
op_writedp(dp, regs.a);
|
||||
} break;
|
||||
|
||||
//mov_dpy_x
|
||||
case 0xd9: {
|
||||
dp = op_readpc();
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
op_io();
|
||||
op_writedp(dp + regs.y, regs.x);
|
||||
dp += regs.y;
|
||||
op_readdp(dp);
|
||||
op_writedp(dp, regs.x);
|
||||
} break;
|
||||
|
||||
//mov_dpx_y
|
||||
case 0xdb: {
|
||||
dp = op_readpc();
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
op_io();
|
||||
op_writedp(dp + regs.x, regs.y);
|
||||
dp += regs.x;
|
||||
op_readdp(dp);
|
||||
op_writedp(dp, regs.y);
|
||||
} break;
|
||||
|
||||
//mov_addr_a
|
||||
case 0xc5: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
op_io();
|
||||
op_readaddr(dp);
|
||||
op_writeaddr(dp, regs.a);
|
||||
} break;
|
||||
|
||||
|
@ -289,7 +292,7 @@ case 0xc5: {
|
|||
case 0xc9: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
op_io();
|
||||
op_readaddr(dp);
|
||||
op_writeaddr(dp, regs.x);
|
||||
} break;
|
||||
|
||||
|
@ -297,7 +300,7 @@ case 0xc9: {
|
|||
case 0xcc: {
|
||||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
op_io();
|
||||
op_readaddr(dp);
|
||||
op_writeaddr(dp, regs.y);
|
||||
} break;
|
||||
|
||||
|
@ -306,8 +309,9 @@ case 0xd5: {
|
|||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
op_io();
|
||||
op_io();
|
||||
op_writeaddr(dp + regs.x, regs.a);
|
||||
dp += regs.x;
|
||||
op_readaddr(dp);
|
||||
op_writeaddr(dp, regs.a);
|
||||
} break;
|
||||
|
||||
//mov_addry_a
|
||||
|
@ -315,28 +319,31 @@ case 0xd6: {
|
|||
dp = op_readpc();
|
||||
dp |= op_readpc() << 8;
|
||||
op_io();
|
||||
op_io();
|
||||
op_writeaddr(dp + regs.y, regs.a);
|
||||
dp += regs.y;
|
||||
op_readaddr(dp);
|
||||
op_writeaddr(dp, regs.a);
|
||||
} break;
|
||||
|
||||
//mov_idpx_a
|
||||
case 0xc7: {
|
||||
sp = op_readpc() + regs.x;
|
||||
sp = op_readpc();
|
||||
op_io();
|
||||
sp += regs.x;
|
||||
dp = op_readdp(sp);
|
||||
dp |= op_readdp(sp + 1) << 8;
|
||||
op_io();
|
||||
op_readaddr(dp);
|
||||
op_writeaddr(dp, regs.a);
|
||||
} break;
|
||||
|
||||
//mov_idpy_a
|
||||
case 0xd7: {
|
||||
sp = op_readpc();
|
||||
op_io();
|
||||
sp = op_readpc();
|
||||
dp = op_readdp(sp);
|
||||
dp |= op_readdp(sp + 1) << 8;
|
||||
op_io();
|
||||
op_writeaddr(dp + regs.y, regs.a);
|
||||
dp += regs.y;
|
||||
op_readaddr(dp);
|
||||
op_writeaddr(dp, regs.a);
|
||||
} break;
|
||||
|
||||
//movw_ya_dp
|
||||
|
@ -352,7 +359,7 @@ case 0xba: {
|
|||
//movw_dp_ya
|
||||
case 0xda: {
|
||||
dp = op_readpc();
|
||||
op_io();
|
||||
op_readdp(dp);
|
||||
op_writedp(dp, regs.a);
|
||||
op_writedp(dp + 1, regs.y);
|
||||
} break;
|
||||
|
|
|
@ -148,7 +148,6 @@ sbc_dp_const(0xb8, sbc, 1) {
|
|||
}
|
||||
|
||||
addw_ya_dp(0x7a, addw),
|
||||
cmpw_ya_dp(0x5a, cmpw),
|
||||
subw_ya_dp(0x9a, subw) {
|
||||
1:dp = op_readpc();
|
||||
2:rd = op_readdp(dp);
|
||||
|
@ -157,6 +156,13 @@ subw_ya_dp(0x9a, subw) {
|
|||
regs.ya = op_$1(regs.ya, rd);
|
||||
}
|
||||
|
||||
cmpw_ya_dp(0x5a) {
|
||||
1:dp = op_readpc();
|
||||
2:rd = op_readdp(dp);
|
||||
3:rd |= op_readdp(dp + 1) << 8;
|
||||
op_cmpw(regs.ya, rd);
|
||||
}
|
||||
|
||||
and1_bit(0x4a, !!),
|
||||
and1_notbit(0x6a, !) {
|
||||
1:dp = op_readpc();
|
||||
|
|
|
@ -661,15 +661,6 @@ case 0x7a: {
|
|||
regs.ya = op_addw(regs.ya, rd);
|
||||
} break;
|
||||
|
||||
//cmpw_ya_dp
|
||||
case 0x5a: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd |= op_readdp(dp + 1) << 8;
|
||||
op_io();
|
||||
regs.ya = op_cmpw(regs.ya, rd);
|
||||
} break;
|
||||
|
||||
//subw_ya_dp
|
||||
case 0x9a: {
|
||||
dp = op_readpc();
|
||||
|
@ -679,6 +670,14 @@ case 0x9a: {
|
|||
regs.ya = op_subw(regs.ya, rd);
|
||||
} break;
|
||||
|
||||
//cmpw_ya_dp
|
||||
case 0x5a: {
|
||||
dp = op_readpc();
|
||||
rd = op_readdp(dp);
|
||||
rd |= op_readdp(dp + 1) << 8;
|
||||
op_cmpw(regs.ya, rd);
|
||||
} break;
|
||||
|
||||
//and1_bit
|
||||
case 0x4a: {
|
||||
dp = op_readpc();
|
||||
|
|
|
@ -1,32 +1,32 @@
|
|||
uint8 sSMP::op_adc(uint8 x, uint8 y) {
|
||||
int16 r = x + y + regs.p.c;
|
||||
regs.p.n = bool(r & 0x80);
|
||||
regs.p.v = bool(~(x ^ y) & (y ^ (uint8)r) & 0x80);
|
||||
regs.p.h = bool((x ^ y ^ (uint8)r) & 0x10);
|
||||
regs.p.n = !!(r & 0x80);
|
||||
regs.p.v = !!(~(x ^ y) & (y ^ (uint8)r) & 0x80);
|
||||
regs.p.h = !!((x ^ y ^ (uint8)r) & 0x10);
|
||||
regs.p.z = ((uint8)r == 0);
|
||||
regs.p.c = (r > 0xff);
|
||||
return r;
|
||||
}
|
||||
|
||||
uint16 sSMP::op_addw(uint16 x, uint16 y) {
|
||||
int16 r;
|
||||
uint16 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.z = (r == 0);
|
||||
return r;
|
||||
}
|
||||
|
||||
uint8 sSMP::op_and(uint8 x, uint8 y) {
|
||||
x &= y;
|
||||
regs.p.n = bool(x & 0x80);
|
||||
regs.p.n = !!(x & 0x80);
|
||||
regs.p.z = (x == 0);
|
||||
return x;
|
||||
}
|
||||
|
||||
uint8 sSMP::op_cmp(uint8 x, uint8 y) {
|
||||
int16 r = x - y;
|
||||
regs.p.n = bool(r & 0x80);
|
||||
regs.p.n = !!(r & 0x80);
|
||||
regs.p.z = ((uint8)r == 0);
|
||||
regs.p.c = (r >= 0);
|
||||
return x;
|
||||
|
@ -34,7 +34,7 @@ int16 r = x - y;
|
|||
|
||||
uint16 sSMP::op_cmpw(uint16 x, uint16 y) {
|
||||
int32 r = x - y;
|
||||
regs.p.n = bool(r & 0x8000);
|
||||
regs.p.n = !!(r & 0x8000);
|
||||
regs.p.z = ((uint16)r == 0);
|
||||
regs.p.c = (r >= 0);
|
||||
return x;
|
||||
|
@ -42,22 +42,22 @@ int32 r = x - y;
|
|||
|
||||
uint8 sSMP::op_eor(uint8 x, uint8 y) {
|
||||
x ^= y;
|
||||
regs.p.n = bool(x & 0x80);
|
||||
regs.p.n = !!(x & 0x80);
|
||||
regs.p.z = (x == 0);
|
||||
return x;
|
||||
}
|
||||
|
||||
uint8 sSMP::op_or(uint8 x, uint8 y) {
|
||||
x |= y;
|
||||
regs.p.n = bool(x & 0x80);
|
||||
regs.p.n = !!(x & 0x80);
|
||||
regs.p.z = (x == 0);
|
||||
return x;
|
||||
}
|
||||
|
||||
uint8 sSMP::op_sbc(uint8 x, uint8 y) {
|
||||
int16 r = x - y - !regs.p.c;
|
||||
regs.p.n = bool(r & 0x80);
|
||||
regs.p.v = bool((x ^ y) & (x ^ (uint8)r) & 0x80);
|
||||
regs.p.n = !!(r & 0x80);
|
||||
regs.p.v = !!((x ^ y) & (x ^ (uint8)r) & 0x80);
|
||||
regs.p.h = !((x ^ y ^ (uint8)r) & 0x10);
|
||||
regs.p.z = ((uint8)r == 0);
|
||||
regs.p.c = (r >= 0);
|
||||
|
@ -65,74 +65,72 @@ int16 r = x - y - !regs.p.c;
|
|||
}
|
||||
|
||||
uint16 sSMP::op_subw(uint16 x, uint16 y) {
|
||||
int16 r;
|
||||
uint16 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.z = (r == 0);
|
||||
return r;
|
||||
}
|
||||
|
||||
uint8 sSMP::op_inc(uint8 x) {
|
||||
x++;
|
||||
regs.p.n = bool(x & 0x80);
|
||||
regs.p.n = !!(x & 0x80);
|
||||
regs.p.z = (x == 0);
|
||||
return x;
|
||||
}
|
||||
|
||||
uint16 sSMP::op_incw(uint16 x) {
|
||||
x++;
|
||||
regs.p.n = bool(x & 0x8000);
|
||||
regs.p.n = !!(x & 0x8000);
|
||||
regs.p.z = (x == 0);
|
||||
return x;
|
||||
}
|
||||
|
||||
uint8 sSMP::op_dec(uint8 x) {
|
||||
x--;
|
||||
regs.p.n = bool(x & 0x80);
|
||||
regs.p.n = !!(x & 0x80);
|
||||
regs.p.z = (x == 0);
|
||||
return x;
|
||||
}
|
||||
|
||||
uint16 sSMP::op_decw(uint16 x) {
|
||||
x--;
|
||||
regs.p.n = bool(x & 0x8000);
|
||||
regs.p.n = !!(x & 0x8000);
|
||||
regs.p.z = (x == 0);
|
||||
return x;
|
||||
}
|
||||
|
||||
uint8 sSMP::op_asl(uint8 x) {
|
||||
regs.p.c = bool(x & 0x80);
|
||||
regs.p.c = !!(x & 0x80);
|
||||
x <<= 1;
|
||||
regs.p.n = bool(x & 0x80);
|
||||
regs.p.n = !!(x & 0x80);
|
||||
regs.p.z = (x == 0);
|
||||
return x;
|
||||
}
|
||||
|
||||
uint8 sSMP::op_lsr(uint8 x) {
|
||||
regs.p.c = bool(x & 0x01);
|
||||
regs.p.c = !!(x & 0x01);
|
||||
x >>= 1;
|
||||
regs.p.n = bool(x & 0x80);
|
||||
regs.p.n = !!(x & 0x80);
|
||||
regs.p.z = (x == 0);
|
||||
return x;
|
||||
}
|
||||
|
||||
uint8 sSMP::op_rol(uint8 x) {
|
||||
uint8 c = regs.p.c;
|
||||
regs.p.c = bool(x & 0x80);
|
||||
x <<= 1;
|
||||
x |= c;
|
||||
regs.p.n = bool(x & 0x80);
|
||||
uint8 carry = (uint8)regs.p.c;
|
||||
regs.p.c = !!(x & 0x80);
|
||||
x = (x << 1) | carry;
|
||||
regs.p.n = !!(x & 0x80);
|
||||
regs.p.z = (x == 0);
|
||||
return x;
|
||||
}
|
||||
|
||||
uint8 sSMP::op_ror(uint8 x) {
|
||||
uint8 c = (regs.p.c)?0x80:0x00;
|
||||
regs.p.c = bool(x & 0x01);
|
||||
x >>= 1;
|
||||
x |= c;
|
||||
regs.p.n = bool(x & 0x80);
|
||||
uint8 carry = (uint8)regs.p.c << 7;
|
||||
regs.p.c = !!(x & 0x01);
|
||||
x = carry | (x >> 1);
|
||||
regs.p.n = !!(x & 0x80);
|
||||
regs.p.z = (x == 0);
|
||||
return x;
|
||||
}
|
||||
|
|
|
@ -1,32 +1,35 @@
|
|||
alwaysinline uint8 sSMP::ram_read(uint16 addr) {
|
||||
alwaysinline
|
||||
uint8 sSMP::ram_read(uint16 addr) {
|
||||
if(addr < 0xffc0)return spcram[addr];
|
||||
if(status.iplrom_enabled == false)return spcram[addr];
|
||||
return iplrom[addr & 0x3f];
|
||||
}
|
||||
|
||||
alwaysinline void sSMP::ram_write(uint16 addr, uint8 data) {
|
||||
alwaysinline
|
||||
void sSMP::ram_write(uint16 addr, uint8 data) {
|
||||
//writes to $ffc0-$ffff always go to spcram, even if the iplrom is enabled
|
||||
spcram[addr] = data;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
alwaysinline uint8 sSMP::port_read(uint8 port) {
|
||||
alwaysinline
|
||||
uint8 sSMP::port_read(uint8 port) {
|
||||
return spcram[0xf4 + (port & 3)];
|
||||
}
|
||||
|
||||
alwaysinline void sSMP::port_write(uint8 port, uint8 data) {
|
||||
alwaysinline
|
||||
void sSMP::port_write(uint8 port, uint8 data) {
|
||||
spcram[0xf4 + (port & 3)] = data;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
alwaysinline uint8 sSMP::op_busread(uint16 addr) {
|
||||
alwaysinline
|
||||
uint8 sSMP::op_busread(uint16 addr) {
|
||||
uint8 r;
|
||||
if((addr & 0xfff0) == 0x00f0) {
|
||||
//addr >= 0x00f0 && addr <= 0x00ff
|
||||
scheduler.sync_smpcpu();
|
||||
|
||||
switch(addr) {
|
||||
|
||||
case 0xf0: { //TEST -- write-only register
|
||||
|
@ -50,12 +53,13 @@ uint8 r;
|
|||
case 0xf5: //CPUIO1
|
||||
case 0xf6: //CPUIO2
|
||||
case 0xf7: { //CPUIO3
|
||||
scheduler.sync_smpcpu();
|
||||
r = r_cpu->port_read(addr & 3);
|
||||
} break;
|
||||
|
||||
case 0xf8: //???
|
||||
case 0xf9: { //??? -- Mapped to SPCRAM
|
||||
r = spcram[addr];
|
||||
r = ram_read(addr);
|
||||
} break;
|
||||
|
||||
case 0xfa: //T0TARGET
|
||||
|
@ -93,11 +97,10 @@ uint8 r;
|
|||
return r;
|
||||
}
|
||||
|
||||
alwaysinline void sSMP::op_buswrite(uint16 addr, uint8 data) {
|
||||
alwaysinline
|
||||
void sSMP::op_buswrite(uint16 addr, uint8 data) {
|
||||
if((addr & 0xfff0) == 0x00f0) {
|
||||
//addr >= 0x00f0 && addr >= 0x00ff
|
||||
scheduler.sync_smpcpu();
|
||||
|
||||
if(status.mmio_disabled == true)return;
|
||||
|
||||
switch(addr) {
|
||||
|
@ -123,15 +126,18 @@ alwaysinline void sSMP::op_buswrite(uint16 addr, uint8 data) {
|
|||
case 0xf1: { //CONTROL
|
||||
status.iplrom_enabled = !!(data & 0x80);
|
||||
|
||||
//one-time clearing of APU port read registers,
|
||||
//emulated by simulating CPU writes of 0x00
|
||||
if(data & 0x20) {
|
||||
r_cpu->port_write(2, 0x00);
|
||||
r_cpu->port_write(3, 0x00);
|
||||
}
|
||||
if(data & 0x10) {
|
||||
r_cpu->port_write(0, 0x00);
|
||||
r_cpu->port_write(1, 0x00);
|
||||
if(data & 0x30) {
|
||||
//one-time clearing of APU port read registers,
|
||||
//emulated by simulating CPU writes of 0x00
|
||||
scheduler.sync_smpcpu();
|
||||
if(data & 0x20) {
|
||||
r_cpu->port_write(2, 0x00);
|
||||
r_cpu->port_write(3, 0x00);
|
||||
}
|
||||
if(data & 0x10) {
|
||||
r_cpu->port_write(0, 0x00);
|
||||
r_cpu->port_write(1, 0x00);
|
||||
}
|
||||
}
|
||||
|
||||
//0->1 transistion resets timers
|
||||
|
@ -169,12 +175,14 @@ alwaysinline void sSMP::op_buswrite(uint16 addr, uint8 data) {
|
|||
case 0xf5: //CPUIO1
|
||||
case 0xf6: //CPUIO2
|
||||
case 0xf7: { //CPUIO3
|
||||
scheduler.sync_smpcpu();
|
||||
port_write(addr & 3, data);
|
||||
} break;
|
||||
|
||||
case 0xf8: //???
|
||||
case 0xf9: { //??? - Mapped to SPCRAM
|
||||
spcram[addr] = data;
|
||||
//$00f1.d1 (ram_writable) has no effect on these two addresses
|
||||
ram_write(addr, data);
|
||||
} break;
|
||||
|
||||
case 0xfa: { //T0TARGET
|
||||
|
@ -220,30 +228,37 @@ void sSMP::op_write(uint16 addr, uint8 data) {
|
|||
|
||||
//
|
||||
|
||||
alwaysinline uint8 sSMP::op_readpc() {
|
||||
alwaysinline
|
||||
uint8 sSMP::op_readpc() {
|
||||
return op_read(regs.pc++);
|
||||
}
|
||||
|
||||
alwaysinline uint8 sSMP::op_readstack() {
|
||||
alwaysinline
|
||||
uint8 sSMP::op_readstack() {
|
||||
return op_read(0x0100 | ++regs.sp);
|
||||
}
|
||||
|
||||
alwaysinline void sSMP::op_writestack(uint8 data) {
|
||||
alwaysinline
|
||||
void sSMP::op_writestack(uint8 data) {
|
||||
op_write(0x0100 | regs.sp--, data);
|
||||
}
|
||||
|
||||
alwaysinline uint8 sSMP::op_readaddr(uint16 addr) {
|
||||
alwaysinline
|
||||
uint8 sSMP::op_readaddr(uint16 addr) {
|
||||
return op_read(addr);
|
||||
}
|
||||
|
||||
alwaysinline void sSMP::op_writeaddr(uint16 addr, uint8 data) {
|
||||
alwaysinline
|
||||
void sSMP::op_writeaddr(uint16 addr, uint8 data) {
|
||||
op_write(addr, data);
|
||||
}
|
||||
|
||||
alwaysinline uint8 sSMP::op_readdp(uint8 addr) {
|
||||
alwaysinline
|
||||
uint8 sSMP::op_readdp(uint8 addr) {
|
||||
return op_read(((uint)regs.p.p << 8) + addr);
|
||||
}
|
||||
|
||||
alwaysinline void sSMP::op_writedp(uint8 addr, uint8 data) {
|
||||
alwaysinline
|
||||
void sSMP::op_writedp(uint8 addr, uint8 data) {
|
||||
op_write(((uint)regs.p.p << 8) + addr, data);
|
||||
}
|
||||
|
|
|
@ -14,7 +14,8 @@ alwaysinline void sSMP::add_clocks(uint clocks) {
|
|||
//1024000 / 768 = 32000 DSP ticks/second
|
||||
if(++status.dsp_counter == 32) {
|
||||
status.dsp_counter = 0;
|
||||
snes->audio_update(r_dsp->run());
|
||||
uint32 sample = r_dsp->run();
|
||||
snes.audio_update( (sample & 0xffff), (sample >> 16) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,28 +1,26 @@
|
|||
void SNES::audio_update(uint32 data) {
|
||||
void SNES::audio_update(uint16 l_sample, uint16 r_sample) {
|
||||
if(pcmfp) {
|
||||
fputc(data, pcmfp);
|
||||
fputc(data >> 8, pcmfp);
|
||||
fputc(data >> 16, pcmfp);
|
||||
fputc(data >> 24, pcmfp);
|
||||
fputlw(pcmfp, l_sample);
|
||||
fputlw(pcmfp, r_sample);
|
||||
}
|
||||
if(config::snes.mute == true) { l_sample = r_sample = 0x0000; }
|
||||
|
||||
if((bool)config::snes.mute == true)data = 0x0000;
|
||||
|
||||
sound_run(data);
|
||||
snesinterface.audio_sample(l_sample, r_sample);
|
||||
}
|
||||
|
||||
void SNES::log_audio_enable(const char *fn) {
|
||||
char tfn[256];
|
||||
int i;
|
||||
if(pcmfp)log_audio_disable();
|
||||
if(pcmfp) { log_audio_disable(); }
|
||||
|
||||
char tfn[256];
|
||||
if(!fn) {
|
||||
for(i=0;i<=999;i++) {
|
||||
int i = 0;
|
||||
while(i < 1000) {
|
||||
sprintf(tfn, "audio%0.3d.wav", i);
|
||||
pcmfp = fopen(tfn, "rb");
|
||||
if(!pcmfp)break;
|
||||
fclose(pcmfp);
|
||||
pcmfp = 0;
|
||||
i++;
|
||||
}
|
||||
if(i >= 1000)return;
|
||||
} else {
|
||||
|
|
|
@ -2,11 +2,9 @@ FILE *pcmfp;
|
|||
|
||||
//if a filename is not specified, one will be generated
|
||||
//automatically ("audio%0.3d.wav")
|
||||
void log_audio_enable(const char *fn = 0);
|
||||
void log_audio_disable();
|
||||
void log_audio_enable(const char *fn = 0);
|
||||
void log_audio_disable();
|
||||
|
||||
void audio_update(uint32 data);
|
||||
void audio_init();
|
||||
void audio_term();
|
||||
|
||||
virtual void sound_run(uint32 data) = 0;
|
||||
void audio_update(uint16 l_sample, uint16 r_sample);
|
||||
void audio_init();
|
||||
void audio_term();
|
||||
|
|
|
@ -61,6 +61,8 @@ void SNES::port_set_deviceid(bool port, uint deviceid) {
|
|||
}
|
||||
|
||||
void SNES::poll_input() {
|
||||
snesinterface.input_poll();
|
||||
|
||||
bool *p0 = input.port0_bits;
|
||||
bool *p1 = input.port1_bits;
|
||||
switch(input.port0_device) {
|
||||
|
@ -68,7 +70,7 @@ bool *p1 = input.port1_bits;
|
|||
break;
|
||||
|
||||
default:
|
||||
for(int i = 0; i < input.port0_devicebits; i++) { *p0++ = get_input_status(input.port0_deviceid, i); }
|
||||
for(int i = 0; i < input.port0_devicebits; i++) { *p0++ = snesinterface.input_poll(input.port0_deviceid, i); }
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -77,7 +79,7 @@ bool *p1 = input.port1_bits;
|
|||
break;
|
||||
|
||||
default:
|
||||
for(int i = 0; i < input.port1_devicebits; i++) { *p1++ = get_input_status(input.port1_deviceid, i); }
|
||||
for(int i = 0; i < input.port1_devicebits; i++) { *p1++ = snesinterface.input_poll(input.port1_deviceid, i); }
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -28,13 +28,5 @@ struct {
|
|||
|
||||
bool port_read(bool port);
|
||||
void port_set_deviceid(bool port, uint deviceid);
|
||||
|
||||
//The CPU calls poll_input() when the main interface should check the
|
||||
//status of all joypad buttons and cache the results...
|
||||
virtual void poll_input();
|
||||
|
||||
//...and then the CPU calls get_input_status() whenever it needs one
|
||||
//of the cached button values to be returned for emulation purposes.
|
||||
virtual bool get_input_status(uint8 device, uint8 button) { return false; }
|
||||
|
||||
virtual void input_init();
|
||||
void input_init();
|
||||
void poll_input();
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
/*****
|
||||
* SNES Interface class
|
||||
*
|
||||
* Interfaces SNES core with platform-specific functionality
|
||||
* (video, audio, input, ...)
|
||||
*****/
|
||||
|
||||
class SNESInterface {
|
||||
public:
|
||||
bool video_lock(uint16 *&data, uint &pitch);
|
||||
void video_unlock();
|
||||
void video_refresh();
|
||||
|
||||
void audio_sample(uint16 l_sample, uint16 r_sample);
|
||||
|
||||
void input_poll();
|
||||
bool input_poll(uint deviceid, uint button);
|
||||
};
|
||||
|
||||
extern SNESInterface snesinterface;
|
|
@ -10,23 +10,23 @@ void threadentry_smp() { r_smp->enter(); }
|
|||
void Scheduler::enter() {
|
||||
switch(clock.active) {
|
||||
case THREAD_CPU:
|
||||
co_jump(thread_cpu);
|
||||
co_switch(thread_cpu);
|
||||
break;
|
||||
case THREAD_SMP:
|
||||
co_jump(thread_smp);
|
||||
co_switch(thread_smp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void Scheduler::exit() {
|
||||
co_jump(thread_snes);
|
||||
co_switch(thread_snes);
|
||||
}
|
||||
|
||||
void Scheduler::init() {
|
||||
clock.cpu_freq = snes->region() == SNES::NTSC ?
|
||||
clock.cpu_freq = snes.region() == SNES::NTSC ?
|
||||
config::cpu.ntsc_clock_rate :
|
||||
config::cpu.pal_clock_rate;
|
||||
clock.smp_freq = snes->region() == SNES::NTSC ?
|
||||
clock.smp_freq = snes.region() == SNES::NTSC ?
|
||||
config::smp.ntsc_clock_rate :
|
||||
config::smp.pal_clock_rate;
|
||||
|
||||
|
@ -36,14 +36,15 @@ void Scheduler::init() {
|
|||
if(thread_cpu)co_delete(thread_cpu);
|
||||
if(thread_smp)co_delete(thread_smp);
|
||||
|
||||
thread_cpu = co_create(threadentry_cpu, 65536);
|
||||
thread_smp = co_create(threadentry_smp, 65536);
|
||||
thread_snes = co_active();
|
||||
thread_cpu = co_create(threadentry_cpu, COTHREAD_STACKSIZE_NORMAL);
|
||||
thread_smp = co_create(threadentry_smp, COTHREAD_STACKSIZE_NORMAL);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
Scheduler::Scheduler() {
|
||||
thread_snes = co_active();
|
||||
thread_snes = 0;
|
||||
thread_cpu = 0;
|
||||
thread_smp = 0;
|
||||
}
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
class Scheduler {
|
||||
public:
|
||||
|
||||
thread_t thread_snes;
|
||||
thread_t thread_cpu;
|
||||
thread_t thread_smp;
|
||||
cothread_t thread_snes;
|
||||
cothread_t thread_cpu;
|
||||
cothread_t thread_smp;
|
||||
|
||||
enum ActiveThread {
|
||||
THREAD_CPU,
|
||||
|
@ -21,25 +21,25 @@ struct {
|
|||
alwaysinline void sync_cpusmp() {
|
||||
if(clock.cpusmp < 0) {
|
||||
clock.active = THREAD_SMP;
|
||||
co_jump(thread_smp);
|
||||
co_switch(thread_smp);
|
||||
}
|
||||
}
|
||||
|
||||
alwaysinline void sync_smpcpu() {
|
||||
if(clock.cpusmp >= 0) {
|
||||
clock.active = THREAD_CPU;
|
||||
co_jump(thread_cpu);
|
||||
co_switch(thread_cpu);
|
||||
}
|
||||
}
|
||||
|
||||
alwaysinline void addclocks_cpu(uint clocks) {
|
||||
clock.cpusmp -= clocks * (uint64)clock.smp_freq;
|
||||
if(clock.cpusmp < -(275000 * (int64)24000000))sync_cpusmp();
|
||||
if(clock.cpusmp < -(250000 * (int64)20000000))sync_cpusmp();
|
||||
}
|
||||
|
||||
alwaysinline void addclocks_smp(uint clocks) {
|
||||
clock.cpusmp += clocks * (uint64)clock.cpu_freq;
|
||||
if(clock.cpusmp > +(275000 * (int64)24000000))sync_smpcpu();
|
||||
if(clock.cpusmp > +(250000 * (int64)20000000))sync_smpcpu();
|
||||
}
|
||||
|
||||
void enter();
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue