mirror of
https://github.com/italicsjenga/agb.git
synced 2024-12-24 00:31:34 +11:00
Merge pull request #86 from agbrs/mgba-test-runner-cycles
Mgba test runner cycles
This commit is contained in:
commit
b0afeade99
7
.github/workflows/rust.yml
vendored
7
.github/workflows/rust.yml
vendored
|
@ -28,7 +28,7 @@ jobs:
|
||||||
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
key: ${{ runner.os }}-cargo-${{ hashFiles('**/Cargo.lock') }}
|
||||||
|
|
||||||
- name: install mgba-test-runner
|
- name: install mgba-test-runner
|
||||||
run: cargo install --path mgba-test-runner
|
run: cargo install --path mgba-test-runner --verbose
|
||||||
- name: Build agb library
|
- name: Build agb library
|
||||||
working-directory: agb
|
working-directory: agb
|
||||||
run: cargo build --verbose
|
run: cargo build --verbose
|
||||||
|
@ -38,7 +38,10 @@ jobs:
|
||||||
- name: Run Clippy on agb image converter
|
- name: Run Clippy on agb image converter
|
||||||
working-directory: agb-image-converter
|
working-directory: agb-image-converter
|
||||||
run: cargo clippy --verbose
|
run: cargo clippy --verbose
|
||||||
- name: Run Tests for agb
|
- name: Run Tests for agb in debug mode
|
||||||
working-directory: agb
|
working-directory: agb
|
||||||
run: cargo test --verbose
|
run: cargo test --verbose
|
||||||
|
- name: Run Tests for agb in release mode
|
||||||
|
working-directory: agb
|
||||||
|
run: cargo test --verbose --release
|
||||||
|
|
|
@ -7,11 +7,10 @@ description = "Library for Game Boy Advance Development"
|
||||||
license = "MPL-2.0"
|
license = "MPL-2.0"
|
||||||
|
|
||||||
[profile.dev]
|
[profile.dev]
|
||||||
opt-level = 0
|
opt-level = 3
|
||||||
debug = true
|
debug = true
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
panic = "abort"
|
|
||||||
lto = true
|
lto = true
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -89,7 +89,9 @@ where
|
||||||
mgba::DebugLevel::Info,
|
mgba::DebugLevel::Info,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
mgba::number_of_cycles_tagged(785);
|
||||||
self(gba);
|
self(gba);
|
||||||
|
mgba::number_of_cycles_tagged(785);
|
||||||
mgba.print(format_args!("[ok]"), mgba::DebugLevel::Info)
|
mgba.print(format_args!("[ok]"), mgba::DebugLevel::Info)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
@ -138,6 +140,8 @@ pub extern "C" fn main() -> ! {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
fn assert_image_output(image: &str) {
|
fn assert_image_output(image: &str) {
|
||||||
|
display::busy_wait_for_VBlank();
|
||||||
|
display::busy_wait_for_VBlank();
|
||||||
let mut mgba = crate::mgba::Mgba::new().unwrap();
|
let mut mgba = crate::mgba::Mgba::new().unwrap();
|
||||||
mgba.print(
|
mgba.print(
|
||||||
format_args!("image:{}", image),
|
format_args!("image:{}", image),
|
||||||
|
|
|
@ -26,6 +26,12 @@ fn is_running_in_mgba() -> bool {
|
||||||
DEBUG_ENABLE.get() == ENABLE_HANDSHAKE_OUT
|
DEBUG_ENABLE.get() == ENABLE_HANDSHAKE_OUT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const NUMBER_OF_CYCLES: MemoryMapped<u16> = unsafe { MemoryMapped::new(0x04FF_F800) };
|
||||||
|
|
||||||
|
pub fn number_of_cycles_tagged(tag: u16) {
|
||||||
|
NUMBER_OF_CYCLES.set(tag)
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Mgba {
|
pub struct Mgba {
|
||||||
bytes_written: usize,
|
bytes_written: usize,
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,9 @@ edition = "2018"
|
||||||
|
|
||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
debug = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
regex = "1"
|
regex = "1"
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
|
|
40
mgba-test-runner/add_cycles_register.patch
Normal file
40
mgba-test-runner/add_cycles_register.patch
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
diff --git a/include/mgba/internal/gba/io.h b/include/mgba/internal/gba/io.h
|
||||||
|
index 9875061f3..bdeafdcd3 100644
|
||||||
|
--- a/include/mgba/internal/gba/io.h
|
||||||
|
+++ b/include/mgba/internal/gba/io.h
|
||||||
|
@@ -157,6 +157,7 @@ enum GBAIORegisters {
|
||||||
|
REG_DEBUG_STRING = 0xFFF600,
|
||||||
|
REG_DEBUG_FLAGS = 0xFFF700,
|
||||||
|
REG_DEBUG_ENABLE = 0xFFF780,
|
||||||
|
+ REG_DEBUG_CYCLES = 0xFFF800,
|
||||||
|
};
|
||||||
|
|
||||||
|
mLOG_DECLARE_CATEGORY(GBA_IO);
|
||||||
|
diff --git a/src/gba/io.c b/src/gba/io.c
|
||||||
|
index cc39e1192..d34dcb4b4 100644
|
||||||
|
--- a/src/gba/io.c
|
||||||
|
+++ b/src/gba/io.c
|
||||||
|
@@ -573,6 +573,11 @@ void GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value) {
|
||||||
|
case REG_DEBUG_ENABLE:
|
||||||
|
gba->debug = value == 0xC0DE;
|
||||||
|
return;
|
||||||
|
+ case REG_DEBUG_CYCLES: {
|
||||||
|
+ int32_t number_of_cycles = mTimingCurrentTime(&gba->timing);
|
||||||
|
+ mLOG(GBA_DEBUG, INFO, "Cycles: %d Tag: %d", number_of_cycles, value);
|
||||||
|
+ return;
|
||||||
|
+ }
|
||||||
|
case REG_DEBUG_FLAGS:
|
||||||
|
if (gba->debug) {
|
||||||
|
GBADebug(gba, value);
|
||||||
|
@@ -936,6 +941,11 @@ uint16_t GBAIORead(struct GBA* gba, uint32_t address) {
|
||||||
|
return 0x1DEA;
|
||||||
|
}
|
||||||
|
// Fall through
|
||||||
|
+ case REG_DEBUG_CYCLES: {
|
||||||
|
+ int32_t number_of_cycles = mTimingCurrentTime(&gba->timing);
|
||||||
|
+ mLOG(GBA_DEBUG, INFO, "Cycles: %d", number_of_cycles);
|
||||||
|
+ return number_of_cycles;
|
||||||
|
+ }
|
||||||
|
default:
|
||||||
|
mLOG(GBA_IO, GAME_ERROR, "Read from unused I/O register: %03X", address);
|
||||||
|
return GBALoadBad(gba->cpu);
|
|
@ -2,12 +2,14 @@
|
||||||
|
|
||||||
MGBA_VERSION=$1
|
MGBA_VERSION=$1
|
||||||
OUT_DIRECTORY=$2
|
OUT_DIRECTORY=$2
|
||||||
|
CURRENT_DIRECTORY=$(pwd)
|
||||||
|
|
||||||
cd ${OUT_DIRECTORY}
|
cd ${OUT_DIRECTORY}
|
||||||
curl -L https://github.com/mgba-emu/mgba/archive/refs/tags/${MGBA_VERSION}.tar.gz -o mgba-${MGBA_VERSION}.tar.gz
|
curl -L https://github.com/mgba-emu/mgba/archive/refs/tags/${MGBA_VERSION}.tar.gz -o mgba-${MGBA_VERSION}.tar.gz
|
||||||
tar -xvf mgba-${MGBA_VERSION}.tar.gz
|
tar -xvf mgba-${MGBA_VERSION}.tar.gz
|
||||||
cd mgba-${MGBA_VERSION}
|
cd mgba-${MGBA_VERSION}
|
||||||
rm -rf build
|
rm -rf build
|
||||||
|
patch --strip=1 < ${CURRENT_DIRECTORY}/add_cycles_register.patch
|
||||||
mkdir -p build
|
mkdir -p build
|
||||||
cd build
|
cd build
|
||||||
cmake .. \
|
cmake .. \
|
||||||
|
@ -29,6 +31,7 @@ cmake .. \
|
||||||
-DUSE_LZMA=OFF \
|
-DUSE_LZMA=OFF \
|
||||||
-DUSE_DISCORD_RPC=OFF \
|
-DUSE_DISCORD_RPC=OFF \
|
||||||
-DENABLE_SCRIPTING=OFF \
|
-DENABLE_SCRIPTING=OFF \
|
||||||
|
-DCMAKE_BUILD_TYPE=Debug \
|
||||||
-DUSE_EPOXY=OFF
|
-DUSE_EPOXY=OFF
|
||||||
make
|
make
|
||||||
|
|
||||||
|
|
|
@ -19,6 +19,7 @@ fn main() {
|
||||||
.file("c/test-runner.c")
|
.file("c/test-runner.c")
|
||||||
.include(&mgba_directory.join("include"))
|
.include(&mgba_directory.join("include"))
|
||||||
.static_flag(true)
|
.static_flag(true)
|
||||||
|
.debug(true)
|
||||||
.compile("test-runner");
|
.compile("test-runner");
|
||||||
|
|
||||||
let bindings = bindgen::Builder::default()
|
let bindings = bindgen::Builder::default()
|
||||||
|
@ -29,4 +30,9 @@ fn main() {
|
||||||
bindings
|
bindings
|
||||||
.write_to_file(&out_path.join("runner-bindings.rs"))
|
.write_to_file(&out_path.join("runner-bindings.rs"))
|
||||||
.expect("Couldn't write bindings!");
|
.expect("Couldn't write bindings!");
|
||||||
|
|
||||||
|
println!("cargo:rerun-if-changed=c/test-runner.c");
|
||||||
|
println!("cargo:rerun-if-changed=c/test-runner.h");
|
||||||
|
println!("cargo:rerun-if-changed=build-mgba.sh");
|
||||||
|
println!("cargo:rerun-if-changed=add_cycles_register.patch");
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ struct MGBA {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MGBA* new_runner(char* filename) {
|
struct MGBA* new_runner(char* filename) {
|
||||||
struct MGBA* mgba = malloc(sizeof(struct MGBA));
|
struct MGBA* mgba = calloc(1, sizeof(struct MGBA));
|
||||||
mgba->mlogger.log = log_output;
|
mgba->mlogger.log = log_output;
|
||||||
mgba->callback.callback = NULL;
|
mgba->callback.callback = NULL;
|
||||||
|
|
||||||
|
|
|
@ -16,12 +16,22 @@ enum Status {
|
||||||
Sucess,
|
Sucess,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum Timing {
|
||||||
|
None,
|
||||||
|
WaitFor(i32),
|
||||||
|
Difference(i32),
|
||||||
|
}
|
||||||
|
|
||||||
|
const TEST_RUNNER_TAG: u16 = 785;
|
||||||
|
|
||||||
fn test_file(file_to_run: &str) -> Status {
|
fn test_file(file_to_run: &str) -> Status {
|
||||||
let mut finished = Status::Running;
|
let mut finished = Status::Running;
|
||||||
let debug_reader_mutex = Regex::new(r"(?s)^\[(.*)\] GBA Debug: (.*)$").unwrap();
|
let debug_reader_mutex = Regex::new(r"(?s)^\[(.*)\] GBA Debug: (.*)$").unwrap();
|
||||||
|
let tagged_cycles_reader = Regex::new(r"Cycles: (\d*) Tag: (\d*)").unwrap();
|
||||||
|
|
||||||
let mut mgba = runner::MGBA::new(file_to_run).unwrap();
|
let mut mgba = runner::MGBA::new(file_to_run).unwrap();
|
||||||
let video_buffer = mgba.get_video_buffer();
|
let video_buffer = mgba.get_video_buffer();
|
||||||
|
let mut number_of_cycles = Timing::None;
|
||||||
|
|
||||||
mgba.set_logger(|message| {
|
mgba.set_logger(|message| {
|
||||||
if let Some(captures) = debug_reader_mutex.captures(message) {
|
if let Some(captures) = debug_reader_mutex.captures(message) {
|
||||||
|
@ -41,6 +51,29 @@ fn test_file(file_to_run: &str) -> Status {
|
||||||
} else if out.ends_with("...") {
|
} else if out.ends_with("...") {
|
||||||
print!("{}", out);
|
print!("{}", out);
|
||||||
io::stdout().flush().expect("can't flush stdout");
|
io::stdout().flush().expect("can't flush stdout");
|
||||||
|
} else if out.starts_with("Cycles: ") {
|
||||||
|
if let Some(captures) = tagged_cycles_reader.captures(out) {
|
||||||
|
let num_cycles: i32 = captures[1].parse().unwrap();
|
||||||
|
let tag: u16 = captures[2].parse().unwrap();
|
||||||
|
|
||||||
|
if tag == TEST_RUNNER_TAG {
|
||||||
|
number_of_cycles = match number_of_cycles {
|
||||||
|
Timing::WaitFor(n) => Timing::Difference(num_cycles - n),
|
||||||
|
Timing::None => Timing::WaitFor(num_cycles),
|
||||||
|
Timing::Difference(_) => Timing::WaitFor(num_cycles),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if out == "[ok]" {
|
||||||
|
if let Timing::Difference(cycles) = number_of_cycles {
|
||||||
|
println!(
|
||||||
|
"[ok: {} c ≈ {} s]",
|
||||||
|
cycles,
|
||||||
|
((cycles as f64 / (16.78 * 1_000_000.0)) * 100.0).round() / 100.0
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
println!("{}", out);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
println!("{}", out);
|
println!("{}", out);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue