o switch to v46

This commit is contained in:
David Voswinkel
2009-05-12 22:17:42 +02:00
parent 7a878eab39
commit 8e877d38d4
217 changed files with 1440 additions and 31284 deletions

View File

@@ -2,7 +2,7 @@ string Utility::selectCartridge() {
audio.clear();
QString filename = QFileDialog::getOpenFileName(0,
"Load Cartridge",
utf8() << (snes.config.path.rom != "" ? snes.config.path.rom : snes.config.path.current),
utf8() << (config.path.rom != "" ? config.path.rom : config.path.current),
"SNES images (*.smc *.sfc *.swc *.fig *.bs *.st"
#if defined(GZIP_SUPPORT)
" *.zip *.gz"
@@ -12,66 +12,150 @@ string Utility::selectCartridge() {
#endif
");;"
"All files (*)"
);
return string() << filename.toUtf8().constData();
);
string name = filename.toUtf8().constData();
if(strlen(name) > 0) config.path.current = basepath(name);
return name;
}
string Utility::selectFolder(const char *title) {
audio.clear();
QString pathname = QFileDialog::getExistingDirectory(0,
title, utf8() << snes.config.path.current,
QFileDialog::ShowDirsOnly);
return string() << pathname.toUtf8().constData();
title, utf8() << config.path.current,
QFileDialog::ShowDirsOnly);
string path = pathname.toUtf8().constData();
strtr(path, "\\", "/");
if(strend(path, "/") == false) path << "/";
return path;
}
void Utility::loadCartridge(const char *filename) {
switch(cartridge.detect_image_type(filename)) {
case Cartridge::TypeNormal: loadCartridgeNormal(filename); break;
case Cartridge::TypeBsxSlotted: winLoader->loadBsxSlottedCartridge(filename, ""); break;
case Cartridge::TypeBsxBios: winLoader->loadBsxCartridge(filename, ""); break;
case Cartridge::TypeBsx: winLoader->loadBsxCartridge(snes.config.path.bsx, filename); break;
case Cartridge::TypeSufamiTurboBios: winLoader->loadSufamiTurboCartridge(filename, "", ""); break;
case Cartridge::TypeSufamiTurbo: winLoader->loadSufamiTurboCartridge(snes.config.path.st, filename, ""); break;
void Utility::loadCartridge(const char *filename) {
SNES::MappedRAM memory;
if(loadCartridge(filename, memory) == false) return;
SNES::Cartridge::Type type = SNES::cartridge.detect_image_type(memory.data(), memory.size());
memory.reset();
switch(type) {
case SNES::Cartridge::TypeNormal: loadCartridgeNormal(filename); break;
case SNES::Cartridge::TypeBsxSlotted: winLoader->loadBsxSlottedCartridge(filename, ""); break;
case SNES::Cartridge::TypeBsxBios: winLoader->loadBsxCartridge(filename, ""); break;
case SNES::Cartridge::TypeBsx: winLoader->loadBsxCartridge(config.path.bsx, filename); break;
case SNES::Cartridge::TypeSufamiTurboBios: winLoader->loadSufamiTurboCartridge(filename, "", ""); break;
case SNES::Cartridge::TypeSufamiTurbo: winLoader->loadSufamiTurboCartridge(config.path.st, filename, ""); break;
case SNES::Cartridge::TypeSuperGameBoyBios: winLoader->loadSuperGameBoyCartridge(filename, ""); break;
case SNES::Cartridge::TypeGameBoy: winLoader->loadSuperGameBoyCartridge(config.path.sgb, filename); break;
}
}
bool Utility::loadCartridgeNormal(const char *base) {
if(!*base) return false;
unloadCartridge();
cartridge.load_normal(base);
bool Utility::loadCartridgeNormal(const char *base) {
unloadCartridge();
if(loadCartridge(cartridge.baseName = base, SNES::memory::cartrom) == false) return false;
SNES::cartridge.load(SNES::Cartridge::ModeNormal);
loadMemory(cartridge.baseName, ".srm", SNES::memory::cartram);
loadMemory(cartridge.baseName, ".rtc", SNES::memory::cartrtc);
cartridge.name = basename(base);
modifySystemState(LoadCartridge);
return true;
}
bool Utility::loadCartridgeBsxSlotted(const char *base, const char *slot) {
if(!*base) return false;
unloadCartridge();
cartridge.load_bsx_slotted(base, slot);
bool Utility::loadCartridgeBsxSlotted(const char *base, const char *slot) {
unloadCartridge();
if(loadCartridge(cartridge.baseName = base, SNES::memory::cartrom) == false) return false;
loadCartridge(cartridge.slotAName = slot, SNES::memory::bsxflash);
SNES::cartridge.load(SNES::Cartridge::ModeBsxSlotted);
loadMemory(cartridge.baseName, ".srm", SNES::memory::cartram);
loadMemory(cartridge.baseName, ".rtc", SNES::memory::cartrtc);
cartridge.name = basename(base);
if(*slot) cartridge.name << " + " << basename(slot);
modifySystemState(LoadCartridge);
return true;
}
bool Utility::loadCartridgeBsx(const char *base, const char *slot) {
if(!*base) return false;
bool Utility::loadCartridgeBsx(const char *base, const char *slot) {
unloadCartridge();
cartridge.load_bsx(base, slot);
if(loadCartridge(cartridge.baseName = base, SNES::memory::cartrom) == false) return false;
loadCartridge(cartridge.slotAName = slot, SNES::memory::bsxflash);
SNES::cartridge.load(SNES::Cartridge::ModeBsx);
loadMemory(cartridge.baseName, ".srm", SNES::memory::bsxram );
loadMemory(cartridge.baseName, ".psr", SNES::memory::bsxpram);
cartridge.name = (*slot ? basename(slot) : basename(base));
modifySystemState(LoadCartridge);
return true;
}
bool Utility::loadCartridgeSufamiTurbo(const char *base, const char *slotA, const char *slotB) {
if(!*base) return false;
unloadCartridge();
cartridge.load_sufami_turbo(base, slotA, slotB);
bool Utility::loadCartridgeSufamiTurbo(const char *base, const char *slotA, const char *slotB) {
unloadCartridge();
if(loadCartridge(cartridge.baseName = base, SNES::memory::cartrom) == false) return false;
loadCartridge(cartridge.slotAName = slotA, SNES::memory::stArom);
loadCartridge(cartridge.slotBName = slotB, SNES::memory::stBrom);
SNES::cartridge.load(SNES::Cartridge::ModeSufamiTurbo);
loadMemory(cartridge.slotAName, ".srm", SNES::memory::stAram);
loadMemory(cartridge.slotBName, ".srm", SNES::memory::stBram);
if(!*slotA && !*slotB) cartridge.name = basename(base);
else if(!*slotB) cartridge.name = basename(slotA);
else if(!*slotA) cartridge.name = basename(slotB);
else cartridge.name = string() << basename(slotA) << " + " << basename(slotB);
modifySystemState(LoadCartridge);
return true;
}
}
bool Utility::loadCartridgeSuperGameBoy(const char *base, const char *slot) {
unloadCartridge();
if(loadCartridge(cartridge.baseName = base, SNES::memory::cartrom) == false) return false;
loadCartridge(cartridge.slotAName = slot, SNES::memory::gbrom);
SNES::cartridge.load(SNES::Cartridge::ModeSuperGameBoy);
loadMemory(cartridge.slotAName, ".sav", SNES::memory::gbram);
cartridge.name = (*slot ? basename(slot) : basename(base));
modifySystemState(LoadCartridge);
return true;
}
void Utility::saveMemory() {
if(SNES::cartridge.loaded() == false) return;
switch(SNES::cartridge.mode()) {
case SNES::Cartridge::ModeNormal:
case SNES::Cartridge::ModeBsxSlotted: {
saveMemory(cartridge.baseName, ".srm", SNES::memory::cartram);
saveMemory(cartridge.baseName, ".rtc", SNES::memory::cartrtc);
} break;
case SNES::Cartridge::ModeBsx: {
saveMemory(cartridge.baseName, ".srm", SNES::memory::bsxram );
saveMemory(cartridge.baseName, ".psr", SNES::memory::bsxpram);
} break;
case SNES::Cartridge::ModeSufamiTurbo: {
saveMemory(cartridge.slotAName, ".srm", SNES::memory::stAram);
saveMemory(cartridge.slotBName, ".srm", SNES::memory::stBram);
} break;
case SNES::Cartridge::ModeSuperGameBoy: {
saveMemory(cartridge.slotAName, ".sav", SNES::memory::gbram);
} break;
}
}
void Utility::unloadCartridge() {
if(cartridge.loaded()) {
cartridge.unload();
modifySystemState(UnloadCartridge);
}
if(SNES::cartridge.loaded() == false) return;
saveMemory();
modifySystemState(UnloadCartridge);
}
void Utility::modifySystemState(system_state_t state) {
@@ -81,19 +165,19 @@ void Utility::modifySystemState(system_state_t state) {
switch(state) {
case LoadCartridge: {
//must call cartridge.load_cart_...() before calling modifySystemState(LoadCartridge)
if(cartridge.loaded() == false) break;
if(SNES::cartridge.loaded() == false) break;
loadCheats();
application.power = true;
application.pause = false;
snes.power();
SNES::system.power();
//warn if unsupported hardware detected
string chip;
if(cartridge.has_superfx()) chip = "SuperFX";
else if(cartridge.has_sa1()) chip = "SA-1";
else if(cartridge.has_st011()) chip = "ST011";
else if(cartridge.has_st018()) chip = "ST018";
else if(cartridge.has_dsp3()) chip = "DSP-3";
if(SNES::cartridge.has_superfx()) chip = "SuperFX";
else if(SNES::cartridge.has_st011()) chip = "ST011";
else if(SNES::cartridge.has_st018()) chip = "ST018";
else if(SNES::cartridge.has_dsp3()) chip = "DSP-3"; //unplayable; only partially supported
if(chip != "") {
QMessageBox::warning(winMain->window, "Warning", utf8()
<< "<p><b>Warning:</b><br>Unsupported " << chip << " chip detected. "
@@ -101,34 +185,36 @@ void Utility::modifySystemState(system_state_t state) {
}
showMessage(utf8()
<< "Loaded " << cartridge.name()
<< (cartridge.patched() ? ", and applied UPS patch." : "."));
winMain->window->setWindowTitle(utf8() << BSNES_TITLE << " - " << cartridge.name());
<< "Loaded " << cartridge.name
<< (false ? ", and applied UPS patch." : "."));
winMain->window->setWindowTitle(utf8() << BSNES_TITLE << " - " << cartridge.name);
} break;
case UnloadCartridge: {
if(cartridge.loaded() == false) break; //no cart to unload?
cartridge.unload();
if(SNES::cartridge.loaded() == false) break; //no cart to unload?
saveCheats();
SNES::cartridge.unload();
application.power = false;
application.pause = true;
showMessage(utf8() << "Unloaded " << cartridge.name() << ".");
showMessage(utf8() << "Unloaded " << cartridge.name << ".");
winMain->window->setWindowTitle(utf8() << BSNES_TITLE);
} break;
case PowerOn: {
if(cartridge.loaded() == false || application.power == true) break;
if(SNES::cartridge.loaded() == false || application.power == true) break;
application.power = true;
application.pause = false;
snes.power();
SNES::system.power();
showMessage("Power on.");
} break;
case PowerOff: {
if(cartridge.loaded() == false || application.power == false) break;
if(SNES::cartridge.loaded() == false || application.power == false) break;
application.power = false;
application.pause = true;
@@ -137,20 +223,20 @@ void Utility::modifySystemState(system_state_t state) {
} break;
case PowerCycle: {
if(cartridge.loaded() == false) break;
if(SNES::cartridge.loaded() == false) break;
application.power = true;
application.pause = false;
snes.power();
SNES::system.power();
showMessage("System power was cycled.");
} break;
case Reset: {
if(cartridge.loaded() == false || application.power == false) break;
if(SNES::cartridge.loaded() == false || application.power == false) break;
application.pause = false;
snes.reset();
SNES::system.reset();
showMessage("System was reset.");
} break;
@@ -161,3 +247,182 @@ void Utility::modifySystemState(system_state_t state) {
winCheatEditor->reloadList();
winCheatEditor->syncUi();
}
//
bool Utility::loadCartridge(const char *filename, SNES::MappedRAM &memory) {
if(file::exists(filename) == false) return false;
Reader::Type filetype = Reader::detect(filename, config.file.autodetect_type);
uint8_t *data;
unsigned size;
switch(filetype) { default:
case Reader::Normal: {
FileReader fp(filename);
if(!fp.ready()) return false;
size = fp.size();
data = fp.read();
} break;
#ifdef GZIP_SUPPORT
case Reader::GZIP: {
GZReader fp(filename);
if(!fp.ready()) return false;
size = fp.size();
data = fp.read();
} break;
case Reader::ZIP: {
ZipReader fp(filename);
if(!fp.ready()) return false;
size = fp.size();
data = fp.read();
} break;
#endif
#ifdef JMA_SUPPORT
case Reader::JMA: {
try {
JMAReader fp(filename);
size = fp.size();
data = fp.read();
} catch(JMA::jma_errors) {
return false;
}
} break;
#endif
}
if((size & 0x7fff) == 512) memmove(data, data + 512, size -= 512);
memory.map(data, size);
return true;
}
bool Utility::loadMemory(const char *filename, const char *extension, SNES::MappedRAM &memory) {
if(memory.size() == 0 || memory.size() == -1U) return false;
string name;
name << filepath(basename(filename), config.path.save);
name << extension;
file fp;
if(fp.open(name, file::mode_read) == false) return false;
unsigned size;
uint8_t *data = new uint8_t[size = fp.size()];
fp.read(data, size);
fp.close();
memcpy(memory.data(), data, min(size, memory.size()));
return true;
}
bool Utility::saveMemory(const char *filename, const char *extension, SNES::MappedRAM &memory) {
if(memory.size() == 0 || memory.size() == -1U) return false;
string name;
name << filepath(basename(filename), config.path.save);
name << extension;
file fp;
if(fp.open(name, file::mode_write) == false) return false;
fp.write(memory.data(), memory.size());
fp.close();
return true;
}
void Utility::loadCheats() {
string name, data;
name << filepath(basename(cartridge.baseName), config.path.cheat);
name << ".cht";
SNES::cheat.clear();
if(data.readfile(name)) SNES::cheat.load(data);
}
void Utility::saveCheats() {
string name;
name << filepath(basename(cartridge.baseName), config.path.cheat);
name << ".cht";
file fp;
if(SNES::cheat.count() > 0 || file::exists(name)) {
if(fp.open(name, file::mode_write)) {
fp.print(SNES::cheat.save());
fp.close();
}
}
}
//
//ensure file path is absolute (eg resolve relative paths)
string Utility::filepath(const char *filename, const char *pathname) {
//if no pathname, return filename as-is
string file(filename);
file.replace("\\", "/");
string path = (!pathname || !*pathname) ? (const char*)config.path.current : pathname;
//ensure path ends with trailing '/'
path.replace("\\", "/");
if(!strend(path, "/")) path.append("/");
//replace relative path with absolute path
if(strbegin(path, "./")) {
ltrim(path, "./");
path = string() << config.path.base << path;
}
//remove folder part of filename
lstring part;
part.split("/", file);
return path << part[part.size() - 1];
}
//remove directory information and file extension ("/foo/bar.ext" -> "bar")
string Utility::basename(const char *filename) {
string name(filename);
//remove extension
for(signed i = strlen(name) - 1; i >= 0; i--) {
if(name[i] == '.') {
name[i] = 0;
break;
}
}
//remove directory information
for(signed i = strlen(name) - 1; i >= 0; i--) {
if(name[i] == '/' || name[i] == '\\') {
i++;
char *output = name();
while(true) {
*output++ = name[i];
if(!name[i]) break;
i++;
}
break;
}
}
return name;
}
//remove filename and return path only ("/foo/bar.ext" -> "/foo/")
string Utility::basepath(const char *filename) {
string path(filename);
path.replace("\\", "/");
//remove filename
for(signed i = strlen(path) - 1; i >= 0; i--) {
if(path[i] == '/') {
path[i] = 0;
break;
}
}
if(!strend(path, "/")) path.append("/");
return path;
}

View File

@@ -57,6 +57,7 @@ void Utility::inputEvent(uint16_t code) {
if(isButtonDown(code, inputUiGeneral.pauseEmulation)) {
application.pause = !application.pause;
if(application.pause) audio.clear();
}
if(isButtonDown(code, inputUiGeneral.resetSystem)) {
@@ -80,11 +81,11 @@ void Utility::inputEvent(uint16_t code) {
}
if(isButtonDown(code, inputUiGeneral.toggleCheatSystem)) {
if(cheat.enabled() == false) {
cheat.enable();
if(SNES::cheat.enabled() == false) {
SNES::cheat.enable();
showMessage("Cheat system enabled.");
} else {
cheat.disable();
SNES::cheat.disable();
showMessage("Cheat system disabled.");
}
}
@@ -125,15 +126,15 @@ void Utility::showMessage(const char *message) {
void Utility::updateSystemState() {
string text;
if(cartridge.loaded() == false) {
if(SNES::cartridge.loaded() == false) {
text = "No cartridge loaded";
} else if(application.power == false) {
text = "Power off";
} else if(application.pause == true || application.autopause == true) {
text = "Paused";
} else if(ppu.status.frames_updated == true) {
ppu.status.frames_updated = false;
text << (int)ppu.status.frames_executed;
} else if(SNES::ppu.status.frames_updated == true) {
SNES::ppu.status.frames_updated = false;
text << (int)SNES::ppu.status.frames_executed;
text << " fps";
} else {
//nothing to update
@@ -144,12 +145,12 @@ void Utility::updateSystemState() {
}
void Utility::acquireMouse() {
if(cartridge.loaded()) {
if(snes.config.controller_port1 == SNES::Input::DeviceMouse
|| snes.config.controller_port2 == SNES::Input::DeviceMouse
|| snes.config.controller_port2 == SNES::Input::DeviceSuperScope
|| snes.config.controller_port2 == SNES::Input::DeviceJustifier
|| snes.config.controller_port2 == SNES::Input::DeviceJustifiers
if(SNES::cartridge.loaded()) {
if(SNES::config.controller_port1 == SNES::Input::DeviceMouse
|| SNES::config.controller_port2 == SNES::Input::DeviceMouse
|| SNES::config.controller_port2 == SNES::Input::DeviceSuperScope
|| SNES::config.controller_port2 == SNES::Input::DeviceJustifier
|| SNES::config.controller_port2 == SNES::Input::DeviceJustifiers
) input.acquire();
}
}
@@ -165,9 +166,9 @@ void Utility::updateAvSync() {
void Utility::updateVideoMode() {
if(config.video.context->region == 0) {
snes.video.set_mode(SNES::Video::ModeNTSC);
SNES::video.set_mode(SNES::Video::ModeNTSC);
} else {
snes.video.set_mode(SNES::Video::ModePAL);
SNES::video.set_mode(SNES::Video::ModePAL);
}
}
@@ -213,6 +214,6 @@ void Utility::updateEmulationSpeed() {
}
void Utility::updateControllers() {
snes.input.port_set_device(0, snes.config.controller_port1);
snes.input.port_set_device(1, snes.config.controller_port2);
SNES::input.port_set_device(0, SNES::config.controller_port1);
SNES::input.port_set_device(1, SNES::config.controller_port2);
}

View File

@@ -16,18 +16,34 @@ public:
void updateEmulationSpeed();
void updateControllers();
//cartridge.cpp
//cartridge.cpp
struct Cartridge {
string name, baseName, slotAName, slotBName;
} cartridge;
string selectCartridge();
string selectFolder(const char *title);
void loadCartridge(const char*);
bool loadCartridgeNormal(const char*);
bool loadCartridgeBsxSlotted(const char*, const char*);
bool loadCartridgeBsx(const char*, const char*);
bool loadCartridgeSufamiTurbo(const char*, const char *, const char*);
bool loadCartridgeSufamiTurbo(const char*, const char *, const char*);
bool loadCartridgeSuperGameBoy(const char*, const char*);
void saveMemory();
void unloadCartridge();
enum system_state_t { LoadCartridge, UnloadCartridge, PowerOn, PowerOff, PowerCycle, Reset };
void modifySystemState(system_state_t state);
void modifySystemState(system_state_t state);
bool loadCartridge(const char*, SNES::MappedRAM&);
bool loadMemory(const char*, const char*, SNES::MappedRAM&);
bool saveMemory(const char*, const char*, SNES::MappedRAM&);
void loadCheats();
void saveCheats();
string filepath(const char *filename, const char *pathname);
string basename(const char *filename);
string basepath(const char *filename);
//window.cpp
void showCentered(QWidget *window);

View File

@@ -2,31 +2,39 @@
void Utility::showCentered(QWidget *window) {
QRect deskRect = QApplication::desktop()->availableGeometry(window);
//place window offscreen, so that it can be shown to get proper frameSize()
window->move(std::numeric_limits<signed>::max(), std::numeric_limits<signed>::max());
#ifdef _WIN32
if(window->isMinimized() == false) {
//place window offscreen, so that it can be shown to get proper frameSize()
window->move(std::numeric_limits<signed>::max(), std::numeric_limits<signed>::max());
}
window->showNormal();
//force-resize window to be as small as minimumSize() will allow, and then center it
window->resize(0, 0);
window->move(
deskRect.center().x() - (window->frameSize().width() / 2),
deskRect.center().y() - (window->frameSize().height() / 2)
);
#else
if(window->isVisible() == false) window->showMinimized();
window->resize(0, 0);
#ifndef _WIN32
//Xlib frame size (excluding inside) is QSize(0, 0) at first, wait for it to be valid
//Xlib returns a frame size of 0,0 at first; wait for it to be valid
for(unsigned counter = 0; counter < 4096; counter++) {
if(window->frameSize() != window->size()) break;
application.processEvents();
}
#endif
//in case frame size changed, recenter window
window->move(
deskRect.center().x() - (window->frameSize().width() / 2),
deskRect.center().y() - (window->frameSize().height() / 2)
);
for(unsigned counter = 0; counter < 4096; counter++) {
window->showNormal();
application.processEvents();
if(window->isMinimized() == false) break;
}
#endif
//ensure window has focus
application.processEvents();
window->activateWindow();
@@ -84,6 +92,15 @@ void Utility::resizeMainWindow() {
//get effective desktop work area region (ignore Windows taskbar, OS X doc, etc.)
QRect deskRect = QApplication::desktop()->availableGeometry(winMain->window);
if(winMain->window->isVisible() == false) {
#ifdef _WIN32
winMain->window->move(std::numeric_limits<signed>::max(), std::numeric_limits<signed>::max());
winMain->window->showNormal();
#else
winMain->window->showMinimized();
#endif
}
//calculate frame geometry (window border + menubar + statusbar)
unsigned frameWidth = winMain->window->frameSize().width() - winMain->canvasContainer->size().width();
unsigned frameHeight = winMain->window->frameSize().height() - winMain->canvasContainer->size().height();