mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-10-04 23:51:47 +02:00
byuu says: higan changelog: - generates title displayed in emulator window by asking the core - core builds title solely from "information/title" ... if it's not there, you don't get a title at all - sub-system load menu is gone ... since there are multiple revisions of the SGB, this never really worked well anyway - to load an SGB, BS-X or ST cartridge, load the base cartridge first - "File->Load Game" moved to "Load->Import Game" ... may cause a bit of confusion to new users, but I don't like having a single-item menu, we'll just have to explain it to new users - browser window redone to look like ananke - home button here goes to ~/Emulation rather than just ~ like ananke, since this is the home of game folders - game folder icon is now the executable icon for the Tango theme (orange diamond), meant to represent a complete game rather than a game file or archive ananke changelog: - outputs GBC games to "Game Boy Color/" instead of "Game Boy/" - adds the file basename to "information/title" Known issues: - using ananke to load a GB game trips the Super Famicom SGB mode and fails (need to make the full-path auto-detection ignore non-bootable systems) - need to dump and test some BS-X media before releasing - ananke lacks BS-X Satellaview cartridge support - v092 isn't going to let you retarget the ananke/higan game folder path of ~/Emulation, you will have to wait for a future version if that bothers you so greatly [Later, after the v092 release, byuu posted this additional changelog: - kill laevateinn - add title() - add bootable, remove load - combine file, library - combine [][][] paths - fix SFC subtype handling XML->BML - update file browser to use buttons - update file browser keyboard handling - update system XML->BML - fix sufami turbo hashing - remove Cartridge::manifest ]
187 lines
4.8 KiB
C++
Executable File
187 lines
4.8 KiB
C++
Executable File
Browser *browser = nullptr;
|
|
|
|
Browser::Browser() {
|
|
bootstrap();
|
|
setGeometry({128, 128, 640, 400});
|
|
windowManager->append(this, "Browser");
|
|
|
|
layout.setMargin(5);
|
|
homeButton.setImage({resource::home, sizeof resource::home});
|
|
upButton.setImage({resource::up, sizeof resource::up});
|
|
openButton.setText("Open");
|
|
|
|
append(layout);
|
|
layout.append(pathLayout, {~0, 0}, 5);
|
|
pathLayout.append(pathEdit, {~0, 0}, 5);
|
|
pathLayout.append(homeButton, {28, 28}, 5);
|
|
pathLayout.append(upButton, {28, 28});
|
|
layout.append(fileList, {~0, ~0}, 5);
|
|
layout.append(controlLayout, {~0, 0});
|
|
controlLayout.append(filterLabel, {~0, 0}, 5);
|
|
controlLayout.append(openButton, {80, 0});
|
|
|
|
pathEdit.onActivate = [&] {
|
|
string path = pathEdit.text();
|
|
path.transform("\\", "/");
|
|
if(path.endswith("/") == false) path.append("/");
|
|
setPath(path);
|
|
};
|
|
|
|
homeButton.onActivate = [&] {
|
|
string pathname = {userpath(), "Emulation/"};
|
|
directory::create(pathname);
|
|
setPath(pathname);
|
|
};
|
|
|
|
upButton.onActivate = [&] {
|
|
setPath(parentdir(path));
|
|
};
|
|
|
|
fileList.onChange = {&Browser::synchronize, this};
|
|
fileList.onActivate = openButton.onActivate = {&Browser::fileListActivate, this};
|
|
onClose = [&] { dialogActive = false; };
|
|
|
|
synchronize();
|
|
}
|
|
|
|
void Browser::synchronize() {
|
|
openButton.setEnabled(fileList.selected());
|
|
if(fileList.selected()) {
|
|
for(auto &folder : folderList) {
|
|
if(folder.extension == extension) {
|
|
folder.selection = fileList.selection();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void Browser::saveConfiguration() {
|
|
config.save(application->path("paths.cfg"));
|
|
}
|
|
|
|
void Browser::bootstrap() {
|
|
for(auto &emulator : application->emulator) {
|
|
for(auto &media : emulator->media) {
|
|
bool found = false;
|
|
for(auto &folder : folderList) {
|
|
if(folder.extension == media.type) {
|
|
found = true;
|
|
break;
|
|
}
|
|
}
|
|
if(found == true) continue;
|
|
|
|
Folder folder;
|
|
folder.extension = media.type;
|
|
folder.path = application->basepath;
|
|
folder.selection = 0;
|
|
folderList.append(folder);
|
|
}
|
|
}
|
|
|
|
for(auto &folder : folderList) {
|
|
config.append(folder.path, folder.extension);
|
|
config.append(folder.selection, string{folder.extension, "::selection"});
|
|
}
|
|
|
|
config.load(application->path("paths.cfg"));
|
|
config.save(application->path("paths.cfg"));
|
|
}
|
|
|
|
string Browser::select(const string &title, const string &extension) {
|
|
this->extension = extension;
|
|
|
|
string path;
|
|
unsigned selection = 0;
|
|
for(auto &folder : folderList) {
|
|
if(folder.extension == extension) {
|
|
path = folder.path;
|
|
selection = folder.selection;
|
|
break;
|
|
}
|
|
}
|
|
if(path.empty()) path = application->basepath;
|
|
setPath(path, selection);
|
|
|
|
filterLabel.setText({"Filter: *.", extension});
|
|
|
|
audio.clear();
|
|
setTitle(title);
|
|
setModal(true);
|
|
setVisible(true);
|
|
fileList.setFocused();
|
|
outputFilename = "";
|
|
|
|
dialogActive = true;
|
|
bool backspace = false;
|
|
using phoenix::Keyboard;
|
|
|
|
while(dialogActive) {
|
|
OS::processEvents();
|
|
if(Keyboard::pressed(Keyboard::Scancode::Escape)) onClose();
|
|
if(Keyboard::pressed(Keyboard::Scancode::Backspace)) {
|
|
if(backspace == false) {
|
|
backspace = true;
|
|
if(fileList.focused()) upButton.onActivate();
|
|
}
|
|
} else {
|
|
backspace = false;
|
|
}
|
|
usleep(20 * 1000);
|
|
}
|
|
|
|
setModal(false);
|
|
setVisible(false);
|
|
return outputFilename;
|
|
}
|
|
|
|
void Browser::setPath(const string &path, unsigned selection) {
|
|
//save path for next browser selection
|
|
for(auto &folder : folderList) {
|
|
if(folder.extension == extension) folder.path = path;
|
|
}
|
|
|
|
this->path = path;
|
|
pathEdit.setText(path);
|
|
|
|
fileList.reset();
|
|
filenameList.reset();
|
|
|
|
lstring contents = directory::contents(path);
|
|
|
|
for(auto &filename : contents) {
|
|
string suffix = {".", this->extension, "/"};
|
|
if(filename.endswith("/") && !filename.endswith(suffix)) {
|
|
string name = filename;
|
|
name.rtrim<1>("/");
|
|
fileList.append(name);
|
|
fileList.setImage(filenameList.size(), 0, {resource::folder, sizeof resource::folder});
|
|
filenameList.append(filename);
|
|
}
|
|
}
|
|
|
|
for(auto &filename : contents) {
|
|
string suffix = {".", this->extension, "/"};
|
|
if(filename.endswith(suffix)) {
|
|
string name = filename;
|
|
name.rtrim<1>(suffix);
|
|
fileList.append(name);
|
|
fileList.setImage(filenameList.size(), 0, {resource::game, sizeof resource::game});
|
|
filenameList.append(filename);
|
|
}
|
|
}
|
|
|
|
fileList.setSelection(selection);
|
|
fileList.setFocused();
|
|
synchronize();
|
|
}
|
|
|
|
void Browser::fileListActivate() {
|
|
unsigned selection = fileList.selection();
|
|
string filename = filenameList[selection];
|
|
if(string{filename}.rtrim<1>("/").endswith(this->extension) == false) return setPath({path, filename});
|
|
|
|
dialogActive = false;
|
|
outputFilename = {path, filename};
|
|
}
|