o cleanup

This commit is contained in:
optixx
2009-04-22 20:04:28 +02:00
parent 55e3468f74
commit 0c378a9f7c
1078 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,163 @@
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),
"SNES images (*.smc *.sfc *.swc *.fig *.bs *.st"
#if defined(GZIP_SUPPORT)
" *.zip *.gz"
#endif
#if defined(JMA_SUPPORT)
" *.jma"
#endif
");;"
"All files (*)"
);
return string() << filename.toUtf8().constData();
}
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();
}
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;
}
}
bool Utility::loadCartridgeNormal(const char *base) {
if(!*base) return false;
unloadCartridge();
cartridge.load_normal(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);
modifySystemState(LoadCartridge);
return true;
}
bool Utility::loadCartridgeBsx(const char *base, const char *slot) {
if(!*base) return false;
unloadCartridge();
cartridge.load_bsx(base, slot);
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);
modifySystemState(LoadCartridge);
return true;
}
void Utility::unloadCartridge() {
if(cartridge.loaded()) {
cartridge.unload();
modifySystemState(UnloadCartridge);
}
}
void Utility::modifySystemState(system_state_t state) {
video.clear();
audio.clear();
switch(state) {
case LoadCartridge: {
//must call cartridge.load_cart_...() before calling modifySystemState(LoadCartridge)
if(cartridge.loaded() == false) break;
application.power = true;
application.pause = false;
snes.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(chip != "") {
QMessageBox::warning(winMain->window, "Warning", utf8()
<< "<p><b>Warning:</b><br>Unsupported " << chip << " chip detected. "
<< "It is unlikely that this title will work properly.</p>");
}
showMessage(utf8()
<< "Loaded " << cartridge.name()
<< (cartridge.patched() ? ", 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();
application.power = false;
application.pause = true;
showMessage(utf8() << "Unloaded " << cartridge.name() << ".");
winMain->window->setWindowTitle(utf8() << BSNES_TITLE);
} break;
case PowerOn: {
if(cartridge.loaded() == false || application.power == true) break;
application.power = true;
application.pause = false;
snes.power();
showMessage("Power on.");
} break;
case PowerOff: {
if(cartridge.loaded() == false || application.power == false) break;
application.power = false;
application.pause = true;
showMessage("Power off.");
} break;
case PowerCycle: {
if(cartridge.loaded() == false) break;
application.power = true;
application.pause = false;
snes.power();
showMessage("System power was cycled.");
} break;
case Reset: {
if(cartridge.loaded() == false || application.power == false) break;
application.pause = false;
snes.reset();
showMessage("System was reset.");
} break;
}
winMain->syncUi();
winCodeEditor->dismiss();
winCheatEditor->reloadList();
winCheatEditor->syncUi();
}

View File

@@ -0,0 +1,218 @@
#include "cartridge.cpp"
#include "window.cpp"
//returns true if requested code is a button, and it has just been pressed down
bool Utility::isButtonDown(uint16_t inputCode, InputObject &object) {
if(inputCode != object.code) return false;
if(object.codetype != InputCode::KeyboardButton
&& object.codetype != InputCode::MouseButton
&& object.codetype != InputCode::JoypadHat
&& object.codetype != InputCode::JoypadAxis
&& object.codetype != InputCode::JoypadButton) return false;
int16_t state = inputManager.state(object.code);
int16_t lastState = inputManager.lastState(object.code);
if(object.codetype == InputCode::JoypadHat) {
switch(object.modifier) {
case InputObject::Up: return (state & joypad<>::hat_up ) && !(lastState & joypad<>::hat_up );
case InputObject::Down: return (state & joypad<>::hat_down ) && !(lastState & joypad<>::hat_down );
case InputObject::Left: return (state & joypad<>::hat_left ) && !(lastState & joypad<>::hat_left );
case InputObject::Right: return (state & joypad<>::hat_right) && !(lastState & joypad<>::hat_right);
}
} else if(object.codetype == InputCode::JoypadAxis) {
switch(object.modifier) {
case InputObject::Lo: return (state < -16384) && !(lastState < -16384);
case InputObject::Hi: return (state > +16384) && !(lastState > +16384);
case InputObject::Trigger: return (state < 0) && !(lastState < 0);
}
} else {
return (state == 1) && !(lastState == 1);
}
return false; //fall-through for modifier-less hats / axes
}
void Utility::inputEvent(uint16_t code) {
//forward key-press event
//(in case window is currently active and capturing a new button / axis assignment)
winInputCapture->inputEvent(code);
//if escape key is pressed on *any* keyboard; release the mouse if it is acquired
for(unsigned i = 0; i < keyboard<>::count; i++) {
if(code == keyboard<>::index(i, keyboard<>::escape) && inputManager.state(code) && input.acquired()) {
input.unacquire();
return; //do not trigger other UI actions that may be bound to escape key
}
}
if(winMain->window->isActiveWindow()) {
bool resizeWindow = false;
if(isButtonDown(code, inputUiGeneral.loadCartridge)) {
string filename = selectCartridge();
if(filename.length() > 0) loadCartridge(filename);
}
if(isButtonDown(code, inputUiGeneral.pauseEmulation)) {
application.pause = !application.pause;
}
if(isButtonDown(code, inputUiGeneral.resetSystem)) {
modifySystemState(Reset);
}
if(isButtonDown(code, inputUiGeneral.powerCycleSystem)) {
modifySystemState(PowerCycle);
}
if(isButtonDown(code, inputUiGeneral.lowerSpeed)) {
config.system.speed--;
updateEmulationSpeed();
winMain->syncUi();
}
if(isButtonDown(code, inputUiGeneral.raiseSpeed)) {
config.system.speed++;
updateEmulationSpeed();
winMain->syncUi();
}
if(isButtonDown(code, inputUiGeneral.toggleCheatSystem)) {
if(cheat.enabled() == false) {
cheat.enable();
showMessage("Cheat system enabled.");
} else {
cheat.disable();
showMessage("Cheat system disabled.");
}
}
if(isButtonDown(code, inputUiGeneral.toggleFullscreen)) {
config.video.isFullscreen = !config.video.isFullscreen;
updateFullscreenState();
winMain->syncUi();
}
if(isButtonDown(code, inputUiGeneral.toggleMenu)) {
winMain->window->menuBar()->setVisible(!winMain->window->menuBar()->isVisibleTo(winMain->window));
resizeWindow = true;
}
if(isButtonDown(code, inputUiGeneral.toggleStatus)) {
winMain->window->statusBar()->setVisible(!winMain->window->statusBar()->isVisibleTo(winMain->window));
resizeWindow = true;
}
//prevent calling twice when toggleMenu == toggleStatus
if(resizeWindow == true) {
resizeMainWindow();
}
if(isButtonDown(code, inputUiGeneral.exitEmulator)) {
application.terminate = true;
}
}
}
//display message in main window statusbar area for three seconds
void Utility::showMessage(const char *message) {
winMain->window->statusBar()->showMessage(utf8() << message, 3000);
}
//updates system state text at bottom-right of main window statusbar
void Utility::updateSystemState() {
string text;
if(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;
text << " fps";
} else {
//nothing to update
return;
}
winMain->systemState->setText(utf8() << text);
}
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
) input.acquire();
}
}
void Utility::unacquireMouse() {
input.unacquire();
}
void Utility::updateAvSync() {
video.set(Video::Synchronize, config.video.synchronize);
audio.set(Audio::Synchronize, config.audio.synchronize);
}
void Utility::updateVideoMode() {
if(config.video.context->region == 0) {
snes.video.set_mode(SNES::Video::ModeNTSC);
} else {
snes.video.set_mode(SNES::Video::ModePAL);
}
}
void Utility::updateColorFilter() {
libfilter::colortable.set_format(libfilter::Colortable::RGB888);
libfilter::colortable.set_contrast(config.video.contrastAdjust);
libfilter::colortable.set_brightness(config.video.brightnessAdjust);
libfilter::colortable.set_gamma(100 + config.video.gammaAdjust);
libfilter::colortable.enable_gamma_ramp(config.video.enableGammaRamp);
libfilter::colortable.update();
}
void Utility::updateHardwareFilter() {
video.set(Video::Filter, config.video.context->hwFilter);
}
void Utility::updateSoftwareFilter() {
libfilter::FilterInterface::FilterType type;
switch(config.video.context->swFilter) { default:
case 0: type = libfilter::FilterInterface::Direct; break;
case 1: type = libfilter::FilterInterface::Scanline; break;
case 2: type = libfilter::FilterInterface::Scale2x; break;
case 3: type = libfilter::FilterInterface::HQ2x; break;
case 4: type = libfilter::FilterInterface::NTSC; break;
}
libfilter::filter.set(type);
if(type == libfilter::FilterInterface::NTSC) {
libfilter::filter_ntsc.adjust(0, 0, 0, 0, 0, config.video.enableNtscMergeFields);
}
}
void Utility::updateEmulationSpeed() {
config.system.speed = max(0, min(4, (signed)config.system.speed));
double scale[] = { 0.50, 0.75, 1.00, 1.50, 2.00 };
unsigned outfreq = config.audio.outputFrequency;
unsigned infreq = config.audio.inputFrequency * scale[config.system.speed] + 0.5;
audio.set(Audio::Resample, outfreq != infreq); //only resample when necessary
audio.set(Audio::ResampleOutputFrequency, outfreq);
audio.set(Audio::ResampleInputFrequency, infreq);
}
void Utility::updateControllers() {
snes.input.port_set_device(0, snes.config.controller_port1);
snes.input.port_set_device(1, snes.config.controller_port2);
}

