mirror of
https://github.com/UpsilonNumworks/Upsilon.git
synced 2026-01-18 16:27:34 +01:00
Casio fx-CG series port (#324)
* Initial test - working on Linux
* Try to make it work with liba
* Stop using liba and the filesystem
* IT WORKS
* Key input, full res, fix some of the crashes
* Fix the hang when doing calculations
* Add some more key mappings
* Fix the square root issue
* Icons
* Better key mappings, brightness control, better gamma correction, more effficient framebuffer
* Cleanup stage 1
* Cleanup stage 2
* Make the build system build a g3a
* Make it not exit when you press the menu button
* Add Casio port to README
* Use omega-master instead of omega-dev
* Fix mistake with cherry-picking in the README
* Fix internal storage crash
* Fix compile error on Numworks calculators
* Upsilon branding
* Sharper icon
* Make the CI work
* Add power off and improve menu
* Map Alpha + up/down to the brightness shortcut
* Add missing file
* Fix web CI build
* Revert "Fix web CI build"
This reverts commit f19657d9fc.
* Change "prizm" to "fxcg"
* Add FASTLOAD option for Add-in Push
* Add some charatcers to the catalog on Casio and improve key mappings
* Build with -Os -flto
* Disable LTO for now as it's causing crashes
* Put back the fonts I accidently changed
I'd like to add an option for this though as I prefer the ones from Epsilon
This commit is contained in:
58
.github/workflows/ci-workflow.yml
vendored
58
.github/workflows/ci-workflow.yml
vendored
@@ -18,6 +18,64 @@ on:
|
||||
required: true
|
||||
default: 'yes'
|
||||
jobs:
|
||||
fxcg:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install curl git python3 build-essential cmake pkg-config -y
|
||||
- name: Get latest gint commit hash
|
||||
run: |
|
||||
LATEST_COMMIT_HASH=$(curl --silent https://gitea.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@v3
|
||||
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://gitea.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@master
|
||||
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
|
||||
|
||||
2
Makefile
2
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
|
||||
|
||||
37
README.md
37
README.md
@@ -264,7 +264,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,7 +280,7 @@ 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.
|
||||
@@ -301,7 +301,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,7 +317,7 @@ 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.
|
||||
@@ -330,7 +330,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,7 +346,7 @@ 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.
|
||||
@@ -400,7 +400,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 +416,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 +430,22 @@ You can then put epsilon.3dsx on a SD card to run it from the HBC or use 3dslink
|
||||
|
||||
<br>
|
||||
|
||||
<details>
|
||||
<summary><b>Casio fx-CG-series Port</b></summary>
|
||||
|
||||
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.
|
||||
|
||||
</details>
|
||||
|
||||
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 +492,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).
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
PythonCommandAmpersand = "&"
|
||||
PythonCommandLF = "\\n"
|
||||
PythonCommandPercent = "%"
|
||||
PythonCommandColon = ":"
|
||||
PythonCommandSemicon = ";"
|
||||
PythonCommandExclamationMark = "!"
|
||||
PythonCommandLessThan = "<"
|
||||
PythonCommandGreaterThan = ">"
|
||||
PythonCommandQuestionMark = "?"
|
||||
PythonCommandPound = "#"
|
||||
PythonCommandSingleQuote = "'x'"
|
||||
PythonCommandSymbolExp = "^"
|
||||
|
||||
@@ -503,6 +503,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),
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -276,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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -854,6 +854,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),
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "about_controller.h"
|
||||
#include "../../../python/src/py/mpconfig.h"
|
||||
#include "poincare/division.h"
|
||||
#include <assert.h>
|
||||
#include <cmath>
|
||||
#include <apps/settings/main_controller.h>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -121,3 +121,4 @@ CatalyticActivityDimension = "Katalitikus aktivitás"
|
||||
SurfaceDimension = "Felület"
|
||||
VolumeDimension = "Hangerő"
|
||||
SpeedDimension = "Sebesség"
|
||||
Factorial = "Faktorál"
|
||||
|
||||
@@ -121,3 +121,4 @@ CatalyticActivityDimension = "Attività catalitica"
|
||||
SurfaceDimension = "Superficie"
|
||||
VolumeDimension = "Volume"
|
||||
SpeedDimension = "Velocità"
|
||||
Factorial = "Fattoriale"
|
||||
|
||||
@@ -121,3 +121,4 @@ CatalyticActivityDimension = "Katalytische activiteit"
|
||||
SurfaceDimension = "Oppervlak"
|
||||
VolumeDimension = "Volume"
|
||||
SpeedDimension = "Snelheid"
|
||||
Factorial = "Faculteit"
|
||||
|
||||
@@ -125,6 +125,8 @@ DotCommandWithArg = "dot(u,v)"
|
||||
E = "e"
|
||||
Equal = "="
|
||||
FactorCommandWithArg = "factor(n)"
|
||||
FactorialCommand = "!"
|
||||
FactorialCommandWithArg = "n!"
|
||||
FccId = "FCC ID"
|
||||
FloorCommandWithArg = "floor(x)"
|
||||
FracCommandWithArg = "frac(x)"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -65,7 +65,11 @@ void ContinuousFunctionCache::ComputeNonCartesianSteps(float * tStep, float * tC
|
||||
const int numberOfWholeSteps = static_cast<int>(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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -511,3 +511,4 @@ MagneticFluxQuantumTag = "Magnetisches Fluss-Quantum"
|
||||
ConductanceQuantumTag = "Leitwertquantum"
|
||||
CirculationQuantumTag = "Auflage-Quantum"
|
||||
MatricesAndVectors = "Matrizen und Vektoren"
|
||||
Factorial = "Fakultät"
|
||||
|
||||
@@ -511,3 +511,4 @@ HartreeConstantTag = "Hartree Constant"
|
||||
MagneticFluxQuantumTag = "Magnetic Flux Quantum"
|
||||
ConductanceQuantumTag = "Conductance Quantum"
|
||||
CirculationQuantumTag = "Circulation Quantum"
|
||||
Factorial = "Factorial"
|
||||
@@ -511,3 +511,4 @@ MagneticFluxQuantumTag = "Flujo Magnético Cuántico"
|
||||
ConductanceQuantumTag = "Conductancia Quantum"
|
||||
CirculationQuantumTag = "Circulación Quantum"
|
||||
MatricesAndVectors = "Matrices y vectores"
|
||||
Factorial = "Factorial"
|
||||
|
||||
@@ -515,3 +515,4 @@ MagneticFluxQuantumTag = "Quantum de Flux Magnétique"
|
||||
ConductanceQuantumTag = "Quantum de Conductance"
|
||||
CirculationQuantumTag = "Quantum de Circulation"
|
||||
MatricesAndVectors = "Matrices et vecteurs"
|
||||
Factorial = "Factorielle"
|
||||
|
||||
@@ -511,3 +511,4 @@ MagneticFluxQuantumTag = "Fluxo Magnético Quântico"
|
||||
ConductanceQuantumTag = "Quantum de Conduta"
|
||||
CirculationQuantumTag = "Quantum de Circulação"
|
||||
MatricesAndVectors = "Matrizes e vetores"
|
||||
Factorial = "Fatorial"
|
||||
|
||||
11
build/platform.simulator.fxcg.mak
Normal file
11
build/platform.simulator.fxcg.mak
Normal file
@@ -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))
|
||||
5
build/targets.simulator.fxcg.mak
Normal file
5
build/targets.simulator.fxcg.mak
Normal file
@@ -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 $@
|
||||
10
build/toolchain.sh-elf-gcc.mak
Normal file
10
build/toolchain.sh-elf-gcc.mak
Normal file
@@ -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
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <escher/icon_view.h>
|
||||
extern "C" {
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
}
|
||||
#include <ion.h>
|
||||
#include <kandinsky.h>
|
||||
@@ -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);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
#include <escher/image_view.h>
|
||||
extern "C" {
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
}
|
||||
#include <ion.h>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -195,7 +195,7 @@ public:
|
||||
class StorageHelper {
|
||||
public:
|
||||
static uint16_t unalignedShort(char * address) {
|
||||
#if __EMSCRIPTEN__
|
||||
#if (defined __EMSCRIPTEN__) || (defined _FXCG)
|
||||
uint8_t f1 = *(address);
|
||||
uint8_t f2 = *(address+1);
|
||||
uint16_t f = (uint16_t)f1 + (((uint16_t)f2)<<8);
|
||||
@@ -205,7 +205,7 @@ public:
|
||||
#endif
|
||||
}
|
||||
static void writeUnalignedShort(uint16_t value, char * address) {
|
||||
#if __EMSCRIPTEN__
|
||||
#if (defined __EMSCRIPTEN__) || (defined _FXCG)
|
||||
*((uint8_t *)address) = (uint8_t)(value & ((1 << 8) - 1));
|
||||
*((uint8_t *)address+1) = (uint8_t)(value >> 8);
|
||||
#else
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
#include <ion/keyboard.h>
|
||||
#include <ion/events.h>
|
||||
#include <ion/timing.h>
|
||||
#include <assert.h>
|
||||
@@ -84,6 +85,16 @@ 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
|
||||
|
||||
2
ion/src/simulator/external/config.fxcg.mak
vendored
Normal file
2
ion/src/simulator/external/config.fxcg.mak
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
undefine sdl_src
|
||||
undefine ion_simulator_sdl_src
|
||||
66
ion/src/simulator/fxcg/Makefile
Normal file
66
ion/src/simulator/fxcg/Makefile
Normal file
@@ -0,0 +1,66 @@
|
||||
|
||||
ion_src += $(addprefix ion/src/simulator/fxcg/, \
|
||||
main.cpp \
|
||||
clipboard.cpp \
|
||||
display.cpp \
|
||||
framebuffer.cpp \
|
||||
telemetry_init.cpp \
|
||||
keyboard.cpp \
|
||||
events_keyboard.cpp \
|
||||
events.cpp \
|
||||
timing.cpp \
|
||||
console.cpp \
|
||||
backlight.cpp \
|
||||
power.cpp \
|
||||
menuHandler.cpp \
|
||||
)
|
||||
|
||||
liba_src += $(addprefix liba/src/, \
|
||||
strlcat.c \
|
||||
strlcpy.c \
|
||||
)
|
||||
|
||||
ion_src += ion/src/shared/collect_registers.cpp
|
||||
|
||||
sdl_simu_needs_to_be_removed += $(addprefix ion/src/simulator/shared/, \
|
||||
main.cpp \
|
||||
clipboard.cpp \
|
||||
display.cpp \
|
||||
framebuffer.cpp \
|
||||
keyboard.cpp \
|
||||
events_keyboard.cpp \
|
||||
events_platform.cpp \
|
||||
events.cpp \
|
||||
layout.cpp \
|
||||
actions.cpp \
|
||||
window.cpp \
|
||||
timing.cpp \
|
||||
console.cpp \
|
||||
)
|
||||
|
||||
sdl_simu_needs_to_be_removed += $(addprefix ion/src/shared/dummy/, \
|
||||
backlight.cpp \
|
||||
power.cpp \
|
||||
)
|
||||
|
||||
#sdl_simu_needs_to_be_removed += $(addprefix ion/src/simulator/shared/dummy/, \
|
||||
# display.cpp \
|
||||
# led.cpp \
|
||||
# usb.cpp \
|
||||
# battery.cpp \
|
||||
# store_script.cpp \
|
||||
#)
|
||||
|
||||
# Remove the dummy diaplay (re-implemented) and the SDL simulator stuff.
|
||||
ion_src := $(filter-out $(sdl_simu_needs_to_be_removed),$(ion_src))
|
||||
|
||||
SFLAGS := $(filter-out -Iion/src/simulator/external/sdl/include,$(SFLAGS))
|
||||
|
||||
SFLAGS += -DFXCG50 -DTARGET_FXCG50 -m4-nofpu -mb -ffreestanding -nostdlib -Wa,--dsp -fstrict-volatile-bitfields -g -Os
|
||||
LDFLAGS += -nostdlib -Wl,--no-warn-rwx-segments -lgint-cg -lc -lgint-cg -lc -lgcc -lopenlibm -lstdc++ -lgcc
|
||||
|
||||
ifdef FASTLOAD
|
||||
LDFLAGS += -T fxcg50_fastload.ld
|
||||
else
|
||||
LDFLAGS += -T fxcg50.ld
|
||||
endif
|
||||
BIN
ion/src/simulator/fxcg/assets/icon-sel.png
Normal file
BIN
ion/src/simulator/fxcg/assets/icon-sel.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.5 KiB |
BIN
ion/src/simulator/fxcg/assets/icon-uns.png
Normal file
BIN
ion/src/simulator/fxcg/assets/icon-uns.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.7 KiB |
67
ion/src/simulator/fxcg/backlight.cpp
Normal file
67
ion/src/simulator/fxcg/backlight.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
#include <ion/backlight.h>
|
||||
|
||||
#include <gint/drivers/r61524.h>
|
||||
#include <gint/defs/util.h>
|
||||
|
||||
// From gint:
|
||||
/* Interface with the controller */
|
||||
static volatile uint16_t *intf = (uint16_t *)0xb4000000;
|
||||
/* Bit 4 of Port R controls the RS bit of the display driver */
|
||||
static volatile uint8_t *PRDR = (uint8_t *)0xa405013c;
|
||||
|
||||
GINLINE static void select(uint16_t reg)
|
||||
{
|
||||
/* Clear RS and write the register number */
|
||||
*PRDR &= ~0x10;
|
||||
synco();
|
||||
*intf = reg;
|
||||
synco();
|
||||
|
||||
/* Set RS back. We don't do this in read()/write() because the display
|
||||
driver is optimized for consecutive GRAM access. LCD-transfers will
|
||||
be faster when executing select() followed by several calls to
|
||||
write(). (Although most applications should use the DMA instead.) */
|
||||
*PRDR |= 0x10;
|
||||
synco();
|
||||
}
|
||||
|
||||
// From Utilities addin:
|
||||
// START OF POWER MANAGEMENT CODE
|
||||
#define LCDC *(unsigned int*)(0xB4000000)
|
||||
int getRawBacklightSubLevel()
|
||||
{
|
||||
// Bdisp_DDRegisterSelect(0x5a1);
|
||||
select(0x5a1);
|
||||
return (LCDC & 0xFF) - 6;
|
||||
}
|
||||
void setRawBacklightSubLevel(int level)
|
||||
{
|
||||
// Bdisp_DDRegisterSelect(0x5a1);
|
||||
select(0x5a1);
|
||||
LCDC = (level & 0xFF) + 6;
|
||||
}
|
||||
// END OF POWER MANAGEMENT CODE
|
||||
|
||||
namespace Ion {
|
||||
namespace Backlight {
|
||||
|
||||
uint8_t brightness() {
|
||||
return getRawBacklightSubLevel();
|
||||
}
|
||||
|
||||
void setBrightness(uint8_t b) {
|
||||
setRawBacklightSubLevel(b);
|
||||
}
|
||||
|
||||
void init() {
|
||||
}
|
||||
|
||||
bool isInitialized() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void shutdown() {
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
18
ion/src/simulator/fxcg/clipboard.cpp
Normal file
18
ion/src/simulator/fxcg/clipboard.cpp
Normal file
@@ -0,0 +1,18 @@
|
||||
#include <ion/clipboard.h>
|
||||
#include <ion.h>
|
||||
#include <string.h>
|
||||
|
||||
namespace Ion {
|
||||
namespace Clipboard {
|
||||
|
||||
uint32_t localClipboardVersion;
|
||||
|
||||
void write(const char * text) {
|
||||
}
|
||||
|
||||
const char * read() {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
24
ion/src/simulator/fxcg/console.cpp
Normal file
24
ion/src/simulator/fxcg/console.cpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#include <ion/console.h>
|
||||
#include "main.h"
|
||||
#include <kandinsky/ion_context.h>
|
||||
#include <stdio.h>
|
||||
|
||||
namespace Ion {
|
||||
namespace Console {
|
||||
|
||||
char readChar() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void writeChar(char c) {
|
||||
// fxlibc conflicts with this
|
||||
#undef putchar
|
||||
KDIonContext::putchar(c);
|
||||
}
|
||||
|
||||
bool transmissionDone() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
30
ion/src/simulator/fxcg/display.cpp
Normal file
30
ion/src/simulator/fxcg/display.cpp
Normal file
@@ -0,0 +1,30 @@
|
||||
#include "display.h"
|
||||
#include "framebuffer.h"
|
||||
#include <kandinsky/color.h>
|
||||
#include <stdint.h>
|
||||
#include <gint/display-cg.h>
|
||||
#include <ion/display.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <gint/display.h>
|
||||
#include <gint/keyboard.h>
|
||||
|
||||
namespace Ion {
|
||||
namespace Simulator {
|
||||
namespace Display {
|
||||
|
||||
void init() {
|
||||
}
|
||||
|
||||
void quit() {
|
||||
}
|
||||
|
||||
void draw() {
|
||||
dupdate();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
19
ion/src/simulator/fxcg/display.h
Normal file
19
ion/src/simulator/fxcg/display.h
Normal file
@@ -0,0 +1,19 @@
|
||||
#ifndef ION_SIMULATOR_DISPLAY_H
|
||||
#define ION_SIMULATOR_DISPLAY_H
|
||||
|
||||
#include <kandinsky.h>
|
||||
|
||||
namespace Ion {
|
||||
namespace Simulator {
|
||||
namespace Display {
|
||||
|
||||
void init();
|
||||
void quit();
|
||||
|
||||
void draw();
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
23
ion/src/simulator/fxcg/events.cpp
Normal file
23
ion/src/simulator/fxcg/events.cpp
Normal file
@@ -0,0 +1,23 @@
|
||||
#include "events.h"
|
||||
#include <ion/events.h>
|
||||
|
||||
namespace Ion {
|
||||
namespace Events {
|
||||
|
||||
void didPressNewKey() {
|
||||
}
|
||||
|
||||
char * sharedExternalTextBuffer() {
|
||||
static char buffer[sharedExternalTextBufferSize];
|
||||
return buffer;
|
||||
}
|
||||
|
||||
const char * Event::text() const {
|
||||
if (*this == ExternalText) {
|
||||
return const_cast<const char *>(sharedExternalTextBuffer());
|
||||
}
|
||||
return defaultText();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
24
ion/src/simulator/fxcg/events.h
Normal file
24
ion/src/simulator/fxcg/events.h
Normal file
@@ -0,0 +1,24 @@
|
||||
#ifndef ION_SIMULATOR_EVENTS_H
|
||||
#define ION_SIMULATOR_EVENTS_H
|
||||
|
||||
#include <ion/events.h>
|
||||
|
||||
namespace Ion {
|
||||
namespace Simulator {
|
||||
namespace Events {
|
||||
|
||||
void dumpEventCount(int i);
|
||||
void logAfter(int numberOfEvents);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
namespace Events {
|
||||
|
||||
static constexpr int sharedExternalTextBufferSize = 2;
|
||||
char * sharedExternalTextBuffer();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
15
ion/src/simulator/fxcg/events_keyboard.cpp
Normal file
15
ion/src/simulator/fxcg/events_keyboard.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#include <ion/events.h>
|
||||
|
||||
namespace Ion {
|
||||
namespace Events {
|
||||
|
||||
|
||||
Event getPlatformEvent() {
|
||||
Event result = None;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
56
ion/src/simulator/fxcg/framebuffer.cpp
Normal file
56
ion/src/simulator/fxcg/framebuffer.cpp
Normal file
@@ -0,0 +1,56 @@
|
||||
#include "framebuffer.h"
|
||||
#include <gint/display-cg.h>
|
||||
#include <ion/display.h>
|
||||
#include "main.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <gint/display.h>
|
||||
|
||||
// static KDColor sPixels[Ion::Display::Width * Ion::Display::Height];
|
||||
static_assert(sizeof(KDColor) == sizeof(uint16_t), "KDColor is not 16 bits");
|
||||
static KDColor* sPixels = (KDColor*) gint_vram;
|
||||
static bool sFrameBufferActive = true;
|
||||
|
||||
namespace Ion {
|
||||
namespace Display {
|
||||
|
||||
static KDFrameBuffer sFrameBuffer = KDFrameBuffer(sPixels, KDSize(Ion::Display::Width, Ion::Display::Height));
|
||||
|
||||
void pushRect(KDRect r, const KDColor * pixels) {
|
||||
if (sFrameBufferActive) {
|
||||
Simulator::Main::setNeedsRefresh();
|
||||
sFrameBuffer.pushRect(r, pixels);
|
||||
}
|
||||
}
|
||||
|
||||
void pushRectUniform(KDRect r, KDColor c) {
|
||||
if (sFrameBufferActive) {
|
||||
Simulator::Main::setNeedsRefresh();
|
||||
sFrameBuffer.pushRectUniform(r, c);
|
||||
}
|
||||
}
|
||||
|
||||
void pullRect(KDRect r, KDColor * pixels) {
|
||||
if (sFrameBufferActive) {
|
||||
sFrameBuffer.pullRect(r, pixels);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
namespace Ion {
|
||||
namespace Simulator {
|
||||
namespace Framebuffer {
|
||||
|
||||
const KDColor * address() {
|
||||
return sPixels;
|
||||
}
|
||||
|
||||
void setActive(bool enabled) {
|
||||
sFrameBufferActive = enabled;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
17
ion/src/simulator/fxcg/framebuffer.h
Normal file
17
ion/src/simulator/fxcg/framebuffer.h
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef ION_SIMULATOR_FRAMEBUFFER_H
|
||||
#define ION_SIMULATOR_FRAMEBUFFER_H
|
||||
|
||||
#include <kandinsky.h>
|
||||
|
||||
namespace Ion {
|
||||
namespace Simulator {
|
||||
namespace Framebuffer {
|
||||
|
||||
const KDColor * address();
|
||||
void setActive(bool enabled);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
262
ion/src/simulator/fxcg/keyboard.cpp
Normal file
262
ion/src/simulator/fxcg/keyboard.cpp
Normal file
@@ -0,0 +1,262 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <gint/display-cg.h>
|
||||
#include <gint/display.h>
|
||||
#include <gint/keycodes.h>
|
||||
#include <gint/keyboard.h>
|
||||
#include <gint/gint.h>
|
||||
#include <gint/clock.h>
|
||||
|
||||
#include <ion/keyboard.h>
|
||||
#include <ion/events.h>
|
||||
#include <ion/power.h>
|
||||
|
||||
#include "keyboard.h"
|
||||
#include "layout_keyboard.h"
|
||||
#include "main.h"
|
||||
#include "menuHandler.h"
|
||||
|
||||
|
||||
using namespace Ion::Keyboard;
|
||||
|
||||
class KeyPair {
|
||||
public:
|
||||
constexpr KeyPair(Key key, bool numworksShift, bool numworksAlpha, int gintKey, bool gintShift, bool gintAlpha, bool ignoreShiftAlpha = false) :
|
||||
m_key(key),
|
||||
m_numworksShift(numworksShift),
|
||||
m_numworksAlpha(numworksAlpha),
|
||||
m_gintKey(gintKey),
|
||||
m_gintShift(gintShift),
|
||||
m_gintAlpha(gintAlpha),
|
||||
m_ignoreShiftAlpha(ignoreShiftAlpha)
|
||||
{}
|
||||
Key key() const { return m_key; }
|
||||
bool numworksShift() const { return m_numworksShift; }
|
||||
bool numworksAlpha() const { return m_numworksAlpha; }
|
||||
int gintKey() const { return m_gintKey; }
|
||||
bool gintShift() const { return m_gintShift; }
|
||||
bool gintAlpha() const { return m_gintAlpha; }
|
||||
bool ignoreShiftAlpha() const { return m_ignoreShiftAlpha; }
|
||||
private:
|
||||
Key m_key;
|
||||
bool m_numworksShift;
|
||||
bool m_numworksAlpha;
|
||||
int m_gintKey;
|
||||
bool m_gintShift;
|
||||
bool m_gintAlpha;
|
||||
bool m_ignoreShiftAlpha;
|
||||
};
|
||||
|
||||
constexpr static KeyPair sKeyPairs[] = {
|
||||
KeyPair(Key::Down, false, false, KEY_DOWN, false, false, true),
|
||||
KeyPair(Key::Left, false, false, KEY_LEFT, false, false, true),
|
||||
KeyPair(Key::Right, false, false, KEY_RIGHT, false, false, true),
|
||||
KeyPair(Key::Up, false, false, KEY_UP, false, false, true),
|
||||
KeyPair(Key::Back, false, false, KEY_EXIT, false, false),
|
||||
KeyPair(Key::Home, false, false, KEY_MENU, false, false),
|
||||
KeyPair(Key::Shift, false, false, KEY_SHIFT, false, false, true),
|
||||
KeyPair(Key::Alpha, false, false, KEY_ALPHA, false, false, true),
|
||||
KeyPair(Key::XNT, false, false, KEY_XOT, false, false),
|
||||
KeyPair(Key::Var, false, false, KEY_VARS, false, false),
|
||||
KeyPair(Key::Toolbox, false, false, KEY_OPTN, false, false),
|
||||
KeyPair(Key::Backspace, false, false, KEY_DEL, false, false),
|
||||
KeyPair(Key::Exp, false, false, KEY_LN, true, false),
|
||||
KeyPair(Key::Ln, false, false, KEY_LN, false, false),
|
||||
KeyPair(Key::Log, false, false, KEY_LOG, false, false),
|
||||
KeyPair(Key::Imaginary, false, false, KEY_0, true, false),
|
||||
KeyPair(Key::Comma, false, false, KEY_COMMA, false, false),
|
||||
KeyPair(Key::Power, false, false, KEY_POWER, false, false),
|
||||
KeyPair(Key::Sine, false, false, KEY_SIN, false, false),
|
||||
KeyPair(Key::Cosine, false, false, KEY_COS, false, false),
|
||||
KeyPair(Key::Tangent, false, false, KEY_TAN, false, false),
|
||||
KeyPair(Key::Pi, false, false, KEY_EXP, true, false),
|
||||
KeyPair(Key::Sqrt, false, false, KEY_SQUARE, true, false),
|
||||
KeyPair(Key::Square, false, false, KEY_SQUARE, false, false),
|
||||
KeyPair(Key::Seven, false, false, KEY_7, false, false),
|
||||
KeyPair(Key::Eight, false, false, KEY_8, false, false),
|
||||
KeyPair(Key::Nine, false, false, KEY_9, false, false),
|
||||
KeyPair(Key::LeftParenthesis, false, false, KEY_LEFTP, false, false),
|
||||
KeyPair(Key::RightParenthesis, false, false, KEY_RIGHTP, false, false),
|
||||
KeyPair(Key::Four, false, false, KEY_4, false, false),
|
||||
KeyPair(Key::Five, false, false, KEY_5, false, false),
|
||||
KeyPair(Key::Six, false, false, KEY_6, false, false),
|
||||
KeyPair(Key::Multiplication, false, false, KEY_MUL, false, false),
|
||||
KeyPair(Key::Division, false, false, KEY_DIV, false, false),
|
||||
KeyPair(Key::Division, false, false, KEY_FRAC, false, false),
|
||||
KeyPair(Key::One, false, false, KEY_1, false, false),
|
||||
KeyPair(Key::Two, false, false, KEY_2, false, false),
|
||||
KeyPair(Key::Three, false, false, KEY_3, false, false),
|
||||
KeyPair(Key::Plus, false, false, KEY_ADD, false, false),
|
||||
KeyPair(Key::Minus, false, false, KEY_SUB, false, false),
|
||||
KeyPair(Key::Zero, false, false, KEY_0, false, false),
|
||||
KeyPair(Key::Dot, false, false, KEY_DOT, false, false),
|
||||
KeyPair(Key::EE, false, false, KEY_EXP, false, false),
|
||||
KeyPair(Key::Ans, false, false, KEY_NEG, true, false),
|
||||
KeyPair(Key::EXE, false, false, KEY_EXE, false, false, true),
|
||||
KeyPair(Key::OnOff, false, false, KEY_ACON, true, false),
|
||||
|
||||
// Cut
|
||||
// Not assigned
|
||||
// Copy
|
||||
KeyPair(Key::Var, true, false, KEY_8, true, false),
|
||||
// Paste
|
||||
KeyPair(Key::Toolbox, true, false, KEY_9, true, false),
|
||||
// Clear
|
||||
KeyPair(Key::Backspace, true, false, KEY_ACON, false, false),
|
||||
// [
|
||||
KeyPair(Key::Exp, true, false, KEY_ADD, true, false),
|
||||
// ]
|
||||
KeyPair(Key::Ln, true, false, KEY_SUB, true, false),
|
||||
// {
|
||||
KeyPair(Key::Log, true, false, KEY_MUL, true, false),
|
||||
// }
|
||||
KeyPair(Key::Imaginary, true, false, KEY_DIV, true, false),
|
||||
// _
|
||||
KeyPair(Key::Comma, true, false, KEY_NEG, false, false),
|
||||
// ->
|
||||
KeyPair(Key::Power, true, false, KEY_STORE, false, false),
|
||||
// asin
|
||||
KeyPair(Key::Sine, true, false, KEY_SIN, true, false),
|
||||
// acos
|
||||
KeyPair(Key::Cosine, true, false, KEY_COS, true, false),
|
||||
// atan
|
||||
KeyPair(Key::Tangent, true, false, KEY_TAN, true, false),
|
||||
// =
|
||||
KeyPair(Key::Pi, true, false, KEY_DOT, true, false),
|
||||
// <
|
||||
KeyPair(Key::Sqrt, true, false, KEY_F1, false, false),
|
||||
// >
|
||||
KeyPair(Key::Square, true, false, KEY_F2, false, false),
|
||||
|
||||
// :
|
||||
KeyPair(Key::XNT, false, true, KEY_F3, false, false),
|
||||
// ;
|
||||
KeyPair(Key::Var, false, true, KEY_F4, false, false),
|
||||
// "
|
||||
KeyPair(Key::Toolbox, false, true, KEY_EXP, false, true),
|
||||
// %
|
||||
KeyPair(Key::Backspace, false, true, KEY_F5, false, false),
|
||||
// A
|
||||
KeyPair(Key::Exp, false, true, KEY_XOT, false, true),
|
||||
// B
|
||||
KeyPair(Key::Ln, false, true, KEY_LOG, false, true),
|
||||
// C
|
||||
KeyPair(Key::Log, false, true, KEY_LN, false, true),
|
||||
// D
|
||||
KeyPair(Key::Imaginary, false, true, KEY_SIN, false, true),
|
||||
// E
|
||||
KeyPair(Key::Comma, false, true, KEY_COS, false, true),
|
||||
// F
|
||||
KeyPair(Key::Power, false, true, KEY_TAN, false, true),
|
||||
// G
|
||||
KeyPair(Key::Sine, false, true, KEY_FRAC, false, true),
|
||||
// H
|
||||
KeyPair(Key::Cosine, false, true, KEY_FD, false, true),
|
||||
// I
|
||||
KeyPair(Key::Tangent, false, true, KEY_LEFTP, false, true),
|
||||
// J
|
||||
KeyPair(Key::Pi, false, true, KEY_RIGHTP, false, true),
|
||||
// K
|
||||
KeyPair(Key::Sqrt, false, true, KEY_COMMA, false, true),
|
||||
// L
|
||||
KeyPair(Key::Square, false, true, KEY_ARROW, false, true),
|
||||
// M
|
||||
KeyPair(Key::Seven, false, true, KEY_7, false, true),
|
||||
// N
|
||||
KeyPair(Key::Eight, false, true, KEY_8, false, true),
|
||||
// O
|
||||
KeyPair(Key::Nine, false, true, KEY_9, false, true),
|
||||
// P
|
||||
KeyPair(Key::LeftParenthesis, false, true, KEY_4, false, true),
|
||||
// Q
|
||||
KeyPair(Key::RightParenthesis, false, true, KEY_5, false, true),
|
||||
// R
|
||||
KeyPair(Key::Four, false, true, KEY_6, false, true),
|
||||
// S
|
||||
KeyPair(Key::Five, false, true, KEY_TIMES, false, true),
|
||||
// T
|
||||
KeyPair(Key::Six, false, true, KEY_DIV, false, true),
|
||||
// U
|
||||
KeyPair(Key::Multiplication, false, true, KEY_1, false, true),
|
||||
// V
|
||||
KeyPair(Key::Division, false, true, KEY_2, false, true),
|
||||
// W
|
||||
KeyPair(Key::One, false, true, KEY_3, false, true),
|
||||
// X
|
||||
KeyPair(Key::Two, false, true, KEY_PLUS, false, true),
|
||||
// Y
|
||||
KeyPair(Key::Three, false, true, KEY_MINUS, false, true),
|
||||
// Z
|
||||
KeyPair(Key::Plus, false, true, KEY_0, false, true),
|
||||
// Space
|
||||
KeyPair(Key::Minus, false, true, KEY_DOT, false, true),
|
||||
// ?
|
||||
KeyPair(Key::Zero, false, true, KEY_F6, true, false),
|
||||
// !
|
||||
KeyPair(Key::Dot, false, true, KEY_F6, false, false),
|
||||
|
||||
// Brightness control shortcut in Upsilon
|
||||
KeyPair(Key::Plus, true, false, KEY_UP, false, true),
|
||||
KeyPair(Key::Minus, true, false, KEY_DOWN, false, true),
|
||||
};
|
||||
|
||||
constexpr int sNumberOfKeyPairs = sizeof(sKeyPairs)/sizeof(KeyPair);
|
||||
|
||||
namespace Ion {
|
||||
namespace Keyboard {
|
||||
|
||||
int menuHeldFor = 0;
|
||||
|
||||
State scan() {
|
||||
State state = 0;
|
||||
|
||||
// Grab this opportunity to refresh the display if needed
|
||||
Simulator::Main::refresh();
|
||||
|
||||
clearevents();
|
||||
if (keydown(KEY_MENU)) {
|
||||
state.setKey(Key::Home);
|
||||
menuHeldFor++;
|
||||
if (menuHeldFor > 30) {
|
||||
Simulator::FXCGMenuHandler::openMenu();
|
||||
dupdate();
|
||||
// Wait until EXE is released
|
||||
do {
|
||||
sleep_ms(10);
|
||||
clearevents();
|
||||
} while (keydown(KEY_EXE));
|
||||
}
|
||||
} else {
|
||||
menuHeldFor = 0;
|
||||
}
|
||||
|
||||
for (int i = 0; i < sNumberOfKeyPairs; i++) {
|
||||
const KeyPair & keyPair = sKeyPairs[i];
|
||||
if (!keyPair.ignoreShiftAlpha() &&
|
||||
(keyPair.gintShift() != Events::isShiftActive() ||
|
||||
keyPair.gintAlpha() != Events::isAlphaActive())) {
|
||||
continue;
|
||||
}
|
||||
if (keydown(keyPair.gintKey())) {
|
||||
if (!keyPair.ignoreShiftAlpha()) {
|
||||
state.setSimulatedShift(keyPair.numworksShift() ? ModSimState::ForceOn : ModSimState::ForceOff);
|
||||
state.setSimulatedAlpha(keyPair.numworksAlpha() ? ModSimState::ForceOn : ModSimState::ForceOff);
|
||||
}
|
||||
state.setKey(keyPair.key());
|
||||
}
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
namespace Ion {
|
||||
namespace Simulator {
|
||||
namespace Keyboard {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
15
ion/src/simulator/fxcg/keyboard.h
Normal file
15
ion/src/simulator/fxcg/keyboard.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef ION_SIMULATOR_KEYBOARD_H
|
||||
#define ION_SIMULATOR_KEYBOARD_H
|
||||
|
||||
#include <ion/keyboard.h>
|
||||
// #include <libndls.h>
|
||||
|
||||
namespace Ion {
|
||||
namespace Simulator {
|
||||
namespace Keyboard {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
114
ion/src/simulator/fxcg/main.cpp
Normal file
114
ion/src/simulator/fxcg/main.cpp
Normal file
@@ -0,0 +1,114 @@
|
||||
#include "main.h"
|
||||
#include "display.h"
|
||||
#include "platform.h"
|
||||
|
||||
#include <gint/display-cg.h>
|
||||
#include <gint/gint.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <vector>
|
||||
|
||||
#include <ion.h>
|
||||
#include <ion/events.h>
|
||||
|
||||
extern "C" {
|
||||
int main() {
|
||||
Ion::Simulator::Main::init();
|
||||
ion_main(0, NULL);
|
||||
Ion::Simulator::Main::quit();
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Ion {
|
||||
namespace Simulator {
|
||||
namespace Main {
|
||||
|
||||
static bool sNeedsRefresh = false;
|
||||
|
||||
void init() {
|
||||
Ion::Simulator::Display::init();
|
||||
setNeedsRefresh();
|
||||
}
|
||||
|
||||
void setNeedsRefresh() {
|
||||
sNeedsRefresh = true;
|
||||
}
|
||||
|
||||
void refresh() {
|
||||
if (!sNeedsRefresh) {
|
||||
return;
|
||||
}
|
||||
|
||||
Display::draw();
|
||||
|
||||
sNeedsRefresh = false;
|
||||
}
|
||||
|
||||
void quit() {
|
||||
Ion::Simulator::Display::quit();
|
||||
}
|
||||
|
||||
void EnableStatusArea(int opt) {
|
||||
__asm__ __volatile__ (
|
||||
".align 2 \n\t"
|
||||
"mov.l 2f, r2 \n\t"
|
||||
"mov.l 1f, r0 \n\t"
|
||||
"jmp @r2 \n\t"
|
||||
"nop \n\t"
|
||||
".align 2 \n\t"
|
||||
"1: \n\t"
|
||||
".long 0x02B7 \n\t"
|
||||
".align 4 \n\t"
|
||||
"2: \n\t"
|
||||
".long 0x80020070 \n\t"
|
||||
);
|
||||
}
|
||||
|
||||
extern "C" void *__GetVRAMAddress(void);
|
||||
|
||||
uint8_t xyram_backup[16 * 1024];
|
||||
uint8_t ilram_backup[4 * 1024];
|
||||
|
||||
void worldSwitchHandler(void (*worldSwitchFunction)(), bool prepareVRAM) {
|
||||
// Back up XYRAM
|
||||
uint8_t* xyram = (uint8_t*) 0xe500e000;
|
||||
memcpy(xyram_backup, xyram, 16 * 1024);
|
||||
// Back up ILRAM
|
||||
uint8_t* ilram = (uint8_t*) 0xe5200000;
|
||||
memcpy(ilram_backup, ilram, 4 * 1024);
|
||||
|
||||
if (prepareVRAM) {
|
||||
// Copying the screen to the OS's VRAM avoids a flicker when powering on
|
||||
uint16_t* dst = (uint16_t *) __GetVRAMAddress();
|
||||
uint16_t* src = gint_vram + 6;
|
||||
|
||||
for (int y = 0; y < 216; y++, dst += 384, src += 396) {
|
||||
for (int x = 0; x < 384; x++) {
|
||||
dst[x] = src[x];
|
||||
}
|
||||
}
|
||||
|
||||
// Disable the status area
|
||||
EnableStatusArea(3);
|
||||
}
|
||||
|
||||
worldSwitchFunction();
|
||||
|
||||
// Restore XYRAM
|
||||
memcpy(xyram, xyram_backup, 16 * 1024);
|
||||
// Restore ILRAM
|
||||
memcpy(ilram, ilram_backup, 4 * 1024);
|
||||
}
|
||||
|
||||
void runPowerOffSafe(void (*powerOffSafeFunction)(), bool prepareVRAM) {
|
||||
gint_world_switch(GINT_CALL(worldSwitchHandler, powerOffSafeFunction, prepareVRAM));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
20
ion/src/simulator/fxcg/main.h
Normal file
20
ion/src/simulator/fxcg/main.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef ION_SIMULATOR_MAIN_H
|
||||
#define ION_SIMULATOR_MAIN_H
|
||||
|
||||
namespace Ion {
|
||||
namespace Simulator {
|
||||
namespace Main {
|
||||
|
||||
void init();
|
||||
void quit();
|
||||
|
||||
void setNeedsRefresh();
|
||||
void refresh();
|
||||
|
||||
void runPowerOffSafe(void (*powerOffSafeFunction)(), bool prepareVRAM);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
97
ion/src/simulator/fxcg/menuHandler.cpp
Normal file
97
ion/src/simulator/fxcg/menuHandler.cpp
Normal file
@@ -0,0 +1,97 @@
|
||||
#include "main.h"
|
||||
|
||||
namespace Ion {
|
||||
namespace Simulator {
|
||||
namespace FXCGMenuHandler {
|
||||
|
||||
int saveAndOpenMainMenu(void) {
|
||||
int addr;
|
||||
|
||||
// get the address of the syscall table in it
|
||||
addr = *(unsigned int *)0x8002007C;
|
||||
|
||||
if (addr < (int)0x80020070)
|
||||
return 1;
|
||||
if (addr >= (int)0x81000000)
|
||||
return 1;
|
||||
|
||||
// get the pointer to syscall 1E58 - SwitchToMainMenu
|
||||
addr += 0x1E58 * 4;
|
||||
if (addr < (int)0x80020070)
|
||||
return 1;
|
||||
if (addr >= (int)0x81000000)
|
||||
return 1;
|
||||
|
||||
addr = *(unsigned int *)addr;
|
||||
if (addr < (int)0x80020070)
|
||||
return 1;
|
||||
if (addr >= (int)0x81000000)
|
||||
return 1;
|
||||
|
||||
// Now addr has the address of the first operation in %1e58
|
||||
|
||||
// Run up to 150 times (300/2). OS 3.60's is 59 instructions, so this should
|
||||
// be plenty, but will let it stop if nothing is found
|
||||
for (unsigned short *currentAddr = (unsigned short *)addr;
|
||||
(unsigned int)currentAddr < ((unsigned int)addr + 300); currentAddr++) {
|
||||
// MOV.L GetkeyToMainFunctionReturn Flag, r14
|
||||
if (*(unsigned char *)currentAddr != 0xDE)
|
||||
continue;
|
||||
|
||||
// MOV #3, 2
|
||||
if (*(currentAddr + 1) != 0xE203)
|
||||
continue;
|
||||
|
||||
// BSR <SaveAndOpenMainMenu>
|
||||
if ((*(unsigned char *)(currentAddr + 2) & 0xF0) != 0xB0)
|
||||
continue;
|
||||
|
||||
// MOV.B r2, @r14
|
||||
if (*(currentAddr + 3) != 0x2E20)
|
||||
continue;
|
||||
|
||||
// BRA <some addr>
|
||||
if ((*(unsigned char *)(currentAddr + 4) & 0xF0) != 0xA0)
|
||||
continue;
|
||||
|
||||
// NOP
|
||||
if (*(currentAddr + 5) != 0x0009)
|
||||
continue;
|
||||
|
||||
unsigned short branchInstruction = *(currentAddr + 2);
|
||||
|
||||
// Clear first 4 bits (BSR identifier)
|
||||
branchInstruction <<= 4;
|
||||
branchInstruction >>= 4;
|
||||
|
||||
// branchInstruction is now the displacement of BSR
|
||||
|
||||
// Create typedef so we can cast the pointer
|
||||
typedef void (*voidFunc)(void);
|
||||
|
||||
// JMP to disp*2 + PC + 4
|
||||
((voidFunc)((unsigned int)branchInstruction * 2 +
|
||||
(unsigned int)currentAddr + 4 + 4))();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
extern "C" void gint_osmenu_native(void);
|
||||
|
||||
void openMenuWrapper(void) {
|
||||
if (saveAndOpenMainMenu() != 0) {
|
||||
// Fallback
|
||||
gint_osmenu_native();
|
||||
}
|
||||
}
|
||||
|
||||
void openMenu(void) {
|
||||
Simulator::Main::runPowerOffSafe(openMenuWrapper, true);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
14
ion/src/simulator/fxcg/menuHandler.h
Normal file
14
ion/src/simulator/fxcg/menuHandler.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef ION_SIMULATOR_MENUHANDLER_H
|
||||
#define ION_SIMULATOR_MENUHANDLER_H
|
||||
|
||||
namespace Ion {
|
||||
namespace Simulator {
|
||||
namespace FXCGMenuHandler {
|
||||
|
||||
void openMenu(void);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
23
ion/src/simulator/fxcg/platform.h
Normal file
23
ion/src/simulator/fxcg/platform.h
Normal file
@@ -0,0 +1,23 @@
|
||||
#ifndef ION_SIMULATOR_PLATFORM_H
|
||||
#define ION_SIMULATOR_PLATFORM_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Those functions should be implemented per-platform.
|
||||
* They are defined as C function for easier interop. */
|
||||
|
||||
const char * IonSimulatorGetLanguageCode();
|
||||
|
||||
void IonSimulatorKeyboardKeyDown(int keyNumber);
|
||||
void IonSimulatorKeyboardKeyUp(int keyNumber);
|
||||
void IonSimulatorEventsPushEvent(int eventNumber);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
42
ion/src/simulator/fxcg/power.cpp
Normal file
42
ion/src/simulator/fxcg/power.cpp
Normal file
@@ -0,0 +1,42 @@
|
||||
#include <ion/power.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "main.h"
|
||||
|
||||
#include <gint/gint.h>
|
||||
#include <gint/display.h>
|
||||
|
||||
void PowerOff(int displayLogo) {
|
||||
__asm__ __volatile__ (
|
||||
".align 2 \n\t"
|
||||
"mov.l 2f, r2 \n\t"
|
||||
"mov.l 1f, r0 \n\t"
|
||||
"jmp @r2 \n\t"
|
||||
"nop \n\t"
|
||||
".align 2 \n\t"
|
||||
"1: \n\t"
|
||||
".long 0x1839 \n\t"
|
||||
".align 4 \n\t"
|
||||
"2: \n\t"
|
||||
".long 0x80020070 \n\t"
|
||||
);
|
||||
}
|
||||
|
||||
void powerOff(void) {
|
||||
PowerOff(1);
|
||||
}
|
||||
|
||||
namespace Ion {
|
||||
namespace Power {
|
||||
|
||||
void suspend(bool checkIfOnOffKeyReleased) {
|
||||
Simulator::Main::runPowerOffSafe(powerOff, true);
|
||||
}
|
||||
|
||||
void standby() {
|
||||
Simulator::Main::runPowerOffSafe(powerOff, true);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
15
ion/src/simulator/fxcg/telemetry_init.cpp
Normal file
15
ion/src/simulator/fxcg/telemetry_init.cpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#include "platform.h"
|
||||
|
||||
namespace Ion {
|
||||
namespace Simulator {
|
||||
namespace Telemetry {
|
||||
|
||||
void init() {
|
||||
}
|
||||
|
||||
void shutdown() {
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
27
ion/src/simulator/fxcg/timing.cpp
Normal file
27
ion/src/simulator/fxcg/timing.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
#include <ion/timing.h>
|
||||
#include "main.h"
|
||||
#include <chrono>
|
||||
// #include <libndls.h>
|
||||
|
||||
#include <gint/clock.h>
|
||||
|
||||
static auto start = std::chrono::steady_clock::now();
|
||||
|
||||
namespace Ion {
|
||||
namespace Timing {
|
||||
|
||||
uint64_t millis() {
|
||||
auto elapsed = std::chrono::steady_clock::now() - start;
|
||||
return std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count();
|
||||
}
|
||||
|
||||
void usleep(uint32_t us) {
|
||||
sleep_us(us);
|
||||
}
|
||||
|
||||
void msleep(uint32_t ms) {
|
||||
sleep_us(ms * 1000);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
#define KANDINSKY_POSTPROCESS_GAMMA_CONTEXT_H
|
||||
|
||||
#include <kandinsky/postprocess_context.h>
|
||||
#include <stdint.h>
|
||||
|
||||
class KDPostProcessGammaContext : public KDPostProcessContext {
|
||||
public:
|
||||
@@ -13,7 +14,16 @@ private:
|
||||
void pushRect(KDRect rect, const KDColor * pixels) override;
|
||||
void pushRectUniform(KDRect rect, KDColor color) override;
|
||||
void pullRect(KDRect rect, KDColor * pixels) override;
|
||||
KDColor correctColor(KDColor color);
|
||||
int m_redGamma, m_greenGamma, m_blueGamma;
|
||||
// Lookup tables to do gamma correction
|
||||
// 5 bits of red
|
||||
uint8_t m_redGammaTable[32];
|
||||
// 6 bits of green
|
||||
uint8_t m_greenGammaTable[64];
|
||||
// 5 bits of blue
|
||||
uint8_t m_blueGammaTable[32];
|
||||
void updateGammaTables();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include <kandinsky/color.h>
|
||||
#include <kandinsky/postprocess_gamma_context.h>
|
||||
#include <ion.h>
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
|
||||
constexpr int MaxGammaStates = 7;
|
||||
constexpr float MaxGammaGamut = 0.75;
|
||||
@@ -13,8 +15,28 @@ constexpr int clampGamma(int gamma) {
|
||||
return gamma < -MaxGammaStates ? -MaxGammaStates : (gamma > MaxGammaStates ? MaxGammaStates : gamma);
|
||||
}
|
||||
|
||||
void KDPostProcessGammaContext::updateGammaTables() {
|
||||
const float redGamma = toGamma(m_redGamma);
|
||||
const float greenGamma = toGamma(m_greenGamma);
|
||||
const float blueGamma = toGamma(m_blueGamma);
|
||||
for (int i = 0; i < 32; i++) {
|
||||
uint8_t r = (uint8_t)(powf((i << 3) / 255.f, redGamma) * 255);
|
||||
m_redGammaTable[i] = r >> 3;
|
||||
}
|
||||
for (int i = 0; i < 64; i++) {
|
||||
uint8_t g = (uint8_t)(powf((i << 2) / 255.f, greenGamma) * 255);
|
||||
m_greenGammaTable[i] = g >> 2;
|
||||
}
|
||||
for (int i = 0; i < 32; i++) {
|
||||
uint8_t b = (uint8_t)(powf((i << 3 )/ 255.f, blueGamma) * 255);
|
||||
m_blueGammaTable[i] = b >> 3;
|
||||
}
|
||||
}
|
||||
|
||||
KDPostProcessGammaContext::KDPostProcessGammaContext() :
|
||||
m_redGamma(0), m_greenGamma(0), m_blueGamma(0) {}
|
||||
m_redGamma(0), m_greenGamma(0), m_blueGamma(0) {
|
||||
updateGammaTables();
|
||||
}
|
||||
|
||||
void KDPostProcessGammaContext::gamma(int& red, int& green, int& blue) {
|
||||
red = m_redGamma;
|
||||
@@ -32,12 +54,20 @@ void KDPostProcessGammaContext::setGamma(int red, int green, int blue) {
|
||||
m_redGamma = clampGamma(red);
|
||||
m_greenGamma = clampGamma(green);
|
||||
m_blueGamma = clampGamma(blue);
|
||||
updateGammaTables();
|
||||
}
|
||||
|
||||
KDColor KDPostProcessGammaContext::correctColor(KDColor color) {
|
||||
uint8_t r5 = (((uint16_t )color)>>11)&0x1F;
|
||||
r5 = m_redGammaTable[r5];
|
||||
uint8_t g6 = (((uint16_t )color)>>5)&0x3F;
|
||||
g6 = m_greenGammaTable[g6];
|
||||
uint8_t b5 = ((uint16_t )color)&0x1F;
|
||||
b5 = m_blueGammaTable[b5];
|
||||
return KDColor::RGB16(r5<<11 | g6<<5 | b5);
|
||||
}
|
||||
|
||||
void KDPostProcessGammaContext::pushRect(KDRect rect, const KDColor * pixels) {
|
||||
const float redGamma = toGamma(m_redGamma);
|
||||
const float greenGamma = toGamma(m_greenGamma);
|
||||
const float blueGamma = toGamma(m_blueGamma);
|
||||
KDColor workingBuffer[rect.width()];
|
||||
|
||||
for (KDCoordinate y = 0; y < rect.height(); y++) {
|
||||
@@ -45,10 +75,7 @@ void KDPostProcessGammaContext::pushRect(KDRect rect, const KDColor * pixels) {
|
||||
|
||||
for (KDCoordinate x = 0; x < rect.width(); x++) {
|
||||
const KDColor color = pixels[y*rect.width()+x];
|
||||
const KDColor result = KDColor::RGB888(
|
||||
(uint8_t)(powf(color.red()/255.f, redGamma)*255),
|
||||
(uint8_t)(powf(color.green()/255.f, greenGamma)*255),
|
||||
(uint8_t)(powf(color.blue()/255.f, blueGamma)*255));
|
||||
const KDColor result = correctColor(color);
|
||||
workingBuffer[x] = result;
|
||||
}
|
||||
KDPostProcessContext::pushRect(workingRect, workingBuffer);
|
||||
@@ -56,15 +83,7 @@ void KDPostProcessGammaContext::pushRect(KDRect rect, const KDColor * pixels) {
|
||||
}
|
||||
|
||||
void KDPostProcessGammaContext::pushRectUniform(KDRect rect, KDColor color) {
|
||||
const float redGamma = toGamma(m_redGamma);
|
||||
const float greenGamma = toGamma(m_greenGamma);
|
||||
const float blueGamma = toGamma(m_blueGamma);
|
||||
const KDColor result = KDColor::RGB888(
|
||||
(uint8_t)(powf(color.red()/255.f, redGamma)*255),
|
||||
(uint8_t)(powf(color.green()/255.f, greenGamma)*255),
|
||||
(uint8_t)(powf(color.blue()/255.f, blueGamma)*255));
|
||||
|
||||
KDPostProcessContext::pushRectUniform(rect, result);
|
||||
KDPostProcessContext::pushRectUniform(rect, correctColor(color));
|
||||
}
|
||||
|
||||
void KDPostProcessGammaContext::pullRect(KDRect rect, KDColor * pixels) {
|
||||
|
||||
20
liba/include/bridge/math.h
Normal file
20
liba/include/bridge/math.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef LIBA_BRIDGE_MATH_H
|
||||
#define LIBA_BRIDGE_MATH_H
|
||||
|
||||
#include_next <math.h>
|
||||
|
||||
#define M_E 2.7182818284590452354 /* e */
|
||||
#define M_LOG2E 1.4426950408889634074 /* log 2e */
|
||||
#define M_LOG10E 0.43429448190325182765 /* log 10e */
|
||||
#define M_LN2 0.69314718055994530942 /* log e2 */
|
||||
#define M_LN10 2.30258509299404568402 /* log e10 */
|
||||
#define M_PI 3.14159265358979323846 /* pi */
|
||||
#define M_PI_2 1.57079632679489661923 /* pi/2 */
|
||||
#define M_PI_4 0.78539816339744830962 /* pi/4 */
|
||||
#define M_1_PI 0.31830988618379067154 /* 1/pi */
|
||||
#define M_2_PI 0.63661977236758134308 /* 2/pi */
|
||||
#define M_2_SQRTPI 1.12837916709551257390 /* 2/sqrt(pi) */
|
||||
#define M_SQRT2 1.41421356237309504880 /* sqrt(2) */
|
||||
#define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */
|
||||
|
||||
#endif
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
LIBA_BEGIN_DECLS
|
||||
|
||||
#if (__GLIBC__ || __MINGW32__)
|
||||
#if (__GLIBC__ || __MINGW32__ || _FXCG)
|
||||
size_t strlcat(char * dst, const char * src, size_t dstSize);
|
||||
size_t strlcpy(char * dst, const char * src, size_t len);
|
||||
#endif
|
||||
|
||||
22
liba/include/bridge/strings.h
Normal file
22
liba/include/bridge/strings.h
Normal file
@@ -0,0 +1,22 @@
|
||||
#ifndef LIBA_STRINGS_H
|
||||
#define LIBA_STRINGS_H
|
||||
|
||||
#if (_FXCG)
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "../private/macros.h"
|
||||
|
||||
LIBA_BEGIN_DECLS
|
||||
|
||||
void bzero(void * s, size_t n);
|
||||
|
||||
LIBA_END_DECLS
|
||||
|
||||
#else
|
||||
|
||||
#include_next <strings.h>
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
3
libaxx/Makefile.bridge
Normal file
3
libaxx/Makefile.bridge
Normal file
@@ -0,0 +1,3 @@
|
||||
SFLAGS += -Ilibaxx/include/bridge
|
||||
|
||||
# libaxx_src += libaxx/src/bridge.c
|
||||
165
libaxx/include/bridge/cmath
Normal file
165
libaxx/include/bridge/cmath
Normal file
@@ -0,0 +1,165 @@
|
||||
#ifndef LIBA_BRIDGE_CMATH_H
|
||||
#define LIBA_BRIDGE_CMATH_H
|
||||
|
||||
#include_next <cmath>
|
||||
|
||||
#define M_E 2.7182818284590452354 /* e */
|
||||
#define M_LOG2E 1.4426950408889634074 /* log 2e */
|
||||
#define M_LOG10E 0.43429448190325182765 /* log 10e */
|
||||
#define M_LN2 0.69314718055994530942 /* log e2 */
|
||||
#define M_LN10 2.30258509299404568402 /* log e10 */
|
||||
#define M_PI 3.14159265358979323846 /* pi */
|
||||
#define M_PI_2 1.57079632679489661923 /* pi/2 */
|
||||
#define M_PI_4 0.78539816339744830962 /* pi/4 */
|
||||
#define M_1_PI 0.31830988618379067154 /* 1/pi */
|
||||
#define M_2_PI 0.63661977236758134308 /* 2/pi */
|
||||
#define M_2_SQRTPI 1.12837916709551257390 /* 2/sqrt(pi) */
|
||||
#define M_SQRT2 1.41421356237309504880 /* sqrt(2) */
|
||||
#define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */
|
||||
|
||||
#if (_FXCG)
|
||||
namespace std {
|
||||
// functions
|
||||
using ::acosh;
|
||||
using ::acoshf;
|
||||
using ::acoshl;
|
||||
|
||||
using ::asinh;
|
||||
using ::asinhf;
|
||||
using ::asinhl;
|
||||
|
||||
using ::atanh;
|
||||
using ::atanhf;
|
||||
using ::atanhl;
|
||||
|
||||
using ::cbrt;
|
||||
using ::cbrtf;
|
||||
using ::cbrtl;
|
||||
|
||||
using ::copysign;
|
||||
using ::copysignf;
|
||||
using ::copysignl;
|
||||
|
||||
using ::erf;
|
||||
using ::erff;
|
||||
using ::erfl;
|
||||
|
||||
using ::erfc;
|
||||
using ::erfcf;
|
||||
using ::erfcl;
|
||||
|
||||
using ::exp2;
|
||||
using ::exp2f;
|
||||
using ::exp2l;
|
||||
|
||||
using ::expm1;
|
||||
using ::expm1f;
|
||||
using ::expm1l;
|
||||
|
||||
using ::fdim;
|
||||
using ::fdimf;
|
||||
using ::fdiml;
|
||||
|
||||
using ::fma;
|
||||
using ::fmaf;
|
||||
using ::fmal;
|
||||
|
||||
using ::fmax;
|
||||
using ::fmaxf;
|
||||
using ::fmaxl;
|
||||
|
||||
using ::fmin;
|
||||
using ::fminf;
|
||||
using ::fminl;
|
||||
|
||||
using ::hypot;
|
||||
using ::hypotf;
|
||||
using ::hypotl;
|
||||
|
||||
using ::ilogb;
|
||||
using ::ilogbf;
|
||||
using ::ilogbl;
|
||||
|
||||
using ::lgamma;
|
||||
using ::lgammaf;
|
||||
using ::lgammal;
|
||||
|
||||
using ::llrint;
|
||||
using ::llrintf;
|
||||
using ::llrintl;
|
||||
|
||||
using ::llround;
|
||||
using ::llroundf;
|
||||
using ::llroundl;
|
||||
|
||||
using ::log1p;
|
||||
using ::log1pf;
|
||||
using ::log1pl;
|
||||
|
||||
using ::log2;
|
||||
using ::log2f;
|
||||
using ::log2l;
|
||||
|
||||
using ::logb;
|
||||
using ::logbf;
|
||||
using ::logbl;
|
||||
|
||||
using ::lrint;
|
||||
using ::lrintf;
|
||||
using ::lrintl;
|
||||
|
||||
using ::lround;
|
||||
using ::lroundf;
|
||||
using ::lroundl;
|
||||
|
||||
using ::nan;
|
||||
using ::nanf;
|
||||
using ::nanl;
|
||||
|
||||
using ::nearbyint;
|
||||
using ::nearbyintf;
|
||||
using ::nearbyintl;
|
||||
|
||||
using ::nextafter;
|
||||
using ::nextafterf;
|
||||
using ::nextafterl;
|
||||
|
||||
using ::nexttoward;
|
||||
using ::nexttowardf;
|
||||
using ::nexttowardl;
|
||||
|
||||
using ::remainder;
|
||||
using ::remainderf;
|
||||
using ::remainderl;
|
||||
|
||||
using ::remquo;
|
||||
using ::remquof;
|
||||
using ::remquol;
|
||||
|
||||
using ::rint;
|
||||
using ::rintf;
|
||||
using ::rintl;
|
||||
|
||||
using ::round;
|
||||
using ::roundf;
|
||||
using ::roundl;
|
||||
|
||||
using ::scalbln;
|
||||
using ::scalblnf;
|
||||
using ::scalblnl;
|
||||
|
||||
using ::scalbn;
|
||||
using ::scalbnf;
|
||||
using ::scalbnl;
|
||||
|
||||
using ::tgamma;
|
||||
using ::tgammaf;
|
||||
using ::tgammal;
|
||||
|
||||
using ::trunc;
|
||||
using ::truncf;
|
||||
using ::truncl;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -4,7 +4,9 @@
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <cmath>
|
||||
#include <type_traits>
|
||||
|
||||
namespace Poincare {
|
||||
|
||||
@@ -41,11 +43,19 @@ public:
|
||||
if (((uint64_t)mantissa >> (size()-k_mantissaNbBits-2)) & 1) {
|
||||
u.ui += 1;
|
||||
}
|
||||
return u.f;
|
||||
if (sizeof(T) == sizeof(float)) {
|
||||
return u.f32.f;
|
||||
} else {
|
||||
return u.f64.f;
|
||||
}
|
||||
}
|
||||
static int exponent(T f) {
|
||||
uint_float u;
|
||||
u.f = f;
|
||||
if (sizeof(T) == sizeof(float)) {
|
||||
u.f32.f = f;
|
||||
} else {
|
||||
u.f64.f = f;
|
||||
}
|
||||
constexpr uint16_t oneOnExponentsBits = maxExponent();
|
||||
int exp = (u.ui >> k_mantissaNbBits) & oneOnExponentsBits;
|
||||
exp -= exponentOffset();
|
||||
@@ -75,10 +85,28 @@ public:
|
||||
}
|
||||
|
||||
private:
|
||||
#ifdef _BIG_ENDIAN
|
||||
union uint_float {
|
||||
uint64_t ui;
|
||||
T f;
|
||||
struct {
|
||||
uint32_t padding;
|
||||
float f;
|
||||
} f32;
|
||||
struct {
|
||||
double f;
|
||||
} f64;
|
||||
};
|
||||
#else
|
||||
union uint_float {
|
||||
uint64_t ui;
|
||||
struct {
|
||||
float f;
|
||||
} f32;
|
||||
struct {
|
||||
double f;
|
||||
} f64;
|
||||
};
|
||||
#endif
|
||||
|
||||
constexpr static size_t k_signNbBits = 1;
|
||||
constexpr static size_t k_exponentNbBits = sizeof(T) == sizeof(float) ? 8 : 11;
|
||||
|
||||
@@ -5,6 +5,14 @@
|
||||
#include <assert.h>
|
||||
#include <poincare/horizontal_layout.h>
|
||||
|
||||
#ifdef _FXCG
|
||||
#include <gint/display.h>
|
||||
#include <gint/keyboard.h>
|
||||
#include <stdio.h>
|
||||
#else
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
namespace Poincare {
|
||||
|
||||
class ExpressionLayout;
|
||||
@@ -13,12 +21,17 @@ class LayoutNode;
|
||||
class Integer;
|
||||
struct IntegerDivision;
|
||||
|
||||
#ifdef _3DS
|
||||
#if (defined _3DS) || (defined _FXCG)
|
||||
typedef unsigned short half_native_uint_t;
|
||||
static_assert(sizeof(half_native_uint_t) == sizeof(uint16_t));
|
||||
typedef int native_int_t;
|
||||
static_assert(sizeof(native_int_t) == sizeof(int32_t));
|
||||
typedef long long int double_native_int_t;
|
||||
static_assert(sizeof(double_native_int_t) == sizeof(int64_t));
|
||||
typedef unsigned int native_uint_t;
|
||||
static_assert(sizeof(native_uint_t) == sizeof(uint32_t));
|
||||
typedef unsigned long long int double_native_uint_t;
|
||||
static_assert(sizeof(double_native_uint_t) == sizeof(uint64_t));
|
||||
#else
|
||||
typedef uint16_t half_native_uint_t;
|
||||
typedef int32_t native_int_t;
|
||||
@@ -199,7 +212,12 @@ private:
|
||||
if (i >= numberOfHalfDigits()) {
|
||||
return 0;
|
||||
}
|
||||
return (usesImmediateDigit() ? ((half_native_uint_t *)&m_digit)[i] : ((half_native_uint_t *)digits())[i]);
|
||||
native_uint_t d = usesImmediateDigit() ? m_digit : digits()[i/2];
|
||||
if (i % 2 == 0) {
|
||||
return d & 0xFFFF;
|
||||
} else {
|
||||
return d >> 16;
|
||||
}
|
||||
}
|
||||
|
||||
native_uint_t digit(uint8_t i) const {
|
||||
|
||||
@@ -138,7 +138,7 @@ private:
|
||||
private:
|
||||
uint16_t m_currentIndex;
|
||||
uint16_t m_availableIdentifiers[MaxNumberOfNodes];
|
||||
static_assert(MaxNumberOfNodes < INT16_MAX && sizeof(m_availableIdentifiers[0] == sizeof(uint16_t)), "Tree node identifiers do not have the right data size.");
|
||||
static_assert(MaxNumberOfNodes < INT16_MAX && sizeof(m_availableIdentifiers[0]) == sizeof(uint16_t), "Tree node identifiers do not have the right data size.");
|
||||
};
|
||||
|
||||
void freePoolFromNode(TreeNode * firstNodeToDiscard);
|
||||
|
||||
@@ -127,7 +127,10 @@ Integer::Integer(native_int_t i) : TreeHandle(TreeNode::NoNodeIdentifier) {
|
||||
|
||||
Integer::Integer(double_native_int_t i) {
|
||||
double_native_uint_t j = i < 0 ? -i : i;
|
||||
native_uint_t * d = (native_uint_t *)&j;
|
||||
native_uint_t d[2] = {
|
||||
static_cast<native_uint_t>(j & 0xFFFFFFFF),
|
||||
static_cast<native_uint_t>(j >> 32)
|
||||
};
|
||||
native_uint_t leastSignificantDigit = *d;
|
||||
native_uint_t mostSignificantDigit = *(d+1);
|
||||
uint8_t numberOfDigits = (mostSignificantDigit == 0) ? 1 : 2;
|
||||
@@ -165,7 +168,8 @@ Integer::Integer(const char * digits, size_t length, bool negative, Base b) :
|
||||
Integer base((int)b);
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
*this = Multiplication(*this, base);
|
||||
*this = Addition(*this, Integer(integerFromCharDigit(*digits)));
|
||||
Integer toAdd = Integer(integerFromCharDigit(*digits));
|
||||
*this = Addition(*this, toAdd);
|
||||
digits++;
|
||||
}
|
||||
}
|
||||
@@ -495,7 +499,10 @@ Integer Integer::multiplication(const Integer & a, const Integer & b, bool oneDi
|
||||
* otherwise the product might end up being computed on single_native size
|
||||
* and then zero-padded. */
|
||||
double_native_uint_t p = aDigit*bDigit + carry + (double_native_uint_t)(s_workingBuffer[i+j]); // TODO: Prove it cannot overflow double_native type
|
||||
native_uint_t * l = (native_uint_t *)&p;
|
||||
native_uint_t l[2] = {
|
||||
static_cast<native_uint_t>(p & 0xFFFFFFFF),
|
||||
static_cast<native_uint_t>(p >> 32)
|
||||
};
|
||||
if (i+j < (uint8_t) k_maxNumberOfDigits+oneDigitOverflow) {
|
||||
s_workingBuffer[i+j] = l[0];
|
||||
} else {
|
||||
@@ -605,18 +612,31 @@ Integer Integer::divideByPowerOf2(uint8_t pow) const {
|
||||
// return this*(2^16)^pow
|
||||
Integer Integer::multiplyByPowerOfBase(uint8_t pow) const {
|
||||
int nbOfHalfDigits = numberOfHalfDigits();
|
||||
half_native_uint_t * digits = reinterpret_cast<half_native_uint_t *>(s_workingBuffer);
|
||||
native_uint_t * digits = s_workingBuffer;
|
||||
/* The number of half digits of the built integer is nbOfHalfDigits+pow.
|
||||
* Still, we set an extra half digit to 0 to easily convert half digits to
|
||||
* digits. */
|
||||
memset(digits, 0, sizeof(half_native_uint_t)*(nbOfHalfDigits+pow+1));
|
||||
for (uint8_t i = 0; i < nbOfHalfDigits; i++) {
|
||||
digits[i+pow] = halfDigit(i);
|
||||
memset(digits, 0, (sizeof(native_uint_t)/2)*(nbOfHalfDigits+pow+1));
|
||||
for (uint8_t i = 0; i < nbOfHalfDigits; i += 2) {
|
||||
native_uint_t toSet = halfDigit(i);
|
||||
if (i+1 < nbOfHalfDigits) {
|
||||
toSet |= (native_uint_t)halfDigit(i+1) << 16;
|
||||
}
|
||||
int index = i+pow;
|
||||
// If it's on an even index, we can just set the value
|
||||
if (index % 2 == 0) {
|
||||
digits[index/2] = toSet;
|
||||
} else {
|
||||
// If it's on an odd index, we need to shift the value
|
||||
digits[index/2] |= toSet << 16;
|
||||
digits[index/2+1] |= toSet >> 16;
|
||||
}
|
||||
}
|
||||
nbOfHalfDigits += pow;
|
||||
return BuildInteger((native_uint_t *)digits, nbOfHalfDigits%2 == 1 ? nbOfHalfDigits/2+1 : nbOfHalfDigits/2, false, true);
|
||||
return BuildInteger(digits, nbOfHalfDigits%2 == 1 ? nbOfHalfDigits/2+1 : nbOfHalfDigits/2, false, true);
|
||||
}
|
||||
|
||||
|
||||
IntegerDivision Integer::udiv(const Integer & numerator, const Integer & denominator) {
|
||||
if (denominator.isOverflow()) {
|
||||
return {.quotient = Overflow(false), .remainder = Integer::Overflow(false)};
|
||||
@@ -679,6 +699,14 @@ IntegerDivision Integer::udiv(const Integer & numerator, const Integer & denomin
|
||||
qNumberOfDigits--;
|
||||
}
|
||||
int qNumberOfDigitsInBase32 = qNumberOfDigits%2 == 1 ? qNumberOfDigits/2+1 : qNumberOfDigits/2;
|
||||
// Swap each pair of digits in qDigits if on a big-endian architecture
|
||||
#ifdef _BIG_ENDIAN
|
||||
for (int i = 0; i < qNumberOfDigitsInBase32; i++) {
|
||||
half_native_uint_t tmp = qDigits[i*2];
|
||||
qDigits[i*2] = qDigits[i*2+1];
|
||||
qDigits[i*2+1] = tmp;
|
||||
}
|
||||
#endif
|
||||
IntegerDivision div = {.quotient = BuildInteger((native_uint_t *)qDigits, qNumberOfDigitsInBase32, false), .remainder = A};
|
||||
if (pow > 0 && !div.remainder.isZero()) {
|
||||
div.remainder = div.remainder.divideByPowerOf2(pow);
|
||||
|
||||
Reference in New Issue
Block a user