Update Write routines for ROM, expand ROM to 2mb

This commit is contained in:
scawful
2024-01-29 00:27:51 -05:00
parent c8a7f1c074
commit db9f78648e
4 changed files with 78 additions and 52 deletions

View File

@@ -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

View File

@@ -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;

View File

@@ -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

View 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);
}