diff --git a/bsnes_accurate.exe b/bsnes_accurate.exe deleted file mode 100644 index 71a8c95c..00000000 Binary files a/bsnes_accurate.exe and /dev/null differ diff --git a/bsnes_fast.exe b/bsnes_fast.exe deleted file mode 100644 index f13268a2..00000000 Binary files a/bsnes_fast.exe and /dev/null differ diff --git a/cart.db b/cart.db deleted file mode 100644 index 83609d43..00000000 Binary files a/cart.db and /dev/null differ diff --git a/readme.txt b/readme.txt index 0e4762af..93926220 100644 --- a/readme.txt +++ b/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 diff --git a/src/base.h b/src/base.h index 66624047..a8d9d52f 100644 --- a/src/base.h +++ b/src/base.h @@ -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" diff --git a/src/cart/cart.cpp b/src/cart/cart.cpp index 612a1170..2f66c6b2 100644 --- a/src/cart/cart.cpp +++ b/src/cart/cart.cpp @@ -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 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() { diff --git a/src/cart/cart.h b/src/cart/cart.h index ffc22457..5ab19607 100644 --- a/src/cart/cart.h +++ b/src/cart/cart.h @@ -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(); diff --git a/src/cart/cart_file.cpp b/src/cart/cart_file.cpp new file mode 100644 index 00000000..b5ee0ead --- /dev/null +++ b/src/cart/cart_file.cpp @@ -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; +} diff --git a/src/cart/cart_header.cpp b/src/cart/cart_header.cpp new file mode 100644 index 00000000..a677ad9a --- /dev/null +++ b/src/cart/cart_header.cpp @@ -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; + } +} diff --git a/src/cart/cart_normal.cpp b/src/cart/cart_normal.cpp new file mode 100644 index 00000000..fad95cb6 --- /dev/null +++ b/src/cart/cart_normal.cpp @@ -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); +} diff --git a/src/cart/cart_st.cpp b/src/cart/cart_st.cpp new file mode 100644 index 00000000..4f639032 --- /dev/null +++ b/src/cart/cart_st.cpp @@ -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); +} diff --git a/src/cart/cart_stdual.cpp b/src/cart/cart_stdual.cpp new file mode 100644 index 00000000..5b7a4a55 --- /dev/null +++ b/src/cart/cart_stdual.cpp @@ -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); +} diff --git a/src/cart/db/cart.db b/src/cart/db/cart.db index 83609d43..a489d594 100644 Binary files a/src/cart/db/cart.db and b/src/cart/db/cart.db differ diff --git a/src/cart/db/cartdb.txt b/src/cart/db/cartdb.txt index 056ba7c3..668aadb1 100644 --- a/src/cart/db/cartdb.txt +++ b/src/cart/db/cartdb.txt @@ -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) [!]" diff --git a/src/cart/db/dbcreate.cpp b/src/cart/db/dbcreate.cpp index 288d778b..2ad529c5 100644 --- a/src/cart/db/dbcreate.cpp +++ b/src/cart/db/dbcreate.cpp @@ -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"); diff --git a/src/cheat/cheat.cpp b/src/cheat/cheat.cpp index e64e88e5..00e3c7a1 100644 --- a/src/cheat/cheat.cpp +++ b/src/cheat/cheat.cpp @@ -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; diff --git a/src/cheat/cheat.h b/src/cheat/cheat.h index eb5b0181..51386f57 100644 --- a/src/cheat/cheat.h +++ b/src/cheat/cheat.h @@ -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(); diff --git a/src/chip/obc1/obc1.cpp b/src/chip/obc1/obc1.cpp index 15cbbc63..01bffac7 100644 --- a/src/chip/obc1/obc1.cpp +++ b/src/chip/obc1/obc1.cpp @@ -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; } } diff --git a/src/config/config.cpp b/src/config/config.cpp index f6be3747..3a045834 100644 --- a/src/config/config.cpp +++ b/src/config/config.cpp @@ -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); }; diff --git a/src/config/config.h b/src/config/config.h index 45d72fcb..d0c4baba 100644 --- a/src/config/config.h +++ b/src/config/config.h @@ -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; diff --git a/src/cpu/cpu.h b/src/cpu/cpu.h index ae2b9555..ae8fa24e 100644 --- a/src/cpu/cpu.h +++ b/src/cpu/cpu.h @@ -2,7 +2,6 @@ class CPU : public MMIO { public: -thread_t thread; virtual void enter() = 0; public: diff --git a/src/cpu/scpu/core/op_misc.b b/src/cpu/scpu/core/op_misc.b index 33c2554f..e6f6b3ab 100644 --- a/src/cpu/scpu/core/op_misc.b +++ b/src/cpu/scpu/core/op_misc.b @@ -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; diff --git a/src/cpu/scpu/core/op_misc.cpp b/src/cpu/scpu/core/op_misc.cpp index e72b63e9..e96bd0c9 100644 --- a/src/cpu/scpu/core/op_misc.cpp +++ b/src/cpu/scpu/core/op_misc.cpp @@ -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; diff --git a/src/cpu/scpu/core/op_rmw.b b/src/cpu/scpu/core/op_rmw.b index cea0cd99..d3b8b2f1 100644 --- a/src/cpu/scpu/core/op_rmw.b +++ b/src/cpu/scpu/core/op_rmw.b @@ -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); } } diff --git a/src/cpu/scpu/core/op_rmw.cpp b/src/cpu/scpu/core/op_rmw.cpp index 104e47a6..7924a1ab 100644 --- a/src/cpu/scpu/core/op_rmw.cpp +++ b/src/cpu/scpu/core/op_rmw.cpp @@ -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; diff --git a/src/cpu/scpu/core/opfn.cpp b/src/cpu/scpu/core/opfn.cpp index ca981f41..9527d983 100644 --- a/src/cpu/scpu/core/opfn.cpp +++ b/src/cpu/scpu/core/opfn.cpp @@ -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); } diff --git a/src/cpu/scpu/dma/dma.cpp b/src/cpu/scpu/dma/dma.cpp index bf15c955..c1d87fe5 100644 --- a/src/cpu/scpu/dma/dma.cpp +++ b/src/cpu/scpu/dma/dma.cpp @@ -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); } /***** diff --git a/src/cpu/scpu/dma/dma.h b/src/cpu/scpu/dma/dma.h index 104ebe44..845e2f8d 100644 --- a/src/cpu/scpu/dma/dma.h +++ b/src/cpu/scpu/dma/dma.h @@ -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); diff --git a/src/cpu/scpu/mmio/mmio.cpp b/src/cpu/scpu/mmio/mmio.cpp index fdd9534e..66b1320d 100644 --- a/src/cpu/scpu/mmio/mmio.cpp +++ b/src/cpu/scpu/mmio/mmio.cpp @@ -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; } diff --git a/src/cpu/scpu/scpu.cpp b/src/cpu/scpu/scpu.cpp index e7658acc..4fdba6fd 100644 --- a/src/cpu/scpu/scpu.cpp +++ b/src/cpu/scpu/scpu.cpp @@ -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; diff --git a/src/cpu/scpu/scpu.h b/src/cpu/scpu/scpu.h index f2d45c9c..a9c991ed 100644 --- a/src/cpu/scpu/scpu.h +++ b/src/cpu/scpu/scpu.h @@ -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; diff --git a/src/cpu/scpu/timing/irq.cpp b/src/cpu/scpu/timing/irq.cpp index f84c71dc..0765ee93 100644 --- a/src/cpu/scpu/timing/irq.cpp +++ b/src/cpu/scpu/timing/irq.cpp @@ -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; } +*/ diff --git a/src/cpu/scpu/timing/irqtiming.cpp b/src/cpu/scpu/timing/irqtiming.cpp new file mode 100644 index 00000000..f29e6d5d --- /dev/null +++ b/src/cpu/scpu/timing/irqtiming.cpp @@ -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; +} diff --git a/src/cpu/scpu/timing/irqtiming_accurate.cpp b/src/cpu/scpu/timing/irqtiming_accurate.cpp deleted file mode 100644 index 31365381..00000000 --- a/src/cpu/scpu/timing/irqtiming_accurate.cpp +++ /dev/null @@ -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; } -} diff --git a/src/cpu/scpu/timing/irqtiming_fast.cpp b/src/cpu/scpu/timing/irqtiming_fast.cpp deleted file mode 100644 index 4d2b4d83..00000000 --- a/src/cpu/scpu/timing/irqtiming_fast.cpp +++ /dev/null @@ -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; } -} diff --git a/src/cpu/scpu/timing/joypad.cpp b/src/cpu/scpu/timing/joypad.cpp index 841c9ae7..3cd1924a 100644 --- a/src/cpu/scpu/timing/joypad.cpp +++ b/src/cpu/scpu/timing/joypad.cpp @@ -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; diff --git a/src/cpu/scpu/timing/timeshift.cpp b/src/cpu/scpu/timing/timeshift.cpp index 79ad8927..1f1408fb 100644 --- a/src/cpu/scpu/timing/timeshift.cpp +++ b/src/cpu/scpu/timing/timeshift.cpp @@ -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; } } } diff --git a/src/cpu/scpu/timing/timing.cpp b/src/cpu/scpu/timing/timing.cpp index a2c2e461..e14d1e0a 100644 --- a/src/cpu/scpu/timing/timing.cpp +++ b/src/cpu/scpu/timing/timing.cpp @@ -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(); diff --git a/src/cpu/scpu/timing/timing.h b/src/cpu/scpu/timing/timing.h index 05817c90..975aa1b5 100644 --- a/src/cpu/scpu/timing/timing.h +++ b/src/cpu/scpu/timing/timing.h @@ -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(); diff --git a/src/dsp/bdsp/bdsp.cpp b/src/dsp/bdsp/bdsp.cpp index debc9d4f..681a4327 100644 --- a/src/dsp/bdsp/bdsp.cpp +++ b/src/dsp/bdsp/bdsp.cpp @@ -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() {} diff --git a/src/lib/libbase.h b/src/lib/libbase.h index 800bec54..90bbc1b9 100644 --- a/src/lib/libbase.h +++ b/src/lib/libbase.h @@ -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 @@ -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 inline void safe_free(T &handle) { + if(handle) { + free(handle); + handle = 0; + } +} + +template inline void safe_delete(T &handle) { + if(handle) { + delete handle; + handle = 0; + } +} + +template inline void safe_release(T &handle) { + if(handle) { + handle->Release(); + handle = 0; + } +} + template 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 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 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 diff --git a/src/lib/libco_win32.cpp b/src/lib/libco_win32.cpp index 7418d168..33fe0c70 100644 --- a/src/lib/libco_win32.cpp +++ b/src/lib/libco_win32.cpp @@ -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(coentry); + s->coentry(); + co_exit(0); +} + +cothread_t co_init() { ConvertThreadToFiber(0); +cothread_struct *s = static_cast(malloc(sizeof(cothread_struct))); + s->colink = 0; + s->coentry = 0; + s->cohandle = GetCurrentFiber(); + __co_active = __co_primary = static_cast(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(malloc(sizeof(cothread_struct))); + s->colink = co_active(); + s->coentry = coentry; + s->cohandle = CreateFiber(heapsize + 512, co_entryproc, static_cast(s)); + return static_cast(s); } -void co_delete(thread_t cothread) { - DeleteFiber(cothread); +void co_delete(cothread_t cothread) { +cothread_struct *s = static_cast(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); + 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(__co_active); + co_switch(s->colink); } diff --git a/src/lib/libco_win32.h b/src/lib/libco_win32.h index 8cd9857a..9c753110 100644 --- a/src/lib/libco_win32.h +++ b/src/lib/libco_win32.h @@ -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); diff --git a/src/lib/libco_x86.asm b/src/lib/libco_x86.asm index 0db03ed3..01fc6fed 100644 --- a/src/lib/libco_x86.asm +++ b/src/lib/libco_x86.asm @@ -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 diff --git a/src/lib/libco_x86.h b/src/lib/libco_x86.h index a08a5347..3f482c7e 100644 --- a/src/lib/libco_x86.h +++ b/src/lib/libco_x86.h @@ -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); diff --git a/src/lib/libconfig.cpp b/src/lib/libconfig.cpp index bf4b8a41..49a86dae 100644 --- a/src/lib/libconfig.cpp +++ b/src/lib/libconfig.cpp @@ -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)); } diff --git a/src/lib/libconfig.h b/src/lib/libconfig.h index 45c4ea30..3cf9af0a 100644 --- a/src/lib/libconfig.h +++ b/src/lib/libconfig.h @@ -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 inline bool operator> (const T &x) { return (T)get() > x; } template inline bool operator<=(const T &x) { return (T)get() <= x; } template 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(); }; diff --git a/src/lib/libfile.h b/src/lib/libfile.h index 094cea1a..ba9a3c1a 100644 --- a/src/lib/libfile.h +++ b/src/lib/libfile.h @@ -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); } /***** diff --git a/src/lib/libsort.h b/src/lib/libsort.h new file mode 100644 index 00000000..d0899e10 --- /dev/null +++ b/src/lib/libsort.h @@ -0,0 +1,34 @@ +/* + libsort : version 0.01 ~byuu (2006-11-15) +*/ + +#ifndef __LIBSORT +#define __LIBSORT + +template +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 +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 diff --git a/src/lib/libstring.cpp b/src/lib/libstring.cpp index fe846645..0dbb02a1 100644 --- a/src/lib/libstring.cpp +++ b/src/lib/libstring.cpp @@ -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 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 diff --git a/src/lib/libstring_int.cpp b/src/lib/libstring_int.cpp new file mode 100644 index 00000000..9c4c7ae4 --- /dev/null +++ b/src/lib/libstring_int.cpp @@ -0,0 +1,5 @@ +string strfmt(const char *fmt, int num) { +string temp; + sprintf(temp, fmt, num); + return temp; +} diff --git a/src/lib/libstring_oo.cpp b/src/lib/libstring_oo.cpp new file mode 100644 index 00000000..4b6c4c56 --- /dev/null +++ b/src/lib/libstring_oo.cpp @@ -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; +} diff --git a/src/lib/libstring_replace.cpp b/src/lib/libstring_replace.cpp index eb0d93ed..c7421a7c 100644 --- a/src/lib/libstring_replace.cpp +++ b/src/lib/libstring_replace.cpp @@ -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)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)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++; diff --git a/src/lib/libstring_sprintf.cpp b/src/lib/libstring_sprintf.cpp index 778e9074..c7bb0259 100644 --- a/src/lib/libstring_sprintf.cpp +++ b/src/lib/libstring_sprintf.cpp @@ -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); } diff --git a/src/lib/libups.h b/src/lib/libups.h index cf312655..8da9fb1d 100644 --- a/src/lib/libups.h +++ b/src/lib/libups.h @@ -226,33 +226,33 @@ uint ptr = 0; template void UPS::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 @@ -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 @@ -385,7 +385,7 @@ void UPS::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; } diff --git a/src/lib/libwin32_button.cpp b/src/lib/libwin32_button.cpp index a2d12160..7deff61a 100644 --- a/src/lib/libwin32_button.cpp +++ b/src/lib/libwin32_button.cpp @@ -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, diff --git a/src/lib/libwin32_checkbox.cpp b/src/lib/libwin32_checkbox.cpp index f2c99185..77fab37f 100644 --- a/src/lib/libwin32_checkbox.cpp +++ b/src/lib/libwin32_checkbox.cpp @@ -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; diff --git a/src/lib/libwin32_combobox.cpp b/src/lib/libwin32_combobox.cpp index c3c887b9..d6083a00 100644 --- a/src/lib/libwin32_combobox.cpp +++ b/src/lib/libwin32_combobox.cpp @@ -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++) { diff --git a/src/lib/libwin32_control.cpp b/src/lib/libwin32_control.cpp index 301d280e..4ec39712 100644 --- a/src/lib/libwin32_control.cpp +++ b/src/lib/libwin32_control.cpp @@ -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() { diff --git a/src/lib/libwin32_editbox.cpp b/src/lib/libwin32_editbox.cpp index c5f458c8..66b3e61a 100644 --- a/src/lib/libwin32_editbox.cpp +++ b/src/lib/libwin32_editbox.cpp @@ -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, diff --git a/src/lib/libwin32_groupbox.cpp b/src/lib/libwin32_groupbox.cpp index 0316dfca..50e08b94 100644 --- a/src/lib/libwin32_groupbox.cpp +++ b/src/lib/libwin32_groupbox.cpp @@ -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, diff --git a/src/lib/libwin32_label.cpp b/src/lib/libwin32_label.cpp index e113db8e..84d31d94 100644 --- a/src/lib/libwin32_label.cpp +++ b/src/lib/libwin32_label.cpp @@ -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, diff --git a/src/lib/libwin32_listbox.cpp b/src/lib/libwin32_listbox.cpp index ffd0ff29..40edd490 100644 --- a/src/lib/libwin32_listbox.cpp +++ b/src/lib/libwin32_listbox.cpp @@ -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++) { diff --git a/src/lib/libwin32_listview.cpp b/src/lib/libwin32_listview.cpp index bffc7715..566f2627 100644 --- a/src/lib/libwin32_listview.cpp +++ b/src/lib/libwin32_listview.cpp @@ -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, diff --git a/src/lib/libwin32_radiobox.cpp b/src/lib/libwin32_radiobox.cpp index ec1a56da..d16d9edc 100644 --- a/src/lib/libwin32_radiobox.cpp +++ b/src/lib/libwin32_radiobox.cpp @@ -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; diff --git a/src/lib/libwin32_slider.cpp b/src/lib/libwin32_slider.cpp index c0581dc5..c2fde39e 100644 --- a/src/lib/libwin32_slider.cpp +++ b/src/lib/libwin32_slider.cpp @@ -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, diff --git a/src/lib/libwin32_window.cpp b/src/lib/libwin32_window.cpp index 7acc2781..ebbda013 100644 --- a/src/lib/libwin32_window.cpp +++ b/src/lib/libwin32_window.cpp @@ -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; diff --git a/src/lib/opgen_s.cpp b/src/lib/opgen_s.cpp index 44228bee..7d90d0e8 100644 --- a/src/lib/opgen_s.cpp +++ b/src/lib/opgen_s.cpp @@ -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]); diff --git a/src/memory/bmemory/bmemory.cpp b/src/memory/bmemory/bmemory.cpp index f6a1e9ad..ed01b3ad 100644 --- a/src/memory/bmemory/bmemory.cpp +++ b/src/memory/bmemory/bmemory.cpp @@ -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; diff --git a/src/memory/bmemory/bmemory_mapper_generic.cpp b/src/memory/bmemory/bmemory_mapper_generic.cpp index b4614d71..3b5c1e07 100644 --- a/src/memory/bmemory/bmemory_mapper_generic.cpp +++ b/src/memory/bmemory/bmemory_mapper_generic.cpp @@ -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; diff --git a/src/memory/bmemory/mapper/mapper.cpp b/src/memory/bmemory/mapper/mapper.cpp index e2269bd2..accfe7dc 100644 --- a/src/memory/bmemory/mapper/mapper.cpp +++ b/src/memory/bmemory/mapper/mapper.cpp @@ -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; diff --git a/src/memory/bmemory/mapper/mapper.h b/src/memory/bmemory/mapper/mapper.h index d41613c8..2ce0a3a3 100644 --- a/src/memory/bmemory/mapper/mapper.h +++ b/src/memory/bmemory/mapper/mapper.h @@ -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 diff --git a/src/memory/bmemory/mapper/mapper_pcb.cpp b/src/memory/bmemory/mapper/mapper_pcb.cpp index 87714dc5..b4171115 100644 --- a/src/memory/bmemory/mapper/mapper_pcb.cpp +++ b/src/memory/bmemory/mapper/mapper_pcb.cpp @@ -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); +} diff --git a/src/ppu/bppu/bppu.cpp b/src/ppu/bppu/bppu.cpp index 42c6fa27..591dd126 100644 --- a/src/ppu/bppu/bppu.cpp +++ b/src/ppu/bppu/bppu.cpp @@ -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; diff --git a/src/ppu/bppu/bppu_mmio.cpp b/src/ppu/bppu/bppu_mmio.cpp index 4fd03248..19d723a3 100644 --- a/src/ppu/bppu/bppu_mmio.cpp +++ b/src/ppu/bppu/bppu_mmio.cpp @@ -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; } diff --git a/src/ppu/bppu/bppu_render_cache.cpp b/src/ppu/bppu/bppu_render_cache.cpp index 40b07695..79113b46 100644 --- a/src/ppu/bppu/bppu_render_cache.cpp +++ b/src/ppu/bppu/bppu_render_cache.cpp @@ -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) { diff --git a/src/ppu/bppu/bppu_render_oam.cpp b/src/ppu/bppu/bppu_render_oam.cpp index fb87ef5c..2cf3184e 100644 --- a/src/ppu/bppu/bppu_render_oam.cpp +++ b/src/ppu/bppu/bppu_render_oam.cpp @@ -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; diff --git a/src/reader/jmareader.cpp b/src/reader/jmareader.cpp index f3376cbb..6b9372f9 100644 --- a/src/reader/jmareader.cpp +++ b/src/reader/jmareader.cpp @@ -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 file_info = JMAFile.get_files_info(); for (std::vector::iterator i = file_info.begin(); i != file_info.end(); i++) diff --git a/src/reader/jmareader.h b/src/reader/jmareader.h index 7fc0d4f9..78eb19a5 100644 --- a/src/reader/jmareader.h +++ b/src/reader/jmareader.h @@ -12,6 +12,6 @@ public: uint32 size(); uint8 *read(uint32 length = 0); - JMAReader(char *fn); + JMAReader(const char *fn); ~JMAReader() { } }; diff --git a/src/reader/reader.cpp b/src/reader/reader.cpp index 1d44af80..bb18db25 100644 --- a/src/reader/reader.cpp +++ b/src/reader/reader.cpp @@ -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; diff --git a/src/reader/reader.h b/src/reader/reader.h index e69e79da..15fc13ec 100644 --- a/src/reader/reader.h +++ b/src/reader/reader.h @@ -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 diff --git a/src/reader/zipreader.cpp b/src/reader/zipreader.cpp index 4f671cab..732fec9a 100644 --- a/src/reader/zipreader.cpp +++ b/src/reader/zipreader.cpp @@ -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)]; diff --git a/src/reader/zipreader.h b/src/reader/zipreader.h index 14eacd58..05a90946 100644 --- a/src/reader/zipreader.h +++ b/src/reader/zipreader.h @@ -15,7 +15,7 @@ public: uint32 size(); uint8 *read(uint32 length = 0); - ZipReader(char *fn); + ZipReader(const char *fn); ~ZipReader() { if (zipfile) diff --git a/src/smp/smp.h b/src/smp/smp.h index 87e12258..cf792492 100644 --- a/src/smp/smp.h +++ b/src/smp/smp.h @@ -2,7 +2,6 @@ class SMP { public: -thread_t thread; virtual void enter() = 0; public: diff --git a/src/smp/ssmp/core/op_mov.b b/src/smp/ssmp/core/op_mov.b index 19fda37a..d5b8f991 100644 --- a/src/smp/ssmp/core/op_mov.b +++ b/src/smp/ssmp/core/op_mov.b @@ -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); } diff --git a/src/smp/ssmp/core/op_mov.cpp b/src/smp/ssmp/core/op_mov.cpp index 45a4165b..d2800edd 100644 --- a/src/smp/ssmp/core/op_mov.cpp +++ b/src/smp/ssmp/core/op_mov.cpp @@ -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; diff --git a/src/smp/ssmp/core/op_read.b b/src/smp/ssmp/core/op_read.b index f5ebff01..fa2ed350 100644 --- a/src/smp/ssmp/core/op_read.b +++ b/src/smp/ssmp/core/op_read.b @@ -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(); diff --git a/src/smp/ssmp/core/op_read.cpp b/src/smp/ssmp/core/op_read.cpp index ec14a189..3a2583c0 100644 --- a/src/smp/ssmp/core/op_read.cpp +++ b/src/smp/ssmp/core/op_read.cpp @@ -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(); diff --git a/src/smp/ssmp/core/opfn.cpp b/src/smp/ssmp/core/opfn.cpp index d4aed28f..dc2f9408 100644 --- a/src/smp/ssmp/core/opfn.cpp +++ b/src/smp/ssmp/core/opfn.cpp @@ -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; } diff --git a/src/smp/ssmp/memory/memory.cpp b/src/smp/ssmp/memory/memory.cpp index 6cbe5abd..3c74de44 100644 --- a/src/smp/ssmp/memory/memory.cpp +++ b/src/smp/ssmp/memory/memory.cpp @@ -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); } diff --git a/src/smp/ssmp/timing/timing.cpp b/src/smp/ssmp/timing/timing.cpp index 6da21668..4dd91355 100644 --- a/src/smp/ssmp/timing/timing.cpp +++ b/src/smp/ssmp/timing/timing.cpp @@ -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) ); } } } diff --git a/src/snes/audio/audio.cpp b/src/snes/audio/audio.cpp index af617cba..f582c9db 100644 --- a/src/snes/audio/audio.cpp +++ b/src/snes/audio/audio.cpp @@ -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 { diff --git a/src/snes/audio/audio.h b/src/snes/audio/audio.h index 1442e57c..7b51c6a5 100644 --- a/src/snes/audio/audio.h +++ b/src/snes/audio/audio.h @@ -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(); diff --git a/src/snes/input/input.cpp b/src/snes/input/input.cpp index a5f7a792..123438ca 100644 --- a/src/snes/input/input.cpp +++ b/src/snes/input/input.cpp @@ -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; } diff --git a/src/snes/input/input.h b/src/snes/input/input.h index b2e414bf..e5a94a31 100644 --- a/src/snes/input/input.h +++ b/src/snes/input/input.h @@ -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(); diff --git a/src/snes/interface/interface.h b/src/snes/interface/interface.h new file mode 100644 index 00000000..160cc7a6 --- /dev/null +++ b/src/snes/interface/interface.h @@ -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; diff --git a/src/snes/scheduler/scheduler.cpp b/src/snes/scheduler/scheduler.cpp index 385d1193..470a996e 100644 --- a/src/snes/scheduler/scheduler.cpp +++ b/src/snes/scheduler/scheduler.cpp @@ -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; } diff --git a/src/snes/scheduler/scheduler.h b/src/snes/scheduler/scheduler.h index 6b55170d..095b9888 100644 --- a/src/snes/scheduler/scheduler.h +++ b/src/snes/scheduler/scheduler.h @@ -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(); diff --git a/src/snes/snes.cpp b/src/snes/snes.cpp index 56b4ca81..36edef94 100644 --- a/src/snes/snes.cpp +++ b/src/snes/snes.cpp @@ -1,6 +1,6 @@ #include "../base.h" -SNES *snes; +SNES snes; #include "scheduler/scheduler.cpp" #include "tracer/tracer.cpp" diff --git a/src/snes/snes.h b/src/snes/snes.h index 58bedad3..65348e57 100644 --- a/src/snes/snes.h +++ b/src/snes/snes.h @@ -1,3 +1,4 @@ +#include "interface/interface.h" #include "scheduler/scheduler.h" #include "tracer/tracer.h" @@ -34,6 +35,6 @@ enum { NTSC = 0, PAL = 1 }; virtual ~SNES() {} }; -extern SNES *snes; +extern SNES snes; #include "video/filter.h" diff --git a/src/snes/video/filter_ntsc_core.h b/src/snes/video/filter_ntsc_core.h index fa6ad8a7..26381733 100644 --- a/src/snes/video/filter_ntsc_core.h +++ b/src/snes/video/filter_ntsc_core.h @@ -174,15 +174,15 @@ enum { snes_ntsc_clamp_add = ntsc_rgb_builder * 0x101 }; if ( bits == 16 ) {\ rgb_out = (raw>>(13-x)& 0xF800)|(raw>>(8-x)&0x07E0)|(raw>>(4-x)&0x001F);\ rgb_out = ((rgb_out&0xf800)>>11)|((rgb_out&0x07c0)>>1)|((rgb_out&0x001f)<<10);\ - rgb_out = snes->color_lookup_table[rgb_out];\ + rgb_out = snes.color_lookup_table[rgb_out];\ } else if ( bits == 24 || bits == 32 ) {\ rgb_out = (raw>>(5-x)&0xFF0000)|(raw>>(3-x)&0xFF00)|(raw>>(1-x)&0xFF);\ rgb_out = ((rgb_out&0xf80000)>>19)|((rgb_out&0x00f800)>>6)|((rgb_out&0x0000f8)<<7);\ - rgb_out = snes->color_lookup_table[rgb_out];\ + rgb_out = snes.color_lookup_table[rgb_out];\ } else if ( bits == 15 ) {\ rgb_out = (raw>>(14-x)& 0x7C00)|(raw>>(9-x)&0x03E0)|(raw>>(4-x)&0x001F);\ rgb_out = ((rgb_out&0x7c00)>>10)|((rgb_out&0x03e0))|((rgb_out&0x001f)<<10);\ - rgb_out = snes->color_lookup_table[rgb_out];\ + rgb_out = snes.color_lookup_table[rgb_out];\ } else {\ rgb_out = raw;\ }\ diff --git a/src/snes/video/video.cpp b/src/snes/video/video.cpp index 4de5d70b..4eefe972 100644 --- a/src/snes/video/video.cpp +++ b/src/snes/video/video.cpp @@ -63,19 +63,18 @@ void SNES::video_update() { if(video.frame_hires) { video.raster_width <<= 1; } if(video.frame_interlace) { video.raster_height <<= 1; } - video.data = (uint16*)video_lock(video.pitch); - if(video.data) { + if(snesinterface.video_lock(video.data, video.pitch) == true) { video_filter->run(color_lookup_table, video.ppu_data, video.raster_width, video.raster_height, video.raster_height <= 240 ? 2048 : 1024, video.data, 512, 480, video.pitch, 512, 480, video.width, video.height, video.raster_height <= 240 ? (pline_width + 1) : (iline_width + 2)); - video_unlock(); + snesinterface.video_unlock(); } } - video_run(); + snesinterface.video_refresh(); video.frame_hires = false; video.frame_interlace = false; diff --git a/src/snes/video/video.h b/src/snes/video/video.h index 3988a1f5..82cde537 100644 --- a/src/snes/video/video.h +++ b/src/snes/video/video.h @@ -47,17 +47,14 @@ struct video_info { //public functions void update_color_lookup_table(); - virtual void set_video_format(uint filter, uint video_standard, uint pixel_format); - virtual void get_video_info(video_info *info); - virtual void video_run() = 0; - virtual uint16 *video_lock(uint &pitch) = 0; - virtual void video_unlock() = 0; + void set_video_format(uint filter, uint video_standard, uint pixel_format); + void get_video_info(video_info *info); //private functions private: - void update_video_format(); - void video_normalize(); - void video_update(); - void video_scanline(); - void video_init(); + void update_video_format(); + void video_normalize(); + void video_update(); + void video_scanline(); + void video_init(); public: diff --git a/src/ui/Makefile b/src/ui/Makefile index 247f2bcf..4824411a 100644 --- a/src/ui/Makefile +++ b/src/ui/Makefile @@ -25,26 +25,16 @@ endif ifeq ($(PLATFORM),win-visualc) OS = win CC = cl -CFLAGS = /nologo /O2 /EHsc /arch:SSE2 /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86 /DUI_WIN +CFLAGS = /nologo /wd4996 /O2 /EHsc /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86 /DUI_WIN AS = nasm ASFLAGS = -f win32 -DWIN32 LIBS = d3d9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib endif -ifeq ($(PLATFORM),win-visualc-wip) -OS = win -CC = cl -CFLAGS = /nologo /O2 /GL /EHsc /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86 /DUI_WIN -AS = nasm -ASFLAGS = -f win32 -DWIN32 -LIBS = d3d9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib -LINK = /link /LTCG -endif - ifeq ($(PLATFORM),win-visualc-pgi) OS = win CC = cl -CFLAGS = /nologo /O2 /GL /EHsc /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86 /DUI_WIN +CFLAGS = /nologo /wd4996 /O2 /GL /EHsc /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86 /DUI_WIN AS = nasm ASFLAGS = -f win32 -DWIN32 LIBS = d3d9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib @@ -54,7 +44,7 @@ endif ifeq ($(PLATFORM),win-visualc-pgo) OS = win CC = cl -CFLAGS = /nologo /O2 /GL /EHsc /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86 /DUI_WIN +CFLAGS = /nologo /wd4996 /O2 /GL /EHsc /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86 /DUI_WIN AS = nasm ASFLAGS = -f win32 -DWIN32 LIBS = d3d9.lib ddraw.lib dsound.lib dinput8.lib dxguid.lib @@ -64,7 +54,7 @@ endif ifeq ($(PLATFORM),win-visualc-sdl) OS = win CC = cl -CFLAGS = /nologo /O2 /EHsc /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86 /DUI_SDL +CFLAGS = /nologo /wd4996 /O2 /EHsc /DPLATFORM_WIN /DCOMPILER_VISUALC /DPROCESSOR_X86 /DUI_SDL AS = nasm ASFLAGS = -f win32 -DWIN32 LIBS = sdlmain.lib sdl.lib dsound.lib diff --git a/src/ui/audio/dsound.cpp b/src/ui/audio/dsound.cpp index a6bd2397..f4c8e1a4 100644 --- a/src/ui/audio/dsound.cpp +++ b/src/ui/audio/dsound.cpp @@ -60,7 +60,7 @@ void AudioDS::init() { clear_audio(); term(); - data.samples_per_frame = (uint)( (double)frequency / ((snes->region() == SNES::NTSC) ? 60.0 : 50.0) + 0.5 ); + data.samples_per_frame = (uint)( (double)frequency / ((snes.region() == SNES::NTSC) ? 60.0 : 50.0) + 0.5 ); data.buffer_size = data.samples_per_frame * sizeof(uint32); data.buffer_count = 4; data.buffer = (uint32*)malloc(data.buffer_size * data.buffer_count); diff --git a/src/ui/cc.bat b/src/ui/cc.bat index e6e3ce31..2dcd14b0 100644 --- a/src/ui/cc.bat +++ b/src/ui/cc.bat @@ -1,3 +1,3 @@ -@make PLATFORM=win-visualc-wip +@make PLATFORM=win-visualc @move bsnes.exe ../../bsnes.exe>nul @pause \ No newline at end of file diff --git a/src/ui/input/input.cpp b/src/ui/input/input.cpp index 5416eb10..b1648a97 100644 --- a/src/ui/input/input.cpp +++ b/src/ui/input/input.cpp @@ -211,7 +211,7 @@ uint r = key.find(strptr(p[0])) & 4095; void Input::init() { stringarray t, part; - strcpy(t, config::input.joypad1.map.sget()); + strcpy(t, config::input.joypad1.map.strget()); replace(t, " ", ""); replace(t, "\t", ""); strlower(t); @@ -229,7 +229,7 @@ stringarray t, part; config::input.joypad1.select = decode(part[10]); config::input.joypad1.start = decode(part[11]); - strcpy(t, config::input.joypad2.map.sget()); + strcpy(t, config::input.joypad2.map.strget()); replace(t, " ", ""); replace(t, "\t", ""); strlower(t); @@ -273,7 +273,7 @@ char t[256]; strcat(result, encode((uint)config::input.joypad1.r)); strcat(result, "; "); strcat(result, encode((uint)config::input.joypad1.select)); strcat(result, "; "); strcat(result, encode((uint)config::input.joypad1.start)); - config::input.joypad1.map.sset(strptr(result)); + config::input.joypad1.map.strset(strptr(result)); strcpy(result, ""); strcat(result, encode((uint)config::input.joypad2.up)); strcat(result, "; "); @@ -288,7 +288,7 @@ char t[256]; strcat(result, encode((uint)config::input.joypad2.r)); strcat(result, "; "); strcat(result, encode((uint)config::input.joypad2.select)); strcat(result, "; "); strcat(result, encode((uint)config::input.joypad2.start)); - config::input.joypad2.map.sset(strptr(result)); + config::input.joypad2.map.strset(strptr(result)); } Input::Input() { diff --git a/src/ui/interface.cpp b/src/ui/interface.cpp new file mode 100644 index 00000000..8fafda99 --- /dev/null +++ b/src/ui/interface.cpp @@ -0,0 +1,31 @@ +SNESInterface snesinterface; + +//video + +bool SNESInterface::video_lock(uint16 *&data, uint &pitch) { + return uiVideo->lock(data, pitch); +} + +void SNESInterface::video_unlock() { + uiVideo->unlock(); +} + +void SNESInterface::video_refresh() { + if(r_ppu->renderer_enabled() == true) { uiVideo->update(); } +} + +//audio + +void SNESInterface::audio_sample(uint16 l_sample, uint16 r_sample) { + uiAudio->run( (l_sample) | (r_sample << 16) ); +} + +//input + +void SNESInterface::input_poll() { + uiInput->poll(); +} + +bool SNESInterface::input_poll(uint deviceid, uint button) { + return uiInput->get_status(deviceid, button); +} diff --git a/src/ui/main.cpp b/src/ui/main.cpp index a8482157..07a76b6a 100644 --- a/src/ui/main.cpp +++ b/src/ui/main.cpp @@ -8,7 +8,7 @@ void init_snes(); void term_snes(); /***** - * OS abstraction layer + * hardware abstraction layer *****/ #include "video/video.h" @@ -18,6 +18,8 @@ void term_snes(); #include "video/video.cpp" #include "input/input.cpp" +#include "interface.cpp" + /***** * platform abstraction layer *****/ @@ -37,6 +39,8 @@ void term_snes(); *****/ void init_snes() { + co_init(); + #ifdef POLYMORPHISM deref(mem) = new MEMCORE(); deref(cpu) = new CPUCORE(); @@ -44,20 +48,20 @@ void init_snes() { deref(dsp) = new DSPCORE(); deref(ppu) = new PPUCORE(); #endif - snes = new bSNES(); - bsnes = static_cast(snes); - snes->init(); + snes.init(); } void term_snes() { - snes->term(); + snes.term(); + #ifdef POLYMORPHISM - SafeDelete(deref(mem)); - SafeDelete(deref(cpu)); - SafeDelete(deref(apu)); - SafeDelete(deref(dsp)); - SafeDelete(deref(ppu)); + safe_delete(deref(mem)); + safe_delete(deref(cpu)); + safe_delete(deref(apu)); + safe_delete(deref(dsp)); + safe_delete(deref(ppu)); #endif - SafeDelete(snes); + + co_term(); } diff --git a/src/ui/video/d3d.cpp b/src/ui/video/d3d.cpp index 44fd8819..e63e9703 100644 --- a/src/ui/video/d3d.cpp +++ b/src/ui/video/d3d.cpp @@ -168,14 +168,15 @@ D3DLOCKED_RECT d3dlr; } } -uint16 *VideoD3D::lock(uint &pitch) { +bool VideoD3D::lock(uint16 *&data, uint &pitch) { if(caps.stretchrect == false) { texture->GetLevelDesc(0, &d3dsd); texture->GetSurfaceLevel(0, &surface); } surface->LockRect(&d3dlr, 0, flags.lock); pitch = d3dlr.Pitch; - return (uint16*)d3dlr.pBits; + data = (uint16*)d3dlr.pBits; + return data; } void VideoD3D::unlock() { @@ -291,7 +292,7 @@ void VideoD3D::redraw() { if(!device)return; device->BeginScene(); - snes->get_video_info(&vi); + snes.get_video_info(&vi); if(caps.stretchrect == true) { RECT rs, rd; @@ -343,7 +344,7 @@ char fn[4096]; int i; for(i = 0; i <= 999; i++) { //should probably check the length of config::misc.image_format here... - sprintf(fn, "image%0.3d.%s", i, config::misc.image_format.sget()); + sprintf(fn, "image%0.3d.%s", i, config::misc.image_format.strget()); fp = fopen(fn, "rb"); if(!fp)break; fclose(fp); @@ -352,9 +353,9 @@ int i; if(i >= 1000)return false; uint32 format; - if(strmatch(config::misc.image_format.sget(), "bmp")) { + if(!strcmp(config::misc.image_format.strget(), "bmp")) { format = D3DXIFF_BMP; - } else if(strmatch(config::misc.image_format.sget(), "jpg")) { + } else if(!strcmp(config::misc.image_format.strget(), "jpg")) { format = D3DXIFF_JPG; } else { format = D3DXIFF_PNG; diff --git a/src/ui/video/d3d.h b/src/ui/video/d3d.h index b353ac7a..aa20c00d 100644 --- a/src/ui/video/d3d.h +++ b/src/ui/video/d3d.h @@ -37,30 +37,30 @@ struct { bool stretchrect; //device supports StretchRect } caps; - void set_vertex(uint32 px, uint32 py, uint32 pw, uint32 ph, - uint32 tw, uint32 th, uint32 x, uint32 y, uint32 w, uint32 h); + void set_vertex(uint32 px, uint32 py, uint32 pw, uint32 ph, + uint32 tw, uint32 th, uint32 x, uint32 y, uint32 w, uint32 h); - uint16 *lock(uint &pitch); - void unlock(); + bool lock(uint16 *&data, uint &pitch); + void unlock(); - uint screen_width() { return GetScreenWidth(); } - uint screen_height() { return GetScreenHeight(); } + uint screen_width() { return GetScreenWidth(); } + uint screen_height() { return GetScreenHeight(); } - void pause_enable(); - void pause_disable(); + void pause_enable(); + void pause_disable(); - bool update_video_profile(); - void update_hardware_filter(); - void update_scanlines(); + bool update_video_profile(); + void update_hardware_filter(); + void update_scanlines(); - bool capture_screenshot(); + bool capture_screenshot(); - void init(); - void term(); + void init(); + void term(); - void clear_video(); - void redraw(); - void update(); + void clear_video(); + void redraw(); + void update(); VideoD3D(HWND handle = 0); ~VideoD3D(); diff --git a/src/ui/video/ddraw.cpp b/src/ui/video/ddraw.cpp index f06e7b0d..a1fae3a8 100644 --- a/src/ui/video/ddraw.cpp +++ b/src/ui/video/ddraw.cpp @@ -83,10 +83,11 @@ DDBLTFX fx; surface->Blt(0, 0, 0, DDBLT_WAIT | DDBLT_COLORFILL, &fx); } -uint16 *VideoDD::lock(uint &pitch) { +bool VideoDD::lock(uint16 *&data, uint &pitch) { if(surface->Lock(0, &ddsd, DDLOCK_WAIT, 0) != DD_OK)return 0; pitch = ddsd.lPitch; - return (uint16*)ddsd.lpSurface; + data = (uint16*)ddsd.lpSurface; + return data; } void VideoDD::unlock() { @@ -146,7 +147,7 @@ void VideoDD::create_presentation() { void VideoDD::redraw() { HRESULT hr; RECT rd, rs; - snes->get_video_info(&vi); + snes.get_video_info(&vi); SetRect(&rs, 0, 0, vi.width, vi.height); if(settings.fullscreen == true) { diff --git a/src/ui/video/ddraw.h b/src/ui/video/ddraw.h index 7b95154c..9935f53e 100644 --- a/src/ui/video/ddraw.h +++ b/src/ui/video/ddraw.h @@ -12,23 +12,22 @@ DDSURFACEDESC2 ddsd; DDSCAPS2 ddscaps; public: - uint16 *lock(uint &pitch); - void unlock(); + bool lock(uint16 *&data, uint &pitch); + void unlock(); - uint screen_width() { return GetScreenWidth(); } - uint screen_height() { return GetScreenHeight(); } + uint screen_width() { return GetScreenWidth(); } + uint screen_height() { return GetScreenHeight(); } - bool update_video_profile(); - void init(); - void term(); + bool update_video_profile(); + void init(); + void term(); - void create_render_target(); - void clear_video(); + void create_render_target(); + void clear_video(); -//ddraw_present.cpp - void create_presentation(); - void redraw(); - void update(); + void create_presentation(); + void redraw(); + void update(); VideoDD(HWND handle); }; diff --git a/src/ui/video/video.cpp b/src/ui/video/video.cpp index 2b967bf4..8105f390 100644 --- a/src/ui/video/video.cpp +++ b/src/ui/video/video.cpp @@ -3,8 +3,8 @@ stringarray line, part; if(profile >= VIDEO_PROFILE_COUNT)profile = 0; switch(profile) { - case 0: strcpy(line, config::video.profile_win.sget()); break; - case 1: strcpy(line, config::video.profile_full.sget()); break; + case 0: strcpy(line, config::video.profile_win.strget()); break; + case 1: strcpy(line, config::video.profile_full.strget()); break; } split(part, ";", line); @@ -14,13 +14,13 @@ int i = 0; v->hardware_filter = strdec(part[i++]); v->video_standard = strdec(part[i++]); v->multiplier = strdec(part[i++]); - v->correct_aspect_ratio = strmatch(part[i++], "true"); - v->enable_scanlines = strmatch(part[i++], "true"); - v->manual_render_size = strmatch(part[i++], "true"); + v->correct_aspect_ratio = !strcmp(part[i++], "true"); + v->enable_scanlines = !strcmp(part[i++], "true"); + v->manual_render_size = !strcmp(part[i++], "true"); v->render_width = strdec(part[i++]); v->render_height = strdec(part[i++]); v->fullscreen = (profile == 1); - v->triple_buffering = strmatch(part[i++], "true"); + v->triple_buffering = !strcmp(part[i++], "true"); v->resolution_width = strdec(part[i++]); v->resolution_height = strdec(part[i++]); v->refresh_rate = strdec(part[i++]); @@ -53,8 +53,8 @@ VideoSettings *v = &video_settings[profile]; sprintf(part, "%d", v->refresh_rate); strcat(line, part); switch(profile) { - case 0: config::video.profile_win.sset(strptr(line)); break; - case 1: config::video.profile_full.sset(strptr(line)); break; + case 0: config::video.profile_win.strset(strptr(line)); break; + case 1: config::video.profile_full.strset(strptr(line)); break; } } @@ -64,7 +64,7 @@ uint profile = uint(config::video.profile); load_video_settings(profile); VideoSettings *v = &video_settings[profile]; - snes->set_video_format(v->software_filter, v->video_standard, SNES::PIXELFORMAT_RGB565); + snes.set_video_format(v->software_filter, v->video_standard, SNES::PIXELFORMAT_RGB565); if(v->manual_render_size == true) { settings.render_width = v->render_width; diff --git a/src/ui/video/video.h b/src/ui/video/video.h index ed1a8a8b..e93b5f4a 100644 --- a/src/ui/video/video.h +++ b/src/ui/video/video.h @@ -47,26 +47,26 @@ struct { } settings; void update_video_settings(); - virtual uint16 *lock(uint &pitch) = 0; - virtual void unlock() = 0; + virtual bool lock(uint16 *&data, uint &pitch) = 0; + virtual void unlock() = 0; - virtual uint screen_width() = 0; - virtual uint screen_height() = 0; + virtual uint screen_width() = 0; + virtual uint screen_height() = 0; - virtual bool update_video_profile() { return true; } - virtual void clear_video() {} + virtual bool update_video_profile() { return true; } + virtual void clear_video() {} - virtual void pause_enable() {} - virtual void pause_disable() {} - virtual void update_hardware_filter() {} - virtual void update_scanlines() {} + virtual void pause_enable() {} + virtual void pause_disable() {} + virtual void update_hardware_filter() {} + virtual void update_scanlines() {} - virtual bool capture_screenshot() { return false; } + virtual bool capture_screenshot() { return false; } - virtual void redraw() = 0; - virtual void update() = 0; - virtual void init() = 0; - virtual void term() = 0; + virtual void redraw() = 0; + virtual void update() = 0; + virtual void init() = 0; + virtual void term() = 0; Video(); virtual ~Video(); diff --git a/src/ui/win/bsnes.cpp b/src/ui/win/bsnes.cpp index 3e91663d..bfb1ae12 100644 --- a/src/ui/win/bsnes.cpp +++ b/src/ui/win/bsnes.cpp @@ -1,8 +1,8 @@ -uint32 bSNES::get_state() { +uint bSNES::get_state() { return state; } -void bSNES::set_state(uint32 new_state) { +void bSNES::set_state(uint new_state) { state = new_state; switch(state) { @@ -20,18 +20,6 @@ void bSNES::set_state(uint32 new_state) { wDebug.SetState(state); } -void bSNES::power() { - SNES::power(); -} - -void bSNES::reset() { - SNES::reset(); -} - -void bSNES::scanline() { - SNES::scanline(); -} - void bSNES::run() { if(!r_mem->cart_loaded()) { Sleep(1); @@ -40,7 +28,8 @@ void bSNES::run() { switch(state) { case RUN: - SNES::runtoframe(); + snes.runtoframe(); + video_run(); break; case STOP: Sleep(1); @@ -49,14 +38,6 @@ void bSNES::run() { } void bSNES::video_run() { -//temporary code to try and fix input buffer stalls -static int sync_counter = 0; - if(++sync_counter >= 30) { - Sleep(1); - sync_counter = 0; - } -//remove above code after testing - if(r_ppu->status.frames_updated) { char s[512], t[512]; r_ppu->status.frames_updated = false; @@ -72,35 +53,5 @@ static int sync_counter = 0; wMain.frameskip_pos++; wMain.frameskip_pos %= (wMain.frameskip + 1); - if(r_ppu->renderer_enabled())uiVideo->update(); r_ppu->enable_renderer(wMain.frameskip_pos == 0); } - -void bSNES::sound_run(uint32 data) { - uiAudio->run(data); -} - -/*********************** - *** video functions *** - ***********************/ - -uint16 *bSNES::video_lock(uint &pitch) { - return uiVideo->lock(pitch); -} - -void bSNES::video_unlock() { - uiVideo->unlock(); -} - -/*********************** - *** input functions *** - ***********************/ - -void bSNES::poll_input() { - uiInput->poll(); - SNES::poll_input(); -} - -bool bSNES::get_input_status(uint8 deviceid, uint8 button) { - return uiInput->get_status(deviceid, button); -} diff --git a/src/ui/win/bsnes.h b/src/ui/win/bsnes.h index c30a2594..e816420c 100644 --- a/src/ui/win/bsnes.h +++ b/src/ui/win/bsnes.h @@ -1,26 +1,11 @@ -class bSNES : public SNES { +class bSNES { public: enum { RUN, STOP }; -uint32 state; - uint32 get_state(); - void set_state(uint32 new_state); - - void power(); - void reset(); - - void scanline(); - - void run(); - void video_run(); - void sound_run(uint32 data); - -//video functions - uint16 *video_lock(uint &pitch); - void video_unlock(); - -//input functions - void poll_input(); - bool get_input_status(uint8 deviceid, uint8 button); +uint state; + uint get_state(); + void set_state(uint new_state); + void run(); + void video_run(); bSNES() { state = RUN; } -} *bsnes; +} bsnes; diff --git a/src/ui/win/debugger/debugger.cpp b/src/ui/win/debugger/debugger.cpp index 90949bde..4f03f610 100644 --- a/src/ui/win/debugger/debugger.cpp +++ b/src/ui/win/debugger/debugger.cpp @@ -29,7 +29,7 @@ void Debugger::activate() { if(status.active == true)return; status.active = true; - bsnes->set_state(bSNES::STOP); + bsnes.set_state(bSNES::STOP); wDebug.Show(); wMain.CheckMenuItem(MENU_SETTINGS_DEBUGGER, true); } @@ -42,7 +42,7 @@ void Debugger::deactivate() { wTracer.Hide(); wMemory.Hide(); wMain.CheckMenuItem(MENU_SETTINGS_DEBUGGER, false); - bsnes->set_state(bSNES::RUN); + bsnes.set_state(bSNES::RUN); } void Debugger::refresh() { diff --git a/src/ui/win/debugger/ui_debugger.cpp b/src/ui/win/debugger/ui_debugger.cpp index ca9a8765..d7aef3c2 100644 --- a/src/ui/win/debugger/ui_debugger.cpp +++ b/src/ui/win/debugger/ui_debugger.cpp @@ -8,10 +8,10 @@ bool DebugWindow::Event(EventInfo &info) { case EVENT_CLICKED: { if(info.control == &Run) { - if(bsnes->get_state() == bSNES::RUN) { - bsnes->set_state(bSNES::STOP); - } else if(bsnes->get_state() == bSNES::STOP) { - bsnes->set_state(bSNES::RUN); + if(bsnes.get_state() == bSNES::RUN) { + bsnes.set_state(bSNES::STOP); + } else if(bsnes.get_state() == bSNES::STOP) { + bsnes.set_state(bSNES::RUN); } } else if(info.control == &Tracer) { wTracer.Show(); @@ -88,7 +88,7 @@ void DebugWindow::SetState(uint state) { } void DebugWindow::Show() { - Run.SetText((bsnes->get_state() == bSNES::RUN) ? " Stop" : " Run"); + Run.SetText((bsnes.get_state() == bSNES::RUN) ? " Stop" : " Run"); Window::Show(); Update(); } diff --git a/src/ui/win/event.cpp b/src/ui/win/event.cpp index 1d5e4eb7..539a4258 100644 --- a/src/ui/win/event.cpp +++ b/src/ui/win/event.cpp @@ -36,7 +36,7 @@ string t; wMain.HideMenu(); HideCursor(); } else { - strcpy(t, config::misc.window_style.sget()); + strcpy(t, config::misc.window_style); if(wMain.Visible())strcat(t, "|visible"); wMain.ShowMenu(); ShowCursor(); @@ -57,12 +57,11 @@ void toggle_fullscreen() { event::set_video_profile(config::video.profile); } -void load_rom() { +bool load_rom(char *fn) { OPENFILENAME ofn; -char t[MAX_PATH]; stringarray dir; - strcpy(t, ""); - strcpy(dir, config::fs.rom_path.sget()); + strcpy(fn, ""); + strcpy(dir, config::path.rom); replace(dir, "\\", "/"); if(strlen(dir) && !strend(dir, "/")) { strcat(dir, "/"); } @@ -70,7 +69,7 @@ stringarray dir; if(strbegin(dir, "./")) { strltrim(dir, "./"); strcpy(dir[1], dir[0]); - strcpy(dir[0], config::fs.base_path.sget()); + strcpy(dir[0], config::path.base); strcat(dir[0], dir[1]); } @@ -81,7 +80,7 @@ stringarray dir; ofn.lStructSize = sizeof(ofn); ofn.hwndOwner = wMain.hwnd; - ofn.lpstrFilter = "SNES ROM Images (*.smc;*.sfc;*.swc;*.fig;*.ufo;*.gd3;*.078" + ofn.lpstrFilter = "SNES ROM Images (*.smc;*.sfc;*.swc;*.fig;*.ufo;*.gd3;*.078;*.st" #ifdef GZIP_SUPPORT ";.gz;.z;.zip" #endif @@ -89,7 +88,7 @@ stringarray dir; ";.jma" #endif ")\0" - "*.smc;*.sfc;*.swc;*.fig;*.ufo;*.gd3;*.078" + "*.smc;*.sfc;*.swc;*.fig;*.ufo;*.gd3;*.078;*.st" #ifdef GZIP_SUPPORT ";*.gz;*.z;*.zip" #endif @@ -99,21 +98,61 @@ stringarray dir; "\0" "All Files (*.*)\0" "*.*\0"; - ofn.lpstrFile = t; + ofn.lpstrFile = fn; ofn.lpstrInitialDir = strptr(dir); ofn.nMaxFile = MAX_PATH; ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST; ofn.lpstrDefExt = "smc"; - if(!GetOpenFileName(&ofn))return; + if(!GetOpenFileName(&ofn))return false; + return true; +} + +void load_rom_normal() { +char fn[MAX_PATH]; + if(load_rom(fn) == false)return; if(cartridge.loaded() == true)cartridge.unload(); wDebug.Clear(); - if(cartridge.load(t) == false)return; - wCheatEditor.Refresh(); + cartridge.load_begin(Cartridge::CART_NORMAL); + cartridge.load(fn); + cartridge.load_end(); + snes.power(); - bsnes->power(); + wCheatEditor.Refresh(); +} + +void load_rom_st() { +char fn[MAX_PATH]; + if(load_rom(fn) == false)return; + + if(cartridge.loaded() == true)cartridge.unload(); + wDebug.Clear(); + + cartridge.load_begin(Cartridge::CART_ST); + cartridge.load(fn); + cartridge.load_end(); + snes.power(); + + wCheatEditor.Refresh(); +} + +void load_rom_stdual() { +char fn_a[MAX_PATH], fn_b[MAX_PATH]; + if(load_rom(fn_a) == false)return; + if(load_rom(fn_b) == false)return; + + if(cartridge.loaded() == true)cartridge.unload(); + wDebug.Clear(); + + cartridge.load_begin(Cartridge::CART_STDUAL); + cartridge.load(fn_a); + cartridge.load(fn_b); + cartridge.load_end(); + snes.power(); + + wCheatEditor.Refresh(); } void unload_rom() { diff --git a/src/ui/win/event.h b/src/ui/win/event.h index 7cfcc506..12163846 100644 --- a/src/ui/win/event.h +++ b/src/ui/win/event.h @@ -5,7 +5,10 @@ void capture_screenshot(); void set_video_profile(uint profile); void toggle_fullscreen(); -void load_rom(); +void load_rom(const char *fn); +void load_rom_normal(); +void load_rom_st(); +void load_rom_stdual(); void unload_rom(); }; diff --git a/src/ui/win/main.cpp b/src/ui/win/main.cpp index cb18ce76..3c299c56 100644 --- a/src/ui/win/main.cpp +++ b/src/ui/win/main.cpp @@ -64,7 +64,7 @@ string t; } if(strend(t, "/") == false) { strcat(t, "/"); } - config::fs.base_path.sset(strptr(t)); + config::path.base = strptr(t); } int __stdcall WinMain(HINSTANCE hinstance, HINSTANCE hprevinstance, LPSTR lpcmdline, int ncmdshow) { @@ -73,7 +73,7 @@ int __stdcall WinMain(HINSTANCE hinstance, HINSTANCE hprevinstance, LPSTR lpcmdl get_base_path(); string cfg_fn; - strcpy(cfg_fn, config::fs.base_path.sget()); + strcpy(cfg_fn, config::path.base); strcat(cfg_fn, "bsnes.cfg"); config_file.load(cfg_fn); @@ -81,9 +81,10 @@ string cfg_fn; init_ui(); if(__argc >= 2) { - if(cartridge.load(__argv[1]) == true) { - snes->power(); - } + cartridge.load_begin(Cartridge::CART_NORMAL); + cartridge.load(__argv[1]); + cartridge.load_end(); + snes.power(); } MSG msg; @@ -93,7 +94,7 @@ MSG msg; TranslateMessage(&msg); DispatchMessage(&msg); } - bsnes->run(); + bsnes.run(); } end: diff --git a/src/ui/win/settings/ui_cheateditor.cpp b/src/ui/win/settings/ui_cheateditor.cpp index abcc48a2..2d155858 100644 --- a/src/ui/win/settings/ui_cheateditor.cpp +++ b/src/ui/win/settings/ui_cheateditor.cpp @@ -35,7 +35,7 @@ void CheatEditorWindow::CheatAdd() { char code[16 + 1], desc[128 + 1]; Code.GetText(code, 16); Desc.GetText(desc, 128); - if(strmatch(code, "") == true)return; + if(!strcmp(code, ""))return; cheat.add(Enabled.Checked(), code, desc); Refresh(); diff --git a/src/ui/win/settings/ui_coloradjust.cpp b/src/ui/win/settings/ui_coloradjust.cpp index d8f779d4..9bfaf2fe 100644 --- a/src/ui/win/settings/ui_coloradjust.cpp +++ b/src/ui/win/settings/ui_coloradjust.cpp @@ -5,15 +5,15 @@ bool ColorAdjustWindow::Event(EventInfo &info) { if(info.control == &ContrastSlider) { config::snes.contrast = ContrastSlider.GetPos(); ContrastLabel.SetText("Contrast: %d", int32(config::snes.contrast)); - snes->update_color_lookup_table(); + snes.update_color_lookup_table(); } else if(info.control == &BrightnessSlider) { config::snes.brightness = BrightnessSlider.GetPos(); BrightnessLabel.SetText("Brightness: %d", int32(config::snes.brightness)); - snes->update_color_lookup_table(); + snes.update_color_lookup_table(); } else if(info.control == &GammaSlider) { config::snes.gamma = GammaSlider.GetPos(); GammaLabel.SetText("Gamma: %0.2f", double(config::snes.gamma) / 100.0); - snes->update_color_lookup_table(); + snes.update_color_lookup_table(); } } break; @@ -21,19 +21,19 @@ bool ColorAdjustWindow::Event(EventInfo &info) { if(info.control == &GammaRamp) { config::snes.gamma_ramp.toggle(); GammaRamp.Check(config::snes.gamma_ramp); - snes->update_color_lookup_table(); + snes.update_color_lookup_table(); } else if(info.control == &Sepia) { config::snes.sepia.toggle(); Sepia.Check(config::snes.sepia); - snes->update_color_lookup_table(); + snes.update_color_lookup_table(); } else if(info.control == &Grayscale) { config::snes.grayscale.toggle(); Grayscale.Check(config::snes.grayscale); - snes->update_color_lookup_table(); + snes.update_color_lookup_table(); } else if(info.control == &Invert) { config::snes.invert.toggle(); Invert.Check(config::snes.invert); - snes->update_color_lookup_table(); + snes.update_color_lookup_table(); } else if(info.control == &Restore) { config::snes.contrast = 0; config::snes.brightness = 0; @@ -52,7 +52,7 @@ bool ColorAdjustWindow::Event(EventInfo &info) { Sepia.Check(config::snes.sepia); Grayscale.Check(config::snes.grayscale); Invert.Check(config::snes.invert); - snes->update_color_lookup_table(); + snes.update_color_lookup_table(); } } break; diff --git a/src/ui/win/settings/ui_emusettings.cpp b/src/ui/win/settings/ui_emusettings.cpp index 98fdfedc..1a237043 100644 --- a/src/ui/win/settings/ui_emusettings.cpp +++ b/src/ui/win/settings/ui_emusettings.cpp @@ -4,10 +4,10 @@ bool EmuSettingsWindow::Event(EventInfo &info) { case EVENT_CHANGED: { if(info.control == &Port1) { config::snes.controller_port0 = Port1.GetSelection(); - snes->port_set_deviceid(0, config::snes.controller_port0); + snes.port_set_deviceid(0, config::snes.controller_port0); } else if(info.control == &Port2) { config::snes.controller_port1 = Port2.GetSelection(); - snes->port_set_deviceid(1, config::snes.controller_port1); + snes.port_set_deviceid(1, config::snes.controller_port1); } } break; diff --git a/src/ui/win/ui.cpp b/src/ui/win/ui.cpp index 1e287ddb..d813c47c 100644 --- a/src/ui/win/ui.cpp +++ b/src/ui/win/ui.cpp @@ -21,7 +21,7 @@ long height; wMain.SetBackgroundColor(0, 0, 0); wMain.SetIcon(100); - wMain.Create(0, "bsnes", config::misc.window_style.sget(), 0, 0, 256, 224, BSNES_TITLE); + wMain.Create(0, "bsnes", config::misc.window_style, 0, 0, 256, 224, BSNES_TITLE); wMain.Center(); wAbout.SetIcon(100); @@ -31,23 +31,23 @@ long height; init_settings(); init_debugger(); - if(!stricmp(config::system.video.sget(), "dd")) { + if(!stricmp(config::system.video, "dd")) { uiVideo = new VideoDD(wMain.hwnd); -//} else if(!stricmp(config::system.video.sget(), "sdl")) { +//} else if(!stricmp(config::system.video, "sdl")) { // uiVideo = new VideoSDL((void*)wMain.hwnd); } else { uiVideo = new VideoD3D(wMain.hwnd); } - if(!stricmp(config::system.audio.sget(), "none")) { + if(!stricmp(config::system.audio, "none")) { uiAudio = new Audio(); } else { uiAudio = new AudioDS(wMain.hwnd); } - if(!stricmp(config::system.input.sget(), "none")) { + if(!stricmp(config::system.input, "none")) { uiInput = new Input(); -//} else if(!stricmp(config::system.input.sget(), "sdl")) { +//} else if(!stricmp(config::system.input, "sdl")) { // uiInput = new InputSDL((void*)wMain.hwnd); } else { uiInput = new InputDI(); diff --git a/src/ui/win/ui.h b/src/ui/win/ui.h index e8adb8b0..99a035dc 100644 --- a/src/ui/win/ui.h +++ b/src/ui/win/ui.h @@ -12,6 +12,10 @@ Font vwf, fwf, font_about, font_header, font_list; enum { MENU_FILE = 100, MENU_FILE_LOAD, + MENU_FILE_LOAD_SPECIAL, + //--- + MENU_FILE_LOAD_ST, + MENU_FILE_LOAD_STDUAL, MENU_FILE_UNLOAD, MENU_FILE_RESET, MENU_FILE_POWER, diff --git a/src/ui/win/ui_main.cpp b/src/ui/win/ui_main.cpp index e2358d70..7beee903 100644 --- a/src/ui/win/ui_main.cpp +++ b/src/ui/win/ui_main.cpp @@ -54,10 +54,10 @@ bool MainWindow::Event(EventInfo &info) { } else if(id == key->f11) { event::toggle_fullscreen(); } else if(id == key->f12) { - if(bsnes->get_state() == bSNES::RUN) { - bsnes->set_state(bSNES::STOP); - } else if(bsnes->get_state() == bSNES::STOP) { - bsnes->set_state(bSNES::RUN); + if(bsnes.get_state() == bSNES::RUN) { + bsnes.set_state(bSNES::STOP); + } else if(bsnes.get_state() == bSNES::STOP) { + bsnes.set_state(bSNES::RUN); } //no idea why this is needed, keydown event should only occur once; //however it is being called repeatedly when F11 is held down ... @@ -101,7 +101,15 @@ bool MainWindow::Event(EventInfo &info) { switch(info.control_id) { case MENU_FILE_LOAD: { - event::load_rom(); + event::load_rom_normal(); + } break; + + case MENU_FILE_LOAD_ST: { + event::load_rom_st(); + } break; + + case MENU_FILE_LOAD_STDUAL: { + event::load_rom_stdual(); } break; case MENU_FILE_UNLOAD: { @@ -110,14 +118,14 @@ bool MainWindow::Event(EventInfo &info) { case MENU_FILE_RESET: { if(cartridge.loaded() == true) { - bsnes->reset(); + snes.reset(); dprintf("* Reset"); } } break; case MENU_FILE_POWER: { if(cartridge.loaded() == true) { - bsnes->power(); + snes.power(); dprintf("* Power"); } } break; @@ -178,10 +186,10 @@ bool MainWindow::Event(EventInfo &info) { case MENU_MISC_LOGAUDIO: { if(MenuItemChecked(MENU_MISC_LOGAUDIO) == false) { CheckMenuItem(MENU_MISC_LOGAUDIO); - snes->log_audio_enable(); + snes.log_audio_enable(); } else { UncheckMenuItem(MENU_MISC_LOGAUDIO); - snes->log_audio_disable(); + snes.log_audio_disable(); } } break; @@ -213,10 +221,14 @@ char t[128]; AddMenuGroup("&File"); AddMenuItem(MENU_FILE_LOAD, "&Load Cartridge"); + AddMenuGroup("&Load Special"); + AddMenuItem(MENU_FILE_LOAD_ST, "&Load ST Cartridge"); + AddMenuItem(MENU_FILE_LOAD_STDUAL, "&Load ST Dual Cartridges"); + EndMenuGroup(); AddMenuItem(MENU_FILE_UNLOAD, "&Unload Cartridge"); AddMenuSeparator(); - AddMenuItem(MENU_FILE_RESET, "&Reset"); - AddMenuItem(MENU_FILE_POWER, "&Power (Hard Reset)"); + AddMenuItem(MENU_FILE_RESET, "&Reset System"); + AddMenuItem(MENU_FILE_POWER, "&Power Cycle System"); AddMenuSeparator(); AddMenuItem(MENU_FILE_EXIT, "E&xit"); EndMenuGroup();