diff --git a/.cargo/config.toml b/.cargo/config.toml index 22e7b31..6e55eef 100644 --- a/.cargo/config.toml +++ b/.cargo/config.toml @@ -1,7 +1,3 @@ -[target.thumbv7em-none-eabihf] -runner = 'npm exec --yes -- nwlink@0.0.19 install-nwa' -rustflags = ["-C", "link-arg=--relocatable", "-C", "link-arg=-no-gc-sections", "-C", "link-arg=-lstorage_c"] - [target.'cfg(target_os="macos")'] rustflags = [ "-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup", "-C", "link-arg=-lSystem" diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index 3949821..0000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,25 +0,0 @@ -name: Build -on: [pull_request, push] - -jobs: - build: - runs-on: ubuntu-latest - steps: - - name: Checkout code - uses: actions/checkout@v3 - - uses: carlosperate/arm-none-eabi-gcc-action@v1 - - name: Install nwlink - uses: actions/setup-node@v4 - with: - node-version: 22 - - run: npm install -g nwlink - - run: echo "$HOME/.npm-global/bin" >> $GITHUB_PATH - - name: Install Rust toolchain - uses: actions-rs/toolchain@v1 - with: - toolchain: nightly - target: thumbv7em-none-eabihf - - name: Install just - uses: extractions/setup-just@v3 - - name: Build app - run: just build diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml new file mode 100644 index 0000000..1504681 --- /dev/null +++ b/.github/workflows/check.yml @@ -0,0 +1,14 @@ +name: Full check +on: [pull_request] + +jobs: + build: + runs-on: ubuntu-latest + steps: + - name: Checkout code + uses: actions/checkout@v3 + - uses: carlosperate/arm-none-eabi-gcc-action@v1 + - name: Install dependencies + run: bash ./setup.sh <<< y + - name: Build app + run: just check diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 769d6f8..06d8a7e 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -25,7 +25,7 @@ jobs: - name: Install just uses: extractions/setup-just@v3 - name: Build app - run: just build + run: just build-epsilon - run: mv target/thumbv7em-none-eabihf/release/Numcraft target/thumbv7em-none-eabihf/release/Numcraft.nwa - uses: actions/upload-artifact@v4 with: diff --git a/.gitignore b/.gitignore index 352c047..8833c88 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,8 @@ /node_modules .DS_store /epsilon_simulator -/.vscode \ No newline at end of file +/.vscode +.venv +*.elf +*.icon +/icon.png \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml index aaf4ba5..e474a81 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,7 @@ name = "Numcraft" version = "0.1.5" authors = ["Yannis300307"] edition = "2024" +build="build/build.rs" [[bin]] name = "Numcraft" @@ -21,8 +22,10 @@ doctest = false bench = false [features] - +default = ["upsilon"] debug_ui = [] +upsilon = [] +epsilon = [] [profile.dev] panic="abort" diff --git a/build/LICENSE.txt b/build/LICENSE.txt new file mode 100644 index 0000000..72728e1 --- /dev/null +++ b/build/LICENSE.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2025 Damien Nicolet + +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. diff --git a/build/archive b/build/archive new file mode 100755 index 0000000..f78f592 --- /dev/null +++ b/build/archive @@ -0,0 +1,51 @@ +#!/usr/bin/env bash + +# MIT License + +# Copyright (c) 2025 Damien Nicolet + +# 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. + +set -e + +LD=arm-none-eabi-ld +OBJCOPY=arm-none-eabi-objcopy + +echo "Building archive..." +echo " - ld: $LD" +echo " - objcopy: $OBJCOPY" +echo " - arguments: $@" + +OUTPUT="$1" +rm -f "target/${OUTPUT}" +shift 1 + +POS=0 + +FILENAME="target/thumbv7em-none-eabihf/release/$1" +NAME="$1" +echo " - $FILENAME" +sed "s/\+ (0)/+ (${POS})/" build/external.ld > target/temp.ld +"${LD}" "$FILENAME" -o "target/${NAME}_linked.elf" -Ttarget/temp.ld +"${OBJCOPY}" -O binary "target/${NAME}_linked.elf" "target/${NAME}" +cd target +tar -rf "${OUTPUT}" "${NAME}" +cd .. +POS=$(( ${POS} + (($(stat --printf="%s" "target/${NAME}") + 1023)/512)*512 )) +rm -f target/temp.ld "target/${NAME}" "target/${NAME}_linked.elf" diff --git a/build.rs b/build/build.rs similarity index 94% rename from build.rs rename to build/build.rs index 0073f66..debf90c 100644 --- a/build.rs +++ b/build/build.rs @@ -36,7 +36,7 @@ fn compile_c_libs() { .expect("Invalid UTF-8 in nwlink flags"); let mut build = cc::Build::new(); - build.file("src/eadk/storage/storage.c"); + build.file("src/nadk/storage/storage.c"); build.flag("-std=c99"); build.flag("-Os"); build.flag("-Wall"); @@ -278,7 +278,16 @@ fn main() { // Compile storage.c if std::env::var("CARGO_CFG_TARGET_OS").unwrap() == "none" { - compile_c_libs(); + println!("cargo:rustc-link-arg=--relocatable"); + println!("cargo:rustc-link-arg=-no-gc-sections"); + + if std::env::var("CARGO_FEATURE_UPSILON").is_ok() { + println!("cargo:rustc-link-arg=-Ltarget/upsilon_api"); + println!("cargo:rustc-link-arg=-lapi"); + } else { + compile_c_libs(); + println!("cargo:rustc-link-arg=-lstorage_c"); + } } else { patch_simulator(); } diff --git a/build/external.ld b/build/external.ld new file mode 100644 index 0000000..2e79085 --- /dev/null +++ b/build/external.ld @@ -0,0 +1,53 @@ +MEMORY { + SRAM (rw) : ORIGIN = 0x00000000, LENGTH = 16K + FLASH (rx) : ORIGIN = 0x90200200 + (0), LENGTH = 6M +} + +SECTIONS { + .entrypoint ORIGIN(FLASH) : { + KEEP(*(.entrypoint)) + } >FLASH + + .init_array : { + . = ALIGN(4); + _init_array_start = .; + KEEP (*(.init_array*)) + _init_array_end = .; + } >FLASH + + .text : { + . = ALIGN(4); + *(.text) + *(.text.*) + } >FLASH + + .rodata : { + . = ALIGN(4); + *(.rodata) + *(.rodata.*) + } >FLASH + + .ARM.exidx : { + __exidx_start = .; +/* *(.ARM.exidx* .gnu.linkonce.armexidx.*) */ + __exidx_end = .; + } >FLASH + + .data : { + . = ALIGN(4); + _data_section_start_flash = LOADADDR(.data); + _data_section_start_ram = .; + *(.data) + *(.data.*) + _data_section_end_ram = .; + } >SRAM AT> FLASH + + .bss : { + . = ALIGN(4); + _bss_section_start_ram = .; + *(.bss) + *(.bss.*) + *(COMMON) + _bss_section_end_ram = .; + } >SRAM +} diff --git a/build/png2icon.py b/build/png2icon.py new file mode 100644 index 0000000..f479a9f --- /dev/null +++ b/build/png2icon.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python3 + +import sys +import argparse +import struct + +def error_exit(message, code): + print(message, file=sys.stderr) + sys.exit(code) + +try: + import png +except ImportError: + error_exit("You need pypng to run this script.\n Use `pip3 install pypng`", 1) + +try: + import lz4.block +except ImportError: + error_exit("You need lz4 to run this script.\n Use `pip3 install lz4`", 1) + + +def main(): + # Parse args. + parser = argparse.ArgumentParser() + parser.add_argument("input") + parser.add_argument("output") + args = parser.parse_args() + + with open(args.input, 'rb') as input_file: + r = png.Reader(file=input_file) + + width, height, rows, infos = r.asRGBA8() + + if width != 55 or height != 56: + error_exit("Icon must be 55x56 !", 2) + + output = bytearray(width * height * 2) + colors = list(rows) + + for y in range(height): + for x in range(width): + + red = colors[y][x * 4 + 0] / 255 + green = colors[y][x * 4 + 1] / 255 + blue = colors[y][x * 4 + 2] / 255 + alpha = colors[y][x * 4 + 3] / 255 + + Bred = red * alpha + 1 * (1 - alpha) + Bgreen = green * alpha + 1 * (1 - alpha) + Bblue = blue * alpha + 1 * (1 - alpha) + + Ired = int(Bred * 0xFF) + Igreen = int(Bgreen * 0xFF) + Iblue = int(Bblue * 0xFF) + + rgb565value = (Ired >> 3) << 11 | (Igreen >> 2) << 5 | (Iblue >> 3) + + i = (y * width + x) * 2 + struct.pack_into(" +#include +#include + +extern void (* const *_api_base)(void); + +uint64_t extapp_millis() { + return ((uint64_t (*)(void))_api_base[0])(); +} + +void extapp_msleep(uint32_t ms) { + ((void (*)(uint32_t))_api_base[1])(ms); +} + +uint64_t extapp_scanKeyboard() { + return ((uint64_t (*)(void))_api_base[2])(); +} + +void extapp_pushRect(int16_t x, int16_t y, uint16_t w, uint16_t h, const uint16_t * pixels) { + ((void (*)(int16_t, int16_t, uint16_t, uint16_t, const uint16_t *))_api_base[3])(x, y, w, h, pixels); +} + +void extapp_pushRectUniform(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t color) { + ((void (*)(int16_t, int16_t, uint16_t, uint16_t, uint16_t))_api_base[4])(x, y, w, h, color); +} + +void extapp_pullRect(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t * pixels) { + ((void (*)(int16_t, int16_t, uint16_t, uint16_t, uint16_t *))_api_base[5])(x, y, w, h, pixels); +} + +int16_t extapp_drawTextLarge(const char *text, int16_t x, int16_t y, uint16_t fg, uint16_t bg, bool fake) { + return ((int16_t (*)(const char *, int16_t, int16_t, uint16_t, uint16_t, bool))_api_base[6])(text, x, y, fg, bg, fake); +} + +int16_t extapp_drawTextSmall(const char *text, int16_t x, int16_t y, uint16_t fg, uint16_t bg, bool fake) { + return ((int16_t (*)(const char *, int16_t, int16_t, uint16_t, uint16_t, bool))_api_base[7])(text, x, y, fg, bg, fake); +} + +bool extapp_waitForVBlank(void) { + return ((bool (*)(void))_api_base[8])(); +} + +void extapp_clipboardStore(const char *text) { + ((void (*)(const char *))_api_base[9])(text); +} + +const char * extapp_clipboardText(void) { + return ((const char * (*)(void))_api_base[10])(); +} + +int extapp_fileListWithExtension(const char ** filenames, int maxrecords, const char * extension, int storage) { + return ((int (*)(const char **, int, const char *, int))_api_base[11])(filenames, maxrecords, extension, storage); +} + +bool extapp_fileExists(const char * filename, int storage) { + return ((bool (*)(const char *, int))_api_base[12])(filename, storage); +} + +bool extapp_fileErase(const char * filename, int storage) { + return ((bool (*)(const char *, int))_api_base[13])(filename, storage); +} + +const char * extapp_fileRead(const char * filename, size_t *len, int storage) { + return ((const char * (*)(const char *, size_t *, int))_api_base[14])(filename, len, storage); +} + +bool extapp_fileWrite(const char * filename, const char * content, size_t len, int storage) { + return ((bool (*)(const char *, const char *, size_t, int))_api_base[15])(filename, content, len, storage); +} + +void extapp_lockAlpha() { + ((void (*)(void))_api_base[16])(); +} + +void extapp_resetKeyboard() { + ((void (*)(void))_api_base[17])(); +} + +int extapp_getKey(bool allowSuspend, bool *alphaWasActive) { + return ((int (*)(bool, bool *))_api_base[18])(allowSuspend, alphaWasActive); +} + +bool extapp_isKeydown(int key){ + return ((bool (*)(int))_api_base[19])(key); +} + +int extapp_restorebackup(int mode){ + return ((int (*)(int))_api_base[20])(mode); +} + +bool extapp_erasesector(void * ptr){ + return ((bool (*)(void *))_api_base[21])(ptr); +} + +bool extapp_writememory(unsigned char * dest,const unsigned char * data,size_t length){ + return ((bool (*)(unsigned char *, const unsigned char *, size_t))_api_base[22])(dest,data,length); +} + +bool extapp_inexammode(){ + return ((bool (*)(void ))_api_base[23])(); +} diff --git a/build/upsilon-api/extapp_api.h b/build/upsilon-api/extapp_api.h new file mode 100644 index 0000000..44e912b --- /dev/null +++ b/build/upsilon-api/extapp_api.h @@ -0,0 +1,415 @@ +#ifndef EXTERNAL_API_H +#define EXTERNAL_API_H + +#include +#include +#include + +#define API_VERSION 2 + +#ifdef __cplusplus +#define EXTERNC extern "C" +#else +#define EXTERNC extern +#endif + +// Screen size +// The screen width +#define LCD_WIDTH 320 +// The screen height +#define LCD_HEIGHT 240 + +// Files systems +// The RAM file system, which can be written, and it is used by the system applications, +// this storage is erased on reset +#define EXTAPP_RAM_FILE_SYSTEM 0 +// The flash file system, which is written by the external application website, +// used for big files storing, and roms, this storage is kept after a reset +#define EXTAPP_FLASH_FILE_SYSTEM 1 +#define EXTAPP_BOTH_FILE_SYSTEM 2 + +// The code of the keys, returned by `extapp_scanKeyboard()` +#define SCANCODE_Left ((uint64_t)1 << 0) +#define SCANCODE_Up ((uint64_t)1 << 1) +#define SCANCODE_Down ((uint64_t)1 << 2) +#define SCANCODE_Right ((uint64_t)1 << 3) +#define SCANCODE_OK ((uint64_t)1 << 4) +#define SCANCODE_Back ((uint64_t)1 << 5) +#define SCANCODE_Home ((uint64_t)1 << 6) +#define SCANCODE_OnOff (((uint64_t)1 << 7) | ((uint64_t)1 << 8)) +#define SCANCODE_Shift ((uint64_t)1 << 12) +#define SCANCODE_Alpha ((uint64_t)1 << 13) +#define SCANCODE_XNT ((uint64_t)1 << 14) +#define SCANCODE_Var ((uint64_t)1 << 15) +#define SCANCODE_Toolbox ((uint64_t)1 << 16) +#define SCANCODE_Backspace ((uint64_t)1 << 17) +#define SCANCODE_Exp ((uint64_t)1 << 18) +#define SCANCODE_Ln ((uint64_t)1 << 19) +#define SCANCODE_Log ((uint64_t)1 << 20) +#define SCANCODE_Imaginary ((uint64_t)1 << 21) +#define SCANCODE_Comma ((uint64_t)1 << 22) +#define SCANCODE_Power ((uint64_t)1 << 23) +#define SCANCODE_Sine ((uint64_t)1 << 24) +#define SCANCODE_Cosine ((uint64_t)1 << 25) +#define SCANCODE_Tangent ((uint64_t)1 << 26) +#define SCANCODE_Pi ((uint64_t)1 << 27) +#define SCANCODE_Sqrt ((uint64_t)1 << 28) +#define SCANCODE_Square ((uint64_t)1 << 29) +#define SCANCODE_Seven ((uint64_t)1 << 30) +#define SCANCODE_Eight ((uint64_t)1 << 31) +#define SCANCODE_Nine ((uint64_t)1 << 32) +#define SCANCODE_LeftParenthesis ((uint64_t)1 << 33) +#define SCANCODE_RightParenthesis ((uint64_t)1 << 34) +#define SCANCODE_Four ((uint64_t)1 << 36) +#define SCANCODE_Five ((uint64_t)1 << 37) +#define SCANCODE_Six ((uint64_t)1 << 38) +#define SCANCODE_Multiplication ((uint64_t)1 << 39) +#define SCANCODE_Division ((uint64_t)1 << 40) +#define SCANCODE_One ((uint64_t)1 << 42) +#define SCANCODE_Two ((uint64_t)1 << 43) +#define SCANCODE_Three ((uint64_t)1 << 44) +#define SCANCODE_Plus ((uint64_t)1 << 45) +#define SCANCODE_Minus ((uint64_t)1 << 46) +#define SCANCODE_Zero ((uint64_t)1 << 48) +#define SCANCODE_Dot ((uint64_t)1 << 49) +#define SCANCODE_EE ((uint64_t)1 << 50) +#define SCANCODE_Ans ((uint64_t)1 << 51) +#define SCANCODE_EXE ((uint64_t)1 << 52) +#define SCANCODE_None ((uint64_t)1 << 54) + +// Keys, returned by `extapp_getKey()` +// Character codes +#define KEY_CHAR_0 0x30 +#define KEY_CHAR_1 0x31 +#define KEY_CHAR_2 0x32 +#define KEY_CHAR_3 0x33 +#define KEY_CHAR_4 0x34 +#define KEY_CHAR_5 0x35 +#define KEY_CHAR_6 0x36 +#define KEY_CHAR_7 0x37 +#define KEY_CHAR_8 0x38 +#define KEY_CHAR_9 0x39 +#define KEY_CHAR_DP 0x2e +#define KEY_CHAR_EXP 0x0f +#define KEY_CHAR_PMINUS 30200 +#define KEY_CHAR_PLUS 43 +#define KEY_CHAR_MINUS 45 +#define KEY_CHAR_MULT 42 +#define KEY_CHAR_DIV 47 +#define KEY_CHAR_FRAC 0xbb +#define KEY_CHAR_LPAR 0x28 +#define KEY_CHAR_RPAR 0x29 +#define KEY_CHAR_COMMA 0x2c +#define KEY_CHAR_STORE 0x0e +#define KEY_CHAR_LOG 0x95 +#define KEY_CHAR_LN 0x85 +#define KEY_CHAR_SIN 0x81 +#define KEY_CHAR_COS 0x82 +#define KEY_CHAR_TAN 0x83 +#define KEY_CHAR_SQUARE 0x8b +#define KEY_CHAR_POW 0xa8 +#define KEY_CHAR_IMGNRY 0x7f50 +#define KEY_CHAR_LIST 0x7f51 +#define KEY_CHAR_MAT 0x7f40 +#define KEY_CHAR_EQUAL 0x3d +#define KEY_CHAR_PI 0xd0 +#define KEY_CHAR_ANS 0xc0 +#define KEY_SHIFT_ANS 0xc1 +#define KEY_CHAR_LBRCKT 0x5b +#define KEY_CHAR_RBRCKT 0x5d +#define KEY_CHAR_LBRACE 0x7b +#define KEY_CHAR_RBRACE 0x7d +#define KEY_CHAR_CR 0x0d +#define KEY_CHAR_CUBEROOT 0x96 +#define KEY_CHAR_RECIP 0x9b +#define KEY_CHAR_ANGLE 0x7f54 +#define KEY_CHAR_EXPN10 0xb5 +#define KEY_CHAR_EXPN 0xa5 +#define KEY_CHAR_ASIN 0x91 +#define KEY_CHAR_ACOS 0x92 +#define KEY_CHAR_ATAN 0x93 +#define KEY_CHAR_ROOT 0x86 +#define KEY_CHAR_POWROOT 0xb8 +#define KEY_CHAR_SPACE 0x20 +#define KEY_CHAR_DQUATE 0x22 +#define KEY_CHAR_VALR 0xcd +#define KEY_CHAR_THETA 0xce +#define KEY_CHAR_FACTOR 0xda +#define KEY_CHAR_NORMAL 0xdb +#define KEY_CHAR_A 0x41 +#define KEY_CHAR_B 0x42 +#define KEY_CHAR_C 0x43 +#define KEY_CHAR_D 0x44 +#define KEY_CHAR_E 0x45 +#define KEY_CHAR_F 0x46 +#define KEY_CHAR_G 0x47 +#define KEY_CHAR_H 0x48 +#define KEY_CHAR_I 0x49 +#define KEY_CHAR_J 0x4a +#define KEY_CHAR_K 0x4b +#define KEY_CHAR_L 0x4c +#define KEY_CHAR_M 0x4d +#define KEY_CHAR_N 0x4e +#define KEY_CHAR_O 0x4f +#define KEY_CHAR_P 0x50 +#define KEY_CHAR_Q 0x51 +#define KEY_CHAR_R 0x52 +#define KEY_CHAR_S 0x53 +#define KEY_CHAR_T 0x54 +#define KEY_CHAR_U 0x55 +#define KEY_CHAR_V 0x56 +#define KEY_CHAR_W 0x57 +#define KEY_CHAR_X 0x58 +#define KEY_CHAR_Y 0x59 +#define KEY_CHAR_Z 0x5a + +// Control codes +#define KEY_CTRL_NOP 30202 +#define KEY_CTRL_EXE 30201 +#define KEY_CTRL_DEL 30025 +#define KEY_CTRL_AC 30070 +#define KEY_CTRL_FD 30046 +#define KEY_CTRL_UNDO 30045 +#define KEY_CTRL_XTT 30001 +#define KEY_CTRL_EXIT 5 +#define KEY_CTRL_OK 4 +#define KEY_CTRL_SHIFT 30006 +#define KEY_CTRL_ALPHA 30007 +#define KEY_CTRL_OPTN 30008 +#define KEY_CTRL_VARS 30030 +#define KEY_CTRL_UP 1 +#define KEY_CTRL_DOWN 2 +#define KEY_CTRL_LEFT 0 +#define KEY_CTRL_RIGHT 3 +#define KEY_CTRL_F1 30009 +#define KEY_CTRL_F2 30010 +#define KEY_CTRL_F3 30011 +#define KEY_CTRL_F4 30012 +#define KEY_CTRL_F5 30013 +#define KEY_CTRL_F6 30014 +#define KEY_CTRL_F7 30015 +#define KEY_CTRL_F8 30016 +#define KEY_CTRL_F9 30017 +#define KEY_CTRL_F10 30018 +#define KEY_CTRL_F11 30019 +#define KEY_CTRL_F12 30020 +#define KEY_CTRL_F13 30021 +#define KEY_CTRL_F14 30022 +#define KEY_CTRL_CATALOG 30100 +#define KEY_CTRL_CAPTURE 30055 +#define KEY_CTRL_CLIP 30050 +#define KEY_CTRL_CUT 30250 +#define KEY_CTRL_PASTE 30036 +#define KEY_CTRL_INS 30033 +#define KEY_CTRL_MIXEDFRAC 30054 +#define KEY_CTRL_FRACCNVRT 30026 +#define KEY_CTRL_QUIT 30029 +#define KEY_CTRL_PRGM 30028 +#define KEY_CTRL_SETUP 30037 +#define KEY_CTRL_PAGEUP 30052 +#define KEY_CTRL_PAGEDOWN 30053 +#define KEY_CTRL_MENU 30003 +#define KEY_SHIFT_OPTN 30059 +#define KEY_CTRL_RESERVE1 30060 +#define KEY_CTRL_RESERVE2 30061 +#define KEY_SHIFT_LEFT 30062 +#define KEY_SHIFT_RIGHT 30063 + +#define KEY_PRGM_ACON 10 +#define KEY_PRGM_DOWN 37 +#define KEY_PRGM_EXIT 47 +#define KEY_PRGM_F1 79 +#define KEY_PRGM_F2 69 +#define KEY_PRGM_F3 59 +#define KEY_PRGM_F4 49 +#define KEY_PRGM_F5 39 +#define KEY_PRGM_F6 29 +#define KEY_PRGM_LEFT 38 +#define KEY_PRGM_NONE 0 +#define KEY_PRGM_RETURN 31 +#define KEY_PRGM_RIGHT 27 +#define KEY_PRGM_UP 28 +#define KEY_PRGM_1 72 +#define KEY_PRGM_2 62 +#define KEY_PRGM_3 52 +#define KEY_PRGM_4 73 +#define KEY_PRGM_5 63 +#define KEY_PRGM_6 53 +#define KEY_PRGM_7 74 +#define KEY_PRGM_8 64 +#define KEY_PRGM_9 54 +#define KEY_PRGM_A 76 +#define KEY_PRGM_F 26 +#define KEY_PRGM_ALPHA 77 +#define KEY_PRGM_SHIFT 78 +#define KEY_PRGM_MENU 48 + +// External API functions +/** + * Get the current date, in milliseconds, from the boot, excluding suspended time + * @return uint64_t, the current date from the boot in milliseconds + */ +EXTERNC uint64_t extapp_millis(); +/** + * Sleep ms milliseconds + * @param ms uint32_t, the number of milliseconds to sleep + */ +EXTERNC void extapp_msleep(uint32_t ms); +// Scan the keyboard, and return a key that can be identified by SCANCODE_* constants (like SCANCODE_Left) +EXTERNC uint64_t extapp_scanKeyboard(); +/** + * Push a buffer of pixels to the screen + * @param x uint16_t, the x position of the buffer to display on the screen + * @param y uint16_t, the y position of the buffer to display on the screen + * @param w uint16_t, the width of the buffer to display on the screen + * @param h uint16_t, the height of the buffer to display on the screen + * @param pixels const uint16_t *, the buffer to display on the screen + */ +EXTERNC void extapp_pushRect(int16_t x, int16_t y, uint16_t w, uint16_t h, const uint16_t * pixels); +/** + * Push a colored rectangle on the screen + * @param x uint16_t, the x position of the rectangle + * @param y uint16_t, the y position of the rectangle + * @param w uint16_t, the width of the rectangle + * @param h uint16_t, the height of the rectangle + * @param color uint16_t, the color of the rectangle + */ +EXTERNC void extapp_pushRectUniform(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t color); +/** + * Push a rectangle from the screen + * @param x uint16_t, the x position of the rectangle + * @param y uint16_t, the y position of the rectangle + * @param w uint16_t, the width of the rectangle + * @param h uint16_t, the height of the rectangle + * @param pixels uint16_t *, the pointer to the buffer to store the pixel rect + */ +EXTERNC void extapp_pullRect(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t * pixels); +/** + * Display large text + * @param text const char *t, the text to display + * @param x int16_t, the x position of the text to display + * @param y int16_t, the y position of the text to display + * @param fg uint16_t, the color of the foreground + * @param bg uint16_t, the color of the background + * @param fake bool, whether to not display the text, just return the size of the text + * @return uint16_t, the width of the text + */ +EXTERNC int16_t extapp_drawTextLarge(const char *text, int16_t x, int16_t y, uint16_t fg, uint16_t bg, bool fake); +/** + * Display small text + * @param text const char *t, the text to display + * @param x int16_t, the x position of the text to display + * @param y int16_t, the y position of the text to display + * @param fg uint16_t, the color of the foreground + * @param bg uint16_t, the color of the background + * @param fake bool, whether to not display the text, just return the size of the text + * @return uint16_t, the width of the text + */ +EXTERNC int16_t extapp_drawTextSmall(const char *text, int16_t x, int16_t y, uint16_t fg, uint16_t bg, bool fake); +/** + * Wait for screen refresh + */ +EXTERNC bool extapp_waitForVBlank(); +/** + * Set text into clipboard + * @param text const char *t, the text to copy + */ +EXTERNC void extapp_clipboardStore(const char *text); +/** + * Get clipboard contents + * @return const char *, the contents of the clipboard + */ +EXTERNC const char * extapp_clipboardText(); +/** + * Get a list of files in "storage", filtered by extension + * @param filename const char **, an array that must to be a equal to + * the maxrecords variable, to avoid buffer overflow + * @param maxrecords int, the maximum number of records that can be retrieved, + * it should be equal to the length of the filenames array, + * to avoid buffer overflow + * @param extension const char *, the extension of the filename to retrieve, + * it work only with RAM file system for now + * @param storage int, the storage to use (like EXTAPP_FLASH_FILE_SYSTEM) + * @return int, the number of retrieved records + */ +EXTERNC int extapp_fileListWithExtension(const char ** filenames, int maxrecords, const char * extension, int storage); +/** + * Return if "filename" exist in "storage" + * @param filename const char *, the file to check existing + * @param storage int, the storage to use (like EXTAPP_FLASH_FILE_SYSTEM) + * @return bool, true if the operation is successful + */ +EXTERNC bool extapp_fileExists(const char * filename, int storage); +/** + * Erase "filename" in "storage" + * @param filename const char *, the file to remove + * @param storage int, the storage to use (like EXTAPP_RAM_FILE_SYSTEM) + * @return bool, true if the operation is successful + */ +EXTERNC bool extapp_fileErase(const char * filename, int storage); +/** + * Read "filename" from "storage" + * @param filename const char *, the file to read + * @param len, size_t, a pointer to a size_t variable, to store the file length + * @param storage int, the storage to use (like EXTAPP_FLASH_FILE_SYSTEM) + * @return const char *, the file content + */ +EXTERNC const char * extapp_fileRead(const char * filename, size_t *len, int storage); +/** + * Write "content" into "filename" in "storage" + * @param filename const char *, the file to write + * @param content, const char *, the content of the file to write + * @param len, size_t, the length of the file to write + * @param storage int, the storage to use (like EXTAPP_FLASH_FILE_SYSTEM) + * @return bool, true if the operation is successful + */ +EXTERNC bool extapp_fileWrite(const char * filename, const char * content, size_t len, int storage); +/** + * Enable alpha lock + */ +EXTERNC void extapp_lockAlpha(); +/** + * Reset keyboard status, like alpha lock + */ +EXTERNC void extapp_resetKeyboard(); +/** + * Get pressed keys + * @param allowSuspend bool, whether to allow suspending the calculator + * @param alphaWasActive bool, a pointer to a bool to store if the alpha (lock) was active + * @return int, the code of the pressed key, like KEY_CHAR_0 or KEY_CTRL_EXE + */ +EXTERNC int extapp_getKey(int allowSuspend, bool *alphaWasActive); +/** + * If given key is pressed + * @param key int, the key to check + * @return bool, true if the key is pressed + */ +EXTERNC bool extapp_isKeydown(int key); +/** + * Restore the exam mode backup, created by KhiCAS and Khi + * @param mode int, the mode to restore (TODO: Improve this) + * @return int, higher than 0 if the operation is successful + */ +EXTERNC int extapp_restorebackup(int mode); // currently works only with mode==-1 to restore scriptstore after exam mode +/** + * Erase flash sector, works only when "Write allowed" is enabled in the calculator + * @param ptr void *, the sector to erase + * @return bool, true if the operation is successful + */ +EXTERNC bool extapp_erasesector(void * ptr); +/** + * Write flash sector, works only when "Write allowed" is enabled in the calculator + * @param dest unsigned char *, the destination address + * @param data unsigned char *, the data to write + * @param length size_t, the length of the data to write + */ +EXTERNC bool extapp_writesector(unsigned char * dest,const unsigned char * data,size_t length); +/** + * Get if the exam mode is active + * @return bool, true if the exam mode is active + */ +EXTERNC bool extapp_inexammode(); +EXTERNC uint32_t _heap_size; +EXTERNC void *_heap_base; +EXTERNC void *_heap_ptr; +#endif diff --git a/build/upsilon-api/extapp_startup.c b/build/upsilon-api/extapp_startup.c new file mode 100644 index 0000000..4038f05 --- /dev/null +++ b/build/upsilon-api/extapp_startup.c @@ -0,0 +1,62 @@ +#include +#include +#include +#include "extapp_api.h" + +void * __dso_handle = 0; + +typedef void (*cxx_constructor)(void); + +extern char _data_section_start_flash; +extern char _data_section_start_ram; +extern char _data_section_end_ram; +extern char _bss_section_start_ram; +extern char _bss_section_end_ram; +extern cxx_constructor _init_array_start; +extern cxx_constructor _init_array_end; + +extern void extapp_main(void); + +void *_heap_base, *_heap_ptr; +const void *_api_base; +uint32_t _heap_size; +jmp_buf oom_jmp_buf; + +uint32_t _extapp_start(const uint32_t api_version, const void * api_base, void * heap, const uint32_t heap_size) { + + if(api_version != API_VERSION) { + return 1; + } + + size_t dataSectionLength = (&_data_section_end_ram - &_data_section_start_ram); + memcpy(&_data_section_start_ram, &_data_section_start_flash, dataSectionLength); + size_t bssSectionLength = (&_bss_section_end_ram - &_bss_section_start_ram); + memset(&_bss_section_start_ram, 0, bssSectionLength); + + _api_base = api_base; + _heap_base = heap; + _heap_ptr = heap; + _heap_size = heap_size; + + int result = setjmp(oom_jmp_buf); + if(result == 0) { + for (cxx_constructor * c = &_init_array_start; c<&_init_array_end; c++) { + (*c)(); + } + extapp_main(); + } + + return result; +} + +void *_sbrk (int nbytes) { + if ((_heap_ptr - _heap_base) + nbytes <= _heap_size) { + void *base = _heap_ptr; + _heap_ptr += nbytes; + return base; + } else { + longjmp(oom_jmp_buf, 2); + } +} + +uint32_t (*entrypoint)(const uint32_t, const void *, void *, const uint32_t) __attribute__((section(".entrypoint"))) __attribute__((used)) = _extapp_start; diff --git a/justfile b/justfile index de28dbe..254a154 100644 --- a/justfile +++ b/justfile @@ -1,32 +1,62 @@ +app_name := "Numcraft" +lib_file_name := "libnumcraft_sim" + +icon_file := "assets/icon.png" + current_target := shell("rustc -vV | grep \"host:\" | awk '{print $2}'") -build: setup_target - cargo build --release --bin Numcraft --target=thumbv7em-none-eabihf +build-epsilon: setup_target + cargo build --release --bin {{app_name}} --target=thumbv7em-none-eabihf --features "epsilon" --no-default-features + +build-upsilon: setup_target + cargo build --release --bin {{app_name}} --target=thumbv7em-none-eabihf --features "upsilon" --no-default-features + +send-epsilon: setup_target + cargo build --release --bin {{app_name}} --target=thumbv7em-none-eabihf --features "epsilon" --no-default-features + npm exec --yes -- nwlink@0.0.19 install-nwa ./target/thumbv7em-none-eabihf/release/{{app_name}} + +send-upsilon: + mkdir -p target/upsilon_api + make -f build/upsilon-api/Makefile + just build-upsilon + # Code adapted from https://github.com/UpsilonNumworks/Upsilon-External/blob/master/Makefile. Under MIT + ./build/archive apps.tar {{app_name}} + echo "Waiting for the calculator to be connected, use the bootloader to flash on Upsilon if your app is bigger than 2MB" + until dfu-util -l | grep -E "0483:a291|0483:df11" > /dev/null 2>&1; do sleep .5;done + dfu-util -i 0 -a 0 -s 0x90200000 -D target/apps.tar -send: setup_target - cargo run --release --bin Numcraft --target=thumbv7em-none-eabihf +release-upsilon: + mkdir -p target/upsilon_api + make -f build/upsilon-api/Makefile + just build-upsilon + . ./.venv/bin/activate && python3 ./build/png2icon.py {{icon_file}} app.icon + cp ./target/thumbv7em-none-eabihf/release/{{app_name}} ./app.elf + cp ./assets/icon.png ./icon.png check: setup_target - cargo build --release --bin Numcraft --target=thumbv7em-none-eabihf - cargo build --release --target={{current_target}} --lib + cargo check --release --bin {{app_name}} --target=thumbv7em-none-eabihf --features "epsilon" --no-default-features + cargo check --release --target={{current_target}} --lib --features "epsilon" --no-default-features + cargo check --release --bin {{app_name}} --target=thumbv7em-none-eabihf --features "upsilon" --no-default-features + cargo check --release --target={{current_target}} --lib --features "upsilon" --no-default-features + @echo All checks passed! setup_target: mkdir -p target/assets target/structs target/crafts [macos] run_nwb: - ./simulator/output/release/simulator/macos/epsilon.app/Contents/MacOS/Epsilon --nwb ./target/{{current_target}}/release/libnumcraft_sim.dylib + ./simulator/output/release/simulator/macos/epsilon.app/Contents/MacOS/Epsilon --nwb ./target/{{current_target}}/release/{{lib_file_name}}.dylib [linux] run_nwb: - ./simulator/output/release/simulator/linux/epsilon.bin --nwb ./target/{{current_target}}/release/libnumcraft_sim.so + ./simulator/output/release/simulator/linux/epsilon.bin --nwb ./target/{{current_target}}/release/{{lib_file_name}}.so sim jobs="1" features="": setup_target -git clone https://github.com/numworks/epsilon.git simulator -b version-20 # Broken with version 21. Nice! if [ -n "{{features}}"];then \ - cargo build --release --target={{current_target}} --lib;\ + cargo build --release --target={{current_target}} --lib --features "epsilon" --no-default-features;\ else \ - cargo build --release --target={{current_target}} --lib --features {{features}};\ + cargo build --release --target={{current_target}} --lib --features "{{features}} epsilon" --no-default-features;\ fi if [ ! -f "target/simulator_patched" ]; then \ @@ -36,12 +66,13 @@ sim jobs="1" features="": setup_target fi just run_nwb -[confirm("This will clean the built app AND the simulator. Do you want to continue ?")] -clean-all: - cd ./simulator && make clean +[confirm("This will clean the built app. Do you want to continue ?")] +clean: + rm -f ./app.elf ./app.icon cargo clean [confirm("This will clean the built app AND DELETE the simulator. Do you want to continue ?")] -clear-all: +clear: rm -rf ./simulator + rm -f ./app.elf ./app.icon ./icon.png cargo clean diff --git a/setup.sh b/setup.sh index ccbc0c6..69bce50 100644 --- a/setup.sh +++ b/setup.sh @@ -49,13 +49,13 @@ if [ ! -d "simulator" ]; then fi fi -python3 -m venv ./simulator/.venv +python3 -m venv ./.venv if [ $? -ne 0 ]; then echo "Cannot create the Python venv. Installation aborted." [[ "$0" = "$BASH_SOURCE" ]] && exit 1 || return 1 fi -source ./simulator/.venv/bin/activate +source ./.venv/bin/activate if [ $? -ne 0 ]; then echo "Cannot activate the Python venv. Installation aborted." [[ "$0" = "$BASH_SOURCE" ]] && exit 1 || return 1 diff --git a/src/camera.rs b/src/camera.rs index 0adf069..95af476 100644 --- a/src/camera.rs +++ b/src/camera.rs @@ -5,7 +5,7 @@ use nalgebra::{Matrix4, UnitQuaternion, Vector3}; use crate::{ constants::{player::ROTATION_SPEED, rendering::FOV}, - eadk, + nadk, input_manager::InputManager, settings::Settings, }; @@ -37,18 +37,18 @@ impl Camera { pub fn update(&mut self, delta: f32, input_manager: &InputManager, settings: &Settings) { // Rotation - if (input_manager.is_keydown(eadk::keyboard::Key::Right) && !settings.reverse_controls) - || (input_manager.is_keydown(eadk::keyboard::Key::Power) && settings.reverse_controls) + if (input_manager.is_keydown(nadk::keyboard::Key::Right) && !settings.reverse_controls) + || (input_manager.is_keydown(nadk::keyboard::Key::Power) && settings.reverse_controls) { self.rotation.y -= delta * ROTATION_SPEED; } - if (input_manager.is_keydown(eadk::keyboard::Key::Left) && !settings.reverse_controls) - || (input_manager.is_keydown(eadk::keyboard::Key::Imaginary) && settings.reverse_controls) + if (input_manager.is_keydown(nadk::keyboard::Key::Left) && !settings.reverse_controls) + || (input_manager.is_keydown(nadk::keyboard::Key::Imaginary) && settings.reverse_controls) { self.rotation.y += delta * ROTATION_SPEED; } - if (input_manager.is_keydown(eadk::keyboard::Key::Up) && !settings.reverse_controls) - || (input_manager.is_keydown(eadk::keyboard::Key::Toolbox) && settings.reverse_controls) + if (input_manager.is_keydown(nadk::keyboard::Key::Up) && !settings.reverse_controls) + || (input_manager.is_keydown(nadk::keyboard::Key::Toolbox) && settings.reverse_controls) { self.rotation.x -= delta * ROTATION_SPEED; @@ -56,8 +56,8 @@ impl Camera { self.rotation.x = -PI / 2.0 + 0.0001 } } - if (input_manager.is_keydown(eadk::keyboard::Key::Down) && !settings.reverse_controls) - || (input_manager.is_keydown(eadk::keyboard::Key::Comma) && settings.reverse_controls) + if (input_manager.is_keydown(nadk::keyboard::Key::Down) && !settings.reverse_controls) + || (input_manager.is_keydown(nadk::keyboard::Key::Comma) && settings.reverse_controls) { self.rotation.x += delta * ROTATION_SPEED; diff --git a/src/constants.rs b/src/constants.rs index 7afcc10..a118074 100644 --- a/src/constants.rs +++ b/src/constants.rs @@ -1,20 +1,23 @@ use nalgebra::Vector3; use serde::{Deserialize, Serialize}; -use crate::{eadk::display::Color565, physic::BoundingBox, renderer::mesh::QuadDir}; +use crate::{nadk::display::Color565, physic::BoundingBox, renderer::mesh::QuadDir}; pub mod rendering { pub const SCREEN_WIDTH: usize = 320; pub const SCREEN_HEIGHT: usize = 240; - pub const SCREEN_TILE_SUBDIVISION: usize = 2; // Minimum 2 + pub const SCREEN_TILE_SUBDIVISION: usize = 4; // Minimum 2 pub const MIN_FOV: f32 = 30.; pub const MAX_FOV: f32 = 110.; pub const FOV: f32 = 45.; + #[cfg(feature = "epsilon")] pub const MAX_TRIANGLES: usize = 1500; + #[cfg(feature = "upsilon")] + pub const MAX_TRIANGLES: usize = 1200; // Sorry Upsilon users pub const MAX_RENDER_DISTANCE: usize = 2; // You shouldn't go higher @@ -27,7 +30,7 @@ pub mod rendering { } pub mod color_palette { - use crate::eadk::display::Color565; + use crate::nadk::display::Color565; pub const MENU_OUTLINE_COLOR: Color565 = Color565::from_rgb888(150, 150, 150); pub const MENU_ELEMENT_BACKGROUND_COLOR: Color565 = Color565::from_rgb888(230, 230, 230); diff --git a/src/eadk/adresses.rs b/src/eadk/adresses.rs deleted file mode 100644 index f947093..0000000 --- a/src/eadk/adresses.rs +++ /dev/null @@ -1,13 +0,0 @@ -unsafe extern "C" { - pub static mut _heap_start: u8; - pub static mut _heap_end: u8; -} - -pub static mut HEAP_START: *mut u8 = core::ptr::addr_of_mut!(_heap_start); -pub static mut HEAP_END: *mut u8 = core::ptr::addr_of_mut!(_heap_end); - -/// Return the size of the heap. -pub fn heap_size() -> usize { - 100_000 - //(unsafe { HEAP_END.offset_from(HEAP_START) }) as usize -} diff --git a/src/eadk/random.rs b/src/eadk/random.rs deleted file mode 100644 index 9ec83f0..0000000 --- a/src/eadk/random.rs +++ /dev/null @@ -1,37 +0,0 @@ -/// Give a random u32. -pub fn get_random_u32() -> u32 { - unsafe { eadk_random() } -} - -/// Give a random u64. -pub fn get_random_u64() -> u64 { - unsafe { (eadk_random() as u64) << 32 | (eadk_random() as u64) } -} - -/// Give a random u16. -pub fn get_random_u16() -> u16 { - unsafe { (eadk_random() >> 16) as u16 } -} - -/// Give a random u8. -pub fn get_random_u8() -> u8 { - unsafe { (eadk_random() >> 24) as u8 } -} - -/// Give a random f32 between 0 and 1. -pub fn get_random_decimal() -> f32 { - unsafe { eadk_random() as f32 / u32::MAX as f32 } -} - -/// Give a random number between start (included) and end (excluded). -pub fn get_random_in_range(start: u32, stop: u32) -> u32 { - assert!(start < stop, "Start must be smaller than stop"); - let mut random_u32 = unsafe { eadk_random() }; - random_u32 %= stop - start; - random_u32 += start; - random_u32 -} - -unsafe extern "C" { - fn eadk_random() -> u32; -} diff --git a/src/game.rs b/src/game.rs index 1e587ce..96d3861 100644 --- a/src/game.rs +++ b/src/game.rs @@ -11,7 +11,7 @@ use crate::{ color_palette::MENU_BACKGROUND_COLOR, rendering::{MAX_FOV, MAX_RENDER_DISTANCE, MIN_FOV}, }, - eadk::{self, display::Color565}, + nadk::{self, display::Color565}, game::{crafting_manager::CraftingManager, game_menus::SettingsMenu}, game_ui::GameUI, hud::Hud, @@ -147,12 +147,12 @@ impl Game { self.input_manager.update(); self.timing_manager.update(); - if self.input_manager.is_just_pressed(eadk::keyboard::Key::Exe) { + if self.input_manager.is_just_pressed(nadk::keyboard::Key::Exe) { self.exit_world(); return GameState::GoMainMenu; } - if self.input_manager.is_just_pressed(eadk::keyboard::Key::Var) { + if self.input_manager.is_just_pressed(nadk::keyboard::Key::Var) { if self.save_manager.get_game_mode() == GameMode::Creative { return GameState::OpenPlayerInventory(game_uis::PlayerInventoryPage::Creative); } else { @@ -189,7 +189,7 @@ impl Game { self.renderer.draw_game( &mut self.world, &self.player, - self.timing_manager.get_fps(), + self.timing_manager.get_frame_time(), &self.hud, true, ); diff --git a/src/game/game_menus.rs b/src/game/game_menus.rs index 4de0582..eb2d587 100644 --- a/src/game/game_menus.rs +++ b/src/game/game_menus.rs @@ -18,7 +18,7 @@ impl Game { }) .with_element(MenuElement::Entry { placeholder_text: "World seed".to_string(), - value: format!("{}", eadk::random::get_random_u32() % 1_000_000_000), + value: format!("{}", nadk::random::get_random_u32() % 1_000_000_000), allow_margin: true, max_len: 9, digits_only: true, @@ -38,7 +38,7 @@ impl Game { }); // Clear the screen - eadk::display::push_rect_uniform(eadk::display::SCREEN_RECT, MENU_BACKGROUND_COLOR); + nadk::display::push_rect_uniform(nadk::display::SCREEN_RECT, MENU_BACKGROUND_COLOR); self.timing_manager.reset(); @@ -50,7 +50,7 @@ impl Game { self.input_manager.update_timing(&self.timing_manager); // Exit the menu when [Back] is pressed - if self.input_manager.is_keydown(eadk::keyboard::Key::Back) { + if self.input_manager.is_keydown(nadk::keyboard::Key::Back) { return GameState::GoSelectWorld; } @@ -79,7 +79,7 @@ impl Game { } if seed.is_empty() { - seed = format!("{}", eadk::random::get_random_u32() % 1_000_000_000); + seed = format!("{}", nadk::random::get_random_u32() % 1_000_000_000); } let world_seed = seed.parse::().unwrap_or(1); @@ -114,7 +114,7 @@ impl Game { menu.finish_buttons_handling(); self.renderer.draw_menu(&mut menu); - eadk::time::wait_milliseconds(50); + nadk::time::wait_milliseconds(50); } } @@ -144,7 +144,7 @@ impl Game { }); // Clear the screen - eadk::display::push_rect_uniform(eadk::display::SCREEN_RECT, MENU_BACKGROUND_COLOR); + nadk::display::push_rect_uniform(nadk::display::SCREEN_RECT, MENU_BACKGROUND_COLOR); self.timing_manager.reset(); @@ -154,7 +154,7 @@ impl Game { self.input_manager.update_timing(&self.timing_manager); // Exit the menu when [Back] is pressed - if self.input_manager.is_keydown(eadk::keyboard::Key::Back) { + if self.input_manager.is_keydown(nadk::keyboard::Key::Back) { return GameState::GoSelectWorld; } @@ -185,7 +185,7 @@ impl Game { menu.finish_buttons_handling(); self.renderer.draw_menu(&mut menu); - eadk::time::wait_milliseconds(50); + nadk::time::wait_milliseconds(50); } } @@ -232,7 +232,7 @@ impl Game { } // Clear the screen - eadk::display::push_rect_uniform(eadk::display::SCREEN_RECT, MENU_BACKGROUND_COLOR); + nadk::display::push_rect_uniform(nadk::display::SCREEN_RECT, MENU_BACKGROUND_COLOR); self.timing_manager.reset(); @@ -245,7 +245,7 @@ impl Game { menu.check_inputs(&self.input_manager); // Exit the menu when [Back] is pressed - if self.input_manager.is_keydown(eadk::keyboard::Key::Back) { + if self.input_manager.is_keydown(nadk::keyboard::Key::Back) { return GameState::GoMainMenu; } @@ -286,7 +286,7 @@ impl Game { menu.finish_buttons_handling(); self.renderer.draw_menu(&mut menu); - eadk::time::wait_milliseconds(50); + nadk::time::wait_milliseconds(50); } } @@ -334,7 +334,7 @@ impl Game { }); // Clear the screen - eadk::display::push_rect_uniform(eadk::display::SCREEN_RECT, MENU_BACKGROUND_COLOR); + nadk::display::push_rect_uniform(nadk::display::SCREEN_RECT, MENU_BACKGROUND_COLOR); self.timing_manager.reset(); @@ -343,7 +343,7 @@ impl Game { self.timing_manager.update(); self.input_manager.update_timing(&self.timing_manager); - if self.input_manager.is_keydown(eadk::keyboard::Key::Back) { + if self.input_manager.is_keydown(nadk::keyboard::Key::Back) { self.update_settings(); self.settings.save(); return GameState::GoSetting(SettingsMenu::Hub); @@ -388,7 +388,7 @@ impl Game { } self.renderer.draw_menu(&mut menu); - eadk::time::wait_milliseconds(50); + nadk::time::wait_milliseconds(50); } } @@ -412,7 +412,7 @@ impl Game { }); // Clear the screen - eadk::display::push_rect_uniform(eadk::display::SCREEN_RECT, MENU_BACKGROUND_COLOR); + nadk::display::push_rect_uniform(nadk::display::SCREEN_RECT, MENU_BACKGROUND_COLOR); self.timing_manager.reset(); @@ -421,7 +421,7 @@ impl Game { self.timing_manager.update(); self.input_manager.update_timing(&self.timing_manager); - if self.input_manager.is_keydown(eadk::keyboard::Key::Back) { + if self.input_manager.is_keydown(nadk::keyboard::Key::Back) { self.update_settings(); self.settings.save(); return GameState::GoSetting(SettingsMenu::Hub); @@ -459,7 +459,7 @@ impl Game { } self.renderer.draw_menu(&mut menu); - eadk::time::wait_milliseconds(50); + nadk::time::wait_milliseconds(50); } } @@ -498,7 +498,7 @@ impl Game { }); // Clear the screen - eadk::display::push_rect_uniform(eadk::display::SCREEN_RECT, MENU_BACKGROUND_COLOR); + nadk::display::push_rect_uniform(nadk::display::SCREEN_RECT, MENU_BACKGROUND_COLOR); self.timing_manager.reset(); @@ -507,7 +507,7 @@ impl Game { self.timing_manager.update(); self.input_manager.update_timing(&self.timing_manager); - if self.input_manager.is_keydown(eadk::keyboard::Key::Back) { + if self.input_manager.is_keydown(nadk::keyboard::Key::Back) { return GameState::GoMainMenu; } @@ -544,7 +544,7 @@ impl Game { } self.renderer.draw_menu(&mut menu); - eadk::time::wait_milliseconds(50); + nadk::time::wait_milliseconds(50); } } @@ -574,7 +574,7 @@ impl Game { allow_margin: true, }); - eadk::display::push_rect_uniform(eadk::display::SCREEN_RECT, MENU_BACKGROUND_COLOR); + nadk::display::push_rect_uniform(nadk::display::SCREEN_RECT, MENU_BACKGROUND_COLOR); self.timing_manager.reset(); @@ -585,7 +585,7 @@ impl Game { menu.check_inputs(&self.input_manager); - if self.input_manager.is_keydown(eadk::keyboard::Key::Home) { + if self.input_manager.is_keydown(nadk::keyboard::Key::Home) { return GameState::Quit; } @@ -610,7 +610,7 @@ impl Game { menu.finish_buttons_handling(); self.renderer.draw_menu(&mut menu); - eadk::time::wait_milliseconds(50); + nadk::time::wait_milliseconds(50); } } } diff --git a/src/game/game_uis.rs b/src/game/game_uis.rs index deb380b..cbeaeb5 100644 --- a/src/game/game_uis.rs +++ b/src/game/game_uis.rs @@ -23,7 +23,7 @@ impl Game { fn player_inventory_survival_loop(&mut self) { // Clear the hud self.renderer - .draw_game(&mut self.world, &self.player, 0., &self.hud, false); + .draw_game(&mut self.world, &self.player, 0, &self.hud, false); let inventories = [ &mut self.player.inventory, @@ -102,15 +102,15 @@ impl Game { self.renderer.draw_game_ui(&mut ui); - eadk::display::wait_for_vblank(); - eadk::time::wait_milliseconds(50); + nadk::display::wait_for_vblank(); + nadk::time::wait_milliseconds(50); } } fn player_inventory_creative_loop(&mut self) { // Clear the hud self.renderer - .draw_game(&mut self.world, &self.player, 0., &self.hud, false); + .draw_game(&mut self.world, &self.player, 0, &self.hud, false); let mut creative_inventory = Inventory::new(21); @@ -188,8 +188,8 @@ impl Game { self.renderer.draw_game_ui(&mut ui); - eadk::display::wait_for_vblank(); - eadk::time::wait_milliseconds(50); + nadk::display::wait_for_vblank(); + nadk::time::wait_milliseconds(50); } } } diff --git a/src/game_ui.rs b/src/game_ui.rs index b3d35f6..51b5862 100644 --- a/src/game_ui.rs +++ b/src/game_ui.rs @@ -2,7 +2,7 @@ use nalgebra::Vector2; use crate::{ constants::ItemType, - eadk::keyboard::Key, + nadk::keyboard::Key, input_manager::InputManager, inventory::{Inventory, ItemStack}, }; diff --git a/src/hud.rs b/src/hud.rs index a51448c..a76c9c1 100644 --- a/src/hud.rs +++ b/src/hud.rs @@ -17,14 +17,14 @@ impl Hud { } } pub fn update(&mut self, input_manager: &InputManager, player: &Player) { - if input_manager.is_just_pressed(crate::eadk::keyboard::Key::LeftParenthesis) { + if input_manager.is_just_pressed(crate::nadk::keyboard::Key::LeftParenthesis) { if self.selected_slot == 0 { self.selected_slot = 5; } else { self.selected_slot -= 1; } } - if input_manager.is_just_pressed(crate::eadk::keyboard::Key::RightParenthesis) { + if input_manager.is_just_pressed(crate::nadk::keyboard::Key::RightParenthesis) { if self.selected_slot == 5 { self.selected_slot = 0; } else { @@ -32,7 +32,7 @@ impl Hud { } } - if input_manager.is_just_pressed(crate::eadk::keyboard::Key::Dot) { + if input_manager.is_just_pressed(crate::nadk::keyboard::Key::Dot) { self.show_debug = !self.show_debug; } diff --git a/src/input_manager.rs b/src/input_manager.rs index bd83b32..2cfc8e1 100644 --- a/src/input_manager.rs +++ b/src/input_manager.rs @@ -1,7 +1,7 @@ use enum_iterator::all; use crate::{ - eadk::{ + nadk::{ self, keyboard::{Key, KeyboardState}, }, @@ -33,7 +33,7 @@ impl InputManager { pub fn update(&mut self) { self.last_keyboard_state = self.keyboard_state; - self.keyboard_state = eadk::keyboard::KeyboardState::scan(); + self.keyboard_state = nadk::keyboard::KeyboardState::scan(); self.just_pressed = self .keyboard_state .get_just_pressed(self.last_keyboard_state); @@ -87,16 +87,16 @@ impl InputManager { } pub fn wait_delay_or_ok(&mut self, delay_ms: usize) { - while self.is_keydown(eadk::keyboard::Key::Ok) { + while self.is_keydown(nadk::keyboard::Key::Ok) { self.update(); - eadk::time::wait_milliseconds(100); + nadk::time::wait_milliseconds(100); } for _ in 0..delay_ms / 50 { self.update(); - if self.is_just_pressed(eadk::keyboard::Key::Ok) { + if self.is_just_pressed(nadk::keyboard::Key::Ok) { break; } - eadk::time::wait_milliseconds(50); + nadk::time::wait_milliseconds(50); } } } diff --git a/src/main.rs b/src/main.rs index 7e0bfd5..51aa906 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,14 +4,12 @@ #![feature(const_trait_impl)] #[macro_use] -mod eadk; +mod nadk; -mod game; -mod renderer; -mod world; mod camera; mod constants; mod entity; +mod game; mod game_ui; mod hud; mod input_manager; @@ -20,9 +18,11 @@ mod menu; mod misc; mod physic; mod player; +mod renderer; mod save_manager; mod settings; mod timing; +mod world; use game::Game; @@ -31,14 +31,12 @@ setup_allocator!(); configure_app!(b"Numcraft\0", 9, "../target/assets/icon.nwi", 3437); #[unsafe(no_mangle)] -fn main() -> isize { +fn main() { init_heap!(); - eadk::utils::wait_ok_released(); + nadk::utils::wait_ok_released(); let mut game = Game::new(); game.main_loop(); - - 0 } diff --git a/src/menu.rs b/src/menu.rs index 172a411..fe8dc05 100644 --- a/src/menu.rs +++ b/src/menu.rs @@ -4,7 +4,7 @@ calc_use!(alloc::vec::Vec); use nalgebra::Vector2; -use crate::{eadk::keyboard::Key, input_manager::InputManager}; +use crate::{nadk::keyboard::Key, input_manager::InputManager}; pub enum MenuElement { /// A simple button diff --git a/src/nadk/adresses.rs b/src/nadk/adresses.rs new file mode 100644 index 0000000..2087103 --- /dev/null +++ b/src/nadk/adresses.rs @@ -0,0 +1,58 @@ +/// Return the size of the heap. +#[inline(always)] +pub fn heap_size() -> usize { + #[cfg(feature = "epsilon")] + { + 100_000 + } + + #[cfg(feature = "upsilon")] + { + unsafe {_heap_size as usize} + } +} + +/// Return the start adress of the heap +#[inline(always)] +pub fn heap_start() -> usize { + #[cfg(feature = "upsilon")] + unsafe { + _heap_base as usize + } + + #[cfg(feature = "epsilon")] + { + core::ptr::addr_of_mut!(_heap_start) as usize + } +} + +#[cfg(feature = "upsilon")] +unsafe extern "C" { + pub static mut _heap_base: *mut u8; + pub static mut _heap_size: u32; +} + +#[cfg(feature = "epsilon")] +unsafe extern "C" { + pub static mut _heap_start: u8; + pub static mut _heap_end: u8; +} + +#[cfg(feature = "upsilon")] +#[unsafe(no_mangle)] +#[inline(always)] +pub extern "C" fn setjmp(_: u32) -> u32 { + return 0; +} + +#[cfg(feature = "upsilon")] +#[unsafe(no_mangle)] +#[inline(always)] +pub extern "C" fn longjmp(_: u32, _: u32) {} + +#[cfg(feature = "upsilon")] +#[unsafe(no_mangle)] +#[inline(always)] +pub extern "C" fn extapp_main() { + crate::main(); +} diff --git a/src/eadk/backlight.rs b/src/nadk/backlight.rs similarity index 71% rename from src/eadk/backlight.rs rename to src/nadk/backlight.rs index c1bd61b..0e6032f 100644 --- a/src/eadk/backlight.rs +++ b/src/nadk/backlight.rs @@ -1,15 +1,23 @@ /// Set the brightness level of the screen's backlight. +#[inline(always)] pub fn set_brightness(brightness: u8) { + #[cfg(feature = "epsilon")] unsafe { eadk_backlight_set_brightness(brightness); } } /// Return the brightness level of the screen's backlight. +#[inline(always)] pub fn get_brightness() -> u8 { + #[cfg(feature = "epsilon")] unsafe { eadk_backlight_brightness() } + + #[cfg(feature = "upsilon")] + 0 } +#[cfg(feature = "epsilon")] unsafe extern "C" { fn eadk_backlight_set_brightness(brightness: u8); fn eadk_backlight_brightness() -> u8; diff --git a/src/eadk/display.rs b/src/nadk/display.rs similarity index 67% rename from src/eadk/display.rs rename to src/nadk/display.rs index 2638c25..5d12736 100644 --- a/src/eadk/display.rs +++ b/src/nadk/display.rs @@ -90,9 +90,15 @@ impl ScreenPoint { /// Fill the screen rect defined by `rect` with the given pixels. pub fn push_rect(rect: ScreenRect, pixels: &[Color565]) { + #[cfg(feature = "epsilon")] unsafe { eadk_display_push_rect(rect, pixels.as_ptr()); } + + #[cfg(feature = "upsilon")] + unsafe { + extapp_pushRect(rect.x, rect.y, rect.width, rect.height, pixels.as_ptr()); + } } /// Fetch pixels from the given rect from the screen. The size of the returned vector will be `rect.width * rect.height` @@ -103,24 +109,48 @@ pub fn pull_rect(rect: ScreenRect) -> Vec { vec.push(COLOR_BLACK); } + #[cfg(feature = "epsilon")] unsafe { eadk_display_pull_rect(rect, vec.as_mut_slice().as_mut_ptr()); } + + #[cfg(feature = "upsilon")] + unsafe { + extapp_pullRect( + rect.x, + rect.y, + rect.width, + rect.height, + vec.as_mut_slice().as_mut_ptr(), + ); + } vec } /// Fill the screen rect defined by `rect` with the given color. pub fn push_rect_uniform(rect: ScreenRect, color: Color565) { + #[cfg(feature = "epsilon")] unsafe { eadk_display_push_rect_uniform(rect, color); } + + #[cfg(feature = "upsilon")] + unsafe { + extapp_pushRectUniform(rect.x, rect.y, rect.width, rect.height, color); + } } -/// Wait until the screen is refreshed. The maximum FPS is 40 on actual hardware. +/// Wait until the screen is ed. The maximum FPS is 40 on actual hardware. pub fn wait_for_vblank() { + #[cfg(feature = "epsilon")] unsafe { eadk_display_wait_for_vblank(); } + + #[cfg(feature = "upsilon")] + unsafe { + extapp_waitForVBlank(); + } } /// Draw a string to the screen. @@ -132,6 +162,7 @@ pub fn draw_string( background_color: Color565, ) -> Option<()> { let c_string = CString::new(text).ok()?; + #[cfg(feature = "epsilon")] unsafe { eadk_display_draw_string( c_string.as_ptr(), @@ -141,9 +172,34 @@ pub fn draw_string( background_color, ) } + + #[cfg(feature = "upsilon")] + unsafe { + if large_font { + extapp_drawTextLarge( + c_string.as_ptr(), + point.x, + point.y, + text_color, + background_color, + false, + ) + } else { + extapp_drawTextSmall( + c_string.as_ptr(), + point.x, + point.y, + text_color, + background_color, + false, + ) + } + } + Some(()) } +#[cfg(feature = "epsilon")] unsafe extern "C" { fn eadk_display_push_rect_uniform(rect: ScreenRect, color: Color565); fn eadk_display_push_rect(rect: ScreenRect, color: *const Color565); @@ -157,3 +213,26 @@ unsafe extern "C" { background_color: Color565, ); } + +unsafe extern "C" { + fn extapp_pushRectUniform(x: u16, y: u16, w: u16, h: u16, color: Color565); + fn extapp_pushRect(x: u16, y: u16, w: u16, h: u16, color: *const Color565); + fn extapp_waitForVBlank() -> bool; + fn extapp_pullRect(x: u16, y: u16, w: u16, h: u16, color: *mut Color565); + fn extapp_drawTextLarge( + text: *const c_char, + x: u16, + y: u16, + text_color: Color565, + background_color: Color565, + fake: bool, + ); + fn extapp_drawTextSmall( + text: *const c_char, + x: u16, + y: u16, + text_color: Color565, + background_color: Color565, + fake: bool, + ); +} diff --git a/src/eadk/keyboard.rs b/src/nadk/keyboard.rs similarity index 95% rename from src/eadk/keyboard.rs rename to src/nadk/keyboard.rs index 0959e3c..48db51a 100644 --- a/src/eadk/keyboard.rs +++ b/src/nadk/keyboard.rs @@ -1,6 +1,6 @@ use enum_iterator::Sequence; -use crate::eadk::time; +use crate::nadk::time; /// A key of the calculator's keyboard. #[derive(Clone, Copy, PartialEq, Eq, Sequence, Debug)] @@ -60,7 +60,7 @@ impl Key { /// With alpha active and shift inactive, you will get uppercase letters. /// With only shift active, you will get special characters. /// If none of alpha and shift are active, you will get digits. - /// You should expect the same behavior as the Epsilon's Python app. + /// You should expect the same behavior as the Epsilon's Python app. pub fn get_matching_char(&self, shift_active: bool, alpha_active: bool) -> Option { if alpha_active && !shift_active { match *self { @@ -173,7 +173,15 @@ pub struct KeyboardState(u64); impl KeyboardState { /// Scan the keyboard. pub fn scan() -> Self { - KeyboardState(unsafe { eadk_keyboard_scan() }) + #[cfg(feature = "epsilon")] + { + KeyboardState(unsafe { eadk_keyboard_scan() }) + } + + #[cfg(feature = "upsilon")] + { + KeyboardState(unsafe { extapp_scanKeyboard() }) + } } /// Return true if the given key was pressed when scan was called. @@ -265,6 +273,12 @@ pub fn wait_until_pressed(key: Key) { } } +#[cfg(feature = "epsilon")] unsafe extern "C" { fn eadk_keyboard_scan() -> u64; } + +#[cfg(feature = "upsilon")] +unsafe extern "C" { + fn extapp_scanKeyboard() -> u64; +} diff --git a/src/eadk/macros.rs b/src/nadk/macros.rs similarity index 85% rename from src/eadk/macros.rs rename to src/nadk/macros.rs index a7cddb9..25d42a7 100644 --- a/src/eadk/macros.rs +++ b/src/nadk/macros.rs @@ -3,16 +3,19 @@ macro_rules! configure_app { #[used] #[cfg(target_os = "none")] #[unsafe(link_section = ".rodata.eadk_app_name")] + #[cfg(feature = "epsilon")] pub static EADK_APP_NAME: [u8; $app_name_size] = *$app_name; #[used] #[cfg(target_os = "none")] #[unsafe(link_section = ".rodata.eadk_api_level")] + #[cfg(feature = "epsilon")] pub static EADK_APP_API_LEVEL: u32 = 0; #[used] #[cfg(target_os = "none")] #[unsafe(link_section = ".rodata.eadk_app_icon")] + #[cfg(feature = "epsilon")] pub static EADK_APP_ICON: [u8; $icon_size] = *include_bytes!($icon_path); }; } @@ -23,10 +26,6 @@ macro_rules! setup_allocator { #[cfg(target_os = "none")] use cortex_m; - #[cfg(target_os = "none")] - use crate::eadk::adresses::HEAP_START; - #[cfg(target_os = "none")] - use eadk::adresses::heap_size; #[cfg(target_os = "none")] use embedded_alloc::LlffHeap as Heap; @@ -43,8 +42,7 @@ macro_rules! init_heap { () => { #[cfg(target_os = "none")] { - let heap_size: usize = heap_size(); - unsafe { HEAP.init(HEAP_START as usize, heap_size) } + unsafe { HEAP.init(nadk::adresses::heap_start(), nadk::adresses::heap_size()) } } }; } @@ -63,4 +61,4 @@ macro_rules! sim_use { #[cfg(not(target_os = "none"))] use $crate_name; }; -} \ No newline at end of file +} diff --git a/src/eadk/mod.rs b/src/nadk/mod.rs similarity index 100% rename from src/eadk/mod.rs rename to src/nadk/mod.rs diff --git a/src/eadk/panic_handler.rs b/src/nadk/panic_handler.rs similarity index 91% rename from src/eadk/panic_handler.rs rename to src/nadk/panic_handler.rs index 5327a2c..eba84c6 100644 --- a/src/eadk/panic_handler.rs +++ b/src/nadk/panic_handler.rs @@ -3,7 +3,7 @@ use core::panic::PanicInfo; calc_use!(alloc::string::String); calc_use!(alloc::format); -use crate::eadk::display::{Color565, ScreenPoint, ScreenRect, draw_string, push_rect_uniform}; +use crate::nadk::display::{Color565, ScreenPoint, ScreenRect, draw_string, push_rect_uniform}; #[cfg(target_os = "none")] fn write_wrapped(text: &str, limit: usize) { @@ -46,6 +46,6 @@ fn panic(panic: &PanicInfo<'_>) -> ! { write_wrapped(format!("{}", panic).as_str(), 42); loop { - crate::eadk::time::wait_milliseconds(50); + crate::nadk::time::wait_milliseconds(50); } } diff --git a/src/nadk/random.rs b/src/nadk/random.rs new file mode 100644 index 0000000..37fb19f --- /dev/null +++ b/src/nadk/random.rs @@ -0,0 +1,88 @@ +static mut COUNTER: u64 = 0; + +/// Give a random u32. +#[inline(always)] +pub fn get_random_u32() -> u32 { + #[cfg(feature = "epsilon")] + unsafe { + eadk_random() + } + #[cfg(feature = "upsilon")] + { + (get_random_u64() >> 32) as u32 + } +} + +/// Give a random u64. +#[inline(always)] +pub fn get_random_u64() -> u64 { + #[cfg(feature = "epsilon")] + unsafe { + (eadk_random() as u64) << 32 | (eadk_random() as u64) + } + + #[cfg(feature = "upsilon")] + { + // Wait! yes, I'm aware that accessing mutable static variables is unsafe BUT the Numworks calculator has a single thread so no multi threading. + let mut nbr: u64 = unsafe { extapp_millis() + COUNTER << 8 }; + nbr ^= nbr << 13; + nbr ^= nbr >> 7; + nbr ^= nbr << 17; + + nbr + } +} + +/// Give a random u16. +#[inline(always)] +pub fn get_random_u16() -> u16 { + #[cfg(feature = "epsilon")] + unsafe { + (eadk_random() >> 16) as u16 + } + + #[cfg(feature = "upsilon")] + { + (get_random_u64() >> 48) as u16 + } +} + +/// Give a random u8. +#[inline(always)] +pub fn get_random_u8() -> u8 { + #[cfg(feature = "epsilon")] + unsafe { + (eadk_random() >> 24) as u8 + } + + #[cfg(feature = "upsilon")] + { + (get_random_u64() >> 56) as u8 + } +} + +/// Give a random f32 between 0 and 1. +pub fn get_random_decimal() -> f32 { + unsafe { + get_random_u32() as f32 / u32::MAX as f32 + } +} + +/// Give a random number between start (included) and end (excluded). +pub fn get_random_in_range(start: u32, stop: u32) -> u32 { + assert!(start < stop, "Start must be smaller than stop"); + let mut random_u32 = unsafe { get_random_u32() }; + random_u32 %= stop - start; + random_u32 += start; + random_u32 +} + +#[cfg(feature = "epsilon")] +unsafe extern "C" { + fn eadk_random() -> u32; +} + +#[cfg(feature = "upsilon")] +unsafe extern "C" { + fn extapp_millis() -> u64; +} diff --git a/src/eadk/storage/mod.rs b/src/nadk/storage/mod.rs similarity index 65% rename from src/eadk/storage/mod.rs rename to src/nadk/storage/mod.rs index 077a832..c1c20af 100644 --- a/src/eadk/storage/mod.rs +++ b/src/nadk/storage/mod.rs @@ -3,16 +3,22 @@ calc_use!(alloc::ffi); calc_use!(alloc::string::String); calc_use!(alloc::vec::Vec); -#[cfg(not(target_os = "none"))] -use std::fs; +sim_use!(std::fs); /// Write a binary file to the records. pub fn file_write(filename: &str, content: &[u8]) -> Option<()> { #[cfg(target_os = "none")] { let c_string = ffi::CString::new(filename).unwrap(); + + #[cfg(feature = "epsilon")] let result = unsafe { extapp_fileWrite(c_string.as_ptr(), content.as_ptr(), content.len()) }; + + #[cfg(feature = "upsilon")] + let result = + unsafe { extapp_fileWrite(c_string.as_ptr(), content.as_ptr(), content.len(), 0) }; + if result { Some(()) } else { None } } #[cfg(not(target_os = "none"))] @@ -29,7 +35,15 @@ pub fn file_exists(filename: &str) -> bool { #[cfg(target_os = "none")] { let c_string = ffi::CString::new(filename).unwrap(); - unsafe { extapp_fileExists(c_string.as_ptr()) } + #[cfg(feature = "epsilon")] + unsafe { + extapp_fileExists(c_string.as_ptr()) + } + + #[cfg(feature = "upsilon")] + unsafe { + extapp_fileExists(c_string.as_ptr(), 0) + } } #[cfg(not(target_os = "none"))] { @@ -43,9 +57,15 @@ pub fn file_read(filename: &str) -> Option> { { let c_string = ffi::CString::new(filename).unwrap(); let mut lenght: usize = 0; + + #[cfg(feature = "epsilon")] let array_pointer = unsafe { extapp_fileRead(c_string.as_ptr(), &mut lenght as *mut usize) }; + #[cfg(feature = "upsilon")] + let array_pointer = + unsafe { extapp_fileRead(c_string.as_ptr(), &mut lenght as *mut usize, 0) }; + if array_pointer.is_null() { return None; } @@ -64,11 +84,15 @@ pub fn file_read_slice(filename: &str, start: usize, mut slice_lenght: usize) -> { let c_string = ffi::CString::new(filename).unwrap(); let mut lenght: usize = 0; + + #[cfg(feature = "epsilon")] let array_pointer = unsafe { - extapp_fileRead( - c_string.as_ptr(), - &mut lenght as *mut usize, - ).offset(start as isize) + extapp_fileRead(c_string.as_ptr(), &mut lenght as *mut usize).offset(start as isize) + }; + + #[cfg(feature = "upsilon")] + let array_pointer = unsafe { + extapp_fileRead(c_string.as_ptr(), &mut lenght as *mut usize, 0).offset(start as isize) }; if array_pointer.is_null() { @@ -94,7 +118,13 @@ pub fn file_erase(filename: &str) -> Option<()> { #[cfg(target_os = "none")] { let c_string = ffi::CString::new(filename).unwrap(); + + #[cfg(feature = "epsilon")] let result = unsafe { extapp_fileErase(c_string.as_ptr()) }; + + #[cfg(feature = "upsilon")] + let result = unsafe { extapp_fileErase(c_string.as_ptr(), 0) }; + if result { Some(()) } else { None } } #[cfg(not(target_os = "none"))] @@ -111,11 +141,20 @@ pub fn file_list_with_extension(max_records: usize, extension: &str) -> Vec = Vec::new(); @@ -132,41 +171,44 @@ pub fn file_list_with_extension(max_records: usize, extension: &str) -> Vec = Vec::new(); - if let Ok(entries) = fs::read_dir("simulator/storage") { - for entry in entries { - if files.len() < max_records { - let entry = entry.unwrap(); - let name = entry.file_name().into_string().unwrap(); - if name.ends_with(extension) { - files.push(name); - } + for entry in fs::read_dir("simulator/storage").unwrap() { + if files.len() < max_records { + let entry = entry.unwrap(); + let name = entry.file_name().into_string().unwrap(); + if name.ends_with(extension) { + files.push(name); } } - - files - } else { - Vec::new() } + + files } } pub enum CalculatorModel { Unknown, - N0110N0115, - N0120, + EpsilonN0110N0115, + EpsilonN0120, + Upsilon, Simulator, } /// Return the model name of the calculator or Simulator on the Simulator. pub fn get_calculator_model() -> CalculatorModel { #[cfg(target_os = "none")] + #[cfg(feature = "epsilon")] { match unsafe { extapp_calculatorModel() } { _ => CalculatorModel::Unknown, - 1 => CalculatorModel::N0110N0115, - 2 => CalculatorModel::N0120, + 1 => CalculatorModel::EpsilonN0110N0115, + 2 => CalculatorModel::EpsilonN0120, } } + #[cfg(target_os = "none")] + #[cfg(feature = "upsilon")] + { + CalculatorModel::Upsilon + } #[cfg(not(target_os = "none"))] { CalculatorModel::Simulator @@ -174,6 +216,7 @@ pub fn get_calculator_model() -> CalculatorModel { } #[cfg(target_os = "none")] +#[cfg(feature = "epsilon")] unsafe extern "C" { fn extapp_fileWrite(filename: *const u8, content: *const u8, len: usize) -> bool; fn extapp_fileExists(filename: *const u8) -> bool; @@ -186,3 +229,23 @@ unsafe extern "C" { ) -> isize; fn extapp_calculatorModel() -> u8; } + +#[cfg(target_os = "none")] +#[cfg(feature = "upsilon")] +unsafe extern "C" { + fn extapp_fileWrite( + filename: *const u8, + content: *const u8, + len: usize, + storage: isize, + ) -> bool; + fn extapp_fileExists(filename: *const u8, storage: isize) -> bool; + fn extapp_fileRead(filename: *const u8, len: *mut usize, storage: isize) -> *const u8; + fn extapp_fileErase(filename: *const u8, storage: isize) -> bool; + fn extapp_fileListWithExtension( + filename: *mut *mut u8, + maxrecord: isize, + extension: *const u8, + storage: isize, + ) -> isize; +} diff --git a/src/eadk/storage/storage.c b/src/nadk/storage/storage.c similarity index 100% rename from src/eadk/storage/storage.c rename to src/nadk/storage/storage.c diff --git a/src/eadk/storage/storage.h b/src/nadk/storage/storage.h similarity index 100% rename from src/eadk/storage/storage.h rename to src/nadk/storage/storage.h diff --git a/src/eadk/time.rs b/src/nadk/time.rs similarity index 51% rename from src/eadk/time.rs rename to src/nadk/time.rs index 3821f16..e1bd391 100644 --- a/src/eadk/time.rs +++ b/src/nadk/time.rs @@ -1,41 +1,62 @@ -/// Wait for the given time in micro seconds. This functions seems not implemented on the simulator so it is replaced by eadk_timing_msleep instead. -pub fn wait_microseconds(delay: u32) { - #[cfg(target_os = "none")] - unsafe { - eadk_timing_usleep(delay); - } - #[cfg(not(target_os = "none"))] - unsafe { - eadk_timing_msleep(delay / 1000); - } -} - /// Wait for the given delay in seconds. The precision is 0.001 second. pub fn wait_seconds(delay: f32) { + #[cfg(feature = "epsilon")] unsafe { eadk_timing_msleep((delay * 1000.) as u32); } + + #[cfg(feature = "upsilon")] + unsafe { + extapp_msleep((delay * 1000.) as u32) + } } /// Wait for the given delay in milliseconds. pub fn wait_milliseconds(delay: u32) { + #[cfg(feature = "epsilon")] unsafe { eadk_timing_msleep(delay); } + #[cfg(feature = "upsilon")] + unsafe { + extapp_msleep(delay); + } } /// Return the time since the startup of the calculator in milliseconds. (No warranty) pub fn get_current_time_millis() -> u64 { - unsafe { eadk_timing_millis() } + #[cfg(feature = "epsilon")] + unsafe { + eadk_timing_millis() + } + + #[cfg(feature = "upsilon")] + unsafe { + extapp_millis() + } } /// Return the time since the startup of the calculator in seconds. (No warranty) pub fn get_current_time_seconds() -> f32 { - unsafe { eadk_timing_millis() as f32 * 0.001} + #[cfg(feature = "epsilon")] + unsafe { + eadk_timing_millis() as f32 * 0.001 + } + + #[cfg(feature = "upsilon")] + unsafe { + extapp_millis() as f32 * 0.001 + } } +#[cfg(feature = "epsilon")] unsafe extern "C" { - fn eadk_timing_usleep(delay: u32); fn eadk_timing_msleep(delay: u32); fn eadk_timing_millis() -> u64; } + +#[cfg(feature = "upsilon")] +unsafe extern "C" { + fn extapp_msleep(us: u32); + fn extapp_millis() -> u64; +} diff --git a/src/eadk/utils.rs b/src/nadk/utils.rs similarity index 91% rename from src/eadk/utils.rs rename to src/nadk/utils.rs index 30cc699..5254cb1 100644 --- a/src/eadk/utils.rs +++ b/src/nadk/utils.rs @@ -1,4 +1,4 @@ -use crate::eadk::{display, keyboard, time}; +use crate::nadk::{display, keyboard, time}; calc_use!(alloc::string::String); calc_use!(alloc::vec::Vec); @@ -28,5 +28,5 @@ pub fn log(text: &[&str]) { #[inline(always)] pub fn refresh_simulator() { #[cfg(not(target_os = "none"))] - crate::eadk::keyboard::KeyboardState::scan(); + crate::nadk::keyboard::KeyboardState::scan(); } diff --git a/src/player.rs b/src/player.rs index 2818762..afcb0ef 100644 --- a/src/player.rs +++ b/src/player.rs @@ -11,7 +11,7 @@ use crate::{ BlockType, EntityType, player::{FLY_SPEED, JUMP_FORCE, MAX_WALKING_VELOCITY, WALK_FORCE}, }, - eadk, + nadk, entity::{Entity, item::ItemEntityCustomData}, game::GameMode, hud::Hud, @@ -95,8 +95,8 @@ impl Player { player_entity.rotation = *camera.get_rotation(); // Movements - if (input_manager.is_keydown(eadk::keyboard::Key::Up) && settings.reverse_controls) - || (input_manager.is_keydown(eadk::keyboard::Key::Toolbox) && !settings.reverse_controls) + if (input_manager.is_keydown(nadk::keyboard::Key::Up) && settings.reverse_controls) + || (input_manager.is_keydown(nadk::keyboard::Key::Toolbox) && !settings.reverse_controls) { // Forward let translation = sincosf(player_entity.rotation.y); @@ -108,8 +108,8 @@ impl Player { player_entity.velocity.z += translation.1 * delta * WALK_FORCE; } } - if (input_manager.is_keydown(eadk::keyboard::Key::Down) && settings.reverse_controls) - || (input_manager.is_keydown(eadk::keyboard::Key::Comma) && !settings.reverse_controls) + if (input_manager.is_keydown(nadk::keyboard::Key::Down) && settings.reverse_controls) + || (input_manager.is_keydown(nadk::keyboard::Key::Comma) && !settings.reverse_controls) { // Backward let translation = sincosf(player_entity.rotation.y); @@ -121,8 +121,8 @@ impl Player { player_entity.velocity.z -= translation.1 * delta * WALK_FORCE; } } - if (input_manager.is_keydown(eadk::keyboard::Key::Left) && settings.reverse_controls) - || (input_manager.is_keydown(eadk::keyboard::Key::Imaginary) && !settings.reverse_controls) + if (input_manager.is_keydown(nadk::keyboard::Key::Left) && settings.reverse_controls) + || (input_manager.is_keydown(nadk::keyboard::Key::Imaginary) && !settings.reverse_controls) { // Left let translation = sincosf(player_entity.rotation.y + PI / 2.0); @@ -134,8 +134,8 @@ impl Player { player_entity.velocity.z += translation.1 * delta * WALK_FORCE; } } - if (input_manager.is_keydown(eadk::keyboard::Key::Right) && settings.reverse_controls) - || (input_manager.is_keydown(eadk::keyboard::Key::Power) && !settings.reverse_controls) + if (input_manager.is_keydown(nadk::keyboard::Key::Right) && settings.reverse_controls) + || (input_manager.is_keydown(nadk::keyboard::Key::Power) && !settings.reverse_controls) { // Right let translation = sincosf(player_entity.rotation.y + PI / 2.0); @@ -147,7 +147,7 @@ impl Player { player_entity.velocity.z -= translation.1 * delta * WALK_FORCE; } } - if input_manager.is_keydown(eadk::keyboard::Key::Shift) { + if input_manager.is_keydown(nadk::keyboard::Key::Shift) { // Up if game_mode == GameMode::Creative { player_entity.pos.y += delta * FLY_SPEED; @@ -155,7 +155,7 @@ impl Player { player_entity.velocity.y += JUMP_FORCE; } } - if input_manager.is_keydown(eadk::keyboard::Key::Exp) { + if input_manager.is_keydown(nadk::keyboard::Key::Exp) { // Down if game_mode == GameMode::Creative { player_entity.pos.y -= delta * FLY_SPEED; @@ -171,7 +171,7 @@ impl Player { // Break Block if game_mode == GameMode::Creative { - if input_manager.is_just_pressed(eadk::keyboard::Key::Back) { + if input_manager.is_just_pressed(nadk::keyboard::Key::Back) { if let Some(result) = &self.ray_cast_result { world .chunks_manager @@ -179,7 +179,7 @@ impl Player { } } } else { - if input_manager.is_keydown(eadk::keyboard::Key::Back) { + if input_manager.is_keydown(nadk::keyboard::Key::Back) { if let Some(ray_cast) = &self.ray_cast_result { if self .breaking_block_pos @@ -208,7 +208,7 @@ impl Player { } } - if input_manager.is_just_pressed(eadk::keyboard::Key::Ok) { + if input_manager.is_just_pressed(nadk::keyboard::Key::Ok) { // Place Block if let Some(result) = &self.ray_cast_result { let block_pos = result.block_pos + result.face_dir.get_normal_vector(); diff --git a/src/renderer.rs b/src/renderer.rs index 303b433..cdbb52a 100644 --- a/src/renderer.rs +++ b/src/renderer.rs @@ -8,18 +8,18 @@ use core::{cmp::Ordering, f32, mem::swap}; use crate::{ camera::Camera, constants::{rendering::*, world::CHUNK_SIZE}, - eadk::display::{COLOR_BLACK, Color565}, + nadk::display::{COLOR_BLACK, Color565}, renderer::mesh::SmallTriangle2D, }; mod engine_3d; +mod entity; +mod frustum; mod hud; mod menus; -mod ui; -mod frustum; pub mod mesh; mod misc; -mod entity; +mod ui; // Screen size related constants diff --git a/src/renderer/engine_3d.rs b/src/renderer/engine_3d.rs index e7a443f..f823417 100644 --- a/src/renderer/engine_3d.rs +++ b/src/renderer/engine_3d.rs @@ -1,6 +1,6 @@ use crate::{ constants::get_quad_color_from_texture_id, - eadk::display::{ScreenRect, push_rect, wait_for_vblank}, + nadk::display::{ScreenRect, push_rect, wait_for_vblank}, hud::Hud, player::Player, renderer::{ @@ -505,12 +505,10 @@ impl Renderer { &mut self, world: &mut World, player: &Player, - fps_count: f32, + frame_time: u64, hud: &Hud, draw_hud: bool, ) { - self.triangles_to_render.clear(); - let mat_view = self.get_mat_view(); let frustum = Frustum::new( @@ -577,7 +575,7 @@ impl Renderer { self.draw_flat_model_entities(world, &mat_view, x, y, &frustum); if draw_hud { - self.draw_hud(hud, fps_count, x, y); + self.draw_hud(hud, frame_time, x, y); } push_rect( @@ -594,5 +592,6 @@ impl Renderer { if self.enable_vsync { wait_for_vblank(); } + self.triangles_to_render.clear(); } } diff --git a/src/renderer/hud.rs b/src/renderer/hud.rs index e3fffe9..acde836 100644 --- a/src/renderer/hud.rs +++ b/src/renderer/hud.rs @@ -1,25 +1,22 @@ use crate::{ constants::{ItemType, color_palette::GAMEUI_SLOT_COLOR}, - eadk::display::ScreenRect, + nadk::display::ScreenRect, hud::Hud, - renderer::*, + renderer::{misc::UnBoundedScreenRect, *}, }; impl Renderer { - pub fn draw_hud(&mut self, hud: &Hud, fps_count: f32, tile_x: usize, tile_y: usize) { + pub fn draw_hud(&mut self, hud: &Hud, frame_time: u64, tile_x: usize, tile_y: usize) { if tile_x == 0 && tile_y == 0 { if hud.show_debug { - self.draw_string( - format!("FPS:{fps_count:.2}").as_str(), - &Vector2::new(10, 10), - ); + self.draw_string(format!("f:{frame_time}").as_str(), &Vector2::new(2, 2)); self.draw_string( - format!("Tris:{}", self.triangles_to_render.len()).as_str(), - &Vector2::new(10, 30), + format!("t:{}", self.triangles_to_render.len()).as_str(), + &Vector2::new(2, 22), ); - self.draw_string( + /*self.draw_string( format!( "{:.1},{:.1},{:.1}", self.camera.get_pos().x, @@ -28,7 +25,7 @@ impl Renderer { ) .as_str(), &Vector2::new(10, 50), - ); + );*/ } } @@ -40,38 +37,54 @@ impl Renderer { ); }; - if tile_x == 0 && tile_y == 0 { + if tile_x == 1 && tile_y == 1 { draw_cross( (SCREEN_TILE_WIDTH - CROSS_WIDTH / 2) as isize, (SCREEN_TILE_HEIGHT - CROSS_HEIGHT / 2) as isize, ) } - if tile_x == 1 && tile_y == 0 { + if tile_x == 2 && tile_y == 1 { draw_cross( -((CROSS_WIDTH / 2) as isize), (SCREEN_TILE_HEIGHT - CROSS_HEIGHT / 2) as isize, ) } - if tile_x == 1 && tile_y == 1 { + if tile_x == 2 && tile_y == 2 { draw_cross( -((CROSS_WIDTH / 2) as isize), -((CROSS_HEIGHT / 2) as isize), ); } - if tile_x == 0 && tile_y == 1 { + if tile_x == 1 && tile_y == 2 { draw_cross( (SCREEN_TILE_WIDTH - CROSS_WIDTH / 2) as isize, -((CROSS_HEIGHT / 2) as isize), ); - self.draw_slot_frame_buffer(Vector2::new(60, 85), hud, 0); - self.draw_slot_frame_buffer(Vector2::new(94, 85), hud, 1); - self.draw_slot_frame_buffer(Vector2::new(128, 85), hud, 2); + //self.draw_slot_frame_buffer(Vector2::new(94, 85), hud, 1); + //self.draw_slot_frame_buffer(Vector2::new(128, 85), hud, 2); } - if tile_x == 1 && tile_y == 1 { - self.draw_slot_frame_buffer(Vector2::new(2, 85), hud, 3); - self.draw_slot_frame_buffer(Vector2::new(36, 85), hud, 4); - self.draw_slot_frame_buffer(Vector2::new(70, 85), hud, 5); + + if tile_x == 0 && tile_y == 3 { + self.draw_slot_frame_buffer(Vector2::new(60, 20), hud, 0); + } + + if tile_x == 1 && tile_y == 3 { + self.draw_slot_frame_buffer(Vector2::new(-20, 20), hud, 0); + self.draw_slot_frame_buffer(Vector2::new(14, 20), hud, 1); + self.draw_slot_frame_buffer(Vector2::new(48, 20), hud, 2); + } + if tile_x == 2 && tile_y == 3 { + self.draw_slot_frame_buffer(Vector2::new(2, 20), hud, 3); + self.draw_slot_frame_buffer(Vector2::new(36, 20), hud, 4); + } + + if tile_x == 2 && tile_y == 3 { + self.draw_slot_frame_buffer(Vector2::new(70, 20), hud, 5); + } + + if tile_x == 3 && tile_y == 3 { + self.draw_slot_frame_buffer(Vector2::new(-10, 20), hud, 5); } self.draw_breaking_indicator(tile_x, tile_y, hud); @@ -80,10 +93,10 @@ impl Renderer { pub fn draw_breaking_indicator(&mut self, tile_x: usize, tile_y: usize, hud: &Hud) { if let Some(progress) = hud.breaking_progress { let bar_len = (40. * progress) as u16; - if tile_x == 0 && tile_y == 1 { + if tile_x == 1 && tile_y == 2 { self.push_rect_uniform_on_frame_buffer( ScreenRect { - x: 138, + x: 58, y: 18, width: 22, height: 9, @@ -92,7 +105,7 @@ impl Renderer { ); self.push_rect_uniform_on_frame_buffer( ScreenRect { - x: 140, + x: 60, y: 20, width: bar_len.min(20), height: 5, @@ -100,7 +113,7 @@ impl Renderer { Color565::from_rgb888(200, 200, 200), ); } - if tile_x == 1 && tile_y == 1 { + if tile_x == 2 && tile_y == 2 { self.push_rect_uniform_on_frame_buffer( ScreenRect { x: 0, @@ -162,8 +175,8 @@ impl Renderer { fn draw_scalled_tile_on_frame_buffer( &mut self, texture_id: u8, - pos: Vector2, - scale: usize, + pos: Vector2, + scale: isize, ) { let tileset_x = (texture_id % 16) as usize * 8; let tileset_y = (texture_id / 16) as usize * 8; @@ -176,12 +189,12 @@ impl Renderer { TILESET_DATA[texture_pixel_index + 1], ]); - self.push_rect_uniform_on_frame_buffer( - ScreenRect { - x: pos.x + (x * scale) as u16, - y: pos.y + (y * scale) as u16, - width: scale as u16, - height: scale as u16, + self.push_unbounded_rect_uniform_on_frame_buffer( + UnBoundedScreenRect { + x: pos.x + (x as isize * scale), + y: pos.y + (y as isize * scale), + width: scale, + height: scale, }, Color565 { value: pixel }, ); @@ -189,9 +202,9 @@ impl Renderer { } } - fn draw_slot_frame_buffer(&mut self, pos: Vector2, hud: &Hud, slot_index: usize) { - self.push_rect_uniform_on_frame_buffer( - ScreenRect { + fn draw_slot_frame_buffer(&mut self, pos: Vector2, hud: &Hud, slot_index: usize) { + self.push_unbounded_rect_uniform_on_frame_buffer( + UnBoundedScreenRect { x: pos.x, y: pos.y, width: 30, @@ -214,9 +227,9 @@ impl Renderer { let max_item_count = item_type.get_max_stack_amount(); if item_type != ItemType::Air && item_type.get_max_stack_amount() > 1 { - let item_bar_lenght = 24 * item_stack.get_amount() as u16 / max_item_count as u16; - self.push_rect_uniform_on_frame_buffer( - ScreenRect { + let item_bar_lenght = 24 * item_stack.get_amount() as isize / max_item_count as isize; + self.push_unbounded_rect_uniform_on_frame_buffer( + UnBoundedScreenRect { x: pos.x + 3, y: pos.y + 24, width: item_bar_lenght, @@ -224,8 +237,8 @@ impl Renderer { }, Color565::from_rgb888(100, 150, 255), ); - self.push_rect_uniform_on_frame_buffer( - ScreenRect { + self.push_unbounded_rect_uniform_on_frame_buffer( + UnBoundedScreenRect { x: pos.x + 3 + item_bar_lenght, y: pos.y + 24, width: 24 - item_bar_lenght, diff --git a/src/renderer/menus.rs b/src/renderer/menus.rs index f761d73..3d247e0 100644 --- a/src/renderer/menus.rs +++ b/src/renderer/menus.rs @@ -1,6 +1,6 @@ use crate::{ constants::color_palette::*, - eadk::{ + nadk::{ display::ScreenPoint, display::ScreenRect, display::{draw_string, push_rect_uniform, wait_for_vblank}, diff --git a/src/renderer/misc.rs b/src/renderer/misc.rs index e4afb68..8acec70 100644 --- a/src/renderer/misc.rs +++ b/src/renderer/misc.rs @@ -1,5 +1,5 @@ use crate::{ - eadk::display::{ + nadk::display::{ Color565, SCREEN_RECT, ScreenPoint, ScreenRect, draw_string, pull_rect, push_rect, push_rect_uniform, }, diff --git a/src/renderer/ui.rs b/src/renderer/ui.rs index 9dd8c00..eceb0da 100644 --- a/src/renderer/ui.rs +++ b/src/renderer/ui.rs @@ -3,7 +3,7 @@ use crate::{ ItemType, color_palette::{GAMEUI_SLOT_COLOR, GAMEUI_SLOT_DEFAULT_OUTLINE_COLOR}, }, - eadk::{ + nadk::{ self, display::{ COLOR_BLACK, ScreenPoint, ScreenRect, draw_string, pull_rect, push_rect, @@ -232,7 +232,7 @@ impl Renderer { } GameUIElements::Button { text, is_pressed } => todo!(), GameUIElements::Label { text } => { - eadk::display::draw_string( + nadk::display::draw_string( text, ScreenPoint { x, y }, false, @@ -241,7 +241,7 @@ impl Renderer { ); } GameUIElements::Arrow { filling } => { - eadk::display::push_rect_uniform( + nadk::display::push_rect_uniform( ScreenRect { x: element.pos.x + 2, y: element.pos.y + 12, @@ -252,7 +252,7 @@ impl Renderer { ); for i in 0..=10 { - eadk::display::push_rect_uniform( + nadk::display::push_rect_uniform( ScreenRect { x: element.pos.x + 18 + i, y: element.pos.y - (10 - i) + 2 + 12, @@ -352,7 +352,7 @@ impl Renderer { #[cfg(feature = "debug_ui")] { - eadk::display::draw_string( + nadk::display::draw_string( format!("{}", element_id).as_str(), Point { x: x + 2, y: y + 2 }, false, diff --git a/src/save_manager.rs b/src/save_manager.rs index e3f93c2..4f461df 100644 --- a/src/save_manager.rs +++ b/src/save_manager.rs @@ -9,9 +9,16 @@ use serde::{Deserialize, Serialize}; use crate::{ constants::{BlockType, save_manager::WORLD_VERSION, world::CHUNK_SIZE}, - eadk::{self, display::Color565, storage::{file_erase, file_exists, file_list_with_extension, file_read, file_read_slice, file_write}}, game::GameMode, inventory::Inventory, + nadk::{ + self, + display::Color565, + storage::{ + file_erase, file_exists, file_list_with_extension, file_read, file_read_slice, + file_write, + }, + }, player::Player, renderer::Renderer, world::{World, chunk::Chunk}, @@ -142,21 +149,18 @@ impl SaveManager { &["Unable to save.", "Cannot delete old save."], Color565::from_rgb888(255, 100, 100), ); - eadk::time::wait_milliseconds(3000); + nadk::time::wait_milliseconds(3000); } if file_write(file_name, &data).is_none() { Renderer::show_msg( &["Unable to save.", "Writing error."], Color565::from_rgb888(255, 100, 100), ); - eadk::time::wait_milliseconds(3000); + nadk::time::wait_milliseconds(3000); } } else { - Renderer::show_msg( - &["Unable to save."], - Color565::from_rgb888(255, 100, 100), - ); - eadk::time::wait_milliseconds(3000); + Renderer::show_msg(&["Unable to save."], Color565::from_rgb888(255, 100, 100)); + nadk::time::wait_milliseconds(3000); } } @@ -219,8 +223,7 @@ impl SaveManager { pub fn get_world_info(&self, filename: &String) -> Option { let raw_data = file_read_slice(filename, 0, 2)?; let world_info_size = u16::from_be_bytes([raw_data[0], raw_data[1]]); - let raw_data = - &file_read_slice(filename, 2, world_info_size as usize)?; + let raw_data = &file_read_slice(filename, 2, world_info_size as usize)?; if let Ok(world_info) = from_bytes::(&raw_data) { Some(world_info) diff --git a/src/settings.rs b/src/settings.rs index c0453f6..2c3352b 100644 --- a/src/settings.rs +++ b/src/settings.rs @@ -2,7 +2,7 @@ use postcard::from_bytes; use serde::{Deserialize, Serialize}; use crate::{ - constants::{rendering::*, save_manager::*}, eadk::storage::{file_erase, file_exists, file_read, file_write}, + constants::{rendering::*, save_manager::*}, nadk::storage::{file_erase, file_exists, file_read, file_write}, }; #[derive(Serialize, Deserialize)] diff --git a/src/timing.rs b/src/timing.rs index 92130f0..cf17a6d 100644 --- a/src/timing.rs +++ b/src/timing.rs @@ -1,21 +1,24 @@ -use crate::eadk; +use crate::nadk; pub struct TimingManager { last_timer: u64, delta_time: f32, + frame_time: u64, } impl TimingManager { pub fn new() -> Self { TimingManager { - last_timer: eadk::time::get_current_time_millis(), + last_timer: nadk::time::get_current_time_millis(), delta_time: 0.1, + frame_time: 1, } } pub fn update(&mut self) { - let current = eadk::time::get_current_time_millis(); - self.delta_time = (current - self.last_timer) as f32 / 1000.0; + let current = nadk::time::get_current_time_millis(); + self.frame_time = current - self.last_timer; + self.delta_time = self.frame_time as f32 / 1000.0; self.last_timer = current; } @@ -23,11 +26,15 @@ impl TimingManager { self.delta_time } + pub fn get_frame_time(&self) -> u64 { + self.frame_time + } pub fn get_fps(&self) -> f32 { return 1. / self.delta_time; } pub fn reset(&mut self) { - self.last_timer = eadk::time::get_current_time_millis(); + self.last_timer = nadk::time::get_current_time_millis(); + self.frame_time = 1; self.delta_time = 0.1; } } diff --git a/src/world.rs b/src/world.rs index 9d9cccf..20a9196 100644 --- a/src/world.rs +++ b/src/world.rs @@ -257,8 +257,8 @@ impl World { pub fn clear_entities(&mut self) { if self.loaded_entities.len() > 1 { - for i in 1..self.loaded_entities.len() { - self.loaded_entities.remove(i); + for _ in 1..self.loaded_entities.len() { + self.loaded_entities.remove(1); } } } diff --git a/src/world/chunk_manager.rs b/src/world/chunk_manager.rs index 5e1afac..3f8a2e4 100644 --- a/src/world/chunk_manager.rs +++ b/src/world/chunk_manager.rs @@ -24,7 +24,7 @@ pub struct ChunksManager { impl ChunksManager { pub fn new() -> Self { - ChunksManager { chunks: Vec::new() } + ChunksManager { chunks: Vec::with_capacity(4*4*4) } } /// Return the chunk at the given position. Return an Option containing a MUTABLE reference to the chunk