rust as intended
This commit is contained in:
parent
3359073498
commit
450335c79a
1
.gitignore
vendored
1
.gitignore
vendored
@ -18,3 +18,4 @@
|
||||
*properties.json
|
||||
/.vs
|
||||
/.vscode
|
||||
*/.idea/
|
||||
|
12
Makefile
12
Makefile
@ -26,9 +26,17 @@ RUST_DEPS := $(wildcard $(RUST_DIR)/src/*) $(wildcard $(RUST_DIR)/Cargo.*)
|
||||
RUST_BIN_DEPS := $(RUST_DEPS) $(RUST_DIR)/mips-nintendo64-none.json
|
||||
RUST_H_DEPS := $(RUST_DEPS) $(RUST_DIR)/cbindgen.toml
|
||||
|
||||
LINK_FLAGS = -O1 -L$(ROOTDIR)/lib -L$(ROOTDIR)/mips64-elf/lib -ldragon -lmad -lyaml -lc -lm -ldragonsys -lnosys -L$(RUST_FULL_TARGET_DIR) -laltra64 $(LIBS) -Tn64ld.x
|
||||
PROG_NAME = $(BINDIR)/OS64P
|
||||
CFLAGS = -std=gnu99 -march=vr4300 -mtune=vr4300 -O1 -I$(INCDIR) -I$(ROOTDIR)/include -I$(ROOTDIR)/mips64-elf/include -I$(RUST_FULL_TARGET_DIR) -lpthread -lrt -D_REENTRANT -DUSE_TRUETYPE $(SET_DEBUG)
|
||||
|
||||
ifdef USE_YAML
|
||||
CFLAGS += -DUSE_YAML
|
||||
LIBS += -lyaml
|
||||
else
|
||||
LIBS += -laltra64
|
||||
endif
|
||||
|
||||
LINK_FLAGS = -O1 -L$(ROOTDIR)/lib -L$(ROOTDIR)/mips64-elf/lib -L$(RUST_FULL_TARGET_DIR) -ldragon -lmad $(LIBS) -lc -lm -ldragonsys -lnosys -Tn64ld.x
|
||||
PROG_NAME = $(BINDIR)/OS64P
|
||||
ASFLAGS = -mtune=vr4300 -march=vr4300
|
||||
CC = $(GCCN64PREFIX)gcc
|
||||
AS = $(GCCN64PREFIX)as
|
||||
|
@ -2,6 +2,13 @@
|
||||
name = "altra64"
|
||||
version = "0.1.0"
|
||||
authors = ["moparisthebest <admin@moparisthebest.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
#libc = {version = "0.2", default-features = false}
|
||||
#no-std-compat = { version = "0.4.1", features = [ "alloc" ] }
|
||||
#libdragon-bindings = { git = "https://github.com/DagothBob/libdragon-bindings" }
|
||||
#cstr_core = {version = "0.2", default-features = false}
|
||||
|
||||
# the profile used for `cargo build`
|
||||
[profile.dev]
|
||||
|
@ -15,3 +15,5 @@ include_guard = "ALTRA64_H"
|
||||
autogen_warning = "/* Warning, this file is autogenerated by cbindgen. Don't modify this manually. */"
|
||||
include_version = false
|
||||
|
||||
[export]
|
||||
exclude = ["strtoul"]
|
||||
|
343
rust/src/lib.rs
343
rust/src/lib.rs
@ -1,5 +1,241 @@
|
||||
#![no_std]
|
||||
|
||||
use core::slice;
|
||||
use core::iter::Iterator;
|
||||
|
||||
const WHITESPACE: &[u8] = b" \t\n\r";
|
||||
|
||||
pub trait SliceSubsequence<T> {
|
||||
fn trim_start(&self, needle: &[T]) -> &[T];
|
||||
fn trim_end(&self, needle: &[T]) -> &[T];
|
||||
fn first_index_of(&self, needle: &[T]) -> Option<usize>;
|
||||
//fn extract_between(&self, before: &[T], after: &[T]) -> Option<&[T]>;
|
||||
fn lines<'a>(&'a self, needle: &'a [T]) -> LineIterator<'a, T>;
|
||||
|
||||
fn trim(&self, needle: &[T]) -> &[T];
|
||||
|
||||
fn contains_seq(&self, needle: &[T]) -> bool {
|
||||
self.first_index_of(needle).is_some()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct LineIterator<'a, T> {
|
||||
inner: &'a [T],
|
||||
needle: &'a [T],
|
||||
pos: usize,
|
||||
}
|
||||
|
||||
impl<'a, T: PartialEq> Iterator for LineIterator<'a, T> {
|
||||
type Item = &'a [T];
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.pos == self.inner.len() {
|
||||
return None;
|
||||
}
|
||||
let search = &self.inner[self.pos..];
|
||||
match search.first_index_of(self.needle) {
|
||||
None => {
|
||||
let pos = self.pos;
|
||||
self.pos = self.inner.len();
|
||||
Some(&self.inner[pos..])
|
||||
}
|
||||
Some(idx) => {
|
||||
self.pos += idx + self.needle.len();
|
||||
Some(&search[..idx])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn last_index_of<T: PartialEq>(s: &[T], needle: &[T]) -> usize {
|
||||
let mut len = 0;
|
||||
for i in s {
|
||||
if needle.contains(i) {
|
||||
len += 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
len
|
||||
}
|
||||
|
||||
fn last_index_of_rev<T: PartialEq>(s: &[T], needle: &[T]) -> usize {
|
||||
let mut len = s.len();
|
||||
for i in s.iter().rev() {
|
||||
if needle.contains(i) {
|
||||
len -= 1;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
len
|
||||
}
|
||||
|
||||
impl<T: PartialEq> SliceSubsequence<T> for &[T] {
|
||||
fn trim_start(&self, needle: &[T]) -> &[T] {
|
||||
&self[last_index_of(self, needle)..]
|
||||
}
|
||||
|
||||
fn trim_end(&self, needle: &[T]) -> &[T] {
|
||||
&self[..last_index_of_rev(self, needle)]
|
||||
}
|
||||
|
||||
fn first_index_of(&self, needle: &[T]) -> Option<usize> {
|
||||
if self.len() >= needle.len() {
|
||||
for i in 0..self.len() - needle.len() + 1 {
|
||||
if self[i..i + needle.len()] == needle[..] {
|
||||
return Some(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn lines<'a>(&'a self, needle: &'a [T]) -> LineIterator<'a, T> {
|
||||
LineIterator {
|
||||
inner: self,
|
||||
needle,
|
||||
pos: 0,
|
||||
}
|
||||
}
|
||||
|
||||
fn trim(&self, needle: &[T]) -> &[T] {
|
||||
let start = last_index_of(self, needle);
|
||||
let end = last_index_of_rev(self, needle);
|
||||
if start >= end {
|
||||
// empty
|
||||
&self[0..0]
|
||||
} else {
|
||||
&self[start..end]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn parse_cheats_ffi(
|
||||
cheat_file: *mut u8, cheat_file_len: usize,
|
||||
boot_cheats: *mut u32, boot_cheats_len: usize,
|
||||
in_game_cheats: *mut u32, in_game_cheats_len: usize,
|
||||
) -> u8 {
|
||||
let cheat_file = unsafe { slice::from_raw_parts(cheat_file, cheat_file_len) };
|
||||
let boot_cheats = unsafe { slice::from_raw_parts_mut(boot_cheats, boot_cheats_len) };
|
||||
let in_game_cheats = unsafe { slice::from_raw_parts_mut(in_game_cheats, in_game_cheats_len) };
|
||||
|
||||
parse_cheats(cheat_file, boot_cheats, in_game_cheats)
|
||||
}
|
||||
|
||||
const SUCCESS: u8 = 0;
|
||||
const INVALID_CODE_LINE: u8 = 1;
|
||||
const INVALID_LINE: u8 = 2;
|
||||
|
||||
pub fn parse_cheats(cheat_file: &[u8], boot_cheats: &mut [u32], in_game_cheats: &mut [u32]) -> u8 {
|
||||
let mut repeater = false;
|
||||
let mut boot_cheats_idx = 0;
|
||||
let mut in_game_cheats_idx = 0;
|
||||
for line in cheat_file.lines(b"\n") {
|
||||
let line = line.trim(WHITESPACE);
|
||||
if line.is_empty() || line.starts_with(b"#") || line == b"---" {
|
||||
continue; // empty or comment or whatever the starting thing is
|
||||
} else if line.ends_with(b":") {
|
||||
repeater = false;
|
||||
} else if line.starts_with(b"- ") {
|
||||
// we found the start of a code
|
||||
let line = line.trim_start(b"- ");
|
||||
let line = line.trim(WHITESPACE);
|
||||
let mut line = line.lines(b" ");
|
||||
match (line.next(), line.next(), line.next()) {
|
||||
(Some(address), Some(value), None) => {
|
||||
// proper line
|
||||
let address = hex_to_u32(address.trim(WHITESPACE));
|
||||
let value = hex_to_u32(value.trim(WHITESPACE));
|
||||
//println!("address: {:X}, value: {:X}", address, value);
|
||||
//println!("dec address: {}, value: {}", address, value);
|
||||
|
||||
// Do not check code types within "repeater data"
|
||||
if repeater {
|
||||
repeater = false;
|
||||
in_game_cheats[in_game_cheats_idx] = address;
|
||||
in_game_cheats_idx += 1;
|
||||
in_game_cheats[in_game_cheats_idx] = value;
|
||||
in_game_cheats_idx += 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
//println!("address >> 24: {:X}", address >> 24);
|
||||
// Determine destination cheat_list for the code type
|
||||
match address >> 24
|
||||
{
|
||||
// Uncessary code types
|
||||
0x20 | // Clear code list
|
||||
0xCC | // Exception Handler Selection
|
||||
0xDE => // Entry Point
|
||||
continue,
|
||||
|
||||
// Boot-time cheats
|
||||
0xEE | // Disable Expansion Pak
|
||||
0xF0 | // 8-bit Boot-Time Write
|
||||
0xF1 | // 16-bit Boot-Time Write
|
||||
0xFF => { // Cheat Engine Location
|
||||
boot_cheats[boot_cheats_idx] = address;
|
||||
boot_cheats_idx += 1;
|
||||
boot_cheats[boot_cheats_idx] = value;
|
||||
boot_cheats_idx += 1;
|
||||
}
|
||||
|
||||
// In-game cheats
|
||||
0x50 => { // Repeater/Patch
|
||||
// Validate repeater count
|
||||
if (address & 0x0000FF00) == 0 {
|
||||
repeater = true;
|
||||
in_game_cheats[in_game_cheats_idx] = address;
|
||||
in_game_cheats_idx += 1;
|
||||
in_game_cheats[in_game_cheats_idx] = value;
|
||||
in_game_cheats_idx += 1;
|
||||
}
|
||||
}
|
||||
// todo: was fallthrough from default in C, does that even work?
|
||||
0xD0 | // 8-bit Equal-To Conditional
|
||||
0xD1 | // 16-bit Equal-To Conditional
|
||||
0xD2 | // 8-bit Not-Equal-To Conditional
|
||||
0xD3 => { // 16-bit Not-Equal-To Conditional
|
||||
// Validate 16-bit codes
|
||||
if (address & 0x01000001) == 0x01000001 {
|
||||
continue; // todo: or error
|
||||
}
|
||||
|
||||
in_game_cheats[in_game_cheats_idx] = address;
|
||||
in_game_cheats_idx += 1;
|
||||
in_game_cheats[in_game_cheats_idx] = value;
|
||||
in_game_cheats_idx += 1;
|
||||
}
|
||||
// Everything else
|
||||
_ => {
|
||||
if address != 0
|
||||
{
|
||||
// TODO: Support special code types! :)
|
||||
}
|
||||
// Validate 16-bit codes
|
||||
if (address & 0x01000001) == 0x01000001 {
|
||||
continue; // todo: or error
|
||||
}
|
||||
|
||||
in_game_cheats[in_game_cheats_idx] = address;
|
||||
in_game_cheats_idx += 1;
|
||||
in_game_cheats[in_game_cheats_idx] = value;
|
||||
in_game_cheats_idx += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => return INVALID_CODE_LINE,
|
||||
}
|
||||
} else {
|
||||
//println!("bad line: '{}'", String::from_utf8_lossy(line));
|
||||
return INVALID_LINE;
|
||||
}
|
||||
}
|
||||
SUCCESS
|
||||
}
|
||||
|
||||
/// This function is called on panic.
|
||||
#[cfg(not(test))]
|
||||
#[panic_handler]
|
||||
@ -7,14 +243,13 @@ fn panic(_info: &core::panic::PanicInfo) -> ! {
|
||||
loop {}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn get_rust_u8() -> u8 {
|
||||
//9
|
||||
unsafe { get_c_u8() }
|
||||
fn hex_to_u32(str: &[u8]) -> u32 {
|
||||
use core::ptr::null_mut;
|
||||
unsafe { strtoul(str.as_ptr(), null_mut(), 16) }
|
||||
}
|
||||
|
||||
extern "C" {
|
||||
fn get_c_u8() -> u8;
|
||||
fn strtoul(s: *const u8, endp: *mut *mut u8, base: i32) -> u32; // todo: is base i32 ?
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@ -22,7 +257,101 @@ mod tests {
|
||||
use crate::*;
|
||||
|
||||
#[test]
|
||||
fn it_works() {
|
||||
assert_eq!(get_rust_u8(), 9);
|
||||
fn test_hex_to_u32() {
|
||||
assert_eq!(hex_to_u32(b"0x09"), 9);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_trim_start() {
|
||||
let buf = &b" bla"[..];
|
||||
let buf = buf.trim_start(WHITESPACE);
|
||||
assert_eq!(buf, b"bla");
|
||||
|
||||
let buf = &b"\n\t\r \rbla"[..];
|
||||
let buf = buf.trim_start(WHITESPACE);
|
||||
assert_eq!(buf, b"bla");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_trim_end() {
|
||||
let buf = &b"bla "[..];
|
||||
let buf = buf.trim_end(WHITESPACE);
|
||||
assert_eq!(buf, b"bla");
|
||||
|
||||
let buf = &b"bla\n\t\r \r"[..];
|
||||
let buf = buf.trim_end(WHITESPACE);
|
||||
assert_eq!(buf, b"bla");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_trim() {
|
||||
let buf = &b" bla "[..];
|
||||
let buf = buf.trim(WHITESPACE);
|
||||
assert_eq!(buf, b"bla");
|
||||
|
||||
let buf = &b"\n\t\r \rbla\n\t\r \r"[..];
|
||||
let buf = buf.trim(WHITESPACE);
|
||||
assert_eq!(buf, b"bla");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_lines() {
|
||||
let lines = &b"\
|
||||
line1
|
||||
line2\r
|
||||
line3
|
||||
"[..];
|
||||
let mut lines = lines.lines(b"\n");
|
||||
assert_eq!(lines.next(), Some(&b"line1"[..]));
|
||||
assert_eq!(lines.next(), Some(&b"line2\r"[..]));
|
||||
assert_eq!(lines.next(), Some(&b"line3"[..]));
|
||||
assert_eq!(lines.next(), None);
|
||||
assert_eq!(lines.next(), None);
|
||||
|
||||
let lines = &b"F10004E4 2400"[..];
|
||||
let mut lines = lines.lines(b" ");
|
||||
assert_eq!(lines.next(), Some(&b"F10004E4"[..]));
|
||||
assert_eq!(lines.next(), Some(&b"2400"[..]));
|
||||
assert_eq!(lines.next(), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_cheats() {
|
||||
let cheats_file = &b"\
|
||||
---
|
||||
|
||||
A:
|
||||
- F10004E4 2400
|
||||
- EE000000 0000
|
||||
|
||||
B:
|
||||
- 8138EDA0 2400
|
||||
|
||||
"[..];
|
||||
let mut boot_cheats = [0u32; 6];
|
||||
let mut in_game_cheats = [0u32; 6];
|
||||
let ok = parse_cheats(cheats_file, &mut boot_cheats, &mut in_game_cheats);
|
||||
assert_eq!(ok, SUCCESS);
|
||||
assert_eq!(boot_cheats, [0xF10004E4, 0x2400, 0xEE000000, 0x0000, 0, 0]);
|
||||
assert_eq!(in_game_cheats, [0x8138EDA0, 0x2400, 0, 0, 0, 0]);
|
||||
|
||||
|
||||
let cheats_file = &b"\
|
||||
---
|
||||
# Legend of Zelda, The - Ocarina of Time (USA) (Rev 2)
|
||||
|
||||
Master Code:
|
||||
- F10004E4 2400
|
||||
- EE000000 0000
|
||||
|
||||
In Health (ASM):
|
||||
- 8138EDA0 2400
|
||||
"[..];
|
||||
let mut boot_cheats = [0u32; 6];
|
||||
let mut in_game_cheats = [0u32; 6];
|
||||
let ok = parse_cheats(cheats_file, &mut boot_cheats, &mut in_game_cheats);
|
||||
assert_eq!(ok, SUCCESS);
|
||||
assert_eq!(boot_cheats, [0xF10004E4, 0x2400, 0xEE000000, 0x0000, 0, 0]);
|
||||
assert_eq!(in_game_cheats, [0x8138EDA0, 0x2400, 0, 0, 0, 0]);
|
||||
}
|
||||
}
|
||||
|
160
src/main.c
160
src/main.c
@ -37,10 +37,13 @@
|
||||
#include "sound.h"
|
||||
#include "mp3.h"
|
||||
|
||||
#ifdef USE_YAML
|
||||
// YAML parser
|
||||
#include <yaml.h>
|
||||
|
||||
#else
|
||||
#include <altra64.h>
|
||||
#endif /* USE_YAML */
|
||||
|
||||
|
||||
#include "constants.h"
|
||||
#include "debug.h"
|
||||
@ -2028,77 +2031,26 @@ void readSDcard(display_context_t disp, char *directory)
|
||||
display_dir(list, cursor, page, MAX_LIST, count, disp);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns two cheat lists:
|
||||
* - One for the "at boot" cheats
|
||||
* - Another for the "in-game" cheats
|
||||
*/
|
||||
int readCheatFile(TCHAR *filename, u32 *cheat_lists[2])
|
||||
{
|
||||
#ifdef USE_YAML
|
||||
int parse_cheats_yaml(char *cheatfile, u32 *list1, u32 *list2) {
|
||||
|
||||
// YAML parser
|
||||
yaml_parser_t parser;
|
||||
yaml_event_t event;
|
||||
|
||||
|
||||
// State for YAML parser
|
||||
int is_code = 0;
|
||||
int code_on = 1;
|
||||
int done = 0;
|
||||
u32 *list1;
|
||||
u32 *list2;
|
||||
char *next;
|
||||
|
||||
int repeater = 0;
|
||||
u32 address;
|
||||
u32 value;
|
||||
|
||||
yaml_parser_initialize(&parser);
|
||||
|
||||
|
||||
FRESULT result;
|
||||
FIL file;
|
||||
UINT bytesread;
|
||||
result = f_open(&file, filename, FA_READ);
|
||||
|
||||
if (result == FR_OK)
|
||||
{
|
||||
int fsize = f_size(&file);
|
||||
|
||||
char *cheatfile = malloc(fsize);
|
||||
if (!cheatfile)
|
||||
{
|
||||
return -2; // Out of memory
|
||||
}
|
||||
|
||||
/*
|
||||
* Size of the cheat list can never be more than half the size of the YAML
|
||||
* Minimum YAML example:
|
||||
* A:-80001234 FFFF
|
||||
* Which is exactly 16 bytes.
|
||||
* The cheat list in this case fits into exactly 8 bytes (2 words):
|
||||
* 0x80001234, 0x0000FFFF
|
||||
*/
|
||||
list1 = calloc(1, fsize + 2 * sizeof(u32)); // Plus 2 words to be safe
|
||||
if (!list1)
|
||||
{
|
||||
// Free
|
||||
free(cheatfile);
|
||||
return -2; // Out of memory
|
||||
}
|
||||
list2 = &list1[fsize / sizeof(u32) / 2];
|
||||
cheat_lists[0] = list1;
|
||||
cheat_lists[1] = list2;
|
||||
|
||||
result =
|
||||
f_read (
|
||||
&file, /* [IN] File object */
|
||||
cheatfile, /* [OUT] Buffer to store read data */
|
||||
fsize, /* [IN] Number of bytes to read */
|
||||
&bytesread /* [OUT] Number of bytes read */
|
||||
);
|
||||
|
||||
f_close(&file);
|
||||
|
||||
yaml_parser_set_input_string(&parser, cheatfile, strlen(cheatfile));
|
||||
char *next;
|
||||
|
||||
int repeater = 0;
|
||||
|
||||
yaml_parser_initialize(&parser);
|
||||
yaml_parser_set_input_string(&parser, cheatfile, strlen(cheatfile));
|
||||
|
||||
do
|
||||
{
|
||||
@ -2106,12 +2058,7 @@ int readCheatFile(TCHAR *filename, u32 *cheat_lists[2])
|
||||
{
|
||||
// Free
|
||||
yaml_parser_delete(&parser);
|
||||
yaml_event_delete(&event);
|
||||
free(cheatfile);
|
||||
free(cheat_lists[0]);
|
||||
cheat_lists[0] = 0;
|
||||
cheat_lists[1] = 0;
|
||||
|
||||
yaml_event_delete(&event);
|
||||
return -3; // Parse error
|
||||
}
|
||||
|
||||
@ -2223,7 +2170,84 @@ int readCheatFile(TCHAR *filename, u32 *cheat_lists[2])
|
||||
|
||||
// Free
|
||||
yaml_parser_delete(&parser);
|
||||
|
||||
return repeater;
|
||||
}
|
||||
#endif /* USE_YAML */
|
||||
|
||||
/*
|
||||
* Returns two cheat lists:
|
||||
* - One for the "at boot" cheats
|
||||
* - Another for the "in-game" cheats
|
||||
*/
|
||||
int readCheatFile(TCHAR *filename, u32 *cheat_lists[2])
|
||||
{
|
||||
u32 *list1;
|
||||
u32 *list2;
|
||||
|
||||
int repeater = 0;
|
||||
|
||||
FRESULT result;
|
||||
FIL file;
|
||||
UINT bytesread;
|
||||
result = f_open(&file, filename, FA_READ);
|
||||
|
||||
if (result == FR_OK)
|
||||
{
|
||||
int fsize = f_size(&file);
|
||||
|
||||
char *cheatfile = malloc(fsize);
|
||||
if (!cheatfile)
|
||||
{
|
||||
return -2; // Out of memory
|
||||
}
|
||||
|
||||
/*
|
||||
* Size of the cheat list can never be more than half the size of the YAML
|
||||
* Minimum YAML example:
|
||||
* A:-80001234 FFFF
|
||||
* Which is exactly 16 bytes.
|
||||
* The cheat list in this case fits into exactly 8 bytes (2 words):
|
||||
* 0x80001234, 0x0000FFFF
|
||||
*/
|
||||
size_t both_list_sizes = fsize + 2 * sizeof(u32);
|
||||
list1 = calloc(1, both_list_sizes); // Plus 2 words to be safe
|
||||
if (!list1)
|
||||
{
|
||||
// Free
|
||||
free(cheatfile);
|
||||
return -2; // Out of memory
|
||||
}
|
||||
size_t list2_size = fsize / sizeof(u32) / 2;
|
||||
list2 = &list1[list2_size];
|
||||
cheat_lists[0] = list1;
|
||||
cheat_lists[1] = list2;
|
||||
|
||||
result =
|
||||
f_read (
|
||||
&file, /* [IN] File object */
|
||||
cheatfile, /* [OUT] Buffer to store read data */
|
||||
fsize, /* [IN] Number of bytes to read */
|
||||
&bytesread /* [OUT] Number of bytes read */
|
||||
);
|
||||
|
||||
f_close(&file);
|
||||
|
||||
#ifdef USE_YAML
|
||||
repeater = parse_cheats_yaml(cheatfile, list1, list2);
|
||||
#else
|
||||
// use rust
|
||||
size_t list1_size = both_list_sizes - list2_size;
|
||||
repeater = parse_cheats_ffi(cheatfile, fsize, list1, list1_size, list2, list2_size);
|
||||
#endif /* USE_YAML */
|
||||
|
||||
free(cheatfile);
|
||||
if (repeater != 0) {
|
||||
// this is what original yaml code did
|
||||
free(cheat_lists[0]);
|
||||
cheat_lists[0] = 0;
|
||||
cheat_lists[1] = 0;
|
||||
}
|
||||
|
||||
return repeater; // Ok or repeater error
|
||||
|
||||
|
@ -2,8 +2,6 @@
|
||||
#include <libdragon.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <altra64.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "menu.h"
|
||||
#include "version.h"
|
||||
@ -16,7 +14,7 @@ void menu_about(display_context_t disp)
|
||||
char version_str[32];
|
||||
char firmware_str[32];
|
||||
|
||||
sprintf(version_str, "Altra64 %d: v%s", get_rust_u8(), Altra64_GetVersionString());
|
||||
sprintf(version_str, "Altra64: v%s", Altra64_GetVersionString());
|
||||
printText(version_str, 9, 8, disp);
|
||||
sprintf(firmware_str, "ED64 firmware: v%03x", evd_getFirmVersion());
|
||||
printText(firmware_str, 9, -1, disp);
|
||||
|
Loading…
Reference in New Issue
Block a user