diff --git a/bsnes/nall/reference_array.hpp b/bsnes/nall/reference_array.hpp index bf96802d..7c915090 100755 --- a/bsnes/nall/reference_array.hpp +++ b/bsnes/nall/reference_array.hpp @@ -7,9 +7,11 @@ namespace nall { template struct reference_array { + struct exception_out_of_bounds{}; + protected: - typedef typename std::remove_reference::type *Tptr; - Tptr *pool; + typedef typename std::remove_reference::type type_t; + type_t **pool; unsigned poolsize, buffersize; public: @@ -26,7 +28,7 @@ namespace nall { void reserve(unsigned newsize) { if(newsize == poolsize) return; - pool = (Tptr*)realloc(pool, newsize * sizeof(T)); + pool = (type_t**)realloc(pool, sizeof(type_t*) * newsize); poolsize = newsize; buffersize = min(buffersize, newsize); } @@ -37,13 +39,13 @@ namespace nall { } template - bool append(const T& data, Args&&... args) { + bool append(type_t& data, Args&&... args) { bool result = append(data); append(std::forward(args)...); return result; } - bool append(const T data) { + bool append(type_t& data) { for(unsigned index = 0; index < buffersize; index++) { if(pool[index] == &data) return false; } @@ -54,7 +56,7 @@ namespace nall { return true; } - bool remove(const T data) { + bool remove(type_t& data) { for(unsigned index = 0; index < buffersize; index++) { if(pool[index] == &data) { for(unsigned i = index; i < buffersize - 1; i++) pool[i] = pool[i + 1]; @@ -77,8 +79,8 @@ namespace nall { if(pool) free(pool); buffersize = source.buffersize; poolsize = source.poolsize; - pool = (Tptr*)malloc(sizeof(T) * poolsize); - memcpy(pool, source.pool, sizeof(T) * buffersize); + pool = (type_t**)malloc(sizeof(type_t*) * poolsize); + memcpy(pool, source.pool, sizeof(type_t*) * buffersize); return *this; } @@ -92,20 +94,20 @@ namespace nall { return *this; } - inline T operator[](unsigned index) { - if(index >= buffersize) throw "reference_array[] out of bounds"; + inline type_t& operator[](unsigned index) { + if(index >= buffersize) throw exception_out_of_bounds(); return *pool[index]; } - inline const T operator[](unsigned index) const { - if(index >= buffersize) throw "reference_array[] out of bounds"; + inline type_t& operator[](unsigned index) const { + if(index >= buffersize) throw exception_out_of_bounds(); return *pool[index]; } //iteration struct iterator { bool operator!=(const iterator &source) const { return index != source.index; } - T& operator*() { return array.operator[](index); } + type_t& operator*() { return array.operator[](index); } iterator& operator++() { index++; return *this; } iterator(const reference_array &array, unsigned index) : array(array), index(index) {} private: diff --git a/bsnes/nes/cartridge/board/board.cpp b/bsnes/nes/cartridge/board/board.cpp index 091da556..00e5917b 100755 --- a/bsnes/nes/cartridge/board/board.cpp +++ b/bsnes/nes/cartridge/board/board.cpp @@ -1,4 +1,7 @@ #include "bandai-fcg.cpp" +#include "konami-vrc1.cpp" +#include "konami-vrc2.cpp" +#include "konami-vrc3.cpp" #include "konami-vrc4.cpp" #include "konami-vrc6.cpp" #include "konami-vrc7.cpp" @@ -8,6 +11,7 @@ #include "nes-exrom.cpp" #include "nes-fxrom.cpp" #include "nes-gxrom.cpp" +#include "nes-hkrom.cpp" #include "nes-nrom.cpp" #include "nes-pxrom.cpp" #include "nes-sxrom.cpp" @@ -113,6 +117,9 @@ Board* Board::load(const string &markup, const uint8_t *data, unsigned size) { if(type == "BANDAI-FCG") return new BandaiFCG(board, data, size); + if(type == "KONAMI-VRC-1") return new KonamiVRC1(board, data, size); + if(type == "KONAMI-VRC-2") return new KonamiVRC2(board, data, size); + if(type == "KONAMI-VRC-3") return new KonamiVRC3(board, data, size); if(type == "KONAMI-VRC-4") return new KonamiVRC4(board, data, size); if(type == "KONAMI-VRC-6") return new KonamiVRC6(board, data, size); if(type == "KONAMI-VRC-7") return new KonamiVRC7(board, data, size); @@ -137,6 +144,8 @@ Board* Board::load(const string &markup, const uint8_t *data, unsigned size) { if(type == "NES-GNROM" ) return new NES_GxROM(board, data, size); if(type == "NES-MHROM" ) return new NES_GxROM(board, data, size); + if(type == "NES-HKROM" ) return new NES_HKROM(board, data, size); + if(type == "NES-NROM-128") return new NES_NROM(board, data, size); if(type == "NES-NROM-256") return new NES_NROM(board, data, size); diff --git a/bsnes/nes/cartridge/board/konami-vrc1.cpp b/bsnes/nes/cartridge/board/konami-vrc1.cpp new file mode 100755 index 00000000..d473e6ba --- /dev/null +++ b/bsnes/nes/cartridge/board/konami-vrc1.cpp @@ -0,0 +1,40 @@ +struct KonamiVRC1 : Board { + +VRC1 vrc1; + +uint8 prg_read(unsigned addr) { + if(addr & 0x8000) return prgrom.read(vrc1.prg_addr(addr)); + return cpu.mdr(); +} + +void prg_write(unsigned addr, uint8 data) { + if(addr & 0x8000) return vrc1.reg_write(addr, data); +} + +uint8 chr_read(unsigned addr) { + if(addr & 0x2000) return ppu.ciram_read(vrc1.ciram_addr(addr)); + return Board::chr_read(vrc1.chr_addr(addr)); +} + +void chr_write(unsigned addr, uint8 data) { + if(addr & 0x2000) return ppu.ciram_write(vrc1.ciram_addr(addr), data); + return Board::chr_write(vrc1.chr_addr(addr), data); +} + +void power() { + vrc1.power(); +} + +void reset() { + vrc1.reset(); +} + +void serialize(serializer &s) { + Board::serialize(s); + vrc1.serialize(s); +} + +KonamiVRC1(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), vrc1(*this) { +} + +}; diff --git a/bsnes/nes/cartridge/board/konami-vrc2.cpp b/bsnes/nes/cartridge/board/konami-vrc2.cpp new file mode 100755 index 00000000..5953377b --- /dev/null +++ b/bsnes/nes/cartridge/board/konami-vrc2.cpp @@ -0,0 +1,45 @@ +struct KonamiVRC2 : Board { + +VRC2 vrc2; +bool latch; + +uint8 prg_read(unsigned addr) { + if(addr == 0x6000) return latch; + if(addr & 0x8000) return prgrom.read(vrc2.prg_addr(addr)); + return cpu.mdr(); +} + +void prg_write(unsigned addr, uint8 data) { + if(addr == 0x6000) latch = data & 0x01; + if(addr & 0x8000) return vrc2.reg_write(addr, data); +} + +uint8 chr_read(unsigned addr) { + if(addr & 0x2000) return ppu.ciram_read(vrc2.ciram_addr(addr)); + return Board::chr_read(vrc2.chr_addr(addr)); +} + +void chr_write(unsigned addr, uint8 data) { + if(addr & 0x2000) return ppu.ciram_write(vrc2.ciram_addr(addr), data); + return Board::chr_write(vrc2.chr_addr(addr), data); +} + +void power() { + vrc2.power(); +} + +void reset() { + vrc2.reset(); + latch = 0; +} + +void serialize(serializer &s) { + Board::serialize(s); + vrc2.serialize(s); + s.integer(latch); +} + +KonamiVRC2(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), vrc2(*this) { +} + +}; diff --git a/bsnes/nes/cartridge/board/konami-vrc3.cpp b/bsnes/nes/cartridge/board/konami-vrc3.cpp new file mode 100755 index 00000000..9aef5df4 --- /dev/null +++ b/bsnes/nes/cartridge/board/konami-vrc3.cpp @@ -0,0 +1,57 @@ +struct KonamiVRC3 : Board { + +struct Settings { + bool mirror; //0 = horizontal, 1 = vertical +} settings; + +VRC3 vrc3; + +void main() { + vrc3.main(); +} + +uint8 prg_read(unsigned addr) { + if((addr & 0xe000) == 0x6000) return prgram.read(addr & 0x1fff); + if(addr & 0x8000) return prgrom.read(vrc3.prg_addr(addr)); + return cpu.mdr(); +} + +void prg_write(unsigned addr, uint8 data) { + if((addr & 0xe000) == 0x6000) return prgram.write(addr & 0x1fff, data); + if(addr & 0x8000) return vrc3.reg_write(addr, data); +} + +uint8 chr_read(unsigned addr) { + if(addr & 0x2000) { + if(settings.mirror == 0) addr = ((addr & 0x0800) >> 1) | (addr & 0x03ff); + return ppu.ciram_read(addr & 0x07ff); + } + return chrram.read(addr); +} + +void chr_write(unsigned addr, uint8 data) { + if(addr & 0x2000) { + if(settings.mirror == 0) addr = ((addr & 0x0800) >> 1) | (addr & 0x03ff); + return ppu.ciram_write(addr & 0x07ff, data); + } + return chrram.write(addr, data); +} + +void power() { + vrc3.power(); +} + +void reset() { + vrc3.reset(); +} + +void serialize(serializer &s) { + Board::serialize(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; +} + +}; diff --git a/bsnes/nes/cartridge/board/nes-hkrom.cpp b/bsnes/nes/cartridge/board/nes-hkrom.cpp new file mode 100755 index 00000000..8eb13a53 --- /dev/null +++ b/bsnes/nes/cartridge/board/nes-hkrom.cpp @@ -0,0 +1,48 @@ +struct NES_HKROM : Board { + +MMC6 mmc6; + +void main() { + mmc6.main(); +} + +uint8 prg_read(unsigned addr) { + if((addr & 0xf000) == 0x7000) return mmc6.ram_read(addr); + if(addr & 0x8000) return prgrom.read(mmc6.prg_addr(addr)); + return cpu.mdr(); +} + +void prg_write(unsigned addr, uint8 data) { + if((addr & 0xf000) == 0x7000) return mmc6.ram_write(addr, data); + if(addr & 0x8000) return mmc6.reg_write(addr, data); +} + +uint8 chr_read(unsigned addr) { + mmc6.irq_test(addr); + if(addr & 0x2000) return ppu.ciram_read(mmc6.ciram_addr(addr)); + return Board::chr_read(mmc6.chr_addr(addr)); +} + +void chr_write(unsigned addr, uint8 data) { + mmc6.irq_test(addr); + if(addr & 0x2000) return ppu.ciram_write(mmc6.ciram_addr(addr), data); + return Board::chr_write(mmc6.chr_addr(addr), data); +} + +void power() { + mmc6.power(); +} + +void reset() { + mmc6.reset(); +} + +void serialize(serializer &s) { + Board::serialize(s); + mmc6.serialize(s); +} + +NES_HKROM(BML::Node &board, const uint8_t *data, unsigned size) : Board(board, data, size), mmc6(*this) { +} + +}; diff --git a/bsnes/nes/cartridge/board/nes-txrom.cpp b/bsnes/nes/cartridge/board/nes-txrom.cpp index 66daf49e..24416f01 100755 --- a/bsnes/nes/cartridge/board/nes-txrom.cpp +++ b/bsnes/nes/cartridge/board/nes-txrom.cpp @@ -32,53 +32,7 @@ uint8 prg_read(unsigned addr) { void prg_write(unsigned addr, uint8 data) { if((addr & 0xe000) == 0x6000) return mmc3.ram_write(addr, data); - - switch(addr & 0xe001) { - case 0x8000: - mmc3.chr_mode = data & 0x80; - mmc3.prg_mode = data & 0x40; - mmc3.bank_select = data & 0x07; - break; - - case 0x8001: - switch(mmc3.bank_select) { - case 0: mmc3.chr_bank[0] = data & ~1; break; - case 1: mmc3.chr_bank[1] = data & ~1; break; - case 2: mmc3.chr_bank[2] = data; break; - case 3: mmc3.chr_bank[3] = data; break; - case 4: mmc3.chr_bank[4] = data; break; - case 5: mmc3.chr_bank[5] = data; break; - case 6: mmc3.prg_bank[0] = data & 0x3f; break; - case 7: mmc3.prg_bank[1] = data & 0x3f; break; - } - break; - - case 0xa000: - mmc3.mirror = data & 0x01; - break; - - case 0xa001: - mmc3.ram_enable = data & 0x80; - mmc3.ram_write_protect = data & 0x40; - break; - - case 0xc000: - mmc3.irq_latch = data; - break; - - case 0xc001: - mmc3.irq_counter = 0; - break; - - case 0xe000: - mmc3.irq_enable = false; - mmc3.irq_line = 0; - break; - - case 0xe001: - mmc3.irq_enable = true; - break; - } + if(addr & 0x8000) return mmc3.reg_write(addr, data); } uint8 chr_read(unsigned addr) { diff --git a/bsnes/nes/cartridge/chip/chip.cpp b/bsnes/nes/cartridge/chip/chip.cpp index 5aa18fde..1d0f9fb6 100755 --- a/bsnes/nes/cartridge/chip/chip.cpp +++ b/bsnes/nes/cartridge/chip/chip.cpp @@ -1,6 +1,10 @@ #include "mmc1.cpp" #include "mmc3.cpp" #include "mmc5.cpp" +#include "mmc6.cpp" +#include "vrc1.cpp" +#include "vrc2.cpp" +#include "vrc3.cpp" #include "vrc4.cpp" #include "vrc6.cpp" #include "vrc7.cpp" diff --git a/bsnes/nes/cartridge/chip/mmc3.cpp b/bsnes/nes/cartridge/chip/mmc3.cpp index 10dbcf18..d4203a0a 100755 --- a/bsnes/nes/cartridge/chip/mmc3.cpp +++ b/bsnes/nes/cartridge/chip/mmc3.cpp @@ -89,6 +89,55 @@ void ram_write(unsigned addr, uint8 data) { if(ram_enable && !ram_write_protect) board.prgram.data[addr & 0x1fff] = data; } +void reg_write(unsigned addr, uint8 data) { + switch(addr & 0xe001) { + case 0x8000: + chr_mode = data & 0x80; + prg_mode = data & 0x40; + bank_select = data & 0x07; + break; + + case 0x8001: + switch(bank_select) { + case 0: chr_bank[0] = data & ~1; break; + case 1: chr_bank[1] = data & ~1; break; + case 2: chr_bank[2] = data; break; + case 3: chr_bank[3] = data; break; + case 4: chr_bank[4] = data; break; + case 5: chr_bank[5] = data; break; + case 6: prg_bank[0] = data & 0x3f; break; + case 7: prg_bank[1] = data & 0x3f; break; + } + break; + + case 0xa000: + mirror = data & 0x01; + break; + + case 0xa001: + ram_enable = data & 0x80; + ram_write_protect = data & 0x40; + break; + + case 0xc000: + irq_latch = data; + break; + + case 0xc001: + irq_counter = 0; + break; + + case 0xe000: + irq_enable = false; + irq_line = 0; + break; + + case 0xe001: + irq_enable = true; + break; + } +} + void power() { } diff --git a/bsnes/nes/cartridge/chip/mmc6.cpp b/bsnes/nes/cartridge/chip/mmc6.cpp new file mode 100755 index 00000000..ce43d0dd --- /dev/null +++ b/bsnes/nes/cartridge/chip/mmc6.cpp @@ -0,0 +1,200 @@ +struct MMC6 : Chip { + +bool chr_mode; +bool prg_mode; +bool ram_enable; +uint3 bank_select; +uint8 prg_bank[2]; +uint8 chr_bank[6]; +bool mirror; +bool ram_readable[2]; +bool ram_writable[2]; +uint8 irq_latch; +uint8 irq_counter; +bool irq_enable; +unsigned irq_delay; +bool irq_line; + +uint16 chr_abus; + +void main() { + while(true) { + if(scheduler.sync == Scheduler::SynchronizeMode::All) { + scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); + } + + if(irq_delay) irq_delay--; + cpu.set_irq_line(irq_line); + tick(); + } +} + +void irq_test(unsigned addr) { + if(!(chr_abus & 0x1000) && (addr & 0x1000)) { + if(irq_delay == 0) { + if(irq_counter == 0) { + irq_counter = irq_latch; + } else if(--irq_counter == 0) { + if(irq_enable) irq_line = 1; + } + } + irq_delay = 6; + } + chr_abus = addr; +} + +unsigned prg_addr(unsigned addr) const { + switch((addr >> 13) & 3) { + case 0: + if(prg_mode == 1) return (0x3e << 13) | (addr & 0x1fff); + return (prg_bank[0] << 13) | (addr & 0x1fff); + case 1: + return (prg_bank[1] << 13) | (addr & 0x1fff); + case 2: + if(prg_mode == 0) return (0x3e << 13) | (addr & 0x1fff); + return (prg_bank[0] << 13) | (addr & 0x1fff); + case 3: + return (0x3f << 13) | (addr & 0x1fff); + } +} + +unsigned chr_addr(unsigned addr) const { + if(chr_mode == 0) { + if(addr <= 0x07ff) return (chr_bank[0] << 10) | (addr & 0x07ff); + if(addr <= 0x0fff) return (chr_bank[1] << 10) | (addr & 0x07ff); + if(addr <= 0x13ff) return (chr_bank[2] << 10) | (addr & 0x03ff); + if(addr <= 0x17ff) return (chr_bank[3] << 10) | (addr & 0x03ff); + if(addr <= 0x1bff) return (chr_bank[4] << 10) | (addr & 0x03ff); + if(addr <= 0x1fff) return (chr_bank[5] << 10) | (addr & 0x03ff); + } else { + if(addr <= 0x03ff) return (chr_bank[2] << 10) | (addr & 0x03ff); + if(addr <= 0x07ff) return (chr_bank[3] << 10) | (addr & 0x03ff); + if(addr <= 0x0bff) return (chr_bank[4] << 10) | (addr & 0x03ff); + if(addr <= 0x0fff) return (chr_bank[5] << 10) | (addr & 0x03ff); + if(addr <= 0x17ff) return (chr_bank[0] << 10) | (addr & 0x07ff); + if(addr <= 0x1fff) return (chr_bank[1] << 10) | (addr & 0x07ff); + } +} + +unsigned ciram_addr(unsigned addr) const { + if(mirror == 0) return ((addr & 0x0400) >> 0) | (addr & 0x03ff); + if(mirror == 1) return ((addr & 0x0800) >> 1) | (addr & 0x03ff); +} + +uint8 ram_read(unsigned addr) { + if(ram_enable == false) return cpu.mdr(); + if(ram_readable[0] == false && ram_readable[1] == false) return cpu.mdr(); + bool region = addr & 0x0200; + if(ram_readable[region] == false) return 0x00; + return board.prgram.read((region * 0x0200) + (addr & 0x01ff)); +} + +void ram_write(unsigned addr, uint8 data) { + if(ram_enable == false) return; + bool region = addr & 0x0200; + if(ram_writable[region] == false) return; + return board.prgram.write((region * 0x0200) + (addr & 0x01ff), data); +} + +void reg_write(unsigned addr, uint8 data) { + switch(addr & 0xe001) { + case 0x8000: + chr_mode = data & 0x80; + prg_mode = data & 0x40; + ram_enable = data & 0x20; + bank_select = data & 0x07; + if(ram_enable == false) { + for(auto &n : ram_readable) n = false; + for(auto &n : ram_writable) n = false; + } + break; + + case 0x8001: + switch(bank_select) { + case 0: chr_bank[0] = data & ~1; break; + case 1: chr_bank[1] = data & ~1; break; + case 2: chr_bank[2] = data; break; + case 3: chr_bank[3] = data; break; + case 4: chr_bank[4] = data; break; + case 5: chr_bank[5] = data; break; + case 6: prg_bank[0] = data & 0x3f; break; + case 7: prg_bank[1] = data & 0x3f; break; + } + break; + + case 0xa000: + mirror = data & 0x01; + break; + + case 0xa001: + if(ram_enable == false) break; + ram_readable[1] = data & 0x80; + ram_writable[1] = data & 0x40; + ram_readable[0] = data & 0x20; + ram_writable[0] = data & 0x10; + break; + + case 0xc000: + irq_latch = data; + break; + + case 0xc001: + irq_counter = 0; + break; + + case 0xe000: + irq_enable = false; + irq_line = 0; + break; + + case 0xe001: + irq_enable = true; + break; + } +} + +void power() { +} + +void reset() { + chr_mode = 0; + prg_mode = 0; + ram_enable = 0; + bank_select = 0; + for(auto &n : prg_bank) n = 0; + for(auto &n : chr_bank) n = 0; + mirror = 0; + for(auto &n : ram_readable) n = 0; + for(auto &n : ram_writable) n = 0; + irq_latch = 0; + irq_counter = 0; + irq_enable = 0; + irq_delay = 0; + irq_line = 0; + + chr_abus = 0; +} + +void serialize(serializer &s) { + s.integer(chr_mode); + s.integer(prg_mode); + s.integer(ram_enable); + s.integer(bank_select); + for(auto &n : prg_bank) s.integer(n); + for(auto &n : chr_bank) s.integer(n); + s.integer(mirror); + for(auto &n : ram_readable) s.integer(n); + for(auto &n : ram_writable) s.integer(n); + s.integer(irq_latch); + s.integer(irq_counter); + s.integer(irq_enable); + s.integer(irq_delay); + s.integer(irq_line); + + s.integer(chr_abus); +} + +MMC6(Board &board) : Chip(board) { +} + +}; diff --git a/bsnes/nes/cartridge/chip/vrc1.cpp b/bsnes/nes/cartridge/chip/vrc1.cpp new file mode 100755 index 00000000..a64c0fa1 --- /dev/null +++ b/bsnes/nes/cartridge/chip/vrc1.cpp @@ -0,0 +1,80 @@ +struct VRC1 : Chip { + +uint4 prg_bank[3]; +uint4 chr_banklo[2]; +bool chr_bankhi[2]; +bool mirror; + +unsigned prg_addr(unsigned addr) const { + unsigned bank = 0x0f; + if((addr & 0xe000) == 0x8000) bank = prg_bank[0]; + if((addr & 0xe000) == 0xa000) bank = prg_bank[1]; + if((addr & 0xe000) == 0xc000) bank = prg_bank[2]; + return (bank * 0x2000) + (addr & 0x1fff); +} + +unsigned chr_addr(unsigned addr) const { + unsigned bank = chr_banklo[(bool)(addr & 0x1000)]; + bank |= chr_bankhi[(bool)(addr & 0x1000)] << 4; + return (bank * 0x1000) + (addr & 0x0fff); +} + +unsigned ciram_addr(unsigned addr) const { + switch(mirror) { + case 0: return ((addr & 0x0400) >> 0) | (addr & 0x03ff); //vertical mirroring + case 1: return ((addr & 0x0800) >> 1) | (addr & 0x03ff); //horizontal mirroring + } + throw; +} + +void reg_write(unsigned addr, uint8 data) { + switch(addr & 0xf000) { + case 0x8000: + prg_bank[0] = data & 0x0f; + break; + + case 0x9000: + chr_bankhi[1] = data & 0x04; + chr_bankhi[0] = data & 0x02; + mirror = data & 0x01; + break; + + case 0xa000: + prg_bank[1] = data & 0x0f; + break; + + case 0xc000: + prg_bank[2] = data & 0x0f; + break; + + case 0xe000: + chr_banklo[0] = data & 0x0f; + break; + + case 0xf000: + chr_banklo[1] = data & 0x0f; + break; + } +} + +void power() { +} + +void reset() { + for(auto &n : prg_bank) n = 0; + for(auto &n : chr_banklo) n = 0; + for(auto &n : chr_bankhi) n = 0; + mirror = 0; +} + +void serialize(serializer &s) { + for(auto &n : prg_bank) s.integer(n); + for(auto &n : chr_banklo) s.integer(n); + for(auto &n : chr_bankhi) s.integer(n); + s.integer(mirror); +} + +VRC1(Board &board) : Chip(board) { +} + +}; diff --git a/bsnes/nes/cartridge/chip/vrc2.cpp b/bsnes/nes/cartridge/chip/vrc2.cpp new file mode 100755 index 00000000..6d46e1e6 --- /dev/null +++ b/bsnes/nes/cartridge/chip/vrc2.cpp @@ -0,0 +1,91 @@ +struct VRC2 : Chip { + +uint4 prg_bank[2]; +uint8 chr_bank[8]; +uint2 mirror; + +unsigned prg_addr(unsigned addr) const { + unsigned bank; + switch(addr & 0xe000) { + case 0x8000: bank = prg_bank[0]; break; + case 0xa000: bank = prg_bank[1]; break; + case 0xc000: bank = 0x0e; break; + case 0xe000: bank = 0x0f; break; + } + return (bank * 0x2000) + (addr & 0x1fff); +} + +unsigned chr_addr(unsigned addr) const { + unsigned bank = chr_bank[addr / 0x0400]; + return (bank * 0x0400) + (addr & 0x03ff); +} + +unsigned ciram_addr(unsigned addr) const { + switch(mirror) { + case 0: return ((addr & 0x0400) >> 0) | (addr & 0x03ff); //vertical mirroring + case 1: return ((addr & 0x0800) >> 1) | (addr & 0x03ff); //horizontal mirroring + case 2: return 0x0000 | (addr & 0x03ff); //one-screen mirroring (first) + case 3: return 0x0400 | (addr & 0x03ff); //one-screen mirroring (second) + } + throw; +} + +void reg_write(unsigned addr, uint8 data) { + switch(addr) { + case 0x8000: case 0x8001: case 0x8002: case 0x8003: + prg_bank[0] = data & 0x0f; + break; + + case 0x9000: case 0x9001: case 0x9002: case 0x9003: + mirror = data & 0x03; + break; + + case 0xa000: case 0xa001: case 0xa002: case 0xa003: + prg_bank[1] = data & 0x0f; + break; + + case 0xb000: chr_bank[0] = (chr_bank[0] & 0xf0) | ((data & 0x0f) << 0); break; + case 0xb001: chr_bank[0] = (chr_bank[0] & 0x0f) | ((data & 0x0f) << 4); break; + + case 0xb002: chr_bank[1] = (chr_bank[1] & 0xf0) | ((data & 0x0f) << 0); break; + case 0xb003: chr_bank[1] = (chr_bank[1] & 0x0f) | ((data & 0x0f) << 4); break; + + case 0xc000: chr_bank[2] = (chr_bank[2] & 0xf0) | ((data & 0x0f) << 0); break; + case 0xc001: chr_bank[2] = (chr_bank[2] & 0x0f) | ((data & 0x0f) << 4); break; + + case 0xc002: chr_bank[3] = (chr_bank[3] & 0xf0) | ((data & 0x0f) << 0); break; + case 0xc003: chr_bank[3] = (chr_bank[3] & 0x0f) | ((data & 0x0f) << 4); break; + + case 0xd000: chr_bank[4] = (chr_bank[4] & 0xf0) | ((data & 0x0f) << 0); break; + case 0xd001: chr_bank[4] = (chr_bank[4] & 0x0f) | ((data & 0x0f) << 4); break; + + case 0xd002: chr_bank[5] = (chr_bank[5] & 0xf0) | ((data & 0x0f) << 0); break; + case 0xd003: chr_bank[5] = (chr_bank[5] & 0x0f) | ((data & 0x0f) << 4); break; + + case 0xe000: chr_bank[6] = (chr_bank[6] & 0xf0) | ((data & 0x0f) << 0); break; + case 0xe001: chr_bank[6] = (chr_bank[6] & 0x0f) | ((data & 0x0f) << 4); break; + + case 0xe002: chr_bank[7] = (chr_bank[7] & 0xf0) | ((data & 0x0f) << 0); break; + case 0xe003: chr_bank[7] = (chr_bank[7] & 0x0f) | ((data & 0x0f) << 4); break; + } +} + +void power() { +} + +void reset() { + for(auto &n : prg_bank) n = 0; + for(auto &n : chr_bank) n = 0; + mirror = 0; +} + +void serialize(serializer &s) { + for(auto &n : prg_bank) s.integer(n); + for(auto &n : chr_bank) s.integer(n); + s.integer(mirror); +} + +VRC2(Board &board) : Chip(board) { +} + +}; diff --git a/bsnes/nes/cartridge/chip/vrc3.cpp b/bsnes/nes/cartridge/chip/vrc3.cpp new file mode 100755 index 00000000..7ced8972 --- /dev/null +++ b/bsnes/nes/cartridge/chip/vrc3.cpp @@ -0,0 +1,100 @@ +struct VRC3 : Chip { + +uint4 prg_bank; +bool irq_mode; +bool irq_enable; +bool irq_acknowledge; +uint16 irq_latch; +struct { + union { + uint16 w; + struct { uint8 order_lsb2(l, h); }; + }; +} irq_counter; +bool irq_line; + +void main() { + while(true) { + if(scheduler.sync == Scheduler::SynchronizeMode::All) { + scheduler.exit(Scheduler::ExitReason::SynchronizeEvent); + } + + if(irq_enable) { + if(irq_mode == 0) { //16-bit + if(++irq_counter.w == 0) { + irq_line = 1; + irq_enable = irq_acknowledge; + irq_counter.w = irq_latch; + } + } + if(irq_mode == 1) { //8-bit + if(++irq_counter.l == 0) { + irq_line = 1; + irq_enable = irq_acknowledge; + irq_counter.l = irq_latch; + } + } + } + + cpu.set_irq_line(irq_line); + tick(); + } +} + +unsigned prg_addr(unsigned addr) const { + unsigned bank = (addr < 0xc000 ? (unsigned)prg_bank : 0x0f); + return (bank * 0x4000) + (addr & 0x3fff); +} + +void reg_write(unsigned addr, uint8 data) { + switch(addr & 0xf000) { + case 0x8000: irq_latch = (irq_latch & 0xfff0) | ((data & 0x0f) << 0); break; + case 0x9000: irq_latch = (irq_latch & 0xff0f) | ((data & 0x0f) << 4); break; + case 0xa000: irq_latch = (irq_latch & 0xf0ff) | ((data & 0x0f) << 8); break; + case 0xb000: irq_latch = (irq_latch & 0x0fff) | ((data & 0x0f) << 12); break; + + case 0xc000: + irq_mode = data & 0x04; + irq_enable = data & 0x02; + irq_acknowledge = data & 0x01; + if(irq_enable) irq_counter.w = irq_latch; + break; + + case 0xd000: + irq_line = 0; + irq_enable = irq_acknowledge; + break; + + case 0xf000: + prg_bank = data & 0x0f; + break; + } +} + +void power() { +} + +void reset() { + prg_bank = 0; + irq_mode = 0; + irq_enable = 0; + irq_acknowledge = 0; + irq_latch = 0; + irq_counter.w = 0; + irq_line = 0; +} + +void serialize(serializer &s) { + s.integer(prg_bank); + s.integer(irq_mode); + s.integer(irq_enable); + s.integer(irq_acknowledge); + s.integer(irq_latch); + s.integer(irq_counter.w); + s.integer(irq_line); +} + +VRC3(Board &board) : Chip(board) { +} + +}; diff --git a/bsnes/nes/cartridge/chip/vrc4.cpp b/bsnes/nes/cartridge/chip/vrc4.cpp index 0bd6c2a0..4a9c3290 100755 --- a/bsnes/nes/cartridge/chip/vrc4.cpp +++ b/bsnes/nes/cartridge/chip/vrc4.cpp @@ -140,6 +140,7 @@ unsigned ciram_addr(unsigned addr) const { case 2: return 0x0000 | (addr & 0x03ff); //one-screen mirroring (first) case 3: return 0x0400 | (addr & 0x03ff); //one-screen mirroring (second) } + throw; } void power() { diff --git a/bsnes/nes/cartridge/ines.cpp b/bsnes/nes/cartridge/ines.cpp index 46bb0916..cf1e3f95 100755 --- a/bsnes/nes/cartridge/ines.cpp +++ b/bsnes/nes/cartridge/ines.cpp @@ -14,7 +14,7 @@ static string iNES(const uint8_t *data, unsigned size) { unsigned prgram = 0; unsigned chrram = chrrom == 0 ? 8192 : 0; -//print("iNES mapper: ", mapper, "\n"); + print("iNES mapper: ", mapper, "\n"); output.append("cartridge\n"); @@ -41,9 +41,14 @@ static string iNES(const uint8_t *data, unsigned size) { break; case 4: + //MMC3 output.append("\tboard type:NES-TLROM\n"); output.append("\t\tchip type:MMC3B\n"); prgram = 8192; + //MMC6 + //output.append("\tboard type:NES-HKROM\n"); + //output.append("\t\tchip type:MMC6\n"); + //prgram = 1024; break; case 5: @@ -76,6 +81,10 @@ static string iNES(const uint8_t *data, unsigned size) { case 21: case 23: case 25: + //VRC2 + //output.append("\tboard type:KONAMI-VRC-2\n"); + //output.append("\t\tchip type:VRC2\n"); + //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"); @@ -109,6 +118,18 @@ static string iNES(const uint8_t *data, unsigned size) { 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"); + prgram = 8192; + break; + + case 75: + output.append("\tboard type:KONAMI-VRC-1\n"); + output.append("\t\tchip type:VRC1\n"); + break; + case 85: output.append("\tboard type:KONAMI-VRC-7\n"); output.append("\t\tchip type:VRC7\n"); @@ -119,7 +140,7 @@ static string iNES(const uint8_t *data, unsigned size) { output.append("\t\tprg rom=", prgrom, " ram=", prgram, "\n"); output.append("\t\tchr rom=", chrrom, " ram=", chrram, "\n"); -//print(output, "\n"); + print(output, "\n"); return output; } diff --git a/bsnes/nes/cpu/core/disassembler.cpp b/bsnes/nes/cpu/core/disassembler.cpp index 83fa8b68..24095bc9 100755 --- a/bsnes/nes/cpu/core/disassembler.cpp +++ b/bsnes/nes/cpu/core/disassembler.cpp @@ -162,6 +162,7 @@ string CPU::disassemble() { op(0xe6, inc, zpg); op(0xe8, inx, imp); op(0xe9, sbc, imm); + op(0xea, nop, imp); op(0xec, cpx, abs); op(0xed, sbc, abs); op(0xee, inc, abs); diff --git a/bsnes/phoenix/core/core.cpp b/bsnes/phoenix/core/core.cpp index 11fd4be1..0426ba10 100755 --- a/bsnes/phoenix/core/core.cpp +++ b/bsnes/phoenix/core/core.cpp @@ -27,6 +27,85 @@ 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(source)); +} + +Image::~Image() { + if(data) delete[] data; +} + //Object //====== @@ -656,8 +735,29 @@ Button::~Button() { //Canvas //====== -uint32_t* Canvas::buffer() { - return p.buffer(); +uint32_t* Canvas::data() { + return state.data; +} + +bool Canvas::setImage(const Image &image) { + if(image.data == nullptr || image.width == 0 || image.height == 0) return false; + state.width = image.width; + state.height = image.height; + setSize({ state.width, state.height }); + memcpy(state.data, image.data, state.width * state.height * sizeof(uint32_t)); + return true; +} + +void Canvas::setSize(const Size &size) { + state.width = size.width; + state.height = size.height; + delete[] state.data; + state.data = new uint32_t[size.width * size.height]; + return p.setSize(size); +} + +Size Canvas::size() { + return { state.width, state.height }; } void Canvas::update() { @@ -665,14 +765,18 @@ void Canvas::update() { } Canvas::Canvas(): +state(*new State), base_from_member(*new pCanvas(*this)), Widget(base_from_member::value), p(base_from_member::value) { + state.data = new uint32_t[state.width * state.height]; p.constructor(); } Canvas::~Canvas() { p.destructor(); + delete[] state.data; + delete &state; } //CheckBox diff --git a/bsnes/phoenix/core/core.hpp b/bsnes/phoenix/core/core.hpp index 7240ede8..d75b1efc 100755 --- a/bsnes/phoenix/core/core.hpp +++ b/bsnes/phoenix/core/core.hpp @@ -41,6 +41,12 @@ enum : unsigned { MinimumSize = 0u, }; +struct Color { + uint8_t red, green, blue, alpha; + inline Color() : red(0), green(0), blue(0), alpha(255) {} + 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; @@ -48,16 +54,37 @@ struct Geometry { 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) {} + inline Position(signed x, signed y) : x(x), y(y) {} +}; + +struct Size { + unsigned width, height; + inline Size() : width(0), height(0) {} + inline Size(unsigned width, unsigned height) : width(width), height(height) {} +}; + struct Font { nall::string description; Geometry geometry(const nall::string &text); Font(const nall::string &description = ""); }; -struct Color { - uint8_t red, green, blue, alpha; - inline Color() : red(0), green(0), blue(0), alpha(255) {} - inline Color(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha = 255) : red(red), green(green), blue(blue), alpha(alpha) {} +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 { @@ -302,11 +329,16 @@ struct Button : private nall::base_from_member, Widget { }; struct Canvas : private nall::base_from_member, Widget { - uint32_t* buffer(); + uint32_t* data(); + bool setImage(const Image &image); + void setSize(const Size &size); + Size size(); void update(); Canvas(); ~Canvas(); + struct State; + State &state; pCanvas &p; }; diff --git a/bsnes/phoenix/core/layout/horizontal-layout.cpp b/bsnes/phoenix/core/layout/horizontal-layout.cpp index cc5c7313..a1146038 100755 --- a/bsnes/phoenix/core/layout/horizontal-layout.cpp +++ b/bsnes/phoenix/core/layout/horizontal-layout.cpp @@ -1,6 +1,6 @@ -void HorizontalLayout::append(Sizable &sizable, unsigned width, unsigned height, unsigned spacing) { +void HorizontalLayout::append(Sizable &sizable, const Size &size, unsigned spacing) { for(auto &child : children) if(child.sizable == &sizable) return; - children.append({ &sizable, width, height, spacing }); + children.append({ &sizable, size.width, size.height, spacing }); synchronizeLayout(); if(window()) window()->synchronizeLayout(); } diff --git a/bsnes/phoenix/core/layout/horizontal-layout.hpp b/bsnes/phoenix/core/layout/horizontal-layout.hpp index 0bc7d926..96d4f101 100755 --- a/bsnes/phoenix/core/layout/horizontal-layout.hpp +++ b/bsnes/phoenix/core/layout/horizontal-layout.hpp @@ -1,5 +1,5 @@ struct HorizontalLayout : public Layout { - void append(Sizable &sizable, unsigned width, unsigned height, unsigned spacing = 0); + void append(Sizable &sizable, const Size &size, unsigned spacing = 0); void append(Sizable &sizable); bool enabled(); Geometry minimumGeometry(); diff --git a/bsnes/phoenix/core/layout/vertical-layout.cpp b/bsnes/phoenix/core/layout/vertical-layout.cpp index 599bbcec..4fd6315b 100755 --- a/bsnes/phoenix/core/layout/vertical-layout.cpp +++ b/bsnes/phoenix/core/layout/vertical-layout.cpp @@ -1,6 +1,6 @@ -void VerticalLayout::append(Sizable &sizable, unsigned width, unsigned height, unsigned spacing) { +void VerticalLayout::append(Sizable &sizable, const Size &size, unsigned spacing) { for(auto &child : children) if(child.sizable == &sizable) return; - children.append({ &sizable, width, height, spacing }); + children.append({ &sizable, size.width, size.height, spacing }); synchronizeLayout(); if(window()) window()->synchronizeLayout(); } diff --git a/bsnes/phoenix/core/layout/vertical-layout.hpp b/bsnes/phoenix/core/layout/vertical-layout.hpp index f15b36e2..8273dbe2 100755 --- a/bsnes/phoenix/core/layout/vertical-layout.hpp +++ b/bsnes/phoenix/core/layout/vertical-layout.hpp @@ -1,5 +1,5 @@ struct VerticalLayout : public Layout { - void append(Sizable &sizable, unsigned width, unsigned height, unsigned spacing = 0); + void append(Sizable &sizable, const Size &size, unsigned spacing = 0); void append(Sizable &sizable); bool enabled(); Geometry minimumGeometry(); diff --git a/bsnes/phoenix/core/state.hpp b/bsnes/phoenix/core/state.hpp index 937da316..136d89e7 100755 --- a/bsnes/phoenix/core/state.hpp +++ b/bsnes/phoenix/core/state.hpp @@ -119,6 +119,18 @@ struct Button::State { } }; +struct Canvas::State { + uint32_t *data; + unsigned width; + unsigned height; + + State() { + data = nullptr; + width = 256; + height = 256; + } +}; + struct CheckBox::State { bool checked; string text; diff --git a/bsnes/phoenix/gtk/platform.hpp b/bsnes/phoenix/gtk/platform.hpp index 0173eccb..8ce3ed92 100755 --- a/bsnes/phoenix/gtk/platform.hpp +++ b/bsnes/phoenix/gtk/platform.hpp @@ -231,8 +231,7 @@ struct pCanvas : public pWidget { Canvas &canvas; cairo_surface_t *surface; - uint32_t* buffer(); - void setGeometry(const Geometry &geometry); + void setSize(const Size &size); void update(); pCanvas(Canvas &canvas) : pWidget(canvas), canvas(canvas) {} diff --git a/bsnes/phoenix/gtk/widget/canvas.cpp b/bsnes/phoenix/gtk/widget/canvas.cpp index a16b2a2d..0231dbdb 100755 --- a/bsnes/phoenix/gtk/widget/canvas.cpp +++ b/bsnes/phoenix/gtk/widget/canvas.cpp @@ -6,33 +6,21 @@ static gboolean Canvas_expose(GtkWidget *widget, GdkEvent *event, pCanvas *self) return true; } -uint32_t* pCanvas::buffer() { - return (uint32_t*)cairo_image_surface_get_data(surface); -} - -void pCanvas::setGeometry(const Geometry &geometry) { - if(geometry.width != cairo_image_surface_get_width (surface) - || geometry.height != cairo_image_surface_get_height(surface) - ) { - cairo_surface_destroy(surface); - surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, geometry.width, geometry.height); - } - - pWidget::setGeometry(geometry); - update(); +void pCanvas::setSize(const Size &size) { + cairo_surface_destroy(surface); + surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, canvas.state.width, canvas.state.height); } void pCanvas::update() { + memcpy(cairo_image_surface_get_data(surface), canvas.state.data, canvas.state.width * canvas.state.height * sizeof(uint32_t)); if(gtk_widget_get_realized(gtkWidget) == false) return; gdk_window_invalidate_rect(gtk_widget_get_window(gtkWidget), 0, true); } void pCanvas::constructor() { - surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, 256, 256); + surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, canvas.state.width, canvas.state.height); + memcpy(cairo_image_surface_get_data(surface), canvas.state.data, canvas.state.width * canvas.state.height * sizeof(uint32_t)); gtkWidget = gtk_drawing_area_new(); - GdkColor color; - color.pixel = color.red = color.green = color.blue = 0; - gtk_widget_modify_bg(gtkWidget, GTK_STATE_NORMAL, &color); gtk_widget_set_double_buffered(gtkWidget, false); gtk_widget_add_events(gtkWidget, GDK_EXPOSURE_MASK); g_signal_connect(G_OBJECT(gtkWidget), "expose_event", G_CALLBACK(Canvas_expose), (gpointer)this); diff --git a/bsnes/phoenix/phoenix.hpp b/bsnes/phoenix/phoenix.hpp index 8caf4775..24ffa185 100755 --- a/bsnes/phoenix/phoenix.hpp +++ b/bsnes/phoenix/phoenix.hpp @@ -2,8 +2,10 @@ #define PHOENIX_HPP #include +#include #include #include +#include #include #include #include diff --git a/bsnes/phoenix/qt/platform.moc b/bsnes/phoenix/qt/platform.moc index 7267d34e..7e04fac2 100755 --- a/bsnes/phoenix/qt/platform.moc +++ b/bsnes/phoenix/qt/platform.moc @@ -1,7 +1,7 @@ /**************************************************************************** ** Meta object code from reading C++ file 'platform.moc.hpp' ** -** Created: Sun Oct 23 22:41:00 2011 +** Created: Wed Nov 2 21:16:00 2011 ** by: The Qt Meta Object Compiler version 62 (Qt 4.7.0) ** ** WARNING! All changes made in this file will be lost! diff --git a/bsnes/phoenix/qt/platform.moc.hpp b/bsnes/phoenix/qt/platform.moc.hpp index c8b52000..133ad9c3 100755 --- a/bsnes/phoenix/qt/platform.moc.hpp +++ b/bsnes/phoenix/qt/platform.moc.hpp @@ -282,8 +282,7 @@ public: QtCanvas(pCanvas &self); } *qtCanvas; - uint32_t* buffer(); - void setGeometry(const Geometry &geometry); + void setSize(const Size &size); void update(); pCanvas(Canvas &canvas) : pWidget(canvas), canvas(canvas) {} diff --git a/bsnes/phoenix/qt/widget/canvas.cpp b/bsnes/phoenix/qt/widget/canvas.cpp index abcae404..4adc54e5 100755 --- a/bsnes/phoenix/qt/widget/canvas.cpp +++ b/bsnes/phoenix/qt/widget/canvas.cpp @@ -1,21 +1,17 @@ -uint32_t* pCanvas::buffer() { - return (uint32_t*)qtImage->bits(); -} - -void pCanvas::setGeometry(const Geometry &geometry) { - qtImage = new QImage(geometry.width, geometry.height, QImage::Format_RGB32); - qtImage->fill(0); - update(); - pWidget::setGeometry(geometry); +void pCanvas::setSize(const Size &size) { + delete qtImage; + qtImage = new QImage(size.width, size.height, QImage::Format_RGB32); } void pCanvas::update() { + memcpy(qtImage->bits(), canvas.state.data, canvas.state.width * canvas.state.height * sizeof(uint32_t)); qtCanvas->update(); } void pCanvas::constructor() { qtWidget = qtCanvas = new QtCanvas(*this); - qtImage = new QImage(256, 256, QImage::Format_RGB32); + qtImage = new QImage(canvas.state.width, canvas.state.height, QImage::Format_RGB32); + memcpy(qtImage->bits(), canvas.state.data, canvas.state.width * canvas.state.height * sizeof(uint32_t)); pWidget::synchronizeState(); update(); @@ -36,6 +32,13 @@ void pCanvas::orphan() { void pCanvas::QtCanvas::paintEvent(QPaintEvent *event) { QPainter painter(self.qtCanvas); painter.drawImage(0, 0, *self.qtImage); + +//this will scale the source image to fit the target widget size (nearest-neighbor): +//painter.drawImage( +// QRect(0, 0, geometry().width(), geometry().height()), +// *self.qtImage, +// QRect(0, 0, self.canvas.state.width, self.canvas.state.height) +//); } pCanvas::QtCanvas::QtCanvas(pCanvas &self) : self(self) { diff --git a/bsnes/phoenix/reference/platform.hpp b/bsnes/phoenix/reference/platform.hpp index 99523bfb..fccb99ed 100755 --- a/bsnes/phoenix/reference/platform.hpp +++ b/bsnes/phoenix/reference/platform.hpp @@ -185,7 +185,7 @@ struct pButton : public pWidget { struct pCanvas : public pWidget { Canvas &canvas; - uint32_t* buffer(); + void setSize(const Size &size); void update(); pCanvas(Canvas &canvas) : pWidget(canvas), canvas(canvas) {} diff --git a/bsnes/phoenix/reference/widget/canvas.cpp b/bsnes/phoenix/reference/widget/canvas.cpp index 70295166..953cfa77 100755 --- a/bsnes/phoenix/reference/widget/canvas.cpp +++ b/bsnes/phoenix/reference/widget/canvas.cpp @@ -1,5 +1,4 @@ -uint32_t* pCanvas::buffer() { - return 0; +void pCanvas::setSize(const Size &size) { } void pCanvas::update() { diff --git a/bsnes/phoenix/windows/platform.cpp b/bsnes/phoenix/windows/platform.cpp index 560adc6d..9b4fbdd1 100755 --- a/bsnes/phoenix/windows/platform.cpp +++ b/bsnes/phoenix/windows/platform.cpp @@ -153,23 +153,10 @@ void OS_processDialogMessage(MSG &msg) { OS_keyboardProc(msg.hwnd, msg.message, msg.wParam, msg.lParam); } - wchar_t className[256]; - GetClassName(msg.hwnd, className, 255); - - //if this HWND accepts tabs to move between controls ... - if(!wcscmp(className, L"BUTTON") //Button, CheckBox, RadioBox - || !wcscmp(className, L"COMBOBOX") //ComboBox - || !wcscmp(className, L"EDIT") //HexEdit, LineEdit, TextEdit - || !wcscmp(className, L"SCROLLBAR") //HorizontalScrollBar, VerticalScrollBar - || !wcscmp(className, TRACKBAR_CLASS) //HorizontalSlider, VerticalSlider - || !wcscmp(className, WC_LISTVIEW) //ListView - ) { - //... return if the message is a dialog command - if(IsDialogMessage(msg.hwnd, &msg)) return; + if(!IsDialogMessage(GetForegroundWindow(), &msg)) { + TranslateMessage(&msg); + DispatchMessage(&msg); } - - TranslateMessage(&msg); - DispatchMessage(&msg); } void pOS::quit() { @@ -195,7 +182,7 @@ void pOS::initialize() { wc.cbClsExtra = 0; wc.cbWndExtra = 0; - wc.hbrBackground = CreateSolidBrush(RGB(0, 0, 0)); + wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE); wc.hCursor = LoadCursor(0, IDC_ARROW); wc.hIcon = LoadIcon(0, IDI_APPLICATION); wc.hInstance = GetModuleHandle(0); diff --git a/bsnes/phoenix/windows/platform.hpp b/bsnes/phoenix/windows/platform.hpp index 14f741ce..2a132222 100755 --- a/bsnes/phoenix/windows/platform.hpp +++ b/bsnes/phoenix/windows/platform.hpp @@ -214,10 +214,9 @@ struct pButton : public pWidget { struct pCanvas : public pWidget { Canvas &canvas; - uint32_t *bufferRGB; + uint32_t *data; - uint32_t* buffer(); - void setGeometry(const Geometry &geometry); + void setSize(const Size &size); void update(); pCanvas(Canvas &canvas) : pWidget(canvas), canvas(canvas) {} diff --git a/bsnes/phoenix/windows/widget/canvas.cpp b/bsnes/phoenix/windows/widget/canvas.cpp index 78f7152c..232aea93 100755 --- a/bsnes/phoenix/windows/widget/canvas.cpp +++ b/bsnes/phoenix/windows/widget/canvas.cpp @@ -1,29 +1,30 @@ static LRESULT CALLBACK Canvas_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { + if(msg == WM_GETDLGCODE) { + return DLGC_STATIC | DLGC_WANTCHARS; + } + if(msg == WM_PAINT) { Object *object = (Object*)GetWindowLongPtr(hwnd, GWLP_USERDATA); if(object && dynamic_cast(object)) { Canvas &canvas = (Canvas&)*object; canvas.update(); } + return TRUE; } + return DefWindowProc(hwnd, msg, wparam, lparam); } -uint32_t* pCanvas::buffer() { - return bufferRGB; -} - -void pCanvas::setGeometry(const Geometry &geometry) { - delete[] bufferRGB; - bufferRGB = new uint32_t[geometry.width * geometry.height](); - pWidget::setGeometry(geometry); - update(); +void pCanvas::setSize(const Size &size) { + delete[] data; + data = new uint32_t[size.width * size.height]; + memcpy(data, canvas.state.data, size.width * size.height * sizeof(uint32_t)); } void pCanvas::update() { RECT rc; GetClientRect(hwnd, &rc); - unsigned width = rc.right, height = rc.bottom; + unsigned width = canvas.state.width, height = canvas.state.height; //rc.right, height = rc.bottom; BITMAPINFO bmi; memset(&bmi, 0, sizeof(BITMAPINFO)); @@ -37,13 +38,14 @@ void pCanvas::update() { PAINTSTRUCT ps; BeginPaint(hwnd, &ps); - SetDIBitsToDevice(ps.hdc, 0, 0, width, height, 0, 0, 0, height, (void*)bufferRGB, &bmi, DIB_RGB_COLORS); + SetDIBitsToDevice(ps.hdc, 0, 0, width, height, 0, 0, 0, height, (void*)data, &bmi, DIB_RGB_COLORS); EndPaint(hwnd, &ps); InvalidateRect(hwnd, 0, false); } void pCanvas::constructor() { - bufferRGB = new uint32_t[256 * 256](); + data = new uint32_t[canvas.state.width * canvas.state.height]; + memcpy(data, canvas.state.data, canvas.state.width * canvas.state.height * sizeof(uint32_t)); hwnd = CreateWindow(L"phoenix_canvas", L"", WS_CHILD, 0, 0, 0, 0, parentWindow->p.hwnd, (HMENU)id, GetModuleHandle(0), 0); SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)&canvas); synchronize(); @@ -51,6 +53,7 @@ void pCanvas::constructor() { void pCanvas::destructor() { DestroyWindow(hwnd); + delete[] data; } void pCanvas::orphan() { diff --git a/bsnes/phoenix/windows/widget/label.cpp b/bsnes/phoenix/windows/widget/label.cpp index 53b894f5..56f0d433 100755 --- a/bsnes/phoenix/windows/widget/label.cpp +++ b/bsnes/phoenix/windows/widget/label.cpp @@ -30,6 +30,10 @@ static LRESULT CALLBACK Label_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPA Label *label = (Label*)GetWindowLongPtr(hwnd, GWLP_USERDATA); if(!window || !label) return DefWindowProc(hwnd, msg, wparam, lparam); + if(msg == WM_GETDLGCODE) { + return DLGC_STATIC | DLGC_WANTCHARS; + } + if(msg == WM_ERASEBKGND) { //background is erased during WM_PAINT to prevent flickering return TRUE; diff --git a/bsnes/phoenix/windows/widget/text-edit.cpp b/bsnes/phoenix/windows/widget/text-edit.cpp index 4c7dd404..c341156c 100755 --- a/bsnes/phoenix/windows/widget/text-edit.cpp +++ b/bsnes/phoenix/windows/widget/text-edit.cpp @@ -34,7 +34,7 @@ string pTextEdit::text() { void pTextEdit::constructor() { hwnd = CreateWindowEx( WS_EX_CLIENTEDGE, L"EDIT", L"", - WS_CHILD | ES_AUTOVSCROLL | ES_MULTILINE | ES_WANTRETURN | (textEdit.state.wordWrap == false ? ES_AUTOHSCROLL : 0), + WS_CHILD | WS_TABSTOP | ES_AUTOVSCROLL | ES_MULTILINE | ES_WANTRETURN | (textEdit.state.wordWrap == false ? ES_AUTOHSCROLL : 0), 0, 0, 0, 0, parentWindow->p.hwnd, (HMENU)id, GetModuleHandle(0), 0 ); SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)&textEdit); diff --git a/bsnes/phoenix/windows/widget/viewport.cpp b/bsnes/phoenix/windows/widget/viewport.cpp index 89942a2b..e46764f7 100755 --- a/bsnes/phoenix/windows/widget/viewport.cpp +++ b/bsnes/phoenix/windows/widget/viewport.cpp @@ -18,5 +18,6 @@ void pViewport::orphan() { } static LRESULT CALLBACK Viewport_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) { + if(msg == WM_GETDLGCODE) return DLGC_STATIC | DLGC_WANTCHARS; return DefWindowProc(hwnd, msg, wparam, lparam); } diff --git a/bsnes/ui/general/dip-switches.cpp b/bsnes/ui/general/dip-switches.cpp index e9f4e304..311e50ca 100755 --- a/bsnes/ui/general/dip-switches.cpp +++ b/bsnes/ui/general/dip-switches.cpp @@ -1,8 +1,8 @@ DipSwitches *dipSwitches = 0; DipSwitch::DipSwitch() { - append(name, ~0, 0, 5); - append(value, ~0, 0); + append(name, { ~0, 0 }, 5); + append(value, { ~0, 0 }, 0); } DipSwitches::DipSwitches() { @@ -13,10 +13,10 @@ DipSwitches::DipSwitches() { append(layout); for(unsigned n = 0; n < 8; n++) - layout.append(dip[n], ~0, 0, 5); - layout.append(controlLayout, ~0, 0, 5); - controlLayout.append(spacer, ~0, 0); - controlLayout.append(acceptButton, 0, 0); + layout.append(dip[n], { ~0, 0 }, 5); + layout.append(controlLayout, { ~0, 0 }, 5); + controlLayout.append(spacer, { ~0, 0 }, 0); + controlLayout.append(acceptButton, { 0, 0 }, 0); setGeometry({ 128, 128, 400, layout.minimumGeometry().height }); windowManager->append(this, "DipSwitches"); diff --git a/bsnes/ui/general/file-browser.cpp b/bsnes/ui/general/file-browser.cpp index 39498021..c250c867 100755 --- a/bsnes/ui/general/file-browser.cpp +++ b/bsnes/ui/general/file-browser.cpp @@ -10,14 +10,14 @@ FileBrowser::FileBrowser() { openButton.setText("Open"); append(layout); - layout.append(pathLayout, ~0, 0, 5); - pathLayout.append(pathEdit, ~0, 0, 5); - pathLayout.append(pathBrowse, 0, 0, 5); - pathLayout.append(pathUp, 0, 0); - layout.append(fileList, ~0, ~0, 5); - layout.append(controlLayout, ~0, 0); - controlLayout.append(filterLabel, ~0, 0, 5); - controlLayout.append(openButton, 80, 0); + layout.append(pathLayout, { ~0, 0 }, 5); + pathLayout.append(pathEdit, { ~0, 0 }, 5); + pathLayout.append(pathBrowse, { 0, 0 }, 5); + pathLayout.append(pathUp, { 0, 0 }); + layout.append(fileList, { ~0, ~0 }, 5); + layout.append(controlLayout, { ~0, 0 }); + controlLayout.append(filterLabel, { ~0, 0 }, 5); + controlLayout.append(openButton, { 80, 0 }); pathEdit.onActivate = [&] { string path = pathEdit.text(); diff --git a/bsnes/ui/general/slot-loader.cpp b/bsnes/ui/general/slot-loader.cpp index a2a329b6..dcf1bc16 100755 --- a/bsnes/ui/general/slot-loader.cpp +++ b/bsnes/ui/general/slot-loader.cpp @@ -2,9 +2,9 @@ SlotLoader *slotLoader = 0; SlotLoaderPath::SlotLoaderPath() { browse.setText("Browse ..."); - append(label, 40, 0, 5); - append(path, ~0, 0, 5); - append(browse, 80, 0); + append(label, { 40, 0 }, 5); + append(path, { ~0, 0 }, 5); + append(browse, { 80, 0 }, 0); } SlotLoader::SlotLoader() { @@ -15,12 +15,12 @@ SlotLoader::SlotLoader() { loadButton.setText("Load"); append(layout); - layout.append(base, ~0, 0, 5); - layout.append(slot[0], ~0, 0, 5); - layout.append(slot[1], ~0, 0, 5); - layout.append(controlLayout, ~0, 0); - controlLayout.append(spacer, ~0, 0); - controlLayout.append(loadButton, 80, 0); + layout.append(base, { ~0, 0 }, 5); + layout.append(slot[0], { ~0, 0 }, 5); + layout.append(slot[1], { ~0, 0 }, 5); + layout.append(controlLayout, { ~0, 0 }, 0); + controlLayout.append(spacer, { ~0, 0 }, 0); + controlLayout.append(loadButton, { 80, 0 }, 0); setGeometry({ 128, 128, 500, layout.minimumGeometry().height }); windowManager->append(this, "SlotLoader"); diff --git a/bsnes/ui/main.cpp b/bsnes/ui/main.cpp index 9a7a5c18..e2552ac2 100755 --- a/bsnes/ui/main.cpp +++ b/bsnes/ui/main.cpp @@ -27,7 +27,7 @@ void Application::run() { } Application::Application(int argc, char **argv) { - title = "bsnes v083.09"; + title = "bsnes v083.10"; application = this; quit = false; diff --git a/bsnes/ui/settings/advanced.cpp b/bsnes/ui/settings/advanced.cpp index f5b8e237..c8608d19 100755 --- a/bsnes/ui/settings/advanced.cpp +++ b/bsnes/ui/settings/advanced.cpp @@ -41,22 +41,22 @@ AdvancedSettings::AdvancedSettings() { if(list[n] == input.default_driver() && config->input.driver == "") inputDriver.setSelection(n); } - append(title, ~0, 0, 5); - append(driverLabel, ~0, 0); - append(driverLayout, ~0, 0, 5); - driverLayout.append(videoLabel, 0, 0, 5); - driverLayout.append(videoDriver, ~0, 0, 5); - driverLayout.append(audioLabel, 0, 0, 5); - driverLayout.append(audioDriver, ~0, 0, 5); - driverLayout.append(inputLabel, 0, 0, 5); - driverLayout.append(inputDriver, ~0, 0); - append(focusPolicyLabel, ~0, 0); - append(focusPolicyLayout, ~0, 0, 5); - focusPolicyLayout.append(focusPolicy[0], ~0, 0, 5); - focusPolicyLayout.append(focusPolicy[1], ~0, 0, 5); - focusPolicyLayout.append(focusPolicy[2], ~0, 0); - append(spacer, ~0, ~0); - append(aboutLabel, ~0, 0); + append(title, { ~0, 0 }, 5); + append(driverLabel, { ~0, 0 }, 0); + append(driverLayout, { ~0, 0 }, 5); + driverLayout.append(videoLabel, { 0, 0 }, 5); + driverLayout.append(videoDriver, { ~0, 0 }, 5); + driverLayout.append(audioLabel, { 0, 0 }, 5); + driverLayout.append(audioDriver, { ~0, 0 }, 5); + driverLayout.append(inputLabel, { 0, 0 }, 5); + driverLayout.append(inputDriver, { ~0, 0 }, 0); + append(focusPolicyLabel, { ~0, 0 }, 0); + append(focusPolicyLayout, { ~0, 0 }, 5); + focusPolicyLayout.append(focusPolicy[0], { ~0, 0 }, 5); + focusPolicyLayout.append(focusPolicy[1], { ~0, 0 }, 5); + focusPolicyLayout.append(focusPolicy[2], { ~0, 0 }, 0); + append(spacer, { ~0, ~0 }, 0); + append(aboutLabel, { ~0, 0 }, 0); videoDriver.onChange = [&] { lstring list; diff --git a/bsnes/ui/settings/audio.cpp b/bsnes/ui/settings/audio.cpp index e9b3baa1..2f7bd6ed 100755 --- a/bsnes/ui/settings/audio.cpp +++ b/bsnes/ui/settings/audio.cpp @@ -1,9 +1,9 @@ AudioSettings *audioSettings = 0; AudioSlider::AudioSlider() { - append(name, 75, 0); - append(value, 75, 0); - append(slider, ~0, 0); + append(name, { 75, 0 }); + append(value, { 75, 0 }); + append(slider, { ~0, 0 }); } unsigned AudioSlider::position() { @@ -68,20 +68,20 @@ AudioSettings::AudioSettings() { gameBoy.base = 4194304; gameBoy.step = 131; - append(title, ~0, 0, 5); - append(outputLabel, ~0, 0); - append(outputLayout, ~0, 0, 5); - outputLayout.append(frequencyLabel, 0, 0, 5); - outputLayout.append(frequencySelection, ~0, 0, 5); - outputLayout.append(latencyLabel, 0, 0, 5); - outputLayout.append(latencySelection, ~0, 0, 5); - outputLayout.append(resamplerLabel, 0, 0, 5); - outputLayout.append(resamplerSelection, ~0, 0); - append(volume, ~0, 0, 5); - append(frequencyAdjustmentLabel, ~0, 0); - append(nes, ~0, 0); - append(snes, ~0, 0); - append(gameBoy, ~0, 0); + append(title, { ~0, 0 }, 5); + append(outputLabel, { ~0, 0 }, 0); + append(outputLayout, { ~0, 0 }, 5); + outputLayout.append(frequencyLabel, { 0, 0 }, 5); + outputLayout.append(frequencySelection, { ~0, 0 }, 5); + outputLayout.append(latencyLabel, { 0, 0 }, 5); + outputLayout.append(latencySelection, { ~0, 0 }, 5); + outputLayout.append(resamplerLabel, { 0, 0 }, 5); + outputLayout.append(resamplerSelection, { ~0, 0 }, 0); + append(volume, { ~0, 0 }, 5); + append(frequencyAdjustmentLabel, { ~0, 0 }, 0); + append(nes, { ~0, 0 }, 0); + append(snes, { ~0, 0 }, 0); + append(gameBoy, { ~0, 0 }, 0); frequencySelection.setSelection( config->audio.frequency == 32000 ? 0 : diff --git a/bsnes/ui/settings/input.cpp b/bsnes/ui/settings/input.cpp index 8c1f6fe3..c5be3c62 100755 --- a/bsnes/ui/settings/input.cpp +++ b/bsnes/ui/settings/input.cpp @@ -15,18 +15,18 @@ InputSettings::InputSettings() : activeInput(0) { } primaryChange(); - append(title, ~0, 0, 5); - append(selectionLayout, ~0, 0, 5); - selectionLayout.append(primary, ~0, 0, 5); - selectionLayout.append(secondary, ~0, 0, 5); - selectionLayout.append(tertiary, ~0, 0); - append(inputList, ~0, ~0, 5); - append(controlLayout, ~0, 0); - controlLayout.append(assignPrimary, 100, 0, 5); - controlLayout.append(assignSecondary, 100, 0, 5); - controlLayout.append(assignTertiary, 100, 0, 5); - controlLayout.append(spacer, ~0, 0); - controlLayout.append(clearButton, 80, 0); + append(title, { ~0, 0 }, 5); + append(selectionLayout, { ~0, 0 }, 5); + selectionLayout.append(primary, { ~0, 0 }, 5); + selectionLayout.append(secondary, { ~0, 0 }, 5); + selectionLayout.append(tertiary, { ~0, 0 }, 0); + append(inputList, { ~0, ~0 }, 5); + append(controlLayout, { ~0, 0 }, 0); + controlLayout.append(assignPrimary, { 100, 0 }, 5); + controlLayout.append(assignSecondary, { 100, 0 }, 5); + controlLayout.append(assignTertiary, { 100, 0 }, 5); + controlLayout.append(spacer, { ~0, 0 }, 0); + controlLayout.append(clearButton, { 80, 0 }, 0); primary.onChange = { &InputSettings::primaryChange, this }; secondary.onChange = { &InputSettings::secondaryChange, this }; diff --git a/bsnes/ui/settings/settings.cpp b/bsnes/ui/settings/settings.cpp index 07b1988d..96a6fdd5 100755 --- a/bsnes/ui/settings/settings.cpp +++ b/bsnes/ui/settings/settings.cpp @@ -5,14 +5,14 @@ #include "advanced.cpp" SettingsWindow *settingsWindow = 0; -void SettingsLayout::append(Sizable &sizable, unsigned width, unsigned height, unsigned spacing) { - layout.append(sizable, width, height, spacing); +void SettingsLayout::append(Sizable &sizable, const Size &size, unsigned spacing) { + layout.append(sizable, size, spacing); } SettingsLayout::SettingsLayout() { setMargin(5); - HorizontalLayout::append(spacer, 120, ~0, 5); - HorizontalLayout::append(layout, ~0, ~0); + HorizontalLayout::append(spacer, { 120, ~0 }, 5); + HorizontalLayout::append(layout, { ~0, ~0 }, 0); } SettingsWindow::SettingsWindow() { @@ -34,7 +34,7 @@ SettingsWindow::SettingsWindow() { advancedSettings = new AdvancedSettings; append(layout); - layout.append(panelList, 120, ~0, 5); + layout.append(panelList, { 120, ~0 }, 5); append(*videoSettings); append(*audioSettings); append(*inputSettings); diff --git a/bsnes/ui/settings/settings.hpp b/bsnes/ui/settings/settings.hpp index 3e2e131a..eee9cc14 100755 --- a/bsnes/ui/settings/settings.hpp +++ b/bsnes/ui/settings/settings.hpp @@ -2,7 +2,7 @@ struct SettingsLayout : HorizontalLayout { Widget spacer; VerticalLayout layout; - void append(Sizable &widget, unsigned width, unsigned height, unsigned spacing = 0); + void append(Sizable &widget, const Size &size, unsigned spacing = 0); SettingsLayout(); }; diff --git a/bsnes/ui/settings/video.cpp b/bsnes/ui/settings/video.cpp index 47fd2ed0..9c829787 100755 --- a/bsnes/ui/settings/video.cpp +++ b/bsnes/ui/settings/video.cpp @@ -1,9 +1,9 @@ VideoSettings *videoSettings = 0; VideoSlider::VideoSlider() { - append(name, 75, 0); - append(value, 75, 0); - append(slider, ~0, 0); + append(name, { 75, 0 }); + append(value, { 75, 0 }); + append(slider, { ~0, 0 }); } VideoSettings::VideoSettings() { @@ -36,24 +36,24 @@ VideoSettings::VideoSettings() { compositor[2].setText("Always"); RadioBox::group(compositor[0], compositor[1], compositor[2]); - append(title, ~0, 0, 5); - append(colorAdjustment, ~0, 0); - append(brightness, ~0, 0); - append(contrast, ~0, 0); - append(gamma, ~0, 0, 5); - append(overscanAdjustment, ~0, 0); - append(overscanHorizontal, ~0, 0); - append(overscanVertical, ~0, 0, 5); - append(fullScreenMode, ~0, 0); - append(fullScreenLayout, ~0, 0, 5); - fullScreenLayout.append(fullScreen[0], ~0, 0, 5); - fullScreenLayout.append(fullScreen[1], ~0, 0, 5); - fullScreenLayout.append(fullScreen[2], ~0, 0); - append(compositorLabel, ~0, 0); - append(compositorLayout, ~0, 0); - compositorLayout.append(compositor[0], ~0, 0, 5); - compositorLayout.append(compositor[1], ~0, 0, 5); - compositorLayout.append(compositor[2], ~0, 0); + append(title, { ~0, 0 }, 5); + append(colorAdjustment, { ~0, 0 }, 0); + append(brightness, { ~0, 0 }, 0); + append(contrast, { ~0, 0 }, 0); + append(gamma, { ~0, 0 }, 5); + append(overscanAdjustment, { ~0, 0 }, 0); + append(overscanHorizontal, { ~0, 0 }, 0); + append(overscanVertical, { ~0, 0 }, 5); + append(fullScreenMode, { ~0, 0 }, 0); + append(fullScreenLayout, { ~0, 0 }, 5); + fullScreenLayout.append(fullScreen[0], { ~0, 0 }, 5); + fullScreenLayout.append(fullScreen[1], { ~0, 0 }, 5); + fullScreenLayout.append(fullScreen[2], { ~0, 0 }, 0); + append(compositorLabel, { ~0, 0 }, 0); + append(compositorLayout, { ~0, 0 }, 0); + compositorLayout.append(compositor[0], { ~0, 0 }, 5); + compositorLayout.append(compositor[1], { ~0, 0 }, 5); + compositorLayout.append(compositor[2], { ~0, 0 }, 0); brightness.slider.setPosition(config->video.brightness); contrast.slider.setPosition(config->video.contrast); @@ -95,9 +95,6 @@ void VideoSettings::synchronize() { config->video.gamma = gamma.slider.position(); config->video.maskOverscanHorizontal = overscanHorizontal.slider.position(); config->video.maskOverscanVertical = overscanVertical.slider.position(); - if(fullScreen[0].checked()) { config->video.fullScreenMode = 0; } - if(fullScreen[1].checked()) { config->video.fullScreenMode = 1; } - if(fullScreen[2].checked()) { config->video.fullScreenMode = 2; } brightness.value.setText({ config->video.brightness, "%" }); contrast.value.setText({ config->video.contrast, "%" }); diff --git a/bsnes/ui/tools/cheat-database.cpp b/bsnes/ui/tools/cheat-database.cpp index b8a3c1fb..77706cc2 100755 --- a/bsnes/ui/tools/cheat-database.cpp +++ b/bsnes/ui/tools/cheat-database.cpp @@ -11,12 +11,12 @@ CheatDatabase::CheatDatabase() { acceptButton.setText("Add Codes"); append(layout); - layout.append(cheatList, ~0, ~0, 5); - layout.append(controlLayout, ~0, 0); - controlLayout.append(selectAllButton, 100, 0, 5); - controlLayout.append(unselectAllButton, 100, 0); - controlLayout.append(spacer, ~0, 0); - controlLayout.append(acceptButton, 80, 0); + layout.append(cheatList, { ~0, ~0 }, 5); + layout.append(controlLayout, { ~0, 0 }, 0); + controlLayout.append(selectAllButton, { 100, 0 }, 5); + controlLayout.append(unselectAllButton, { 100, 0 }, 0); + controlLayout.append(spacer, { ~0, 0 }, 0); + controlLayout.append(acceptButton, { 80, 0 }, 0); selectAllButton.onTick = [&] { for(unsigned n = 0; n < cheatCode.size(); n++) cheatList.setChecked(n, true); diff --git a/bsnes/ui/tools/cheat-editor.cpp b/bsnes/ui/tools/cheat-editor.cpp index 87d88cc2..bf616b97 100755 --- a/bsnes/ui/tools/cheat-editor.cpp +++ b/bsnes/ui/tools/cheat-editor.cpp @@ -16,18 +16,18 @@ CheatEditor::CheatEditor() { append(layout); layout.setMargin(5); - layout.append(cheatList, ~0, ~0, 5); - layout.append(codeLayout, ~0, 0, 5); - codeLayout.append(codeLabel, 80, 0); - codeLayout.append(codeEdit, ~0, 0); - layout.append(descLayout, ~0, 0, 5); - descLayout.append(descLabel, 80, 0); - descLayout.append(descEdit, ~0, 0); - layout.append(controlLayout, ~0, 0); - controlLayout.append(findButton, 100, 0); - controlLayout.append(spacer, ~0, 0); - controlLayout.append(clearAllButton, 80, 0, 5); - controlLayout.append(clearButton, 80, 0); + layout.append(cheatList, { ~0, ~0 }, 5); + layout.append(codeLayout, { ~0, 0 }, 5); + codeLayout.append(codeLabel, { 80, 0 }, 0); + codeLayout.append(codeEdit, { ~0, 0 }, 0); + layout.append(descLayout, { ~0, 0 }, 5); + descLayout.append(descLabel, { 80, 0 }, 0); + descLayout.append(descEdit, { ~0, 0 }, 0); + layout.append(controlLayout, { ~0, 0 }, 0); + controlLayout.append(findButton, { 100, 0 }, 0); + controlLayout.append(spacer, { ~0, 0 }, 0); + controlLayout.append(clearAllButton, { 80, 0 }, 5); + controlLayout.append(clearButton, { 80, 0 }, 0); for(unsigned n = 0; n < 128; n++) cheatList.append("", "", ""); updateUI(); diff --git a/bsnes/ui/tools/state-manager.cpp b/bsnes/ui/tools/state-manager.cpp index 33cb530b..bb8f25df 100755 --- a/bsnes/ui/tools/state-manager.cpp +++ b/bsnes/ui/tools/state-manager.cpp @@ -14,15 +14,15 @@ StateManager::StateManager() { append(layout); layout.setMargin(5); - layout.append(stateList, ~0, ~0, 5); - layout.append(descLayout, ~0, 0, 5); - descLayout.append(descLabel, 0, 0, 5); - descLayout.append(descEdit, ~0, 0); - layout.append(controlLayout, ~0, 0); - controlLayout.append(spacer, ~0, 0); - controlLayout.append(loadButton, 80, 0, 5); - controlLayout.append(saveButton, 80, 0, 5); - controlLayout.append(eraseButton, 80, 0); + layout.append(stateList, { ~0, ~0 }, 5); + layout.append(descLayout, { ~0, 0 }, 5); + descLayout.append(descLabel, { 0, 0 }, 5); + descLayout.append(descEdit, { ~0, 0 }, 0); + layout.append(controlLayout, { ~0, 0 }, 0); + controlLayout.append(spacer, { ~0, 0 }, 0); + controlLayout.append(loadButton, { 80, 0 }, 5); + controlLayout.append(saveButton, { 80, 0 }, 5); + controlLayout.append(eraseButton, { 80, 0 }, 0); for(unsigned n = 0; n < 32; n++) stateList.append(decimal<2>(n + 1), "(empty)"); stateList.autoSizeColumns(); diff --git a/bsnes/ui/utility/utility.cpp b/bsnes/ui/utility/utility.cpp index cfcd5f31..25e7fa56 100755 --- a/bsnes/ui/utility/utility.cpp +++ b/bsnes/ui/utility/utility.cpp @@ -47,6 +47,7 @@ void Utility::resizeMainWindow(bool shrink) { unsigned width = geometry.width, height = geometry.height; switch(interface->mode()) { + case Interface::Mode::None: return; case Interface::Mode::NES: width = 256, height = 240; break; case Interface::Mode::SNES: width = 256, height = 240; break; case Interface::Mode::GameBoy: width = 160, height = 144; break;