Skip to content

Commit 8fcb989

Browse files
committed
memoryCard: options window, ability to remove card from slot
1 parent 1a4bc86 commit 8fcb989

7 files changed

Lines changed: 109 additions & 16 deletions

File tree

src/config.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ const json defaultConfig = {
176176
}},
177177
{"memoryCard", {
178178
{"1", "data/memory/card1.mcr"},
179-
{"2", nullptr}
179+
{"2", ""}
180180
}}
181181
};
182182
// clang-format on

src/device/controller/peripherals/memory_card.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ MemoryCard::MemoryCard(int port) : AbstractDevice(Type::MemoryCard, port) { verb
77

88
uint8_t MemoryCard::handle(uint8_t byte) {
99
if (state == 0) command = Command::None;
10+
11+
if (!inserted) {
12+
return 0xff;
13+
}
14+
1015
if (verbose >= 3) printf("[MEMCARD] state %d\n", state);
1116
if (command == Command::Read) return handleRead(byte);
1217
if (command == Command::Write) return handleWrite(byte);

src/device/controller/peripherals/memory_card.h

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
namespace peripherals {
66
struct MemoryCard : public AbstractDevice {
7+
private:
78
enum class Command { Read, Write, ID, None };
89
enum class WriteStatus : uint8_t { Good = 'G', BadChecksum = 'N', BadSector = 0xff };
910
union Flag {
@@ -19,23 +20,23 @@ struct MemoryCard : public AbstractDevice {
1920
Flag() : error(0), fresh(1), unknown(1) {}
2021
};
2122

22-
int verbose = 0;
23+
uint8_t handleRead(uint8_t byte);
24+
uint8_t handleWrite(uint8_t byte);
25+
uint8_t handleId(uint8_t byte);
2326

27+
int verbose;
2428
Command command = Command::None;
25-
2629
Flag flag;
2730
Reg16 address; // Read/Write address (in 128B blocks)
2831
uint8_t checksum = 0;
2932
WriteStatus writeStatus = WriteStatus::Good;
3033

31-
bool dirty = false;
32-
34+
public:
3335
std::array<uint8_t, 128 * 1024> data;
36+
bool inserted = true;
37+
bool dirty = false;
3438

3539
MemoryCard(int port);
3640
uint8_t handle(uint8_t byte) override;
37-
uint8_t handleRead(uint8_t byte);
38-
uint8_t handleWrite(uint8_t byte);
39-
uint8_t handleId(uint8_t byte);
4041
};
4142
} // namespace peripherals

src/platform/windows/gui/gui.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "debug/timers/timers.h"
1010
#include "imgui/imgui_impl_sdl_gl3.h"
1111
#include "options.h"
12+
#include "options/memory_card/memory_card.h"
1213
#include "platform/windows/input/key.h"
1314
#include "version.h"
1415

@@ -43,6 +44,8 @@ gui::debug::cdrom::Cdrom cdromDebug;
4344
gui::debug::cpu::CPU cpuDebug;
4445
gui::debug::timers::Timers timersDebug;
4546

47+
gui::options::memory_card::MemoryCard memoryCardOptions;
48+
4649
void aboutWindow() {
4750
ImGui::Begin("About", &showAboutWindow);
4851
ImGui::Text("Avocado %s", BUILD_STRING);
@@ -136,6 +139,7 @@ void renderImgui(System* sys) {
136139
if (ImGui::MenuItem("Graphics", nullptr)) showGraphicsOptionsWindow = true;
137140
if (ImGui::MenuItem("BIOS", nullptr)) showBiosWindow = true;
138141
if (ImGui::MenuItem("Controller", nullptr)) showControllerSetupWindow = true;
142+
ImGui::MenuItem("Memory Card", nullptr, &memoryCardOptions.memoryCardWindowOpen);
139143
ImGui::EndMenu();
140144
}
141145
if (ImGui::BeginMenu("Help")) {
@@ -169,6 +173,8 @@ void renderImgui(System* sys) {
169173
if (showBiosWindow) biosSelectionWindow();
170174
if (showControllerSetupWindow) controllerSetupWindow();
171175

176+
memoryCardOptions.displayWindows(sys);
177+
172178
// Help
173179
if (showAboutWindow) aboutWindow();
174180
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
#include "memory_card.h"
2+
#include <imgui.h>
3+
#include <misc/cpp/imgui_stdlib.h>
4+
#include "config.h"
5+
#include "system.h"
6+
#include "utils/string.h"
7+
8+
namespace gui::options::memory_card {
9+
void MemoryCard::memoryCardWindow(System* sys) {
10+
if (loadPaths) {
11+
for (size_t i = 0; i < cardPaths.size(); i++) {
12+
cardPaths[i] = config["memoryCard"][std::to_string(i + 1)];
13+
}
14+
loadPaths = false;
15+
}
16+
ImGui::Begin("MemoryCard", &memoryCardWindowOpen, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse);
17+
ImGui::BeginTabBar("##memory_select");
18+
19+
for (size_t i = 0; i < sys->controller->card.size(); i++) {
20+
if (ImGui::BeginTabItem(string_format("Slot %d", i + 1).c_str())) {
21+
if (ImGui::InputText("Path", &cardPaths[i])) {
22+
config["memoryCard"][std::to_string(i + 1)] = cardPaths[i];
23+
}
24+
// TODO: Reload contents on change?
25+
// TODO: Check if card exists, override or reload?
26+
27+
bool inserted = sys->controller->card[0]->inserted;
28+
if (ImGui::Checkbox("Inserted", &inserted)) {
29+
sys->controller->card[0]->inserted = inserted;
30+
}
31+
32+
ImGui::EndTabItem();
33+
}
34+
}
35+
36+
ImGui::EndTabBar();
37+
ImGui::End();
38+
}
39+
40+
void MemoryCard::displayWindows(System* sys) {
41+
if (memoryCardWindowOpen) memoryCardWindow(sys);
42+
}
43+
} // namespace gui::options::memory_card
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
#pragma once
2+
#include <array>
3+
#include <string>
4+
5+
struct System;
6+
7+
namespace gui::options::memory_card {
8+
class MemoryCard {
9+
bool loadPaths = true;
10+
std::array<std::string, 2> cardPaths;
11+
void memoryCardWindow(System* sys);
12+
13+
public:
14+
bool memoryCardWindowOpen = false;
15+
void displayWindows(System* sys);
16+
};
17+
} // namespace gui::options::memory_card

src/platform/windows/main.cpp

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -149,14 +149,28 @@ std::unique_ptr<System> hardReset() {
149149
printf("Using iso %s\n", iso.c_str());
150150
}
151151

152-
std::string pathCard1 = config["memoryCard"]["1"];
153-
if (!pathCard1.empty()) {
154-
auto card1 = getFileContents(pathCard1);
155-
if (!card1.empty()) {
156-
std::copy_n(std::make_move_iterator(card1.begin()), card1.size(), sys->controller->card[0]->data.begin());
157-
printf("[INFO] Loaded memory card 1 from %s\n", getFilenameExt(pathCard1).c_str());
152+
auto loadMemoryCard = [&](int slot) {
153+
assert(slot == 0 || slot == 1);
154+
auto card = sys->controller->card[slot].get();
155+
156+
auto configEntry = config["memoryCard"][std::to_string(slot + 1)];
157+
std::string pathCard = configEntry.is_null() ? "" : configEntry;
158+
159+
card->inserted = false;
160+
161+
if (!pathCard.empty()) {
162+
auto cardData = getFileContents(pathCard);
163+
if (!cardData.empty()) {
164+
std::copy_n(std::make_move_iterator(cardData.begin()), cardData.size(), sys->controller->card[slot]->data.begin());
165+
card->inserted = true;
166+
printf("[INFO] Loaded memory card %d from %s\n", slot, getFilenameExt(pathCard).c_str());
167+
}
158168
}
159-
}
169+
};
170+
171+
loadMemoryCard(0);
172+
loadMemoryCard(1);
173+
160174
return sys;
161175
}
162176

@@ -362,13 +376,16 @@ int main(int argc, char** argv) {
362376
bool frameLimitEnabled = true;
363377
bool windowFocused = true;
364378

379+
bool forceRedraw = false;
380+
365381
SDL_Event event;
366382
while (running && !exitProgram) {
367383
bool newEvent = false;
368-
if (sys->state != System::State::run) {
384+
if (!forceRedraw && sys->state != System::State::run) {
369385
SDL_WaitEvent(&event);
370386
newEvent = true;
371387
}
388+
forceRedraw = false;
372389

373390
auto lockMouse = sys->state == System::State::run && inputManager->mouseLocked;
374391
SDL_SetRelativeMouseMode((SDL_bool)lockMouse);
@@ -427,6 +444,10 @@ int main(int argc, char** argv) {
427444
opengl.width = event.window.data1;
428445
opengl.height = event.window.data2;
429446
}
447+
448+
// Crude hack to force next frame after last event received (in paused mode)
449+
// Fixes ImGui window drawing
450+
forceRedraw = true;
430451
}
431452

432453
if (doHardReset) {

0 commit comments

Comments
 (0)