rust-console / gba

A crate that helps you make GBA games
https://docs.rs/gba
Apache License 2.0
659 stars 50 forks source link

Setting `RUST_IRQ_HANDLER` breaks interrupts on real hardware #198

Closed svkampen closed 2 months ago

svkampen commented 2 months ago

When running a ROM which sets RUST_IRQ_HANDLER on real hardware, interrupts do not seem to work properly; e.g. VBlankIntrWait() never returns. Presumably, something goes wrong while entering or exiting the Rust IRQ handler.

Further information

Minimal example

I've put up a repo here which reproduces the issue for me. As written, this example does not work on real hardware for me, continuing to show "Pre VBlankIntrWait". On emulators, or after removing src/main.rs:21 (the initialization of RUST_IRQ_HANDLER), it works properly, showing "Post VBlankIntrWait".

Crate version

0.13.0

Rust toolchain, as reported by rustup show

nightly-x86_64-unknown-linux-gnu (default)
rustc 1.83.0-nightly (9b72238eb 2024-09-14)

Please let me know if there is anything else I can do to help figure this out!

Anders429 commented 2 months ago

I can also verify this with the pong example.

$ cargo b --example mode3_pong_example_game
$ arm-none-eabi-objcopy -O binary target\thumbv4t-none-eabi\debug\examples\mode3_pong_example_game pong.gba
$ gbafix pong.gba

produces a file that runs on mgba but not on real hardware. I'm guessing something was missed with #197.

Anders429 commented 2 months ago

Can also confirm that this behavior did work correctly on gba version 0.12.0 (with bracer version 0.1.2, as version 0.1.3 fixed a bug old gba versions were relying on; you'll have to manually edit the Cargo.lock file to get version 0.1.2, using a checksum of 6559b8c3065745016f5cc2d1095273fe8a175e953c976426947ad828d6ba6fda). I can try to dig in a little bit and see what else is different between those two versions in the IRQ handling.

Lokathor commented 2 months ago

The difference I expect you to find is in the CPU mode changing. I had the constants wrong in the old version, or I thought i did, so it was switching to the "wrong" CPU mode when returning from the interrupt.

But maybe it's supposed to have been in the other mode and that's why it's not working now?