mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-09-19 05:21:30 +02:00
Compare commits
8 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
ba081d309e | ||
|
1bf9265b7c | ||
|
f947d84309 | ||
|
0bd21185b8 | ||
|
6227974bf6 | ||
|
ea95eaca3c | ||
|
ad0805b168 | ||
|
2cc077e12b |
@@ -12,7 +12,7 @@ ui := ui
|
||||
# compiler
|
||||
c := $(compiler) -std=gnu99
|
||||
cpp := $(subst cc,++,$(compiler)) -std=gnu++0x
|
||||
flags := -O3 -fomit-frame-pointer -I.
|
||||
flags := -I. -O3 -fomit-frame-pointer
|
||||
link :=
|
||||
objects := libco
|
||||
|
||||
@@ -29,8 +29,6 @@ endif
|
||||
|
||||
# platform
|
||||
ifeq ($(platform),x)
|
||||
# tree vectorization causes code generation errors with Linux/GCC 4.6.1
|
||||
flags += -fno-tree-vectorize
|
||||
link += -s -ldl -lX11 -lXext
|
||||
else ifeq ($(platform),osx)
|
||||
else ifeq ($(platform),win)
|
||||
@@ -76,7 +74,23 @@ clean:
|
||||
-@$(call delete,*.pdb)
|
||||
-@$(call delete,*.manifest)
|
||||
|
||||
sync:
|
||||
if [ -d ./libco ]; then rm -r ./libco; fi
|
||||
if [ -d ./nall ]; then rm -r ./nall; fi
|
||||
if [ -d ./ruby ]; then rm -r ./ruby; fi
|
||||
if [ -d ./phoenix ]; then rm -r ./phoenix; fi
|
||||
cp -r ../libco ./libco
|
||||
cp -r ../nall ./nall
|
||||
cp -r ../ruby ./ruby
|
||||
cp -r ../phoenix ./phoenix
|
||||
rm -r libco/doc
|
||||
rm -r libco/test
|
||||
rm -r nall/test
|
||||
rm -r ruby/_test
|
||||
rm -r phoenix/nall
|
||||
rm -r phoenix/test
|
||||
|
||||
archive-all:
|
||||
tar -cjf bsnes.tar.bz2 data gameboy libco nall nes obj out phoenix ruby snes ui ui-libsnes Makefile cc.bat clean.bat sync.sh
|
||||
tar -cjf bsnes.tar.bz2 data gameboy libco nall nes obj out phoenix ruby snes ui ui-libsnes Makefile cc.bat clean.bat
|
||||
|
||||
help:;
|
||||
|
79635
bsnes/data/cheats.bml
79635
bsnes/data/cheats.bml
File diff suppressed because it is too large
Load Diff
112549
bsnes/data/cheats.xml
Executable file
112549
bsnes/data/cheats.xml
Executable file
File diff suppressed because it is too large
Load Diff
@@ -30,9 +30,9 @@ void Cartridge::load(System::Revision revision, const string &markup, const uint
|
||||
info.romsize = 0;
|
||||
info.ramsize = 0;
|
||||
|
||||
BML::Document document(markup);
|
||||
XML::Document document(markup);
|
||||
|
||||
auto &mapperid = document["cartridge"]["mapper"].value;
|
||||
auto &mapperid = document["cartridge"]["mapper"].data;
|
||||
if(mapperid == "none" ) info.mapper = Mapper::MBC0;
|
||||
if(mapperid == "MBC1" ) info.mapper = Mapper::MBC1;
|
||||
if(mapperid == "MBC2" ) info.mapper = Mapper::MBC2;
|
||||
@@ -42,12 +42,12 @@ void Cartridge::load(System::Revision revision, const string &markup, const uint
|
||||
if(mapperid == "HuC1" ) info.mapper = Mapper::HuC1;
|
||||
if(mapperid == "HuC3" ) info.mapper = Mapper::HuC3;
|
||||
|
||||
info.rtc = document["cartridge"]["rtc"].exists();
|
||||
info.rumble = document["cartridge"]["rumble"].exists();
|
||||
info.rtc = document["cartridge"]["rtc"].data == "true";
|
||||
info.rumble = document["cartridge"]["rumble"].data == "true";
|
||||
|
||||
info.romsize = hex(document["cartridge"]["rom"]["size"].value);
|
||||
info.ramsize = hex(document["cartridge"]["ram"]["size"].value);
|
||||
info.battery = document["cartridge"]["ram"]["non-volatile"].exists();
|
||||
info.romsize = hex(document["cartridge"]["rom"]["size"].data);
|
||||
info.ramsize = hex(document["cartridge"]["ram"]["size"].data);
|
||||
info.battery = document["cartridge"]["ram"]["battery"].data == "true";
|
||||
|
||||
switch(info.mapper) { default:
|
||||
case Mapper::MBC0: mapper = &mbc0; break;
|
||||
|
@@ -1,53 +1,54 @@
|
||||
#ifdef CARTRIDGE_CPP
|
||||
|
||||
uint8 Cartridge::HuC1::mmio_read(uint16 addr) {
|
||||
if(within<0x0000, 0x3fff>(addr)) {
|
||||
if((addr & 0xc000) == 0x0000) { //$0000-3fff
|
||||
return cartridge.rom_read(addr);
|
||||
}
|
||||
|
||||
if(within<0x4000, 0x7fff>(addr)) {
|
||||
if((addr & 0xc000) == 0x4000) { //$4000-7fff
|
||||
return cartridge.rom_read((rom_select << 14) | (addr & 0x3fff));
|
||||
}
|
||||
|
||||
if(within<0xa000, 0xbfff>(addr)) {
|
||||
if(ram_enable) return cartridge.ram_read((ram_select << 13) | (addr & 0x1fff));
|
||||
return 0x00;
|
||||
if((addr & 0xe000) == 0xa000) { //$a000-bfff
|
||||
return cartridge.ram_read((ram_select << 13) | (addr & 0x1fff));
|
||||
}
|
||||
|
||||
return 0x00;
|
||||
}
|
||||
|
||||
void Cartridge::HuC1::mmio_write(uint16 addr, uint8 data) {
|
||||
if(within<0x0000, 0x1fff>(addr)) {
|
||||
ram_enable = (data & 0x0f) == 0x0a;
|
||||
if((addr & 0xe000) == 0x0000) { //$0000-1fff
|
||||
ram_writable = (data & 0x0f) == 0x0a;
|
||||
return;
|
||||
}
|
||||
|
||||
if(within<0x2000, 0x3fff>(addr)) {
|
||||
if((addr & 0xe000) == 0x2000) { //$2000-3fff
|
||||
rom_select = data;
|
||||
if(rom_select == 0) rom_select = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if(within<0x4000, 0x5fff>(addr)) {
|
||||
if((addr & 0xe000) == 0x4000) { //$4000-5fff
|
||||
ram_select = data;
|
||||
return;
|
||||
}
|
||||
|
||||
if(within<0x6000, 0x7fff>(addr)) {
|
||||
//unknown purpose
|
||||
if((addr & 0xe000) == 0x6000) { //$6000-7fff
|
||||
model = data & 0x01;
|
||||
return;
|
||||
}
|
||||
|
||||
if(within<0xa000, 0xbfff>(addr)) {
|
||||
if(ram_enable) cartridge.ram_write((ram_select << 13) | (addr & 0x1fff), data);
|
||||
return;
|
||||
if((addr & 0xe000) == 0xa000) { //$a000-bfff
|
||||
if(ram_writable == false) return;
|
||||
return cartridge.ram_write((ram_select << 13) | (addr & 0x1fff), data);
|
||||
}
|
||||
}
|
||||
|
||||
void Cartridge::HuC1::power() {
|
||||
ram_enable = false;
|
||||
ram_writable = false;
|
||||
rom_select = 0x01;
|
||||
ram_select = 0x00;
|
||||
model = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -1,7 +1,8 @@
|
||||
struct HuC1 : MMIO {
|
||||
bool ram_enable; //0000-1fff
|
||||
uint8 rom_select; //2000-3fff
|
||||
uint8 ram_select; //4000-5fff
|
||||
bool ram_writable; //$0000-1fff
|
||||
uint8 rom_select; //$2000-3fff
|
||||
uint8 ram_select; //$4000-5fff
|
||||
bool model; //$6000-7fff
|
||||
|
||||
uint8 mmio_read(uint16 addr);
|
||||
void mmio_write(uint16 addr, uint8 data);
|
||||
|
@@ -1,15 +1,15 @@
|
||||
#ifdef CARTRIDGE_CPP
|
||||
|
||||
uint8 Cartridge::HuC3::mmio_read(uint16 addr) {
|
||||
if(within<0x0000, 0x3fff>(addr)) {
|
||||
if((addr & 0xc000) == 0x0000) { //$0000-3fff
|
||||
return cartridge.rom_read(addr);
|
||||
}
|
||||
|
||||
if(within<0x4000, 0x7fff>(addr)) {
|
||||
if((addr & 0xc000) == 0x4000) { //$4000-7fff
|
||||
return cartridge.rom_read((rom_select << 14) | (addr & 0x3fff));
|
||||
}
|
||||
|
||||
if(within<0xa000, 0xbfff>(addr)) {
|
||||
if((addr & 0xe000) == 0xa000) { //$a000-bfff
|
||||
if(ram_enable) return cartridge.ram_read((ram_select << 13) | (addr & 0x1fff));
|
||||
return 0x00;
|
||||
}
|
||||
@@ -18,27 +18,27 @@ uint8 Cartridge::HuC3::mmio_read(uint16 addr) {
|
||||
}
|
||||
|
||||
void Cartridge::HuC3::mmio_write(uint16 addr, uint8 data) {
|
||||
if(within<0x0000, 0x1fff>(addr)) {
|
||||
if((addr & 0xe000) == 0x0000) { //$0000-1fff
|
||||
ram_enable = (data & 0x0f) == 0x0a;
|
||||
return;
|
||||
}
|
||||
|
||||
if(within<0x2000, 0x3fff>(addr)) {
|
||||
if((addr & 0xe000) == 0x2000) { //$2000-3fff
|
||||
rom_select = data;
|
||||
return;
|
||||
}
|
||||
|
||||
if(within<0x4000, 0x5fff>(addr)) {
|
||||
if((addr & 0xe000) == 0x4000) { //$4000-5fff
|
||||
ram_select = data;
|
||||
return;
|
||||
}
|
||||
|
||||
if(within<0x6000, 0x7fff>(addr)) {
|
||||
if((addr & 0xe000) == 0x6000) { //$6000-7fff
|
||||
//unknown purpose
|
||||
return;
|
||||
}
|
||||
|
||||
if(within<0xa000, 0xbfff>(addr)) {
|
||||
if((addr & 0xe000) == 0xa000) { //$a000-bfff
|
||||
if(ram_enable) cartridge.ram_write((ram_select << 13) | (addr & 0x1fff), data);
|
||||
return;
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
struct HuC3 : MMIO {
|
||||
bool ram_enable; //0000-1fff
|
||||
uint8 rom_select; //2000-3fff
|
||||
uint8 ram_select; //4000-5fff
|
||||
bool ram_enable; //$0000-1fff
|
||||
uint8 rom_select; //$2000-3fff
|
||||
uint8 ram_select; //$4000-5fff
|
||||
|
||||
uint8 mmio_read(uint16 addr);
|
||||
void mmio_write(uint16 addr, uint8 data);
|
||||
|
@@ -1,11 +1,11 @@
|
||||
#ifdef CARTRIDGE_CPP
|
||||
|
||||
uint8 Cartridge::MBC0::mmio_read(uint16 addr) {
|
||||
if(within<0x0000, 0x7fff>(addr)) {
|
||||
if((addr & 0x8000) == 0x0000) { //$0000-7fff
|
||||
return cartridge.rom_read(addr);
|
||||
}
|
||||
|
||||
if(within<0xa000, 0xbfff>(addr)) {
|
||||
if((addr & 0xe000) == 0xa000) { //$a000-bfff
|
||||
return cartridge.ram_read(addr & 0x1fff);
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ uint8 Cartridge::MBC0::mmio_read(uint16 addr) {
|
||||
}
|
||||
|
||||
void Cartridge::MBC0::mmio_write(uint16 addr, uint8 data) {
|
||||
if(within<0xa000, 0xbfff>(addr)) {
|
||||
if((addr & 0xe000) == 0xa000) { //$a000-bfff
|
||||
cartridge.ram_write(addr & 0x1fff, data);
|
||||
return;
|
||||
}
|
||||
|
@@ -1,11 +1,11 @@
|
||||
#ifdef CARTRIDGE_CPP
|
||||
|
||||
uint8 Cartridge::MBC1::mmio_read(uint16 addr) {
|
||||
if(within<0x0000, 0x3fff>(addr)) {
|
||||
if((addr & 0xc000) == 0x0000) { //$0000-3fff
|
||||
return cartridge.rom_read(addr);
|
||||
}
|
||||
|
||||
if(within<0x4000, 0x7fff>(addr)) {
|
||||
if((addr & 0xc000) == 0x4000) { //$4000-7fff
|
||||
if(mode_select == 0) {
|
||||
return cartridge.rom_read((ram_select << 19) | (rom_select << 14) | (addr & 0x3fff));
|
||||
} else {
|
||||
@@ -13,7 +13,7 @@ uint8 Cartridge::MBC1::mmio_read(uint16 addr) {
|
||||
}
|
||||
}
|
||||
|
||||
if(within<0xa000, 0xbfff>(addr)) {
|
||||
if((addr & 0xe000) == 0xa000) { //$a000-bfff
|
||||
if(ram_enable) {
|
||||
if(mode_select == 0) {
|
||||
return cartridge.ram_read(addr & 0x1fff);
|
||||
@@ -28,27 +28,27 @@ uint8 Cartridge::MBC1::mmio_read(uint16 addr) {
|
||||
}
|
||||
|
||||
void Cartridge::MBC1::mmio_write(uint16 addr, uint8 data) {
|
||||
if(within<0x0000, 0x1fff>(addr)) {
|
||||
if((addr & 0xe000) == 0x0000) { //$0000-1fff
|
||||
ram_enable = (data & 0x0f) == 0x0a;
|
||||
return;
|
||||
}
|
||||
|
||||
if(within<0x2000, 0x3fff>(addr)) {
|
||||
if((addr & 0xe000) == 0x2000) { //$2000-3fff
|
||||
rom_select = (data & 0x1f) + ((data & 0x1f) == 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if(within<0x4000, 0x5fff>(addr)) {
|
||||
if((addr & 0xe000) == 0x4000) { //$4000-5fff
|
||||
ram_select = data & 0x03;
|
||||
return;
|
||||
}
|
||||
|
||||
if(within<0x6000, 0x7fff>(addr)) {
|
||||
if((addr & 0xe000) == 0x6000) { //$6000-7fff
|
||||
mode_select = data & 0x01;
|
||||
return;
|
||||
}
|
||||
|
||||
if(within<0xa000, 0xbfff>(addr)) {
|
||||
if((addr & 0xe000) == 0xa000) { //$a000-bfff
|
||||
if(ram_enable) {
|
||||
if(mode_select == 0) {
|
||||
cartridge.ram_write(addr & 0x1fff, data);
|
||||
|
@@ -1,8 +1,8 @@
|
||||
struct MBC1 : MMIO {
|
||||
bool ram_enable; //0000-1fff
|
||||
uint8 rom_select; //2000-3fff
|
||||
uint8 ram_select; //4000-5fff
|
||||
bool mode_select; //6000-7fff
|
||||
bool ram_enable; //$0000-1fff
|
||||
uint8 rom_select; //$2000-3fff
|
||||
uint8 ram_select; //$4000-5fff
|
||||
bool mode_select; //$6000-7fff
|
||||
|
||||
uint8 mmio_read(uint16 addr);
|
||||
void mmio_write(uint16 addr, uint8 data);
|
||||
|
@@ -1,15 +1,15 @@
|
||||
#ifdef CARTRIDGE_CPP
|
||||
|
||||
uint8 Cartridge::MBC2::mmio_read(uint16 addr) {
|
||||
if(within<0x0000, 0x3fff>(addr)) {
|
||||
if((addr & 0xc000) == 0x0000) { //$0000-3fff
|
||||
return cartridge.rom_read(addr);
|
||||
}
|
||||
|
||||
if(within<0x4000, 0x7fff>(addr)) {
|
||||
if((addr & 0xc000) == 0x4000) { //$4000-7fff
|
||||
return cartridge.rom_read((rom_select << 14) | (addr & 0x3fff));
|
||||
}
|
||||
|
||||
if(within<0xa000, 0xa1ff>(addr)) {
|
||||
if((addr & 0xee00) == 0xa000) { //$a000-a1ff
|
||||
if(ram_enable) return cartridge.ram_read(addr & 0x1ff);
|
||||
return 0x00;
|
||||
}
|
||||
@@ -18,17 +18,17 @@ uint8 Cartridge::MBC2::mmio_read(uint16 addr) {
|
||||
}
|
||||
|
||||
void Cartridge::MBC2::mmio_write(uint16 addr, uint8 data) {
|
||||
if(within<0x0000, 0x1fff>(addr)) {
|
||||
if((addr & 0xe000) == 0x0000) { //$0000-1fff
|
||||
if(!(addr & 0x0100)) ram_enable = (data & 0x0f) == 0x0a;
|
||||
return;
|
||||
}
|
||||
|
||||
if(within<0x2000, 0x3fff>(addr)) {
|
||||
if((addr & 0xe000) == 0x2000) { //$2000-3fff
|
||||
if( (addr & 0x0100)) rom_select = (data & 0x0f) + ((data & 0x0f) == 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if(within<0xa000, 0xa1ff>(addr)) {
|
||||
if((addr & 0xee00) == 0xa000) { //$a000-a1ff
|
||||
if(ram_enable) cartridge.ram_write(addr & 0x1ff, data & 0x0f);
|
||||
return;
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
struct MBC2 : MMIO {
|
||||
bool ram_enable; //0000-1fff
|
||||
uint8 rom_select; //2000-3fff
|
||||
bool ram_enable; //$0000-1fff
|
||||
uint8 rom_select; //$2000-3fff
|
||||
|
||||
uint8 mmio_read(uint16 addr);
|
||||
void mmio_write(uint16 addr, uint8 data);
|
||||
|
@@ -19,15 +19,15 @@ void Cartridge::MBC3::second() {
|
||||
}
|
||||
|
||||
uint8 Cartridge::MBC3::mmio_read(uint16 addr) {
|
||||
if(within<0x0000, 0x3fff>(addr)) {
|
||||
if((addr & 0xc000) == 0x0000) { //$0000-3fff
|
||||
return cartridge.rom_read(addr);
|
||||
}
|
||||
|
||||
if(within<0x4000, 0x7fff>(addr)) {
|
||||
if((addr & 0xc000) == 0x4000) { //$4000-7fff
|
||||
return cartridge.rom_read((rom_select << 14) | (addr & 0x3fff));
|
||||
}
|
||||
|
||||
if(within<0xa000, 0xbfff>(addr)) {
|
||||
if((addr & 0xe000) == 0xa000) { //$a000-bfff
|
||||
if(ram_enable) {
|
||||
if(ram_select >= 0x00 && ram_select <= 0x03) {
|
||||
return cartridge.ram_read((ram_select << 13) | (addr & 0x1fff));
|
||||
@@ -45,22 +45,22 @@ uint8 Cartridge::MBC3::mmio_read(uint16 addr) {
|
||||
}
|
||||
|
||||
void Cartridge::MBC3::mmio_write(uint16 addr, uint8 data) {
|
||||
if(within<0x0000, 0x1fff>(addr)) {
|
||||
if((addr & 0xe000) == 0x0000) { //$0000-1fff
|
||||
ram_enable = (data & 0x0f) == 0x0a;
|
||||
return;
|
||||
}
|
||||
|
||||
if(within<0x2000, 0x3fff>(addr)) {
|
||||
if((addr & 0xe000) == 0x2000) { //$2000-3fff
|
||||
rom_select = (data & 0x7f) + ((data & 0x7f) == 0);
|
||||
return;
|
||||
}
|
||||
|
||||
if(within<0x4000, 0x5fff>(addr)) {
|
||||
if((addr & 0xe000) == 0x4000) { //$4000-5fff
|
||||
ram_select = data;
|
||||
return;
|
||||
}
|
||||
|
||||
if(within<0x6000, 0x7fff>(addr)) {
|
||||
if((addr & 0xe000) == 0x6000) { //$6000-7fff
|
||||
if(rtc_latch == 0 && data == 1) {
|
||||
rtc_latch_second = rtc_second;
|
||||
rtc_latch_minute = rtc_minute;
|
||||
@@ -72,7 +72,7 @@ void Cartridge::MBC3::mmio_write(uint16 addr, uint8 data) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(within<0xa000, 0xbfff>(addr)) {
|
||||
if((addr & 0xe000) == 0xa000) { //$a000-bfff
|
||||
if(ram_enable) {
|
||||
if(ram_select >= 0x00 && ram_select <= 0x03) {
|
||||
cartridge.ram_write((ram_select << 13) | (addr & 0x1fff), data);
|
||||
|
@@ -1,8 +1,8 @@
|
||||
struct MBC3 : MMIO {
|
||||
bool ram_enable; //0000-1fff
|
||||
uint8 rom_select; //2000-3fff
|
||||
uint8 ram_select; //4000-5fff
|
||||
bool rtc_latch; //6000-7fff
|
||||
bool ram_enable; //$0000-1fff
|
||||
uint8 rom_select; //$2000-3fff
|
||||
uint8 ram_select; //$4000-5fff
|
||||
bool rtc_latch; //$6000-7fff
|
||||
|
||||
bool rtc_halt;
|
||||
unsigned rtc_second;
|
||||
|
@@ -1,15 +1,15 @@
|
||||
#ifdef CARTRIDGE_CPP
|
||||
|
||||
uint8 Cartridge::MBC5::mmio_read(uint16 addr) {
|
||||
if(within<0x0000, 0x3fff>(addr)) {
|
||||
if((addr & 0xc000) == 0x0000) { //$0000-3fff
|
||||
return cartridge.rom_read(addr);
|
||||
}
|
||||
|
||||
if(within<0x4000, 0x7fff>(addr)) {
|
||||
if((addr & 0xc000) == 0x4000) { //$4000-7fff
|
||||
return cartridge.rom_read((rom_select << 14) | (addr & 0x3fff));
|
||||
}
|
||||
|
||||
if(within<0xa000, 0xbfff>(addr)) {
|
||||
if((addr & 0xe000) == 0xa000) { //$a000-bfff
|
||||
if(ram_enable) return cartridge.ram_read((ram_select << 13) | (addr & 0x1fff));
|
||||
return 0x00;
|
||||
}
|
||||
@@ -18,27 +18,27 @@ uint8 Cartridge::MBC5::mmio_read(uint16 addr) {
|
||||
}
|
||||
|
||||
void Cartridge::MBC5::mmio_write(uint16 addr, uint8 data) {
|
||||
if(within<0x0000, 0x1fff>(addr)) {
|
||||
if((addr & 0xe000) == 0x0000) { //$0000-1fff
|
||||
ram_enable = (data & 0x0f) == 0x0a;
|
||||
return;
|
||||
}
|
||||
|
||||
if(within<0x2000, 0x2fff>(addr)) {
|
||||
if((addr & 0xf000) == 0x2000) { //$2000-2fff
|
||||
rom_select = (rom_select & 0x0100) | data;
|
||||
return;
|
||||
}
|
||||
|
||||
if(within<0x3000, 0x3fff>(addr)) {
|
||||
if((addr & 0xf000) == 0x3000) { //$3000-3fff
|
||||
rom_select = ((data & 1) << 8) | (rom_select & 0x00ff);
|
||||
return;
|
||||
}
|
||||
|
||||
if(within<0x4000, 0x5fff>(addr)) {
|
||||
if((addr & 0xe000) == 0x4000) { //$4000-5fff
|
||||
ram_select = data & 0x0f;
|
||||
return;
|
||||
}
|
||||
|
||||
if(within<0xa000, 0xbfff>(addr)) {
|
||||
if((addr & 0xe000) == 0xa000) { //$a000-bfff
|
||||
if(ram_enable) cartridge.ram_write((ram_select << 13) | (addr & 0x1fff), data);
|
||||
return;
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
struct MBC5 : MMIO {
|
||||
bool ram_enable; //0000-1fff
|
||||
uint16 rom_select; //2000-2fff + 3000-3fff
|
||||
uint8 ram_select; //4000-5fff
|
||||
bool ram_enable; //$0000-1fff
|
||||
uint16 rom_select; //$2000-2fff + $3000-3fff
|
||||
uint8 ram_select; //$4000-5fff
|
||||
|
||||
uint8 mmio_read(uint16 addr);
|
||||
void mmio_write(uint16 addr, uint8 data);
|
||||
|
@@ -1,19 +1,19 @@
|
||||
#ifdef CARTRIDGE_CPP
|
||||
|
||||
uint8 Cartridge::MMM01::mmio_read(uint16 addr) {
|
||||
if(within<0x0000, 0x7fff>(addr)) {
|
||||
if((addr & 0x8000) == 0x0000) { //$0000-7fff
|
||||
if(rom_mode == 0) return cartridge.rom_read(addr);
|
||||
}
|
||||
|
||||
if(within<0x0000, 0x3fff>(addr)) {
|
||||
if((addr & 0xc000) == 0x0000) { //$0000-3fff
|
||||
return cartridge.rom_read(0x8000 + (rom_base << 14) + (addr & 0x3fff));
|
||||
}
|
||||
|
||||
if(within<0x4000, 0x7fff>(addr)) {
|
||||
if((addr & 0xc000) == 0x4000) { //$4000-7fff
|
||||
return cartridge.rom_read(0x8000 + (rom_base << 14) + (rom_select << 14) + (addr & 0x3fff));
|
||||
}
|
||||
|
||||
if(within<0xa000, 0xbfff>(addr)) {
|
||||
if((addr & 0xe000) == 0xa000) { //$a000-bfff
|
||||
if(ram_enable) return cartridge.ram_read((ram_select << 13) + (addr & 0x1fff));
|
||||
return 0x00;
|
||||
}
|
||||
@@ -22,7 +22,7 @@ uint8 Cartridge::MMM01::mmio_read(uint16 addr) {
|
||||
}
|
||||
|
||||
void Cartridge::MMM01::mmio_write(uint16 addr, uint8 data) {
|
||||
if(within<0x0000, 0x1fff>(addr)) {
|
||||
if((addr & 0xe000) == 0x0000) { //$0000-1fff
|
||||
if(rom_mode == 0) {
|
||||
rom_mode = 1;
|
||||
} else {
|
||||
@@ -30,7 +30,7 @@ void Cartridge::MMM01::mmio_write(uint16 addr, uint8 data) {
|
||||
}
|
||||
}
|
||||
|
||||
if(within<0x2000, 0x3fff>(addr)) {
|
||||
if((addr & 0xe000) == 0x2000) { //$2000-3fff
|
||||
if(rom_mode == 0) {
|
||||
rom_base = data & 0x3f;
|
||||
} else {
|
||||
@@ -38,17 +38,17 @@ void Cartridge::MMM01::mmio_write(uint16 addr, uint8 data) {
|
||||
}
|
||||
}
|
||||
|
||||
if(within<0x4000, 0x5fff>(addr)) {
|
||||
if((addr & 0xe000) == 0x4000) { //$4000-5fff
|
||||
if(rom_mode == 1) {
|
||||
ram_select = data;
|
||||
}
|
||||
}
|
||||
|
||||
if(within<0x6000, 0x7fff>(addr)) {
|
||||
if((addr & 0xe000) == 0x6000) { //$6000-7fff
|
||||
//unknown purpose
|
||||
}
|
||||
|
||||
if(within<0xa000, 0xbfff>(addr)) {
|
||||
if((addr & 0xe000) == 0xa000) { //$a000-bfff
|
||||
if(ram_enable) cartridge.ram_write((ram_select << 13) + (addr & 0x1fff), data);
|
||||
}
|
||||
}
|
||||
|
@@ -41,9 +41,10 @@ void Cartridge::serialize(serializer &s) {
|
||||
s.integer(mmm01.rom_select);
|
||||
s.integer(mmm01.ram_select);
|
||||
|
||||
s.integer(huc1.ram_enable);
|
||||
s.integer(huc1.ram_writable);
|
||||
s.integer(huc1.rom_select);
|
||||
s.integer(huc1.ram_select);
|
||||
s.integer(huc1.model);
|
||||
|
||||
s.integer(huc3.ram_enable);
|
||||
s.integer(huc3.rom_select);
|
||||
|
@@ -69,12 +69,6 @@ namespace GameBoy {
|
||||
typedef uint_t<30> uint30;
|
||||
typedef uint_t<31> uint31;
|
||||
|
||||
template<uint16 lo, uint16 hi>
|
||||
alwaysinline bool within(uint16 addr) {
|
||||
static const uint16 mask = ~(hi ^ lo);
|
||||
return (addr & mask) == lo;
|
||||
}
|
||||
|
||||
struct Processor {
|
||||
cothread_t thread;
|
||||
unsigned frequency;
|
||||
|
@@ -140,7 +140,7 @@ void LCD::cgb_render_ob() {
|
||||
unsigned n = sprite[s] << 2;
|
||||
unsigned sy = oam[n + 0] - 16;
|
||||
unsigned sx = oam[n + 1] - 8;
|
||||
unsigned tile = oam[n + 2];
|
||||
unsigned tile = oam[n + 2] & ~status.ob_size;
|
||||
unsigned attr = oam[n + 3];
|
||||
|
||||
sy = status.ly - sy;
|
||||
|
@@ -109,7 +109,7 @@ void LCD::dmg_render_ob() {
|
||||
unsigned n = sprite[s] << 2;
|
||||
unsigned sy = oam[n + 0] - 16;
|
||||
unsigned sx = oam[n + 1] - 8;
|
||||
unsigned tile = oam[n + 2];
|
||||
unsigned tile = oam[n + 2] & ~status.ob_size;
|
||||
unsigned attr = oam[n + 3];
|
||||
|
||||
sy = status.ly - sy;
|
||||
|
@@ -41,6 +41,9 @@ ifeq ($(compiler),)
|
||||
endif
|
||||
endif
|
||||
|
||||
c := $(compiler) -std=gnu99
|
||||
cpp := $(subst cc,++,$(compiler)) -std=gnu++0x
|
||||
|
||||
ifeq ($(prefix),)
|
||||
prefix := /usr/local
|
||||
endif
|
||||
|
@@ -118,16 +118,21 @@ namespace nall {
|
||||
operator=(std::move(source));
|
||||
}
|
||||
|
||||
//index
|
||||
inline T& operator[](unsigned index) {
|
||||
if(index >= buffersize) resize(index + 1);
|
||||
if(index >= buffersize) throw "array[] out of bounds";
|
||||
return pool[index];
|
||||
//access
|
||||
inline T& operator[](unsigned position) {
|
||||
if(position >= buffersize) resize(position + 1);
|
||||
if(position >= buffersize) throw "array[] out of bounds";
|
||||
return pool[position];
|
||||
}
|
||||
|
||||
inline const T& operator[](unsigned index) const {
|
||||
if(index >= buffersize) throw "array[] out of bounds";
|
||||
return pool[index];
|
||||
inline const T& operator[](unsigned position) const {
|
||||
if(position >= buffersize) throw "array[] out of bounds";
|
||||
return pool[position];
|
||||
}
|
||||
|
||||
inline const T& operator()(unsigned position, const T& data) {
|
||||
if(position >= buffersize) return data;
|
||||
return pool[position];
|
||||
}
|
||||
|
||||
//iteration
|
||||
|
@@ -8,11 +8,49 @@ namespace nall {
|
||||
struct compositor {
|
||||
inline static bool enabled();
|
||||
inline static bool enable(bool status);
|
||||
|
||||
#if defined(PLATFORM_X)
|
||||
enum class Compositor : unsigned { Unknown, Metacity, Xfwm4 };
|
||||
inline static Compositor detect();
|
||||
|
||||
inline static bool enabled_metacity();
|
||||
inline static bool enable_metacity(bool status);
|
||||
|
||||
inline static bool enabled_xfwm4();
|
||||
inline static bool enable_xfwm4(bool status);
|
||||
#endif
|
||||
};
|
||||
|
||||
#if defined(PLATFORM_X)
|
||||
|
||||
bool compositor::enabled() {
|
||||
//Metacity
|
||||
|
||||
bool compositor::enabled_metacity() {
|
||||
FILE *fp = popen("gconftool-2 --get /apps/metacity/general/compositing_manager", "r");
|
||||
if(fp == 0) return false;
|
||||
|
||||
char buffer[512];
|
||||
if(fgets(buffer, sizeof buffer, fp) == 0) return false;
|
||||
|
||||
if(!memcmp(buffer, "true", 4)) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool compositor::enable_metacity(bool status) {
|
||||
FILE *fp;
|
||||
if(status) {
|
||||
fp = popen("gconftool-2 --set --type bool /apps/metacity/general/compositing_manager true", "r");
|
||||
} else {
|
||||
fp = popen("gconftool-2 --set --type bool /apps/metacity/general/compositing_manager false", "r");
|
||||
}
|
||||
if(fp == 0) return false;
|
||||
pclose(fp);
|
||||
return true;
|
||||
}
|
||||
|
||||
//Xfwm4
|
||||
|
||||
bool compositor::enabled_xfwm4() {
|
||||
FILE *fp = popen("xfconf-query -c xfwm4 -p '/general/use_compositing'", "r");
|
||||
if(fp == 0) return false;
|
||||
|
||||
@@ -23,7 +61,7 @@ bool compositor::enabled() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool compositor::enable(bool status) {
|
||||
bool compositor::enable_xfwm4(bool status) {
|
||||
FILE *fp;
|
||||
if(status) {
|
||||
fp = popen("xfconf-query -c xfwm4 -p '/general/use_compositing' -t 'bool' -s 'true'", "r");
|
||||
@@ -35,6 +73,41 @@ bool compositor::enable(bool status) {
|
||||
return true;
|
||||
}
|
||||
|
||||
//General
|
||||
|
||||
compositor::Compositor compositor::detect() {
|
||||
Compositor result = Compositor::Unknown;
|
||||
|
||||
FILE *fp;
|
||||
char buffer[512];
|
||||
|
||||
fp = popen("pidof metacity", "r");
|
||||
if(fp && fgets(buffer, sizeof buffer, fp)) result = Compositor::Metacity;
|
||||
pclose(fp);
|
||||
|
||||
fp = popen("pidof xfwm4", "r");
|
||||
if(fp && fgets(buffer, sizeof buffer, fp)) result = Compositor::Xfwm4;
|
||||
pclose(fp);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool compositor::enabled() {
|
||||
switch(detect()) {
|
||||
case Compositor::Metacity: return enabled_metacity();
|
||||
case Compositor::Xfwm4: return enabled_xfwm4();
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool compositor::enable(bool status) {
|
||||
switch(detect()) {
|
||||
case Compositor::Metacity: return enable_metacity(status);
|
||||
case Compositor::Xfwm4: return enable_xfwm4(status);
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
#elif defined(PLATFORM_WINDOWS)
|
||||
|
||||
bool compositor::enabled() {
|
||||
|
@@ -1,6 +1,7 @@
|
||||
#ifndef NALL_FILEMAP_HPP
|
||||
#define NALL_FILEMAP_HPP
|
||||
|
||||
#include <nall/file.hpp>
|
||||
#include <nall/stdint.hpp>
|
||||
#include <nall/windows/utf8.hpp>
|
||||
|
||||
|
@@ -100,6 +100,16 @@ GameBoyCartridge::GameBoyCartridge(uint8_t *romdata, unsigned romsize) {
|
||||
|
||||
if(info.mapper == "MBC2") info.ramsize = 512; //512 x 4-bit
|
||||
|
||||
markup.append(
|
||||
"<?xml version='1.0' encoding='UTF-8'?>\n",
|
||||
"<cartridge mapper='", info.mapper, "' rtc='", info.rtc, "' rumble='", info.rumble, "'>\n",
|
||||
" <rom size='0x", hex(romsize), "'/>\n");
|
||||
if(info.ramsize > 0) markup.append(
|
||||
" <ram size='0x", hex(info.ramsize), "' battery='", info.battery, "'/>\n");
|
||||
markup.append(
|
||||
"</cartridge>\n");
|
||||
|
||||
/*
|
||||
markup.append("cartridge mapper=", info.mapper);
|
||||
if(info.rtc) markup.append(" rtc");
|
||||
if(info.rumble) markup.append(" rumble");
|
||||
@@ -109,6 +119,7 @@ GameBoyCartridge::GameBoyCartridge(uint8_t *romdata, unsigned romsize) {
|
||||
|
||||
if(info.ramsize > 0)
|
||||
markup.append("\t" "ram size=", hex(info.ramsize), info.battery ? " non-volatile\n" : "\n");
|
||||
*/
|
||||
}
|
||||
|
||||
}
|
||||
|
55
bsnes/nall/hid.hpp
Executable file
55
bsnes/nall/hid.hpp
Executable file
@@ -0,0 +1,55 @@
|
||||
#ifndef NALL_HID_HPP
|
||||
#define NALL_HID_HPP
|
||||
|
||||
#include <nall/xorg/xorg.hpp>
|
||||
#include <nall/input.hpp>
|
||||
|
||||
namespace nall {
|
||||
namespace HID {
|
||||
|
||||
struct Keyboard {
|
||||
XlibDisplay *display;
|
||||
|
||||
inline void poll() {
|
||||
XQueryKeymap(display, state);
|
||||
}
|
||||
|
||||
inline bool operator[](unsigned id) {
|
||||
return state[scancode[id] >> 3] & (1 << (scancode[id] & 7));
|
||||
}
|
||||
|
||||
inline Keyboard() {
|
||||
display = XOpenDisplay(0);
|
||||
memset(&scancode, 0, sizeof scancode);
|
||||
|
||||
#define map(key, sym) scancode[key] = XKeysymToKeycode(display, sym)
|
||||
|
||||
using nall::Keyboard;
|
||||
map(Keyboard::Insert, XK_Insert);
|
||||
map(Keyboard::Delete, XK_Delete);
|
||||
map(Keyboard::Home, XK_Home);
|
||||
map(Keyboard::End, XK_End);
|
||||
map(Keyboard::PageUp, XK_Prior);
|
||||
map(Keyboard::PageDown, XK_Next);
|
||||
|
||||
map(Keyboard::Up, XK_Up);
|
||||
map(Keyboard::Down, XK_Down);
|
||||
map(Keyboard::Left, XK_Left);
|
||||
map(Keyboard::Right, XK_Right);
|
||||
|
||||
#undef map
|
||||
}
|
||||
|
||||
inline ~Keyboard() {
|
||||
XCloseDisplay(display);
|
||||
}
|
||||
|
||||
private:
|
||||
char state[32];
|
||||
uint8_t scancode[256];
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
443
bsnes/nall/image.hpp
Executable file
443
bsnes/nall/image.hpp
Executable file
@@ -0,0 +1,443 @@
|
||||
#ifndef NALL_IMAGE_HPP
|
||||
#define NALL_IMAGE_HPP
|
||||
|
||||
#include <nall/bmp.hpp>
|
||||
#include <nall/interpolation.hpp>
|
||||
#include <nall/png.hpp>
|
||||
#include <nall/stdint.hpp>
|
||||
#include <algorithm>
|
||||
|
||||
namespace nall {
|
||||
|
||||
struct image {
|
||||
uint8_t *data;
|
||||
unsigned width;
|
||||
unsigned height;
|
||||
unsigned pitch;
|
||||
|
||||
bool endian; //0 = little, 1 = big
|
||||
unsigned depth;
|
||||
unsigned stride;
|
||||
|
||||
struct Channel {
|
||||
uint64_t mask;
|
||||
unsigned depth;
|
||||
unsigned shift;
|
||||
} alpha, red, green, blue;
|
||||
|
||||
typedef double (*interpolation)(double, double, double, double, double);
|
||||
static inline unsigned bitDepth(uint64_t color);
|
||||
static inline unsigned bitShift(uint64_t color);
|
||||
static inline uint64_t normalize(uint64_t color, unsigned sourceDepth, unsigned targetDepth);
|
||||
|
||||
inline image& operator=(const image &source);
|
||||
inline image& operator=(image &&source);
|
||||
inline image(const image &source);
|
||||
inline image(image &&source);
|
||||
inline image(bool endian, unsigned depth, uint64_t alphaMask, uint64_t redMask, uint64_t greenMask, uint64_t blueMask);
|
||||
inline ~image();
|
||||
|
||||
inline uint64_t read(const uint8_t *data) const;
|
||||
inline void write(uint8_t *data, uint64_t value) const;
|
||||
|
||||
inline void free();
|
||||
inline void allocate(unsigned width, unsigned height);
|
||||
inline void clear(uint64_t color);
|
||||
inline bool load(const string &filename);
|
||||
inline void scale(unsigned width, unsigned height, interpolation op);
|
||||
inline void transform(bool endian, unsigned depth, uint64_t alphaMask, uint64_t redMask, uint64_t greenMask, uint64_t blueMask);
|
||||
inline void alphaBlend(uint64_t alphaColor);
|
||||
|
||||
protected:
|
||||
inline uint64_t interpolate(double mu, const uint64_t *s, interpolation op);
|
||||
inline void scaleX(unsigned width, interpolation op);
|
||||
inline void scaleY(unsigned height, interpolation op);
|
||||
inline bool loadBMP(const string &filename);
|
||||
inline bool loadPNG(const string &filename);
|
||||
};
|
||||
|
||||
//static
|
||||
|
||||
unsigned image::bitDepth(uint64_t color) {
|
||||
unsigned depth = 0;
|
||||
if(color) while((color & 1) == 0) color >>= 1;
|
||||
while((color & 1) == 1) { color >>= 1; depth++; }
|
||||
return depth;
|
||||
}
|
||||
|
||||
unsigned image::bitShift(uint64_t color) {
|
||||
unsigned shift = 0;
|
||||
if(color) while((color & 1) == 0) { color >>= 1; shift++; }
|
||||
return shift;
|
||||
}
|
||||
|
||||
uint64_t image::normalize(uint64_t color, unsigned sourceDepth, unsigned targetDepth) {
|
||||
while(sourceDepth < targetDepth) {
|
||||
color = (color << sourceDepth) | color;
|
||||
sourceDepth += sourceDepth;
|
||||
}
|
||||
if(targetDepth < sourceDepth) color >>= (sourceDepth - targetDepth);
|
||||
return color;
|
||||
}
|
||||
|
||||
//public
|
||||
|
||||
image& image::operator=(const image &source) {
|
||||
free();
|
||||
|
||||
width = source.width;
|
||||
height = source.height;
|
||||
pitch = source.pitch;
|
||||
|
||||
endian = source.endian;
|
||||
stride = source.stride;
|
||||
|
||||
alpha = source.alpha;
|
||||
red = source.red;
|
||||
green = source.green;
|
||||
blue = source.blue;
|
||||
|
||||
data = new uint8_t[width * height * stride];
|
||||
memcpy(data, source.data, width * height * stride);
|
||||
return *this;
|
||||
}
|
||||
|
||||
image& image::operator=(image &&source) {
|
||||
width = source.width;
|
||||
height = source.height;
|
||||
pitch = source.pitch;
|
||||
|
||||
endian = source.endian;
|
||||
stride = source.stride;
|
||||
|
||||
alpha = source.alpha;
|
||||
red = source.red;
|
||||
green = source.green;
|
||||
blue = source.blue;
|
||||
|
||||
data = source.data;
|
||||
source.data = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
image::image(const image &source) : data(nullptr) {
|
||||
operator=(source);
|
||||
}
|
||||
|
||||
image::image(image &&source) : data(nullptr) {
|
||||
operator=(std::forward<image>(source));
|
||||
}
|
||||
|
||||
image::image(bool endian, unsigned depth, uint64_t alphaMask, uint64_t redMask, uint64_t greenMask, uint64_t blueMask) : data(nullptr) {
|
||||
width = 0, height = 0, pitch = 0;
|
||||
|
||||
this->endian = endian;
|
||||
this->depth = depth;
|
||||
this->stride = (depth / 8) + ((depth & 7) > 0);
|
||||
|
||||
alpha.mask = alphaMask, red.mask = redMask, green.mask = greenMask, blue.mask = blueMask;
|
||||
alpha.depth = bitDepth(alpha.mask), alpha.shift = bitShift(alpha.mask);
|
||||
red.depth = bitDepth(red.mask), red.shift = bitShift(red.mask);
|
||||
green.depth = bitDepth(green.mask), green.shift = bitShift(green.mask);
|
||||
blue.depth = bitDepth(blue.mask), blue.shift = bitShift(blue.mask);
|
||||
}
|
||||
|
||||
image::~image() {
|
||||
free();
|
||||
}
|
||||
|
||||
uint64_t image::read(const uint8_t *data) const {
|
||||
uint64_t result = 0;
|
||||
if(endian == 0) {
|
||||
for(signed n = stride - 1; n >= 0; n--) result = (result << 8) | data[n];
|
||||
} else {
|
||||
for(signed n = 0; n < stride; n++) result = (result << 8) | data[n];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void image::write(uint8_t *data, uint64_t value) const {
|
||||
if(endian == 0) {
|
||||
for(signed n = 0; n < stride; n++) { data[n] = value; value >>= 8; }
|
||||
} else {
|
||||
for(signed n = stride - 1; n >= 0; n--) { data[n] = value; value >>= 8; }
|
||||
}
|
||||
}
|
||||
|
||||
void image::free() {
|
||||
if(data) delete[] data;
|
||||
data = nullptr;
|
||||
}
|
||||
|
||||
void image::allocate(unsigned width, unsigned height) {
|
||||
if(data != nullptr && this->width == width && this->height == height) return;
|
||||
free();
|
||||
data = new uint8_t[width * height * stride]();
|
||||
pitch = width * stride;
|
||||
this->width = width;
|
||||
this->height = height;
|
||||
}
|
||||
|
||||
void image::clear(uint64_t color) {
|
||||
uint8_t *dp = data;
|
||||
for(unsigned n = 0; n < width * height; n++) {
|
||||
write(dp, color);
|
||||
dp += stride;
|
||||
}
|
||||
}
|
||||
|
||||
bool image::load(const string &filename) {
|
||||
if(loadBMP(filename) == true) return true;
|
||||
if(loadPNG(filename) == true) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
void image::scale(unsigned outputWidth, unsigned outputHeight, interpolation op) {
|
||||
scaleX(outputWidth, op);
|
||||
scaleY(outputHeight, op);
|
||||
}
|
||||
|
||||
void image::transform(bool outputEndian, unsigned outputDepth, uint64_t outputAlphaMask, uint64_t outputRedMask, uint64_t outputGreenMask, uint64_t outputBlueMask) {
|
||||
image output(outputEndian, outputDepth, outputAlphaMask, outputRedMask, outputGreenMask, outputBlueMask);
|
||||
output.allocate(width, height);
|
||||
|
||||
#pragma omp parallel for
|
||||
for(unsigned y = 0; y < height; y++) {
|
||||
uint8_t *dp = output.data + output.pitch * y;
|
||||
uint8_t *sp = data + pitch * y;
|
||||
for(unsigned x = 0; x < width; x++) {
|
||||
uint64_t color = read(sp);
|
||||
sp += stride;
|
||||
|
||||
uint64_t a = (color & alpha.mask) >> alpha.shift;
|
||||
uint64_t r = (color & red.mask) >> red.shift;
|
||||
uint64_t g = (color & green.mask) >> green.shift;
|
||||
uint64_t b = (color & blue.mask) >> blue.shift;
|
||||
|
||||
a = normalize(a, alpha.depth, output.alpha.depth);
|
||||
r = normalize(r, red.depth, output.red.depth);
|
||||
g = normalize(g, green.depth, output.green.depth);
|
||||
b = normalize(b, blue.depth, output.blue.depth);
|
||||
|
||||
output.write(dp, (a << output.alpha.shift) | (r << output.red.shift) | (g << output.green.shift) | (b << output.blue.shift));
|
||||
dp += output.stride;
|
||||
}
|
||||
}
|
||||
|
||||
operator=(std::move(output));
|
||||
}
|
||||
|
||||
void image::alphaBlend(uint64_t alphaColor) {
|
||||
uint64_t alphaR = (alphaColor & red.mask) >> red.shift;
|
||||
uint64_t alphaG = (alphaColor & green.mask) >> green.shift;
|
||||
uint64_t alphaB = (alphaColor & blue.mask) >> blue.shift;
|
||||
|
||||
#pragma omp parallel for
|
||||
for(unsigned y = 0; y < height; y++) {
|
||||
uint8_t *dp = data + pitch * y;
|
||||
for(unsigned x = 0; x < width; x++) {
|
||||
uint64_t color = read(dp);
|
||||
|
||||
uint64_t colorA = (color & alpha.mask) >> alpha.shift;
|
||||
uint64_t colorR = (color & red.mask) >> red.shift;
|
||||
uint64_t colorG = (color & green.mask) >> green.shift;
|
||||
uint64_t colorB = (color & blue.mask) >> blue.shift;
|
||||
double alphaScale = (double)colorA / (double)((1 << alpha.depth) - 1);
|
||||
|
||||
colorA = (1 << alpha.depth) - 1;
|
||||
colorR = (colorR * alphaScale) + (alphaR * (1.0 - alphaScale));
|
||||
colorG = (colorG * alphaScale) + (alphaG * (1.0 - alphaScale));
|
||||
colorB = (colorB * alphaScale) + (alphaB * (1.0 - alphaScale));
|
||||
|
||||
write(dp, (colorA << alpha.shift) | (colorR << red.shift) | (colorG << green.shift) | (colorB << blue.shift));
|
||||
dp += stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//protected
|
||||
|
||||
uint64_t image::interpolate(double mu, const uint64_t *s, double (*op)(double, double, double, double, double)) {
|
||||
uint64_t aa = (s[0] & alpha.mask) >> alpha.shift, ar = (s[0] & red.mask) >> red.shift,
|
||||
ag = (s[0] & green.mask) >> green.shift, ab = (s[0] & blue.mask) >> blue.shift;
|
||||
uint64_t ba = (s[1] & alpha.mask) >> alpha.shift, br = (s[1] & red.mask) >> red.shift,
|
||||
bg = (s[1] & green.mask) >> green.shift, bb = (s[1] & blue.mask) >> blue.shift;
|
||||
uint64_t ca = (s[2] & alpha.mask) >> alpha.shift, cr = (s[2] & red.mask) >> red.shift,
|
||||
cg = (s[2] & green.mask) >> green.shift, cb = (s[2] & blue.mask) >> blue.shift;
|
||||
uint64_t da = (s[3] & alpha.mask) >> alpha.shift, dr = (s[3] & red.mask) >> red.shift,
|
||||
dg = (s[3] & green.mask) >> green.shift, db = (s[3] & blue.mask) >> blue.shift;
|
||||
|
||||
int64_t A = op(mu, aa, ba, ca, da);
|
||||
int64_t R = op(mu, ar, br, cr, dr);
|
||||
int64_t G = op(mu, ag, bg, cg, dg);
|
||||
int64_t B = op(mu, ab, bb, cb, db);
|
||||
|
||||
A = max(0, min(A, (1 << alpha.depth) - 1));
|
||||
R = max(0, min(R, (1 << red.depth) - 1));
|
||||
G = max(0, min(G, (1 << green.depth) - 1));
|
||||
B = max(0, min(B, (1 << blue.depth) - 1));
|
||||
|
||||
return (A << alpha.shift) | (R << red.shift) | (G << green.shift) | (B << blue.shift);
|
||||
}
|
||||
|
||||
void image::scaleX(unsigned outputWidth, interpolation op) {
|
||||
uint8_t *outputData = new uint8_t[outputWidth * height * stride];
|
||||
unsigned outputPitch = outputWidth * stride;
|
||||
double step = (double)width / (double)outputWidth;
|
||||
|
||||
#pragma omp parallel for
|
||||
for(unsigned y = 0; y < height; y++) {
|
||||
uint8_t *dp = outputData + outputPitch * y;
|
||||
uint8_t *sp = data + pitch * y;
|
||||
|
||||
double fraction = 0.0;
|
||||
uint64_t s[4] = { read(sp), read(sp), read(sp), read(sp) };
|
||||
|
||||
for(unsigned x = 0; x < width; x++) {
|
||||
if(sp >= data + pitch * height) break;
|
||||
s[0] = s[1];
|
||||
s[1] = s[2];
|
||||
s[2] = s[3];
|
||||
s[3] = read(sp);
|
||||
|
||||
while(fraction <= 1.0) {
|
||||
if(dp >= outputData + outputPitch * height) break;
|
||||
write(dp, interpolate(fraction, (const uint64_t*)&s, op));
|
||||
dp += stride;
|
||||
fraction += step;
|
||||
}
|
||||
|
||||
sp += stride;
|
||||
fraction -= 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
free();
|
||||
data = outputData;
|
||||
width = outputWidth;
|
||||
pitch = width * stride;
|
||||
}
|
||||
|
||||
void image::scaleY(unsigned outputHeight, interpolation op) {
|
||||
uint8_t *outputData = new uint8_t[width * outputHeight * stride];
|
||||
double step = (double)height / (double)outputHeight;
|
||||
|
||||
#pragma omp parallel for
|
||||
for(unsigned x = 0; x < width; x++) {
|
||||
uint8_t *dp = outputData + stride * x;
|
||||
uint8_t *sp = data + stride * x;
|
||||
|
||||
double fraction = 0.0;
|
||||
uint64_t s[4] = { read(sp), read(sp), read(sp), read(sp) };
|
||||
|
||||
for(unsigned y = 0; y < height; y++) {
|
||||
if(sp >= data + pitch * height) break;
|
||||
s[0] = s[1];
|
||||
s[1] = s[2];
|
||||
s[2] = s[3];
|
||||
s[3] = read(sp);
|
||||
|
||||
while(fraction <= 1.0) {
|
||||
if(dp >= outputData + pitch * outputHeight) break;
|
||||
write(dp, interpolate(fraction, (const uint64_t*)&s, op));
|
||||
dp += pitch;
|
||||
fraction += step;
|
||||
}
|
||||
|
||||
sp += pitch;
|
||||
fraction -= 1.0;
|
||||
}
|
||||
}
|
||||
|
||||
free();
|
||||
data = outputData;
|
||||
height = outputHeight;
|
||||
}
|
||||
|
||||
bool image::loadBMP(const string &filename) {
|
||||
uint32_t *outputData;
|
||||
unsigned outputWidth, outputHeight;
|
||||
if(bmp::read(filename, outputData, outputWidth, outputHeight) == false) return false;
|
||||
|
||||
allocate(outputWidth, outputHeight);
|
||||
const uint32_t *sp = outputData;
|
||||
uint8_t *dp = data;
|
||||
|
||||
for(unsigned y = 0; y < outputHeight; y++) {
|
||||
for(unsigned x = 0; x < outputWidth; x++) {
|
||||
uint32_t color = *sp++;
|
||||
uint64_t a = normalize((uint8_t)(color >> 24), 8, alpha.depth);
|
||||
uint64_t r = normalize((uint8_t)(color >> 16), 8, red.depth);
|
||||
uint64_t g = normalize((uint8_t)(color >> 8), 8, green.depth);
|
||||
uint64_t b = normalize((uint8_t)(color >> 0), 8, blue.depth);
|
||||
write(dp, (a << alpha.shift) | (r << red.shift) | (g << green.shift) | (b << blue.shift));
|
||||
dp += stride;
|
||||
}
|
||||
}
|
||||
|
||||
delete[] outputData;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool image::loadPNG(const string &filename) {
|
||||
png source;
|
||||
if(source.decode(filename) == false) return false;
|
||||
|
||||
allocate(source.info.width, source.info.height);
|
||||
const uint8_t *sp = source.data;
|
||||
uint8_t *dp = data;
|
||||
|
||||
auto decode = [&]() -> uint64_t {
|
||||
uint64_t p, r, g, b, a;
|
||||
|
||||
switch(source.info.colorType) {
|
||||
case 0: //L
|
||||
r = g = b = source.readbits(sp);
|
||||
a = (1 << source.info.bitDepth) - 1;
|
||||
break;
|
||||
case 2: //R,G,B
|
||||
r = source.readbits(sp);
|
||||
g = source.readbits(sp);
|
||||
b = source.readbits(sp);
|
||||
a = (1 << source.info.bitDepth) - 1;
|
||||
break;
|
||||
case 3: //P
|
||||
p = source.readbits(sp);
|
||||
r = source.info.palette[p][0];
|
||||
g = source.info.palette[p][1];
|
||||
b = source.info.palette[p][2];
|
||||
a = (1 << source.info.bitDepth) - 1;
|
||||
break;
|
||||
case 4: //L,A
|
||||
r = g = b = source.readbits(sp);
|
||||
a = source.readbits(sp);
|
||||
break;
|
||||
case 6: //R,G,B,A
|
||||
r = source.readbits(sp);
|
||||
g = source.readbits(sp);
|
||||
b = source.readbits(sp);
|
||||
a = source.readbits(sp);
|
||||
break;
|
||||
}
|
||||
|
||||
a = normalize(a, source.info.bitDepth, alpha.depth);
|
||||
r = normalize(r, source.info.bitDepth, red.depth);
|
||||
g = normalize(g, source.info.bitDepth, green.depth);
|
||||
b = normalize(b, source.info.bitDepth, blue.depth);
|
||||
|
||||
return (a << alpha.shift) | (r << red.shift) | (g << green.shift) | (b << blue.shift);
|
||||
};
|
||||
|
||||
for(unsigned y = 0; y < height; y++) {
|
||||
for(unsigned x = 0; x < width; x++) {
|
||||
write(dp, decode());
|
||||
dp += stride;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
59
bsnes/nall/interpolation.hpp
Executable file
59
bsnes/nall/interpolation.hpp
Executable file
@@ -0,0 +1,59 @@
|
||||
#ifndef NALL_INTERPOLATION_HPP
|
||||
#define NALL_INTERPOLATION_HPP
|
||||
|
||||
namespace nall {
|
||||
|
||||
struct Interpolation {
|
||||
static inline double Nearest(double mu, double a, double b, double c, double d) {
|
||||
return (mu < 0.5 ? c : d);
|
||||
}
|
||||
|
||||
static inline double Sublinear(double mu, double a, double b, double c, double d) {
|
||||
mu = ((mu - 0.5) * 2.0) + 0.5;
|
||||
if(mu < 0) mu = 0;
|
||||
if(mu > 1) mu = 1;
|
||||
return c * (1.0 - mu) + d * mu;
|
||||
}
|
||||
|
||||
static inline double Linear(double mu, double a, double b, double c, double d) {
|
||||
return c * (1.0 - mu) + d * mu;
|
||||
}
|
||||
|
||||
static inline double Cosine(double mu, double a, double b, double c, double d) {
|
||||
mu = (1.0 - cos(mu * 3.14159265)) / 2.0;
|
||||
return c * (1.0 - mu) + d * mu;
|
||||
}
|
||||
|
||||
static inline double Cubic(double mu, double a, double b, double c, double d) {
|
||||
double A = d - c - a + b;
|
||||
double B = a - b - A;
|
||||
double C = c - a;
|
||||
double D = b;
|
||||
return A * (mu * mu * mu) + B * (mu * mu) + C * mu + D;
|
||||
}
|
||||
|
||||
static inline double Hermite(double mu1, double a, double b, double c, double d) {
|
||||
const double tension = 0.0; //-1 = low, 0 = normal, +1 = high
|
||||
const double bias = 0.0; //-1 = left, 0 = even, +1 = right
|
||||
double mu2, mu3, m0, m1, a0, a1, a2, a3;
|
||||
|
||||
mu2 = mu1 * mu1;
|
||||
mu3 = mu2 * mu1;
|
||||
|
||||
m0 = (b - a) * (1.0 + bias) * (1.0 - tension) / 2.0;
|
||||
m0 += (c - b) * (1.0 - bias) * (1.0 - tension) / 2.0;
|
||||
m1 = (c - b) * (1.0 + bias) * (1.0 - tension) / 2.0;
|
||||
m1 += (d - c) * (1.0 - bias) * (1.0 - tension) / 2.0;
|
||||
|
||||
a0 = +2 * mu3 - 3 * mu2 + 1;
|
||||
a1 = mu3 - 2 * mu2 + mu1;
|
||||
a2 = mu3 - mu2;
|
||||
a3 = -2 * mu3 + 3 * mu2;
|
||||
|
||||
return (a0 * b) + (a1 * m0) + (a2 * m1) + (a3 * c);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
10
bsnes/nall/mosaic.hpp
Executable file
10
bsnes/nall/mosaic.hpp
Executable file
@@ -0,0 +1,10 @@
|
||||
#ifndef NALL_MOSAIC_HPP
|
||||
#define NALL_MOSAIC_HPP
|
||||
|
||||
#define NALL_MOSAIC_INTERNAL_HPP
|
||||
#include <nall/mosaic/bitstream.hpp>
|
||||
#include <nall/mosaic/context.hpp>
|
||||
#include <nall/mosaic/parser.hpp>
|
||||
#undef NALL_MOSAIC_INTERNAL_HPP
|
||||
|
||||
#endif
|
55
bsnes/nall/mosaic/bitstream.hpp
Executable file
55
bsnes/nall/mosaic/bitstream.hpp
Executable file
@@ -0,0 +1,55 @@
|
||||
#ifdef NALL_MOSAIC_INTERNAL_HPP
|
||||
|
||||
namespace nall {
|
||||
namespace mosaic {
|
||||
|
||||
struct bitstream {
|
||||
filemap fp;
|
||||
uint8_t *data;
|
||||
unsigned size;
|
||||
bool readonly;
|
||||
bool endian;
|
||||
|
||||
inline bool read(uint64_t addr) const {
|
||||
if(data == nullptr || (addr >> 3) >= size) return 0;
|
||||
unsigned mask = endian == 0 ? (0x01 << (addr & 7)) : (0x80 >> (addr & 7));
|
||||
return data[addr >> 3] & mask;
|
||||
}
|
||||
|
||||
inline void write(uint64_t addr, bool value) {
|
||||
if(data == nullptr || readonly == true || (addr >> 3) >= size) return;
|
||||
unsigned mask = endian == 0 ? (0x01 << (addr & 7)) : (0x80 >> (addr & 7));
|
||||
if(value == 0) data[addr >> 3] &= ~mask;
|
||||
if(value == 1) data[addr >> 3] |= mask;
|
||||
}
|
||||
|
||||
inline bool open(const string &filename) {
|
||||
readonly = false;
|
||||
if(fp.open(filename, filemap::mode::readwrite) == false) {
|
||||
readonly = true;
|
||||
if(fp.open(filename, filemap::mode::read) == false) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
data = fp.data();
|
||||
size = fp.size();
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void close() {
|
||||
fp.close();
|
||||
data = nullptr;
|
||||
}
|
||||
|
||||
inline bitstream() : data(nullptr), endian(1) {
|
||||
}
|
||||
|
||||
inline ~bitstream() {
|
||||
close();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
224
bsnes/nall/mosaic/context.hpp
Executable file
224
bsnes/nall/mosaic/context.hpp
Executable file
@@ -0,0 +1,224 @@
|
||||
#ifdef NALL_MOSAIC_INTERNAL_HPP
|
||||
|
||||
namespace nall {
|
||||
namespace mosaic {
|
||||
|
||||
struct context {
|
||||
unsigned offset;
|
||||
unsigned width;
|
||||
unsigned height;
|
||||
unsigned count;
|
||||
|
||||
bool endian; //0 = lsb, 1 = msb
|
||||
bool order; //0 = linear, 1 = planar
|
||||
unsigned depth; //1 - 24bpp
|
||||
|
||||
unsigned blockWidth;
|
||||
unsigned blockHeight;
|
||||
unsigned blockStride;
|
||||
unsigned blockOffset;
|
||||
array<unsigned> block;
|
||||
|
||||
unsigned tileWidth;
|
||||
unsigned tileHeight;
|
||||
unsigned tileStride;
|
||||
unsigned tileOffset;
|
||||
array<unsigned> tile;
|
||||
|
||||
unsigned mosaicWidth;
|
||||
unsigned mosaicHeight;
|
||||
unsigned mosaicStride;
|
||||
unsigned mosaicOffset;
|
||||
array<unsigned> mosaic;
|
||||
|
||||
unsigned paddingWidth;
|
||||
unsigned paddingHeight;
|
||||
unsigned paddingColor;
|
||||
array<unsigned> palette;
|
||||
|
||||
inline unsigned objectWidth() const { return blockWidth * tileWidth * mosaicWidth + paddingWidth; }
|
||||
inline unsigned objectHeight() const { return blockHeight * tileHeight * mosaicHeight + paddingHeight; }
|
||||
inline unsigned objectSize() const {
|
||||
unsigned size = blockStride * tileWidth * tileHeight * mosaicWidth * mosaicHeight
|
||||
+ blockOffset * tileHeight * mosaicWidth * mosaicHeight
|
||||
+ tileStride * mosaicWidth * mosaicHeight
|
||||
+ tileOffset * mosaicHeight;
|
||||
return max(1u, size);
|
||||
}
|
||||
|
||||
inline unsigned eval(const string &expression) {
|
||||
intmax_t result;
|
||||
if(fixedpoint::eval(expression, result) == false) return 0u;
|
||||
return result;
|
||||
}
|
||||
|
||||
inline void eval(array<unsigned> &buffer, const string &expression_) {
|
||||
string expression = expression_;
|
||||
bool function = false;
|
||||
for(auto &c : expression) {
|
||||
if(c == '(') function = true;
|
||||
if(c == ')') function = false;
|
||||
if(c == ',' && function == true) c = ';';
|
||||
}
|
||||
|
||||
lstring list = expression.split(",");
|
||||
for(auto &item : list) {
|
||||
item.trim();
|
||||
if(item.wildcard("f(?*) ?*")) {
|
||||
item.ltrim<1>("f(");
|
||||
lstring part = item.split<1>(") ");
|
||||
lstring args = part[0].split<3>(";");
|
||||
for(auto &item : args) item.trim();
|
||||
|
||||
unsigned length = eval(args(0, "0"));
|
||||
unsigned offset = eval(args(1, "0"));
|
||||
unsigned stride = eval(args(2, "0"));
|
||||
if(args.size() < 2) offset = buffer.size();
|
||||
if(args.size() < 3) stride = 1;
|
||||
|
||||
for(unsigned n = 0; n < length; n++) {
|
||||
string fn = part[1];
|
||||
fn.replace("n", decimal(n));
|
||||
fn.replace("o", decimal(offset));
|
||||
fn.replace("p", decimal(buffer.size()));
|
||||
buffer.resize(offset + 1);
|
||||
buffer[offset] = eval(fn);
|
||||
offset += stride;
|
||||
}
|
||||
} else if(item.wildcard("base64*")) {
|
||||
unsigned offset = 0;
|
||||
item.ltrim<1>("base64");
|
||||
if(item.wildcard("(?*) *")) {
|
||||
item.ltrim<1>("(");
|
||||
lstring part = item.split<1>(") ");
|
||||
offset = eval(part[0]);
|
||||
item = part(1, "");
|
||||
}
|
||||
item.trim();
|
||||
for(auto &c : item) {
|
||||
if(c >= 'A' && c <= 'Z') buffer.append(offset + c - 'A' + 0);
|
||||
if(c >= 'a' && c <= 'z') buffer.append(offset + c - 'a' + 26);
|
||||
if(c >= '0' && c <= '9') buffer.append(offset + c - '0' + 52);
|
||||
if(c == '-') buffer.append(offset + 62);
|
||||
if(c == '_') buffer.append(offset + 63);
|
||||
}
|
||||
} else if(item.wildcard("file *")) {
|
||||
item.ltrim<1>("file ");
|
||||
item.trim();
|
||||
//...
|
||||
} else if(item.empty() == false) {
|
||||
buffer.append(eval(item));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void parse(const string &data) {
|
||||
reset();
|
||||
|
||||
lstring lines = data.split("\n");
|
||||
for(auto &line : lines) {
|
||||
lstring part = line.split<1>(":");
|
||||
if(part.size() != 2) continue;
|
||||
part[0].trim();
|
||||
part[1].trim();
|
||||
|
||||
if(part[0] == "offset") offset = eval(part[1]);
|
||||
if(part[0] == "width") width = eval(part[1]);
|
||||
if(part[0] == "height") height = eval(part[1]);
|
||||
if(part[0] == "count") count = eval(part[1]);
|
||||
|
||||
if(part[0] == "endian") endian = eval(part[1]);
|
||||
if(part[0] == "order") order = eval(part[1]);
|
||||
if(part[0] == "depth") depth = eval(part[1]);
|
||||
|
||||
if(part[0] == "blockWidth") blockWidth = eval(part[1]);
|
||||
if(part[0] == "blockHeight") blockHeight = eval(part[1]);
|
||||
if(part[0] == "blockStride") blockStride = eval(part[1]);
|
||||
if(part[0] == "blockOffset") blockOffset = eval(part[1]);
|
||||
if(part[0] == "block") eval(block, part[1]);
|
||||
|
||||
if(part[0] == "tileWidth") tileWidth = eval(part[1]);
|
||||
if(part[0] == "tileHeight") tileHeight = eval(part[1]);
|
||||
if(part[0] == "tileStride") tileStride = eval(part[1]);
|
||||
if(part[0] == "tileOffset") tileOffset = eval(part[1]);
|
||||
if(part[0] == "tile") eval(tile, part[1]);
|
||||
|
||||
if(part[0] == "mosaicWidth") mosaicWidth = eval(part[1]);
|
||||
if(part[0] == "mosaicHeight") mosaicHeight = eval(part[1]);
|
||||
if(part[0] == "mosaicStride") mosaicStride = eval(part[1]);
|
||||
if(part[0] == "mosaicOffset") mosaicOffset = eval(part[1]);
|
||||
if(part[0] == "mosaic") eval(mosaic, part[1]);
|
||||
|
||||
if(part[0] == "paddingWidth") paddingWidth = eval(part[1]);
|
||||
if(part[0] == "paddingHeight") paddingHeight = eval(part[1]);
|
||||
if(part[0] == "paddingColor") paddingColor = eval(part[1]);
|
||||
if(part[0] == "palette") eval(palette, part[1]);
|
||||
}
|
||||
|
||||
sanitize();
|
||||
}
|
||||
|
||||
inline bool load(const string &filename) {
|
||||
string filedata;
|
||||
if(filedata.readfile(filename) == false) return false;
|
||||
parse(filedata);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void sanitize() {
|
||||
if(depth < 1) depth = 1;
|
||||
if(depth > 24) depth = 24;
|
||||
|
||||
if(blockWidth < 1) blockWidth = 1;
|
||||
if(blockHeight < 1) blockHeight = 1;
|
||||
|
||||
if(tileWidth < 1) tileWidth = 1;
|
||||
if(tileHeight < 1) tileHeight = 1;
|
||||
|
||||
if(mosaicWidth < 1) mosaicWidth = 1;
|
||||
if(mosaicHeight < 1) mosaicHeight = 1;
|
||||
}
|
||||
|
||||
inline void reset() {
|
||||
offset = 0;
|
||||
width = 0;
|
||||
height = 0;
|
||||
count = 0;
|
||||
|
||||
endian = 1;
|
||||
order = 0;
|
||||
depth = 1;
|
||||
|
||||
blockWidth = 1;
|
||||
blockHeight = 1;
|
||||
blockStride = 0;
|
||||
blockOffset = 0;
|
||||
block.reset();
|
||||
|
||||
tileWidth = 1;
|
||||
tileHeight = 1;
|
||||
tileStride = 0;
|
||||
tileOffset = 0;
|
||||
tile.reset();
|
||||
|
||||
mosaicWidth = 1;
|
||||
mosaicHeight = 1;
|
||||
mosaicStride = 0;
|
||||
mosaicOffset = 0;
|
||||
mosaic.reset();
|
||||
|
||||
paddingWidth = 0;
|
||||
paddingHeight = 0;
|
||||
paddingColor = 0x000000;
|
||||
palette.reset();
|
||||
}
|
||||
|
||||
inline context() {
|
||||
reset();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
126
bsnes/nall/mosaic/parser.hpp
Executable file
126
bsnes/nall/mosaic/parser.hpp
Executable file
@@ -0,0 +1,126 @@
|
||||
#ifdef NALL_MOSAIC_INTERNAL_HPP
|
||||
|
||||
namespace nall {
|
||||
namespace mosaic {
|
||||
|
||||
struct parser {
|
||||
image canvas;
|
||||
|
||||
//export from bitstream to canvas
|
||||
inline void load(bitstream &stream, uint64_t offset, context &ctx, unsigned width, unsigned height) {
|
||||
canvas.allocate(width, height);
|
||||
canvas.clear(ctx.paddingColor);
|
||||
parse(1, stream, offset, ctx, width, height);
|
||||
}
|
||||
|
||||
//import from canvas to bitstream
|
||||
inline bool save(bitstream &stream, uint64_t offset, context &ctx) {
|
||||
if(stream.readonly) return false;
|
||||
parse(0, stream, offset, ctx, canvas.width, canvas.height);
|
||||
return true;
|
||||
}
|
||||
|
||||
inline parser() : canvas(0, 32, 0u, 255u << 16, 255u << 8, 255u << 0) {
|
||||
}
|
||||
|
||||
private:
|
||||
inline uint32_t read(unsigned x, unsigned y) const {
|
||||
unsigned addr = y * canvas.width + x;
|
||||
if(addr >= canvas.width * canvas.height) return 0u;
|
||||
uint32_t *buffer = (uint32_t*)canvas.data;
|
||||
return buffer[addr];
|
||||
}
|
||||
|
||||
inline void write(unsigned x, unsigned y, uint32_t data) {
|
||||
unsigned addr = y * canvas.width + x;
|
||||
if(addr >= canvas.width * canvas.height) return;
|
||||
uint32_t *buffer = (uint32_t*)canvas.data;
|
||||
buffer[addr] = data;
|
||||
}
|
||||
|
||||
inline void parse(bool load, bitstream &stream, uint64_t offset, context &ctx, unsigned width, unsigned height) {
|
||||
stream.endian = ctx.endian;
|
||||
unsigned canvasWidth = width / (ctx.mosaicWidth * ctx.tileWidth * ctx.blockWidth + ctx.paddingWidth);
|
||||
unsigned canvasHeight = height / (ctx.mosaicHeight * ctx.tileHeight * ctx.blockHeight + ctx.paddingHeight);
|
||||
unsigned bitsPerBlock = ctx.depth * ctx.blockWidth * ctx.blockHeight;
|
||||
|
||||
unsigned objectOffset = 0;
|
||||
for(unsigned objectY = 0; objectY < canvasHeight; objectY++) {
|
||||
for(unsigned objectX = 0; objectX < canvasWidth; objectX++) {
|
||||
if(objectOffset >= ctx.count && ctx.count > 0) break;
|
||||
unsigned objectIX = objectX * ctx.objectWidth();
|
||||
unsigned objectIY = objectY * ctx.objectHeight();
|
||||
objectOffset++;
|
||||
|
||||
unsigned mosaicOffset = 0;
|
||||
for(unsigned mosaicY = 0; mosaicY < ctx.mosaicHeight; mosaicY++) {
|
||||
for(unsigned mosaicX = 0; mosaicX < ctx.mosaicWidth; mosaicX++) {
|
||||
unsigned mosaicData = ctx.mosaic(mosaicOffset, mosaicOffset);
|
||||
unsigned mosaicIX = (mosaicData % ctx.mosaicWidth) * (ctx.tileWidth * ctx.blockWidth);
|
||||
unsigned mosaicIY = (mosaicData / ctx.mosaicWidth) * (ctx.tileHeight * ctx.blockHeight);
|
||||
mosaicOffset++;
|
||||
|
||||
unsigned tileOffset = 0;
|
||||
for(unsigned tileY = 0; tileY < ctx.tileHeight; tileY++) {
|
||||
for(unsigned tileX = 0; tileX < ctx.tileWidth; tileX++) {
|
||||
unsigned tileData = ctx.tile(tileOffset, tileOffset);
|
||||
unsigned tileIX = (tileData % ctx.tileWidth) * ctx.blockWidth;
|
||||
unsigned tileIY = (tileData / ctx.tileWidth) * ctx.blockHeight;
|
||||
tileOffset++;
|
||||
|
||||
unsigned blockOffset = 0;
|
||||
for(unsigned blockY = 0; blockY < ctx.blockHeight; blockY++) {
|
||||
for(unsigned blockX = 0; blockX < ctx.blockWidth; blockX++) {
|
||||
if(load) {
|
||||
unsigned palette = 0;
|
||||
for(unsigned n = 0; n < ctx.depth; n++) {
|
||||
unsigned index = blockOffset++;
|
||||
if(ctx.order == 1) index = (index % ctx.depth) * ctx.blockWidth * ctx.blockHeight + (index / ctx.depth);
|
||||
palette |= stream.read(offset + ctx.block(index, index)) << n;
|
||||
}
|
||||
|
||||
write(
|
||||
objectIX + mosaicIX + tileIX + blockX,
|
||||
objectIY + mosaicIY + tileIY + blockY,
|
||||
ctx.palette(palette, palette)
|
||||
);
|
||||
} else /* save */ {
|
||||
uint32_t palette = read(
|
||||
objectIX + mosaicIX + tileIX + blockX,
|
||||
objectIY + mosaicIY + tileIY + blockY
|
||||
);
|
||||
|
||||
for(unsigned n = 0; n < ctx.depth; n++) {
|
||||
unsigned index = blockOffset++;
|
||||
if(ctx.order == 1) index = (index % ctx.depth) * ctx.blockWidth * ctx.blockHeight + (index / ctx.depth);
|
||||
stream.write(offset + ctx.block(index, index), palette & 1);
|
||||
palette >>= 1;
|
||||
}
|
||||
}
|
||||
} //blockX
|
||||
} //blockY
|
||||
|
||||
offset += ctx.blockStride;
|
||||
} //tileX
|
||||
|
||||
offset += ctx.blockOffset;
|
||||
} //tileY
|
||||
|
||||
offset += ctx.tileStride;
|
||||
} //mosaicX
|
||||
|
||||
offset += ctx.tileOffset;
|
||||
} //mosaicY
|
||||
|
||||
offset += ctx.mosaicStride;
|
||||
} //objectX
|
||||
|
||||
offset += ctx.mosaicOffset;
|
||||
} //objectY
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
@@ -10,9 +10,12 @@
|
||||
namespace nall {
|
||||
|
||||
struct png {
|
||||
uint32_t *data;
|
||||
unsigned size;
|
||||
|
||||
//colorType:
|
||||
//0 = L
|
||||
//2 = R,G,B
|
||||
//3 = P
|
||||
//4 = L,A
|
||||
//6 = R,G,B,A
|
||||
struct Info {
|
||||
unsigned width;
|
||||
unsigned height;
|
||||
@@ -28,13 +31,14 @@ struct png {
|
||||
uint8_t palette[256][3];
|
||||
} info;
|
||||
|
||||
uint8_t *rawData;
|
||||
unsigned rawSize;
|
||||
uint8_t *data;
|
||||
unsigned size;
|
||||
|
||||
inline bool decode(const string &filename);
|
||||
inline bool decode(const uint8_t *sourceData, unsigned sourceSize);
|
||||
inline void transform();
|
||||
inline void alphaTransform(uint32_t rgb = 0xffffff);
|
||||
inline unsigned readbits(const uint8_t *&data);
|
||||
unsigned bitpos;
|
||||
|
||||
inline png();
|
||||
inline ~png();
|
||||
|
||||
@@ -46,16 +50,11 @@ protected:
|
||||
IEND = 0x49454e44,
|
||||
};
|
||||
|
||||
unsigned bitpos;
|
||||
|
||||
inline unsigned interlace(unsigned pass, unsigned index);
|
||||
inline unsigned inflateSize();
|
||||
inline bool deinterlace(const uint8_t *&inputData, unsigned pass);
|
||||
inline bool filter(uint8_t *outputData, const uint8_t *inputData, unsigned width, unsigned height);
|
||||
inline unsigned read(const uint8_t *data, unsigned length);
|
||||
inline unsigned decode(const uint8_t *&data);
|
||||
inline unsigned readbits(const uint8_t *&data);
|
||||
inline unsigned scale(unsigned n);
|
||||
};
|
||||
|
||||
bool png::decode(const string &filename) {
|
||||
@@ -146,14 +145,14 @@ bool png::decode(const uint8_t *sourceData, unsigned sourceSize) {
|
||||
return false;
|
||||
}
|
||||
|
||||
rawSize = info.width * info.height * info.bytesPerPixel;
|
||||
rawData = new uint8_t[rawSize];
|
||||
size = info.width * info.height * info.bytesPerPixel;
|
||||
data = new uint8_t[size];
|
||||
|
||||
if(info.interlaceMethod == 0) {
|
||||
if(filter(rawData, interlacedData, info.width, info.height) == false) {
|
||||
if(filter(data, interlacedData, info.width, info.height) == false) {
|
||||
delete[] interlacedData;
|
||||
delete[] rawData;
|
||||
rawData = 0;
|
||||
delete[] data;
|
||||
data = 0;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
@@ -161,8 +160,8 @@ bool png::decode(const uint8_t *sourceData, unsigned sourceSize) {
|
||||
for(unsigned pass = 0; pass < 7; pass++) {
|
||||
if(deinterlace(passData, pass) == false) {
|
||||
delete[] interlacedData;
|
||||
delete[] rawData;
|
||||
rawData = 0;
|
||||
delete[] data;
|
||||
data = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -216,7 +215,7 @@ bool png::deinterlace(const uint8_t *&inputData, unsigned pass) {
|
||||
|
||||
const uint8_t *rd = outputData;
|
||||
for(unsigned y = yo; y < info.height; y += yd) {
|
||||
uint8_t *wr = rawData + y * info.pitch;
|
||||
uint8_t *wr = data + y * info.pitch;
|
||||
for(unsigned x = xo; x < info.width; x += xd) {
|
||||
for(unsigned b = 0; b < info.bytesPerPixel; b++) {
|
||||
wr[x * info.bytesPerPixel + b] = *rd++;
|
||||
@@ -298,42 +297,6 @@ unsigned png::read(const uint8_t *data, unsigned length) {
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned png::decode(const uint8_t *&data) {
|
||||
unsigned p, r, g, b, a;
|
||||
|
||||
switch(info.colorType) {
|
||||
case 0: //L
|
||||
r = g = b = scale(readbits(data));
|
||||
a = 0xff;
|
||||
break;
|
||||
case 2: //R,G,B
|
||||
r = scale(readbits(data));
|
||||
g = scale(readbits(data));
|
||||
b = scale(readbits(data));
|
||||
a = 0xff;
|
||||
break;
|
||||
case 3: //P
|
||||
p = readbits(data);
|
||||
r = info.palette[p][0];
|
||||
g = info.palette[p][1];
|
||||
b = info.palette[p][2];
|
||||
a = 0xff;
|
||||
break;
|
||||
case 4: //L,A
|
||||
r = g = b = scale(readbits(data));
|
||||
a = scale(readbits(data));
|
||||
break;
|
||||
case 6: //R,G,B,A
|
||||
r = scale(readbits(data));
|
||||
g = scale(readbits(data));
|
||||
b = scale(readbits(data));
|
||||
a = scale(readbits(data));
|
||||
break;
|
||||
}
|
||||
|
||||
return (a << 24) | (r << 16) | (g << 8) | (b << 0);
|
||||
}
|
||||
|
||||
unsigned png::readbits(const uint8_t *&data) {
|
||||
unsigned result = 0;
|
||||
switch(info.bitDepth) {
|
||||
@@ -363,62 +326,12 @@ unsigned png::readbits(const uint8_t *&data) {
|
||||
return result;
|
||||
}
|
||||
|
||||
unsigned png::scale(unsigned n) {
|
||||
switch(info.bitDepth) {
|
||||
case 1: return n ? 0xff : 0x00;
|
||||
case 2: return n * 0x55;
|
||||
case 4: return n * 0x11;
|
||||
case 8: return n;
|
||||
case 16: return n >> 8;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void png::transform() {
|
||||
if(data) delete[] data;
|
||||
data = new uint32_t[info.width * info.height];
|
||||
|
||||
png::png() : data(nullptr) {
|
||||
bitpos = 0;
|
||||
const uint8_t *rd = rawData;
|
||||
for(unsigned y = 0; y < info.height; y++) {
|
||||
uint32_t *wr = data + y * info.width;
|
||||
for(unsigned x = 0; x < info.width; x++) {
|
||||
wr[x] = decode(rd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void png::alphaTransform(uint32_t rgb) {
|
||||
transform();
|
||||
|
||||
uint8_t ir = rgb >> 16;
|
||||
uint8_t ig = rgb >> 8;
|
||||
uint8_t ib = rgb >> 0;
|
||||
|
||||
uint32_t *p = data;
|
||||
for(unsigned y = 0; y < info.height; y++) {
|
||||
for(unsigned x = 0; x < info.width; x++) {
|
||||
uint32_t pixel = *p;
|
||||
uint8_t a = pixel >> 24;
|
||||
uint8_t r = pixel >> 16;
|
||||
uint8_t g = pixel >> 8;
|
||||
uint8_t b = pixel >> 0;
|
||||
|
||||
r = (r * a) + (ir * (255 - a)) >> 8;
|
||||
g = (g * a) + (ig * (255 - a)) >> 8;
|
||||
b = (b * a) + (ib * (255 - a)) >> 8;
|
||||
|
||||
*p++ = (255 << 24) | (r << 16) | (g << 8) | (b << 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
png::png() : data(nullptr), rawData(nullptr) {
|
||||
}
|
||||
|
||||
png::~png() {
|
||||
if(data) delete[] data;
|
||||
if(rawData) delete[] rawData;
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -105,345 +105,438 @@ public:
|
||||
bool has_st018;
|
||||
};
|
||||
|
||||
#define T "\t"
|
||||
|
||||
SnesCartridge::SnesCartridge(const uint8_t *data, unsigned size) {
|
||||
read_header(data, size);
|
||||
|
||||
string xml;
|
||||
markup = "";
|
||||
markup = "<?xml version='1.0' encoding='UTF-8'?>\n";
|
||||
|
||||
if(type == TypeBsx) {
|
||||
markup.append("cartridge");
|
||||
markup.append("<cartridge/>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if(type == TypeSufamiTurbo) {
|
||||
markup.append("cartridge");
|
||||
markup.append("<cartridge/>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if(type == TypeGameBoy) {
|
||||
markup.append("cartridge rtc=", gameboy_has_rtc(data, size), "\n");
|
||||
markup.append("<cartridge rtc='", gameboy_has_rtc(data, size), "'\n");
|
||||
if(gameboy_ram_size(data, size) > 0) {
|
||||
markup.append(T "ram size=0x", hex(gameboy_ram_size(data, size)), "\n");
|
||||
markup.append(" <ram size='0x", hex(gameboy_ram_size(data, size)), "'>\n");
|
||||
}
|
||||
markup.append("</cartridge>\n");
|
||||
return;
|
||||
}
|
||||
|
||||
markup.append("cartridge region=", region == NTSC ? "NTSC\n" : "PAL\n");
|
||||
const char *range = (rom_size > 0x200000) || (ram_size > 32 * 1024) ? "0000-7fff" : "0000-ffff";
|
||||
markup.append("<cartridge region='", region == NTSC ? "NTSC" : "PAL", "'>\n");
|
||||
|
||||
if(type == TypeSuperGameBoy1Bios) {
|
||||
markup.append(T "rom\n");
|
||||
markup.append(T T "map mode=linear address=00-7f:8000-ffff\n");
|
||||
markup.append(T T "map mode=linear address=80-ff:8000-ffff\n");
|
||||
markup.append(T "icd2 revision=1\n");
|
||||
markup.append(T T "map address=00-3f:6000-7fff\n");
|
||||
markup.append(T T "map address=80-bf:6000-7fff\n");
|
||||
} else if(type == TypeSuperGameBoy2Bios) {
|
||||
markup.append(T "rom\n");
|
||||
markup.append(T T "map mode=linear address=00-7f:8000-ffff\n");
|
||||
markup.append(T T "map mode=linear address=80-ff:8000-ffff\n");
|
||||
markup.append(T "icd2 revision=1\n");
|
||||
markup.append(T T "map address=00-3f:6000-7fff\n");
|
||||
markup.append(T T "map address=80-bf:6000-7fff\n");
|
||||
} else if(has_cx4) {
|
||||
markup.append(T "hitachidsp model=HG51B169 frequency=20000000 firmware=cx4.bin sha256=ae8d4d1961b93421ff00b3caa1d0f0ce7783e749772a3369c36b3dbf0d37ef18\n");
|
||||
markup.append(T T "rom\n");
|
||||
markup.append(T T T "map mode=linear address=00-7f:8000-ffff\n");
|
||||
markup.append(T T T "map mode=linear address=80-ff:8000-ffff\n");
|
||||
markup.append(T T "mmio\n");
|
||||
markup.append(T T T "map address=00-3f:6000-7fff\n");
|
||||
markup.append(T T T "map address=80-bf:6000-7fff\n");
|
||||
} else if(has_spc7110) {
|
||||
markup.append(T "rom\n");
|
||||
markup.append(T T "map mode=shadow address=00-0f:8000-ffff\n");
|
||||
markup.append(T T "map mode=shadow address=80-bf:8000-ffff\n");
|
||||
markup.append(T T "map mode=linear address=c0-cf:0000-ffff\n");
|
||||
if(type == TypeSuperGameBoy1Bios || type == TypeSuperGameBoy2Bios) markup.append(
|
||||
" <rom>\n"
|
||||
" <map mode='linear' address='00-7f:8000-ffff'/>\n"
|
||||
" <map mode='linear' address='80-ff:8000-ffff'/>\n"
|
||||
" </rom>\n"
|
||||
" <icd2 revision='1'>\n"
|
||||
" <map address='00-3f:6000-7fff'/>\n"
|
||||
" <map address='80-bf:6000-7fff'/>\n"
|
||||
" </icd2>\n"
|
||||
);
|
||||
|
||||
markup.append(T "spc7110\n");
|
||||
markup.append(T T "mcu\n");
|
||||
markup.append(T T T "map address=d0-ff:0000-ffff offset=0x100000 size=0x", hex(size - 0x100000), "\n");
|
||||
markup.append(T T "ram size=0x", hex(ram_size), "\n");
|
||||
markup.append(T T T "map mode=linear address=00:6000-7fff\n");
|
||||
markup.append(T T T "map mode=linear address=30:6000-7fff\n");
|
||||
markup.append(T T "mmio\n");
|
||||
markup.append(T T T "map address=00-3f:4800-483f\n");
|
||||
markup.append(T T T "map address=80-bf:4800-483f\n");
|
||||
if(has_spc7110rtc) {
|
||||
markup.append(T T "rtc\n");
|
||||
markup.append(T T T "map address=00-3f:4840-4842\n");
|
||||
markup.append(T T T "map address=80-bf:4840-4842\n");
|
||||
}
|
||||
markup.append(T T "dcu\n");
|
||||
markup.append(T T T "map address=50:0000-ffff\n");
|
||||
} else if(mapper == LoROM) {
|
||||
markup.append(T "rom\n");
|
||||
markup.append(T T "map mode=linear address=00-7f:8000-ffff\n");
|
||||
markup.append(T T "map mode=linear address=80-ff:8000-ffff\n");
|
||||
else if(has_cx4) markup.append(
|
||||
" <hitachidsp model='HG51B169' frequency='20000000' firmware='cx4.bin' sha256='ae8d4d1961b93421ff00b3caa1d0f0ce7783e749772a3369c36b3dbf0d37ef18'>\n"
|
||||
" <rom>\n"
|
||||
" <map mode='linear' address='00-7f:8000-ffff'/>\n"
|
||||
" <map mode='linear' address='80-ff:8000-ffff'/>\n"
|
||||
" </rom>\n"
|
||||
" <mmio>\n"
|
||||
" <map address='00-3f:6000-7fff'/>\n"
|
||||
" <map address='80-bf:6000-7fff'/>\n"
|
||||
" </mmio>\n"
|
||||
" </hitachidsp>\n"
|
||||
);
|
||||
|
||||
if(ram_size > 0) {
|
||||
markup.append(T "ram size=0x", hex(ram_size), "\n");
|
||||
markup.append(T T "map mode=linear address=20-3f:6000-7fff\n");
|
||||
markup.append(T T "map mode=linear address=a0-bf:6000-7fff\n");
|
||||
if((rom_size > 0x200000) || (ram_size > 32 * 1024)) {
|
||||
markup.append(T T "map mode=linear address=70-7f:0000-7fff\n");
|
||||
markup.append(T T "map mode=linear address=f0-ff:0000-7fff\n");
|
||||
} else {
|
||||
markup.append(T T "map mode=linear address=70-7f:0000-ffff\n");
|
||||
markup.append(T T "map mode=linear address=f0-ff:0000-ffff\n");
|
||||
}
|
||||
}
|
||||
} else if(mapper == HiROM) {
|
||||
markup.append(T "rom\n");
|
||||
markup.append(T T "map mode=shadow address=00-3f:8000-ffff\n");
|
||||
markup.append(T T "map mode=linear address=40-7f:0000-ffff\n");
|
||||
markup.append(T T "map mode=shadow address=80-bf:8000-ffff\n");
|
||||
markup.append(T T "map mode=linear address=c0-ff:0000-ffff\n");
|
||||
|
||||
if(ram_size > 0) {
|
||||
markup.append(T "ram size=0x", hex(ram_size), "\n");
|
||||
markup.append(T T "map mode=linear address=20-3f:6000-7fff\n");
|
||||
markup.append(T T "map mode=linear address=a0-bf:6000-7fff\n");
|
||||
if((rom_size > 0x200000) || (ram_size > 32 * 1024)) {
|
||||
markup.append(T T "map mode=linear address=70-7f:0000-7fff\n");
|
||||
} else {
|
||||
markup.append(T T "map mode=linear address=70-7f:0000-ffff\n");
|
||||
}
|
||||
}
|
||||
} else if(mapper == ExLoROM) {
|
||||
markup.append(T "rom\n");
|
||||
markup.append(T T "map mode=linear address=00-3f:8000-ffff\n");
|
||||
markup.append(T T "map mode=linear address=40-7f:0000-ffff\n");
|
||||
markup.append(T T "map mode=linear address=80-bf:8000-ffff\n");
|
||||
|
||||
if(ram_size > 0) {
|
||||
markup.append(T "ram size=0x", hex(ram_size), "\n");
|
||||
markup.append(T T "map mode=linear address=20-3f:6000-7fff\n");
|
||||
markup.append(T T "map mode=linear address=a0-bf:6000-7fff\n");
|
||||
markup.append(T T "map mode=linear address=70-7f:0000-7fff\n");
|
||||
}
|
||||
} else if(mapper == ExHiROM) {
|
||||
markup.append(T "rom\n");
|
||||
markup.append(T T "map mode=shadow address=00-3f:8000-ffff offset=0x400000\n");
|
||||
markup.append(T T "map mode=linear address=40-7f:0000-ffff offset=0x400000\n");
|
||||
markup.append(T T "map mode=shadow address=80-bf:8000-ffff offset=0x000000\n");
|
||||
markup.append(T T "map mode=linear address=c0-ff:0000-ffff offset=0x000000\n");
|
||||
|
||||
if(ram_size > 0) {
|
||||
markup.append(T "ram size=0x", hex(ram_size), "\n");
|
||||
markup.append(T T "map mode=linear address=20-3f:6000-7fff\n");
|
||||
markup.append(T T "map mode=linear address=a0-bf:6000-7fff\n");
|
||||
if((rom_size > 0x200000) || (ram_size > 32 * 1024)) {
|
||||
markup.append(T T "map mode=linear address=70-7f:0000-7fff\n");
|
||||
} else {
|
||||
markup.append(T T "map mode=linear address=70-7f:0000-ffff\n");
|
||||
}
|
||||
}
|
||||
} else if(mapper == SuperFXROM) {
|
||||
markup.append(T "superfx revision=2\n");
|
||||
markup.append(T T "rom\n");
|
||||
markup.append(T T T "map mode=linear address=00-3f:8000-ffff\n");
|
||||
markup.append(T T T "map mode=linear address=40-5f:0000-ffff\n");
|
||||
markup.append(T T T "map mode=linear address=80-bf:8000-ffff\n");
|
||||
markup.append(T T T "map mode=linear address=c0-df:0000-ffff\n");
|
||||
markup.append(T T "ram size=0x", hex(ram_size), "\n");
|
||||
markup.append(T T T "map mode=linear address=00-3f:6000-7fff size=0x2000\n");
|
||||
markup.append(T T T "map mode=linear address=60-7f:0000-ffff\n");
|
||||
markup.append(T T T "map mode=linear address=80-bf:6000-7fff size=0x2000\n");
|
||||
markup.append(T T T "map mode=linear address=e0-ff:0000-ffff\n");
|
||||
markup.append(T T "mmio\n");
|
||||
markup.append(T T T "map address=00-3f:3000-32ff\n");
|
||||
markup.append(T T T "map address=80-bf:3000-32ff\n");
|
||||
} else if(mapper == SA1ROM) {
|
||||
markup.append(T "sa1\n");
|
||||
markup.append(T T "mcu\n");
|
||||
markup.append(T T T "rom\n");
|
||||
markup.append(T T T T "map mode=direct address=00-3f:8000-ffff\n");
|
||||
markup.append(T T T T "map mode=direct address=80-bf:8000-ffff\n");
|
||||
markup.append(T T T T "map mode=direct address=c0-ff:0000-ffff\n");
|
||||
markup.append(T T T "ram\n");
|
||||
markup.append(T T T T "map mode=direct address=00-3f:6000-7fff\n");
|
||||
markup.append(T T T T "map mode=direct address=80-bf:6000-7fff\n");
|
||||
markup.append(T T "iram size=0x800\n");
|
||||
markup.append(T T T "map mode=linear address=00-3f:3000-37ff\n");
|
||||
markup.append(T T T "map mode=linear address=80-bf:3000-37ff\n");
|
||||
markup.append(T T "bwram size=0x", hex(ram_size), "\n");
|
||||
markup.append(T T T "map mode=linear address=40-4f:0000-ffff\n");
|
||||
markup.append(T T "mmio\n");
|
||||
markup.append(T T T "map address=00-3f:2200-23ff\n");
|
||||
markup.append(T T T "map address=80-bf:2200-23ff\n");
|
||||
} else if(mapper == BSCLoROM) {
|
||||
markup.append(T "rom\n");
|
||||
markup.append(T T "map mode=linear address=00-1f:8000-ffff offset=0x000000\n");
|
||||
markup.append(T T "map mode=linear address=20-3f:8000-ffff offset=0x100000\n");
|
||||
markup.append(T T "map mode=linear address=80-9f:8000-ffff offset=0x200000\n");
|
||||
markup.append(T T "map mode=linear address=a0-bf:8000-ffff offset=0x100000\n");
|
||||
markup.append(T "ram size=0x", hex(ram_size), "\n");
|
||||
markup.append(T T "map mode=linear address=70-7f:0000-7fff\n");
|
||||
markup.append(T T "map mode=linear address=f0-ff:0000-7fff\n");
|
||||
markup.append(T "bsx\n");
|
||||
markup.append(T T "slot\n");
|
||||
markup.append(T T T "map mode=linear address=c0-ef:0000-ffff\n");
|
||||
} else if(mapper == BSCHiROM) {
|
||||
markup.append(T "rom\n");
|
||||
markup.append(T T "map mode=shadow address=00-1f:8000-ffff\n");
|
||||
markup.append(T T "map mode=linear address=40-5f:0000-ffff\n");
|
||||
markup.append(T T "map mode=shadow address=80-9f:8000-ffff\n");
|
||||
markup.append(T T "map mode=linear address=c0-df:0000-ffff\n");
|
||||
markup.append(T "ram size=0x", hex(ram_size), "\n");
|
||||
markup.append(T T "map mode=linear address=20-3f:6000-7fff\n");
|
||||
markup.append(T T "map mode=linear address=a0-bf:6000-7fff\n");
|
||||
markup.append(T "bsx\n");
|
||||
markup.append(T T "slot\n");
|
||||
markup.append(T T T "map mode=shadow address=20-3f:8000-ffff\n");
|
||||
markup.append(T T T "map mode=linear address=60-7f:0000-ffff\n");
|
||||
markup.append(T T T "map mode=shadow address=a0-bf:8000-ffff\n");
|
||||
markup.append(T T T "map mode=linear address=e0-ff:0000-ffff\n");
|
||||
} else if(mapper == BSXROM) {
|
||||
markup.append(T "bsx\n");
|
||||
markup.append(T T "mcu\n");
|
||||
markup.append(T T T "map address=00-3f:8000-ffff\n");
|
||||
markup.append(T T T "map address=80-bf:8000-ffff\n");
|
||||
markup.append(T T T "map address=40-7f:0000-ffff\n");
|
||||
markup.append(T T T "map address=c0-ff:0000-ffff\n");
|
||||
markup.append(T T T "map address=20-3f:6000-7fff\n");
|
||||
markup.append(T T "mmio\n");
|
||||
markup.append(T T T "map address=00-3f:5000-5fff\n");
|
||||
markup.append(T T T "map address=80-bf:5000-5fff\n");
|
||||
} else if(mapper == STROM) {
|
||||
markup.append(T "rom\n");
|
||||
markup.append(T T "map mode=linear address=00-1f:8000-ffff\n");
|
||||
markup.append(T T "map mode=linear address=80-9f:8000-ffff\n");
|
||||
markup.append(T "sufamiturbo\n");
|
||||
markup.append(T T "slot id=A\n");
|
||||
markup.append(T T T "rom\n");
|
||||
markup.append(T T T T "map mode=linear address=20-3f:8000-ffff\n");
|
||||
markup.append(T T T T "map mode=linear address=a0-bf:8000-ffff\n");
|
||||
markup.append(T T T "ram size=0x20000\n");
|
||||
markup.append(T T T T "map mode=linear address=60-63:8000-ffff\n");
|
||||
markup.append(T T T T "map mode=linear address=e0-e3:8000-ffff\n");
|
||||
markup.append(T T "slot id=B\n");
|
||||
markup.append(T T T "rom\n");
|
||||
markup.append(T T T T "map mode=linear address=40-5f:8000-ffff\n");
|
||||
markup.append(T T T T "map mode=linear address=c0-df:8000-ffff\n");
|
||||
markup.append(T T T "ram size=0x20000\n");
|
||||
markup.append(T T T T "map mode=linear address=70-73:8000-ffff\n");
|
||||
markup.append(T T T T "map mode=linear address=f0-f3:8000-ffff\n");
|
||||
else if(has_spc7110) {
|
||||
markup.append(
|
||||
" <rom>\n"
|
||||
" <map mode='shadow' address='00-0f:8000-ffff'/>\n"
|
||||
" <map mode='shadow' address='80-bf:8000-ffff'/>\n"
|
||||
" <map mode='linear' address='c0-cf:0000-ffff'/>\n"
|
||||
" </rom>\n"
|
||||
" <spc7110>\n"
|
||||
" <ram size='0x", hex(ram_size), "'>\n"
|
||||
" <map mode='linear' address='00:6000-7fff'/>\n"
|
||||
" <map mode='linear' address='30:6000-7fff'/>\n"
|
||||
" </ram>\n"
|
||||
" <mmio>\n"
|
||||
" <map address='00-3f:4800-483f'/>\n"
|
||||
" <map address='80-bf:4800-483f'/>\n"
|
||||
" </mmio>\n"
|
||||
" <mcu>\n"
|
||||
" <map address='d0-ff:0000-ffff' offset='0x100000' size='0x", hex(size - 0x100000), "'/>\n"
|
||||
" </mcu>\n"
|
||||
" <dcu>\n"
|
||||
" <map address='50:0000-ffff'/>\n"
|
||||
" </dcu>\n"
|
||||
);
|
||||
if(has_spc7110rtc) markup.append(
|
||||
" <rtc>\n"
|
||||
" <map address='00-3f:4840-4842'/>\n"
|
||||
" <map address='80-bf:4840-4842'/>\n"
|
||||
" </rtc>\n"
|
||||
);
|
||||
markup.append(
|
||||
" </spc7110>\n"
|
||||
);
|
||||
}
|
||||
|
||||
if(has_srtc) {
|
||||
markup.append(T "srtc\n");
|
||||
markup.append(T T "map address=00-3f:2800-2801\n");
|
||||
markup.append(T T "map address=80-bf:2800-2801\n");
|
||||
else if(mapper == LoROM) {
|
||||
markup.append(
|
||||
" <rom>\n"
|
||||
" <map mode='linear' address='00-7f:8000-ffff'/>\n"
|
||||
" <map mode='linear' address='80-ff:8000-ffff'/>\n"
|
||||
" </rom>\n"
|
||||
);
|
||||
if(ram_size > 0) markup.append(
|
||||
" <ram size='0x", hex(ram_size), "'>\n"
|
||||
" <map mode='linear' address='20-3f:6000-7fff'/>\n"
|
||||
" <map mode='linear' address='a0-bf:6000-7fff'/>\n"
|
||||
" <map mode='linear' address='70-7f:", range, "'/>\n"
|
||||
" <map mode='linear' address='f0-ff:", range, "'/>\n"
|
||||
" </ram>\n"
|
||||
);
|
||||
}
|
||||
|
||||
if(has_sdd1) {
|
||||
markup.append(T "sdd1\n");
|
||||
markup.append(T T "mcu\n");
|
||||
markup.append(T T T "map address=c0-ff:0000-ffff\n");
|
||||
markup.append(T T "mmio\n");
|
||||
markup.append(T T T "map address=00-3f:4800-4807\n");
|
||||
markup.append(T T T "map address=80-bf:4800-4807\n");
|
||||
else if(mapper == HiROM) {
|
||||
markup.append(
|
||||
" <rom>\n"
|
||||
" <map mode='shadow' address='00-3f:8000-ffff'/>\n"
|
||||
" <map mode='linear' address='40-7f:0000-ffff'/>\n"
|
||||
" <map mode='shadow' address='80-bf:8000-ffff'/>\n"
|
||||
" <map mode='linear' address='c0-ff:0000-ffff'/>\n"
|
||||
" </rom>\n"
|
||||
);
|
||||
if(ram_size > 0) markup.append(
|
||||
" <ram size='0x", hex(ram_size), "'>\n"
|
||||
" <map mode='linear' address='20-3f:6000-7fff'/>\n"
|
||||
" <map mode='linear' address='a0-bf:6000-7fff'/>\n"
|
||||
" <map mode='linear' address='70-7f:", range, "'/>\n"
|
||||
" </ram>\n"
|
||||
);
|
||||
}
|
||||
|
||||
else if(mapper == ExLoROM) {
|
||||
markup.append(
|
||||
" <rom>\n"
|
||||
" <map mode='linear' address='00-3f:8000-ffff'/>\n"
|
||||
" <map mode='linear' address='40-7f:0000-ffff'/>\n"
|
||||
" <map mode='linear' address='80-bf:8000-ffff'/>\n"
|
||||
" </rom>\n"
|
||||
);
|
||||
if(ram_size > 0) markup.append(
|
||||
" <ram size='0x", hex(ram_size), "'>\n"
|
||||
" <map mode='linear' address='20-3f:6000-7fff'/>\n"
|
||||
" <map mode='linear' address='a0-bf:6000-7fff'/>\n"
|
||||
" <map mode='linear' address='70-7f:0000-7fff'/>\n"
|
||||
" </ram>\n"
|
||||
);
|
||||
}
|
||||
|
||||
else if(mapper == ExHiROM) {
|
||||
markup.append(
|
||||
" <rom>\n"
|
||||
" <map mode='shadow' address='00-3f:8000-ffff' offset='0x400000'/>\n"
|
||||
" <map mode='linear' address='40-7f:0000-ffff' offset='0x400000'/>\n"
|
||||
" <map mode='shadow' address='80-bf:8000-ffff' offset='0x000000'/>\n"
|
||||
" <map mode='linear' address='c0-ff:0000-ffff' offset='0x000000'/>\n"
|
||||
" </rom>\n"
|
||||
);
|
||||
if(ram_size > 0) markup.append(
|
||||
" <ram size='0x", hex(ram_size), "'>\n"
|
||||
" <map mode='linear' address='20-3f:6000-7fff'/>\n"
|
||||
" <map mode='linear' address='a0-bf:6000-7fff'/>\n"
|
||||
" <map mode='linear' address='70-7f:", range, "'/>\n"
|
||||
" </ram>\n"
|
||||
);
|
||||
}
|
||||
|
||||
else if(mapper == SuperFXROM) markup.append(
|
||||
" <superfx revision='2'>\n"
|
||||
" <rom>\n"
|
||||
" <map mode='linear' address='00-3f:8000-ffff'/>\n"
|
||||
" <map mode='linear' address='40-5f:0000-ffff'/>\n"
|
||||
" <map mode='linear' address='80-bf:8000-ffff'/>\n"
|
||||
" <map mode='linear' address='c0-df:0000-ffff'/>\n"
|
||||
" </rom>\n"
|
||||
" <ram size='0x", hex(ram_size), "'>\n"
|
||||
" <map mode='linear' address='00-3f:6000-7fff' size='0x2000'/>\n"
|
||||
" <map mode='linear' address='60-7f:0000-ffff'/>\n"
|
||||
" <map mode='linear' address='80-bf:6000-7fff' size='0x2000'/>\n"
|
||||
" <map mode='linear' address='e0-ff:0000-ffff'/>\n"
|
||||
" </ram>\n"
|
||||
" <mmio>\n"
|
||||
" <map address='00-3f:3000-32ff'/>\n"
|
||||
" <map address='80-bf:3000-32ff'/>\n"
|
||||
" </mmio>\n"
|
||||
" </superfx>\n"
|
||||
);
|
||||
|
||||
else if(mapper == SA1ROM) markup.append(
|
||||
" <sa1>\n"
|
||||
" <mcu>\n"
|
||||
" <rom>\n"
|
||||
" <map mode='direct' address='00-3f:8000-ffff'/>\n"
|
||||
" <map mode='direct' address='80-bf:8000-ffff'/>\n"
|
||||
" <map mode='direct' address='c0-ff:0000-ffff'/>\n"
|
||||
" </rom>\n"
|
||||
" <ram>\n"
|
||||
" <map mode='direct' address='00-3f:6000-7fff'/>\n"
|
||||
" <map mode='direct' address='80-bf:6000-7fff'/>\n"
|
||||
" </ram>\n"
|
||||
" </mcu>\n"
|
||||
" <iram size='0x800'>\n"
|
||||
" <map mode='linear' address='00-3f:3000-37ff'/>\n"
|
||||
" <map mode='linear' address='80-bf:3000-37ff'/>\n"
|
||||
" </iram>\n"
|
||||
" <bwram size='0x", hex(ram_size), "'>\n"
|
||||
" <map mode='linear' address='40-4f:0000-ffff'/>\n"
|
||||
" </bwram>\n"
|
||||
" <mmio>\n"
|
||||
" <map address='00-3f:2200-23ff'/>\n"
|
||||
" <map address='80-bf:2200-23ff'/>\n"
|
||||
" </mmio>\n"
|
||||
" </sa1>\n"
|
||||
);
|
||||
|
||||
else if(mapper == BSCLoROM) markup.append(
|
||||
" <rom>\n"
|
||||
" <map mode='linear' address='00-1f:8000-ffff' offset='0x000000'/>\n"
|
||||
" <map mode='linear' address='20-3f:8000-ffff' offset='0x100000'/>\n"
|
||||
" <map mode='linear' address='80-9f:8000-ffff' offset='0x200000'/>\n"
|
||||
" <map mode='linear' address='a0-bf:8000-ffff' offset='0x100000'/>\n"
|
||||
" </rom>\n"
|
||||
" <ram size='0x", hex(ram_size), "'>\n"
|
||||
" <map mode='linear' address='70-7f:0000-7fff'/>\n"
|
||||
" <map mode='linear' address='f0-ff:0000-7fff'/>\n"
|
||||
" </ram>\n"
|
||||
" <bsx>\n"
|
||||
" <slot>\n"
|
||||
" <map mode='linear' address='c0-ef:0000-ffff'/>\n"
|
||||
" </slot>\n"
|
||||
" </bsx>\n"
|
||||
);
|
||||
|
||||
else if(mapper == BSCHiROM) markup.append(
|
||||
" <rom>\n"
|
||||
" <map mode='shadow' address='00-1f:8000-ffff'/>\n"
|
||||
" <map mode='linear' address='40-5f:0000-ffff'/>\n"
|
||||
" <map mode='shadow' address='80-9f:8000-ffff'/>\n"
|
||||
" <map mode='linear' address='c0-df:0000-ffff'/>\n"
|
||||
" </rom>\n"
|
||||
" <ram size='0x", hex(ram_size), "'>\n"
|
||||
" <map mode='linear' address='20-3f:6000-7fff'/>\n"
|
||||
" <map mode='linear' address='a0-bf:6000-7fff'/>\n"
|
||||
" </ram>\n"
|
||||
" <bsx>\n"
|
||||
" <slot>\n"
|
||||
" <map mode='shadow' address='20-3f:8000-ffff'/>\n"
|
||||
" <map mode='linear' address='60-7f:0000-ffff'/>\n"
|
||||
" <map mode='shadow' address='a0-bf:8000-ffff'/>\n"
|
||||
" <map mode='linear' address='e0-ff:0000-ffff'/>\n"
|
||||
" </slot>\n"
|
||||
" </bsx>\n"
|
||||
);
|
||||
|
||||
else if(mapper == BSXROM) markup.append(
|
||||
" <bsx>\n"
|
||||
" <mcu>\n"
|
||||
" <map address='00-3f:8000-ffff'/>\n"
|
||||
" <map address='80-bf:8000-ffff'/>\n"
|
||||
" <map address='40-7f:0000-ffff'/>\n"
|
||||
" <map address='c0-ff:0000-ffff'/>\n"
|
||||
" <map address='20-3f:6000-7fff'/>\n"
|
||||
" </mcu>\n"
|
||||
" <mmio>\n"
|
||||
" <map address='00-3f:5000-5fff'/>\n"
|
||||
" <map address='80-bf:5000-5fff'/>\n"
|
||||
" </mmio>\n"
|
||||
" </bsx>\n"
|
||||
);
|
||||
|
||||
else if(mapper == STROM) markup.append(
|
||||
" <rom>\n"
|
||||
" <map mode='linear' address='00-1f:8000-ffff'/>\n"
|
||||
" <map mode='linear' address='80-9f:8000-ffff'/>\n"
|
||||
" </rom>\n"
|
||||
" <sufamiturbo>\n"
|
||||
" <slot id='A'>\n"
|
||||
" <rom>\n"
|
||||
" <map mode='linear' address='20-3f:8000-ffff'/>\n"
|
||||
" <map mode='linear' address='a0-bf:8000-ffff'/>\n"
|
||||
" </rom>\n"
|
||||
" <ram size='0x20000'>\n"
|
||||
" <map mode='linear' address='60-63:8000-ffff'/>\n"
|
||||
" <map mode='linear' address='e0-e3:8000-ffff'/>\n"
|
||||
" </ram>\n"
|
||||
" </slot>\n"
|
||||
" <slot id='B'>\n"
|
||||
" <rom>\n"
|
||||
" <map mode='linear' address='40-5f:8000-ffff'/>\n"
|
||||
" <map mode='linear' address='c0-df:8000-ffff'/>\n"
|
||||
" </rom>\n"
|
||||
" <ram size='0x20000'>\n"
|
||||
" <map mode='linear' address='70-73:8000-ffff'/>\n"
|
||||
" <map mode='linear' address='f0-f3:8000-ffff'/>\n"
|
||||
" </ram>\n"
|
||||
" </slot>\n"
|
||||
" </sufamiturbo>\n"
|
||||
);
|
||||
|
||||
if(has_srtc) markup.append(
|
||||
" <srtc>\n"
|
||||
" <map address='00-3f:2800-2801'/>\n"
|
||||
" <map address='80-bf:2800-2801'/>\n"
|
||||
" </srtc>\n"
|
||||
);
|
||||
|
||||
if(has_sdd1) markup.append(
|
||||
" <sdd1>\n"
|
||||
" <mcu>\n"
|
||||
" <map address='c0-ff:0000-ffff'/>\n"
|
||||
" </mcu>\n"
|
||||
" <mmio>\n"
|
||||
" <map address='00-3f:4800-4807'/>\n"
|
||||
" <map address='80-bf:4800-4807'/>\n"
|
||||
" </mmio>\n"
|
||||
" </sdd1>\n"
|
||||
);
|
||||
|
||||
if(has_obc1) markup.append(
|
||||
" <obc1>\n"
|
||||
" <map address='00-3f:6000-7fff'/>\n"
|
||||
" <map address='80-bf:6000-7fff'/>\n"
|
||||
" </obc1>\n"
|
||||
);
|
||||
|
||||
if(has_dsp1) {
|
||||
markup.append(T "necdsp model=uPD7725 frequency=8000000 firmware=dsp1b.bin sha256=4d42db0f36faef263d6b93f508e8c1c4ae8fc2605fd35e3390ecc02905cd420c\n");
|
||||
if(dsp1_mapper == DSP1LoROM1MB) {
|
||||
markup.append(T T "dr\n");
|
||||
markup.append(T T T "map address=20-3f:8000-bfff\n");
|
||||
markup.append(T T T "map address=a0-bf:8000-bfff\n");
|
||||
markup.append(T T "sr\n");
|
||||
markup.append(T T T "map address=20-3f:c000-ffff\n");
|
||||
markup.append(T T T "map address=a0-bf:c000-ffff\n");
|
||||
} else if(dsp1_mapper == DSP1LoROM2MB) {
|
||||
markup.append(T T "dr\n");
|
||||
markup.append(T T T "map address=60-6f:0000-3fff\n");
|
||||
markup.append(T T T "map address=e0-ef:0000-3fff\n");
|
||||
markup.append(T T "sr\n");
|
||||
markup.append(T T T "map address=60-6f:4000-7fff\n");
|
||||
markup.append(T T T "map address=e0-ef:4000-7fff\n");
|
||||
} else if(dsp1_mapper == DSP1HiROM) {
|
||||
markup.append(T T "dr\n");
|
||||
markup.append(T T T "map address=00-1f:6000-6fff\n");
|
||||
markup.append(T T T "map address=80-9f:6000-6fff\n");
|
||||
markup.append(T T "sr\n");
|
||||
markup.append(T T T "map address=00-1f:7000-7fff\n");
|
||||
markup.append(T T T "map address=80-9f:7000-7fff\n");
|
||||
}
|
||||
markup.append(" <necdsp model='uPD7725' frequency='8000000' firmware='dsp1b.bin' sha256='4d42db0f36faef263d6b93f508e8c1c4ae8fc2605fd35e3390ecc02905cd420c'>\n");
|
||||
if(dsp1_mapper == DSP1LoROM1MB) markup.append(
|
||||
" <dr>\n"
|
||||
" <map address='20-3f:8000-bfff'/>\n"
|
||||
" <map address='a0-bf:8000-bfff'/>\n"
|
||||
" </dr>\n"
|
||||
" <sr>\n"
|
||||
" <map address='20-3f:c000-ffff'/>\n"
|
||||
" <map address='a0-bf:c000-ffff'/>\n"
|
||||
" </sr>\n"
|
||||
);
|
||||
if(dsp1_mapper == DSP1LoROM2MB) markup.append(
|
||||
" <dr>\n"
|
||||
" <map address='60-6f:0000-3fff'/>\n"
|
||||
" <map address='e0-ef:0000-3fff'/>\n"
|
||||
" </dr>\n"
|
||||
" <sr>\n"
|
||||
" <map address='60-6f:4000-7fff'/>\n"
|
||||
" <map address='e0-ef:4000-7fff'/>\n"
|
||||
" </sr>\n"
|
||||
);
|
||||
if(dsp1_mapper == DSP1HiROM) markup.append(
|
||||
" <dr>\n"
|
||||
" <map address='00-1f:6000-6fff'/>\n"
|
||||
" <map address='80-9f:6000-6fff'/>\n"
|
||||
" </dr>\n"
|
||||
" <sr>\n"
|
||||
" <map address='00-1f:7000-7fff'/>\n"
|
||||
" <map address='80-9f:7000-7fff'/>\n"
|
||||
" </sr>\n"
|
||||
);
|
||||
markup.append(" </necdsp>\n");
|
||||
}
|
||||
|
||||
if(has_dsp2) {
|
||||
markup.append(T "necdsp model=uPD7725 frequency=8000000 firmware=dsp2.bin sha256=5efbdf96ed0652790855225964f3e90e6a4d466cfa64df25b110933c6cf94ea1\n");
|
||||
markup.append(T T "dr\n");
|
||||
markup.append(T T T "map address=20-3f:8000-bfff\n");
|
||||
markup.append(T T T "map address=a0-bf:8000-bfff\n");
|
||||
markup.append(T T "sr\n");
|
||||
markup.append(T T T "map address=20-3f:c000-ffff\n");
|
||||
markup.append(T T T "map address=a0-bf:c000-ffff\n");
|
||||
}
|
||||
if(has_dsp2) markup.append(
|
||||
" <necdsp model='uPD7725' frequency='8000000' firmware='dsp2.bin' sha256='5efbdf96ed0652790855225964f3e90e6a4d466cfa64df25b110933c6cf94ea1'>\n"
|
||||
" <dr>\n"
|
||||
" <map address='20-3f:8000-bfff'/>\n"
|
||||
" <map address='a0-bf:8000-bfff'/>\n"
|
||||
" </dr>\n"
|
||||
" <sr>\n"
|
||||
" <map address='20-3f:c000-ffff'/>\n"
|
||||
" <map address='a0-bf:c000-ffff'/>\n"
|
||||
" </sr>\n"
|
||||
" </necdsp>\n"
|
||||
);
|
||||
|
||||
if(has_dsp3) {
|
||||
markup.append(T "necdsp model=uPD7725 frequency=8000000 firmware=dsp3.bin sha256=2e635f72e4d4681148bc35429421c9b946e4f407590e74e31b93b8987b63ba90\n");
|
||||
markup.append(T T "dr\n");
|
||||
markup.append(T T T "map address=20-3f:8000-bfff\n");
|
||||
markup.append(T T T "map address=a0-bf:8000-bfff\n");
|
||||
markup.append(T T "sr\n");
|
||||
markup.append(T T T "map address=20-3f:c000-ffff\n");
|
||||
markup.append(T T T "map address=a0-bf:c000-ffff\n");
|
||||
}
|
||||
if(has_dsp3) markup.append(
|
||||
" <necdsp model='uPD7725' frequency='8000000' firmware='dsp3.bin' sha256='2e635f72e4d4681148bc35429421c9b946e4f407590e74e31b93b8987b63ba90'>\n"
|
||||
" <dr>\n"
|
||||
" <map address='20-3f:8000-bfff'/>\n"
|
||||
" <map address='a0-bf:8000-bfff'/>\n"
|
||||
" </dr>\n"
|
||||
" <sr>\n"
|
||||
" <map address='20-3f:c000-ffff'/>\n"
|
||||
" <map address='a0-bf:c000-ffff'/>\n"
|
||||
" </sr>\n"
|
||||
" </necdsp>\n"
|
||||
);
|
||||
|
||||
if(has_dsp4) {
|
||||
markup.append(T "necdsp model=uPD7725 frequency=8000000 firmware=dsp4.bin sha256=63ede17322541c191ed1fdf683872554a0a57306496afc43c59de7c01a6e764a\n");
|
||||
markup.append(T T "dr\n");
|
||||
markup.append(T T T "map address=30-3f:8000-bfff\n");
|
||||
markup.append(T T T "map address=b0-bf:8000-bfff\n");
|
||||
markup.append(T T "sr\n");
|
||||
markup.append(T T T "map address=30-3f:c000-ffff\n");
|
||||
markup.append(T T T "map address=b0-bf:c000-ffff\n");
|
||||
}
|
||||
if(has_dsp4) markup.append(
|
||||
" <necdsp model='uPD7725' frequency='8000000' firmware='dsp4.bin' sha256='63ede17322541c191ed1fdf683872554a0a57306496afc43c59de7c01a6e764a'>\n"
|
||||
" <dr>\n"
|
||||
" <map address='30-3f:8000-bfff'/>\n"
|
||||
" <map address='b0-bf:8000-bfff'/>\n"
|
||||
" </dr>\n"
|
||||
" <sr>\n"
|
||||
" <map address='30-3f:c000-ffff'/>\n"
|
||||
" <map address='b0-bf:c000-ffff'/>\n"
|
||||
" </sr>\n"
|
||||
" </necdsp>\n"
|
||||
);
|
||||
|
||||
if(has_obc1) {
|
||||
markup.append(T "obc1\n");
|
||||
markup.append(T T "map address=00-3f:6000-7fff\n");
|
||||
markup.append(T T "map address=80-bf:6000-7fff\n");
|
||||
}
|
||||
if(has_st010) markup.append(
|
||||
" <necdsp model='uPD96050' frequency='10000000' firmware='st0010.bin' sha256='55c697e864562445621cdf8a7bf6e84ae91361e393d382a3704e9aa55559041e'>\n"
|
||||
" <dr>\n"
|
||||
" <map address='60:0000'/>\n"
|
||||
" <map address='e0:0000'/>\n"
|
||||
" </dr>\n"
|
||||
" <sr>\n"
|
||||
" <map address='60:0001'/>\n"
|
||||
" <map address='e0:0001'/>\n"
|
||||
" </sr>\n"
|
||||
" <dp>\n"
|
||||
" <map address='68-6f:0000-0fff'/>\n"
|
||||
" <map address='e8-ef:0000-0fff'/>\n"
|
||||
" </dp>\n"
|
||||
" </necdsp>\n"
|
||||
);
|
||||
|
||||
if(has_st010) {
|
||||
markup.append(T "necdsp model=uPD96050 frequency=10000000 firmware=st0010.bin sha256=55c697e864562445621cdf8a7bf6e84ae91361e393d382a3704e9aa55559041e\n");
|
||||
markup.append(T T "dr\n");
|
||||
markup.append(T T T "map address=60:0000\n");
|
||||
markup.append(T T T "map address=e0:0000\n");
|
||||
markup.append(T T "sr\n");
|
||||
markup.append(T T T "map address=60:0001\n");
|
||||
markup.append(T T T "map address=e0:0001\n");
|
||||
markup.append(T T "dp\n");
|
||||
markup.append(T T T "map address=68-6f:0000-0fff\n");
|
||||
markup.append(T T T "map address=e8-ef:0000-0fff\n");
|
||||
}
|
||||
if(has_st011) markup.append(
|
||||
" <necdsp model='uPD96050' frequency='15000000' firmware='st0011.bin' sha256='651b82a1e26c4fa8dd549e91e7f923012ed2ca54c1d9fd858655ab30679c2f0e'>\n"
|
||||
" <dr>\n"
|
||||
" <map address='60:0000'/>\n"
|
||||
" <map address='e0:0000'/>\n"
|
||||
" </dr>\n"
|
||||
" <sr>\n"
|
||||
" <map address='60:0001'/>\n"
|
||||
" <map address='e0:0001'/>\n"
|
||||
" </sr>\n"
|
||||
" <dp>\n"
|
||||
" <map address='68-6f:0000-0fff'/>\n"
|
||||
" <map address='e8-ef:0000-0fff'/>\n"
|
||||
" </dp>\n"
|
||||
" </necdsp>\n"
|
||||
);
|
||||
|
||||
if(has_st011) {
|
||||
markup.append(T "necdsp model=uPD96050 frequency=15000000 firmware=st0011.bin sha256=651b82a1e26c4fa8dd549e91e7f923012ed2ca54c1d9fd858655ab30679c2f0e\n");
|
||||
markup.append(T T "dr\n");
|
||||
markup.append(T T T "map address=60:0000\n");
|
||||
markup.append(T T T "map address=e0:0000\n");
|
||||
markup.append(T T "sr\n");
|
||||
markup.append(T T T "map address=60:0001\n");
|
||||
markup.append(T T T "map address=e0:0001\n");
|
||||
markup.append(T T "dp\n");
|
||||
markup.append(T T T "map address=68-6f:0000-0fff\n");
|
||||
markup.append(T T T "map address=e8-ef:0000-0fff\n");
|
||||
}
|
||||
if(has_st018) markup.append(
|
||||
" <setarisc firmware='ST-0018'>\n"
|
||||
" <map address='00-3f:3800-38ff'/>\n"
|
||||
" <map address='80-bf:3800-38ff'/>\n"
|
||||
" </setarisc>\n"
|
||||
);
|
||||
|
||||
if(has_st018) {
|
||||
markup.append(T "setarisc firmware=ST-0018\n");
|
||||
markup.append(T T "map address=00-3f:3800-38ff\n");
|
||||
markup.append(T T "map address=80-bf:3800-38ff\n");
|
||||
}
|
||||
markup.append("</cartridge>\n");
|
||||
}
|
||||
|
||||
#undef T
|
||||
|
||||
void SnesCartridge::read_header(const uint8_t *data, unsigned size) {
|
||||
type = TypeUnknown;
|
||||
mapper = LoROM;
|
||||
|
@@ -16,6 +16,7 @@
|
||||
#include <nall/sha256.hpp>
|
||||
#include <nall/stdint.hpp>
|
||||
#include <nall/utility.hpp>
|
||||
#include <nall/varint.hpp>
|
||||
#include <nall/vector.hpp>
|
||||
|
||||
#include <nall/windows/utf8.hpp>
|
||||
@@ -31,6 +32,8 @@
|
||||
#include <nall/string/cstring.hpp>
|
||||
#include <nall/string/filename.hpp>
|
||||
#include <nall/string/math.hpp>
|
||||
#include <nall/string/math-fixed-point.hpp>
|
||||
#include <nall/string/math-floating-point.hpp>
|
||||
#include <nall/string/platform.hpp>
|
||||
#include <nall/string/strl.hpp>
|
||||
#include <nall/string/strpos.hpp>
|
||||
@@ -39,8 +42,10 @@
|
||||
#include <nall/string/split.hpp>
|
||||
#include <nall/string/utility.hpp>
|
||||
#include <nall/string/variadic.hpp>
|
||||
#include <nall/string/wildcard.hpp>
|
||||
#include <nall/string/wrapper.hpp>
|
||||
#include <nall/string/xml.hpp>
|
||||
#include <nall/string/xml-legacy.hpp>
|
||||
#undef NALL_STRING_INTERNAL_HPP
|
||||
|
||||
#endif
|
||||
|
@@ -23,6 +23,7 @@ namespace nall {
|
||||
|
||||
struct string {
|
||||
inline void reserve(unsigned);
|
||||
inline bool empty() const;
|
||||
|
||||
template<typename... Args> inline string& assign(Args&&... args);
|
||||
template<typename... Args> inline string& append(Args&&... args);
|
||||
@@ -35,6 +36,7 @@ namespace nall {
|
||||
template<unsigned Limit = 0> inline string& iqreplace(const char*, const char*);
|
||||
|
||||
inline unsigned length() const;
|
||||
inline unsigned capacity() const;
|
||||
|
||||
template<unsigned Limit = 0> inline lstring split(const char*) const;
|
||||
template<unsigned Limit = 0> inline lstring isplit(const char*) const;
|
||||
@@ -128,8 +130,6 @@ namespace nall {
|
||||
inline char chrlower(char c);
|
||||
inline char chrupper(char c);
|
||||
inline int istrcmp(const char *str1, const char *str2);
|
||||
inline bool wildcard(const char *str, const char *pattern);
|
||||
inline bool iwildcard(const char *str, const char *pattern);
|
||||
inline bool strbegin(const char *str, const char *key);
|
||||
inline bool istrbegin(const char *str, const char *key);
|
||||
inline bool strend(const char *str, const char *key);
|
||||
@@ -185,11 +185,15 @@ namespace nall {
|
||||
template<unsigned length = 0, char padding = ' '> inline string ldecimal(uintmax_t value);
|
||||
template<unsigned length = 0, char padding = '0'> inline string hex(uintmax_t value);
|
||||
template<unsigned length = 0, char padding = '0'> inline string binary(uintmax_t value);
|
||||
inline unsigned fp(char *str, double value);
|
||||
inline string fp(double value);
|
||||
inline unsigned fp(char *str, long double value);
|
||||
inline string fp(long double value);
|
||||
|
||||
//variadic.hpp
|
||||
template<typename... Args> inline void print(Args&&... args);
|
||||
|
||||
//wildcard.hpp
|
||||
inline bool wildcard(const char *str, const char *pattern);
|
||||
inline bool iwildcard(const char *str, const char *pattern);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@@ -2,39 +2,184 @@
|
||||
|
||||
namespace nall {
|
||||
|
||||
//this is needed, as C++0x does not support explicit template specialization inside classes
|
||||
template<> inline const char* to_string<bool>(bool v) { return v ? "true" : "false"; }
|
||||
template<> inline const char* to_string<char>(char v) { static char temp[256]; return integer(temp, v); }
|
||||
//convert any (supported) type to a const char* without constructing a new nall::string
|
||||
//this is used inside istring(...) to build nall::string values
|
||||
template<typename T> struct stringify;
|
||||
|
||||
template<> inline const char* to_string<signed char> (signed char v) { static char temp[256]; return integer(temp, v); }
|
||||
template<> inline const char* to_string<signed short> (signed short v) { static char temp[256]; return integer(temp, v); }
|
||||
template<> inline const char* to_string<signed int> (signed int v) { static char temp[256]; return integer(temp, v); }
|
||||
template<> inline const char* to_string<signed long> (signed long v) { static char temp[256]; return integer(temp, v); }
|
||||
template<> inline const char* to_string<signed long long>(signed long long v) { static char temp[256]; return integer(temp, v); }
|
||||
// base types
|
||||
|
||||
template<> inline const char* to_string<unsigned char> (unsigned char v) { static char temp[256]; return decimal(temp, v); }
|
||||
template<> inline const char* to_string<unsigned short> (unsigned short v) { static char temp[256]; return decimal(temp, v); }
|
||||
template<> inline const char* to_string<unsigned int> (unsigned int v) { static char temp[256]; return decimal(temp, v); }
|
||||
template<> inline const char* to_string<unsigned long> (unsigned long v) { static char temp[256]; return decimal(temp, v); }
|
||||
template<> inline const char* to_string<unsigned long long>(unsigned long long v) { static char temp[256]; return decimal(temp, v); }
|
||||
template<> struct stringify<bool> {
|
||||
bool value;
|
||||
operator const char*() const { return value ? "true" : "false"; }
|
||||
stringify(bool value) : value(value) {}
|
||||
};
|
||||
|
||||
template<> inline const char* to_string<float> (float v) { static char temp[256]; snprintf(temp, 255, "%f", v); return temp; }
|
||||
template<> inline const char* to_string<double> (double v) { static char temp[256]; snprintf(temp, 255, "%f", v); return temp; }
|
||||
template<> inline const char* to_string<long double>(long double v) { static char temp[256]; snprintf(temp, 255, "%Lf", v); return temp; }
|
||||
template<> struct stringify<char> {
|
||||
char data[256];
|
||||
operator const char*() const { return data; }
|
||||
stringify(char value) { integer(data, value); }
|
||||
};
|
||||
|
||||
template<> inline const char* to_string<char*> (char *v) { return v; }
|
||||
template<> inline const char* to_string<const char*> (const char *v) { return v; }
|
||||
template<> inline const char* to_string<string> (string v) { return v; }
|
||||
template<> inline const char* to_string<const string&> (const string &v) { return v; }
|
||||
template<> inline const char* to_string<cstring> (cstring v) { return v; }
|
||||
template<> inline const char* to_string<const cstring&>(const cstring &v) { return v; }
|
||||
// signed integers
|
||||
|
||||
template<> struct stringify<signed char> {
|
||||
char data[256];
|
||||
operator const char*() const { return data; }
|
||||
stringify(signed char value) { integer(data, value); }
|
||||
};
|
||||
|
||||
template<> struct stringify<signed short> {
|
||||
char data[256];
|
||||
operator const char*() const { return data; }
|
||||
stringify(signed short value) { integer(data, value); }
|
||||
};
|
||||
|
||||
template<> struct stringify<signed int> {
|
||||
char data[256];
|
||||
operator const char*() const { return data; }
|
||||
stringify(signed int value) { integer(data, value); }
|
||||
};
|
||||
|
||||
template<> struct stringify<signed long> {
|
||||
char data[256];
|
||||
operator const char*() const { return data; }
|
||||
stringify(signed long value) { integer(data, value); }
|
||||
};
|
||||
|
||||
template<> struct stringify<signed long long> {
|
||||
char data[256];
|
||||
operator const char*() const { return data; }
|
||||
stringify(signed long long value) { integer(data, value); }
|
||||
};
|
||||
|
||||
template<unsigned bits> struct stringify<int_t<bits>> {
|
||||
char data[256];
|
||||
operator const char*() const { return data; }
|
||||
stringify(int_t<bits> value) { integer(data, value); }
|
||||
};
|
||||
|
||||
// unsigned integers
|
||||
|
||||
template<> struct stringify<unsigned char> {
|
||||
char data[256];
|
||||
operator const char*() const { return data; }
|
||||
stringify(unsigned char value) { decimal(data, value); }
|
||||
};
|
||||
|
||||
template<> struct stringify<unsigned short> {
|
||||
char data[256];
|
||||
operator const char*() const { return data; }
|
||||
stringify(unsigned short value) { decimal(data, value); }
|
||||
};
|
||||
|
||||
template<> struct stringify<unsigned int> {
|
||||
char data[256];
|
||||
operator const char*() const { return data; }
|
||||
stringify(unsigned int value) { decimal(data, value); }
|
||||
};
|
||||
|
||||
template<> struct stringify<unsigned long> {
|
||||
char data[256];
|
||||
operator const char*() const { return data; }
|
||||
stringify(unsigned long value) { decimal(data, value); }
|
||||
};
|
||||
|
||||
template<> struct stringify<unsigned long long> {
|
||||
char data[256];
|
||||
operator const char*() const { return data; }
|
||||
stringify(unsigned long long value) { decimal(data, value); }
|
||||
};
|
||||
|
||||
template<unsigned bits> struct stringify<uint_t<bits>> {
|
||||
char data[256];
|
||||
operator const char*() const { return data; }
|
||||
stringify(uint_t<bits> value) { decimal(data, value); }
|
||||
};
|
||||
|
||||
// floating-point
|
||||
|
||||
template<> struct stringify<float> {
|
||||
char data[256];
|
||||
operator const char*() const { return data; }
|
||||
stringify(float value) { fp(data, value); }
|
||||
};
|
||||
|
||||
template<> struct stringify<double> {
|
||||
char data[256];
|
||||
operator const char*() const { return data; }
|
||||
stringify(double value) { fp(data, value); }
|
||||
};
|
||||
|
||||
template<> struct stringify<long double> {
|
||||
char data[256];
|
||||
operator const char*() const { return data; }
|
||||
stringify(long double value) { fp(data, value); }
|
||||
};
|
||||
|
||||
// strings
|
||||
|
||||
template<> struct stringify<char*> {
|
||||
const char *value;
|
||||
operator const char*() const { return value; }
|
||||
stringify(char *value) : value(value) {}
|
||||
};
|
||||
|
||||
template<> struct stringify<const char*> {
|
||||
const char *value;
|
||||
operator const char*() const { return value; }
|
||||
stringify(const char *value) : value(value) {}
|
||||
};
|
||||
|
||||
template<> struct stringify<string> {
|
||||
const string &value;
|
||||
operator const char*() const { return value; }
|
||||
stringify(const string &value) : value(value) {}
|
||||
};
|
||||
|
||||
template<> struct stringify<const string&> {
|
||||
const string &value;
|
||||
operator const char*() const { return value; }
|
||||
stringify(const string &value) : value(value) {}
|
||||
};
|
||||
|
||||
template<> struct stringify<cstring> {
|
||||
const char *value;
|
||||
operator const char*() const { return value; }
|
||||
stringify(const cstring &value) : value(value) {}
|
||||
};
|
||||
|
||||
template<> struct stringify<const cstring&> {
|
||||
const char *value;
|
||||
operator const char*() const { return value; }
|
||||
stringify(const cstring &value) : value(value) {}
|
||||
};
|
||||
|
||||
#if defined(QSTRING_H)
|
||||
template<> inline const char* to_string<QString>(QString v) { return v.toUtf8().constData(); }
|
||||
template<> inline const char* to_string<const QString&>(const QString &v) { return v.toUtf8().constData(); }
|
||||
string::operator QString() const { return QString::fromUtf8(*this); }
|
||||
|
||||
template<> struct stringify<QString> {
|
||||
const QString &value;
|
||||
operator const char*() const { return value.toUtf8().constData(); }
|
||||
stringify(const QString &value) : value(value) {}
|
||||
};
|
||||
|
||||
template<> struct stringify<const QString&> {
|
||||
const QString &value;
|
||||
operator const char*() const { return value.toUtf8().constData(); }
|
||||
stringify(const QString &value) : value(value) {}
|
||||
};
|
||||
|
||||
string::operator QString() const {
|
||||
return QString::fromUtf8(*this);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//
|
||||
|
||||
template<typename T> stringify<T> make_string(T value) {
|
||||
return stringify<T>(std::forward<T>(value));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -18,46 +18,6 @@ int istrcmp(const char *str1, const char *str2) {
|
||||
return (int)chrlower(*str1) - (int)chrlower(*str2);
|
||||
}
|
||||
|
||||
bool wildcard(const char *s, const char *p) {
|
||||
const char *cp = 0, *mp = 0;
|
||||
while(*s && *p != '*') {
|
||||
if(*p != '?' && *s != *p) return false;
|
||||
p++, s++;
|
||||
}
|
||||
while(*s) {
|
||||
if(*p == '*') {
|
||||
if(!*++p) return true;
|
||||
mp = p, cp = s + 1;
|
||||
} else if(*p == '?' || *p == *s) {
|
||||
p++, s++;
|
||||
} else {
|
||||
p = mp, s = cp++;
|
||||
}
|
||||
}
|
||||
while(*p == '*') p++;
|
||||
return !*p;
|
||||
}
|
||||
|
||||
bool iwildcard(const char *s, const char *p) {
|
||||
const char *cp = 0, *mp = 0;
|
||||
while(*s && *p != '*') {
|
||||
if(*p != '?' && chrlower(*s) != chrlower(*p)) return false;
|
||||
p++, s++;
|
||||
}
|
||||
while(*s) {
|
||||
if(*p == '*') {
|
||||
if(!*++p) return true;
|
||||
mp = p, cp = s + 1;
|
||||
} else if(*p == '?' || chrlower(*p) == chrlower(*s)) {
|
||||
p++, s++;
|
||||
} else {
|
||||
p = mp, s = cp++;
|
||||
}
|
||||
}
|
||||
while(*p == '*') p++;
|
||||
return !*p;
|
||||
}
|
||||
|
||||
bool strbegin(const char *str, const char *key) {
|
||||
int i, ssl = strlen(str), ksl = strlen(key);
|
||||
|
||||
|
@@ -7,7 +7,7 @@ static void istring(string &output) {
|
||||
|
||||
template<typename T, typename... Args>
|
||||
static void istring(string &output, const T &value, Args&&... args) {
|
||||
output.append_(to_string(value));
|
||||
output.append_(make_string(value));
|
||||
istring(output, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,10 @@ void string::reserve(unsigned size_) {
|
||||
}
|
||||
}
|
||||
|
||||
bool string::empty() const {
|
||||
return !*data;
|
||||
}
|
||||
|
||||
template<typename... Args> string& string::assign(Args&&... args) {
|
||||
*data = 0;
|
||||
istring(*this, std::forward<Args>(args)...);
|
||||
|
166
bsnes/nall/string/math-fixed-point.hpp
Executable file
166
bsnes/nall/string/math-fixed-point.hpp
Executable file
@@ -0,0 +1,166 @@
|
||||
#ifdef NALL_STRING_INTERNAL_HPP
|
||||
|
||||
namespace fixedpoint {
|
||||
|
||||
static nall::function<intmax_t (const char *&)> eval_fallback;
|
||||
|
||||
static intmax_t eval_integer(const char *& s) {
|
||||
if(!*s) throw "unrecognized integer";
|
||||
intmax_t value = 0, x = *s, y = *(s + 1);
|
||||
|
||||
//hexadecimal
|
||||
if(x == '0' && (y == 'X' || y == 'x')) {
|
||||
s += 2;
|
||||
while(true) {
|
||||
if(*s >= '0' && *s <= '9') { value = value * 16 + (*s++ - '0'); continue; }
|
||||
if(*s >= 'A' && *s <= 'F') { value = value * 16 + (*s++ - 'A' + 10); continue; }
|
||||
if(*s >= 'a' && *s <= 'f') { value = value * 16 + (*s++ - 'a' + 10); continue; }
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
//binary
|
||||
if(x == '0' && (y == 'B' || y == 'b')) {
|
||||
s += 2;
|
||||
while(true) {
|
||||
if(*s == '0' || *s == '1') { value = value * 2 + (*s++ - '0'); continue; }
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
//octal (or decimal '0')
|
||||
if(x == '0') {
|
||||
s += 1;
|
||||
while(true) {
|
||||
if(*s >= '0' && *s <= '7') { value = value * 8 + (*s++ - '0'); continue; }
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
//decimal
|
||||
if(x >= '0' && x <= '9') {
|
||||
while(true) {
|
||||
if(*s >= '0' && *s <= '9') { value = value * 10 + (*s++ - '0'); continue; }
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
//char
|
||||
if(x == '\'' && y != '\'') {
|
||||
s += 1;
|
||||
while(true) {
|
||||
value = value * 256 + *s++;
|
||||
if(*s == '\'') { s += 1; return value; }
|
||||
if(!*s) throw "mismatched char";
|
||||
}
|
||||
}
|
||||
|
||||
throw "unrecognized integer";
|
||||
}
|
||||
|
||||
static intmax_t eval(const char *&s, int depth = 0) {
|
||||
while(*s == ' ' || *s == '\t') s++; //trim whitespace
|
||||
if(!*s) throw "unrecognized token";
|
||||
intmax_t value = 0, x = *s, y = *(s + 1);
|
||||
|
||||
if(*s == '(') {
|
||||
value = eval(++s, 1);
|
||||
if(*s++ != ')') throw "mismatched group";
|
||||
}
|
||||
|
||||
else if(x == '!') value = !eval(++s, 13);
|
||||
else if(x == '~') value = ~eval(++s, 13);
|
||||
else if(x == '+') value = +eval(++s, 13);
|
||||
else if(x == '-') value = -eval(++s, 13);
|
||||
|
||||
else if((x >= '0' && x <= '9') || x == '\'') value = eval_integer(s);
|
||||
|
||||
else if(eval_fallback) value = eval_fallback(s); //optional user-defined syntax parsing
|
||||
|
||||
else throw "unrecognized token";
|
||||
|
||||
while(true) {
|
||||
while(*s == ' ' || *s == '\t') s++; //trim whitespace
|
||||
if(!*s) break;
|
||||
x = *s, y = *(s + 1);
|
||||
|
||||
if(depth >= 13) break;
|
||||
if(x == '*') { value *= eval(++s, 13); continue; }
|
||||
if(x == '/') { intmax_t result = eval(++s, 13); if(result == 0) throw "division by zero"; value /= result; continue; }
|
||||
if(x == '%') { intmax_t result = eval(++s, 13); if(result == 0) throw "division by zero"; value %= result; continue; }
|
||||
|
||||
if(depth >= 12) break;
|
||||
if(x == '+') { value += eval(++s, 12); continue; }
|
||||
if(x == '-') { value -= eval(++s, 12); continue; }
|
||||
|
||||
if(depth >= 11) break;
|
||||
if(x == '<' && y == '<') { value <<= eval(++++s, 11); continue; }
|
||||
if(x == '>' && y == '>') { value >>= eval(++++s, 11); continue; }
|
||||
|
||||
if(depth >= 10) break;
|
||||
if(x == '<' && y == '=') { value = value <= eval(++++s, 10); continue; }
|
||||
if(x == '>' && y == '=') { value = value >= eval(++++s, 10); continue; }
|
||||
if(x == '<') { value = value < eval(++s, 10); continue; }
|
||||
if(x == '>') { value = value > eval(++s, 10); continue; }
|
||||
|
||||
if(depth >= 9) break;
|
||||
if(x == '=' && y == '=') { value = value == eval(++++s, 9); continue; }
|
||||
if(x == '!' && y == '=') { value = value != eval(++++s, 9); continue; }
|
||||
|
||||
if(depth >= 8) break;
|
||||
if(x == '&' && y != '&') { value = value & eval(++s, 8); continue; }
|
||||
|
||||
if(depth >= 7) break;
|
||||
if(x == '^' && y != '^') { value = value ^ eval(++s, 7); continue; }
|
||||
|
||||
if(depth >= 6) break;
|
||||
if(x == '|' && y != '|') { value = value | eval(++s, 6); continue; }
|
||||
|
||||
if(depth >= 5) break;
|
||||
if(x == '&' && y == '&') { value = eval(++++s, 5) && value; continue; }
|
||||
|
||||
if(depth >= 4) break;
|
||||
if(x == '^' && y == '^') { value = (!eval(++++s, 4) != !value); continue; }
|
||||
|
||||
if(depth >= 3) break;
|
||||
if(x == '|' && y == '|') { value = eval(++++s, 3) || value; continue; }
|
||||
|
||||
if(x == '?') {
|
||||
intmax_t lhs = eval(++s, 2);
|
||||
if(*s != ':') throw "mismatched ternary";
|
||||
intmax_t rhs = eval(++s, 2);
|
||||
value = value ? lhs : rhs;
|
||||
continue;
|
||||
}
|
||||
if(depth >= 2) break;
|
||||
|
||||
if(depth > 0 && x == ')') break;
|
||||
|
||||
throw "unrecognized token";
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static bool eval(const char *s, intmax_t &result) {
|
||||
try {
|
||||
result = eval(s);
|
||||
return true;
|
||||
} catch(const char*) {
|
||||
result = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static intmax_t parse(const char *s) {
|
||||
try {
|
||||
intmax_t result = eval(s);
|
||||
return result;
|
||||
} catch(const char *) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
157
bsnes/nall/string/math-floating-point.hpp
Executable file
157
bsnes/nall/string/math-floating-point.hpp
Executable file
@@ -0,0 +1,157 @@
|
||||
#ifdef NALL_STRING_INTERNAL_HPP
|
||||
|
||||
namespace floatingpoint {
|
||||
|
||||
static nall::function<double (const char *&)> eval_fallback;
|
||||
|
||||
static double eval_integer(const char *&s) {
|
||||
if(!*s) throw "unrecognized integer";
|
||||
intmax_t value = 0, radix = 0, x = *s, y = *(s + 1);
|
||||
|
||||
//hexadecimal
|
||||
if(x == '0' && (y == 'X' || y == 'x')) {
|
||||
s += 2;
|
||||
while(true) {
|
||||
if(*s >= '0' && *s <= '9') { value = value * 16 + (*s++ - '0'); continue; }
|
||||
if(*s >= 'A' && *s <= 'F') { value = value * 16 + (*s++ - 'A' + 10); continue; }
|
||||
if(*s >= 'a' && *s <= 'f') { value = value * 16 + (*s++ - 'a' + 10); continue; }
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
//binary
|
||||
if(x == '0' && (y == 'B' || y == 'b')) {
|
||||
s += 2;
|
||||
while(true) {
|
||||
if(*s == '0' || *s == '1') { value = value * 2 + (*s++ - '0'); continue; }
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
//octal (or decimal '0')
|
||||
if(x == '0' && y != '.') {
|
||||
s += 1;
|
||||
while(true) {
|
||||
if(*s >= '0' && *s <= '7') { value = value * 8 + (*s++ - '0'); continue; }
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
//decimal
|
||||
if(x >= '0' && x <= '9') {
|
||||
while(true) {
|
||||
if(*s >= '0' && *s <= '9') { value = value * 10 + (*s++ - '0'); continue; }
|
||||
if(*s == '.') { s++; break; }
|
||||
return value;
|
||||
}
|
||||
//floating-point
|
||||
while(true) {
|
||||
if(*s >= '0' && *s <= '9') { radix = radix * 10 + (*s++ - '0'); continue; }
|
||||
return atof(nall::string{ nall::decimal(value), ".", nall::decimal(radix) });
|
||||
}
|
||||
}
|
||||
|
||||
//char
|
||||
if(x == '\'' && y != '\'') {
|
||||
s += 1;
|
||||
while(true) {
|
||||
value = value * 256 + *s++;
|
||||
if(*s == '\'') { s += 1; return value; }
|
||||
if(!*s) throw "mismatched char";
|
||||
}
|
||||
}
|
||||
|
||||
throw "unrecognized integer";
|
||||
}
|
||||
|
||||
static double eval(const char *&s, int depth = 0) {
|
||||
while(*s == ' ' || *s == '\t') s++; //trim whitespace
|
||||
if(!*s) throw "unrecognized token";
|
||||
double value = 0, x = *s, y = *(s + 1);
|
||||
|
||||
if(*s == '(') {
|
||||
value = eval(++s, 1);
|
||||
if(*s++ != ')') throw "mismatched group";
|
||||
}
|
||||
|
||||
else if(x == '!') value = !eval(++s, 9);
|
||||
else if(x == '+') value = +eval(++s, 9);
|
||||
else if(x == '-') value = -eval(++s, 9);
|
||||
|
||||
else if((x >= '0' && x <= '9') || x == '\'') value = eval_integer(s);
|
||||
|
||||
else if(eval_fallback) value = eval_fallback(s); //optional user-defined syntax parsing
|
||||
|
||||
else throw "unrecognized token";
|
||||
|
||||
while(true) {
|
||||
while(*s == ' ' || *s == '\t') s++; //trim whitespace
|
||||
if(!*s) break;
|
||||
x = *s, y = *(s + 1);
|
||||
|
||||
if(depth >= 9) break;
|
||||
if(x == '*') { value *= eval(++s, 9); continue; }
|
||||
if(x == '/') { double result = eval(++s, 9); if(result == 0.0) throw "division by zero"; value /= result; continue; }
|
||||
|
||||
if(depth >= 8) break;
|
||||
if(x == '+') { value += eval(++s, 8); continue; }
|
||||
if(x == '-') { value -= eval(++s, 8); continue; }
|
||||
|
||||
if(depth >= 7) break;
|
||||
if(x == '<' && y == '=') { value = value <= eval(++++s, 7); continue; }
|
||||
if(x == '>' && y == '=') { value = value >= eval(++++s, 7); continue; }
|
||||
if(x == '<') { value = value < eval(++s, 7); continue; }
|
||||
if(x == '>') { value = value > eval(++s, 7); continue; }
|
||||
|
||||
if(depth >= 6) break;
|
||||
if(x == '=' && y == '=') { value = value == eval(++++s, 6); continue; }
|
||||
if(x == '!' && y == '=') { value = value != eval(++++s, 6); continue; }
|
||||
|
||||
if(depth >= 5) break;
|
||||
if(x == '&' && y == '&') { value = eval(++++s, 5) && value; continue; }
|
||||
|
||||
if(depth >= 4) break;
|
||||
if(x == '^' && y == '^') { value = (!eval(++++s, 4) != !value); continue; }
|
||||
|
||||
if(depth >= 3) break;
|
||||
if(x == '|' && y == '|') { value = eval(++++s, 3) || value; continue; }
|
||||
|
||||
if(x == '?') {
|
||||
double lhs = eval(++s, 2);
|
||||
if(*s != ':') throw "mismatched ternary";
|
||||
double rhs = eval(++s, 2);
|
||||
value = value ? lhs : rhs;
|
||||
continue;
|
||||
}
|
||||
if(depth >= 2) break;
|
||||
|
||||
if(depth > 0 && x == ')') break;
|
||||
|
||||
throw "unrecognized token";
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static bool eval(const char *s, double &result) {
|
||||
try {
|
||||
result = eval(s);
|
||||
return true;
|
||||
} catch(const char*e) {
|
||||
result = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
static double parse(const char *s) {
|
||||
try {
|
||||
double result = eval(s);
|
||||
return result;
|
||||
} catch(const char *) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@@ -86,8 +86,8 @@ static int eval(const char *&s, int depth = 0) {
|
||||
|
||||
if(depth >= 13) break;
|
||||
if(x == '*') { value *= eval(++s, 13); continue; }
|
||||
if(x == '/') { value /= eval(++s, 13); continue; }
|
||||
if(x == '%') { value %= eval(++s, 13); continue; }
|
||||
if(x == '/') { int result = eval(++s, 13); if(result == 0) throw "division_by_zero"; value /= result; continue; }
|
||||
if(x == '%') { int result = eval(++s, 13); if(result == 0) throw "division_by_zero"; value %= result; continue; }
|
||||
|
||||
if(depth >= 12) break;
|
||||
if(x == '+') { value += eval(++s, 12); continue; }
|
||||
|
@@ -253,9 +253,14 @@ template<unsigned length_, char padding> string binary(uintmax_t value) {
|
||||
//using sprintf is certainly not the most ideal method to convert
|
||||
//a double to a string ... but attempting to parse a double by
|
||||
//hand, digit-by-digit, results in subtle rounding errors.
|
||||
unsigned fp(char *str, double value) {
|
||||
unsigned fp(char *str, long double value) {
|
||||
char buffer[256];
|
||||
sprintf(buffer, "%f", value);
|
||||
#ifdef _WIN32
|
||||
//Windows C-runtime does not support long double via sprintf()
|
||||
sprintf(buffer, "%f", (double)value);
|
||||
#else
|
||||
sprintf(buffer, "%Lf", value);
|
||||
#endif
|
||||
|
||||
//remove excess 0's in fraction (2.500000 -> 2.5)
|
||||
for(char *p = buffer; *p; p++) {
|
||||
@@ -274,7 +279,7 @@ unsigned fp(char *str, double value) {
|
||||
return length + 1;
|
||||
}
|
||||
|
||||
string fp(double value) {
|
||||
string fp(long double value) {
|
||||
string temp;
|
||||
temp.reserve(fp(0, value));
|
||||
fp(temp(), value);
|
||||
|
78
bsnes/nall/string/wildcard.hpp
Executable file
78
bsnes/nall/string/wildcard.hpp
Executable file
@@ -0,0 +1,78 @@
|
||||
#ifdef NALL_STRING_INTERNAL_HPP
|
||||
|
||||
namespace nall {
|
||||
|
||||
bool wildcard(const char *s, const char *p) {
|
||||
const char *cp = 0, *mp = 0;
|
||||
while(*s && *p != '*') {
|
||||
if(*p != '?' && *s != *p) return false;
|
||||
p++, s++;
|
||||
}
|
||||
while(*s) {
|
||||
if(*p == '*') {
|
||||
if(!*++p) return true;
|
||||
mp = p, cp = s + 1;
|
||||
} else if(*p == '?' || *p == *s) {
|
||||
p++, s++;
|
||||
} else {
|
||||
p = mp, s = cp++;
|
||||
}
|
||||
}
|
||||
while(*p == '*') p++;
|
||||
return !*p;
|
||||
}
|
||||
|
||||
bool iwildcard(const char *s, const char *p) {
|
||||
const char *cp = 0, *mp = 0;
|
||||
while(*s && *p != '*') {
|
||||
if(*p != '?' && chrlower(*s) != chrlower(*p)) return false;
|
||||
p++, s++;
|
||||
}
|
||||
while(*s) {
|
||||
if(*p == '*') {
|
||||
if(!*++p) return true;
|
||||
mp = p, cp = s + 1;
|
||||
} else if(*p == '?' || chrlower(*p) == chrlower(*s)) {
|
||||
p++, s++;
|
||||
} else {
|
||||
p = mp, s = cp++;
|
||||
}
|
||||
}
|
||||
while(*p == '*') p++;
|
||||
return !*p;
|
||||
}
|
||||
|
||||
inline bool tokenize(const char *s, const char *p) {
|
||||
while(*s) {
|
||||
if(*p == '*') {
|
||||
while(*s) if(tokenize(s++, p + 1)) return true;
|
||||
return !*++p;
|
||||
}
|
||||
if(*s++ != *p++) return false;
|
||||
}
|
||||
while(*p == '*') p++;
|
||||
return !*p;
|
||||
}
|
||||
|
||||
inline bool tokenize(lstring &list, const char *s, const char *p) {
|
||||
while(*s) {
|
||||
if(*p == '*') {
|
||||
const char *b = s;
|
||||
while(*s) {
|
||||
if(tokenize(list, s++, p + 1)) {
|
||||
list.prepend(substr(b, 0, --s - b));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
list.prepend(b);
|
||||
return !*++p;
|
||||
}
|
||||
if(*s++ != *p++) return false;
|
||||
}
|
||||
while(*p == '*') { list.prepend(s); p++; }
|
||||
return !*p;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@@ -3,6 +3,7 @@
|
||||
namespace nall {
|
||||
|
||||
unsigned string::length() const { return strlen(data); }
|
||||
unsigned string::capacity() const { return size; }
|
||||
|
||||
template<unsigned limit> lstring string::split(const char *key) const { lstring result; result.split<limit>(key, data); return result; }
|
||||
template<unsigned limit> lstring string::isplit(const char *key) const { lstring result; result.isplit<limit>(key, data); return result; }
|
||||
|
265
bsnes/nall/string/xml-legacy.hpp
Executable file
265
bsnes/nall/string/xml-legacy.hpp
Executable file
@@ -0,0 +1,265 @@
|
||||
#ifdef NALL_STRING_INTERNAL_HPP
|
||||
|
||||
//XML v1.0 subset parser
|
||||
//revision 0.05
|
||||
|
||||
namespace nall {
|
||||
|
||||
struct xml_attribute {
|
||||
string name;
|
||||
string content;
|
||||
virtual string parse() const;
|
||||
};
|
||||
|
||||
struct xml_element : xml_attribute {
|
||||
string parse() const;
|
||||
linear_vector<xml_attribute> attribute;
|
||||
linear_vector<xml_element> element;
|
||||
|
||||
protected:
|
||||
void parse_doctype(const char *&data);
|
||||
bool parse_head(string data);
|
||||
bool parse_body(const char *&data);
|
||||
friend xml_element xml_parse(const char *data);
|
||||
};
|
||||
|
||||
inline string xml_attribute::parse() const {
|
||||
string data;
|
||||
unsigned offset = 0;
|
||||
|
||||
const char *source = content;
|
||||
while(*source) {
|
||||
if(*source == '&') {
|
||||
if(strbegin(source, "<")) { data[offset++] = '<'; source += 4; continue; }
|
||||
if(strbegin(source, ">")) { data[offset++] = '>'; source += 4; continue; }
|
||||
if(strbegin(source, "&")) { data[offset++] = '&'; source += 5; continue; }
|
||||
if(strbegin(source, "'")) { data[offset++] = '\''; source += 6; continue; }
|
||||
if(strbegin(source, """)) { data[offset++] = '"'; source += 6; continue; }
|
||||
}
|
||||
|
||||
//reject illegal characters
|
||||
if(*source == '&') return "";
|
||||
if(*source == '<') return "";
|
||||
if(*source == '>') return "";
|
||||
|
||||
data[offset++] = *source++;
|
||||
}
|
||||
|
||||
data[offset] = 0;
|
||||
return data;
|
||||
}
|
||||
|
||||
inline string xml_element::parse() const {
|
||||
string data;
|
||||
unsigned offset = 0;
|
||||
|
||||
const char *source = content;
|
||||
while(*source) {
|
||||
if(*source == '&') {
|
||||
if(strbegin(source, "<")) { data[offset++] = '<'; source += 4; continue; }
|
||||
if(strbegin(source, ">")) { data[offset++] = '>'; source += 4; continue; }
|
||||
if(strbegin(source, "&")) { data[offset++] = '&'; source += 5; continue; }
|
||||
if(strbegin(source, "'")) { data[offset++] = '\''; source += 6; continue; }
|
||||
if(strbegin(source, """)) { data[offset++] = '"'; source += 6; continue; }
|
||||
}
|
||||
|
||||
if(strbegin(source, "<!--")) {
|
||||
if(auto pos = strpos(source, "-->")) {
|
||||
source += pos() + 3;
|
||||
continue;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
if(strbegin(source, "<![CDATA[")) {
|
||||
if(auto pos = strpos(source, "]]>")) {
|
||||
if(pos() - 9 > 0) {
|
||||
string cdata = substr(source, 9, pos() - 9);
|
||||
data.append(cdata);
|
||||
offset += strlen(cdata);
|
||||
}
|
||||
source += 9 + offset + 3;
|
||||
continue;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
//reject illegal characters
|
||||
if(*source == '&') return "";
|
||||
if(*source == '<') return "";
|
||||
if(*source == '>') return "";
|
||||
|
||||
data[offset++] = *source++;
|
||||
}
|
||||
|
||||
data[offset] = 0;
|
||||
return data;
|
||||
}
|
||||
|
||||
inline void xml_element::parse_doctype(const char *&data) {
|
||||
name = "!DOCTYPE";
|
||||
const char *content_begin = data;
|
||||
|
||||
signed counter = 0;
|
||||
while(*data) {
|
||||
char value = *data++;
|
||||
if(value == '<') counter++;
|
||||
if(value == '>') counter--;
|
||||
if(counter < 0) {
|
||||
content = substr(content_begin, 0, data - content_begin - 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw "...";
|
||||
}
|
||||
|
||||
inline bool xml_element::parse_head(string data) {
|
||||
data.qreplace("\t", " ");
|
||||
data.qreplace("\r", " ");
|
||||
data.qreplace("\n", " ");
|
||||
while(qstrpos(data, " ")) data.qreplace(" ", " ");
|
||||
data.qreplace(" =", "=");
|
||||
data.qreplace("= ", "=");
|
||||
data.rtrim();
|
||||
|
||||
lstring part;
|
||||
part.qsplit(" ", data);
|
||||
|
||||
name = part[0];
|
||||
if(name == "") throw "...";
|
||||
|
||||
for(unsigned i = 1; i < part.size(); i++) {
|
||||
lstring side;
|
||||
side.qsplit("=", part[i]);
|
||||
if(side.size() != 2) throw "...";
|
||||
|
||||
xml_attribute attr;
|
||||
attr.name = side[0];
|
||||
attr.content = side[1];
|
||||
if(strbegin(attr.content, "\"") && strend(attr.content, "\"")) attr.content.trim<1>("\"");
|
||||
else if(strbegin(attr.content, "'") && strend(attr.content, "'")) attr.content.trim<1>("'");
|
||||
else throw "...";
|
||||
attribute.append(attr);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool xml_element::parse_body(const char *&data) {
|
||||
while(true) {
|
||||
if(!*data) return false;
|
||||
if(*data++ != '<') continue;
|
||||
if(*data == '/') return false;
|
||||
|
||||
if(strbegin(data, "!DOCTYPE") == true) {
|
||||
parse_doctype(data);
|
||||
return true;
|
||||
}
|
||||
|
||||
if(strbegin(data, "!--")) {
|
||||
if(auto offset = strpos(data, "-->")) {
|
||||
data += offset() + 3;
|
||||
continue;
|
||||
} else {
|
||||
throw "...";
|
||||
}
|
||||
}
|
||||
|
||||
if(strbegin(data, "![CDATA[")) {
|
||||
if(auto offset = strpos(data, "]]>")) {
|
||||
data += offset() + 3;
|
||||
continue;
|
||||
} else {
|
||||
throw "...";
|
||||
}
|
||||
}
|
||||
|
||||
auto offset = strpos(data, ">");
|
||||
if(!offset) throw "...";
|
||||
|
||||
string tag = substr(data, 0, offset());
|
||||
data += offset() + 1;
|
||||
const char *content_begin = data;
|
||||
|
||||
bool self_terminating = false;
|
||||
|
||||
if(strend(tag, "?") == true) {
|
||||
self_terminating = true;
|
||||
tag.rtrim<1>("?");
|
||||
} else if(strend(tag, "/") == true) {
|
||||
self_terminating = true;
|
||||
tag.rtrim<1>("/");
|
||||
}
|
||||
|
||||
parse_head(tag);
|
||||
if(self_terminating) return true;
|
||||
|
||||
while(*data) {
|
||||
unsigned index = element.size();
|
||||
xml_element node;
|
||||
if(node.parse_body(data) == false) {
|
||||
if(*data == '/') {
|
||||
signed length = data - content_begin - 1;
|
||||
if(length > 0) content = substr(content_begin, 0, length);
|
||||
|
||||
data++;
|
||||
auto offset = strpos(data, ">");
|
||||
if(!offset) throw "...";
|
||||
|
||||
tag = substr(data, 0, offset());
|
||||
data += offset() + 1;
|
||||
|
||||
tag.replace("\t", " ");
|
||||
tag.replace("\r", " ");
|
||||
tag.replace("\n", " ");
|
||||
while(strpos(tag, " ")) tag.replace(" ", " ");
|
||||
tag.rtrim();
|
||||
|
||||
if(name != tag) throw "...";
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
element.append(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//ensure there is only one root element
|
||||
inline bool xml_validate(xml_element &document) {
|
||||
unsigned root_counter = 0;
|
||||
|
||||
for(unsigned i = 0; i < document.element.size(); i++) {
|
||||
string &name = document.element[i].name;
|
||||
if(strbegin(name, "?")) continue;
|
||||
if(strbegin(name, "!")) continue;
|
||||
if(++root_counter > 1) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline xml_element xml_parse(const char *data) {
|
||||
xml_element self;
|
||||
|
||||
try {
|
||||
while(*data) {
|
||||
xml_element node;
|
||||
if(node.parse_body(data) == false) {
|
||||
break;
|
||||
} else {
|
||||
self.element.append(node);
|
||||
}
|
||||
}
|
||||
|
||||
if(xml_validate(self) == false) throw "...";
|
||||
return self;
|
||||
} catch(const char*) {
|
||||
xml_element empty;
|
||||
return empty;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@@ -1,265 +1,250 @@
|
||||
#ifdef NALL_STRING_INTERNAL_HPP
|
||||
|
||||
//XML v1.0 subset parser
|
||||
//revision 0.05
|
||||
//revision 0.01
|
||||
|
||||
namespace nall {
|
||||
namespace XML {
|
||||
|
||||
struct xml_attribute {
|
||||
struct Node {
|
||||
string name;
|
||||
string content;
|
||||
virtual string parse() const;
|
||||
};
|
||||
|
||||
struct xml_element : xml_attribute {
|
||||
string parse() const;
|
||||
linear_vector<xml_attribute> attribute;
|
||||
linear_vector<xml_element> element;
|
||||
|
||||
protected:
|
||||
void parse_doctype(const char *&data);
|
||||
bool parse_head(string data);
|
||||
bool parse_body(const char *&data);
|
||||
friend xml_element xml_parse(const char *data);
|
||||
};
|
||||
|
||||
inline string xml_attribute::parse() const {
|
||||
string data;
|
||||
unsigned offset = 0;
|
||||
bool attribute;
|
||||
array<Node*> children;
|
||||
|
||||
const char *source = content;
|
||||
while(*source) {
|
||||
if(*source == '&') {
|
||||
if(strbegin(source, "<")) { data[offset++] = '<'; source += 4; continue; }
|
||||
if(strbegin(source, ">")) { data[offset++] = '>'; source += 4; continue; }
|
||||
if(strbegin(source, "&")) { data[offset++] = '&'; source += 5; continue; }
|
||||
if(strbegin(source, "'")) { data[offset++] = '\''; source += 6; continue; }
|
||||
if(strbegin(source, """)) { data[offset++] = '"'; source += 6; continue; }
|
||||
}
|
||||
|
||||
//reject illegal characters
|
||||
if(*source == '&') return "";
|
||||
if(*source == '<') return "";
|
||||
if(*source == '>') return "";
|
||||
|
||||
data[offset++] = *source++;
|
||||
inline bool exists() const {
|
||||
return !name.empty();
|
||||
}
|
||||
|
||||
data[offset] = 0;
|
||||
return data;
|
||||
}
|
||||
inline bool isName(char c) const {
|
||||
if(c >= 'A' && c <= 'Z') return true;
|
||||
if(c >= 'a' && c <= 'z') return true;
|
||||
if(c >= '0' && c <= '9') return true;
|
||||
if(c == '.' || c == '_') return true;
|
||||
if(c == '?') return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
inline string xml_element::parse() const {
|
||||
string data;
|
||||
unsigned offset = 0;
|
||||
inline bool isWhitespace(char c) const {
|
||||
if(c == ' ' || c == '\t') return true;
|
||||
if(c == '\r' || c == '\n') return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
const char *source = content;
|
||||
while(*source) {
|
||||
if(*source == '&') {
|
||||
if(strbegin(source, "<")) { data[offset++] = '<'; source += 4; continue; }
|
||||
if(strbegin(source, ">")) { data[offset++] = '>'; source += 4; continue; }
|
||||
if(strbegin(source, "&")) { data[offset++] = '&'; source += 5; continue; }
|
||||
if(strbegin(source, "'")) { data[offset++] = '\''; source += 6; continue; }
|
||||
if(strbegin(source, """)) { data[offset++] = '"'; source += 6; continue; }
|
||||
}
|
||||
//copy part of string from source document into target string; decode markup while copying
|
||||
inline void copy(string &target, const char *source, unsigned length) {
|
||||
target.reserve(length + 1);
|
||||
|
||||
if(strbegin(source, "<!--")) {
|
||||
if(auto pos = strpos(source, "-->")) {
|
||||
source += pos() + 3;
|
||||
continue;
|
||||
} else {
|
||||
return "";
|
||||
#if defined(NALL_XML_LITERAL)
|
||||
memcpy(target(), source, length);
|
||||
target[length] = 0;
|
||||
return;
|
||||
#endif
|
||||
|
||||
char *output = target();
|
||||
while(length) {
|
||||
if(*source == '&') {
|
||||
if(!memcmp(source, "<", 4)) { *output++ = '<'; source += 4; length -= 4; continue; }
|
||||
if(!memcmp(source, ">", 4)) { *output++ = '>'; source += 4; length -= 4; continue; }
|
||||
if(!memcmp(source, "&", 5)) { *output++ = '&'; source += 5; length -= 5; continue; }
|
||||
if(!memcmp(source, "'", 6)) { *output++ = '\''; source += 6; length -= 6; continue; }
|
||||
if(!memcmp(source, """, 6)) { *output++ = '\"'; source += 6; length -= 6; continue; }
|
||||
}
|
||||
}
|
||||
|
||||
if(strbegin(source, "<![CDATA[")) {
|
||||
if(auto pos = strpos(source, "]]>")) {
|
||||
if(pos() - 9 > 0) {
|
||||
string cdata = substr(source, 9, pos() - 9);
|
||||
data.append(cdata);
|
||||
offset += strlen(cdata);
|
||||
if(attribute == false && source[0] == '<' && source[1] == '!') {
|
||||
//comment
|
||||
if(!memcmp(source, "<!--", 4)) {
|
||||
source += 4, length -= 4;
|
||||
while(memcmp(source, "-->", 3)) source++, length--;
|
||||
source += 3, length -= 3;
|
||||
continue;
|
||||
}
|
||||
|
||||
//CDATA
|
||||
if(!memcmp(source, "<![CDATA[", 9)) {
|
||||
source += 9, length -= 9;
|
||||
while(memcmp(source, "]]>", 3)) *output++ = *source++, length--;
|
||||
source += 3, length -= 3;
|
||||
continue;
|
||||
}
|
||||
source += 9 + offset + 3;
|
||||
continue;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
|
||||
*output++ = *source++, length--;
|
||||
}
|
||||
|
||||
//reject illegal characters
|
||||
if(*source == '&') return "";
|
||||
if(*source == '<') return "";
|
||||
if(*source == '>') return "";
|
||||
|
||||
data[offset++] = *source++;
|
||||
*output = 0;
|
||||
}
|
||||
|
||||
data[offset] = 0;
|
||||
return data;
|
||||
}
|
||||
inline bool parseExpression(const char *&p) {
|
||||
if(*(p + 1) != '!') return false;
|
||||
|
||||
inline void xml_element::parse_doctype(const char *&data) {
|
||||
name = "!DOCTYPE";
|
||||
const char *content_begin = data;
|
||||
|
||||
signed counter = 0;
|
||||
while(*data) {
|
||||
char value = *data++;
|
||||
if(value == '<') counter++;
|
||||
if(value == '>') counter--;
|
||||
if(counter < 0) {
|
||||
content = substr(content_begin, 0, data - content_begin - 1);
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw "...";
|
||||
}
|
||||
|
||||
inline bool xml_element::parse_head(string data) {
|
||||
data.qreplace("\t", " ");
|
||||
data.qreplace("\r", " ");
|
||||
data.qreplace("\n", " ");
|
||||
while(qstrpos(data, " ")) data.qreplace(" ", " ");
|
||||
data.qreplace(" =", "=");
|
||||
data.qreplace("= ", "=");
|
||||
data.rtrim();
|
||||
|
||||
lstring part;
|
||||
part.qsplit(" ", data);
|
||||
|
||||
name = part[0];
|
||||
if(name == "") throw "...";
|
||||
|
||||
for(unsigned i = 1; i < part.size(); i++) {
|
||||
lstring side;
|
||||
side.qsplit("=", part[i]);
|
||||
if(side.size() != 2) throw "...";
|
||||
|
||||
xml_attribute attr;
|
||||
attr.name = side[0];
|
||||
attr.content = side[1];
|
||||
if(strbegin(attr.content, "\"") && strend(attr.content, "\"")) attr.content.trim<1>("\"");
|
||||
else if(strbegin(attr.content, "'") && strend(attr.content, "'")) attr.content.trim<1>("'");
|
||||
else throw "...";
|
||||
attribute.append(attr);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool xml_element::parse_body(const char *&data) {
|
||||
while(true) {
|
||||
if(!*data) return false;
|
||||
if(*data++ != '<') continue;
|
||||
if(*data == '/') return false;
|
||||
|
||||
if(strbegin(data, "!DOCTYPE") == true) {
|
||||
parse_doctype(data);
|
||||
//comment
|
||||
if(!memcmp(p, "<!--", 4)) {
|
||||
while(*p && memcmp(p, "-->", 3)) p++;
|
||||
if(!*p) throw "unclosed comment";
|
||||
p += 3;
|
||||
return true;
|
||||
}
|
||||
|
||||
if(strbegin(data, "!--")) {
|
||||
if(auto offset = strpos(data, "-->")) {
|
||||
data += offset() + 3;
|
||||
continue;
|
||||
} else {
|
||||
throw "...";
|
||||
}
|
||||
//CDATA
|
||||
if(!memcmp(p, "<![CDATA[", 9)) {
|
||||
while(*p && memcmp(p, "]]>", 3)) p++;
|
||||
if(!*p) throw "unclosed CDATA";
|
||||
p += 3;
|
||||
return true;
|
||||
}
|
||||
|
||||
if(strbegin(data, "![CDATA[")) {
|
||||
if(auto offset = strpos(data, "]]>")) {
|
||||
data += offset() + 3;
|
||||
continue;
|
||||
} else {
|
||||
throw "...";
|
||||
}
|
||||
//DOCTYPE
|
||||
if(!memcmp(p, "<!DOCTYPE", 9)) {
|
||||
unsigned counter = 0;
|
||||
do {
|
||||
char n = *p++;
|
||||
if(!n) throw "unclosed DOCTYPE";
|
||||
if(n == '<') counter++;
|
||||
if(n == '>') counter--;
|
||||
} while(counter);
|
||||
return true;
|
||||
}
|
||||
|
||||
auto offset = strpos(data, ">");
|
||||
if(!offset) throw "...";
|
||||
|
||||
string tag = substr(data, 0, offset());
|
||||
data += offset() + 1;
|
||||
const char *content_begin = data;
|
||||
|
||||
bool self_terminating = false;
|
||||
|
||||
if(strend(tag, "?") == true) {
|
||||
self_terminating = true;
|
||||
tag.rtrim<1>("?");
|
||||
} else if(strend(tag, "/") == true) {
|
||||
self_terminating = true;
|
||||
tag.rtrim<1>("/");
|
||||
}
|
||||
|
||||
parse_head(tag);
|
||||
if(self_terminating) return true;
|
||||
|
||||
while(*data) {
|
||||
unsigned index = element.size();
|
||||
xml_element node;
|
||||
if(node.parse_body(data) == false) {
|
||||
if(*data == '/') {
|
||||
signed length = data - content_begin - 1;
|
||||
if(length > 0) content = substr(content_begin, 0, length);
|
||||
|
||||
data++;
|
||||
auto offset = strpos(data, ">");
|
||||
if(!offset) throw "...";
|
||||
|
||||
tag = substr(data, 0, offset());
|
||||
data += offset() + 1;
|
||||
|
||||
tag.replace("\t", " ");
|
||||
tag.replace("\r", " ");
|
||||
tag.replace("\n", " ");
|
||||
while(strpos(tag, " ")) tag.replace(" ", " ");
|
||||
tag.rtrim();
|
||||
|
||||
if(name != tag) throw "...";
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
element.append(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//ensure there is only one root element
|
||||
inline bool xml_validate(xml_element &document) {
|
||||
unsigned root_counter = 0;
|
||||
|
||||
for(unsigned i = 0; i < document.element.size(); i++) {
|
||||
string &name = document.element[i].name;
|
||||
if(strbegin(name, "?")) continue;
|
||||
if(strbegin(name, "!")) continue;
|
||||
if(++root_counter > 1) return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//returns true if tag closes itself (<tag/>); false if not (<tag>)
|
||||
inline bool parseHead(const char *&p) {
|
||||
//parse name
|
||||
const char *nameStart = ++p; //skip '<'
|
||||
while(isName(*p)) p++;
|
||||
const char *nameEnd = p;
|
||||
copy(name, nameStart, nameEnd - nameStart);
|
||||
if(name.empty()) throw "missing element name";
|
||||
|
||||
inline xml_element xml_parse(const char *data) {
|
||||
xml_element self;
|
||||
//parse attributes
|
||||
while(*p) {
|
||||
while(isWhitespace(*p)) p++;
|
||||
if(!*p) throw "unclosed attribute";
|
||||
if(*p == '?' || *p == '/' || *p == '>') break;
|
||||
|
||||
try {
|
||||
while(*data) {
|
||||
xml_element node;
|
||||
if(node.parse_body(data) == false) {
|
||||
break;
|
||||
} else {
|
||||
self.element.append(node);
|
||||
}
|
||||
//parse attribute name
|
||||
Node *attribute = new Node;
|
||||
children.append(attribute);
|
||||
attribute->attribute = true;
|
||||
|
||||
const char *nameStart = p;
|
||||
while(isName(*p)) p++;
|
||||
const char *nameEnd = p;
|
||||
copy(attribute->name, nameStart, nameEnd - nameStart);
|
||||
if(attribute->name.empty()) throw "missing attribute name";
|
||||
|
||||
//parse attribute data
|
||||
if(*p++ != '=') throw "missing attribute value";
|
||||
char terminal = *p++;
|
||||
if(terminal != '\'' && terminal != '\"') throw "attribute value not quoted";
|
||||
const char *dataStart = p;
|
||||
while(*p && *p != terminal) p++;
|
||||
if(!*p) throw "missing attribute data terminal";
|
||||
const char *dataEnd = p++; //skip closing terminal
|
||||
|
||||
copy(attribute->data, dataStart, dataEnd - dataStart);
|
||||
}
|
||||
|
||||
if(xml_validate(self) == false) throw "...";
|
||||
return self;
|
||||
} catch(const char*) {
|
||||
xml_element empty;
|
||||
return empty;
|
||||
//parse closure
|
||||
if(*p == '?' && *(p + 1) == '>') { p += 2; return true; }
|
||||
if(*p == '/' && *(p + 1) == '>') { p += 2; return true; }
|
||||
if(*p == '>') { p += 1; return false; }
|
||||
throw "invalid element tag";
|
||||
}
|
||||
}
|
||||
|
||||
//parse element and all of its child elements
|
||||
inline void parseElement(const char *&p) {
|
||||
Node *node = new Node;
|
||||
children.append(node);
|
||||
if(node->parseHead(p) == true) return;
|
||||
node->parse(p);
|
||||
}
|
||||
|
||||
//return true if </tag> matches this node's name
|
||||
inline bool parseClosureElement(const char *&p) {
|
||||
if(p[0] != '<' || p[1] != '/') return false;
|
||||
p += 2;
|
||||
const char *nameStart = p;
|
||||
while(*p && *p != '>') p++;
|
||||
if(*p != '>') throw "unclosed closure element";
|
||||
const char *nameEnd = p++;
|
||||
if(memcmp(name, nameStart, nameEnd - nameStart)) throw "closure element name mismatch";
|
||||
return true;
|
||||
}
|
||||
|
||||
//parse contents of an element
|
||||
inline void parse(const char *&p) {
|
||||
const char *dataStart = p, *dataEnd = p;
|
||||
|
||||
while(*p) {
|
||||
while(*p && *p != '<') p++;
|
||||
if(!*p) break;
|
||||
dataEnd = p;
|
||||
if(parseClosureElement(p) == true) break;
|
||||
if(parseExpression(p) == true) continue;
|
||||
parseElement(p);
|
||||
}
|
||||
|
||||
copy(data, dataStart, dataEnd - dataStart);
|
||||
}
|
||||
|
||||
inline void reset() {
|
||||
for(auto &child : children) delete child;
|
||||
children.reset();
|
||||
}
|
||||
|
||||
struct iterator {
|
||||
inline bool operator!=(const iterator &source) const { return index != source.index; }
|
||||
inline Node& operator*() { return *node.children[index]; }
|
||||
inline iterator& operator++() { index++; return *this; }
|
||||
inline iterator(const Node &node, unsigned index) : node(node), index(index) {}
|
||||
private:
|
||||
const Node &node;
|
||||
unsigned index;
|
||||
};
|
||||
|
||||
inline iterator begin() { return iterator(*this, 0); }
|
||||
inline iterator end() { return iterator(*this, children.size()); }
|
||||
inline const iterator begin() const { return iterator(*this, 0); }
|
||||
inline const iterator end() const { return iterator(*this, children.size()); }
|
||||
|
||||
inline Node& operator[](const char *name) {
|
||||
for(auto &node : *this) {
|
||||
if(node.name == name) return node;
|
||||
}
|
||||
static Node node;
|
||||
return node;
|
||||
}
|
||||
|
||||
inline Node() : attribute(false) {}
|
||||
inline ~Node() { reset(); }
|
||||
|
||||
Node(const Node&) = delete;
|
||||
Node& operator=(const Node&) = delete;
|
||||
};
|
||||
|
||||
struct Document : Node {
|
||||
string error;
|
||||
|
||||
inline bool load(const char *document) {
|
||||
if(document == nullptr) return false;
|
||||
reset();
|
||||
try {
|
||||
parse(document);
|
||||
} catch(const char *error) {
|
||||
reset();
|
||||
this->error = error;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
inline Document() {}
|
||||
inline Document(const char *document) { load(document); }
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -55,6 +55,11 @@ namespace nall {
|
||||
new(pool + objectsize++) T(data);
|
||||
}
|
||||
|
||||
void prepend(const T& data) {
|
||||
append(data);
|
||||
for(unsigned n = objectsize - 1; n; n--) swap(pool[n], pool[n - 1]);
|
||||
}
|
||||
|
||||
void remove(unsigned index, unsigned count = 1) {
|
||||
for(unsigned n = index; count + n < objectsize; n++) {
|
||||
pool[n] = pool[count + n];
|
||||
|
29
bsnes/nall/xorg/guard.hpp
Executable file
29
bsnes/nall/xorg/guard.hpp
Executable file
@@ -0,0 +1,29 @@
|
||||
#ifndef NALL_XORG_GUARD_HPP
|
||||
#define NALL_XORG_GUARD_HPP
|
||||
|
||||
#define None
|
||||
#undef XlibNone
|
||||
#define XlibNone 0L
|
||||
#define Button1 XlibButton1
|
||||
#define Button2 XlibButton2
|
||||
#define Button3 XlibButton3
|
||||
#define Button4 XlibButton4
|
||||
#define Button5 XlibButton5
|
||||
#define Display XlibDisplay
|
||||
#define Screen XlibScreen
|
||||
#define Window XlibWindow
|
||||
|
||||
#else
|
||||
#undef NALL_XORG_GUARD_HPP
|
||||
|
||||
#undef None
|
||||
#undef Button1
|
||||
#undef Button2
|
||||
#undef Button3
|
||||
#undef Button4
|
||||
#undef Button5
|
||||
#undef Display
|
||||
#undef Screen
|
||||
#undef Window
|
||||
|
||||
#endif
|
12
bsnes/nall/xorg/xorg.hpp
Executable file
12
bsnes/nall/xorg/xorg.hpp
Executable file
@@ -0,0 +1,12 @@
|
||||
#ifndef NALL_XORG_XORG_HPP
|
||||
#define NALL_XORG_XORG_HPP
|
||||
|
||||
#include <nall/xorg/guard.hpp>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/Xatom.h>
|
||||
#include <nall/xorg/guard.hpp>
|
||||
|
||||
#endif
|
@@ -111,7 +111,7 @@ void serialize(serializer &s) {
|
||||
s.integer(irq_latch);
|
||||
}
|
||||
|
||||
BandaiFCG(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
|
||||
BandaiFCG(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
|
||||
}
|
||||
|
||||
};
|
||||
|
@@ -86,14 +86,14 @@ void Board::serialize(serializer &s) {
|
||||
if(chrram.size) s.array(chrram.data, chrram.size);
|
||||
}
|
||||
|
||||
Board::Board(BML::Node &board, const uint8_t *data, unsigned size) {
|
||||
information.type = board["type"].value;
|
||||
information.battery = board["prg"]["battery"].value;
|
||||
Board::Board(XML::Node &board, const uint8_t *data, unsigned size) {
|
||||
information.type = board["type"].data;
|
||||
information.battery = board["prg"]["battery"].data == "true";
|
||||
|
||||
prgrom.size = decimal(board["prg"]["rom"].value);
|
||||
prgram.size = decimal(board["prg"]["ram"].value);
|
||||
chrrom.size = decimal(board["chr"]["rom"].value);
|
||||
chrram.size = decimal(board["chr"]["ram"].value);
|
||||
prgrom.size = hex(board["prg"]["rom"].data);
|
||||
prgram.size = hex(board["prg"]["ram"].data);
|
||||
chrrom.size = hex(board["chr"]["rom"].data);
|
||||
chrram.size = hex(board["chr"]["ram"].data);
|
||||
|
||||
if(prgrom.size) prgrom.data = new uint8[prgrom.size]();
|
||||
if(prgram.size) prgram.data = new uint8[prgram.size]();
|
||||
@@ -111,9 +111,9 @@ Board::~Board() {
|
||||
}
|
||||
|
||||
Board* Board::load(const string &markup, const uint8_t *data, unsigned size) {
|
||||
BML::Document document(markup);
|
||||
XML::Document document(markup);
|
||||
auto &board = document["cartridge"]["board"];
|
||||
string type = board["type"].value;
|
||||
string type = board["type"].data;
|
||||
|
||||
if(type == "BANDAI-FCG") return new BandaiFCG(board, data, size);
|
||||
|
||||
|
@@ -31,7 +31,7 @@ struct Board {
|
||||
virtual void reset();
|
||||
|
||||
virtual void serialize(serializer&);
|
||||
Board(BML::Node &board, const uint8_t *data, unsigned size);
|
||||
Board(XML::Node &board, const uint8_t *data, unsigned size);
|
||||
virtual ~Board();
|
||||
|
||||
static Board* load(const string &markup, const uint8_t *data, unsigned size);
|
||||
|
@@ -34,7 +34,7 @@ void serialize(serializer &s) {
|
||||
vrc1.serialize(s);
|
||||
}
|
||||
|
||||
KonamiVRC1(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), vrc1(*this) {
|
||||
KonamiVRC1(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), vrc1(*this) {
|
||||
}
|
||||
|
||||
};
|
||||
|
@@ -49,9 +49,9 @@ void serialize(serializer &s) {
|
||||
vrc2.serialize(s);
|
||||
}
|
||||
|
||||
KonamiVRC2(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), vrc2(*this) {
|
||||
settings.pinout.a0 = 1 << decimal(board["chip"]["pinout"]["a0"].value);
|
||||
settings.pinout.a1 = 1 << decimal(board["chip"]["pinout"]["a1"].value);
|
||||
KonamiVRC2(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), vrc2(*this) {
|
||||
settings.pinout.a0 = 1 << decimal(board["chip"]["pinout"]["a0"].data);
|
||||
settings.pinout.a1 = 1 << decimal(board["chip"]["pinout"]["a1"].data);
|
||||
}
|
||||
|
||||
};
|
||||
|
@@ -50,8 +50,8 @@ void serialize(serializer &s) {
|
||||
vrc3.serialize(s);
|
||||
}
|
||||
|
||||
KonamiVRC3(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), vrc3(*this) {
|
||||
settings.mirror = board["mirror"].value == "vertical" ? 1 : 0;
|
||||
KonamiVRC3(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), vrc3(*this) {
|
||||
settings.mirror = board["mirror"]["mode"].data == "vertical" ? 1 : 0;
|
||||
}
|
||||
|
||||
};
|
||||
|
@@ -53,9 +53,9 @@ void serialize(serializer &s) {
|
||||
vrc4.serialize(s);
|
||||
}
|
||||
|
||||
KonamiVRC4(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), vrc4(*this) {
|
||||
settings.pinout.a0 = 1 << decimal(board["chip"]["pinout"]["a0"].value);
|
||||
settings.pinout.a1 = 1 << decimal(board["chip"]["pinout"]["a1"].value);
|
||||
KonamiVRC4(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), vrc4(*this) {
|
||||
settings.pinout.a0 = 1 << decimal(board["chip"]["pinout"]["a0"].data);
|
||||
settings.pinout.a1 = 1 << decimal(board["chip"]["pinout"]["a1"].data);
|
||||
}
|
||||
|
||||
};
|
||||
|
@@ -36,7 +36,7 @@ void main() { vrc6.main(); }
|
||||
void power() { vrc6.power(); }
|
||||
void reset() { vrc6.reset(); }
|
||||
|
||||
KonamiVRC6(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), vrc6(*this) {
|
||||
KonamiVRC6(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), vrc6(*this) {
|
||||
}
|
||||
|
||||
};
|
||||
|
@@ -41,7 +41,7 @@ void serialize(serializer &s) {
|
||||
vrc7.serialize(s);
|
||||
}
|
||||
|
||||
KonamiVRC7(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), vrc7(*this) {
|
||||
KonamiVRC7(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), vrc7(*this) {
|
||||
}
|
||||
|
||||
};
|
||||
|
@@ -45,7 +45,7 @@ void serialize(serializer &s) {
|
||||
s.integer(mirror_select);
|
||||
}
|
||||
|
||||
NES_AxROM(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
|
||||
NES_AxROM(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
|
||||
}
|
||||
|
||||
};
|
||||
|
@@ -45,8 +45,8 @@ void serialize(serializer &s) {
|
||||
s.integer(prg_bank);
|
||||
}
|
||||
|
||||
NES_BNROM(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
|
||||
settings.mirror = board["mirror"].value == "vertical" ? 1 : 0;
|
||||
NES_BNROM(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
|
||||
settings.mirror = board["mirror"]["mode"].data == "vertical" ? 1 : 0;
|
||||
}
|
||||
|
||||
};
|
||||
|
@@ -47,8 +47,8 @@ void serialize(serializer &s) {
|
||||
s.integer(chr_bank);
|
||||
}
|
||||
|
||||
NES_CNROM(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
|
||||
settings.mirror = board["mirror"].value == "vertical" ? 1 : 0;
|
||||
NES_CNROM(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
|
||||
settings.mirror = board["mirror"]["mode"].data == "vertical" ? 1 : 0;
|
||||
}
|
||||
|
||||
};
|
||||
|
@@ -46,7 +46,7 @@ void serialize(serializer &s) {
|
||||
mmc5.serialize(s);
|
||||
}
|
||||
|
||||
NES_ExROM(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), mmc5(*this) {
|
||||
NES_ExROM(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), mmc5(*this) {
|
||||
revision = Revision::ELROM;
|
||||
}
|
||||
|
||||
|
@@ -84,7 +84,7 @@ void serialize(serializer &s) {
|
||||
s.array(latch);
|
||||
}
|
||||
|
||||
NES_FxROM(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
|
||||
NES_FxROM(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
|
||||
revision = Revision::FKROM;
|
||||
}
|
||||
|
||||
|
@@ -54,8 +54,8 @@ void serialize(serializer &s) {
|
||||
s.integer(chr_bank);
|
||||
}
|
||||
|
||||
NES_GxROM(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
|
||||
settings.mirror = board["mirror"].value == "vertical" ? 1 : 0;
|
||||
NES_GxROM(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
|
||||
settings.mirror = board["mirror"]["mode"].data == "vertical" ? 1 : 0;
|
||||
}
|
||||
|
||||
};
|
||||
|
@@ -42,7 +42,7 @@ void serialize(serializer &s) {
|
||||
mmc6.serialize(s);
|
||||
}
|
||||
|
||||
NES_HKROM(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), mmc6(*this) {
|
||||
NES_HKROM(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), mmc6(*this) {
|
||||
}
|
||||
|
||||
};
|
||||
|
@@ -36,8 +36,8 @@ void serialize(serializer &s) {
|
||||
Board::serialize(s);
|
||||
}
|
||||
|
||||
NES_NROM(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
|
||||
settings.mirror = board["mirror"].value == "vertical" ? 1 : 0;
|
||||
NES_NROM(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
|
||||
settings.mirror = board["mirror"]["mode"].data == "vertical" ? 1 : 0;
|
||||
}
|
||||
|
||||
};
|
||||
|
@@ -90,7 +90,7 @@ void serialize(serializer &s) {
|
||||
s.array(latch);
|
||||
}
|
||||
|
||||
NES_PxROM(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
|
||||
NES_PxROM(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
|
||||
revision = Revision::PNROM;
|
||||
}
|
||||
|
||||
|
@@ -94,7 +94,7 @@ void serialize(serializer &s) {
|
||||
mmc1.serialize(s);
|
||||
}
|
||||
|
||||
NES_SxROM(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), mmc1(*this) {
|
||||
NES_SxROM(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), mmc1(*this) {
|
||||
revision = Revision::SXROM;
|
||||
}
|
||||
|
||||
|
@@ -60,7 +60,7 @@ void serialize(serializer &s) {
|
||||
mmc3.serialize(s);
|
||||
}
|
||||
|
||||
NES_TxROM(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), mmc3(*this) {
|
||||
NES_TxROM(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), mmc3(*this) {
|
||||
revision = Revision::TLROM;
|
||||
}
|
||||
|
||||
|
@@ -48,8 +48,8 @@ void serialize(serializer &s) {
|
||||
s.integer(prg_bank);
|
||||
}
|
||||
|
||||
NES_UxROM(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
|
||||
settings.mirror = board["mirror"].value == "vertical" ? 1 : 0;
|
||||
NES_UxROM(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
|
||||
settings.mirror = board["mirror"]["mode"].data == "vertical" ? 1 : 0;
|
||||
}
|
||||
|
||||
};
|
||||
|
@@ -220,7 +220,7 @@ void serialize(serializer &s) {
|
||||
pulse[2].serialize(s);
|
||||
}
|
||||
|
||||
Sunsoft5B(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
|
||||
Sunsoft5B(XML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size) {
|
||||
}
|
||||
|
||||
};
|
||||
|
@@ -16,135 +16,142 @@ static string iNES(const uint8_t *data, unsigned size) {
|
||||
|
||||
//print("iNES mapper: ", mapper, "\n");
|
||||
|
||||
output.append("cartridge\n");
|
||||
output.append("<?xml version='1.0' encoding='UTF-8'?>\n");
|
||||
output.append("<cartridge>\n");
|
||||
|
||||
switch(mapper) {
|
||||
default:
|
||||
output.append("\tboard type:NES-NROM-256\n");
|
||||
output.append("\t\tmirror:", mirror == 0 ? "horizontal" : "vertical", "\n");
|
||||
output.append(" <board type='NES-NROM-256'>\n");
|
||||
output.append(" <mirror mode='", mirror == 0 ? "horizontal" : "vertical", "'/>\n");
|
||||
break;
|
||||
|
||||
case 1:
|
||||
output.append("\tboard type:NES-SXROM\n");
|
||||
output.append("\t\tchip type:MMC1B2\n");
|
||||
output.append(" <board type='NES-SXROM'>\n");
|
||||
output.append(" <chip type='MMC1B2'/>\n");
|
||||
prgram = 8192;
|
||||
break;
|
||||
|
||||
case 2:
|
||||
output.append("\tboard type:NES-UOROM\n");
|
||||
output.append("\t\tmirror:", mirror == 0 ? "horizontal" : "vertical", "\n");
|
||||
output.append(" <board type='NES-UOROM'>\n");
|
||||
output.append(" <mirror mode='", mirror == 0 ? "horizontal" : "vertical", "'/>\n");
|
||||
break;
|
||||
|
||||
case 3:
|
||||
output.append("\tboard type:NES-CNROM\n");
|
||||
output.append("\t\tmirror:", mirror == 0 ? "horizontal" : "vertical", "\n");
|
||||
output.append(" <board type='NES-CNROM'>\n");
|
||||
output.append(" <mirror mode='", mirror == 0 ? "horizontal" : "vertical", "'/>\n");
|
||||
break;
|
||||
|
||||
case 4:
|
||||
//MMC3
|
||||
output.append("\tboard type:NES-TLROM\n");
|
||||
output.append("\t\tchip type:MMC3B\n");
|
||||
output.append(" <board type='NES-TLROM'>\n");
|
||||
output.append(" <chip type='MMC3B'/>\n");
|
||||
prgram = 8192;
|
||||
//MMC6
|
||||
//output.append("\tboard type:NES-HKROM\n");
|
||||
//output.append("\t\tchip type:MMC6\n");
|
||||
//output.append(" <board type='NES-HKROM'>\n");
|
||||
//output.append(" <chip type='MMC6'/>\n");
|
||||
//prgram = 1024;
|
||||
break;
|
||||
|
||||
case 5:
|
||||
output.append("\tboard type:NES-ELROM\n");
|
||||
output.append("\t\tchip type:MMC5\n");
|
||||
output.append(" <board type='NES-ELROM'>\n");
|
||||
output.append(" <chip type='MMC5'/>\n");
|
||||
prgram = 65536;
|
||||
break;
|
||||
|
||||
case 7:
|
||||
output.append("\tboard type:NES-AOROM\n");
|
||||
output.append(" <board type='NES-AOROM'>\n");
|
||||
break;
|
||||
|
||||
case 9:
|
||||
output.append("\tboard type:NES-PNROM\n");
|
||||
output.append("\t\tchip type:MMC2\n");
|
||||
output.append(" <board type='NES-PNROM'>\n");
|
||||
output.append(" <chip type='MMC2'/>\n");
|
||||
prgram = 8192;
|
||||
break;
|
||||
|
||||
case 10:
|
||||
output.append("\tboard type:NES-FKROM\n");
|
||||
output.append("\t\tchip type:MMC4\n");
|
||||
output.append(" <board type='NES-FKROM'>\n");
|
||||
output.append(" <chip type='MMC4'/>\n");
|
||||
prgram = 8192;
|
||||
break;
|
||||
|
||||
case 16:
|
||||
output.append("\tboard type:BANDAI-FCG\n");
|
||||
output.append("\t\tchip type:LZ93D50\n");
|
||||
output.append(" <board type='BANDAI-FCG'>\n");
|
||||
output.append(" <chip type='LZ93D50'/>\n");
|
||||
break;
|
||||
|
||||
case 21:
|
||||
case 23:
|
||||
case 25:
|
||||
//VRC4
|
||||
output.append("\tboard type:KONAMI-VRC-4\n");
|
||||
output.append("\t\tchip type:VRC4\n");
|
||||
output.append("\t\t\tpinout a0=1 a1=0\n");
|
||||
output.append(" <board type='KONAMI-VRC-4'>\n");
|
||||
output.append(" <chip type='VRC4'>\n");
|
||||
output.append(" <pinout a0='1' a1='0'/>\n");
|
||||
output.append(" </chip>\n");
|
||||
prgram = 8192;
|
||||
break;
|
||||
|
||||
case 22:
|
||||
//VRC2
|
||||
output.append("\tboard type:KONAMI-VRC-2\n");
|
||||
output.append("\t\tchip type:VRC2\n");
|
||||
output.append("\t\t\tpinout a0=0 a1=1\n");
|
||||
output.append(" <board type='KONAMI-VRC-2'>\n");
|
||||
output.append(" <chip type='VRC2'>\n");
|
||||
output.append(" <pinout a0='0' a1='1'/>\n");
|
||||
output.append(" </chip>\n");
|
||||
break;
|
||||
|
||||
case 24:
|
||||
output.append("\tboard type:KONAMI-VRC-6\n");
|
||||
output.append("\t\tchip type:VRC6\n");
|
||||
output.append(" <board type='KONAMI-VRC-6'>\n");
|
||||
output.append(" <chip type='VRC6'/>\n");
|
||||
break;
|
||||
|
||||
case 26:
|
||||
output.append("\tboard type:KONAMI-VRC-6\n");
|
||||
output.append("\t\tchip type:VRC6\n");
|
||||
output.append(" <board type='KONAMI-VRC-6'>\n");
|
||||
output.append(" <chip type='VRC6'/>\n");
|
||||
prgram = 8192;
|
||||
break;
|
||||
|
||||
case 34:
|
||||
output.append("\tboard type:NES-BNROM\n");
|
||||
output.append("\t\tmirror:", mirror == 0 ? "horizontal" : "vertical", "\n");
|
||||
output.append(" <board type='NES-BNROM'>\n");
|
||||
output.append(" <mirror type='", mirror == 0 ? "horizontal" : "vertical", "'/>\n");
|
||||
break;
|
||||
|
||||
case 66:
|
||||
output.append("\tboard type:NES-GNROM\n");
|
||||
output.append("\t\tmirror:", mirror == 0 ? "horizontal" : "vertical", "\n");
|
||||
output.append(" <board type='NES-GNROM'>\n");
|
||||
output.append(" <mirror type='", mirror == 0 ? "horizontal" : "vertical", "'/>\n");
|
||||
break;
|
||||
|
||||
case 69:
|
||||
output.append("\tboard type:SUNSOFT-5B\n");
|
||||
output.append("\t\tchip type:5B\n");
|
||||
output.append(" <board type='SUNSOFT-5B'>\n");
|
||||
output.append(" <chip type='5B'/>\n");
|
||||
prgram = 8192;
|
||||
break;
|
||||
|
||||
case 73:
|
||||
output.append("\tboard type:KONAMI-VRC-3\n");
|
||||
output.append("\t\tchip type:VRC3\n");
|
||||
output.append("\t\tmirror:", mirror == 0 ? "horizontal" : "vertical", "\n");
|
||||
output.append(" <board type='KONAMI-VRC-3'>\n");
|
||||
output.append(" <chip type='VRC3'/>\n");
|
||||
output.append(" <mirror type='", mirror == 0 ? "horizontal" : "vertical", "'/>\n");
|
||||
prgram = 8192;
|
||||
break;
|
||||
|
||||
case 75:
|
||||
output.append("\tboard type:KONAMI-VRC-1\n");
|
||||
output.append("\t\tchip type:VRC1\n");
|
||||
output.append(" <board type='KONAMI-VRC-1'>\n");
|
||||
output.append(" <chip type='VRC1'/>\n");
|
||||
break;
|
||||
|
||||
case 85:
|
||||
output.append("\tboard type:KONAMI-VRC-7\n");
|
||||
output.append("\t\tchip type:VRC7\n");
|
||||
output.append(" <board type='KONAMI-VRC-7'>\n");
|
||||
output.append(" <chip type='VRC7'/>\n");
|
||||
prgram = 8192;
|
||||
break;
|
||||
}
|
||||
|
||||
output.append("\t\tprg rom=", prgrom, " ram=", prgram, "\n");
|
||||
output.append("\t\tchr rom=", chrrom, " ram=", chrram, "\n");
|
||||
output.append(
|
||||
" <prg rom='0x", hex(prgrom), "' ram='0x", hex(prgram), "'/>\n"
|
||||
" <chr rom='0x", hex(chrrom), "' ram='0x", hex(chrram), "'/>\n"
|
||||
" </board>\n"
|
||||
"</cartridge>\n"
|
||||
);
|
||||
|
||||
//print(output, "\n");
|
||||
print(output, "\n");
|
||||
|
||||
return output;
|
||||
}
|
||||
|
@@ -42,7 +42,6 @@ void Input::connect(bool port, Device device) {
|
||||
}
|
||||
|
||||
void Input::power() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void Input::reset() {
|
||||
|
@@ -16,7 +16,6 @@ void Scheduler::exit(ExitReason reason) {
|
||||
}
|
||||
|
||||
void Scheduler::power() {
|
||||
reset();
|
||||
}
|
||||
|
||||
void Scheduler::reset() {
|
||||
|
21
bsnes/phoenix/Makefile
Executable file
21
bsnes/phoenix/Makefile
Executable file
@@ -0,0 +1,21 @@
|
||||
ifeq ($(platform),x)
|
||||
ifeq ($(phoenix),)
|
||||
phoenix := gtk
|
||||
endif
|
||||
|
||||
ifeq ($(phoenix),gtk)
|
||||
phoenixflags := -DPHOENIX_GTK `pkg-config --cflags gtk+-2.0`
|
||||
phoenixlink := `pkg-config --libs gtk+-2.0`
|
||||
endif
|
||||
|
||||
ifeq ($(phoenix),qt)
|
||||
phoenixflags := -DPHOENIX_QT `pkg-config --cflags QtCore QtGui`
|
||||
phoenixlink := `pkg-config --libs QtCore QtGui`
|
||||
endif
|
||||
else ifeq ($(platform),win)
|
||||
phoenixflags := -DPHOENIX_WINDOWS
|
||||
phoenixlink := -lkernel32 -luser32 -lgdi32 -ladvapi32 -lole32 -lcomctl32 -lcomdlg32
|
||||
else
|
||||
phoenixflags := -DPHOENIX_REFERENCE
|
||||
phoenixlink :=
|
||||
endif
|
@@ -16,6 +16,29 @@
|
||||
static bool OS_quit = false;
|
||||
Window Window::None;
|
||||
|
||||
//Geometry
|
||||
//========
|
||||
|
||||
Position Geometry::position() const {
|
||||
return { x, y };
|
||||
}
|
||||
|
||||
Size Geometry::size() const {
|
||||
return { width, height };
|
||||
}
|
||||
|
||||
string Geometry::text() const {
|
||||
return { x, ",", y, ",", width, ",", height };
|
||||
}
|
||||
|
||||
Geometry::Geometry(const string &text) {
|
||||
lstring part = text.split(",");
|
||||
x = integer(part(0, "256"));
|
||||
y = integer(part(1, "256"));
|
||||
width = decimal(part(2, "256"));
|
||||
height = decimal(part(3, "256"));
|
||||
}
|
||||
|
||||
//Font
|
||||
//====
|
||||
|
||||
@@ -27,85 +50,6 @@ Font::Font(const string &description):
|
||||
description(description) {
|
||||
}
|
||||
|
||||
//Image
|
||||
//=====
|
||||
|
||||
bool Image::load(const string &filename, const Color &alpha) {
|
||||
if(data) { delete[] data; data = nullptr; }
|
||||
|
||||
file fp;
|
||||
if(fp.open(filename, file::mode::read) == false) return false;
|
||||
uint8_t d0 = fp.read();
|
||||
uint8_t d1 = fp.read();
|
||||
uint8_t d2 = fp.read();
|
||||
uint8_t d3 = fp.read();
|
||||
fp.close();
|
||||
|
||||
if(d0 == 'B' && d1 == 'M') {
|
||||
bmp::read(filename, data, width, height);
|
||||
}
|
||||
|
||||
if(d0 == 0x89 && d1 == 'P' && d2 == 'N' && d3 == 'G') {
|
||||
png image;
|
||||
if(image.decode(filename)) {
|
||||
image.alphaTransform((alpha.red << 16) + (alpha.green << 8) + (alpha.blue << 0));
|
||||
width = image.info.width, height = image.info.height;
|
||||
data = new uint32_t[width * height];
|
||||
memcpy(data, image.data, width * height * sizeof(uint32_t));
|
||||
}
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
void Image::load(const uint32_t *data, const Size &size) {
|
||||
if(data) { delete[] data; data = nullptr; }
|
||||
width = size.width, height = size.height;
|
||||
this->data = new uint32_t[width * height];
|
||||
memcpy(this->data, data, width * height * sizeof(uint32_t));
|
||||
}
|
||||
|
||||
Image& Image::operator=(const Image &source) {
|
||||
if(this == &source) return *this;
|
||||
if(data) { delete[] data; data = nullptr; }
|
||||
if(source.data == nullptr) return *this;
|
||||
width = source.width, height = source.height;
|
||||
data = new uint32_t[width * height];
|
||||
memcpy(data, source.data, width * height * sizeof(uint32_t));
|
||||
return *this;
|
||||
}
|
||||
|
||||
Image& Image::operator=(Image &&source) {
|
||||
if(this == &source) return *this;
|
||||
if(data) { delete[] data; data = nullptr; }
|
||||
data = source.data, width = source.width, height = source.height;
|
||||
source.data = nullptr;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Image::Image() : data(nullptr) {
|
||||
}
|
||||
|
||||
Image::Image(const string &filename, const Color &alpha) : data(nullptr) {
|
||||
load(filename, alpha);
|
||||
}
|
||||
|
||||
Image::Image(const uint32_t *data, const Size &size) {
|
||||
load(data, size);
|
||||
}
|
||||
|
||||
Image::Image(const Image &source) : data(nullptr) {
|
||||
operator=(source);
|
||||
}
|
||||
|
||||
Image::Image(Image &&source) : data(nullptr) {
|
||||
operator=(std::forward<Image>(source));
|
||||
}
|
||||
|
||||
Image::~Image() {
|
||||
if(data) delete[] data;
|
||||
}
|
||||
|
||||
//Object
|
||||
//======
|
||||
|
||||
@@ -739,7 +683,7 @@ uint32_t* Canvas::data() {
|
||||
return state.data;
|
||||
}
|
||||
|
||||
bool Canvas::setImage(const Image &image) {
|
||||
bool Canvas::setImage(const nall::image &image) {
|
||||
if(image.data == nullptr || image.width == 0 || image.height == 0) return false;
|
||||
state.width = image.width;
|
||||
state.height = image.height;
|
||||
|
@@ -47,13 +47,6 @@ struct Color {
|
||||
inline Color(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha = 255) : red(red), green(green), blue(blue), alpha(alpha) {}
|
||||
};
|
||||
|
||||
struct Geometry {
|
||||
signed x, y;
|
||||
unsigned width, height;
|
||||
inline Geometry() : x(0), y(0), width(0), height(0) {}
|
||||
inline Geometry(signed x, signed y, unsigned width, unsigned height) : x(x), y(y), width(width), height(height) {}
|
||||
};
|
||||
|
||||
struct Position {
|
||||
signed x, y;
|
||||
inline Position() : x(0), y(0) {}
|
||||
@@ -66,27 +59,23 @@ struct Size {
|
||||
inline Size(unsigned width, unsigned height) : width(width), height(height) {}
|
||||
};
|
||||
|
||||
struct Geometry {
|
||||
signed x, y;
|
||||
unsigned width, height;
|
||||
Position position() const;
|
||||
Size size() const;
|
||||
nall::string text() const;
|
||||
inline Geometry() : x(0), y(0), width(0), height(0) {}
|
||||
inline Geometry(signed x, signed y, unsigned width, unsigned height) : x(x), y(y), width(width), height(height) {}
|
||||
Geometry(const nall::string &text);
|
||||
};
|
||||
|
||||
struct Font {
|
||||
nall::string description;
|
||||
Geometry geometry(const nall::string &text);
|
||||
Font(const nall::string &description = "");
|
||||
};
|
||||
|
||||
struct Image {
|
||||
uint32_t *data;
|
||||
unsigned width, height;
|
||||
bool load(const nall::string &filename, const Color &alpha = Color{255, 255, 255});
|
||||
void load(const uint32_t *data, const Size &size);
|
||||
Image& operator=(const Image &source);
|
||||
Image& operator=(Image &&source);
|
||||
Image();
|
||||
Image(const nall::string &filename, const Color &alpha = Color{255, 255, 255});
|
||||
Image(const uint32_t *data, const Size &size);
|
||||
Image(const Image &source);
|
||||
Image(Image &&source);
|
||||
~Image();
|
||||
};
|
||||
|
||||
struct Object {
|
||||
Object(pObject &p);
|
||||
Object& operator=(const Object&) = delete;
|
||||
@@ -223,7 +212,7 @@ struct Separator : private nall::base_from_member<pSeparator&>, Action {
|
||||
};
|
||||
|
||||
struct Item : private nall::base_from_member<pItem&>, Action {
|
||||
nall::function<void ()> onTick;
|
||||
nall::function<void ()> onActivate;
|
||||
|
||||
void setText(const nall::string &text);
|
||||
|
||||
@@ -235,7 +224,7 @@ struct Item : private nall::base_from_member<pItem&>, Action {
|
||||
};
|
||||
|
||||
struct CheckItem : private nall::base_from_member<pCheckItem&>, Action {
|
||||
nall::function<void ()> onTick;
|
||||
nall::function<void ()> onToggle;
|
||||
|
||||
bool checked();
|
||||
void setChecked(bool checked = true);
|
||||
@@ -252,7 +241,7 @@ struct RadioItem : private nall::base_from_member<pRadioItem&>, Action {
|
||||
template<typename... Args> static void group(Args&... args) { group({ args... }); }
|
||||
static void group(const nall::reference_array<RadioItem&> &list);
|
||||
|
||||
nall::function<void ()> onTick;
|
||||
nall::function<void ()> onActivate;
|
||||
|
||||
bool checked();
|
||||
void setChecked();
|
||||
@@ -317,7 +306,7 @@ struct Widget : private nall::base_from_member<pWidget&>, Sizable {
|
||||
};
|
||||
|
||||
struct Button : private nall::base_from_member<pButton&>, Widget {
|
||||
nall::function<void ()> onTick;
|
||||
nall::function<void ()> onActivate;
|
||||
|
||||
void setText(const nall::string &text);
|
||||
|
||||
@@ -330,7 +319,7 @@ struct Button : private nall::base_from_member<pButton&>, Widget {
|
||||
|
||||
struct Canvas : private nall::base_from_member<pCanvas&>, Widget {
|
||||
uint32_t* data();
|
||||
bool setImage(const Image &image);
|
||||
bool setImage(const nall::image &image);
|
||||
void setSize(const Size &size);
|
||||
Size size();
|
||||
void update();
|
||||
@@ -343,7 +332,7 @@ struct Canvas : private nall::base_from_member<pCanvas&>, Widget {
|
||||
};
|
||||
|
||||
struct CheckBox : private nall::base_from_member<pCheckBox&>, Widget {
|
||||
nall::function<void ()> onTick;
|
||||
nall::function<void ()> onToggle;
|
||||
|
||||
bool checked();
|
||||
void setChecked(bool checked = true);
|
||||
@@ -446,7 +435,7 @@ struct LineEdit : private nall::base_from_member<pLineEdit&>, Widget {
|
||||
struct ListView : private nall::base_from_member<pListView&>, Widget {
|
||||
nall::function<void ()> onActivate;
|
||||
nall::function<void ()> onChange;
|
||||
nall::function<void (unsigned)> onTick;
|
||||
nall::function<void (unsigned)> onToggle;
|
||||
|
||||
template<typename... Args> void append(const Args&... args) { append_({ args... }); }
|
||||
void autoSizeColumns();
|
||||
@@ -488,7 +477,7 @@ struct RadioBox : private nall::base_from_member<pRadioBox&>, Widget {
|
||||
template<typename... Args> static void group(Args&... args) { group({ args... }); }
|
||||
static void group(const nall::reference_array<RadioBox&> &list);
|
||||
|
||||
nall::function<void ()> onTick;
|
||||
nall::function<void ()> onActivate;
|
||||
|
||||
bool checked();
|
||||
void setChecked();
|
||||
|
@@ -1,5 +1,5 @@
|
||||
static void CheckItem_tick(CheckItem *self) {
|
||||
if(self->p.locked == false && self->onTick) self->onTick();
|
||||
static void CheckItem_toggle(CheckItem *self) {
|
||||
if(self->p.locked == false && self->onToggle) self->onToggle();
|
||||
}
|
||||
|
||||
bool pCheckItem::checked() {
|
||||
@@ -19,7 +19,7 @@ void pCheckItem::setText(const string &text) {
|
||||
void pCheckItem::constructor() {
|
||||
widget = gtk_check_menu_item_new_with_label(checkItem.state.text);
|
||||
setChecked(checkItem.state.checked);
|
||||
g_signal_connect_swapped(G_OBJECT(widget), "toggled", G_CALLBACK(CheckItem_tick), (gpointer)&checkItem);
|
||||
g_signal_connect_swapped(G_OBJECT(widget), "toggled", G_CALLBACK(CheckItem_toggle), (gpointer)&checkItem);
|
||||
}
|
||||
|
||||
void pCheckItem::destructor() {
|
||||
|
@@ -1,5 +1,5 @@
|
||||
static void Item_tick(Item *self) {
|
||||
if(self->onTick) self->onTick();
|
||||
static void Item_activate(Item *self) {
|
||||
if(self->onActivate) self->onActivate();
|
||||
}
|
||||
|
||||
void pItem::setText(const string &text) {
|
||||
@@ -8,7 +8,7 @@ void pItem::setText(const string &text) {
|
||||
|
||||
void pItem::constructor() {
|
||||
widget = gtk_menu_item_new_with_label(item.state.text);
|
||||
g_signal_connect_swapped(G_OBJECT(widget), "activate", G_CALLBACK(Item_tick), (gpointer)&item);
|
||||
g_signal_connect_swapped(G_OBJECT(widget), "activate", G_CALLBACK(Item_activate), (gpointer)&item);
|
||||
}
|
||||
|
||||
void pItem::destructor() {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
static void RadioItem_tick(RadioItem *self) {
|
||||
static void RadioItem_activate(RadioItem *self) {
|
||||
for(auto &item : self->state.group) item.state.checked = (&item == self);
|
||||
if(self->p.locked == false && self->checked() && self->onTick) self->onTick();
|
||||
if(self->p.locked == false && self->checked() && self->onActivate) self->onActivate();
|
||||
}
|
||||
|
||||
bool pRadioItem::checked() {
|
||||
@@ -34,7 +34,7 @@ void pRadioItem::constructor() {
|
||||
for(auto &item : radioItem.state.group) {
|
||||
gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(item.p.widget), item.state.checked);
|
||||
}
|
||||
g_signal_connect_swapped(G_OBJECT(widget), "toggled", G_CALLBACK(RadioItem_tick), (gpointer)&radioItem);
|
||||
g_signal_connect_swapped(G_OBJECT(widget), "toggled", G_CALLBACK(RadioItem_activate), (gpointer)&radioItem);
|
||||
}
|
||||
|
||||
void pRadioItem::destructor() {
|
||||
|
@@ -34,11 +34,11 @@
|
||||
Font pOS::defaultFont;
|
||||
|
||||
Geometry pOS::availableGeometry() {
|
||||
Display *display = XOpenDisplay(0);
|
||||
XlibDisplay *display = XOpenDisplay(0);
|
||||
int screen = DefaultScreen(display);
|
||||
|
||||
static Atom atom = X11None;
|
||||
if(atom == X11None) atom = XInternAtom(display, "_NET_WORKAREA", True);
|
||||
static Atom atom = XlibNone;
|
||||
if(atom == XlibNone) atom = XInternAtom(display, "_NET_WORKAREA", True);
|
||||
|
||||
int format;
|
||||
unsigned char *data = 0;
|
||||
@@ -150,8 +150,6 @@ void pOS::processEvents() {
|
||||
}
|
||||
|
||||
void pOS::quit() {
|
||||
settings->save();
|
||||
|
||||
gtk_main_quit();
|
||||
}
|
||||
|
||||
@@ -167,13 +165,16 @@ void pOS::initialize() {
|
||||
char **argvp = argv;
|
||||
gtk_init(&argc, &argvp);
|
||||
|
||||
gtk_rc_parse_string(
|
||||
"style \"phoenix-gtk\"\n"
|
||||
"{\n"
|
||||
" GtkComboBox::appears-as-list = 1\n"
|
||||
" GtkTreeView::vertical-separator = 0\n"
|
||||
"}\n"
|
||||
//"class \"GtkComboBox\" style \"phoenix-gtk\"\n"
|
||||
"class \"GtkTreeView\" style \"phoenix-gtk\"\n"
|
||||
);
|
||||
gtk_rc_parse_string(R"(
|
||||
style "phoenix-gtk"
|
||||
{
|
||||
GtkWindow::resize-grip-width = 0
|
||||
GtkWindow::resize-grip-height = 0
|
||||
GtkTreeView::vertical-separator = 0
|
||||
GtkComboBox::appears-as-list = 1
|
||||
}
|
||||
class "GtkWindow" style "phoenix-gtk"
|
||||
class "GtkTreeView" style "phoenix-gtk"
|
||||
# class "GtkComboBox" style "phoenix-gtk"
|
||||
)");
|
||||
}
|
||||
|
@@ -1,5 +1,5 @@
|
||||
static void Button_tick(Button *self) {
|
||||
if(self->onTick) self->onTick();
|
||||
static void Button_activate(Button *self) {
|
||||
if(self->onActivate) self->onActivate();
|
||||
}
|
||||
|
||||
Geometry pButton::minimumGeometry() {
|
||||
@@ -9,11 +9,12 @@ Geometry pButton::minimumGeometry() {
|
||||
|
||||
void pButton::setText(const string &text) {
|
||||
gtk_button_set_label(GTK_BUTTON(gtkWidget), text);
|
||||
setFont(widget.state.font);
|
||||
}
|
||||
|
||||
void pButton::constructor() {
|
||||
gtkWidget = gtk_button_new();
|
||||
g_signal_connect_swapped(G_OBJECT(gtkWidget), "clicked", G_CALLBACK(Button_tick), (gpointer)&button);
|
||||
g_signal_connect_swapped(G_OBJECT(gtkWidget), "clicked", G_CALLBACK(Button_activate), (gpointer)&button);
|
||||
|
||||
setText(button.state.text);
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
static void CheckBox_tick(CheckBox *self) {
|
||||
static void CheckBox_toggle(CheckBox *self) {
|
||||
self->state.checked = self->checked();
|
||||
if(self->p.locked == false && self->onTick) self->onTick();
|
||||
if(self->p.locked == false && self->onToggle) self->onToggle();
|
||||
}
|
||||
|
||||
bool pCheckBox::checked() {
|
||||
@@ -24,7 +24,7 @@ void pCheckBox::setText(const string &text) {
|
||||
|
||||
void pCheckBox::constructor() {
|
||||
gtkWidget = gtk_check_button_new_with_label("");
|
||||
g_signal_connect_swapped(G_OBJECT(gtkWidget), "toggled", G_CALLBACK(CheckBox_tick), (gpointer)&checkBox);
|
||||
g_signal_connect_swapped(G_OBJECT(gtkWidget), "toggled", G_CALLBACK(CheckBox_toggle), (gpointer)&checkBox);
|
||||
|
||||
setChecked(checkBox.state.checked);
|
||||
setText(checkBox.state.text);
|
||||
|
@@ -130,17 +130,17 @@ bool pHexEdit::keyPress(unsigned scancode) {
|
||||
unsigned cursorY = position / lineWidth;
|
||||
unsigned cursorX = position % lineWidth;
|
||||
|
||||
if(scancode == GDK_KEY_Home) {
|
||||
if(scancode == GDK_Home) {
|
||||
setCursorPosition(cursorY * lineWidth + 10);
|
||||
return true;
|
||||
}
|
||||
|
||||
if(scancode == GDK_KEY_End) {
|
||||
if(scancode == GDK_End) {
|
||||
setCursorPosition(cursorY * lineWidth + 10 + (hexEdit.state.columns * 3 - 1));
|
||||
return true;
|
||||
}
|
||||
|
||||
if(scancode == GDK_KEY_Up) {
|
||||
if(scancode == GDK_Up) {
|
||||
if(cursorY != 0) return false;
|
||||
|
||||
signed newOffset = hexEdit.state.offset - hexEdit.state.columns;
|
||||
@@ -151,7 +151,7 @@ bool pHexEdit::keyPress(unsigned scancode) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if(scancode == GDK_KEY_Down) {
|
||||
if(scancode == GDK_Down) {
|
||||
if(cursorY != hexEdit.state.rows - 1) return false;
|
||||
|
||||
signed newOffset = hexEdit.state.offset + hexEdit.state.columns;
|
||||
@@ -162,7 +162,7 @@ bool pHexEdit::keyPress(unsigned scancode) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if(scancode == GDK_KEY_Page_Up) {
|
||||
if(scancode == GDK_Page_Up) {
|
||||
signed newOffset = hexEdit.state.offset - hexEdit.state.columns * hexEdit.state.rows;
|
||||
if(newOffset >= 0) {
|
||||
hexEdit.setOffset(newOffset);
|
||||
@@ -173,7 +173,7 @@ bool pHexEdit::keyPress(unsigned scancode) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if(scancode == GDK_KEY_Page_Down) {
|
||||
if(scancode == GDK_Page_Down) {
|
||||
signed newOffset = hexEdit.state.offset + hexEdit.state.columns * hexEdit.state.rows;
|
||||
for(unsigned n = 0; n < hexEdit.state.rows; n++) {
|
||||
if(newOffset + hexEdit.state.columns * hexEdit.state.rows - (hexEdit.state.columns - 1) <= hexEdit.state.length) {
|
||||
|
@@ -1,7 +1,7 @@
|
||||
static void HorizontalScrollBar_change(HorizontalScrollBar *self) {
|
||||
if(self->state.position == self->position()) return;
|
||||
self->state.position = self->position();
|
||||
if(self->onChange) self->onChange();
|
||||
if(self->p.locked == false && self->onChange) self->onChange();
|
||||
}
|
||||
|
||||
Geometry pHorizontalScrollBar::minimumGeometry() {
|
||||
@@ -13,9 +13,11 @@ unsigned pHorizontalScrollBar::position() {
|
||||
}
|
||||
|
||||
void pHorizontalScrollBar::setLength(unsigned length) {
|
||||
locked = true;
|
||||
length += length == 0;
|
||||
gtk_range_set_range(GTK_RANGE(gtkWidget), 0, length - 1);
|
||||
gtk_range_set_range(GTK_RANGE(gtkWidget), 0, max(1u, length - 1));
|
||||
gtk_range_set_increments(GTK_RANGE(gtkWidget), 1, length >> 3);
|
||||
locked = false;
|
||||
}
|
||||
|
||||
void pHorizontalScrollBar::setPosition(unsigned position) {
|
||||
|
@@ -14,7 +14,7 @@ unsigned pHorizontalSlider::position() {
|
||||
|
||||
void pHorizontalSlider::setLength(unsigned length) {
|
||||
length += length == 0;
|
||||
gtk_range_set_range(GTK_RANGE(gtkWidget), 0, length - 1);
|
||||
gtk_range_set_range(GTK_RANGE(gtkWidget), 0, max(1u, length - 1));
|
||||
gtk_range_set_increments(GTK_RANGE(gtkWidget), 1, length >> 3);
|
||||
}
|
||||
|
||||
|
@@ -10,10 +10,10 @@ static void ListView_change(ListView *self) {
|
||||
}
|
||||
}
|
||||
|
||||
static void ListView_tick(GtkCellRendererToggle *cell, gchar *path_string, ListView *self) {
|
||||
static void ListView_toggle(GtkCellRendererToggle *cell, gchar *path_string, ListView *self) {
|
||||
unsigned row = decimal(path_string);
|
||||
self->setChecked(row, !self->checked(row));
|
||||
if(self->onTick) self->onTick(row);
|
||||
if(self->onToggle) self->onToggle(row);
|
||||
}
|
||||
|
||||
void pListView::append(const lstring &text) {
|
||||
@@ -28,22 +28,17 @@ void pListView::autoSizeColumns() {
|
||||
|
||||
bool pListView::checked(unsigned row) {
|
||||
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(subWidget));
|
||||
GtkTreePath *path = gtk_tree_path_new_from_string(string(row));
|
||||
GtkTreeIter iter;
|
||||
bool state;
|
||||
gtk_tree_model_get_iter(model, &iter, path);
|
||||
if(gtk_tree_model_get_iter_from_string(model, &iter, string(row)) == false) return false;
|
||||
gtk_tree_model_get(model, &iter, 0, &state, -1);
|
||||
gtk_tree_path_free(path);
|
||||
return state;
|
||||
}
|
||||
|
||||
void pListView::modify(unsigned row, const lstring &text) {
|
||||
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(subWidget));
|
||||
GtkTreeIter iter;
|
||||
for(unsigned i = 0; i <= row; i++) {
|
||||
if(i == 0) gtk_tree_model_get_iter_first(model, &iter);
|
||||
else gtk_tree_model_iter_next(model, &iter);
|
||||
}
|
||||
gtk_tree_model_get_iter_from_string(model, &iter, string(row));
|
||||
for(unsigned n = 0; n < text.size(); n++) gtk_list_store_set(store, &iter, 1 + n, (const char*)text[n], -1);
|
||||
}
|
||||
|
||||
@@ -59,30 +54,18 @@ void pListView::reset() {
|
||||
|
||||
bool pListView::selected() {
|
||||
GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(subWidget));
|
||||
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(subWidget));
|
||||
GtkTreeIter iter;
|
||||
if(gtk_tree_model_get_iter_first(model, &iter) == false) return false;
|
||||
if(gtk_tree_selection_iter_is_selected(selection, &iter) == true) return true;
|
||||
for(unsigned n = 1;; n++) {
|
||||
if(gtk_tree_model_iter_next(model, &iter) == false) return false;
|
||||
if(gtk_tree_selection_iter_is_selected(selection, &iter) == true) return true;
|
||||
}
|
||||
return false;
|
||||
return gtk_tree_selection_get_selected(selection, 0, 0);
|
||||
}
|
||||
|
||||
unsigned pListView::selection() {
|
||||
if(selected() == false) return listView.state.selection;
|
||||
|
||||
GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(subWidget));
|
||||
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(subWidget));
|
||||
GtkTreeIter iter;
|
||||
if(gtk_tree_model_get_iter_first(model, &iter) == false) return 0;
|
||||
if(gtk_tree_selection_iter_is_selected(selection, &iter) == true) return 0;
|
||||
for(unsigned n = 1;; n++) {
|
||||
if(gtk_tree_model_iter_next(model, &iter) == false) return 0;
|
||||
if(gtk_tree_selection_iter_is_selected(selection, &iter) == true) return n;
|
||||
}
|
||||
return 0;
|
||||
if(gtk_tree_selection_get_selected(selection, 0, &iter) == false) return listView.state.selection;
|
||||
char *path = gtk_tree_model_get_string_from_iter(model, &iter);
|
||||
unsigned row = decimal(path);
|
||||
g_free(path);
|
||||
return row;
|
||||
}
|
||||
|
||||
void pListView::setCheckable(bool checkable) {
|
||||
@@ -91,11 +74,9 @@ void pListView::setCheckable(bool checkable) {
|
||||
|
||||
void pListView::setChecked(unsigned row, bool checked) {
|
||||
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(subWidget));
|
||||
GtkTreePath *path = gtk_tree_path_new_from_string(string(row));
|
||||
GtkTreeIter iter;
|
||||
gtk_tree_model_get_iter(model, &iter, path);
|
||||
gtk_tree_model_get_iter_from_string(model, &iter, string(row));
|
||||
gtk_list_store_set(GTK_LIST_STORE(model), &iter, 0, checked, -1);
|
||||
gtk_tree_path_free(path);
|
||||
}
|
||||
|
||||
void pListView::setHeaderText(const lstring &text) {
|
||||
@@ -117,25 +98,12 @@ void pListView::setSelected(bool selected) {
|
||||
}
|
||||
|
||||
void pListView::setSelection(unsigned row) {
|
||||
signed current = -1;
|
||||
if(selected()) current = selection();
|
||||
GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(subWidget));
|
||||
GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(subWidget));
|
||||
gtk_tree_selection_unselect_all(selection);
|
||||
|
||||
GtkTreeIter iter;
|
||||
if(gtk_tree_model_get_iter_first(model, &iter) == false) return;
|
||||
if(row == 0) {
|
||||
gtk_tree_selection_select_iter(selection, &iter);
|
||||
return;
|
||||
}
|
||||
for(unsigned n = 1;; n++) {
|
||||
if(gtk_tree_model_iter_next(model, &iter) == false) return;
|
||||
if(row == n) {
|
||||
gtk_tree_selection_select_iter(selection, &iter);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if(gtk_tree_model_get_iter_from_string(model, &iter, string(row)) == false) return;
|
||||
gtk_tree_selection_select_iter(selection, &iter);
|
||||
}
|
||||
|
||||
void pListView::constructor() {
|
||||
@@ -166,7 +134,7 @@ void pListView::constructor() {
|
||||
column[n].column = gtk_tree_view_column_new_with_attributes("", column[n].renderer, "active", n, (void*)0);
|
||||
gtk_tree_view_column_set_resizable(column[n].column, false);
|
||||
gtk_tree_view_column_set_visible(column[n].column, false);
|
||||
g_signal_connect(column[n].renderer, "toggled", G_CALLBACK(ListView_tick), (gpointer)&listView);
|
||||
g_signal_connect(column[n].renderer, "toggled", G_CALLBACK(ListView_toggle), (gpointer)&listView);
|
||||
} else {
|
||||
column[n].renderer = gtk_cell_renderer_text_new();
|
||||
column[n].column = gtk_tree_view_column_new_with_attributes("", column[n].renderer, "text", n, (void*)0);
|
||||
|
@@ -1,5 +1,5 @@
|
||||
static void RadioBox_tick(RadioBox *self) {
|
||||
if(self->p.locked == false && self->checked() && self->onTick) self->onTick();
|
||||
static void RadioBox_activate(RadioBox *self) {
|
||||
if(self->p.locked == false && self->checked() && self->onActivate) self->onActivate();
|
||||
}
|
||||
|
||||
bool pRadioBox::checked() {
|
||||
@@ -35,7 +35,7 @@ void pRadioBox::setText(const string &text) {
|
||||
|
||||
void pRadioBox::constructor() {
|
||||
gtkWidget = gtk_radio_button_new_with_label(0, "");
|
||||
g_signal_connect_swapped(G_OBJECT(gtkWidget), "toggled", G_CALLBACK(RadioBox_tick), (gpointer)&radioBox);
|
||||
g_signal_connect_swapped(G_OBJECT(gtkWidget), "toggled", G_CALLBACK(RadioBox_activate), (gpointer)&radioBox);
|
||||
|
||||
setText(radioBox.state.text);
|
||||
}
|
||||
|
@@ -1,7 +1,7 @@
|
||||
static void VerticalScrollBar_change(VerticalScrollBar *self) {
|
||||
if(self->state.position == self->position()) return;
|
||||
self->state.position = self->position();
|
||||
if(self->onChange) self->onChange();
|
||||
if(self->p.locked == false && self->onChange) self->onChange();
|
||||
}
|
||||
|
||||
Geometry pVerticalScrollBar::minimumGeometry() {
|
||||
@@ -13,9 +13,11 @@ unsigned pVerticalScrollBar::position() {
|
||||
}
|
||||
|
||||
void pVerticalScrollBar::setLength(unsigned length) {
|
||||
locked = true;
|
||||
length += length == 0;
|
||||
gtk_range_set_range(GTK_RANGE(gtkWidget), 0, length - 1);
|
||||
gtk_range_set_range(GTK_RANGE(gtkWidget), 0, max(1u, length - 1));
|
||||
gtk_range_set_increments(GTK_RANGE(gtkWidget), 1, length >> 3);
|
||||
locked = false;
|
||||
}
|
||||
|
||||
void pVerticalScrollBar::setPosition(unsigned position) {
|
||||
|
@@ -14,7 +14,7 @@ unsigned pVerticalSlider::position() {
|
||||
|
||||
void pVerticalSlider::setLength(unsigned length) {
|
||||
length += length == 0;
|
||||
gtk_range_set_range(GTK_RANGE(gtkWidget), 0, length - 1);
|
||||
gtk_range_set_range(GTK_RANGE(gtkWidget), 0, max(1u, length - 1));
|
||||
gtk_range_set_increments(GTK_RANGE(gtkWidget), 1, length >> 3);
|
||||
}
|
||||
|
||||
|
@@ -6,6 +6,7 @@ static gint Window_close(GtkWidget *widget, GdkEvent *event, Window *window) {
|
||||
}
|
||||
|
||||
static gboolean Window_expose(GtkWidget *widget, GdkEvent *event, Window *window) {
|
||||
if(window->state.backgroundColorOverride == false) return false;
|
||||
cairo_t *context = gdk_cairo_create(widget->window);
|
||||
|
||||
Color color = window->backgroundColor();
|
||||
@@ -42,6 +43,7 @@ static gboolean Window_configure(GtkWidget *widget, GdkEvent *event, Window *win
|
||||
settings->frameGeometryY = client.y - border.y;
|
||||
settings->frameGeometryWidth = border.width - client.width;
|
||||
settings->frameGeometryHeight = border.height - client.height;
|
||||
settings->save();
|
||||
}
|
||||
|
||||
//move
|
||||
@@ -240,6 +242,10 @@ void pWindow::constructor() {
|
||||
}
|
||||
|
||||
gtk_window_set_resizable(GTK_WINDOW(widget), true);
|
||||
#if GTK_MAJOR_VERSION >= 3
|
||||
gtk_window_set_has_resize_grip(GTK_WINDOW(widget), false);
|
||||
#endif
|
||||
|
||||
gtk_widget_set_app_paintable(widget, true);
|
||||
gtk_widget_add_events(widget, GDK_CONFIGURE);
|
||||
|
||||
|
@@ -18,19 +18,14 @@
|
||||
#include <QApplication>
|
||||
#include <QtGui>
|
||||
#elif defined(PHOENIX_GTK)
|
||||
#define None
|
||||
#define Window X11Window
|
||||
#define X11None 0L
|
||||
|
||||
#include <nall/xorg/guard.hpp>
|
||||
#include <gtk/gtk.h>
|
||||
#include <gdk/gdk.h>
|
||||
#include <gdk/gdkx.h>
|
||||
#include <cairo.h>
|
||||
#include <gdk/gdkkeysyms.h>
|
||||
#include <X11/Xatom.h>
|
||||
|
||||
#undef None
|
||||
#undef Window
|
||||
#include <nall/xorg/guard.hpp>
|
||||
#elif defined(PHOENIX_REFERENCE)
|
||||
#else
|
||||
#error "phoenix: unrecognized target"
|
||||
|
@@ -1,11 +1,11 @@
|
||||
#ifndef PHOENIX_HPP
|
||||
#define PHOENIX_HPP
|
||||
|
||||
#include <nall/platform.hpp>
|
||||
#include <nall/array.hpp>
|
||||
#include <nall/bmp.hpp>
|
||||
#include <nall/config.hpp>
|
||||
#include <nall/function.hpp>
|
||||
#include <nall/png.hpp>
|
||||
#include <nall/image.hpp>
|
||||
#include <nall/reference_array.hpp>
|
||||
#include <nall/stdint.hpp>
|
||||
#include <nall/string.hpp>
|
||||
|
@@ -13,7 +13,7 @@ void pCheckItem::setText(const string &text) {
|
||||
void pCheckItem::constructor() {
|
||||
qtAction = new QAction(0);
|
||||
qtAction->setCheckable(true);
|
||||
connect(qtAction, SIGNAL(triggered()), SLOT(onTick()));
|
||||
connect(qtAction, SIGNAL(triggered()), SLOT(onToggle()));
|
||||
}
|
||||
|
||||
void pCheckItem::destructor() {
|
||||
@@ -21,7 +21,7 @@ void pCheckItem::destructor() {
|
||||
delete qtAction;
|
||||
}
|
||||
|
||||
void pCheckItem::onTick() {
|
||||
void pCheckItem::onToggle() {
|
||||
checkItem.state.checked = checked();
|
||||
if(checkItem.onTick) checkItem.onTick();
|
||||
if(checkItem.onToggle) checkItem.onToggle();
|
||||
}
|
||||
|
@@ -4,7 +4,7 @@ void pItem::setText(const string &text) {
|
||||
|
||||
void pItem::constructor() {
|
||||
qtAction = new QAction(0);
|
||||
connect(qtAction, SIGNAL(triggered()), SLOT(onTick()));
|
||||
connect(qtAction, SIGNAL(triggered()), SLOT(onActivate()));
|
||||
}
|
||||
|
||||
void pItem::destructor() {
|
||||
@@ -12,6 +12,6 @@ void pItem::destructor() {
|
||||
delete qtAction;
|
||||
}
|
||||
|
||||
void pItem::onTick() {
|
||||
if(item.onTick) item.onTick();
|
||||
void pItem::onActivate() {
|
||||
if(item.onActivate) item.onActivate();
|
||||
}
|
||||
|
@@ -25,7 +25,7 @@ void pRadioItem::constructor() {
|
||||
qtAction->setCheckable(true);
|
||||
qtAction->setActionGroup(qtGroup);
|
||||
qtAction->setChecked(true);
|
||||
connect(qtAction, SIGNAL(triggered()), SLOT(onTick()));
|
||||
connect(qtAction, SIGNAL(triggered()), SLOT(onActivate()));
|
||||
}
|
||||
|
||||
void pRadioItem::destructor() {
|
||||
@@ -33,9 +33,9 @@ void pRadioItem::destructor() {
|
||||
delete qtAction;
|
||||
}
|
||||
|
||||
void pRadioItem::onTick() {
|
||||
void pRadioItem::onActivate() {
|
||||
if(radioItem.state.checked == false) {
|
||||
setChecked();
|
||||
if(locked == false && radioItem.onTick) radioItem.onTick();
|
||||
if(locked == false && radioItem.onActivate) radioItem.onActivate();
|
||||
}
|
||||
}
|
||||
|
@@ -113,8 +113,6 @@ void pOS::processEvents() {
|
||||
}
|
||||
|
||||
void pOS::quit() {
|
||||
settings->save();
|
||||
|
||||
QApplication::quit();
|
||||
//note: QApplication cannot be deleted; or libQtGui will crash
|
||||
qtApplication = 0;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user