diff --git a/.github/workflows/ci-docker.yml b/.github/workflows/ci-docker.yml
index ef955c806..66946cf91 100644
--- a/.github/workflows/ci-docker.yml
+++ b/.github/workflows/ci-docker.yml
@@ -5,7 +5,7 @@ jobs:
docker:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v4
with:
submodules: true
- name: Build the Docker image
diff --git a/.github/workflows/ci-workflow.yml b/.github/workflows/ci-workflow.yml
index 36de0e30a..24dccbdb5 100644
--- a/.github/workflows/ci-workflow.yml
+++ b/.github/workflows/ci-workflow.yml
@@ -8,47 +8,117 @@ on:
triggerIos:
description: 'Run iOS tests'
required: true
- default: 'no'
+ default: 'yes'
triggerMacos:
description: 'Run macOS tests'
required: true
- default: 'no'
+ default: 'yes'
trigger3DS:
description: 'Run 3DS tests'
required: true
- default: 'no'
+ default: 'yes'
jobs:
- nintendo_3ds:
- if: github.event.inputs.trigger3DS == 'yes'
+ fxcg:
runs-on: ubuntu-latest
steps:
- - run: wget https://github.com/devkitPro/pacman/releases/download/v1.0.2/devkitpro-pacman.amd64.deb -O /tmp/devkitpro-pacman.deb
- - run: yes | sudo dpkg -i /tmp/devkitpro-pacman.deb
- - run: yes | sudo dkp-pacman -Syu --needed devkitARM 3dstools libctru
- - run: echo ::set-env name=DEVKITPRO::/opt/devkitpro
- - run: echo ::set-env name=DEVKITARM::/opt/devkitpro/devkitARM
- - run: echo ::set-env name=PATH::$DEVKITPRO/tools/bin:$DEVKITARM/bin:$PATH
-
- - uses: actions/checkout@v1
+ - uses: actions/checkout@v4
+ with:
+ submodules: 'recursive'
+ - name: Install dependencies
+ run: |
+ sudo apt-get update
+ sudo apt-get install build-essential cmake libfreetype-dev -y
+ - name: Get latest gint commit hash
+ run: |
+ LATEST_COMMIT_HASH=$(curl --silent https://git.planet-casio.com/api/v1/repos/Lephenixnoir/gint/branches/master | jq -r .commit.id)
+ echo "Latest commit hash is: $LATEST_COMMIT_HASH"
+ echo "LATEST_COMMIT_HASH=$LATEST_COMMIT_HASH" >> $GITHUB_OUTPUT
+ id: get-latest-commit-hash
+ - name: Cache gint/fxsdk installation
+ id: cache-gint
+ uses: actions/cache@v4
+ with:
+ path: |
+ ~/.local/*/*
+ !~/.local/share/containers
+ key: ${{ runner.os }}-gint-${{ steps.get-latest-commit-hash.outputs.LATEST_COMMIT_HASH }}
+ - name: Install gint/fxsdk
+ if: steps.cache-gint.outputs.cache-hit != 'true'
+ env:
+ URL: "https://git.planet-casio.com/Lephenixnoir/GiteaPC/archive/master.tar.gz"
+ run: |
+ export PATH="~/.local/bin:$PATH"
+ cd "$(mktemp -d)"
+ curl "$URL" -o giteapc-master.tar.gz
+ tar -xzf giteapc-master.tar.gz
+ cd giteapc
+ python3 giteapc.py install Lephenixnoir/GiteaPC -y
+ sudo apt-get install python3-pil libusb-1.0-0-dev libudev-dev libsdl2-dev libpng-dev libudisks2-dev libglib2.0-dev libmpfr-dev libmpc-dev libppl-dev -y
+ giteapc install Lephenixnoir/fxsdk:noudisks2 Lephenixnoir/sh-elf-binutils Lephenixnoir/sh-elf-gcc -y
+ giteapc install Lephenixnoir/OpenLibm Vhex-Kernel-Core/fxlibc Lephenixnoir/sh-elf-gcc -y
+ giteapc install Lephenixnoir/gint -y
+ - name: Add fxsdk to PATH
+ run: echo "~/.local/bin" >> $GITHUB_PATH
+ - run: make -j2 PLATFORM=simulator TARGET=fxcg
+ - id: 'auth'
+ if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
+ uses: 'google-github-actions/auth@v0'
+ with:
+ credentials_json: '${{secrets.GOOGLE_CREDENTIALS}}'
+ - id: 'upload-directory'
+ if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
+ uses: 'google-github-actions/upload-cloud-storage@v0'
+ with:
+ path: 'output/release/simulator/fxcg/epsilon.g3a'
+ destination: 'upsilon-binfiles.appspot.com/dev/simulator/'
+ parent: false
+ - uses: actions/upload-artifact@v4
+ with:
+ name: epsilon.g3a
+ path: output/release/simulator/fxcg/epsilon.g3a
+ nintendo_3ds:
+ if: github.event.inputs.trigger3DS == 'yes' || github.event.inputs.trigger3DS == ''
+ runs-on: ubuntu-latest
+ container: devkitpro/devkitarm:latest
+ steps:
+ - uses: actions/checkout@v4
with:
submodules: true
+ - run: sudo apt-get update
+ - run: sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config -y
+ - run: yes | sudo dkp-pacman -S --needed devkitARM 3dstools libctru
+ - run: wget https://github.com/3DSGuy/Project_CTR/releases/download/makerom-v0.18.3/makerom-v0.18.3-ubuntu_x86_64.zip
+ - run: unzip makerom-v0.18.3-ubuntu_x86_64.zip
+ - run: rm makerom-v0.18.3-ubuntu_x86_64.zip
+ - run: chmod +x ./makerom
+ - run: echo "PATH=.:$PATH" >> $GITHUB_ENV
- run: make -j2 PLATFORM=simulator TARGET=3ds
- run: make -j2 PLATFORM=simulator TARGET=3ds epsilon.cia
- - uses: actions/upload-artifact@master
+ - uses: actions/upload-artifact@v4
with:
name: epsilon-3ds.3dsx
path: output/release/simulator/3ds/epsilon.3dsx
- - uses: actions/upload-artifact@master
+ - uses: actions/upload-artifact@v4
with:
name: epsilon-3ds.cia
path: output/release/simulator/3ds/epsilon.cia
android:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v4
with:
submodules: 'recursive'
- - run: make -j2 PLATFORM=simulator TARGET=android
+ - run: |
+ sudo apt-get update
+ sudo apt-get install imagemagick libfreetype-dev libpng-dev
+ - name: Set up JDK 21
+ uses: actions/setup-java@v4
+ with:
+ java-version: '21'
+ distribution: 'temurin'
+ - run: wget -nv https://dl.google.com/android/repository/android-ndk-r21e-linux-x86_64.zip
+ - run: unzip -q android-ndk-r21e-linux-x86_64.zip
+ - run: make -j2 PLATFORM=simulator TARGET=android NDK_PATH=./android-ndk-r21e
- id: 'auth'
if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
uses: 'google-github-actions/auth@v0'
@@ -61,69 +131,88 @@ jobs:
path: 'output/release/simulator/android/epsilon.apk'
destination: 'upsilon-binfiles.appspot.com/dev/simulator/'
parent: false
- - uses: actions/upload-artifact@master
+ - uses: actions/upload-artifact@v4
with:
name: epsilon-android.apk
path: output/release/simulator/android/epsilon.apk
n0100:
- runs-on: ubuntu-latest
+ runs-on: ubuntu-24.04-arm
steps:
- - run: sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config
- - uses: numworks/setup-arm-toolchain@2020-q2
- - uses: actions/checkout@v2
+ - run: |
+ sudo apt-get update
+ sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config gcc-arm-none-eabi binutils-arm-none-eabi
+ - uses: actions/checkout@v4
with:
submodules: 'recursive'
- run: mkdir final-output
- run: make -j2 MODEL=n0100 EPSILON_I18N=en output/release/device/n0100/epsilon.onboarding.two_binaries
- - run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.internal.en.bin
+ - run: make -j2 MODEL=n0100 EPSILON_I18N=en output/release/device/n0100/epsilon.onboarding.two_binaries
+ - run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.en.internal.bin
- run: rm output/release/device/n0100/apps/i18n.o output/release/device/n0100/apps/i18n.cpp
+ # We need to duplicate make to work around i18n generator race condition in Makefile leading to inconsistent incremental rebuilds
- run: make -j2 MODEL=n0100 EPSILON_I18N=fr output/release/device/n0100/epsilon.onboarding.two_binaries
- - run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.internal.fr.bin
+ - run: make -j2 MODEL=n0100 EPSILON_I18N=fr output/release/device/n0100/epsilon.onboarding.two_binaries
+ - run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.fr.internal.bin
- run: rm output/release/device/n0100/apps/i18n.o output/release/device/n0100/apps/i18n.cpp
- run: make -j2 MODEL=n0100 EPSILON_I18N=nl output/release/device/n0100/epsilon.onboarding.two_binaries
- - run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.internal.nl.bin
+ - run: make -j2 MODEL=n0100 EPSILON_I18N=nl output/release/device/n0100/epsilon.onboarding.two_binaries
+ - run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.nl.internal.bin
- run: rm output/release/device/n0100/apps/i18n.o output/release/device/n0100/apps/i18n.cpp
- run: make -j2 MODEL=n0100 EPSILON_I18N=pt output/release/device/n0100/epsilon.onboarding.two_binaries
- - run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.internal.pt.bin
+ - run: make -j2 MODEL=n0100 EPSILON_I18N=pt output/release/device/n0100/epsilon.onboarding.two_binaries
+ - run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.pt.internal.bin
- run: rm output/release/device/n0100/apps/i18n.o output/release/device/n0100/apps/i18n.cpp
- run: make -j2 MODEL=n0100 EPSILON_I18N=it output/release/device/n0100/epsilon.onboarding.two_binaries
- - run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.internal.it.bin
+ - run: make -j2 MODEL=n0100 EPSILON_I18N=it output/release/device/n0100/epsilon.onboarding.two_binaries
+ - run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.it.internal.bin
- run: rm output/release/device/n0100/apps/i18n.o output/release/device/n0100/apps/i18n.cpp
- run: make -j2 MODEL=n0100 EPSILON_I18N=de output/release/device/n0100/epsilon.onboarding.two_binaries
- - run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.internal.de.bin
+ - run: make -j2 MODEL=n0100 EPSILON_I18N=de output/release/device/n0100/epsilon.onboarding.two_binaries
+ - run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.de.internal.bin
- run: rm output/release/device/n0100/apps/i18n.o output/release/device/n0100/apps/i18n.cpp
- run: make -j2 MODEL=n0100 EPSILON_I18N=es output/release/device/n0100/epsilon.onboarding.two_binaries
- - run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.internal.es.bin
+ - run: make -j2 MODEL=n0100 EPSILON_I18N=es output/release/device/n0100/epsilon.onboarding.two_binaries
+ - run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.es.internal.bin
- run: rm output/release/device/n0100/apps/i18n.o output/release/device/n0100/apps/i18n.cpp
- run: make -j2 MODEL=n0100 EPSILON_I18N=hu output/release/device/n0100/epsilon.onboarding.two_binaries
- - run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.internal.hu.bin
+ - run: make -j2 MODEL=n0100 EPSILON_I18N=hu output/release/device/n0100/epsilon.onboarding.two_binaries
+ - run: mv output/release/device/n0100/epsilon.onboarding.internal.bin final-output/epsilon.onboarding.hu.internal.bin
- run: rm output/release/device/n0100/apps/i18n.o output/release/device/n0100/apps/i18n.cpp
- run: make -j2 MODEL=n0100 output/release/device/n0100/flasher.light.bin
- run: mv output/release/device/n0100/flasher.light.bin final-output/flasher.light.bin
+ - run: make -j2 MODEL=n0100 output/release/device/n0100/flasher.verbose.bin
+ - run: mv output/release/device/n0100/flasher.verbose.bin final-output/flasher.verbose.bin
- run: find final-output/ -type f -exec bash -c "shasum -a 256 -b {} > {}.sha256" \;
- run: tar cvfz binpack-n0100.tgz final-output/*
- - id: 'auth'
- if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon'}}
- uses: 'google-github-actions/auth@v0'
- with:
- credentials_json: '${{secrets.GOOGLE_CREDENTIALS}}'
- - id: 'upload-directory'
- if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon'}}
- uses: 'google-github-actions/upload-cloud-storage@v0'
- with:
- path: 'final-output/'
- destination: 'upsilon-binfiles.appspot.com/dev/n100/'
- parent: false
- - uses: actions/upload-artifact@master
+ - uses: actions/upload-artifact@v4
with:
name: epsilon-binpack-n0100.tgz
path: binpack-n0100.tgz
+ - uses: actions/checkout@v5
+ with:
+ repository: Yaya-Cout/Upsilon-binfiles
+ ref: 'main'
+ token: ${{ secrets.PAT_UPSILON_BINFILES }}
+ path: 'binfiles'
+ # TODO: Handle git conflicts using rebase
+ - name: Upload binary files to website
+ if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon'}}
+ run: |
+ cp -r final-output/* binfiles/binaries/dev/n100
+ cd binfiles
+ git add -A
+ git config --global user.email "ci@github.com"
+ git config --global user.name "GitHub Upsilon CI"
+ git pull
+ git commit -m "Update from CI"
+ git push
n0110:
- runs-on: ubuntu-latest
+ runs-on: ubuntu-24.04-arm
steps:
- - run: sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config
- - uses: numworks/setup-arm-toolchain@2020-q2
- - uses: actions/checkout@v2
+ - run: |
+ sudo apt-get update
+ sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config gcc-arm-none-eabi binutils-arm-none-eabi
+ - uses: actions/checkout@v4
with:
submodules: 'recursive'
- run: make -j2 MODEL=n0110 epsilon.dfu
@@ -132,33 +221,43 @@ jobs:
- run: make -j2 MODEL=n0110 epsilon.onboarding.beta.dfu
- run: make -j2 MODEL=n0110 flasher.light.dfu
- run: make -j2 MODEL=n0110 flasher.verbose.dfu
- # We don't need bench as it is used only in factory
- # - run: make -j2 bench.ram.dfu
- # - run: make -j2 bench.flash.dfu
+ - run: make -j2 MODEL=n0110 flasher.verbose.bin
+ - run: make -j2 MODEL=n0110 bench.ram.dfu
+ # - run: make -j2 MODEL=n0110 bench.flash.dfu
- run: make -j2 MODEL=n0110 binpack
- run: cp output/release/device/n0110/binpack-n0110-`git rev-parse HEAD | head -c 7`.tgz output/release/device/n0110/binpack-n0110.tgz
- - id: 'auth'
- if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
- uses: 'google-github-actions/auth@v0'
- with:
- credentials_json: '${{secrets.GOOGLE_CREDENTIALS}}'
- - id: 'upload-directory'
- if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
- uses: 'google-github-actions/upload-cloud-storage@v0'
- with:
- path: 'output/release/device/n0110/binpack/'
- destination: 'upsilon-binfiles.appspot.com/dev/n110/'
- parent: false
- - uses: actions/upload-artifact@master
+ - run: cp output/release/device/n0110/flasher.verbose.bin output/release/device/n0110/binpack/
+ - run: cd output/release/device/n0110 && for binary in *.bin; do shasum -a 256 -b binpack/${binary} > binpack/${binary}.sha256;done
+ - run: cp output/release/device/n0110/binpack-n0110-`git rev-parse HEAD | head -c 7`.tgz output/release/device/n0110/binpack/binpack.tgz
+ - uses: actions/upload-artifact@v4
with:
name: epsilon-binpack-n0110.tgz
path: output/release/device/n0110/binpack-n0110.tgz
+ - uses: actions/checkout@v5
+ with:
+ repository: Yaya-Cout/Upsilon-binfiles
+ ref: 'main'
+ token: ${{ secrets.PAT_UPSILON_BINFILES }}
+ path: 'binfiles'
+ # TODO: Handle git conflicts using rebase
+ - name: Upload binary files to website
+ if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon'}}
+ run: |
+ cp -r output/release/device/n0110/binpack/* binfiles/binaries/dev/n110
+ cd binfiles
+ git add -A
+ git config --global user.email "ci@github.com"
+ git config --global user.name "GitHub Upsilon CI"
+ git pull
+ git commit -m "Update from CI"
+ git push
bootloader:
- runs-on: ubuntu-latest
+ runs-on: ubuntu-24.04-arm
steps:
- - run: sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config
- - uses: numworks/setup-arm-toolchain@2020-q2
- - uses: actions/checkout@v2
+ - run: |
+ sudo apt-get update
+ sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config gcc-arm-none-eabi binutils-arm-none-eabi
+ - uses: actions/checkout@v5
with:
submodules: 'recursive'
- run: make -j2 MODEL=n0110 bootloader
@@ -171,27 +270,32 @@ jobs:
- run: make -j2 epsilon.onboarding.beta.B.dfu
- run: make -j2 binpack
- run: cp output/release/device/bootloader/binpack-bootloader-`git rev-parse HEAD | head -c 7`.tgz output/release/device/bootloader/binpack-bootloader.tgz
- - run: |
- gzip -d output/release/device/bootloader/binpack-bootloader.tgz
- tar rvf output/release/device/bootloader/binpack-bootloader.tar output/release/device/n0110/bootloader.bin --transform 's,^output/release/device/n0110/bootloader.bin,binpack/bootloader.bin,'
- gzip output/release/device/bootloader/binpack-bootloader.tar
- mv output/release/device/bootloader/binpack-bootloader.tar.gz output/release/device/bootloader/binpack-bootloader.tgz
- - id: 'auth'
- if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
- uses: 'google-github-actions/auth@v0'
- with:
- credentials_json: '${{secrets.GOOGLE_CREDENTIALS}}'
- - id: 'upload-directory'
- if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon' }}
- uses: 'google-github-actions/upload-cloud-storage@v0'
- with:
- path: 'output/release/device/bootloader/binpack/'
- destination: 'upsilon-binfiles.appspot.com/dev/n110/'
- parent: false
- - uses: actions/upload-artifact@master
+ - run: cp output/release/device/n0110/bootloader.bin output/release/device/bootloader/binpack/
+ - run: cp output/release/device/n0110/bootloader.bin output/release/device/bootloader/
+ - run: cd output/release/device/bootloader && for binary in *.bin; do shasum -a 256 -b binpack/${binary} > binpack/${binary}.sha256;done
+ - run: cd output/release/device/bootloader && tar cvfz binpack-bootloader.tgz binpack/*
+ - uses: actions/upload-artifact@v4
with:
name: epsilon-binpack-bootloader.tgz
path: output/release/device/bootloader/binpack-bootloader.tgz
+ - uses: actions/checkout@v5
+ with:
+ repository: Yaya-Cout/Upsilon-binfiles
+ ref: 'main'
+ token: ${{ secrets.PAT_UPSILON_BINFILES }}
+ path: 'binfiles'
+ # TODO: Handle git conflicts using rebase
+ - name: Upload binary files to website
+ if: ${{ github.event_name == 'push' && github.ref_name == 'upsilon-dev' && github.repository == 'UpsilonNumworks/Upsilon'}}
+ run: |
+ cp -r output/release/device/bootloader/binpack/* binfiles/binaries/dev/n110
+ cd binfiles
+ git add -A
+ git config --global user.email "ci@github.com"
+ git config --global user.name "GitHub Upsilon CI"
+ git pull
+ git commit -m "Update from CI"
+ git push
windows:
runs-on: windows-latest
defaults:
@@ -199,7 +303,7 @@ jobs:
shell: msys2 {0}
steps:
- uses: msys2/setup-msys2@v2
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v4
with:
submodules: 'recursive'
- run: pacman -S --noconfirm mingw-w64-x86_64-gcc mingw-w64-x86_64-freetype mingw-w64-x86_64-pkg-config make mingw-w64-x86_64-python3 mingw-w64-x86_64-libjpeg-turbo mingw-w64-x86_64-libpng
@@ -218,7 +322,7 @@ jobs:
path: 'output/release/simulator/windows/epsilon.exe'
destination: 'upsilon-binfiles.appspot.com/dev/simulator/'
parent: false
- - uses: actions/upload-artifact@master
+ - uses: actions/upload-artifact@v4
with:
name: epsilon-windows.exe
path: output/release/simulator/windows/epsilon.exe
@@ -227,10 +331,14 @@ jobs:
steps:
- uses: numworks/setup-emscripten@master
with:
- sdk: 1.40.1
- - uses: actions/checkout@v2
+ sdk: latest
+ - uses: actions/checkout@v4
with:
submodules: 'recursive'
+ # Install the Linux toolchin to avoid dependancies issues, but maybe only libpng is needed
+ - run: |
+ sudo apt-get update
+ sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config libxtst-dev
- run: make -j2 PLATFORM=simulator TARGET=web
- run: make -j2 PLATFORM=simulator TARGET=web test.js
- run: node output/release/simulator/web/test.js --headless
@@ -246,15 +354,17 @@ jobs:
path: 'output/release/simulator/web/epsilon.js'
destination: 'upsilon-binfiles.appspot.com/dev/simulator/'
parent: false
- - uses: actions/upload-artifact@master
+ - uses: actions/upload-artifact@v4
with:
name: epsilon-web.zip
path: output/release/simulator/web/epsilon.zip
linux:
runs-on: ubuntu-latest
steps:
- - run: sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config
- - uses: actions/checkout@v2
+ - run: |
+ sudo apt-get update
+ sudo apt-get install build-essential imagemagick libfreetype6-dev libjpeg-dev libpng-dev pkg-config libxtst-dev
+ - uses: actions/checkout@v4
with:
submodules: 'recursive'
- run: make -j2 PLATFORM=simulator
@@ -272,36 +382,38 @@ jobs:
path: 'output/release/simulator/linux/epsilon.bin'
destination: 'upsilon-binfiles.appspot.com/dev/simulator/'
parent: false
- - uses: actions/upload-artifact@master
+ - uses: actions/upload-artifact@v4
with:
name: epsilon-linux.bin
path: output/release/simulator/linux/epsilon.bin
macos:
- if: github.event.inputs.triggerMacos == 'yes'
+ if: github.event.inputs.triggerMacos == 'yes' || github.event.inputs.triggerMacos == ''
runs-on: macOS-latest
steps:
+ - run: brew install python-setuptools
- run: brew install numworks/tap/epsilon-sdk
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v4
with:
submodules: 'recursive'
- run: make -j2 PLATFORM=simulator
- run: make -j2 PLATFORM=simulator ARCH=x86_64 test.bin
- run: output/release/simulator/macos/x86_64/test.bin --headless
- - uses: actions/upload-artifact@master
+ - uses: actions/upload-artifact@v4
with:
name: epsilon-macos.zip
path: output/release/simulator/macos/epsilon.app
ios:
- if: github.event.inputs.triggerIos == 'yes'
+ if: github.event.inputs.triggerIos == 'yes' || github.event.inputs.triggerIos == ''
runs-on: macOS-latest
steps:
+ - run: brew install python-setuptools
- run: brew install numworks/tap/epsilon-sdk
- - uses: actions/checkout@v2
+ - uses: actions/checkout@v4
with:
submodules: 'recursive'
- run: make -j2 PLATFORM=simulator TARGET=ios EPSILON_TELEMETRY=0
- run: make -j2 PLATFORM=simulator TARGET=ios EPSILON_TELEMETRY=0 APPLE_PLATFORM=ios-simulator
- - uses: actions/upload-artifact@master
+ - uses: actions/upload-artifact@v4
with:
name: epsilon-ios.ipa
path: output/release/simulator/ios/epsilon.ipa
diff --git a/.github/workflows/metric-workflow.yml b/.github/workflows/metric-workflow.yml
index d7ec925fc..06692943f 100644
--- a/.github/workflows/metric-workflow.yml
+++ b/.github/workflows/metric-workflow.yml
@@ -10,7 +10,7 @@ jobs:
- name: Install ARM toolchain
uses: numworks/setup-arm-toolchain@2020-q2
- name: Checkout PR base
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
with:
submodules: recursive
ref: ${{ github.event.pull_request.base.sha }}
@@ -18,7 +18,7 @@ jobs:
- name: Build base
run: make -j2 -C base MODEL=n0110 epsilon.elf
- name: Checkout PR head
- uses: actions/checkout@v2
+ uses: actions/checkout@v4
with:
submodules: recursive
ref: ${{ github.event.pull_request.head.sha }}
@@ -27,12 +27,12 @@ jobs:
run: make -j2 -C head MODEL=n0110 epsilon.elf
- name: Retrieve binary size analysis
id: binary_size
- run: echo "::set-output name=table::$(python3 head/build/metrics/binary_size.py base/output/release/device/n0110/epsilon.elf head/output/release/device/n0110/epsilon.elf --labels Base Head --sections .text .rodata .bss .data --custom 'Total (RAM)' .data .bss --custom 'Total (ROM)' .text .rodata .data --escape)"
+ run: echo "table=$(python3 head/build/metrics/binary_size.py base/output/release/device/n0110/epsilon.elf head/output/release/device/n0110/epsilon.elf --labels Base Head --sections .text .rodata .bss .data --custom 'Total (RAM)' .data .bss --custom 'Total (ROM)' .text .rodata .data --escape)" >> $GITHUB_OUTPUT
- name: Add comment
- uses: actions/github-script@v3.0.0
+ uses: actions/github-script@v7
with:
script: |
- await github.issues.createComment({
+ await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number,
diff --git a/.gitmodules b/.gitmodules
index 35f8c77ce..a535fa5da 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,6 +1,6 @@
[submodule "apps/rpn"]
path = apps/rpn
- url = https://github.com/Lauryy06/Upsilon-RPN.git
+ url = https://github.com/UpsilonNumworks/Upsilon-RPN.git
[submodule "apps/atomic"]
path = apps/atomic
- url = https://github.com/Lauryy06/atomic
+ url = https://github.com/UpsilonNumworks/atomic
diff --git a/Makefile b/Makefile
index c42ed081a..b3705e7f4 100644
--- a/Makefile
+++ b/Makefile
@@ -93,6 +93,7 @@ help:
@echo " make PLATFORM=simulator TARGET=web"
@echo " make PLATFORM=simulator TARGET=windows"
@echo " make PLATFORM=simulator TARGET=3ds"
+ @echo " make PLATFORM=simulator TARGET=fxcg"
.PHONY: doc
doc:
@@ -127,6 +128,7 @@ ifndef USE_LIBA
endif
ifeq ($(USE_LIBA),0)
include liba/Makefile.bridge
+include libaxx/Makefile.bridge
else
SFLAGS += -ffreestanding -nostdinc -nostdlib
include liba/Makefile
diff --git a/README.fr.md b/README.fr.md
index 806a8379e..c9c80e628 100644
--- a/README.fr.md
+++ b/README.fr.md
@@ -7,19 +7,19 @@
-> Don't understand french ? speak english ? here's the [english README](./README.md) !
+> Don't understand French ? Speak English ? here's the [english README](./README.md) !
## À propos
-Upsilon est un fork d'Omega, un fork d'Epsilon, l'OS de Numworks tournant sur les calculatrices du même nom, qui apporte beaucoup de fonctionnalités en plus, mais qui fut archivé et fermé pour des raisons légales après un changement de politique de Numworks. Upsilon est fait pour ceux qui aimeraient voir un futur pour les OS créées par les utilisateurs pour Numworks, même après l'arrèt du projet initial.
+Upsilon est un fork d'Omega, un fork d'Epsilon, l'OS de NumWorks tournant sur les calculatrices du même nom, qui apporte beaucoup de fonctionnalités en plus, mais qui fut archivé et fermé pour des raisons légales après un changement de politique de NumWorks. Upsilon est fait pour ceux qui aimeraient voir un futur pour les OS créés par les utilisateurs pour NumWorks, même après l'arrêt du projet initial.
### Quelques fonctionnalités supplémentaires
-- Un module python kandinsky amélioré
+- Un module Python Kandinsky amélioré
- Un support pour fonds d'écrans personnalisés
- Des applications externes
- Un thème Upsilon
-- La surcharge des opérateurs en python
+- La surcharge des opérateurs en Python
- Un tableau périodique légèrement amélioré
- L'utilisation possible du signe "=" dans les calculs
- *Ainsi que tout ce qui a été ajouté sur Omega, et bien plus...* [Changelogs complets d'Omega](https://github.com/Omega-Numworks/Omega/wiki/Changelog) | [Fonctionnalités principales d'Omega & captures d'écran](https://github.com/Omega-Numworks/Omega/wiki/Main-features).
@@ -29,12 +29,12 @@ Upsilon est un fork d'Omega, un fork d'Epsilon, l'OS de Numworks tournant sur le
### Site web
Rendez-vous sur le [site d'Upsilon](https://getupsilon.web.app/) à la section "Installer".
-Si votre calculatrice est reconnue, qu'elle contient une version d'Epsilon inférieure à 16 et que votre navigateur accepte WebUSB, la page vous proposera d'installer Upsilon.
+Si votre calculatrice est reconnue, qu'elle contient une version d'Epsilon inférieure à 16 et que votre navigateur accepte WebUSB, la page vous proposera d'installer Upsilon.
Ne débranchez votre calculatrice qu'une fois l'installation terminée.
### Manuelle
- *Vous pouvez vous référer à ce [site internet](https://www.numworks.com/resources/engineering/software/build/)pour la première étape si vous avez des erreurs*
+ *Vous pouvez vous référer à ce [site internet](https://www.numworks.com/resources/engineering/software/build/) pour la première étape si vous avez des erreurs*
### 1. Installation du SDK
@@ -52,13 +52,13 @@ Ne débranchez votre calculatrice qu'une fois l'installation terminée.
-Il suffit juste d'installer les dépendances en tapant ces commandes dans un Terminal en mode super-utilisateur.
+Il suffit juste d'installer les dépendances en tapant ces commandes dans un terminal en mode super-utilisateur.
```bash
apt-get install build-essential git imagemagick libx11-dev libxext-dev libfreetype6-dev libpng-dev libjpeg-dev pkg-config gcc-arm-none-eabi binutils-arm-none-eabi
```
-C'est fait! Vous pouvez aller à l'étape 2.
+C'est fait ! Vous pouvez aller à l'étape 2.
@@ -70,7 +70,7 @@ C'est fait! Vous pouvez aller à l'étape 2.
-Installez toutes les dépendances grâce à cette commande:
+Installez toutes les dépendances grâce à cette commande :
```bash
dnf install make automake gcc gcc-c++ kernel-devel git ImageMagick libX11-devel libXext-devel freetype-devel libpng-devel libjpeg-devel pkg-config arm-none-eabi-gcc-cs arm-none-eabi-gcc-cs-c++
@@ -86,7 +86,7 @@ dnf install make automake gcc gcc-c++ kernel-devel git ImageMagick libX11-devel
-Installez toutes les dépendances grâce à cette commande:
+Installez toutes les dépendances grâce à cette commande :
```bash
nix-env -p gcc libpng libjpeg xorg.libX11 pkg-config freetype xorg.libXext python3 imagemagick python310Packages.lz4 python310Packages.pypng python310Packages.pypng gcc-arm-embedded
```
@@ -103,7 +103,7 @@ nix-env -p gcc libpng libjpeg xorg.libX11 pkg-config freetype xorg.libXext pytho
-Il est recommandé d'utiliser [Homebrew](https://brew.sh/). Une fois intsallé, utilisez:
+Il est recommandé d'utiliser [Homebrew](https://brew.sh/). Une fois installé, utilisez :
```bash
brew install numworks/tap/epsilon-sdk
@@ -129,16 +129,16 @@ Vous pouvez aller à l'étape 2.
-Avec Msys2/Mingw (Supportés par Numwoks bien qu'il y ait beaucoup de bugs)
+Avec Msys2/Mingw (Supportés par NumWorks bien qu'il y ait beaucoup de bugs)
-L'environnement de compilation [Msys2](https://www.msys2.org/) est recommandé par Numworks pour obtenir la plupart des outils requis facilement. C'est ici que vous allez copier-colletoutes lecommandes de ce tutoriel. Une fois installé, copier-coller ces deux commandes dans le terminal:
+L'environnement de compilation [Msys2](https://www.msys2.org/) est recommandé par NumWorks pour obtenir la plupart des outils requis facilement. C'est ici que vous allez copier-coller toutes les commandes de ce tutoriel. Une fois installé, copiez-collez ces deux commandes dans le terminal:
```bash
pacman -S mingw-w64-x86_64-gcc mingw-w64-x86_64-freetype mingw-w64-x86_64-pkg-config mingw-w64-x86_64-libusb git make python
echo "export PATH=/mingw64/bin:$PATH" >> .bashrc
```
-Ensuite, vous devrez installer [GCC toolchain for ARM](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads). Quand il vouest demandde choisir u dossier d'installation, choisissez `C:\msys64\home\User\gcc-arm\`. Il vous faudra ensuite ajouter ce dossier à votre $PATH. Tapez juste:
+Ensuite, vous devrez installer [GCC toolchain for ARM](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads). Quand il vous est demandé de choisir un dossier d'installation, choisissez `C:\msys64\home\User\gcc-arm\`. Il vous faudra ensuite ajouter ce dossier à votre $PATH. Tapez juste:
```bash
echo "export PATH=$PATH:$HOME/gcc-arm/bin" >> .bashrc
@@ -154,11 +154,11 @@ Redémarrez votre terminal et vous pouvez aller à l'étape 2!
WSL est un système qui virtualise un environnement GNU/Linux dans Windows.
-Votre version de windows doit être >= 1903.
+Votre version de Windows doit être >= 1903.
#### Installation de WSL
-1. Apuyez simulatanément sur les touches "windows" et "x" puis cliquez sur "Powershell administrateur". Entrez ensuite ceci dans la nouvelle fenêtre:
+1. Apuyez simultanément sur les touches "Windows" et "X" puis cliquez sur "PowerShell Administrateur". Entrez ensuite ceci dans la nouvelle fenêtre:
```powershell
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
@@ -176,45 +176,47 @@ Cette commande permet d'autoriser le démarrage des machines signées par Micros
3. Téléchargez [ce fichier](https://wslstorestorage.blob.core.windows.net/wslblob/wsl_update_x64.msi) et suivez les instructions d'installation.
-4. Ouvrez votre fenêtre powershell comme avant et tapez:
+4. Ouvrez votre fenêtre PowerShell comme avant et tapez:
```powershell
wsl --set-default-version 2
```
-5. téléchargez [Ubuntu](https://www.microsoft.com/store/apps/9n6svws3rx71) depuis le Microsoft store. Vous pouvez aussi installer [Debian](https://www.microsoft.com/store/productI9MSVKQC78PK6).
+5. Téléchargez [Ubuntu](https://www.microsoft.com/store/apps/9n6svws3rx71) depuis le Microsoft store. Vous pouvez aussi installer [Debian](https://www.microsoft.com/store/productI9MSVKQC78PK6) à la place.
WSL est maintenant installé.
6. Installez maintenant la version pour ARM de GCC.
+
```bash
+sudo apt-get update
sudo apt-get install build-essential git imagemagick libx11-dev libxext-dev libfreetype6-dev libpng-dev libjpeg-dev pkg-config gcc-arm-none-eabi binutils-arm-none-eabi
```
### Installation d'usbipd pour connecter la calculatrice à WSL (facultatif)
-Pour connecter la calculatrice, il faut installer cet [outil](https://github.com/dorssel/usbipd-win/releases/download/v1.3.0/usbipd-win_1.3.0.msi). Il permet de connecter deperiphériques USpar internet.Suivez les instructions pour installer.
+Pour connecter la calculatrice, il faut installer cet [outil](hthttps://github.com/dorssel/usbipd-win/releases/download/v5.0.0/usbipd-win_5.0.0_x64.msi). Il permet de connecter des périphériques par Internet. Suivez les instructions pour l'installer.
#### Ubuntu
-1. Dans un terminal WSL Ubuntu, tapez:
+1. Dans un terminal WSL Ubuntu, tapez :
```bash
-sudo apt install linux-tools-5.4.0-77-generic hwdata
+sudo apt install linux-tools-generic hwdata
```
-2. Editez /etc/sudoers pour que l'on puisse utiliser la commande usbip. Sur Ubutu, cele est fait de cette manière:
+
#### Debian
-1.Si vous utiliser Debian, utilisez cette commande:
+1.Si vous utilisez Debian, lancez cette commande:
```bash
sudo apt install usbip hwdata usbutils
@@ -222,18 +224,19 @@ sudo apt install usbip hwdata usbutils
### Pour connecter la calculatrice à WSL
-1. Ouvrez encore un powershell en mode administrateur et tapez:
+1. Ouvrez à nouveau un PowerShell en mode administrateur et tapez :
```powershell
- usbipd wsl list
+usbipd list
```
-Ceci va lister les périphériques USB connectés à l'ordinateur. Reagrdez le BUSID de votre "Numworks Calculator".
+Ceci va lister les périphériques USB connectés à l'ordinateur. Regardez le BUSID de votre "Numworks Calculator".
-2. Maintenant, lancez cette commande en remplçant par celui de votre caculatrice:
+2. Maintenant, lancez cette commande en remplaçant par celui de votre calculatrice :
```powershell
-usbipd wsl attach --busid
+usbipd bind --busid
+usbipd attach --wsl --busid
```
Le mot de passe de votre machine WSL vous sera demandé.
@@ -248,7 +251,7 @@ Vous pouvez aller à l'étape 2.
### 2. Récupérer le code source
-Le code source est disponible dans une repository git. Récupérez-le de cette manière:
+Le code source est disponible dans une repository git. Récupérez-le de cette manière :
```bash
git clone --recursive https://github.com/UpsilonNumworks/Upsilon.git
@@ -287,7 +290,7 @@ soit:
make MODEL=n0100 OMEGA_USERNAME="" binpack -j4
```
-pour compiler les binpacks que vous pouvez distribuer et flasher depuis le [Ti-planet's webDFU](https://ti-planet.github.io/webdfu_numworks/n0100/).
+pour compiler les binpacks que vous pouvez distribuer et flasher depuis le [WebDFU de TI-Planet](https://ti-planet.github.io/webdfu_numworks/n0100/).
@@ -295,7 +298,7 @@ pour compiler les binpacks que vous pouvez distribuer et flasher depuis le [Ti-p
Model n0110
-Le bootloader vous permet d'installer firmware dans des "slots" séparés. Dans ce cas les applications externes ne pourront pas utiliser toute la mémoire mais la moitié. Si un seul slot est utilisé, le bootloader permettra d'utiliser toute la mémoire. Sans bootloader, les apps external peuvent utiliser toute la mémoire.
+Le bootloader vous permet d'installer 2 firmwares dans des "slots" séparés. Dans ce cas les applications externes ne pourront pas utiliser toute la mémoire mais la moitié. Si un seul slot est utilisé, le bootloader permettra d'utiliser toute la mémoire. Sans bootloader, les apps externes peuvent utiliser toute la mémoire.
Bootloader
@@ -324,7 +327,7 @@ soit:
make OMEGA_USERNAME="{Votre nom, max 15 caractères}" binpack -j4
```
-pour compiler les binpacks que vous pouvez distribuer et flasher depuis le [Ti-planet's webDFU](https://ti-planet.github.io/webdfu_numworks/n0100/). Vous les trouverez dans `output/release/device/bootloader/`.
+pour compiler les binpacks que vous pouvez distribuer et flasher depuis le [WebDFU de TI-Planet](https://ti-planet.github.io/webdfu_numworks/n0100/). Vous les trouverez dans `output/release/device/bootloader/`.
@@ -353,7 +356,7 @@ soit:
make MODEL=n0110 OMEGA_USERNAME="{Votre nom, max 15 caractères}" binpack -j4
```
-pour compiler les binpacks que vous pouvez distribuer et flasher depuis le [Ti-planet's webDFU](https://ti-planet.github.io/webdfu_numworks/n0100/). Vous les trouverez dans `output/release/device/n0110/`.
+pour compiler les binpacks que vous pouvez distribuer et flasher depuis le [WebDFU de TI-Planet](https://ti-planet.github.io/webdfu_numworks/n0100/). Vous les trouverez dans `output/release/device/n0110/`.
@@ -424,7 +427,7 @@ git checkout --recursive upsilon-dev
make PLATFORM=simulator TARGET=3ds -j
```
-Vous pouvez ensuite mettre epsilon.3dsx sur une carte SDpour le lancer depuis le HBC ou utilisez 3dslink pour le lancer via le réseau:
+Vous pouvez ensuite mettre epsilon.3dsx sur une carte SD pour le lancer depuis le HBC ou utilisez 3dslink pour le lancer via le réseau:
```bash
3dslink output/release/simulator/3ds/epsilon.3dsx -a <3DS' IP ADDRESS>
@@ -434,19 +437,19 @@ Vous pouvez ensuite mettre epsilon.3dsx sur une carte SDpour le lancer depuis le
-Important: n'oubliez pas l'argument `--recursive` Parce qu'Upsilon dépend de submodules.
+Important: n'oubliez pas l'argument `--recursive` parce qu'Upsilon dépend de submodules.
Aussi, vous pouvez changer le nombre de processus de compilation en parallèles en changeant le nombre après l'argument `-j`.
-N'oubliez pas de mettre votre nom à la place `{Votre nom, maximum 15 caractères}`.Si vous n'en voulez pas, enlevez l'argument `OMEGA_USERNAME`.
+N'oubliez pas de mettre votre nom à la place `{Votre nom, maximum 15 caractères}`. Si vous n'en voulez pas, enlevez l'argument `OMEGA_USERNAME`.
-Si vous avez besoin d'aide, n'hésitez pas à rejoindre notre serveur discord :
+Si vous avez besoin d'aide, n'hésitez pas à rejoindre notre serveur Discord :

---
## Liens utiles
-- [Upsilon external (pour installer des applications supplémentaires et des fonds d'écran)](https://upsilonnumworks.github.io/Upsilon-External/)
-- [Documentation d'ulab](https://micropython-ulab.readthedocs.io/en/latest/)
+- [Upsilon-External (pour installer des applications supplémentaires et des fonds d'écran)](https://upsilonnumworks.github.io/Upsilon-External/)
+- [Documentation d'Ulab](https://micropython-ulab.readthedocs.io/en/latest/)
## Contribution
@@ -467,18 +470,18 @@ Les anciens projets d'Omega, avant sa fermeture, qui ont été utilisés pour ce
## À propos d'Epsilon
-Upsilon est un fork d'Omega, visant a continuer le projet des OS utilisateurs pour Numworks
+Upsilon est un fork d'Omega, visant a continuer le projet des OS utilisateurs pour NumWorks.
-Omega est un fork d'Epsilon, un système d'exploitation performant pour calculatrices graphiques. Il inclut huit applications pour les mathématiques de lycée et d'études supérieurs
+Omega est un fork d'Epsilon, un système d'exploitation performant pour calculatrices graphiques. Il inclut huit applications pour les mathématiques de lycée et d'études supérieures.
Vous pouvez essayer Epsilon depuis votre navigateur sur le [simulateur en ligne](https://www.numworks.com/simulator/).
## Licence
NumWorks est une marque déposée de NumWorks SAS, 24 Rue Godot de Mauroy, 75009 Paris, France.
-Nintendo est Nintendo 3DS sont des marques déposées de Nintendo of America Inc, 4600 150th Ave NE, Redmond, WA 98052, Etats-Unis.
+Nintendo et Nintendo 3DS sont des marques déposées de Nintendo of America Inc, 4600 150th Ave NE, Redmond, WA 98052, Etats-Unis.
NumWorks SAS et Nintendo of America Inc ne sont en aucun cas associés avec ce projet.
-- NumWorks Epsilon est disponible sous [Lisense CC BY-NC-SA](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode).
-- Omega est disponible sous [Lisense CC BY-NC-SA](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode).
-- Upsilon est disponible sous [Lisense CC BY-NC-SA](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode).
+- NumWorks Epsilon est disponible sous [licence CC BY-NC-SA](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.fr).
+- Omega est disponible sous [licence CC BY-NC-SA](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.fr).
+- Upsilon est disponible sous [licence CC BY-NC-SA](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode.fr).
diff --git a/README.md b/README.md
index 4135856a1..74be9a622 100644
--- a/README.md
+++ b/README.md
@@ -7,11 +7,11 @@
-> Vous ne comprenez pas l'anglais ? Vous êtes francophone ? Regardez le [*LISEZ-MOI* français](./README.fr.md) !
+> 🇫🇷 Vous ne comprenez pas l'anglais ? Vous êtes francophone ? Regardez le [*LISEZ-MOI* français](./README.fr.md) ! 🇫🇷
## About
-Upsilon is a fork of Omega, an user-made OS that runs on the Numworks calculator, which brings many features to it, but was discontinued because of a policy change from Numworks. Upsilon is for the people who want to see a future for user-made OSes for Numworks, even after the closure and archiving of Omega.
+Upsilon is a fork of Omega, an user-made OS that runs on the NumWorks calculator, which brings many features to it, but was discontinued because of a policy change from NumWorks. Upsilon is for the people who want to see a future for user-made OSes for NumWorks, even after the closure and archiving of Omega.
### Some new features
@@ -131,16 +131,16 @@ And there you can go to step 2!
-With Msys2/Mingw (officialized by numworks but with a lot of bugs)
+With Msys2/Mingw (officialized by NumWorks but with a lot of bugs)
-[Msys2](https://www.msys2.org/) environment is recommended by Numworks to get most of the required tools on Windows easily. It's where you'll paste all the commands of this tutorial. Once it'sinstalled, paste these commands into the Msys2 terminal.
+[Msys2](https://www.msys2.org/) environment is recommended by NumWorks to get most of the required tools on Windows easily. It's where you'll paste all the commands of this tutorial. Once it's installed, paste these commands into the Msys2 terminal.
```bash
pacman -S mingw-w64-x86_64-gcc mingw-w64-x86_64-freetype mingw-w64-x86_64-pkg-config mingw-w64-x86_64-libusb git make python
echo "export PATH=/mingw64/bin:$PATH" >> .bashrc
```
-Next, you'll need to install the [GCC toolchain for ARM](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads). When prompted for aninstall location, choose `C:\msys64\home\User\gcc-arm\`. You'll then need to add this folder to your $PATH. Just enter:
+Next, you'll need to install the [GCC toolchain for ARM](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads). When prompted for an install location, choose `C:\msys64\home\User\gcc-arm\`. You'll then need to add this folder to your $PATH. Just enter:
```bash
echo "export PATH=$PATH:$HOME/gcc-arm/bin" >> .bashrc
@@ -154,11 +154,11 @@ Just restart terminal and you can go to step 2!
With WSL 2
-You need a windows version >= 1903.
+You need a Windows version >= 1903.
#### WSL Installation
-1. Use simultaneously win + X keys and then click on "admin powershell".
+1. Use simultaneously Win + X keys and then click on "admin powershell".
```powershell
dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
@@ -181,35 +181,47 @@ This one allows virtual machines developed by Microsoft.
```powershell
wsl --set-default-version 2
```
+
5. Download [Ubuntu](https://www.microsoft.com/store/apps/9n6svws3rx71) from Microsoft store.
WSL is now installed.
-6. Then Install GCC cross compiler for ARM.
+6. Then Install GCC cross compiler for ARM. In your Ubuntu teminal, run:
+
+
```bash
-apt-get install build-essential git imagemagick libx11-dev libxext-dev libfreetype6-dev libpng-dev libjpeg-dev pkg-config gcc-arm-none-eabi binutils-arm-none-eabi
+sudo apt-get update
+sudo apt-get install build-essential git imagemagick libx11-dev libxext-dev libfreetype6-dev libpng-dev libjpeg-dev pkg-config gcc-arm-none-eabi binutils-arm-none-eabi
```
### Usbipd installation to connect your calculator
-If you want to connect to the calculator, you have to connect to install this [tool](https://github.com/dorssel/usbipd-win/releases/download/v1.3.0/usbipd-win_1.3.0.msi). This will allow you toconnect WSL to the calculator through internet. Follow the on screen information to install.
+
+If you want to connect to the calculator, you have to connect to install this
+[tool](https://github.com/dorssel/usbipd-win/releases/download/v5.0.0/usbipd-win_5.0.0_x64.msi).
+This will allow you to connect WSL to the calculator through internet. Follow
+the on screen information to install.
+
#### Ubuntu
+
1. In a WSL Ubuntu command prompt, type:
+
```bash
-sudo apt install linux-tools-5.4.0-77-generic hwdata
+sudo apt install linux-tools-generic hwdata
```
-2. Edit /etc/sudoers so that root can find the usbip command. On Ubuntu, run this command.
+
#### Debian
-1. If you use debian for your WSL distro, use this command instead:
+1. If you use Debian for your WSL distro, use this command instead:
```bash
sudo apt install usbip hwdata usbutils
@@ -219,20 +231,22 @@ And that's all for installation and set up.
### To connect your calculator
-1. Open an Admin powershell and type:
+1. Open an admin PowerShell and type:
```powershell
- usbipd wsl list
+usbipd list
```
-This will list your usb devices connected. Look at the BUSID column and remember the one for your calculator (it should be called "Numworks Calculator").
-2. Now run this command replacing `` by your calculator's usb port id:
+This will list your USB devices connected. Look at the BUSID column and remember the one for your calculator (it should be called "Numworks Calculator").
+2. Now run this command replacing `` by your calculator's USB port id:
```powershell
-usbipd wsl attach --busid
+usbipd bind --busid
+usbipd attach --wsl --busid
+
```
-It will ask you to type your wsl's password and will connect your calculator to WSL.
+It will ask you to type your WSL's password and will connect your calculator to WSL.
You can now go to step 2!
@@ -264,7 +278,7 @@ git checkout upsilon-dev
```bash
make MODEL=n0100 clean
-make MODEL=n0100 EPSILON_I18N=en OMEGA_USERNAME="{Your name, max 15 characters}" -j4
+make MODEL=n0100 EPSILON_I18N=en OMEGA_USERNAME="{Your name, max 15 characters}" -j$(nproc)
```
Now, run either:
@@ -280,10 +294,10 @@ to directly flash the calculator after pressing simultaneously `reset` and `6` b
or:
```bash
-make MODEL=n0100 OMEGA_USERNAME="" binpack -j4
+make MODEL=n0100 OMEGA_USERNAME="" binpack -j$(nproc)
```
-to make binpack which you can flash to the calculator from [Ti-planet's webDFU](https://ti-planet.github.io/webdfu_numworks/n0100/). Binpacks are a great way to share a custom build of Upsilonto friends.
+to make binpack which you can flash to the calculator from [TI-Planet's WebDFU](https://ti-planet.github.io/webdfu_numworks/n0100/). Binpacks are a great way to share a custom build of Upsilon to friends.
@@ -291,7 +305,7 @@ to make binpack which you can flash to the calculator from [Ti-planet's webDFU](
Model n0110
-The bootloader allows you to install 2 firmware in separated "slots". If so, external apps won't have all the space but half. Bootloader will allow use of all of the memory if only one slot is flashed. In legacy mode, external apps use all the space available.
+The bootloader allows you to install 2 firmwares in separated "slots". If so, external apps won't have all the space but half. Bootloader will allow use of all of the memory if only one slot is flashed. In legacy mode, external apps use all the space available.
Bootloader
@@ -301,7 +315,7 @@ Then, build with:
```bash
make clean
-make OMEGA_USERNAME="{Your name, max 15 characters}" -j4
+make OMEGA_USERNAME="{Your name, max 15 characters}" -j$(nproc)
```
Now, run either:
@@ -317,10 +331,10 @@ to directly flash the calculator into the current slot, or thought bootloader's
or:
```bash
-make OMEGA_USERNAME="" binpack -j4
+make OMEGA_USERNAME="" binpack -j$(nproc)
```
-to make binpack which you can flash to the calculator from [Ti-planet's webDFU](https://ti-planet.github.io/webdfu_numworks/n0110/). You'll find them at `output/release/device/bootloader/`. Binpacks are a great way to share a custom build of Upsilon to friends.
+to make binpack which you can flash to the calculator from [TI-Planet's webDFU](https://ti-planet.github.io/webdfu_numworks/n0110/). You'll find them at `output/release/device/bootloader/`. Binpacks are a great way to share a custom build of Upsilon to friends.
@@ -330,7 +344,7 @@ to make binpack which you can flash to the calculator from [Ti-planet's webDFU](
```bash
make MODEL=n0110 clean
-make MODEL=n0110 OMEGA_USERNAME="{Your name, max 15 characters}" -j4
+make MODEL=n0110 OMEGA_USERNAME="{Your name, max 15 characters}" -j$(nproc)
```
Now, run either:
@@ -346,10 +360,10 @@ to directly flash the calculator after pressing simultaneously `reset` and `6` b
or:
```bash
-make MODEL=n0110 OMEGA_USERNAME="" binpack -j4
+make MODEL=n0110 OMEGA_USERNAME="" binpack -j$(nproc)
```
-to make binpack which you can flash to the calculator from [Ti-planet's webDFU](https://ti-planet.github.io/webdfu_numworks/n0110/). You'll find them at `output/release/device/bootloader/`. Binpacks are a great way to share a custom build of Upsilon to friends.
+to make binpack which you can flash to the calculator from [Ti-Planet's WebDFU](https://ti-planet.github.io/webdfu_numworks/n0110/). You'll find them at `output/release/device/bootloader/`. Binpacks are a great way to share a custom build of Upsilon to friends.
@@ -400,7 +414,7 @@ Then, compile Upsilon :
```bash
make clean
-make PLATFORM=simulator TARGET=web OMEGA_USERNAME="{Your name, max 15 characters}" -j4
+make PLATFORM=simulator TARGET=web OMEGA_USERNAME="{Your name, max 15 characters}" -j$(nproc)
```
The simulator is now in `output/release/simulator/web/simulator.zip`
@@ -416,8 +430,8 @@ You need devkitPro and devkitARM installed and in your path (instructions [here]
```bash
git clone --recursive https://github.com/UpsilonNumworks/Upsilon.git
cd Upsilon
-git checkout --recursive upsilon-dev
-make PLATFORM=simulator TARGET=3ds -j
+git checkout upsilon-dev
+make PLATFORM=simulator TARGET=3ds -j$(nproc)
```
You can then put epsilon.3dsx on a SD card to run it from the HBC or use 3dslink to launch it over the network:
@@ -430,6 +444,22 @@ You can then put epsilon.3dsx on a SD card to run it from the HBC or use 3dslink
+
+ Casio fx-CG-series Port
+
+First, install gint and fxsdk along with a cross compiler for the calculator. There are instructions for this (in French, but Google Translate works well enough) [here](https://www.planet-casio.com/Fr/forums/topic16614-last-giteapc-installer-et-mettre-a-jour-automatiquement-des-projets-gitea.html).
+
+Next:
+```bash
+git clone --recursive https://github.com/UpsilonNumworks/Upsilon.git
+cd Omega
+git checkout upsilon-dev
+make PLATFORM=simulator TARGET=fxcg -j$(nproc)
+```
+Then copy the file at `./output/release/simulator/fxcg/epsilon.g3a` to the calculator over USB.
+
+
+
Important: Don't forget the `--recursive` tag, because Upsilon relies on submodules.
Also, you can change the number of processes that run in parallel during the build by changing the value of the `-j` flag.
Don't forget to put your pseudo instead of `{your pseudo, max 15 char}`. If you don't want one, just remove the `OMEGA_USERNAME=""` argument.
@@ -476,7 +506,8 @@ You can try Epsilon straight from your browser in the [online simulator](https:/
NumWorks is a registered trademark of NumWorks SAS, 24 Rue Godot de Mauroy, 75009 Paris, France.
Nintendo and Nintendo 3DS are registered trademarks of Nintendo of America Inc, 4600 150th Ave NE, Redmond, WA 98052, USA.
-NumWorks SAS and Nintendo of America Inc aren't associated in any shape or form with this project.
+Casio is a registered trademark of Casio Computer Co., Ltd. CORPORATION JAPAN 6-2, Hon-machi 1-chome Shibuya-ku, Tokyo JAPAN 151-8543.
+NumWorks SAS, Nintendo of America Inc and Casio aren't associated in any shape or form with this project.
- NumWorks Epsilon is released under a [CC BY-NC-SA License](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode).
- Omega is released under a [CC BY-NC-SA License](https://creativecommons.org/licenses/by-nc-sa/4.0/legalcode).
diff --git a/apps/Makefile b/apps/Makefile
index 3aed30735..b2e67a832 100644
--- a/apps/Makefile
+++ b/apps/Makefile
@@ -50,6 +50,7 @@ apps_src += $(addprefix apps/,\
exam_mode_configuration_official.cpp:+official \
exam_mode_configuration_non_official.cpp:-official \
global_preferences.cpp \
+ host_filemanager.cpp \
i18n.py \
lock_view.cpp \
main.cpp \
diff --git a/apps/apps_container.cpp b/apps/apps_container.cpp
index 7e63f7503..b01c388e2 100644
--- a/apps/apps_container.cpp
+++ b/apps/apps_container.cpp
@@ -37,7 +37,8 @@ AppsContainer::AppsContainer() :
m_homeSnapshot(),
m_onBoardingSnapshot(),
m_hardwareTestSnapshot(),
- m_usbConnectedSnapshot()
+ m_usbConnectedSnapshot(),
+ m_startAppSnapshot()
{
m_emptyBatteryWindow.setFrame(KDRect(0, 0, Ion::Display::Width, Ion::Display::Height), false);
// #if __EMSCRIPTEN__
@@ -151,7 +152,10 @@ bool AppsContainer::dispatchEvent(Ion::Events::Event event) {
* We do it before switching to USB application to redraw the battery
* pictogram. */
updateBatteryState();
- if (switchTo(usbConnectedAppSnapshot())) {
+ if (GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) {
+ // If we are in exam mode, we don't switch to usb connected app
+ didProcessEvent = true;
+ } else if (switchTo(usbConnectedAppSnapshot())) {
Ion::USB::DFU(true);
// Update LED when exiting DFU mode
Ion::LED::updateColorWithPlugAndCharge();
@@ -346,7 +350,13 @@ void AppsContainer::run() {
/* Normal execution. The exception checkpoint must be created before
* switching to the first app, because the first app might create nodes on
* the pool. */
- bool switched = switchTo(initialAppSnapshot());
+ bool switched;
+ if (m_startAppSnapshot != nullptr) {
+ switched = switchTo(m_startAppSnapshot);
+ } else {
+ switched = switchTo(initialAppSnapshot());
+ }
+
assert(switched);
(void) switched; // Silence compilation warning about unused variable.
} else {
diff --git a/apps/apps_container.h b/apps/apps_container.h
index 0d49cdedb..485c5ce3b 100644
--- a/apps/apps_container.h
+++ b/apps/apps_container.h
@@ -59,6 +59,9 @@ public:
// Ion::StorageDelegate
void storageDidChangeForRecord(const Ion::Storage::Record record) override;
void storageIsFull() override;
+ #ifdef EPSILON_GETOPT
+ void setStartApp(App::Snapshot * snapshot) { m_startAppSnapshot = snapshot; }
+ #endif
protected:
Home::App::Snapshot * homeAppSnapshot() { return &m_homeSnapshot; }
private:
@@ -89,6 +92,9 @@ private:
HardwareTest::App::Snapshot m_hardwareTestSnapshot;
USB::App::Snapshot m_usbConnectedSnapshot;
XNTLoop m_XNTLoop;
+ #ifdef EPSILON_GETOPT
+ App::Snapshot * m_startAppSnapshot;
+ #endif
};
#endif
diff --git a/apps/apps_container_storage.cpp b/apps/apps_container_storage.cpp
index ad2dec619..6a945af11 100644
--- a/apps/apps_container_storage.cpp
+++ b/apps/apps_container_storage.cpp
@@ -34,6 +34,11 @@ App::Snapshot * AppsContainerStorage::appSnapshotAtIndex(int index) {
};
assert(sizeof(snapshots)/sizeof(snapshots[0]) == k_numberOfCommonApps);
assert(index >= 0 && index < k_numberOfCommonApps);
+ // To avoid crashes, we return the home app snapshot if the index is out of
+ // bounds. (no crash in release mode, but an assert in debug mode)
+ if (index >= k_numberOfCommonApps) {
+ return snapshots[0];
+ }
return snapshots[index];
}
@@ -49,7 +54,5 @@ int AppsContainerStorage::appIndexFromSnapshot(App::Snapshot * snapshot) {
return i;
}
}
- // Achievement unlock : how did you get here ?
- assert(false);
return NULL;
}
diff --git a/apps/atomic b/apps/atomic
index acefa4fa3..5f7063d44 160000
--- a/apps/atomic
+++ b/apps/atomic
@@ -1 +1 @@
-Subproject commit acefa4fa3c0b562cbc0cbd64c35d718e17a913e2
+Subproject commit 5f7063d447414028a3c4b750cd6dbe83bd6296e6
diff --git a/apps/calculation/additional_outputs/unit_list_controller.cpp b/apps/calculation/additional_outputs/unit_list_controller.cpp
index 41ac6d8f2..37fdcf776 100644
--- a/apps/calculation/additional_outputs/unit_list_controller.cpp
+++ b/apps/calculation/additional_outputs/unit_list_controller.cpp
@@ -24,7 +24,12 @@ bool UnitListController::handleEvent(Ion::Events::Event event) {
if (selectedRow() == 0 && (event == Ion::Events::OK || event == Ion::Events::EXE)) {
return true;
}
- return ListController::handleEvent(event);
+
+ // HACK: Change the selected row (prevent some bugs when OK is pressed)
+ selectRow(selectedRow() - 1);
+ bool value = ListController::handleEvent(event);
+ selectRow(selectedRow() + 1);
+ return value;
}
void UnitListController::setExpression(Poincare::Expression e) {
diff --git a/apps/calculation/base.de.i18n b/apps/calculation/base.de.i18n
index c2c11d837..419d3b965 100644
--- a/apps/calculation/base.de.i18n
+++ b/apps/calculation/base.de.i18n
@@ -18,27 +18,3 @@ Discriminant = "Diskriminante"
OnlyRoot = "Wurzel"
FirstRoot = "Erste Wurzel"
SecondRoot = "Zweite Wurzel"
-TimeDimension = "Zeit"
-DistanceDimension = "Distanz"
-MassDimension = "Masse"
-CurrentDimension = "Betrieb"
-TemperatureDimension = "Temperatur"
-AmountOfSubstanceDimension = "Quantität der Materie"
-LuminousIntensityDimension = "Lichtintensität"
-FrequencyDimension = "Frequenz"
-ForceDimension = "Stärke"
-PressureDimension = "Druck"
-EnergyDimension = "Energie"
-PowerDimension = "Mächtig"
-ElectricChargeDimension = "Elektrische Ladung"
-ElectricPotentialDimension = "Elektrisches Potenzial"
-ElectricCapacitanceDimension = "Elektrische Kapazität"
-ElectricResistanceDimension = "Elektrischer Wiederstand"
-ElectricConductanceDimension = "elektrische Leitfähigkeit"
-MagneticFluxDimension = "magnetischer Fluss"
-MagneticFieldDimension = "Magnetfeld"
-InductanceDimension = "Induktivität"
-CatalyticActivityDimension = "Katalytische Aktivität"
-SurfaceDimension = "Auftauchen"
-VolumeDimension = "Volumen"
-SpeedDimension = "Geschwindigkeit"
diff --git a/apps/calculation/base.en.i18n b/apps/calculation/base.en.i18n
index b636b47a5..23df23e3a 100644
--- a/apps/calculation/base.en.i18n
+++ b/apps/calculation/base.en.i18n
@@ -18,27 +18,3 @@ Discriminant = "Discriminant"
OnlyRoot = "Root"
FirstRoot = "First root"
SecondRoot = "Second root"
-TimeDimension = "Time"
-DistanceDimension = "Distance"
-MassDimension = "Mass"
-CurrentDimension = "Running"
-TemperatureDimension = "Temperature"
-AmountOfSubstanceDimension = "Quantity of matter"
-LuminousIntensityDimension = "Light intensity"
-FrequencyDimension = "Frequency"
-ForceDimension = "Strength"
-PressureDimension = "Pressure"
-EnergyDimension = "Energy"
-PowerDimension = "Powerful"
-ElectricChargeDimension = "Electrical charge"
-ElectricPotentialDimension = "Electric potential"
-ElectricCapacitanceDimension = "Electrical capacity"
-ElectricResistanceDimension = "Electrical resistance"
-ElectricConductanceDimension = "electrical conductance"
-MagneticFluxDimension = "magnetic flux"
-MagneticFieldDimension = "Magnetic field"
-InductanceDimension = "Inductance"
-CatalyticActivityDimension = "Catalytic activity"
-SurfaceDimension = "Surface"
-VolumeDimension = "Volume"
-SpeedDimension = "Speed"
diff --git a/apps/calculation/base.es.i18n b/apps/calculation/base.es.i18n
index b23115eab..1df949c38 100644
--- a/apps/calculation/base.es.i18n
+++ b/apps/calculation/base.es.i18n
@@ -18,27 +18,3 @@ Discriminant = "Discriminante"
OnlyRoot = "Raíz"
FirstRoot = "Primera raíz"
SecondRoot = "Segunda raíz"
-TimeDimension = "Tiempo"
-DistanceDimension = "Distancia"
-MassDimension = "Masa"
-CurrentDimension = "Correr"
-TemperatureDimension = "La temperatura"
-AmountOfSubstanceDimension = "cantidad de materia"
-LuminousIntensityDimension = "Intensidad de luz"
-FrequencyDimension = "Frecuencia"
-ForceDimension = "Fuerza"
-PressureDimension = "Presión"
-EnergyDimension = "Energía"
-PowerDimension = "Potencia"
-ElectricChargeDimension = "Carga eléctrica"
-ElectricPotentialDimension = "Potencial eléctrico"
-ElectricCapacitanceDimension = "Capacidad eléctrica"
-ElectricResistanceDimension = "Resistencia eléctrica"
-ElectricConductanceDimension = "conductancia eléctrica"
-MagneticFluxDimension = "flujo magnético"
-MagneticFieldDimension = "Campo magnético"
-InductanceDimension = "Inductancia"
-CatalyticActivityDimension = "Actividad catalítica"
-SurfaceDimension = "Superficie"
-VolumeDimension = "Volumen"
-SpeedDimension = "Velocidad"
diff --git a/apps/calculation/base.fr.i18n b/apps/calculation/base.fr.i18n
index 74416f32c..2b9e7bdac 100644
--- a/apps/calculation/base.fr.i18n
+++ b/apps/calculation/base.fr.i18n
@@ -18,27 +18,3 @@ Discriminant = "Discriminant"
OnlyRoot = "Racine"
FirstRoot = "Première racine"
SecondRoot = "Seconde racine"
-TimeDimension = "Temps"
-DistanceDimension = "Distance"
-MassDimension = "Masse"
-CurrentDimension = "Courant"
-TemperatureDimension = "Température"
-AmountOfSubstanceDimension = "Quantité de matière"
-LuminousIntensityDimension = "Intensité lumineuse"
-FrequencyDimension = "Fréquence"
-ForceDimension = "Force"
-PressureDimension = "Pression"
-EnergyDimension = "Énergie"
-PowerDimension = "Puissance"
-ElectricChargeDimension = "Charge électrique"
-ElectricPotentialDimension = "Potentiel électrique"
-ElectricCapacitanceDimension = "Capacité électrique"
-ElectricResistanceDimension = "Résistance électrique"
-ElectricConductanceDimension = "Conductance électrique"
-MagneticFluxDimension = "Flux magnétique"
-MagneticFieldDimension = "Champ magnétique"
-InductanceDimension = "Inductance"
-CatalyticActivityDimension = "Activité catalytique"
-SurfaceDimension = "Surface"
-VolumeDimension = "Volume"
-SpeedDimension = "Vitesse"
\ No newline at end of file
diff --git a/apps/calculation/base.hu.i18n b/apps/calculation/base.hu.i18n
index 7879cdf42..4c6cfc4a0 100644
--- a/apps/calculation/base.hu.i18n
+++ b/apps/calculation/base.hu.i18n
@@ -1,44 +1,20 @@
-CalculApp = "Számolás"
-CalculAppCapital = "SZÁMOLÁS"
-AdditionalResults = "További eredmények"
-DecimalBase = "Decimális"
-HexadecimalBase = "Hexadecimális"
-BinaryBase = "Bináris"
-PrimeFactors = "Alapvetö tényezök"
-MixedFraction = "Vegyes frakció"
-EuclideanDivision = "Euklideszi osztás"
-AdditionalDeterminant = "Meghatározó"
-AdditionalInverse = "inverz"
-AdditionalRowEchelonForm = "Sor echelon forma"
-AdditionalReducedRowEchelonForm = "Csökkentett sorú Echelon forma"
-AdditionalTrace = "Nyomkövetés"
-CanonicalForm = "Kanonikus forma"
-FactorizedForm = "Factorizált forma"
-Discriminant = "Discriminant"
-OnlyRoot = "Gyökér"
-FirstRoot = "Első gyökér"
+CalculApp = "Számolás"
+CalculAppCapital = "SZÁMOLÁS"
+AdditionalResults = "További eredmények"
+DecimalBase = "Decimális"
+HexadecimalBase = "Hexadecimális"
+BinaryBase = "Bináris"
+PrimeFactors = "Alapvetö tényezök"
+MixedFraction = "Vegyes frakció"
+EuclideanDivision = "Euklideszi osztás"
+AdditionalDeterminant = "Meghatározó"
+AdditionalInverse = "inverz"
+AdditionalRowEchelonForm = "Sor echelon forma"
+AdditionalReducedRowEchelonForm = "Csökkentett sorú Echelon forma"
+AdditionalTrace = "Nyomkövetés"
+CanonicalForm = "Kanonikus forma"
+FactorizedForm = "Factorizált forma"
+Discriminant = "Discriminant"
+OnlyRoot = "Gyökér"
+FirstRoot = "Első gyökér"
SecondRoot = "Második gyökér"
-TimeDimension = "Idő"
-DistanceDimension = "Távolság"
-MassDimension = "Tömeg"
-CurrentDimension = "Futó"
-TemperatureDimension = "Hőfok"
-AmountOfSubstanceDimension = "Az anyag mennyisége"
-LuminousIntensityDimension = "Fény intenzitása"
-FrequencyDimension = "Frekvencia"
-ForceDimension = "Erő"
-PressureDimension = "Nyomás"
-EnergyDimension = "Energia"
-PowerDimension = "Erős"
-ElectricChargeDimension = "Elektromos töltő"
-ElectricPotentialDimension = "Elektromos potenciál"
-ElectricCapacitanceDimension = "Elektromos kapacitás"
-ElectricResistanceDimension = "Elektromos ellenállás"
-ElectricConductanceDimension = "elektromos vezetőképesség"
-MagneticFluxDimension = "mágneses fluxus"
-MagneticFieldDimension = "Mágneses mező"
-InductanceDimension = "Induktivitás"
-CatalyticActivityDimension = "Katalitikus aktivitás"
-SurfaceDimension = "Felület"
-VolumeDimension = "Hangerő"
-SpeedDimension = "Sebesség"
diff --git a/apps/calculation/base.it.i18n b/apps/calculation/base.it.i18n
index 8e00cd884..62620d05c 100644
--- a/apps/calculation/base.it.i18n
+++ b/apps/calculation/base.it.i18n
@@ -18,27 +18,3 @@ Discriminant = "Discriminante"
OnlyRoot = "Radice"
FirstRoot = "Prima radice"
SecondRoot = "Seconda radice"
-TimeDimension = "Volta"
-DistanceDimension = "Distanza"
-MassDimension = "Messa"
-CurrentDimension = "In esecuzione"
-TemperatureDimension = "Temperatura"
-AmountOfSubstanceDimension = "Quantità di materia"
-LuminousIntensityDimension = "Intensità luminosa"
-FrequencyDimension = "Frequenza"
-ForceDimension = "Forza"
-PressureDimension = "Pressione"
-EnergyDimension = "Energia"
-PowerDimension = "Potere"
-ElectricChargeDimension = "Carica elettrica"
-ElectricPotentialDimension = "Potenziale elettrico"
-ElectricCapacitanceDimension = "Capacità elettrica"
-ElectricResistanceDimension = "Resistenza elettrica"
-ElectricConductanceDimension = "conduttanza elettrica"
-MagneticFluxDimension = "flusso magnetico"
-MagneticFieldDimension = "Campo magnetico"
-InductanceDimension = "Induttanza"
-CatalyticActivityDimension = "Attività catalitica"
-SurfaceDimension = "Superficie"
-VolumeDimension = "Volume"
-SpeedDimension = "Velocità"
diff --git a/apps/calculation/base.nl.i18n b/apps/calculation/base.nl.i18n
index c2385f018..1b286d49b 100644
--- a/apps/calculation/base.nl.i18n
+++ b/apps/calculation/base.nl.i18n
@@ -18,27 +18,3 @@ Discriminant = "Discriminant"
OnlyRoot = "Wortel"
FirstRoot = "Eerste wortel"
SecondRoot = "Tweede wortel"
-TimeDimension = "Tijd"
-DistanceDimension = "Afstand"
-MassDimension = "Massa"
-CurrentDimension = "Rennen"
-TemperatureDimension = "Temperatuur"
-AmountOfSubstanceDimension = "Hoeveelheid materie"
-LuminousIntensityDimension = "Lichtsterkte"
-FrequencyDimension = "Frequentie"
-ForceDimension = "Kracht"
-PressureDimension = "Druk"
-EnergyDimension = "Energie"
-PowerDimension = "Kracht"
-ElectricChargeDimension = "Elektrische lading"
-ElectricPotentialDimension = "elektrische potentiaal"
-ElectricCapacitanceDimension = "elektrische capaciteit:"
-ElectricResistanceDimension = "Elektrische weerstand"
-ElectricConductanceDimension = "elektrische geleiding:"
-MagneticFluxDimension = "magnetische flux"
-MagneticFieldDimension = "Magnetisch veld"
-InductanceDimension = "Inductie"
-CatalyticActivityDimension = "Katalytische activiteit"
-SurfaceDimension = "Oppervlak"
-VolumeDimension = "Volume"
-SpeedDimension = "Snelheid"
diff --git a/apps/calculation/base.pt.i18n b/apps/calculation/base.pt.i18n
index c6a1aa7ae..15abb51a7 100644
--- a/apps/calculation/base.pt.i18n
+++ b/apps/calculation/base.pt.i18n
@@ -18,27 +18,3 @@ Discriminant = "Discriminante"
OnlyRoot = "Raiz"
FirstRoot = "Primeira raiz"
SecondRoot = "Segunda raiz"
-TimeDimension = "Tempo"
-DistanceDimension = "Distância"
-MassDimension = "Massa"
-CurrentDimension = "Corrida"
-TemperatureDimension = "Temperatura"
-AmountOfSubstanceDimension = "Quantidade de matéria"
-LuminousIntensityDimension = "Intensidade da luz"
-FrequencyDimension = "Frequência"
-ForceDimension = "Força"
-PressureDimension = "Pressão"
-EnergyDimension = "Energia"
-PowerDimension = "Poderoso"
-ElectricChargeDimension = "Carga elétrica"
-ElectricPotentialDimension = "Potencial elétrico"
-ElectricCapacitanceDimension = "Capacidade elétrica"
-ElectricResistanceDimension = "Resistência elétrica"
-ElectricConductanceDimension = "condutância elétrica"
-MagneticFluxDimension = "fluxo magnético"
-MagneticFieldDimension = "Campo magnético"
-InductanceDimension = "Indutância"
-CatalyticActivityDimension = "Atividade catalítica"
-SurfaceDimension = "Superfície"
-VolumeDimension = "Volume"
-SpeedDimension = "Velocidade"
diff --git a/apps/calculation/calculation_store.cpp b/apps/calculation/calculation_store.cpp
index f1bb4b940..eee89ac89 100644
--- a/apps/calculation/calculation_store.cpp
+++ b/apps/calculation/calculation_store.cpp
@@ -7,6 +7,39 @@
#include "../exam_mode_configuration.h"
#include
+#if defined _FXCG || defined NSPIRE_NEWLIB
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+static KDCoordinate dummyHeight(::Calculation::Calculation * c, bool expanded) {
+ bool b;
+ Poincare::Layout l = c->createExactOutputLayout(&b);
+ if (!b) {
+ l=c->createInputLayout();
+ }
+ KDSize s = l.layoutSize();
+ const int bordersize = 10;
+ int h = s.height() + bordersize;
+ const int maxheight = 64;
+ if (h > maxheight) {
+ return maxheight;
+ }
+ return h;
+}
+
+extern void * last_calculation_history;
+void * last_calculation_history = 0;
+const char * retrieve_calc_history();
+
+#endif
+
using namespace Poincare;
using namespace Shared;
@@ -21,10 +54,39 @@ CalculationStore::CalculationStore(char * buffer, int size) :
{
assert(m_buffer != nullptr);
assert(m_bufferSize > 0);
+#if defined _FXCG || defined NSPIRE_NEWLIB
+ if (last_calculation_history == 0){
+ // Restore from scriptstore
+ const char * buf=retrieve_calc_history();
+ if (buf) {
+ Shared::GlobalContext globalContext;
+ char * ptr=(char *)buf;
+ for (;*ptr;) {
+ for (;*ptr;++ptr) {
+ if (*ptr=='\n') {
+ break;
+ }
+ }
+ char c = *ptr;
+ *ptr=0;
+ if (ptr > buf) {
+ push(buf,&globalContext, dummyHeight);
+ }
+ *ptr = c;
+ ++ptr;
+ buf = ptr;
+ }
+ }
+ last_calculation_history = (void *) this;
+ }
+#endif
}
// Returns an expiring pointer to the calculation of index i, and ignore the trash
ExpiringPointer CalculationStore::calculationAtIndex(int i) {
+#if defined _FXCG || defined NSPIRE_NEWLIB
+ last_calculation_history = (void *) this;
+#endif
if (m_trashIndex == -1 || i < m_trashIndex) {
return realCalculationAtIndex(i);
} else {
diff --git a/apps/calculation/expression_field.cpp b/apps/calculation/expression_field.cpp
index b96c4b1fe..8096a6e1d 100644
--- a/apps/calculation/expression_field.cpp
+++ b/apps/calculation/expression_field.cpp
@@ -1,6 +1,9 @@
#include "expression_field.h"
#include
+#include
+#include
+using namespace Poincare;
namespace Calculation {
bool ExpressionField::handleEvent(Ion::Events::Event event) {
@@ -21,7 +24,30 @@ bool ExpressionField::handleEvent(Ion::Events::Event event) {
event == Ion::Events::EE)) {
handleEventWithText(Poincare::Symbol::k_ans);
}
- return(::ExpressionField::handleEvent(event));
+ if (event == Ion::Events::Minus
+ && isEditing()
+ && fieldHasOnlyAMinus()) {
+ setText(Poincare::Symbol::k_ans);
+ }
+ return (::ExpressionField::handleEvent(event));
+}
+
+bool ExpressionField::fieldHasOnlyAMinus() const {
+ if (editionIsInTextField()) {
+ const char *inputBuffer = m_textField.draftTextBuffer();
+ return (inputBuffer[0] == '-' && inputBuffer[1] == '\0');
+ }
+ Layout layout = m_layoutField.layout();
+ if (layout.type() == LayoutNode::Type::HorizontalLayout && layout.numberOfChildren() == 1) {
+ Layout child = layout.childAtIndex(0);
+ if (child.type() == LayoutNode::Type::CodePointLayout) {
+ CodePointLayout &codePointLayout = static_cast(child);
+ if (codePointLayout.codePoint() == '-'){
+ return true;
+ }
+ }
+ }
+ return false;
}
}
diff --git a/apps/calculation/expression_field.h b/apps/calculation/expression_field.h
index 284404628..33477a874 100644
--- a/apps/calculation/expression_field.h
+++ b/apps/calculation/expression_field.h
@@ -13,6 +13,8 @@ public:
}
protected:
bool handleEvent(Ion::Events::Event event) override;
+private:
+ bool fieldHasOnlyAMinus() const;
};
}
diff --git a/apps/code/app.cpp b/apps/code/app.cpp
index 12833f6f8..873903087 100644
--- a/apps/code/app.cpp
+++ b/apps/code/app.cpp
@@ -5,6 +5,12 @@
#include
#include
+#if defined _FXCG || defined NSPIRE_NEWLIB
+extern "C" int calculator;
+extern "C" const int prizm_heap_size;
+extern "C" char prizm_heap[];
+#endif
+
namespace Code {
I18n::Message App::Descriptor::name() {
@@ -150,7 +156,17 @@ bool App::textInputDidReceiveEvent(InputEventHandler * textInput, Ion::Events::E
void App::initPythonWithUser(const void * pythonUser) {
if (!m_pythonUser) {
- MicroPython::init(m_pythonHeap, m_pythonHeap + k_pythonHeapSize);
+#if defined _FXCG || defined NSPIRE_NEWLIB
+ if (calculator == 1) { // fxcg50
+ MicroPython::init( (void *) 0x8c200000, (void *)(0x8c200000+ 0x2e0000));
+ } else if (calculator >= 1 && calculator <=4 ) {
+ MicroPython::init( prizm_heap, prizm_heap+prizm_heap_size);
+ } else {
+#endif
+ MicroPython::init(m_pythonHeap, m_pythonHeap + k_pythonHeapSize);
+#if defined _FXCG || defined NSPIRE_NEWLIB
+ }
+#endif
}
m_pythonUser = pythonUser;
}
diff --git a/apps/code/catalog.de.i18n b/apps/code/catalog.de.i18n
index 5ead15875..1cac8628f 100644
--- a/apps/code/catalog.de.i18n
+++ b/apps/code/catalog.de.i18n
@@ -1,5 +1,11 @@
PythonPound = "Kommentar"
PythonPercent = "Modulo"
+PythonColon = "Doppelpunkt"
+PythonSemicon = "Semikolon"
+PythonExclamationMark = "Ausrufezeichen"
+PythonLessThan = "Kleiner als"
+PythonGreaterThan = "Größer als"
+PythonQuestionMark = "Fragezeichen"
Python1J = "Imaginäres i"
PythonLF = "Zeilenvorschub"
PythonTab = "Tabulator"
@@ -256,3 +262,4 @@ PythonFileReadable = "Kann Datei gelesen werden?"
PythonFileWritable = "Kann Datei geschrieben werden?"
PythonImportUtils = "Importieren von ulab.utils"
PythonUtilsFunction = "Funktionspräfix des utils-Moduls"
+PythonTurtleBgcolor = "Ändern Sie die Hintergrundfarbe"
diff --git a/apps/code/catalog.en.i18n b/apps/code/catalog.en.i18n
index 62a940057..00bc6311e 100644
--- a/apps/code/catalog.en.i18n
+++ b/apps/code/catalog.en.i18n
@@ -1,5 +1,11 @@
PythonPound = "Comment"
PythonPercent = "Modulo"
+PythonColon = "Colon"
+PythonSemicon = "Semicolon"
+PythonExclamationMark = "Exclamation mark"
+PythonLessThan = "Less than"
+PythonGreaterThan = "Greater than"
+PythonQuestionMark = "Question mark"
Python1J = "Imaginary i"
PythonLF = "Line feed"
PythonTab = "Tabulation"
@@ -256,3 +262,4 @@ PythonFileReadable = "Tells if read can be used on a file"
PythonFileWritable = "Tells if write can be used on a file"
PythonImportUtils = "Importing ulab.utils"
PythonUtilsFunction = "utils module function prefix"
+PythonTurtleBgcolor = "Change the background color"
diff --git a/apps/code/catalog.es.i18n b/apps/code/catalog.es.i18n
index 883b47cf4..80145d28b 100644
--- a/apps/code/catalog.es.i18n
+++ b/apps/code/catalog.es.i18n
@@ -1,5 +1,11 @@
PythonPound = "Comment"
PythonPercent = "Modulo"
+PythonColon = "Colon"
+PythonSemicon = "Semicolon"
+PythonExclamationMark = "Exclamation mark"
+PythonLessThan = "Less than"
+PythonGreaterThan = "Greater than"
+PythonQuestionMark = "Question mark"
Python1J = "Imaginary i"
PythonLF = "Line feed"
PythonTab = "Tabulation"
@@ -256,3 +262,4 @@ PythonFileReadable = "Tells if read can be used on a file"
PythonFileWritable = "Tells if write can be used on a file"
PythonImportUtils = "Importando ulab.utils"
PythonUtilsFunction = "prefijo de función del módulo utils"
+PythonTurtleBgcolor = "Cambiar el color de fondo"
diff --git a/apps/code/catalog.fr.i18n b/apps/code/catalog.fr.i18n
index 993770157..29d2620bd 100644
--- a/apps/code/catalog.fr.i18n
+++ b/apps/code/catalog.fr.i18n
@@ -1,5 +1,11 @@
PythonPound = "Commentaire"
PythonPercent = "Modulo"
+PythonColon = "Deux-points"
+PythonSemicon = "Point-virgule"
+PythonExclamationMark = "Point d'exclamation"
+PythonLessThan = "Inférieur à"
+PythonGreaterThan = "Supérieur à"
+PythonQuestionMark = "Point d'interrogation"
Python1J = "i complexe"
PythonLF = "Saut à la ligne"
PythonTab = "Tabulation"
@@ -206,6 +212,7 @@ PythonTurtleBackward = "Recule de x pixels"
PythonTurtleCircle = "Cercle de rayon r pixels"
PythonTurtleColor = "Modifie la couleur du tracé"
PythonTurtleColorMode = "Met le mode de couleur à 1.0 ou 255"
+PythonTurtleBgcolor = "Modifie la couleur du fond"
PythonTurtleForward = "Avance de x pixels"
PythonTurtleFunction = "Préfixe fonction du module turtle"
PythonTurtleGoto = "Va au point de coordonnées (x,y)"
diff --git a/apps/code/catalog.hu.i18n b/apps/code/catalog.hu.i18n
index 6242e4dc3..e13a97886 100644
--- a/apps/code/catalog.hu.i18n
+++ b/apps/code/catalog.hu.i18n
@@ -1,5 +1,11 @@
PythonPound = "Megjegyzés"
PythonPercent = "Modulo"
+PythonColon = "Kettőspont"
+PythonSemicon = "Pontosvessző"
+PythonExclamationMark = "Felkiáltójel"
+PythonLessThan = "Kisebb mint"
+PythonGreaterThan = "Nagyobb mint"
+PythonQuestionMark = "Kérdőjel"
Python1J = "Képzeletbeli i"
PythonLF = "Enter"
PythonTab = "Táblázat"
@@ -256,3 +262,4 @@ PythonKeyAns = "ANS kulcs"
PythonKeyExe = "EXE kulcs"
PythonImportUtils = "Az ulab.utils importálása"
PythonUtilsFunction = "utils modul függvény előtagja"
+PythonTurtleBgcolor = "Módosítsa a háttérszínt"
diff --git a/apps/code/catalog.it.i18n b/apps/code/catalog.it.i18n
index d8a24f355..db2f8bbed 100644
--- a/apps/code/catalog.it.i18n
+++ b/apps/code/catalog.it.i18n
@@ -1,5 +1,11 @@
PythonPound = "Commento"
PythonPercent = "Modulo"
+PythonColon = "Due punti"
+PythonSemicon = "Punto e virgola"
+PythonExclamationMark = "Punto esclamativo"
+PythonLessThan = "Minore di"
+PythonGreaterThan = "Maggiore di"
+PythonQuestionMark = "Punto interrogativo"
Python1J = "Unità immaginaria"
PythonLF = "Nuova riga"
PythonTab = "Tabulazione"
@@ -25,7 +31,7 @@ PythonBin = "Converte un intero in binario"
PythonCeil = "Parte intera superiore"
PythonChoice = "Numero aleatorio nella lista"
PythonClear = "Svuota la lista"
-PythonCmathFunction = "Funz. prefissata modulo cmath"
+PythonCmathFunction = "Prefisso funzione del modulo cmath"
PythonColor = "Definisci un colore rvb"
PythonColorBlack = "Colore nero"
PythonColorBlue = "Colore blu"
@@ -63,7 +69,7 @@ PythonFloor = "Parte intera"
PythonFmod = "a modulo b"
PythonFrExp = "Mantissa ed esponente di x : (m,e)"
PythonGamma = "Funzione gamma"
-PythonGetKeys = "Premere i tasti"
+PythonGetKeys = "Ottieni i tasti premuti"
PythonGetPalette = "Ottieni la tavolozza del tema"
PythonGetPixel = "Restituisce colore del pixel(x,y)"
PythonGetrandbits = "Numero aleatorio con k bit"
@@ -82,25 +88,25 @@ PythonImportTurtle = "Importa del modulo turtle"
PythonImportTime = "Importa del modulo time"
PythonImportOs = "Importa modulo os"
PythonOsUname = "Ottieni informazioni sul sistema"
-PythonOsGetlogin = "Get username"
+PythonOsGetlogin = "Ottieni username"
PythonOsRemove = "Rimuovere un file"
PythonOsRename = "Rinomina file"
PythonOsListdir = "Elenca file"
PythonImportSys = "Importa modulo sys"
-PythonSysExit = "Terminate current program"
-PythonSysPrintexception = "Print exception"
-PythonSysByteorder = "The byte order of the system"
-PythonSysImplementation = "Information about Python"
-PythonSysModules = "Dictionary of loaded modules"
-PythonSysVersion = "Python language version (string)"
-PythonSysVersioninfo = "Python language version (tuple)"
+PythonSysExit = "Termina programma corrente"
+PythonSysPrintexception = "Stampa eccezione"
+PythonSysByteorder = "Ordine di byte del sistema"
+PythonSysImplementation = "Informazioni su Python"
+PythonSysModules = "Dizionario dei moduli caricati"
+PythonSysVersion = "Versione linguaggio Python (stringa)"
+PythonSysVersioninfo = "Versione linguaggio Python (tupla)"
PythonIndex = "Indice prima occorrenza di x"
PythonInput = "Inserire un valore"
PythonInsert = "Inserire x in posizione i-esima"
PythonInt = "Conversione in intero"
PythonIonFunction = "Prefisso di funzione modulo ion"
PythonIsFinite = "Testa se x è finito"
-PythonIsInfinite = "Testa se x est infinito"
+PythonIsInfinite = "Testa se x è infinito"
PythonIsKeyDown = "Restituisce True premendo tasto k"
PythonBattery = "Restituisce la tensione della batteria"
PythonBatteryLevel = "Restituisce il livello della batteria"
@@ -236,23 +242,24 @@ PythonTurtleShowturtle = "Mostra la tartaruga"
PythonTurtleSpeed = "Velocità di disegno (x tra 0 e 10)"
PythonTurtleWrite = "Mostra un testo"
PythonUniform = "Numero decimale tra [a,b]"
-PythonImportTime = "Import time module"
-PythonMonotonic = "Return monotonic time"
-PythonFileOpen = "Opens a file"
-PythonFileSeekable = "Tells if seek can be used on a file"
-PythonFileSeek = "Move file's cursor"
-PythonFileTell = "Get file's cursor location"
-PythonFileClose = "Closes a file"
-PythonFileClosed = "True if file was closed"
-PythonFileRead = "Read up to size bytes"
-PythonFileWrite = "Write b into file"
-PythonFileReadline = "Reads a line or up to size bytes"
-PythonFileReadlines = "Reads a list of lines"
-PythonFileTruncate = "Resize the file to size"
-PythonFileWritelines = "Writes a list of lines"
-PythonFileName = "Contains file's name"
-PythonFileMode = "Contains file's open mode"
-PythonFileReadable = "Tells if read can be used on a file"
-PythonFileWritable = "Tells if write can be used on a file"
+PythonImportTime = "Importa modulo time"
+PythonMonotonic = "Restituisce tempo monotonico"
+PythonFileOpen = "Apre un file"
+PythonFileSeekable = "Dice se si può usare il cursore su un file"
+PythonFileSeek = "Sposta cursore di un file"
+PythonFileTell = "Ottieni posizione del cursore del file"
+PythonFileClose = "Chiude un file"
+PythonFileClosed = "True se un file è stato chiuso"
+PythonFileRead = "Legge fino ai byte di un file"
+PythonFileWrite = "Scrive b in un file"
+PythonFileReadline = "Legge una riga o fino ai byte di un file"
+PythonFileReadlines = "Legge una lista di linee di un file"
+PythonFileTruncate = "Ridimensiona il file"
+PythonFileWritelines = "Scrive una lista di linee su file"
+PythonFileName = "Contiene il nome del file"
+PythonFileMode = "Contiene la modalità di apertura del file"
+PythonFileReadable = "Dice se si può leggere sul file"
+PythonFileWritable = "Dice se si può scrivere sul file"
PythonImportUtils = "Importazione di ulab.utils"
-PythonUtilsFunction = "prefisso della funzione del modulo utils"
+PythonUtilsFunction = "Prefisso funzione del modulo utils"
+PythonTurtleBgcolor = "Cambia il colore dello sfondo"
diff --git a/apps/code/catalog.nl.i18n b/apps/code/catalog.nl.i18n
index 876073d95..91fe3b6b3 100644
--- a/apps/code/catalog.nl.i18n
+++ b/apps/code/catalog.nl.i18n
@@ -1,5 +1,11 @@
PythonPound = "Opmerkingen"
PythonPercent = "Modulo"
+PythonColon = "Dubbele punt"
+PythonSemicon = "Puntkomma"
+PythonExclamationMark = "Uitroepteken"
+PythonLessThan = "Kleiner dan"
+PythonGreaterThan = "Groter dan"
+PythonQuestionMark = "Vraagteken"
Python1J = "Imaginaire i"
PythonLF = "Nieuwe regel"
PythonTab = "Tabulatie"
@@ -257,3 +263,4 @@ PythonFileReadable = "Tells if read can be used on a file"
PythonFileWritable = "Tells if write can be used on a file"
PythonImportUtils = "Ulab.utils importeren"
PythonUtilsFunction = "utils module functie prefix"
+PythonTurtleBgcolor = "Verander de achtergrondkleur"
diff --git a/apps/code/catalog.pt.i18n b/apps/code/catalog.pt.i18n
index 155aa785f..aef378835 100644
--- a/apps/code/catalog.pt.i18n
+++ b/apps/code/catalog.pt.i18n
@@ -1,5 +1,11 @@
PythonPound = "Comentário"
PythonPercent = "Módulo"
+PythonColon = "Dois pontos"
+PythonSemicon = "Ponto e vírgula"
+PythonExclamationMark = "Ponto de exclamação"
+PythonLessThan = "Menor que"
+PythonGreaterThan = "Maior que"
+PythonQuestionMark = "Ponto de interrogação"
Python1J = "i Complexo"
PythonLF = "Nova linha"
PythonTab = "Tabulação"
@@ -256,3 +262,4 @@ PythonFileReadable = "Tells if read can be used on a file"
PythonFileWritable = "Tells if write can be used on a file"
PythonImportUtils = "Importando ulab.utils"
PythonUtilsFunction = "prefixo de função do módulo utils"
+PythonTurtleBgcolor = "Alterar a cor de fundo"
diff --git a/apps/code/catalog.universal.i18n b/apps/code/catalog.universal.i18n
index ca6e19c45..d1878d9de 100644
--- a/apps/code/catalog.universal.i18n
+++ b/apps/code/catalog.universal.i18n
@@ -1,6 +1,12 @@
PythonCommandAmpersand = "&"
PythonCommandLF = "\\n"
PythonCommandPercent = "%"
+PythonCommandColon = ":"
+PythonCommandSemicon = ";"
+PythonCommandExclamationMark = "!"
+PythonCommandLessThan = "<"
+PythonCommandGreaterThan = ">"
+PythonCommandQuestionMark = "?"
PythonCommandPound = "#"
PythonCommandSingleQuote = "'x'"
PythonCommandSymbolExp = "^"
@@ -398,6 +404,7 @@ PythonTurtleCommandBackward = "backward(x)"
PythonTurtleCommandCircle = "circle(r)"
PythonTurtleCommandColor = "color('c')"
PythonTurtleCommandColorMode = "colormode(x)"
+PythonTurtleCommandBgcolor = "bgcolor('c')"
PythonTurtleCommandForward = "forward(x)"
PythonTurtleCommandGoto = "goto(x,y)"
PythonTurtleCommandHeading = "heading()"
diff --git a/apps/code/console_line_cell.cpp b/apps/code/console_line_cell.cpp
index 3cad12787..e445b280d 100644
--- a/apps/code/console_line_cell.cpp
+++ b/apps/code/console_line_cell.cpp
@@ -19,7 +19,7 @@ void ConsoleLineCell::ScrollableConsoleLineView::ConsoleLineView::setLine(Consol
void ConsoleLineCell::ScrollableConsoleLineView::ConsoleLineView::drawRect(KDContext * ctx, KDRect rect) const {
ctx->fillRect(bounds(), Palette::CodeBackground);
- ctx->drawString(m_line->text(), KDPointZero, GlobalPreferences::sharedGlobalPreferences()->font(), textColor(m_line), isHighlighted()? Palette::Select : Palette::BackgroundApps);
+ ctx->drawString(m_line->text(), KDPointZero, GlobalPreferences::sharedGlobalPreferences()->font(), textColor(m_line), isHighlighted()? Palette::Select : Palette::CodeBackground);
}
KDSize ConsoleLineCell::ScrollableConsoleLineView::ConsoleLineView::minimalSizeForOptimalDisplay() const {
diff --git a/apps/code/python_toolbox.cpp b/apps/code/python_toolbox.cpp
index 1f75378d3..9affd7a6f 100644
--- a/apps/code/python_toolbox.cpp
+++ b/apps/code/python_toolbox.cpp
@@ -338,6 +338,7 @@ const ToolboxMessageTree TurtleModuleChildren[] = {
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandHideturtle, I18n::Message::PythonTurtleHideturtle, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandColor, I18n::Message::PythonTurtleColor),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandColorMode, I18n::Message::PythonTurtleColorMode),
+ ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandBgcolor, I18n::Message::PythonTurtleBgcolor),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColorBlue, I18n::Message::PythonColorBlue, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColorRed, I18n::Message::PythonColorRed, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColorGreen, I18n::Message::PythonColorGreen, false),
@@ -503,6 +504,15 @@ const ToolboxMessageTree modulesChildren[] = {
const ToolboxMessageTree catalogChildren[] = {
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandPound, I18n::Message::PythonPound, false),
+ #ifdef _FXCG
+ // There is no question mark button on the fx-CG calculators
+ ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColon, I18n::Message::PythonColon, false),
+ ToolboxMessageTree::Leaf(I18n::Message::PythonCommandSemicon, I18n::Message::PythonSemicon, false),
+ ToolboxMessageTree::Leaf(I18n::Message::PythonCommandExclamationMark, I18n::Message::PythonExclamationMark, false),
+ ToolboxMessageTree::Leaf(I18n::Message::PythonCommandLessThan, I18n::Message::PythonLessThan, false),
+ ToolboxMessageTree::Leaf(I18n::Message::PythonCommandGreaterThan, I18n::Message::PythonGreaterThan, false),
+ ToolboxMessageTree::Leaf(I18n::Message::PythonCommandQuestionMark, I18n::Message::PythonQuestionMark, false),
+ #endif
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandPercent, I18n::Message::PythonPercent, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommand1J, I18n::Message::Python1J, false),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandLF, I18n::Message::PythonLF, false),
@@ -533,6 +543,7 @@ const ToolboxMessageTree catalogChildren[] = {
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandCmathFunction, I18n::Message::PythonCmathFunction, false, I18n::Message::PythonCommandCmathFunctionWithoutArg),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandColor, I18n::Message::PythonColor),
ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandColorMode, I18n::Message::PythonTurtleColorMode),
+ ToolboxMessageTree::Leaf(I18n::Message::PythonTurtleCommandBgcolor, I18n::Message::PythonTurtleBgcolor),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandComplex, I18n::Message::PythonComplex),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandCopySign, I18n::Message::PythonCopySign),
ToolboxMessageTree::Leaf(I18n::Message::PythonCommandCos, I18n::Message::PythonCos),
diff --git a/apps/code/script_template.h b/apps/code/script_template.h
index c3f0f5b99..6eac56d34 100644
--- a/apps/code/script_template.h
+++ b/apps/code/script_template.h
@@ -10,7 +10,7 @@ public:
constexpr ScriptTemplate(const char * name, const char * value) : m_name(name), m_value(value) {}
static const ScriptTemplate * Empty();
const char * name() const { return m_name; }
- const char * content() const { return m_value;}
+ const char * content() const { return m_value + Script::StatusSize(); }
const char * value() const { return m_value; }
private:
const char * m_name;
diff --git a/apps/code/toolbox.it.i18n b/apps/code/toolbox.it.i18n
index 7ec36994c..fe6546b30 100644
--- a/apps/code/toolbox.it.i18n
+++ b/apps/code/toolbox.it.i18n
@@ -2,9 +2,9 @@ Functions = "Funzioni"
Catalog = "Catalogo"
Modules = "Moduli"
LoopsAndTests = "Cicli e test"
-Files = "Files"
-Exceptions = "Exceptions"
+Files = "File"
+Exceptions = "Eccezioni"
UlabDocumentation = "Documentazione"
-IonSelector = "Selettore a chiave"
+IonSelector = "Selettore tasti"
PressAKey = "Premi un tasto"
-IonKeyList = "Elenco delle chiavi"
+IonKeyList = "Elenco dei tasti"
diff --git a/apps/external/app/sample.c b/apps/external/app/sample.c
index dbc13fd95..a779bf2f4 100644
--- a/apps/external/app/sample.c
+++ b/apps/external/app/sample.c
@@ -1,6 +1,15 @@
#include
+#if defined _FXCG || defined NSPIRE_NEWLIB
+// On the port, we use the Built-in file manager to import files.
+void host_filemanager();
+void extapp_main() {
+ host_filemanager();
+}
+#else
+// Elsewhere, just draw a rectangle to test the extapp API.
void extapp_main() {
extapp_pushRectUniform(10, 10, LCD_WIDTH-20, LCD_HEIGHT-20, 0);
extapp_msleep(1000);
}
+#endif
diff --git a/apps/external/base.it.i18n b/apps/external/base.it.i18n
index 49b8a2173..d1341ea67 100644
--- a/apps/external/base.it.i18n
+++ b/apps/external/base.it.i18n
@@ -1,9 +1,9 @@
-ExternalApp = "External"
-ExternalAppCapital = "EXTERNAL"
-ExternalAppApiMismatch = "API mismatch"
-ExternalAppExecError = "Cannot execute file"
-ExternalNotCompatible = "External is not compatible"
-WithSimulator = "with the simulator"
-WithN0100 = "with n0100"
-GetMoreAppsAt = "Get more apps at"
-NoAppsInstalled = "No apps installed"
+ExternalApp = "Esterna"
+ExternalAppCapital = "ESTERNA"
+ExternalAppApiMismatch = "Discordanza di API"
+ExternalAppExecError = "Impossibile eseguire file"
+ExternalNotCompatible = "Esterna non compatibile"
+WithSimulator = "con il simulatore"
+WithN0100 = "con n0100"
+GetMoreAppsAt = "Ottieni altre app a"
+NoAppsInstalled = "Nessuna app installata"
diff --git a/apps/external/extapp_api.h b/apps/external/extapp_api.h
index 9a98e5526..af90b68e2 100644
--- a/apps/external/extapp_api.h
+++ b/apps/external/extapp_api.h
@@ -27,7 +27,7 @@
#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_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)
diff --git a/apps/global_preferences.h b/apps/global_preferences.h
index 3077b93fe..9ab267a8c 100644
--- a/apps/global_preferences.h
+++ b/apps/global_preferences.h
@@ -36,6 +36,8 @@ public:
void setAutocomplete(bool autocomple) { m_autoComplete = autocomple; }
bool syntaxhighlighting() const { return m_syntaxhighlighting; }
void setSyntaxhighlighting(bool syntaxhighlight) { m_syntaxhighlighting = syntaxhighlight; }
+ bool clearShift() const { return m_clearshift; }
+ void setClearShift(bool clearalphashift) { m_clearshift = clearalphashift; }
int brightnessLevel() const { return m_brightnessLevel; }
void setBrightnessLevel(int brightnessLevel);
const KDFont * font() const { return m_font; }
@@ -63,6 +65,7 @@ private:
m_dfuUnlocked(false),
m_autoComplete(true),
m_syntaxhighlighting(true),
+ m_clearshift(true),
m_brightnessLevel(Ion::Backlight::MaxBrightness),
m_idleBeforeSuspendSeconds(55),
m_idleBeforeDimmingSeconds(45),
@@ -80,6 +83,7 @@ private:
bool m_dfuUnlocked;
bool m_autoComplete;
bool m_syntaxhighlighting;
+ bool m_clearshift;
int m_brightnessLevel;
int m_idleBeforeSuspendSeconds;
int m_idleBeforeDimmingSeconds;
diff --git a/apps/graph/graph/graph_view.h b/apps/graph/graph/graph_view.h
index ded212f6d..876881140 100644
--- a/apps/graph/graph/graph_view.h
+++ b/apps/graph/graph/graph_view.h
@@ -18,7 +18,13 @@ public:
* 10.0938275501223 which are hopefully rare enough.
* TODO: The drawCurve algorithm should use the derivative function to know
* how fast the function moves... */
+ #ifndef _FXCG
static constexpr float k_graphStepDenominator = 10.0938275501223f;
+ #else
+ // This value rounded down has to be a factor of the horizontal resolution / 2
+ // On the Casio calculator the resolution is 396 pixels, so 11 is close but works
+ static constexpr float k_graphStepDenominator = 11.0938275501223f;
+ #endif
GraphView(Shared::InteractiveCurveViewRange * graphRange,
Shared::CurveViewCursor * cursor, Shared::BannerView * bannerView, Shared::CursorView * cursorView);
diff --git a/apps/home/Makefile b/apps/home/Makefile
index d23bcdc30..e696447ff 100644
--- a/apps/home/Makefile
+++ b/apps/home/Makefile
@@ -17,12 +17,13 @@ i18n_files += $(call i18n_without_universal_for,home/base)
SFLAGS += -I$(BUILD_DIR)
apps_layout = apps/home/apps_layout.csv
+apps_layout_list = $(foreach i, $${EPSILON_APPS}, $(if $(filter external, $(i)),,"$(i),"))
$(eval $(call rule_for, \
APPS_LAYOUT, \
apps/home/apps_layout.cpp, \
, \
- $$(PYTHON) apps/home/apps_layout.py --layouts $(apps_layout) --header $$(subst .cpp,.h,$$@) --implementation $$@ --apps $$(EPSILON_APPS), \
+ $$(PYTHON) apps/home/apps_layout.py --layouts $(apps_layout) --header $$(subst .cpp,.h,$$@) --implementation $$@ --apps $$(EPSILON_APPS) --apps_layout $(apps_layout_list), \
global \
))
diff --git a/apps/home/apps_layout.py b/apps/home/apps_layout.py
index cff1f712b..40a1f6755 100644
--- a/apps/home/apps_layout.py
+++ b/apps/home/apps_layout.py
@@ -12,9 +12,18 @@ parser.add_argument('--header', help='the .h file to generate')
parser.add_argument('--implementation', help='the .cpp file to generate')
parser.add_argument('--apps', nargs='+', help='apps that are actually compiled')
parser.add_argument('--layouts', help='the apps_layout.csv file')
+parser.add_argument('--apps_layout', help='the apps_layout from the make command')
args = parser.parse_args()
+with io.open(args.layouts, "w", encoding="utf-8") as f:
+ ordered = args.apps_layout.split()
+ line1 = 'Default,'+','.join(ordered)+'\n'
+ line2 = 'HidePython,'+','.join(ordered)+'\n'
+ after = line1 + line2
+ f.truncate()
+ f.write(after)
+
def build_permutation(apps, appsOrdered):
res = [0] * len(apps)
i = 0
@@ -29,6 +38,8 @@ def parse_config_file(layouts, apps):
with io.open(layouts, "r", encoding="utf-8") as f:
csvreader = csv.reader(f, delimiter=',')
for row in csvreader:
+ for stg in row:
+ stg.strip()
res['styles'].append(row[0])
res['permutations'].append(build_permutation(apps, row[1:]))
return res
diff --git a/apps/home/controller.cpp b/apps/home/controller.cpp
index a79700b3f..1936b47ef 100644
--- a/apps/home/controller.cpp
+++ b/apps/home/controller.cpp
@@ -75,7 +75,7 @@ Controller::Controller(Responder * parentResponder, SelectableTableViewDataSourc
m_view.backgroundView()->setDefaultColor(Palette::HomeBackground);
-
+
#ifdef HOME_DISPLAY_EXTERNALS
int index = External::Archive::indexFromName("wallpaper.obm");
if(index > -1) {
@@ -86,6 +86,13 @@ Controller::Controller(Responder * parentResponder, SelectableTableViewDataSourc
#endif
}
+static constexpr Ion::Events::Event home_fast_navigation_events[] = {
+ Ion::Events::Seven, Ion::Events::Eight, Ion::Events::Nine,
+ Ion::Events::Four, Ion::Events::Five, Ion::Events::Six,
+ Ion::Events::One, Ion::Events::Two, Ion::Events::Three,
+ Ion::Events::Zero, Ion::Events::Dot, Ion::Events::EE
+};
+
bool Controller::handleEvent(Ion::Events::Event event) {
if (event == Ion::Events::OK || event == Ion::Events::EXE) {
AppsContainer * container = AppsContainer::sharedAppsContainer();
@@ -143,6 +150,21 @@ bool Controller::handleEvent(Ion::Events::Event event) {
return m_view.selectableTableView()->selectCellAtLocation(numberOfColumns() - 1, selectionDataSource()->selectedRow() - 1);
}
+ // Handle fast home navigation
+ for(int i = 0; i < std::min((int) (sizeof(home_fast_navigation_events) / sizeof(Ion::Events::Event)), this->numberOfIcons()); i++) {
+ if (event == home_fast_navigation_events[i]) {
+ int row = i / k_numberOfColumns;
+ int column = i % k_numberOfColumns;
+ // Get if app is already selected
+ if (selectionDataSource()->selectedRow() == row && selectionDataSource()->selectedColumn() == column) {
+ // If app is already selected, launch it
+ return handleEvent(Ion::Events::OK);
+ }
+ // Else, select the app
+ return m_view.selectableTableView()->selectCellAtLocation(column, row);
+ }
+ }
+
return false;
}
@@ -254,7 +276,7 @@ void Controller::tableViewDidChangeSelection(SelectableTableView * t, int previo
* (so the previous one is always visible). */
int appIndex = (t->selectedColumn()+t->selectedRow()*k_numberOfColumns)+1;
if (appIndex >= this->numberOfIcons()+1) {
- t->selectCellAtLocation((this->numberOfIcons()%3)-1, (this->numberOfIcons() / k_numberOfColumns));
+ t->selectCellAtLocation((this->numberOfIcons()%k_numberOfColumns)-1, (this->numberOfIcons() / k_numberOfColumns));
}
}
diff --git a/apps/home/controller.h b/apps/home/controller.h
index 3301fac78..a330a7564 100644
--- a/apps/home/controller.h
+++ b/apps/home/controller.h
@@ -47,10 +47,19 @@ private:
static constexpr KDCoordinate k_sideMargin = 4;
static constexpr KDCoordinate k_bottomMargin = 14;
static constexpr KDCoordinate k_indicatorMargin = 61;
+
+ #ifndef _FXCG
static constexpr int k_numberOfColumns = 3;
- static constexpr int k_maxNumberOfCells = 16;
static constexpr int k_cellHeight = 104;
static constexpr int k_cellWidth = 104;
+ #else
+ // A different screen resolution so different dimensions
+ static constexpr int k_numberOfColumns = 4;
+ static constexpr int k_cellHeight = 96;
+ static constexpr int k_cellWidth = 97;
+ #endif
+
+ static constexpr int k_maxNumberOfCells = 16;
ContentView m_view;
AppCell m_cells[k_maxNumberOfCells];
App * m_app;
diff --git a/apps/host_filemanager.cpp b/apps/host_filemanager.cpp
new file mode 100644
index 000000000..86d5b4ca8
--- /dev/null
+++ b/apps/host_filemanager.cpp
@@ -0,0 +1,859 @@
+// #include
+// // #include "../apps_container.h"
+// #include "stddef.h"
+// #include "string.h"
+// #include "math.h"
+// #include "app.h"
+#include
+#include "apps_container.h"
+#include "global_preferences.h"
+// #include "../exam_mode_configuration.h"
+
+extern "C" {
+#include
+}
+
+#ifdef NSPIRE_NEWLIB
+const char * storage_name="/documents/nwstore.nws.tns";
+#else
+const char * storage_name="nwstore.nws";
+#endif
+
+const char * calc_storage_name="nwcalc.txt";
+void * storage_address(); // ion/src/simulator/shared/platform_info.cpp
+const char * retrieve_calc_history();
+#if defined _FXCG || defined NSPIRE_NEWLIB
+bool save_calc_history();
+void display_host_help();
+int load_state(const char * fname);
+#endif
+
+// Additional code by B. Parisse for host file system support and persistence
+// on Casio Graph 90/FXCG50 and TI Nspire
+void erase_record(const char * name){
+ unsigned char * ptr=(unsigned char *)storage_address();
+ for (ptr+=4;;){ // skip header
+ size_t L=ptr[1]*256+ptr[0];
+ if (L==0) return;
+ if (strcmp((const char *)ptr+2,name)==0){
+ unsigned char * newptr=ptr;
+ int S=0,erased=L;
+ ptr+=L;
+ for (;;){
+ L=ptr[1]*256+ptr[0];
+ if (L==0){
+ for (int i=0;inewptr+S)
+ memmove(newptr+S,ptr,L);
+ S+=L;
+ ptr+=L;
+ }
+ return;
+ }
+ ptr+=L;
+ }
+}
+
+
+// record filtering on read
+void filter(unsigned char * ptr){
+ unsigned char * newptr=ptr;
+ int S; ptr+=4;
+ for (S=4;;){
+ size_t L=ptr[1]*256+ptr[0];
+ if (L==0) break;
+ int l=strlen((const char *)ptr+2);
+ // filter py records
+ if (l>3 && strncmp((const char *)ptr+2+l-3,".py",3)==0){
+ // if (ptr>newptr+S)
+ memmove(newptr+S,ptr,L);
+ S+=L;
+ }
+#if 0 // def STRING_STORAGE
+ if (l>5 && strncmp((const char *)ptr+2+l-5,".func",5)==0){
+ int shift=l+4+13;
+ Ion::Storage::Record * record=(Ion::Storage::Record *)malloc(1024);
+ memcpy(record,ptr,L);
+ //ExpressionModelHandle
+ Poincare::Expression e=Poincare::Expression::Parse((const char *)ptr+shift,NULL);
+ //ExpressionModel::setContent(Ion::Storage::Record * record, const char * c, Context * context, CodePoint symbol);
+ Shared::ExpressionModel md;
+ Ion::Storage::Record::ErrorStatus err=md.setExpressionContent(record, e);
+ if (1){
+ // if (ptr>newptr+S)
+ int newL=record->value().size;
+ memmove(newptr+S,record,newL);
+ S+=newL;
+ }
+ free(record);
+ }
+#endif
+ ptr+=L;
+ }
+}
+
+
+#ifdef NSPIRE_NEWLIB
+#include "../../ion/src/simulator/fxcg/platform.h"
+#include "../../ion/src/simulator/fxcg/menuHandler.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include "../../ion/src/simulator/nspire/k_csdk.h"
+#include "../calculation/calculation_store.h"
+
+#define C_WHITE SDK_WHITE
+#define C_BLACK SDK_BLACK
+#define C_RED (31<<11)
+
+int do_getkey(){
+ os_wait_1ms(50);
+ return getkey(0);
+}
+
+void dtext(int x,int y,int fg,const char * s){
+ os_draw_string_medium(x,y,fg,SDK_WHITE,s);
+}
+
+void dclear(int c){
+ os_fill_rect(0,0,LCD_WIDTH_PX,LCD_HEIGHT_PX,c);
+}
+
+void dupdate(){
+ sync_screen();
+}
+
+const int storage_length=60000; // 60000 in Upsilon, 32768 in Epsilon
+// k_storageSize = 60000; in ion/include/ion/internal_storage.h
+extern void * last_calculation_history;
+
+int load_state(const char * fname){
+ FILE * f=fopen(fname,"rb");
+ if (f){
+ unsigned char * ptr=(unsigned char *)storage_address();
+ fread(ptr,1,storage_length,f);
+ fclose(f);
+#ifdef FILTER_STORE
+ filter(ptr);
+#endif
+ return 1;
+ }
+ return 0;
+}
+
+int save_state(const char * fname){
+ save_calc_history();
+ if (1 || Ion::Storage::sharedStorage()->numberOfRecords()){
+ const unsigned char * ptr=(const unsigned char *)storage_address();
+ // find store size
+ int S=4;
+ for (ptr+=4;;){ // skip header
+ size_t L=ptr[1]*256+ptr[0];
+ ptr+=L;
+ S+=L;
+ if (L==0) break;
+ }
+ S = ((S+1023)/1024)*1024;
+#ifdef FILTER_STORE
+ // keep only python scripts
+ unsigned char * newptr=(unsigned char *) malloc(S);
+ bzero(newptr,S);
+ ptr=(const unsigned char *) storage_address();
+ memcpy(newptr,ptr,4); ptr+=4;
+ for (S=4;;){
+ size_t L=ptr[1]*256+ptr[0];
+ if (L==0) break;
+ int l=strlen((const char *)ptr+2);
+ if (l>3 && strncmp((const char *)ptr+2+l-3,".py",3)==0){
+ memcpy(newptr+S,ptr,L);
+ S+=L;
+ }
+ ptr+=L;
+ }
+ S = ((S+1023)/1024)*1024;
+ FILE * f;
+ f=fopen(fname,"wb");
+ if (f){
+ fwrite(newptr,S,1,f);
+ //fwrite(ptr+4,1,S-4,f);
+ fclose(f);
+ free(newptr);
+ return S;
+ }
+ free(newptr);
+ return 0;
+#else
+ ptr=(const unsigned char *)storage_address();
+ FILE * f;
+ f=fopen(fname,"wb");
+ if (f){
+ fwrite(ptr,S,1,f);
+ //fwrite(ptr+4,1,S-4,f);
+ fclose(f);
+ return S;
+ }
+ return 0;
+#endif
+ }
+ return 2;
+}
+
+#endif // NSPIRE_NEWLIB
+
+#ifdef _FXCG
+#include "../../ion/src/simulator/fxcg/platform.h"
+#include "../../ion/src/simulator/fxcg/menuHandler.h"
+#include "../calculation/calculation_store.h"
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#define KEY_CTRL_OK KEY_EXE
+int do_getkey(){
+ return getkey().key;
+}
+
+const int storage_length=60000; // 60000 in Upsilon, 32768 in Epsilon
+// k_storageSize = 60000; in ion/include/ion/internal_storage.h
+extern void * last_calculation_history;
+
+int load_state(const char * fname){
+ FILE * f=fopen(fname,"rb");
+ if (f){
+ unsigned char * ptr=(unsigned char *)storage_address();
+ ptr[3]=fgetc(f);
+ ptr[2]=fgetc(f);
+ ptr[1]=fgetc(f);
+ ptr[0]=fgetc(f);
+ fread(ptr+4,1,storage_length-4,f);
+ fclose(f);
+ return 1;
+ }
+ return 0;
+}
+
+int save_state(const char * fname){
+ save_calc_history();
+ if (Ion::Storage::sharedStorage()->numberOfRecords()){
+#if 0
+ unsigned short pFile[512];
+ convert(fname,pFile);
+ int hf = BFile_Open(pFile, BFile_WriteOnly); // Get handle
+ // cout << hf << endl << "f:" << filename << endl; Console_Disp();
+ if (hf<0){
+ int l=storage_length;
+ BFile_Create(pFile,0,&l);
+ hf = BFile_Open(pFile, BFile_WriteOnly);
+ }
+ if (hf < 0)
+ return 0;
+ int l=BFile_Write(hf,storage_address(),storage_length);
+ BFile_Close(hf);
+ if (l==storage_length)
+ return 1;
+ return -1;
+#else
+ const unsigned char * ptr=(const unsigned char *)storage_address();
+ // find store size
+ int S=4;
+ for (ptr+=4;;){ // skip header
+ size_t L=ptr[1]*256+ptr[0];
+ ptr+=L;
+ S+=L;
+ if (L==0) break;
+ }
+ S = ((S+1023)/1024)*1024;
+ FILE * f=fopen(fname,"wb");
+ if (f){
+ ptr=(const unsigned char *) storage_address();
+ fputc(ptr[3],f);
+ fputc(ptr[2],f);
+ fputc(ptr[1],f);
+ fputc(ptr[0],f);
+ //fwrite(ptr+4,1,S-4,f);
+ fwrite(ptr+4,S-4,1,f);
+ fclose(f);
+ return S;
+ }
+ return 0;
+#endif
+ }
+ return 2;
+}
+#endif // _FXCG
+
+const char * retrieve_calc_history(){
+#if defined _FXCG || defined NSPIRE_NEWLIB
+ static bool firstrun=true;
+ if (firstrun){
+#ifdef _FXCG
+ int l=gint_world_switch(GINT_CALL(load_state,storage_name));
+#else
+ int l=load_state(storage_name);
+#endif
+ if (l==0){
+ display_host_help();
+ // ((App*)m_app)->redraw();
+ }
+ firstrun=false;
+ }
+#endif
+ unsigned char * ptr=(unsigned char *)storage_address();
+ for (ptr+=4;;){ // skip header
+ size_t L=ptr[1]*256+ptr[0];
+ if (L==0) return 0;
+ if (strcmp((const char *)ptr+2,calc_storage_name)==0){
+ const char * buf=(const char *)ptr+2+strlen(calc_storage_name)+1;
+ return buf;
+ }
+ ptr += L;
+ }
+ return 0;
+}
+
+#if defined _FXCG || defined NSPIRE_NEWLIB
+bool save_calc_history(){
+ if (!last_calculation_history)
+ return false;
+ erase_record(calc_storage_name);
+ std::string s;
+ Calculation::CalculationStore * store=(Calculation::CalculationStore *) last_calculation_history;
+ int N=store->numberOfCalculations();
+ for (int i=N-1;i>=0;--i){
+ s += store->calculationAtIndex(i)->inputText();
+ s += '\n';
+ }
+ if (s.empty())
+ return false;
+ Ion::Storage::Record::ErrorStatus res= Ion::Storage::sharedStorage()->createRecordWithFullName(calc_storage_name,&s[0],s.size());
+ if (res==Ion::Storage::Record::ErrorStatus::NotEnoughSpaceAvailable)
+ return false;
+ return true;
+}
+
+void confirm_load_state(const char * buf){
+ dclear(C_WHITE);
+ dtext(1,1, C_BLACK, "Loading from state file");
+ dtext(1,17,C_BLACK,buf);
+ dtext(1,33,C_BLACK,"Current context will be lost!");
+ dtext(1,49,C_BLACK,"Press EXE to confirm");
+ dupdate();
+ int k=do_getkey();
+ if (k==KEY_EXE || k==KEY_CTRL_OK){
+#ifdef _FXCG
+ int l=gint_world_switch(GINT_CALL(load_state,buf));
+#else
+ int l=load_state(buf);
+#endif
+ char buf2[]="0";
+ buf2[0] += l;
+ if (l==0)
+ dtext(1,65,C_BLACK,"Error reading state");
+ if (l==1)
+ dtext(1,65,C_BLACK,"Success reading state");
+ dtext(1,81,C_BLACK,buf2);
+ dtext(1,97,C_BLACK,"Press any key");
+ dupdate();
+ do_getkey();
+ }
+}
+
+static void convert(const char * fname,unsigned short * pFile){
+ for ( ;*fname;++fname,++pFile)
+ *pFile=*fname;
+ *pFile=0;
+}
+
+struct file {
+ std::string s;
+ int length;
+ bool isdir;
+};
+
+void host_scripts(std::vector & v,const char * dirname,const char * extension){
+ v.clear();
+ file f={".._parent_dir",0,true};
+ if (strlen(dirname)>1)
+ v.push_back(f);
+ DIR *dp;
+ struct dirent *ep;
+ dp = opendir (dirname);
+ int l=extension?strlen(extension):0;
+ if (dp != NULL){
+ int t;
+ while ( (ep = readdir (dp)) ){
+ if (strlen(ep->d_name)>=1 && ep->d_name[0]=='.')
+ continue;
+ f.s=ep->d_name;
+ if (f.s=="@MainMem")
+ continue;
+#ifdef NSPIRE_NEWLIB
+ DIR * chk=opendir((dirname+f.s).c_str());
+ f.isdir=true;
+ if (chk)
+ closedir(chk);
+ else
+ f.isdir=false;
+#else
+ f.isdir=ep->d_type==DT_DIR;
+#endif
+#if 1
+ if (f.isdir)
+ f.length=0;
+ else {
+ struct stat st;
+ stat((dirname+f.s).c_str(), &st);
+ f.length = st.st_size;
+ if (f.length>=32768)
+ continue;
+ }
+#else
+ f.length=f.isdir?0:-1;
+#endif
+ if (f.isdir || !extension)
+ v.push_back(f);
+ else {
+ t=strlen(ep->d_name);
+ if (t>l && strncmp(ep->d_name+t-l,extension,l)==0)
+ v.push_back(f);
+ }
+ }
+ closedir (dp);
+ }
+}
+
+void nw_scripts(std::vector & v,const char * extension){
+ v.clear();
+#if 0
+ int n=Ion::Storage::sharedStorage()->numberOfRecords();
+ for (int i=0;irecordAtIndex(i).fullName());
+ }
+#else
+ const unsigned char * ptr=(const unsigned char *)storage_address();
+ int l=extension?strlen(extension):0;
+ for (ptr+=4;;){ // skip header
+ size_t L=ptr[1]*256+ptr[0];
+ ptr+=2;
+ if (L==0) break;
+ L-=2;
+ file f={(const char *)ptr,(int)L,false};
+ if (!extension)
+ v.push_back(f);
+ else {
+ int namesize=strlen((const char *)ptr);
+ if (namesize>l && strncmp((const char *)ptr+namesize-l,extension,l)==0)
+ v.push_back(f);
+ }
+ ptr+=L;
+ }
+#endif
+}
+
+int copy_nw_to_host(const char * nwname,const char * hostname){
+#ifdef NSPIRE_NEWLIB
+ int s=strlen(hostname);
+ if (s<4 || strncmp(hostname+s-4,".tns",4)){
+ std::string S(hostname);
+ S+=".tns";
+ return copy_nw_to_host(nwname,S.c_str());
+ }
+#endif
+ const unsigned char * ptr=(const unsigned char *)storage_address();
+ for (ptr+=4;;){ // skip header
+ size_t L=ptr[1]*256+ptr[0];
+ if (L==0) return 3; // not found
+ //dclear(C_WHITE);
+ //dtext(1,1,C_BLACK,ptr+2);
+ //dtext(1,17,C_BLACK,nwname);
+ //dupdate();
+ //getkey();
+ if (strcmp((const char *)ptr+2,nwname)){
+ ptr += L;
+ continue;
+ }
+ ptr+=2;
+ L-=2;
+ int l=strlen((const char *)ptr);
+ ptr += l+2;
+ L -= l;
+ L = 2*((L+1)/2);
+ FILE * f=fopen(hostname,"wb");
+ if (!f)
+ return 2;
+ fwrite(ptr,1,L,f);
+ fclose(f);
+ return 0;
+ }
+ return 1;
+}
+
+int copy_host_to_nw(const char * hostname,const char * nwname,int autoexec){
+ FILE * f=fopen(hostname,"rb");
+ if (!f)
+ return -1;
+ std::vector v(1,autoexec?1:0);
+ for (;;){
+ unsigned char c=fgetc(f);
+ if (feof(f)){
+ if (c>=' ' && c<=0x7e)
+ v.push_back(c);
+ break;
+ }
+ if (c==0xa && !v.empty() && v.back()==0xd)
+ v.back()=0xa;
+ else
+ v.push_back(c);
+ }
+ if (!v.empty() && v.back()!=0xa)
+ v.push_back(0xa);
+ v.push_back(0);
+ fclose(f);
+ if (Ion::Storage::sharedStorage()->hasRecord(Ion::Storage::sharedStorage()->recordNamed(nwname)))
+ Ion::Storage::sharedStorage()-> destroyRecord(Ion::Storage::sharedStorage()->recordNamed(nwname));
+ Ion::Storage::Record::ErrorStatus res= Ion::Storage::sharedStorage()->createRecordWithFullName(nwname,&v.front(),v.size());
+ if (res==Ion::Storage::Record::ErrorStatus::NotEnoughSpaceAvailable)
+ return -2;
+ return 0;
+}
+
+bool filesort(const file & a,const file & b){
+ if (a.isdir!=b.isdir)
+ return a.isdir;
+ return a.s v,w;
+#ifdef NSPIRE_NEWLIB
+ std::string hostdir="/documents/";
+#else
+ std::string hostdir="/";
+#endif
+ bool onlypy=true;
+ for (;;){
+ if (reload){
+ nw_scripts(v,onlypy?".py":0);
+ sort(v.begin(),v.end(),filesort);
+#ifdef NSPIRE_NEWLIB
+ host_scripts(w,hostdir.c_str(),onlypy?".py.tns":0);
+#else
+ host_scripts(w,hostdir.c_str(),onlypy?".py":0);
+#endif
+ sort(w.begin(),w.end(),filesort);
+ reload=false;
+ }
+ dclear(C_WHITE);
+ dtext(1,1, C_BLACK,"EXIT: leave; key 1 to 9: load state from file");
+#ifdef _FXCG
+ dtext(1,17,C_BLACK,"Cursor keys: move, /: rootdir, OPTN: all/py files");
+#else
+ dtext(1,17,C_BLACK,"Cursor keys: move, /: rootdir");
+#endif
+ dtext(1,33,C_BLACK,"EXE or STO key: copy selection from/to host");
+ dtext(1,49,C_BLACK,("Upsilon records Host "+hostdir).c_str());
+ int nitems=9;
+ if (posnw<0)
+ posnw=v.size()-1;
+ if (posnw>=int(v.size()))
+ posnw=0;
+ if (posnwstartnw+nitems)
+ startnw=posnw-4;
+ if (startnw>=int(v.size())-nitems)
+ startnw=v.size()-nitems;
+ if (startnw<0)
+ startnw=0;
+ if (v.empty())
+ nw=false;
+ for (int i=0;i<=nitems;++i){
+ int I=i+startnw;
+ if (I>=int(v.size()))
+ break;
+ dtext(1,65+16*i,(nw && I==posnw)?C_RED:C_BLACK,v[I].s.c_str());
+ char buf[256];
+ sprintf(buf,"%i",v[I].length);
+ dtext(90,65+16*i,(nw && I==posnw)?C_RED:C_BLACK,buf);
+ }
+ if (w.empty())
+ nw=true;
+ if (poshost<0)
+ poshost=w.size()-1;
+ if (poshost>=int(w.size()))
+ poshost=0;
+ if (poshoststarthost+nitems)
+ starthost=poshost-4;
+ if (starthost>=int(w.size())-nitems)
+ starthost=w.size()-nitems;
+ if (starthost<0)
+ starthost=0;
+ for (int i=0;i<=nitems;++i){
+ int I=i+starthost;
+ if (I>=int(w.size()))
+ break;
+ std::string fname=w[I].s;
+ if (fname.size()>16)
+ fname=fname.substr(0,16)+"...";
+ dtext(192,65+16*i,(!nw && I==poshost)?C_RED:C_BLACK,fname.c_str());
+ if (w[I].isdir)
+ dtext(154,65+16*i,(!nw && I==poshost)?C_RED:C_BLACK,"");
+ else {
+ char buf[256];
+ sprintf(buf,"%i",w[I].length);
+#ifdef _FXCG
+ dtext(340,65+16*i,(!nw && I==poshost)?C_RED:C_BLACK,buf);
+#else
+ dtext(285,65+16*i,(!nw && I==poshost)?C_RED:C_BLACK,buf);
+#endif
+ }
+ }
+ dupdate();
+ int key=do_getkey();
+ if (key==KEY_EXIT || key==KEY_MENU)
+ break;
+ if (key==KEY_OPTN || key=='\t'){
+ onlypy=!onlypy;
+ reload=true;
+ continue;
+ }
+ if (key==KEY_DIV){
+#ifdef NSPIRE_NEWLIB
+ hostdir="/documents/";
+#else
+ hostdir="/";
+#endif
+ reload=true;
+ continue;
+ }
+ if (key==KEY_DEL){
+ if (!nw && w[poshost].isdir) // can not remove directory
+ continue;
+ dclear(C_WHITE);
+ dtext(1,17,C_BLACK,nw?"About to suppress Upsilon record:":"About to suppress Host file:");
+ dtext(1,33,C_BLACK,(nw?v[posnw].s:w[poshost].s).c_str());
+ dtext(1,49,C_BLACK,"Press EXE or OK to confirm");
+ dupdate();
+ int ev=do_getkey();
+ if (ev!=KEY_EXE && ev!=KEY_CTRL_OK)
+ continue;
+ if (nw){
+#if 1
+ erase_record(v[posnw].s.c_str());
+#else
+ char buf[256];
+ strcpy(buf,v[posnw].s.c_str());
+ int l=strlen(buf)-4;
+ buf[l]=0;
+ Ion::Storage::sharedStorage()-> destroyRecordWithBaseNameAndExtension(buf,buf+l+1);
+#endif
+ }
+ else
+ remove((hostdir+w[poshost].s).c_str());
+ reload=true;
+ }
+ if (key==KEY_LEFT){
+ nw=true;
+ continue;
+ }
+ if (key==KEY_RIGHT){
+ nw=false;
+ continue;
+ }
+ if (key==KEY_PLUS){
+ if (nw)
+ posnw+=5;
+ else
+ poshost+=5;
+ continue;
+ }
+ if (key==KEY_MINUS){
+ if (nw)
+ posnw-=5;
+ else
+ poshost-=5;
+ continue;
+ }
+ if (key==KEY_DOWN){
+ if (nw)
+ ++posnw;
+ else
+ ++poshost;
+ continue;
+ }
+ if (key==KEY_UP){
+ if (nw)
+ --posnw;
+ else
+ --poshost;
+ continue;
+ }
+ int autoexec = key==KEY_EXE || key==KEY_CTRL_OK;
+ if (key==KEY_STORE || autoexec){
+ if (nw && posnw>=0 && posnw=0 && poshost=0;--j){
+ if (hostdir[j]=='/'){
+ hostdir=hostdir.substr(0,j+1);
+ break;
+ }
+ }
+ reload=true;
+ continue;
+ }
+ // lookup if poshost is in directories
+ if (w[poshost].isdir){
+ hostdir += w[poshost].s;
+ hostdir += "/";
+ reload=true;
+ continue;
+ }
+ size_t i;
+ std::string fname=w[poshost].s;
+#ifdef NSPIRE_NEWLIB
+ if (fname.size()>4 && fname.substr(fname.size()-4,4)==".tns")
+ fname=fname.substr(0,fname.size()-4);
+#endif
+ for (i=0;i12){
+ dclear(C_WHITE);
+ dtext(1,33,C_BLACK,"Host filename too long");
+ dtext(1,49,C_BLACK,fname.c_str());
+ dupdate();
+ do_getkey();
+ continue;
+ }
+ if (fname.size()>4 && fname.substr(fname.size()-4,4)==".nws")
+ confirm_load_state((hostdir+fname).c_str());
+ else {
+#ifdef _FXCG
+ gint_world_switch(GINT_CALL(copy_host_to_nw,(hostdir+fname).c_str(),nwname.c_str(),autoexec));
+#else
+ copy_host_to_nw((hostdir+w[poshost].s).c_str(),nwname.c_str(),autoexec);
+#endif
+ }
+ reload=true;
+ }
+ }
+ if (key>=KEY_1 && key<=KEY_9){
+#ifdef NSPIRE_NEWLIB
+ char buf[]="nwstate0.nws.tns";
+#else
+ char buf[]="nwstate0.nws";
+#endif
+ buf[7]='1'+(key-KEY_1);
+ confirm_load_state(buf);
+ reload=true;
+ }
+ }
+}
+#endif // FXCG || NSPIRE
\ No newline at end of file
diff --git a/apps/main.cpp b/apps/main.cpp
index b73b73e77..ec1db8b80 100644
--- a/apps/main.cpp
+++ b/apps/main.cpp
@@ -1,6 +1,7 @@
#include "apps_container.h"
#include "global_preferences.h"
#include
+#include
#define DUMMY_MAIN 0
#if DUMMY_MAIN
@@ -50,13 +51,29 @@ void ion_main(int argc, const char * const argv[]) {
}
continue;
}
+
+ /* Option should be given at run-time:
+ * $ ./epsilon.elf --open-app code
+ */
+ const char * appNames[] = {"home", EPSILON_APPS_NAMES};
+ if (strcmp(argv[i], "--open-app") == 0 && argc > i+1) {
+ const char * requestedAppName = argv[i+1];
+ for (int j = 0; j < AppsContainer::sharedAppsContainer()->numberOfApps(); j++) {
+ App::Snapshot * snapshot = AppsContainer::sharedAppsContainer()->appSnapshotAtIndex(j);
+ if (strcmp(requestedAppName, appNames[j]) == 0) {
+ AppsContainer::sharedAppsContainer()->setStartApp(snapshot);
+ break;
+ }
+ }
+ continue;
+ }
+
/* Option should be given at run-time:
* $ ./epsilon.elf --[app_name]-[option] [arguments]
* For example:
* $ make -j8 PLATFORM=emscripten EPSILON_APPS=code
* $ ./epsilon.elf --code-script hello_world.py:print("hello") --code-lock-on-console
*/
- const char * appNames[] = {"home", EPSILON_APPS_NAMES};
for (int j = 0; j < AppsContainer::sharedAppsContainer()->numberOfApps(); j++) {
App::Snapshot * snapshot = AppsContainer::sharedAppsContainer()->appSnapshotAtIndex(j);
// Compare name in order to find if the firsts chars which are different are NULL and '-'
diff --git a/apps/math_toolbox.cpp b/apps/math_toolbox.cpp
index 85e1a688f..e58d4aeea 100644
--- a/apps/math_toolbox.cpp
+++ b/apps/math_toolbox.cpp
@@ -38,7 +38,8 @@ const ToolboxMessageTree complexChildren[] = {
const ToolboxMessageTree combinatoricsChildren[] = {
ToolboxMessageTree::Leaf(I18n::Message::BinomialCommandWithArg, I18n::Message::Combination),
- ToolboxMessageTree::Leaf(I18n::Message::PermuteCommandWithArg, I18n::Message::Permutation)
+ ToolboxMessageTree::Leaf(I18n::Message::PermuteCommandWithArg, I18n::Message::Permutation),
+ ToolboxMessageTree::Leaf(I18n::Message::FactorialCommandWithArg, I18n::Message::Factorial)
};
const ToolboxMessageTree normalDistributionChildren[] = {
@@ -67,13 +68,10 @@ const ToolboxMessageTree arithmeticChildren[] = {
};
const ToolboxMessageTree matricesChildren[] = {
- ToolboxMessageTree::Leaf(I18n::Message::MatrixCommandWithArg, I18n::Message::NewMatrix, false, I18n::Message::MatrixCommand),
- ToolboxMessageTree::Leaf(I18n::Message::IndentityCommandWithArg, I18n::Message::Identity),
- ToolboxMessageTree::Leaf(I18n::Message::InverseCommandWithArg, I18n::Message::Inverse),
ToolboxMessageTree::Leaf(I18n::Message::DeterminantCommandWithArg, I18n::Message::Determinant),
- ToolboxMessageTree::Leaf(I18n::Message::TransposeCommandWithArg, I18n::Message::Transpose),
+ ToolboxMessageTree::Leaf(I18n::Message::InverseCommandWithArg, I18n::Message::Inverse),
+ ToolboxMessageTree::Leaf(I18n::Message::IndentityCommandWithArg, I18n::Message::Identity),
ToolboxMessageTree::Leaf(I18n::Message::TraceCommandWithArg, I18n::Message::Trace),
- ToolboxMessageTree::Leaf(I18n::Message::DimensionCommandWithArg, I18n::Message::Dimension),
ToolboxMessageTree::Leaf(I18n::Message::RowEchelonFormCommandWithArg, I18n::Message::RowEchelonForm),
ToolboxMessageTree::Leaf(I18n::Message::ReducedRowEchelonFormCommandWithArg, I18n::Message::ReducedRowEchelonForm)
};
@@ -111,6 +109,14 @@ const ToolboxMessageTree logicChildren[] = {
ToolboxMessageTree::Leaf(I18n::Message::CeilingLog2CommandWithArg, I18n::Message::CeilingLog2)
};
+const ToolboxMessageTree matricesAndVectorsChildren[] = {
+ ToolboxMessageTree::Leaf(I18n::Message::MatrixCommandWithArg, I18n::Message::NewMatrix, false, I18n::Message::MatrixCommand),
+ ToolboxMessageTree::Leaf(I18n::Message::TransposeCommandWithArg, I18n::Message::Transpose),
+ ToolboxMessageTree::Leaf(I18n::Message::DimensionCommandWithArg, I18n::Message::Dimension),
+ ToolboxMessageTree::Node(I18n::Message::Matrices, matricesChildren),
+ ToolboxMessageTree::Node(I18n::Message::Vectors, vectorsChildren)
+};
+
#if LIST_ARE_DEFINED
const ToolboxMessageTree listsChildren[] = {
ToolboxMessageTree::Leaf(I18n::Message::SortCommandWithArg, I18n::Message::Sort),
@@ -138,6 +144,7 @@ constexpr ToolboxMessageTree unitDistanceMeterPico = ToolboxMessageTree::Leaf(I1
constexpr ToolboxMessageTree unitDistanceMeterNano = ToolboxMessageTree::Leaf(I18n::Message::UnitDistanceMeterNanoSymbol, I18n::Message::UnitDistanceMeterNano);
constexpr ToolboxMessageTree unitDistanceMeterMicro = ToolboxMessageTree::Leaf(I18n::Message::UnitDistanceMeterMicroSymbol, I18n::Message::UnitDistanceMeterMicro);
constexpr ToolboxMessageTree unitDistanceMeterMilli = ToolboxMessageTree::Leaf(I18n::Message::UnitDistanceMeterMilliSymbol, I18n::Message::UnitDistanceMeterMilli);
+constexpr ToolboxMessageTree unitDistanceMeterCenti = ToolboxMessageTree::Leaf(I18n::Message::UnitDistanceMeterCentiSymbol, I18n::Message::UnitDistanceMeterCenti);
constexpr ToolboxMessageTree unitDistanceMeter = ToolboxMessageTree::Leaf(I18n::Message::UnitDistanceMeterSymbol, I18n::Message::UnitDistanceMeter);
constexpr ToolboxMessageTree unitDistanceMeterKilo = ToolboxMessageTree::Leaf(I18n::Message::UnitDistanceMeterKiloSymbol, I18n::Message::UnitDistanceMeterKilo);
constexpr ToolboxMessageTree unitDistanceAstronomicalUnit = ToolboxMessageTree::Leaf(I18n::Message::UnitDistanceAstronomicalUnitSymbol, I18n::Message::UnitDistanceAstronomicalUnit);
@@ -148,7 +155,7 @@ constexpr ToolboxMessageTree unitDistanceFoot = ToolboxMessageTree::Leaf(I18n::M
constexpr ToolboxMessageTree unitDistanceYard = ToolboxMessageTree::Leaf(I18n::Message::UnitDistanceYardSymbol, I18n::Message::UnitDistanceYard);
constexpr ToolboxMessageTree unitDistanceMile = ToolboxMessageTree::Leaf(I18n::Message::UnitDistanceMileSymbol, I18n::Message::UnitDistanceMile);
-const ToolboxMessageTree * unitDistanceMeterChildren[] = {&unitDistanceMeterPico, &unitDistanceMeterNano, &unitDistanceMeterMicro, &unitDistanceMeterMilli, &unitDistanceMeter, &unitDistanceMeterKilo};
+const ToolboxMessageTree * unitDistanceMeterChildren[] = {&unitDistanceMeterPico, &unitDistanceMeterNano, &unitDistanceMeterMicro, &unitDistanceMeterMilli, &unitDistanceMeterCenti, &unitDistanceMeter, &unitDistanceMeterKilo};
const ToolboxMessageTree unitDistanceMeterNode = ToolboxMessageTree::Node(I18n::Message::UnitMetricMenu, unitDistanceMeterChildren);
const ToolboxMessageTree * unitDistanceChildrenForImperialToolbox[] = {
&unitDistanceInch,
@@ -326,11 +333,13 @@ const ToolboxMessageTree unitInductanceChildren[] = {
const ToolboxMessageTree unitSurfaceChildrenForMetricToolbox[] = {
ToolboxMessageTree::Leaf(I18n::Message::UnitSurfaceHectarSymbol, I18n::Message::UnitSurfaceHectar),
+ ToolboxMessageTree::Leaf(I18n::Message::UnitSurfaceMeterSquareSymbol, I18n::Message::UnitSurfaceMeterSquare),
ToolboxMessageTree::Leaf(I18n::Message::UnitSurfaceAcreSymbol, I18n::Message::UnitSurfaceAcre)
};
const ToolboxMessageTree unitSurfaceChildrenForImperialToolbox[] = {
ToolboxMessageTree::Leaf(I18n::Message::UnitSurfaceAcreSymbol, I18n::Message::UnitSurfaceAcre),
- ToolboxMessageTree::Leaf(I18n::Message::UnitSurfaceHectarSymbol, I18n::Message::UnitSurfaceHectar)
+ ToolboxMessageTree::Leaf(I18n::Message::UnitSurfaceHectarSymbol, I18n::Message::UnitSurfaceHectar),
+ ToolboxMessageTree::Leaf(I18n::Message::UnitSurfaceMeterSquareSymbol, I18n::Message::UnitSurfaceMeterSquare),
};
const ToolboxMessageTree unitSurfaceFork[] = {
ToolboxMessageTree::Node(I18n::Message::UnitSurfaceMenu, unitSurfaceChildrenForMetricToolbox),
@@ -876,6 +885,10 @@ const ToolboxMessageTree Physics[] = {
const ToolboxMessageTree menu[] = {
+ #ifdef _FXCG
+ // There is no factorial button on the fx-CG calculators
+ ToolboxMessageTree::Leaf(I18n::Message::FactorialCommandWithArg, I18n::Message::Factorial, false, I18n::Message::FactorialCommand),
+ #endif
ToolboxMessageTree::Leaf(I18n::Message::AbsCommandWithArg, I18n::Message::AbsoluteValue),
ToolboxMessageTree::Leaf(I18n::Message::RootCommandWithArg, I18n::Message::NthRoot),
ToolboxMessageTree::Leaf(I18n::Message::LogCommandWithArg, I18n::Message::BasedLogarithm),
@@ -883,9 +896,8 @@ const ToolboxMessageTree menu[] = {
ToolboxMessageTree::Node(I18n::Message::ComplexNumber, complexChildren),
ToolboxMessageTree::Node(I18n::Message::Unit, unitChildren),
ToolboxMessageTree::Node(I18n::Message::Arithmetic, arithmeticChildren),
- ToolboxMessageTree::Node(I18n::Message::Matrices, matricesChildren),
+ ToolboxMessageTree::Node(I18n::Message::MatricesAndVectors, matricesAndVectorsChildren),
ToolboxMessageTree::Node(I18n::Message::Probability, probabilityChildren),
- ToolboxMessageTree::Node(I18n::Message::Vectors, vectorsChildren),
#if LIST_ARE_DEFINED
ToolboxMessageTree::Node(I18n::Message::Lists,listsChildren),
#endif
diff --git a/apps/on_boarding/app.cpp b/apps/on_boarding/app.cpp
index 59f83fc2f..1b789338b 100644
--- a/apps/on_boarding/app.cpp
+++ b/apps/on_boarding/app.cpp
@@ -25,7 +25,7 @@ bool App::processEvent(Ion::Events::Event e) {
if (e == Ion::Events::Home) {
return true;
}
- if (e == Ion::Events::OnOff) {
+ if (e == Ion::Events::OnOff && !GlobalPreferences::sharedGlobalPreferences()->isInExamMode()) {
Ion::Power::standby(); // Force a core reset to exit
}
return ::App::processEvent(e);
diff --git a/apps/on_boarding/logo_controller.cpp b/apps/on_boarding/logo_controller.cpp
index 0597bfcdf..fb870c382 100644
--- a/apps/on_boarding/logo_controller.cpp
+++ b/apps/on_boarding/logo_controller.cpp
@@ -16,8 +16,7 @@ LogoController::LogoController() :
}
bool LogoController::fire() {
- Container::activeApp()->dismissModalViewController();
- AppsContainer::sharedAppsContainer()->removeTimer(this);
+ Container::activeApp()->dismissModalViewController();
return true;
}
@@ -53,6 +52,7 @@ void LogoController::viewDidDisappear() {
AppsContainer::sharedAppsContainer()->activateExamMode(GlobalPreferences::sharedGlobalPreferences()->examMode());
}
}
+ AppsContainer::sharedAppsContainer()->removeTimer(this);
ViewController::viewDidDisappear();
}
diff --git a/apps/probability/app.h b/apps/probability/app.h
index d93905c46..2e8e3fddf 100644
--- a/apps/probability/app.h
+++ b/apps/probability/app.h
@@ -57,7 +57,7 @@ public:
void deleteDistributionAndCalculation();
void initializeDistributionAndCalculation();
-#if __EMSCRIPTEN__
+#if (defined __EMSCRIPTEN__) || (defined _FXCG)
constexpr static int k_distributionAlignments[] = {alignof(BinomialDistribution),alignof(ExponentialDistribution), alignof(NormalDistribution), alignof(PoissonDistribution), alignof(UniformDistribution), 0};
constexpr static size_t k_distributionAlignment = max(k_distributionAlignments);
constexpr static int k_calculationAlignments[] = {alignof(LeftIntegralCalculation),alignof(FiniteIntegralCalculation), alignof(RightIntegralCalculation), 0};
diff --git a/apps/reader/base.de.i18n b/apps/reader/base.de.i18n
index 9cbb39897..873f577b1 100644
--- a/apps/reader/base.de.i18n
+++ b/apps/reader/base.de.i18n
@@ -1,5 +1,3 @@
ReaderApp = "Leser"
ReaderAppCapital = "LESER"
NoFileToDisplay = "Keine Dateien zum Anzeigen"
-FileError1 = "Fehler beim Lesen der Datei"
-FileError2 = "Bitte überprüfen Sie die Syntax"
diff --git a/apps/reader/base.en.i18n b/apps/reader/base.en.i18n
index 2cb016526..812b213b8 100644
--- a/apps/reader/base.en.i18n
+++ b/apps/reader/base.en.i18n
@@ -1,5 +1,3 @@
ReaderApp = "Reader"
ReaderAppCapital = "READER"
NoFileToDisplay = "No file to display"
-FileError1 = "Error while reading file"
-FileError2 = "Please check its syntax"
diff --git a/apps/reader/base.es.i18n b/apps/reader/base.es.i18n
index 76962dca3..674bec03e 100644
--- a/apps/reader/base.es.i18n
+++ b/apps/reader/base.es.i18n
@@ -1,5 +1,3 @@
ReaderApp = "Lector"
ReaderAppCapital = "LECTOR"
NoFileToDisplay ="No hay archivos para mostrar"
-FileError1 = "Error al leer el archivo"
-FileError2 = "Por favor revise su sintaxis"
diff --git a/apps/reader/base.fr.i18n b/apps/reader/base.fr.i18n
index b74e6add0..e017f6bda 100644
--- a/apps/reader/base.fr.i18n
+++ b/apps/reader/base.fr.i18n
@@ -1,5 +1,3 @@
ReaderApp = "Liseuse"
ReaderAppCapital = "LISEUSE"
NoFileToDisplay = "Aucun fichier à afficher"
-FileError1 = "Erreur durant la lecture du fichier"
-FileError2 = "Veuillez vérifier sa syntaxe"
\ No newline at end of file
diff --git a/apps/reader/base.hu.i18n b/apps/reader/base.hu.i18n
index 9580dc40a..d0595b0c6 100644
--- a/apps/reader/base.hu.i18n
+++ b/apps/reader/base.hu.i18n
@@ -1,5 +1,3 @@
ReaderApp = "Olvasó"
ReaderAppCapital = "OLVASÓ"
NoFileToDisplay = "Nincs megjeleníthető fájl"
-FileError1 = "Hiba a fájl olvasása közben"
-FileError2 = "Kérjük, ellenőrizze a szintaxisát"
diff --git a/apps/reader/base.it.i18n b/apps/reader/base.it.i18n
index abfa80eda..7adef7e4a 100644
--- a/apps/reader/base.it.i18n
+++ b/apps/reader/base.it.i18n
@@ -1,5 +1,3 @@
ReaderApp = "Lettore"
ReaderAppCapital = "LETTORE"
-NoFileToDisplay = "essun file da visualizzare"
-FileError1 = "Errore durante la lettura del file"
-FileError2 = "Si prega di controllare la sua sintassi"
+NoFileToDisplay = "Nessun file da visualizzare"
diff --git a/apps/reader/base.nl.i18n b/apps/reader/base.nl.i18n
index 9f8c2304f..0e744c24c 100644
--- a/apps/reader/base.nl.i18n
+++ b/apps/reader/base.nl.i18n
@@ -1,5 +1,3 @@
ReaderApp = "Lezer"
ReaderAppCapital = "LEZER"
NoFileToDisplay = "Geen bestanden om weer te geven"
-FileError1 = "Fout tijdens het lezen van bestand"
-FileError2 = "Controleer de syntaxis ervan"
diff --git a/apps/reader/base.pt.i18n b/apps/reader/base.pt.i18n
index 0c2281287..0be936522 100644
--- a/apps/reader/base.pt.i18n
+++ b/apps/reader/base.pt.i18n
@@ -1,5 +1,3 @@
ReaderApp = "Leitor"
ReaderAppCapital = "LEITOR"
NoFileToDisplay = "Nenhum arquivo para exibir"
-FileError1 = "Erro ao ler o arquivo"
-FileError2 = "Verifique sua sintaxe"
diff --git a/apps/reader/word_wrap_view.cpp b/apps/reader/word_wrap_view.cpp
index b02c4ed03..3585e9669 100644
--- a/apps/reader/word_wrap_view.cpp
+++ b/apps/reader/word_wrap_view.cpp
@@ -17,6 +17,7 @@ WordWrapTextView::WordWrapTextView(ReadBookController * readBookController) :
m_length(0),
m_isRichTextFile(false), // Value isn't important, it will change when the file is loaded
m_lastPagesOffsetsIndex(0),
+ m_textColor(Palette::PrimaryText),
m_readBookController(readBookController)
{
for (int i = 0; i < k_lastOffsetsBufferSize; i++) {
@@ -618,7 +619,8 @@ BookSave WordWrapTextView::getBookSave() const {
void WordWrapTextView::setBookSave(BookSave save) {
m_pageOffset = save.offset;
- m_textColor = save.color;
+ // TODO: Understand why the color save crash the calculator and fix it
+ // m_textColor = save.color;
m_lastPagesOffsetsIndex = 0;
for (int i = 0; i < k_lastOffsetsBufferSize; i++) {
diff --git a/apps/settings/base.de.i18n b/apps/settings/base.de.i18n
index 3eb0e59fb..52552d351 100644
--- a/apps/settings/base.de.i18n
+++ b/apps/settings/base.de.i18n
@@ -72,14 +72,6 @@ Time = "Uhrzeit"
RTCWarning1 = "Das Aktivieren der Uhr verkürzt die"
RTCWarning2 = "Akkulaufzeit im Bereitschaftsmodus."
SyntaxHighlighting = "Syntaxhervorhebung"
-USBExplanation1 = "USB-Schutz schützt Ihren"
-USBExplanation2 = "Taschenrechner vor"
-USBExplanation3 = "unbeabsichtigter Verriegelung"
-USBProtection = "USB-Schutz"
-USBProtectionLevel = "Akzeptierte Updates"
-USBDefaultLevel = "Basierend auf Upsilon"
-USBLowLevel = "Basierend auf Omega"
-USBParanoidLevel = "Nichts"
Normal = "Normal"
IdleTimeBeforeDimming = "Abdunkeln nach (s)"
IdleTimeBeforeSuspend = "Anhalten nach (s)"
@@ -89,3 +81,4 @@ ExtAppWriteExplanation1 = "Standardmäßig externe Anwendungen"
ExtAppWriteExplanation2 = "kann nicht in den Speicher schreiben"
ExtAppWriteExplanation3 = "Flash (dauerhaft) Ihres Rechners."
ExtAppEnabled = "Aufstecken"
+ClearShift = "Tastenkombination shift + clear"
diff --git a/apps/settings/base.en.i18n b/apps/settings/base.en.i18n
index c6a048e2a..4395c0ae2 100644
--- a/apps/settings/base.en.i18n
+++ b/apps/settings/base.en.i18n
@@ -72,14 +72,6 @@ Time = "Time"
RTCWarning1 = "Enabling the clock drains the battery faster"
RTCWarning2 = "when the calculator is powered off."
SyntaxHighlighting = "Syntax Highlighting"
-USBExplanation1 = "The USB protection protects"
-USBExplanation2 = "the calculator from"
-USBExplanation3 = "unintentional locking"
-USBProtection = "USB Protection"
-USBProtectionLevel = "Updates accepted"
-USBDefaultLevel = "Based on Upsilon"
-USBLowLevel = "Based on Omega"
-USBParanoidLevel = "None"
Normal = "Normal"
IdleTimeBeforeDimming = "Dim after (s)"
IdleTimeBeforeSuspend = "Suspend after (s)"
@@ -89,3 +81,4 @@ ExtAppWriteExplanation1 = "By default, external applications"
ExtAppWriteExplanation2 = "cannot write to memory"
ExtAppWriteExplanation3 = "flash (persistent) of your calculator."
ExtAppEnabled = "Pin up"
+ClearShift = "Shift + clear shortcut"
diff --git a/apps/settings/base.es.i18n b/apps/settings/base.es.i18n
index 839f25ba8..d70e8bdd5 100644
--- a/apps/settings/base.es.i18n
+++ b/apps/settings/base.es.i18n
@@ -72,14 +72,6 @@ Time = "Hora"
RTCWarning1 = "Activar el reloj gasta la batería más rápido"
RTCWarning2 = "cuando la calculadora está apagada."
SyntaxHighlighting = "Resaltado de sintaxis"
-USBExplanation1 = "La protección USB protege"
-USBExplanation2 = "su calculadora del"
-USBExplanation3 = "bloqueo involuntario"
-USBProtection = "Protección USB"
-USBProtectionLevel = "Actualizaciones aceptadas"
-USBDefaultLevel = "Basado en Upsilon"
-USBLowLevel = "Basado en Omega"
-USBParanoidLevel = "Ninguno"
Normal = "Normal"
IdleTimeBeforeDimming = "Oscurecer después de (s)"
IdleTimeBeforeSuspend = "Suspender después de (s)"
@@ -89,3 +81,4 @@ ExtAppWriteExplanation1 = "Por defecto, las aplicaciones externas"
ExtAppWriteExplanation2 = "no se puede escribir en la memoria"
ExtAppWriteExplanation3 = "flash (persistente) de su calculadora."
ExtAppEnabled = "Fijar"
+ClearShift = "Atajo de shift + clear"
diff --git a/apps/settings/base.fr.i18n b/apps/settings/base.fr.i18n
index 87a4596ce..85817ffe5 100644
--- a/apps/settings/base.fr.i18n
+++ b/apps/settings/base.fr.i18n
@@ -72,14 +72,7 @@ Time = "Heure"
RTCWarning1 = "Activer l'horloge décharge la batterie plus"
RTCWarning2 = "vite quand la calculatrice est éteinte."
SyntaxHighlighting = "Coloration syntaxique"
-USBExplanation1 = "La protection USB protège votre"
-USBExplanation2 = "calculatrice contre un verrouillage"
-USBExplanation3 = "non-intentionnel"
-USBProtection = "Protection USB"
-USBProtectionLevel = "Mise à jour acceptées"
-USBDefaultLevel = "Basées sur Upsilon"
-USBLowLevel = "Basées sur Omega"
-USBParanoidLevel = "Aucune"
+ClearShift = "Raccourci shift + clear"
Normal = "Normale"
IdleTimeBeforeDimming = "Assombrir après (s)"
IdleTimeBeforeSuspend = "Éteindre après (s)"
diff --git a/apps/settings/base.hu.i18n b/apps/settings/base.hu.i18n
index 99dc79fc3..1874de1c8 100644
--- a/apps/settings/base.hu.i18n
+++ b/apps/settings/base.hu.i18n
@@ -72,14 +72,6 @@ Time = "Óra"
RTCWarning1 = "Amikor a számológép alvómódban van, az óra"
RTCWarning2 = "használása az elemet gyorsabban meríti ki."
SyntaxHighlighting = "Szintaxis kiemelés"
-USBExplanation1 = "Az USB-védelem megvédi"
-USBExplanation2 = "a számológépet a nem"
-USBExplanation3 = "szándékos reteszeléstől"
-USBProtection = "USB védelem"
-USBProtectionLevel = "Elfogadott frissítések"
-USBDefaultLevel = "Upsilon alapján"
-USBLowLevel = "Omega alapján"
-USBParanoidLevel = "Egyik sem"
Normal = "Normale"
IdleTimeBeforeDimming = "Assombrir après (s)"
IdleTimeBeforeSuspend = "Éteindre après (s)"
@@ -89,3 +81,4 @@ ExtAppWriteExplanation1 = "Alapértelmezés szerint külső alkalmazások"
ExtAppWriteExplanation2 = "nem tud a memóriába írni"
ExtAppWriteExplanation3 = "villog (tartósan) a számológép."
ExtAppEnabled = "Feltűz"
+ClearShift = "Gyorsbillentyű shift + clear"
diff --git a/apps/settings/base.it.i18n b/apps/settings/base.it.i18n
index 2603da889..850bed789 100644
--- a/apps/settings/base.it.i18n
+++ b/apps/settings/base.it.i18n
@@ -32,60 +32,53 @@ Real = "Reale "
Cartesian = "Algebrico "
Polar = "Esponenziale "
Brightness = "Luminosità"
-BrightnessSettings = "Impostazioni di luminosità"
-SoftwareVersion = "Epsilon version"
-UpsilonVersion = "Upsilon version"
-OmegaVersion = "Omega version"
-Username = "Name"
-MicroPythonVersion = "µPython version"
+BrightnessSettings = "Impostazioni luminosità"
+SoftwareVersion = "Versione di Epsilon"
+UpsilonVersion = "Versione di Upsilon"
+OmegaVersion = "Versione di Omega"
+Username = "Nome"
+MicroPythonVersion = "Versione µPython"
FontSizes = "Carattere Python"
LargeFont = "Grande "
SmallFont = "Piccolo "
SerialNumber = "Numero di serie"
UpdatePopUp = "Promemoria aggiornamento"
BetaPopUp = "Promemoria beta"
-Contributors = "Contributors"
+Contributors = "Contributori"
Battery = "Batteria"
-Accessibility = "Accessibility"
-AccessibilityInvertColors = "Invert colors"
-AccessibilityMagnify = "Magnify"
-AccessibilityGamma = "Gamma correction"
-AccessibilityGammaRed = "Red gamma"
-AccessibilityGammaGreen = "Green gamma"
-AccessibilityGammaBlue = "Blue gamma"
-MathOptions = "Math options"
-SymbolMultiplication = "Multiply"
-SymbolMultiplicationCross = "Cross "
-SymbolMultiplicationMiddleDot = "Dot "
-SymbolMultiplicationStar = "Star "
-SymbolMultiplicationAutoSymbol = "Auto "
-SymbolFunction = "Expression format "
-SymbolDefaultFunction = "Default "
-SymbolArgFunction = "Empty "
-SymbolArgDefaultFunction = "Argument "
-MemUse = "Memory"
-DateTime = "Date/time"
+Accessibility = "Accessibilità"
+AccessibilityInvertColors = "Inversione colori"
+AccessibilityMagnify = "Ingrandimento"
+AccessibilityGamma = "Correzione gamma"
+AccessibilityGammaRed = "Gamma del rosso"
+AccessibilityGammaGreen = "Gamma del verde"
+AccessibilityGammaBlue = "Gamma del blu"
+MathOptions = "Opzioni matematica"
+SymbolMultiplication = "Simbolo moltiplicaz."
+SymbolMultiplicationCross = "Croce "
+SymbolMultiplicationMiddleDot = "Punto "
+SymbolMultiplicationStar = "Stella "
+SymbolMultiplicationAutoSymbol = "Automatico "
+SymbolFunction = "Formato espressioni "
+SymbolDefaultFunction = "Predefinito "
+SymbolArgFunction = "Vuoto "
+SymbolArgDefaultFunction = "Argomento "
+MemUse = "Memoria"
+DateTime = "Data/ora"
ExternalApps = "App esterne"
-ActivateClock = "Activate clock"
-Date = "Date"
-Time = "Time"
-RTCWarning1 = "Enabling the clock drains the battery faster"
-RTCWarning2 = "when the calculator is powered off."
-SyntaxHighlighting = "Evidenziazione della sintassi"
-USBExplanation1 = "La protezione USB protegge"
-USBExplanation2 = "la calcolatrice dal"
-USBExplanation3 = "blocco involontario"
-USBProtection = "Protezione USB"
-USBProtectionLevel = "Aggiornamenti accettati"
-USBDefaultLevel = "Basato su Upsilon"
-USBLowLevel = "A base di Omega"
-USBParanoidLevel = "Nessuno"
+ActivateClock = "Attiva orologio"
+Date = "Data"
+Time = "Ora"
+RTCWarning1 = "Attivare l'orologio drena la batteria più"
+RTCWarning2 = "velocemente quando la calcolatrice è spenta."
+SyntaxHighlighting = "Evidenz. sintassi"
Normal = "Normale"
IdleTimeBeforeDimming = "Scurisci dopo (s)"
IdleTimeBeforeSuspend = "Sospendi dopo (s)"
-BrightnessShortcut = "Passaggi di scelta rapida"
+BrightnessShortcut = "Livelli scelta rapida"
ExtAppWrite = "Scrittura abilitata"
-ExtAppWriteExplanation1 = "Per impostazione predefinita, applicazioni esterne"
-ExtAppWriteExplanation2 = "non può scrivere in memoria"
-ExtAppWriteExplanation3 = "flash (persistente) della calcolatrice."
+ExtAppWriteExplanation1 = "Per impostazione predefinita, le app esterne"
+ExtAppWriteExplanation2 = "non possono scrivere in memoria flash"
+ExtAppWriteExplanation3 = "(persistente) della calcolatrice."
ExtAppEnabled = "Affiggere"
+ClearShift = "Scorciatoia shift + clear"
diff --git a/apps/settings/base.nl.i18n b/apps/settings/base.nl.i18n
index d71a76824..24b20a6a9 100644
--- a/apps/settings/base.nl.i18n
+++ b/apps/settings/base.nl.i18n
@@ -72,14 +72,6 @@ Time = "Time"
RTCWarning1 = "Enabling the clock drains the battery faster"
RTCWarning2 = "when the calculator is powered off."
SyntaxHighlighting = "Syntax Highlighting"
-USBExplanation1 = "USB-beveiliging beschermt uw"
-USBExplanation2 = "rekenmachine tegen"
-USBExplanation3 = "onbedoelde vergrendeling"
-USBProtection = "USB-beveiliging"
-USBProtectionLevel = "Updates geaccepteerd"
-USBDefaultLevel = "Gebaseerd op Upsilon"
-USBLowLevel = "Op basis van Omega"
-USBParanoidLevel = "Geen"
Normal = "Normaal"
IdleTimeBeforeDimming = "Donkerder maken na (s)"
IdleTimeBeforeSuspend = "Suspend after (s)"
@@ -89,3 +81,4 @@ ExtAppWriteExplanation1 = "Standaard zijn externe toepassingen"
ExtAppWriteExplanation2 = "kan niet naar het geheugen schrijven"
ExtAppWriteExplanation3 = "flash (aanhoudend) van uw rekenmachine."
ExtAppEnabled = "Vastpinnen"
+ClearShift = "Sneltoets shift + clear"
diff --git a/apps/settings/base.pt.i18n b/apps/settings/base.pt.i18n
index b7639cb6e..8a9d83c9f 100644
--- a/apps/settings/base.pt.i18n
+++ b/apps/settings/base.pt.i18n
@@ -72,14 +72,6 @@ Time = "Time"
RTCWarning1 = "Enabling the clock drains the battery faster"
RTCWarning2 = "when the calculator is powered off."
SyntaxHighlighting = "Destaque da sintaxe"
-USBExplanation1 = "A proteção USB protege"
-USBExplanation2 = "sua calculadora contra"
-USBExplanation3 = "bloqueios não intencionais"
-USBProtection = "Proteção USB"
-USBProtectionLevel = "Atualizações aceitas"
-USBDefaultLevel = "Baseado em Upsilon"
-USBLowLevel = "Baseado em Ômega"
-USBParanoidLevel = "Nenhum"
Normal = "Normal"
IdleTimeBeforeDimming = "Diminuir depois (s)"
IdleTimeBeforeSuspend = "Suspender depois (s)"
@@ -89,3 +81,4 @@ ExtAppWriteExplanation1 = "Por padrão, aplicativos externos"
ExtAppWriteExplanation2 = "não pode gravar na memória"
ExtAppWriteExplanation3 = "flash (persistente) de sua calculadora."
ExtAppEnabled = "Pôster"
+ClearShift = "Shift de shift + clear"
diff --git a/apps/settings/base.universal.i18n b/apps/settings/base.universal.i18n
index 124dc2112..210e673fb 100644
--- a/apps/settings/base.universal.i18n
+++ b/apps/settings/base.universal.i18n
@@ -1,4 +1 @@
UsbSetting = "USB"
-USBDefaultLevelDesc = "L0"
-USBLowLevelDesc = "L1"
-USBParanoidLevelDesc = "L2"
diff --git a/apps/settings/main_controller.cpp b/apps/settings/main_controller.cpp
index 4b590b45f..f797520fb 100644
--- a/apps/settings/main_controller.cpp
+++ b/apps/settings/main_controller.cpp
@@ -15,8 +15,6 @@ constexpr SettingsMessageTree s_modelFloatDisplayModeChildren[4] = {SettingsMess
constexpr SettingsMessageTree s_modelComplexFormatChildren[3] = {SettingsMessageTree(I18n::Message::Real), SettingsMessageTree(I18n::Message::Cartesian), SettingsMessageTree(I18n::Message::Polar)};
constexpr SettingsMessageTree s_modelDateTimeChildren[3] = {SettingsMessageTree(I18n::Message::ActivateClock), SettingsMessageTree(I18n::Message::Date), SettingsMessageTree(I18n::Message::Time)};
constexpr SettingsMessageTree s_symbolChildren[4] = {SettingsMessageTree(I18n::Message::SymbolMultiplicationCross),SettingsMessageTree(I18n::Message::SymbolMultiplicationMiddleDot),SettingsMessageTree(I18n::Message::SymbolMultiplicationStar),SettingsMessageTree(I18n::Message::SymbolMultiplicationAutoSymbol)};
-constexpr SettingsMessageTree s_usbProtectionChildren[2] = {SettingsMessageTree(I18n::Message::USBProtection), SettingsMessageTree(I18n::Message::USBProtectionLevel, s_usbProtectionLevelChildren)};
-constexpr SettingsMessageTree s_usbProtectionLevelChildren[3] = {SettingsMessageTree(I18n::Message::USBDefaultLevel), SettingsMessageTree(I18n::Message::USBLowLevel), SettingsMessageTree(I18n::Message::USBParanoidLevel)};
constexpr SettingsMessageTree s_externalChildren[2] = {SettingsMessageTree(I18n::Message::ExtAppWrite), SettingsMessageTree(I18n::Message::ExtAppEnabled)};
constexpr SettingsMessageTree s_symbolFunctionChildren[3] = {SettingsMessageTree(I18n::Message::SymbolDefaultFunction), SettingsMessageTree(I18n::Message::SymbolArgDefaultFunction), SettingsMessageTree(I18n::Message::SymbolArgFunction)};
constexpr SettingsMessageTree s_modelMathOptionsChildren[6] = {SettingsMessageTree(I18n::Message::AngleUnit, s_modelAngleChildren), SettingsMessageTree(I18n::Message::DisplayMode, s_modelFloatDisplayModeChildren), SettingsMessageTree(I18n::Message::EditionMode, s_modelEditionModeChildren), SettingsMessageTree(I18n::Message::SymbolFunction, s_symbolFunctionChildren), SettingsMessageTree(I18n::Message::ComplexFormat, s_modelComplexFormatChildren), SettingsMessageTree(I18n::Message::SymbolMultiplication, s_symbolChildren)};
@@ -26,7 +24,7 @@ constexpr SettingsMessageTree s_contributorsChildren[18] = {SettingsMessageTree(
// Code Settings
#ifdef HAS_CODE
-constexpr SettingsMessageTree s_codeChildren[3] = {SettingsMessageTree(I18n::Message::FontSizes, s_modelFontChildren), SettingsMessageTree(I18n::Message::Autocomplete), SettingsMessageTree(I18n::Message::SyntaxHighlighting)};
+constexpr SettingsMessageTree s_codeChildren[4] = {SettingsMessageTree(I18n::Message::FontSizes, s_modelFontChildren), SettingsMessageTree(I18n::Message::Autocomplete), SettingsMessageTree(I18n::Message::SyntaxHighlighting), SettingsMessageTree(I18n::Message::ClearShift)};
#endif
constexpr SettingsMessageTree s_modelFontChildren[2] = {SettingsMessageTree(I18n::Message::LargeFont), SettingsMessageTree(I18n::Message::SmallFont)};
diff --git a/apps/settings/main_controller.h b/apps/settings/main_controller.h
index e78aff9a2..3e1c5ba82 100644
--- a/apps/settings/main_controller.h
+++ b/apps/settings/main_controller.h
@@ -25,7 +25,7 @@ extern const Shared::SettingsMessageTree s_symbolChildren[4];
extern const Shared::SettingsMessageTree s_symbolFunctionChildren[3];
extern const Shared::SettingsMessageTree s_modelMathOptionsChildren[6];
extern const Shared::SettingsMessageTree s_modelFontChildren[2];
-extern const Shared::SettingsMessageTree s_codeChildren[3];
+extern const Shared::SettingsMessageTree s_codeChildren[4];
extern const Shared::SettingsMessageTree s_modelDateTimeChildren[3];
extern const Shared::SettingsMessageTree s_accessibilityChildren[6];
extern const Shared::SettingsMessageTree s_contributorsChildren[18];
diff --git a/apps/settings/main_controller_prompt_beta.cpp b/apps/settings/main_controller_prompt_beta.cpp
index 3b169700c..6b1825ddd 100644
--- a/apps/settings/main_controller_prompt_beta.cpp
+++ b/apps/settings/main_controller_prompt_beta.cpp
@@ -1,7 +1,8 @@
-#include "main_controller.h"
-#include "../exam_mode_configuration.h"
#include
+#include "../exam_mode_configuration.h"
+#include "main_controller.h"
+
using namespace Shared;
namespace Settings {
@@ -17,7 +18,6 @@ constexpr SettingsMessageTree s_modelMenu[] =
SettingsMessageTree(I18n::Message::CodeApp, s_codeChildren),
#endif
SettingsMessageTree(I18n::Message::BetaPopUp),
- //SettingsMessageTree(I18n::Message::UsbSetting, s_usbProtectionChildren),
SettingsMessageTree(I18n::Message::ExternalApps, s_externalChildren),
SettingsMessageTree(I18n::Message::Accessibility, s_accessibilityChildren),
SettingsMessageTree(I18n::Message::About, s_modelAboutChildren)};
diff --git a/apps/settings/main_controller_prompt_none.cpp b/apps/settings/main_controller_prompt_none.cpp
index 46511e360..1911c2af4 100644
--- a/apps/settings/main_controller_prompt_none.cpp
+++ b/apps/settings/main_controller_prompt_none.cpp
@@ -17,7 +17,6 @@ constexpr SettingsMessageTree s_modelMenu[] =
#ifdef HAS_CODE
SettingsMessageTree(I18n::Message::CodeApp, s_codeChildren),
#endif
- //SettingsMessageTree(I18n::Message::UsbSetting, s_usbProtectionChildren),
SettingsMessageTree(I18n::Message::ExternalApps, s_externalChildren),
SettingsMessageTree(I18n::Message::Accessibility, s_accessibilityChildren),
SettingsMessageTree(I18n::Message::About, s_modelAboutChildren)};
diff --git a/apps/settings/main_controller_prompt_update.cpp b/apps/settings/main_controller_prompt_update.cpp
index b56612457..c5104c8d4 100644
--- a/apps/settings/main_controller_prompt_update.cpp
+++ b/apps/settings/main_controller_prompt_update.cpp
@@ -1,11 +1,12 @@
-#include "main_controller.h"
-#include "../exam_mode_configuration.h"
#include
-namespace Settings {
+#include "../exam_mode_configuration.h"
+#include "main_controller.h"
using namespace Shared;
+namespace Settings {
+
constexpr SettingsMessageTree s_modelMenu[] =
{SettingsMessageTree(I18n::Message::MathOptions, s_modelMathOptionsChildren),
SettingsMessageTree(I18n::Message::BrightnessSettings, s_brightnessChildren),
@@ -17,10 +18,8 @@ constexpr SettingsMessageTree s_modelMenu[] =
SettingsMessageTree(I18n::Message::CodeApp, s_codeChildren),
#endif
SettingsMessageTree(I18n::Message::UpdatePopUp),
- SettingsMessageTree(I18n::Message::Accessibility, s_accessibilityChildren),
- // SettingsMessageTree(I18n::Message::UsbSetting, s_usbProtectionChildren),
- SettingsMessageTree(I18n::Message::UsbSetting, s_usbProtectionChildren),
SettingsMessageTree(I18n::Message::ExternalApps, s_externalChildren),
+ SettingsMessageTree(I18n::Message::Accessibility, s_accessibilityChildren),
SettingsMessageTree(I18n::Message::About, s_modelAboutChildren)};
constexpr SettingsMessageTree s_model = SettingsMessageTree(I18n::Message::SettingsApp, s_modelMenu);
diff --git a/apps/settings/sub_menu/about_controller.cpp b/apps/settings/sub_menu/about_controller.cpp
index a022c48f0..dcae3211a 100644
--- a/apps/settings/sub_menu/about_controller.cpp
+++ b/apps/settings/sub_menu/about_controller.cpp
@@ -1,5 +1,6 @@
#include "about_controller.h"
#include "../../../python/src/py/mpconfig.h"
+#include "poincare/division.h"
#include
#include
#include
diff --git a/apps/settings/sub_menu/code_options_controller.cpp b/apps/settings/sub_menu/code_options_controller.cpp
index ae7d5bbc2..d2d2c0a3b 100644
--- a/apps/settings/sub_menu/code_options_controller.cpp
+++ b/apps/settings/sub_menu/code_options_controller.cpp
@@ -13,6 +13,7 @@ CodeOptionsController::CodeOptionsController(Responder * parentResponder) :
m_chevronCellFontSize.setMessageFont(KDFont::LargeFont);
m_switchCellAutoCompletion.setMessageFont(KDFont::LargeFont);
m_switchCellSyntaxHighlighting.setMessageFont(KDFont::LargeFont);
+ m_switchCellClearShift.setMessageFont(KDFont::LargeFont);
}
bool CodeOptionsController::handleEvent(Ion::Events::Event event) {
@@ -26,6 +27,10 @@ bool CodeOptionsController::handleEvent(Ion::Events::Event event) {
GlobalPreferences::sharedGlobalPreferences()->setSyntaxhighlighting(!GlobalPreferences::sharedGlobalPreferences()->syntaxhighlighting());
m_selectableTableView.reloadCellAtLocation(m_selectableTableView.selectedColumn(), m_selectableTableView.selectedRow());
break;
+ case 3:
+ GlobalPreferences::sharedGlobalPreferences()->setClearShift(!GlobalPreferences::sharedGlobalPreferences()->clearShift());
+ m_selectableTableView.reloadCellAtLocation(m_selectableTableView.selectedColumn(), m_selectableTableView.selectedRow());
+ break;
default:
GenericSubController * subController = nullptr;
subController = &m_preferencesController;
@@ -48,8 +53,10 @@ HighlightCell * CodeOptionsController::reusableCell(int index, int type) {
}
else if (index == 1) {
return &m_switchCellAutoCompletion;
+ } else if (index == 2) {
+ return &m_switchCellSyntaxHighlighting;
}
- return &m_switchCellSyntaxHighlighting;
+ return &m_switchCellClearShift;
}
int CodeOptionsController::reusableCellCount(int type) {
@@ -79,6 +86,11 @@ void CodeOptionsController::willDisplayCellForIndex(HighlightCell * cell, int in
SwitchView * mySwitch = (SwitchView *)mySwitchCell->accessoryView();
mySwitch->setState(GlobalPreferences::sharedGlobalPreferences()->syntaxhighlighting());
}
+ else if (thisLabel == I18n::Message::ClearShift) {
+ MessageTableCellWithSwitch * mySwitchCell = (MessageTableCellWithSwitch *)cell;
+ SwitchView * mySwitch = (SwitchView *)mySwitchCell->accessoryView();
+ mySwitch->setState(GlobalPreferences::sharedGlobalPreferences()->clearShift());
+ }
#endif
}
diff --git a/apps/settings/sub_menu/code_options_controller.h b/apps/settings/sub_menu/code_options_controller.h
index 5f9b6acea..1a14c75f0 100644
--- a/apps/settings/sub_menu/code_options_controller.h
+++ b/apps/settings/sub_menu/code_options_controller.h
@@ -14,11 +14,12 @@ public:
int reusableCellCount(int type) override;
void willDisplayCellForIndex(HighlightCell * cell, int index) override;
private:
- constexpr static int k_totalNumberOfCell = 4;
+ constexpr static int k_totalNumberOfCell = 5;
PreferencesController m_preferencesController;
MessageTableCellWithChevronAndMessage m_chevronCellFontSize;
MessageTableCellWithSwitch m_switchCellAutoCompletion;
MessageTableCellWithSwitch m_switchCellSyntaxHighlighting;
+ MessageTableCellWithSwitch m_switchCellClearShift;
};
}
diff --git a/apps/settings/sub_menu/datetime_controller.cpp b/apps/settings/sub_menu/datetime_controller.cpp
index 1f9e801b9..35fb8c994 100644
--- a/apps/settings/sub_menu/datetime_controller.cpp
+++ b/apps/settings/sub_menu/datetime_controller.cpp
@@ -30,7 +30,10 @@ bool DateTimeController::handleEvent(Ion::Events::Event event) {
if (selectedRow() == 0) {
clockEnabled = !clockEnabled;
if (clockEnabled) {
+ #ifndef _FXCG
+ // This doesn't apply on Casio calculators
Container::activeApp()->displayWarning(I18n::Message::RTCWarning1, I18n::Message::RTCWarning2);
+ #endif
}
Ion::RTC::setMode(clockEnabled ? Ion::RTC::Mode::HSE : Ion::RTC::Mode::Disabled);
}
diff --git a/apps/settings/sub_menu/preferences_controller.cpp b/apps/settings/sub_menu/preferences_controller.cpp
index 06650e842..dbf254966 100644
--- a/apps/settings/sub_menu/preferences_controller.cpp
+++ b/apps/settings/sub_menu/preferences_controller.cpp
@@ -170,15 +170,6 @@ Layout PreferencesController::layoutForPreferences(I18n::Message message) {
return LayoutHelper::String(text, strlen(text), font);
}
- // DFU Protection level
- case I18n::Message::USBDefaultLevel:
- case I18n::Message::USBLowLevel:
- case I18n::Message::USBParanoidLevel:
- {
- const char * text = " ";
- return LayoutHelper::String(text, strlen(text), k_layoutFont);
- }
-
default:
assert(false);
return Layout();
diff --git a/apps/shared.de.i18n b/apps/shared.de.i18n
index b72d2803a..f4fb2d05f 100644
--- a/apps/shared.de.i18n
+++ b/apps/shared.de.i18n
@@ -97,3 +97,27 @@ ColorPurple = "Violett "
ColorCyan = "Cyan "
ColorPink = "Rosa "
ColorOrange = "Orange "
+TimeDimension = "Zeit"
+DistanceDimension = "Distanz"
+MassDimension = "Masse"
+CurrentDimension = "Betrieb"
+TemperatureDimension = "Temperatur"
+AmountOfSubstanceDimension = "Quantität der Materie"
+LuminousIntensityDimension = "Lichtintensität"
+FrequencyDimension = "Frequenz"
+ForceDimension = "Stärke"
+PressureDimension = "Druck"
+EnergyDimension = "Energie"
+PowerDimension = "Mächtig"
+ElectricChargeDimension = "Elektrische Ladung"
+ElectricPotentialDimension = "Elektrisches Potenzial"
+ElectricCapacitanceDimension = "Elektrische Kapazität"
+ElectricResistanceDimension = "Elektrischer Wiederstand"
+ElectricConductanceDimension = "elektrische Leitfähigkeit"
+MagneticFluxDimension = "magnetischer Fluss"
+MagneticFieldDimension = "Magnetfeld"
+InductanceDimension = "Induktivität"
+CatalyticActivityDimension = "Katalytische Aktivität"
+SurfaceDimension = "Auftauchen"
+VolumeDimension = "Volumen"
+SpeedDimension = "Geschwindigkeit"
diff --git a/apps/shared.en.i18n b/apps/shared.en.i18n
index 257e39c94..a5f65b594 100644
--- a/apps/shared.en.i18n
+++ b/apps/shared.en.i18n
@@ -97,3 +97,27 @@ ColorPurple = "Purple "
ColorCyan = "Cyan "
ColorPink = "Pink "
ColorOrange = "Orange "
+TimeDimension = "Time"
+DistanceDimension = "Distance"
+MassDimension = "Mass"
+CurrentDimension = "Running"
+TemperatureDimension = "Temperature"
+AmountOfSubstanceDimension = "Quantity of matter"
+LuminousIntensityDimension = "Light intensity"
+FrequencyDimension = "Frequency"
+ForceDimension = "Strength"
+PressureDimension = "Pressure"
+EnergyDimension = "Energy"
+PowerDimension = "Powerful"
+ElectricChargeDimension = "Electrical charge"
+ElectricPotentialDimension = "Electric potential"
+ElectricCapacitanceDimension = "Electrical capacity"
+ElectricResistanceDimension = "Electrical resistance"
+ElectricConductanceDimension = "electrical conductance"
+MagneticFluxDimension = "magnetic flux"
+MagneticFieldDimension = "Magnetic field"
+InductanceDimension = "Inductance"
+CatalyticActivityDimension = "Catalytic activity"
+SurfaceDimension = "Surface"
+VolumeDimension = "Volume"
+SpeedDimension = "Speed"
diff --git a/apps/shared.es.i18n b/apps/shared.es.i18n
index f1f6ca4ad..cc76ce7e0 100644
--- a/apps/shared.es.i18n
+++ b/apps/shared.es.i18n
@@ -97,3 +97,27 @@ ColorPurple = "Púrpura "
ColorCyan = "Cian "
ColorPink = "Rosa "
ColorOrange = "Naranja "
+TimeDimension = "Tiempo"
+DistanceDimension = "Distancia"
+MassDimension = "Masa"
+CurrentDimension = "Correr"
+TemperatureDimension = "La temperatura"
+AmountOfSubstanceDimension = "cantidad de materia"
+LuminousIntensityDimension = "Intensidad de luz"
+FrequencyDimension = "Frecuencia"
+ForceDimension = "Fuerza"
+PressureDimension = "Presión"
+EnergyDimension = "Energía"
+PowerDimension = "Potencia"
+ElectricChargeDimension = "Carga eléctrica"
+ElectricPotentialDimension = "Potencial eléctrico"
+ElectricCapacitanceDimension = "Capacidad eléctrica"
+ElectricResistanceDimension = "Resistencia eléctrica"
+ElectricConductanceDimension = "conductancia eléctrica"
+MagneticFluxDimension = "flujo magnético"
+MagneticFieldDimension = "Campo magnético"
+InductanceDimension = "Inductancia"
+CatalyticActivityDimension = "Actividad catalítica"
+SurfaceDimension = "Superficie"
+VolumeDimension = "Volumen"
+SpeedDimension = "Velocidad"
\ No newline at end of file
diff --git a/apps/shared.fr.i18n b/apps/shared.fr.i18n
index e7c89c7a0..2428b309b 100644
--- a/apps/shared.fr.i18n
+++ b/apps/shared.fr.i18n
@@ -97,3 +97,27 @@ ColorPurple = "Violet "
ColorCyan = "Cyan "
ColorPink = "Rose "
ColorOrange = "Orange "
+TimeDimension = "Temps"
+DistanceDimension = "Distance"
+MassDimension = "Masse"
+CurrentDimension = "Courant"
+TemperatureDimension = "Température"
+AmountOfSubstanceDimension = "Quantité de matière"
+LuminousIntensityDimension = "Intensité lumineuse"
+FrequencyDimension = "Fréquence"
+ForceDimension = "Force"
+PressureDimension = "Pression"
+EnergyDimension = "Énergie"
+PowerDimension = "Puissance"
+ElectricChargeDimension = "Charge électrique"
+ElectricPotentialDimension = "Potentiel électrique"
+ElectricCapacitanceDimension = "Capacité électrique"
+ElectricResistanceDimension = "Résistance électrique"
+ElectricConductanceDimension = "Conductance électrique"
+MagneticFluxDimension = "Flux magnétique"
+MagneticFieldDimension = "Champ magnétique"
+InductanceDimension = "Inductance"
+CatalyticActivityDimension = "Activité catalytique"
+SurfaceDimension = "Surface"
+VolumeDimension = "Volume"
+SpeedDimension = "Vitesse"
diff --git a/apps/shared.hu.i18n b/apps/shared.hu.i18n
index 7931f0c75..91e45f3d1 100644
--- a/apps/shared.hu.i18n
+++ b/apps/shared.hu.i18n
@@ -97,3 +97,28 @@ ColorPurple = "Lila "
ColorCyan = "Cián "
ColorPink = "Rózsaszín "
ColorOrange = "Narancssárga "
+TimeDimension = "Idő"
+DistanceDimension = "Távolság"
+MassDimension = "Tömeg"
+CurrentDimension = "Futó"
+TemperatureDimension = "Hőfok"
+AmountOfSubstanceDimension = "Az anyag mennyisége"
+LuminousIntensityDimension = "Fény intenzitása"
+FrequencyDimension = "Frekvencia"
+ForceDimension = "Erő"
+PressureDimension = "Nyomás"
+EnergyDimension = "Energia"
+PowerDimension = "Erős"
+ElectricChargeDimension = "Elektromos töltő"
+ElectricPotentialDimension = "Elektromos potenciál"
+ElectricCapacitanceDimension = "Elektromos kapacitás"
+ElectricResistanceDimension = "Elektromos ellenállás"
+ElectricConductanceDimension = "elektromos vezetőképesség"
+MagneticFluxDimension = "mágneses fluxus"
+MagneticFieldDimension = "Mágneses mező"
+InductanceDimension = "Induktivitás"
+CatalyticActivityDimension = "Katalitikus aktivitás"
+SurfaceDimension = "Felület"
+VolumeDimension = "Hangerő"
+SpeedDimension = "Sebesség"
+Factorial = "Faktorál"
diff --git a/apps/shared.it.i18n b/apps/shared.it.i18n
index 91bef493b..d1932fbd3 100644
--- a/apps/shared.it.i18n
+++ b/apps/shared.it.i18n
@@ -97,3 +97,28 @@ ColorPurple = "Viola "
ColorCyan = "Ciano"
ColorPink = "Rosa "
ColorOrange = "Arancia "
+TimeDimension = "Volta"
+DistanceDimension = "Distanza"
+MassDimension = "Messa"
+CurrentDimension = "In esecuzione"
+TemperatureDimension = "Temperatura"
+AmountOfSubstanceDimension = "Quantità di materia"
+LuminousIntensityDimension = "Intensità luminosa"
+FrequencyDimension = "Frequenza"
+ForceDimension = "Forza"
+PressureDimension = "Pressione"
+EnergyDimension = "Energia"
+PowerDimension = "Potere"
+ElectricChargeDimension = "Carica elettrica"
+ElectricPotentialDimension = "Potenziale elettrico"
+ElectricCapacitanceDimension = "Capacità elettrica"
+ElectricResistanceDimension = "Resistenza elettrica"
+ElectricConductanceDimension = "conduttanza elettrica"
+MagneticFluxDimension = "flusso magnetico"
+MagneticFieldDimension = "Campo magnetico"
+InductanceDimension = "Induttanza"
+CatalyticActivityDimension = "Attività catalitica"
+SurfaceDimension = "Superficie"
+VolumeDimension = "Volume"
+SpeedDimension = "Velocità"
+Factorial = "Fattoriale"
diff --git a/apps/shared.nl.i18n b/apps/shared.nl.i18n
index 62060e011..e63e98605 100644
--- a/apps/shared.nl.i18n
+++ b/apps/shared.nl.i18n
@@ -97,3 +97,28 @@ ColorPurple = "Purper"
ColorCyan = "Cyaan "
ColorPink = "Roze"
ColorOrange = "Oranje"
+TimeDimension = "Tijd"
+DistanceDimension = "Afstand"
+MassDimension = "Massa"
+CurrentDimension = "Rennen"
+TemperatureDimension = "Temperatuur"
+AmountOfSubstanceDimension = "Hoeveelheid materie"
+LuminousIntensityDimension = "Lichtsterkte"
+FrequencyDimension = "Frequentie"
+ForceDimension = "Kracht"
+PressureDimension = "Druk"
+EnergyDimension = "Energie"
+PowerDimension = "Kracht"
+ElectricChargeDimension = "Elektrische lading"
+ElectricPotentialDimension = "elektrische potentiaal"
+ElectricCapacitanceDimension = "elektrische capaciteit:"
+ElectricResistanceDimension = "Elektrische weerstand"
+ElectricConductanceDimension = "elektrische geleiding:"
+MagneticFluxDimension = "magnetische flux"
+MagneticFieldDimension = "Magnetisch veld"
+InductanceDimension = "Inductie"
+CatalyticActivityDimension = "Katalytische activiteit"
+SurfaceDimension = "Oppervlak"
+VolumeDimension = "Volume"
+SpeedDimension = "Snelheid"
+Factorial = "Faculteit"
diff --git a/apps/shared.pt.i18n b/apps/shared.pt.i18n
index 4edea43ba..de0852119 100644
--- a/apps/shared.pt.i18n
+++ b/apps/shared.pt.i18n
@@ -97,3 +97,27 @@ ColorPurple = "Roxa "
ColorCyan = "Ciano"
ColorPink = "Cor de rosa "
ColorOrange = "Laranja "
+TimeDimension = "Tempo"
+DistanceDimension = "Distância"
+MassDimension = "Massa"
+CurrentDimension = "Corrida"
+TemperatureDimension = "Temperatura"
+AmountOfSubstanceDimension = "Quantidade de matéria"
+LuminousIntensityDimension = "Intensidade da luz"
+FrequencyDimension = "Frequência"
+ForceDimension = "Força"
+PressureDimension = "Pressão"
+EnergyDimension = "Energia"
+PowerDimension = "Poderoso"
+ElectricChargeDimension = "Carga elétrica"
+ElectricPotentialDimension = "Potencial elétrico"
+ElectricCapacitanceDimension = "Capacidade elétrica"
+ElectricResistanceDimension = "Resistência elétrica"
+ElectricConductanceDimension = "condutância elétrica"
+MagneticFluxDimension = "fluxo magnético"
+MagneticFieldDimension = "Campo magnético"
+InductanceDimension = "Indutância"
+CatalyticActivityDimension = "Atividade catalítica"
+SurfaceDimension = "Superfície"
+VolumeDimension = "Volume"
+SpeedDimension = "Velocidade"
diff --git a/apps/shared.universal.i18n b/apps/shared.universal.i18n
index 08a516ff5..3c8702832 100644
--- a/apps/shared.universal.i18n
+++ b/apps/shared.universal.i18n
@@ -10,6 +10,7 @@ UnitTimeMonthSymbol = "_month"
UnitTimeYearSymbol = "_year"
UnitDistanceMeterKiloSymbol = "_km"
UnitDistanceMeterSymbol = "_m"
+UnitDistanceMeterCentiSymbol = "_cm"
UnitDistanceMeterMilliSymbol = "_mm"
UnitDistanceMeterMicroSymbol = "_μm"
UnitDistanceMeterNanoSymbol = "_nm"
@@ -82,6 +83,7 @@ UnitConductanceSiemensMilliSymbol = "_mS"
UnitMagneticFieldTeslaSymbol = "_T"
UnitInductanceHenrySymbol = "_H"
UnitSurfaceAcreSymbol = "_acre"
+UnitSurfaceMeterSquareSymbol = "_m^2"
UnitSurfaceHectarSymbol = "_ha"
UnitVolumeLiterSymbol = "_L"
UnitVolumeLiterDeciSymbol = "_dL"
@@ -125,6 +127,8 @@ DotCommandWithArg = "dot(u,v)"
E = "e"
Equal = "="
FactorCommandWithArg = "factor(n)"
+FactorialCommand = "!"
+FactorialCommandWithArg = "n!"
FccId = "FCC ID"
FloorCommandWithArg = "floor(x)"
FracCommandWithArg = "frac(x)"
diff --git a/apps/shared/continuous_function.cpp b/apps/shared/continuous_function.cpp
index e127feed5..39c705ecd 100644
--- a/apps/shared/continuous_function.cpp
+++ b/apps/shared/continuous_function.cpp
@@ -270,7 +270,7 @@ void ContinuousFunction::rangeForDisplay(float * xMin, float * xMax, float * yMi
}
if (!basedOnCostlyAlgorithms(context)) {
- Zoom::ValueAtAbscissa evaluation = [](float x, Context * context, const void * auxiliary) {
+ Zoom::ValueAtAbscissa evaluation = [](float x, Context * context, const void * auxiliary) -> float {
/* When evaluating sin(x)/x close to zero using the standard sine function,
* one can detect small variations, while the cardinal sine is supposed to be
* locally monotonous. To smooth our such variations, we round the result of
diff --git a/apps/shared/continuous_function_cache.cpp b/apps/shared/continuous_function_cache.cpp
index 00a8cd687..5ff498052 100644
--- a/apps/shared/continuous_function_cache.cpp
+++ b/apps/shared/continuous_function_cache.cpp
@@ -65,7 +65,11 @@ void ContinuousFunctionCache::ComputeNonCartesianSteps(float * tStep, float * tC
const int numberOfWholeSteps = static_cast(Graph::GraphView::k_graphStepDenominator);
static_assert(numberOfCacheablePoints % numberOfWholeSteps == 0, "numberOfCacheablePoints should be a multiple of numberOfWholeSteps for optimal caching");
const int multiple = numberOfCacheablePoints / numberOfWholeSteps;
+ // Ignore this on Casio calculators for now, as the screen resolution breaks this
+ // TODO: fix this. if it's possible
+ #ifndef _FXCG
static_assert(multiple && !(multiple & (multiple - 1)), "multiple should be a power of 2 for optimal caching");
+ #endif
/* Define cacheStep such that every whole graph steps are equally divided
* For instance, with :
* graphStepDenominator = 10.1
diff --git a/apps/shared/expression_model.cpp b/apps/shared/expression_model.cpp
index ab7dd0d09..d37e6b4ca 100644
--- a/apps/shared/expression_model.cpp
+++ b/apps/shared/expression_model.cpp
@@ -72,7 +72,7 @@ Expression ExpressionModel::expressionReduced(const Storage::Record * record, Po
if (isCircularlyDefined(record, context)) {
m_expression = Undefined::Builder();
} else {
- m_expression = Expression::ExpressionFromAddress(expressionAddress(record), expressionSize(record));
+ m_expression = Expression::ExpressionFromAddress(expressionAddress(record), expressionSize(record), record);
/* 'Simplify' routine might need to call expressionReduced on the very
* same function. So we need to keep a valid m_expression while executing
* 'Simplify'. Thus, we use a temporary expression. */
@@ -90,7 +90,7 @@ Expression ExpressionModel::expressionReduced(const Storage::Record * record, Po
Expression ExpressionModel::expressionClone(const Storage::Record * record) const {
assert(record->fullName() != nullptr);
/* A new Expression has to be created at each call (because it might be tempered with after calling) */
- return Expression::ExpressionFromAddress(expressionAddress(record), expressionSize(record));
+ return Expression::ExpressionFromAddress(expressionAddress(record), expressionSize(record), record);
/* TODO
* The substitution of UCodePointUnknown back and forth is done in the
* methods text, setContent (through BuildExpressionFromText), layout and
@@ -125,6 +125,39 @@ Ion::Storage::Record::ErrorStatus ExpressionModel::setExpressionContent(Ion::Sto
Ion::Storage::Record::Data newData = record->value();
size_t previousExpressionSize = expressionSize(record);
size_t newExpressionSize = newExpression.isUninitialized() ? 0 : newExpression.size();
+#ifdef STRING_STORAGE
+ size_t stringsize = 0;
+ char buf[1024] = {0};
+ char repl = 0;
+ buf[0] = '"';
+ if (!newExpression.isUninitialized()) {
+ size_t l = newExpression.serialize(buf+1,sizeof(buf)-2);
+ if (l >= sizeof(buf) - 3) {
+ newExpressionSize = 0;
+ } else {
+ buf[l + 1] = '"';
+ // replace 0x1 by x for func or n for seq
+ const char * name = record->fullName();
+ int namel = strlen(name);
+ if (namel > 4 && strncmp(name + namel - 4, ".seq", 4) == 0) {
+ repl = 'n';
+ } else if (namel > 5 && strncmp(name + namel - 5, ".func", 5) == 0) {
+ repl = 'x';
+ }
+ if (repl) {
+ for (char * ptr = buf; *ptr; ++ptr) {
+ if (*ptr == 1) {
+ *ptr = repl;
+ }
+ }
+ }
+ stringsize= l + 3; // 2 quotes and 0 at end
+ if (newExpressionSize < stringsize) {
+ newExpressionSize = stringsize;
+ }
+ }
+ }
+#endif
size_t previousDataSize = newData.size;
size_t newDataSize = previousDataSize - previousExpressionSize + newExpressionSize;
void * expAddress = expressionAddress(record);
@@ -140,6 +173,12 @@ Ion::Storage::Record::ErrorStatus ExpressionModel::setExpressionContent(Ion::Sto
* (as it is sometimes computed from metadata). Thus, the expression address
* is given as a parameter to updateNewDataWithExpression. */
updateNewDataWithExpression(record, newExpression, expAddress, newExpressionSize, previousExpressionSize);
+#ifdef STRING_STORAGE
+ if (stringsize && stringsizesetValue(newData);
diff --git a/apps/shared/store_controller.h b/apps/shared/store_controller.h
index 1083f8201..d0eebb316 100644
--- a/apps/shared/store_controller.h
+++ b/apps/shared/store_controller.h
@@ -49,7 +49,12 @@ protected:
static constexpr KDCoordinate k_cellWidth = Poincare::PrintFloat::glyphLengthForFloatWithPrecision(Poincare::Preferences::LargeNumberOfSignificantDigits) * 7 + 2*Metric::CellMargin + Metric::TableSeparatorThickness; // KDFont::SmallFont->glyphSize().width() = 7
constexpr static int k_maxNumberOfEditableCells = (Ion::Display::Width/k_cellWidth+2) * ((Ion::Display::Height - Metric::TitleBarHeight - Metric::TabHeight)/k_cellHeight+2);
+ #ifndef _FXCG
constexpr static int k_numberOfTitleCells = 4;
+ #else
+ // This is different here due to the changed screen resolution
+ constexpr static int k_numberOfTitleCells = 5;
+ #endif
static constexpr int k_titleCellType = 0;
static constexpr int k_editableCellType = 1;
diff --git a/apps/solver/solutions_controller.h b/apps/solver/solutions_controller.h
index 4fac929a1..2bf90d04b 100644
--- a/apps/solver/solutions_controller.h
+++ b/apps/solver/solutions_controller.h
@@ -87,7 +87,7 @@ private:
// Number of cells
constexpr static int k_maxNumberOfVisibleCells = (Ion::Display::Height - 3 * Metric::TitleBarHeight) / k_defaultCellHeight + 1; // When displaying approximate solutions for cos(x) = 0 between 0 and 1800 and scrolling down
- static_assert(k_maxNumberOfVisibleCells == 10, "k_maxNumberOfVisibleCells has changed"); //This assert is just for information purposes
+ // static_assert(k_maxNumberOfVisibleCells == 10, "k_maxNumberOfVisibleCells has changed"); //This assert is just for information purposes
static_assert(k_maxNumberOfVisibleCells <= EquationStore::k_maxNumberOfSolutions + Poincare::Expression::k_maxNumberOfVariables, "We can reduce the number of cells in Solver:SolutionsController.");
constexpr static int k_maxNumberOfSymbols = EquationStore::k_maxNumberOfSolutions + Poincare::Expression::k_maxNumberOfVariables;
constexpr static int k_numberOfSymbolCells = k_maxNumberOfVisibleCells < k_maxNumberOfSymbols ? k_maxNumberOfVisibleCells : k_maxNumberOfSymbols;
diff --git a/apps/toolbox.de.i18n b/apps/toolbox.de.i18n
index c8d8dc5ae..b9d6588c0 100644
--- a/apps/toolbox.de.i18n
+++ b/apps/toolbox.de.i18n
@@ -13,17 +13,18 @@ UnitTimeYear = "Jahr"
UnitDistanceMenu = "Entfernung"
UnitDistanceMeterKilo = "Kilometer"
UnitDistanceMeter = "Meter"
+UnitDistanceMeterCenti = "Zentimeter"
UnitDistanceMeterMilli = "Millimeter"
UnitDistanceMeterMicro = "Micrometer"
UnitDistanceMeterNano = "Nanometer"
UnitDistanceMeterPico = "Pikometer"
+UnitDistanceInch = "Zoll"
+UnitDistanceFoot = "Fuß"
+UnitDistanceYard = "Yard"
+UnitDistanceMile = "Meile"
UnitDistanceAstronomicalUnit = "Astronomische Einheit"
UnitDistanceLightYear = "Lichtjahr"
UnitDistanceParsec = "Parsec"
-UnitDistanceMile = "Meile"
-UnitDistanceYard = "Yard"
-UnitDistanceFoot = "Fuß"
-UnitDistanceInch = "Zoll"
UnitMassMenu = "Masse"
UnitMassGramKilo = "Kilogramm"
UnitMassGram = "Gramm"
@@ -77,13 +78,14 @@ InductanceMenu = "Elektrische Induktivität"
UnitSurfaceMenu = "Fläche"
UnitSurfaceAcre = "Morgen"
UnitSurfaceHectar = "Hektar"
+UnitSurfaceMeterSquare = "Quadratmeter"
UnitVolumeMenu = "Volumen"
UnitVolumeLiter = "Liter"
UnitVolumeLiterDeci = "Deziliter"
UnitVolumeLiterCenti = "Centiliter"
UnitVolumeLiterMilli = "Milliliter"
UnitVolumeTeaspoon = "Teelöffel"
-UnitVolumeTablespoon= "Esslöffel"
+UnitVolumeTablespoon = "Esslöffel"
UnitVolumeFluidOunce = "Flüssigunze"
UnitVolumeCup = "Tasse"
UnitVolumePint = "Pint"
@@ -409,21 +411,16 @@ NumberElementUbn = "120 - Unbinilium (Ubn)"
AlphaElementUbn = "Ubn - Unbinilium (120)"
Speed = "Geschwindigkeit"
SpeedOfSound = "Schallgeschwindigkeit"
-SpeedOfLightTag = "Lichtgeschwindigkeit"
SpeedOfSound0Tag = "Meeresspiegel, 20 ° C"
SpeedOfSoundWaterTag = "In Wasser"
SpeedOfSoundSteelTag = "In Stahl"
SpeedOfSoundGlassTag = "In Glas"
-EscapeVelocity = "Fluchtgeschwindigkeit"
-EscapeVelocityFromEarth = "Von der Erde"
-EscapeVelocityFromMoon = "Vom Mond"
-EscapeVelocityFromSun = "Von der Sonne"
+SpeedOfLightTag = "Lichtgeschwindigkeit"
Thermodynamics = "Thermodynamik"
BoltzmannTag = "Boltzmann Konstante"
AvogadroTag = "Avogadro-Konstante"
GasTag = "Gaskonstante"
Electromagnetism = "Elektromagnetismus"
-CoulombTag = "Coulomb-Konstante"
ConductivityConstants = "Leitfähigkeitskonstanten"
Electricity = "Elektrizität"
ResistivityConstants = "Konstanten der Widerstandsfähigkeit"
@@ -445,6 +442,11 @@ Water = "Wasser"
Air = "Luft"
Glass = "Glas"
Wood = "Holz"
+CoulombTag = "Coulomb-Konstante"
+EscapeVelocity = "Fluchtgeschwindigkeit"
+EscapeVelocityFromEarth = "Von der Erde"
+EscapeVelocityFromMoon = "Vom Mond"
+EscapeVelocityFromSun = "Von der Sonne"
Vacuum_permittivityTag = "Vakuum-Durchlässigkeit"
Vacuum_permeabilityTag = "Vakuumdurchlässigkeit"
PlanckTag = "Planck - Konstante"
@@ -524,3 +526,5 @@ LogicalRotateRight= "Rotieren von a um r Bit n. rechts"
TwosComplementToBits = "Äquivalent im Zweierkomplement"
CeilingLog2 = "Anzahl der Bits, die zum Speichern von a benötigt werden"
ExplicitNumberOfBits = "Explizite Bitbreite"
+MatricesAndVectors = "Matrizen und Vektoren"
+Factorial = "Fakultät"
diff --git a/apps/toolbox.en.i18n b/apps/toolbox.en.i18n
index 4e093158a..b10560262 100644
--- a/apps/toolbox.en.i18n
+++ b/apps/toolbox.en.i18n
@@ -13,6 +13,7 @@ UnitTimeYear = "Year"
UnitDistanceMenu = "Distance"
UnitDistanceMeterKilo = "Kilometer"
UnitDistanceMeter = "Meter"
+UnitDistanceMeterCenti = "Centimeter"
UnitDistanceMeterMilli = "Millimeter"
UnitDistanceMeterMicro = "Micrometer"
UnitDistanceMeterNano = "Nanometer"
@@ -77,13 +78,14 @@ InductanceMenu = "Electrical inductance"
UnitSurfaceMenu = "Area"
UnitSurfaceAcre = "Acre"
UnitSurfaceHectar = "Hectare"
+UnitSurfaceMeterSquare = "Square meter"
UnitVolumeMenu = "Volume"
UnitVolumeLiter = "Liter"
UnitVolumeLiterDeci = "Deciliter"
UnitVolumeLiterCenti = "Centiliter"
UnitVolumeLiterMilli = "Milliliter"
UnitVolumeTeaspoon = "Teaspoon"
-UnitVolumeTablespoon= "Tablespoon"
+UnitVolumeTablespoon = "Tablespoon"
UnitVolumeFluidOunce = "Fluid Ounce"
UnitVolumeCup = "Cup"
UnitVolumePint = "Pint"
@@ -413,17 +415,12 @@ SpeedOfSound0Tag = "Sea level, 20°C"
SpeedOfSoundWaterTag = "In water"
SpeedOfSoundSteelTag = "In steel"
SpeedOfSoundGlassTag = "In glass"
-EscapeVelocity = "Escape Velocity"
-EscapeVelocityFromEarth = "Of Earth"
-EscapeVelocityFromMoon = "Of Moon"
-EscapeVelocityFromSun = "Of Sun"
SpeedOfLightTag = "Speed of light"
Thermodynamics = "Thermodynamics"
BoltzmannTag = "Boltzmann Constant"
AvogadroTag = "Avogadro Constant"
GasTag = "Gas Constant"
Electromagnetism = "Electromagnetism"
-CoulombTag = "Coulomb Constant"
ConductivityConstants = "Conductivity constants"
Electricity = "Electricity"
ResistivityConstants = "Resistivity Constants"
@@ -445,6 +442,11 @@ Water = "Water"
Air = "Air"
Glass = "Glass"
Wood = "Wood"
+CoulombTag = "Coulomb Constant"
+EscapeVelocity = "Escape Velocity"
+EscapeVelocityFromEarth = "Of Earth"
+EscapeVelocityFromMoon = "Of Moon"
+EscapeVelocityFromSun = "Of Sun"
Vacuum_permittivityTag = "Vacuum permittivity"
Vacuum_permeabilityTag = "Vacuum permeability"
PlanckTag = "Planck Constant"
@@ -524,3 +526,5 @@ LogicalRotateRight= "Rotate r bits of a to the right"
TwosComplementToBits = "Two's complement equivalent"
CeilingLog2 = "Number of bits needed to store a"
ExplicitNumberOfBits = "Explicit number of bits"
+MatricesAndVectors = "Matrices and vectors"
+Factorial = "Factorial"
diff --git a/apps/toolbox.es.i18n b/apps/toolbox.es.i18n
index 483bee019..091a2bbae 100644
--- a/apps/toolbox.es.i18n
+++ b/apps/toolbox.es.i18n
@@ -13,17 +13,18 @@ UnitTimeYear = "Year"
UnitDistanceMenu = "Distance"
UnitDistanceMeterKilo = "Kilometer"
UnitDistanceMeter = "Meter"
+UnitDistanceMeterCenti = "Centímetro"
UnitDistanceMeterMilli = "Millimeter"
UnitDistanceMeterMicro = "Micrometer"
UnitDistanceMeterNano = "Nanometer"
UnitDistanceMeterPico = "Picometer"
+UnitDistanceInch = "Pulgada"
+UnitDistanceFoot = "Pie"
+UnitDistanceYard = "Yardas"
+UnitDistanceMile = "Milla"
UnitDistanceAstronomicalUnit = "Astronomical unit"
UnitDistanceLightYear = "Light year"
UnitDistanceParsec = "Parsec"
-UnitDistanceMile = "Milla"
-UnitDistanceYard = "Yardas"
-UnitDistanceFoot = "Pie"
-UnitDistanceInch = "Pulgada"
UnitMassMenu = "Mass"
UnitMassGramKilo = "Kilogram"
UnitMassGram = "Gram"
@@ -77,13 +78,14 @@ InductanceMenu = "Electrical inductance"
UnitSurfaceMenu = "Area"
UnitSurfaceAcre = "Acre"
UnitSurfaceHectar = "Hectare"
+UnitSurfaceMeterSquare = "Metro cuadrado"
UnitVolumeMenu = "Volume"
UnitVolumeLiter = "Liter"
UnitVolumeLiterDeci = "Deciliter"
UnitVolumeLiterCenti = "Centiliter"
UnitVolumeLiterMilli = "Milliliter"
UnitVolumeTeaspoon = "Cucharadita"
-UnitVolumeTablespoon= "Cucharada"
+UnitVolumeTablespoon = "Cucharada"
UnitVolumeFluidOunce = "Onza líquida"
UnitVolumeCup = "Taza"
UnitVolumePint = "Pinta"
@@ -408,22 +410,17 @@ AlphaElementUue = "Uue - Ununennio (119)"
NumberElementUbn = "120 - Unbinilio (Ubn)"
AlphaElementUbn = "Ubn - Unbinilio (120)"
Speed = "Velocidad"
-SpeedOfLightTag = "Velocidad de la luz"
SpeedOfSound = "La velocidad del sonido"
-Thermodynamics = "Termodinámica"
SpeedOfSound0Tag = "Nivel del mar, 20 ° C"
SpeedOfSoundWaterTag = "En el agua"
SpeedOfSoundSteelTag = "En acero"
SpeedOfSoundGlassTag = "En vidrio"
-EscapeVelocity = "Velocidad de escape"
-EscapeVelocityFromEarth = "De La Tierra"
-EscapeVelocityFromMoon = "De la Luna"
-EscapeVelocityFromSun = "De el Sol"
+SpeedOfLightTag = "Velocidad de la luz"
+Thermodynamics = "Termodinámica"
BoltzmannTag = "Constante Boltzmann"
AvogadroTag = "Constante de Avogadro"
GasTag = "Constante de gas"
Electromagnetism = "Electromagnetismo"
-CoulombTag = "Constante de Coulomb"
ConductivityConstants = "Constantes de conductividad"
Electricity = "Electricidad"
ResistivityConstants = "Constantes de resistividad"
@@ -445,6 +442,11 @@ Water = "Agua"
Air = "Aire"
Glass = "Vidrio"
Wood = "Madera"
+CoulombTag = "Constante de Coulomb"
+EscapeVelocity = "Velocidad de escape"
+EscapeVelocityFromEarth = "De La Tierra"
+EscapeVelocityFromMoon = "De la Luna"
+EscapeVelocityFromSun = "De el Sol"
Vacuum_permittivityTag = "Permisividad de vacío"
Vacuum_permeabilityTag = "Permeabilidad al vacío"
PlanckTag = "Constante de Planck"
@@ -524,3 +526,5 @@ LogicalRotateRight= "Gire r bits de a hacia derecha"
TwosComplementToBits = "Equivalente en complemento a dos"
CeilingLog2 = "Número de bits necesarios para almacenar a"
ExplicitNumberOfBits = "Número explícito de bits"
+MatricesAndVectors = "Matrices y vectores"
+Factorial = "Factorial"
diff --git a/apps/toolbox.fr.i18n b/apps/toolbox.fr.i18n
index 7ad42eaa8..3b5639e64 100644
--- a/apps/toolbox.fr.i18n
+++ b/apps/toolbox.fr.i18n
@@ -13,21 +13,18 @@ UnitTimeYear = "Année"
UnitDistanceMenu = "Distance"
UnitDistanceMeterKilo = "Kilomètre"
UnitDistanceMeter = "Mètre"
+UnitDistanceMeterCenti = "Centimètre"
UnitDistanceMeterMilli = "Millimètre"
UnitDistanceMeterMicro = "Micromètre"
UnitDistanceMeterNano = "Nanomètre"
UnitDistanceMeterPico = "Picomètre"
-UnitDistanceInch = "Inch"
-UnitDistanceFoot = "Foot"
+UnitDistanceInch = "Pouce"
+UnitDistanceFoot = "Pied"
UnitDistanceYard = "Yard"
UnitDistanceMile = "Mile"
UnitDistanceAstronomicalUnit = "Unité astronomique"
UnitDistanceLightYear = "Année-lumière"
UnitDistanceParsec = "Parsec"
-UnitDistanceMile = "Mile"
-UnitDistanceYard = "Yard"
-UnitDistanceFoot = "Pied"
-UnitDistanceInch = "Pouce"
UnitMassMenu = "Masse"
UnitMassGramKilo = "Kilogramme"
UnitMassGram = "Gramme"
@@ -81,13 +78,14 @@ InductanceMenu = "Inductance"
UnitSurfaceMenu = "Superficie"
UnitSurfaceAcre = "Acre"
UnitSurfaceHectar = "Hectare"
+UnitSurfaceMeterSquare = "Mètre carré"
UnitVolumeMenu = "Volume"
UnitVolumeLiter = "Litre"
UnitVolumeLiterDeci = "Décilitre"
UnitVolumeLiterCenti = "Centilitre"
UnitVolumeLiterMilli = "Millilitre"
UnitVolumeTeaspoon = "Cuillère à café"
-UnitVolumeTablespoon= "Cuillère à soupe"
+UnitVolumeTablespoon = "Cuillère à soupe"
UnitVolumeFluidOunce = "Once fluide"
UnitVolumeCup = "Tasse"
UnitVolumePint = "Pinte"
@@ -528,3 +526,5 @@ LogicalRotateRight= "Rotation droite de a par r bits"
TwosComplementToBits = "Equivalent en complément à deux"
CeilingLog2 = "Nb de bits nécessaires pour stocker a"
ExplicitNumberOfBits = "Nombre indiqué de bits"
+MatricesAndVectors = "Matrices et vecteurs"
+Factorial = "Factorielle"
diff --git a/apps/toolbox.hu.i18n b/apps/toolbox.hu.i18n
index 45a437bfd..4caf39e6c 100644
--- a/apps/toolbox.hu.i18n
+++ b/apps/toolbox.hu.i18n
@@ -13,6 +13,7 @@ UnitTimeYear = "Év"
UnitDistanceMenu = "Távolság"
UnitDistanceMeterKilo = "Kilométer"
UnitDistanceMeter = "Méter"
+UnitDistanceMeterCenti = "Centiméter"
UnitDistanceMeterMilli = "Milliméter"
UnitDistanceMeterMicro = "Mikrométer"
UnitDistanceMeterNano = "Nanométer"
@@ -24,16 +25,16 @@ UnitDistanceMile = "Mérföld"
UnitDistanceAstronomicalUnit = "Csillagászati egység"
UnitDistanceLightYear = "Fény év"
UnitDistanceParsec = "Parsec"
-UnitMassShortTon = "Rövid tonna"
-UnitMassLongTon = "Hosszú tonna"
-UnitMassPound = "Font"
-UnitMassOunce = "Uncia"
UnitMassMenu = "Tömeg"
UnitMassGramKilo = "Kilogramm"
UnitMassGram = "Gramm"
UnitMassGramMilli = "Milligramm"
UnitMassGramMicro = "Mikrogramm"
UnitMassTonne = "Tonna"
+UnitMassOunce = "Uncia"
+UnitMassPound = "Font"
+UnitMassShortTon = "Rövid tonna"
+UnitMassLongTon = "Hosszú tonna"
UnitCurrentMenu = "Áram"
UnitCurrentAmpere = "Amper"
UnitCurrentAmpereMilli = "Milliamper"
@@ -77,6 +78,7 @@ InductanceMenu = "Elektromos induktivitás"
UnitSurfaceMenu = "Terület"
UnitSurfaceAcre = "Acre"
UnitSurfaceHectar = "Hektár"
+UnitSurfaceMeterSquare = "Négyzetméter"
UnitVolumeMenu = "Kötet"
UnitVolumeLiter = "Liter"
UnitVolumeLiterDeci = "Deciliter"
@@ -155,11 +157,11 @@ RandomInteger = "Véletlen egész szám [a, b] -ben"
PrimeFactorDecomposition = "Egész szám tényezö"
NormCDF = "P (X isBooting()) { // Bus error is normal if we are booting, it's triggered when we lock OPTCR
- asm("mov lr, r12");
- asm("bx lr");
+ return;
}
Bootloader::Recovery::crash_handler("BusFault");
}
@@ -65,7 +63,7 @@ bool Boot::isKernelPatched(const Slot & s) {
return *(uint32_t *)(origin_isr + sizeof(uint32_t) * 7) == ((uint32_t)&_fake_isr_function_start) + 1;
}
-__attribute((section(".fake_isr_function"))) __attribute__((used)) void Boot::flash_interrupt() {
+__attribute__((section(".fake_isr_function"))) __attribute__((used)) void Boot::flash_interrupt() {
// a simple function
Ion::Device::Flash::ClearInternalFlashErrors();
asm("bx lr");
@@ -82,19 +80,19 @@ void Boot::patchKernel(const Slot & s) {
data[origin_isr + sizeof(uint32_t) * 6 + 1] = ptr[1];
data[origin_isr + sizeof(uint32_t) * 6 + 2] = ptr[2];
data[origin_isr + sizeof(uint32_t) * 6 + 3] = ptr[3];
-
+
// data[origin_isr + sizeof(uint32_t) * 5] = ptr[0]; // MemManage
// data[origin_isr + sizeof(uint32_t) * 5 + 1] = ptr[1];
// data[origin_isr + sizeof(uint32_t) * 5 + 2] = ptr[2];
// data[origin_isr + sizeof(uint32_t) * 5 + 3] = ptr[3];
-
+
data[origin_isr + sizeof(uint32_t) * 7] = ptr[0]; // UsageFault
data[origin_isr + sizeof(uint32_t) * 7 + 1] = ptr[1];
data[origin_isr + sizeof(uint32_t) * 7 + 2] = ptr[2];
data[origin_isr + sizeof(uint32_t) * 7 + 3] = ptr[3];
// data[origin_isr + sizeof(uint32_t) * 4] = ptr[0];//hardfault
- // data[origin_isr + sizeof(uint32_t) * 4 + 1] = ptr[1];
+ // data[origin_isr + sizeof(uint32_t) * 4 + 1] = ptr[1];
// data[origin_isr + sizeof(uint32_t) * 4 + 2] = ptr[2];
// data[origin_isr + sizeof(uint32_t) * 4 + 3] = ptr[3];
@@ -105,9 +103,9 @@ void Boot::patchKernel(const Slot & s) {
void Boot::bootSlot(Bootloader::Slot s) {
config()->setSlot(&s);
if (!s.userlandHeader()->isOmega() && !s.userlandHeader()->isUpsilon()) {
- // We are trying to boot epsilon, so we check the version and show an advertisement if needed
+ // We are trying to boot epsilon, so we check the version and show a warning if needed
const char * version = s.userlandHeader()->version();
- const char * min = "20.0.0";
+ const char * min = "24.4.1";
int versionSum = Utility::versionSum(version, strlen(version));
int minimalVersionTrigger = Utility::versionSum(min, strlen(min));
if (versionSum >= minimalVersionTrigger) {
diff --git a/bootloader/boot.h b/bootloader/boot.h
index 300fb762c..c771e5678 100644
--- a/bootloader/boot.h
+++ b/bootloader/boot.h
@@ -47,7 +47,7 @@ public:
static void bootSlot(Bootloader::Slot slot);
static void bootSelectedSlot();
__attribute__ ((noreturn)) static void jumpToInternalBootloader();
- __attribute((section(".fake_isr_function"))) __attribute__((used)) static void flash_interrupt();
+ __attribute__ ((section(".fake_isr_function"))) __attribute__((used)) static void flash_interrupt();
static void bootloader();
static void lockInternal();
diff --git a/bootloader/drivers/board.cpp b/bootloader/drivers/board.cpp
index 0a80a89ec..0958a942f 100644
--- a/bootloader/drivers/board.cpp
+++ b/bootloader/drivers/board.cpp
@@ -272,7 +272,7 @@ void initClocks() {
ahb1enr.setGPIOCEN(true);
ahb1enr.setGPIODEN(true);
ahb1enr.setGPIOEEN(true);
- ahb1enr.setDMA2EN(true);
+ ahb1enr.setDMA2EN(false);
RCC.AHB1ENR()->set(ahb1enr);
// AHB2 bus
@@ -282,8 +282,8 @@ void initClocks() {
RCC.AHB3ENR()->setFSMCEN(true);
// APB1 bus
- // We're using TIM3 for the LEDs
- RCC.APB1ENR()->setTIM3EN(true);
+ // We're using TIM3 for the LEDs (disabled to stick with E16+ Bootloader)
+ /*RCC.APB1ENR()->setTIM3EN(true); */
RCC.APB1ENR()->setPWREN(true);
RCC.APB1ENR()->setRTCAPB(true);
@@ -291,7 +291,7 @@ void initClocks() {
class RCC::APB2ENR apb2enr(0); // Reset value
apb2enr.setADC1EN(true);
apb2enr.setSYSCFGEN(true);
- apb2enr.setUSART6EN(true); // TODO required if building bench target only?
+ apb2enr.setUSART6EN(false); // TODO required if building bench target only? (disabled to stick with E16+ Bootloader)
RCC.APB2ENR()->set(apb2enr);
// Configure clocks in sleep mode
@@ -300,86 +300,86 @@ void initClocks() {
ahb1lpenr.setGPIOALPEN(true); // Enable IO port A for Charging/USB plug/Keyboard pins
ahb1lpenr.setGPIOBLPEN(true); // Enable IO port B for LED pins
ahb1lpenr.setGPIOCLPEN(true); // Enable IO port C for LED/Keyboard pins
- ahb1lpenr.setGPIODLPEN(false); // Disable IO port D (LCD...)
+ ahb1lpenr.setGPIODLPEN(true); // Enable IO port D (LCD...)
ahb1lpenr.setGPIOELPEN(true); // Enable IO port E for Keyboard/Battery pins
- ahb1lpenr.setGPIOFLPEN(false); // Disable IO port F
- ahb1lpenr.setGPIOGLPEN(false); // Disable IO port G
- ahb1lpenr.setGPIOHLPEN(false); // Disable IO port H
- ahb1lpenr.setGPIOILPEN(false); // Disable IO port I
- ahb1lpenr.setCRCLPEN(false);
- ahb1lpenr.setFLITFLPEN(false);
- ahb1lpenr.setSRAM1LPEN(false);
- ahb1lpenr.setDMA1LPEN(false);
- ahb1lpenr.setDMA2LPEN(false);
- ahb1lpenr.setAXILPEN(false);
- ahb1lpenr.setSRAM2LPEN(false);
- ahb1lpenr.setBKPSRAMLPEN(false);
- ahb1lpenr.setDTCMLPEN(false);
- ahb1lpenr.setOTGHSLPEN(false);
- ahb1lpenr.setOTGHSULPILPEN(false);
+ ahb1lpenr.setGPIOFLPEN(true); // Enable IO port F
+ ahb1lpenr.setGPIOGLPEN(true); // Enable IO port G
+ ahb1lpenr.setGPIOHLPEN(true); // Enable IO port H
+ ahb1lpenr.setGPIOILPEN(true); // Enable IO port I
+ ahb1lpenr.setCRCLPEN(true);
+ ahb1lpenr.setFLITFLPEN(true);
+ ahb1lpenr.setSRAM1LPEN(true);
+ ahb1lpenr.setDMA1LPEN(true);
+ ahb1lpenr.setDMA2LPEN(true);
+ ahb1lpenr.setAXILPEN(true);
+ ahb1lpenr.setSRAM2LPEN(true);
+ ahb1lpenr.setBKPSRAMLPEN(true);
+ ahb1lpenr.setDTCMLPEN(true);
+ ahb1lpenr.setOTGHSLPEN(true);
+ ahb1lpenr.setOTGHSULPILPEN(true);
RCC.AHB1LPENR()->set(ahb1lpenr);
// AHB2 peripheral clock enable in low-power mode register
class RCC::AHB2LPENR ahb2lpenr(0x000000F1); // Reset value
- ahb2lpenr.setOTGFSLPEN(false);
- ahb2lpenr.setRNGLPEN(false);
- ahb2lpenr.setAESLPEN(false);
+ ahb2lpenr.setOTGFSLPEN(true);
+ ahb2lpenr.setRNGLPEN(true);
+ ahb2lpenr.setAESLPEN(true);
RCC.AHB2LPENR()->set(ahb2lpenr);
// AHB3 peripheral clock enable in low-power mode register
class RCC::AHB3LPENR ahb3lpenr(0x00000003); // Reset value
- ahb3lpenr.setFMCLPEN(false);
- ahb3lpenr.setQSPILPEN(false);
+ ahb3lpenr.setFMCLPEN(true);
+ ahb3lpenr.setQSPILPEN(true);
RCC.AHB3LPENR()->set(ahb3lpenr);
// APB1 peripheral clock enable in low-power mode register
class RCC::APB1LPENR apb1lpenr(0xFFFFCBFF); // Reset value
- apb1lpenr.setTIM2LPEN(false);
+ apb1lpenr.setTIM2LPEN(true);
apb1lpenr.setTIM3LPEN(true); // Enable TIM3 in sleep mode for LEDs
- apb1lpenr.setTIM4LPEN(false);
- apb1lpenr.setTIM5LPEN(false);
- apb1lpenr.setTIM6LPEN(false);
- apb1lpenr.setTIM7LPEN(false);
- apb1lpenr.setTIM12LPEN(false);
- apb1lpenr.setTIM13LPEN(false);
- apb1lpenr.setTIM14LPEN(false);
- apb1lpenr.setRTCAPBLPEN(false);
- apb1lpenr.setWWDGLPEN(false);
- apb1lpenr.setSPI2LPEN(false);
- apb1lpenr.setSPI3LPEN(false);
- apb1lpenr.setUSART2LPEN(false);
- apb1lpenr.setUSART3LPEN(false);
- apb1lpenr.setI2C1LPEN(false);
- apb1lpenr.setI2C2LPEN(false);
- apb1lpenr.setI2C3LPEN(false);
- apb1lpenr.setCAN1LPEN(false);
- apb1lpenr.setPWRLPEN(false);
- apb1lpenr.setLPTIM1LPEN(false);
- apb1lpenr.setUSART4LPEN(false);
- apb1lpenr.setUSART5LPEN(false);
- apb1lpenr.setOTGHSLPEN(false);
- apb1lpenr.setOTGHSULPILPEN(false);
+ apb1lpenr.setTIM4LPEN(true);
+ apb1lpenr.setTIM5LPEN(true);
+ apb1lpenr.setTIM6LPEN(true);
+ apb1lpenr.setTIM7LPEN(true);
+ apb1lpenr.setTIM12LPEN(true);
+ apb1lpenr.setTIM13LPEN(true);
+ apb1lpenr.setTIM14LPEN(true);
+ apb1lpenr.setRTCAPBLPEN(true);
+ apb1lpenr.setWWDGLPEN(true);
+ apb1lpenr.setSPI2LPEN(true);
+ apb1lpenr.setSPI3LPEN(true);
+ apb1lpenr.setUSART2LPEN(true);
+ apb1lpenr.setUSART3LPEN(true);
+ apb1lpenr.setI2C1LPEN(true);
+ apb1lpenr.setI2C2LPEN(true);
+ apb1lpenr.setI2C3LPEN(true);
+ apb1lpenr.setCAN1LPEN(true);
+ apb1lpenr.setPWRLPEN(true);
+ apb1lpenr.setLPTIM1LPEN(true);
+ apb1lpenr.setUSART4LPEN(true);
+ apb1lpenr.setUSART5LPEN(true);
+ apb1lpenr.setOTGHSLPEN(true);
+ apb1lpenr.setOTGHSULPILPEN(true);
RCC.APB1LPENR()->set(apb1lpenr);
// APB2 peripheral clock enable in low-power mode register
class RCC::APB2LPENR apb2lpenr(0x04F77F33); // Reset value
- apb2lpenr.setTIM1LPEN(false);
- apb2lpenr.setTIM8LPEN(false);
- apb2lpenr.setUSART1LPEN(false);
- apb2lpenr.setUSART6LPEN(false);
- apb2lpenr.setADC1LPEN(false);
- apb2lpenr.setSPI1LPEN(false);
- apb2lpenr.setSPI4LPEN(false);
- apb2lpenr.setSYSCFGLPEN(false);
- apb2lpenr.setTIM9LPEN(false);
- apb2lpenr.setTIM10LPEN(false);
- apb2lpenr.setTIM11LPEN(false);
- apb2lpenr.setSPI5LPEN(false);
- apb2lpenr.setSDMMC2LPEN(false);
- apb2lpenr.setADC2LPEN(false);
- apb2lpenr.setADC3LPEN(false);
- apb2lpenr.setSAI1LPEN(false);
- apb2lpenr.setSAI2LPEN(false);
+ apb2lpenr.setTIM1LPEN(true);
+ apb2lpenr.setTIM8LPEN(true);
+ apb2lpenr.setUSART1LPEN(true);
+ apb2lpenr.setUSART6LPEN(true);
+ apb2lpenr.setADC1LPEN(true);
+ apb2lpenr.setSPI1LPEN(true);
+ apb2lpenr.setSPI4LPEN(true);
+ apb2lpenr.setSYSCFGLPEN(true);
+ apb2lpenr.setTIM9LPEN(true);
+ apb2lpenr.setTIM10LPEN(true);
+ apb2lpenr.setTIM11LPEN(true);
+ apb2lpenr.setSPI5LPEN(true);
+ apb2lpenr.setSDMMC2LPEN(true);
+ apb2lpenr.setADC2LPEN(true);
+ apb2lpenr.setADC3LPEN(true);
+ apb2lpenr.setSAI1LPEN(true);
+ apb2lpenr.setSAI2LPEN(true);
RCC.APB2LPENR()->set(apb2lpenr);
}
@@ -399,6 +399,7 @@ void shutdownClocks(bool keepLEDAwake) {
class RCC::AHB1ENR ahb1enr(0x00100000); // Reset value
if (keepLEDAwake) {
apb1enr.setTIM3EN(true);
+ apb1enr.setTIM5EN(true);
ahb1enr.setGPIOBEN(true);
}
RCC.APB1ENR()->set(apb1enr);
diff --git a/bootloader/interface/menus/upsilon_recovery.cpp b/bootloader/interface/menus/upsilon_recovery.cpp
new file mode 100644
index 000000000..0529bd307
--- /dev/null
+++ b/bootloader/interface/menus/upsilon_recovery.cpp
@@ -0,0 +1,48 @@
+#include "upsilon_recovery.h"
+#include
+#include
+#include
+#include
+#include
+
+extern "C" void jump_to_firmware(const uint32_t* stackPtr, const void(*startPtr)(void));
+
+Bootloader::UpsilonRecoveryMenu::UpsilonRecoveryMenu() : Menu(KDColorBlack, KDColorWhite, Messages::upsilonRecoveryTitle, Messages::mainTitle) {
+ setup();
+}
+
+void Bootloader::UpsilonRecoveryMenu::setup() {
+ m_defaultColumns[0] = Column(Messages::upsilonRecoveryMessage1, k_small_font, 0, true);
+ m_defaultColumns[1] = Column(Messages::upsilonRecoveryMessage2, k_small_font, 0, true);
+ m_defaultColumns[2] = Column(Messages::upsilonRecoveryMessage3, k_small_font, 0, true);
+ m_defaultColumns[3] = Column(Messages::upsilonRecoveryMessage4, k_small_font, 0, true);
+ m_defaultColumns[4] = Column(Messages::upsilonRecoveryMessage5, k_small_font, 0, true);
+
+ m_columns[0] = ColumnBinder(&m_defaultColumns[0]);
+ m_columns[1] = ColumnBinder(&m_defaultColumns[1]);
+ m_columns[2] = ColumnBinder(&m_defaultColumns[2]);
+ m_columns[3] = ColumnBinder(&m_defaultColumns[3]);
+ m_columns[4] = ColumnBinder(&m_defaultColumns[4]);
+}
+
+void Bootloader::UpsilonRecoveryMenu::postOpen() {
+ // We override the open method
+ for (;;) {
+ uint64_t scan = Ion::Keyboard::scan();
+ if (scan == Ion::Keyboard::State(Ion::Keyboard::Key::Back)) {
+ while (Ion::Keyboard::scan() == Ion::Keyboard::State(Ion::Keyboard::Key::Back));
+ forceExit();
+ return;
+ } else if (scan == Ion::Keyboard::State(Ion::Keyboard::Key::OnOff)) {
+ Ion::Power::suspend();
+ return;
+ } else if (scan == Ion::Keyboard::State(Ion::Keyboard::Key::OK)) {
+ Slot slot = Slot::Upsilon();
+ Ion::Device::Board::bootloaderMPU();
+ // Deinitialize the backlight to prevent bugs when the firmware boots
+ Ion::Backlight::shutdown();
+ jump_to_firmware(slot.kernelHeader()->stackPointer(), slot.userlandHeader()->upsilonRecoveryBootFunction());
+ for(;;);
+ }
+ }
+}
diff --git a/bootloader/interface/menus/upsilon_recovery.h b/bootloader/interface/menus/upsilon_recovery.h
new file mode 100644
index 000000000..90793b6c7
--- /dev/null
+++ b/bootloader/interface/menus/upsilon_recovery.h
@@ -0,0 +1,15 @@
+#ifndef _BOOTLOADER_INTERFACE_MENUS_UPSILON_RECOVERY_H_
+#define _BOOTLOADER_INTERFACE_MENUS_UPSILON_RECOVERY_H_
+
+#include
+
+namespace Bootloader {
+ class UpsilonRecoveryMenu : public Menu {
+ public:
+ UpsilonRecoveryMenu();
+ void setup() override;
+ void postOpen() override;
+ };
+}
+
+#endif
diff --git a/bootloader/interface/static/interface.cpp b/bootloader/interface/static/interface.cpp
index c0e95db73..18160d1ab 100644
--- a/bootloader/interface/static/interface.cpp
+++ b/bootloader/interface/static/interface.cpp
@@ -69,7 +69,12 @@ void Interface::drawLoading() {
for (uint8_t i = 0; i < strlen(Messages::mainTitle); i++) {
char tmp[2] = {Messages::mainTitle[i], '\0'};
ctx->drawString(tmp, KDPoint(initPos + i * (fontSize.width()), ImageStore::Computer->height() + 25 + 10), KDFont::LargeFont, KDColorBlack, KDColorWhite);
- Ion::Timing::msleep(50);
+
+ int t = 50;
+ Ion::Events::Event e = Ion::Events::getEvent(&t);
+ if (e.isKeyboardEvent()){
+ return;
+ }
}
Ion::Timing::msleep(500);
}
diff --git a/bootloader/interface/static/messages.h b/bootloader/interface/static/messages.h
index 6d97ee991..2088e8220 100644
--- a/bootloader/interface/static/messages.h
+++ b/bootloader/interface/static/messages.h
@@ -6,7 +6,7 @@ namespace Bootloader {
class Messages {
public:
constexpr static const char * mainTitle = "Upsilon Calculator";
-
+
// Home menu
constexpr static const char * homeTitle = "Select a slot";
@@ -53,12 +53,21 @@ public:
constexpr static const char * recoveryMessage4 = "Press Back to continue.";
constexpr static const char * recoveryMessage5 = "(you will not be able to recover your data !)";
+ // Upsilon Recovery menu
+ constexpr static const char * upsilonRecoveryTitle = "Upsilon Recovery";
+
+ constexpr static const char * upsilonRecoveryMessage1 = "The bootloader has detected a crash.";
+ constexpr static const char * upsilonRecoveryMessage2 = "Because you also have an Upsilon slot,";
+ constexpr static const char * upsilonRecoveryMessage3 = "you can recover your data by booting";
+ constexpr static const char * upsilonRecoveryMessage4 = "the Upsilon slot.";
+ constexpr static const char * upsilonRecoveryMessage5 = "Press OK to continue, BACK to cancel";
+
// Warning menu
constexpr static const char * epsilonWarningTitle = "Epsilon Slot";
constexpr static const char * epsilonWarningMessage1 = "!! WARNING !! ";
- constexpr static const char * epsilonWarningMessage2 = "This version of Epsilon";
- constexpr static const char * epsilonWarningMessage3 = "can lock the calculator.";
+ constexpr static const char * epsilonWarningMessage2 = "This version of Epsilon can lock the";
+ constexpr static const char * epsilonWarningMessage3 = "calculator or be incompatible.";
constexpr static const char * epsilonWarningMessage4 = "Proceed the boot ?";
constexpr static const char * epsilonWarningMessage5 = "EXE - Yes";
constexpr static const char * epsilonWarningMessage6 = "BACK - No";
@@ -72,11 +81,11 @@ public:
constexpr static const char * aboutMessage4 = "and select the OS";
constexpr static const char * aboutMessage5 = "to boot.";
- constexpr static const char * bootloaderVersion = "Version 1.0.2 - FREED0M.20";
+ constexpr static const char * bootloaderVersion = "Version 1.1.2 - RECOVER.24.4";
//USB NAMES
- constexpr static const char * usbUpsilonBootloader = "Upsilon Bootloader";
- constexpr static const char * usbUpsilonRecovery = "Upsilon Recovery";
+ constexpr static const char * usbUpsilonBootloader = "NumWorks Calculator";
+ constexpr static const char * usbUpsilonRecovery = "NumWorks Calculator";
constexpr static const char * usbBootloaderUpdate = "Bootloader Update";
};
diff --git a/bootloader/recovery.cpp b/bootloader/recovery.cpp
index 8c849f781..1e6174bb1 100644
--- a/bootloader/recovery.cpp
+++ b/bootloader/recovery.cpp
@@ -1,6 +1,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -10,6 +11,7 @@
#include
#include
#include
+#include
constexpr static uint32_t MagicStorage = 0xEE0BDDBA;
@@ -76,7 +78,15 @@ void Bootloader::Recovery::recoverData() {
Ion::Display::pushRectUniform(KDRect(0,0,320,240), KDColorWhite);
Ion::Backlight::init();
- USBData udata = USBData::Recovery((uint32_t)getSlotConcerned().getStorageAddress(), (uint32_t)getSlotConcerned().getStorageSize());
+ CrashedSlot slot = getSlotConcerned();
+
+ if (Slot::hasUpsilon() && Slot::Upsilon().userlandHeader()->hasUpsilonExtras()) {
+ Ion::Device::BootloaderSharedData::sharedBootloaderData()->setRecovery((uint32_t)slot.getStorageAddress(), slot.getStorageSize());
+ UpsilonRecoveryMenu reco = UpsilonRecoveryMenu();
+ reco.open();
+ }
+
+ USBData udata = USBData::Recovery((uint32_t)slot.getStorageAddress(), (uint32_t)slot.getStorageSize());
SlotRecoveryMenu menu = SlotRecoveryMenu(&udata);
menu.open();
diff --git a/bootloader/slots/slot.cpp b/bootloader/slots/slot.cpp
index 2a3cebee2..5175aa45f 100644
--- a/bootloader/slots/slot.cpp
+++ b/bootloader/slots/slot.cpp
@@ -3,6 +3,8 @@
#include
#include
#include
+#include
+#include
extern "C" void jump_to_firmware(const uint32_t* stackPtr, const void(*startPtr)(void));
@@ -20,6 +22,15 @@ const Slot Slot::Khi() {
return Slot(0x90180000);
}
+const bool Slot::hasUpsilon() {
+ return (isFullyValid(A()) && A().userlandHeader()->isUpsilon()) || (isFullyValid(B()) && B().userlandHeader()->isUpsilon());
+}
+
+const Slot Slot::Upsilon() {
+ assert(hasUpsilon());
+ return (isFullyValid(A()) && A().userlandHeader()->isUpsilon()) ? A() : B();
+}
+
const KernelHeader* Slot::kernelHeader() const {
return m_kernelHeader;
}
diff --git a/bootloader/slots/slot.h b/bootloader/slots/slot.h
index 1d0046605..a0ce406ae 100644
--- a/bootloader/slots/slot.h
+++ b/bootloader/slots/slot.h
@@ -25,6 +25,8 @@ public:
static const Slot A();
static const Slot B();
static const Slot Khi();
+ static const bool hasUpsilon();
+ static const Slot Upsilon();
static bool isFullyValid(const Slot& slot) {
return slot.kernelHeader()->isValid() && slot.userlandHeader()->isValid();
diff --git a/bootloader/slots/slot_exam_mode.cpp b/bootloader/slots/slot_exam_mode.cpp
index 47c22995e..70a776fd4 100644
--- a/bootloader/slots/slot_exam_mode.cpp
+++ b/bootloader/slots/slot_exam_mode.cpp
@@ -41,48 +41,56 @@ size_t numberOfBitsAfterLeadingZeroes(int i) {
}
uint8_t SlotsExamMode::FetchSlotExamMode(const char * version, const char * Slot) {
- // Get start and end from version and slot
- uint32_t start = 0;
- uint32_t end = 0;
+ // Get start and end from version and slot
+ uint32_t start = 0;
+ uint32_t end = 0;
if (Slot == "A") {
- // If version under 16 get old addresses
- if (version[0] < '1' || (version[0] == '1' && version[1] < '6')) {
- start = getSlotAStartExamAddress(0);
+ // If version under 16 get old addresses
+ if (version[0] < '1' || (version[0] == '1' && version[1] < '6')) {
+ start = getSlotAStartExamAddress(0);
end = getSlotAEndExamAddress(0);
- }
- // Else get new addresses
- else {
+ }
+ // Else versions before 22
+ else if ((version[0] == '2' && version[1] < '2') || (version[0] == '1')) {
start = getSlotAStartExamAddress(1);
end = getSlotAEndExamAddress(1);
- }
- }
- else if (Slot == "B") {
- // If version under 16 get old
- if (version[0] < '1' || (version[0] == '1' && version[1] < '6')) {
+ }
+ // Else Epsilon 22 +
+ else {
+ start = getSlotAStartExamAddress(2);
+ end = getSlotAEndExamAddress(2);
+ }
+ }
+ else if (Slot == "B") {
+ // If version under 16 get old
+ if (version[0] < '1' || (version[0] == '1' && version[1] < '6')) {
start = getSlotBStartExamAddress(0);
end = getSlotBEndExamAddress(0);
- }
- // Else get new
- else {
+ }
+ // Else versions before 22
+ else if ((version[0] == '2' && version[1] < '2') || (version[0] == '1')) {
start = getSlotBStartExamAddress(1);
- end = getSlotBEndExamAddress(1);
- }
- } else if (Slot == "Khi") {
+ end = getSlotBEndExamAddress(1);
+ }
+ // Else Epsilon 22 +
+ else {
+ start = getSlotBStartExamAddress(2);
+ end = getSlotBEndExamAddress(2);
+ }
+ } else if (Slot == "Khi") {
// We directly get the address of the Khi exam mode without checking the
// version, because on Khi, version is KhiCAS version, not the OS version
start = getSlotKhiStartExamAddress();
end = getSlotKhiEndExamAddress();
}
- if (strcmp("15.9.0", version) >= 0) {
+ if (strcmp("15.9.0", version) >= 0) {
return examFetch15(start, end);
} else if (strcmp("16.9.0", version) > 0) {
return examFetch16(start, end);
- }
- else if (strcmp("19.0.0", version) > 0) {
+ } else if (strcmp("19.0.0", version) > 0) {
return examFetch1718(start, end);
- }
- else {
+ } else {
return examFetch19(start, end);
}
}
@@ -157,47 +165,80 @@ uint8_t SlotsExamMode::examFetch19(uint32_t start, uint32_t end) {
uint16_t* start16 = (uint16_t*)start;
uint16_t* end16 = (uint16_t*)end;
- while (start16 + 1 <= end16 && *start16 != 0xFFFF) {
- start16++;
+ for (uint16_t* i = end16 - 2; i > start16; i--) {
+ if (*i != 0xFFFF) {
+ uint8_t highByte = *i >> 8;
+ uint8_t lowByte = *i & 0xFF;
+ if (highByte > lowByte) {
+ return highByte;
+ }
+ else {
+ return lowByte;
+ }
+ }
}
-
- return *(start16 - 1) >> 8;
+ return 0;
}
uint32_t SlotsExamMode::getSlotAStartExamAddress(int ExamVersion) {
- if (ExamVersion == 0) {
- return SlotAExamModeBufferStartOldVersions;
- }
- else {
- return SlotAExamModeBufferStartNewVersions;
- }
+ if (ExamVersion == 0) {
+ return SlotAExamModeBufferStartBefore16;
+ }
+ if (ExamVersion == 1) {
+ return SlotAExamModeBufferStartEpsilon16;
+ }
+ if (ExamVersion == 2) {
+ return SlotAExamModeBufferStartEpsilon22;
+ }
+ assert(false);
+ // Should not happen
+ return SlotAExamModeBufferStartEpsilon22;
}
uint32_t SlotsExamMode::getSlotAEndExamAddress(int ExamVersion) {
- if (ExamVersion == 0) {
- return SlotAExamModeBufferEndOldVersions;
- }
- else {
- return SlotAExamModeBufferEndNewVersions;;
- }
+ if (ExamVersion == 0) {
+ return SlotAExamModeBufferEndBefore16;
+ }
+ if (ExamVersion == 1) {
+ return SlotAExamModeBufferEndEpsilon16;
+ }
+ if (ExamVersion == 2) {
+ return SlotAExamModeBufferEndEpsilon22;
+ }
+ assert(false);
+ // Should not happen
+ return SlotAExamModeBufferEndEpsilon22;
+
}
uint32_t SlotsExamMode::getSlotBStartExamAddress(int ExamVersion) {
- if (ExamVersion == 0) {
- return SlotBExamModeBufferStartOldVersions;
- }
- else {
- return SlotBExamModeBufferStartNewVersions;
- }
+ if (ExamVersion == 0) {
+ return SlotBExamModeBufferStartBeforeEpsilon16;
+ }
+ if (ExamVersion == 1) {
+ return SlotBExamModeBufferStartEpsilon16;
+ }
+ if (ExamVersion == 2) {
+ return SlotBExamModeBufferStartEpsilon22;
+ }
+ assert(false);
+ // Should not happen
+ return SlotBExamModeBufferStartEpsilon22;
}
uint32_t SlotsExamMode::getSlotBEndExamAddress(int ExamVersion) {
- if (ExamVersion == 0) {
- return SlotBExamModeBufferEndOldVersions;
- }
- else {
- return SlotBExamModeBufferEndNewVersions;
- }
+ if (ExamVersion == 0) {
+ return SlotBExamModeBufferEndBeforeEpsilon16;
+ }
+ if (ExamVersion == 1) {
+ return SlotBExamModeBufferEndEpsilon16;
+ }
+ if (ExamVersion == 2) {
+ return SlotBExamModeBufferEndEpsilon22;
+ }
+ assert(false);
+ // Should not happen
+ return SlotBExamModeBufferEndEpsilon22;
}
uint32_t SlotsExamMode::getSlotKhiStartExamAddress() {
diff --git a/bootloader/slots/slot_exam_mode.h b/bootloader/slots/slot_exam_mode.h
index 3c19ac7a9..d0f7473d5 100644
--- a/bootloader/slots/slot_exam_mode.h
+++ b/bootloader/slots/slot_exam_mode.h
@@ -8,17 +8,23 @@ extern "C" {
namespace Bootloader {
namespace ExamMode {
-static const uint32_t SlotAExamModeBufferStartOldVersions = 0x90001000;
-static const uint32_t SlotAExamModeBufferEndOldVersions = 0x90003000;
+static const uint32_t SlotAExamModeBufferStartBefore16 = 0x90001000;
+static const uint32_t SlotAExamModeBufferEndBefore16 = 0x90003000;
-static const uint32_t SlotAExamModeBufferStartNewVersions = 0x903f0000;
-static const uint32_t SlotAExamModeBufferEndNewVersions = 0x90400000;
+static const uint32_t SlotAExamModeBufferStartEpsilon16 = 0x903f0000;
+static const uint32_t SlotAExamModeBufferEndEpsilon16 = 0x90400000;
-static const uint32_t SlotBExamModeBufferStartOldVersions = 0x90401000;
-static const uint32_t SlotBExamModeBufferEndOldVersions = 0x90403000;
+static const uint32_t SlotAExamModeBufferStartEpsilon22 = 0x903f0400;
+static const uint32_t SlotAExamModeBufferEndEpsilon22 = 0x90400000;
-static const uint32_t SlotBExamModeBufferStartNewVersions = 0x907f0000;
-static const uint32_t SlotBExamModeBufferEndNewVersions = 0x90800000;
+static const uint32_t SlotBExamModeBufferStartBeforeEpsilon16 = 0x90401000;
+static const uint32_t SlotBExamModeBufferEndBeforeEpsilon16 = 0x90403000;
+
+static const uint32_t SlotBExamModeBufferStartEpsilon16 = 0x907f0000;
+static const uint32_t SlotBExamModeBufferEndEpsilon16 = 0x90800000;
+
+static const uint32_t SlotBExamModeBufferStartEpsilon22 = 0x907f0400;
+static const uint32_t SlotBExamModeBufferEndEpsilon22 = 0x90800000;
static const uint32_t SlotKhiExamModeBufferStart = 0x90181000;
static const uint32_t SlotKhiExamModeBufferEnd = 0x90183000;
diff --git a/bootloader/slots/userland_header.cpp b/bootloader/slots/userland_header.cpp
index a3e57afec..80769e02a 100644
--- a/bootloader/slots/userland_header.cpp
+++ b/bootloader/slots/userland_header.cpp
@@ -40,4 +40,16 @@ const size_t UserlandHeader::storageSize() const {
return m_storageSizeRAM;
}
+const bool UserlandHeader::hasUpsilonExtras() const {
+ return m_upsilonExtraMagicHeader == UpsilonExtraMagic && m_upsilonExtraMagicFooter == UpsilonExtraMagic;
+}
+
+const uint32_t UserlandHeader::getExtraVersion() const {
+ return m_extraVersion;
+}
+
+const void (*UserlandHeader::upsilonRecoveryBootFunction() const)() {
+ return m_recoveryAddress;
+}
+
}
diff --git a/bootloader/slots/userland_header.h b/bootloader/slots/userland_header.h
index 382e409b0..85fa64d3b 100644
--- a/bootloader/slots/userland_header.h
+++ b/bootloader/slots/userland_header.h
@@ -17,12 +17,17 @@ public:
const char * upsilonVersion() const;
const void * storageAddress() const;
const size_t storageSize() const;
+ const bool hasUpsilonExtras() const;
+ const void (*upsilonRecoveryBootFunction() const)();
+ const uint32_t getExtraVersion() const;
+
private:
UserlandHeader();
constexpr static uint32_t Magic = 0xDEC0EDFE;
constexpr static uint32_t OmegaMagic = 0xEFBEADDE;
constexpr static uint32_t UpsilonMagic = 0x55707369;
+ constexpr static uint32_t UpsilonExtraMagic = 0xaa7073ff;
uint32_t m_header;
const char m_expectedEpsilonVersion[8];
void * m_storageAddressRAM;
@@ -42,6 +47,10 @@ private:
const char m_UpsilonVersion[16];
uint32_t m_osType;
uint32_t m_upsilonMagicFooter;
+ uint32_t m_upsilonExtraMagicHeader;
+ const void (*m_recoveryAddress)();
+ uint32_t m_extraVersion;
+ uint32_t m_upsilonExtraMagicFooter;
};
extern const UserlandHeader* s_userlandHeaderA;
diff --git a/bootloader/trampoline.cpp b/bootloader/trampoline.cpp
index 876db0496..56cf2d5e9 100644
--- a/bootloader/trampoline.cpp
+++ b/bootloader/trampoline.cpp
@@ -10,6 +10,8 @@ namespace Bootloader {
void __attribute__((noinline)) suspend() {
Ion::Device::Power::internalFlashSuspend(true);
+ // Restore slotInfo magic header (broken on Epsilon, IDK why)
+ *(uint8_t *)0x20000000 = 0xBA;
}
void* Trampolines[TRAMPOLINES_COUNT]
diff --git a/build/config.mak b/build/config.mak
index cf91239fe..9245ebbe5 100644
--- a/build/config.mak
+++ b/build/config.mak
@@ -6,7 +6,7 @@ DEBUG ?= 0
HOME_DISPLAY_EXTERNALS ?= 1
EPSILON_VERSION ?= 15.5.0
OMEGA_VERSION ?= 2.0.2
-UPSILON_VERSION ?= 1.0.1-dev
+UPSILON_VERSION ?= 1.1.2
# OMEGA_USERNAME ?= N/A
OMEGA_STATE ?= dev
EPSILON_APPS ?= calculation graph rpn code statistics probability solver atomic sequence regression reader settings external
diff --git a/build/device/dfu.py b/build/device/dfu.py
index 7245632ad..36df3a029 100644
--- a/build/device/dfu.py
+++ b/build/device/dfu.py
@@ -79,7 +79,7 @@ __DFU_INTERFACE = 0
# Python 3 deprecated getargspec in favour of getfullargspec, but
# Python 2 doesn't have the latter, so detect which one to use
import inspect
-getargspec = getattr(inspect, 'getfullargspec', inspect.getargspec)
+getargspec = getattr(inspect, 'getfullargspec', inspect.getfullargspec)
if 'length' in getargspec(usb.util.get_string).args:
# PyUSB 1.0.0.b1 has the length argument
diff --git a/build/platform.simulator.3ds.mak b/build/platform.simulator.3ds.mak
index d829e5e0a..dc35a659d 100644
--- a/build/platform.simulator.3ds.mak
+++ b/build/platform.simulator.3ds.mak
@@ -1,5 +1,7 @@
TOOLCHAIN = devkitarm
EXE = elf
+EPSILON_TELEMETRY ?= 0
+
HANDY_TARGETS_EXTENSIONS = 3dsx cia
diff --git a/build/platform.simulator.fxcg.mak b/build/platform.simulator.fxcg.mak
new file mode 100644
index 000000000..fc30c12e8
--- /dev/null
+++ b/build/platform.simulator.fxcg.mak
@@ -0,0 +1,11 @@
+TOOLCHAIN = sh-elf-gcc
+EXE = elf
+
+EPSILON_TELEMETRY ?= 0
+
+HANDY_TARGETS_EXTENSIONS = g3a bin
+
+USE_LIBA = 0
+POINCARE_TREE_LOG = 0
+
+SFLAGS := $(filter-out -fPIE, $(SFLAGS))
diff --git a/build/platform.simulator.macos.mak b/build/platform.simulator.macos.mak
index dcfeac04b..927d80636 100644
--- a/build/platform.simulator.macos.mak
+++ b/build/platform.simulator.macos.mak
@@ -5,7 +5,9 @@ APPLE_PLATFORM = macos
APPLE_PLATFORM_MIN_VERSION = 10.10
EPSILON_TELEMETRY ?= 0
-ARCHS = x86_64
+# Build universal binary for both x86_64 and ARM64 by default
+# Can be overridden with ARCHS=arm64 or ARCHS=x86_64 for single architecture builds
+ARCHS ?= x86_64 arm64
ifdef ARCH
BUILD_DIR := $(BUILD_DIR)/$(ARCH)
diff --git a/build/platform.simulator.nspire.mak b/build/platform.simulator.nspire.mak
new file mode 100644
index 000000000..d158bbc09
--- /dev/null
+++ b/build/platform.simulator.nspire.mak
@@ -0,0 +1,11 @@
+TOOLCHAIN = nspire-gcc
+EXE = elf
+
+EPSILON_TELEMETRY ?= 0
+
+HANDY_TARGETS_EXTENSIONS = tns
+
+USE_LIBA = 0
+POINCARE_TREE_LOG = 0
+
+SFLAGS := $(filter-out -fPIE, $(SFLAGS))
diff --git a/build/targets.simulator.3ds.mak b/build/targets.simulator.3ds.mak
index d06cf52ad..23cbe0a3a 100644
--- a/build/targets.simulator.3ds.mak
+++ b/build/targets.simulator.3ds.mak
@@ -1,7 +1,7 @@
%.smdh: ion/src/simulator/3ds/assets/logo.png
$(Q) echo "SMDH $(notdir $@)"
- $(Q) smdhtool --create "Epsilon" "A Numworks in your 3DS!" "Numworks" $< $@
+ $(Q) smdhtool --create "Upsilon" "A Numworks in your 3DS!" "Numworks" $< $@
$(BUILD_DIR)/%.3dsx: $(BUILD_DIR)/%.elf $(BUILD_DIR)/%.smdh
$(Q) echo "3DSX $(notdir $@)"
diff --git a/build/targets.simulator.fxcg.mak b/build/targets.simulator.fxcg.mak
new file mode 100644
index 000000000..ec26dcc81
--- /dev/null
+++ b/build/targets.simulator.fxcg.mak
@@ -0,0 +1,5 @@
+$(BUILD_DIR)/%.bin: $(BUILD_DIR)/%.elf
+ $(OBJCOPY) -O binary -R .bss -R .gint_bss $< $@
+
+$(BUILD_DIR)/%.g3a: $(BUILD_DIR)/%.bin ion/src/simulator/fxcg/assets/icon-uns.png ion/src/simulator/fxcg/assets/icon-sel.png
+ $(FXGXA) --g3a --icon-uns=ion/src/simulator/fxcg/assets/icon-uns.png --icon-sel=ion/src/simulator/fxcg/assets/icon-sel.png -n Upsilon $< -o $@
diff --git a/build/targets.simulator.nspire.mak b/build/targets.simulator.nspire.mak
new file mode 100644
index 000000000..574bb4d24
--- /dev/null
+++ b/build/targets.simulator.nspire.mak
@@ -0,0 +1,6 @@
+$(BUILD_DIR)/%.tns: $(BUILD_DIR)/%.elf
+# comment one of these lines. For B&W old nspire, do not use the compress option
+ genzehn --compress --input $(BUILD_DIR)/epsilon.elf --output upsilon.tns --name "upsilon" --uses-lcd-blit true
+# genzehn --input $(BUILD_DIR)/epsilon.elf --output upsilon.tns --name "upsilon" --uses-lcd-blit true
+ genzehn --info --input upsilon.tns
+ firebird-send upsilon.tns /ndless
diff --git a/build/toolchain.devkitarm.mak b/build/toolchain.devkitarm.mak
index 52fd7de75..ce7b31e84 100644
--- a/build/toolchain.devkitarm.mak
+++ b/build/toolchain.devkitarm.mak
@@ -31,7 +31,7 @@ LIBDIRS := $(DEVKITPRO)/libctru
INCLUDE = $(foreach dir,$(LIBDIRS),-I$(dir)/include) \
-I$(CURDIR)/$(BUILD)
-CFLAGS += $(INCLUDE) -DARM11 -D_3DS
+CFLAGS += $(INCLUDE) -DARM11 -D_3DS -D__3DS__
CXXFLAGS = $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
diff --git a/build/toolchain.emscripten.mak b/build/toolchain.emscripten.mak
index 14baf3a8f..551ddbc19 100644
--- a/build/toolchain.emscripten.mak
+++ b/build/toolchain.emscripten.mak
@@ -12,6 +12,8 @@ EMFLAGS += -s SAFE_HEAP=1
EMFLAGS += -s STACK_OVERFLOW_CHECK=1
EMFLAGS += -s DEMANGLE_SUPPORT=1
EMFLAGS += -s MAIN_MODULE=1
+EMFLAGS += -g
+EMFLAGS += -O3
else
EMFLAGS += -s MAIN_MODULE=2
endif
@@ -20,10 +22,11 @@ endif
# Configure EMFLAGS
EMFLAGS += -s WASM=1 -s SINGLE_FILE=1
+EMFLAGS += -Wno-unused-command-line-argument
# Configure LDFLAGS
EMSCRIPTEN_MODULARIZE ?= 1
-LDFLAGS += -s MODULARIZE=$(EMSCRIPTEN_MODULARIZE) -s 'EXPORT_NAME="Epsilon"' --memory-init-file 0
+LDFLAGS += -s MODULARIZE=$(EMSCRIPTEN_MODULARIZE) -s 'EXPORT_NAME="Epsilon"'
SFLAGS += $(EMFLAGS)
-LDFLAGS += $(EMFLAGS) -Oz -s EXPORTED_FUNCTIONS='["_main", "_IonSimulatorKeyboardKeyDown", "_IonSimulatorKeyboardKeyUp", "_IonSimulatorEventsPushEvent", "_IonSoftwareVersion", "_IonPatchLevel", "_IonDisplayForceRefresh"]' -s EXPORTED_RUNTIME_METHODS='["UTF8ToString"]'
+LDFLAGS += $(EMFLAGS) -Oz -s EXPORTED_RUNTIME_METHODS='["UTF8ToString"]' -s EXPORTED_FUNCTIONS='["_main", "_IonSimulatorKeyboardKeyDown", "_IonSimulatorKeyboardKeyUp", "_IonSimulatorEventsPushEvent", "_IonSoftwareVersion", "_IonPatchLevel", "_IonDisplayForceRefresh"]'
diff --git a/build/toolchain.nspire-gcc.mak b/build/toolchain.nspire-gcc.mak
new file mode 100644
index 000000000..fe8518942
--- /dev/null
+++ b/build/toolchain.nspire-gcc.mak
@@ -0,0 +1,9 @@
+CC = nspire-gcc
+CXX = nspire-g++
+LD = nspire-g++
+GDB = gdb
+OBJCOPY = nspire-objcopy
+SIZE = nspire-size
+AS = nspire-as
+
+SFLAGS += -DNSPIRE_NEWLIB -DSTRING_STORAGE
diff --git a/build/toolchain.sh-elf-gcc.mak b/build/toolchain.sh-elf-gcc.mak
new file mode 100644
index 000000000..43432065c
--- /dev/null
+++ b/build/toolchain.sh-elf-gcc.mak
@@ -0,0 +1,10 @@
+CC = sh-elf-gcc
+CXX = sh-elf-g++
+LD = sh-elf-g++
+GDB = gdb
+OBJCOPY = sh-elf-objcopy
+SIZE = sh-elf-size
+AS = sh-elf-as
+FXGXA = fxgxa
+
+SFLAGS += -D_FXCG -D_BIG_ENDIAN -DSTRING_STORAGE
diff --git a/build/utilities/translations_clean.py b/build/utilities/translations_clean.py
index bc955991a..afee202fa 100644
--- a/build/utilities/translations_clean.py
+++ b/build/utilities/translations_clean.py
@@ -32,7 +32,7 @@ IGNORE_PATHS = [
]
IGNORE_PATHS_CONTENTS = [
"__pycache__", ".png", ".esc", ".ttf", ".ico", ".jpg", ".jar", ".icn",
- ".bnr", ".i18n"
+ ".bnr", ".i18n", ".cache"
]
# If the key contain something that's in this list, keep it to prevent code breaking
diff --git a/escher/include/escher/expression_field.h b/escher/include/escher/expression_field.h
index 7ecaf57d4..1619dfdd4 100644
--- a/escher/include/escher/expression_field.h
+++ b/escher/include/escher/expression_field.h
@@ -40,6 +40,10 @@ public:
bool handleEvent(Ion::Events::Event event) override;
void didBecomeFirstResponder() override;
+protected:
+ TextField m_textField;
+ LayoutField m_layoutField;
+
private:
static constexpr int k_textFieldBufferSize = TextField::maxBufferSize();
static constexpr KDCoordinate k_minimalHeight = 37;
@@ -49,8 +53,6 @@ private:
constexpr static KDCoordinate k_separatorThickness = Metric::CellSeparatorThickness;
KDCoordinate inputViewHeight() const;
KDCoordinate m_inputViewMemoizedHeight;
- TextField m_textField;
- LayoutField m_layoutField;
};
#endif
diff --git a/escher/src/icon_view.cpp b/escher/src/icon_view.cpp
index 7a5453d2a..1c1db37fe 100644
--- a/escher/src/icon_view.cpp
+++ b/escher/src/icon_view.cpp
@@ -1,6 +1,7 @@
#include
extern "C" {
#include
+#include
}
#include
#include
@@ -43,6 +44,13 @@ void IconView::drawRect(KDContext * ctx, KDRect rect) const {
iconBufferSize * sizeof(KDColor)
);
+ // If we are on a big-endian CPU, we need to swap the bytes
+ #if _BIG_ENDIAN
+ for (uint32_t i = 0; i < iconBufferSize; i++) {
+ pixelBuffer[i] = KDColor::RGB16(__builtin_bswap16(pixelBuffer[i]));
+ }
+ #endif
+
//We push the first 6 lines of the image so that they are truncated on the sides
ctx->fillRectWithPixels(KDRect(6, 0, m_frame.width()-12, 1),pixelBuffer+6, nullptr);
ctx->fillRectWithPixels(KDRect(4, 1, m_frame.width()-8, 1),pixelBuffer+4+55, nullptr);
diff --git a/escher/src/image_view.cpp b/escher/src/image_view.cpp
index 7cb4ee39e..5062ef3f7 100644
--- a/escher/src/image_view.cpp
+++ b/escher/src/image_view.cpp
@@ -1,6 +1,7 @@
#include
extern "C" {
#include
+#include
}
#include
@@ -50,6 +51,13 @@ void ImageView::drawRect(KDContext * ctx, KDRect rect) const {
pixelBufferSize * sizeof(KDColor)
);
+ // If we are on a big-endian CPU, we need to swap the bytes
+ #if _BIG_ENDIAN
+ for (uint32_t i = 0; i < pixelBufferSize; i++) {
+ pixelBuffer[i] = KDColor::RGB16(__builtin_bswap16(pixelBuffer[i]));
+ }
+ #endif
+
ctx->fillRectWithPixels(bounds(), pixelBuffer, nullptr);
}
diff --git a/escher/src/text_area.cpp b/escher/src/text_area.cpp
index 5427ed5b6..c1fd83b39 100644
--- a/escher/src/text_area.cpp
+++ b/escher/src/text_area.cpp
@@ -4,6 +4,7 @@
#include
#include
#include
+#include <../../apps/global_preferences.h>
#include
#include
@@ -249,11 +250,13 @@ bool TextArea::handleEvent(Ion::Events::Event event) {
contentView()->resetSelection();
contentView()->moveCursorGeo(0, event == Ion::Events::Up ? -step : step);
} else if (event == Ion::Events::Clear) {
- if (!contentView()->selectionIsEmpty()) {
- deleteSelection();
- return true;
- } else if (!contentView()->removeEndOfLine()) {
- contentView()->removeStartOfLine();
+ if (GlobalPreferences::sharedGlobalPreferences()->clearShift()) {
+ if (!contentView()->selectionIsEmpty()) {
+ deleteSelection();
+ return true;
+ } else if (!contentView()->removeEndOfLine()) {
+ contentView()->removeStartOfLine();
+ }
}
} else if (event == Ion::Events::Paste) {
return handleEventWithText(Clipboard::sharedClipboard()->storedText());
diff --git a/ion/include/ion/display.h b/ion/include/ion/display.h
index 1b7f32508..0abd90c16 100644
--- a/ion/include/ion/display.h
+++ b/ion/include/ion/display.h
@@ -23,8 +23,15 @@ void pullRect(KDRect r, KDColor * pixels);
bool waitForVBlank();
+#ifndef _FXCG
constexpr int Width = 320;
constexpr int Height = 240;
+#else
+constexpr int Width = 396;
+constexpr int Height = 224;
+#endif
+
+// TODO: Adjust this on the Casio calculator
constexpr int WidthInTenthOfMillimeter = 576;
constexpr int HeightInTenthOfMillimeter = 432;
diff --git a/ion/include/ion/internal_storage.h b/ion/include/ion/internal_storage.h
index 257d243ce..29371b320 100644
--- a/ion/include/ion/internal_storage.h
+++ b/ion/include/ion/internal_storage.h
@@ -22,8 +22,11 @@ public:
static constexpr char expExtension[] = "exp";
static constexpr char funcExtension[] = "func";
static constexpr char seqExtension[] = "seq";
-
- constexpr static size_t k_storageSize = 60000;
+#ifdef _FXCG
+ constexpr static size_t k_storageSize = 65500;
+#else
+ constexpr static size_t k_storageSize = 59992;
+#endif
static_assert(UINT16_MAX >= k_storageSize, "record_size_t not big enough");
constexpr static char k_dotChar = '.';
@@ -195,7 +198,7 @@ public:
class StorageHelper {
public:
static uint16_t unalignedShort(char * address) {
-#if __EMSCRIPTEN__
+#if (defined __EMSCRIPTEN__) || (defined _FXCG) || defined NSPIRE_NEWLIB
uint8_t f1 = *(address);
uint8_t f2 = *(address+1);
uint16_t f = (uint16_t)f1 + (((uint16_t)f2)<<8);
@@ -205,7 +208,7 @@ public:
#endif
}
static void writeUnalignedShort(uint16_t value, char * address) {
-#if __EMSCRIPTEN__
+#if (defined __EMSCRIPTEN__) || (defined _FXCG) || defined NSPIRE_NEWLIB
*((uint8_t *)address) = (uint8_t)(value & ((1 << 8) - 1));
*((uint8_t *)address+1) = (uint8_t)(value >> 8);
#else
diff --git a/ion/include/ion/keyboard.h b/ion/include/ion/keyboard.h
index ba056ffd2..7d448991c 100644
--- a/ion/include/ion/keyboard.h
+++ b/ion/include/ion/keyboard.h
@@ -26,6 +26,12 @@ constexpr Key ValidKeys[] = {
constexpr int NumberOfKeys = 54;
constexpr int NumberOfValidKeys = 46;
+enum class ModSimState : uint8_t {
+ None,
+ ForceOn,
+ ForceOff,
+};
+
class State {
public:
constexpr State(uint64_t s = 0) :
@@ -50,8 +56,25 @@ public:
void clearKey(Key k) {
m_bitField &= ~((uint64_t)1 << (uint8_t)k);
}
+ void setSimulatedShift(ModSimState s) {
+ m_simulateShiftState = s;
+ }
+ ModSimState simulatedShift() const {
+ return m_simulateShiftState;
+ }
+ void setSimulatedAlpha(ModSimState s) {
+ m_simulateAlphaState = s;
+ }
+ ModSimState simulatedAlpha() const {
+ return m_simulateAlphaState;
+ }
private:
uint64_t m_bitField;
+
+ // Simulated key states
+ // These override the real key states and are used to map keys to keys under modifiers
+ ModSimState m_simulateShiftState = ModSimState::None;
+ ModSimState m_simulateAlphaState = ModSimState::None;
};
State scan();
diff --git a/ion/src/device/bootloader/Makefile b/ion/src/device/bootloader/Makefile
index c5d7208f7..93a6f6536 100644
--- a/ion/src/device/bootloader/Makefile
+++ b/ion/src/device/bootloader/Makefile
@@ -3,6 +3,7 @@ ion_device_src += $(addprefix ion/src/device/bootloader/drivers/, \
board.cpp \
cache.cpp \
external_flash_tramp.cpp \
+ storage.cpp \
led.cpp \
power.cpp \
reset.cpp \
diff --git a/ion/src/device/bootloader/boot/rt0.cpp b/ion/src/device/bootloader/boot/rt0.cpp
index a631356bb..1e12db275 100644
--- a/ion/src/device/bootloader/boot/rt0.cpp
+++ b/ion/src/device/bootloader/boot/rt0.cpp
@@ -1,11 +1,15 @@
#include
#include
#include
+#include
+#include
+#include
#include
#include
#include
#include
#include
+#include
typedef void (*cxx_constructor)();
@@ -14,6 +18,8 @@ extern "C" {
extern char _data_section_start_ram;
extern char _data_section_end_ram;
extern char _bss_section_start_ram;
+ extern char _static_storage_start;
+ extern char _static_storage_end;
extern char _bss_section_end_ram;
extern cxx_constructor _init_array_start;
extern cxx_constructor _init_array_end;
@@ -129,6 +135,43 @@ void __attribute__((noinline)) start() {
abort();
}
+void __attribute__((noinline)) __attribute__((section(".recovery_boot"))) __attribute__((used)) recovery_start() {
+ // Here we are in the recovery boot.
+ Ion::Device::Board::initFPU();
+
+ bool is_recoverying = Ion::Device::BootloaderSharedData::sharedBootloaderData()->storageAddress() != 0;
+
+ if (is_recoverying) {
+ uint32_t address = Ion::Device::BootloaderSharedData::sharedBootloaderData()->storageAddress();
+ uint32_t size = Ion::Device::BootloaderSharedData::sharedBootloaderData()->storageSize();
+
+ memcpy(&_static_storage_start, (void*)address, size);
+
+ 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 - &_static_storage_end);
+ memset(&_static_storage_end, 0, bssSectionLength);
+ } else {
+ 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);
+ }
+
+ if (&_init_array_start != &_init_array_end) {
+ abort();
+ }
+ size_t isrSectionLength = (&_isr_vector_table_end_ram - &_isr_vector_table_start_ram);
+ memcpy(&_isr_vector_table_start_ram, &_isr_vector_table_start_flash, isrSectionLength);
+
+ Ion::Device::Board::init();
+
+ jump_to_external_flash();
+
+ abort();
+}
+
void __attribute__((interrupt, noinline)) isr_systick() {
auto t = Ion::Device::Timing::MillisElapsed;
t++;
diff --git a/ion/src/device/bootloader/bootloader_common.ld b/ion/src/device/bootloader/bootloader_common.ld
index e8f0c9bbc..5f2db3750 100644
--- a/ion/src/device/bootloader/bootloader_common.ld
+++ b/ion/src/device/bootloader/bootloader_common.ld
@@ -1,3 +1,4 @@
+BOOTLOADER_SHARED_OFFSET = 0x3d0;
SECTIONS {
.signed_payload_prefix ORIGIN(FLASH) : {
@@ -34,7 +35,14 @@ SECTIONS {
_isr_vector_table_end_ram = .;
} >SRAM
- .exam_mode_buffer ORIGIN(FLASH) + SIZEOF(.signed_payload_prefix) + SIZEOF(.kernel_header) + SIZEOF(.isr_vector_table) : {
+ .bootloader_shared ORIGIN(SRAM) + BOOTLOADER_SHARED_OFFSET : AT(ORIGIN(FLASH) + SIZEOF(.signed_payload_prefix) + SIZEOF(.kernel_header) + SIZEOF(.isr_vector_table) + SIZEOF(.slot_info)) {
+ _bootloader_shared_start = .;
+ KEEP(*(.bootloader_shared))
+ KEEP(*(.bootloader_shared.*))
+ _bootloader_shared_end = .;
+ } >SRAM
+
+ .exam_mode_buffer ORIGIN(FLASH) + SIZEOF(.signed_payload_prefix) + SIZEOF(.kernel_header) + SIZEOF(.isr_vector_table) + SIZEOF(.bootloader_shared) + SIZEOF(.slot_info) : {
. = ALIGN(4K);
_exam_mode_buffer_start = .;
KEEP(*(.exam_mode_buffer))
@@ -49,6 +57,13 @@ SECTIONS {
KEEP(*(.userland_header));
} > FLASH
+ .recovery_boot : {
+ . = ALIGN(4);
+ _recovery_boot_start = .;
+ KEEP(*(.recovery_boot));
+ _recovery_boot_end = .;
+ } >FLASH
+
.text : {
. = ALIGN(4);
*(.text)
@@ -97,6 +112,9 @@ SECTIONS {
* need pointers to the beginning and end of this section. */
. = ALIGN(4);
_bss_section_start_ram = .;
+ _static_storage_start = .;
+ KEEP (*(.static_storage))
+ _static_storage_end = .;
*(.bss)
*(.bss.*)
/* The compiler may choose to allocate uninitialized global variables as
diff --git a/ion/src/device/bootloader/drivers/storage.cpp b/ion/src/device/bootloader/drivers/storage.cpp
new file mode 100644
index 000000000..f04b0793d
--- /dev/null
+++ b/ion/src/device/bootloader/drivers/storage.cpp
@@ -0,0 +1,10 @@
+#include
+
+namespace Ion {
+
+// TODO: Check if the storage is initialized at runtime and not at compile time:
+// As far as I can see, it break build for N0110 legacy internal storage and
+// N0100 due to lack of storage, so it's probably wasting space.
+uint32_t __attribute__((section(".static_storage"))) staticStorageArea[sizeof(Storage)/sizeof(uint32_t)] = {0};
+
+}
diff --git a/ion/src/device/bootloader/internal_flash.ld b/ion/src/device/bootloader/internal_flash.ld
index 6a2555c35..2f5cf3189 100644
--- a/ion/src/device/bootloader/internal_flash.ld
+++ b/ion/src/device/bootloader/internal_flash.ld
@@ -8,6 +8,7 @@ MEMORY {
STACK_SIZE = 32K;
TRAMPOLINES_OFFSET = 0xE000;
CUSTOM_TRAMPOLINES_OFFSET = 64K - 64;
+BOOTLOADER_SHARED_OFFSET = 0x3d0;
SECTIONS {
.isr_vector_table ORIGIN(INTERNAL_FLASH) : {
@@ -31,7 +32,16 @@ SECTIONS {
KEEP(*(.header))
} >INTERNAL_FLASH
- .rodata : {
+ .bootloader_shared ORIGIN(SRAM) + BOOTLOADER_SHARED_OFFSET : AT(ORIGIN(INTERNAL_FLASH) + SIZEOF(.isr_vector_table) + SIZEOF(.header)) {
+ . = ORIGIN(SRAM) + BOOTLOADER_SHARED_OFFSET;
+ _bootloader_shared_start = .;
+ KEEP(*(.bootloader_shared))
+ KEEP(*(.bootloader_shared.*))
+ _bootloader_shared_end = .;
+ } >SRAM
+
+ .rodata ORIGIN(INTERNAL_FLASH) + SIZEOF(.isr_vector_table) + SIZEOF(.header) + SIZEOF(.bootloader_shared) : {
+
. = ALIGN(4);
*(.rodata)
*(.rodata.*)
diff --git a/ion/src/device/bootloader/platform_info.cpp b/ion/src/device/bootloader/platform_info.cpp
index 3b08c1860..8ca190a0d 100644
--- a/ion/src/device/bootloader/platform_info.cpp
+++ b/ion/src/device/bootloader/platform_info.cpp
@@ -17,10 +17,15 @@
#error This file expects UPSILON_VERSION to be defined
#endif
+extern "C" {
+ extern void recovery_start();
+}
namespace Ion {
extern char staticStorageArea[];
}
constexpr void * storageAddress = &(Ion::staticStorageArea);
+typedef void (*recoveryStartPointerType)();
+constexpr recoveryStartPointerType recoveryStartPointer = &(recovery_start);
class KernelHeader {
public:
@@ -72,7 +77,16 @@ public:
m_upsilonMagicHeader(UpsilonMagic),
m_UpsilonVersion{UPSILON_VERSION},
m_osType(OSType),
- m_upsilonMagicFooter(UpsilonMagic) { }
+ m_upsilonMagicFooter(UpsilonMagic),
+ m_upsilonExtraMagicHeader(UpsilonExtraMagic),
+ // We need to be careful with the pointer to the recovery entrypoint as GCC
+ // will simply generate a blank userland header if it wasn't able to
+ // generate it. This code used to work on GCC 12, but is broken since GCC 13
+ // probably due to the cast preventing LD to just copy the address:
+ // m_recoveryAddress((uint32_t)recovery_start + 1),
+ m_recoveryAddress(recoveryStartPointer),
+ m_extraVersion(1),
+ m_upsilonExtraMagicFooter(UpsilonExtraMagic) { }
const char * omegaVersion() const {
assert(m_storageAddressRAM != nullptr);
@@ -109,6 +123,7 @@ private:
constexpr static uint32_t OmegaMagic = 0xEFBEADDE;
constexpr static uint32_t UpsilonMagic = 0x55707369;
constexpr static uint32_t OSType = 0x79827178;
+ constexpr static uint32_t UpsilonExtraMagic = 0xaa7073ff;
uint32_t m_header;
const char m_expectedEpsilonVersion[8];
void * m_storageAddressRAM;
@@ -128,6 +143,10 @@ private:
const char m_UpsilonVersion[16];
uint32_t m_osType;
uint32_t m_upsilonMagicFooter;
+ uint32_t m_upsilonExtraMagicHeader;
+ recoveryStartPointerType m_recoveryAddress;
+ uint32_t m_extraVersion;
+ uint32_t m_upsilonExtraMagicFooter;
};
const UserlandHeader __attribute__((section(".userland_header"), used)) k_userlandHeader;
diff --git a/ion/src/device/n0110/flash.ld b/ion/src/device/n0110/flash.ld
index eb5578ac6..e00ce31e1 100644
--- a/ion/src/device/n0110/flash.ld
+++ b/ion/src/device/n0110/flash.ld
@@ -71,6 +71,7 @@ SECTIONS {
*(.text.__assert)
*(.text.memcpy)
*(.text.memset)
+ *(.text.__udivmoddi4)
/*
*(.text.strlen)
*(.text.strncmp)
diff --git a/ion/src/device/regs/rcc.h b/ion/src/device/regs/rcc.h
index 017e15aeb..b6b951930 100644
--- a/ion/src/device/regs/rcc.h
+++ b/ion/src/device/regs/rcc.h
@@ -75,6 +75,7 @@ public:
public:
using Register32::Register32;
REGS_BOOL_FIELD(TIM3EN, 1);
+ REGS_BOOL_FIELD(TIM5EN, 3);
REGS_BOOL_FIELD(RTCAPB, 10);
REGS_BOOL_FIELD(SPI3EN, 15);
REGS_BOOL_FIELD(USART3EN, 18);
diff --git a/ion/src/device/shared/boot/isr.h b/ion/src/device/shared/boot/isr.h
index ca5becb13..474522699 100644
--- a/ion/src/device/shared/boot/isr.h
+++ b/ion/src/device/shared/boot/isr.h
@@ -8,6 +8,7 @@ extern "C" {
void start();
void abort();
void isr_systick();
+void recovery_start();
#ifdef __cplusplus
}
diff --git a/ion/src/device/shared/drivers/Makefile b/ion/src/device/shared/drivers/Makefile
index 2db043c5f..0ec24eca3 100644
--- a/ion/src/device/shared/drivers/Makefile
+++ b/ion/src/device/shared/drivers/Makefile
@@ -26,4 +26,5 @@ ion_device_src += $(addprefix ion/src/device/shared/drivers/, \
timing.cpp \
usb.cpp \
wakeup.cpp \
+ bldata.cpp \
)
diff --git a/ion/src/device/shared/drivers/bldata.cpp b/ion/src/device/shared/drivers/bldata.cpp
new file mode 100644
index 000000000..f329224bf
--- /dev/null
+++ b/ion/src/device/shared/drivers/bldata.cpp
@@ -0,0 +1,23 @@
+#include "bldata.h"
+#include
+#include
+
+namespace Ion {
+ uint32_t staticSharedData[sizeof(Ion::Device::BootloaderSharedData)/sizeof(uint32_t)] __attribute__((section(".bootloader_shared"))) __attribute__((used)) = {0};
+
+ Device::BootloaderSharedData * Device::BootloaderSharedData::sharedBootloaderData() {
+ static BootloaderSharedData * sharedData = new (staticSharedData) BootloaderSharedData();
+ return sharedData;
+ }
+
+ Device::BootloaderSharedData::BootloaderSharedData() {
+ // FIXME: Find why calculator is crashing when footer is defined
+ // if (m_header != Magic || m_footer != Magic) {
+ if (m_header != Magic) {
+ m_header = Magic;
+ m_storageAddress = 0;
+ m_storageSize = 0;
+ // m_footer = Magic;
+ }
+ }
+}
diff --git a/ion/src/device/shared/drivers/bldata.h b/ion/src/device/shared/drivers/bldata.h
new file mode 100644
index 000000000..97d563144
--- /dev/null
+++ b/ion/src/device/shared/drivers/bldata.h
@@ -0,0 +1,24 @@
+#include
+
+namespace Ion
+{
+namespace Device
+{
+ class BootloaderSharedData {
+ public:
+ constexpr static uint32_t Magic = 0x626C6461;
+ static BootloaderSharedData * sharedBootloaderData();
+
+ BootloaderSharedData();
+
+ void setRecovery(uint32_t address, uint32_t size) { m_storageAddress = address; m_storageSize = size; }
+ uint32_t storageAddress() const { return m_storageAddress; }
+ uint32_t storageSize() const { return m_storageSize; }
+ private:
+ uint32_t m_header;
+ uint32_t m_storageAddress;
+ uint32_t m_storageSize;
+ // uint32_t m_footer;
+ };
+}
+}
diff --git a/ion/src/device/shared/ram.ld b/ion/src/device/shared/ram.ld
index ef027f3e0..0c57f5089 100644
--- a/ion/src/device/shared/ram.ld
+++ b/ion/src/device/shared/ram.ld
@@ -23,10 +23,10 @@ MEMORY {
* overwritten (for instance, vtables that live in the .rodata section). */
/* The image is quite large too!
- * So we put the stack to 18K so there's still space
+ * So we put the stack to 17K so there's still space
* for our image, if not LD will throw an error. */
-STACK_SIZE = 18K;
+STACK_SIZE = 17K;
SECTIONS {
.isr_vector_table ORIGIN(RAM_BUFFER) : {
diff --git a/ion/src/device/shared/regs/rcc.h b/ion/src/device/shared/regs/rcc.h
index 050512632..07b8854be 100644
--- a/ion/src/device/shared/regs/rcc.h
+++ b/ion/src/device/shared/regs/rcc.h
@@ -118,6 +118,7 @@ public:
public:
using Register32::Register32;
REGS_BOOL_FIELD(TIM3EN, 1);
+ REGS_BOOL_FIELD(TIM5EN, 3);
REGS_BOOL_FIELD(RTCAPB, 10);
REGS_BOOL_FIELD(SPI3EN, 15);
REGS_BOOL_FIELD(USART3EN, 18);
diff --git a/ion/src/device/shared/regs/syscfg.h b/ion/src/device/shared/regs/syscfg.h
index e044a65f6..7423b88f4 100644
--- a/ion/src/device/shared/regs/syscfg.h
+++ b/ion/src/device/shared/regs/syscfg.h
@@ -2,7 +2,7 @@
#define REGS_SYSCFG_H
#include "register.h"
-#include
+// #include
#include "gpio.h"
#define REGS_SYSCFG_CONFIG_F412 1
diff --git a/ion/src/device/shared/usb/calculator.h b/ion/src/device/shared/usb/calculator.h
index 29a7203c6..e411aac04 100644
--- a/ion/src/device/shared/usb/calculator.h
+++ b/ion/src/device/shared/usb/calculator.h
@@ -63,7 +63,7 @@ public:
* switching to DFU mode. It does not apply to the calculator.*/
2048, // wTransferSize: Maximum number of bytes that the device can accept per control-write transaction
0x0100),// bcdDFUVersion
- m_interfaceDescriptor(
+ m_interfaceDescriptor1(
0, // bInterfaceNumber
k_dfuInterfaceAlternateSetting, // bAlternateSetting
0, // bNumEndpoints: Other than endpoint 0
@@ -71,9 +71,20 @@ public:
1, // bInterfaceSubClass: DFU
2, // bInterfaceProtocol: DFU Mode (not DFU Runtime, which would be 1)
4, // iInterface: Index of the Interface string, see m_descriptor
+ &m_interfaceDescriptor2),
+ m_interfaceDescriptor2(
+ 0, // bInterfaceNumber
+ k_dfuInterfaceAlternateSetting + 1, // bAlternateSetting
+ 0, // bNumEndpoints: Other than endpoint 0
+ 0xFE, // bInterfaceClass: DFU (https://www.usb.org/defined-class-codes)
+ 1, // bInterfaceSubClass: DFU
+ 2, // bInterfaceProtocol: DFU Mode (not DFU Runtime, which would be 1)
+ // TODO: Use real descriptor, not required for now as the descriptor isn't
+ // used anywhere in DFU firmware, but is only present so NumWorks website work.
+ 4, // iInterface: Index of the Interface string, see m_descriptor
&m_dfuFunctionalDescriptor),
m_configurationDescriptor(
- 9 + 9 + 9, // wTotalLength: configuration descriptor + interface descriptor + dfu functional descriptor lengths
+ 9 + 9 + 9 + 9, // wTotalLength: configuration descriptor + interface descriptor 1 + interface descriptor 2 + dfu functional descriptor lengths2
1, // bNumInterfaces
k_bConfigurationValue, // bConfigurationValue
0, // iConfiguration: No string descriptor for the configuration
@@ -83,7 +94,7 @@ public:
* Bit 5: Remote Wakeup (allows the device to wake up the host when the host is in suspend)
* Bit 4..0: Reserved, set to 0 */
0x32, // bMaxPower: half of the Maximum Power Consumption
- &m_interfaceDescriptor),
+ &m_interfaceDescriptor1),
m_webUSBPlatformDescriptor(
k_webUSBVendorCode,
k_webUSBLandingPageIndex),
@@ -93,12 +104,15 @@ public:
&m_webUSBPlatformDescriptor),
m_languageStringDescriptor(),
m_manufacturerStringDescriptor("NumWorks"),
- m_productStringDescriptor("Upsilon Calculator"),
+ m_productStringDescriptor("NumWorks Calculator"),
m_serialNumberStringDescriptor(serialNumber),
m_interfaceStringDescriptor(stringDescriptor()),
//m_interfaceStringDescriptor("@SRAM/0x20000000/01*256Ke"),
/* Switch to this descriptor to use dfu-util to write in the SRAM.
* FIXME Should be an alternate Interface. */
+ // Epsilon 25.6.0 descriptors for example
+ // @SRAM/0x20000000/01*252Ke
+ // @Flash/0x90030000/61*064Kg,64*064Kg
m_microsoftOSStringDescriptor(k_microsoftOSVendorCode),
m_workshopURLDescriptor(URLDescriptor::Scheme::HTTPS, "getupsilon.web.app"),
m_extendedCompatIdDescriptor("WINUSB"),
@@ -141,7 +155,8 @@ private:
// Descriptors
DeviceDescriptor m_deviceDescriptor;
DFUFunctionalDescriptor m_dfuFunctionalDescriptor;
- InterfaceDescriptor m_interfaceDescriptor;
+ InterfaceDescriptor m_interfaceDescriptor1;
+ InterfaceDescriptor m_interfaceDescriptor2;
ConfigurationDescriptor m_configurationDescriptor;
WebUSBPlatformDescriptor m_webUSBPlatformDescriptor;
BOSDescriptor m_bosDescriptor;
diff --git a/ion/src/shared/events_keyboard.cpp b/ion/src/shared/events_keyboard.cpp
index 73038b619..3fe943fd2 100644
--- a/ion/src/shared/events_keyboard.cpp
+++ b/ion/src/shared/events_keyboard.cpp
@@ -1,3 +1,4 @@
+#include
#include
#include
#include
@@ -50,10 +51,6 @@ void resetLongRepetition() {
ComputeAndSetRepetitionFactor(sEventRepetitionCount);
}
-static Keyboard::Key keyFromState(Keyboard::State state) {
- return static_cast(63 - __builtin_clzll(state));
-}
-
static inline Event innerGetEvent(int * timeout) {
assert(*timeout > delayBeforeRepeat);
assert(*timeout > delayBetweenRepeat);
@@ -84,8 +81,18 @@ static inline Event innerGetEvent(int * timeout) {
Keyboard::Key key = (Keyboard::Key)(63-__builtin_clzll(keysSeenTransitioningFromUpToDown));
bool shift = isShiftActive() || state.keyDown(Keyboard::Key::Shift);
bool alpha = isAlphaActive() || state.keyDown(Keyboard::Key::Alpha);
+
+ // Allow the detected states to be overriden by the simulated states
+ // This is used for key mapping
+ if (state.simulatedShift() != Keyboard::ModSimState::None) {
+ shift = state.simulatedShift() == Keyboard::ModSimState::ForceOn;
+ }
+ if (state.simulatedAlpha() != Keyboard::ModSimState::None) {
+ alpha = state.simulatedAlpha() == Keyboard::ModSimState::ForceOn;
+ }
+
bool lock = isLockActive();
-
+
if ( key == Keyboard::Key::Left
|| key == Keyboard::Key::Right
|| key == Keyboard::Key::Up
@@ -97,7 +104,7 @@ static inline Event innerGetEvent(int * timeout) {
// shift = false;
}
}
-
+
Event event(key, shift, alpha, lock);
sLastEventShift = shift;
sLastEventAlpha = alpha;
diff --git a/ion/src/shared/internal_storage.cpp b/ion/src/shared/internal_storage.cpp
index 5fc4a90d1..82373da6f 100644
--- a/ion/src/shared/internal_storage.cpp
+++ b/ion/src/shared/internal_storage.cpp
@@ -336,18 +336,14 @@ void InternalStorage::destroyRecordsWithExtension(const char * extension) {
}
}
-InternalStorage::InternalStorage() :
- m_magicHeader(Magic),
- m_buffer(),
- m_magicFooter(Magic),
- m_delegate(nullptr),
- m_lastRecordRetrieved(nullptr),
- m_lastRecordRetrievedPointer(nullptr)
-{
+InternalStorage::InternalStorage() {
+ m_magicHeader = Magic;
+ m_magicFooter = Magic;
+ m_delegate = nullptr;
+ m_lastRecordRetrieved = nullptr;
+ m_lastRecordRetrievedPointer = nullptr;
assert(m_magicHeader == Magic);
assert(m_magicFooter == Magic);
- // Set the size of the first record to 0
- overrideSizeAtPosition(m_buffer, 0);
}
// PRIVATE
diff --git a/ion/src/shared/storage.cpp b/ion/src/shared/storage.cpp
index 50a8a4c70..ebc2dc8d2 100644
--- a/ion/src/shared/storage.cpp
+++ b/ion/src/shared/storage.cpp
@@ -6,7 +6,9 @@
namespace Ion {
-uint32_t staticStorageArea[sizeof(Storage)/sizeof(uint32_t)] = {0};
+// Declaration for N0110 with bootloader is in ion/src/device/bootloader/drivers/storage.cpp
+// to fix LD build
+__attribute__((weak)) uint32_t staticStorageArea[sizeof(Storage)/sizeof(uint32_t)] = {0};
Storage * Storage::sharedStorage() {
static Storage * storage = new (staticStorageArea) Storage();
diff --git a/ion/src/simulator/3ds/Makefile b/ion/src/simulator/3ds/Makefile
index a7de79edd..5ca58d891 100644
--- a/ion/src/simulator/3ds/Makefile
+++ b/ion/src/simulator/3ds/Makefile
@@ -19,22 +19,29 @@ ion_src += $(addprefix ion/src/simulator/3ds/, \
ion_src += ion/src/shared/collect_registers.cpp
-sdl_simu_needs_to_be_removed += $(addprefix ion/src/simulator/shared/, \
+sdl_simu_needs_to_be_removed += $(addprefix ion/src/shared/, \
dummy/display.cpp \
dummy/led.cpp \
dummy/usb.cpp \
dummy/battery.cpp \
+ dummy/store_script.cpp \
+)
+
+sdl_simu_needs_to_be_removed += $(addprefix ion/src/simulator/shared/, \
clipboard.cpp \
display.cpp:-headless \
events_keyboard.cpp:-headless \
events.cpp \
+ events_platform.cpp \
framebuffer_base.cpp \
+ framebuffer.cpp \
keyboard_sdl.cpp:-headless \
+ keyboard.cpp \
main_sdl.cpp:-headless \
+ main.cpp \
layout.cpp:-headless \
- dummy/store_script.cpp \
+ timing.cpp \
)
# Remove the dummy display (re-implemented) and the SDL simulator stuff.
ion_src := $(filter-out $(sdl_simu_needs_to_be_removed),$(ion_src))
-
diff --git a/ion/src/simulator/3ds/main.cpp b/ion/src/simulator/3ds/main.cpp
index c0b38e9c4..d95a248c8 100644
--- a/ion/src/simulator/3ds/main.cpp
+++ b/ion/src/simulator/3ds/main.cpp
@@ -19,6 +19,10 @@ void Ion::Timing::msleep(uint32_t ms) {
svcSleepThread((s64) ms * 1000);
}
+uint64_t Ion::Timing::millis() {
+ return svcGetSystemTick() / (1000 * 1000);
+}
+
int main(int argc, char * argv[]) {
Ion::Simulator::Main::init();
diff --git a/ion/src/simulator/android/Makefile b/ion/src/simulator/android/Makefile
index 0af9abb97..154280005 100644
--- a/ion/src/simulator/android/Makefile
+++ b/ion/src/simulator/android/Makefile
@@ -30,9 +30,13 @@ ifndef ARCH
$(BUILD_DIR)/app/res/mipmap/ic_launcher.png: ion/src/simulator/assets/logo.svg | $$(@D)/.
$(call rule_label,CONVERT)
- $(Q) convert -background "#b1403b" $< $@
+ $(Q) convert -background "#5c83ab" $< $@
$(BUILD_DIR)/app/res/mipmap-v26/ic_launcher_foreground.png: ion/src/simulator/assets/logo.svg | $$(@D)/.
+ $(call rule_label,CONVERT)
+ $(Q) convert -background none $< -resize 694x694 -gravity center -background none -extent 1024x1024 $@
+
+$(BUILD_DIR)/app/res/mipmap-v26/ic_launcher_monochrome.png: ion/src/simulator/assets/logo_monochrome.svg | $$(@D)/.
$(call rule_label,CONVERT)
$(Q) convert -background none $< -resize 1024x1024 -gravity center -background none -extent 1024x1024 $@
@@ -58,13 +62,13 @@ $(foreach ARCH,$(ARCHS),$(eval $(call rule_for_arch_jni_lib,$(ARCH))))
apk_deps = $(foreach ARCH,$(ARCHS),$(call path_for_arch_jni_lib,$(ARCH)))
apk_deps += $(subst ion/src/simulator/android/src/res,$(BUILD_DIR)/app/res,$(wildcard ion/src/simulator/android/src/res/*/*))
-apk_deps += $(addprefix $(BUILD_DIR)/app/res/,mipmap/ic_launcher.png mipmap-v26/ic_launcher_foreground.png)
+apk_deps += $(addprefix $(BUILD_DIR)/app/res/,mipmap/ic_launcher.png mipmap-v26/ic_launcher_foreground.png mipmap-v26/ic_launcher_monochrome.png)
.PRECIOUS: $(apk_deps)
$(BUILD_DIR)/%.apk: $(apk_deps)
$(call rule_label,GRADLE)
- $(Q) ANDROID_HOME=$(ANDROID_HOME) EPSILON_VERSION=$(EPSILON_VERSION) OMEGA_VERSION=$(OMEGA_VERSION) BUILD_DIR=$(BUILD_DIR) EPSILON_VARIANT=$* ion/src/simulator/android/gradlew -b ion/src/simulator/android/build.gradle assembleRelease
+ $(Q) ANDROID_HOME=$(ANDROID_HOME) UPSILON_VERSION=$(UPSILON_VERSION) BUILD_DIR=$(BUILD_DIR) EPSILON_VARIANT=$* ion/src/simulator/android/gradlew -p ion/src/simulator/android assembleRelease --warning-mode all
$(Q) cp $(BUILD_DIR)/app/outputs/apk/release/android-release*.apk $@
endif
diff --git a/ion/src/simulator/android/build.gradle b/ion/src/simulator/android/build.gradle
index bb48650fd..d432f5c76 100644
--- a/ion/src/simulator/android/build.gradle
+++ b/ion/src/simulator/android/build.gradle
@@ -12,18 +12,17 @@ def fileIfPath(path) {
buildscript {
repositories {
- jcenter()
+ mavenCentral()
google()
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.2.0'
- classpath 'com.google.gms:google-services:4.2.0'
+ classpath 'com.android.tools.build:gradle:8.8.1'
}
}
allprojects {
repositories {
- jcenter()
+ mavenCentral()
google()
}
buildDir = BUILD_DIR
@@ -32,14 +31,15 @@ allprojects {
apply plugin: 'com.android.application'
android {
- compileSdkVersion 29
+ namespace = "io.github.upsilon.simulator"
+ compileSdkVersion 35
defaultConfig {
- applicationId "io.github.omega.simulator"
- minSdkVersion 16
- targetSdkVersion 29
- def (major, minor, patch) = System.getenv('OMEGA_VERSION').toLowerCase().tokenize('.').collect{it.toInteger()}
- versionCode major*1000000 + minor*10000 + patch * 100
- versionName System.getenv('OMEGA_VERSION')
+ applicationId "io.github.upsilon.simulator"
+ minSdkVersion 21
+ targetSdkVersion 33
+ def d=new Date()
+ versionCode Instant.now().getEpochSecond().toInteger()
+ versionName LocalDate.now().format("yyyyMMdd")+'-'+System.getenv('UPSILON_VERSION')
}
signingConfigs {
environment {
@@ -54,7 +54,9 @@ android {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt')
if (projectVariable('SIGNING_STORE_FILE')) {
- signingConfig signingConfigs.environment
+ signingConfig = signingConfigs.environment
+ } else {
+ signingConfig = signingConfigs.debug
}
}
}
@@ -68,13 +70,15 @@ android {
}
}
lintOptions {
- abortOnError false
- checkReleaseBuilds false
+ abortOnError = false
+ checkReleaseBuilds = false
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
- implementation "androidx.appcompat:appcompat:1.0.2"
- implementation "com.google.android.gms:play-services-analytics:16.0.7"
+ implementation "androidx.appcompat:appcompat:1.7.0"
+ implementation(platform("org.jetbrains.kotlin:kotlin-bom:2.1.10"))
}
+
+java{toolchain{languageVersion=JavaLanguageVersion.of(21)}}
diff --git a/ion/src/simulator/android/gradle/wrapper/gradle-wrapper.properties b/ion/src/simulator/android/gradle/wrapper/gradle-wrapper.properties
index 44e7c4d1d..58abf278a 100644
--- a/ion/src/simulator/android/gradle/wrapper/gradle-wrapper.properties
+++ b/ion/src/simulator/android/gradle/wrapper/gradle-wrapper.properties
@@ -1,5 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-5.2.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.12.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
+
diff --git a/ion/src/simulator/android/src/AndroidManifest.xml b/ion/src/simulator/android/src/AndroidManifest.xml
index 061134649..45e5a672b 100644
--- a/ion/src/simulator/android/src/AndroidManifest.xml
+++ b/ion/src/simulator/android/src/AndroidManifest.xml
@@ -1,16 +1,15 @@
-
+
-
-
+
+
-
diff --git a/ion/src/simulator/android/src/cpp/haptics_enabled.cpp b/ion/src/simulator/android/src/cpp/haptics_enabled.cpp
index 52a8b5480..3dacea1c5 100644
--- a/ion/src/simulator/android/src/cpp/haptics_enabled.cpp
+++ b/ion/src/simulator/android/src/cpp/haptics_enabled.cpp
@@ -10,7 +10,7 @@ namespace Haptics {
bool isEnabled() {
JNIEnv * env = static_cast(SDL_AndroidGetJNIEnv());
jobject activity = static_cast(SDL_AndroidGetActivity());
- jclass j_class = env->FindClass("io/github/omega/simulator/OmegaActivity");
+ jclass j_class = env->FindClass("io/github/upsilon/simulator/UpsilonActivity");
jmethodID j_methodId = env->GetMethodID(j_class,"hapticFeedbackIsEnabled", "()Z");
assert(j_methodId != 0);
bool result = (env->CallBooleanMethod(activity, j_methodId) != JNI_FALSE);
diff --git a/ion/src/simulator/android/src/cpp/platform_images.cpp b/ion/src/simulator/android/src/cpp/platform_images.cpp
index 86ed18060..5a5535bec 100644
--- a/ion/src/simulator/android/src/cpp/platform_images.cpp
+++ b/ion/src/simulator/android/src/cpp/platform_images.cpp
@@ -12,7 +12,7 @@ SDL_Texture * loadImage(SDL_Renderer * renderer, const char * identifier) {
JNIEnv * env = static_cast(SDL_AndroidGetJNIEnv());
jobject activity = static_cast(SDL_AndroidGetActivity());
- jclass j_class = env->FindClass("io/github/omega/simulator/OmegaActivity");
+ jclass j_class = env->FindClass("io/github/upsilon/simulator/UpsilonActivity");
jmethodID j_methodId = env->GetMethodID(
j_class,
"retrieveBitmapAsset",
diff --git a/ion/src/simulator/android/src/cpp/platform_language.cpp b/ion/src/simulator/android/src/cpp/platform_language.cpp
index b41b1ae46..6d1b3ed1f 100644
--- a/ion/src/simulator/android/src/cpp/platform_language.cpp
+++ b/ion/src/simulator/android/src/cpp/platform_language.cpp
@@ -12,7 +12,7 @@ const char * languageCode() {
JNIEnv * env = static_cast(SDL_AndroidGetJNIEnv());
jobject activity = static_cast(SDL_AndroidGetActivity());
- jclass j_class = env->FindClass("io/github/omega/OmegaActivity");
+ jclass j_class = env->FindClass("io/github/upsilon/simulator/UpsilonActivity");
jmethodID j_methodId = env->GetMethodID(
j_class,
"retrieveLanguage",
diff --git a/ion/src/simulator/android/src/java/io/github/omega/simulator/OmegaActivity.java b/ion/src/simulator/android/src/java/io/github/upsilon/simulator/UpsilonActivity.java
similarity index 88%
rename from ion/src/simulator/android/src/java/io/github/omega/simulator/OmegaActivity.java
rename to ion/src/simulator/android/src/java/io/github/upsilon/simulator/UpsilonActivity.java
index 317847f3a..7b1a9c53b 100644
--- a/ion/src/simulator/android/src/java/io/github/omega/simulator/OmegaActivity.java
+++ b/ion/src/simulator/android/src/java/io/github/upsilon/simulator/UpsilonActivity.java
@@ -1,4 +1,4 @@
-package io.github.omega.simulator;
+package io.github.upsilon.simulator;
import java.util.Locale;
@@ -11,14 +11,10 @@ import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
-import com.google.android.gms.analytics.GoogleAnalytics;
-import com.google.android.gms.analytics.Tracker;
-import com.google.android.gms.analytics.HitBuilders;
-
import org.libsdl.app.SDLActivity;
import org.libsdl.app.SDL;
-public class OmegaActivity extends SDLActivity {
+public class UpsilonActivity extends SDLActivity {
protected String[] getLibraries() {
return new String[] {
"epsilon"
diff --git a/ion/src/simulator/android/src/res/mipmap-v26/ic_launcher.xml b/ion/src/simulator/android/src/res/mipmap-v26/ic_launcher.xml
index 166130012..8b5c4f9f6 100644
--- a/ion/src/simulator/android/src/res/mipmap-v26/ic_launcher.xml
+++ b/ion/src/simulator/android/src/res/mipmap-v26/ic_launcher.xml
@@ -1,5 +1,6 @@
-
+
+
diff --git a/ion/src/simulator/android/src/res/values/colors.xml b/ion/src/simulator/android/src/res/values/colors.xml
deleted file mode 100644
index e59207b60..000000000
--- a/ion/src/simulator/android/src/res/values/colors.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
- #C03535
- #F7F7F7
-
diff --git a/ion/src/simulator/android/src/res/values/styles.xml b/ion/src/simulator/android/src/res/values/resources.xml
similarity index 77%
rename from ion/src/simulator/android/src/res/values/styles.xml
rename to ion/src/simulator/android/src/res/values/resources.xml
index b787ddffb..d5a665be2 100644
--- a/ion/src/simulator/android/src/res/values/styles.xml
+++ b/ion/src/simulator/android/src/res/values/resources.xml
@@ -1,8 +1,10 @@
+ Upsilon
+ #5c83ab