chore: special case saving for ROMS without titles
This commit is contained in:
parent
74335cacbf
commit
36f3b0d381
|
@ -2,8 +2,8 @@ const std = @import("std");
|
||||||
const Allocator = std.mem.Allocator;
|
const Allocator = std.mem.Allocator;
|
||||||
const log = std.log.scoped(.Backup);
|
const log = std.log.scoped(.Backup);
|
||||||
|
|
||||||
const correctTitle = @import("../util.zig").correctTitle;
|
const escape = @import("../util.zig").escape;
|
||||||
const safeTitle = @import("../util.zig").safeTitle;
|
const asString = @import("../util.zig").asString;
|
||||||
const intToBytes = @import("../util.zig").intToBytes;
|
const intToBytes = @import("../util.zig").intToBytes;
|
||||||
|
|
||||||
const backup_kinds = [5]Needle{
|
const backup_kinds = [5]Needle{
|
||||||
|
@ -76,6 +76,11 @@ pub const Backup = struct {
|
||||||
const file_path = try self.getSaveFilePath(path);
|
const file_path = try self.getSaveFilePath(path);
|
||||||
defer self.alloc.free(file_path);
|
defer self.alloc.free(file_path);
|
||||||
|
|
||||||
|
// FIXME: Don't rely on this lol
|
||||||
|
if (std.mem.eql(u8, file_path[file_path.len - 12 .. file_path.len], "untitled.sav")) {
|
||||||
|
return log.err("ROM header lacks title, no save loaded", .{});
|
||||||
|
}
|
||||||
|
|
||||||
const file: std.fs.File = try std.fs.openFileAbsolute(file_path, .{});
|
const file: std.fs.File = try std.fs.openFileAbsolute(file_path, .{});
|
||||||
const file_buf = try file.readToEndAlloc(self.alloc, try file.getEndPos());
|
const file_buf = try file.readToEndAlloc(self.alloc, try file.getEndPos());
|
||||||
defer self.alloc.free(file_buf);
|
defer self.alloc.free(file_buf);
|
||||||
|
@ -98,7 +103,10 @@ pub const Backup = struct {
|
||||||
return log.info("Loaded Save from {s}", .{file_path});
|
return log.info("Loaded Save from {s}", .{file_path});
|
||||||
}
|
}
|
||||||
|
|
||||||
log.err("EEPROM can either be 0x200 bytes or 0x2000 byes, but {s} was {X:} bytes", .{ file_path, file_buf.len, });
|
log.err("EEPROM can either be 0x200 bytes or 0x2000 byes, but {s} was {X:} bytes", .{
|
||||||
|
file_path,
|
||||||
|
file_buf.len,
|
||||||
|
});
|
||||||
},
|
},
|
||||||
.None => return SaveError.UnsupportedBackupKind,
|
.None => return SaveError.UnsupportedBackupKind,
|
||||||
}
|
}
|
||||||
|
@ -112,8 +120,10 @@ pub const Backup = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn getSaveFilename(self: *const Self) ![]const u8 {
|
fn getSaveFilename(self: *const Self) ![]const u8 {
|
||||||
const title = correctTitle(safeTitle(self.title));
|
const title = asString(escape(self.title));
|
||||||
return try std.mem.concat(self.alloc, u8, &[_][]const u8{ title, ".sav" });
|
const name = if (title.len != 0) title else "untitled";
|
||||||
|
|
||||||
|
return try std.mem.concat(self.alloc, u8, &[_][]const u8{ name, ".sav" });
|
||||||
}
|
}
|
||||||
|
|
||||||
fn writeSaveToDisk(self: Self, path: []const u8) !void {
|
fn writeSaveToDisk(self: Self, path: []const u8) !void {
|
||||||
|
@ -411,7 +421,7 @@ const Eeprom = struct {
|
||||||
const addr = @intCast(u10, self.writer.finish());
|
const addr = @intCast(u10, self.writer.finish());
|
||||||
|
|
||||||
// TODO: Bit Verbose eh?
|
// TODO: Bit Verbose eh?
|
||||||
const value_buf = buf[@as(u13, addr) * 8..][0..8];
|
const value_buf = buf[@as(u13, addr) * 8 ..][0..8];
|
||||||
const value = @as(u64, value_buf[7]) << 56 | @as(u64, value_buf[6]) << 48 | @as(u64, value_buf[5]) << 40 | @as(u64, value_buf[4]) << 32 | @as(u64, value_buf[3]) << 24 | @as(u64, value_buf[2]) << 16 | @as(u64, value_buf[1]) << 8 | @as(u64, value_buf[0]) << 0;
|
const value = @as(u64, value_buf[7]) << 56 | @as(u64, value_buf[6]) << 48 | @as(u64, value_buf[5]) << 40 | @as(u64, value_buf[4]) << 32 | @as(u64, value_buf[3]) << 24 | @as(u64, value_buf[2]) << 16 | @as(u64, value_buf[1]) << 8 | @as(u64, value_buf[0]) << 0;
|
||||||
|
|
||||||
self.reader.configure(value);
|
self.reader.configure(value);
|
||||||
|
@ -423,7 +433,7 @@ const Eeprom = struct {
|
||||||
const addr = @intCast(u6, self.writer.finish());
|
const addr = @intCast(u6, self.writer.finish());
|
||||||
|
|
||||||
// TODO: Bit Verbose eh?, also duplicate code
|
// TODO: Bit Verbose eh?, also duplicate code
|
||||||
const value_buf = buf[@as(u13, addr) * 8..][0..8];
|
const value_buf = buf[@as(u13, addr) * 8 ..][0..8];
|
||||||
const value = @as(u64, value_buf[7]) << 56 | @as(u64, value_buf[6]) << 48 | @as(u64, value_buf[5]) << 40 | @as(u64, value_buf[4]) << 32 | @as(u64, value_buf[3]) << 24 | @as(u64, value_buf[2]) << 16 | @as(u64, value_buf[1]) << 8 | @as(u64, value_buf[0]) << 0;
|
const value = @as(u64, value_buf[7]) << 56 | @as(u64, value_buf[6]) << 48 | @as(u64, value_buf[5]) << 40 | @as(u64, value_buf[4]) << 32 | @as(u64, value_buf[3]) << 24 | @as(u64, value_buf[2]) << 16 | @as(u64, value_buf[1]) << 8 | @as(u64, value_buf[0]) << 0;
|
||||||
|
|
||||||
self.reader.configure(value);
|
self.reader.configure(value);
|
||||||
|
@ -452,7 +462,7 @@ const Eeprom = struct {
|
||||||
},
|
},
|
||||||
.WriteTransfer => {
|
.WriteTransfer => {
|
||||||
if (self.writer.len() == 64) {
|
if (self.writer.len() == 64) {
|
||||||
std.mem.copy(u8, buf[self.addr * 8..][0..8], &intToBytes(u64, self.writer.finish()));
|
std.mem.copy(u8, buf[self.addr * 8 ..][0..8], &intToBytes(u64, self.writer.finish()));
|
||||||
self.state = .RequestEnd;
|
self.state = .RequestEnd;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -29,7 +29,7 @@ const is_binary: bool = false;
|
||||||
const log = std.log.scoped(.GUI);
|
const log = std.log.scoped(.GUI);
|
||||||
pub const log_level = if (builtin.mode != .Debug) .info else std.log.default_level;
|
pub const log_level = if (builtin.mode != .Debug) .info else std.log.default_level;
|
||||||
|
|
||||||
const correctTitle = @import("util.zig").correctTitle;
|
const asString = @import("util.zig").asString;
|
||||||
|
|
||||||
pub fn main() anyerror!void {
|
pub fn main() anyerror!void {
|
||||||
// Allocator for Emulator + CLI
|
// Allocator for Emulator + CLI
|
||||||
|
@ -106,7 +106,7 @@ pub fn main() anyerror!void {
|
||||||
defer emu_thread.join();
|
defer emu_thread.join();
|
||||||
|
|
||||||
var title_buf: [0x20]u8 = std.mem.zeroes([0x20]u8);
|
var title_buf: [0x20]u8 = std.mem.zeroes([0x20]u8);
|
||||||
const window_title = try std.fmt.bufPrint(&title_buf, "ZBA | {s}", .{correctTitle(cpu.bus.pak.title)});
|
const window_title = try std.fmt.bufPrint(&title_buf, "ZBA | {s}", .{asString(cpu.bus.pak.title)});
|
||||||
|
|
||||||
const window = createWindow(window_title, gba_width, gba_height);
|
const window = createWindow(window_title, gba_width, gba_height);
|
||||||
defer SDL.SDL_DestroyWindow(window);
|
defer SDL.SDL_DestroyWindow(window);
|
||||||
|
|
|
@ -60,7 +60,7 @@ pub fn intToBytes(comptime T: type, value: anytype) [@sizeOf(T)]u8 {
|
||||||
///
|
///
|
||||||
/// This function returns a slice of everything just before the first
|
/// This function returns a slice of everything just before the first
|
||||||
/// `\0`
|
/// `\0`
|
||||||
pub fn correctTitle(title: [12]u8) []const u8 {
|
pub fn asString(title: [12]u8) []const u8 {
|
||||||
var len = title.len;
|
var len = title.len;
|
||||||
for (title) |char, i| {
|
for (title) |char, i| {
|
||||||
if (char == 0) {
|
if (char == 0) {
|
||||||
|
@ -76,7 +76,7 @@ pub fn correctTitle(title: [12]u8) []const u8 {
|
||||||
/// array consisting of ASCII that won't make any file system angry
|
/// array consisting of ASCII that won't make any file system angry
|
||||||
///
|
///
|
||||||
/// e.g. POKEPIN R/S to POKEPIN R_S
|
/// e.g. POKEPIN R/S to POKEPIN R_S
|
||||||
pub fn safeTitle(title: [12]u8) [12]u8 {
|
pub fn escape(title: [12]u8) [12]u8 {
|
||||||
var result: [12]u8 = title;
|
var result: [12]u8 = title;
|
||||||
|
|
||||||
for (result) |*char| {
|
for (result) |*char| {
|
||||||
|
|
Loading…
Reference in New Issue