mirror of https://github.com/bsnes-emu/bsnes.git
Update to v082r10 release.
byuu says: Emulated the Game Genie for the NES and Game Boy, and wrote a new cheat editor that doesn't reach into specific emulation cores so that it would work. Before you ask: yes, long-term I'd like Super Game Boy mode to accept Game Boy codes. But that's not high on the priority list. Renamed the mappers toward board names, LZ...->BandaiFCG, LS161...->AOROM, added CNROM emulation (Adventure Island, Gradius, etc.) Added the tools menu load/save state stuff, but note that the NES doesn't have save state support yet (waiting for the interface to stabilize a bit more first.) Note: this will be the last release to have the ui-gameboy folder, it's been deleted locally from my end, as the new multi-GUI does all that it does and more now.
This commit is contained in:
parent
7f4381b505
commit
278cf8462c
|
@ -1,6 +1,7 @@
|
||||||
gameboy_objects := gameboy-system gameboy-scheduler
|
gameboy_objects := gameboy-system gameboy-scheduler
|
||||||
gameboy_objects += gameboy-memory gameboy-cartridge
|
gameboy_objects += gameboy-memory gameboy-cartridge
|
||||||
gameboy_objects += gameboy-cpu gameboy-apu gameboy-lcd
|
gameboy_objects += gameboy-cpu gameboy-apu gameboy-lcd
|
||||||
|
gameboy_objects += gameboy-cheat
|
||||||
objects += $(gameboy_objects)
|
objects += $(gameboy_objects)
|
||||||
|
|
||||||
obj/gameboy-system.o: $(gameboy)/system/system.cpp $(call rwildcard,$(gameboy)/system/)
|
obj/gameboy-system.o: $(gameboy)/system/system.cpp $(call rwildcard,$(gameboy)/system/)
|
||||||
|
@ -10,3 +11,4 @@ obj/gameboy-memory.o: $(gameboy)/memory/memory.cpp $(call rwildcard,$(gameboy)/m
|
||||||
obj/gameboy-cpu.o: $(gameboy)/cpu/cpu.cpp $(call rwildcard,$(gameboy)/cpu/)
|
obj/gameboy-cpu.o: $(gameboy)/cpu/cpu.cpp $(call rwildcard,$(gameboy)/cpu/)
|
||||||
obj/gameboy-apu.o: $(gameboy)/apu/apu.cpp $(call rwildcard,$(gameboy)/apu/)
|
obj/gameboy-apu.o: $(gameboy)/apu/apu.cpp $(call rwildcard,$(gameboy)/apu/)
|
||||||
obj/gameboy-lcd.o: $(gameboy)/lcd/lcd.cpp $(call rwildcard,$(gameboy)/lcd/)
|
obj/gameboy-lcd.o: $(gameboy)/lcd/lcd.cpp $(call rwildcard,$(gameboy)/lcd/)
|
||||||
|
obj/gameboy-cheat.o: $(gameboy)/cheat/cheat.cpp $(call rwildcard,$(gameboy)/cheat/)
|
||||||
|
|
|
@ -0,0 +1,91 @@
|
||||||
|
#include <gameboy/gameboy.hpp>
|
||||||
|
|
||||||
|
namespace GameBoy {
|
||||||
|
|
||||||
|
Cheat cheat;
|
||||||
|
|
||||||
|
bool Cheat::decode(const string &code, unsigned &addr, unsigned &data, unsigned &comp) {
|
||||||
|
static bool initialize = false;
|
||||||
|
static uint8 asciiMap[256];
|
||||||
|
|
||||||
|
if(initialize == false) {
|
||||||
|
initialize = true;
|
||||||
|
foreach(n, asciiMap) n = ~0;
|
||||||
|
asciiMap['0'] = 0; asciiMap['1'] = 1; asciiMap['2'] = 2; asciiMap['3'] = 3;
|
||||||
|
asciiMap['4'] = 4; asciiMap['5'] = 5; asciiMap['6'] = 6; asciiMap['7'] = 7;
|
||||||
|
asciiMap['8'] = 8; asciiMap['9'] = 9; asciiMap['A'] = 10; asciiMap['B'] = 11;
|
||||||
|
asciiMap['C'] = 12; asciiMap['D'] = 13; asciiMap['E'] = 14; asciiMap['F'] = 15;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned length = code.length(), bits = 0;
|
||||||
|
for(unsigned n = 0; n < length; n++) if(asciiMap[code[n]] > 15 && code[n] != '-') return false;
|
||||||
|
|
||||||
|
if(code.wildcard("???" "-" "???")) {
|
||||||
|
string text = string(code).replace("-", "");
|
||||||
|
for(unsigned n = 0; n < 6; n++) bits |= asciiMap[text[n]] << (20 - n * 4);
|
||||||
|
|
||||||
|
addr = (bits >> 0) & 0xffff;
|
||||||
|
data = (bits >> 16) & 0xff;
|
||||||
|
comp = ~0;
|
||||||
|
|
||||||
|
addr = (((addr >> 4) | (addr << 12)) & 0xffff) ^ 0xf000;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(code.wildcard("???" "-" "???" "-" "???")) {
|
||||||
|
string text = string(code).replace("-", "");
|
||||||
|
for(unsigned n = 0; n < 8; n++) bits |= asciiMap[text[n == 7 ? 8 : n]] << (28 - n * 4);
|
||||||
|
|
||||||
|
addr = (bits >> 8) & 0xffff;
|
||||||
|
data = (bits >> 24) & 0xff;
|
||||||
|
comp = (bits >> 0) & 0xff;
|
||||||
|
|
||||||
|
addr = (((addr >> 4) | (addr << 12)) & 0xffff) ^ 0xf000;
|
||||||
|
comp = (((comp >> 2) | (comp << 6)) & 0xff) ^ 0xba;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cheat::synchronize() {
|
||||||
|
foreach(n, override) n = false;
|
||||||
|
|
||||||
|
for(unsigned n = 0; n < size(); n++) {
|
||||||
|
const CheatCode &code = operator[](n);
|
||||||
|
|
||||||
|
for(unsigned n = 0; n < code.addr.size(); n++) {
|
||||||
|
override[code.addr[n]] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CheatCode::operator=(const string &s) {
|
||||||
|
addr.reset(), data.reset(), comp.reset();
|
||||||
|
|
||||||
|
lstring list;
|
||||||
|
list.split("+", s);
|
||||||
|
|
||||||
|
for(unsigned n = 0; n < list.size(); n++) {
|
||||||
|
unsigned codeaddr, codedata, codecomp;
|
||||||
|
if(Cheat::decode(list[n], codeaddr, codedata, codecomp) == false) {
|
||||||
|
addr.reset(), data.reset(), comp.reset();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
addr.append(codeaddr), data.append(codedata), comp.append(codecomp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
CheatCode::CheatCode(const string &s) {
|
||||||
|
operator=(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
CheatCode::CheatCode() {
|
||||||
|
enable = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
struct CheatCode {
|
||||||
|
bool enable;
|
||||||
|
array<unsigned> addr;
|
||||||
|
array<unsigned> data;
|
||||||
|
array<unsigned> comp;
|
||||||
|
|
||||||
|
bool operator=(const string&);
|
||||||
|
CheatCode(const string&);
|
||||||
|
CheatCode();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Cheat : public linear_vector<CheatCode> {
|
||||||
|
static bool decode(const string &code, unsigned &addr, unsigned &data, unsigned &comp);
|
||||||
|
|
||||||
|
void synchronize();
|
||||||
|
bool override[65536];
|
||||||
|
};
|
||||||
|
|
||||||
|
extern Cheat cheat;
|
|
@ -99,6 +99,7 @@ namespace GameBoy {
|
||||||
#include <gameboy/cpu/cpu.hpp>
|
#include <gameboy/cpu/cpu.hpp>
|
||||||
#include <gameboy/apu/apu.hpp>
|
#include <gameboy/apu/apu.hpp>
|
||||||
#include <gameboy/lcd/lcd.hpp>
|
#include <gameboy/lcd/lcd.hpp>
|
||||||
|
#include <gameboy/cheat/cheat.hpp>
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -42,7 +42,22 @@ Memory::~Memory() {
|
||||||
//
|
//
|
||||||
|
|
||||||
uint8 Bus::read(uint16 addr) {
|
uint8 Bus::read(uint16 addr) {
|
||||||
return mmio[addr]->mmio_read(addr);
|
uint8 data = mmio[addr]->mmio_read(addr);
|
||||||
|
|
||||||
|
if(cheat.override[addr]) {
|
||||||
|
for(unsigned x = 0; x < cheat.size(); x++) {
|
||||||
|
const CheatCode &code = cheat[x];
|
||||||
|
for(unsigned y = 0; y < code.addr.size(); y++) {
|
||||||
|
if(code.addr[y] == addr) {
|
||||||
|
if(code.comp[y] > 255 || code.comp[y] == data) {
|
||||||
|
return code.data[y];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Bus::write(uint16 addr, uint8 data) {
|
void Bus::write(uint16 addr, uint8 data) {
|
||||||
|
|
|
@ -49,6 +49,11 @@ void System::power() {
|
||||||
lcd.power();
|
lcd.power();
|
||||||
scheduler.init();
|
scheduler.init();
|
||||||
|
|
||||||
|
// cheat.reset();
|
||||||
|
// cheat.append(CheatCode("3EB-81B-4CA"));
|
||||||
|
// cheat[0].enable = true;
|
||||||
|
// cheat.synchronize();
|
||||||
|
|
||||||
clocks_executed = 0;
|
clocks_executed = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
nes_objects := nes-system nes-scheduler
|
nes_objects := nes-system nes-scheduler
|
||||||
nes_objects += nes-mapper nes-cartridge nes-memory
|
nes_objects += nes-mapper nes-cartridge nes-memory
|
||||||
nes_objects += nes-cpu nes-apu nes-ppu
|
nes_objects += nes-cpu nes-apu nes-ppu
|
||||||
|
nes_objects += nes-cheat
|
||||||
objects += $(nes_objects)
|
objects += $(nes_objects)
|
||||||
|
|
||||||
obj/nes-system.o: $(nes)/system/system.cpp $(call rwildcard,$(nes)/system/)
|
obj/nes-system.o: $(nes)/system/system.cpp $(call rwildcard,$(nes)/system/)
|
||||||
|
@ -11,3 +12,4 @@ obj/nes-memory.o: $(nes)/memory/memory.cpp $(call rwildcard,$(nes)/memory/)
|
||||||
obj/nes-cpu.o: $(nes)/cpu/cpu.cpp $(call rwildcard,$(nes)/cpu/)
|
obj/nes-cpu.o: $(nes)/cpu/cpu.cpp $(call rwildcard,$(nes)/cpu/)
|
||||||
obj/nes-apu.o: $(nes)/apu/apu.cpp $(call rwildcard,$(nes)/apu/)
|
obj/nes-apu.o: $(nes)/apu/apu.cpp $(call rwildcard,$(nes)/apu/)
|
||||||
obj/nes-ppu.o: $(nes)/ppu/ppu.cpp $(call rwildcard,$(nes)/ppu/)
|
obj/nes-ppu.o: $(nes)/ppu/ppu.cpp $(call rwildcard,$(nes)/ppu/)
|
||||||
|
obj/nes-cheat.o: $(nes)/cheat/cheat.cpp $(call rwildcard,$(nes)/cheat/)
|
||||||
|
|
|
@ -31,8 +31,9 @@ void Cartridge::load(const string &xml, const uint8_t *data, unsigned size) {
|
||||||
switch(mapperNumber) {
|
switch(mapperNumber) {
|
||||||
default : mapper = &Mapper::none; break;
|
default : mapper = &Mapper::none; break;
|
||||||
case 1: mapper = &Mapper::mmc1; break;
|
case 1: mapper = &Mapper::mmc1; break;
|
||||||
case 7: mapper = &Mapper::sn74hc161n; break;
|
case 3: mapper = &Mapper::cnrom; break;
|
||||||
case 16: mapper = &Mapper::lz93d50; break;
|
case 7: mapper = &Mapper::aorom; break;
|
||||||
|
case 16: mapper = &Mapper::bandaiFCG; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
loaded = true;
|
loaded = true;
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
#include <nes/nes.hpp>
|
||||||
|
|
||||||
|
namespace NES {
|
||||||
|
|
||||||
|
Cheat cheat;
|
||||||
|
|
||||||
|
bool Cheat::decode(const string &code, unsigned &addr, unsigned &data, unsigned &comp) {
|
||||||
|
static bool initialize = false;
|
||||||
|
static uint8 asciiMap[256];
|
||||||
|
|
||||||
|
if(initialize == false) {
|
||||||
|
initialize = true;
|
||||||
|
foreach(n, asciiMap) n = ~0;
|
||||||
|
asciiMap['A'] = 0; asciiMap['P'] = 1; asciiMap['Z'] = 2; asciiMap['L'] = 3;
|
||||||
|
asciiMap['G'] = 4; asciiMap['I'] = 5; asciiMap['T'] = 6; asciiMap['Y'] = 7;
|
||||||
|
asciiMap['E'] = 8; asciiMap['O'] = 9; asciiMap['X'] = 10; asciiMap['U'] = 11;
|
||||||
|
asciiMap['K'] = 12; asciiMap['S'] = 13; asciiMap['V'] = 14; asciiMap['N'] = 15;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned length = code.length(), bits = 0;
|
||||||
|
for(unsigned n = 0; n < length; n++) if(asciiMap[code[n]] > 15) return false;
|
||||||
|
|
||||||
|
if(code.length() == 6) {
|
||||||
|
for(unsigned n = 0; n < 6; n++) bits |= asciiMap[code[n]] << (20 - n * 4);
|
||||||
|
unsigned addrTable[] = { 10, 9, 8, 7, 2, 1, 0, 19, 14, 13, 12, 11, 6, 5, 4 };
|
||||||
|
unsigned dataTable[] = { 23, 18, 17, 16, 3, 22, 21, 20 };
|
||||||
|
|
||||||
|
addr = 0x8000, data = 0x00, comp = ~0;
|
||||||
|
for(unsigned n = 0; n < 15; n++) addr |= bits & (1 << addrTable[n]) ? 0x4000 >> n : 0;
|
||||||
|
for(unsigned n = 0; n < 8; n++) data |= bits & (1 << dataTable[n]) ? 0x80 >> n : 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(code.length() == 8) {
|
||||||
|
for(unsigned n = 0; n < 8; n++) bits |= asciiMap[code[n]] << (28 - n * 4);
|
||||||
|
unsigned addrTable[] = { 18, 17, 16, 15, 10, 9, 8, 27, 22, 21, 20, 19, 14, 13, 12 };
|
||||||
|
unsigned dataTable[] = { 31, 26, 25, 24, 3, 30, 29, 28 };
|
||||||
|
unsigned compTable[] = { 7, 2, 1, 0, 11, 6, 5,4 };
|
||||||
|
|
||||||
|
addr = 0x8000, data = 0x00, comp = 0x00;
|
||||||
|
for(unsigned n = 0; n < 15; n++) addr |= bits & (1 << addrTable[n]) ? 0x4000 >> n : 0;
|
||||||
|
for(unsigned n = 0; n < 8; n++) data |= bits & (1 << dataTable[n]) ? 0x80 >> n : 0;
|
||||||
|
for(unsigned n = 0; n < 8; n++) comp |= bits & (1 << compTable[n]) ? 0x80 >> n : 0;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Cheat::synchronize() {
|
||||||
|
foreach(n, override) n = false;
|
||||||
|
|
||||||
|
for(unsigned n = 0; n < size(); n++) {
|
||||||
|
const CheatCode &code = operator[](n);
|
||||||
|
|
||||||
|
for(unsigned n = 0; n < code.addr.size(); n++) {
|
||||||
|
override[code.addr[n]] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CheatCode::operator=(const string &s) {
|
||||||
|
addr.reset(), data.reset(), comp.reset();
|
||||||
|
|
||||||
|
lstring list;
|
||||||
|
list.split("+", s);
|
||||||
|
|
||||||
|
for(unsigned n = 0; n < list.size(); n++) {
|
||||||
|
unsigned codeaddr, codedata, codecomp;
|
||||||
|
if(Cheat::decode(list[n], codeaddr, codedata, codecomp) == false) {
|
||||||
|
addr.reset(), data.reset(), comp.reset();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
addr.append(codeaddr), data.append(codedata), comp.append(codecomp);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
CheatCode::CheatCode(const string &s) {
|
||||||
|
operator=(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
CheatCode::CheatCode() {
|
||||||
|
enable = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
struct CheatCode {
|
||||||
|
bool enable;
|
||||||
|
array<unsigned> addr;
|
||||||
|
array<unsigned> data;
|
||||||
|
array<unsigned> comp;
|
||||||
|
|
||||||
|
bool operator=(const string&);
|
||||||
|
CheatCode(const string&);
|
||||||
|
CheatCode();
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Cheat : public linear_vector<CheatCode> {
|
||||||
|
static bool decode(const string &code, unsigned &addr, unsigned &data, unsigned &comp);
|
||||||
|
|
||||||
|
void synchronize();
|
||||||
|
bool override[65536];
|
||||||
|
};
|
||||||
|
|
||||||
|
extern Cheat cheat;
|
|
@ -1,10 +1,6 @@
|
||||||
//TODO: this naming nomenclature does not work.
|
AOROM aorom;
|
||||||
//AOROM and CNROM use this same chip in different pin configurations.
|
|
||||||
//this emulates AOROM currently ...
|
|
||||||
|
|
||||||
SN74HC161N sn74hc161n;
|
uint8 AOROM::prg_read(uint16 addr) {
|
||||||
|
|
||||||
uint8 SN74HC161N::prg_read(uint16 addr) {
|
|
||||||
if(addr & 0x8000) {
|
if(addr & 0x8000) {
|
||||||
unsigned rom_addr = (prg_bank << 15) | (addr & 0x7fff);
|
unsigned rom_addr = (prg_bank << 15) | (addr & 0x7fff);
|
||||||
return cartridge.prg_data[mirror(rom_addr, cartridge.prg_size)];
|
return cartridge.prg_data[mirror(rom_addr, cartridge.prg_size)];
|
||||||
|
@ -13,35 +9,35 @@ uint8 SN74HC161N::prg_read(uint16 addr) {
|
||||||
return cpu.mdr();
|
return cpu.mdr();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SN74HC161N::prg_write(uint16 addr, uint8 data) {
|
void AOROM::prg_write(uint16 addr, uint8 data) {
|
||||||
if(addr & 0x8000) {
|
if(addr & 0x8000) {
|
||||||
prg_bank = data & 0x0f;
|
prg_bank = data & 0x0f;
|
||||||
mirror_select = data & 0x10;
|
mirror_select = data & 0x10;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 SN74HC161N::chr_read(uint16 addr) {
|
uint8 AOROM::chr_read(uint16 addr) {
|
||||||
return cartridge.chr_data[mirror(addr, cartridge.chr_size)];
|
return cartridge.chr_data[mirror(addr, cartridge.chr_size)];
|
||||||
}
|
}
|
||||||
|
|
||||||
void SN74HC161N::chr_write(uint16 addr, uint8 data) {
|
void AOROM::chr_write(uint16 addr, uint8 data) {
|
||||||
if(cartridge.chr_ram == false) return;
|
if(cartridge.chr_ram == false) return;
|
||||||
cartridge.chr_data[mirror(addr, cartridge.chr_size)] = data;
|
cartridge.chr_data[mirror(addr, cartridge.chr_size)] = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 SN74HC161N::ciram_read(uint13 addr) {
|
uint8 AOROM::ciram_read(uint13 addr) {
|
||||||
return ppu.ciram_read((mirror_select << 10) | (addr & 0x03ff));
|
return ppu.ciram_read((mirror_select << 10) | (addr & 0x03ff));
|
||||||
}
|
}
|
||||||
|
|
||||||
void SN74HC161N::ciram_write(uint13 addr, uint8 data) {
|
void AOROM::ciram_write(uint13 addr, uint8 data) {
|
||||||
return ppu.ciram_write((mirror_select << 10) | (addr & 0x03ff), data);
|
return ppu.ciram_write((mirror_select << 10) | (addr & 0x03ff), data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SN74HC161N::power() {
|
void AOROM::power() {
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SN74HC161N::reset() {
|
void AOROM::reset() {
|
||||||
prg_bank = 0x0f;
|
prg_bank = 0x0f;
|
||||||
mirror_select = 0;
|
mirror_select = 0;
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
struct SN74HC161N : Mapper {
|
struct AOROM : Mapper {
|
||||||
uint8 prg_read(uint16 addr);
|
uint8 prg_read(uint16 addr);
|
||||||
void prg_write(uint16 addr, uint8 data);
|
void prg_write(uint16 addr, uint8 data);
|
||||||
|
|
||||||
|
@ -16,4 +16,4 @@ private:
|
||||||
bool mirror_select;
|
bool mirror_select;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern SN74HC161N sn74hc161n;
|
extern AOROM aorom;
|
|
@ -1,6 +1,6 @@
|
||||||
LZ93D50 lz93d50;
|
BandaiFCG bandaiFCG;
|
||||||
|
|
||||||
uint8 LZ93D50::prg_read(uint16 addr) {
|
uint8 BandaiFCG::prg_read(uint16 addr) {
|
||||||
clock();
|
clock();
|
||||||
|
|
||||||
if(addr >= 0x8000 && addr <= 0xbfff) {
|
if(addr >= 0x8000 && addr <= 0xbfff) {
|
||||||
|
@ -16,7 +16,7 @@ uint8 LZ93D50::prg_read(uint16 addr) {
|
||||||
return cpu.mdr();
|
return cpu.mdr();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LZ93D50::prg_write(uint16 addr, uint8 data) {
|
void BandaiFCG::prg_write(uint16 addr, uint8 data) {
|
||||||
clock();
|
clock();
|
||||||
|
|
||||||
if(addr >= 0x6000) {
|
if(addr >= 0x6000) {
|
||||||
|
@ -49,32 +49,32 @@ void LZ93D50::prg_write(uint16 addr, uint8 data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 LZ93D50::chr_read(uint16 addr) {
|
uint8 BandaiFCG::chr_read(uint16 addr) {
|
||||||
unsigned rom_addr = (chr_bank[addr >> 10] << 10) | (addr & 0x03ff);
|
unsigned rom_addr = (chr_bank[addr >> 10] << 10) | (addr & 0x03ff);
|
||||||
return cartridge.chr_data[mirror(rom_addr, cartridge.chr_size)];
|
return cartridge.chr_data[mirror(rom_addr, cartridge.chr_size)];
|
||||||
}
|
}
|
||||||
|
|
||||||
void LZ93D50::chr_write(uint16 addr, uint8 data) {
|
void BandaiFCG::chr_write(uint16 addr, uint8 data) {
|
||||||
if(cartridge.chr_ram == false) return;
|
if(cartridge.chr_ram == false) return;
|
||||||
unsigned rom_addr = (chr_bank[addr >> 10] << 10) | (addr & 0x03ff);
|
unsigned rom_addr = (chr_bank[addr >> 10] << 10) | (addr & 0x03ff);
|
||||||
cartridge.chr_data[mirror(rom_addr, cartridge.chr_size)] = data;
|
cartridge.chr_data[mirror(rom_addr, cartridge.chr_size)] = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8 LZ93D50::ciram_read(uint13 addr) {
|
uint8 BandaiFCG::ciram_read(uint13 addr) {
|
||||||
addr = ciram_addr(addr);
|
addr = ciram_addr(addr);
|
||||||
return ppu.ciram_read(addr);
|
return ppu.ciram_read(addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LZ93D50::ciram_write(uint13 addr, uint8 data) {
|
void BandaiFCG::ciram_write(uint13 addr, uint8 data) {
|
||||||
addr = ciram_addr(addr);
|
addr = ciram_addr(addr);
|
||||||
return ppu.ciram_write(addr, data);
|
return ppu.ciram_write(addr, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void LZ93D50::power() {
|
void BandaiFCG::power() {
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LZ93D50::reset() {
|
void BandaiFCG::reset() {
|
||||||
for(unsigned n = 0; n < 8; n++) chr_bank[n] = 0x00;
|
for(unsigned n = 0; n < 8; n++) chr_bank[n] = 0x00;
|
||||||
prg_bank = 0x00;
|
prg_bank = 0x00;
|
||||||
mirror_select = 0;
|
mirror_select = 0;
|
||||||
|
@ -85,7 +85,7 @@ void LZ93D50::reset() {
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
unsigned LZ93D50::ciram_addr(unsigned addr) const {
|
unsigned BandaiFCG::ciram_addr(unsigned addr) const {
|
||||||
switch(mirror_select & 0x03) {
|
switch(mirror_select & 0x03) {
|
||||||
case 0: return ((addr & 0x0400) >> 0) | (addr & 0x03ff); //vertical mirroring
|
case 0: return ((addr & 0x0400) >> 0) | (addr & 0x03ff); //vertical mirroring
|
||||||
case 1: return ((addr & 0x0800) >> 1) | (addr & 0x03ff); //horizontal mirroring
|
case 1: return ((addr & 0x0800) >> 1) | (addr & 0x03ff); //horizontal mirroring
|
||||||
|
@ -95,7 +95,7 @@ unsigned LZ93D50::ciram_addr(unsigned addr) const {
|
||||||
throw;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LZ93D50::clock() {
|
void BandaiFCG::clock() {
|
||||||
if(irq_counter_enable) {
|
if(irq_counter_enable) {
|
||||||
if(--irq_counter == 0xffff) {
|
if(--irq_counter == 0xffff) {
|
||||||
cpu.set_irq_line(1);
|
cpu.set_irq_line(1);
|
|
@ -1,4 +1,4 @@
|
||||||
struct LZ93D50 : Mapper {
|
struct BandaiFCG : Mapper {
|
||||||
uint8 prg_read(uint16 addr);
|
uint8 prg_read(uint16 addr);
|
||||||
void prg_write(uint16 addr, uint8 data);
|
void prg_write(uint16 addr, uint8 data);
|
||||||
|
|
||||||
|
@ -23,4 +23,4 @@ private:
|
||||||
uint16 irq_latch;
|
uint16 irq_latch;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern LZ93D50 lz93d50;
|
extern BandaiFCG bandaiFCG;
|
|
@ -0,0 +1,42 @@
|
||||||
|
CNROM cnrom;
|
||||||
|
|
||||||
|
uint8 CNROM::prg_read(uint16 addr) {
|
||||||
|
if(addr & 0x8000) {
|
||||||
|
return cartridge.prg_data[mirror(addr & 0x7fff, cartridge.prg_size)];
|
||||||
|
}
|
||||||
|
|
||||||
|
return cpu.mdr();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CNROM::prg_write(uint16 addr, uint8 data) {
|
||||||
|
if(addr & 0x8000) chr_bank = data & 0x03;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 CNROM::chr_read(uint16 addr) {
|
||||||
|
unsigned chr_addr = (chr_bank * 0x2000) + (addr & 0x1fff);
|
||||||
|
return cartridge.chr_data[mirror(chr_addr, cartridge.chr_size)];
|
||||||
|
}
|
||||||
|
|
||||||
|
void CNROM::chr_write(uint16 addr, uint8 data) {
|
||||||
|
if(cartridge.chr_ram == false) return;
|
||||||
|
unsigned chr_addr = (chr_bank * 0x2000) + (addr & 0x1fff);
|
||||||
|
cartridge.chr_data[mirror(chr_addr, cartridge.chr_size)] = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8 CNROM::ciram_read(uint13 addr) {
|
||||||
|
if(cartridge.mirroring == 0) addr = ((addr & 0x0800) >> 1) | (addr & 0x03ff);
|
||||||
|
return ppu.ciram_read(addr & 0x07ff);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CNROM::ciram_write(uint13 addr, uint8 data) {
|
||||||
|
if(cartridge.mirroring == 0) addr = ((addr & 0x0800) >> 1) | (addr & 0x03ff);
|
||||||
|
return ppu.ciram_write(addr & 0x07ff, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CNROM::power() {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CNROM::reset() {
|
||||||
|
chr_bank = 0;
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
struct CNROM : Mapper {
|
||||||
|
uint8 prg_read(uint16 addr);
|
||||||
|
void prg_write(uint16 addr, uint8 data);
|
||||||
|
|
||||||
|
uint8 chr_read(uint16 addr);
|
||||||
|
void chr_write(uint16 addr, uint8 data);
|
||||||
|
|
||||||
|
uint8 ciram_read(uint13 addr);
|
||||||
|
void ciram_write(uint13 addr, uint8 data);
|
||||||
|
|
||||||
|
void power();
|
||||||
|
void reset();
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint2 chr_bank;
|
||||||
|
};
|
||||||
|
|
||||||
|
extern CNROM cnrom;
|
|
@ -22,9 +22,10 @@ namespace Mapper {
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "none/none.cpp"
|
#include "none/none.cpp"
|
||||||
#include "lz93d50/lz93d50.cpp"
|
#include "aorom/aorom.cpp"
|
||||||
|
#include "bandai-fcg/bandai-fcg.cpp"
|
||||||
|
#include "cnrom/cnrom.cpp"
|
||||||
#include "mmc1/mmc1.cpp"
|
#include "mmc1/mmc1.cpp"
|
||||||
#include "sn74hc161n/sn74hc161n.cpp"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,8 @@ namespace Mapper {
|
||||||
};
|
};
|
||||||
|
|
||||||
#include "none/none.hpp"
|
#include "none/none.hpp"
|
||||||
#include "lz93d50/lz93d50.hpp"
|
#include "aorom/aorom.hpp"
|
||||||
|
#include "bandai-fcg/bandai-fcg.hpp"
|
||||||
|
#include "cnrom/cnrom.hpp"
|
||||||
#include "mmc1/mmc1.hpp"
|
#include "mmc1/mmc1.hpp"
|
||||||
#include "sn74hc161n/sn74hc161n.hpp"
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,20 @@ uint8 Bus::read(uint16 addr) {
|
||||||
if(addr <= 0x1fff) return cpu.ram_read(addr);
|
if(addr <= 0x1fff) return cpu.ram_read(addr);
|
||||||
if(addr <= 0x3fff) return ppu.read(addr);
|
if(addr <= 0x3fff) return ppu.read(addr);
|
||||||
if(addr <= 0x4017) return cpu.read(addr);
|
if(addr <= 0x4017) return cpu.read(addr);
|
||||||
|
|
||||||
|
if(cheat.override[addr]) {
|
||||||
|
for(unsigned x = 0; x < cheat.size(); x++) {
|
||||||
|
const CheatCode &code = cheat[x];
|
||||||
|
for(unsigned y = 0; y < code.addr.size(); y++) {
|
||||||
|
if(code.addr[y] == addr) {
|
||||||
|
if(code.comp[y] > 255 || code.comp[y] == data) {
|
||||||
|
return code.data[y];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
namespace NES {
|
namespace NES {
|
||||||
namespace Info {
|
namespace Info {
|
||||||
static const char Name[] = "bnes";
|
static const char Name[] = "bnes";
|
||||||
static const char Version[] = "000.05";
|
static const char Version[] = "000.06";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,6 +107,7 @@ namespace NES {
|
||||||
#include <nes/cpu/cpu.hpp>
|
#include <nes/cpu/cpu.hpp>
|
||||||
#include <nes/apu/apu.hpp>
|
#include <nes/apu/apu.hpp>
|
||||||
#include <nes/ppu/ppu.hpp>
|
#include <nes/ppu/ppu.hpp>
|
||||||
|
#include <nes/cheat/cheat.hpp>
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -14,6 +14,11 @@ void System::power() {
|
||||||
apu.power();
|
apu.power();
|
||||||
ppu.power();
|
ppu.power();
|
||||||
scheduler.power();
|
scheduler.power();
|
||||||
|
|
||||||
|
// cheat.reset();
|
||||||
|
// cheat.append(CheatCode("GXXZZLVI"));
|
||||||
|
// cheat[0].enable = true;
|
||||||
|
// cheat.synchronize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void System::reset() {
|
void System::reset() {
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
namespace SNES {
|
namespace SNES {
|
||||||
namespace Info {
|
namespace Info {
|
||||||
static const char Name[] = "bsnes";
|
static const char Name[] = "bsnes";
|
||||||
static const char Version[] = "082.09";
|
static const char Version[] = "082.10";
|
||||||
static const unsigned SerializerVersion = 21;
|
static const unsigned SerializerVersion = 21;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,8 @@ include $(snes)/Makefile
|
||||||
include $(gameboy)/Makefile
|
include $(gameboy)/Makefile
|
||||||
name := batch
|
name := batch
|
||||||
|
|
||||||
ui_objects := ui-main ui-config ui-interface ui-utility ui-general
|
ui_objects := ui-main ui-config ui-interface ui-utility
|
||||||
|
ui_objects += ui-general ui-tools
|
||||||
ui_objects += phoenix ruby
|
ui_objects += phoenix ruby
|
||||||
ui_objects += $(if $(call streq,$(platform),win),resource)
|
ui_objects += $(if $(call streq,$(platform),win),resource)
|
||||||
|
|
||||||
|
@ -71,6 +72,7 @@ obj/ui-config.o: $(ui)/config/config.cpp $(call rwildcard,$(ui)/)
|
||||||
obj/ui-interface.o: $(ui)/interface/interface.cpp $(call rwildcard,$(ui)/)
|
obj/ui-interface.o: $(ui)/interface/interface.cpp $(call rwildcard,$(ui)/)
|
||||||
obj/ui-utility.o: $(ui)/utility/utility.cpp $(call rwildcard,$(ui)/)
|
obj/ui-utility.o: $(ui)/utility/utility.cpp $(call rwildcard,$(ui)/)
|
||||||
obj/ui-general.o: $(ui)/general/general.cpp $(call rwildcard,$(ui)/)
|
obj/ui-general.o: $(ui)/general/general.cpp $(call rwildcard,$(ui)/)
|
||||||
|
obj/ui-tools.o: $(ui)/tools/tools.cpp $(call rwildcard,$(ui)/)
|
||||||
|
|
||||||
obj/ruby.o: ruby/ruby.cpp $(call rwildcard,ruby/*)
|
obj/ruby.o: ruby/ruby.cpp $(call rwildcard,ruby/*)
|
||||||
$(call compile,$(rubydef) $(rubyflags))
|
$(call compile,$(rubydef) $(rubyflags))
|
||||||
|
|
|
@ -23,6 +23,7 @@ using namespace ruby;
|
||||||
#include "interface/interface.hpp"
|
#include "interface/interface.hpp"
|
||||||
#include "utility/utility.hpp"
|
#include "utility/utility.hpp"
|
||||||
#include "general/general.hpp"
|
#include "general/general.hpp"
|
||||||
|
#include "tools/tools.hpp"
|
||||||
|
|
||||||
struct Application {
|
struct Application {
|
||||||
bool quit;
|
bool quit;
|
||||||
|
|
|
@ -32,7 +32,20 @@ MainWindow::MainWindow() {
|
||||||
settingsMuteAudio.setText("Mute Audio");
|
settingsMuteAudio.setText("Mute Audio");
|
||||||
|
|
||||||
toolsMenu.setText("Tools");
|
toolsMenu.setText("Tools");
|
||||||
|
toolsStateSave.setText("Save State");
|
||||||
|
toolsStateSave1.setText("Slot 1");
|
||||||
|
toolsStateSave2.setText("Slot 2");
|
||||||
|
toolsStateSave3.setText("Slot 3");
|
||||||
|
toolsStateSave4.setText("Slot 4");
|
||||||
|
toolsStateSave5.setText("Slot 5");
|
||||||
|
toolsStateLoad.setText("Load State");
|
||||||
|
toolsStateLoad1.setText("Slot 1");
|
||||||
|
toolsStateLoad2.setText("Slot 2");
|
||||||
|
toolsStateLoad3.setText("Slot 3");
|
||||||
|
toolsStateLoad4.setText("Slot 4");
|
||||||
|
toolsStateLoad5.setText("Slot 5");
|
||||||
toolsShrinkWindow.setText("Shrink Window");
|
toolsShrinkWindow.setText("Shrink Window");
|
||||||
|
toolsCheatEditor.setText("Cheat Editor ...");
|
||||||
toolsTest.setText("Test");
|
toolsTest.setText("Test");
|
||||||
|
|
||||||
helpMenu.setText("Help");
|
helpMenu.setText("Help");
|
||||||
|
@ -66,7 +79,21 @@ MainWindow::MainWindow() {
|
||||||
settingsMenu.append(settingsMuteAudio);
|
settingsMenu.append(settingsMuteAudio);
|
||||||
|
|
||||||
append(toolsMenu);
|
append(toolsMenu);
|
||||||
|
toolsMenu.append(toolsStateSave);
|
||||||
|
toolsStateSave.append(toolsStateSave1);
|
||||||
|
toolsStateSave.append(toolsStateSave2);
|
||||||
|
toolsStateSave.append(toolsStateSave3);
|
||||||
|
toolsStateSave.append(toolsStateSave4);
|
||||||
|
toolsStateSave.append(toolsStateSave5);
|
||||||
|
toolsMenu.append(toolsStateLoad);
|
||||||
|
toolsStateLoad.append(toolsStateLoad1);
|
||||||
|
toolsStateLoad.append(toolsStateLoad2);
|
||||||
|
toolsStateLoad.append(toolsStateLoad3);
|
||||||
|
toolsStateLoad.append(toolsStateLoad4);
|
||||||
|
toolsStateLoad.append(toolsStateLoad5);
|
||||||
|
toolsMenu.append(toolsSeparator);
|
||||||
toolsMenu.append(toolsShrinkWindow);
|
toolsMenu.append(toolsShrinkWindow);
|
||||||
|
toolsMenu.append(toolsCheatEditor);
|
||||||
toolsMenu.append(toolsTest);
|
toolsMenu.append(toolsTest);
|
||||||
|
|
||||||
append(helpMenu);
|
append(helpMenu);
|
||||||
|
@ -87,32 +114,32 @@ MainWindow::MainWindow() {
|
||||||
|
|
||||||
cartridgeLoadNES.onTick = [&] {
|
cartridgeLoadNES.onTick = [&] {
|
||||||
fileBrowser->open("Load NES Cartridge", { "*.nes" }, [](string filename) {
|
fileBrowser->open("Load NES Cartridge", { "*.nes" }, [](string filename) {
|
||||||
interface->loadCartridgeNES(filename);
|
interface->loadCartridge(filename);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
cartridgeLoadSNES.onTick = [&] {
|
cartridgeLoadSNES.onTick = [&] {
|
||||||
fileBrowser->open("Load SNES Cartridge", { "*.sfc" }, [](string filename) {
|
fileBrowser->open("Load SNES Cartridge", { "*.sfc" }, [](string filename) {
|
||||||
interface->loadCartridgeSNES(filename);
|
interface->loadCartridge(filename);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
cartridgeLoadGameBoy.onTick = [&] {
|
cartridgeLoadGameBoy.onTick = [&] {
|
||||||
fileBrowser->open("Load Game Boy Cartridge", { "*.gb", "*.gbc" }, [](string filename) {
|
fileBrowser->open("Load Game Boy Cartridge", { "*.gb", "*.gbc" }, [](string filename) {
|
||||||
interface->loadCartridgeGameBoy(filename);
|
interface->loadCartridge(filename);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
nesPower.onTick = { &Interface::power, interface };
|
nesPower.onTick = { &Interface::power, interface };
|
||||||
nesReset.onTick = { &Interface::reset, interface };
|
nesReset.onTick = { &Interface::reset, interface };
|
||||||
nesCartridgeUnload.onTick = { &Interface::unloadCartridgeNES, interface };
|
nesCartridgeUnload.onTick = { &Interface::unloadCartridge, interface };
|
||||||
|
|
||||||
snesPower.onTick = { &Interface::power, interface };
|
snesPower.onTick = { &Interface::power, interface };
|
||||||
snesReset.onTick = { &Interface::reset, interface };
|
snesReset.onTick = { &Interface::reset, interface };
|
||||||
snesCartridgeUnload.onTick = { &Interface::unloadCartridgeSNES, interface };
|
snesCartridgeUnload.onTick = { &Interface::unloadCartridge, interface };
|
||||||
|
|
||||||
gameBoyPower.onTick = { &Interface::power, interface };
|
gameBoyPower.onTick = { &Interface::power, interface };
|
||||||
gameBoyCartridgeUnload.onTick = { &Interface::unloadCartridgeGameBoy, interface };
|
gameBoyCartridgeUnload.onTick = { &Interface::unloadCartridge, interface };
|
||||||
|
|
||||||
settingsSynchronizeVideo.onTick = [&] {
|
settingsSynchronizeVideo.onTick = [&] {
|
||||||
video.set(Video::Synchronize, settingsSynchronizeVideo.checked());
|
video.set(Video::Synchronize, settingsSynchronizeVideo.checked());
|
||||||
|
@ -126,8 +153,22 @@ MainWindow::MainWindow() {
|
||||||
dspaudio.setVolume(settingsMuteAudio.checked() ? 0.0 : 1.0);
|
dspaudio.setVolume(settingsMuteAudio.checked() ? 0.0 : 1.0);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
toolsStateSave1.onTick = [&] { interface->saveState({ interface->baseName, "-1.bst" }); };
|
||||||
|
toolsStateSave2.onTick = [&] { interface->saveState({ interface->baseName, "-2.bst" }); };
|
||||||
|
toolsStateSave3.onTick = [&] { interface->saveState({ interface->baseName, "-3.bst" }); };
|
||||||
|
toolsStateSave4.onTick = [&] { interface->saveState({ interface->baseName, "-4.bst" }); };
|
||||||
|
toolsStateSave5.onTick = [&] { interface->saveState({ interface->baseName, "-5.bst" }); };
|
||||||
|
|
||||||
|
toolsStateLoad1.onTick = [&] { interface->loadState({ interface->baseName, "-1.bst" }); };
|
||||||
|
toolsStateLoad2.onTick = [&] { interface->loadState({ interface->baseName, "-2.bst" }); };
|
||||||
|
toolsStateLoad3.onTick = [&] { interface->loadState({ interface->baseName, "-3.bst" }); };
|
||||||
|
toolsStateLoad4.onTick = [&] { interface->loadState({ interface->baseName, "-4.bst" }); };
|
||||||
|
toolsStateLoad5.onTick = [&] { interface->loadState({ interface->baseName, "-5.bst" }); };
|
||||||
|
|
||||||
toolsShrinkWindow.onTick = [&] { utility->resizeMainWindow(true); };
|
toolsShrinkWindow.onTick = [&] { utility->resizeMainWindow(true); };
|
||||||
|
|
||||||
|
toolsCheatEditor.onTick = [&] { cheatEditor->setVisible(); };
|
||||||
|
|
||||||
toolsTest.onTick = [&] {
|
toolsTest.onTick = [&] {
|
||||||
NES::cpu.trace = toolsTest.checked();
|
NES::cpu.trace = toolsTest.checked();
|
||||||
};
|
};
|
||||||
|
@ -139,4 +180,16 @@ MainWindow::MainWindow() {
|
||||||
"Website: http://byuu.org/"
|
"Website: http://byuu.org/"
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
synchronize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::synchronize() {
|
||||||
|
if(interface->loaded()) {
|
||||||
|
toolsStateSave.setEnabled(true);
|
||||||
|
toolsStateLoad.setEnabled(true);
|
||||||
|
} else {
|
||||||
|
toolsStateSave.setEnabled(false);
|
||||||
|
toolsStateLoad.setEnabled(false);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,12 +30,27 @@ struct MainWindow : Window {
|
||||||
CheckItem settingsMuteAudio;
|
CheckItem settingsMuteAudio;
|
||||||
|
|
||||||
Menu toolsMenu;
|
Menu toolsMenu;
|
||||||
|
Menu toolsStateSave;
|
||||||
|
Item toolsStateSave1;
|
||||||
|
Item toolsStateSave2;
|
||||||
|
Item toolsStateSave3;
|
||||||
|
Item toolsStateSave4;
|
||||||
|
Item toolsStateSave5;
|
||||||
|
Menu toolsStateLoad;
|
||||||
|
Item toolsStateLoad1;
|
||||||
|
Item toolsStateLoad2;
|
||||||
|
Item toolsStateLoad3;
|
||||||
|
Item toolsStateLoad4;
|
||||||
|
Item toolsStateLoad5;
|
||||||
|
Separator toolsSeparator;
|
||||||
Item toolsShrinkWindow;
|
Item toolsShrinkWindow;
|
||||||
|
Item toolsCheatEditor;
|
||||||
CheckItem toolsTest;
|
CheckItem toolsTest;
|
||||||
|
|
||||||
Menu helpMenu;
|
Menu helpMenu;
|
||||||
Item helpAbout;
|
Item helpAbout;
|
||||||
|
|
||||||
|
void synchronize();
|
||||||
MainWindow();
|
MainWindow();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,30 @@ void InterfaceGameBoy::unloadCartridge() {
|
||||||
interface->baseName = "";
|
interface->baseName = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool InterfaceGameBoy::saveState(const string &filename) {
|
||||||
|
GameBoy::system.runtosave();
|
||||||
|
serializer s = GameBoy::system.serialize();
|
||||||
|
return file::write(filename, s.data(), s.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InterfaceGameBoy::loadState(const string &filename) {
|
||||||
|
uint8_t *data;
|
||||||
|
unsigned size;
|
||||||
|
if(file::read(filename, data, size) == false) return false;
|
||||||
|
serializer s(data, size);
|
||||||
|
delete[] data;
|
||||||
|
return GameBoy::system.unserialize(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InterfaceGameBoy::setCheatCodes(const lstring &list) {
|
||||||
|
GameBoy::cheat.reset();
|
||||||
|
for(unsigned n = 0; n < list.size(); n++) {
|
||||||
|
GameBoy::cheat[n] = list[n];
|
||||||
|
GameBoy::cheat[n].enable = true;
|
||||||
|
}
|
||||||
|
GameBoy::cheat.synchronize();
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
void InterfaceGameBoy::video_refresh(const uint8_t *data) {
|
void InterfaceGameBoy::video_refresh(const uint8_t *data) {
|
||||||
|
|
|
@ -2,6 +2,10 @@ struct InterfaceGameBoy : GameBoy::Interface {
|
||||||
bool loadCartridge(const string &filename);
|
bool loadCartridge(const string &filename);
|
||||||
void unloadCartridge();
|
void unloadCartridge();
|
||||||
|
|
||||||
|
bool saveState(const string &filename);
|
||||||
|
bool loadState(const string &filename);
|
||||||
|
void setCheatCodes(const lstring &list);
|
||||||
|
|
||||||
void video_refresh(const uint8_t *data);
|
void video_refresh(const uint8_t *data);
|
||||||
void audio_sample(int16_t csample, int16_t lsample, int16_t rsample);
|
void audio_sample(int16_t csample, int16_t lsample, int16_t rsample);
|
||||||
bool input_poll(unsigned id);
|
bool input_poll(unsigned id);
|
||||||
|
|
|
@ -14,11 +14,14 @@ bool Interface::loaded() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Interface::loadCartridge(const string &filename) {
|
bool Interface::loadCartridge(const string &filename) {
|
||||||
if(filename.endswith(".nes")) return loadCartridgeNES(filename);
|
bool result = false;
|
||||||
if(filename.endswith(".sfc")) return loadCartridgeSNES(filename);
|
unloadCartridge();
|
||||||
if(filename.endswith(".gb" )) return loadCartridgeGameBoy(filename);
|
if(filename.endswith(".nes")) result = loadCartridgeNES(filename);
|
||||||
if(filename.endswith(".gbc")) return loadCartridgeGameBoy(filename);
|
if(filename.endswith(".sfc")) result = loadCartridgeSNES(filename);
|
||||||
return true;
|
if(filename.endswith(".gb" )) result = loadCartridgeGameBoy(filename);
|
||||||
|
if(filename.endswith(".gbc")) result = loadCartridgeGameBoy(filename);
|
||||||
|
if(result == true) cheatEditor->load({ baseName, ".cht" });
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Interface::loadCartridgeNES(const string &filename) {
|
bool Interface::loadCartridgeNES(const string &filename) {
|
||||||
|
@ -27,6 +30,19 @@ bool Interface::loadCartridgeNES(const string &filename) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Interface::unloadCartridge() {
|
||||||
|
if(loaded() == false) return;
|
||||||
|
cheatEditor->save({ baseName, ".cht" });
|
||||||
|
|
||||||
|
switch(mode()) {
|
||||||
|
case Mode::NES: nes.unloadCartridge(); break;
|
||||||
|
case Mode::SNES: snes.unloadCartridge(); break;
|
||||||
|
case Mode::GameBoy: gameBoy.unloadCartridge(); break;
|
||||||
|
}
|
||||||
|
|
||||||
|
utility->setMode(mode = Mode::None);
|
||||||
|
}
|
||||||
|
|
||||||
void Interface::unloadCartridgeNES() {
|
void Interface::unloadCartridgeNES() {
|
||||||
nes.unloadCartridge();
|
nes.unloadCartridge();
|
||||||
utility->setMode(mode = Mode::None);
|
utility->setMode(mode = Mode::None);
|
||||||
|
@ -86,6 +102,30 @@ void Interface::run() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Interface::saveState(const string &filename) {
|
||||||
|
switch(mode()) {
|
||||||
|
case Mode::SNES: return snes.saveState(filename);
|
||||||
|
case Mode::GameBoy: return gameBoy.saveState(filename);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Interface::loadState(const string &filename) {
|
||||||
|
switch(mode()) {
|
||||||
|
case Mode::SNES: return snes.loadState(filename);
|
||||||
|
case Mode::GameBoy: return gameBoy.loadState(filename);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Interface::setCheatCodes(const lstring &list) {
|
||||||
|
switch(mode()) {
|
||||||
|
case Mode::NES: return nes.setCheatCodes(list);
|
||||||
|
case Mode::SNES: return snes.setCheatCodes(list);
|
||||||
|
case Mode::GameBoy: return gameBoy.setCheatCodes(list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Interface::Interface() {
|
Interface::Interface() {
|
||||||
mode = Mode::None;
|
mode = Mode::None;
|
||||||
NES::system.init(&nes);
|
NES::system.init(&nes);
|
||||||
|
|
|
@ -13,6 +13,7 @@ struct Interface : property<Interface> {
|
||||||
bool loadCartridgeSNES(const string &filename);
|
bool loadCartridgeSNES(const string &filename);
|
||||||
bool loadCartridgeGameBoy(const string &filename);
|
bool loadCartridgeGameBoy(const string &filename);
|
||||||
|
|
||||||
|
void unloadCartridge();
|
||||||
void unloadCartridgeNES();
|
void unloadCartridgeNES();
|
||||||
void unloadCartridgeSNES();
|
void unloadCartridgeSNES();
|
||||||
void unloadCartridgeGameBoy();
|
void unloadCartridgeGameBoy();
|
||||||
|
@ -21,6 +22,10 @@ struct Interface : property<Interface> {
|
||||||
void reset();
|
void reset();
|
||||||
void run();
|
void run();
|
||||||
|
|
||||||
|
bool saveState(const string &filename);
|
||||||
|
bool loadState(const string &filename);
|
||||||
|
void setCheatCodes(const lstring &list);
|
||||||
|
|
||||||
Interface();
|
Interface();
|
||||||
|
|
||||||
int16_t inputState[Scancode::Limit];
|
int16_t inputState[Scancode::Limit];
|
||||||
|
|
|
@ -15,6 +15,15 @@ void InterfaceNES::unloadCartridge() {
|
||||||
interface->baseName = "";
|
interface->baseName = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InterfaceNES::setCheatCodes(const lstring &list) {
|
||||||
|
NES::cheat.reset();
|
||||||
|
for(unsigned n = 0; n < list.size(); n++) {
|
||||||
|
NES::cheat[n] = list[n];
|
||||||
|
NES::cheat[n].enable = true;
|
||||||
|
}
|
||||||
|
NES::cheat.synchronize();
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
void InterfaceNES::video_refresh(const uint32_t *data) {
|
void InterfaceNES::video_refresh(const uint32_t *data) {
|
||||||
|
|
|
@ -2,6 +2,8 @@ struct InterfaceNES : NES::Interface {
|
||||||
bool loadCartridge(const string &filename);
|
bool loadCartridge(const string &filename);
|
||||||
void unloadCartridge();
|
void unloadCartridge();
|
||||||
|
|
||||||
|
void setCheatCodes(const lstring &list);
|
||||||
|
|
||||||
void video_refresh(const uint32_t *data);
|
void video_refresh(const uint32_t *data);
|
||||||
void audio_sample(int16_t sample);
|
void audio_sample(int16_t sample);
|
||||||
int16_t input_poll(bool port, unsigned device, unsigned id);
|
int16_t input_poll(bool port, unsigned device, unsigned id);
|
||||||
|
|
|
@ -18,6 +18,30 @@ void InterfaceSNES::unloadCartridge() {
|
||||||
interface->baseName = "";
|
interface->baseName = "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool InterfaceSNES::saveState(const string &filename) {
|
||||||
|
SNES::system.runtosave();
|
||||||
|
serializer s = SNES::system.serialize();
|
||||||
|
return file::write(filename, s.data(), s.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool InterfaceSNES::loadState(const string &filename) {
|
||||||
|
uint8_t *data;
|
||||||
|
unsigned size;
|
||||||
|
if(file::read(filename, data, size) == false) return false;
|
||||||
|
serializer s(data, size);
|
||||||
|
delete[] data;
|
||||||
|
return SNES::system.unserialize(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
void InterfaceSNES::setCheatCodes(const lstring &list) {
|
||||||
|
SNES::cheat.reset();
|
||||||
|
for(unsigned n = 0; n < list.size(); n++) {
|
||||||
|
SNES::cheat[n] = list[n];
|
||||||
|
SNES::cheat[n].enabled = true;
|
||||||
|
}
|
||||||
|
SNES::cheat.synchronize();
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
void InterfaceSNES::video_refresh(const uint16_t *data, bool hires, bool interlace, bool overscan) {
|
void InterfaceSNES::video_refresh(const uint16_t *data, bool hires, bool interlace, bool overscan) {
|
||||||
|
@ -87,5 +111,5 @@ int16_t InterfaceSNES::input_poll(bool port, SNES::Input::Device device, unsigne
|
||||||
}
|
}
|
||||||
|
|
||||||
string InterfaceSNES::path(SNES::Cartridge::Slot slot, const string &hint) {
|
string InterfaceSNES::path(SNES::Cartridge::Slot slot, const string &hint) {
|
||||||
return "/home/byuu/Desktop/test";
|
return dir(interface->baseName);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,10 @@ struct InterfaceSNES : SNES::Interface {
|
||||||
bool loadCartridge(const string &filename);
|
bool loadCartridge(const string &filename);
|
||||||
void unloadCartridge();
|
void unloadCartridge();
|
||||||
|
|
||||||
|
bool saveState(const string &filename);
|
||||||
|
bool loadState(const string &filename);
|
||||||
|
void setCheatCodes(const lstring &list);
|
||||||
|
|
||||||
void video_refresh(const uint16_t *data, bool hires, bool interlace, bool overscan);
|
void video_refresh(const uint16_t *data, bool hires, bool interlace, bool overscan);
|
||||||
void audio_sample(int16_t lsample, int16_t rsample);
|
void audio_sample(int16_t lsample, int16_t rsample);
|
||||||
int16_t input_poll(bool port, SNES::Input::Device device, unsigned index, unsigned id);
|
int16_t input_poll(bool port, SNES::Input::Device device, unsigned index, unsigned id);
|
||||||
|
|
|
@ -41,6 +41,7 @@ Application::Application(int argc, char **argv) : quit(false) {
|
||||||
|
|
||||||
mainWindow = new MainWindow;
|
mainWindow = new MainWindow;
|
||||||
fileBrowser = new FileBrowser;
|
fileBrowser = new FileBrowser;
|
||||||
|
cheatEditor = new CheatEditor;
|
||||||
utility->setMode(Interface::Mode::None);
|
utility->setMode(Interface::Mode::None);
|
||||||
mainWindow->setVisible();
|
mainWindow->setVisible();
|
||||||
|
|
||||||
|
@ -73,9 +74,12 @@ Application::Application(int argc, char **argv) : quit(false) {
|
||||||
OS::processEvents();
|
OS::processEvents();
|
||||||
Application::run();
|
Application::run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface->unloadCartridge();
|
||||||
}
|
}
|
||||||
|
|
||||||
Application::~Application() {
|
Application::~Application() {
|
||||||
|
delete cheatEditor;
|
||||||
delete fileBrowser;
|
delete fileBrowser;
|
||||||
delete mainWindow;
|
delete mainWindow;
|
||||||
delete utility;
|
delete utility;
|
||||||
|
|
|
@ -0,0 +1,197 @@
|
||||||
|
CheatEditor *cheatEditor = 0;
|
||||||
|
|
||||||
|
CheatEditor::CheatEditor() {
|
||||||
|
setTitle("Cheat Editor");
|
||||||
|
setGeometry({ 128, 128, 600, 360 });
|
||||||
|
|
||||||
|
cheatList.setHeaderText("Slot", "Code", "Description");
|
||||||
|
cheatList.setHeaderVisible();
|
||||||
|
cheatList.setCheckable();
|
||||||
|
codeLabel.setText("Code(s):");
|
||||||
|
descLabel.setText("Description:");
|
||||||
|
findButton.setText("Find Codes ...");
|
||||||
|
findButton.setEnabled(false);
|
||||||
|
clearAllButton.setText("Clear All");
|
||||||
|
clearButton.setText("Clear");
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
for(unsigned n = 0; n < 128; n++) cheatList.append("", "", "");
|
||||||
|
updateUI();
|
||||||
|
synchronize();
|
||||||
|
|
||||||
|
cheatList.onChange = { &CheatEditor::synchronize, this };
|
||||||
|
cheatList.onTick = [&](unsigned) { updateInterface(); };
|
||||||
|
codeEdit.onChange = { &CheatEditor::updateCode, this };
|
||||||
|
descEdit.onChange = { &CheatEditor::updateDesc, this };
|
||||||
|
clearAllButton.onTick = { &CheatEditor::clearAll, this };
|
||||||
|
clearButton.onTick = { &CheatEditor::clearSelected, this };
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheatEditor::synchronize() {
|
||||||
|
layout.setEnabled(interface->loaded());
|
||||||
|
|
||||||
|
if(cheatList.selected()) {
|
||||||
|
unsigned n = cheatList.selection();
|
||||||
|
codeEdit.setText(cheatText[n][Code]);
|
||||||
|
descEdit.setText(cheatText[n][Desc]);
|
||||||
|
codeEdit.setEnabled(true);
|
||||||
|
descEdit.setEnabled(true);
|
||||||
|
clearButton.setEnabled(true);
|
||||||
|
} else {
|
||||||
|
codeEdit.setText("");
|
||||||
|
codeEdit.setEnabled(false);
|
||||||
|
descEdit.setText("");
|
||||||
|
descEdit.setEnabled(false);
|
||||||
|
clearButton.setEnabled(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheatEditor::updateUI() {
|
||||||
|
for(unsigned n = 0; n < 128; n++) {
|
||||||
|
string code = cheatText[n][Code];
|
||||||
|
string description = cheatText[n][Code] == "" && cheatText[n][Desc] == "" ? "(empty)" : cheatText[n][Desc];
|
||||||
|
lstring codes;
|
||||||
|
codes.split("+", code);
|
||||||
|
cheatList.modify(n, decimal<3>(n + 1), codes.size() == 1 ? code : string{ codes[0], "+..." }, description);
|
||||||
|
}
|
||||||
|
cheatList.autoSizeColumns();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheatEditor::updateInterface() {
|
||||||
|
lstring cheatCodes;
|
||||||
|
for(unsigned n = 0; n < 128; n++) {
|
||||||
|
string code = cheatText[n][Code];
|
||||||
|
if(cheatList.checked(n) && code != "") cheatCodes.append(code.replace(" ", ""));
|
||||||
|
}
|
||||||
|
interface->setCheatCodes(cheatCodes);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheatEditor::updateCode() {
|
||||||
|
unsigned n = cheatList.selection();
|
||||||
|
cheatText[n][Code] = codeEdit.text();
|
||||||
|
updateUI(), updateInterface();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheatEditor::updateDesc() {
|
||||||
|
unsigned n = cheatList.selection();
|
||||||
|
cheatText[n][Desc] = descEdit.text();
|
||||||
|
updateUI(), updateInterface();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheatEditor::clearAll() {
|
||||||
|
if(MessageWindow::question(*this, "Warning: all cheat codes will be permanently erased!\nAre you sure?")
|
||||||
|
== MessageWindow::Response::Yes) {
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheatEditor::clearSelected() {
|
||||||
|
unsigned n = cheatList.selection();
|
||||||
|
cheatList.setChecked(n, false);
|
||||||
|
cheatText[n][Code] = "";
|
||||||
|
cheatText[n][Desc] = "";
|
||||||
|
codeEdit.setText("");
|
||||||
|
descEdit.setText("");
|
||||||
|
updateUI(), updateInterface();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheatEditor::reset() {
|
||||||
|
synchronize();
|
||||||
|
for(unsigned n = 0; n < 128; n++) {
|
||||||
|
cheatList.setChecked(n, false);
|
||||||
|
cheatText[n][Code] = "";
|
||||||
|
cheatText[n][Desc] = "";
|
||||||
|
}
|
||||||
|
codeEdit.setText("");
|
||||||
|
descEdit.setText("");
|
||||||
|
updateUI(), updateInterface();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CheatEditor::load(const string &filename) {
|
||||||
|
synchronize();
|
||||||
|
|
||||||
|
string data;
|
||||||
|
if(data.readfile(filename) == false) return false;
|
||||||
|
|
||||||
|
unsigned n = 0;
|
||||||
|
xml_element document = xml_parse(data);
|
||||||
|
foreach(head, document.element) {
|
||||||
|
if(head.name == "cartridge") {
|
||||||
|
foreach(node, head.element) {
|
||||||
|
if(node.name == "cheat") {
|
||||||
|
bool enable = false;
|
||||||
|
string description;
|
||||||
|
string code;
|
||||||
|
foreach(attribute, node.attribute) {
|
||||||
|
if(attribute.name == "enabled") enable = (attribute.parse() == "true");
|
||||||
|
}
|
||||||
|
foreach(element, node.element) {
|
||||||
|
if(element.name == "description") description = element.parse();
|
||||||
|
else if(element.name == "code") code.append(element.parse(), "+");
|
||||||
|
}
|
||||||
|
code.rtrim<1>("+");
|
||||||
|
|
||||||
|
cheatList.setChecked(n, enable);
|
||||||
|
cheatText[n][Code] = code;
|
||||||
|
cheatText[n][Desc] = description;
|
||||||
|
|
||||||
|
if(++n >= 128) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateUI(), updateInterface();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CheatEditor::save(const string &filename) {
|
||||||
|
synchronize();
|
||||||
|
|
||||||
|
signed lastSave = -1;
|
||||||
|
for(signed n = 127; n >= 0; n--) {
|
||||||
|
if(cheatText[n][Code] != "" || cheatText[n][Desc] != "") {
|
||||||
|
lastSave = n;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(lastSave == -1) {
|
||||||
|
unlink(filename);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
file fp;
|
||||||
|
if(fp.open(filename, file::mode::write) == false) return false;
|
||||||
|
|
||||||
|
fp.print("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
|
||||||
|
fp.print("<cartridge>\n");
|
||||||
|
for(unsigned n = 0; n <= lastSave; n++) {
|
||||||
|
fp.print(" <cheat enabled=\"", cheatList.checked(n) ? "true" : "false", "\">\n");
|
||||||
|
fp.print(" <description>", cheatText[n][Desc], "</description>\n");
|
||||||
|
lstring list;
|
||||||
|
list.split("+", cheatText[n][Code]);
|
||||||
|
foreach(code, list) {
|
||||||
|
fp.print(" <code>", code, "</code>\n");
|
||||||
|
}
|
||||||
|
fp.print(" </cheat>\n");
|
||||||
|
}
|
||||||
|
fp.print("</cartridge>\n");
|
||||||
|
fp.close();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
struct CheatEditor : Window {
|
||||||
|
VerticalLayout layout;
|
||||||
|
ListView cheatList;
|
||||||
|
HorizontalLayout codeLayout;
|
||||||
|
Label codeLabel;
|
||||||
|
LineEdit codeEdit;
|
||||||
|
HorizontalLayout descLayout;
|
||||||
|
Label descLabel;
|
||||||
|
LineEdit descEdit;
|
||||||
|
HorizontalLayout controlLayout;
|
||||||
|
Button findButton;
|
||||||
|
Widget spacer;
|
||||||
|
Button clearAllButton;
|
||||||
|
Button clearButton;
|
||||||
|
|
||||||
|
void synchronize();
|
||||||
|
void updateUI();
|
||||||
|
void updateInterface();
|
||||||
|
void updateCode();
|
||||||
|
void updateDesc();
|
||||||
|
void clearAll();
|
||||||
|
void clearSelected();
|
||||||
|
|
||||||
|
void reset();
|
||||||
|
bool load(const string &filename);
|
||||||
|
bool save(const string &filename);
|
||||||
|
|
||||||
|
CheatEditor();
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum : unsigned { Code = 0, Desc = 1 };
|
||||||
|
string cheatText[128][2];
|
||||||
|
};
|
||||||
|
|
||||||
|
extern CheatEditor *cheatEditor;
|
|
@ -0,0 +1,2 @@
|
||||||
|
#include "../base.hpp"
|
||||||
|
#include "cheat-editor.cpp"
|
|
@ -0,0 +1 @@
|
||||||
|
#include "cheat-editor.hpp"
|
|
@ -12,6 +12,7 @@ void Utility::setMode(Interface::Mode mode) {
|
||||||
if(mode == Interface::Mode::None) {
|
if(mode == Interface::Mode::None) {
|
||||||
mainWindow->setTitle(application->title);
|
mainWindow->setTitle(application->title);
|
||||||
mainWindow->setStatusText("No cartridge loaded");
|
mainWindow->setStatusText("No cartridge loaded");
|
||||||
|
cheatEditor->reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
else if(mode == Interface::Mode::NES) {
|
else if(mode == Interface::Mode::NES) {
|
||||||
|
@ -32,6 +33,7 @@ void Utility::setMode(Interface::Mode mode) {
|
||||||
dspaudio.setFrequency(4194304.0);
|
dspaudio.setFrequency(4194304.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mainWindow->synchronize();
|
||||||
resizeMainWindow();
|
resizeMainWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue