├── .github └── workflows │ ├── in-game-tests.yml │ └── rust-tests.yml ├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── app ├── doom3d │ ├── .cargo │ │ └── config.toml │ ├── .vimspector.json │ ├── Cargo.lock │ ├── Cargo.toml │ ├── build.rs │ ├── copy-bin.sh │ └── src │ │ ├── main.rs │ │ ├── maps.rs │ │ └── raycaster.rs ├── game-of-life │ ├── .cargo │ │ └── config.toml │ ├── .vimspector.json │ ├── Cargo.lock │ ├── Cargo.toml │ ├── copy-bin.sh │ └── src │ │ └── main.rs ├── pong │ ├── .cargo │ │ └── config.toml │ ├── .vimspector.json │ ├── Cargo.lock │ ├── Cargo.toml │ ├── copy-bin.sh │ └── src │ │ └── main.rs ├── tdriver │ ├── .cargo │ │ └── config.toml │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ ├── build.rs │ ├── link.x │ ├── rust-analyzer.toml │ └── src │ │ ├── graphics.rs │ │ └── lib.rs ├── template │ ├── .cargo │ │ └── config.toml │ ├── .vimspector.json │ ├── Cargo.lock │ ├── Cargo.toml │ ├── README.md │ ├── copy-bin.sh │ └── src │ │ └── main.rs ├── tetris │ ├── .cargo │ │ └── config.toml │ ├── .vimspector.json │ ├── Cargo.lock │ ├── Cargo.toml │ ├── copy-bin.sh │ └── src │ │ ├── main.rs │ │ └── tiles.rs └── video │ ├── .cargo │ └── config.toml │ ├── .vimspector.json │ ├── Cargo.lock │ ├── Cargo.toml │ ├── assets │ └── bad-apple.mp4 │ ├── build.py │ ├── copy-bin.sh │ └── src │ ├── main.rs │ └── video.rs ├── computerraria.tar.gz ├── computerraria.twld ├── copy-world.sh ├── doc ├── img │ ├── control-panel.png │ ├── logo-old.png │ ├── logo.png │ ├── pong-still.png │ └── poster-small.png ├── logo-old.pixil ├── logo.pixil ├── notes.txt ├── old-worlds │ ├── blank.wld │ └── computer.wld ├── reference │ └── computer-old.wld └── riscv.pdf ├── docker ├── Dockerfile ├── build.sh ├── push.sh ├── run.sh └── tModLoader.targets ├── run-tests.sh ├── test ├── .gitignore ├── computerraria │ ├── computerraria_isa.yaml │ ├── computerraria_platform.yaml │ ├── env │ │ ├── link.ld │ │ └── model_test.h │ └── riscof_computerraria.py ├── config.ini ├── manual │ ├── inf.s │ ├── inf.txt │ ├── loop.s │ └── loop.txt └── sail_cSim │ ├── __init__.py │ ├── env │ ├── link.ld │ └── model_test.h │ └── riscof_sail_cSim.py └── tinterface ├── bin └── tcli ├── setup.py └── tinterface └── __init__.py /.github/workflows/in-game-tests.yml: -------------------------------------------------------------------------------- 1 | name: Compliance Tests 2 | run-name: Compliance Tests 3 | on: 4 | push: 5 | paths: 6 | - 'computer.wld' 7 | - 'test/**' 8 | - 'tinterface/**' 9 | branches: 10 | - main 11 | repository_dispatch: 12 | workflow_dispatch: 13 | 14 | jobs: 15 | riscof: 16 | name: RISCV Compliance Tests 17 | runs-on: ubuntu-latest 18 | container: misprit7/computerraria:latest 19 | steps: 20 | - name: Compile WireHead 21 | run: | 22 | cd /root/.local/share/Terraria/tModLoader/ModSources &&\ 23 | git clone https://github.com/misprit7/WireHead.git &&\ 24 | cd WireHead &&\ 25 | dotnet build 26 | 27 | - name: Checkout computerraria 28 | uses: actions/checkout@v3 29 | with: 30 | submodules: recursive 31 | 32 | - name: Install tinterface 33 | run: pip3 install --break-system-packages -e ./tinterface 34 | 35 | - name: Run riscof tests 36 | run: ./run-tests.sh 37 | 38 | - name: Upload results 39 | if: always() 40 | uses: actions/upload-artifact@v3 41 | with: 42 | name: Result summary 43 | path: | 44 | ./test/riscof_work/ 45 | 46 | -------------------------------------------------------------------------------- /.github/workflows/rust-tests.yml: -------------------------------------------------------------------------------- 1 | name: Rust Apps 2 | run-name: Rust Apps 3 | on: 4 | push: 5 | paths: 6 | - 'app/**' 7 | branches: 8 | - main 9 | workflow_dispatch: 10 | 11 | env: 12 | CARGO_TERM_COLOR: always 13 | 14 | jobs: 15 | Build: 16 | 17 | runs-on: ubuntu-latest 18 | 19 | steps: 20 | - name: Checkout computerraria 21 | uses: actions/checkout@v3 22 | 23 | - name: Build 24 | run: | 25 | rustup target add riscv32i-unknown-none-elf 26 | for i in app/* ; do 27 | if [ -d "$i" ]; then 28 | echo "::group::$i" 29 | cargo build --verbose --manifest-path="$i/Cargo.toml" 30 | cargo build --target=riscv32i-unknown-none-elf --verbose --manifest-path="$i/Cargo.toml" 31 | echo "::endgroup" 32 | fi 33 | done 34 | 35 | 36 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Computerraria's world is very large (~400mb) but compresses very well. Since it's binary anyways I compress it so it's not stored directly 2 | computerraria.wld 3 | 4 | # Terraria world backups 5 | *.twld.bak 6 | *.wld.bak 7 | *.wld.bak2 8 | 9 | # Me being dumb 10 | --to 11 | 12 | # Docker secrets 13 | docker/.env 14 | 15 | # Docker build artifact 16 | docker/riscv_sim_RV32 17 | 18 | # Byte-compiled / optimized / DLL files 19 | __pycache__/ 20 | *.py[cod] 21 | *$py.class 22 | 23 | # C extensions 24 | *.so 25 | 26 | # Distribution / packaging 27 | .Python 28 | build/ 29 | develop-eggs/ 30 | dist/ 31 | downloads/ 32 | eggs/ 33 | .eggs/ 34 | lib/ 35 | lib64/ 36 | parts/ 37 | sdist/ 38 | var/ 39 | wheels/ 40 | share/python-wheels/ 41 | *.egg-info/ 42 | .installed.cfg 43 | *.egg 44 | MANIFEST 45 | 46 | # PyInstaller 47 | # Usually these files are written by a python script from a template 48 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 49 | *.manifest 50 | *.spec 51 | 52 | # Installer logs 53 | pip-log.txt 54 | pip-delete-this-directory.txt 55 | 56 | # Unit test / coverage reports 57 | htmlcov/ 58 | .tox/ 59 | .nox/ 60 | .coverage 61 | .coverage.* 62 | .cache 63 | nosetests.xml 64 | coverage.xml 65 | *.cover 66 | *.py,cover 67 | .hypothesis/ 68 | .pytest_cache/ 69 | cover/ 70 | 71 | # Translations 72 | *.mo 73 | *.pot 74 | 75 | # Django stuff: 76 | *.log 77 | local_settings.py 78 | db.sqlite3 79 | db.sqlite3-journal 80 | 81 | # Flask stuff: 82 | instance/ 83 | .webassets-cache 84 | 85 | # Scrapy stuff: 86 | .scrapy 87 | 88 | # Sphinx documentation 89 | docs/_build/ 90 | 91 | # PyBuilder 92 | .pybuilder/ 93 | target/ 94 | 95 | # Jupyter Notebook 96 | .ipynb_checkpoints 97 | 98 | # IPython 99 | profile_default/ 100 | ipython_config.py 101 | 102 | # pyenv 103 | # For a library or package, you might want to ignore these files since the code is 104 | # intended to run in multiple environments; otherwise, check them in: 105 | # .python-version 106 | 107 | # pipenv 108 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 109 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 110 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 111 | # install all needed dependencies. 112 | #Pipfile.lock 113 | 114 | # poetry 115 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 116 | # This is especially recommended for binary packages to ensure reproducibility, and is more 117 | # commonly ignored for libraries. 118 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 119 | #poetry.lock 120 | 121 | # pdm 122 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 123 | #pdm.lock 124 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 125 | # in version control. 126 | # https://pdm.fming.dev/#use-with-ide 127 | .pdm.toml 128 | 129 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 130 | __pypackages__/ 131 | 132 | # Celery stuff 133 | celerybeat-schedule 134 | celerybeat.pid 135 | 136 | # SageMath parsed files 137 | *.sage.py 138 | 139 | # Environments 140 | .env 141 | .venv 142 | # env/ 143 | venv/ 144 | ENV/ 145 | env.bak/ 146 | venv.bak/ 147 | 148 | # Spyder project settings 149 | .spyderproject 150 | .spyproject 151 | 152 | # Rope project settings 153 | .ropeproject 154 | 155 | # mkdocs documentation 156 | /site 157 | 158 | # mypy 159 | .mypy_cache/ 160 | .dmypy.json 161 | dmypy.json 162 | 163 | # Pyre type checker 164 | .pyre/ 165 | 166 | # pytype static type analyzer 167 | .pytype/ 168 | 169 | # Cython debug symbols 170 | cython_debug/ 171 | 172 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "test/riscv-arch-test"] 2 | path = test/riscv-arch-test 3 | url = https://github.com/misprit7/riscv-arch-test-low-mem.git 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Xander Naumenko 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

2 | 3 |
4 | Computerraria 5 |

6 |

7 | A fully compliant RISC-V computer inside Terraria 8 |

9 |

10 | Video explanation: https://youtu.be/zXPiqk0-zDY 11 |

