first commit

This commit is contained in:
Zenn 2023-08-06 18:14:49 +02:00
commit c591b2c272
50 changed files with 2650 additions and 0 deletions

19
.cargo/config.toml Normal file
View file

@ -0,0 +1,19 @@
[build]
target = "arduboy.json"
target-dir = "./target"
[profile.release]
codegen-units = 1
lto = "fat"
opt-level = "z"
panic = "abort"
[profile.dev]
codegen-units = 1
lto = "fat"
opt-level = "z"
panic = "abort"
[unstable]
build-std = ["core", "compiler_builtins"]
build-std-features = ["compiler-builtins-mem"]

5
.gitignore vendored Normal file
View file

@ -0,0 +1,5 @@
/target
/.vscode
/Wrapper-Project/.pio
/Wrapper-Project/lib/*.a

95
Cargo.lock generated Normal file
View file

@ -0,0 +1,95 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 3
[[package]]
name = "arduboy-rust"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e80037f297e2a5db1e58804b7a3b1b10f448b104623422db1c94b185b45b1ea5"
dependencies = [
"panic-halt",
]
[[package]]
name = "demo2"
version = "0.1.0"
dependencies = [
"arduboy-rust",
]
[[package]]
name = "demo3"
version = "0.1.0"
dependencies = [
"arduboy-rust",
]
[[package]]
name = "demo4"
version = "0.1.0"
dependencies = [
"arduboy-rust",
]
[[package]]
name = "demo5"
version = "0.1.0"
dependencies = [
"arduboy-rust",
]
[[package]]
name = "demo6"
version = "0.1.0"
dependencies = [
"arduboy-rust",
]
[[package]]
name = "eeprom-demo"
version = "0.1.0"
dependencies = [
"arduboy-rust",
]
[[package]]
name = "game"
version = "0.1.0"
dependencies = [
"arduboy-rust",
]
[[package]]
name = "panic-halt"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "de96540e0ebde571dc55c73d60ef407c653844e6f9a1e2fdbd40c07b9252d812"
[[package]]
name = "pong"
version = "0.1.0"
dependencies = [
"arduboy-rust",
]
[[package]]
name = "rustacean"
version = "0.1.0"
dependencies = [
"arduboy-rust",
]
[[package]]
name = "snake"
version = "0.1.0"
dependencies = [
"arduboy-rust",
]
[[package]]
name = "tone"
version = "0.1.0"
dependencies = [
"arduboy-rust",
]

15
Cargo.toml Normal file
View file

@ -0,0 +1,15 @@
[workspace]
members = [
"Examples/Arduboy-Tutorials/eeprom",
"Examples/Arduboy-Tutorials/tone",
"Examples/Arduboy-Tutorials/demo2",
"Examples/Arduboy-Tutorials/demo3",
"Examples/Arduboy-Tutorials/demo4",
"Examples/Arduboy-Tutorials/demo5",
"Examples/Arduboy-Tutorials/demo6",
"Examples/pong",
"Examples/rustacean",
"Examples/snake",
"Project/game",
]
resolver = "2"

View file

@ -0,0 +1,11 @@
[package]
name = "demo2"
version = "0.1.0"
authors = ["ZennDev <zenndev@protonmail.com>"]
edition = "2021"
[lib]
crate-type = ["staticlib"]
[dependencies]
arduboy-rust = "1.0.0"

View file

@ -0,0 +1,18 @@
#![no_std]
//Include the Arduboy Library
//Initialize the arduboy object
use arduboy_rust::prelude::*;
//The setup() function runs once when you turn your Arduboy on
#[no_mangle]
pub unsafe extern "C" fn setup() {
// put your setup code here, to run once:
arduboy.begin();
arduboy.clear();
arduboy.print("Holmes is cool!\0");
arduboy.display();
}
#[no_mangle]
#[export_name = "loop"]
pub unsafe extern "C" fn loop_() {
// put your main code here, to run repeatedly:
}

View file

@ -0,0 +1,11 @@
[package]
name = "demo3"
version = "0.1.0"
authors = ["ZennDev <zenndev@protonmail.com>"]
edition = "2021"
[lib]
crate-type = ["staticlib"]
[dependencies]
arduboy-rust = "1.0.0"

View file

@ -0,0 +1,38 @@
#![no_std]
//Include the Arduboy Library
//Initialize the arduboy object
use arduboy_rust::prelude::*;
//Initialize our counter variable
#[allow(non_upper_case_globals)]
static mut counter: c_int = 0;
//The setup() function runs once when you turn your Arduboy on
#[no_mangle]
pub unsafe extern "C" fn setup() {
//Start the Arduboy properly and display the Arduboy logo
arduboy.begin();
//Get rid of the Arduboy logo and clear the screen
arduboy.clear();
//Assign our counter variable to be equal to 0
counter = 0;
//Set framerate to 30
arduboy.set_frame_rate(30);
}
//The loop() function repeats forever after setup() is done
#[no_mangle]
#[export_name = "loop"]
pub unsafe extern "C" fn loop_() {
//Skip cycles not in the framerate
if !arduboy.next_frame() {
return;
}
//Clear whatever is printed on the screen
arduboy.clear();
//Move the cursor to the position 30, 30 of the screen
arduboy.set_cursor(0, 0);
//Increase counter's value by 1
counter += 1;
//Print out the value of counter
arduboy.print(counter);
//Refresh the screen to show whatever's printed to it
arduboy.display();
}

View file

@ -0,0 +1,11 @@
[package]
name = "demo4"
version = "0.1.0"
authors = ["ZennDev <zenndev@protonmail.com>"]
edition = "2021"
[lib]
crate-type = ["staticlib"]
[dependencies]
arduboy-rust = "1.0.0"

View file

@ -0,0 +1,54 @@
#![no_std]
#![allow(non_upper_case_globals)]
//Include the Arduboy Library
//Initialize the arduboy object
use arduboy_rust::prelude::*;
//Initialize our counter variable
static mut counter: c_int = 0;
//The setup() function runs once when you turn your Arduboy on
#[no_mangle]
pub unsafe extern "C" fn setup() {
//Start the Arduboy properly and display the Arduboy logo
arduboy.begin();
//Get rid of the Arduboy logo and clear the screen
arduboy.clear();
//Assign our counter variable to be equal to 0
counter = 0;
//Set framerate to 10
arduboy.set_frame_rate(10);
}
//The loop() function repeats forever after setup() is done
#[no_mangle]
#[export_name = "loop"]
pub unsafe extern "C" fn loop_() {
//Skip cycles not in the framerate
if !arduboy.next_frame() {
return;
}
//Clear whatever is printed on the screen
arduboy.clear();
//Check if the UP_BUTTON is being pressed
if UP.pressed() {
//Increase counter by 1
counter = counter + 1;
}
//Check if the DOWN_BUTTON is being pressed
if DOWN.pressed() {
//Decrease counter
counter = counter - 1;
}
//Check if counter is equal to 36
if counter == 36 {
//Move the cursor to the position 30, 30 of the screen
arduboy.set_cursor(30, 30);
//Printing the yay (important always put the \0 at the end for &str)
arduboy.print("Yay!\0");
}
//Move the cursor back to the top-left of the screen
arduboy.set_cursor(0, 0);
//Print out the value of counter
arduboy.print(counter);
//Refresh the screen to show whatever's printed to it
arduboy.display();
}

View file

@ -0,0 +1,10 @@
[package]
name = "demo5"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["staticlib"]
[dependencies]
arduboy-rust = "1.0.0"

View file

@ -0,0 +1,95 @@
#![no_std]
#![allow(non_upper_case_globals)]
//Include the Arduboy Library
//Initialize the arduboy object
use arduboy_rust::prelude::*;
//Initialize variables used in this game
static mut playerwin: c_int = 0;
static mut attempts: c_int = 0;
static mut guessednumber: c_int = 0;
static mut randomnumber: c_int = 0;
static mut lastguess: c_int = 0;
//The setup() function runs once when you turn your Arduboy on
#[no_mangle]
pub unsafe extern "C" fn setup() {
// put your setup code here, to run once:
arduboy.begin();
arduboy.clear();
arduboy.init_random_seed();
randomnumber = random_between(1, 101) as i16;
}
//The loop() function repeats forever after setup() is done
#[no_mangle]
#[export_name = "loop"]
pub unsafe extern "C" fn loop_() {
// put your main code here, to run repeatedly:
arduboy.clear();
arduboy.poll_buttons();
if playerwin == 0 {
//Ask the player for a number and play the game
if attempts == 7 {
//Game Over screen
arduboy.set_cursor(0, 0);
arduboy.print("You lost!\0");
arduboy.print("\n\0");
arduboy.print("Correct Number: \0");
arduboy.print(randomnumber);
if A.just_pressed() {
randomnumber = random_between(1, 101) as i16;
attempts = 0;
playerwin = 0;
}
} else {
//Player has more attempts
if UP.just_pressed() {
guessednumber += 1;
}
if DOWN.just_pressed() {
guessednumber -= 1;
}
if A.just_pressed() {
if guessednumber == randomnumber {
playerwin += 1;
} else {
attempts += 1;
lastguess = guessednumber
}
}
arduboy.set_cursor(0, 0);
arduboy.print("Attempt: \0");
arduboy.print(attempts);
arduboy.print("\n\0");
arduboy.print("Number to guess: \0");
arduboy.print(guessednumber);
arduboy.print("\n\0");
if attempts == 0 {
arduboy.print("Good luck!\0");
} else {
arduboy.print(lastguess);
if lastguess > randomnumber {
arduboy.print(" is too high!\0");
}
if lastguess < randomnumber {
arduboy.print(" is too low!\0");
}
}
}
} else {
//Tell the player that they won!
arduboy.set_cursor(0, 0);
arduboy.print("You won!\0");
arduboy.print("\n\0");
arduboy.print("Correct Number: \0");
arduboy.print(randomnumber);
if A.just_pressed() {
randomnumber = random_between(1, 101) as c_int;
attempts = 0;
playerwin = 0;
}
}
arduboy.display();
}

View file

@ -0,0 +1,10 @@
[package]
name = "demo6"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["staticlib"]
[dependencies]
arduboy-rust = "1.0.0"

View file

@ -0,0 +1,76 @@
#![no_std]
#![allow(non_upper_case_globals)]
//Include the Arduboy Library
//Initialize the arduboy object
#[allow(unused_imports)]
use arduboy_rust::prelude::*;
#[link_section = ".progmem.data"]
static background_sprite: [u8; 10] = [8, 8, 0x81, 0x00, 0x12, 0x40, 0x04, 0x11, 0x00, 0x04];
#[link_section = ".progmem.data"]
static player_sprite1: [u8; 34] = [
16, 16, 0xfe, 0x01, 0x3d, 0x25, 0x25, 0x3d, 0x01, 0x01, 0xc1, 0x01, 0x3d, 0x25, 0x25, 0x3d,
0x01, 0xfe, 0x7f, 0x80, 0x9c, 0xbc, 0xb0, 0xb0, 0xb2, 0xb2, 0xb3, 0xb0, 0xb0, 0xb0, 0xbc, 0x9c,
0x80, 0x7f,
];
#[link_section = ".progmem.data"]
static player_sprite2: [u8; 34] = [
16, 16, 0xfc, 0x02, 0x19, 0x25, 0x25, 0x19, 0x01, 0x01, 0x01, 0x01, 0x19, 0x25, 0x25, 0x19,
0x02, 0xfc, 0x3f, 0x40, 0x80, 0x98, 0x8c, 0x86, 0x82, 0x82, 0x82, 0x82, 0x86, 0x8c, 0x98, 0x80,
0x40, 0x3f,
];
// Put your variables here
static mut playerx: c_int = 5;
static mut playery: c_int = 10;
static mut playermode: bool = false;
// The setup() function runs once when you turn your Arduboy on
#[no_mangle]
pub unsafe extern "C" fn setup() {
// put your setup code here, to run once:
arduboy.begin();
arduboy.clear();
arduboy.set_frame_rate(60);
}
// The loop() function repeats forever after setup() is done
#[no_mangle]
#[export_name = "loop"]
pub unsafe extern "C" fn loop_() {
if !arduboy.next_frame() {
return;
}
// put your main code here, to run repeatedly:
arduboy.clear();
arduboy.poll_buttons();
if arduboy.pressed(LEFT) {
playerx -= 1;
}
if arduboy.pressed(RIGHT) {
playerx += 1;
}
if arduboy.pressed(UP) {
playery -= 1;
}
if arduboy.pressed(DOWN) {
playery += 1;
}
if arduboy.just_pressed(A) {
playermode = !playermode
}
for i in (0..WIDTH).step_by(8) {
for j in (0..HEIGHT).step_by(8) {
sprites::draw_override(i.into(), j.into(), get_sprite_addr!(background_sprite), 0)
}
}
if playermode {
sprites::draw_override(playerx, playery, get_sprite_addr!(player_sprite1), 0);
} else {
sprites::draw_override(playerx, playery, get_sprite_addr!(player_sprite2), 0);
}
arduboy.set_cursor(0, 0);
arduboy.display();
}

View file

@ -0,0 +1,12 @@
[package]
name = "eeprom-demo"
version = "0.1.0"
authors = ["ZennDev <zenndev@protonmail.com>"]
license = "MIT OR Apache-2.0"
edition = "2021"
[lib]
crate-type = ["staticlib"]
[dependencies]
arduboy-rust = "1.0.0"

View file

@ -0,0 +1,59 @@
#![no_std]
#![allow(non_upper_case_globals)]
//Include the Arduboy Library
//Initialize the arduboy object
#[allow(unused_imports)]
use arduboy_rust::prelude::*;
// #[link_section = ".progmem.data"]
// Setup eeprom memory
static mut eeprom: EEPROM = EEPROM::new(10);
static mut count: u8 = 0;
static mut MEM: u8 = 0;
// The setup() function runs once when you turn your Arduboy on
#[no_mangle]
pub unsafe extern "C" fn setup() {
// put your setup code here, to run once:
arduboy.begin();
eeprom.init();
arduboy.clear();
arduboy.set_frame_rate(30);
}
// The loop() function repeats forever after setup() is done
#[no_mangle]
#[export_name = "loop"]
pub unsafe extern "C" fn loop_() {
// put your main code here, to run repeatedly:
if !arduboy.next_frame() {
return;
}
arduboy.clear();
arduboy.poll_buttons();
if arduboy.just_pressed(UP) {
count += 1;
}
if arduboy.just_pressed(DOWN) {
count -= 1;
}
if arduboy.just_pressed(A) {
unsafe { eeprom.put(count) }
}
if arduboy.just_pressed(B) {
eeprom.get(&mut MEM)
}
arduboy.set_cursor(0, 0);
arduboy.print(count as u16);
arduboy.set_cursor(0, 30);
arduboy.print("Memory:\0");
arduboy.print(MEM as u16);
arduboy.set_cursor(0, 40);
arduboy.print("eeprom:\0");
arduboy.print(eeprom.read() as u16);
arduboy.display();
}

View file

@ -0,0 +1,12 @@
[package]
name = "tone"
version = "0.1.0"
authors = ["ZennDev <zenndev@protonmail.com>"]
license = "MIT OR Apache-2.0"
edition = "2021"
[lib]
crate-type = ["staticlib"]
[dependencies]
arduboy-rust = "1.0.0"

View file

@ -0,0 +1,490 @@
#![no_std]
#![allow(non_upper_case_globals)]
//Include the Arduboy Library
//Initialize the arduboy object
use arduboy_rust::arduboy_tone_pitch::*;
#[allow(unused_imports)]
use arduboy_rust::prelude::*;
#[link_section = ".progmem.data"]
static allNotes: [u16; 241] = [
NOTE_C0H,
NDUR,
NOTE_CS0,
NDUR,
NOTE_D0,
NDUR,
NOTE_DS0,
NDUR,
NOTE_E0,
NDUR,
NOTE_F0,
NDUR,
NOTE_FS0,
NDUR,
NOTE_G0,
NDUR,
NOTE_GS0,
NDUR,
NOTE_A0,
NDUR,
NOTE_AS0,
NDUR,
NOTE_B0,
NDUR,
NOTE_C1H,
NDUR,
NOTE_CS1,
NDUR,
NOTE_D1,
NDUR,
NOTE_DS1,
NDUR,
NOTE_E1,
NDUR,
NOTE_F1,
NDUR,
NOTE_FS1,
NDUR,
NOTE_G1,
NDUR,
NOTE_GS1,
NDUR,
NOTE_A1,
NDUR,
NOTE_AS1,
NDUR,
NOTE_B1,
NDUR,
NOTE_C2H,
NDUR,
NOTE_CS2,
NDUR,
NOTE_D2,
NDUR,
NOTE_DS2,
NDUR,
NOTE_E2,
NDUR,
NOTE_F2,
NDUR,
NOTE_FS2,
NDUR,
NOTE_G2,
NDUR,
NOTE_GS2,
NDUR,
NOTE_A2,
NDUR,
NOTE_AS2,
NDUR,
NOTE_B2,
NDUR,
NOTE_C3H,
NDUR,
NOTE_CS3,
NDUR,
NOTE_D3,
NDUR,
NOTE_DS3,
NDUR,
NOTE_E3,
NDUR,
NOTE_F3,
NDUR,
NOTE_FS3,
NDUR,
NOTE_G3,
NDUR,
NOTE_GS3,
NDUR,
NOTE_A3,
NDUR,
NOTE_AS3,
NDUR,
NOTE_B3,
NDUR,
NOTE_C4H,
NDUR,
NOTE_CS4,
NDUR,
NOTE_D4,
NDUR,
NOTE_DS4,
NDUR,
NOTE_E4,
NDUR,
NOTE_F4,
NDUR,
NOTE_FS4,
NDUR,
NOTE_G4,
NDUR,
NOTE_GS4,
NDUR,
NOTE_A4,
NDUR,
NOTE_AS4,
NDUR,
NOTE_B4,
NDUR,
NOTE_C5H,
NDUR,
NOTE_CS5,
NDUR,
NOTE_D5,
NDUR,
NOTE_DS5,
NDUR,
NOTE_E5,
NDUR,
NOTE_F5,
NDUR,
NOTE_FS5,
NDUR,
NOTE_G5,
NDUR,
NOTE_GS5,
NDUR,
NOTE_A5,
NDUR,
NOTE_AS5,
NDUR,
NOTE_B5,
NDUR,
NOTE_C6H,
NDUR,
NOTE_CS6,
NDUR,
NOTE_D6,
NDUR,
NOTE_DS6,
NDUR,
NOTE_E6,
NDUR,
NOTE_F6,
NDUR,
NOTE_FS6,
NDUR,
NOTE_G6,
NDUR,
NOTE_GS6,
NDUR,
NOTE_A6,
NDUR,
NOTE_AS6,
NDUR,
NOTE_B6,
NDUR,
NOTE_C7H,
NDUR,
NOTE_CS7,
NDUR,
NOTE_D7,
NDUR,
NOTE_DS7,
NDUR,
NOTE_E7,
NDUR,
NOTE_F7,
NDUR,
NOTE_FS7,
NDUR,
NOTE_G7,
NDUR,
NOTE_GS7,
NDUR,
NOTE_A7,
NDUR,
NOTE_AS7,
NDUR,
NOTE_B7,
NDUR,
NOTE_C8H,
NDUR,
NOTE_CS8,
NDUR,
NOTE_D8,
NDUR,
NOTE_DS8,
NDUR,
NOTE_E8,
NDUR,
NOTE_F8,
NDUR,
NOTE_FS8,
NDUR,
NOTE_G8,
NDUR,
NOTE_GS8,
NDUR,
NOTE_A8,
NDUR,
NOTE_AS8,
NDUR,
NOTE_B8,
NDUR,
NOTE_C9H,
NDUR,
NOTE_CS9,
NDUR,
NOTE_D9,
NDUR,
NOTE_DS9,
NDUR,
NOTE_E9,
NDUR,
NOTE_F9,
NDUR,
NOTE_FS9,
NDUR,
NOTE_G9,
NDUR,
NOTE_GS9,
NDUR,
NOTE_A9,
NDUR,
NOTE_AS9,
NDUR,
NOTE_B9,
NDUR,
TONES_REPEAT,
];
#[link_section = ".progmem.data"]
static sound1: [u16; 73] = [
NOTE_C1, 500, NOTE_C1H, 500, NOTE_G1, 500, NOTE_G1H, 500, NOTE_C2, 500, NOTE_C2H, 500, NOTE_G2,
500, NOTE_G2H, 500, NOTE_C3, 500, NOTE_C3H, 500, NOTE_G3, 500, NOTE_G3H, 500, NOTE_C4, 500,
NOTE_C4H, 500, NOTE_G4, 500, NOTE_G4H, 500, NOTE_C5, 500, NOTE_C5H, 500, NOTE_G5, 500,
NOTE_G5H, 500, NOTE_C6, 500, NOTE_C6H, 500, NOTE_G6, 500, NOTE_G6H, 500, NOTE_C7, 500,
NOTE_C7H, 500, NOTE_G7, 500, NOTE_G7H, 500, NOTE_C8, 500, NOTE_C8H, 500, NOTE_G8, 500,
NOTE_G8H, 500, NOTE_C9, 500, NOTE_C9H, 500, NOTE_G9, 500, NOTE_G9H, 500, TONES_END,
];
static mut circle_pos: i16 = 7;
const BUTTON_DELAY: u32 = 200;
// The setup() function runs once when you turn your Arduboy on
#[no_mangle]
pub unsafe extern "C" fn setup() {
// put your setup code here, to run once:
arduboy.begin();
}
// The loop() function repeats forever after setup() is done
#[no_mangle]
#[export_name = "loop"]
pub unsafe extern "C" fn loop_() {
let mut in_ram: [u16; 43] = [
NOTE_E4,
400,
NOTE_D4,
200,
NOTE_C4,
400,
NOTE_REST,
200,
NOTE_D4,
200,
NOTE_C4,
300,
NOTE_REST,
100,
NOTE_C4,
300,
NOTE_REST,
100,
NOTE_E4,
300,
NOTE_REST,
100,
NOTE_G4,
300,
NOTE_REST,
100,
NOTE_F4,
300,
NOTE_REST,
100,
NOTE_A4,
300,
NOTE_REST,
100,
NOTE_D5H,
200,
NOTE_REST,
200,
NOTE_D5H,
200,
NOTE_REST,
1500,
TONES_REPEAT,
];
// put your main code here, to run repeatedly:
let mut new_notes: bool;
display_audio();
loop {
move_circle();
if arduboy.pressed(UP) {
arduboy.audio_on();
display_audio();
}
if arduboy.pressed(DOWN) {
arduboy.audio_off();
display_audio();
}
if arduboy.pressed(B) {
delay(BUTTON_DELAY);
break;
}
}
sound.tone(1000, 0);
arduboy.clear();
arduboy.print("tone(1000)\n\nB: no_tone()\n delay(1000)\n break\0");
while sound.playing() {
move_circle();
if arduboy.pressed(B_BUTTON) {
sound.no_tone();
delay(1000);
break;
}
}
sound.tone(500, 4000);
arduboy.clear();
arduboy.print("tone(500, 4000)\n\nB: break\0");
while sound.playing() {
move_circle();
if arduboy.pressed(B_BUTTON) {
delay(BUTTON_DELAY);
break;
}
}
sound.tone2(NOTE_C4, 500, NOTE_C5H, 5000);
arduboy.clear();
arduboy.print("tone(C4,500,C5H,5000)\n\nB: no_tone(), break\0");
while sound.playing() {
move_circle();
if arduboy.pressed(B_BUTTON) {
sound.no_tone();
delay(BUTTON_DELAY);
break;
}
}
sound.tone3(NOTE_C7H, 500, NOTE_REST, 1000, NOTE_C6, 5000);
arduboy.clear();
arduboy.print("tone(C7H,500,\n REST,1000,\n C6,6000)\n\nB: no_tone(), break\0");
while sound.playing() {
move_circle();
if arduboy.pressed(B_BUTTON) {
sound.no_tone();
delay(BUTTON_DELAY);
break;
}
}
sound.tones(get_tones_addr!(allNotes));
arduboy.clear();
arduboy.print("tones(allNotes)\n\nA: no_tone(), again\nUP: again\nB: break\0");
while sound.playing() {
move_circle();
if arduboy.pressed(A_BUTTON) {
sound.no_tone();
sound.tones(get_tones_addr!(allNotes));
}
if arduboy.pressed(UP_BUTTON) {
sound.tones(get_tones_addr!(allNotes));
}
if arduboy.pressed(B_BUTTON) {
delay(BUTTON_DELAY);
break;
}
}
new_notes = false;
sound.tones_in_ram(get_tones_addr!(in_ram) as *mut u32);
arduboy.clear();
arduboy.print("tonesInRAM(inRAM)\n\nA: change notes\nB: break\0");
while sound.playing() {
move_circle();
if arduboy.pressed(A_BUTTON) {
new_notes = !new_notes;
if new_notes {
in_ram[34] = in_ram[38];
in_ram[38] = NOTE_C5H;
} else {
in_ram[34] = in_ram[38];
in_ram[38] = NOTE_D5H;
}
delay(BUTTON_DELAY);
}
if arduboy.pressed(B) {
delay(BUTTON_DELAY);
break;
}
}
sound.tones(get_tones_addr!(sound1));
arduboy.clear();
arduboy.print("volume_mode(IN_TONES)\ntones(sound1)\n\nB: break\0");
while sound.playing() {
move_circle();
if arduboy.pressed(B) {
delay(BUTTON_DELAY);
break;
}
}
sound.volume_mode(VOLUME_ALWAYS_NORMAL);
sound.tones(get_tones_addr!(sound1));
arduboy.clear();
arduboy.print("volume_mode(NORMAL)\ntones(sound1)\n\nB: no_tone(), break\0");
while sound.playing() {
move_circle();
if arduboy.pressed(B) {
sound.no_tone();
delay(BUTTON_DELAY);
break;
}
}
sound.volume_mode(VOLUME_ALWAYS_HIGH);
sound.tones(get_tones_addr!(sound1));
arduboy.clear();
arduboy.print("volume_mode(HIGH)\ntones(sound1)\n\nB: break\0");
while sound.playing() {
move_circle();
if arduboy.pressed(B) {
delay(BUTTON_DELAY);
break;
}
}
sound.volume_mode(VOLUME_IN_TONE);
}
fn move_circle() {
unsafe {
arduboy.fill_circle(circle_pos, 54, 7, Color::Black);
circle_pos += 8;
if circle_pos > 119 {
circle_pos = 7;
}
arduboy.fill_circle(circle_pos, 54, 7, Color::White);
}
arduboy.display();
delay(100);
}
fn display_audio() {
arduboy.clear();
arduboy.print("Audio enabled: \0");
if arduboy.audio_enabled() {
arduboy.print("YES\0");
} else {
arduboy.print("NO\0")
}
arduboy.print("\n\nUP: enable\nDOWN: disable\nB: break\0");
arduboy.invert(!arduboy.audio_enabled());
}

12
Examples/pong/Cargo.toml Normal file
View file

@ -0,0 +1,12 @@
[package]
name = "pong"
version = "0.1.0"
authors = ["Brian Bowman <seeker14491@gmail.com>"]
license = "MIT OR Apache-2.0"
edition = "2021"
[lib]
crate-type = ["staticlib"]
[dependencies]
arduboy-rust = "1.0.0"

230
Examples/pong/src/lib.rs Normal file
View file

@ -0,0 +1,230 @@
#![no_std]
use arduboy_rust::prelude::*;
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Ord, PartialOrd)]
enum GameState {
Title,
Gameplay,
Win,
Lose,
}
struct Ball {
x: i16,
y: i16,
size: u8,
right: bool,
down: bool,
}
impl Ball {
unsafe fn draw(&self) {
arduboy.fill_rect(self.x.into(), self.y.into(), self.size, self.size, Color::White);
}
}
struct Paddle {
x: i16,
y: i16,
width: u8,
height: u8,
}
impl Paddle {
unsafe fn draw(&self) {
arduboy.fill_rect(self.x.into(), self.y.into(), self.width, self.height, Color::White);
}
}
static mut G: Globals = Globals {
game_state: GameState::Title,
player_score: 0,
ai_score: 0,
ball: Ball {
x: 62,
y: 1,
size: 4,
right: true,
down: true,
},
player: Paddle {
x: 0,
y: 50,
width: 2,
height: 12,
},
ai: Paddle {
x: (WIDTH - 4) as i16,
y: 50,
width: 2,
height: 12,
},
};
struct Globals {
game_state: GameState,
player_score: u8,
ai_score: u8,
ball: Ball,
player: Paddle,
ai: Paddle,
}
#[no_mangle]
pub unsafe extern "C" fn setup() {
arduboy.begin();
arduboy.init_random_seed();
arduboy.set_frame_rate(60);
}
#[no_mangle]
#[export_name = "loop"]
pub unsafe extern "C" fn loop_() {
if !arduboy.next_frame() {
return;
}
arduboy.poll_buttons();
arduboy.clear();
match G.game_state {
GameState::Title => {
arduboy.set_cursor(52, 10);
arduboy.print(&b"PONG\0"[..]);
arduboy.set_cursor(16, 22);
arduboy.print(&b"Press A to start\0"[..]);
if A.just_pressed() {
G.game_state = GameState::Gameplay;
}
}
GameState::Gameplay => {
gameplay();
if A.just_pressed() {
reset_game();
}
}
GameState::Win => {
arduboy.set_cursor(40, 10);
arduboy.print(&b"You Win!\0"[..]);
if A.just_pressed() {
reset_game();
}
}
GameState::Lose => {
arduboy.set_cursor(37, 10);
arduboy.print(&b"Game Over\0"[..]);
if A.just_pressed() {
reset_game();
}
}
}
arduboy.display();
}
unsafe fn reset_game() {
G.game_state = GameState::Title;
G.ball.x = (WIDTH / 2) as i16;
G.player_score = 0;
G.ai_score = 0;
}
unsafe fn gameplay() {
//
// Player movement
//
if UP.pressed() && G.player.y > 0 {
G.player.y -= 1;
}
if DOWN.pressed() && G.player.y + (G.player.height as i16) < (HEIGHT - 1) as i16 {
G.player.y += 1;
}
//
// AI movement
//
if G.ball.x > 115 || random_between(0, 20) == 0 {
if G.ball.y < G.ai.y {
G.ai.y -= 1;
} else if G.ball.y + (G.ball.size as i16) > G.ai.y + G.ai.height as i16 {
G.ai.y += 1;
}
}
//
// Ball movement
//
if G.ball.y == 1 {
G.ball.down = true;
} else if G.ball.y + G.ball.size as i16 == (HEIGHT - 1) as i16 {
G.ball.down = false;
}
if G.ball.x == G.player.x + G.player.width as i16
&& G.ball.y + G.ball.size as i16 > G.player.y
&& G.ball.y < G.player.y + G.player.height as i16
{
G.ball.right = true;
}
if G.ball.x + G.ball.size as i16 == G.ai.x
&& G.ball.y + G.ball.size as i16 > G.ai.y
&& G.ball.y < G.ai.y + G.ai.height as i16
{
G.ball.right = false;
}
if G.ball.right {
G.ball.x += 1;
} else {
G.ball.x -= 1;
}
if G.ball.down {
G.ball.y += 1;
} else {
G.ball.y -= 1;
}
//
//
// Scoring
if G.ball.x + G.ball.size as i16 == -10 {
G.ai_score += 1;
G.ball.x = (WIDTH / 2) as i16;
G.ball.right = true;
} else if G.ball.x == (WIDTH + 10) as i16 {
G.player_score += 1;
G.ball.x = (WIDTH / 2) as i16;
G.ball.right = false;
}
if G.player_score == 5 {
G.game_state = GameState::Win;
} else if G.ai_score == 5 {
G.game_state = GameState::Lose;
}
//
// Drawing
//
arduboy.set_cursor(20, 2);
arduboy.print(G.player_score as u16);
arduboy.set_cursor(101, 2);
arduboy.print(G.ai_score as u16);
arduboy.draw_fast_hline(0, 0, WIDTH, Color::White);
arduboy.draw_fast_hline(0, (HEIGHT - 1) as i16, WIDTH, Color::White);
G.player.draw();
G.ai.draw();
G.ball.draw();
}

View file

@ -0,0 +1,10 @@
[package]
name = "rustacean"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["staticlib"]
[dependencies]
arduboy-rust = "1.0.0"

View file

@ -0,0 +1,74 @@
#![no_std]
#![feature(c_size_t)]
use arduboy_rust::prelude::*;
const BOTTOM: u8 = 64;
const RIGHT_END: u8 = 128;
const CHAR_WIDTH: u8 = 6;
const CHAR_HEIGHT: u8 = 8;
const MSG: &str = " I'm now a \0";
const MSG2: &str = "Rustacean <3\0";
struct Environment {
x: u8,
y: u8,
msg_len: u8,
}
impl Environment {
unsafe fn setup(&mut self) {
arduboy.begin();
arduboy.set_frame_rate(60);
let msg_len = MSG.len();
debug_assert!(msg_len <= (core::u8::MAX as c_size_t));
self.msg_len = msg_len as u8;
}
unsafe fn loop_(&mut self) {
if !arduboy.next_frame() {
return;
}
if UP.pressed() && self.y > 0 {
self.y -= 1;
}
if RIGHT.pressed() && self.x < RIGHT_END - CHAR_WIDTH * self.msg_len {
self.x += 1;
}
if LEFT.pressed() && self.x > 0 {
self.x -= 1;
}
if DOWN.pressed() && self.y < BOTTOM - CHAR_HEIGHT * 2 {
self.y += 1;
}
if (A | B).pressed() {
sound.tone(0xff, 0x3f);
}
arduboy.clear();
arduboy.set_cursor(self.x.into(), self.y.into());
arduboy.print(MSG);
arduboy.set_cursor(self.x.into(), (self.y + 9).into());
arduboy.print(MSG2);
arduboy.display();
}
}
static mut E: Environment = Environment {
x: 0,
y: 0,
msg_len: 0,
};
#[no_mangle]
pub unsafe extern "C" fn setup() {
E.setup();
}
#[no_mangle]
#[export_name = "loop"]
pub unsafe extern "C" fn loop_() {
E.loop_();
}

12
Examples/snake/Cargo.toml Normal file
View file

@ -0,0 +1,12 @@
[package]
name = "snake"
version = "0.1.0"
authors = ["ZennDev <zenndev@protonmail.com>"]
license = "MIT OR Apache-2.0"
edition = "2021"
[lib]
crate-type = ["staticlib"]
[dependencies]
arduboy-rust = "1.0.0"

274
Examples/snake/src/lib.rs Normal file
View file

@ -0,0 +1,274 @@
#![no_std]
use arduboy_rust::prelude::*;
static mut MEM: u8 = 0;
static SCORE: EEPROM = EEPROM::new(100);
const WORLD_WIDTH: u8 = 32;
const WORLD_HEIGHT: u8 = 16;
const SCALE_FACTOR: u8 = 4;
#[allow(dead_code)]
enum State {
Title,
Game,
Win,
GameOver,
Reset,
Pause,
}
#[derive(PartialEq, Copy, Clone)]
enum Direction {
Up,
Left,
Down,
Right,
}
struct Snake {
game_state: State,
points: u8,
len: u8,
pos: [(u8, u8); 255 as usize],
next_food: (u8, u8),
delta_time: u8,
direction: Direction,
last_direction: Direction,
}
impl Snake {
fn movement(&mut self) {
for i in 0..(self.len - 1) as usize {
self.pos[i] = self.pos[i + 1];
}
let (x, y) = self.pos[(self.len - 1) as usize];
match self.direction {
Direction::Up => {
self.pos[(self.len - 1) as usize] = (x, y - 1);
}
Direction::Left => {
self.pos[(self.len - 1) as usize] = (x - 1, y);
}
Direction::Down => {
self.pos[(self.len - 1) as usize] = (x, y + 1);
}
Direction::Right => {
self.pos[(self.len - 1) as usize] = (x + 1, y);
}
}
self.last_direction = self.direction;
}
unsafe fn get_new_dir(&mut self) {
if UP.just_pressed() && self.last_direction != Direction::Down {
self.direction = Direction::Up
}
if LEFT.just_pressed() && self.last_direction != Direction::Right {
self.direction = Direction::Left
}
if DOWN.just_pressed() && self.last_direction != Direction::Up {
self.direction = Direction::Down
}
if RIGHT.just_pressed() && self.last_direction != Direction::Left {
self.direction = Direction::Right
}
}
fn new_food(&mut self) {
self.next_food.0 = 0;
self.next_food.1 = 0;
while self.next_food.0 == 0 && self.next_food.1 == 0 {
self.next_food.0 = random_between(2, (WORLD_WIDTH - 2).into()) as u8;
self.next_food.1 = random_between(2, (WORLD_HEIGHT - 2).into()) as u8;
for i in 0..(self.len) as usize {
if self.pos[i] == self.next_food {
self.next_food.0 = 0;
self.next_food.1 = 0;
}
}
}
}
unsafe fn render(&self) {
arduboy.draw_circle(
((self.next_food.0 * SCALE_FACTOR) + SCALE_FACTOR / 4)
.try_into()
.unwrap(),
((self.next_food.1 * SCALE_FACTOR) + SCALE_FACTOR / 4)
.try_into()
.unwrap(),
SCALE_FACTOR / 4,
Color::White,
);
self.pos.iter().enumerate().for_each(|(i, p)| {
if i == (self.len) as usize {
return;
}
if *p == (0, 0) {
return;
}
arduboy.fill_rect(
(p.0 as u8 * SCALE_FACTOR).try_into().unwrap(),
(p.1 as u8 * SCALE_FACTOR).try_into().unwrap(),
SCALE_FACTOR / 2,
SCALE_FACTOR / 2,
Color::White,
);
});
}
unsafe fn init(&mut self) {
self.points = 0;
self.len = 3;
self.direction = Direction::Right;
self.last_direction = Direction::Left;
self.pos = [(0, 0); 255 as usize];
self.pos[0] = (3, 4);
self.pos[1] = (4, 4);
self.pos[2] = (5, 4);
}
unsafe fn boarder(&self) {
for x in 0..WORLD_WIDTH as usize {
for y in 0..WORLD_HEIGHT as usize {
if x == 0
|| y == 0
|| x == (WORLD_WIDTH - 1) as usize
|| y == (WORLD_HEIGHT - 1) as usize
{
let scale: u8 = 2;
if self.delta_time % 20 == 0 {
//scale = 1;
};
arduboy.fill_rect(
(x as u8 * SCALE_FACTOR + scale / 2).try_into().unwrap(),
(y as u8 * SCALE_FACTOR + scale / 2).try_into().unwrap(),
SCALE_FACTOR / scale,
SCALE_FACTOR / scale,
Color::White,
);
}
}
}
}
fn collision_check(&mut self) {
let (x, y) = self.pos[(self.len - 1) as usize];
if x == 0 || x == 31 || y == 0 || y == 15 {
self.game_state = State::GameOver;
}
self.pos.iter().enumerate().for_each(|(i, p)| {
if p == &(x, y) && i != (self.len - 1) as usize {
self.game_state = State::GameOver;
}
});
if self.pos[(self.len - 1) as usize] == self.next_food {
self.points += 1;
self.new_food();
self.pos[self.len as usize] = self.pos[(self.len - 1) as usize];
self.len += 1;
sound.tone(0xff, 0x3f);
}
}
}
#[allow(non_upper_case_globals)]
static mut snake: Snake = Snake {
game_state: State::Reset,
len: 3,
points: 0,
pos: [(0, 0); 255 as usize],
next_food: (0, 0),
delta_time: 0,
direction: Direction::Right,
last_direction: Direction::Left,
};
#[no_mangle]
pub unsafe extern "C" fn setup() {
arduboy.begin();
SCORE.init();
arduboy.init_random_seed();
arduboy.set_frame_rate(60);
arduboy.clear();
}
#[no_mangle]
#[export_name = "loop"]
pub unsafe extern "C" fn loop_() {
if !arduboy.next_frame() {
return;
}
arduboy.poll_buttons();
arduboy.clear();
match snake.game_state {
State::Reset => {
snake.init();
snake.new_food();
snake.game_state = State::Title;
}
State::Title => {
arduboy.set_cursor(0, 0);
arduboy.set_text_size(2);
arduboy.print(&b"RustySnake\n\0"[..]);
arduboy.set_text_size(1);
arduboy.print(&b"\nControls: \nB for Pause\nA&B for reset\n\0"[..]);
arduboy.print(&b"\nZennDev 2023\n\0"[..]);
if A.just_pressed() {
snake.game_state = State::Game;
}
}
State::Game => {
snake.get_new_dir();
if snake.delta_time % 10 == 0 {
snake.movement();
snake.collision_check();
};
snake.render();
snake.boarder();
if B.just_pressed() {
sound.tone(800, 100);
snake.game_state = State::Pause;
}
}
State::Win => (),
State::Pause => {
let msg = &b"[ Break ]\0"[..];
let l = msg.len() as u8 * FONT_SIZE / 2;
arduboy.set_cursor(
((WIDTH / 2) as u16 - l as u16).try_into().unwrap(),
((HEIGHT / 2) as u16).try_into().unwrap(),
);
snake.render();
snake.boarder();
arduboy.print(msg);
if B.just_pressed() {
snake.game_state = State::Game;
sound.tone(800, 100);
}
}
State::GameOver => {
SCORE.get(&mut MEM);
if MEM == 255 {
MEM = 0;
}
if snake.points > MEM {
SCORE.put(snake.points);
}
arduboy.set_cursor(0, 0);
arduboy.print(&b"Game Over!\0"[..]);
arduboy.print(&b"\n\n\0"[..]);
arduboy.print(&b"Score: \0"[..]);
arduboy.print(snake.points as u16);
arduboy.print(&b"\nHigh Score: \0"[..]);
arduboy.print(MEM as u16);
arduboy.print(&b"\n\n\0"[..]);
arduboy.print(&b"Press A to Play Again\0"[..]);
if A.just_pressed() {
snake.game_state = State::Reset;
}
}
}
if (A | B).pressed() {
snake.game_state = State::Reset;
}
arduboy.display();
if snake.delta_time == 60 {
snake.delta_time = 1
} else {
snake.delta_time += 1;
}
}

199
LICENSE-APACHE Normal file
View file

@ -0,0 +1,199 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

19
LICENSE-MIT Normal file
View file

@ -0,0 +1,19 @@
MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

10
Project/game/Cargo.toml Normal file
View file

@ -0,0 +1,10 @@
[package]
name = "game"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["staticlib"]
[dependencies]
arduboy-rust = "1.0.0"

20
Project/game/src/lib.rs Normal file
View file

@ -0,0 +1,20 @@
#![no_std]
#![allow(non_upper_case_globals)]
//Include the Arduboy Library
//Initialize the arduboy object
#[allow(unused_imports)]
use arduboy_rust::prelude::*;
//#[link_section = ".progmem.data"]
// The setup() function runs once when you turn your Arduboy on
#[no_mangle]
pub unsafe extern "C" fn setup() {
// put your setup code here, to run once:
}
// The loop() function repeats forever after setup() is done
#[no_mangle]
#[export_name = "loop"]
pub unsafe extern "C" fn loop_() {
// put your main code here, to run repeatedly:
}

199
README.md Normal file
View file

@ -0,0 +1,199 @@
# Rust for Arduboy
Running Rust on the [Arduboy](https://arduboy.com/) miniature game system.
The most important first.
I didn't create this project from scratch, @Seeker14491 the legend has already done a lot in his old project [ArduboyRust](https://github.com/Seeker14491/ArduboyRust)
I just updated and completed the project.
### What do i mean by completed?
I provided all the important functions from the [Arduboy2](https://github.com/MLXXXp/Arduboy2) library in a safe Rust API.
Most of the Arduboy2 funktions can be called the same way like in C.
# How to use this Project
First clone the repo
```bash
git clone https://github.com/ZennDev1337/Rust-for-Arduboy
```
Install [PlatformIO Core](https://docs.platformio.org/en/latest/core/installation/methods/pypi.html) on your system.
I recommend the pip install if you don't want to configure a new path variable for pio.
Otherwise you will know how to do that.
The rust-analyzer will complain about a missing test crate to fix this
add the following rule to the lsp settings :
```json
{
"rust-analyzer.checkOnSave.allTargets": false
}
```
If your using Visual Studio Code: Create a folder named `.vscode` and a file named `settings.json` inside. Past the setting above in the new file. (I have excluded my `.vscode` folder because I have many different settings there that you don't need)
Your game is located in the Project/game folder. This is also the folder you are working in
Inside the game folder you will find a lib.rs file which contains the setup and loop function as you know it from a normal Arduboy C project.
You can use the following command to open the Rust doc of the arduboy_rust crate
```bash
cargo doc -p arduboy_rust --open
```
Most of the time you will use the prelude.
There is listed witch funktionality you will have.
And last but not least there are multiple examples inside of the Examples folder which shows you how to use the functions.
I will from time to time also upload my projects to the Example folder so you have as much ressurces as possible.
## Usage of the run tool
**Both run scripts** (only works if you use the given folder structure)
requirements:
- [PlatformIO Core](https://docs.platformio.org/en/latest/core/installation/methods/pypi.html) must be installed
- The Arduboy must be plugged in
- You are in the root directory of this project
All builded `.hex` files are saved inside of `Wrapper-Project/.pio/build/<GAMENAME>.hex` after you uploaded them to the Arduboy.
To upload your own game to the Arduboy use:
Linux:
```bash
./run
```
Windows:
```ps1
.\run.bat
```
## Play the examples
### Snake
To upload snake to the Arduboy use:
Linux:
```bash
./run snake
```
Windows:
```ps1
.\run.bat snake
```
### Pong
To upload pong to the Arduboy use:
Linux:
```bash
./run pong
```
Windows:
```ps1
.\run.bat pong
```
### I'm now a Rustacean <3
To upload rustacean to the Arduboy use:
Linux:
```bash
./run rustacean
```
Windows:
```ps1
.\run.bat rustacean
```
### The demo games / tutorials from the official Arduboy forum [Rewritten in Rust]
- [Make Your Own Arduboy Game: Part 1 - Setting Up Your Computer](https://community.arduboy.com/t/make-your-own-arduboy-game-part-1-setting-up-your-computer/7924/1)
- [demo2] [Make Your Own Arduboy Game: Part 2 - Printing Text](https://community.arduboy.com/t/make-your-own-arduboy-game-part-2-printing-text/7925)
- [demo3] [Make Your Own Arduboy Game: Part 3 - Storing Data & Loops](https://community.arduboy.com/t/make-your-own-arduboy-game-part-3-storing-data-loops/7926)
- [demo4] [Make Your Own Arduboy Game: Part 4 - Questions & Button Input](https://community.arduboy.com/t/make-your-own-arduboy-game-part-4-questions-button-input/7927)
- [demo5] [Make Your Own Arduboy Game: Part 5 - Your First Game!](https://community.arduboy.com/t/make-your-own-arduboy-game-part-5-your-first-game/7928)
- [demo6] [Make Your Own Arduboy Game: Part 6 - Graphics!](https://community.arduboy.com/t/make-your-own-arduboy-game-part-6-graphics/7929)
Link for the [arduboy-tile-converter](https://github.com/Team-ARG-Museum/arduboy-tile-converter)
- not done [demo7] [Make Your Own Arduboy Game: Part 7 - Make Pong From Scratch!](https://community.arduboy.com/t/make-your-own-arduboy-game-part-7-make-pong-from-scratch/7930)
- not done [demo8] [Make Your Own Arduboy Game: Part 8 - Starting DinoSmasher](https://community.arduboy.com/t/make-your-own-arduboy-game-part-8-starting-dinosmasher/7932)
- [eeprom] [Help, Im struggling with EEPROM!](https://community.arduboy.com/t/help-im-struggling-with-eeprom/7178)
- [tone] [ArduboyTonesTest](https://github.com/MLXXXp/ArduboyTones/blob/master/examples/ArduboyTonesTest/ArduboyTonesTest.ino)
To upload a demo to the Arduboy use:
Linux:
```bash
./run demo2
./run demo3
./run demo4
./run demo5
./run demo6
./run eeprom
./run tone
```
Windows:
```ps1
.\run.bat demo2
.\run.bat demo3
.\run.bat demo4
.\run.bat demo5
.\run.bat demo6
.\run.bat eeprom
.\run.bat tone
```
## Creating and building an Arduboy crate [Outdated]
You can find instructions on how all build steps work in detail here [ArduboyRust creating and building an arduboy crate](https://github.com/Seeker14491/ArduboyRust#creating-and-building-an-arduboy-crate)
## Linking the static library to the Arduino C++ project [Outdated]
Instructions on how to link all the static libraries in the Arduino C++ project can be found here [ArduboyRust linking the static library to the arduino c++ project](https://github.com/Seeker14491/ArduboyRust#linking-the-static-library-to-the-arduino-c-project)
## Credits
Thanks to @Seeker14491 who wrote [ArduboyRust](https://github.com/Seeker14491/ArduboyRust), the starting point for me to create my own project based on this project. (you are a hero <3)
Thanks to @simon-i1-h who wrote [arduboy-hello-rs](https://github.com/simon-i1-h/arduboy-hello-rs), the proof of concept that inspired me to try Rust on the Arduboy.
## License
You can license it under either one of those licenses:
- Apache License, Version 2.0
([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license
([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)
Whichever you may prefer.
## Contribution
Unless you explicitly state otherwise, any contribution intentionally submitted
for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

View file

@ -0,0 +1,39 @@
This directory is intended for project header files.
A header file is a file containing C declarations and macro definitions
to be shared between several project source files. You request the use of a
header file in your project source file (C, C++, etc) located in `src` folder
by including it, with the C preprocessing directive `#include'.
```src/main.c
#include "header.h"
int main (void)
{
...
}
```
Including a header file produces the same results as copying the header file
into each source file that needs it. Such copying would be time-consuming
and error-prone. With a header file, the related declarations appear
in only one place. If they need to be changed, they can be changed in one
place, and programs that include the header file will automatically use the
new version when next recompiled. The header file eliminates the labor of
finding and changing all the copies as well as the risk that a failure to
find one copy will result in inconsistencies within a program.
In C, the usual convention is to give header files names that end with `.h'.
It is most portable to use only letters, digits, dashes, and underscores in
header file names, and at most one dot.
Read more about using header files in official GCC documentation:
* Include Syntax
* Include Operation
* Once-Only Headers
* Computed Includes
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html

View file

@ -0,0 +1,46 @@
This directory is intended for project specific (private) libraries.
PlatformIO will compile them to static libraries and link into executable file.
The source code of each library should be placed in a an own separate directory
("lib/your_library_name/[here are source files]").
For example, see a structure of the following two libraries `Foo` and `Bar`:
|--lib
| |
| |--Bar
| | |--docs
| | |--examples
| | |--src
| | |- Bar.c
| | |- Bar.h
| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
| |
| |--Foo
| | |- Foo.c
| | |- Foo.h
| |
| |- README --> THIS FILE
|
|- platformio.ini
|--src
|- main.c
and a contents of `src/main.c`:
```
#include <Foo.h>
#include <Bar.h>
int main (void)
{
...
}
```
PlatformIO Library Dependency Finder will find automatically dependent
libraries scanning project source files.
More information about PlatformIO Library Dependency Finder
- https://docs.platformio.org/page/librarymanager/ldf.html

View file

@ -0,0 +1,21 @@
;PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:arduboy]
platform = atmelavr
board = arduboy
framework = arduino
build_flags =
-L lib -l libgame
lib_deps =
mlxxxp/Arduboy2@^6.0.0
ArduboyTones@^1.0.3

View file

@ -0,0 +1,123 @@
#include "arduboy.h"
extern Arduboy2 arduboy;
void arduboy_begin(void)
{
arduboy.begin();
}
void arduboy_clear(void)
{
arduboy.clear();
}
void arduboy_display(void)
{
arduboy.display();
}
void arduboy_display_and_clear_buffer(void)
{
arduboy.display(CLEAR_BUFFER);
}
void arduboy_draw_fast_hline(int16_t x, int16_t y, uint8_t w, uint8_t color)
{
arduboy.drawFastHLine(x, y, w, color);
}
void arduboy_draw_fast_vline(int16_t x, int16_t y, uint8_t h, uint8_t color)
{
arduboy.drawFastVLine(x, y, h, color);
}
void arduboy_draw_pixel(int16_t x, int16_t y, uint8_t color)
{
arduboy.drawPixel(x, y, color);
}
void arduboy_draw_circle(int16_t x, int16_t y, uint8_t r, uint8_t color)
{
arduboy.drawCircle(x, y, r, color);
}
void arduboy_fill_circle(int16_t x, int16_t y, uint8_t r, uint8_t color)
{
arduboy.fillCircle(x, y, r, color);
}
void arduboy_fill_rect(int16_t x, int16_t y, uint8_t w, uint8_t h, uint8_t color)
{
arduboy.fillRect(x, y, w, h, color);
}
unsigned long arduboy_generate_random_seed()
{
return arduboy.generateRandomSeed();
}
uint8_t arduboy_get_pixel(uint8_t x, uint8_t y)
{
return arduboy.getPixel(x, y);
}
void arduboy_init_random_seed(void)
{
arduboy.initRandomSeed();
}
bool arduboy_just_pressed(uint8_t button)
{
return arduboy.justPressed(button);
}
bool arduboy_just_released(uint8_t button)
{
return arduboy.justReleased(button);
}
bool arduboy_next_frame(void)
{
return arduboy.nextFrame();
}
void arduboy_poll_buttons()
{
arduboy.pollButtons();
}
bool arduboy_pressed(uint8_t buttons)
{
return arduboy.pressed(buttons);
}
void arduboy_print_chars(const char *cstr)
{
arduboy.print(cstr);
}
size_t arduboy_print_char(char c)
{
return arduboy.print(c);
}
size_t arduboy_print_int(int n, int base)
{
return arduboy.print(n, base);
}
size_t arduboy_print_long(long n, int base)
{
return arduboy.print(n, base);
}
size_t arduboy_print_unsigned_char(unsigned char n, int base)
{
return arduboy.print(n, base);
}
size_t arduboy_print_unsigned_int(unsigned int n, int base)
{
return arduboy.print(n, base);
}
size_t arduboy_print_unsigned_long(unsigned long n, int base)
{
return arduboy.print(n, base);
}
void arduboy_set_cursor(int16_t x, int16_t y)
{
arduboy.setCursor(x, y);
}
void arduboy_set_frame_rate(uint8_t rate)
{
arduboy.setFrameRate(rate);
}
bool arduboy_not_pressed(uint8_t button)
{
arduboy.notPressed(button);
}
void arduboy_set_text_size(uint8_t s)
{
arduboy.setTextSize(s);
}
void arduboy_invert(bool inverse)
{
arduboy.invert(inverse);
}

View file

@ -0,0 +1,36 @@
#pragma once
#include <Arduboy2.h>
extern "C"
{
void arduboy_begin(void);
void arduboy_clear(void);
void arduboy_display(void);
void arduboy_display_and_clear_buffer(void);
void arduboy_draw_fast_hline(int16_t x, int16_t y, uint8_t w, uint8_t color);
void arduboy_draw_fast_vline(int16_t x, int16_t y, uint8_t h, uint8_t color);
void arduboy_draw_pixel(int16_t x, int16_t y, uint8_t color);
void arduboy_draw_circle(int16_t x, int16_t y, uint8_t r, uint8_t color);
void arduboy_fill_circle(int16_t x, int16_t y, uint8_t r, uint8_t color);
void arduboy_fill_rect(int16_t x, int16_t y, uint8_t w, uint8_t h, uint8_t color);
unsigned long arduboy_generate_random_seed();
uint8_t arduboy_get_pixel(uint8_t x, uint8_t y);
void arduboy_init_random_seed(void);
bool arduboy_just_pressed(uint8_t button);
bool arduboy_just_released(uint8_t button);
bool arduboy_next_frame(void);
void arduboy_poll_buttons();
bool arduboy_pressed(uint8_t buttons);
void arduboy_print_chars(const char *cstr);
size_t arduboy_print_char(char c);
size_t arduboy_print_int(int n, int base);
size_t arduboy_print_long(long n, int base);
size_t arduboy_print_unsigned_char(unsigned char n, int base);
size_t arduboy_print_unsigned_int(unsigned int n, int base);
size_t arduboy_print_unsigned_long(unsigned long n, int base);
void arduboy_set_cursor(int16_t x, int16_t y);
void arduboy_set_frame_rate(uint8_t rate);
bool arduboy_not_pressed(uint8_t button);
void arduboy_set_text_size(uint8_t s);
void arduboy_invert(bool inverse);
}

View file

@ -0,0 +1,46 @@
#include "arduboy_tones.h"
void arduboy_audio_on()
{
arduboy.audio.on();
}
void arduboy_audio_off()
{
arduboy.audio.off();
}
bool arduboy_audio_enabled()
{
return arduboy.audio.enabled();
}
void sound_tone(unsigned int frequency, unsigned long duration)
{
sound.tone(frequency, duration);
}
void sound_tone2(unsigned int frequency1, unsigned long duration1, unsigned int frequency2, unsigned long duration2)
{
sound.tone(frequency1, duration1, frequency2, duration2);
}
void sound_tone3(unsigned int frequency1, unsigned long duration1, unsigned int frequency2, unsigned long duration2, unsigned int frequency3, unsigned long duration3)
{
sound.tone(frequency1, duration1, frequency2, duration2, frequency3, duration3);
}
void sound_tones(const uint16_t *tones)
{
sound.tones(tones);
}
void sound_no_tone()
{
sound.noTone();
}
bool sound_playing()
{
sound.playing();
}
void sound_tones_in_ram(uint16_t *tones)
{
sound.tonesInRAM(tones);
}
void sound_volume_mode(uint8_t mode)
{
sound.volumeMode(mode);
}

View file

@ -0,0 +1,21 @@
#pragma once
#include <ArduboyTones.h>
#include <Arduboy2.h>
extern ArduboyTones sound;
extern Arduboy2 arduboy;
extern "C"
{
void arduboy_audio_on();
void arduboy_audio_off();
bool arduboy_audio_enabled();
void sound_tone(unsigned int frequency, unsigned long duration);
void sound_tone2(unsigned int frequency1, unsigned long duration1, unsigned int frequency2, unsigned long duration2);
void sound_tone3(unsigned int frequency1, unsigned long duration1, unsigned int frequency2, unsigned long duration2, unsigned int frequency3, unsigned long duration3);
void sound_tones(const uint16_t *tones);
void sound_no_tone();
bool sound_playing();
void sound_tones_in_ram(uint16_t *tones);
void sound_volume_mode(uint8_t mode);
}

View file

@ -0,0 +1,6 @@
#include "sprites.h"
void arduino_draw_override(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t frame)
{
Sprites::drawOverwrite(x, y, bitmap, frame);
}

View file

@ -0,0 +1,7 @@
#pragma once
#include <Sprites.h>
extern "C"
{
void arduino_draw_override(int16_t x, int16_t y, const uint8_t *bitmap, uint8_t frame);
}

View file

@ -0,0 +1,14 @@
#include "arduino.h"
long arduino_random_between(long min, long max)
{
return random(min, max);
}
long arduino_random_less_than(long max)
{
return random(max);
}
void arduino_delay(unsigned long ms)
{
delay(ms);
}

View file

@ -0,0 +1,9 @@
#pragma once
#include <Arduboy2.h>
extern "C"
{
long arduino_random_between(long min, long max);
long arduino_random_less_than(long max);
void arduino_delay(unsigned long ms);
}

View file

@ -0,0 +1,26 @@
#include "eeprom.h"
int eeprom;
uint8_t arduboy_eeprom_read(int idx)
{
eeprom = EEPROM.read(idx);
return eeprom;
}
void arduboy_eeprom_update(int idx, uint8_t val)
{
EEPROM.update(idx, val);
}
void arduboy_eeprom_write(int idx, uint8_t val)
{
EEPROM.write(idx, val);
}
uint8_t arduboy_eeprom_get(int idx)
{
EEPROM.get(idx, eeprom);
return eeprom;
}
void arduboy_eeprom_put(int idx, uint8_t val)
{
EEPROM.put(idx, val);
}

View file

@ -0,0 +1,12 @@
#pragma once
#include <EEPROM.h>
extern "C"
{
uint8_t arduboy_eeprom_read(int idx);
void arduboy_eeprom_update(int idx, uint8_t val);
void arduboy_eeprom_write(int idx, uint8_t val);
uint8_t arduboy_eeprom_get(int idx);
void arduboy_eeprom_put(int idx, uint8_t val);
}

View file

@ -0,0 +1,4 @@
#include "main.h"
Arduboy2 arduboy;
ArduboyTones sound(arduboy.audio.enabled);

View file

@ -0,0 +1,9 @@
#pragma once
#include <Arduboy2.h>
#include <ArduboyTones.h>
#include "./library/arduboy/arduboy.h"
#include "./library/arduboy/sprites.h"
#include "./library/arduboy/arduboy_tones.h"
#include "./library/arduino/arduino.h"
#include "./library/arduino/eeprom.h"

View file

@ -0,0 +1,11 @@
This directory is intended for PIO Unit Testing and project tests.
Unit Testing is a software testing method by which individual units of
source code, sets of one or more MCU program modules together with associated
control data, usage procedures, and operating procedures, are tested to
determine whether they are fit for use. Unit testing finds problems early
in the development cycle.
More information about PIO Unit Testing:
- https://docs.platformio.org/page/plus/unit-testing.html

27
arduboy.json Normal file
View file

@ -0,0 +1,27 @@
{
"arch": "avr",
"atomic-cas": false,
"cpu": "atmega32u4",
"data-layout": "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8",
"eh-frame-header": false,
"exe-suffix": ".elf",
"executables": true,
"late-link-args": {
"gcc": [
"-lgcc"
]
},
"linker": "avr-gcc",
"linker-is-gnu": true,
"llvm-target": "avr-unknown-unknown",
"max-atomic-width": 8,
"no-default-libraries": false,
"pre-link-args": {
"gcc": [
"-mmcu=atmega32u4",
"-Wl,--as-needed"
]
},
"target-c-int-width": "16",
"target-pointer-width": "16"
}

41
run Executable file
View file

@ -0,0 +1,41 @@
#!/bin/bash
option=$1
if [ -z "$option" ]
then
cargo build -p game --release && cp ./target/arduboy/release/libgame.a ./Wrapper-Project/lib/libgame.a && cd Wrapper-Project/ && pio run -t upload && cp ./.pio/build/arduboy/firmware.hex ./.pio/build/game.hex && pio run -t clean && rm lib/libgame.a && cd ..
elif [ "$option" = "snake" ]
then
cargo build -p snake --release && cp ./target/arduboy/release/libsnake.a ./Wrapper-Project/lib/libgame.a && cd Wrapper-Project/ && pio run -t upload && cp ./.pio/build/arduboy/firmware.hex ./.pio/build/snake.hex && pio run -t clean && rm lib/libgame.a && cd ..
elif [ "$option" = "pong" ]
then
cargo build -p pong --release && cp ./target/arduboy/release/libpong.a ./Wrapper-Project/lib/libgame.a && cd Wrapper-Project/ && pio run -t upload && cp ./.pio/build/arduboy/firmware.hex ./.pio/build/pong.hex && pio run -t clean && rm lib/libgame.a && cd ..
elif [ "$option" = "rustacean" ]
then
cargo build -p rustacean --release && cp ./target/arduboy/release/librustacean.a ./Wrapper-Project/lib/libgame.a && cd Wrapper-Project/ && pio run -t upload && cp ./.pio/build/arduboy/firmware.hex ./.pio/build/rustacean.hex && pio run -t clean && rm lib/libgame.a && cd ..
elif [ "$option" = "tone" ]
then
cargo build -p tone --release && cp ./target/arduboy/release/libtone.a ./Wrapper-Project/lib/libgame.a && cd Wrapper-Project/ && pio run -t upload && cp ./.pio/build/arduboy/firmware.hex ./.pio/build/tone.hex && pio run -t clean && rm lib/libgame.a && cd ..
elif [ "$option" = "eeprom" ]
then
cargo build -p eeprom-demo --release && cp ./target/arduboy/release/libeeprom_demo.a ./Wrapper-Project/lib/libgame.a && cd Wrapper-Project/ && pio run -t upload && cp ./.pio/build/arduboy/firmware.hex ./.pio/build/eeprom.hex && pio run -t clean && rm lib/libgame.a && cd ..
elif [ "$option" = "demo2" ]
then
cargo build -p demo2 --release && cp ./target/arduboy/release/libdemo2.a ./Wrapper-Project/lib/libgame.a && cd Wrapper-Project/ && pio run -t upload && cp ./.pio/build/arduboy/firmware.hex ./.pio/build/demo2.hex && pio run -t clean && rm lib/libgame.a && cd ..
elif [ "$option" = "demo3" ]
then
cargo build -p demo3 --release && cp ./target/arduboy/release/libdemo3.a ./Wrapper-Project/lib/libgame.a && cd Wrapper-Project/ && pio run -t upload && cp ./.pio/build/arduboy/firmware.hex ./.pio/build/demo3.hex && pio run -t clean && rm lib/libgame.a && cd ..
elif [ "$option" = "demo4" ]
then
cargo build -p demo4 --release && cp ./target/arduboy/release/libdemo4.a ./Wrapper-Project/lib/libgame.a && cd Wrapper-Project/ && pio run -t upload && cp ./.pio/build/arduboy/firmware.hex ./.pio/build/demo4.hex && pio run -t clean && rm lib/libgame.a && cd ..
elif [ "$option" = "demo5" ]
then
cargo build -p demo5 --release && cp ./target/arduboy/release/libdemo5.a ./Wrapper-Project/lib/libgame.a && cd Wrapper-Project/ && pio run -t upload && cp ./.pio/build/arduboy/firmware.hex ./.pio/build/demo5.hex && pio run -t clean && rm lib/libgame.a && cd ..
elif [ "$option" = "demo6" ]
then
cargo build -p demo6 --release && cp ./target/arduboy/release/libdemo6.a ./Wrapper-Project/lib/libgame.a && cd Wrapper-Project/ && pio run -t upload && cp ./.pio/build/arduboy/firmware.hex ./.pio/build/demo6.hex && pio run -t clean && rm lib/libgame.a && cd ..
else
echo Usage: for uploading your game \|./run.sh
echo Usage: for uploading an example game \| ./run.sh \<Example Game\>
fi

43
run.bat Normal file
View file

@ -0,0 +1,43 @@
@echo off
set option=%1
if [%option%]==[] (
powershell -Command "cargo build -p game --release; cp ./target/arduboy/release/libgame.a ./Wrapper-Project/lib/libgame.a; cd Wrapper-Project/; pio run -t upload; cp ./.pio/build/arduboy/firmware.hex ./.pio/build/game.hex; pio run -t clean; rm lib/libgame.a; cd .."
goto :eof
)
if %option%==snake (
powershell -Command "cargo build -p snake --release; cp ./target/arduboy/release/libsnake.a ./Wrapper-Project/lib/libgame.a; cd Wrapper-Project/; pio run -t upload; cp ./.pio/build/arduboy/firmware.hex ./.pio/build/snake.hex; pio run -t clean; rm lib/libgame.a; cd .."
goto :eof
) else if %option%==pong (
powershell -Command "cargo build -p pong --release; cp ./target/arduboy/release/libpong.a ./Wrapper-Project/lib/libgame.a; cd Wrapper-Project/; pio run -t upload; cp ./.pio/build/arduboy/firmware.hex ./.pio/build/pong.hex; pio run -t clean; rm lib/libgame.a; cd .."
goto :eof
) else if %option%==rustacean (
powershell -Command "cargo build -p rustacean --release; cp ./target/arduboy/release/librustacean.a ./Wrapper-Project/lib/libgame.a; cd Wrapper-Project/; cp ./.pio/build/arduboy/firmware.hex ./.pio/build/rustacean.hex; pio run -t upload; pio run -t clean; rm lib/libgame.a; cd .."
goto :eof
) else if %option%==tone (
powershell -Command "cargo build -p tone --release; cp ./target/arduboy/release/libtone.a ./Wrapper-Project/lib/libgame.a; cd Wrapper-Project/; pio run -t upload; cp ./.pio/build/arduboy/firmware.hex ./.pio/build/tone.hex; pio run -t clean; rm lib/libgame.a; cd .."
goto :eof
) else if %option%==eeprom (
powershell -Command "cargo build -p eeprom-demo --release; cp ./target/arduboy/release/libeeprom_demo.a ./Wrapper-Project/lib/libgame.a; cd Wrapper-Project/; pio run -t upload; cp ./.pio/build/arduboy/firmware.hex ./.pio/build/eeprom.hex; pio run -t clean; rm lib/libgame.a; cd .."
goto :eof
) else if %option%==demo2 (
powershell -Command "cargo build -p demo2 --release; cp ./target/arduboy/release/libdemo2.a ./Wrapper-Project/lib/libgame.a; cd Wrapper-Project/; pio run -t upload; cp ./.pio/build/arduboy/firmware.hex ./.pio/build/demo2.hex; pio run -t clean; rm lib/libgame.a; cd .."
goto :eof
) else if %option%==demo3 (
powershell -Command "cargo build -p demo3 --release; cp ./target/arduboy/release/libdemo3.a ./Wrapper-Project/lib/libgame.a; cd Wrapper-Project/; pio run -t upload; cp ./.pio/build/arduboy/firmware.hex ./.pio/build/demo3.hex; pio run -t clean; rm lib/libgame.a; cd .."
goto :eof
) else if %option%==demo4 (
powershell -Command "cargo build -p demo4 --release; cp ./target/arduboy/release/libdemo4.a ./Wrapper-Project/lib/libgame.a; cd Wrapper-Project/; pio run -t upload; cp ./.pio/build/arduboy/firmware.hex ./.pio/build/demo4.hex; pio run -t clean; rm lib/libgame.a; cd .."
goto :eof
) else if %option%==demo5 (
powershell -Command "cargo build -p demo5 --release; cp ./target/arduboy/release/libdemo5.a ./Wrapper-Project/lib/libgame.a; cd Wrapper-Project/; pio run -t upload; cp ./.pio/build/arduboy/firmware.hex ./.pio/build/demo5.hex; pio run -t clean; rm lib/libgame.a; cd .."
goto :eof
) else if %option%==demo6 (
powershell -Command "cargo build -p demo6 --release; cp ./target/arduboy/release/libdemo6.a ./Wrapper-Project/lib/libgame.a; cd Wrapper-Project/; pio run -t upload; cp ./.pio/build/arduboy/firmware.hex ./.pio/build/demo6.hex; pio run -t clean; rm lib/libgame.a; cd .."
goto :eof
)
@echo Usage: .\run.bat // for uploading your game
@echo Usage: .\run.bat ^<Example Game^> // for uploading an example game

4
rust-toolchain.toml Normal file
View file

@ -0,0 +1,4 @@
[toolchain]
# We need to pin to this old Rust version due to an LLVM bug: https://github.com/rust-lang/rust/issues/82104
channel = "nightly"
components = ["rust-src"]

5
rustfmt.toml Normal file
View file

@ -0,0 +1,5 @@
format_code_in_doc_comments = true
imports_granularity = "Module"
newline_style = "Unix"
use_field_init_shorthand = true
use_try_shorthand = true