Update Write routines for ROM, expand ROM to 2mb
This commit is contained in:
@@ -350,6 +350,7 @@ void MasterEditor::DrawFileMenu() {
|
||||
|
||||
if (BeginMenu("Options")) {
|
||||
MenuItem("Backup ROM", "", &backup_rom_);
|
||||
MenuItem("Save New Auto", "", &save_new_auto_);
|
||||
ImGui::Separator();
|
||||
if (BeginMenu("Experiment Flags")) {
|
||||
if (BeginMenu("Overworld Flags")) {
|
||||
@@ -387,6 +388,8 @@ void MasterEditor::DrawFileMenu() {
|
||||
Checkbox("Save With Change Queue",
|
||||
&mutable_flags()->kSaveWithChangeQueue);
|
||||
Checkbox("Use New ImGui Input", &mutable_flags()->kUseNewImGuiInput);
|
||||
Checkbox("Use Classic Compression",
|
||||
&mutable_flags()->kUseClassicCompression);
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
@@ -568,11 +571,11 @@ void MasterEditor::SaveRom() {
|
||||
RETURN_VOID_IF_ERROR(status_);
|
||||
}
|
||||
if (flags()->overworld.kSaveOverworldMaps) {
|
||||
if (overworld_editor_.overworld()->CreateTile32Tilemap()) {
|
||||
status_ = overworld_editor_.overworld()->SaveMap16Tiles();
|
||||
RETURN_VOID_IF_ERROR(status_);
|
||||
if (!overworld_editor_.overworld()->CreateTile32Tilemap()) {
|
||||
status_ = overworld_editor_.overworld()->SaveMap32Tiles();
|
||||
RETURN_VOID_IF_ERROR(status_);
|
||||
status_ = overworld_editor_.overworld()->SaveMap16Tiles();
|
||||
RETURN_VOID_IF_ERROR(status_);
|
||||
status_ = overworld_editor_.overworld()->SaveOverworldMaps();
|
||||
RETURN_VOID_IF_ERROR(status_);
|
||||
} else {
|
||||
@@ -598,7 +601,7 @@ void MasterEditor::SaveRom() {
|
||||
RETURN_VOID_IF_ERROR(status_);
|
||||
}
|
||||
|
||||
status_ = rom()->SaveToFile(backup_rom_);
|
||||
status_ = rom()->SaveToFile(backup_rom_, save_new_auto_);
|
||||
}
|
||||
|
||||
} // namespace editor
|
||||
|
||||
@@ -61,7 +61,8 @@ class MasterEditor : public SharedROM,
|
||||
|
||||
bool about_ = false;
|
||||
bool rom_info_ = false;
|
||||
bool backup_rom_ = true;
|
||||
bool backup_rom_ = false;
|
||||
bool save_new_auto_ = true;
|
||||
bool show_status_ = false;
|
||||
bool rom_assets_loaded_ = false;
|
||||
|
||||
|
||||
@@ -347,6 +347,10 @@ absl::Status ROM::LoadFromFile(const absl::string_view& filename,
|
||||
LoadGfxGroups();
|
||||
}
|
||||
|
||||
// Expand the ROM data to 2MB without changing the data in the first 1MB
|
||||
rom_data_.resize(baseROMSize * 2);
|
||||
size_ = baseROMSize * 2;
|
||||
|
||||
// Set up the resource labels
|
||||
std::string resource_label_filename = absl::StrFormat("%s.labels", filename);
|
||||
resource_label_manager_.LoadLabels(resource_label_filename);
|
||||
@@ -377,7 +381,7 @@ absl::Status ROM::LoadFromBytes(const Bytes& data) {
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status ROM::SaveToFile(bool backup, absl::string_view filename) {
|
||||
absl::Status ROM::SaveToFile(bool backup, bool save_new, std::string filename) {
|
||||
absl::Status non_firing_status;
|
||||
if (rom_data_.empty()) {
|
||||
return absl::InternalError("ROM data is empty.");
|
||||
@@ -427,11 +431,34 @@ absl::Status ROM::SaveToFile(bool backup, absl::string_view filename) {
|
||||
}
|
||||
}
|
||||
|
||||
if (save_new) {
|
||||
// Create a file of the same name and append the date between the filename
|
||||
// and file extension
|
||||
auto now = std::chrono::system_clock::now();
|
||||
auto now_c = std::chrono::system_clock::to_time_t(now);
|
||||
auto filename_no_ext = filename.substr(0, filename.find_last_of("."));
|
||||
std::cout << filename_no_ext << std::endl;
|
||||
filename = absl::StrCat(filename_no_ext, "_", std::ctime(&now_c));
|
||||
// Remove spaces from new_filename and replace with _
|
||||
filename.erase(std::remove(filename.begin(), filename.end(), ' '),
|
||||
filename.end());
|
||||
// Remove newline character from ctime()
|
||||
filename.erase(std::remove(filename.begin(), filename.end(), '\n'),
|
||||
filename.end());
|
||||
// Add the file extension back to the new_filename
|
||||
filename = filename + ".sfc";
|
||||
std::cout << filename << std::endl;
|
||||
}
|
||||
|
||||
// Open the file that we know exists for writing
|
||||
std::ofstream file(filename.data(), std::ios::binary);
|
||||
std::ofstream file(filename.data(), std::ios::binary | std::ios::app);
|
||||
if (!file) {
|
||||
return absl::InternalError(
|
||||
absl::StrCat("Could not open ROM file: ", filename));
|
||||
// Create the file if it does not exist
|
||||
file.open(filename.data(), std::ios::binary);
|
||||
if (!file) {
|
||||
return absl::InternalError(
|
||||
absl::StrCat("Could not open or create ROM file: ", filename));
|
||||
}
|
||||
}
|
||||
|
||||
// Save the data to the file
|
||||
|
||||
@@ -133,8 +133,8 @@ constexpr uint32_t gfx_groups_pointer = 0x6237;
|
||||
|
||||
struct WriteAction {
|
||||
int address;
|
||||
std::variant<int, uint8_t, uint16_t, std::vector<uint8_t>, gfx::SNESColor,
|
||||
std::vector<gfx::SNESColor>>
|
||||
std::variant<int, uint8_t, uint16_t, short, std::vector<uint8_t>,
|
||||
gfx::SNESColor, std::vector<gfx::SNESColor>>
|
||||
value;
|
||||
};
|
||||
|
||||
@@ -148,24 +148,11 @@ class ROM : public core::ExperimentFlags {
|
||||
return status;
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
absl::Status RunTransactionV2(int address, T& var, Args&&... args) {
|
||||
absl::Status status = WriteHelperV2<T>(var, address);
|
||||
if (!status.ok()) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if constexpr (sizeof...(args) > 0) {
|
||||
status = WriteHelperV2(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
absl::Status WriteHelper(const WriteAction& action) {
|
||||
if (std::holds_alternative<uint8_t>(action.value)) {
|
||||
return Write(action.address, std::get<uint8_t>(action.value));
|
||||
} else if (std::holds_alternative<uint16_t>(action.value)) {
|
||||
} else if (std::holds_alternative<uint16_t>(action.value) ||
|
||||
std::holds_alternative<short>(action.value)) {
|
||||
return WriteShort(action.address, std::get<uint16_t>(action.value));
|
||||
} else if (std::holds_alternative<std::vector<uint8_t>>(action.value)) {
|
||||
return WriteVector(action.address,
|
||||
@@ -179,25 +166,7 @@ class ROM : public core::ExperimentFlags {
|
||||
}
|
||||
auto error_message = absl::StrFormat("Invalid write argument type: %s",
|
||||
typeid(action.value).name());
|
||||
return absl::InvalidArgumentError(error_message);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
absl::Status WriteHelperV2(int address, T& var) {
|
||||
if constexpr (std::is_same_v<T, uint8_t>) {
|
||||
return Write(address, var);
|
||||
} else if constexpr (std::is_same_v<T, uint16_t>) {
|
||||
return WriteShort(address, var);
|
||||
} else if constexpr (std::is_same_v<T, std::vector<uint8_t>>) {
|
||||
return WriteVector(address, var);
|
||||
} else if constexpr (std::is_same_v<T, gfx::SNESColor>) {
|
||||
return WriteColor(address, var);
|
||||
} else if constexpr (std::is_same_v<T, std::vector<gfx::SNESColor>>) {
|
||||
return absl::UnimplementedError(
|
||||
"WriteHelperV2: std::vector<gfx::SNESColor>");
|
||||
}
|
||||
auto error_message =
|
||||
absl::StrFormat("Invalid write argument type: %s", typeid(T).name());
|
||||
throw std::runtime_error(error_message);
|
||||
return absl::InvalidArgumentError(error_message);
|
||||
}
|
||||
|
||||
@@ -291,7 +260,8 @@ class ROM : public core::ExperimentFlags {
|
||||
* @return absl::Status Returns an OK status if the save was successful,
|
||||
* otherwise returns an error status
|
||||
*/
|
||||
absl::Status SaveToFile(bool backup, absl::string_view filename = "");
|
||||
absl::Status SaveToFile(bool backup, bool save_new = false,
|
||||
std::string filename = "");
|
||||
|
||||
/**
|
||||
* Saves the given palette to the ROM if any of its colors have been modified.
|
||||
@@ -403,7 +373,9 @@ class ROM : public core::ExperimentFlags {
|
||||
// Write functions
|
||||
absl::Status Write(int addr, int value) {
|
||||
if (addr >= rom_data_.size()) {
|
||||
return absl::InvalidArgumentError("Address out of range");
|
||||
return absl::InvalidArgumentError(absl::StrFormat(
|
||||
"Attempt to write %d value failed, address %d out of range", value,
|
||||
addr));
|
||||
}
|
||||
rom_data_[addr] = value;
|
||||
return absl::OkStatus();
|
||||
@@ -411,47 +383,68 @@ class ROM : public core::ExperimentFlags {
|
||||
|
||||
absl::Status WriteByte(int addr, uint8_t value) {
|
||||
if (addr >= rom_data_.size()) {
|
||||
return absl::InvalidArgumentError("Address out of range");
|
||||
return absl::InvalidArgumentError(absl::StrFormat(
|
||||
"Attempt to write byte %#02x value failed, address %d out of range",
|
||||
value, addr));
|
||||
}
|
||||
rom_data_[addr] = value;
|
||||
std::string log_str = absl::StrFormat("WriteByte: %#06X: %s", addr,
|
||||
core::UppercaseHexByte(value).data());
|
||||
core::Logger::log(log_str);
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status WriteWord(int addr, uint16_t value) {
|
||||
if (addr + 1 >= rom_data_.size()) {
|
||||
return absl::InvalidArgumentError("Address out of range");
|
||||
return absl::InvalidArgumentError(absl::StrFormat(
|
||||
"Attempt to write word %#04x value failed, address %d out of range",
|
||||
value, addr));
|
||||
}
|
||||
rom_data_[addr] = (uint8_t)(value & 0xFF);
|
||||
rom_data_[addr + 1] = (uint8_t)((value >> 8) & 0xFF);
|
||||
core::Logger::log(absl::StrFormat("WriteWord: %#06X: %s", addr,
|
||||
core::UppercaseHexWord(value)));
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status WriteShort(uint32_t addr, uint16_t value) {
|
||||
if (addr + 1 >= rom_data_.size()) {
|
||||
return absl::InvalidArgumentError("Address out of range");
|
||||
return absl::InvalidArgumentError(absl::StrFormat(
|
||||
"Attempt to write short %#04x value failed, address %d out of range",
|
||||
value, addr));
|
||||
}
|
||||
rom_data_[addr] = (uint8_t)(value & 0xFF);
|
||||
rom_data_[addr + 1] = (uint8_t)((value >> 8) & 0xFF);
|
||||
core::Logger::log(absl::StrFormat("WriteShort: %#06X: %s", addr,
|
||||
core::UppercaseHexWord(value)));
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status WriteLong(uint32_t addr, uint32_t value) {
|
||||
if (addr + 2 >= rom_data_.size()) {
|
||||
return absl::InvalidArgumentError("Address out of range");
|
||||
return absl::InvalidArgumentError(absl::StrFormat(
|
||||
"Attempt to write long %#06x value failed, address %d out of range",
|
||||
value, addr));
|
||||
}
|
||||
rom_data_[addr] = (uint8_t)(value & 0xFF);
|
||||
rom_data_[addr + 1] = (uint8_t)((value >> 8) & 0xFF);
|
||||
rom_data_[addr + 2] = (uint8_t)((value >> 16) & 0xFF);
|
||||
core::Logger::log(absl::StrFormat("WriteLong: %#06X: %s", addr,
|
||||
core::UppercaseHexLong(value)));
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
absl::Status WriteVector(int addr, std::vector<uint8_t> data) {
|
||||
if (addr + data.size() > rom_data_.size()) {
|
||||
return absl::InvalidArgumentError("Address and data size out of range");
|
||||
return absl::InvalidArgumentError(absl::StrFormat(
|
||||
"Attempt to write vector value failed, address %d out of range",
|
||||
addr));
|
||||
}
|
||||
for (int i = 0; i < data.size(); i++) {
|
||||
rom_data_[addr + i] = data[i];
|
||||
}
|
||||
core::Logger::log(absl::StrFormat("WriteVector: %#06X: %s", addr,
|
||||
core::UppercaseHexByte(data[0])));
|
||||
return absl::OkStatus();
|
||||
}
|
||||
|
||||
@@ -461,6 +454,8 @@ class ROM : public core::ExperimentFlags {
|
||||
(color.GetSNES() & 0x7C00);
|
||||
|
||||
// Write the 16-bit color value to the ROM at the specified address
|
||||
core::Logger::log(absl::StrFormat("WriteColor: %#06X: %s", address,
|
||||
core::UppercaseHexWord(bgr)));
|
||||
return WriteShort(address, bgr);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user