Rust ã§ã²ãŒã ããŒã€ã¢ããã³ã¹åãã®é³æ¥œãœãããéçºããã«ã¯ (1) åºç€ç·š
ã²ãŒã ããŒã€ã¢ããã³ã¹ã®ãœããã¯äžã€ãæã£ãŠããŸããããæãç«ã£ãŠ Analogue Pocket ãè²·ããŸããã察æŠãããããé¡ãããŸãã
ãªãä»ã²ãŒã ããŒã€ã¢ããã³ã¹ãã¢ããã®ã
å æãFMS ãšããã²ãŒã ããŒã€ã¢ããã³ã¹å°çšã®æ°äœãœãããçºå£²ãããŸããããšãã£ãŠãã²ãŒã ã§ã¯ãªãã鳿¥œãæŒå¥ããããã®ãã®ã§ãã
ã²ãŒã ããŒã€ã§é³æ¥œããããšãããšãLSDj ãæãæµ®ãã¹ã人ãå€ããããããŸããããããããããã¥ãŒã³ããšããæãã®é³ã§ãã
èŽãæ¯ã¹ãŠã¿ããšãFMSã®æ¹ã¯ãããŒãã¡ã€ã§ã¯ããã©ããããŸãããããã¥ãŒã³æããªãé³ãå€ãã§ããããFMS 㯠LSDj ãšéã£ãŠã²ãŒã ããŒã€ã¢ããã³ã¹å°çšã®ãœãããªã®ã§ãã²ãŒã ããŒã€ã¢ããã³ã¹ã®æ§èœãéºæŸãªãçºæ®ãããªãããªé³ãåºããŠããã®ã§ãããããã²ãŒã ããŒã€ã¢ããã³ã¹ã®é¢çœããšããã§ãã²ãŒã ããŒã€ãšåã鳿ºããããããã€ã€ããã£ãšã¢ãã³ãªé³ãçµã¿åãããããŸãã
ãšãã話ãã以äžã®ã€ã³ã¿ãã¥ãŒãèªãã§ç¥ããŸããã
GBAã¯ãã²ãŒã æ©ãšããŠã¯ã»ãŒæåŸãšèšã£ãŠããã鳿ºãããã§é³æ¥œã鳎ããããŒãã§ãã
GBAã®ééå³ã¯ãäºã€ã®é³æºãä¹ã£ãŠããããšã«ãããã§ããäžã€ã¯ã²ãŒã ããŒã€ãšå šãåããã®ã§ãããäžã€ã¯ãã®ãããç²ããµã³ããªã³ã°é³æºãåŸè ã®æ¹ã¯ãã¹ãŒããŒãã¡ãã³ã³ãšåçšåºŠã®é³æ°ã質æãåºããŸãããé³è³ªã¯ãã£ãšç²ãã§ãããããã²ãŒã ããŒã€æ¬æ¥ã®PSGç³»ãµãŠã³ããâ»ããšçµ¶åŠã«çµ¡ã¿åããšããããGBAã®é³æ¥œã®é¢çœããšãããªãã§ãã
ãã®ã€ã³ã¿ãã¥ãŒã§èªãããŠããããã«ãã²ãŒã ããŒã€ã¢ããã³ã¹ã®ããã³ã·ã£ã«ã¯ãŸã ãŸã çãããåã£ãŠããªãããã§ããå®ã¯ FMS ããPSG 鳿ºãšããŠäœ¿ã£ãŠããã®ã¯ãã€ãºã ããªã®ã§ãããã¡ãã£ãšããããã¥ãŒã³å¯ãã®ãœãããåºãŠããäœå°ã¯ããããããããã§ãã
ä¹ããããªãããã®ããã°ãŠã§ãŒãã«ïŒããšããããšã§ïŒïŒïŒãRust ã§ã²ãŒã ããŒã€ã¢ããã³ã¹åãã®ãœãããéçºããæ¹æ³ã調ã¹ãŠãããŸãã
ãããã Rust ã£ãŠã²ãŒã ããŒã€ã¢ããã³ã¹åãã®ãã€ããªãã³ã³ãã€ã«ã§ããã®ïŒ
ã²ãŒã ããŒã€ã¯ç¡çãªãã§ãããã²ãŒã ããŒã€ã¢ããã³ã¹ã¯ã§ããŸãã
ã²ãŒã ããŒã€ã¢ããã³ã¹ã®ã¡ã€ã³ã¯ ARM7TDMI ãšãã ARMv4T åœä»€ã»ããã«å¯Ÿå¿ããŠãã CPU ã§ããRust ã§ã¯ãã®ããã« armv4t-none-eabiïŒ32ãããåœä»€ïŒãš thumbv4t-none-eabiïŒ16ãããåœä»€ïŒãšããã¿ãŒã²ãããçšæãããŠããŸããã²ãŒã ããŒã€ã¢ããã³ã¹ã§ã¯ãã«ãŒããªããžãèªã¿åããã¹ã®å¹
ã16ããããããªãããšãšãã«ãŒããªããžã®å®¹éãéãããŠããã®ã§ãthumbv4t-none-eabi ã®æ¹ãããã©ãŒãã³ã¹ãåºããšãããŠããŸãã
ãã®ã¿ãŒã²ããã¯ãARM ãªã®ãšãä»ã®ãšãã tier 3 ãªã®ã§ãããã¥ã¡ã³ãã® requirements ã«æžãããŠããããã«ãããã€ãèšå®ãå¿
èŠã§ãã以äžã¯ cargo new ããåŸã«ããããšã§ãããç°¡åã«ç޹ä»ããŸãã
rust-toolchain.toml
ãŸããtier 3 ãªã®ã§ãã³ã¢ã©ã€ãã©ãªããã«ãããå¿ èŠããããŸãããã®ããã«ãnightly ã®ããŒã«ãã§ãŒã³ãšãRust ã®ãœãŒã¹ã³ãŒããå¿ èŠã§ãã
[toolchain]
channel = "nightly"
components = ["rust-src"]
.cargo/config.toml
ã³ã¢ã©ã€ãã©ãªããã«ããããããã« build-std = ["core"] ã®èšå®ãå
¥ããŠããŸãããã¢ã¡ã¿ã«ã§ã¯ std ã¯äœ¿ãã core ã§ãã
[build]
target = "thumbv4t-none-eabi"
[unstable]
build-std = ["core"]
[target.thumbv4t-none-eabi]
rustflags = ["-Clink-arg=-Tmono_boot.ld"]
æåŸã®è¡ã® rustflags ã¯ããªã³ã«ã¹ã¯ãªãããã¿ãŒã²ããã«å«ãŸããŠããªãã®ã§èªåã§æå®ããªããšãããªãããšã®ããšã§å
¥ããŠããŸãããã㯠gba ã®ã¬ããžããªã«ããã®ã§ããããããŠã³ããŒãããŠããŠæå®ããŠããŸãã
ãããã°
ãã«ããããã€ããªã¯ãã²ãŒã ããŒã€ã¢ããã³ã¹ã®ãšãã¥ã¬ãŒã¿ã runner ãšããŠæå®ããŠãããš cargo run ããã ãã§åäœç¢ºèªãã§ããŠäŸ¿å©ã§ãããšãã¥ã¬ãŒã¿ãšããŠã¯ãmGBA ã䜿ã£ãŠããã°ééããªãããã§ãã
ã€ã³ã¹ããŒã«ãããã.cargo/config.toml ã® [target.thumbv4t-none-eabi] ã®ã»ã¯ã·ã§ã³ã«ä»¥äžã远å ããŸãã
[target.thumbv4t-none-eabi]
runner = ["/path/to/mGBA"]
ã²ãŒã ããŒã€ã¢ããã³ã¹åãã® crate ã¯ã©ãã䜿ãã
ã²ãŒã ããŒã€ã¢ããã³ã¹åãã® crate ãšããŠã¯ã以äžã®2ã€ãäž»èŠãªãã®ã®ããã§ãããã£ããèŠãæããæ®éã«ã²ãŒã ãéçºãããªã agb ã®æ¹ãããããæŽã£ãŠããŠãgba ã®æ¹ãäœã¬ãã«ãª API ãæäŸããŠããããã§ãã
æ®éã«èãããš agb ã䟿å©ãããªãã§ãããäžã§ãµãŠã³ãã®ããšãæžããããã«ã¯é³æºããããè§Šãããã€ã®æ¹ãããã§ãããããããã芳ç¹ã§ agb ãçºããŠã¿ããšããããããé²é³ãã鳿¥œã WAV ãã¡ã€ã«ãªã©ã«ããŠæµãããšããæ¹æ³ããæ³å®ãããŠããªãããã§ãããŸãã²ãŒã éçºãªãã ããããã§ããã...
ãšããããšã§ãgba ã§ãã£ãŠãããŸãããã
0) cargo new
ãšãããããcargo new ã§ crate ãã€ãããgba crate ãäŸåé¢ä¿ã«è¿œå ããŸãã
cargo new --bin gba-simple-app
cd gba-simple-app
cargo add gba
äžã«æžããããã«ãrust-toolchain.toml ãš .cargo/config.toml ã®èšå®ãå¿
èŠã§ãã
1) çã£çœãç»é¢ãåºã
gba ã®ã¬ããžããªã® examples/ ãã£ã¬ã¯ããªäžã«ã¯ããããã³ãŒãäŸããããã§ãããããã® hello.rs ã¯ã¡ãã£ãš hello world ãšããã«ã¯ããã³ãŒããå€ãã®ã§ããã®ãã¥ãŒããªã¢ã«ã«åŸã£ãŠãã£ãŠãããŸããèŠã€ããäžã§ã¯äžçªäžå¯§ã«æžãããŠããŠãèªã¿ãããã£ãã§ãã
ãŸãã¯æãã·ã³ãã«ã«ãäœãããªãã³ãŒãããå§ããŠãããŸãããããããªæãã§ãã
#![no_std]
#![no_main]
use gba::prelude::*;
#[panic_handler]
fn panic_handler(_: &core::panic::PanicInfo) -> ! {
loop {}
}
#[unsafe(no_mangle)]
extern "C" fn main() -> ! {
loop {}
}
#[panic_handler]ãšããèŠæ
£ããªãã¢ãããŒã·ã§ã³ããããŸããããã¢ã¡ã¿ã«ã®å Žå㯠panic ããéã®æåãèªåã§å®çŸ©ããå¿
èŠãããããããã€ããŠãã颿°ããªããšãšã©ãŒã«ãªããŸãïŒåèïŒãé»åå·¥äœãªã©ã®éã«ã¯panic-probe ãªã©ã® crate ã䜿ãããšãå€ãæ°ãããŸãã
ã¡ãªã¿ã«ãgba crate ã«ã¯ mGBA ã®ãã°ã«ã¡ãã»ãŒãžãåºåããæ©èœãããã®ã§ãããã䜿ãããšãã§ããŸãããããªæãâã«ããŠããã° panic ãããšãã®ã¡ãã»ãŒãžããã£ã¡ã«åºãŠãããã¿ããã§ãïŒæ¬å®¶ã® hello.rs åç §ïŒã
#[panic_handler]
fn panic_handler(info: &core::panic::PanicInfo) -> ! {
use core::fmt::Write as _;
#[cfg(debug_assertions)]
if let Ok(mut logger) = MgbaBufferedLogger::try_new(MgbaMessageLevel::Fatal) {
writeln!(logger, "{info}").ok();
}
loop {}
}
ãšããã cargo run ã§å®è¡ããŠã¿ãŸããããmGBA ãç«ã¡äžãã£ãŠä»¥äžã®ãããªçã£çœãç»é¢ãåºãã°æåã§ãã

