├── .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 |
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 |
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 | 
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 | 
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 |
--------------------------------------------------------------------------------