mirror of https://github.com/bsnes-emu/bsnes.git
Update to v083r10 release.
byuu says: Changelog: - NES: added VRC1, VRC2, VRC3, MMC6 emulation - shrink window doesn't do anything when no cartridge is loaded - phoenix Horizontal,VerticalLayout use const Size& instead of unsigned width,height [for consistency] So, all official NES ASICs are supported now. Just need sound output for MMC5+VRC7 to complete them; and then some board re-arrangement stuff for VRC2+MMC3. Note that MMC6 uses the same mapper ID as MMC3, and VRC2 uses the same ID as VRC4, so you have to make a BML board mapping or toggle which type is chosen in the source file to use these two chips. Side note: NES overscan clamping is obviously still assuming 16-bit, as only half the lines are erased. Need to fix that.
This commit is contained in:
parent
bf78e66027
commit
891f1ab7af
|
@ -7,9 +7,11 @@
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
template<typename T> struct reference_array {
|
template<typename T> struct reference_array {
|
||||||
|
struct exception_out_of_bounds{};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
typedef typename std::remove_reference<T>::type *Tptr;
|
typedef typename std::remove_reference<T>::type type_t;
|
||||||
Tptr *pool;
|
type_t **pool;
|
||||||
unsigned poolsize, buffersize;
|
unsigned poolsize, buffersize;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -26,7 +28,7 @@ namespace nall {
|
||||||
void reserve(unsigned newsize) {
|
void reserve(unsigned newsize) {
|
||||||
if(newsize == poolsize) return;
|
if(newsize == poolsize) return;
|
||||||
|
|
||||||
pool = (Tptr*)realloc(pool, newsize * sizeof(T));
|
pool = (type_t**)realloc(pool, sizeof(type_t*) * newsize);
|
||||||
poolsize = newsize;
|
poolsize = newsize;
|
||||||
buffersize = min(buffersize, newsize);
|
buffersize = min(buffersize, newsize);
|
||||||
}
|
}
|
||||||
|
@ -37,13 +39,13 @@ namespace nall {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args>
|
||||||
bool append(const T& data, Args&&... args) {
|
bool append(type_t& data, Args&&... args) {
|
||||||
bool result = append(data);
|
bool result = append(data);
|
||||||
append(std::forward<Args>(args)...);
|
append(std::forward<Args>(args)...);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool append(const T data) {
|
bool append(type_t& data) {
|
||||||
for(unsigned index = 0; index < buffersize; index++) {
|
for(unsigned index = 0; index < buffersize; index++) {
|
||||||
if(pool[index] == &data) return false;
|
if(pool[index] == &data) return false;
|
||||||
}
|
}
|
||||||
|
@ -54,7 +56,7 @@ namespace nall {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool remove(const T data) {
|
bool remove(type_t& data) {
|
||||||
for(unsigned index = 0; index < buffersize; index++) {
|
for(unsigned index = 0; index < buffersize; index++) {
|
||||||
if(pool[index] == &data) {
|
if(pool[index] == &data) {
|
||||||
for(unsigned i = index; i < buffersize - 1; i++) pool[i] = pool[i + 1];
|
for(unsigned i = index; i < buffersize - 1; i++) pool[i] = pool[i + 1];
|
||||||
|
@ -77,8 +79,8 @@ namespace nall {
|
||||||
if(pool) free(pool);
|
if(pool) free(pool);
|
||||||
buffersize = source.buffersize;
|
buffersize = source.buffersize;
|
||||||
poolsize = source.poolsize;
|
poolsize = source.poolsize;
|
||||||
pool = (Tptr*)malloc(sizeof(T) * poolsize);
|
pool = (type_t**)malloc(sizeof(type_t*) * poolsize);
|
||||||
memcpy(pool, source.pool, sizeof(T) * buffersize);
|
memcpy(pool, source.pool, sizeof(type_t*) * buffersize);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -92,20 +94,20 @@ namespace nall {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline T operator[](unsigned index) {
|
inline type_t& operator[](unsigned index) {
|
||||||
if(index >= buffersize) throw "reference_array[] out of bounds";
|
if(index >= buffersize) throw exception_out_of_bounds();
|
||||||
return *pool[index];
|
return *pool[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const T operator[](unsigned index) const {
|
inline type_t& operator[](unsigned index) const {
|
||||||
if(index >= buffersize) throw "reference_array[] out of bounds";
|
if(index >= buffersize) throw exception_out_of_bounds();
|
||||||
return *pool[index];
|
return *pool[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
//iteration
|
//iteration
|
||||||
struct iterator {
|
struct iterator {
|
||||||
bool operator!=(const iterator &source) const { return index != source.index; }
|
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& operator++() { index++; return *this; }
|
||||||
iterator(const reference_array &array, unsigned index) : array(array), index(index) {}
|
iterator(const reference_array &array, unsigned index) : array(array), index(index) {}
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
#include "bandai-fcg.cpp"
|
#include "bandai-fcg.cpp"
|
||||||
|
#include "konami-vrc1.cpp"
|
||||||
|
#include "konami-vrc2.cpp"
|
||||||
|
#include "konami-vrc3.cpp"
|
||||||
#include "konami-vrc4.cpp"
|
#include "konami-vrc4.cpp"
|
||||||
#include "konami-vrc6.cpp"
|
#include "konami-vrc6.cpp"
|
||||||
#include "konami-vrc7.cpp"
|
#include "konami-vrc7.cpp"
|
||||||
|
@ -8,6 +11,7 @@
|
||||||
#include "nes-exrom.cpp"
|
#include "nes-exrom.cpp"
|
||||||
#include "nes-fxrom.cpp"
|
#include "nes-fxrom.cpp"
|
||||||
#include "nes-gxrom.cpp"
|
#include "nes-gxrom.cpp"
|
||||||
|
#include "nes-hkrom.cpp"
|
||||||
#include "nes-nrom.cpp"
|
#include "nes-nrom.cpp"
|
||||||
#include "nes-pxrom.cpp"
|
#include "nes-pxrom.cpp"
|
||||||
#include "nes-sxrom.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 == "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-4") return new KonamiVRC4(board, data, size);
|
||||||
if(type == "KONAMI-VRC-6") return new KonamiVRC6(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);
|
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-GNROM" ) return new NES_GxROM(board, data, size);
|
||||||
if(type == "NES-MHROM" ) 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-128") return new NES_NROM(board, data, size);
|
||||||
if(type == "NES-NROM-256") return new NES_NROM(board, data, size);
|
if(type == "NES-NROM-256") return new NES_NROM(board, data, size);
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
|
@ -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) {
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
|
@ -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) {
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
|
@ -32,53 +32,7 @@ uint8 prg_read(unsigned addr) {
|
||||||
|
|
||||||
void prg_write(unsigned addr, uint8 data) {
|
void prg_write(unsigned addr, uint8 data) {
|
||||||
if((addr & 0xe000) == 0x6000) return mmc3.ram_write(addr, data);
|
if((addr & 0xe000) == 0x6000) return mmc3.ram_write(addr, data);
|
||||||
|
if(addr & 0x8000) return mmc3.reg_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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 chr_read(unsigned addr) {
|
uint8 chr_read(unsigned addr) {
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
#include "mmc1.cpp"
|
#include "mmc1.cpp"
|
||||||
#include "mmc3.cpp"
|
#include "mmc3.cpp"
|
||||||
#include "mmc5.cpp"
|
#include "mmc5.cpp"
|
||||||
|
#include "mmc6.cpp"
|
||||||
|
#include "vrc1.cpp"
|
||||||
|
#include "vrc2.cpp"
|
||||||
|
#include "vrc3.cpp"
|
||||||
#include "vrc4.cpp"
|
#include "vrc4.cpp"
|
||||||
#include "vrc6.cpp"
|
#include "vrc6.cpp"
|
||||||
#include "vrc7.cpp"
|
#include "vrc7.cpp"
|
||||||
|
|
|
@ -89,6 +89,55 @@ void ram_write(unsigned addr, uint8 data) {
|
||||||
if(ram_enable && !ram_write_protect) board.prgram.data[addr & 0x1fff] = 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() {
|
void power() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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) {
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
|
@ -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) {
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
|
@ -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) {
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
|
@ -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) {
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
|
@ -140,6 +140,7 @@ unsigned ciram_addr(unsigned addr) const {
|
||||||
case 2: return 0x0000 | (addr & 0x03ff); //one-screen mirroring (first)
|
case 2: return 0x0000 | (addr & 0x03ff); //one-screen mirroring (first)
|
||||||
case 3: return 0x0400 | (addr & 0x03ff); //one-screen mirroring (second)
|
case 3: return 0x0400 | (addr & 0x03ff); //one-screen mirroring (second)
|
||||||
}
|
}
|
||||||
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
void power() {
|
void power() {
|
||||||
|
|
|
@ -14,7 +14,7 @@ static string iNES(const uint8_t *data, unsigned size) {
|
||||||
unsigned prgram = 0;
|
unsigned prgram = 0;
|
||||||
unsigned chrram = chrrom == 0 ? 8192 : 0;
|
unsigned chrram = chrrom == 0 ? 8192 : 0;
|
||||||
|
|
||||||
//print("iNES mapper: ", mapper, "\n");
|
print("iNES mapper: ", mapper, "\n");
|
||||||
|
|
||||||
output.append("cartridge\n");
|
output.append("cartridge\n");
|
||||||
|
|
||||||
|
@ -41,9 +41,14 @@ static string iNES(const uint8_t *data, unsigned size) {
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 4:
|
case 4:
|
||||||
|
//MMC3
|
||||||
output.append("\tboard type:NES-TLROM\n");
|
output.append("\tboard type:NES-TLROM\n");
|
||||||
output.append("\t\tchip type:MMC3B\n");
|
output.append("\t\tchip type:MMC3B\n");
|
||||||
prgram = 8192;
|
prgram = 8192;
|
||||||
|
//MMC6
|
||||||
|
//output.append("\tboard type:NES-HKROM\n");
|
||||||
|
//output.append("\t\tchip type:MMC6\n");
|
||||||
|
//prgram = 1024;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 5:
|
case 5:
|
||||||
|
@ -76,6 +81,10 @@ static string iNES(const uint8_t *data, unsigned size) {
|
||||||
case 21:
|
case 21:
|
||||||
case 23:
|
case 23:
|
||||||
case 25:
|
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("\tboard type:KONAMI-VRC-4\n");
|
||||||
output.append("\t\tchip type:VRC4\n");
|
output.append("\t\tchip type:VRC4\n");
|
||||||
output.append("\t\t\tpinout a0=1 a1=0\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;
|
prgram = 8192;
|
||||||
break;
|
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:
|
case 85:
|
||||||
output.append("\tboard type:KONAMI-VRC-7\n");
|
output.append("\tboard type:KONAMI-VRC-7\n");
|
||||||
output.append("\t\tchip type:VRC7\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\tprg rom=", prgrom, " ram=", prgram, "\n");
|
||||||
output.append("\t\tchr rom=", chrrom, " ram=", chrram, "\n");
|
output.append("\t\tchr rom=", chrrom, " ram=", chrram, "\n");
|
||||||
|
|
||||||
//print(output, "\n");
|
print(output, "\n");
|
||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
|
@ -162,6 +162,7 @@ string CPU::disassemble() {
|
||||||
op(0xe6, inc, zpg);
|
op(0xe6, inc, zpg);
|
||||||
op(0xe8, inx, imp);
|
op(0xe8, inx, imp);
|
||||||
op(0xe9, sbc, imm);
|
op(0xe9, sbc, imm);
|
||||||
|
op(0xea, nop, imp);
|
||||||
op(0xec, cpx, abs);
|
op(0xec, cpx, abs);
|
||||||
op(0xed, sbc, abs);
|
op(0xed, sbc, abs);
|
||||||
op(0xee, inc, abs);
|
op(0xee, inc, abs);
|
||||||
|
|
|
@ -27,6 +27,85 @@ Font::Font(const string &description):
|
||||||
description(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
|
//Object
|
||||||
//======
|
//======
|
||||||
|
|
||||||
|
@ -656,8 +735,29 @@ Button::~Button() {
|
||||||
//Canvas
|
//Canvas
|
||||||
//======
|
//======
|
||||||
|
|
||||||
uint32_t* Canvas::buffer() {
|
uint32_t* Canvas::data() {
|
||||||
return p.buffer();
|
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() {
|
void Canvas::update() {
|
||||||
|
@ -665,14 +765,18 @@ void Canvas::update() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Canvas::Canvas():
|
Canvas::Canvas():
|
||||||
|
state(*new State),
|
||||||
base_from_member<pCanvas&>(*new pCanvas(*this)),
|
base_from_member<pCanvas&>(*new pCanvas(*this)),
|
||||||
Widget(base_from_member<pCanvas&>::value),
|
Widget(base_from_member<pCanvas&>::value),
|
||||||
p(base_from_member<pCanvas&>::value) {
|
p(base_from_member<pCanvas&>::value) {
|
||||||
|
state.data = new uint32_t[state.width * state.height];
|
||||||
p.constructor();
|
p.constructor();
|
||||||
}
|
}
|
||||||
|
|
||||||
Canvas::~Canvas() {
|
Canvas::~Canvas() {
|
||||||
p.destructor();
|
p.destructor();
|
||||||
|
delete[] state.data;
|
||||||
|
delete &state;
|
||||||
}
|
}
|
||||||
|
|
||||||
//CheckBox
|
//CheckBox
|
||||||
|
|
|
@ -41,6 +41,12 @@ enum : unsigned {
|
||||||
MinimumSize = 0u,
|
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 {
|
struct Geometry {
|
||||||
signed x, y;
|
signed x, y;
|
||||||
unsigned width, height;
|
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) {}
|
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 {
|
struct Font {
|
||||||
nall::string description;
|
nall::string description;
|
||||||
Geometry geometry(const nall::string &text);
|
Geometry geometry(const nall::string &text);
|
||||||
Font(const nall::string &description = "");
|
Font(const nall::string &description = "");
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Color {
|
struct Image {
|
||||||
uint8_t red, green, blue, alpha;
|
uint32_t *data;
|
||||||
inline Color() : red(0), green(0), blue(0), alpha(255) {}
|
unsigned width, height;
|
||||||
inline Color(uint8_t red, uint8_t green, uint8_t blue, uint8_t alpha = 255) : red(red), green(green), blue(blue), alpha(alpha) {}
|
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 {
|
struct Object {
|
||||||
|
@ -302,11 +329,16 @@ struct Button : private nall::base_from_member<pButton&>, Widget {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Canvas : private nall::base_from_member<pCanvas&>, Widget {
|
struct Canvas : private nall::base_from_member<pCanvas&>, Widget {
|
||||||
uint32_t* buffer();
|
uint32_t* data();
|
||||||
|
bool setImage(const Image &image);
|
||||||
|
void setSize(const Size &size);
|
||||||
|
Size size();
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
Canvas();
|
Canvas();
|
||||||
~Canvas();
|
~Canvas();
|
||||||
|
struct State;
|
||||||
|
State &state;
|
||||||
pCanvas &p;
|
pCanvas &p;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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;
|
for(auto &child : children) if(child.sizable == &sizable) return;
|
||||||
children.append({ &sizable, width, height, spacing });
|
children.append({ &sizable, size.width, size.height, spacing });
|
||||||
synchronizeLayout();
|
synchronizeLayout();
|
||||||
if(window()) window()->synchronizeLayout();
|
if(window()) window()->synchronizeLayout();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
struct HorizontalLayout : public Layout {
|
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);
|
void append(Sizable &sizable);
|
||||||
bool enabled();
|
bool enabled();
|
||||||
Geometry minimumGeometry();
|
Geometry minimumGeometry();
|
||||||
|
|
|
@ -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;
|
for(auto &child : children) if(child.sizable == &sizable) return;
|
||||||
children.append({ &sizable, width, height, spacing });
|
children.append({ &sizable, size.width, size.height, spacing });
|
||||||
synchronizeLayout();
|
synchronizeLayout();
|
||||||
if(window()) window()->synchronizeLayout();
|
if(window()) window()->synchronizeLayout();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
struct VerticalLayout : public Layout {
|
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);
|
void append(Sizable &sizable);
|
||||||
bool enabled();
|
bool enabled();
|
||||||
Geometry minimumGeometry();
|
Geometry minimumGeometry();
|
||||||
|
|
|
@ -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 {
|
struct CheckBox::State {
|
||||||
bool checked;
|
bool checked;
|
||||||
string text;
|
string text;
|
||||||
|
|
|
@ -231,8 +231,7 @@ struct pCanvas : public pWidget {
|
||||||
Canvas &canvas;
|
Canvas &canvas;
|
||||||
cairo_surface_t *surface;
|
cairo_surface_t *surface;
|
||||||
|
|
||||||
uint32_t* buffer();
|
void setSize(const Size &size);
|
||||||
void setGeometry(const Geometry &geometry);
|
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
pCanvas(Canvas &canvas) : pWidget(canvas), canvas(canvas) {}
|
pCanvas(Canvas &canvas) : pWidget(canvas), canvas(canvas) {}
|
||||||
|
|
|
@ -6,33 +6,21 @@ static gboolean Canvas_expose(GtkWidget *widget, GdkEvent *event, pCanvas *self)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t* pCanvas::buffer() {
|
void pCanvas::setSize(const Size &size) {
|
||||||
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);
|
cairo_surface_destroy(surface);
|
||||||
surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, geometry.width, geometry.height);
|
surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, canvas.state.width, canvas.state.height);
|
||||||
}
|
|
||||||
|
|
||||||
pWidget::setGeometry(geometry);
|
|
||||||
update();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void pCanvas::update() {
|
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;
|
if(gtk_widget_get_realized(gtkWidget) == false) return;
|
||||||
gdk_window_invalidate_rect(gtk_widget_get_window(gtkWidget), 0, true);
|
gdk_window_invalidate_rect(gtk_widget_get_window(gtkWidget), 0, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pCanvas::constructor() {
|
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();
|
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_set_double_buffered(gtkWidget, false);
|
||||||
gtk_widget_add_events(gtkWidget, GDK_EXPOSURE_MASK);
|
gtk_widget_add_events(gtkWidget, GDK_EXPOSURE_MASK);
|
||||||
g_signal_connect(G_OBJECT(gtkWidget), "expose_event", G_CALLBACK(Canvas_expose), (gpointer)this);
|
g_signal_connect(G_OBJECT(gtkWidget), "expose_event", G_CALLBACK(Canvas_expose), (gpointer)this);
|
||||||
|
|
|
@ -2,8 +2,10 @@
|
||||||
#define PHOENIX_HPP
|
#define PHOENIX_HPP
|
||||||
|
|
||||||
#include <nall/array.hpp>
|
#include <nall/array.hpp>
|
||||||
|
#include <nall/bmp.hpp>
|
||||||
#include <nall/config.hpp>
|
#include <nall/config.hpp>
|
||||||
#include <nall/function.hpp>
|
#include <nall/function.hpp>
|
||||||
|
#include <nall/png.hpp>
|
||||||
#include <nall/reference_array.hpp>
|
#include <nall/reference_array.hpp>
|
||||||
#include <nall/stdint.hpp>
|
#include <nall/stdint.hpp>
|
||||||
#include <nall/string.hpp>
|
#include <nall/string.hpp>
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/****************************************************************************
|
/****************************************************************************
|
||||||
** Meta object code from reading C++ file 'platform.moc.hpp'
|
** 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)
|
** by: The Qt Meta Object Compiler version 62 (Qt 4.7.0)
|
||||||
**
|
**
|
||||||
** WARNING! All changes made in this file will be lost!
|
** WARNING! All changes made in this file will be lost!
|
||||||
|
|
|
@ -282,8 +282,7 @@ public:
|
||||||
QtCanvas(pCanvas &self);
|
QtCanvas(pCanvas &self);
|
||||||
} *qtCanvas;
|
} *qtCanvas;
|
||||||
|
|
||||||
uint32_t* buffer();
|
void setSize(const Size &size);
|
||||||
void setGeometry(const Geometry &geometry);
|
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
pCanvas(Canvas &canvas) : pWidget(canvas), canvas(canvas) {}
|
pCanvas(Canvas &canvas) : pWidget(canvas), canvas(canvas) {}
|
||||||
|
|
|
@ -1,21 +1,17 @@
|
||||||
uint32_t* pCanvas::buffer() {
|
void pCanvas::setSize(const Size &size) {
|
||||||
return (uint32_t*)qtImage->bits();
|
delete qtImage;
|
||||||
}
|
qtImage = new QImage(size.width, size.height, QImage::Format_RGB32);
|
||||||
|
|
||||||
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::update() {
|
void pCanvas::update() {
|
||||||
|
memcpy(qtImage->bits(), canvas.state.data, canvas.state.width * canvas.state.height * sizeof(uint32_t));
|
||||||
qtCanvas->update();
|
qtCanvas->update();
|
||||||
}
|
}
|
||||||
|
|
||||||
void pCanvas::constructor() {
|
void pCanvas::constructor() {
|
||||||
qtWidget = qtCanvas = new QtCanvas(*this);
|
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();
|
pWidget::synchronizeState();
|
||||||
update();
|
update();
|
||||||
|
@ -36,6 +32,13 @@ void pCanvas::orphan() {
|
||||||
void pCanvas::QtCanvas::paintEvent(QPaintEvent *event) {
|
void pCanvas::QtCanvas::paintEvent(QPaintEvent *event) {
|
||||||
QPainter painter(self.qtCanvas);
|
QPainter painter(self.qtCanvas);
|
||||||
painter.drawImage(0, 0, *self.qtImage);
|
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) {
|
pCanvas::QtCanvas::QtCanvas(pCanvas &self) : self(self) {
|
||||||
|
|
|
@ -185,7 +185,7 @@ struct pButton : public pWidget {
|
||||||
struct pCanvas : public pWidget {
|
struct pCanvas : public pWidget {
|
||||||
Canvas &canvas;
|
Canvas &canvas;
|
||||||
|
|
||||||
uint32_t* buffer();
|
void setSize(const Size &size);
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
pCanvas(Canvas &canvas) : pWidget(canvas), canvas(canvas) {}
|
pCanvas(Canvas &canvas) : pWidget(canvas), canvas(canvas) {}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
uint32_t* pCanvas::buffer() {
|
void pCanvas::setSize(const Size &size) {
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void pCanvas::update() {
|
void pCanvas::update() {
|
||||||
|
|
|
@ -153,23 +153,10 @@ void OS_processDialogMessage(MSG &msg) {
|
||||||
OS_keyboardProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
|
OS_keyboardProc(msg.hwnd, msg.message, msg.wParam, msg.lParam);
|
||||||
}
|
}
|
||||||
|
|
||||||
wchar_t className[256];
|
if(!IsDialogMessage(GetForegroundWindow(), &msg)) {
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
TranslateMessage(&msg);
|
TranslateMessage(&msg);
|
||||||
DispatchMessage(&msg);
|
DispatchMessage(&msg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pOS::quit() {
|
void pOS::quit() {
|
||||||
|
@ -195,7 +182,7 @@ void pOS::initialize() {
|
||||||
|
|
||||||
wc.cbClsExtra = 0;
|
wc.cbClsExtra = 0;
|
||||||
wc.cbWndExtra = 0;
|
wc.cbWndExtra = 0;
|
||||||
wc.hbrBackground = CreateSolidBrush(RGB(0, 0, 0));
|
wc.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
|
||||||
wc.hCursor = LoadCursor(0, IDC_ARROW);
|
wc.hCursor = LoadCursor(0, IDC_ARROW);
|
||||||
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
|
wc.hIcon = LoadIcon(0, IDI_APPLICATION);
|
||||||
wc.hInstance = GetModuleHandle(0);
|
wc.hInstance = GetModuleHandle(0);
|
||||||
|
|
|
@ -214,10 +214,9 @@ struct pButton : public pWidget {
|
||||||
|
|
||||||
struct pCanvas : public pWidget {
|
struct pCanvas : public pWidget {
|
||||||
Canvas &canvas;
|
Canvas &canvas;
|
||||||
uint32_t *bufferRGB;
|
uint32_t *data;
|
||||||
|
|
||||||
uint32_t* buffer();
|
void setSize(const Size &size);
|
||||||
void setGeometry(const Geometry &geometry);
|
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
pCanvas(Canvas &canvas) : pWidget(canvas), canvas(canvas) {}
|
pCanvas(Canvas &canvas) : pWidget(canvas), canvas(canvas) {}
|
||||||
|
|
|
@ -1,29 +1,30 @@
|
||||||
static LRESULT CALLBACK Canvas_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
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) {
|
if(msg == WM_PAINT) {
|
||||||
Object *object = (Object*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
Object *object = (Object*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||||
if(object && dynamic_cast<Canvas*>(object)) {
|
if(object && dynamic_cast<Canvas*>(object)) {
|
||||||
Canvas &canvas = (Canvas&)*object;
|
Canvas &canvas = (Canvas&)*object;
|
||||||
canvas.update();
|
canvas.update();
|
||||||
}
|
}
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
return DefWindowProc(hwnd, msg, wparam, lparam);
|
return DefWindowProc(hwnd, msg, wparam, lparam);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t* pCanvas::buffer() {
|
void pCanvas::setSize(const Size &size) {
|
||||||
return bufferRGB;
|
delete[] data;
|
||||||
}
|
data = new uint32_t[size.width * size.height];
|
||||||
|
memcpy(data, canvas.state.data, size.width * size.height * sizeof(uint32_t));
|
||||||
void pCanvas::setGeometry(const Geometry &geometry) {
|
|
||||||
delete[] bufferRGB;
|
|
||||||
bufferRGB = new uint32_t[geometry.width * geometry.height]();
|
|
||||||
pWidget::setGeometry(geometry);
|
|
||||||
update();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void pCanvas::update() {
|
void pCanvas::update() {
|
||||||
RECT rc;
|
RECT rc;
|
||||||
GetClientRect(hwnd, &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;
|
BITMAPINFO bmi;
|
||||||
memset(&bmi, 0, sizeof(BITMAPINFO));
|
memset(&bmi, 0, sizeof(BITMAPINFO));
|
||||||
|
@ -37,13 +38,14 @@ void pCanvas::update() {
|
||||||
|
|
||||||
PAINTSTRUCT ps;
|
PAINTSTRUCT ps;
|
||||||
BeginPaint(hwnd, &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);
|
EndPaint(hwnd, &ps);
|
||||||
InvalidateRect(hwnd, 0, false);
|
InvalidateRect(hwnd, 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pCanvas::constructor() {
|
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);
|
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);
|
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)&canvas);
|
||||||
synchronize();
|
synchronize();
|
||||||
|
@ -51,6 +53,7 @@ void pCanvas::constructor() {
|
||||||
|
|
||||||
void pCanvas::destructor() {
|
void pCanvas::destructor() {
|
||||||
DestroyWindow(hwnd);
|
DestroyWindow(hwnd);
|
||||||
|
delete[] data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pCanvas::orphan() {
|
void pCanvas::orphan() {
|
||||||
|
|
|
@ -30,6 +30,10 @@ static LRESULT CALLBACK Label_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPA
|
||||||
Label *label = (Label*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
Label *label = (Label*)GetWindowLongPtr(hwnd, GWLP_USERDATA);
|
||||||
if(!window || !label) return DefWindowProc(hwnd, msg, wparam, lparam);
|
if(!window || !label) return DefWindowProc(hwnd, msg, wparam, lparam);
|
||||||
|
|
||||||
|
if(msg == WM_GETDLGCODE) {
|
||||||
|
return DLGC_STATIC | DLGC_WANTCHARS;
|
||||||
|
}
|
||||||
|
|
||||||
if(msg == WM_ERASEBKGND) {
|
if(msg == WM_ERASEBKGND) {
|
||||||
//background is erased during WM_PAINT to prevent flickering
|
//background is erased during WM_PAINT to prevent flickering
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
|
@ -34,7 +34,7 @@ string pTextEdit::text() {
|
||||||
void pTextEdit::constructor() {
|
void pTextEdit::constructor() {
|
||||||
hwnd = CreateWindowEx(
|
hwnd = CreateWindowEx(
|
||||||
WS_EX_CLIENTEDGE, L"EDIT", L"",
|
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
|
0, 0, 0, 0, parentWindow->p.hwnd, (HMENU)id, GetModuleHandle(0), 0
|
||||||
);
|
);
|
||||||
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)&textEdit);
|
SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)&textEdit);
|
||||||
|
|
|
@ -18,5 +18,6 @@ void pViewport::orphan() {
|
||||||
}
|
}
|
||||||
|
|
||||||
static LRESULT CALLBACK Viewport_windowProc(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
|
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);
|
return DefWindowProc(hwnd, msg, wparam, lparam);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
DipSwitches *dipSwitches = 0;
|
DipSwitches *dipSwitches = 0;
|
||||||
|
|
||||||
DipSwitch::DipSwitch() {
|
DipSwitch::DipSwitch() {
|
||||||
append(name, ~0, 0, 5);
|
append(name, { ~0, 0 }, 5);
|
||||||
append(value, ~0, 0);
|
append(value, { ~0, 0 }, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
DipSwitches::DipSwitches() {
|
DipSwitches::DipSwitches() {
|
||||||
|
@ -13,10 +13,10 @@ DipSwitches::DipSwitches() {
|
||||||
|
|
||||||
append(layout);
|
append(layout);
|
||||||
for(unsigned n = 0; n < 8; n++)
|
for(unsigned n = 0; n < 8; n++)
|
||||||
layout.append(dip[n], ~0, 0, 5);
|
layout.append(dip[n], { ~0, 0 }, 5);
|
||||||
layout.append(controlLayout, ~0, 0, 5);
|
layout.append(controlLayout, { ~0, 0 }, 5);
|
||||||
controlLayout.append(spacer, ~0, 0);
|
controlLayout.append(spacer, { ~0, 0 }, 0);
|
||||||
controlLayout.append(acceptButton, 0, 0);
|
controlLayout.append(acceptButton, { 0, 0 }, 0);
|
||||||
|
|
||||||
setGeometry({ 128, 128, 400, layout.minimumGeometry().height });
|
setGeometry({ 128, 128, 400, layout.minimumGeometry().height });
|
||||||
windowManager->append(this, "DipSwitches");
|
windowManager->append(this, "DipSwitches");
|
||||||
|
|
|
@ -10,14 +10,14 @@ FileBrowser::FileBrowser() {
|
||||||
openButton.setText("Open");
|
openButton.setText("Open");
|
||||||
|
|
||||||
append(layout);
|
append(layout);
|
||||||
layout.append(pathLayout, ~0, 0, 5);
|
layout.append(pathLayout, { ~0, 0 }, 5);
|
||||||
pathLayout.append(pathEdit, ~0, 0, 5);
|
pathLayout.append(pathEdit, { ~0, 0 }, 5);
|
||||||
pathLayout.append(pathBrowse, 0, 0, 5);
|
pathLayout.append(pathBrowse, { 0, 0 }, 5);
|
||||||
pathLayout.append(pathUp, 0, 0);
|
pathLayout.append(pathUp, { 0, 0 });
|
||||||
layout.append(fileList, ~0, ~0, 5);
|
layout.append(fileList, { ~0, ~0 }, 5);
|
||||||
layout.append(controlLayout, ~0, 0);
|
layout.append(controlLayout, { ~0, 0 });
|
||||||
controlLayout.append(filterLabel, ~0, 0, 5);
|
controlLayout.append(filterLabel, { ~0, 0 }, 5);
|
||||||
controlLayout.append(openButton, 80, 0);
|
controlLayout.append(openButton, { 80, 0 });
|
||||||
|
|
||||||
pathEdit.onActivate = [&] {
|
pathEdit.onActivate = [&] {
|
||||||
string path = pathEdit.text();
|
string path = pathEdit.text();
|
||||||
|
|
|
@ -2,9 +2,9 @@ SlotLoader *slotLoader = 0;
|
||||||
|
|
||||||
SlotLoaderPath::SlotLoaderPath() {
|
SlotLoaderPath::SlotLoaderPath() {
|
||||||
browse.setText("Browse ...");
|
browse.setText("Browse ...");
|
||||||
append(label, 40, 0, 5);
|
append(label, { 40, 0 }, 5);
|
||||||
append(path, ~0, 0, 5);
|
append(path, { ~0, 0 }, 5);
|
||||||
append(browse, 80, 0);
|
append(browse, { 80, 0 }, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
SlotLoader::SlotLoader() {
|
SlotLoader::SlotLoader() {
|
||||||
|
@ -15,12 +15,12 @@ SlotLoader::SlotLoader() {
|
||||||
loadButton.setText("Load");
|
loadButton.setText("Load");
|
||||||
|
|
||||||
append(layout);
|
append(layout);
|
||||||
layout.append(base, ~0, 0, 5);
|
layout.append(base, { ~0, 0 }, 5);
|
||||||
layout.append(slot[0], ~0, 0, 5);
|
layout.append(slot[0], { ~0, 0 }, 5);
|
||||||
layout.append(slot[1], ~0, 0, 5);
|
layout.append(slot[1], { ~0, 0 }, 5);
|
||||||
layout.append(controlLayout, ~0, 0);
|
layout.append(controlLayout, { ~0, 0 }, 0);
|
||||||
controlLayout.append(spacer, ~0, 0);
|
controlLayout.append(spacer, { ~0, 0 }, 0);
|
||||||
controlLayout.append(loadButton, 80, 0);
|
controlLayout.append(loadButton, { 80, 0 }, 0);
|
||||||
|
|
||||||
setGeometry({ 128, 128, 500, layout.minimumGeometry().height });
|
setGeometry({ 128, 128, 500, layout.minimumGeometry().height });
|
||||||
windowManager->append(this, "SlotLoader");
|
windowManager->append(this, "SlotLoader");
|
||||||
|
|
|
@ -27,7 +27,7 @@ void Application::run() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Application::Application(int argc, char **argv) {
|
Application::Application(int argc, char **argv) {
|
||||||
title = "bsnes v083.09";
|
title = "bsnes v083.10";
|
||||||
|
|
||||||
application = this;
|
application = this;
|
||||||
quit = false;
|
quit = false;
|
||||||
|
|
|
@ -41,22 +41,22 @@ AdvancedSettings::AdvancedSettings() {
|
||||||
if(list[n] == input.default_driver() && config->input.driver == "") inputDriver.setSelection(n);
|
if(list[n] == input.default_driver() && config->input.driver == "") inputDriver.setSelection(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
append(title, ~0, 0, 5);
|
append(title, { ~0, 0 }, 5);
|
||||||
append(driverLabel, ~0, 0);
|
append(driverLabel, { ~0, 0 }, 0);
|
||||||
append(driverLayout, ~0, 0, 5);
|
append(driverLayout, { ~0, 0 }, 5);
|
||||||
driverLayout.append(videoLabel, 0, 0, 5);
|
driverLayout.append(videoLabel, { 0, 0 }, 5);
|
||||||
driverLayout.append(videoDriver, ~0, 0, 5);
|
driverLayout.append(videoDriver, { ~0, 0 }, 5);
|
||||||
driverLayout.append(audioLabel, 0, 0, 5);
|
driverLayout.append(audioLabel, { 0, 0 }, 5);
|
||||||
driverLayout.append(audioDriver, ~0, 0, 5);
|
driverLayout.append(audioDriver, { ~0, 0 }, 5);
|
||||||
driverLayout.append(inputLabel, 0, 0, 5);
|
driverLayout.append(inputLabel, { 0, 0 }, 5);
|
||||||
driverLayout.append(inputDriver, ~0, 0);
|
driverLayout.append(inputDriver, { ~0, 0 }, 0);
|
||||||
append(focusPolicyLabel, ~0, 0);
|
append(focusPolicyLabel, { ~0, 0 }, 0);
|
||||||
append(focusPolicyLayout, ~0, 0, 5);
|
append(focusPolicyLayout, { ~0, 0 }, 5);
|
||||||
focusPolicyLayout.append(focusPolicy[0], ~0, 0, 5);
|
focusPolicyLayout.append(focusPolicy[0], { ~0, 0 }, 5);
|
||||||
focusPolicyLayout.append(focusPolicy[1], ~0, 0, 5);
|
focusPolicyLayout.append(focusPolicy[1], { ~0, 0 }, 5);
|
||||||
focusPolicyLayout.append(focusPolicy[2], ~0, 0);
|
focusPolicyLayout.append(focusPolicy[2], { ~0, 0 }, 0);
|
||||||
append(spacer, ~0, ~0);
|
append(spacer, { ~0, ~0 }, 0);
|
||||||
append(aboutLabel, ~0, 0);
|
append(aboutLabel, { ~0, 0 }, 0);
|
||||||
|
|
||||||
videoDriver.onChange = [&] {
|
videoDriver.onChange = [&] {
|
||||||
lstring list;
|
lstring list;
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
AudioSettings *audioSettings = 0;
|
AudioSettings *audioSettings = 0;
|
||||||
|
|
||||||
AudioSlider::AudioSlider() {
|
AudioSlider::AudioSlider() {
|
||||||
append(name, 75, 0);
|
append(name, { 75, 0 });
|
||||||
append(value, 75, 0);
|
append(value, { 75, 0 });
|
||||||
append(slider, ~0, 0);
|
append(slider, { ~0, 0 });
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned AudioSlider::position() {
|
unsigned AudioSlider::position() {
|
||||||
|
@ -68,20 +68,20 @@ AudioSettings::AudioSettings() {
|
||||||
gameBoy.base = 4194304;
|
gameBoy.base = 4194304;
|
||||||
gameBoy.step = 131;
|
gameBoy.step = 131;
|
||||||
|
|
||||||
append(title, ~0, 0, 5);
|
append(title, { ~0, 0 }, 5);
|
||||||
append(outputLabel, ~0, 0);
|
append(outputLabel, { ~0, 0 }, 0);
|
||||||
append(outputLayout, ~0, 0, 5);
|
append(outputLayout, { ~0, 0 }, 5);
|
||||||
outputLayout.append(frequencyLabel, 0, 0, 5);
|
outputLayout.append(frequencyLabel, { 0, 0 }, 5);
|
||||||
outputLayout.append(frequencySelection, ~0, 0, 5);
|
outputLayout.append(frequencySelection, { ~0, 0 }, 5);
|
||||||
outputLayout.append(latencyLabel, 0, 0, 5);
|
outputLayout.append(latencyLabel, { 0, 0 }, 5);
|
||||||
outputLayout.append(latencySelection, ~0, 0, 5);
|
outputLayout.append(latencySelection, { ~0, 0 }, 5);
|
||||||
outputLayout.append(resamplerLabel, 0, 0, 5);
|
outputLayout.append(resamplerLabel, { 0, 0 }, 5);
|
||||||
outputLayout.append(resamplerSelection, ~0, 0);
|
outputLayout.append(resamplerSelection, { ~0, 0 }, 0);
|
||||||
append(volume, ~0, 0, 5);
|
append(volume, { ~0, 0 }, 5);
|
||||||
append(frequencyAdjustmentLabel, ~0, 0);
|
append(frequencyAdjustmentLabel, { ~0, 0 }, 0);
|
||||||
append(nes, ~0, 0);
|
append(nes, { ~0, 0 }, 0);
|
||||||
append(snes, ~0, 0);
|
append(snes, { ~0, 0 }, 0);
|
||||||
append(gameBoy, ~0, 0);
|
append(gameBoy, { ~0, 0 }, 0);
|
||||||
|
|
||||||
frequencySelection.setSelection(
|
frequencySelection.setSelection(
|
||||||
config->audio.frequency == 32000 ? 0 :
|
config->audio.frequency == 32000 ? 0 :
|
||||||
|
|
|
@ -15,18 +15,18 @@ InputSettings::InputSettings() : activeInput(0) {
|
||||||
}
|
}
|
||||||
primaryChange();
|
primaryChange();
|
||||||
|
|
||||||
append(title, ~0, 0, 5);
|
append(title, { ~0, 0 }, 5);
|
||||||
append(selectionLayout, ~0, 0, 5);
|
append(selectionLayout, { ~0, 0 }, 5);
|
||||||
selectionLayout.append(primary, ~0, 0, 5);
|
selectionLayout.append(primary, { ~0, 0 }, 5);
|
||||||
selectionLayout.append(secondary, ~0, 0, 5);
|
selectionLayout.append(secondary, { ~0, 0 }, 5);
|
||||||
selectionLayout.append(tertiary, ~0, 0);
|
selectionLayout.append(tertiary, { ~0, 0 }, 0);
|
||||||
append(inputList, ~0, ~0, 5);
|
append(inputList, { ~0, ~0 }, 5);
|
||||||
append(controlLayout, ~0, 0);
|
append(controlLayout, { ~0, 0 }, 0);
|
||||||
controlLayout.append(assignPrimary, 100, 0, 5);
|
controlLayout.append(assignPrimary, { 100, 0 }, 5);
|
||||||
controlLayout.append(assignSecondary, 100, 0, 5);
|
controlLayout.append(assignSecondary, { 100, 0 }, 5);
|
||||||
controlLayout.append(assignTertiary, 100, 0, 5);
|
controlLayout.append(assignTertiary, { 100, 0 }, 5);
|
||||||
controlLayout.append(spacer, ~0, 0);
|
controlLayout.append(spacer, { ~0, 0 }, 0);
|
||||||
controlLayout.append(clearButton, 80, 0);
|
controlLayout.append(clearButton, { 80, 0 }, 0);
|
||||||
|
|
||||||
primary.onChange = { &InputSettings::primaryChange, this };
|
primary.onChange = { &InputSettings::primaryChange, this };
|
||||||
secondary.onChange = { &InputSettings::secondaryChange, this };
|
secondary.onChange = { &InputSettings::secondaryChange, this };
|
||||||
|
|
|
@ -5,14 +5,14 @@
|
||||||
#include "advanced.cpp"
|
#include "advanced.cpp"
|
||||||
SettingsWindow *settingsWindow = 0;
|
SettingsWindow *settingsWindow = 0;
|
||||||
|
|
||||||
void SettingsLayout::append(Sizable &sizable, unsigned width, unsigned height, unsigned spacing) {
|
void SettingsLayout::append(Sizable &sizable, const Size &size, unsigned spacing) {
|
||||||
layout.append(sizable, width, height, spacing);
|
layout.append(sizable, size, spacing);
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsLayout::SettingsLayout() {
|
SettingsLayout::SettingsLayout() {
|
||||||
setMargin(5);
|
setMargin(5);
|
||||||
HorizontalLayout::append(spacer, 120, ~0, 5);
|
HorizontalLayout::append(spacer, { 120, ~0 }, 5);
|
||||||
HorizontalLayout::append(layout, ~0, ~0);
|
HorizontalLayout::append(layout, { ~0, ~0 }, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
SettingsWindow::SettingsWindow() {
|
SettingsWindow::SettingsWindow() {
|
||||||
|
@ -34,7 +34,7 @@ SettingsWindow::SettingsWindow() {
|
||||||
advancedSettings = new AdvancedSettings;
|
advancedSettings = new AdvancedSettings;
|
||||||
|
|
||||||
append(layout);
|
append(layout);
|
||||||
layout.append(panelList, 120, ~0, 5);
|
layout.append(panelList, { 120, ~0 }, 5);
|
||||||
append(*videoSettings);
|
append(*videoSettings);
|
||||||
append(*audioSettings);
|
append(*audioSettings);
|
||||||
append(*inputSettings);
|
append(*inputSettings);
|
||||||
|
|
|
@ -2,7 +2,7 @@ struct SettingsLayout : HorizontalLayout {
|
||||||
Widget spacer;
|
Widget spacer;
|
||||||
VerticalLayout layout;
|
VerticalLayout layout;
|
||||||
|
|
||||||
void append(Sizable &widget, unsigned width, unsigned height, unsigned spacing = 0);
|
void append(Sizable &widget, const Size &size, unsigned spacing = 0);
|
||||||
SettingsLayout();
|
SettingsLayout();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
VideoSettings *videoSettings = 0;
|
VideoSettings *videoSettings = 0;
|
||||||
|
|
||||||
VideoSlider::VideoSlider() {
|
VideoSlider::VideoSlider() {
|
||||||
append(name, 75, 0);
|
append(name, { 75, 0 });
|
||||||
append(value, 75, 0);
|
append(value, { 75, 0 });
|
||||||
append(slider, ~0, 0);
|
append(slider, { ~0, 0 });
|
||||||
}
|
}
|
||||||
|
|
||||||
VideoSettings::VideoSettings() {
|
VideoSettings::VideoSettings() {
|
||||||
|
@ -36,24 +36,24 @@ VideoSettings::VideoSettings() {
|
||||||
compositor[2].setText("Always");
|
compositor[2].setText("Always");
|
||||||
RadioBox::group(compositor[0], compositor[1], compositor[2]);
|
RadioBox::group(compositor[0], compositor[1], compositor[2]);
|
||||||
|
|
||||||
append(title, ~0, 0, 5);
|
append(title, { ~0, 0 }, 5);
|
||||||
append(colorAdjustment, ~0, 0);
|
append(colorAdjustment, { ~0, 0 }, 0);
|
||||||
append(brightness, ~0, 0);
|
append(brightness, { ~0, 0 }, 0);
|
||||||
append(contrast, ~0, 0);
|
append(contrast, { ~0, 0 }, 0);
|
||||||
append(gamma, ~0, 0, 5);
|
append(gamma, { ~0, 0 }, 5);
|
||||||
append(overscanAdjustment, ~0, 0);
|
append(overscanAdjustment, { ~0, 0 }, 0);
|
||||||
append(overscanHorizontal, ~0, 0);
|
append(overscanHorizontal, { ~0, 0 }, 0);
|
||||||
append(overscanVertical, ~0, 0, 5);
|
append(overscanVertical, { ~0, 0 }, 5);
|
||||||
append(fullScreenMode, ~0, 0);
|
append(fullScreenMode, { ~0, 0 }, 0);
|
||||||
append(fullScreenLayout, ~0, 0, 5);
|
append(fullScreenLayout, { ~0, 0 }, 5);
|
||||||
fullScreenLayout.append(fullScreen[0], ~0, 0, 5);
|
fullScreenLayout.append(fullScreen[0], { ~0, 0 }, 5);
|
||||||
fullScreenLayout.append(fullScreen[1], ~0, 0, 5);
|
fullScreenLayout.append(fullScreen[1], { ~0, 0 }, 5);
|
||||||
fullScreenLayout.append(fullScreen[2], ~0, 0);
|
fullScreenLayout.append(fullScreen[2], { ~0, 0 }, 0);
|
||||||
append(compositorLabel, ~0, 0);
|
append(compositorLabel, { ~0, 0 }, 0);
|
||||||
append(compositorLayout, ~0, 0);
|
append(compositorLayout, { ~0, 0 }, 0);
|
||||||
compositorLayout.append(compositor[0], ~0, 0, 5);
|
compositorLayout.append(compositor[0], { ~0, 0 }, 5);
|
||||||
compositorLayout.append(compositor[1], ~0, 0, 5);
|
compositorLayout.append(compositor[1], { ~0, 0 }, 5);
|
||||||
compositorLayout.append(compositor[2], ~0, 0);
|
compositorLayout.append(compositor[2], { ~0, 0 }, 0);
|
||||||
|
|
||||||
brightness.slider.setPosition(config->video.brightness);
|
brightness.slider.setPosition(config->video.brightness);
|
||||||
contrast.slider.setPosition(config->video.contrast);
|
contrast.slider.setPosition(config->video.contrast);
|
||||||
|
@ -95,9 +95,6 @@ void VideoSettings::synchronize() {
|
||||||
config->video.gamma = gamma.slider.position();
|
config->video.gamma = gamma.slider.position();
|
||||||
config->video.maskOverscanHorizontal = overscanHorizontal.slider.position();
|
config->video.maskOverscanHorizontal = overscanHorizontal.slider.position();
|
||||||
config->video.maskOverscanVertical = overscanVertical.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, "%" });
|
brightness.value.setText({ config->video.brightness, "%" });
|
||||||
contrast.value.setText({ config->video.contrast, "%" });
|
contrast.value.setText({ config->video.contrast, "%" });
|
||||||
|
|
|
@ -11,12 +11,12 @@ CheatDatabase::CheatDatabase() {
|
||||||
acceptButton.setText("Add Codes");
|
acceptButton.setText("Add Codes");
|
||||||
|
|
||||||
append(layout);
|
append(layout);
|
||||||
layout.append(cheatList, ~0, ~0, 5);
|
layout.append(cheatList, { ~0, ~0 }, 5);
|
||||||
layout.append(controlLayout, ~0, 0);
|
layout.append(controlLayout, { ~0, 0 }, 0);
|
||||||
controlLayout.append(selectAllButton, 100, 0, 5);
|
controlLayout.append(selectAllButton, { 100, 0 }, 5);
|
||||||
controlLayout.append(unselectAllButton, 100, 0);
|
controlLayout.append(unselectAllButton, { 100, 0 }, 0);
|
||||||
controlLayout.append(spacer, ~0, 0);
|
controlLayout.append(spacer, { ~0, 0 }, 0);
|
||||||
controlLayout.append(acceptButton, 80, 0);
|
controlLayout.append(acceptButton, { 80, 0 }, 0);
|
||||||
|
|
||||||
selectAllButton.onTick = [&] {
|
selectAllButton.onTick = [&] {
|
||||||
for(unsigned n = 0; n < cheatCode.size(); n++) cheatList.setChecked(n, true);
|
for(unsigned n = 0; n < cheatCode.size(); n++) cheatList.setChecked(n, true);
|
||||||
|
|
|
@ -16,18 +16,18 @@ CheatEditor::CheatEditor() {
|
||||||
|
|
||||||
append(layout);
|
append(layout);
|
||||||
layout.setMargin(5);
|
layout.setMargin(5);
|
||||||
layout.append(cheatList, ~0, ~0, 5);
|
layout.append(cheatList, { ~0, ~0 }, 5);
|
||||||
layout.append(codeLayout, ~0, 0, 5);
|
layout.append(codeLayout, { ~0, 0 }, 5);
|
||||||
codeLayout.append(codeLabel, 80, 0);
|
codeLayout.append(codeLabel, { 80, 0 }, 0);
|
||||||
codeLayout.append(codeEdit, ~0, 0);
|
codeLayout.append(codeEdit, { ~0, 0 }, 0);
|
||||||
layout.append(descLayout, ~0, 0, 5);
|
layout.append(descLayout, { ~0, 0 }, 5);
|
||||||
descLayout.append(descLabel, 80, 0);
|
descLayout.append(descLabel, { 80, 0 }, 0);
|
||||||
descLayout.append(descEdit, ~0, 0);
|
descLayout.append(descEdit, { ~0, 0 }, 0);
|
||||||
layout.append(controlLayout, ~0, 0);
|
layout.append(controlLayout, { ~0, 0 }, 0);
|
||||||
controlLayout.append(findButton, 100, 0);
|
controlLayout.append(findButton, { 100, 0 }, 0);
|
||||||
controlLayout.append(spacer, ~0, 0);
|
controlLayout.append(spacer, { ~0, 0 }, 0);
|
||||||
controlLayout.append(clearAllButton, 80, 0, 5);
|
controlLayout.append(clearAllButton, { 80, 0 }, 5);
|
||||||
controlLayout.append(clearButton, 80, 0);
|
controlLayout.append(clearButton, { 80, 0 }, 0);
|
||||||
|
|
||||||
for(unsigned n = 0; n < 128; n++) cheatList.append("", "", "");
|
for(unsigned n = 0; n < 128; n++) cheatList.append("", "", "");
|
||||||
updateUI();
|
updateUI();
|
||||||
|
|
|
@ -14,15 +14,15 @@ StateManager::StateManager() {
|
||||||
|
|
||||||
append(layout);
|
append(layout);
|
||||||
layout.setMargin(5);
|
layout.setMargin(5);
|
||||||
layout.append(stateList, ~0, ~0, 5);
|
layout.append(stateList, { ~0, ~0 }, 5);
|
||||||
layout.append(descLayout, ~0, 0, 5);
|
layout.append(descLayout, { ~0, 0 }, 5);
|
||||||
descLayout.append(descLabel, 0, 0, 5);
|
descLayout.append(descLabel, { 0, 0 }, 5);
|
||||||
descLayout.append(descEdit, ~0, 0);
|
descLayout.append(descEdit, { ~0, 0 }, 0);
|
||||||
layout.append(controlLayout, ~0, 0);
|
layout.append(controlLayout, { ~0, 0 }, 0);
|
||||||
controlLayout.append(spacer, ~0, 0);
|
controlLayout.append(spacer, { ~0, 0 }, 0);
|
||||||
controlLayout.append(loadButton, 80, 0, 5);
|
controlLayout.append(loadButton, { 80, 0 }, 5);
|
||||||
controlLayout.append(saveButton, 80, 0, 5);
|
controlLayout.append(saveButton, { 80, 0 }, 5);
|
||||||
controlLayout.append(eraseButton, 80, 0);
|
controlLayout.append(eraseButton, { 80, 0 }, 0);
|
||||||
|
|
||||||
for(unsigned n = 0; n < 32; n++) stateList.append(decimal<2>(n + 1), "(empty)");
|
for(unsigned n = 0; n < 32; n++) stateList.append(decimal<2>(n + 1), "(empty)");
|
||||||
stateList.autoSizeColumns();
|
stateList.autoSizeColumns();
|
||||||
|
|
|
@ -47,6 +47,7 @@ void Utility::resizeMainWindow(bool shrink) {
|
||||||
unsigned width = geometry.width, height = geometry.height;
|
unsigned width = geometry.width, height = geometry.height;
|
||||||
|
|
||||||
switch(interface->mode()) {
|
switch(interface->mode()) {
|
||||||
|
case Interface::Mode::None: return;
|
||||||
case Interface::Mode::NES: width = 256, height = 240; break;
|
case Interface::Mode::NES: width = 256, height = 240; break;
|
||||||
case Interface::Mode::SNES: width = 256, height = 240; break;
|
case Interface::Mode::SNES: width = 256, height = 240; break;
|
||||||
case Interface::Mode::GameBoy: width = 160, height = 144; break;
|
case Interface::Mode::GameBoy: width = 160, height = 144; break;
|
||||||
|
|
Loading…
Reference in New Issue