2) ç»é¢ã«ãªã«ãæç»ãã
ãã¥ãŒããªã¢ã«ã«ããã°ããŸããã®ã³ãŒãã main() ã«å
¥ãããšç»é¢ãé»ããªããŸããé ã远ã£ãŠèŠãŠãããŸãããã
DISPCNT.write(
DisplayControl::new()
.with_video_mode(VideoMode::_3)
.with_show_bg2(true),
);
DISPCNT ã¯ç»é¢ãã³ã³ãããŒã«ããã¡ã¢ãªã®é åïŒã¬ãžã¹ã¿ïŒã衚ã structãVolAddress ã§ããããã« read() ã write() ã®ãããªã¡ãœãããçããŠããŠããã®ã¡ã¢ãªãèªã¿æžãããããšãã§ããŸããããã«æž¡ãããŠãã DisplayControl ã®æ£äœã¯ u16 ã§ããwith_*() ãåŒã³åºããšå¯Ÿå¿ããããããæžãæããããŸããèŠã¯ã16 bit ã®ã¡ã¢ãªãé åãæžãæããã®ãããããæŒç®ã§è¡šçŸãã代ããã«ããæãã®ã€ã³ã¿ãŒãã§ãŒã¹ã被ãããã®ã§ãã
with_video_mode(VideoMode::_3) ã¯ãã²ãŒã ããŒã€ã¢ããã³ã¹ã«ã¯6ã€ã®ãããªã¢ãŒãããã£ãŠããããéžæããŠããŸãã詳现ã¯å²æããŸãããmode 3 ã¯ãããããããããã®ãŸãŸè¡šç€ºããã¢ãŒãã§ããVideoMode ã®ããã¥ã¡ã³ãã«ããã°
BG2 is a single full color bitmap.
ãšæžãããŠããŸããBG2 ãšããã®ã¯ãèæ¯ã«äœ¿ãããã£ã³ãã¹ã§ããBG0 ïœ BG3 ãŸã§ãã£ãŠãã¢ãŒãã«ãã£ãŠäœ¿ããæ°ãçšéãç°ãªããŸãããšããããä»åéžãã mode 3 ã§ã¯ BG2 ã«æžã蟌ãããšã«ãªããŸãããªã®ã§ããã®æ¬¡ã« .with_show_bg2(true) ã§ BG2 ã衚瀺ããåœä»€ãåºããŠããŸãããã㊠BG2 ã衚瀺ãããŸããããã®æç¹ã§ã¯ãŸã BG2 ã«ã¯äœãæžãããŸããŠããªãã®ã§ãé»äžé¢ã®ç»é¢ãåºãããšããã®ãèµ·ãã£ãŠããããšã§ãã
ã§ã¯ãããã«æžã蟌ãã«ã¯ã©ãããã°ããã®ã§ãããããããã¯ãŸã ããŸãã¡ããçè§£ã§ããŠããªãã®ã§ãããmode 3ïœ5 ã¯ããããããçšã®æç»ã¢ãŒãã§ãããããã«å°çšã®ã€ã³ã¿ãŒãã§ãŒã¹ãçšæãããŠããŸãã
ä»å㯠mode 3 ãªã®ã§ VIDEO3_VRAM ã«æžã蟌ã¿ãŸããããšãã°ä»¥äžã®ã³ãŒãã§ã(10, 20) ã®äœçœ®ã«ãããã¯ã»ã«ãéãããŸããColor ãäžèº«ã¯ u16 ã§ãRGB555 ãšããã5 bit ãã€ã§èµ€ç·éã衚ã圢åŒïŒæ®ã 1 bit ã¯äœ¿ããªãïŒã«ãªã£ãŠããŸãã
VIDEO3_VRAM.index(10, 20).write(Color::BLUE);
1ãã¯ã»ã«ã ãã ãšèŠããªãã®ã§ããã¡ãã£ãšå¡ãé¢ç©ãå¢ãããš...
for i in 10..100 {
for j in 10..100 {
VIDEO3_VRAM.index(i, j).write(Color::BLUE);
}
}
以äžã®ãããªç»é¢ã«ãªããŸããã¡ãªã¿ã«ãcargo runïŒãããã°ãã«ãïŒã ãšé
ãã®ã§åŸã
ã«å¡ããåºãã£ãŠãããŸãããcargo run --releaseã ãšäžç¬ã§è¡šç€ºãããã¯ãã§ãã

