1 #include "shared_state.h"
2
3 #include "fs/load.h"
4
load_rom(const char * rompath)5 int SharedState::load_rom(const char* rompath) {
6 // cleanup previous cart
7 for (uint i = 0; i < 4; i++) {
8 delete this->savestate[i];
9 this->savestate[i] = nullptr;
10 }
11
12 fprintf(stderr, "[Load] Loading '%s'\n", rompath);
13 Cartridge* cart = new Cartridge (ANESE_fs::load::load_rom_file(rompath));
14
15 switch (cart->status()) {
16 case Cartridge::Status::CART_BAD_DATA:
17 fprintf(stderr, "[Cart] ROM file could not be parsed!\n");
18 delete cart;
19 return 1;
20 case Cartridge::Status::CART_BAD_MAPPER:
21 fprintf(stderr, "[Cart] Mapper %u has not been implemented yet!\n",
22 cart->get_rom_file()->meta.mapper);
23 delete cart;
24 return 1;
25 case Cartridge::Status::CART_NO_ERROR:
26 fprintf(stderr, "[Cart] ROM file loaded successfully!\n");
27 this->current_rom_file = rompath;
28 this->cart = cart;
29 break;
30 }
31
32 // Try to load battery-backed save
33 if (!this->config.cli.no_sav) {
34 u8* data = nullptr;
35 uint len = 0;
36 ANESE_fs::load::load_file((this->current_rom_file + ".sav").c_str(), data, len);
37
38 if (!data) fprintf(stderr, "[Savegame][Load] No save data found.\n");
39 else {
40 fprintf(stderr, "[Savegame][Load] Found save data.\n");
41 const Serializable::Chunk* sav = Serializable::Chunk::parse(data, len);
42 this->cart->get_mapper()->setBatterySave(sav);
43 }
44
45 delete data;
46 }
47
48 // Try to load savestate
49 // kinda jank lol
50 if (!this->config.cli.no_sav) {
51 u8* data = nullptr;
52 uint len = 0;
53 ANESE_fs::load::load_file((this->current_rom_file + ".state").c_str(), data, len);
54
55 u8* og_data = data;
56
57 if (!data) fprintf(stderr, "[Savegame][Load] No savestate data found.\n");
58 else {
59 fprintf(stderr, "[Savegame][Load] Found savestate data.\n");
60 for (const Serializable::Chunk*& savestate : this->savestate) {
61 uint sav_len = ((uint*)data)[0];
62 data += sizeof(uint);
63 if (!sav_len) savestate = nullptr;
64 else {
65 savestate = Serializable::Chunk::parse(data, sav_len);
66 data += sav_len;
67 }
68 }
69 }
70
71 delete og_data;
72 }
73
74 // Slap a cartridge in!
75 this->nes.loadCartridge(this->cart->get_mapper());
76
77 // Power-cycle the NES
78 this->nes.power_cycle();
79
80 return 0;
81 }
82
unload_rom()83 int SharedState::unload_rom() {
84 if (!this->cart) return 0;
85 fprintf(stderr, "[UnLoad] Unloading cart...\n");
86
87 // Save Battey-Backed RAM
88 if (this->cart != nullptr && !this->config.cli.no_sav) {
89 const Serializable::Chunk* sav = this->cart->get_mapper()->getBatterySave();
90 if (sav) {
91 const u8* data;
92 uint len;
93 Serializable::Chunk::collate(data, len, sav);
94
95 FILE* sav_file = fopen((this->current_rom_file + ".sav").c_str(), "wb");
96 if (!sav_file) {
97 fprintf(stderr, "[Savegame][Save] Failed to open save file!\n");
98 return 1;
99 }
100
101 fwrite(data, 1, len, sav_file);
102 fclose(sav_file);
103 fprintf(stderr, "[Savegame][Save] Game saved to '%s.sav'!\n",
104 this->current_rom_file.c_str());
105
106 delete sav;
107 }
108 }
109
110 // Save Savestates
111 if (this->cart != nullptr && !this->config.cli.no_sav) {
112 FILE* state_file = fopen((this->current_rom_file + ".state").c_str(), "wb");
113 if (!state_file) {
114 fprintf(stderr, "[Savegame][Save] Failed to open savestate file!\n");
115 return 1;
116 }
117
118 // kinda jank lol
119 for (const Serializable::Chunk* savestate : this->savestate) {
120 const u8* data;
121 uint len;
122 Serializable::Chunk::collate(data, len, savestate);
123
124 fwrite(&len, sizeof(uint), 1, state_file);
125 if (data) fwrite(data, 1, len, state_file);
126 }
127
128 fclose(state_file);
129 fprintf(stderr, "[Savegame][Save] Savestates saved to '%s.state'!\n",
130 this->current_rom_file.c_str());
131 }
132
133 this->nes.removeCartridge();
134
135 delete this->cart;
136
137 return 0;
138 }
139