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