3) ãã¿ã³å ¥åãåãåã
ãã¿ã³å
¥å㯠KEYINPUT ã§åããŸããread() ããçµæã®ãªããžã§ã¯ãã« .a() ã .b() ãªã©åãã¿ã³ã«å¯Ÿå¿ããã¡ãœããïŒæŒãããŠããã° true ãè¿ãïŒãããã®ã§ãããã§ãã¿ã³ã®ç¶æ
ã調ã¹ãŸããäŸãã°ãAãã¿ã³ãæŒãããŠããéã¯èµ€è²ãæŒãããŠããªããšãã¯éè²ã«ããããšãããšã次ã®ãããªã³ãŒãã«ãªããŸãã
let keys = KEYINPUT.read();
let color = if keys.a() { Color::RED } else { Color::BLUE };
for i in 10..100 {
for j in 10..100 {
VIDEO3_VRAM.index(i, j).write(color);
}
}
ãããã«ãŒãã®äžã«å ¥ãããšã
#[unsafe(no_mangle)]
extern "C" fn main() -> ! {
DISPCNT.write(
DisplayControl::new()
.with_video_mode(VideoMode::_3)
.with_show_bg2(true),
);
loop {
let keys = KEYINPUT.read();
let color = if keys.a() { Color::RED } else { Color::BLUE };
for i in 10..100 {
for j in 10..100 {
VIDEO3_VRAM.index(i, j).write(color);
}
}
}
}
ãããªæãã§è²ãå€ãããŸãã