12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | # Pitch 23 | 24 | There are two fundamentally competing forces when it comes to computer speed. The first, and most famous, is Moore's law, where physical transistor densities scale exponentially. The second is the inevitable growth of software bloat that runs on top of increasingly modern processors. There's a kind of equilibrium between these two competing beasts, ensuring that a user always manages to get at least a split second of mindfulness while staring at a frozen screen whenever attempting to open the latest app. 25 | 26 | This project is an attempt to score a decisive rout in this ongoing battle in favor of the *programmer*. By emulating a complete rv32i instruction set inside the wiring system of [Terraria](https://www.terraria.org/), we push back speeds to the early 70s era, tossing the ball firmly back into the court of the silicon engineer without losing any software functionality. 27 | 28 | # Overview 29 | 30 |
31 | 32 | 33 | Click to see navigable image 34 | 35 |
36 | 37 | Despite what the pitch may lead one to believe the goal of this project is to maximize the compliance and processing ability of the in game cpu. This is only possible with the help of an accelerator mod, which maintains full compatibility with the vanilla wiring system but reimplements it in a much more efficient manner: 38 | 39 | [WireHead](https://github.com/misprit7/WireHead) - A wiring accelerator and headless control mod 40 | 41 | With this installed, the current specs of the computer are as follows: 42 | 43 | - Clock speed: ~5kHz 44 | - Ram: 96kb 45 | - Instruction set: rv32i 46 | 47 | As an example of what it can do, here is Pong, running purely on the in-game cpu (see [app/pong/src/main.rs](app/pong/src/main.rs) for implementation): 48 | 49 | https://user-images.githubusercontent.com/33139843/229342342-de4708e1-7467-4f99-834b-3d0fb28d0858.mp4 50 | 51 | # Setup 52 | 53 | Note that currently only Linux is fully supported, and only parts of this have been tested on Windows. However I've left some steps for anyone who wants to try getting Windows working, in theory using wsl it should be fairly straightforward and things should be identical. 54 | 55 | ## Prerequisites 56 | 57 | For a comprehensive list of everything that is needed to run all aspects of this project, see the [Dockerfile](docker/Dockerfile). However, to develop and run applications for the computer all you really need is a working Cargo/rustc installation, install it [here](https://www.rust-lang.org/tools/install) or through your package manager. 58 | 59 | ## Setup Process 60 | 61 | Navigate to where you want to keep this project and clone it. Copy computer.wld to your tModLoader world path. Depending on your platform, this is: 62 | ``` 63 | Windows: Documents\My Games\Terraria\ModLoader\Worlds 64 | Linux: ~/.local/share/Terraria/tModLoader/Worlds 65 | ``` 66 | On Linux you can automate copying back and forth like this with the `copy-world.sh` script with either the `--to` (copy to world folder) or `--from` (copy from world folder) flags. 67 | 68 | Next, navigate to the mod sources folder and clone [WireHead](https://github.com/misprit7/WireHead): 69 | ``` 70 | #Windows 71 | cd "%userprofile%\Documents\My Games\Terraria\ModLoader\ModSources" && git clone https://github.com/misprit7/WireHead.git 72 | 73 | #Linux 74 | cd "~/.local/share/Terraria/tModLoader/ModSources" && git clone https://github.com/misprit7/WireHead.git 75 | ``` 76 | 77 | Prepare the binary you wish to run. For example for pong compile the rust app and copy the binary to a more convenient path: 78 | 79 | ``` 80 | cd /app/pong 81 | cargo rb 82 | ./copy-bin.sh /tmp/pong.txt 83 | ``` 84 | 85 | Start [tModLoader](https://store.steampowered.com/app/1281930/tModLoader/), and from the main menu go to Workshop->Develop and click on the Build button next to WireHead. For convenience I'd also recommend installing Cheat Sheet and HERO's Mod from the Download Mods section of the workshop if you haven't already. Then open the new world you copied earlier in game. In game type: 86 | ``` 87 | /bin write /tmp/pong.txt 88 | ``` 89 | 90 | Currently the NPCs that run the CPU clock are too far away to spawn immediately, this is a bug and should be fixed soon. As a workaround, go through the blue teleporter shown below, fly upwards a bit, come back down and go back through the same teleporter. 91 | 92 | ![Control Panel](doc/img/control-panel.png) 93 | 94 | After this workaround is done, press the first two of the three levers on the far right to start the program. Go through the orange teleporter to arrive at the screen area. Pong should be running and is controllable by the controller beneath the screen (use HERO's Mod's camera lock to see the screen and controls at the same time). 95 | 96 | ![Pong](doc/img/pong-still.png) 97 | 98 | ## Docker 99 | 100 | For advanced CI/headless usage you can use the docker image: 101 | 102 | [Docker Image](https://hub.docker.com/r/misprit7/computerraria) 103 | 104 | If you already have docker installed this can be pulled with 105 | 106 | ```bash 107 | docker pull misprit7/computerraria 108 | ``` 109 | 110 | You can then start the container with 111 | 112 | ```bash 113 | docker run -it misprit7/computerraria 114 | ``` 115 | 116 | This image already has all tooling installed so you should be able to build everything. 117 | 118 | # File Structure 119 | 120 | The major relevant parts of the project are as follows: 121 | 122 | ``` 123 | . 124 | ├── app/ 125 | │ ├── tdriver/ 126 | │   └── template/ 127 | ├── computer.wld 128 | ├── doc/ 129 | ├── docker/ 130 | ├── test/ 131 | └── tinterface/ 132 | ├── bin/ 133 | └── tinterface/ 134 | ``` 135 | 136 | `app/` 137 | 138 | Higher level applications to be run on the computer, not including compliance tests. Currently all in rust but could also easily be in C. 139 | 140 | `app/tdriver/` 141 | 142 | Driver API for interacting cpu from rust, mostly extremely low level startup code and graphics drivers. 143 | 144 | `app/template/` 145 | 146 | Template for new rust projects that implements minimal tdriver 147 | 148 | `computer.wld` 149 | 150 | The actual world file. This is technically a binary file, but given the context of the project it acts much more like source code given that it is edited manually and compresses extremely well. This generally isn't edited in place, it's copied back and forth to the user installation with [copy-world.sh](copy-world.sh). 151 | 152 | `doc/` 153 | 154 | Documentation/notes for the project 155 | 156 | `docker/` 157 | 158 | Files required to build docker image for CI. 159 | 160 | `test/` 161 | 162 | All automated tests written for the CPU. These are mostly handled through [riscof](https://github.com/riscv-software-src/riscof). This consists of both the computerraria plugin as well as a reference plugin ([sail_cSim](test/sail_cSim/)) to compare the results to. 163 | 164 | `tinterface/` 165 | 166 | Interfaces programmatically with running Terraria instance. This consists of both a python module as well as a command line wrapper to upload binaries, start execution and manipulate other fine grain controls without needing a GUI. 167 | 168 | 169 | -------------------------------------------------------------------------------- /app/doom3d/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [target.riscv32i-unknown-none-elf] 2 | rustflags = ["-C", "link-arg=-Tlink.x", "-C", "llvm-args=-ffast-math"] 3 | 4 | [env] 5 | EMU_TICK_RATE = "100" 6 | 7 | [alias] 8 | rbuild = "build --release --target riscv32i-unknown-none-elf" 9 | rb = "rbuild" 10 | 11 | rdoc = "doc --release --target riscv32i-unknown-none-elf" 12 | rd = "rdoc" 13 | 14 | rsize = "size --release --target riscv32i-unknown-none-elf" 15 | rs = "rsize" 16 | 17 | robjdump = "objdump --release --target riscv32i-unknown-none-elf" 18 | rod = "robjdump" 19 | 20 | -------------------------------------------------------------------------------- /app/doom3d/.vimspector.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": { 3 | "Launch": { 4 | "adapter": "vscode-cpptools", 5 | "filetypes": [ "cpp", "c", "objc", "rust" ], 6 | "configuration": { 7 | "request": "launch", 8 | "program": "${workspaceRoot}/target/x86_64-unknown-linux-gnu/debug/doom3d", 9 | "args": [], 10 | "cwd": ".", 11 | "environment": [], 12 | "externalConsole": true, 13 | "MIMode": "gdb", 14 | "stopAtEntry": true 15 | } 16 | }, 17 | "Attach": { 18 | "adapter": "vscode-cpptools", 19 | "filetypes": [ "cpp", "c", "objc", "rust" ], 20 | "configuration": { 21 | "request": "attach", 22 | "program": "${workspaceRoot}/target/x86_64-unknown-linux-gnu/debug/doom3d", 23 | "MIMode": "gdb", 24 | "stopAtEntry": true 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/doom3d/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "autocfg" 7 | version = "1.1.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 10 | 11 | [[package]] 12 | name = "az" 13 | version = "1.2.1" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "7b7e4c2464d97fe331d41de9d5db0def0a96f4d823b8b32a2efd503578988973" 16 | 17 | [[package]] 18 | name = "bitflags" 19 | version = "1.3.2" 20 | source = "registry+https://github.com/rust-lang/crates.io-index" 21 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 22 | 23 | [[package]] 24 | name = "bytemuck" 25 | version = "1.13.1" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | checksum = "17febce684fd15d89027105661fec94afb475cb995fbc59d2865198446ba2eea" 28 | 29 | [[package]] 30 | name = "cassowary" 31 | version = "0.3.0" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" 34 | 35 | [[package]] 36 | name = "cfg-if" 37 | version = "1.0.0" 38 | source = "registry+https://github.com/rust-lang/crates.io-index" 39 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 40 | 41 | [[package]] 42 | name = "cordic" 43 | version = "0.1.5" 44 | source = "registry+https://github.com/rust-lang/crates.io-index" 45 | checksum = "0ed0a176c0b8c5c95fa0523177530364c5b68a8895d9745730dbfa692a7412d0" 46 | dependencies = [ 47 | "fixed", 48 | ] 49 | 50 | [[package]] 51 | name = "crossterm" 52 | version = "0.25.0" 53 | source = "registry+https://github.com/rust-lang/crates.io-index" 54 | checksum = "e64e6c0fbe2c17357405f7c758c1ef960fce08bdfb2c03d88d2a18d7e09c4b67" 55 | dependencies = [ 56 | "bitflags", 57 | "crossterm_winapi", 58 | "libc", 59 | "mio", 60 | "parking_lot", 61 | "signal-hook", 62 | "signal-hook-mio", 63 | "winapi", 64 | ] 65 | 66 | [[package]] 67 | name = "crossterm" 68 | version = "0.26.1" 69 | source = "registry+https://github.com/rust-lang/crates.io-index" 70 | checksum = "a84cda67535339806297f1b331d6dd6320470d2a0fe65381e79ee9e156dd3d13" 71 | dependencies = [ 72 | "bitflags", 73 | "crossterm_winapi", 74 | "libc", 75 | "mio", 76 | "parking_lot", 77 | "signal-hook", 78 | "signal-hook-mio", 79 | "winapi", 80 | ] 81 | 82 | [[package]] 83 | name = "crossterm_winapi" 84 | version = "0.9.0" 85 | source = "registry+https://github.com/rust-lang/crates.io-index" 86 | checksum = "2ae1b35a484aa10e07fe0638d02301c5ad24de82d310ccbd2f3693da5f09bf1c" 87 | dependencies = [ 88 | "winapi", 89 | ] 90 | 91 | [[package]] 92 | name = "crunchy" 93 | version = "0.2.2" 94 | source = "registry+https://github.com/rust-lang/crates.io-index" 95 | checksum = "7a81dae078cea95a014a339291cec439d2f232ebe854a9d672b796c6afafa9b7" 96 | 97 | [[package]] 98 | name = "doom3d" 99 | version = "0.1.0" 100 | dependencies = [ 101 | "cordic", 102 | "fixed", 103 | "libm", 104 | "tdriver", 105 | ] 106 | 107 | [[package]] 108 | name = "fixed" 109 | version = "1.23.1" 110 | source = "registry+https://github.com/rust-lang/crates.io-index" 111 | checksum = "79386fdcec5e0fde91b1a6a5bcd89677d1f9304f7f986b154a1b9109038854d9" 112 | dependencies = [ 113 | "az", 114 | "bytemuck", 115 | "half", 116 | "typenum", 117 | ] 118 | 119 | [[package]] 120 | name = "half" 121 | version = "2.2.1" 122 | source = "registry+https://github.com/rust-lang/crates.io-index" 123 | checksum = "02b4af3693f1b705df946e9fe5631932443781d0aabb423b62fcd4d73f6d2fd0" 124 | dependencies = [ 125 | "crunchy", 126 | ] 127 | 128 | [[package]] 129 | name = "libc" 130 | version = "0.2.141" 131 | source = "registry+https://github.com/rust-lang/crates.io-index" 132 | checksum = "3304a64d199bb964be99741b7a14d26972741915b3649639149b2479bb46f4b5" 133 | 134 | [[package]] 135 | name = "libm" 136 | version = "0.2.6" 137 | source = "registry+https://github.com/rust-lang/crates.io-index" 138 | checksum = "348108ab3fba42ec82ff6e9564fc4ca0247bdccdc68dd8af9764bbc79c3c8ffb" 139 | 140 | [[package]] 141 | name = "lock_api" 142 | version = "0.4.9" 143 | source = "registry+https://github.com/rust-lang/crates.io-index" 144 | checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" 145 | dependencies = [ 146 | "autocfg", 147 | "scopeguard", 148 | ] 149 | 150 | [[package]] 151 | name = "log" 152 | version = "0.4.17" 153 | source = "registry+https://github.com/rust-lang/crates.io-index" 154 | checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" 155 | dependencies = [ 156 | "cfg-if", 157 | ] 158 | 159 | [[package]] 160 | name = "mio" 161 | version = "0.8.6" 162 | source = "registry+https://github.com/rust-lang/crates.io-index" 163 | checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" 164 | dependencies = [ 165 | "libc", 166 | "log", 167 | "wasi", 168 | "windows-sys", 169 | ] 170 | 171 | [[package]] 172 | name = "parking_lot" 173 | version = "0.12.1" 174 | source = "registry+https://github.com/rust-lang/crates.io-index" 175 | checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" 176 | dependencies = [ 177 | "lock_api", 178 | "parking_lot_core", 179 | ] 180 | 181 | [[package]] 182 | name = "parking_lot_core" 183 | version = "0.9.7" 184 | source = "registry+https://github.com/rust-lang/crates.io-index" 185 | checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" 186 | dependencies = [ 187 | "cfg-if", 188 | "libc", 189 | "redox_syscall", 190 | "smallvec", 191 | "windows-sys", 192 | ] 193 | 194 | [[package]] 195 | name = "ratatui" 196 | version = "0.20.1" 197 | source = "registry+https://github.com/rust-lang/crates.io-index" 198 | checksum = "dcc0d032bccba900ee32151ec0265667535c230169f5a011154cdcd984e16829" 199 | dependencies = [ 200 | "bitflags", 201 | "cassowary", 202 | "crossterm 0.26.1", 203 | "unicode-segmentation", 204 | "unicode-width", 205 | ] 206 | 207 | [[package]] 208 | name = "redox_syscall" 209 | version = "0.2.16" 210 | source = "registry+https://github.com/rust-lang/crates.io-index" 211 | checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" 212 | dependencies = [ 213 | "bitflags", 214 | ] 215 | 216 | [[package]] 217 | name = "scopeguard" 218 | version = "1.1.0" 219 | source = "registry+https://github.com/rust-lang/crates.io-index" 220 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 221 | 222 | [[package]] 223 | name = "signal-hook" 224 | version = "0.3.15" 225 | source = "registry+https://github.com/rust-lang/crates.io-index" 226 | checksum = "732768f1176d21d09e076c23a93123d40bba92d50c4058da34d45c8de8e682b9" 227 | dependencies = [ 228 | "libc", 229 | "signal-hook-registry", 230 | ] 231 | 232 | [[package]] 233 | name = "signal-hook-mio" 234 | version = "0.2.3" 235 | source = "registry+https://github.com/rust-lang/crates.io-index" 236 | checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" 237 | dependencies = [ 238 | "libc", 239 | "mio", 240 | "signal-hook", 241 | ] 242 | 243 | [[package]] 244 | name = "signal-hook-registry" 245 | version = "1.4.1" 246 | source = "registry+https://github.com/rust-lang/crates.io-index" 247 | checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" 248 | dependencies = [ 249 | "libc", 250 | ] 251 | 252 | [[package]] 253 | name = "smallvec" 254 | version = "1.10.0" 255 | source = "registry+https://github.com/rust-lang/crates.io-index" 256 | checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" 257 | 258 | [[package]] 259 | name = "tdriver" 260 | version = "0.1.0" 261 | dependencies = [ 262 | "crossterm 0.25.0", 263 | "ratatui", 264 | ] 265 | 266 | [[package]] 267 | name = "typenum" 268 | version = "1.16.0" 269 | source = "registry+https://github.com/rust-lang/crates.io-index" 270 | checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" 271 | 272 | [[package]] 273 | name = "unicode-segmentation" 274 | version = "1.10.1" 275 | source = "registry+https://github.com/rust-lang/crates.io-index" 276 | checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" 277 | 278 | [[package]] 279 | name = "unicode-width" 280 | version = "0.1.10" 281 | source = "registry+https://github.com/rust-lang/crates.io-index" 282 | checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" 283 | 284 | [[package]] 285 | name = "wasi" 286 | version = "0.11.0+wasi-snapshot-preview1" 287 | source = "registry+https://github.com/rust-lang/crates.io-index" 288 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 289 | 290 | [[package]] 291 | name = "winapi" 292 | version = "0.3.9" 293 | source = "registry+https://github.com/rust-lang/crates.io-index" 294 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 295 | dependencies = [ 296 | "winapi-i686-pc-windows-gnu", 297 | "winapi-x86_64-pc-windows-gnu", 298 | ] 299 | 300 | [[package]] 301 | name = "winapi-i686-pc-windows-gnu" 302 | version = "0.4.0" 303 | source = "registry+https://github.com/rust-lang/crates.io-index" 304 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 305 | 306 | [[package]] 307 | name = "winapi-x86_64-pc-windows-gnu" 308 | version = "0.4.0" 309 | source = "registry+https://github.com/rust-lang/crates.io-index" 310 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 311 | 312 | [[package]] 313 | name = "windows-sys" 314 | version = "0.45.0" 315 | source = "registry+https://github.com/rust-lang/crates.io-index" 316 | checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" 317 | dependencies = [ 318 | "windows-targets", 319 | ] 320 | 321 | [[package]] 322 | name = "windows-targets" 323 | version = "0.42.2" 324 | source = "registry+https://github.com/rust-lang/crates.io-index" 325 | checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" 326 | dependencies = [ 327 | "windows_aarch64_gnullvm", 328 | "windows_aarch64_msvc", 329 | "windows_i686_gnu", 330 | "windows_i686_msvc", 331 | "windows_x86_64_gnu", 332 | "windows_x86_64_gnullvm", 333 | "windows_x86_64_msvc", 334 | ] 335 | 336 | [[package]] 337 | name = "windows_aarch64_gnullvm" 338 | version = "0.42.2" 339 | source = "registry+https://github.com/rust-lang/crates.io-index" 340 | checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" 341 | 342 | [[package]] 343 | name = "windows_aarch64_msvc" 344 | version = "0.42.2" 345 | source = "registry+https://github.com/rust-lang/crates.io-index" 346 | checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" 347 | 348 | [[package]] 349 | name = "windows_i686_gnu" 350 | version = "0.42.2" 351 | source = "registry+https://github.com/rust-lang/crates.io-index" 352 | checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" 353 | 354 | [[package]] 355 | name = "windows_i686_msvc" 356 | version = "0.42.2" 357 | source = "registry+https://github.com/rust-lang/crates.io-index" 358 | checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" 359 | 360 | [[package]] 361 | name = "windows_x86_64_gnu" 362 | version = "0.42.2" 363 | source = "registry+https://github.com/rust-lang/crates.io-index" 364 | checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" 365 | 366 | [[package]] 367 | name = "windows_x86_64_gnullvm" 368 | version = "0.42.2" 369 | source = "registry+https://github.com/rust-lang/crates.io-index" 370 | checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" 371 | 372 | [[package]] 373 | name = "windows_x86_64_msvc" 374 | version = "0.42.2" 375 | source = "registry+https://github.com/rust-lang/crates.io-index" 376 | checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" 377 | -------------------------------------------------------------------------------- /app/doom3d/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "doom3d" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | cordic = "0.1.5" 8 | fixed = "1.23.1" 9 | libm = "0.2.6" 10 | tdriver = { path = "../tdriver" } 11 | 12 | [build_dependencies] 13 | tdriver = { path = "../tdriver" } 14 | 15 | # Don't ever use this for riscv builds or they will be massive 16 | [profile.dev] 17 | 18 | [profile.release] 19 | panic = "abort" 20 | # Use either 2, 3, s or z 21 | opt-level = 3 22 | overflow-checks = false 23 | lto = true 24 | 25 | -------------------------------------------------------------------------------- /app/doom3d/build.rs: -------------------------------------------------------------------------------- 1 | use std::fs::File; 2 | use std::io::prelude::*; 3 | use tdriver::graphics; 4 | 5 | const PI: f32 = 3.14159; 6 | const FOV_DEG: f32 = 60.0; 7 | const FOV_RAD: f32 = FOV_DEG * PI / 180.0; 8 | 9 | fn main() { 10 | let out_dir = std::env::var("OUT_DIR").unwrap(); 11 | let dest_path = std::path::Path::new(&out_dir).join("pixel_to_ray_angle_lookup.rs"); 12 | let mut file = File::create(&dest_path).unwrap(); 13 | write!( 14 | file, 15 | "pub const PIXEL_TO_RAY_ANGLE_TABLE: [I5F11; {}] = [\n", 16 | graphics::WIDTH 17 | ) 18 | .unwrap(); 19 | 20 | let tan_half_fov = (FOV_RAD / 2.0).tan(); 21 | for x_pixel in 0..graphics::WIDTH { 22 | // Create a lookup table to map x pixel index to the ray angle pointing in the direction of that pixel, in rad 23 | let screen_coord = x_pixel as f32 / graphics::WIDTH as f32; 24 | let angle_rad = ((2.0 * screen_coord - 1.0) * tan_half_fov).atan(); 25 | 26 | // Couldn't find a const fn to make a fixed point from a f32, but for some reason there's one for a string 27 | write!(file, " I5F11::unwrapped_from_str(\"{}\"),\n", angle_rad).unwrap(); 28 | } 29 | 30 | write!(file, "];\n").unwrap(); 31 | } 32 | -------------------------------------------------------------------------------- /app/doom3d/copy-bin.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/sh 2 | 3 | # Helper script to copy file to txt file format WireHead expects 4 | # Example: ./copy_bin.sh /tmp/in.txt 5 | 6 | # Rebuild project 7 | cargo rbuild --release 8 | 9 | # Convert from elf to bin 10 | # Fancy glob matching! https://zsh.sourceforge.io/Doc/Release/Expansion.html#Glob-Qualifiers 11 | # rust-objcopy -O binary ./target/riscv32i-unknown-none-elf/release/*(x.) /tmp/rust.bin 12 | rust-objcopy -O binary ./target/riscv32i-unknown-none-elf/release/doom3d /tmp/rust.bin 13 | 14 | # Convert from bin to txt 15 | hexdump -ve '1/1 "%.2x "' /tmp/rust.bin | head -c -1 > $1 16 | 17 | -------------------------------------------------------------------------------- /app/doom3d/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | mod maps; 5 | mod raycaster; 6 | 7 | use maps::MAP; 8 | use tdriver::entry; 9 | use tdriver::graphics; 10 | use tdriver::graphics::Screen; 11 | 12 | use fixed::types::{I5F11}; 13 | 14 | entry!(main); 15 | 16 | fn main() -> ! { 17 | let mut screen = graphics::init(); 18 | let raycaster = raycaster::Raycaster::new(MAP); 19 | let mut pixels: [[bool; graphics::WIDTH]; graphics::HEIGHT] = 20 | [[false; graphics::WIDTH]; graphics::HEIGHT]; 21 | 22 | let mut angle = I5F11::const_from_int(0); 23 | let x = I5F11::from_num(2.5); 24 | let y = I5F11::from_num(3.5); 25 | // let mut forward = true; 26 | loop { 27 | raycaster.render(x, y, angle, &mut pixels); 28 | angle += I5F11::from_num(0.04); 29 | angle %= 2 * I5F11::PI; 30 | // if x < 2 { forward = false } 31 | // if x > 3 { forward = true } 32 | // if forward { x += I5F11::from_num(0.01) } 33 | // else { x -= I5F11::from_num(0.01) } 34 | // y += I5F11::from_num(0.01); 35 | update_screen(&mut screen, &pixels); 36 | } 37 | } 38 | 39 | fn update_screen(screen: &mut Screen, pixels: &[[bool; graphics::WIDTH]; graphics::HEIGHT]) { 40 | for y_pix in 0..graphics::HEIGHT { 41 | let mut word: u64 = 0; 42 | for x_pix in 0..graphics::WIDTH { 43 | if pixels[y_pix][x_pix] { 44 | word |= 0b1 << x_pix; 45 | } 46 | } 47 | 48 | graphics::write_line(screen, word as u32, y_pix, 0); 49 | graphics::write_line(screen, (word >> 32) as u32, y_pix, 1); 50 | } 51 | 52 | graphics::update(screen); 53 | } 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /app/doom3d/src/maps.rs: -------------------------------------------------------------------------------- 1 | pub const MAP_WIDTH: usize = 5; 2 | pub const MAP_HEIGHT: usize = 7; 3 | 4 | // pub const MAP: [[bool; MAP_WIDTH]; MAP_HEIGHT] = 5 | // [[true, true, true], 6 | // [true, false, true], 7 | // [true, true, true]]; 8 | 9 | pub const MAP: [[bool; MAP_WIDTH]; MAP_HEIGHT] = 10 | [[true, true, true, true, true], 11 | [true, true, false, true, true], 12 | [true, false, false, false, true], 13 | [true, false, false, false, true], 14 | [true, false, false, false, true], 15 | [true, true, false, true, true], 16 | [true, true, true, true, true]]; 17 | 18 | // pub const MAP: [[bool; MAP_WIDTH]; MAP_HEIGHT] = [ 19 | // [true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true], 20 | // [true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true], 21 | // [true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true], 22 | // [true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true], 23 | // [true,false,false,false,false,false,true,true,true,true,true,false,false,false,false,true,false,true,false,true,false,false,false,true], 24 | // [true,false,false,false,false,false,true,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,true], 25 | // [true,false,false,false,false,false,true,false,false,false,true,false,false,false,false,true,false,false,false,true,false,false,false,true], 26 | // [true,false,false,false,false,false,true,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,true], 27 | // [true,false,false,false,false,false,true,true,false,true,true,false,false,false,false,true,false,true,false,true,false,false,false,true], 28 | // [true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true], 29 | // [true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true], 30 | // [true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true], 31 | // [true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true], 32 | // [true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true], 33 | // [true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true], 34 | // [true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true], 35 | // [true,true,true,true,true,true,true,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true], 36 | // [true,true,false,true,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true], 37 | // [true,true,false,false,false,false,true,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true], 38 | // [true,true,false,true,false,false,false,false,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true], 39 | // [true,true,false,true,true,true,true,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true], 40 | // [true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true], 41 | // [true,true,true,true,true,true,true,true,true,false,false,false,false,false,false,false,false,false,false,false,false,false,false,true], 42 | // [true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true,true] 43 | // ]; 44 | -------------------------------------------------------------------------------- /app/doom3d/src/raycaster.rs: -------------------------------------------------------------------------------- 1 | use core::cmp::{max, min}; 2 | use tdriver::graphics; 3 | use crate::maps::{MAP_WIDTH, MAP_HEIGHT}; 4 | use fixed::types::{I9F7, I5F11}; 5 | use cordic; 6 | 7 | use fixed::prelude::*; 8 | 9 | include!(concat!(env!("OUT_DIR"), "/pixel_to_ray_angle_lookup.rs")); 10 | 11 | pub struct Raycaster { 12 | map: [[bool; MAP_WIDTH]; MAP_HEIGHT], 13 | } 14 | 15 | struct RayHit { 16 | length: I5F11, 17 | idx_x: usize, 18 | idx_y: usize, 19 | normal_along_x: bool, 20 | } 21 | 22 | impl Raycaster { 23 | pub fn new(map: [[bool; MAP_WIDTH]; MAP_HEIGHT]) -> Self { 24 | Raycaster { 25 | map, 26 | } 27 | } 28 | 29 | pub fn render( 30 | &self, 31 | start_x: I5F11, 32 | start_y: I5F11, 33 | cam_angle_rad: I5F11, 34 | pixels: &mut [[bool; graphics::WIDTH]; graphics::HEIGHT], 35 | ) { 36 | let mut last_hit = RayHit { 37 | length: I5F11::const_from_int(0), 38 | idx_x: 0, 39 | idx_y: 0, 40 | normal_along_x: false, 41 | }; 42 | let mut last_top = 0; 43 | let mut last_bottom = 0; 44 | let mut last_on_wall = false; 45 | 46 | for x_pixel in 0..graphics::WIDTH { 47 | let ray_angle_rad = PIXEL_TO_RAY_ANGLE_TABLE[x_pixel] + cam_angle_rad; 48 | let hit = self.cast_ray(start_x, start_y, ray_angle_rad); 49 | 50 | if let Some(hit) = hit { 51 | let height: i32 = (graphics::HEIGHT.to_fixed::().wide_div(hit.length)).to_num(); 52 | let top: usize = min( 53 | (graphics::HEIGHT as i32 / 2) + (height / 2), 54 | graphics::HEIGHT as i32 - 1, 55 | ) as usize; 56 | let bottom: usize = max((graphics::HEIGHT as i32 / 2) - (height / 2), 0) as usize; 57 | 58 | let x_diff = hit.idx_x.abs_diff(last_hit.idx_x); 59 | let y_diff = hit.idx_y.abs_diff(last_hit.idx_y); 60 | let diagonal = x_diff == 1 && y_diff == 1; 61 | let far_away = x_diff >= 2 || y_diff >= 2; 62 | let new_normal = hit.normal_along_x != last_hit.normal_along_x; 63 | 64 | if (diagonal || far_away || new_normal || !last_on_wall) && x_pixel > 0 { 65 | // hit a wall corner, draw a vertical line 66 | for y_pixel in 0..graphics::HEIGHT { 67 | pixels[y_pixel][x_pixel] = y_pixel >= min(bottom, last_bottom) && y_pixel <= max(top, last_top); 68 | } 69 | } else { 70 | // hit a wall, draw top and bottom only 71 | for y_pixel in 0..graphics::HEIGHT { 72 | pixels[y_pixel][x_pixel] = false; 73 | } 74 | 75 | pixels[top][x_pixel] = true; 76 | pixels[bottom][x_pixel] = true; 77 | } 78 | 79 | last_hit = hit; 80 | last_top = top; 81 | last_bottom = bottom; 82 | last_on_wall = true; 83 | } else { 84 | if last_on_wall { 85 | // hit blank space after seeing wall, draw a vertical line 86 | for y_pixel in 0..graphics::HEIGHT { 87 | pixels[y_pixel][x_pixel] = y_pixel >= last_bottom && y_pixel <= last_top; 88 | } 89 | } else { 90 | // hit blank space, draw nothing 91 | for y_pixel in 0..graphics::HEIGHT { 92 | pixels[y_pixel][x_pixel] = false; 93 | } 94 | } 95 | 96 | last_on_wall = false; 97 | } 98 | } 99 | } 100 | 101 | // DDA algorithm (https://www.youtube.com/watch?v=NbSee-XM7WA&ab_channel=javidx9) 102 | fn cast_ray(&self, start_x: I5F11, start_y: I5F11, ray_angle_rad: I5F11) -> Option { 103 | let (dir_y, dir_x) = cordic::sin_cos(ray_angle_rad); 104 | let ray_unit_step_size_x = match dir_x.abs().checked_recip() { 105 | Some(v) => v, 106 | None => I5F11::MAX 107 | }; // Length of step if moving 1 unit in x 108 | let ray_unit_step_size_y = match dir_y.abs().checked_recip() { 109 | Some(v) => v, 110 | None => I5F11::MAX 111 | }; // Length of step if moving 1 unit in y 112 | let mut last_hit_x_normal = false; // Normal of last wall hit 113 | 114 | // Length of ray if next step is 1 unit in x (account for off-grid start) 115 | let mut ray_length_x = if dir_x >= 0.0 { 116 | last_hit_x_normal = true; 117 | start_x.ceil() - start_x 118 | } else { 119 | start_x - start_x.floor() 120 | } * ray_unit_step_size_x; 121 | 122 | // Length of ray if next step is 1 unit in y (account for off-grid start) 123 | let mut ray_length_y = if dir_y >= 0.0 { 124 | start_y.ceil() - start_y 125 | } else { 126 | start_y - start_y.floor() 127 | } * ray_unit_step_size_y; 128 | 129 | let step_x = if dir_x > 0.0 {1} else {-1}; 130 | let step_y = if dir_y > 0.0 {1} else {-1}; 131 | let mut idx_x = start_x.to_num::(); 132 | let mut idx_y = start_y.to_num::(); 133 | 134 | let mut ray_length = I5F11::const_from_int(0); 135 | loop { 136 | if self.valid_map_idx(idx_x, idx_y) { 137 | if self.map[idx_y as usize][idx_x as usize] { 138 | // ray has collided with a wall! 139 | return Some(RayHit { 140 | length: ray_length, 141 | idx_x: idx_x as usize, 142 | idx_y: idx_y as usize, 143 | normal_along_x: last_hit_x_normal, 144 | }); 145 | } 146 | } else { 147 | // ray has left map area, exit 148 | return None; 149 | } 150 | 151 | // Walk along shortest ray 152 | if ray_length_x <= ray_length_y { 153 | idx_x += step_x; 154 | ray_length = ray_length_x; 155 | ray_length_x += ray_unit_step_size_x; 156 | last_hit_x_normal = true; 157 | } else { 158 | idx_y += step_y; 159 | ray_length = ray_length_y; 160 | ray_length_y += ray_unit_step_size_y; 161 | last_hit_x_normal = false; 162 | } 163 | } 164 | } 165 | 166 | fn valid_map_idx(&self, pos_x: i32, pos_y: i32) -> bool { 167 | pos_x >= 0 && pos_y >= 0 && pos_x < MAP_WIDTH as i32 && pos_y < MAP_HEIGHT as i32 168 | } 169 | } 170 | -------------------------------------------------------------------------------- /app/game-of-life/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [target.riscv32i-unknown-none-elf] 2 | rustflags = ["-C", "link-arg=-Tlink.x"] 3 | 4 | [alias] 5 | rbuild = "build --release --target riscv32i-unknown-none-elf" 6 | rb = "rbuild" 7 | 8 | rdoc = "doc --release --target riscv32i-unknown-none-elf" 9 | rd = "rdoc" 10 | 11 | rsize = "size --release --target riscv32i-unknown-none-elf" 12 | rs = "rsize" 13 | 14 | robjdump = "objdump --release --target riscv32i-unknown-none-elf" 15 | rod = "robjdump" 16 | 17 | -------------------------------------------------------------------------------- /app/game-of-life/.vimspector.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": { 3 | "Launch": { 4 | "adapter": "vscode-cpptools", 5 | "filetypes": [ "cpp", "c", "objc", "rust" ], 6 | "configuration": { 7 | "request": "launch", 8 | "program": "${workspaceRoot}/target/x86_64-unknown-linux-gnu/debug/game-of-life", 9 | "args": [], 10 | "cwd": ".", 11 | "environment": [], 12 | "externalConsole": true, 13 | "MIMode": "gdb", 14 | "stopAtEntry": true 15 | } 16 | }, 17 | "Attach": { 18 | "adapter": "vscode-cpptools", 19 | "filetypes": [ "cpp", "c", "objc", "rust" ], 20 | "configuration": { 21 | "request": "attach", 22 | "program": "${workspaceRoot}/target/x86_64-unknown-linux-gnu/debug/game-of-life", 23 | "MIMode": "gdb", 24 | "stopAtEntry": true 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/game-of-life/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "autocfg" 7 | version = "1.1.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 10 | 11 | [[package]] 12 | name = "bitflags" 13 | version = "1.3.2" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 16 | 17 | [[package]] 18 | name = "cassowary" 19 | version = "0.3.0" 20 | source = "registry+https://github.com/rust-lang/crates.io-index" 21 | checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" 22 | 23 | [[package]] 24 | name = "cfg-if" 25 | version = "1.0.0" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 28 | 29 | [[package]] 30 | name = "crossterm" 31 | version = "0.25.0" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | checksum = "e64e6c0fbe2c17357405f7c758c1ef960fce08bdfb2c03d88d2a18d7e09c4b67" 34 | dependencies = [ 35 | "bitflags", 36 | "crossterm_winapi", 37 | "libc", 38 | "mio", 39 | "parking_lot", 40 | "signal-hook", 41 | "signal-hook-mio", 42 | "winapi", 43 | ] 44 | 45 | [[package]] 46 | name = "crossterm" 47 | version = "0.26.1" 48 | source = "registry+https://github.com/rust-lang/crates.io-index" 49 | checksum = "a84cda67535339806297f1b331d6dd6320470d2a0fe65381e79ee9e156dd3d13" 50 | dependencies = [ 51 | "bitflags", 52 | "crossterm_winapi", 53 | "libc", 54 | "mio", 55 | "parking_lot", 56 | "signal-hook", 57 | "signal-hook-mio", 58 | "winapi", 59 | ] 60 | 61 | [[package]] 62 | name = "crossterm_winapi" 63 | version = "0.9.0" 64 | source = "registry+https://github.com/rust-lang/crates.io-index" 65 | checksum = "2ae1b35a484aa10e07fe0638d02301c5ad24de82d310ccbd2f3693da5f09bf1c" 66 | dependencies = [ 67 | "winapi", 68 | ] 69 | 70 | [[package]] 71 | name = "game-of-life" 72 | version = "0.1.0" 73 | dependencies = [ 74 | "tdriver", 75 | ] 76 | 77 | [[package]] 78 | name = "libc" 79 | version = "0.2.140" 80 | source = "registry+https://github.com/rust-lang/crates.io-index" 81 | checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" 82 | 83 | [[package]] 84 | name = "lock_api" 85 | version = "0.4.9" 86 | source = "registry+https://github.com/rust-lang/crates.io-index" 87 | checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" 88 | dependencies = [ 89 | "autocfg", 90 | "scopeguard", 91 | ] 92 | 93 | [[package]] 94 | name = "log" 95 | version = "0.4.17" 96 | source = "registry+https://github.com/rust-lang/crates.io-index" 97 | checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" 98 | dependencies = [ 99 | "cfg-if", 100 | ] 101 | 102 | [[package]] 103 | name = "mio" 104 | version = "0.8.6" 105 | source = "registry+https://github.com/rust-lang/crates.io-index" 106 | checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" 107 | dependencies = [ 108 | "libc", 109 | "log", 110 | "wasi", 111 | "windows-sys", 112 | ] 113 | 114 | [[package]] 115 | name = "parking_lot" 116 | version = "0.12.1" 117 | source = "registry+https://github.com/rust-lang/crates.io-index" 118 | checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" 119 | dependencies = [ 120 | "lock_api", 121 | "parking_lot_core", 122 | ] 123 | 124 | [[package]] 125 | name = "parking_lot_core" 126 | version = "0.9.7" 127 | source = "registry+https://github.com/rust-lang/crates.io-index" 128 | checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" 129 | dependencies = [ 130 | "cfg-if", 131 | "libc", 132 | "redox_syscall", 133 | "smallvec", 134 | "windows-sys", 135 | ] 136 | 137 | [[package]] 138 | name = "ratatui" 139 | version = "0.20.1" 140 | source = "registry+https://github.com/rust-lang/crates.io-index" 141 | checksum = "dcc0d032bccba900ee32151ec0265667535c230169f5a011154cdcd984e16829" 142 | dependencies = [ 143 | "bitflags", 144 | "cassowary", 145 | "crossterm 0.26.1", 146 | "unicode-segmentation", 147 | "unicode-width", 148 | ] 149 | 150 | [[package]] 151 | name = "redox_syscall" 152 | version = "0.2.16" 153 | source = "registry+https://github.com/rust-lang/crates.io-index" 154 | checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" 155 | dependencies = [ 156 | "bitflags", 157 | ] 158 | 159 | [[package]] 160 | name = "scopeguard" 161 | version = "1.1.0" 162 | source = "registry+https://github.com/rust-lang/crates.io-index" 163 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 164 | 165 | [[package]] 166 | name = "signal-hook" 167 | version = "0.3.15" 168 | source = "registry+https://github.com/rust-lang/crates.io-index" 169 | checksum = "732768f1176d21d09e076c23a93123d40bba92d50c4058da34d45c8de8e682b9" 170 | dependencies = [ 171 | "libc", 172 | "signal-hook-registry", 173 | ] 174 | 175 | [[package]] 176 | name = "signal-hook-mio" 177 | version = "0.2.3" 178 | source = "registry+https://github.com/rust-lang/crates.io-index" 179 | checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" 180 | dependencies = [ 181 | "libc", 182 | "mio", 183 | "signal-hook", 184 | ] 185 | 186 | [[package]] 187 | name = "signal-hook-registry" 188 | version = "1.4.1" 189 | source = "registry+https://github.com/rust-lang/crates.io-index" 190 | checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" 191 | dependencies = [ 192 | "libc", 193 | ] 194 | 195 | [[package]] 196 | name = "smallvec" 197 | version = "1.10.0" 198 | source = "registry+https://github.com/rust-lang/crates.io-index" 199 | checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" 200 | 201 | [[package]] 202 | name = "tdriver" 203 | version = "0.1.0" 204 | dependencies = [ 205 | "crossterm 0.25.0", 206 | "ratatui", 207 | ] 208 | 209 | [[package]] 210 | name = "unicode-segmentation" 211 | version = "1.10.1" 212 | source = "registry+https://github.com/rust-lang/crates.io-index" 213 | checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" 214 | 215 | [[package]] 216 | name = "unicode-width" 217 | version = "0.1.10" 218 | source = "registry+https://github.com/rust-lang/crates.io-index" 219 | checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" 220 | 221 | [[package]] 222 | name = "wasi" 223 | version = "0.11.0+wasi-snapshot-preview1" 224 | source = "registry+https://github.com/rust-lang/crates.io-index" 225 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 226 | 227 | [[package]] 228 | name = "winapi" 229 | version = "0.3.9" 230 | source = "registry+https://github.com/rust-lang/crates.io-index" 231 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 232 | dependencies = [ 233 | "winapi-i686-pc-windows-gnu", 234 | "winapi-x86_64-pc-windows-gnu", 235 | ] 236 | 237 | [[package]] 238 | name = "winapi-i686-pc-windows-gnu" 239 | version = "0.4.0" 240 | source = "registry+https://github.com/rust-lang/crates.io-index" 241 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 242 | 243 | [[package]] 244 | name = "winapi-x86_64-pc-windows-gnu" 245 | version = "0.4.0" 246 | source = "registry+https://github.com/rust-lang/crates.io-index" 247 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 248 | 249 | [[package]] 250 | name = "windows-sys" 251 | version = "0.45.0" 252 | source = "registry+https://github.com/rust-lang/crates.io-index" 253 | checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" 254 | dependencies = [ 255 | "windows-targets", 256 | ] 257 | 258 | [[package]] 259 | name = "windows-targets" 260 | version = "0.42.2" 261 | source = "registry+https://github.com/rust-lang/crates.io-index" 262 | checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" 263 | dependencies = [ 264 | "windows_aarch64_gnullvm", 265 | "windows_aarch64_msvc", 266 | "windows_i686_gnu", 267 | "windows_i686_msvc", 268 | "windows_x86_64_gnu", 269 | "windows_x86_64_gnullvm", 270 | "windows_x86_64_msvc", 271 | ] 272 | 273 | [[package]] 274 | name = "windows_aarch64_gnullvm" 275 | version = "0.42.2" 276 | source = "registry+https://github.com/rust-lang/crates.io-index" 277 | checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" 278 | 279 | [[package]] 280 | name = "windows_aarch64_msvc" 281 | version = "0.42.2" 282 | source = "registry+https://github.com/rust-lang/crates.io-index" 283 | checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" 284 | 285 | [[package]] 286 | name = "windows_i686_gnu" 287 | version = "0.42.2" 288 | source = "registry+https://github.com/rust-lang/crates.io-index" 289 | checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" 290 | 291 | [[package]] 292 | name = "windows_i686_msvc" 293 | version = "0.42.2" 294 | source = "registry+https://github.com/rust-lang/crates.io-index" 295 | checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" 296 | 297 | [[package]] 298 | name = "windows_x86_64_gnu" 299 | version = "0.42.2" 300 | source = "registry+https://github.com/rust-lang/crates.io-index" 301 | checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" 302 | 303 | [[package]] 304 | name = "windows_x86_64_gnullvm" 305 | version = "0.42.2" 306 | source = "registry+https://github.com/rust-lang/crates.io-index" 307 | checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" 308 | 309 | [[package]] 310 | name = "windows_x86_64_msvc" 311 | version = "0.42.2" 312 | source = "registry+https://github.com/rust-lang/crates.io-index" 313 | checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" 314 | -------------------------------------------------------------------------------- /app/game-of-life/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "game-of-life" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | tdriver = { path = "../tdriver" } 8 | 9 | # Don't ever use this for riscv builds or they will be massive 10 | [profile.dev] 11 | 12 | [profile.release] 13 | panic = "abort" 14 | # Use either 2, 3, s or z 15 | opt-level = 3 16 | overflow-checks = false 17 | lto = true 18 | 19 | -------------------------------------------------------------------------------- /app/game-of-life/copy-bin.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/sh 2 | 3 | # Helper script to copy file to txt file format WireHead expects 4 | # Example: ./copy_bin.sh /tmp/in.txt 5 | 6 | # Rebuild project 7 | cargo rbuild --release 8 | 9 | # Convert from elf to bin 10 | # Fancy glob matching! https://zsh.sourceforge.io/Doc/Release/Expansion.html#Glob-Qualifiers 11 | # rust-objcopy -O binary ./target/riscv32i-unknown-none-elf/release/*(x.) /tmp/rust.bin 12 | rust-objcopy -O binary ./target/riscv32i-unknown-none-elf/release/game-of-life /tmp/rust.bin 13 | 14 | # Convert from bin to txt 15 | hexdump -ve '1/1 "%.2x "' /tmp/rust.bin | head -c -1 > $1 16 | 17 | -------------------------------------------------------------------------------- /app/game-of-life/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | use tdriver::entry; 5 | use tdriver::graphics; 6 | 7 | entry!(main); 8 | 9 | const WIDTH: usize = 64; 10 | const HEIGHT: usize = 48; 11 | 12 | fn update_board(board: &[[u8; WIDTH]; HEIGHT]) -> [[u8; WIDTH]; HEIGHT] { 13 | let mut board_next: [[u8; WIDTH]; HEIGHT] = board.clone(); 14 | // board_next[1][1] = board[1][1]; 15 | for r in 1..HEIGHT-1 { 16 | // board_next[r+1][1] = board[r+1][1]; 17 | // board_next[r][0] = board[r][0]; 18 | // board_next[r+1][0] = board[r+1][0]; 19 | for c in 1..WIDTH-1 { 20 | // board_next[r][c+1] = board[r][c+1]; 21 | // board_next[r+1][c+1] = board[r+1][c+1]; 22 | let neighbors_alive = (board[r][c] & 0b1110) >> 1; 23 | if board[r][c] & 1 == 0 { 24 | if neighbors_alive != 3 { continue } 25 | board_next[r][c] |= 1; 26 | board_next[r-1][c-1] += 0b10; 27 | board_next[r-1][c] += 0b10; 28 | board_next[r-1][c+1] += 0b10; 29 | board_next[r][c-1] += 0b10; 30 | board_next[r][c+1] += 0b10; 31 | board_next[r+1][c-1] += 0b10; 32 | board_next[r+1][c] += 0b10; 33 | board_next[r+1][c+1] += 0b10; 34 | } else { 35 | if neighbors_alive == 2 || neighbors_alive == 3 { continue } 36 | board_next[r][c] &= !1; 37 | board_next[r-1][c-1] -= 0b10; 38 | board_next[r-1][c] -= 0b10; 39 | board_next[r-1][c+1] -= 0b10; 40 | board_next[r][c-1] -= 0b10; 41 | board_next[r][c+1] -= 0b10; 42 | board_next[r+1][c-1] -= 0b10; 43 | board_next[r+1][c] -= 0b10; 44 | board_next[r+1][c+1] -= 0b10; 45 | } 46 | 47 | } 48 | } 49 | board_next 50 | } 51 | 52 | // Following technique from https://www.jagregory.com/abrash-black-book/#chapter-17-the-game-of-life 53 | fn main() -> ! { 54 | let mut board: [[u8; WIDTH]; HEIGHT] = [ 55 | [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 56 | [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 57 | [0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 58 | [0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 59 | [0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 60 | [0,0,1,1,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 61 | [0,0,1,1,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 62 | [0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 63 | [0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 64 | [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 65 | [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 66 | [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 67 | [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 68 | [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 69 | [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 70 | [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 71 | [0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 72 | [0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 73 | [0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 74 | [0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 75 | [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 76 | [0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 77 | [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 78 | [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 79 | [0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 80 | [0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 81 | [0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 82 | [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 83 | [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 84 | [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 85 | [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 86 | [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 87 | [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 88 | [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 89 | [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 90 | [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 91 | [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 92 | [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 93 | [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 94 | [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 95 | [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 96 | [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 97 | [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 98 | [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 99 | [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 100 | [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 101 | [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 102 | [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0], 103 | ]; 104 | for r in 0..board.len() { 105 | for c in 0..board[0].len() { 106 | if r == 0 || r == board.len() - 1 || c == 0 || c == board[0].len() - 1 { 107 | board[r][c] = 0b1110; 108 | continue 109 | } 110 | let neighbors_alive = (board[r-1][c-1] & 1) + 111 | (board[r-1][c] & 1) + 112 | (board[r-1][c+1] & 1) + 113 | (board[r][c-1] & 1) + 114 | (board[r][c+1] & 1) + 115 | (board[r+1][c-1] & 1) + 116 | (board[r+1][c] & 1) + 117 | (board[r+1][c+1] & 1); 118 | board[r][c] |= neighbors_alive << 1; 119 | } 120 | } 121 | let mut pixels: [u64; graphics::HEIGHT] = [0; graphics::HEIGHT]; 122 | let mut screen = graphics::init(); 123 | graphics::write_long(&mut screen, &pixels); 124 | graphics::update(&mut screen); 125 | loop { 126 | board = update_board(&board); 127 | for r in 0..HEIGHT { 128 | pixels[r] = 0; 129 | for c in 0..WIDTH { 130 | if board[r][c] & 1 == 1 { 131 | pixels[r] |= 1 << c; 132 | } 133 | } 134 | } 135 | graphics::write_long(&mut screen, &pixels); 136 | graphics::update(&mut screen); 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /app/pong/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [target.riscv32i-unknown-none-elf] 2 | rustflags = ["-C", "link-arg=-Tlink.x"] 3 | 4 | [alias] 5 | rbuild = "build --release --target riscv32i-unknown-none-elf" 6 | rb = "rbuild" 7 | 8 | rdoc = "doc --release --target riscv32i-unknown-none-elf" 9 | rd = "rdoc" 10 | 11 | rsize = "size --release --target riscv32i-unknown-none-elf" 12 | rs = "rsize" 13 | 14 | robjdump = "objdump --release --target riscv32i-unknown-none-elf" 15 | rod = "robjdump" 16 | 17 | -------------------------------------------------------------------------------- /app/pong/.vimspector.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": { 3 | "Launch": { 4 | "adapter": "vscode-cpptools", 5 | "filetypes": [ "cpp", "c", "objc", "rust" ], 6 | "configuration": { 7 | "request": "launch", 8 | "program": "${workspaceRoot}/target/x86_64-unknown-linux-gnu/debug/pong", 9 | "args": [], 10 | "cwd": ".", 11 | "environment": [], 12 | "externalConsole": true, 13 | "MIMode": "gdb", 14 | "stopAtEntry": true 15 | } 16 | }, 17 | "Attach": { 18 | "adapter": "vscode-cpptools", 19 | "filetypes": [ "cpp", "c", "objc", "rust" ], 20 | "configuration": { 21 | "request": "attach", 22 | "program": "${workspaceRoot}/target/x86_64-unknown-linux-gnu/debug/pong", 23 | "MIMode": "gdb", 24 | "stopAtEntry": true 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/pong/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "autocfg" 7 | version = "1.1.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 10 | 11 | [[package]] 12 | name = "bitflags" 13 | version = "1.3.2" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 16 | 17 | [[package]] 18 | name = "cassowary" 19 | version = "0.3.0" 20 | source = "registry+https://github.com/rust-lang/crates.io-index" 21 | checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" 22 | 23 | [[package]] 24 | name = "cfg-if" 25 | version = "1.0.0" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 28 | 29 | [[package]] 30 | name = "crossterm" 31 | version = "0.25.0" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | checksum = "e64e6c0fbe2c17357405f7c758c1ef960fce08bdfb2c03d88d2a18d7e09c4b67" 34 | dependencies = [ 35 | "bitflags", 36 | "crossterm_winapi", 37 | "libc", 38 | "mio", 39 | "parking_lot", 40 | "signal-hook", 41 | "signal-hook-mio", 42 | "winapi", 43 | ] 44 | 45 | [[package]] 46 | name = "crossterm" 47 | version = "0.26.1" 48 | source = "registry+https://github.com/rust-lang/crates.io-index" 49 | checksum = "a84cda67535339806297f1b331d6dd6320470d2a0fe65381e79ee9e156dd3d13" 50 | dependencies = [ 51 | "bitflags", 52 | "crossterm_winapi", 53 | "libc", 54 | "mio", 55 | "parking_lot", 56 | "signal-hook", 57 | "signal-hook-mio", 58 | "winapi", 59 | ] 60 | 61 | [[package]] 62 | name = "crossterm_winapi" 63 | version = "0.9.0" 64 | source = "registry+https://github.com/rust-lang/crates.io-index" 65 | checksum = "2ae1b35a484aa10e07fe0638d02301c5ad24de82d310ccbd2f3693da5f09bf1c" 66 | dependencies = [ 67 | "winapi", 68 | ] 69 | 70 | [[package]] 71 | name = "libc" 72 | version = "0.2.140" 73 | source = "registry+https://github.com/rust-lang/crates.io-index" 74 | checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" 75 | 76 | [[package]] 77 | name = "lock_api" 78 | version = "0.4.9" 79 | source = "registry+https://github.com/rust-lang/crates.io-index" 80 | checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" 81 | dependencies = [ 82 | "autocfg", 83 | "scopeguard", 84 | ] 85 | 86 | [[package]] 87 | name = "log" 88 | version = "0.4.17" 89 | source = "registry+https://github.com/rust-lang/crates.io-index" 90 | checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" 91 | dependencies = [ 92 | "cfg-if", 93 | ] 94 | 95 | [[package]] 96 | name = "mio" 97 | version = "0.8.6" 98 | source = "registry+https://github.com/rust-lang/crates.io-index" 99 | checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" 100 | dependencies = [ 101 | "libc", 102 | "log", 103 | "wasi", 104 | "windows-sys", 105 | ] 106 | 107 | [[package]] 108 | name = "parking_lot" 109 | version = "0.12.1" 110 | source = "registry+https://github.com/rust-lang/crates.io-index" 111 | checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" 112 | dependencies = [ 113 | "lock_api", 114 | "parking_lot_core", 115 | ] 116 | 117 | [[package]] 118 | name = "parking_lot_core" 119 | version = "0.9.7" 120 | source = "registry+https://github.com/rust-lang/crates.io-index" 121 | checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" 122 | dependencies = [ 123 | "cfg-if", 124 | "libc", 125 | "redox_syscall", 126 | "smallvec", 127 | "windows-sys", 128 | ] 129 | 130 | [[package]] 131 | name = "pong" 132 | version = "0.1.0" 133 | dependencies = [ 134 | "tdriver", 135 | ] 136 | 137 | [[package]] 138 | name = "ratatui" 139 | version = "0.20.1" 140 | source = "registry+https://github.com/rust-lang/crates.io-index" 141 | checksum = "dcc0d032bccba900ee32151ec0265667535c230169f5a011154cdcd984e16829" 142 | dependencies = [ 143 | "bitflags", 144 | "cassowary", 145 | "crossterm 0.26.1", 146 | "unicode-segmentation", 147 | "unicode-width", 148 | ] 149 | 150 | [[package]] 151 | name = "redox_syscall" 152 | version = "0.2.16" 153 | source = "registry+https://github.com/rust-lang/crates.io-index" 154 | checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" 155 | dependencies = [ 156 | "bitflags", 157 | ] 158 | 159 | [[package]] 160 | name = "scopeguard" 161 | version = "1.1.0" 162 | source = "registry+https://github.com/rust-lang/crates.io-index" 163 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 164 | 165 | [[package]] 166 | name = "signal-hook" 167 | version = "0.3.15" 168 | source = "registry+https://github.com/rust-lang/crates.io-index" 169 | checksum = "732768f1176d21d09e076c23a93123d40bba92d50c4058da34d45c8de8e682b9" 170 | dependencies = [ 171 | "libc", 172 | "signal-hook-registry", 173 | ] 174 | 175 | [[package]] 176 | name = "signal-hook-mio" 177 | version = "0.2.3" 178 | source = "registry+https://github.com/rust-lang/crates.io-index" 179 | checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" 180 | dependencies = [ 181 | "libc", 182 | "mio", 183 | "signal-hook", 184 | ] 185 | 186 | [[package]] 187 | name = "signal-hook-registry" 188 | version = "1.4.1" 189 | source = "registry+https://github.com/rust-lang/crates.io-index" 190 | checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" 191 | dependencies = [ 192 | "libc", 193 | ] 194 | 195 | [[package]] 196 | name = "smallvec" 197 | version = "1.10.0" 198 | source = "registry+https://github.com/rust-lang/crates.io-index" 199 | checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" 200 | 201 | [[package]] 202 | name = "tdriver" 203 | version = "0.1.0" 204 | dependencies = [ 205 | "crossterm 0.25.0", 206 | "ratatui", 207 | ] 208 | 209 | [[package]] 210 | name = "unicode-segmentation" 211 | version = "1.10.1" 212 | source = "registry+https://github.com/rust-lang/crates.io-index" 213 | checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" 214 | 215 | [[package]] 216 | name = "unicode-width" 217 | version = "0.1.10" 218 | source = "registry+https://github.com/rust-lang/crates.io-index" 219 | checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" 220 | 221 | [[package]] 222 | name = "wasi" 223 | version = "0.11.0+wasi-snapshot-preview1" 224 | source = "registry+https://github.com/rust-lang/crates.io-index" 225 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 226 | 227 | [[package]] 228 | name = "winapi" 229 | version = "0.3.9" 230 | source = "registry+https://github.com/rust-lang/crates.io-index" 231 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 232 | dependencies = [ 233 | "winapi-i686-pc-windows-gnu", 234 | "winapi-x86_64-pc-windows-gnu", 235 | ] 236 | 237 | [[package]] 238 | name = "winapi-i686-pc-windows-gnu" 239 | version = "0.4.0" 240 | source = "registry+https://github.com/rust-lang/crates.io-index" 241 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 242 | 243 | [[package]] 244 | name = "winapi-x86_64-pc-windows-gnu" 245 | version = "0.4.0" 246 | source = "registry+https://github.com/rust-lang/crates.io-index" 247 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 248 | 249 | [[package]] 250 | name = "windows-sys" 251 | version = "0.45.0" 252 | source = "registry+https://github.com/rust-lang/crates.io-index" 253 | checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" 254 | dependencies = [ 255 | "windows-targets", 256 | ] 257 | 258 | [[package]] 259 | name = "windows-targets" 260 | version = "0.42.2" 261 | source = "registry+https://github.com/rust-lang/crates.io-index" 262 | checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" 263 | dependencies = [ 264 | "windows_aarch64_gnullvm", 265 | "windows_aarch64_msvc", 266 | "windows_i686_gnu", 267 | "windows_i686_msvc", 268 | "windows_x86_64_gnu", 269 | "windows_x86_64_gnullvm", 270 | "windows_x86_64_msvc", 271 | ] 272 | 273 | [[package]] 274 | name = "windows_aarch64_gnullvm" 275 | version = "0.42.2" 276 | source = "registry+https://github.com/rust-lang/crates.io-index" 277 | checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" 278 | 279 | [[package]] 280 | name = "windows_aarch64_msvc" 281 | version = "0.42.2" 282 | source = "registry+https://github.com/rust-lang/crates.io-index" 283 | checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" 284 | 285 | [[package]] 286 | name = "windows_i686_gnu" 287 | version = "0.42.2" 288 | source = "registry+https://github.com/rust-lang/crates.io-index" 289 | checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" 290 | 291 | [[package]] 292 | name = "windows_i686_msvc" 293 | version = "0.42.2" 294 | source = "registry+https://github.com/rust-lang/crates.io-index" 295 | checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" 296 | 297 | [[package]] 298 | name = "windows_x86_64_gnu" 299 | version = "0.42.2" 300 | source = "registry+https://github.com/rust-lang/crates.io-index" 301 | checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" 302 | 303 | [[package]] 304 | name = "windows_x86_64_gnullvm" 305 | version = "0.42.2" 306 | source = "registry+https://github.com/rust-lang/crates.io-index" 307 | checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" 308 | 309 | [[package]] 310 | name = "windows_x86_64_msvc" 311 | version = "0.42.2" 312 | source = "registry+https://github.com/rust-lang/crates.io-index" 313 | checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" 314 | -------------------------------------------------------------------------------- /app/pong/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "pong" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | tdriver = { path = "../tdriver" } 8 | 9 | # Don't ever use this for riscv builds or they will be massive 10 | [profile.dev] 11 | 12 | [profile.release] 13 | panic = "abort" 14 | # Use either 2, 3, s or z 15 | opt-level = 3 16 | overflow-checks = false 17 | lto = true 18 | 19 | -------------------------------------------------------------------------------- /app/pong/copy-bin.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/sh 2 | 3 | # Helper script to copy file to txt file format WireHead expects 4 | # Example: ./copy_bin.sh /tmp/in.txt 5 | 6 | # Rebuild project 7 | cargo rbuild 8 | 9 | # Convert from elf to bin 10 | # Fancy glob matching! https://zsh.sourceforge.io/Doc/Release/Expansion.html#Glob-Qualifiers 11 | # rust-objcopy -O binary ./target/riscv32i-unknown-none-elf/release/*(x.) /tmp/rust.bin 12 | rust-objcopy -O binary ./target/riscv32i-unknown-none-elf/release/pong /tmp/rust.bin 13 | 14 | # Convert from bin to txt 15 | hexdump -ve '1/1 "%.2x "' /tmp/rust.bin | head -c -1 > $1 16 | 17 | -------------------------------------------------------------------------------- /app/pong/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | use tdriver::entry; 5 | use tdriver::graphics; 6 | use tdriver::graphics::WIDTH; 7 | use tdriver::graphics::HEIGHT; 8 | 9 | entry!(main); 10 | 11 | 12 | // Entry point of user code 13 | fn main() -> ! { 14 | let mut pixels: [u64; graphics::HEIGHT] = [0x0000000000000000; graphics::HEIGHT]; 15 | let mut ball_pos: (usize, usize) = ((WIDTH / 2) as usize, (HEIGHT / 2) as usize); 16 | let mut ball_vel: (i8, i8) = (3, 1); 17 | let mut screen = graphics::init(); 18 | 19 | let mut p_left = HEIGHT / 2; 20 | let mut p_right = HEIGHT / 2; 21 | let p_size: usize = 5; 22 | 23 | // Init paddles 24 | for i in p_left-p_size..=p_left+p_size { 25 | let data: u32 = 0x00000001; 26 | graphics::write_line(&mut screen, data, i, 0); 27 | pixels[i] |= (0xFFFFFFFF & data) as u64; 28 | } 29 | for i in p_right-p_size..=p_right+p_size { 30 | let data: u32 = 0x80000000; 31 | graphics::write_line(&mut screen, data, i, 1); 32 | pixels[i] |= (data as u64) << 32; 33 | } 34 | graphics::update(&mut screen); 35 | 36 | loop { 37 | // Move left platform 38 | let input = graphics::input(&mut screen); 39 | let up = input & graphics::input_flags::UP != 0; 40 | let down = input & graphics::input_flags::DOWN != 0; 41 | 42 | if up && down {} 43 | else if down { 44 | if p_left + p_size < HEIGHT - 1 { 45 | graphics::write_line(&mut screen, 0, p_left-p_size, 0); 46 | pixels[p_left-p_size] &= !1; 47 | graphics::write_line(&mut screen, 1, p_left+p_size, 0); 48 | pixels[p_left+p_size] |= 1; 49 | p_left += 1; 50 | } 51 | } else if up { 52 | if p_left - p_size > 0 { 53 | graphics::write_line(&mut screen, 1, p_left-p_size, 0); 54 | pixels[p_left-p_size] |= 1; 55 | graphics::write_line(&mut screen, 0, p_left+p_size, 0); 56 | pixels[p_left+p_size] &= !1; 57 | p_left -= 1; 58 | } 59 | } 60 | 61 | // Move right platform 62 | let defense_right = ball_vel.0 > 0; 63 | if (defense_right && ball_pos.1 > p_right) || (!defense_right && p_right < HEIGHT / 2) { 64 | if p_right + p_size < HEIGHT - 1 { 65 | graphics::write_line(&mut screen, 0, p_right-p_size, 1); 66 | pixels[p_right-p_size] &= !(1 << 63); 67 | graphics::write_line(&mut screen, 1 << 31, p_right+p_size, 1); 68 | pixels[p_right+p_size] |= 1 << 63; 69 | p_right += 1; 70 | } 71 | } else { 72 | if p_right - p_size > 0 { 73 | graphics::write_line(&mut screen, 1 << 31, p_right-p_size, 1); 74 | pixels[p_right-p_size] |= 1 << 63; 75 | graphics::write_line(&mut screen, 0, p_right+p_size, 1); 76 | pixels[p_right+p_size] &= !(1 << 63); 77 | p_right -= 1; 78 | } 79 | } 80 | 81 | // Erase old ball 82 | let mut word = ball_pos.0 / 32; 83 | if !(ball_pos.0 == 0 && ball_pos.1 >= p_left - p_size && ball_pos.1 <= p_left + p_size) && 84 | !(ball_pos.0 == WIDTH-1 && ball_pos.1 >= p_right - p_size && ball_pos.1 <= p_right + p_size) { 85 | pixels[ball_pos.1 as usize] &= !(1 << ball_pos.0); 86 | } 87 | graphics::write_line(&mut screen, (pixels[ball_pos.1 as usize] >> (32 * word)) as u32, ball_pos.1, word); 88 | 89 | // Update new ball position 90 | ball_pos = ((ball_pos.0 as i8 + ball_vel.0) as usize, (ball_pos.1 as i8 + ball_vel.1) as usize); 91 | 92 | // If close snap to edge 93 | if ball_vel.0 < 0 && ball_pos.0 <= -ball_vel.0 as usize + 1 { ball_pos.0 = 1; ball_vel.0 *= -1 } 94 | if ball_vel.0 > 0 && ball_pos.0 >= WIDTH - ball_vel.0 as usize { ball_pos.0 = WIDTH-2; ball_vel.0 *= -1 } 95 | 96 | // Bounce 97 | if ball_pos.0 as i8 + ball_vel.0 < 0 { 98 | ball_vel.0 *= -1; 99 | } 100 | else if ball_pos.0 as i8 + ball_vel.0 >= WIDTH as i8 { 101 | ball_vel.0 *= -1; 102 | } 103 | if ball_pos.1 as i8 + ball_vel.1 < 1 || ball_pos.1 as i8 + ball_vel.1 >= HEIGHT as i8 { 104 | ball_vel.1 *= -1; 105 | } 106 | // Draw new ball 107 | word = ball_pos.0 / 32; 108 | pixels[ball_pos.1 as usize] |= 1 << ball_pos.0; 109 | graphics::write_line(&mut screen, (pixels[ball_pos.1 as usize] >> (32 * word)) as u32, ball_pos.1, word); 110 | graphics::update(&mut screen); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /app/tdriver/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [target.riscv32i-unknown-none-elf] 2 | rustflags = ["-C", "link-arg=-Tlink.x"] 3 | 4 | [env] 5 | EMU_TICK_RATE = "100" 6 | 7 | [alias] 8 | rbuild = "build --target riscv32i-unknown-none-elf --release" 9 | rb = "rbuild" 10 | 11 | rdoc = "doc --target riscv32i-unknown-none-elf --release" 12 | rd = "rdoc" 13 | 14 | -------------------------------------------------------------------------------- /app/tdriver/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /app/tdriver/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "autocfg" 7 | version = "1.1.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 10 | 11 | [[package]] 12 | name = "bitflags" 13 | version = "1.3.2" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 16 | 17 | [[package]] 18 | name = "cassowary" 19 | version = "0.3.0" 20 | source = "registry+https://github.com/rust-lang/crates.io-index" 21 | checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" 22 | 23 | [[package]] 24 | name = "cfg-if" 25 | version = "1.0.0" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 28 | 29 | [[package]] 30 | name = "crossterm" 31 | version = "0.25.0" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | checksum = "e64e6c0fbe2c17357405f7c758c1ef960fce08bdfb2c03d88d2a18d7e09c4b67" 34 | dependencies = [ 35 | "bitflags", 36 | "crossterm_winapi", 37 | "libc", 38 | "mio", 39 | "parking_lot", 40 | "signal-hook", 41 | "signal-hook-mio", 42 | "winapi", 43 | ] 44 | 45 | [[package]] 46 | name = "crossterm" 47 | version = "0.26.1" 48 | source = "registry+https://github.com/rust-lang/crates.io-index" 49 | checksum = "a84cda67535339806297f1b331d6dd6320470d2a0fe65381e79ee9e156dd3d13" 50 | dependencies = [ 51 | "bitflags", 52 | "crossterm_winapi", 53 | "libc", 54 | "mio", 55 | "parking_lot", 56 | "signal-hook", 57 | "signal-hook-mio", 58 | "winapi", 59 | ] 60 | 61 | [[package]] 62 | name = "crossterm_winapi" 63 | version = "0.9.0" 64 | source = "registry+https://github.com/rust-lang/crates.io-index" 65 | checksum = "2ae1b35a484aa10e07fe0638d02301c5ad24de82d310ccbd2f3693da5f09bf1c" 66 | dependencies = [ 67 | "winapi", 68 | ] 69 | 70 | [[package]] 71 | name = "libc" 72 | version = "0.2.140" 73 | source = "registry+https://github.com/rust-lang/crates.io-index" 74 | checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" 75 | 76 | [[package]] 77 | name = "lock_api" 78 | version = "0.4.9" 79 | source = "registry+https://github.com/rust-lang/crates.io-index" 80 | checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" 81 | dependencies = [ 82 | "autocfg", 83 | "scopeguard", 84 | ] 85 | 86 | [[package]] 87 | name = "log" 88 | version = "0.4.17" 89 | source = "registry+https://github.com/rust-lang/crates.io-index" 90 | checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" 91 | dependencies = [ 92 | "cfg-if", 93 | ] 94 | 95 | [[package]] 96 | name = "mio" 97 | version = "0.8.6" 98 | source = "registry+https://github.com/rust-lang/crates.io-index" 99 | checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" 100 | dependencies = [ 101 | "libc", 102 | "log", 103 | "wasi", 104 | "windows-sys", 105 | ] 106 | 107 | [[package]] 108 | name = "parking_lot" 109 | version = "0.12.1" 110 | source = "registry+https://github.com/rust-lang/crates.io-index" 111 | checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" 112 | dependencies = [ 113 | "lock_api", 114 | "parking_lot_core", 115 | ] 116 | 117 | [[package]] 118 | name = "parking_lot_core" 119 | version = "0.9.7" 120 | source = "registry+https://github.com/rust-lang/crates.io-index" 121 | checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" 122 | dependencies = [ 123 | "cfg-if", 124 | "libc", 125 | "redox_syscall", 126 | "smallvec", 127 | "windows-sys", 128 | ] 129 | 130 | [[package]] 131 | name = "ratatui" 132 | version = "0.20.1" 133 | source = "registry+https://github.com/rust-lang/crates.io-index" 134 | checksum = "dcc0d032bccba900ee32151ec0265667535c230169f5a011154cdcd984e16829" 135 | dependencies = [ 136 | "bitflags", 137 | "cassowary", 138 | "crossterm 0.26.1", 139 | "unicode-segmentation", 140 | "unicode-width", 141 | ] 142 | 143 | [[package]] 144 | name = "redox_syscall" 145 | version = "0.2.16" 146 | source = "registry+https://github.com/rust-lang/crates.io-index" 147 | checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" 148 | dependencies = [ 149 | "bitflags", 150 | ] 151 | 152 | [[package]] 153 | name = "scopeguard" 154 | version = "1.1.0" 155 | source = "registry+https://github.com/rust-lang/crates.io-index" 156 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 157 | 158 | [[package]] 159 | name = "signal-hook" 160 | version = "0.3.15" 161 | source = "registry+https://github.com/rust-lang/crates.io-index" 162 | checksum = "732768f1176d21d09e076c23a93123d40bba92d50c4058da34d45c8de8e682b9" 163 | dependencies = [ 164 | "libc", 165 | "signal-hook-registry", 166 | ] 167 | 168 | [[package]] 169 | name = "signal-hook-mio" 170 | version = "0.2.3" 171 | source = "registry+https://github.com/rust-lang/crates.io-index" 172 | checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" 173 | dependencies = [ 174 | "libc", 175 | "mio", 176 | "signal-hook", 177 | ] 178 | 179 | [[package]] 180 | name = "signal-hook-registry" 181 | version = "1.4.1" 182 | source = "registry+https://github.com/rust-lang/crates.io-index" 183 | checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" 184 | dependencies = [ 185 | "libc", 186 | ] 187 | 188 | [[package]] 189 | name = "smallvec" 190 | version = "1.10.0" 191 | source = "registry+https://github.com/rust-lang/crates.io-index" 192 | checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" 193 | 194 | [[package]] 195 | name = "tdriver" 196 | version = "0.1.0" 197 | dependencies = [ 198 | "crossterm 0.25.0", 199 | "ratatui", 200 | ] 201 | 202 | [[package]] 203 | name = "unicode-segmentation" 204 | version = "1.10.1" 205 | source = "registry+https://github.com/rust-lang/crates.io-index" 206 | checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" 207 | 208 | [[package]] 209 | name = "unicode-width" 210 | version = "0.1.10" 211 | source = "registry+https://github.com/rust-lang/crates.io-index" 212 | checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" 213 | 214 | [[package]] 215 | name = "wasi" 216 | version = "0.11.0+wasi-snapshot-preview1" 217 | source = "registry+https://github.com/rust-lang/crates.io-index" 218 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 219 | 220 | [[package]] 221 | name = "winapi" 222 | version = "0.3.9" 223 | source = "registry+https://github.com/rust-lang/crates.io-index" 224 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 225 | dependencies = [ 226 | "winapi-i686-pc-windows-gnu", 227 | "winapi-x86_64-pc-windows-gnu", 228 | ] 229 | 230 | [[package]] 231 | name = "winapi-i686-pc-windows-gnu" 232 | version = "0.4.0" 233 | source = "registry+https://github.com/rust-lang/crates.io-index" 234 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 235 | 236 | [[package]] 237 | name = "winapi-x86_64-pc-windows-gnu" 238 | version = "0.4.0" 239 | source = "registry+https://github.com/rust-lang/crates.io-index" 240 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 241 | 242 | [[package]] 243 | name = "windows-sys" 244 | version = "0.45.0" 245 | source = "registry+https://github.com/rust-lang/crates.io-index" 246 | checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" 247 | dependencies = [ 248 | "windows-targets", 249 | ] 250 | 251 | [[package]] 252 | name = "windows-targets" 253 | version = "0.42.2" 254 | source = "registry+https://github.com/rust-lang/crates.io-index" 255 | checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" 256 | dependencies = [ 257 | "windows_aarch64_gnullvm", 258 | "windows_aarch64_msvc", 259 | "windows_i686_gnu", 260 | "windows_i686_msvc", 261 | "windows_x86_64_gnu", 262 | "windows_x86_64_gnullvm", 263 | "windows_x86_64_msvc", 264 | ] 265 | 266 | [[package]] 267 | name = "windows_aarch64_gnullvm" 268 | version = "0.42.2" 269 | source = "registry+https://github.com/rust-lang/crates.io-index" 270 | checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" 271 | 272 | [[package]] 273 | name = "windows_aarch64_msvc" 274 | version = "0.42.2" 275 | source = "registry+https://github.com/rust-lang/crates.io-index" 276 | checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" 277 | 278 | [[package]] 279 | name = "windows_i686_gnu" 280 | version = "0.42.2" 281 | source = "registry+https://github.com/rust-lang/crates.io-index" 282 | checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" 283 | 284 | [[package]] 285 | name = "windows_i686_msvc" 286 | version = "0.42.2" 287 | source = "registry+https://github.com/rust-lang/crates.io-index" 288 | checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" 289 | 290 | [[package]] 291 | name = "windows_x86_64_gnu" 292 | version = "0.42.2" 293 | source = "registry+https://github.com/rust-lang/crates.io-index" 294 | checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" 295 | 296 | [[package]] 297 | name = "windows_x86_64_gnullvm" 298 | version = "0.42.2" 299 | source = "registry+https://github.com/rust-lang/crates.io-index" 300 | checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" 301 | 302 | [[package]] 303 | name = "windows_x86_64_msvc" 304 | version = "0.42.2" 305 | source = "registry+https://github.com/rust-lang/crates.io-index" 306 | checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" 307 | -------------------------------------------------------------------------------- /app/tdriver/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "tdriver" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [profile.dev] 7 | 8 | # [target.'cfg(target_arch="riscv32")'.profile.release] 9 | [profile.release] 10 | panic = "abort" 11 | opt-level = "z" 12 | overflow-checks = false 13 | lto = true 14 | 15 | [target.'cfg(not(target_arch = "riscv32"))'.dependencies] 16 | tui = { package = "ratatui", version = "0.20.1" } 17 | crossterm = "0.25" 18 | 19 | -------------------------------------------------------------------------------- /app/tdriver/build.rs: -------------------------------------------------------------------------------- 1 | use std::{env, error::Error, fs::File, io::Write, path::PathBuf}; 2 | 3 | fn main() -> Result<(), Box> { 4 | // build directory for this crate 5 | let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); 6 | 7 | // extend the library search path 8 | println!("cargo:rustc-link-search={}", out_dir.display()); 9 | 10 | // put `link.x` in the build directory 11 | File::create(out_dir.join("link.x"))?.write_all(include_bytes!("link.x"))?; 12 | 13 | Ok(()) 14 | } 15 | -------------------------------------------------------------------------------- /app/tdriver/link.x: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | FLASH (rx) : ORIGIN = 0x00000000, LENGTH = 768K 4 | RAM (rwx) : ORIGIN = 0x00100000, LENGTH = 368K 5 | /* Memory mapped io */ 6 | SCREEN (w) : ORIGIN = 0x00200000, LENGTH = 16K 7 | BW_SCREEN (rw) : ORIGIN = 0x0020E000, LENGTH = 8K 8 | } 9 | 10 | /* The entry point is the reset handler */ 11 | ENTRY(Reset); 12 | 13 | SECTIONS 14 | { 15 | .text : 16 | { 17 | KEEP(*(.text.start)); 18 | *(.text.reset); 19 | *(.text .text.*); 20 | } > FLASH 21 | 22 | .rodata : 23 | { 24 | *(.rodata .rodata.*); 25 | } > FLASH 26 | 27 | .bss : 28 | { 29 | _sbss = .; 30 | *(.bss .bss.*); 31 | _ebss = .; 32 | } > RAM 33 | 34 | .data : AT(ADDR(.rodata) + SIZEOF(.rodata)) 35 | { 36 | _sdata = .; 37 | *(.data .data.*); 38 | _edata = .; 39 | } > RAM 40 | 41 | _sidata = LOADADDR(.data); 42 | _stack_start = ORIGIN(RAM) + LENGTH(RAM); 43 | 44 | 45 | } 46 | -------------------------------------------------------------------------------- /app/tdriver/rust-analyzer.toml: -------------------------------------------------------------------------------- 1 | [diagnostics] 2 | disabled = ["inactive-code"] 3 | -------------------------------------------------------------------------------- /app/tdriver/src/graphics.rs: -------------------------------------------------------------------------------- 1 | #[cfg(not(target_arch = "riscv32"))] 2 | use { 3 | tui::{ 4 | backend::{Backend, CrosstermBackend}, 5 | layout::{Constraint, Direction, Layout}, 6 | widgets::{ 7 | Block, Borders, 8 | canvas::{Canvas, Rectangle}, 9 | }, 10 | style::Color, 11 | Terminal, symbols, Frame, 12 | }, 13 | std::{io, time::{Duration, Instant}, process}, 14 | crossterm::{ 15 | event::{self, DisableMouseCapture, EnableMouseCapture, Event, KeyCode}, 16 | execute, 17 | terminal::{disable_raw_mode, enable_raw_mode, EnterAlternateScreen, LeaveAlternateScreen}, 18 | }, 19 | }; 20 | 21 | /****************************************************************************** 22 | * Constants 23 | ******************************************************************************/ 24 | 25 | /// Number of pixels in horizontal direction 26 | pub const WIDTH: usize = 64; 27 | /// Number of pixels in vertical direction 28 | pub const HEIGHT: usize = 48; 29 | 30 | /// Width in number of 32 bit words that can fit horizontally 31 | pub const WORDS: usize = WIDTH / 32; 32 | 33 | /// Bitflag definitions for controller inputs 34 | pub mod input_flags { 35 | pub const DOWN: u32 = 0b0001; 36 | pub const LEFT: u32 = 0b0010; 37 | pub const RIGHT: u32 = 0b0100; 38 | pub const UP: u32 = 0b1000; 39 | } 40 | 41 | /****************************************************************************** 42 | * Types 43 | ******************************************************************************/ 44 | 45 | /** 46 | * Struct describing the current state of screen 47 | */ 48 | pub struct Screen { 49 | #[cfg(target_arch = "riscv32")] 50 | base_addr: *mut u32, 51 | #[cfg(target_arch = "riscv32")] 52 | update_addr: *mut u32, 53 | #[cfg(target_arch = "riscv32")] 54 | input_addr: *mut u32, 55 | 56 | #[cfg(not(target_arch = "riscv32"))] 57 | terminal: Terminal>, 58 | #[cfg(not(target_arch = "riscv32"))] 59 | state: [[bool; WIDTH]; HEIGHT], 60 | #[cfg(not(target_arch = "riscv32"))] 61 | tick_rate: Duration, 62 | #[cfg(not(target_arch = "riscv32"))] 63 | last_tick: Instant, 64 | #[cfg(not(target_arch = "riscv32"))] 65 | input: u32, 66 | } 67 | 68 | 69 | /****************************************************************************** 70 | * x86 HAL 71 | ******************************************************************************/ 72 | 73 | #[cfg(not(target_arch = "riscv32"))] 74 | fn write_screen(screen: &mut Screen) { 75 | while screen.last_tick.elapsed() < screen.tick_rate { 76 | screen.terminal.draw(|f| { ui(f, &screen.state) }).unwrap(); 77 | if event::poll(Duration::from_millis(0)).unwrap() { 78 | if let Event::Key(key) = event::read().unwrap() { 79 | match key.code { 80 | KeyCode::Char('q') => { 81 | disable_raw_mode().unwrap(); 82 | execute!( 83 | screen.terminal.backend_mut(), 84 | LeaveAlternateScreen, 85 | DisableMouseCapture 86 | ).unwrap(); 87 | screen.terminal.show_cursor().unwrap(); 88 | process::exit(0) 89 | }, 90 | KeyCode::Char('w') => screen.input |= input_flags::UP, 91 | KeyCode::Char('d') => screen.input |= input_flags::RIGHT, 92 | KeyCode::Char('a') => screen.input |= input_flags::LEFT, 93 | KeyCode::Char('s') => screen.input |= input_flags::DOWN, 94 | _ => {} 95 | } 96 | } 97 | } 98 | } 99 | 100 | screen.last_tick = Instant::now(); 101 | } 102 | 103 | #[cfg(not(target_arch = "riscv32"))] 104 | fn ui(f: &mut Frame, state: &[[bool; WIDTH]; HEIGHT]) { 105 | let vertical_chunks = Layout::default() 106 | .direction(Direction::Vertical) 107 | .constraints( 108 | [ 109 | Constraint::Length((HEIGHT) as u16), Constraint::Min(0) 110 | ].as_ref() 111 | ) 112 | .split(f.size()); 113 | 114 | let chunks = Layout::default() 115 | .direction(Direction::Horizontal) 116 | .constraints( 117 | [ 118 | Constraint::Length(((WIDTH+1) * 2) as u16), Constraint::Min(0) 119 | ].as_ref() 120 | ) 121 | .split(vertical_chunks[0]); 122 | 123 | let canvas = Canvas::default() 124 | .marker(symbols::Marker::Braille) 125 | .block(Block::default().borders(Borders::ALL).title("Screen")) 126 | .paint(|ctx| { 127 | for h in 0..state.len() { 128 | for w in 0..state[0].len() { 129 | if state[h][w] { 130 | ctx.draw(&Rectangle { 131 | x: w as f64, y: HEIGHT as f64 - h as f64-1.0, 132 | width: 1.0, height: 1.0, 133 | color: Color::White 134 | }); 135 | } 136 | } 137 | } 138 | }) 139 | .x_bounds([0.0, WIDTH as f64]) 140 | .y_bounds([0.0, HEIGHT as f64]); 141 | f.render_widget(canvas, chunks[0]); 142 | } 143 | 144 | /****************************************************************************** 145 | * Public Functions 146 | ******************************************************************************/ 147 | 148 | /** 149 | * Initializes screen and returns screen struct 150 | */ 151 | pub fn init() -> Screen { 152 | 153 | #[cfg(target_arch = "riscv32")] { 154 | Screen { 155 | base_addr: 0x20E000 as *mut u32, 156 | update_addr: 0x20E1FC as *mut u32, 157 | input_addr: 0x20E1F8 as *mut u32, 158 | } 159 | } 160 | 161 | #[cfg(not(target_arch = "riscv32"))] { 162 | enable_raw_mode().unwrap(); 163 | let mut stdout = io::stdout(); 164 | execute!(stdout, EnterAlternateScreen, EnableMouseCapture).unwrap(); 165 | let backend = CrosstermBackend::new(stdout); 166 | let terminal = Terminal::new(backend).unwrap(); 167 | 168 | let mut screen = Screen { 169 | terminal, 170 | state: [[false; WIDTH]; HEIGHT], 171 | tick_rate: Duration::from_millis( 172 | std::option_env!("EMU_TICK_RATE").unwrap_or("100").parse().unwrap() 173 | // std::env!("EMU_TICK_RATE").parse().unwrap() 174 | ), 175 | last_tick: Instant::now(), 176 | input: 0, 177 | }; 178 | 179 | write_screen(&mut screen); 180 | 181 | screen 182 | }} 183 | 184 | /** 185 | * Writes a pixel array into screen as implemented in hardware 186 | */ 187 | pub fn write_raw(screen: &mut Screen, pixels: &[[u32; WORDS]; HEIGHT]) { 188 | 189 | #[cfg(target_arch = "riscv32")] { 190 | unsafe { 191 | for w in 0..WORDS { 192 | for h in 0..HEIGHT{ 193 | screen.base_addr.add(w + WORDS * h).write_volatile(pixels[h][w]); 194 | } 195 | } 196 | } 197 | } 198 | 199 | #[cfg(not(target_arch = "riscv32"))] { 200 | for h in 0..screen.state.len() { 201 | for w in 0..screen.state[0].len() { 202 | screen.state[h][w] = (pixels[h][w/32] >> (w%32)) & 0b1 == 1 203 | } 204 | } 205 | }} 206 | 207 | 208 | /** 209 | * Equivalent to write_raw except with u64 instead of [u32; 2] 210 | */ 211 | pub fn write_long(screen: &mut Screen, pixels: &[u64; HEIGHT]) { 212 | 213 | #[cfg(target_arch = "riscv32")] { 214 | unsafe { 215 | for h in 0..pixels.len(){ 216 | screen.base_addr.add(2 * h).write_volatile(pixels[h] as u32); 217 | screen.base_addr.add(2 * h + 1).write_volatile((pixels[h] >> 32) as u32); 218 | } 219 | } 220 | } 221 | 222 | #[cfg(not(target_arch = "riscv32"))] { 223 | for h in 0..screen.state.len() { 224 | for w in 0..screen.state[0].len() { 225 | screen.state[h][w] = (pixels[h] >> w) & 0b1 == 1 226 | } 227 | } 228 | }} 229 | 230 | /** 231 | * Writes a line to screen at a specified row, word is 0 for lower word and 1 for upper 232 | */ 233 | pub fn write_line(screen: &mut Screen, data: u32, row: usize, word: usize) { 234 | 235 | #[cfg(target_arch = "riscv32")] { 236 | unsafe { 237 | screen.base_addr.add((2*row + word) as usize).write_volatile(data); 238 | } 239 | } 240 | 241 | #[cfg(not(target_arch = "riscv32"))] { 242 | for w in 0..32 { 243 | screen.state[row as usize][(word * 32 + w) as usize] = (data >> w) & 0b1 == 1; 244 | } 245 | }} 246 | 247 | /** 248 | * Updates screen by writing to screen register 249 | */ 250 | pub fn update(screen: &mut Screen) { 251 | 252 | #[cfg(target_arch = "riscv32")] { 253 | unsafe { 254 | screen.update_addr.write_volatile(0b1); 255 | } 256 | } 257 | 258 | #[cfg(not(target_arch = "riscv32"))] { 259 | write_screen(screen); 260 | }} 261 | 262 | /** 263 | * Reads input from controller since last call to this 264 | * 265 | * Returns a bitmask of the buttons pressed, see input_flags for bit position 266 | * definitions 267 | */ 268 | pub fn input(screen: &mut Screen) -> u32 { 269 | 270 | #[cfg(target_arch = "riscv32")] { 271 | unsafe { 272 | return screen.input_addr.read_volatile() 273 | } 274 | } 275 | 276 | #[cfg(not(target_arch = "riscv32"))] { 277 | let input: u32 = screen.input; 278 | screen.input = 0; 279 | input 280 | }} 281 | 282 | /****************************************************************************** 283 | * Legacy Functions 284 | ******************************************************************************/ 285 | 286 | /** 287 | * Sanity check to ensure all pixels in screen work by running a pixel accross the entire screen 288 | * 289 | * This is kept as super low level/hardcoded intentionally to prevent other stuff in this module 290 | * from breaking this, might change this later when I'm more confident in my code 291 | */ 292 | #[cfg(target_arch = "riscv32")] 293 | pub fn sanity_check() { 294 | let screen: *mut u32 = 0x1E000 as *mut u32; 295 | let screen_write: *mut u32 = 0x1E1FC as *mut u32; 296 | unsafe { 297 | for i in 0..96 { 298 | for j in 0..32 { 299 | screen.add(i).write_volatile(1 << j); 300 | screen_write.write_volatile(1); 301 | } 302 | screen.add(i).write_volatile(0); 303 | } 304 | } 305 | } 306 | 307 | -------------------------------------------------------------------------------- /app/tdriver/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Conditional version of #![no_std] 2 | #![cfg_attr(target_arch = "riscv32", no_std)] 3 | 4 | #[cfg(target_arch = "riscv32")] 5 | use { 6 | core::arch::global_asm, 7 | core::panic::PanicInfo, 8 | core::ptr, 9 | }; 10 | 11 | 12 | pub mod graphics; 13 | 14 | /****************************************************************************** 15 | * Reset handling 16 | ******************************************************************************/ 17 | 18 | // Init stack pointer 19 | // This has to be before Reset in linker script since otherwise function can't 20 | // enter 21 | #[cfg(target_arch = "riscv32")] 22 | global_asm!(" 23 | .section .text.start 24 | la sp, _stack_start 25 | "); 26 | 27 | // Entry point of program 28 | // Sets up abi and initializes memory 29 | #[no_mangle] 30 | #[link_section = ".text.reset"] 31 | #[cfg(target_arch = "riscv32")] 32 | unsafe extern "C" fn Reset() -> ! { 33 | 34 | // Occasionaly useful for debuggin, should write to screen 35 | // If it doesn't then something is probably wrong with hardware 36 | // let base_addr = 0x20E000 as *mut u32; 37 | // let update_addr = 0x20E1FC as *mut u32; 38 | // base_addr.write_volatile(0b11111111111110010011); 39 | // update_addr.write_volatile(0b101); 40 | 41 | // Initialize RAM 42 | extern "C" { 43 | static mut _sbss: u8; 44 | static mut _ebss: u8; 45 | 46 | static mut _sdata: u8; 47 | static mut _edata: u8; 48 | static _sidata: u8; 49 | } 50 | 51 | // Copy static variables 52 | let count = &_ebss as *const u8 as usize - &_sbss as *const u8 as usize; 53 | ptr::write_bytes(&mut _sbss as *mut u8, 0, count); 54 | 55 | let count = &_edata as *const u8 as usize - &_sdata as *const u8 as usize; 56 | ptr::copy_nonoverlapping(&_sidata as *const u8, &mut _sdata as *mut u8, count); 57 | 58 | extern "Rust" { 59 | fn main() -> !; 60 | } 61 | 62 | main() 63 | } 64 | 65 | #[panic_handler] 66 | #[cfg(target_arch = "riscv32")] 67 | fn panic(_info: &PanicInfo) -> ! { 68 | loop {} 69 | } 70 | 71 | /****************************************************************************** 72 | * Macros 73 | ******************************************************************************/ 74 | 75 | /** 76 | * Macro to define entry point of program in a type safe way. 77 | * 78 | * To use, define a divergent function (a function with `-> !`) and call this macro: 79 | * ``` 80 | * entry!(main); 81 | * 82 | * fn main() -> ! { 83 | * // Your code here 84 | * } 85 | * ``` 86 | */ 87 | #[macro_export] 88 | macro_rules! entry { 89 | ($path:path) => { 90 | #[export_name = "main"] 91 | pub unsafe fn __main() -> ! { 92 | // type check the given path 93 | let f: fn() -> ! = $path; 94 | 95 | f() 96 | } 97 | } 98 | } 99 | 100 | -------------------------------------------------------------------------------- /app/template/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [target.riscv32i-unknown-none-elf] 2 | rustflags = ["-C", "link-arg=-Tlink.x"] 3 | 4 | [env] 5 | EMU_TICK_RATE = "100" 6 | 7 | [alias] 8 | rbuild = "build --release --target riscv32i-unknown-none-elf" 9 | rb = "rbuild" 10 | 11 | rdoc = "doc --release --target riscv32i-unknown-none-elf" 12 | rd = "rdoc" 13 | 14 | rsize = "size --release --target riscv32i-unknown-none-elf" 15 | rs = "rsize" 16 | 17 | robjdump = "objdump --release --target riscv32i-unknown-none-elf" 18 | rod = "robjdump" 19 | 20 | -------------------------------------------------------------------------------- /app/template/.vimspector.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": { 3 | "Launch": { 4 | "adapter": "vscode-cpptools", 5 | "filetypes": [ "cpp", "c", "objc", "rust" ], 6 | "configuration": { 7 | "request": "launch", 8 | "program": "${workspaceRoot}/target/x86_64-unknown-linux-gnu/debug/template", 9 | "args": [], 10 | "cwd": ".", 11 | "environment": [], 12 | "externalConsole": true, 13 | "MIMode": "gdb", 14 | "stopAtEntry": true 15 | } 16 | }, 17 | "Attach": { 18 | "adapter": "vscode-cpptools", 19 | "filetypes": [ "cpp", "c", "objc", "rust" ], 20 | "configuration": { 21 | "request": "attach", 22 | "program": "${workspaceRoot}/target/x86_64-unknown-linux-gnu/debug/template", 23 | "MIMode": "gdb", 24 | "stopAtEntry": true 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/template/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "autocfg" 7 | version = "1.1.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 10 | 11 | [[package]] 12 | name = "bitflags" 13 | version = "1.3.2" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 16 | 17 | [[package]] 18 | name = "cassowary" 19 | version = "0.3.0" 20 | source = "registry+https://github.com/rust-lang/crates.io-index" 21 | checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" 22 | 23 | [[package]] 24 | name = "cfg-if" 25 | version = "1.0.0" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 28 | 29 | [[package]] 30 | name = "crossterm" 31 | version = "0.25.0" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | checksum = "e64e6c0fbe2c17357405f7c758c1ef960fce08bdfb2c03d88d2a18d7e09c4b67" 34 | dependencies = [ 35 | "bitflags", 36 | "crossterm_winapi", 37 | "libc", 38 | "mio", 39 | "parking_lot", 40 | "signal-hook", 41 | "signal-hook-mio", 42 | "winapi", 43 | ] 44 | 45 | [[package]] 46 | name = "crossterm" 47 | version = "0.26.1" 48 | source = "registry+https://github.com/rust-lang/crates.io-index" 49 | checksum = "a84cda67535339806297f1b331d6dd6320470d2a0fe65381e79ee9e156dd3d13" 50 | dependencies = [ 51 | "bitflags", 52 | "crossterm_winapi", 53 | "libc", 54 | "mio", 55 | "parking_lot", 56 | "signal-hook", 57 | "signal-hook-mio", 58 | "winapi", 59 | ] 60 | 61 | [[package]] 62 | name = "crossterm_winapi" 63 | version = "0.9.0" 64 | source = "registry+https://github.com/rust-lang/crates.io-index" 65 | checksum = "2ae1b35a484aa10e07fe0638d02301c5ad24de82d310ccbd2f3693da5f09bf1c" 66 | dependencies = [ 67 | "winapi", 68 | ] 69 | 70 | [[package]] 71 | name = "libc" 72 | version = "0.2.140" 73 | source = "registry+https://github.com/rust-lang/crates.io-index" 74 | checksum = "99227334921fae1a979cf0bfdfcc6b3e5ce376ef57e16fb6fb3ea2ed6095f80c" 75 | 76 | [[package]] 77 | name = "lock_api" 78 | version = "0.4.9" 79 | source = "registry+https://github.com/rust-lang/crates.io-index" 80 | checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" 81 | dependencies = [ 82 | "autocfg", 83 | "scopeguard", 84 | ] 85 | 86 | [[package]] 87 | name = "log" 88 | version = "0.4.17" 89 | source = "registry+https://github.com/rust-lang/crates.io-index" 90 | checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" 91 | dependencies = [ 92 | "cfg-if", 93 | ] 94 | 95 | [[package]] 96 | name = "mio" 97 | version = "0.8.6" 98 | source = "registry+https://github.com/rust-lang/crates.io-index" 99 | checksum = "5b9d9a46eff5b4ff64b45a9e316a6d1e0bc719ef429cbec4dc630684212bfdf9" 100 | dependencies = [ 101 | "libc", 102 | "log", 103 | "wasi", 104 | "windows-sys", 105 | ] 106 | 107 | [[package]] 108 | name = "parking_lot" 109 | version = "0.12.1" 110 | source = "registry+https://github.com/rust-lang/crates.io-index" 111 | checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" 112 | dependencies = [ 113 | "lock_api", 114 | "parking_lot_core", 115 | ] 116 | 117 | [[package]] 118 | name = "parking_lot_core" 119 | version = "0.9.7" 120 | source = "registry+https://github.com/rust-lang/crates.io-index" 121 | checksum = "9069cbb9f99e3a5083476ccb29ceb1de18b9118cafa53e90c9551235de2b9521" 122 | dependencies = [ 123 | "cfg-if", 124 | "libc", 125 | "redox_syscall", 126 | "smallvec", 127 | "windows-sys", 128 | ] 129 | 130 | [[package]] 131 | name = "ratatui" 132 | version = "0.20.1" 133 | source = "registry+https://github.com/rust-lang/crates.io-index" 134 | checksum = "dcc0d032bccba900ee32151ec0265667535c230169f5a011154cdcd984e16829" 135 | dependencies = [ 136 | "bitflags", 137 | "cassowary", 138 | "crossterm 0.26.1", 139 | "unicode-segmentation", 140 | "unicode-width", 141 | ] 142 | 143 | [[package]] 144 | name = "redox_syscall" 145 | version = "0.2.16" 146 | source = "registry+https://github.com/rust-lang/crates.io-index" 147 | checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" 148 | dependencies = [ 149 | "bitflags", 150 | ] 151 | 152 | [[package]] 153 | name = "scopeguard" 154 | version = "1.1.0" 155 | source = "registry+https://github.com/rust-lang/crates.io-index" 156 | checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" 157 | 158 | [[package]] 159 | name = "signal-hook" 160 | version = "0.3.15" 161 | source = "registry+https://github.com/rust-lang/crates.io-index" 162 | checksum = "732768f1176d21d09e076c23a93123d40bba92d50c4058da34d45c8de8e682b9" 163 | dependencies = [ 164 | "libc", 165 | "signal-hook-registry", 166 | ] 167 | 168 | [[package]] 169 | name = "signal-hook-mio" 170 | version = "0.2.3" 171 | source = "registry+https://github.com/rust-lang/crates.io-index" 172 | checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" 173 | dependencies = [ 174 | "libc", 175 | "mio", 176 | "signal-hook", 177 | ] 178 | 179 | [[package]] 180 | name = "signal-hook-registry" 181 | version = "1.4.1" 182 | source = "registry+https://github.com/rust-lang/crates.io-index" 183 | checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" 184 | dependencies = [ 185 | "libc", 186 | ] 187 | 188 | [[package]] 189 | name = "smallvec" 190 | version = "1.10.0" 191 | source = "registry+https://github.com/rust-lang/crates.io-index" 192 | checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" 193 | 194 | [[package]] 195 | name = "tdriver" 196 | version = "0.1.0" 197 | dependencies = [ 198 | "crossterm 0.25.0", 199 | "ratatui", 200 | ] 201 | 202 | [[package]] 203 | name = "template" 204 | version = "0.1.0" 205 | dependencies = [ 206 | "tdriver", 207 | ] 208 | 209 | [[package]] 210 | name = "unicode-segmentation" 211 | version = "1.10.1" 212 | source = "registry+https://github.com/rust-lang/crates.io-index" 213 | checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" 214 | 215 | [[package]] 216 | name = "unicode-width" 217 | version = "0.1.10" 218 | source = "registry+https://github.com/rust-lang/crates.io-index" 219 | checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" 220 | 221 | [[package]] 222 | name = "wasi" 223 | version = "0.11.0+wasi-snapshot-preview1" 224 | source = "registry+https://github.com/rust-lang/crates.io-index" 225 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 226 | 227 | [[package]] 228 | name = "winapi" 229 | version = "0.3.9" 230 | source = "registry+https://github.com/rust-lang/crates.io-index" 231 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 232 | dependencies = [ 233 | "winapi-i686-pc-windows-gnu", 234 | "winapi-x86_64-pc-windows-gnu", 235 | ] 236 | 237 | [[package]] 238 | name = "winapi-i686-pc-windows-gnu" 239 | version = "0.4.0" 240 | source = "registry+https://github.com/rust-lang/crates.io-index" 241 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 242 | 243 | [[package]] 244 | name = "winapi-x86_64-pc-windows-gnu" 245 | version = "0.4.0" 246 | source = "registry+https://github.com/rust-lang/crates.io-index" 247 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 248 | 249 | [[package]] 250 | name = "windows-sys" 251 | version = "0.45.0" 252 | source = "registry+https://github.com/rust-lang/crates.io-index" 253 | checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" 254 | dependencies = [ 255 | "windows-targets", 256 | ] 257 | 258 | [[package]] 259 | name = "windows-targets" 260 | version = "0.42.2" 261 | source = "registry+https://github.com/rust-lang/crates.io-index" 262 | checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" 263 | dependencies = [ 264 | "windows_aarch64_gnullvm", 265 | "windows_aarch64_msvc", 266 | "windows_i686_gnu", 267 | "windows_i686_msvc", 268 | "windows_x86_64_gnu", 269 | "windows_x86_64_gnullvm", 270 | "windows_x86_64_msvc", 271 | ] 272 | 273 | [[package]] 274 | name = "windows_aarch64_gnullvm" 275 | version = "0.42.2" 276 | source = "registry+https://github.com/rust-lang/crates.io-index" 277 | checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" 278 | 279 | [[package]] 280 | name = "windows_aarch64_msvc" 281 | version = "0.42.2" 282 | source = "registry+https://github.com/rust-lang/crates.io-index" 283 | checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" 284 | 285 | [[package]] 286 | name = "windows_i686_gnu" 287 | version = "0.42.2" 288 | source = "registry+https://github.com/rust-lang/crates.io-index" 289 | checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" 290 | 291 | [[package]] 292 | name = "windows_i686_msvc" 293 | version = "0.42.2" 294 | source = "registry+https://github.com/rust-lang/crates.io-index" 295 | checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" 296 | 297 | [[package]] 298 | name = "windows_x86_64_gnu" 299 | version = "0.42.2" 300 | source = "registry+https://github.com/rust-lang/crates.io-index" 301 | checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" 302 | 303 | [[package]] 304 | name = "windows_x86_64_gnullvm" 305 | version = "0.42.2" 306 | source = "registry+https://github.com/rust-lang/crates.io-index" 307 | checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" 308 | 309 | [[package]] 310 | name = "windows_x86_64_msvc" 311 | version = "0.42.2" 312 | source = "registry+https://github.com/rust-lang/crates.io-index" 313 | checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" 314 | -------------------------------------------------------------------------------- /app/template/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "template" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | tdriver = { path = "../tdriver" } 8 | 9 | # Don't ever use this for riscv builds or they will be massive 10 | [profile.dev] 11 | 12 | [profile.release] 13 | panic = "abort" 14 | # Use either 2, 3, s or z 15 | opt-level = 3 16 | overflow-checks = false 17 | lto = true 18 | 19 | -------------------------------------------------------------------------------- /app/template/README.md: -------------------------------------------------------------------------------- 1 | # Computerraria Rust Template 2 | 3 | This is a template for building Rust applications targeting [Computerraria](https://github.com/misprit7/computerraria). 4 | 5 | ## Setup 6 | 7 | To set up a new project, run the following: 8 | ```bash 9 | cp -r template PATH/NAME_OF_PROJECT 10 | cd PATH/NAME_OF_PROJECT 11 | sed -i s/template/NAME_OF_PROJECT/ Cargo.toml copy-bin.sh .vimspector.json 12 | cargo build --release 13 | ``` 14 | To actually use the project, you can convert the file to the required [WireHead](https://github.com/misprit7/WireHead) file format with the provided script: 15 | ```bash 16 | ./copy_bin.sh /tmp/in.txt 17 | ``` 18 | You can then load it into Computerraria with the following command, written in the in-game chat (NOT your terminal): 19 | ``` 20 | /bin write /tmp/in.txt 21 | ``` 22 | Once you start the clock the screen should update to be on in the outer horizontal border. 23 | 24 | ## Development 25 | The entrance point of the program is `main` in [`src/main.rs`](src/main.rs), make changes there. You can change the tick rate of the emulator in the `[env]` section of [`.cargo/config.toml`](.cargo/config.toml). 26 | -------------------------------------------------------------------------------- /app/template/copy-bin.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/sh 2 | 3 | # Helper script to copy file to txt file format WireHead expects 4 | # Example: ./copy_bin.sh /tmp/in.txt 5 | 6 | # Rebuild project 7 | cargo rbuild --release 8 | 9 | # Convert from elf to bin 10 | # Fancy glob matching! https://zsh.sourceforge.io/Doc/Release/Expansion.html#Glob-Qualifiers 11 | # rust-objcopy -O binary ./target/riscv32i-unknown-none-elf/release/*(x.) /tmp/rust.bin 12 | rust-objcopy -O binary ./target/riscv32i-unknown-none-elf/release/template /tmp/rust.bin 13 | 14 | # Convert from bin to txt 15 | hexdump -ve '1/1 "%.2x "' /tmp/rust.bin | head -c -1 > $1 16 | 17 | -------------------------------------------------------------------------------- /app/template/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | use tdriver::entry; 5 | use tdriver::graphics; 6 | 7 | entry!(main); 8 | 9 | // Entry point of user code 10 | fn main() -> ! { 11 | let arr: [u64; graphics::HEIGHT] = [0xF00000000000000F; graphics::HEIGHT]; 12 | let mut screen = graphics::init(); 13 | loop { 14 | graphics::write_long(&mut screen, &arr); 15 | graphics::update(&mut screen); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /app/tetris/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [target.riscv32i-unknown-none-elf] 2 | rustflags = ["-C", "link-arg=-Tlink.x"] 3 | 4 | [alias] 5 | rbuild = "build --release --target riscv32i-unknown-none-elf" 6 | rb = "rbuild" 7 | 8 | rdoc = "doc --release --target riscv32i-unknown-none-elf" 9 | rd = "rdoc" 10 | 11 | rsize = "size --release --target riscv32i-unknown-none-elf" 12 | rs = "rsize" 13 | 14 | robjdump = "objdump --release --target riscv32i-unknown-none-elf" 15 | rod = "robjdump" 16 | 17 | -------------------------------------------------------------------------------- /app/tetris/.vimspector.json: -------------------------------------------------------------------------------- 1 | { 2 | "configurations": { 3 | "Launch": { 4 | "adapter": "vscode-cpptools", 5 | "filetypes": [ "cpp", "c", "objc", "rust" ], 6 | "configuration": { 7 | "request": "launch", 8 | "program": "${workspaceRoot}/target/x86_64-unknown-linux-gnu/debug/tetris", 9 | "args": [], 10 | "cwd": ".", 11 | "environment": [], 12 | "externalConsole": true, 13 | "MIMode": "gdb", 14 | "stopAtEntry": true 15 | } 16 | }, 17 | "Attach": { 18 | "adapter": "vscode-cpptools", 19 | "filetypes": [ "cpp", "c", "objc", "rust" ], 20 | "configuration": { 21 | "request": "attach", 22 | "program": "${workspaceRoot}/target/x86_64-unknown-linux-gnu/debug/tetris", 23 | "MIMode": "gdb", 24 | "stopAtEntry": true 25 | } 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /app/tetris/Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "autocfg" 7 | version = "1.1.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" 10 | 11 | [[package]] 12 | name = "bitflags" 13 | version = "1.3.2" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 16 | 17 | [[package]] 18 | name = "cassowary" 19 | version = "0.3.0" 20 | source = "registry+https://github.com/rust-lang/crates.io-index" 21 | checksum = "df8670b8c7b9dae1793364eafadf7239c40d669904660c5960d74cfd80b46a53" 22 | 23 | [[package]] 24 | name = "cfg-if" 25 | version = "1.0.0" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 28 | 29 | [[package]] 30 | name = "crossterm" 31 | version = "0.25.0" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | checksum = "e64e6c0fbe2c17357405f7c758c1ef960fce08bdfb2c03d88d2a18d7e09c4b67" 34 | dependencies = [ 35 | "bitflags", 36 | "crossterm_winapi", 37 | "libc", 38 | "mio", 39 | "parking_lot", 40 | "signal-hook", 41 | "signal-hook-mio", 42 | "winapi", 43 | ] 44 | 45 | [[package]] 46 | name = "crossterm" 47 | version = "0.26.1" 48 | source = "registry+https://github.com/rust-lang/crates.io-index" 49 | checksum = "a84cda67535339806297f1b331d6dd6320470d2a0fe65381e79ee9e156dd3d13" 50 | dependencies = [ 51 | "bitflags", 52 | "crossterm_winapi", 53 | "libc", 54 | "mio", 55 | "parking_lot", 56 | "signal-hook", 57 | "signal-hook-mio", 58 | "winapi", 59 | ] 60 | 61 | [[package]] 62 | name = "crossterm_winapi" 63 | version = "0.9.1" 64 | source = "registry+https://github.com/rust-lang/crates.io-index" 65 | checksum = "acdd7c62a3665c7f6830a51635d9ac9b23ed385797f70a83bb8bafe9c572ab2b" 66 | dependencies = [ 67 | "winapi", 68 | ] 69 | 70 | [[package]] 71 | name = "libc" 72 | version = "0.2.147" 73 | source = "registry+https://github.com/rust-lang/crates.io-index" 74 | checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" 75 | 76 | [[package]] 77 | name = "lock_api" 78 | version = "0.4.10" 79 | source = "registry+https://github.com/rust-lang/crates.io-index" 80 | checksum = "c1cc9717a20b1bb222f333e6a92fd32f7d8a18ddc5a3191a11af45dcbf4dcd16" 81 | dependencies = [ 82 | "autocfg", 83 | "scopeguard", 84 | ] 85 | 86 | [[package]] 87 | name = "log" 88 | version = "0.4.20" 89 | source = "registry+https://github.com/rust-lang/crates.io-index" 90 | checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" 91 | 92 | [[package]] 93 | name = "mio" 94 | version = "0.8.8" 95 | source = "registry+https://github.com/rust-lang/crates.io-index" 96 | checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" 97 | dependencies = [ 98 | "libc", 99 | "log", 100 | "wasi", 101 | "windows-sys", 102 | ] 103 | 104 | [[package]] 105 | name = "parking_lot" 106 | version = "0.12.1" 107 | source = "registry+https://github.com/rust-lang/crates.io-index" 108 | checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" 109 | dependencies = [ 110 | "lock_api", 111 | "parking_lot_core", 112 | ] 113 | 114 | [[package]] 115 | name = "parking_lot_core" 116 | version = "0.9.8" 117 | source = "registry+https://github.com/rust-lang/crates.io-index" 118 | checksum = "93f00c865fe7cabf650081affecd3871070f26767e7b2070a3ffae14c654b447" 119 | dependencies = [ 120 | "cfg-if", 121 | "libc", 122 | "redox_syscall", 123 | "smallvec", 124 | "windows-targets", 125 | ] 126 | 127 | [[package]] 128 | name = "ratatui" 129 | version = "0.20.1" 130 | source = "registry+https://github.com/rust-lang/crates.io-index" 131 | checksum = "dcc0d032bccba900ee32151ec0265667535c230169f5a011154cdcd984e16829" 132 | dependencies = [ 133 | "bitflags", 134 | "cassowary", 135 | "crossterm 0.26.1", 136 | "unicode-segmentation", 137 | "unicode-width", 138 | ] 139 | 140 | [[package]] 141 | name = "redox_syscall" 142 | version = "0.3.5" 143 | source = "registry+https://github.com/rust-lang/crates.io-index" 144 | checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" 145 | dependencies = [ 146 | "bitflags", 147 | ] 148 | 149 | [[package]] 150 | name = "scopeguard" 151 | version = "1.2.0" 152 | source = "registry+https://github.com/rust-lang/crates.io-index" 153 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 154 | 155 | [[package]] 156 | name = "signal-hook" 157 | version = "0.3.17" 158 | source = "registry+https://github.com/rust-lang/crates.io-index" 159 | checksum = "8621587d4798caf8eb44879d42e56b9a93ea5dcd315a6487c357130095b62801" 160 | dependencies = [ 161 | "libc", 162 | "signal-hook-registry", 163 | ] 164 | 165 | [[package]] 166 | name = "signal-hook-mio" 167 | version = "0.2.3" 168 | source = "registry+https://github.com/rust-lang/crates.io-index" 169 | checksum = "29ad2e15f37ec9a6cc544097b78a1ec90001e9f71b81338ca39f430adaca99af" 170 | dependencies = [ 171 | "libc", 172 | "mio", 173 | "signal-hook", 174 | ] 175 | 176 | [[package]] 177 | name = "signal-hook-registry" 178 | version = "1.4.1" 179 | source = "registry+https://github.com/rust-lang/crates.io-index" 180 | checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1" 181 | dependencies = [ 182 | "libc", 183 | ] 184 | 185 | [[package]] 186 | name = "smallvec" 187 | version = "1.11.0" 188 | source = "registry+https://github.com/rust-lang/crates.io-index" 189 | checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" 190 | 191 | [[package]] 192 | name = "tdriver" 193 | version = "0.1.0" 194 | dependencies = [ 195 | "crossterm 0.25.0", 196 | "ratatui", 197 | ] 198 | 199 | [[package]] 200 | name = "tetris" 201 | version = "0.1.0" 202 | dependencies = [ 203 | "tdriver", 204 | ] 205 | 206 | [[package]] 207 | name = "unicode-segmentation" 208 | version = "1.10.1" 209 | source = "registry+https://github.com/rust-lang/crates.io-index" 210 | checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" 211 | 212 | [[package]] 213 | name = "unicode-width" 214 | version = "0.1.10" 215 | source = "registry+https://github.com/rust-lang/crates.io-index" 216 | checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" 217 | 218 | [[package]] 219 | name = "wasi" 220 | version = "0.11.0+wasi-snapshot-preview1" 221 | source = "registry+https://github.com/rust-lang/crates.io-index" 222 | checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" 223 | 224 | [[package]] 225 | name = "winapi" 226 | version = "0.3.9" 227 | source = "registry+https://github.com/rust-lang/crates.io-index" 228 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 229 | dependencies = [ 230 | "winapi-i686-pc-windows-gnu", 231 | "winapi-x86_64-pc-windows-gnu", 232 | ] 233 | 234 | [[package]] 235 | name = "winapi-i686-pc-windows-gnu" 236 | version = "0.4.0" 237 | source = "registry+https://github.com/rust-lang/crates.io-index" 238 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 239 | 240 | [[package]] 241 | name = "winapi-x86_64-pc-windows-gnu" 242 | version = "0.4.0" 243 | source = "registry+https://github.com/rust-lang/crates.io-index" 244 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 245 | 246 | [[package]] 247 | name = "windows-sys" 248 | version = "0.48.0" 249 | source = "registry+https://github.com/rust-lang/crates.io-index" 250 | checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" 251 | dependencies = [ 252 | "windows-targets", 253 | ] 254 | 255 | [[package]] 256 | name = "windows-targets" 257 | version = "0.48.5" 258 | source = "registry+https://github.com/rust-lang/crates.io-index" 259 | checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" 260 | dependencies = [ 261 | "windows_aarch64_gnullvm", 262 | "windows_aarch64_msvc", 263 | "windows_i686_gnu", 264 | "windows_i686_msvc", 265 | "windows_x86_64_gnu", 266 | "windows_x86_64_gnullvm", 267 | "windows_x86_64_msvc", 268 | ] 269 | 270 | [[package]] 271 | name = "windows_aarch64_gnullvm" 272 | version = "0.48.5" 273 | source = "registry+https://github.com/rust-lang/crates.io-index" 274 | checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" 275 | 276 | [[package]] 277 | name = "windows_aarch64_msvc" 278 | version = "0.48.5" 279 | source = "registry+https://github.com/rust-lang/crates.io-index" 280 | checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" 281 | 282 | [[package]] 283 | name = "windows_i686_gnu" 284 | version = "0.48.5" 285 | source = "registry+https://github.com/rust-lang/crates.io-index" 286 | checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" 287 | 288 | [[package]] 289 | name = "windows_i686_msvc" 290 | version = "0.48.5" 291 | source = "registry+https://github.com/rust-lang/crates.io-index" 292 | checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" 293 | 294 | [[package]] 295 | name = "windows_x86_64_gnu" 296 | version = "0.48.5" 297 | source = "registry+https://github.com/rust-lang/crates.io-index" 298 | checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" 299 | 300 | [[package]] 301 | name = "windows_x86_64_gnullvm" 302 | version = "0.48.5" 303 | source = "registry+https://github.com/rust-lang/crates.io-index" 304 | checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" 305 | 306 | [[package]] 307 | name = "windows_x86_64_msvc" 308 | version = "0.48.5" 309 | source = "registry+https://github.com/rust-lang/crates.io-index" 310 | checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" 311 | -------------------------------------------------------------------------------- /app/tetris/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "tetris" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | tdriver = { path = "../tdriver" } 8 | 9 | # Don't ever use this for riscv builds or they will be massive 10 | [profile.dev] 11 | 12 | [profile.release] 13 | panic = "abort" 14 | # Use either 2, 3, s or z 15 | opt-level = 3 16 | overflow-checks = false 17 | lto = true 18 | 19 | -------------------------------------------------------------------------------- /app/tetris/copy-bin.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/sh 2 | 3 | # Helper script to copy file to txt file format WireHead expects 4 | # Example: ./copy_bin.sh /tmp/in.txt 5 | 6 | # Rebuild project 7 | cargo rbuild --release 8 | 9 | # Convert from elf to bin 10 | # Fancy glob matching! https://zsh.sourceforge.io/Doc/Release/Expansion.html#Glob-Qualifiers 11 | # rust-objcopy -O binary ./target/riscv32i-unknown-none-elf/release/*(x.) /tmp/rust.bin 12 | rust-objcopy -O binary ./target/riscv32i-unknown-none-elf/release/tetris /tmp/rust.bin 13 | 14 | # Convert from bin to txt 15 | hexdump -ve '1/1 "%.2x "' /tmp/rust.bin | head -c -1 > $1 16 | 17 | -------------------------------------------------------------------------------- /app/tetris/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | use tdriver::entry; 5 | use tdriver::graphics; 6 | use tiles::SHAPES; 7 | 8 | mod tiles; 9 | 10 | entry!(main); 11 | 12 | const TOP: usize = 7; 13 | const MIDDLE: usize = 30; 14 | 15 | 16 | // Entry point of user code 17 | 18 | fn create_board() -> [u64; graphics::HEIGHT] { 19 | let mut base_board : [u64; graphics::HEIGHT] = [0;graphics::HEIGHT]; 20 | for i in 0..8{ 21 | base_board[i] |= u64::MAX; 22 | } 23 | for i in 8..40{ 24 | base_board[i] |= 0xFFFFFF0000FFFFFF; 25 | } 26 | for i in 40..48{ 27 | base_board[i] |= u64::MAX; 28 | } 29 | base_board 30 | } 31 | 32 | fn find_bottom(curr_pos: &[u64;4]) -> usize{ 33 | for i in 0..4{ 34 | if curr_pos[3-i] != 0{ 35 | return 3-i 36 | } 37 | } 38 | return 0; 39 | } 40 | 41 | fn find_top(curr_pos: &[u64;4]) -> usize{ 42 | for i in 0..4{ 43 | if curr_pos[i] != 0{ 44 | return i 45 | } 46 | } 47 | return 0; 48 | } 49 | 50 | fn get_rand(x: usize)->usize{ 51 | ((690697*x+1)%3_usize.pow(4)).into() 52 | } 53 | 54 | fn clear_tiles(curr_board: &mut [u64; graphics::HEIGHT]) { 55 | let mut row_index = 8; 56 | 57 | while row_index < 40 { 58 | if curr_board[row_index] == u64::MAX { 59 | for j in (8..row_index).rev() { 60 | curr_board[j + 1] = curr_board[j]; 61 | } 62 | curr_board[8] = 0; 63 | } else { 64 | row_index += 1; 65 | } 66 | } 67 | } 68 | 69 | fn main() -> ! { 70 | let base_board = create_board(); 71 | let mut curr_board: [u64; graphics::HEIGHT] = create_board(); 72 | let mut screen = graphics::init(); 73 | 74 | let mut new_tile = true; 75 | 76 | let mut shape: [[u64;4];4] = [[0;4];4]; 77 | let mut a = tiles::I[1]; 78 | let mut new_pos: [u64;4] = [0;4]; 79 | let mut curr_pos: [u64;4] = [0;4]; 80 | let mut n = find_bottom(&a); 81 | 82 | 83 | let mut r = TOP + n; 84 | let mut tile_pos = MIDDLE; 85 | let mut rot: usize = 0; 86 | let mut rand = 67; 87 | 88 | 89 | loop { 90 | graphics::write_long(&mut screen, &curr_board); 91 | graphics::update(&mut screen); 92 | 93 | if (curr_board[r+n] & curr_pos[n]) > 0{ 94 | if r == TOP-find_top(&a)+2{ 95 | curr_board = [u64::MAX;graphics::HEIGHT]; 96 | continue; 97 | } 98 | new_tile = true; 99 | } 100 | if ((!curr_pos[n] & curr_board[r+n-1]) & curr_pos[n-1])>0{ 101 | if r == TOP-find_top(&a)+2{ 102 | curr_board = [u64::MAX;graphics::HEIGHT]; 103 | continue; 104 | } 105 | new_tile = true; 106 | } 107 | 108 | if new_tile{ 109 | //clear board 110 | clear_tiles(&mut curr_board); 111 | 112 | rand = get_rand(rand); 113 | shape = SHAPES[rand%7]; 114 | rand = get_rand(rand); 115 | rot = rand%4; 116 | a = shape[rot]; 117 | tile_pos = MIDDLE; 118 | r = TOP-find_top(&a)+1; 119 | 120 | for i in 0..4{ 121 | new_pos[i] = a[i]<>1; 140 | } 141 | } 142 | else if right { 143 | tile_pos += 1; 144 | for i in 0..4{ 145 | new_pos[i] = curr_pos[i]<<1; 146 | } 147 | } 148 | else if up { 149 | if !(rot == 3){ 150 | rot += 1; 151 | } 152 | else{ 153 | rot = 0; 154 | } 155 | a = shape[rot]; 156 | for i in 0..4{ 157 | new_pos[i] = a[i]< $1 16 | 17 | -------------------------------------------------------------------------------- /app/video/src/main.rs: -------------------------------------------------------------------------------- 1 | #![no_std] 2 | #![no_main] 3 | 4 | use tdriver::entry; 5 | use tdriver::graphics; 6 | 7 | mod video; 8 | 9 | entry!(main); 10 | 11 | // Entry point of user code 12 | fn main() -> ! { 13 | let mut screen = graphics::init(); 14 | let mut i = 0; 15 | loop { 16 | if i >= video::FRAMES.len() { 17 | i = 0; 18 | } 19 | graphics::write_raw(&mut screen, &video::FRAMES[i]); 20 | i += 1; 21 | graphics::update(&mut screen); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /computerraria.tar.gz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misprit7/computerraria/7d761296af5a3f8764ccb2af44a171e0a57e0e6b/computerraria.tar.gz -------------------------------------------------------------------------------- /computerraria.twld: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misprit7/computerraria/7d761296af5a3f8764ccb2af44a171e0a57e0e6b/computerraria.twld -------------------------------------------------------------------------------- /copy-world.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ################################################# 4 | # Copies world to/from game files 5 | ################################################# 6 | 7 | TARGET_DIR="$HOME/.local/share/Terraria/tModLoader/Worlds" 8 | TO_FLAG=0 9 | FROM_FLAG=0 10 | MNT_FLAG=0 11 | 12 | for arg in "$@" 13 | do 14 | case $arg in 15 | -t|--to) 16 | TO_FLAG=1 17 | ;; 18 | -f|--from) 19 | FROM_FLAG=1 20 | ;; 21 | --mnt) 22 | MNT_FLAG=1 23 | ;; 24 | *) 25 | echo "Invalid option: $arg" 26 | echo "Supply either --to or --from and optionally --mnt to specify directory" 27 | exit 1 28 | ;; 29 | esac 30 | done 31 | 32 | if [ "$MNT_FLAG" -eq 1 ]; then 33 | TARGET_DIR="/mnt/d/computerraria" 34 | fi 35 | 36 | if [ "$TO_FLAG" -eq 1 ]; then 37 | tar -xzf $(dirname "$0")/computerraria.tar.gz -C $(dirname "$0") 38 | cp $(dirname "$0")/computerraria.wld $TARGET_DIR 39 | cp $(dirname "$0")/computerraria.twld $TARGET_DIR 40 | elif [ "$FROM_FLAG" -eq 1 ]; then 41 | cp "$TARGET_DIR/computerraria.wld" $(dirname "$0") 42 | cp "$TARGET_DIR/computerraria.twld" $(dirname "$0") 43 | tar -czf $(dirname "$0")/computerraria.tar.gz $(dirname "$0")/computerraria.wld 44 | else 45 | echo "Supply either --to or --from to copy either to or from the Terraria world files" 46 | exit 1 47 | fi 48 | -------------------------------------------------------------------------------- /doc/img/control-panel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misprit7/computerraria/7d761296af5a3f8764ccb2af44a171e0a57e0e6b/doc/img/control-panel.png -------------------------------------------------------------------------------- /doc/img/logo-old.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misprit7/computerraria/7d761296af5a3f8764ccb2af44a171e0a57e0e6b/doc/img/logo-old.png -------------------------------------------------------------------------------- /doc/img/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misprit7/computerraria/7d761296af5a3f8764ccb2af44a171e0a57e0e6b/doc/img/logo.png -------------------------------------------------------------------------------- /doc/img/pong-still.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misprit7/computerraria/7d761296af5a3f8764ccb2af44a171e0a57e0e6b/doc/img/pong-still.png -------------------------------------------------------------------------------- /doc/img/poster-small.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misprit7/computerraria/7d761296af5a3f8764ccb2af44a171e0a57e0e6b/doc/img/poster-small.png -------------------------------------------------------------------------------- /doc/logo.pixil: -------------------------------------------------------------------------------- 1 | {"application":"pixil","type":".pixil","version":"2.7.0","website":"pixilart.com","author":"https://www.pixilart.com","contact":"support@pixilart.com","width":"42","height":"105","colors":{"default":["000000","ffffff","f44336","E91E63","9C27B0","673AB7","3F51B5","2196F3","03A9F4","00BCD4","009688","4CAF50","8BC34A","CDDC39","FFEB3B","FFC107","FF9800","FF5722","795548","9E9E9E","607D8B","ffebee","ffcdd2","ef9a9a","e57373","ef5350","e53935","d32f2f","c62828","b71c1c","ff8a80","ff5252","ff1744","d50000","fce4ec","f8bbd0","f48fb1","f06292","ec407a","e91e63","d81b60","c2185b","ad1457","880e4f","ff80ab","ff4081","f50057","c51162","f3e5f5","e1bee7","ce93d8","ba68c8","ab47bc","9c27b0","8e24aa","7b1fa2","6a1b9a","4a148c","ea80fc","e040fb","d500f9","aa00ff","ede7f6","d1c4e9","b39ddb","9575cd","7e57c2","673ab7","5e35b1","512da8","4527a0","311b92","b388ff","7c4dff","651fff","6200ea","e8eaf6","c5cae9","9fa8da","7986cb","5c6bc0","3f51b5","3949ab","303f9f","283593","1a237e","8c9eff","536dfe","3d5afe","304ffe","e3f2fd","bbdefb","90caf9","64b5f6","42a5f5","2196f3","1e88e5","1976d2","1565c0","0d47a1","82b1ff","448aff","2979ff","2962ff","e1f5fe","b3e5fc","81d4fa","4fc3f7","29b6f6","03a9f4","039be5","0288d1","0277bd","01579b","80d8ff","40c4ff","00b0ff","0091ea","e0f7fa","b2ebf2","80deea","4dd0e1","26c6da","00bcd4","00acc1","0097a7","00838f","006064","84ffff","18ffff","00e5ff","00b8d4","e0f2f1","b2dfdb","80cbc4","4db6ac","26a69a","009688","00897b","00796b","00695c","004d40","a7ffeb","64ffda","1de9b6","00bfa5","e8f5e9","c8e6c9","a5d6a7","81c784","66bb6a","4caf50","43a047","388e3c","2e7d32","1b5e20","b9f6ca","69f0ae","00e676","00c853","f1f8e9","dcedc8","c5e1a5","aed581","9ccc65","8bc34a","7cb342","689f38","558b2f","33691e","ccff90","b2ff59","76ff03","64dd17","f9fbe7","f0f4c3","e6ee9c","dce775","d4e157","cddc39","c0ca33","afb42b","9e9d24","827717","f4ff81","eeff41","c6ff00","aeea00","fffde7","fff9c4","fff59d","fff176","ffee58","ffeb3b","fdd835","fbc02d","f9a825","f57f17","ffff8d","ffff00","ffea00","ffd600","fff8e1","ffecb3","ffe082","ffd54f","ffca28","ffc107","ffb300","ffa000","ff8f00","ff6f00","ffe57f","ffd740","ffc400","ffab00","fff3e0","ffe0b2","ffcc80","ffb74d","ffa726","ff9800","fb8c00","f57c00","ef6c00","e65100","ffd180","ffab40","ff9100","ff6d00","fbe9e7","ffccbc","ffab91","ff8a65","ff7043","ff5722","f4511e","e64a19","d84315","bf360c","ff9e80","ff6e40","ff3d00","dd2c00","efebe9","d7ccc8","bcaaa4","a1887f","8d6e63","795548","6d4c41","5d4037","4e342e","3e2723","fafafa","f5f5f5","eeeeee","e0e0e0","bdbdbd","9e9e9e","757575","616161","424242","212121","eceff1","cfd8dc","b0bec5","90a4ae","78909c","607d8b","546e7a","455a64","37474f","263238"],"simple":["ffffff","d4d4d4","a1a1a1","787878","545454","303030","000000","edc5c5","e68383","ff0000","de2424","ad3636","823737","592b2b","f5d2ee","eb8dd7","f700b9","bf1f97","9c277f","732761","4f2445","e2bcf7","bf79e8","9d00ff","8330ba","6d3096","502c69","351b47","c5c3f0","736feb","0905f7","2e2eb0","2d2d80","252554","090936","c7e2ed","6ac3e6","00bbff","279ac4","347c96","2d5b6b","103947","bbf0d9","6febb3","00ff88","2eb878","349166","2b694c","0c3d25","c2edc0","76ed70","0dff00","36c72c","408c3b","315c2e","144511","d6edbb","b5eb73","8cff00","89c93a","6f8f44","4b632a","2a400c","f1f2bf","eef069","ffff00","baba30","91913f","5e5e2b","3b3b09","ffdeb8","f2ae61","ff8400","c48037","85623d","573e25","3d2309","fcbbae","ff8066","ff2b00","cc553d","9c5b4e","61372e","36130b","757575"],"common":["000000","ffffff","464646","b4b4b4","990030","9c5a3c","ed1c24","ffa3b1","ff7e00","e5aa7a","ffc20e","f5e49c","fff200","fff9bd","a8e61d","d3f9bc","22b14c","00b7ef","99d9ea","4d6df3","709ad1","2f3699","546d8e","6f3198","b5a5d5","424242","242424","616161","949494","a3a3a3","563e2c","78553c","858585","a0a0a0","2b2b2b","727272","4a4a4a","393939","5d5d5d","313131","3a302a","976b4b","3b2a1e","bf8f6f","a97d5d","2c2c2c","752424","b01515","c91c1c","17331c","1bcf5a","1d9043","197b3b","848484","414141","969696"],"skin tones":["ffe0bd","ffdbac","ffcd94","eac086","e0ac69","f1c27d","ffad60","c68642","8d5524","896347","765339","613D24","4C2D17","391E0B","351606","2D1304","180A01","090300"]},"colorSelected":"common","frames":[{"name":"","speed":100,"layers":[{"id":0,"src":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,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","edit":false,"name":"Layer 2","opacity":"1","active":true,"unqid":"","options":{"blend":"source-over","locked":false,"filter":{"brightness":"100%","contrast":"100%","grayscale":"0%","blur":0,"dropshadow_x":0,"dropshadow_y":0,"dropshadow_blur":0,"dropshadow_alpha":1}}}],"active":true,"selectedLayer":0,"unqid":"vbisup","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,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","width":"42","height":"105"}],"currentFrame":0,"speed":100,"name":"Untitled","preview":"data:image/pngp98kjasdnasd983/24kasdjasdbase64,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","previewApp":"","art_edit_id":0,"palette_id":false,"created_at":1678681854619,"updated_at":1678681854619,"isExternal":true,"id":1678681234982} -------------------------------------------------------------------------------- /doc/notes.txt: -------------------------------------------------------------------------------- 1 | My personal messy notes for while I'm doing things 2 | 3 | Instruction numbers: 4 | 0110111: 7 5 | 0010111: 9 6 | 1101111: 1 7 | 1100111: 3 8 | 1100011: 0 9 | 0000011: 10 10 | 0100011: 4 11 | 0010011: 11 12 | 0110011: 5 13 | 0001111: 8 14 | 15 | Commands: 16 | ALU: 17 | 0-1: Load 2 18 | 0-2: Load 1 19 | 0-3: exec 20 | 6-0: funct3[0] 21 | 6-1: funct3[1] 22 | 6-2: funct3[2] 23 | 6-3: dir, i1 24 | Registers: 25 | 1-2: Store 26 | 1-3: Load 27 | Memory: 28 | 2-1: store address 29 | 2-2: Execute 30 | 2-3: Load/store, i1 31 | PC: 32 | 3-0: Store 33 | 3-1: Load 34 | 3-2: Load (reserved for base instruction logic) 35 | 3-3: Increment 36 | Decoder: 37 | 4-0: Write rd 38 | 4-1: Read rs2 39 | 4-2: Read rs1 40 | 5-2: Load immediate 41 | 5-3: Load instr 42 | Control unit: 43 | 7-0: Clock 44 | 7-1: Instruction finished 45 | Aligner: 46 | 1-0: Align load 47 | 1-1: Store 2 least significant bits 48 | 7-3: Store funct3, WARNING: no sync 49 | 8-1: Store data to store 50 | 8-2: Align store 51 | Misc: 52 | 0-0: Increment data bus 53 | 4-3: Store add to funct3, WARNING: no sync 54 | 8-0: Load tmp 55 | 8-3: Store tmp 56 | 57 | Registers: 58 | 0x1E1FC (write only): 59 | 0: Write screen 60 | 61 | 0x1E1F8 (read only): 62 | 0: Down 63 | 1: Left 64 | 2: Right 65 | 3: Up 66 | 67 | Notes on registers: 68 | - Use 32 bit binary tree multiplexer 69 | - Two logic gates per bit, 1 for loading and the other for storing 70 | - Duplicated binary tree to allow a read and write in one iteration 71 | - Can't easily allow two reads in one iteration, so instructions with rs1 and rs2 aren't allowed 72 | 73 | Notes on memory: 74 | - Massive binary tree structure for selection, bottom layer is load/store select 75 | - Address is cached both to deal with colour problems and because reads need two data bus inputs 76 | - Same memory structure as registers with 2 gates for each bit, although much more compact 77 | 78 | Notes on adder: 79 | - Could just use a 3 to 8 multiplexer for 1 bit adders, but I'd like something nicer 80 | - Output of adder is xor of all three inputs A, B and C which is implicit with wiring, carry is harder 81 | - Carry is determined with following equation: C_out = (A&B)^(A^B if C) which is easy to implement in faulty logic 82 | - To get subtraction simply invert B's bits to and set first carry for two's complement 83 | - In my implementation B is toggled back after operation, although since operands aren't expected to be reused strictly speaking this is unnecessary 84 | 85 | Notes on comparator: 86 | - Was lazy and didn't think through things myself: http://lumetta.web.engr.illinois.edu/120-S17/slide-copies/053-2's-complement-comparator.pdf 87 | - If dir is 1 then actually less than or equal, useful for conditional branches 88 | 89 | Notes on AND/OR/XOR: 90 | - Went for a super compact design 91 | - xor xors, and zeros then ands, or xors then ands 92 | 93 | Notes on equalitator: 94 | - Definitely not a word 95 | - Not part of original ALU requirements but is required for BEQ/BNE 96 | - Encoded as funct3=001, dir=1 since that's only free combination 97 | - Doesn't bother to zero other bits, so sets last bit 0 if neq and 1 if eq 98 | 99 | Notes on decoder: 100 | - Multiplexes opcodes out 101 | - Immediate loading is done as efficiently as possible by reusing common overlap 102 | - Load instr signal tells decoder to cache registers, functX, etc. so that data bas can be reused 103 | 104 | Notes on PC: 105 | - Increment loads as well to enable one clock cycle jumps 106 | - Wire colour scheme for increment has convoluted colour sharer circuit for previous design that tried to increment and load in one iteration 107 | - A bit of a mess, leaving as is for now since I might realize I've made a mistake in terms of pc loading timing 108 | 109 | Notes on aligner: 110 | - Not the best put together, kinda hacky 111 | - Completely undefined behavior for misaligned reads, be careful!!! 112 | 113 | Notes on control unit: 114 | - Instructions are responsible for incrementing pc since some instructions want to do that later or earlier 115 | 116 | Instruction programming 117 | Prelude (common to all instructions) 118 | Load PC 119 | Store address and set mem to read 120 | Mem exec 121 | Load instr 122 | 123 | OP-IMM 124 | Load imm 125 | ALU store 1 126 | Load rs1 127 | ALU store 2 128 | ALU exec 129 | Incr pc 130 | 131 | LUI 132 | Load imm 133 | Store rd 134 | Incr pc 135 | 136 | AUIPC 137 | Load imm 138 | ALU store 2 139 | Read pc 140 | ALU store 1 141 | ALU exec 142 | Store rd 143 | Incr pc 144 | 145 | JAL 146 | Load imm 147 | ALU store 2 148 | Read pc 149 | Incr db 150 | Store rd 151 | Delay 152 | Read pc 153 | ALU store 1 154 | ALU exec 155 | Store pc 156 | 157 | JALR 158 | Load imm 159 | ALU store 2 160 | Read rs1 161 | ALU store 1 162 | Load PC 163 | Incr db 164 | Store rd 165 | ALU exec 166 | Set lsb of db to 0 167 | Store pc 168 | 169 | OP 170 | Load rs2 171 | ALU store 2 172 | Delay 173 | Load rs1 174 | ALU store 1 175 | ALU exec 176 | Store rd 177 | Incr PC 178 | 179 | LOAD 180 | Load imm and store funct3 to align 181 | ALU store 2 182 | Load rs1 and store add to funct3 183 | ALU store 1 184 | ALU exec 185 | Store 2 lsbs 186 | Delay 187 | Mem store addr 188 | Mem exec 189 | Align load 190 | Write rd 191 | Incr pc 192 | 193 | STORE 194 | Load imm and store funct3 to align 195 | ALU store 2 196 | Load rs1 197 | ALU store 1 198 | ALU exec 199 | Store 2 lsbs 200 | Delay 201 | If funct3[1]==1 202 | Mem store address 203 | Load rs2 204 | goto last delay 205 | Mem store addr 206 | Load rs2 207 | Store store data 208 | Mem exec 209 | Put store onto db 210 | Delay 211 | Mem exec and set mem to write 212 | Incr pc 213 | 214 | BRANCH 215 | Load imm 216 | Store tmp 217 | Load rs1 218 | Store ALU 1/2 219 | Delay 220 | Load rs2 221 | Store ALU 2/1 222 | Load proper funct3 223 | ALU exec 224 | If db[0]==0 225 | Incr pc 226 | finish 227 | Load tmp 228 | Delay 229 | Store ALU 2 230 | Load pc 231 | Store ALU 1 and set ALU to add 232 | ALU exec 233 | Store pc 234 | 235 | 236 | # RAM/ROM Overhaul Notes 237 | 238 | RAM/ROM 239 | 47 rows 240 | 24 rom, 23 ram 241 | 242 | Screen: 176x96 243 | 244 | ROM: 0x0-0xC0000, i.e. 768kb 245 | RAM: 0x100000-0x15BFFF, i.e. 368kb 246 | Peripherals: starting at 0x200000 247 | Color screen: 0x200000 248 | Color update: 0x203FFC (end of of 0x204000 region) 249 | Old screen: 0x20E000 250 | Old screen update: 0x20E1FC 251 | Old screen input: 0x20E1F8 252 | 253 | 254 | 255 | -------------------------------------------------------------------------------- /doc/old-worlds/blank.wld: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misprit7/computerraria/7d761296af5a3f8764ccb2af44a171e0a57e0e6b/doc/old-worlds/blank.wld -------------------------------------------------------------------------------- /doc/old-worlds/computer.wld: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misprit7/computerraria/7d761296af5a3f8764ccb2af44a171e0a57e0e6b/doc/old-worlds/computer.wld -------------------------------------------------------------------------------- /doc/reference/computer-old.wld: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misprit7/computerraria/7d761296af5a3f8764ccb2af44a171e0a57e0e6b/doc/reference/computer-old.wld -------------------------------------------------------------------------------- /doc/riscv.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/misprit7/computerraria/7d761296af5a3f8764ccb2af44a171e0a57e0e6b/doc/riscv.pdf -------------------------------------------------------------------------------- /docker/Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax = docker/dockerfile:1.2 2 | 3 | ################################################################################ 4 | # CI dockerfile 5 | ################################################################################ 6 | # This dockerfile contains everything required to run a full CI test suite 7 | # 8 | # One could potentially also use this for development, as long as another 9 | # computer with a Terraria client installed can connect 10 | 11 | 12 | ################################################################################ 13 | # Base 14 | ################################################################################ 15 | # Probably should have used this in hindsight: 16 | # https://github.com/tModLoader/tModLoader/tree/1.4/patches/tModLoader/Terraria/release_extras/DedicatedServerUtils 17 | FROM steamcmd/steamcmd@sha256:0d3d8716fb0ac76f02bd9d850334b892d1caf92632fcce362bb52592d63211c3 18 | 19 | 20 | ################################################################################ 21 | # Base 22 | ################################################################################ 23 | # Yeah I'm not supposed to install user applications (vim), but it helps when 24 | # debugging and is trivially lightweight 25 | RUN apt-get update && apt-get install -y \ 26 | bsdmainutils \ 27 | curl \ 28 | gcc \ 29 | git \ 30 | libsdl2-2.0-0 \ 31 | python3 \ 32 | python3-pip \ 33 | python3-tqdm \ 34 | make \ 35 | vim \ 36 | wget 37 | 38 | # libicu70 \ 39 | 40 | 41 | ################################################################################ 42 | # tModLoader 43 | ################################################################################ 44 | RUN --mount=type=secret,id=_env,dst=/etc/secrets/.env \ 45 | echo exit | steamcmd \ 46 | "+login $(sed -n 1p /etc/secrets/.env) $(sed -n 2p /etc/secrets/.env)" \ 47 | "+app_update 1281930 validate" &&\ 48 | mkdir -p /root/.local/share/Terraria/tModLoader/ModSources &&\ 49 | mkdir -p /root/.local/share/Terraria/tModLoader/Mods 50 | # ln -s /root/Steam/steamapps/ /root/.local/share/Steam/ &&\ 51 | COPY tModLoader.targets /root/.local/share/Terraria/tModLoader/ModSources 52 | 53 | 54 | ################################################################################ 55 | # RISCV Toolchain 56 | ################################################################################ 57 | # These are kind of sketchy prebuilt binaries, but building from scratch takes 58 | # forever 59 | WORKDIR /opt 60 | RUN mkdir /opt/riscv &&\ 61 | wget https://github.com/stnolting/riscv-gcc-prebuilt/releases/download/rv32i-4.0.0/riscv32-unknown-elf.gcc-12.1.0.tar.gz &&\ 62 | tar -xzf riscv32-unknown-elf.gcc-12.1.0.tar.gz -C /opt/riscv/ &&\ 63 | rm riscv32-unknown-elf.gcc-12.1.0.tar.gz 64 | WORKDIR /root 65 | 66 | 67 | ################################################################################ 68 | # Rust 69 | ################################################################################ 70 | RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > rustup.sh &&\ 71 | sh rustup.sh -y --profile minimal &&\ 72 | source "$HOME/.cargo/env" &&\ 73 | rustup target add riscv32i-unknown-none-elf &&\ 74 | rustup component add llvm-tools-preview &&\ 75 | cargo install cargo-binutils &&\ 76 | rm -rf /root/.cargo/registry &&\ 77 | rustup target remove x86_64-unknown-linux-gnu 78 | ENV PATH "$PATH:/opt/riscv/bin" 79 | 80 | 81 | ################################################################################ 82 | # Dotnet 83 | ################################################################################ 84 | RUN wget https://dot.net/v1/dotnet-install.sh &&\ 85 | bash ./dotnet-install.sh --install-dir /usr/local/bin -channel 8.0 &&\ 86 | dotnet --list-sdks 87 | 88 | 89 | ################################################################################ 90 | # Riscof 91 | ################################################################################ 92 | # RUN pip3 install git+https://github.com/riscv/riscof.git 93 | RUN pip3 install --break-system-packages git+https://github.com/riscv/riscof.git 94 | # I should set this up to be built, right now it relies on host machine 95 | # already having it installed 96 | # This would require setting up ocaml as well as other build dependencies 97 | COPY riscv_sim_RV32 /usr/local/bin 98 | 99 | 100 | ################################################################################ 101 | # Entry point 102 | ################################################################################ 103 | # Override default entrypoint/cmd from base image 104 | ENTRYPOINT ["/usr/bin/env"] 105 | CMD ["/bin/bash"] 106 | 107 | -------------------------------------------------------------------------------- /docker/build.sh: -------------------------------------------------------------------------------- 1 | #/usr/bin/sh 2 | 3 | ################################################# 4 | # Script to build docker image 5 | ################################################# 6 | 7 | cp /usr/local/bin/riscv_sim_RV32 . 8 | DOCKER_BUILDKIT=1 docker build --secret id=_env,src=./.env -t computerraria . 9 | -------------------------------------------------------------------------------- /docker/push.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/sh 2 | 3 | ################################################# 4 | # Script to push docker image to docker hub 5 | ################################################# 6 | 7 | docker tag computerraria:latest misprit7/computerraria:latest 8 | docker push misprit7/computerraria:latest 9 | 10 | -------------------------------------------------------------------------------- /docker/run.sh: -------------------------------------------------------------------------------- 1 | #/usr/bin/sh 2 | 3 | ################################################# 4 | # Script to run docker container ephemerally 5 | ################################################# 6 | 7 | # --rm is important, otherwise you end up with a million extraneous containers 8 | docker run -it --rm computerraria 9 | -------------------------------------------------------------------------------- /docker/tModLoader.targets: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /run-tests.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | ################################################# 4 | # Runs all riscof tests 5 | ################################################# 6 | 7 | cd test 8 | # Why all this junk isn't specified in the config is weird, hate having to make little wrapper scripts like this 9 | riscof run --config=config.ini --suite=riscv-arch-test/riscv-test-suite/ --env=riscv-arch-test/riscv-test-suite/env 10 | -------------------------------------------------------------------------------- /test/.gitignore: -------------------------------------------------------------------------------- 1 | riscof_work/ 2 | -------------------------------------------------------------------------------- /test/computerraria/computerraria_isa.yaml: -------------------------------------------------------------------------------- 1 | hart_ids: [0] 2 | hart0: 3 | ISA: RV32I 4 | physical_addr_sz: 32 5 | User_Spec_Version: '2.3' 6 | supported_xlen: [32] 7 | misa: 8 | # reset-val: 0x40001104 9 | rv32: 10 | accessible: true 11 | mxl: 12 | implemented: true 13 | type: 14 | warl: 15 | dependency_fields: [] 16 | legal: 17 | - mxl[1:0] in [0x1] 18 | wr_illegal: 19 | - Unchanged 20 | extensions: 21 | implemented: true 22 | type: 23 | warl: 24 | dependency_fields: [] 25 | legal: 26 | - extensions[25:0] bitmask [0x0001104, 0x0000000] 27 | wr_illegal: 28 | - Unchanged 29 | 30 | -------------------------------------------------------------------------------- /test/computerraria/computerraria_platform.yaml: -------------------------------------------------------------------------------- 1 | mtime: 2 | implemented: false 3 | address: 0xbff8 4 | mtimecmp: 5 | implemented: false 6 | address: 0x4000 7 | nmi: 8 | label: nmi_vector 9 | reset: 10 | label: reset_vector 11 | -------------------------------------------------------------------------------- /test/computerraria/env/link.ld: -------------------------------------------------------------------------------- 1 | OUTPUT_ARCH( "riscv" ) 2 | ENTRY(rvtest_entry_point) 3 | 4 | SECTIONS 5 | { 6 | . = 0x00000000; 7 | .text.init : { *(.text.init) } 8 | . = ALIGN(0x1000); 9 | .tohost : { *(.tohost) } 10 | . = ALIGN(0x1000); 11 | .text : { *(.text) } 12 | /* . = ALIGN(0x1000); */ 13 | . = 0x10000; 14 | .data : { *(.data) } 15 | .data.string : { *(.data.string)} 16 | .bss : { *(.bss) } 17 | _end = .; 18 | } 19 | 20 | -------------------------------------------------------------------------------- /test/computerraria/env/model_test.h: -------------------------------------------------------------------------------- 1 | #ifndef _COMPLIANCE_MODEL_H 2 | #define _COMPLIANCE_MODEL_H 3 | #define RVMODEL_DATA_SECTION \ 4 | .pushsection .tohost,"aw",@progbits; \ 5 | .align 8; .global tohost; tohost: .dword 0; \ 6 | .align 8; .global fromhost; fromhost: .dword 0; \ 7 | .popsection; \ 8 | .align 8; .global begin_regstate; begin_regstate: \ 9 | .word 128; \ 10 | .align 8; .global end_regstate; end_regstate: \ 11 | .word 4; 12 | 13 | //RV_COMPLIANCE_HALT 14 | #define RVMODEL_HALT \ 15 | li x1, 1; \ 16 | write_tohost: \ 17 | sw x1, tohost, t5; \ 18 | j write_tohost; 19 | 20 | #define RVMODEL_BOOT 21 | 22 | //RV_COMPLIANCE_DATA_BEGIN 23 | #define RVMODEL_DATA_BEGIN \ 24 | RVMODEL_DATA_SECTION \ 25 | .align 4;\ 26 | .global begin_signature; begin_signature: 27 | 28 | //RV_COMPLIANCE_DATA_END 29 | #define RVMODEL_DATA_END \ 30 | .align 4;\ 31 | .global end_signature; end_signature: 32 | 33 | //RVTEST_IO_INIT 34 | #define RVMODEL_IO_INIT 35 | //RVTEST_IO_WRITE_STR 36 | #define RVMODEL_IO_WRITE_STR(_R, _STR) 37 | //RVTEST_IO_CHECK 38 | #define RVMODEL_IO_CHECK() 39 | //RVTEST_IO_ASSERT_GPR_EQ 40 | #define RVMODEL_IO_ASSERT_GPR_EQ(_S, _R, _I) 41 | //RVTEST_IO_ASSERT_SFPR_EQ 42 | #define RVMODEL_IO_ASSERT_SFPR_EQ(_F, _R, _I) 43 | //RVTEST_IO_ASSERT_DFPR_EQ 44 | #define RVMODEL_IO_ASSERT_DFPR_EQ(_D, _R, _I) 45 | 46 | #define RVMODEL_SET_MSW_INT \ 47 | li t1, 1; \ 48 | li t2, 0x2000000; \ 49 | sw t1, 0(t2); 50 | 51 | #define RVMODEL_CLEAR_MSW_INT \ 52 | li t2, 0x2000000; \ 53 | sw x0, 0(t2); 54 | 55 | #define RVMODEL_CLEAR_MTIMER_INT 56 | 57 | #define RVMODEL_CLEAR_MEXT_INT 58 | 59 | 60 | #endif // _COMPLIANCE_MODEL_H 61 | -------------------------------------------------------------------------------- /test/computerraria/riscof_computerraria.py: -------------------------------------------------------------------------------- 1 | import os 2 | import logging 3 | import tinterface 4 | 5 | 6 | import riscof.utils as utils 7 | import riscof.constants as constants 8 | from riscof.pluginTemplate import pluginTemplate 9 | 10 | logger = logging.getLogger() 11 | 12 | class computerraria(pluginTemplate): 13 | __model__ = "computerraria" 14 | 15 | __version__ = "2.0" 16 | 17 | def __init__(self, *args, **kwargs): 18 | super().__init__(*args, **kwargs) 19 | 20 | config = kwargs.get('config') 21 | 22 | if config is None: 23 | print("Please enter input file paths in configuration.") 24 | raise SystemExit(1) 25 | logger.info(config) 26 | 27 | # self.dut_exe = os.path.join(config['PATH'] if 'PATH' in config else \ 28 | # "~/.local/share/Steam/steamapps/common/tModLoader","start-tModLoaderServer.sh") 29 | self.dut_exe = os.path.join(config['PATH'] if 'PATH' in config else \ 30 | "echo","start-tModLoaderServer.sh") 31 | 32 | 33 | self.num_jobs = str(config['jobs'] if 'jobs' in config else 1) 34 | self.pluginpath=os.path.abspath(config['pluginpath']) 35 | self.isa_spec = os.path.abspath(config['ispec']) 36 | self.platform_spec = os.path.abspath(config['pspec']) 37 | if 'target_run' in config and config['target_run']=='0': 38 | self.target_run = False 39 | else: 40 | self.target_run = True 41 | 42 | def initialise(self, suite, work_dir, archtest_env): 43 | 44 | self.work_dir = work_dir 45 | self.suite_dir = suite 46 | self.compile_cmd = 'riscv{1}-unknown-elf-gcc -march={0} \ 47 | -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles -g\ 48 | -T '+self.pluginpath+'/env/link.ld\ 49 | -I '+self.pluginpath+'/env/\ 50 | -I ' + archtest_env + ' {2} -o {3} {4}' 51 | 52 | def build(self, isa_yaml, platform_yaml): 53 | 54 | # load the isa yaml as a dictionary in python. 55 | ispec = utils.load_yaml(isa_yaml)['hart0'] 56 | 57 | self.xlen = '32' 58 | self.isa = 'rv32I' 59 | self.compile_cmd = self.compile_cmd+' -mabi=ilp32' 60 | 61 | def runTests(self, testList): 62 | 63 | logger.info('Starting server') 64 | tserver = tinterface.TServer(terracc=False) 65 | tserver.start() 66 | logger.info('Server loaded') 67 | for testname in testList: 68 | logger.info('Running Test: {0} on DUT'.format(testname)) 69 | 70 | # for each testname we get all its fields (as described by the testList format) 71 | testentry = testList[testname] 72 | test = testentry['test_path'] 73 | test_dir = testentry['work_dir'] 74 | 75 | elf = 'dut.elf' 76 | out = 'dut-out.txt' 77 | 78 | # name of the signature file as per requirement of RISCOF. RISCOF expects the signature to 79 | # be named as DUT-.signature. The below variable creates an absolute path of 80 | # signature file. 81 | sig_file = os.path.join(test_dir, self.name[:-1] + ".signature") 82 | elf_file = os.path.join(test_dir, elf) 83 | out_file = os.path.join(test_dir, out) 84 | compile_macros= ' -D' + " -D".join(testentry['macros']) 85 | 86 | cmd = self.compile_cmd.format(testentry['isa'].lower(), self.xlen, test, elf_file, compile_macros) 87 | 88 | logger.info('Compile command: ' + cmd) 89 | utils.shellCommand(cmd).run(cwd=test_dir) 90 | 91 | if not self.target_run: 92 | continue 93 | 94 | logger.info('Starting test') 95 | 96 | try: 97 | tserver.run(elf_file, out_file, clock_cycles=50000) 98 | # Don't love hardcoding this but riscof has made it difficult enough as it is for me 99 | # Seriously why don't they pass this as a parameter to runTests 100 | tinterface.gen_signature(out_file, sig_file, 0x11110) 101 | except Exception as e: 102 | logger.error(e) 103 | logger.error('An error occured, dropping into interactive mode to debug') 104 | tserver.process.interact() 105 | raise SystemExit 106 | 107 | logger.info('Test complete') 108 | 109 | 110 | 111 | -------------------------------------------------------------------------------- /test/config.ini: -------------------------------------------------------------------------------- 1 | [RISCOF] 2 | ReferencePlugin=sail_cSim 3 | ReferencePluginPath=./sail_cSim 4 | DUTPlugin=computerraria 5 | DUTPluginPath=./computerraria 6 | 7 | [computerraria] 8 | pluginpath=./computerraria 9 | ispec=./computerraria/computerraria_isa.yaml 10 | pspec=./computerraria/computerraria_platform.yaml 11 | target_run=1 12 | 13 | [sail_cSim] 14 | pluginpath=./sail_cSim 15 | -------------------------------------------------------------------------------- /test/manual/inf.s: -------------------------------------------------------------------------------- 1 | jal x0, 4 2 | jal x0, -4 3 | -------------------------------------------------------------------------------- /test/manual/inf.txt: -------------------------------------------------------------------------------- 1 | 6f 00 40 00 6f f0 df ff 2 | -------------------------------------------------------------------------------- /test/manual/loop.s: -------------------------------------------------------------------------------- 1 | .global _start 2 | .text 3 | # bin read /home/xander/dev/terraria/computerraria/test/manual/loop.txt 4 | 5 | _start: 6 | xor x1, x1, x1 7 | xor x2, x2, x2 8 | xor x3, x3, x3 9 | xor x4, x4, x4 10 | addi x1, x1, 1 11 | addi x2, x2, 3 12 | addi x4, x4, 5 13 | loop: 14 | add x1, x1, x2 15 | addi x3, x3, 1 16 | blt x3, x4, loop 17 | sw x1, 100(x0) 18 | lui x5, 0x1 19 | addi x5, x5, 2046 20 | addi x5, x5, 2046 21 | sw x2, 0(x5) 22 | -------------------------------------------------------------------------------- /test/manual/loop.txt: -------------------------------------------------------------------------------- 1 | b3 c0 10 00 33 41 21 00 b3 c1 31 00 33 42 42 00 93 80 10 00 13 01 31 00 13 02 52 00 b3 80 20 00 93 81 11 00 e3 cc 41 fe 23 22 10 06 b7 12 00 00 93 82 e2 7f 93 82 e2 7f 23 a0 22 00 2 | -------------------------------------------------------------------------------- /test/sail_cSim/__init__.py: -------------------------------------------------------------------------------- 1 | from pkgutil import extend_path 2 | __path__ = extend_path(__path__, __name__) -------------------------------------------------------------------------------- /test/sail_cSim/env/link.ld: -------------------------------------------------------------------------------- 1 | OUTPUT_ARCH( "riscv" ) 2 | ENTRY(rvtest_entry_point) 3 | 4 | SECTIONS 5 | { 6 | . = 0x80000000; 7 | .text.init : { *(.text.init) } 8 | . = ALIGN(0x1000); 9 | .tohost : { *(.tohost) } 10 | . = ALIGN(0x1000); 11 | .text : { *(.text) } 12 | . = ALIGN(0x1000); 13 | .data : { *(.data) } 14 | .data.string : { *(.data.string)} 15 | .bss : { *(.bss) } 16 | _end = .; 17 | } 18 | 19 | -------------------------------------------------------------------------------- /test/sail_cSim/env/model_test.h: -------------------------------------------------------------------------------- 1 | #ifndef _COMPLIANCE_MODEL_H 2 | #define _COMPLIANCE_MODEL_H 3 | 4 | #define RVMODEL_DATA_SECTION \ 5 | .pushsection .tohost,"aw",@progbits; \ 6 | .align 8; .global tohost; tohost: .dword 0; \ 7 | .align 8; .global fromhost; fromhost: .dword 0; \ 8 | .popsection; \ 9 | .align 8; .global begin_regstate; begin_regstate: \ 10 | .word 128; \ 11 | .align 8; .global end_regstate; end_regstate: \ 12 | .word 4; 13 | 14 | //RV_COMPLIANCE_HALT 15 | #define RVMODEL_HALT \ 16 | li x1, 1; \ 17 | write_tohost: \ 18 | sw x1, tohost, t5; \ 19 | j write_tohost; 20 | 21 | #define RVMODEL_BOOT 22 | 23 | //RV_COMPLIANCE_DATA_BEGIN 24 | #define RVMODEL_DATA_BEGIN \ 25 | RVMODEL_DATA_SECTION \ 26 | .align 4;\ 27 | .global begin_signature; begin_signature: 28 | 29 | //RV_COMPLIANCE_DATA_END 30 | #define RVMODEL_DATA_END \ 31 | .align 4; .global end_signature; end_signature: 32 | 33 | //RVTEST_IO_INIT 34 | #define RVMODEL_IO_INIT 35 | //RVTEST_IO_WRITE_STR 36 | #define RVMODEL_IO_WRITE_STR(_R, _STR) 37 | //RVTEST_IO_CHECK 38 | #define RVMODEL_IO_CHECK() 39 | //RVTEST_IO_ASSERT_GPR_EQ 40 | #define RVMODEL_IO_ASSERT_GPR_EQ(_S, _R, _I) 41 | //RVTEST_IO_ASSERT_SFPR_EQ 42 | #define RVMODEL_IO_ASSERT_SFPR_EQ(_F, _R, _I) 43 | //RVTEST_IO_ASSERT_DFPR_EQ 44 | #define RVMODEL_IO_ASSERT_DFPR_EQ(_D, _R, _I) 45 | 46 | #define RVMODEL_SET_MSW_INT 47 | 48 | #define RVMODEL_CLEAR_MSW_INT 49 | 50 | #define RVMODEL_CLEAR_MTIMER_INT 51 | 52 | #define RVMODEL_CLEAR_MEXT_INT 53 | 54 | 55 | #endif // _COMPLIANCE_MODEL_H 56 | -------------------------------------------------------------------------------- /test/sail_cSim/riscof_sail_cSim.py: -------------------------------------------------------------------------------- 1 | import os 2 | import re 3 | import shutil 4 | import subprocess 5 | import shlex 6 | import logging 7 | import random 8 | import string 9 | from string import Template 10 | 11 | import riscof.utils as utils 12 | from riscof.pluginTemplate import pluginTemplate 13 | import riscof.constants as constants 14 | from riscv_isac.isac import isac 15 | 16 | logger = logging.getLogger() 17 | 18 | class sail_cSim(pluginTemplate): 19 | __model__ = "sail_c_simulator" 20 | __version__ = "0.5.0" 21 | 22 | def __init__(self, *args, **kwargs): 23 | sclass = super().__init__(*args, **kwargs) 24 | 25 | config = kwargs.get('config') 26 | if config is None: 27 | logger.error("Config node for sail_cSim missing.") 28 | raise SystemExit(1) 29 | self.num_jobs = str(config['jobs'] if 'jobs' in config else 1) 30 | self.pluginpath = os.path.abspath(config['pluginpath']) 31 | self.sail_exe = { '32' : os.path.join(config['PATH'] if 'PATH' in config else "","riscv_sim_RV32"), 32 | '64' : os.path.join(config['PATH'] if 'PATH' in config else "","riscv_sim_RV64")} 33 | self.isa_spec = os.path.abspath(config['ispec']) if 'ispec' in config else '' 34 | self.platform_spec = os.path.abspath(config['pspec']) if 'ispec' in config else '' 35 | self.make = config['make'] if 'make' in config else 'make' 36 | logger.debug("SAIL CSim plugin initialised using the following configuration.") 37 | for entry in config: 38 | logger.debug(entry+' : '+config[entry]) 39 | return sclass 40 | 41 | def initialise(self, suite, work_dir, archtest_env): 42 | self.suite = suite 43 | self.work_dir = work_dir 44 | self.objdump_cmd = 'riscv{1}-unknown-elf-objdump -D {0} > {2};' 45 | self.compile_cmd = 'riscv{1}-unknown-elf-gcc -march={0} \ 46 | -static -mcmodel=medany -fvisibility=hidden -nostdlib -nostartfiles\ 47 | -T '+self.pluginpath+'/env/link.ld\ 48 | -I '+self.pluginpath+'/env/\ 49 | -I ' + archtest_env 50 | 51 | def build(self, isa_yaml, platform_yaml): 52 | ispec = utils.load_yaml(isa_yaml)['hart0'] 53 | self.xlen = ('64' if 64 in ispec['supported_xlen'] else '32') 54 | self.isa = 'rv' + self.xlen 55 | self.compile_cmd = self.compile_cmd+' -mabi='+('lp64 ' if 64 in ispec['supported_xlen'] else 'ilp32 ') 56 | if "I" in ispec["ISA"]: 57 | self.isa += 'i' 58 | if "M" in ispec["ISA"]: 59 | self.isa += 'm' 60 | if "C" in ispec["ISA"]: 61 | self.isa += 'c' 62 | if "F" in ispec["ISA"]: 63 | self.isa += 'f' 64 | if "D" in ispec["ISA"]: 65 | self.isa += 'd' 66 | objdump = "riscv{0}-unknown-elf-objdump".format(self.xlen) 67 | if shutil.which(objdump) is None: 68 | logger.error(objdump+": executable not found. Please check environment setup.") 69 | raise SystemExit(1) 70 | compiler = "riscv{0}-unknown-elf-gcc".format(self.xlen) 71 | if shutil.which(compiler) is None: 72 | logger.error(compiler+": executable not found. Please check environment setup.") 73 | raise SystemExit(1) 74 | if shutil.which(self.sail_exe[self.xlen]) is None: 75 | logger.error(self.sail_exe[self.xlen]+ ": executable not found. Please check environment setup.") 76 | raise SystemExit(1) 77 | if shutil.which(self.make) is None: 78 | logger.error(self.make+": executable not found. Please check environment setup.") 79 | raise SystemExit(1) 80 | 81 | 82 | def runTests(self, testList, cgf_file=None): 83 | if os.path.exists(self.work_dir+ "/Makefile." + self.name[:-1]): 84 | os.remove(self.work_dir+ "/Makefile." + self.name[:-1]) 85 | make = utils.makeUtil(makefilePath=os.path.join(self.work_dir, "Makefile." + self.name[:-1])) 86 | make.makeCommand = self.make + ' -j' + self.num_jobs 87 | for file in testList: 88 | testentry = testList[file] 89 | test = testentry['test_path'] 90 | test_dir = testentry['work_dir'] 91 | test_name = test.rsplit('/',1)[1][:-2] 92 | 93 | elf = 'ref.elf' 94 | 95 | execute = "@cd "+testentry['work_dir']+";" 96 | 97 | cmd = self.compile_cmd.format(testentry['isa'].lower(), self.xlen) + ' ' + test + ' -o ' + elf 98 | compile_cmd = cmd + ' -D' + " -D".join(testentry['macros']) 99 | execute+=compile_cmd+";" 100 | 101 | execute += self.objdump_cmd.format(elf, self.xlen, 'ref.disass') 102 | sig_file = os.path.join(test_dir, self.name[:-1] + ".signature") 103 | 104 | execute += self.sail_exe[self.xlen] + ' --test-signature={0} {1} > {2}.log 2>&1;'.format(sig_file, elf, test_name) 105 | 106 | cov_str = ' ' 107 | for label in testentry['coverage_labels']: 108 | cov_str+=' -l '+label 109 | 110 | if cgf_file is not None: 111 | coverage_cmd = 'riscv_isac --verbose info coverage -d \ 112 | -t {0}.log --parser-name c_sail -o coverage.rpt \ 113 | --sig-label begin_signature end_signature \ 114 | --test-label rvtest_code_begin rvtest_code_end \ 115 | -e ref.elf -c {1} -x{2} {3};'.format(\ 116 | test_name, ' -c '.join(cgf_file), self.xlen, cov_str) 117 | else: 118 | coverage_cmd = '' 119 | 120 | 121 | execute+=coverage_cmd 122 | 123 | make.add_target(execute) 124 | make.execute_all(self.work_dir) 125 | -------------------------------------------------------------------------------- /tinterface/bin/tcli: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | import argparse 4 | import tinterface 5 | 6 | # pyright: reportOptionalMemberAccess=false 7 | 8 | parser = argparse.ArgumentParser( 9 | prog = 'tinterfacecli', 10 | description = 'A command line interface to interact with terraria server for computerraria', 11 | ) 12 | 13 | parser.add_argument( 14 | '-p', 15 | '--path', 16 | type=str, 17 | help='path to Terraria server executable', 18 | ) 19 | parser.add_argument( 20 | '-w', 21 | '--world', 22 | type=str, 23 | help='path to .wld world file', 24 | ) 25 | parser.add_argument( 26 | '-r', 27 | '--run', 28 | type=str, 29 | help='run the given program and write the results to the output file', 30 | ) 31 | parser.add_argument( 32 | '-o', 33 | '--output', 34 | type=str, 35 | help='output file of run', 36 | ) 37 | parser.add_argument( 38 | '-c', 39 | '--cycles', 40 | type=int, 41 | help='number of cycles to let program run for', 42 | default=50000 43 | ) 44 | parser.add_argument( 45 | '-i', 46 | '--interactive', 47 | action='store_true', 48 | help='leave the server in interactive mode after other operations finish', 49 | ) 50 | 51 | 52 | 53 | args = parser.parse_args() 54 | 55 | t = tinterface.TServer(path=args.path, world=args.world, verbose=True) 56 | t.start() 57 | 58 | if args.run is not None: 59 | try: 60 | t.run(args.run, args.output, clock_cycles=args.cycles) 61 | except Exception as e: 62 | print(e) 63 | print('An error occured, starting interactive mode to let you debug') 64 | args.interactive = True 65 | 66 | if args.interactive: 67 | t.process.interact() 68 | 69 | 70 | -------------------------------------------------------------------------------- /tinterface/setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | setup( 4 | name='tinterface', 5 | version='0.1', 6 | description='Terraria server python/cli interface', 7 | url='https://github.com/misprit7/computerraria', 8 | author='Xander Naumenko', 9 | author_email='xandernaumenko@gmail.com', 10 | license='MIT', 11 | packages=['tinterface'], 12 | zip_safe=False, 13 | scripts=['bin/tcli'], 14 | install_requires=[ 15 | "pexpect" 16 | ], 17 | ) 18 | --------------------------------------------------------------------------------