View File

@@ -0,0 +1,37 @@
class Utility {
public:
//utility.cpp
bool isButtonDown(uint16_t inputCode, InputObject &object);
void inputEvent(uint16_t code);
void showMessage(const char *message);
void updateSystemState();
void acquireMouse();
void unacquireMouse();
void updateAvSync();
void updateVideoMode();
void updateColorFilter();
void updateHardwareFilter();
void updateSoftwareFilter();
void updateEmulationSpeed();
void updateControllers();
//cartridge.cpp
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*);
void unloadCartridge();
enum system_state_t { LoadCartridge, UnloadCartridge, PowerOn, PowerOff, PowerCycle, Reset };
void modifySystemState(system_state_t state);
//window.cpp
void showCentered(QWidget *window);
void updateFullscreenState();
void constrainSize(unsigned &x, unsigned &y, unsigned max);
void resizeMainWindow();
} utility;

View File

@@ -0,0 +1,123 @@
//show specified window in the center of the screen.
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());
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)
);
#ifndef _WIN32
//Xlib frame size (excluding inside) is QSize(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)
);
//ensure window has focus
application.processEvents();
window->activateWindow();
window->raise();
}
void Utility::updateFullscreenState() {
video.clear();
if(config.video.isFullscreen == false) {
config.video.context = &config.video.windowed;
winMain->window->showNormal();
} else {
config.video.context = &config.video.fullscreen;
winMain->window->showFullScreen();
}
//Xlib requires time to propogate fullscreen state change message to window manager;
//if window is resized before this occurs, canvas may not resize correctly
application.processEvents();
usleep(50000);
//refresh options that are unique to each video context
resizeMainWindow();
updateVideoMode();
updateHardwareFilter();
updateSoftwareFilter();
winMain->syncUi();
}
//if max exceeds x: x is set to max, and y is scaled down to keep proportion to x
void Utility::constrainSize(unsigned &x, unsigned &y, unsigned max) {
if(x > max) {
double scalar = (double)max / (double)x;
y = (unsigned)((double)y * (double)scalar);
x = max;
}
}
void Utility::resizeMainWindow() {
for(unsigned i = 0; i < 8; i++) {
unsigned multiplier = config.video.context->multiplier;
unsigned width = 256 * config.video.context->multiplier;
unsigned height = (config.video.context->region == 0 ? 224 : 239) * config.video.context->multiplier;
if(config.video.context->correctAspectRatio) {
if(config.video.context->region == 0) {
width = (double)width * config.video.ntscAspectRatio + 0.5; //NTSC adjust
} else {
width = (double)width * config.video.palAspectRatio + 0.5; //PAL adjust
}
}
if(config.video.isFullscreen == false) {
//get effective desktop work area region (ignore Windows taskbar, OS X doc, etc.)
QRect deskRect = QApplication::desktop()->availableGeometry(winMain->window);
//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();
//ensure window size will not be larger than viewable desktop area
constrainSize(height, width, deskRect.height() - frameHeight);
constrainSize(width, height, deskRect.width() - frameWidth );
//resize window such that it is as small as possible to hold canvas of size (width, height)
winMain->canvas->setFixedSize(width, height);
winMain->window->resize(width, height);
//center window onscreen
winMain->window->move(
deskRect.center().x() - (winMain->window->frameSize().width() / 2),
deskRect.center().y() - (winMain->window->frameSize().height() / 2)
);
} else {
constrainSize(height, width, winMain->canvasContainer->size().height());
constrainSize(width, height, winMain->canvasContainer->size().width());
//center canvas onscreen; ensure it is not larger than viewable area
winMain->canvas->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
winMain->canvas->setMaximumSize(width, height);
}
application.processEvents();
usleep(2000);
}
//work around for Qt/Xlib bug:
//if window resize occurs with cursor over it, Qt shows Qt::Size*DiagCursor;
//so force it to show Qt::ArrowCursor, as expected
winMain->window->setCursor(Qt::ArrowCursor);
winMain->canvasContainer->setCursor(Qt::ArrowCursor);
winMain->canvas->setCursor(Qt::ArrowCursor);
}