ããã§ãããŸããããã«åãæ¿ãã£ãŠããªãã®ã¯ãç»é¢æç»ãšåæã§ããŠããªãããã§ããããã«ã¯ã1ãã¬ãŒã ã®ç»é¢ãæç»ãçµãã£ãåŸã«çºçãã VBLANK ãšããå²ã蟌ã¿ãããã®ã§ããããåŸ
〠VBlankIntrWait() ã䜿ãã°åæãããããããã®ã§ãã...ããã®ã³ãŒãã¯VBLANK äžã ãã§ã¯åŠçãçµãããªãã®ããæ¹åã¯ãããã®ã®ã¡ãã€ãã¯æ®ã£ããŸãŸã§ããã
IE 㯠Interrupt Enable ã§æå®ããå²ã蟌ã¿ãæå¹ã«ãããã®ãIME 㯠Interrupt Master Enable ã§å
šå²ã蟌ã¿ã®æå¹ã»ç¡å¹ãåãæ¿ãããã®ããããã§ãã
#[unsafe(no_mangle)]
extern "C" fn main() -> ! {
DISPSTAT.write(DisplayStatus::new().with_irq_vblank(true));
IE.write(IrqBits::VBLANK);
IME.write(true);
// ...
loop {
VBlankIntrWait();
// ...
}
}
ãšããããšã§åé¡ã¯è§£æ±ºããŠããªãã®ã§ããããŸããã¿ã³å ¥åãåããããšã¯ããã£ãã®ã§æ¬¡ã«é²ã¿ãŸãã
4) é³ã鳎ãã
ããŠãã€ãã«æ¬äžžã§ãã
ããããããŠãããšãã²ãŒã ããŒã€ã¢ããã³ã¹ã§é³ã鳎ããã«ã¯2ã€ã®æ¹æ³ããããŸãã
- ã²ãŒã ããŒã€äºæã®é³æºãããã鳎ããïŒPSG鳿ºïŒ
- ã²ãŒã ããŒã€ã¢ããã³ã¹ã§èªã¿èŸŒãã or äœã£ã波圢ã鳎ããïŒPCM鳿ºïŒ
ããå ·äœçã«æžããšã以äžã®4çš®é¡6ãã£ã³ãã«ã䜿ããŸãã
- PSG
- ç©åœ¢æ³¢ x 2
- ãŠã§ãŒãããŒãã«
- ãã€ãº
- PCM x 2ïŒãdirect soundããšåŒã°ããŠããïŒ
ããããæäœæ¹æ³ãéãã®ã§ããããã調ã¹ãŠãããªããšãã¡ãªãã§ãããçŽå¹ ãå°œããŠããããïŒéæ³ã®èšãèš³ïŒä»åã¯ãšããããç©åœ¢æ³¢ã鳎ããã ãã§ååŒããŠãã ãããã
ãšããããåãã³ãŒããå ã«èŒãããšãç©åœ¢æ³¢ã®ãã£ã³ãã«ã鳎ãã Tonc ã®äŸ ããã®ãŸãŸç¿»èš³ããŠãããªæãã§ããå®è¡ãããšããã³ãŒã³ããšããæãã®é³ã鳎ãã¯ãã§ãã
SOUND_ENABLED.write(
SoundEnable::new()
.with_enabled(true)
.with_tone1_playing(true),
);
LEFT_RIGHT_VOLUME.write(
LeftRightVolume::new()
.with_left_volume(7)
.with_right_volume(7)
.with_tone1_left(true)
.with_tone1_right(true),
);
SOUND_MIX.write(SoundMix::new().with_psg(PsgMix::_100));
TONE1_PATTERN.write(
TonePattern::new()
.with_duty(2)
.with_volume(15)
.with_step_increasing(false)
.with_length(7)
.with_step_time(4),
);
TONE1_FREQUENCY.write(ToneFrequency::new().with_enabled(true).with_frequency(10000));
ãŸã㯠SOUND_ENABLED ã§ãµãŠã³ããæå¹ã«ããŠããŸãããµãŠã³ãå
šäœã®æå¹/ç¡å¹ã«å ããŠãPSG鳿ºã¯åå¥ã«æå¹/ç¡å¹ã®èšå®ãããããã§ããããã§æå®ããŠãã _tone1_ ã¯ç©åœ¢æ³¢ã®ãã£ã³ãã«ã®1ã€ç®ã§ãã
LEFT_RIGHT_VOLUME ã¯å·Šå³ã®ããªã¥ãŒã ãšãåPSG鳿ºãã£ã³ãã«ã®æå¹/ç¡å¹ãèšå®ããŸããããªã¥ãŒã 㯠3 bit ãªã®ã§ã7 ãæå€§ã§ãã
SOUND_MIX ã¯ãPSG 鳿ºãš PCM 鳿ºã®ãããµãŒãªãã§ãããããã»ã©çްããèšå®ã¯ã§ããŸããããã£ãã以äžã®ããã«ãªã£ãŠããããã§ãã
- PSG 鳿ºãŸãšããŠã®é³éã3段éã§èšå®ïŒ25%ã50%ã100%ïŒ
- PCM 鳿ºãã£ã³ãã«ããããã®é³éã2段éã§èšå®ïŒ50%ã100%ïŒ
- PCM 鳿ºãã£ã³ãã«ããããã®å·Šå³ã®æå¹/ç¡å¹ã®èšå®
ä»åã¯ãPSG 鳿ºãã䜿ã£ãŠããªãã®ã§ .with_psg(PsgMix::_100) ã ããèšå®ããŠããŸãã
TONE1_PATTERN ã¯ãšã³ãããŒãã®èšå®ã§ãã现ããæå³ã¯ãŸã ããŸãçè§£ã§ããŠããŸããããããããããšãèšå®ããŠããŸãã
-
.with_duty(2)ã¯ç©åœ¢æ³¢ã®ãã¥ãŒãã£æ¯ïŒãã«ã¹å¹ ïŒã®èšå®ã§ãããã㯠enum ãå®çŸ©ãããŠããªãã®ã§èªåã§èª¿ã¹ããã§ããã4 bit ã®å€ã§ã0 â 1/8ã1 â 1/4ã2 â 1/2ã3 â 3/4 ã«ãªã£ãŠããããã§ãã -
.with_volume(15)ã¯ããªã¥ãŒã ã§ãã4 bit ãªã®ã§ 15 ãæå€§ã§ãã -
.with_step_increasing(false)ã¯ãåŸã ã«é³éãäžãããšã³ãããŒãããåŸã ã«é³éãäžãããšã³ãããŒãããåãæ¿ããŸãã -
.with_length(7)ã¯é³ã®é·ãã§ãã3 bit ãªã®ã§ 7 ãæå€§ã§ãã -
.with_step_time(4)ã¯ãšã³ãããŒããå€åãããæéã®è§£å床ã§ãã説æãé£ããã§ãããæ°åãå°ããã»ã©é³ãçããªããŸãã3 bit ãªã®ã§ 7 ãæå€§ã§ãããªããé³ã®é·ãã§æå®ããŠããã®ãšã¯ãŸãå¥ã®åäœã§ãã
æåŸã® TONE1_FREQUENCY ã¯ãåšæ³¢æ°ã®èšå®ãããŠããŸããåšæ³¢æ°ãªãã§ãããããã§ with_frequency() ã«æå®ããŠããæ°åããã®ãŸãŸãã«ããšããã§ã¯ãªããæã£ãé³ãåºãã«ã¯ã¡ãã£ãšèšç®ãå¿
èŠã¿ããã§ãïŒãŸã çè§£ã§ããŠããŸããïŒãã§ãwith_enabled(true) ãšããã®ãéèŠã§ããããå®éã«é³ãããªã¬ãŒããŸããgba crate ã§ã¯ enabled ãšããååã«ãªã£ãŠããã§ãããrestart ãšããæ£ãããã§ãã
5) ã²ãŒã ããŒã€ã¢ããã³ã¹ã§åããã€ããªã«ãã
ããä»ãŸã§ã®ã¯åããŠãªãã£ãã£ãŠããšïŒãéšããŠããã§ããïŒïŒ
ãšèšããããªãã®ããã®ã¯ããç§ããŠã£ãããmGBA ã§åãããããããããã®ãŸãŸã²ãŒã ããŒã€ã¢ããã³ã¹ã«æã£ãŠããã°åããã®ãšæã蟌ãã§ããŸããããããããã㯠mGBA ãæ°ãå©ãããŠå¯Ÿå¿ããŠãããŠããã ãã§ãcargo build ã§åºãŠãããã€ããªã¯ãã®ãŸãŸã§ã¯ã²ãŒã ããŒã€ã¢ããã³ã¹å®æ©ã§ã¯åããŸããã
ãªãã§ã ïŒããšæã£ãŠgba crate ã®ããã¥ã¡ã³ããèªããšãã¡ãããšæ³šææžãããããŸãããELF 圢åŒã«ãªã£ãŠããã®ã .bin ã«å€æããã®ãšãã²ãŒã ããŒã€ã¢ããã³ã¹çšã®ããããã€ããå¿ èŠããããšã®ããšã§ãã
Optional: Use objcopy and gbafix: The cargo build will produce ELF files, which mGBA can run directly. If you want to run your program on real hardware youâll need to first objcopy the raw binary out of the ELF into its own file, then Use gbafix to give an appropriate header to the file. objcopy is part of the ARM binutils you already installed, it should be named arm-none-eabi-objcopy. You can get gbafix through cargo: cargo install gbafix.
ELF ãã plain binary ãžã®å€æã¯ãobjcopy ã³ãã³ãã§ã§ããŸãããã£ãšè©³ããèšããšãArm GNU toolchain ãã€ã³ã¹ããŒã«ã㊠arm-none-eabi-objcopy ã䜿ããŸããããã¡ãªã¿ã«å®ã¯ããªã³ã«ããã®ããŒã«ãã§ãŒã³ã䜿ãã®ãããã¿ããïŒlinker = "arm-none-eabi-ld"ïŒãªãã§ããããšãããããããŸã§ã«æžããã³ãŒãã¯æšæºã®ãªã³ã«ã§ãåé¡ãªãããã§ããã
arm-none-eabi-objcopy -O binary \
./target/thumbv4t-none-eabi/release/gba-simple-app \
./gba-simple-app.gba
ã²ãŒã ããŒã€ã¢ããã³ã¹çšã®ãããã远å ããã®ã¯ãgbafix ã³ãã³ãã§ã§ããŸãããã㯠devkitPro ãšãã C/C++ åãã®ããŒã«ãã§ãŒã³ã«å«ãŸããŠãããã§ããããã®ã³ãã³ãã ãã®ããã«ã€ã³ã¹ããŒã«ããã«ã¯ã¡ãã£ãšãããŒãªãã€ãªã®ã§ãgba crate ãçšæããŠãããŠããããŒãžã§ã³ã®ã³ãã³ãã cargo install gbafix ã§ã€ã³ã¹ããŒã«ãããšããã§ãããã
gbafix ./gba-simple-app.gba
ããã§åºæ¥äžãã£ããã€ããªã¯å®æ©ã§åãã¯ãã§ãã
çµæ
ãããŸã§ã«è²Œã£ãã³ãŒãããå°ãæ¹é ããããã®ã§ãããã»ããšã«åããŠãŸãããšãã蚌æ ãšããŠåç»ã貌ã£ãŠãããŸãã
次åäºåãšåèæç®
ãšããããšã§ããšããããé³ãåºããšãããŸã§ãã©ãçããŸããïŒ
ãããŸã ã鳿¥œãœãããéçºãããã«ã¯çšé ãã®ã§ãããã¡ãã£ãšå匷ããŠããåºçŽããããšæããŸãããšããããšã§ãèªããŠããªããã®ãå«ããŠåèã«ãããŠã§ããµã€ãããããŠãããŸãã
ä»åã¡ã€ã³ã§èªãã§ããã®ã¯ã以äžã®2ã€ã®ãŠã§ããµã€ãã§ãããåè 㯠Rust ã®è©±ã§ãããåŸè 㯠C ã§ãã
ãŸã èªããŠããŸãããã以äžã®ãã¥ãŒããªã¢ã«ããŸãã«ãã²ãŒã ããŒã€ã¢ããã³ã¹ã®ãµãŠã³ãã«é¢ãããã®ã§ããæ§ã ãªãŠã§ããµã€ãã§èšåãããŠããã®ãèŠãããã®ã§ãä¿¡é Œã眮ãããã§ãã
ãŸããã¬ãžã¹ã¿ã®äžèº«ã«ã€ããŠã¯ãã®ãµã€ãã詳ããããã§ãã
ãªãã ããã è²ã æ å ±ã¯ãããããªã®ã§ãåŒãç¶ãæ¢ããŠãããŸãã
Discussion