Merge pull request #86 from agbrs/mgba-test-runner-cycles

Mgba test runner cycles
This commit is contained in:
Corwin 2021-07-13 22:30:05 +01:00 committed by GitHub
commit b0afeade99
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 102 additions and 5 deletions

View file

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

View file

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

View file

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

View file

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

View file

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

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

View file

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

View file

@ -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");
} }

View file

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

View file

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