Remove Rust emulator
3222
Cargo.lock
generated
21
Cargo.toml
|
@ -1,21 +0,0 @@
|
||||||
[package]
|
|
||||||
name = "fox32"
|
|
||||||
version = "0.5.0"
|
|
||||||
authors = ["ry"]
|
|
||||||
edition = "2021"
|
|
||||||
build = "build.rs"
|
|
||||||
|
|
||||||
[dependencies]
|
|
||||||
chrono = "0.4"
|
|
||||||
image = "0.24"
|
|
||||||
log = "0.4"
|
|
||||||
pixels = "0.9.0"
|
|
||||||
rfd = "0.7.0"
|
|
||||||
ringbuf = "0.2"
|
|
||||||
rodio = "0.15.0"
|
|
||||||
winit = "0.26"
|
|
||||||
winit_input_helper = "0.11"
|
|
||||||
|
|
||||||
[build-dependencies]
|
|
||||||
anyhow = "1.0"
|
|
||||||
vergen = { version = "7", default-features = false, features = ["build", "git"] }
|
|
21
LICENSE
|
@ -1,21 +0,0 @@
|
||||||
MIT License
|
|
||||||
|
|
||||||
Copyright (c) 2022 ryfox/ry755
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
9
build.rs
|
@ -1,9 +0,0 @@
|
||||||
use anyhow::Result;
|
|
||||||
use vergen::{Config, ShaKind, vergen};
|
|
||||||
|
|
||||||
fn main() -> Result<()> {
|
|
||||||
let mut config = Config::default();
|
|
||||||
*config.git_mut().sha_kind_mut() = ShaKind::Short;
|
|
||||||
*config.git_mut().skip_if_error_mut() = true;
|
|
||||||
vergen(config)
|
|
||||||
}
|
|
|
@ -1,51 +0,0 @@
|
||||||
# Encoding
|
|
||||||
```
|
|
||||||
size instr . cond dest src <src> <dest>
|
|
||||||
xx xxxxxx 0 xxx xx xx <8,16,32 bits> <8,16,32 bits>
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
# Size table
|
|
||||||
If the instruction doesn't allow variable sizes or a size was not specified, set the size bits to Word (0b10)
|
|
||||||
| | |
|
|
||||||
| :--: | -------------- |
|
|
||||||
| 0b00 | byte (8 bits) |
|
|
||||||
| 0b01 | half (16 bits) |
|
|
||||||
| 0b10 | word (32 bits) |
|
|
||||||
|
|
||||||
# Instruction table
|
|
||||||
| 0x | -0 | -1 | -2 | -3 | -4 | -5 | -6 | -7 | -8 | -9 | -A | -B | -C | -D | -E | -F |
|
|
||||||
| :-: | ---- | ------------- | ------------- | ------------- | ------------- | ------------- | ------------- | -------------- | ---- | ----- | -------------- | --- | --- | --- | --- | --- |
|
|
||||||
| 0- | NOP | ADD[.8,16,32] | MUL[.8,16,32] | AND[.8,16,32] | SLA[.8,16,32] | SRA[.8,16,32] | BSE[.8,16,32] | CMP[.8,16,32] | JMP | RJMP | PUSH[.8,16,32] | IN | ISE | MSE | | |
|
|
||||||
| 1- | HALT | INC[.8,16,32] | | OR[.8,16,32] | | SRL[.8,16,32] | BCL[.8,16,32] | MOV[.8,16,32] | CALL | RCALL | POP[.8,16,32] | OUT | ICL | MCL | | |
|
|
||||||
| 2- | BRK | SUB[.8,16,32] | DIV[.8,16,32] | XOR[.8,16,32] | ROL[.8,16,32] | ROR[.8,16,32] | BTS[.8,16,32] | MOVZ[.8,16,32] | LOOP | RLOOP | RET | | INT | TLB | | |
|
|
||||||
| 3- | | DEC[.8,16,32] | REM[.8,16,32] | NOT[.8,16,32] | | | | | | RTA | RETI | | | FLP | | |
|
|
||||||
|
|
||||||
# Condition table
|
|
||||||
| | | |
|
|
||||||
| :---: | ------ | --------------------------------------------- |
|
|
||||||
| 0b000 | --- | always |
|
|
||||||
| 0b001 | IFZ | zero |
|
|
||||||
| 0b010 | IFNZ | not zero |
|
|
||||||
| 0b011 | IFC | carry |
|
|
||||||
| 0b011 | IFLT | less than (equivalent to IFC) |
|
|
||||||
| 0b100 | IFNC | not carry |
|
|
||||||
| 0b100 | IFGTEQ | greater than or equal to (equivalent to IFNC) |
|
|
||||||
| 0b101 | IFGT | greater than |
|
|
||||||
| 0b110 | IFLTEQ | less than or equal to |
|
|
||||||
|
|
||||||
# Destination table
|
|
||||||
| | |
|
|
||||||
| :--: | ------------------- |
|
|
||||||
| 0b00 | register |
|
|
||||||
| 0b01 | register (pointer) |
|
|
||||||
| 0b10 | (invalid) |
|
|
||||||
| 0b11 | immediate (pointer) |
|
|
||||||
|
|
||||||
# Source table
|
|
||||||
| | |
|
|
||||||
| :--: | ------------------- |
|
|
||||||
| 0b00 | register |
|
|
||||||
| 0b01 | register (pointer) |
|
|
||||||
| 0b10 | immediate |
|
|
||||||
| 0b11 | immediate (pointer) |
|
|
Before Width: | Height: | Size: 8.5 KiB |
|
@ -1,150 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<svg
|
|
||||||
viewBox="0 0 36 36"
|
|
||||||
version="1.1"
|
|
||||||
id="svg16"
|
|
||||||
sodipodi:docname="32.svg"
|
|
||||||
inkscape:export-filename="/home/ry/Documents/fox32/docs/logos/32.png"
|
|
||||||
inkscape:export-xdpi="341.33334"
|
|
||||||
inkscape:export-ydpi="341.33334"
|
|
||||||
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04, custom)"
|
|
||||||
width="36"
|
|
||||||
height="36"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg">
|
|
||||||
<defs
|
|
||||||
id="defs20">
|
|
||||||
<inkscape:path-effect
|
|
||||||
effect="powerclip"
|
|
||||||
id="path-effect51605"
|
|
||||||
is_visible="true"
|
|
||||||
lpeversion="1"
|
|
||||||
inverse="true"
|
|
||||||
flatten="false"
|
|
||||||
hide_clip="false"
|
|
||||||
message="Use fill-rule evenodd on <b>fill and stroke</b> dialog if no flatten result after convert clip to paths." />
|
|
||||||
<clipPath
|
|
||||||
clipPathUnits="userSpaceOnUse"
|
|
||||||
id="clipPath51601">
|
|
||||||
<path
|
|
||||||
style="display:none;fill:#f18f26;fill-opacity:1;stroke-width:0.0502793"
|
|
||||||
d="M 14.587831,27.863504 C 14.382965,27.727479 13.734884,26.908543 13.457514,26.435201 13.074891,25.782241 12.802463,25.12596 12.2477,23.520759 11.54419,21.485155 11.532784,21.464321 11.049545,21.332324 10.678257,21.230906 9.0747412,21.190197 8.3212291,21.263058 7.5503856,21.337595 6.4089614,21.570204 5.6761529,21.802094 4.1005881,22.300666 3.0721423,22.860948 2.1641077,23.715406 1.7440613,24.110668 1.696405,24.142717 1.7284655,24.00838 1.7908089,23.747154 2.5898195,22.17273 2.964067,21.573668 3.3024942,21.031943 4.10012,19.944034 4.5066782,19.469646 4.6078844,19.351555 4.6742061,19.238427 4.6540598,19.21825 4.6339135,19.198073 4.172433,19.1738 3.6285475,19.164311 c -0.5438855,-0.0095 -0.9971402,-0.02529 -1.0072326,-0.03511 -0.051212,-0.04983 1.4590175,-2.760125 2.0373689,-3.656307 0.7207834,-1.116888 1.8379204,-2.499044 2.7887559,-3.450332 1.1558488,-1.1564 2.2171525,-1.919729 3.7145713,-2.6716564 1.167618,-0.5863179 2.814287,-0.8933047 5.434415,-1.0131321 2.787996,-0.1275046 5.8009,0.134319 7.311395,0.6353659 1.064281,0.3530328 2.407592,1.1206046 3.519475,2.0110386 1.248433,0.999788 2.838308,2.82234 3.90961,4.48178 0.566992,0.878269 2.048569,3.523133 2.048569,3.657043 0,0.01838 -0.345042,0.03566 -0.76676,0.0384 -0.421718,0.0027 -0.889733,0.0197 -1.040035,0.03771 l -0.273275,0.03274 0.340993,0.418558 c 0.563124,0.691217 1.176336,1.55625 1.545759,2.18054 0.377875,0.638571 1.019097,1.934392 1.077479,2.177438 0.03251,0.135328 -0.0072,0.109342 -0.386254,-0.25271 -1.055819,-1.008484 -2.340669,-1.658309 -4.22344,-2.136041 -1.067335,-0.270825 -1.740108,-0.360359 -2.911339,-0.387453 -1.113448,-0.02576 -1.922155,0.05148 -2.104624,0.201 -0.172488,0.141344 -0.558337,1.078132 -1.216006,2.952299 -0.549422,1.565695 -1.162101,2.673918 -1.842111,3.332038 l -0.247837,0.239859 -0.159143,-0.07939 c -0.269958,-0.134674 -0.960666,-0.172303 -3.153742,-0.171816 -2.179025,5.03e-4 -2.9376,0.03891 -3.182763,0.16121 -0.123158,0.06144 -0.156957,0.06093 -0.254546,-0.0039 z"
|
|
||||||
id="path51603" />
|
|
||||||
<path
|
|
||||||
id="lpe_path-effect51605"
|
|
||||||
style="fill:#f18f26;fill-opacity:1;stroke-width:0.0502793"
|
|
||||||
class="powerclip"
|
|
||||||
d="M 6,10.5 H 30 V 36.776 H 6 Z m 8.587831,17.363504 v -2.1e-5 c 0.09759,0.06483 0.131388,0.06534 0.254546,0.0039 0.245163,-0.1223 1.003738,-0.160707 3.182763,-0.16121 2.193076,-4.87e-4 2.883784,0.03714 3.153742,0.171816 l 0.159143,0.07939 0.247837,-0.239859 c 0.68001,-0.65812 1.292689,-1.766343 1.842111,-3.332038 0.657669,-1.874167 1.043518,-2.810955 1.216006,-2.952299 0.182469,-0.14952 0.991176,-0.22676 2.104624,-0.201 1.171231,0.02709 1.844004,0.116628 2.911339,0.387453 1.882771,0.477732 3.167621,1.127557 4.22344,2.136041 0.379054,0.362052 0.418764,0.388038 0.386254,0.25271 -0.05838,-0.243046 -0.699604,-1.538867 -1.077479,-2.177438 -0.369423,-0.62429 -0.982635,-1.489323 -1.545759,-2.18054 l -0.340993,-0.418558 0.273275,-0.03274 c 0.150302,-0.01801 0.618317,-0.03501 1.040035,-0.03771 0.421718,-0.0027 0.76676,-0.02002 0.76676,-0.0384 0,-0.13391 -1.481577,-2.778774 -2.048569,-3.657043 -1.071302,-1.65944 -2.661177,-3.481992 -3.90961,-4.48178 C 26.315413,10.093744 24.972102,9.3261722 23.907821,8.9731394 22.397326,8.4720925 19.384422,8.2102689 16.596426,8.3377735 13.976298,8.4576009 12.329629,8.7645877 11.162011,9.3509056 9.6645922,10.102833 8.6032885,10.866162 7.4474397,12.022562 6.4966042,12.97385 5.3794672,14.356006 4.6586838,15.472894 c -0.5783514,0.896182 -2.0885809,3.606477 -2.0373689,3.656307 0.010092,0.0098 0.4633471,0.02561 1.0072326,0.03511 0.5438855,0.0095 1.005366,0.03376 1.0255123,0.05394 0.020146,0.02018 -0.046175,0.133305 -0.1473816,0.251396 -0.4065582,0.474388 -1.204184,1.562297 -1.5426112,2.104022 -0.3742475,0.599062 -1.1732581,2.173486 -1.2356015,2.434712 -0.032061,0.134337 0.015596,0.102288 0.4356422,-0.292974 0.9080346,-0.854458 1.9364804,-1.41474 3.5120452,-1.913312 0.7328085,-0.23189 1.8742327,-0.464499 2.6450762,-0.539036 0.7535121,-0.07286 2.3570279,-0.03215 2.7283159,0.06927 0.483239,0.131997 0.494645,0.152831 1.198155,2.188435 0.554763,1.605201 0.827191,2.261482 1.209814,2.914442 0.27737,0.473342 0.925451,1.292278 1.130317,1.428303 z" />
|
|
||||||
</clipPath>
|
|
||||||
</defs>
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="namedview18"
|
|
||||||
pagecolor="#ffffff"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1.0"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:pageopacity="0.0"
|
|
||||||
inkscape:pagecheckerboard="0"
|
|
||||||
showgrid="false"
|
|
||||||
inkscape:zoom="19.888889"
|
|
||||||
inkscape:cx="14.606145"
|
|
||||||
inkscape:cy="16.240223"
|
|
||||||
inkscape:window-width="1920"
|
|
||||||
inkscape:window-height="1132"
|
|
||||||
inkscape:window-x="0"
|
|
||||||
inkscape:window-y="32"
|
|
||||||
inkscape:window-maximized="1"
|
|
||||||
inkscape:current-layer="svg16"
|
|
||||||
fit-margin-top="0"
|
|
||||||
fit-margin-left="0"
|
|
||||||
fit-margin-right="0"
|
|
||||||
fit-margin-bottom="0"
|
|
||||||
width="36px" />
|
|
||||||
<path
|
|
||||||
fill="#f4900c"
|
|
||||||
d="M 13.436985,9.7783459 C 14.094985,12.416346 4.7639847,20.267346 2.1929847,13.876346 0.70198476,10.173346 -0.60001524,2.4103459 0.87998476,2.0413459 c 1.47999994,-0.368 11.90000024,5.098 12.55700024,7.737 z"
|
|
||||||
id="path2" />
|
|
||||||
<path
|
|
||||||
fill="#a0041e"
|
|
||||||
d="m 11.442985,10.331346 c 0.96,1.538 -1.8310003,4.561 -3.3680003,5.522 -1.538,0.961 -2.899,-0.552 -4.414,-4.414 -0.662,-1.6890001 -1.666,-6.2700001 -1.103,-6.6220001 0.562,-0.351 7.9240003,3.976 8.8850003,5.5140001 z"
|
|
||||||
id="path4" />
|
|
||||||
<path
|
|
||||||
fill="#f4900c"
|
|
||||||
d="m 22.562985,9.7783459 c -0.657,2.6390001 8.673,10.4890001 11.245,4.0980001 1.49,-3.703 2.792,-11.4660001 1.312,-11.8350001 -1.48,-0.368 -11.899,5.098 -12.557,7.737 z"
|
|
||||||
id="path6" />
|
|
||||||
<path
|
|
||||||
fill="#a0041e"
|
|
||||||
d="m 24.557985,10.331346 c -0.96,1.538 1.831,4.561 3.368,5.522 1.537,0.961 2.898,-0.552 4.413,-4.414 0.662,-1.6880001 1.666,-6.2690001 1.104,-6.6210001 -0.563,-0.352 -7.924,3.975 -8.885,5.5130001 z"
|
|
||||||
id="path8" />
|
|
||||||
<path
|
|
||||||
fill="#f18f26"
|
|
||||||
d="m 32.352985,26.888346 c 0,-0.454 -0.188,-1.091 -0.407,-1.687 0.585,0.028 1.519,0.191 2.77,0.817 -0.008,-0.536 -0.118,-0.984 -0.273,-1.393 0.041,0.02 0.075,0.034 0.116,0.055 -1.103,-3.31 -3.309,-5.517 -3.309,-5.517 h 2.206 c -2.331,-4.663 -4.965,-8.015 -8.075,-9.5590001 -1.39,-0.873 -3.688,-1.338 -7.373,-1.339 h -0.003 c -3.695,0 -5.996,0.468 -7.385,1.346 C 7.5159847,11.158346 4.8859847,14.507346 2.5589847,19.163346 h 2.207 c 0,0 -2.207,2.206 -3.311,5.517 0.03,-0.015 0.055,-0.025 0.084,-0.04 -0.201,0.392 -0.307,0.847 -0.282,1.377 1.263,-0.632 2.217,-0.792 2.813,-0.818 -0.189,0.513 -0.343,1.044 -0.386,1.475 -0.123,0.371 -0.191,0.812 -0.135,1.343 3.207,-1.457 4.707,-1.249 6.4570003,-0.374 1.213,3.623 4.206,6.333 8.001,6.333 3.793,0 6.746,-2.794 7.958,-6.416 1.458,-1.25 3.708,-0.875 6.416,0.416 0.066,-0.414 0.036,-0.773 -0.036,-1.093 z"
|
|
||||||
id="path10" />
|
|
||||||
<path
|
|
||||||
fill="#ffd983"
|
|
||||||
d="m 31.248985,23.577346 c 0.006,0 1.108,0.003 3.309,1.103 -1.249,-2.839 -7.525,-4.07 -9.931,-3.291 -1.171,1.954 -1.281,5.003 -3.383,6.622 -1.741,1.431 -4.713,1.458 -6.479,0 -2.345,-1.924 -2.559,-5.813 -3.382,-6.622 -2.4070003,-0.781 -8.6810003,0.454 -9.9310003,3.291 2.201,-1.101 3.304,-1.103 3.309,-1.103 0,0.001 -1.103,2.208 -1.103,3.311 l 10e-4,-10e-4 v 10e-4 c 2.398,-1.573 5.116,-2.271 7.4290003,-0.452 1.666,7.921 12.293,7.545 13.833,0 2.314,-1.818 5.03,-1.122 7.429,0.452 v -10e-4 l 0.001,10e-4 c 0.002,-1.103 -1.101,-3.311 -1.102,-3.311 z"
|
|
||||||
id="path12" />
|
|
||||||
<path
|
|
||||||
fill="#272b2b"
|
|
||||||
d="m 11,17 c 0,0 0,-1.5 1.5,-1.5 1.5,0 1.5,1.5 1.5,1.5 v 1.5 c 0,0 0,1.5 -1.5,1.5 C 11,20 11,18.5 11,18.5 Z m 11,0 c 0,0 0,-1.5 1.5,-1.5 1.5,0 1.5,1.5 1.5,1.5 v 1.5 c 0,0 0,1.5 -1.5,1.5 C 22,20 22,18.5 22,18.5 Z m -7.061,10.808 c -1.021,0.208 2.041,3.968 3.062,3.968 1.02,0 4.082,-3.76 3.062,-3.968 -1.021,-0.208 -5.103,-0.208 -6.124,0 z"
|
|
||||||
id="path14"
|
|
||||||
clip-path="url(#clipPath51601)"
|
|
||||||
inkscape:path-effect="#path-effect51605"
|
|
||||||
inkscape:original-d="m 11,17 c 0,0 0,-1.5 1.5,-1.5 1.5,0 1.5,1.5 1.5,1.5 v 1.5 c 0,0 0,1.5 -1.5,1.5 C 11,20 11,18.5 11,18.5 Z m 11,0 c 0,0 0,-1.5 1.5,-1.5 1.5,0 1.5,1.5 1.5,1.5 v 1.5 c 0,0 0,1.5 -1.5,1.5 C 22,20 22,18.5 22,18.5 Z m -7.061,10.808 c -1.021,0.208 2.041,3.968 3.062,3.968 1.02,0 4.082,-3.76 3.062,-3.968 -1.021,-0.208 -5.103,-0.208 -6.124,0 z"
|
|
||||||
transform="translate(0.00598476,-0.0236541)" />
|
|
||||||
<rect
|
|
||||||
id="rect20344"
|
|
||||||
width="14.987617"
|
|
||||||
height="5.4221425"
|
|
||||||
x="10.660814"
|
|
||||||
y="15.06275" />
|
|
||||||
<path
|
|
||||||
style="fill:#f18f26;fill-opacity:1;stroke-width:0.0502793"
|
|
||||||
d="m 10.665203,17.775229 v -2.664805 h 7.49162 7.49162 v 2.664805 2.664804 h -7.49162 -7.49162 z"
|
|
||||||
id="path43623" />
|
|
||||||
<path
|
|
||||||
style="fill:#f18f26;fill-opacity:1;stroke-width:0.0502793"
|
|
||||||
d="M 14.315606,27.528379 C 13.46489,26.637945 12.88055,25.459451 12.197043,23.255676 11.923358,22.373255 11.743921,21.90606 11.554649,21.583091 c -0.126701,-0.216198 -0.142027,-0.225105 -0.547607,-0.318215 -0.576266,-0.132297 -2.3143337,-0.134641 -3.1574819,-0.0043 -1.9761923,0.305592 -3.8463816,0.979038 -4.9946162,1.798537 -0.2443852,0.174418 -0.60074,0.4846 -0.7918994,0.689291 -0.1911594,0.204691 -0.3475626,0.348334 -0.3475626,0.319207 0,-0.09995 0.5829805,-1.340028 0.870599,-1.851886 0.5399921,-0.960992 1.3195062,-2.062849 1.937075,-2.73809 0.1426508,-0.155972 0.2593651,-0.297382 0.2593651,-0.314246 0,-0.01686 -0.4864525,-0.03066 -1.0810056,-0.03066 -0.594553,0 -1.0810056,-0.0066 -1.0810056,-0.01461 0,-0.008 0.1833343,-0.364389 0.4074094,-0.7919 1.3941728,-2.659922 2.6984315,-4.540018 4.2674621,-6.151569 1.2172475,-1.250235 2.0634416,-1.874141 3.7971957,-2.7997066 1.47896,-0.7895434 4.73153,-1.2087858 8.205581,-1.0576642 1.542956,0.067119 2.444202,0.1617141 3.459224,0.3630819 1.241039,0.2462071 1.689399,0.4193972 3.041899,1.1750086 2.206292,1.2326053 4.353351,3.5582893 6.223065,6.7407943 0.468591,0.797605 1.369114,2.447936 1.369114,2.509089 0,0.01511 -0.486453,0.02747 -1.081006,0.02747 -0.594553,0 -1.081005,0.01868 -1.081005,0.04152 0,0.02283 0.05931,0.09637 0.131808,0.163408 0.463289,0.428437 1.593185,2.012135 2.124307,2.977497 0.261765,0.47578 0.810924,1.656856 0.810924,1.744054 0,0.02366 -0.197975,-0.154148 -0.439944,-0.395139 -0.24197,-0.240991 -0.633862,-0.566615 -0.870873,-0.723611 -1.169171,-0.774457 -2.937534,-1.390064 -4.823261,-1.679088 -0.843788,-0.129326 -2.585209,-0.127933 -3.1531,0.0025 l -0.412876,0.09485 -0.199056,0.407949 c -0.263912,0.540865 -0.354247,0.774214 -0.771053,1.991746 -0.764143,2.232138 -1.188289,3.06167 -1.961072,3.835402 l -0.340569,0.340988 -0.1384,-0.100049 c -0.229821,-0.166136 -1.295001,-0.220591 -3.692872,-0.188789 -2.082095,0.02761 -2.542915,0.06325 -2.70411,0.209133 -0.07997,0.07237 -0.116314,0.04729 -0.473696,-0.326774 z m 3.853787,-7.075775 -7.50419,-0.0129 v -2.664475 -2.664476 l 7.50419,-0.0129 7.50419,-0.0129 -7.52933,-0.01241 -7.529329,-0.0124 v 2.715084 2.715083 l 7.529329,-0.0124 7.52933,-0.0124 z"
|
|
||||||
id="path43662" />
|
|
||||||
<path
|
|
||||||
style="fill:#f18f26;fill-opacity:1;stroke-width:0.0502793"
|
|
||||||
d="m 14.315606,27.528379 c -0.858133,-0.898197 -1.294443,-1.768132 -2.082541,-4.152256 -0.453391,-1.371583 -0.623116,-1.783587 -0.800933,-1.944255 -0.05428,-0.04904 -0.266012,-0.127112 -0.470518,-0.173485 -0.537398,-0.121859 -2.3187637,-0.120056 -3.1120539,0.0031 -2.5177159,0.391026 -4.52037,1.236284 -5.6941341,2.403317 -0.2419692,0.240582 -0.4399441,0.41806 -0.4399441,0.394396 0,-0.09303 0.5649821,-1.300197 0.8328803,-1.779577 0.5548107,-0.992785 1.4670937,-2.282752 2.0134029,-2.846949 0.1214158,-0.125391 0.2207559,-0.244176 0.2207559,-0.263966 0,-0.01979 -0.4864525,-0.03598 -1.0810056,-0.03598 -0.594553,0 -1.0810056,-0.0086 -1.0810056,-0.01908 0,-0.01049 0.1893241,-0.378161 0.4207201,-0.817039 1.4213479,-2.695802 2.675331,-4.500353 4.2541514,-6.121959 1.0008,-1.027921 1.9509803,-1.778947 2.9731667,-2.3500022 1.288882,-0.720047 1.747815,-0.8957786 2.98604,-1.1433947 2.603668,-0.5206727 6.897439,-0.5235156 9.481668,-0.00628 0.810558,0.1622346 1.418164,0.3402647 1.892064,0.5543799 0.416508,0.1881844 1.509162,0.808149 1.964242,1.114496 1.814892,1.221739 3.72945,3.392111 5.252648,5.954483 0.654748,1.101437 1.54625,2.717627 1.54625,2.803172 0,0.01609 -0.491382,0.03536 -1.09196,0.04281 l -1.091961,0.01355 0.250247,0.276537 c 0.953898,1.054113 1.937825,2.571956 2.554235,3.940261 0.156457,0.347302 0.284147,0.660573 0.283756,0.696157 -4.02e-4,0.03559 -0.11605,-0.06615 -0.257019,-0.226068 -0.301615,-0.342166 -0.928812,-0.83947 -1.433824,-1.136878 -2.088393,-1.229881 -5.635517,-1.874161 -7.74358,-1.406501 l -0.259156,0.05749 -0.27716,0.583858 c -0.152438,0.321121 -0.451215,1.092936 -0.663951,1.715142 -0.806048,2.357523 -1.176235,3.091227 -1.983372,3.931008 -0.335728,0.349305 -0.352068,0.35943 -0.444753,0.275552 -0.198119,-0.179244 -0.645408,-0.207911 -3.226977,-0.206772 -2.544916,0.0011 -3.032833,0.03113 -3.217026,0.197818 -0.07951,0.07196 -0.116595,0.04633 -0.473353,-0.327085 z m 3.753665,-7.075775 -7.403195,-0.0129 -0.01345,-2.702347 -0.01345,-2.702348 -0.01212,2.727654 -0.01212,2.727653 7.42877,-0.0124 7.428771,-0.0124 z m -6.234117,-5.37516 c -0.03404,-0.01377 -0.101918,-0.01461 -0.150838,-0.0019 -0.04892,0.01275 -0.02107,0.02402 0.06189,0.02504 0.08296,0.001 0.122987,-0.0094 0.08895,-0.02318 z m 10.683401,-0.0047 c -1.624651,-0.0074 -4.283171,-0.0074 -5.907821,0 -1.624651,0.0074 -0.295391,0.01338 2.95391,0.01338 3.249302,0 4.578562,-0.006 2.953911,-0.01338 z"
|
|
||||||
id="path43701" />
|
|
||||||
<path
|
|
||||||
style="fill:#f18f26;fill-opacity:1;stroke-width:0.0502793"
|
|
||||||
d="M 14.315606,27.528379 C 13.457727,26.630447 13.020865,25.759248 12.224592,23.358434 11.766106,21.976069 11.607421,21.590252 11.432253,21.431977 11.188211,21.211471 9.7687669,21.089992 8.6105901,21.190491 5.9196975,21.423992 3.466552,22.369886 2.1336025,23.687914 c -0.2299663,0.227393 -0.4181206,0.392023 -0.4181206,0.365847 0,-0.02618 0.1280101,-0.331751 0.2844669,-0.679053 C 2.6122967,22.01542 3.6074184,20.48026 4.5541051,19.434447 L 4.8044301,19.15791 3.7124699,19.14436 c -0.600578,-0.0075 -1.0919601,-0.02371 -1.0919601,-0.03612 0,-0.05096 0.8842852,-1.682765 1.2576431,-2.320774 0.2208661,-0.377426 0.4015748,-0.693185 0.4015748,-0.701687 0,-0.0085 0.1505915,-0.248405 0.3346478,-0.533115 1.364098,-2.110082 3.1972851,-4.1069 4.7403577,-5.163486 0.6436101,-0.4407007 1.9177378,-1.1351211 2.4099198,-1.3134489 1.642493,-0.5951092 4.542093,-0.886847 7.536025,-0.7582232 2.958097,0.1270843 4.523179,0.4525661 5.97067,1.2416886 2.070491,1.1287605 3.468266,2.3767155 5.119518,4.5707825 0.511814,0.680063 1.341376,1.890066 1.341376,1.956538 0,0.0109 0.166289,0.299165 0.369532,0.640582 0.381881,0.641502 1.289686,2.309489 1.289686,2.369648 0,0.01874 -0.487165,0.04016 -1.082589,0.04762 l -1.082588,0.01355 0.409348,0.477654 c 0.728605,0.850182 1.459337,1.935402 2.008279,2.982522 0.2891,0.551465 0.652578,1.356755 0.652578,1.445796 0,0.02481 -0.18708,-0.141233 -0.415732,-0.368981 -0.459366,-0.457548 -0.947507,-0.811573 -1.595441,-1.157098 -1.84659,-0.984732 -4.765843,-1.563688 -6.762132,-1.341089 -0.760641,0.08482 -0.882011,0.134495 -1.042574,0.426732 -0.22706,0.413268 -0.466509,1.018831 -0.899239,2.274161 -0.226234,0.656295 -0.488581,1.37427 -0.582994,1.595499 -0.404249,0.947246 -0.903675,1.72207 -1.423247,2.208069 -0.241042,0.225466 -0.262615,0.235288 -0.347687,0.158299 -0.190116,-0.172053 -0.65957,-0.201352 -3.196317,-0.199487 -2.513635,0.0018 -3.064686,0.03486 -3.240687,0.194139 -0.08147,0.07373 -0.115416,0.05045 -0.474832,-0.325747 z m 2.873847,-7.075775 -6.523236,-0.01295 -0.0136,-2.300091 -0.0136,-2.300092 -0.01205,2.325419 -0.01205,2.325419 6.548882,-0.01238 6.548883,-0.01238 z m -5.354299,-5.37516 c -0.03404,-0.01377 -0.101918,-0.01461 -0.150838,-0.0019 -0.04892,0.01275 -0.02107,0.02402 0.06189,0.02504 0.08296,0.001 0.122987,-0.0094 0.08895,-0.02318 z m 9.555821,-0.0047 c -1.000406,-0.0076 -2.652082,-0.0076 -3.670391,-8e-6 -1.018309,0.0076 -0.199795,0.01384 1.818921,0.01384 2.018715,5e-6 2.851876,-0.0062 1.85147,-0.01383 z"
|
|
||||||
id="path43740" />
|
|
||||||
<path
|
|
||||||
style="fill:#f18f26;fill-opacity:1;stroke-width:0.0502793"
|
|
||||||
d="m 14.325997,27.541936 c -0.844775,-0.868685 -1.348283,-1.873086 -2.122513,-4.234001 -0.424452,-1.294313 -0.628837,-1.773879 -0.805273,-1.889486 -0.381442,-0.24993 -2.3063045,-0.33559 -3.4983716,-0.155684 -1.5140705,0.228503 -2.8859632,0.641115 -4.0167581,1.208083 -0.7854121,0.393797 -1.2734414,0.741269 -1.8282139,1.30167 -0.186662,0.188555 -0.3393855,0.32011 -0.3393855,0.292343 0,-0.09043 0.4018864,-0.971524 0.7130925,-1.563375 C 2.9541431,21.50196 3.89147,20.152277 4.5760284,19.409307 L 4.8076607,19.15791 3.7140853,19.14436 c -0.6014665,-0.0075 -1.0935755,-0.02547 -1.0935755,-0.04004 0,-0.03944 0.8013273,-1.530374 1.133204,-2.108417 0.1587701,-0.276536 0.3461605,-0.604609 0.4164232,-0.72905 0.4732593,-0.838184 1.5628449,-2.34916 2.3693132,-3.285629 0.6277435,-0.728939 1.7527867,-1.804517 2.3804372,-2.27578 0.9717958,-0.7296601 2.3086426,-1.4682698 3.1279966,-1.7282229 1.481794,-0.4701224 3.269439,-0.6716382 5.958101,-0.6716382 2.195716,0 3.257411,0.083729 4.767801,0.3760062 1.256669,0.2431792 1.907448,0.5040377 3.242609,1.2997688 1.835364,1.0938421 3.585621,2.8803621 5.247666,5.3563911 0.471778,0.702831 2.127399,3.63113 2.127399,3.762734 0,0.01776 -0.47514,0.03229 -1.055866,0.03229 -0.580726,0 -1.055773,0.01697 -1.055659,0.03771 1.01e-4,0.02074 0.217628,0.297905 0.483363,0.615922 0.602682,0.721254 1.454692,1.997159 1.863518,2.790662 0.366886,0.712099 0.679684,1.427905 0.655578,1.500223 -0.0094,0.02827 -0.08364,-0.03598 -0.164928,-0.142785 -0.382107,-0.502058 -1.481398,-1.265062 -2.410364,-1.673001 -2.141741,-0.94051 -5.182137,-1.364547 -6.837989,-0.953679 l -0.251396,0.06238 -0.232691,0.466103 c -0.223298,0.44729 -0.411953,0.943731 -1.026605,2.701495 -0.51683,1.478012 -1.113194,2.536577 -1.780879,3.161118 -0.238327,0.222928 -0.266421,0.236286 -0.345819,0.164431 -0.189387,-0.171397 -0.75719,-0.207396 -3.225738,-0.204519 -2.436274,0.0028 -3.04453,0.04052 -3.22021,0.199512 -0.07233,0.06546 -0.120963,0.032 -0.459778,-0.316409 z m -3.673466,-9.377043 c -0.0084,-0.421717 -0.01529,-0.07667 -0.01529,0.76676 0,0.843436 0.0069,1.188478 0.01529,0.76676 0.0084,-0.421718 0.0084,-1.111802 0,-1.53352 z m 1.181666,-3.087768 c -0.03457,-0.01395 -0.09113,-0.01395 -0.125698,0 -0.03457,0.01395 -0.0063,0.02536 0.06285,0.02536 0.06913,0 0.09742,-0.01141 0.06285,-0.02536 z m 8.726849,-0.0043 c -0.571952,-0.0081 -1.522231,-0.0081 -2.111732,-2.3e-5 -0.589502,0.008 -0.121541,0.01464 1.039911,0.01466 1.161453,1.2e-5 1.643772,-0.0066 1.071821,-0.01464 z"
|
|
||||||
id="path43779" />
|
|
||||||
<path
|
|
||||||
style="fill:#f18f26;fill-opacity:1;stroke-width:0.0502793"
|
|
||||||
d="M 14.297924,27.510248 C 13.853145,27.045673 13.544349,26.59754 13.209282,25.930381 12.892377,25.299386 12.734493,24.892448 12.24958,23.456793 11.589984,21.503964 11.557413,21.440224 11.158635,21.321799 10.719198,21.1913 9.5994975,21.131802 8.7288234,21.192685 c -2.6588492,0.185921 -5.2324127,1.16491 -6.6000538,2.510674 -0.2273082,0.223672 -0.4132877,0.386143 -0.4132877,0.361047 0,-0.09381 0.3688001,-0.905326 0.6855013,-1.508386 0.5331622,-1.015244 1.3849081,-2.266627 2.0489722,-3.010346 0.1552575,-0.17388 0.2822863,-0.337916 0.2822863,-0.364525 0,-0.02945 -0.413128,-0.04838 -1.0558659,-0.04838 -0.5807263,0 -1.055866,-0.01369 -1.055866,-0.03043 0,-0.137871 1.6653086,-3.075618 2.1692035,-3.826661 1.1979585,-1.785524 2.8371426,-3.599712 4.1279648,-4.568674 0.9368462,-0.703248 2.2900469,-1.4587652 3.0860919,-1.7230229 2.826214,-0.9381997 9.2758,-0.9273473 12.071338,0.020312 0.713002,0.2417002 2.069755,0.9989949 2.943357,1.6428839 1.39549,1.028547 2.899712,2.684807 4.204254,4.629195 0.521966,0.777977 2.168741,3.680774 2.168741,3.822874 0,0.01844 -0.47514,0.03352 -1.055866,0.03352 -0.580726,0 -1.055211,0.01697 -1.05441,0.03771 8e-4,0.02074 0.1821,0.252654 0.402886,0.515363 0.74682,0.888627 1.482659,1.99088 1.986074,2.97505 0.28875,0.564501 0.626344,1.32273 0.626344,1.406755 0,0.02688 -0.17751,-0.12864 -0.394467,-0.345596 -1.412345,-1.412345 -4.121534,-2.401571 -6.996595,-2.554719 -0.69945,-0.03726 -1.646374,0.03398 -2.051724,0.154357 l -0.261309,0.0776 -0.221468,0.463109 c -0.19834,0.414745 -0.423098,1.012699 -1.090673,2.901655 -0.444479,1.257688 -1.075762,2.348426 -1.693751,2.926482 l -0.250441,0.234259 -0.208933,-0.103372 c -0.306587,-0.151687 -2.26663,-0.219912 -4.419227,-0.153825 -1.451778,0.04457 -1.632438,0.05951 -1.815679,0.150175 l -0.203488,0.100677 z m -3.645933,-8.591165 c -0.01016,-0.145181 -0.01847,-0.0264 -0.01847,0.263967 0,0.290363 0.0083,0.409148 0.01847,0.263966 0.01016,-0.145181 0.01016,-0.382751 0,-0.527933 z m 1.156019,-3.839036 c -0.01671,-0.01671 -0.06007,-0.01849 -0.09637,-0.004 -0.04011,0.01605 -0.0282,0.02796 0.03038,0.03038 0.053,0.0022 0.0827,-0.0097 0.06599,-0.02641 z m 7.997431,-0.0067 c -0.157924,-0.0099 -0.429433,-0.01003 -0.603351,-2.01e-4 -0.17392,0.0098 -0.04471,0.01798 0.287135,0.01808 0.331844,1.01e-4 0.474141,-0.008 0.316216,-0.0179 z"
|
|
||||||
id="path43818" />
|
|
||||||
<path
|
|
||||||
style="fill:#f18f26;fill-opacity:1;stroke-width:0.0502793"
|
|
||||||
d="m 14.359921,27.586146 c -0.449118,-0.46165 -0.774129,-0.921958 -1.097682,-1.554631 -0.357124,-0.698319 -0.501736,-1.067487 -1.04548,-2.668928 -0.529824,-1.56044 -0.683673,-1.895886 -0.913053,-1.990778 -0.433149,-0.179189 -2.1903377,-0.250274 -3.1776096,-0.128545 -1.5393556,0.189799 -3.2368706,0.697742 -4.3994413,1.316434 -0.6531412,0.347585 -1.0528936,0.638018 -1.5712291,1.141547 -0.2419692,0.235057 -0.4399441,0.404558 -0.4399441,0.376667 0,-0.104533 0.2723938,-0.719479 0.6177788,-1.394674 0.5418102,-1.059186 1.3855229,-2.307419 2.150618,-3.181736 0.1353957,-0.154724 0.2340183,-0.300986 0.2191615,-0.325024 -0.014857,-0.02404 -0.489504,-0.04371 -1.0547714,-0.04371 -0.5652675,0 -1.027759,-0.01453 -1.027759,-0.03229 0,-0.13601 1.6603023,-3.067457 2.1602058,-3.814081 1.5348801,-2.2924 3.3386499,-4.149172 5.0728368,-5.221896 0.6873586,-0.4251822 1.6391386,-0.9096447 2.0820556,-1.0597805 0.810768,-0.2748262 2.129365,-0.5100076 3.58155,-0.638796 0.903836,-0.080157 4.05342,-0.079476 4.977654,0.00108 1.543209,0.1345005 3.004547,0.4073241 3.772959,0.7043904 0.494496,0.1911708 1.647102,0.8170272 2.256994,1.2255301 1.617327,1.08328 3.256759,2.818797 4.689489,4.964335 0.549829,0.823379 2.177206,3.692152 2.177206,3.838024 0,0.01842 -0.446858,0.03383 -0.993017,0.03425 -0.546159,4.03e-4 -1.01874,0.01739 -1.050179,0.03771 -0.03719,0.02403 0.08213,0.203835 0.341489,0.514593 0.467784,0.560485 0.947496,1.226338 1.392085,1.93225 0.344109,0.546372 1.138107,2.120417 1.193805,2.366633 0.03066,0.135554 -0.0063,0.111054 -0.364842,-0.241791 -0.550334,-0.541597 -1.132137,-0.944948 -1.902023,-1.318634 -1.412288,-0.685492 -3.031636,-1.10039 -4.81663,-1.234084 -0.860028,-0.06442 -1.872246,-0.007 -2.343561,0.132992 -0.251044,0.07455 -0.257802,0.08188 -0.453253,0.491388 -0.237949,0.498551 -0.355853,0.804095 -0.816878,2.116898 -0.193656,0.551449 -0.419991,1.173656 -0.502966,1.382682 -0.379566,0.956182 -0.938898,1.852392 -1.487633,2.383612 -0.244267,0.236471 -0.255468,0.241404 -0.373107,0.164323 -0.0667,-0.0437 -0.289916,-0.100907 -0.496028,-0.127113 -0.62273,-0.07918 -2.496509,-0.106834 -4.10597,-0.0606 -1.367916,0.03929 -1.539255,0.05369 -1.723341,0.144766 l -0.204409,0.101133 z"
|
|
||||||
id="path43857" />
|
|
||||||
<path
|
|
||||||
style="fill:#f18f26;fill-opacity:1;stroke-width:0.0502793"
|
|
||||||
d="m 14.403969,27.642829 c -0.427383,-0.432058 -0.826131,-0.994183 -1.138203,-1.604554 -0.354369,-0.6931 -0.577208,-1.261284 -1.070533,-2.729591 -0.217837,-0.64836 -0.47586,-1.338444 -0.573384,-1.53352 -0.199017,-0.398091 -0.269341,-0.439497 -0.901874,-0.531014 -0.519927,-0.07523 -2.0883058,-0.0595 -2.752725,0.02759 -1.1152026,0.14619 -2.2770199,0.44766 -3.2862076,0.852708 -1.0888276,0.437013 -1.7838744,0.868696 -2.5029605,1.55455 -0.5888592,0.561646 -0.5881332,0.521868 0.012773,-0.699864 0.606453,-1.233008 1.3020399,-2.306209 2.1363972,-3.296187 0.3300835,-0.391649 0.3851535,-0.480745 0.3145717,-0.508938 -0.047058,-0.0188 -0.521105,-0.03577 -1.0534374,-0.03771 -0.5323324,-0.0019 -0.9678771,-0.01862 -0.9678771,-0.03706 0,-0.124898 1.6059164,-2.980203 2.0872048,-3.711033 C 6.1018147,13.271287 7.894097,11.364917 9.4992903,10.291624 9.9649538,9.9802629 10.609756,9.6091278 11.20764,9.3083303 c 1.271804,-0.6398471 3.355514,-0.9712565 6.34583,-1.0092898 3.181374,-0.040463 5.6787,0.2818303 7.033277,0.9076827 1.495578,0.6910001 2.777111,1.5889428 3.976731,2.7864108 1.615843,1.612944 2.990855,3.580493 4.478694,6.408707 0.192108,0.365175 0.349287,0.677703 0.349287,0.694508 0,0.0168 -0.450681,0.03753 -1.001513,0.04605 -0.550831,0.0085 -1.017787,0.03183 -1.037679,0.05178 -0.01989,0.01996 0.08238,0.178336 0.227266,0.351956 0.916457,1.098194 1.635258,2.19891 2.24185,3.43299 0.600022,1.220717 0.600959,1.261037 0.01635,0.703911 -0.26116,-0.248883 -0.655072,-0.572872 -0.875359,-0.719976 -1.940371,-1.295749 -5.363968,-2.055624 -7.716166,-1.712621 -0.59776,0.08717 -0.627462,0.10635 -0.83244,0.53764 -0.252864,0.532044 -0.417325,0.954211 -0.821666,2.109194 -0.191096,0.545857 -0.419453,1.173472 -0.507461,1.394701 -0.390215,0.980902 -0.943457,1.870135 -1.496784,2.405801 -0.245376,0.237545 -0.254975,0.241726 -0.374723,0.163265 -0.225302,-0.147624 -0.879789,-0.185601 -3.182009,-0.184635 -2.300094,9.66e-4 -3.012214,0.04044 -3.223155,0.17865 -0.113682,0.07449 -0.127616,0.06717 -0.404001,-0.21224 z"
|
|
||||||
id="path43896" />
|
|
||||||
<path
|
|
||||||
style="fill:#f18f26;fill-opacity:1;stroke-width:0.0502793"
|
|
||||||
d="m 14.402815,27.645005 c -0.914169,-0.94931 -1.324158,-1.742554 -2.138694,-4.137933 -0.514997,-1.514499 -0.667383,-1.879371 -0.848583,-2.031841 -0.251243,-0.211407 -0.605124,-0.256092 -2.0073187,-0.253472 -1.3984275,0.0026 -1.8778887,0.06065 -3.0832261,0.373225 -1.8362553,0.476185 -3.1519523,1.140892 -4.1677735,2.105612 -0.5567972,0.528788 -0.5580281,0.490824 -0.020131,-0.620898 0.591698,-1.222918 1.335546,-2.380104 2.1729246,-3.380366 0.20299,-0.242475 0.3697199,-0.455004 0.370511,-0.472288 0.00305,-0.06659 -0.3452735,-0.09427 -1.1864109,-0.09427 -0.4804819,0 -0.8736034,-0.01509 -0.8736034,-0.03352 0,-0.126809 1.510769,-2.823522 2.0490637,-3.657565 0.7109995,-1.101635 1.7502949,-2.389306 2.7167692,-3.366037 1.2149256,-1.22782 2.247209,-1.975378 3.8212981,-2.7673067 1.084716,-0.545723 2.805538,-0.8702497 5.253707,-0.990787 2.841031,-0.1398801 5.918483,0.1234604 7.477598,0.6398651 0.860348,0.2849616 2.198054,1.0215625 3.142458,1.7303796 1.465297,1.099769 3.204842,3.063773 4.384783,4.950562 0.585857,0.936818 1.925273,3.344592 1.925273,3.460929 0,0.01842 -0.401606,0.03616 -0.892458,0.03943 -0.490852,0.0033 -0.95769,0.02024 -1.037418,0.03771 l -0.14496,0.03176 0.432232,0.541124 c 0.572343,0.716534 1.056151,1.402831 1.443931,2.048261 0.348187,0.579531 1.02598,1.948309 1.083035,2.187151 0.0323,0.135225 -0.008,0.108727 -0.389552,-0.256004 -0.726692,-0.69469 -1.495458,-1.178794 -2.531123,-1.593889 -1.035404,-0.414991 -2.231442,-0.718368 -3.423787,-0.868447 -1.19753,-0.150732 -3.016979,-0.07553 -3.270888,0.135199 -0.195888,0.162573 -0.518918,0.935502 -1.174128,2.809398 -0.599601,1.714853 -1.192001,2.80287 -1.898487,3.486806 -0.242337,0.234602 -0.256309,0.240868 -0.37076,0.166265 -0.218777,-0.142607 -0.936215,-0.183811 -3.184654,-0.182904 -2.308691,9.3e-4 -3.019274,0.03947 -3.22605,0.174952 -0.120415,0.0789 -0.128275,0.07479 -0.403578,-0.211097 z"
|
|
||||||
id="path43935" />
|
|
||||||
<text
|
|
||||||
xml:space="preserve"
|
|
||||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:1.25;font-family:Overpass;-inkscape-font-specification:Overpass;letter-spacing:-1px;fill:#272b2b;fill-opacity:1;stroke:none"
|
|
||||||
x="8.9459906"
|
|
||||||
y="23.576347"
|
|
||||||
id="text48393"><tspan
|
|
||||||
sodipodi:role="line"
|
|
||||||
id="tspan48391"
|
|
||||||
x="8.9459906"
|
|
||||||
y="23.576347"
|
|
||||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;font-family:Overpass;-inkscape-font-specification:Overpass;fill:#272b2b;fill-opacity:1">32</tspan></text>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 25 KiB |
|
@ -1,162 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<svg
|
|
||||||
viewBox="0 0 54 36"
|
|
||||||
version="1.1"
|
|
||||||
id="svg16"
|
|
||||||
sodipodi:docname="fox32.svg"
|
|
||||||
inkscape:export-filename="/home/ry/Documents/fox32/docs/logos/fox32.png"
|
|
||||||
inkscape:export-xdpi="682.66669"
|
|
||||||
inkscape:export-ydpi="682.66669"
|
|
||||||
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04, custom)"
|
|
||||||
width="54"
|
|
||||||
height="36"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg">
|
|
||||||
<defs
|
|
||||||
id="defs20">
|
|
||||||
<inkscape:path-effect
|
|
||||||
effect="powerclip"
|
|
||||||
id="path-effect51605"
|
|
||||||
is_visible="true"
|
|
||||||
lpeversion="1"
|
|
||||||
inverse="true"
|
|
||||||
flatten="false"
|
|
||||||
hide_clip="false"
|
|
||||||
message="-0.21577385" />
|
|
||||||
<clipPath
|
|
||||||
clipPathUnits="userSpaceOnUse"
|
|
||||||
id="clipPath51601">
|
|
||||||
<path
|
|
||||||
style="display:none;fill:#f18f26;fill-opacity:1;stroke-width:0.0502793"
|
|
||||||
d="M 14.587831,27.863504 C 14.382965,27.727479 13.734884,26.908543 13.457514,26.435201 13.074891,25.782241 12.802463,25.12596 12.2477,23.520759 11.54419,21.485155 11.532784,21.464321 11.049545,21.332324 10.678257,21.230906 9.0747412,21.190197 8.3212291,21.263058 7.5503856,21.337595 6.4089614,21.570204 5.6761529,21.802094 4.1005881,22.300666 3.0721423,22.860948 2.1641077,23.715406 1.7440613,24.110668 1.696405,24.142717 1.7284655,24.00838 1.7908089,23.747154 2.5898195,22.17273 2.964067,21.573668 3.3024942,21.031943 4.10012,19.944034 4.5066782,19.469646 4.6078844,19.351555 4.6742061,19.238427 4.6540598,19.21825 4.6339135,19.198073 4.172433,19.1738 3.6285475,19.164311 c -0.5438855,-0.0095 -0.9971402,-0.02529 -1.0072326,-0.03511 -0.051212,-0.04983 1.4590175,-2.760125 2.0373689,-3.656307 0.7207834,-1.116888 1.8379204,-2.499044 2.7887559,-3.450332 1.1558488,-1.1564 2.2171525,-1.919729 3.7145713,-2.6716564 1.167618,-0.5863179 2.814287,-0.8933047 5.434415,-1.0131321 2.787996,-0.1275046 5.8009,0.134319 7.311395,0.6353659 1.064281,0.3530328 2.407592,1.1206046 3.519475,2.0110386 1.248433,0.999788 2.838308,2.82234 3.90961,4.48178 0.566992,0.878269 2.048569,3.523133 2.048569,3.657043 0,0.01838 -0.345042,0.03566 -0.76676,0.0384 -0.421718,0.0027 -0.889733,0.0197 -1.040035,0.03771 l -0.273275,0.03274 0.340993,0.418558 c 0.563124,0.691217 1.176336,1.55625 1.545759,2.18054 0.377875,0.638571 1.019097,1.934392 1.077479,2.177438 0.03251,0.135328 -0.0072,0.109342 -0.386254,-0.25271 -1.055819,-1.008484 -2.340669,-1.658309 -4.22344,-2.136041 -1.067335,-0.270825 -1.740108,-0.360359 -2.911339,-0.387453 -1.113448,-0.02576 -1.922155,0.05148 -2.104624,0.201 -0.172488,0.141344 -0.558337,1.078132 -1.216006,2.952299 -0.549422,1.565695 -1.162101,2.673918 -1.842111,3.332038 l -0.247837,0.239859 -0.159143,-0.07939 c -0.269958,-0.134674 -0.960666,-0.172303 -3.153742,-0.171816 -2.179025,5.03e-4 -2.9376,0.03891 -3.182763,0.16121 -0.123158,0.06144 -0.156957,0.06093 -0.254546,-0.0039 z"
|
|
||||||
id="path51603" />
|
|
||||||
<path
|
|
||||||
id="lpe_path-effect51605"
|
|
||||||
style="fill:#f18f26;fill-opacity:1;stroke-width:0.0502793"
|
|
||||||
class="powerclip"
|
|
||||||
d="M 6,10.5 H 30 V 36.776 H 6 Z m 8.587831,17.363504 v -2.1e-5 c 0.09759,0.06483 0.131388,0.06534 0.254546,0.0039 0.245163,-0.1223 1.003738,-0.160707 3.182763,-0.16121 2.193076,-4.87e-4 2.883784,0.03714 3.153742,0.171816 l 0.159143,0.07939 0.247837,-0.239859 c 0.68001,-0.65812 1.292689,-1.766343 1.842111,-3.332038 0.657669,-1.874167 1.043518,-2.810955 1.216006,-2.952299 0.182469,-0.14952 0.991176,-0.22676 2.104624,-0.201 1.171231,0.02709 1.844004,0.116628 2.911339,0.387453 1.882771,0.477732 3.167621,1.127557 4.22344,2.136041 0.379054,0.362052 0.418764,0.388038 0.386254,0.25271 -0.05838,-0.243046 -0.699604,-1.538867 -1.077479,-2.177438 -0.369423,-0.62429 -0.982635,-1.489323 -1.545759,-2.18054 l -0.340993,-0.418558 0.273275,-0.03274 c 0.150302,-0.01801 0.618317,-0.03501 1.040035,-0.03771 0.421718,-0.0027 0.76676,-0.02002 0.76676,-0.0384 0,-0.13391 -1.481577,-2.778774 -2.048569,-3.657043 -1.071302,-1.65944 -2.661177,-3.481992 -3.90961,-4.48178 C 26.315413,10.093744 24.972102,9.3261722 23.907821,8.9731394 22.397326,8.4720925 19.384422,8.2102689 16.596426,8.3377735 13.976298,8.4576009 12.329629,8.7645877 11.162011,9.3509056 9.6645922,10.102833 8.6032885,10.866162 7.4474397,12.022562 6.4966042,12.97385 5.3794672,14.356006 4.6586838,15.472894 c -0.5783514,0.896182 -2.0885809,3.606477 -2.0373689,3.656307 0.010092,0.0098 0.4633471,0.02561 1.0072326,0.03511 0.5438855,0.0095 1.005366,0.03376 1.0255123,0.05394 0.020146,0.02018 -0.046175,0.133305 -0.1473816,0.251396 -0.4065582,0.474388 -1.204184,1.562297 -1.5426112,2.104022 -0.3742475,0.599062 -1.1732581,2.173486 -1.2356015,2.434712 -0.032061,0.134337 0.015596,0.102288 0.4356422,-0.292974 0.9080346,-0.854458 1.9364804,-1.41474 3.5120452,-1.913312 0.7328085,-0.23189 1.8742327,-0.464499 2.6450762,-0.539036 0.7535121,-0.07286 2.3570279,-0.03215 2.7283159,0.06927 0.483239,0.131997 0.494645,0.152831 1.198155,2.188435 0.554763,1.605201 0.827191,2.261482 1.209814,2.914442 0.27737,0.473342 0.925451,1.292278 1.130317,1.428303 z" />
|
|
||||||
</clipPath>
|
|
||||||
</defs>
|
|
||||||
<sodipodi:namedview
|
|
||||||
id="namedview18"
|
|
||||||
pagecolor="#ffffff"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1.0"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:pageopacity="0.0"
|
|
||||||
inkscape:pagecheckerboard="0"
|
|
||||||
showgrid="false"
|
|
||||||
inkscape:zoom="19.888889"
|
|
||||||
inkscape:cx="27.427374"
|
|
||||||
inkscape:cy="16.240223"
|
|
||||||
inkscape:window-width="1920"
|
|
||||||
inkscape:window-height="1132"
|
|
||||||
inkscape:window-x="0"
|
|
||||||
inkscape:window-y="32"
|
|
||||||
inkscape:window-maximized="1"
|
|
||||||
inkscape:current-layer="svg16"
|
|
||||||
width="56px"
|
|
||||||
fit-margin-top="0"
|
|
||||||
fit-margin-left="0"
|
|
||||||
fit-margin-right="0"
|
|
||||||
fit-margin-bottom="0"
|
|
||||||
height="32px" />
|
|
||||||
<path
|
|
||||||
fill="#f4900c"
|
|
||||||
d="m 31.323892,9.7783459 c 0.658,2.6380001 -8.673005,10.4890001 -11.244005,4.0980001 -1.491,-3.703 -2.793,-11.4660001 -1.313,-11.8350001 1.48,-0.368 11.900005,5.098 12.557005,7.737 z"
|
|
||||||
id="path2" />
|
|
||||||
<path
|
|
||||||
fill="#a0041e"
|
|
||||||
d="m 29.329892,10.331346 c 0.96,1.538 -1.83101,4.561 -3.36801,5.522 -1.537995,0.961 -2.898995,-0.552 -4.413995,-4.414 -0.662,-1.6890001 -1.666,-6.2700001 -1.103,-6.6220001 0.562,-0.351 7.924005,3.976 8.885005,5.5140001 z"
|
|
||||||
id="path4" />
|
|
||||||
<path
|
|
||||||
fill="#f4900c"
|
|
||||||
d="m 40.449892,9.7783459 c -0.657,2.6390001 8.673,10.4890001 11.245,4.0980001 1.49,-3.703 2.792,-11.4660001 1.312,-11.8350001 -1.48,-0.368 -11.899,5.098 -12.557,7.737 z"
|
|
||||||
id="path6" />
|
|
||||||
<path
|
|
||||||
fill="#a0041e"
|
|
||||||
d="m 42.444892,10.331346 c -0.96,1.538 1.831,4.561 3.368,5.522 1.537,0.961 2.898,-0.552 4.413,-4.414 0.662,-1.6880001 1.666,-6.2690001 1.104,-6.6210001 -0.563,-0.352 -7.924,3.975 -8.885,5.5130001 z"
|
|
||||||
id="path8" />
|
|
||||||
<path
|
|
||||||
fill="#f18f26"
|
|
||||||
d="m 50.239892,26.888346 c 0,-0.454 -0.188,-1.091 -0.407,-1.687 0.585,0.028 1.519,0.191 2.77,0.817 -0.008,-0.536 -0.118,-0.984 -0.273,-1.393 0.041,0.02 0.075,0.034 0.116,0.055 -1.103,-3.31 -3.309,-5.517 -3.309,-5.517 h 2.206 c -2.331,-4.663 -4.965,-8.015 -8.075,-9.5590001 -1.39,-0.873 -3.688,-1.338 -7.373,-1.339 h -0.003 c -3.695,0 -5.996,0.468 -7.385,1.346 -3.104005,1.5470001 -5.734005,4.8960001 -8.061005,9.5520001 h 2.207 c 0,0 -2.207,2.206 -3.311,5.517 0.03,-0.015 0.055,-0.025 0.084,-0.04 -0.201,0.392 -0.307,0.847 -0.282,1.377 1.263,-0.632 2.217,-0.792 2.813,-0.818 -0.189,0.513 -0.343,1.044 -0.386,1.475 -0.123,0.371 -0.191,0.812 -0.135,1.343 3.207,-1.457 4.706995,-1.249 6.456995,-0.374 1.21301,3.623 4.20601,6.333 8.00101,6.333 3.793,0 6.746,-2.794 7.958,-6.416 1.458,-1.25 3.708,-0.875 6.416,0.416 0.066,-0.414 0.036,-0.773 -0.036,-1.093 z"
|
|
||||||
id="path10" />
|
|
||||||
<path
|
|
||||||
fill="#ffd983"
|
|
||||||
d="m 49.135892,23.577346 c 0.006,0 1.108,0.003 3.309,1.103 -1.249,-2.839 -7.525,-4.07 -9.931,-3.291 -1.171,1.954 -1.281,5.003 -3.383,6.622 -1.741,1.431 -4.713,1.458 -6.479,0 -2.345,-1.924 -2.559,-5.813 -3.382,-6.622 -2.40701,-0.781 -8.681005,0.454 -9.931005,3.291 2.201,-1.101 3.304,-1.103 3.309,-1.103 0,0.001 -1.103,2.208 -1.103,3.311 l 0.001,-10e-4 v 10e-4 c 2.398,-1.573 5.115995,-2.271 7.429005,-0.452 1.666,7.921 12.293,7.545 13.833,0 2.314,-1.818 5.03,-1.122 7.429,0.452 v -10e-4 l 0.001,10e-4 c 0.002,-1.103 -1.101,-3.311 -1.102,-3.311 z"
|
|
||||||
id="path12" />
|
|
||||||
<path
|
|
||||||
fill="#272b2b"
|
|
||||||
d="m 11,17 c 0,0 0,-1.5 1.5,-1.5 1.5,0 1.5,1.5 1.5,1.5 v 1.5 c 0,0 0,1.5 -1.5,1.5 C 11,20 11,18.5 11,18.5 Z m 11,0 c 0,0 0,-1.5 1.5,-1.5 1.5,0 1.5,1.5 1.5,1.5 v 1.5 c 0,0 0,1.5 -1.5,1.5 C 22,20 22,18.5 22,18.5 Z m -7.061,10.808 c -1.021,0.208 2.041,3.968 3.062,3.968 1.02,0 4.082,-3.76 3.062,-3.968 -1.021,-0.208 -5.103,-0.208 -6.124,0 z"
|
|
||||||
id="path14"
|
|
||||||
clip-path="url(#clipPath51601)"
|
|
||||||
inkscape:path-effect="#path-effect51605"
|
|
||||||
inkscape:original-d="m 11,17 c 0,0 0,-1.5 1.5,-1.5 1.5,0 1.5,1.5 1.5,1.5 v 1.5 c 0,0 0,1.5 -1.5,1.5 C 11,20 11,18.5 11,18.5 Z m 11,0 c 0,0 0,-1.5 1.5,-1.5 1.5,0 1.5,1.5 1.5,1.5 v 1.5 c 0,0 0,1.5 -1.5,1.5 C 22,20 22,18.5 22,18.5 Z m -7.061,10.808 c -1.021,0.208 2.041,3.968 3.062,3.968 1.02,0 4.082,-3.76 3.062,-3.968 -1.021,-0.208 -5.103,-0.208 -6.124,0 z"
|
|
||||||
transform="translate(17.892887,-0.0236541)" />
|
|
||||||
<rect
|
|
||||||
id="rect20344"
|
|
||||||
width="14.987617"
|
|
||||||
height="5.4221425"
|
|
||||||
x="28.54771"
|
|
||||||
y="15.06275" />
|
|
||||||
<path
|
|
||||||
style="fill:#f18f26;fill-opacity:1;stroke-width:0.0502793"
|
|
||||||
d="m 28.552102,17.775229 v -2.664805 h 7.49162 7.49162 v 2.664805 2.664804 h -7.49162 -7.49162 z"
|
|
||||||
id="path43623" />
|
|
||||||
<path
|
|
||||||
style="fill:#f18f26;fill-opacity:1;stroke-width:0.0502793"
|
|
||||||
d="m 32.202512,27.528379 c -0.85072,-0.890434 -1.43506,-2.068928 -2.11857,-4.272703 -0.27368,-0.882421 -0.45312,-1.349616 -0.64239,-1.672585 -0.1267,-0.216198 -0.14203,-0.225105 -0.54761,-0.318215 -0.57626,-0.132297 -2.31433,-0.134641 -3.15748,-0.0043 -1.976192,0.305592 -3.846381,0.979038 -4.994616,1.798537 -0.244385,0.174418 -0.60074,0.4846 -0.791899,0.689291 -0.191159,0.204691 -0.347563,0.348334 -0.347563,0.319207 0,-0.09995 0.582981,-1.340028 0.870599,-1.851886 0.539993,-0.960992 1.319507,-2.062849 1.937075,-2.73809 0.142651,-0.155972 0.259366,-0.297382 0.259366,-0.314246 0,-0.01686 -0.486453,-0.03066 -1.081006,-0.03066 -0.594553,0 -1.081006,-0.0066 -1.081006,-0.01461 0,-0.008 0.183335,-0.364389 0.40741,-0.7919 1.394173,-2.659922 2.698431,-4.540018 4.267462,-6.151569 1.217248,-1.250235 2.063438,-1.874141 3.797198,-2.7997066 1.47896,-0.7895434 4.73153,-1.2087858 8.20558,-1.0576642 1.54295,0.067119 2.4442,0.1617141 3.45922,0.3630819 1.24104,0.2462071 1.6894,0.4193972 3.0419,1.1750086 2.20629,1.2326053 4.35335,3.5582893 6.22307,6.7407943 0.46859,0.797605 1.36911,2.447936 1.36911,2.509089 0,0.01511 -0.48645,0.02747 -1.08101,0.02747 -0.59455,0 -1.081,0.01868 -1.081,0.04152 0,0.02283 0.0593,0.09637 0.13181,0.163408 0.46329,0.428437 1.59318,2.012135 2.1243,2.977497 0.26177,0.47578 0.81093,1.656856 0.81093,1.744054 0,0.02366 -0.19798,-0.154148 -0.43995,-0.395139 -0.24197,-0.240991 -0.63386,-0.566615 -0.87087,-0.723611 -1.16917,-0.774457 -2.93753,-1.390064 -4.82326,-1.679088 -0.84379,-0.129326 -2.58521,-0.127933 -3.1531,0.0025 l -0.41288,0.09485 -0.19905,0.407949 c -0.26391,0.540865 -0.35425,0.774214 -0.77105,1.991746 -0.76415,2.232138 -1.18829,3.06167 -1.96108,3.835402 l -0.34057,0.340988 -0.1384,-0.100049 c -0.22982,-0.166136 -1.295,-0.220591 -3.69287,-0.188789 -2.08209,0.02761 -2.54291,0.06325 -2.70411,0.209133 -0.08,0.07237 -0.11631,0.04729 -0.47369,-0.326774 z m 3.85378,-7.075775 -7.50419,-0.0129 v -2.664475 -2.664476 l 7.50419,-0.0129 7.50419,-0.0129 -7.52933,-0.01241 -7.52933,-0.0124 v 2.715084 2.715083 l 7.52933,-0.0124 7.52933,-0.0124 z"
|
|
||||||
id="path43662" />
|
|
||||||
<path
|
|
||||||
style="fill:#f18f26;fill-opacity:1;stroke-width:0.0502793"
|
|
||||||
d="m 32.202512,27.528379 c -0.85814,-0.898197 -1.29445,-1.768132 -2.08254,-4.152256 -0.4534,-1.371583 -0.62312,-1.783587 -0.80094,-1.944255 -0.0543,-0.04904 -0.26601,-0.127112 -0.47052,-0.173485 -0.53739,-0.121859 -2.31876,-0.120056 -3.11205,0.0031 -2.517715,0.391026 -4.520369,1.236284 -5.694133,2.403317 -0.24197,0.240582 -0.439945,0.41806 -0.439945,0.394396 0,-0.09303 0.564983,-1.300197 0.832881,-1.779577 0.55481,-0.992785 1.467093,-2.282752 2.013403,-2.846949 0.121415,-0.125391 0.220756,-0.244176 0.220756,-0.263966 0,-0.01979 -0.486453,-0.03598 -1.081006,-0.03598 -0.594553,0 -1.081006,-0.0086 -1.081006,-0.01908 0,-0.01049 0.189324,-0.378161 0.42072,-0.817039 1.421348,-2.695802 2.675331,-4.500353 4.254152,-6.121959 1.000798,-1.027921 1.950978,-1.778947 2.973168,-2.3500022 1.28888,-0.720047 1.74781,-0.8957786 2.98604,-1.1433947 2.60367,-0.5206727 6.89744,-0.5235156 9.48167,-0.00628 0.81055,0.1622346 1.41816,0.3402647 1.89206,0.5543799 0.41651,0.1881844 1.50916,0.808149 1.96424,1.114496 1.81489,1.221739 3.72945,3.392111 5.25265,5.954483 0.65475,1.101437 1.54625,2.717627 1.54625,2.803172 0,0.01609 -0.49138,0.03536 -1.09196,0.04281 l -1.09196,0.01355 0.25025,0.276537 c 0.95389,1.054113 1.93782,2.571956 2.55423,3.940261 0.15646,0.347302 0.28415,0.660573 0.28376,0.696157 -4e-4,0.03559 -0.11605,-0.06615 -0.25702,-0.226068 -0.30162,-0.342166 -0.92881,-0.83947 -1.43383,-1.136878 -2.08839,-1.229881 -5.63551,-1.874161 -7.74358,-1.406501 l -0.25915,0.05749 -0.27716,0.583858 c -0.15244,0.321121 -0.45122,1.092936 -0.66395,1.715142 -0.80605,2.357523 -1.17624,3.091227 -1.98337,3.931008 -0.33573,0.349305 -0.35207,0.35943 -0.44476,0.275552 -0.19812,-0.179244 -0.64541,-0.207911 -3.22697,-0.206772 -2.54492,0.0011 -3.03284,0.03113 -3.21703,0.197818 -0.0795,0.07196 -0.1166,0.04633 -0.47335,-0.327085 z m 3.75366,-7.075775 -7.40319,-0.0129 -0.0134,-2.702347 -0.0135,-2.702348 -0.0121,2.727654 -0.0121,2.727653 7.42877,-0.0124 7.42877,-0.0124 z m -6.23412,-5.37516 c -0.034,-0.01377 -0.10191,-0.01461 -0.15083,-0.0019 -0.0489,0.01275 -0.0211,0.02402 0.0619,0.02504 0.083,0.001 0.12298,-0.0094 0.0889,-0.02318 z m 10.68341,-0.0047 c -1.62466,-0.0074 -4.28318,-0.0074 -5.90783,0 -1.62465,0.0074 -0.29539,0.01338 2.95391,0.01338 3.24931,0 4.57857,-0.006 2.95392,-0.01338 z"
|
|
||||||
id="path43701" />
|
|
||||||
<path
|
|
||||||
style="fill:#f18f26;fill-opacity:1;stroke-width:0.0502793"
|
|
||||||
d="m 32.202512,27.528379 c -0.85788,-0.897932 -1.29474,-1.769131 -2.09102,-4.169945 -0.45848,-1.382365 -0.61717,-1.768182 -0.79234,-1.926457 -0.24404,-0.220506 -1.66348,-0.341985 -2.82166,-0.241486 -2.690892,0.233501 -5.144037,1.179395 -6.476987,2.497423 -0.229966,0.227393 -0.418121,0.392023 -0.418121,0.365847 0,-0.02618 0.128011,-0.331751 0.284467,-0.679053 0.612348,-1.359288 1.60747,-2.894448 2.554157,-3.940261 l 0.250325,-0.276537 -1.091961,-0.01355 c -0.600578,-0.0075 -1.09196,-0.02371 -1.09196,-0.03612 0,-0.05096 0.884286,-1.682765 1.257643,-2.320774 0.220867,-0.377426 0.401575,-0.693185 0.401575,-0.701687 0,-0.0085 0.150592,-0.248405 0.334648,-0.533115 1.364098,-2.110082 3.197284,-4.1069 4.740354,-5.163486 0.64361,-0.4407007 1.91774,-1.1351211 2.40992,-1.3134489 1.6425,-0.5951092 4.5421,-0.886847 7.53603,-0.7582232 2.9581,0.1270843 4.52318,0.4525661 5.97067,1.2416886 2.07049,1.1287605 3.46826,2.3767155 5.11952,4.5707825 0.51181,0.680063 1.34137,1.890066 1.34137,1.956538 0,0.0109 0.16629,0.299165 0.36953,0.640582 0.38189,0.641502 1.28969,2.309489 1.28969,2.369648 0,0.01874 -0.48716,0.04016 -1.08259,0.04762 l -1.08259,0.01355 0.40935,0.477654 c 0.72861,0.850182 1.45934,1.935402 2.00828,2.982522 0.2891,0.551465 0.65258,1.356755 0.65258,1.445796 0,0.02481 -0.18708,-0.141233 -0.41573,-0.368981 -0.45937,-0.457548 -0.94751,-0.811573 -1.59544,-1.157098 -1.84659,-0.984732 -4.76585,-1.563688 -6.76214,-1.341089 -0.76064,0.08482 -0.88201,0.134495 -1.04257,0.426732 -0.22706,0.413268 -0.46651,1.018831 -0.89924,2.274161 -0.22623,0.656295 -0.48858,1.37427 -0.58299,1.595499 -0.40425,0.947246 -0.90368,1.72207 -1.42325,2.208069 -0.24104,0.225466 -0.26262,0.235288 -0.34769,0.158299 -0.19011,-0.172053 -0.65957,-0.201352 -3.19631,-0.199487 -2.51364,0.0018 -3.06469,0.03486 -3.24069,0.194139 -0.0815,0.07373 -0.11542,0.05045 -0.47483,-0.325747 z m 2.87384,-7.075775 -6.52323,-0.01295 -0.0136,-2.300091 -0.0136,-2.300092 -0.0121,2.325419 -0.0121,2.325419 6.54888,-0.01238 6.54888,-0.01238 z m -5.3543,-5.37516 c -0.034,-0.01377 -0.10191,-0.01461 -0.15083,-0.0019 -0.0489,0.01275 -0.0211,0.02402 0.0619,0.02504 0.083,0.001 0.12298,-0.0094 0.0889,-0.02318 z m 9.55583,-0.0047 c -1.00041,-0.0076 -2.65209,-0.0076 -3.6704,-8e-6 -1.0183,0.0076 -0.19979,0.01384 1.81893,0.01384 2.01871,5e-6 2.85187,-0.0062 1.85147,-0.01383 z"
|
|
||||||
id="path43740" />
|
|
||||||
<path
|
|
||||||
style="fill:#f18f26;fill-opacity:1;stroke-width:0.0502793"
|
|
||||||
d="m 32.212902,27.541936 c -0.84478,-0.868685 -1.34829,-1.873086 -2.12252,-4.234001 -0.42445,-1.294313 -0.62883,-1.773879 -0.80527,-1.889486 -0.38144,-0.24993 -2.3063,-0.33559 -3.49837,-0.155684 -1.514071,0.228503 -2.885963,0.641115 -4.016758,1.208083 -0.785412,0.393797 -1.273442,0.741269 -1.828214,1.30167 -0.186662,0.188555 -0.339386,0.32011 -0.339386,0.292343 0,-0.09043 0.401887,-0.971524 0.713093,-1.563375 0.525569,-0.999526 1.462896,-2.349209 2.147454,-3.092179 l 0.231632,-0.251397 -1.093575,-0.01355 c -0.601467,-0.0075 -1.093576,-0.02547 -1.093576,-0.04004 0,-0.03944 0.801328,-1.530374 1.133204,-2.108417 0.15877,-0.276536 0.346161,-0.604609 0.416424,-0.72905 0.473259,-0.838184 1.562844,-2.34916 2.369313,-3.285629 0.627743,-0.728939 1.752789,-1.804517 2.380439,-2.27578 0.97179,-0.7296601 2.30864,-1.4682698 3.12799,-1.7282229 1.4818,-0.4701224 3.26944,-0.6716382 5.95811,-0.6716382 2.19571,0 3.25741,0.083729 4.7678,0.3760062 1.25667,0.2431792 1.90744,0.5040377 3.24261,1.2997688 1.83536,1.0938421 3.58562,2.8803621 5.24766,5.3563911 0.47178,0.702831 2.1274,3.63113 2.1274,3.762734 0,0.01776 -0.47514,0.03229 -1.05587,0.03229 -0.58072,0 -1.05577,0.01697 -1.05565,0.03771 10e-5,0.02074 0.21762,0.297905 0.48336,0.615922 0.60268,0.721254 1.45469,1.997159 1.86352,2.790662 0.36688,0.712099 0.67968,1.427905 0.65557,1.500223 -0.009,0.02827 -0.0836,-0.03598 -0.16492,-0.142785 -0.38211,-0.502058 -1.4814,-1.265062 -2.41037,-1.673001 -2.14174,-0.94051 -5.18213,-1.364547 -6.83799,-0.953679 l -0.25139,0.06238 -0.23269,0.466103 c -0.2233,0.44729 -0.41196,0.943731 -1.02661,2.701495 -0.51683,1.478012 -1.11319,2.536577 -1.78088,3.161118 -0.23832,0.222928 -0.26642,0.236286 -0.34582,0.164431 -0.18938,-0.171397 -0.75719,-0.207396 -3.22573,-0.204519 -2.43628,0.0028 -3.04453,0.04052 -3.22021,0.199512 -0.0723,0.06546 -0.12097,0.032 -0.45978,-0.316409 z m -3.67347,-9.377043 c -0.008,-0.421717 -0.0153,-0.07667 -0.0153,0.76676 0,0.843436 0.007,1.188478 0.0153,0.76676 0.008,-0.421718 0.008,-1.111802 0,-1.53352 z m 1.18167,-3.087768 c -0.0346,-0.01395 -0.0911,-0.01395 -0.1257,0 -0.0346,0.01395 -0.006,0.02536 0.0628,0.02536 0.0691,0 0.0974,-0.01141 0.0628,-0.02536 z m 8.72685,-0.0043 c -0.57196,-0.0081 -1.52223,-0.0081 -2.11174,-2.3e-5 -0.5895,0.008 -0.12154,0.01464 1.03992,0.01466 1.16145,1.2e-5 1.64377,-0.0066 1.07182,-0.01464 z"
|
|
||||||
id="path43779" />
|
|
||||||
<path
|
|
||||||
style="fill:#f18f26;fill-opacity:1;stroke-width:0.0502793"
|
|
||||||
d="m 32.184822,27.510248 c -0.44477,-0.464575 -0.75357,-0.912708 -1.08864,-1.579867 -0.3169,-0.630995 -0.47479,-1.037933 -0.9597,-2.473588 -0.6596,-1.952829 -0.69217,-2.016569 -1.09094,-2.134994 -0.43944,-0.130499 -1.55914,-0.189997 -2.42982,-0.129114 -2.658845,0.185921 -5.232409,1.16491 -6.60005,2.510674 -0.227308,0.223672 -0.413288,0.386143 -0.413288,0.361047 0,-0.09381 0.368801,-0.905326 0.685502,-1.508386 0.533162,-1.015244 1.384908,-2.266627 2.048972,-3.010346 0.155257,-0.17388 0.282286,-0.337916 0.282286,-0.364525 0,-0.02945 -0.413128,-0.04838 -1.055866,-0.04838 -0.580726,0 -1.055866,-0.01369 -1.055866,-0.03043 0,-0.137871 1.665309,-3.075618 2.169204,-3.826661 1.197958,-1.785524 2.837142,-3.599712 4.127966,-4.568674 0.93684,-0.703248 2.29005,-1.4587652 3.08609,-1.7230229 2.82621,-0.9381997 9.2758,-0.9273473 12.07134,0.020312 0.713,0.2417002 2.06975,0.9989949 2.94336,1.6428839 1.39549,1.028547 2.89971,2.684807 4.20425,4.629195 0.52197,0.777977 2.16874,3.680774 2.16874,3.822874 0,0.01844 -0.47514,0.03352 -1.05587,0.03352 -0.58072,0 -1.05521,0.01697 -1.05441,0.03771 8e-4,0.02074 0.1821,0.252654 0.40289,0.515363 0.74682,0.888627 1.48266,1.99088 1.98607,2.97505 0.28875,0.564501 0.62635,1.32273 0.62635,1.406755 0,0.02688 -0.17751,-0.12864 -0.39447,-0.345596 -1.41234,-1.412345 -4.12153,-2.401571 -6.99659,-2.554719 -0.69945,-0.03726 -1.64638,0.03398 -2.05173,0.154357 l -0.26131,0.0776 -0.22146,0.463109 c -0.19834,0.414745 -0.4231,1.012699 -1.09068,2.901655 -0.44448,1.257688 -1.07576,2.348426 -1.69375,2.926482 l -0.25044,0.234259 -0.20893,-0.103372 c -0.30659,-0.151687 -2.26663,-0.219912 -4.41923,-0.153825 -1.45178,0.04457 -1.63244,0.05951 -1.81568,0.150175 l -0.20349,0.100677 z m -3.64593,-8.591165 c -0.0102,-0.145181 -0.0185,-0.0264 -0.0185,0.263967 0,0.290363 0.008,0.409148 0.0185,0.263966 0.0102,-0.145181 0.0102,-0.382751 0,-0.527933 z m 1.15602,-3.839036 c -0.0167,-0.01671 -0.0601,-0.01849 -0.0964,-0.004 -0.0401,0.01605 -0.0282,0.02796 0.0304,0.03038 0.053,0.0022 0.0827,-0.0097 0.066,-0.02641 z m 7.99743,-0.0067 c -0.15792,-0.0099 -0.42943,-0.01003 -0.60335,-2.01e-4 -0.17392,0.0098 -0.0447,0.01798 0.28714,0.01808 0.33184,1.01e-4 0.47414,-0.008 0.31621,-0.0179 z"
|
|
||||||
id="path43818" />
|
|
||||||
<path
|
|
||||||
style="fill:#f18f26;fill-opacity:1;stroke-width:0.0502793"
|
|
||||||
d="m 32.246822,27.586146 c -0.44912,-0.46165 -0.77413,-0.921958 -1.09768,-1.554631 -0.35712,-0.698319 -0.50174,-1.067487 -1.04548,-2.668928 -0.52982,-1.56044 -0.68367,-1.895886 -0.91305,-1.990778 -0.43315,-0.179189 -2.19034,-0.250274 -3.17761,-0.128545 -1.539359,0.189799 -3.236874,0.697742 -4.399444,1.316434 -0.653142,0.347585 -1.052894,0.638018 -1.571229,1.141547 -0.24197,0.235057 -0.439945,0.404558 -0.439945,0.376667 0,-0.104533 0.272394,-0.719479 0.617779,-1.394674 0.54181,-1.059186 1.385523,-2.307419 2.150618,-3.181736 0.135396,-0.154724 0.234019,-0.300986 0.219162,-0.325024 -0.01486,-0.02404 -0.489504,-0.04371 -1.054772,-0.04371 -0.565267,0 -1.027759,-0.01453 -1.027759,-0.03229 0,-0.13601 1.660303,-3.067457 2.160206,-3.814081 1.53488,-2.2924 3.338654,-4.149172 5.072834,-5.221896 0.68736,-0.4251822 1.63914,-0.9096447 2.08206,-1.0597805 0.81077,-0.2748262 2.12936,-0.5100076 3.58155,-0.638796 0.90383,-0.080157 4.05342,-0.079476 4.97765,0.00108 1.54321,0.1345005 3.00455,0.4073241 3.77296,0.7043904 0.4945,0.1911708 1.6471,0.8170272 2.257,1.2255301 1.61732,1.08328 3.25675,2.818797 4.68948,4.964335 0.54983,0.823379 2.17721,3.692152 2.17721,3.838024 0,0.01842 -0.44686,0.03383 -0.99302,0.03425 -0.54616,4.03e-4 -1.01874,0.01739 -1.05018,0.03771 -0.0372,0.02403 0.0821,0.203835 0.34149,0.514593 0.46779,0.560485 0.9475,1.226338 1.39209,1.93225 0.34411,0.546372 1.13811,2.120417 1.1938,2.366633 0.0307,0.135554 -0.006,0.111054 -0.36484,-0.241791 -0.55033,-0.541597 -1.13214,-0.944948 -1.90202,-1.318634 -1.41229,-0.685492 -3.03164,-1.10039 -4.81663,-1.234084 -0.86003,-0.06442 -1.87225,-0.007 -2.34356,0.132992 -0.25105,0.07455 -0.2578,0.08188 -0.45326,0.491388 -0.23794,0.498551 -0.35585,0.804095 -0.81687,2.116898 -0.19366,0.551449 -0.41999,1.173656 -0.50297,1.382682 -0.37957,0.956182 -0.9389,1.852392 -1.48763,2.383612 -0.24427,0.236471 -0.25547,0.241404 -0.37311,0.164323 -0.0667,-0.0437 -0.28992,-0.100907 -0.49603,-0.127113 -0.62273,-0.07918 -2.49651,-0.106834 -4.10597,-0.0606 -1.36791,0.03929 -1.53925,0.05369 -1.72334,0.144766 l -0.20441,0.101133 z"
|
|
||||||
id="path43857" />
|
|
||||||
<path
|
|
||||||
style="fill:#f18f26;fill-opacity:1;stroke-width:0.0502793"
|
|
||||||
d="m 32.290872,27.642829 c -0.42738,-0.432058 -0.82613,-0.994183 -1.1382,-1.604554 -0.35437,-0.6931 -0.57721,-1.261284 -1.07054,-2.729591 -0.21783,-0.64836 -0.47586,-1.338444 -0.57338,-1.53352 -0.19902,-0.398091 -0.26934,-0.439497 -0.90187,-0.531014 -0.51993,-0.07523 -2.08831,-0.0595 -2.75273,0.02759 -1.115202,0.14619 -2.277019,0.44766 -3.286207,0.852708 -1.088828,0.437013 -1.783874,0.868696 -2.502961,1.55455 -0.588859,0.561646 -0.588133,0.521868 0.01277,-0.699864 0.606453,-1.233008 1.30204,-2.306209 2.136398,-3.296187 0.330083,-0.391649 0.385153,-0.480745 0.314571,-0.508938 -0.04706,-0.0188 -0.521105,-0.03577 -1.053437,-0.03771 -0.532332,-0.0019 -0.967877,-0.01862 -0.967877,-0.03706 0,-0.124898 1.605916,-2.980203 2.087205,-3.711033 1.3941,-2.116919 3.186378,-4.023289 4.791578,-5.096582 0.46566,-0.3113611 1.11046,-0.6824962 1.70835,-0.9832937 1.2718,-0.6398471 3.35551,-0.9712565 6.34583,-1.0092898 3.18137,-0.040463 5.6787,0.2818303 7.03327,0.9076827 1.49558,0.6910001 2.77712,1.5889428 3.97674,2.7864108 1.61584,1.612944 2.99085,3.580493 4.47869,6.408707 0.19211,0.365175 0.34929,0.677703 0.34929,0.694508 0,0.0168 -0.45068,0.03753 -1.00152,0.04605 -0.55083,0.0085 -1.01778,0.03183 -1.03768,0.05178 -0.0199,0.01996 0.0824,0.178336 0.22727,0.351956 0.91646,1.098194 1.63526,2.19891 2.24185,3.43299 0.60002,1.220717 0.60096,1.261037 0.0163,0.703911 -0.26116,-0.248883 -0.65507,-0.572872 -0.87536,-0.719976 -1.94037,-1.295749 -5.36397,-2.055624 -7.71616,-1.712621 -0.59776,0.08717 -0.62747,0.10635 -0.83244,0.53764 -0.25287,0.532044 -0.41733,0.954211 -0.82167,2.109194 -0.1911,0.545857 -0.41945,1.173472 -0.50746,1.394701 -0.39022,0.980902 -0.94346,1.870135 -1.49679,2.405801 -0.24537,0.237545 -0.25497,0.241726 -0.37472,0.163265 -0.2253,-0.147624 -0.87979,-0.185601 -3.18201,-0.184635 -2.30009,9.66e-4 -3.01221,0.04044 -3.22315,0.17865 -0.11368,0.07449 -0.12762,0.06717 -0.404,-0.21224 z"
|
|
||||||
id="path43896" />
|
|
||||||
<path
|
|
||||||
style="fill:#f18f26;fill-opacity:1;stroke-width:0.0502793"
|
|
||||||
d="m 32.289722,27.645005 c -0.91417,-0.94931 -1.32416,-1.742554 -2.1387,-4.137933 -0.515,-1.514499 -0.66738,-1.879371 -0.84858,-2.031841 -0.25124,-0.211407 -0.60513,-0.256092 -2.00732,-0.253472 -1.39843,0.0026 -1.877889,0.06065 -3.083226,0.373225 -1.836256,0.476185 -3.151953,1.140892 -4.167774,2.105612 -0.556797,0.528788 -0.558028,0.490824 -0.02013,-0.620898 0.591698,-1.222918 1.335546,-2.380104 2.172925,-3.380366 0.20299,-0.242475 0.36972,-0.455004 0.370511,-0.472288 0.003,-0.06659 -0.345274,-0.09427 -1.186411,-0.09427 -0.480482,0 -0.873603,-0.01509 -0.873603,-0.03352 0,-0.126809 1.510769,-2.823522 2.049063,-3.657565 0.711,-1.101635 1.750295,-2.389306 2.716769,-3.366037 1.214926,-1.22782 2.247206,-1.975378 3.821296,-2.7673067 1.08472,-0.545723 2.80554,-0.8702497 5.25371,-0.990787 2.84103,-0.1398801 5.91848,0.1234604 7.4776,0.6398651 0.86035,0.2849616 2.19805,1.0215625 3.14246,1.7303796 1.46529,1.099769 3.20484,3.063773 4.38478,4.950562 0.58586,0.936818 1.92527,3.344592 1.92527,3.460929 0,0.01842 -0.4016,0.03616 -0.89246,0.03943 -0.49085,0.0033 -0.95769,0.02024 -1.03741,0.03771 l -0.14496,0.03176 0.43223,0.541124 c 0.57234,0.716534 1.05615,1.402831 1.44393,2.048261 0.34819,0.579531 1.02598,1.948309 1.08303,2.187151 0.0323,0.135225 -0.008,0.108727 -0.38955,-0.256004 -0.72669,-0.69469 -1.49546,-1.178794 -2.53112,-1.593889 -1.03541,-0.414991 -2.23144,-0.718368 -3.42379,-0.868447 -1.19753,-0.150732 -3.01698,-0.07553 -3.27089,0.135199 -0.19588,0.162573 -0.51891,0.935502 -1.17412,2.809398 -0.59961,1.714853 -1.19201,2.80287 -1.89849,3.486806 -0.24234,0.234602 -0.25631,0.240868 -0.37076,0.166265 -0.21878,-0.142607 -0.93622,-0.183811 -3.18466,-0.182904 -2.30869,9.3e-4 -3.01927,0.03947 -3.22605,0.174952 -0.12041,0.0789 -0.12827,0.07479 -0.40357,-0.211097 z"
|
|
||||||
id="path43935" />
|
|
||||||
<text
|
|
||||||
xml:space="preserve"
|
|
||||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:1.25;font-family:Overpass;-inkscape-font-specification:Overpass;letter-spacing:-1px;fill:#272b2b;fill-opacity:1;stroke:none"
|
|
||||||
x="26.83289"
|
|
||||||
y="23.576347"
|
|
||||||
id="text48393"><tspan
|
|
||||||
sodipodi:role="line"
|
|
||||||
id="tspan48391"
|
|
||||||
x="26.83289"
|
|
||||||
y="23.576347"
|
|
||||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;font-family:Overpass;-inkscape-font-specification:Overpass;fill:#272b2b;fill-opacity:1">32</tspan></text>
|
|
||||||
<text
|
|
||||||
xml:space="preserve"
|
|
||||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;line-height:1.25;font-family:Overpass;-inkscape-font-specification:Overpass;letter-spacing:-1px;fill:#272b2b;fill-opacity:1;stroke:#f18f26;stroke-width:0.2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
|
||||||
x="-0.086526871"
|
|
||||||
y="23.6"
|
|
||||||
id="text48393-3"><tspan
|
|
||||||
sodipodi:role="line"
|
|
||||||
id="tspan48391-6"
|
|
||||||
x="-0.086526871"
|
|
||||||
y="23.6"
|
|
||||||
style="font-style:normal;font-variant:normal;font-weight:normal;font-stretch:normal;font-size:16px;font-family:Overpass;-inkscape-font-specification:Overpass;fill:#272b2b;fill-opacity:1;stroke:#f18f26;stroke-width:0.2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1">fox</tspan></text>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 586 KiB |
BIN
src/32.png
Before Width: | Height: | Size: 8.5 KiB |
70
src/audio.rs
|
@ -1,70 +0,0 @@
|
||||||
// audio.rs
|
|
||||||
|
|
||||||
use crate::Interrupt;
|
|
||||||
use crate::memory::Memory;
|
|
||||||
|
|
||||||
use std::sync::{Arc, Mutex};
|
|
||||||
use std::sync::mpsc::Sender;
|
|
||||||
use std::{thread, time};
|
|
||||||
use rodio::{OutputStream, buffer::SamplesBuffer, Sink};
|
|
||||||
|
|
||||||
const AUDIO_BUFFER_0_ADDRESS: usize = 0x0212C000;
|
|
||||||
const AUDIO_BUFFER_1_ADDRESS: usize = 0x02134000;
|
|
||||||
const AUDIO_BUFFER_2_ADDRESS: usize = 0x02290000;
|
|
||||||
const AUDIO_BUFFER_3_ADDRESS: usize = 0x02298000;
|
|
||||||
const AUDIO_BUFFER_SIZE: usize = 0x8000;
|
|
||||||
|
|
||||||
const AUDIO_CHANNEL_0_INTERRUPT: u8 = 0xFE;
|
|
||||||
const AUDIO_CHANNEL_1_INTERRUPT: u8 = 0xFD;
|
|
||||||
const AUDIO_CHANNEL_2_INTERRUPT: u8 = 0xFC;
|
|
||||||
const AUDIO_CHANNEL_3_INTERRUPT: u8 = 0xFB;
|
|
||||||
|
|
||||||
pub struct AudioChannel {
|
|
||||||
pub id: u8,
|
|
||||||
pub playing: bool,
|
|
||||||
pub sample_rate: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AudioChannel {
|
|
||||||
pub fn new(id: u8) -> Self {
|
|
||||||
AudioChannel {
|
|
||||||
id,
|
|
||||||
playing: false,
|
|
||||||
sample_rate: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// this is terrible
|
|
||||||
pub fn spawn_thread(this: Arc<Mutex<Self>>, interrupt_sender: Sender<Interrupt>, memory: Memory) {
|
|
||||||
let (audio_buffer_address, audio_channel_interrupt) = match this.lock().unwrap().id {
|
|
||||||
0 => (AUDIO_BUFFER_0_ADDRESS, AUDIO_CHANNEL_0_INTERRUPT),
|
|
||||||
1 => (AUDIO_BUFFER_1_ADDRESS, AUDIO_CHANNEL_1_INTERRUPT),
|
|
||||||
2 => (AUDIO_BUFFER_2_ADDRESS, AUDIO_CHANNEL_2_INTERRUPT),
|
|
||||||
3 => (AUDIO_BUFFER_3_ADDRESS, AUDIO_CHANNEL_3_INTERRUPT),
|
|
||||||
_ => unreachable!(),
|
|
||||||
};
|
|
||||||
let builder = thread::Builder::new().name("audio".to_string());
|
|
||||||
builder.spawn({
|
|
||||||
move || {
|
|
||||||
let (_stream, stream_handle) = OutputStream::try_default().unwrap();
|
|
||||||
let channel = Sink::try_new(&stream_handle).unwrap();
|
|
||||||
loop {
|
|
||||||
// every `sleep` number of ms, play what is in the audio buffer
|
|
||||||
let self_lock = this.lock().unwrap();
|
|
||||||
if self_lock.playing {
|
|
||||||
let audio_buffer: Vec<i16> = memory.ram()[audio_buffer_address..audio_buffer_address+AUDIO_BUFFER_SIZE]
|
|
||||||
.to_vec()
|
|
||||||
.chunks_exact(2)
|
|
||||||
.map(|x| ((x[1] as i16) << 8) | x[0] as i16)
|
|
||||||
.collect();
|
|
||||||
// 1 Hz = 1000 ms
|
|
||||||
let sleep: f32 = (1000 as f32 / self_lock.sample_rate as f32) * (AUDIO_BUFFER_SIZE as f32 / 2.0);
|
|
||||||
channel.append(SamplesBuffer::new(1, self_lock.sample_rate, audio_buffer));
|
|
||||||
interrupt_sender.send(Interrupt::Request(audio_channel_interrupt)).unwrap();
|
|
||||||
thread::sleep(time::Duration::from_millis(sleep as u64));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}).unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
300
src/bus.rs
|
@ -1,300 +0,0 @@
|
||||||
// bus.rs
|
|
||||||
|
|
||||||
use crate::{Memory, AudioChannel, DiskController, Keyboard, Mouse, Overlay};
|
|
||||||
|
|
||||||
use chrono::prelude::*;
|
|
||||||
use std::sync::{Arc, Mutex};
|
|
||||||
use std::io::{Write, stdout};
|
|
||||||
|
|
||||||
pub struct Bus {
|
|
||||||
pub memory: Memory,
|
|
||||||
|
|
||||||
pub disk_controller: DiskController,
|
|
||||||
|
|
||||||
pub audio_channel_0: Arc<Mutex<AudioChannel>>,
|
|
||||||
pub audio_channel_1: Arc<Mutex<AudioChannel>>,
|
|
||||||
pub audio_channel_2: Arc<Mutex<AudioChannel>>,
|
|
||||||
pub audio_channel_3: Arc<Mutex<AudioChannel>>,
|
|
||||||
|
|
||||||
pub keyboard: Arc<Mutex<Keyboard>>,
|
|
||||||
pub mouse: Arc<Mutex<Mouse>>,
|
|
||||||
|
|
||||||
pub overlays: Arc<Mutex<Vec<Overlay>>>,
|
|
||||||
|
|
||||||
pub startup_time: i64,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Bus {
|
|
||||||
pub fn read_io(&mut self, port: u32) -> u32 {
|
|
||||||
match port {
|
|
||||||
0x80000000..=0x8000031F => { // overlay port
|
|
||||||
let overlay_lock = self.overlays.lock().unwrap();
|
|
||||||
let overlay_number = (port & 0x000000FF) as usize;
|
|
||||||
let setting = (port & 0x0000FF00) >> 8;
|
|
||||||
|
|
||||||
match setting {
|
|
||||||
0x00 => {
|
|
||||||
// we're reading the position of this overlay
|
|
||||||
let x = overlay_lock[overlay_number].x as u32;
|
|
||||||
let y = overlay_lock[overlay_number].y as u32;
|
|
||||||
(y << 16) | x
|
|
||||||
}
|
|
||||||
0x01 => {
|
|
||||||
// we're reading the size of this overlay
|
|
||||||
let width = overlay_lock[overlay_number].width as u32;
|
|
||||||
let height = overlay_lock[overlay_number].height as u32;
|
|
||||||
(height << 16) | width
|
|
||||||
}
|
|
||||||
0x02 => {
|
|
||||||
// we're reading the framebuffer pointer of this overlay
|
|
||||||
overlay_lock[overlay_number].framebuffer_pointer
|
|
||||||
}
|
|
||||||
0x03 => {
|
|
||||||
// we're reading the enable status of this overlay
|
|
||||||
overlay_lock[overlay_number].enabled as u32
|
|
||||||
}
|
|
||||||
_ => panic!("invalid overlay control port"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
0x80000400..=0x80000401 => { // mouse port
|
|
||||||
let setting = (port & 0x000000FF) as u8;
|
|
||||||
match setting {
|
|
||||||
0x00 => {
|
|
||||||
// we're reading the button states
|
|
||||||
let mut byte: u8 = 0x00;
|
|
||||||
let mouse_lock = self.mouse.lock().expect("failed to lock the mouse mutex");
|
|
||||||
if mouse_lock.clicked {
|
|
||||||
byte |= 0b001;
|
|
||||||
}
|
|
||||||
if mouse_lock.released {
|
|
||||||
byte |= 0b010;
|
|
||||||
}
|
|
||||||
if mouse_lock.held {
|
|
||||||
byte |= 0b100;
|
|
||||||
} else {
|
|
||||||
byte &= !0b100;
|
|
||||||
}
|
|
||||||
byte as u32
|
|
||||||
}
|
|
||||||
0x01 => {
|
|
||||||
// we're reading the position
|
|
||||||
let mouse_lock = self.mouse.lock().expect("failed to lock the mouse mutex");
|
|
||||||
let x = mouse_lock.x as u32;
|
|
||||||
let y = mouse_lock.y as u32;
|
|
||||||
(y << 16) | x
|
|
||||||
}
|
|
||||||
_ => panic!("invalid mouse control port"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
0x80000500 => { // keyboard port
|
|
||||||
let mut keyboard_lock = self.keyboard.lock().expect("failed to lock the keyboard mutex");
|
|
||||||
keyboard_lock.pop() as u32
|
|
||||||
}
|
|
||||||
0x80000600..=0x80000603 => { // audio port
|
|
||||||
let channel = (port & 0x000000FF) as u8;
|
|
||||||
match channel {
|
|
||||||
0 => {
|
|
||||||
let audio_lock = self.audio_channel_0.lock().unwrap();
|
|
||||||
audio_lock.sample_rate
|
|
||||||
},
|
|
||||||
1 => {
|
|
||||||
let audio_lock = self.audio_channel_1.lock().unwrap();
|
|
||||||
audio_lock.sample_rate
|
|
||||||
},
|
|
||||||
2 => {
|
|
||||||
let audio_lock = self.audio_channel_2.lock().unwrap();
|
|
||||||
audio_lock.sample_rate
|
|
||||||
},
|
|
||||||
3 => {
|
|
||||||
let audio_lock = self.audio_channel_3.lock().unwrap();
|
|
||||||
audio_lock.sample_rate
|
|
||||||
},
|
|
||||||
_ => panic!("invalid audio channel"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
0x80000700..=0x80000706 => { // RTC port
|
|
||||||
let setting = (port & 0x000000FF) as u8;
|
|
||||||
match setting {
|
|
||||||
0 => { // year
|
|
||||||
Local::now().year() as u32
|
|
||||||
},
|
|
||||||
1 => { // month
|
|
||||||
Local::now().month()
|
|
||||||
},
|
|
||||||
2 => { // day
|
|
||||||
Local::now().day()
|
|
||||||
},
|
|
||||||
3 => { // hour
|
|
||||||
Local::now().hour()
|
|
||||||
},
|
|
||||||
4 => { // minute
|
|
||||||
Local::now().minute()
|
|
||||||
},
|
|
||||||
5 => { // second
|
|
||||||
Local::now().second()
|
|
||||||
},
|
|
||||||
6 => { // milliseconds elapsed since startup
|
|
||||||
(Local::now().timestamp_millis() - self.startup_time) as u32
|
|
||||||
},
|
|
||||||
_ => panic!("invalid RTC port"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
0x80001000..=0x80002003 => { // disk controller port
|
|
||||||
let id = port as u8;
|
|
||||||
let operation = (port & 0x0000F000) >> 8;
|
|
||||||
|
|
||||||
match operation {
|
|
||||||
0x10 => {
|
|
||||||
// we're reading the current insert state of the specified disk id
|
|
||||||
if id > 3 {
|
|
||||||
panic!("invalid disk ID");
|
|
||||||
}
|
|
||||||
match &self.disk_controller.disk[id as usize] {
|
|
||||||
Some(_) => self.disk_controller.get_size(id) as u32, // return size if this disk is inserted
|
|
||||||
None => 0, // return 0 if this disk is not inserted
|
|
||||||
}
|
|
||||||
}
|
|
||||||
0x20 => {
|
|
||||||
// we're getting the location of the memory sector buffer
|
|
||||||
self.disk_controller.buffer_pointer as u32
|
|
||||||
}
|
|
||||||
_ => panic!("invalid disk controller port"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn write_io(&mut self, port: u32, word: u32) {
|
|
||||||
match port {
|
|
||||||
0x00000000 => { // terminal output port
|
|
||||||
print!("{}", word as u8 as char);
|
|
||||||
stdout().flush().expect("could not flush stdout");
|
|
||||||
}
|
|
||||||
0x80000000..=0x8000031F => { // overlay port
|
|
||||||
let mut overlay_lock = self.overlays.lock().unwrap();
|
|
||||||
let overlay_number = (port & 0x000000FF) as usize;
|
|
||||||
let setting = (port & 0x0000FF00) >> 8;
|
|
||||||
|
|
||||||
match setting {
|
|
||||||
0x00 => {
|
|
||||||
// we're setting the position of this overlay
|
|
||||||
let x = (word & 0x0000FFFF) as usize;
|
|
||||||
let y = ((word & 0xFFFF0000) >> 16) as usize;
|
|
||||||
overlay_lock[overlay_number].x = x;
|
|
||||||
overlay_lock[overlay_number].y = y;
|
|
||||||
}
|
|
||||||
0x01 => {
|
|
||||||
// we're setting the size of this overlay
|
|
||||||
let width = (word & 0x0000FFFF) as usize;
|
|
||||||
let height = ((word & 0xFFFF0000) >> 16) as usize;
|
|
||||||
overlay_lock[overlay_number].width = width;
|
|
||||||
overlay_lock[overlay_number].height = height;
|
|
||||||
}
|
|
||||||
0x02 => {
|
|
||||||
// we're setting the framebuffer pointer of this overlay
|
|
||||||
overlay_lock[overlay_number].framebuffer_pointer = word;
|
|
||||||
}
|
|
||||||
0x03 => {
|
|
||||||
// we're setting the enable status of this overlay
|
|
||||||
overlay_lock[overlay_number].enabled = word != 0;
|
|
||||||
}
|
|
||||||
_ => panic!("invalid overlay control port"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
0x80000400..=0x80000401 => { // mouse port
|
|
||||||
let setting = (port & 0x000000FF) as u8;
|
|
||||||
match setting {
|
|
||||||
0x00 => {
|
|
||||||
// we're setting the button states
|
|
||||||
let mut mouse_lock = self.mouse.lock().expect("failed to lock the mouse mutex");
|
|
||||||
mouse_lock.clicked = word & (1 << 0) != 0;
|
|
||||||
mouse_lock.released = word & (1 << 1) != 0;
|
|
||||||
mouse_lock.held = word & (1 << 2) != 0;
|
|
||||||
}
|
|
||||||
0x01 => {
|
|
||||||
// we're setting the position
|
|
||||||
let mut mouse_lock = self.mouse.lock().expect("failed to lock the mouse mutex");
|
|
||||||
let x = (word & 0x0000FFFF) as u16;
|
|
||||||
let y = ((word & 0xFFFF0000) >> 16) as u16;
|
|
||||||
mouse_lock.x = x;
|
|
||||||
mouse_lock.y = y;
|
|
||||||
}
|
|
||||||
_ => panic!("invalid mouse control port"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
0x80000600..=0x80000603 => { // audio port
|
|
||||||
let channel = (port & 0x000000FF) as u8;
|
|
||||||
match channel {
|
|
||||||
0 => {
|
|
||||||
let mut audio_lock = self.audio_channel_0.lock().unwrap();
|
|
||||||
audio_lock.playing = word != 0;
|
|
||||||
audio_lock.sample_rate = word;
|
|
||||||
},
|
|
||||||
1 => {
|
|
||||||
let mut audio_lock = self.audio_channel_1.lock().unwrap();
|
|
||||||
audio_lock.playing = word != 0;
|
|
||||||
audio_lock.sample_rate = word;
|
|
||||||
},
|
|
||||||
2 => {
|
|
||||||
let mut audio_lock = self.audio_channel_2.lock().unwrap();
|
|
||||||
audio_lock.playing = word != 0;
|
|
||||||
audio_lock.sample_rate = word;
|
|
||||||
},
|
|
||||||
3 => {
|
|
||||||
let mut audio_lock = self.audio_channel_3.lock().unwrap();
|
|
||||||
audio_lock.playing = word != 0;
|
|
||||||
audio_lock.sample_rate = word;
|
|
||||||
},
|
|
||||||
_ => panic!("invalid audio channel"),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
0x80001000..=0x80005003 => { // disk controller port
|
|
||||||
let id = port as u8;
|
|
||||||
let operation = (port & 0x0000F000) >> 8;
|
|
||||||
|
|
||||||
match operation {
|
|
||||||
0x10 => {
|
|
||||||
// we're requesting a disk to be inserted to the specified disk id
|
|
||||||
if id > 3 {
|
|
||||||
panic!("invalid disk ID");
|
|
||||||
}
|
|
||||||
let file = self.disk_controller.select_file();
|
|
||||||
match file {
|
|
||||||
Some(file) => self.disk_controller.insert(file, id),
|
|
||||||
None => {},
|
|
||||||
};
|
|
||||||
}
|
|
||||||
0x20 => {
|
|
||||||
// we're setting the location of the memory sector buffer
|
|
||||||
self.disk_controller.buffer_pointer = word as usize;
|
|
||||||
}
|
|
||||||
0x30 => {
|
|
||||||
// we're reading the specified sector of the specified disk id into the memory sector buffer
|
|
||||||
if id > 3 {
|
|
||||||
panic!("invalid disk ID");
|
|
||||||
}
|
|
||||||
self.disk_controller.set_current_sector(id, word);
|
|
||||||
self.disk_controller.read_into_memory(id, self.memory.ram());
|
|
||||||
}
|
|
||||||
0x40 => {
|
|
||||||
// we're writing the specified sector to the specified disk id from the memory sector buffer
|
|
||||||
if id > 3 {
|
|
||||||
panic!("invalid disk ID");
|
|
||||||
}
|
|
||||||
self.disk_controller.set_current_sector(id, word);
|
|
||||||
self.disk_controller.write_from_memory(id, self.memory.ram());
|
|
||||||
}
|
|
||||||
0x50 => {
|
|
||||||
// we're requesting a disk to be removed from the specified disk id
|
|
||||||
if id > 3 {
|
|
||||||
panic!("invalid disk ID");
|
|
||||||
}
|
|
||||||
self.disk_controller.remove(id);
|
|
||||||
}
|
|
||||||
_ => panic!("invalid disk controller port"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => return,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
2935
src/cpu.rs
84
src/disk.rs
|
@ -1,84 +0,0 @@
|
||||||
// disk.rs
|
|
||||||
|
|
||||||
use crate::memory::MemoryRam;
|
|
||||||
|
|
||||||
use std::io::{Seek, SeekFrom, Read, Write};
|
|
||||||
use std::fs::File;
|
|
||||||
use rfd::FileDialog;
|
|
||||||
|
|
||||||
pub struct Disk {
|
|
||||||
file: File,
|
|
||||||
size: u64,
|
|
||||||
current_sector: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Disk {
|
|
||||||
pub fn new(file: File) -> Self {
|
|
||||||
Disk {
|
|
||||||
size: file.metadata().unwrap().len(),
|
|
||||||
file,
|
|
||||||
current_sector: 0,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct DiskController {
|
|
||||||
pub disk: [Option<Disk>; 4],
|
|
||||||
pub buffer_pointer: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl DiskController {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
DiskController {
|
|
||||||
disk: [None, None, None, None],
|
|
||||||
buffer_pointer: 0x00000000
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn select_file(&self) -> Option<File> {
|
|
||||||
let path = FileDialog::new()
|
|
||||||
.add_filter("Disk Image", &["img", "dsk"])
|
|
||||||
.add_filter("Raw Binary", &["bin"])
|
|
||||||
.add_filter("All Files", &["*"])
|
|
||||||
.set_title(&format!("Select a file to insert"))
|
|
||||||
.pick_file();
|
|
||||||
match path {
|
|
||||||
Some(path) => Some(File::options().read(true).write(true).open(path).expect("failed to open disk image")),
|
|
||||||
None => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn insert(&mut self, file: File, disk_id: u8) {
|
|
||||||
self.disk[disk_id as usize] = Some(Disk::new(file));
|
|
||||||
}
|
|
||||||
pub fn remove(&mut self, disk_id: u8) {
|
|
||||||
self.disk[disk_id as usize] = None;
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn get_size(&self, disk_id: u8) -> u64 {
|
|
||||||
self.disk[disk_id as usize].as_ref().expect("attempted to access unmounted disk").size
|
|
||||||
}
|
|
||||||
pub fn get_current_sector(&self, disk_id: u8) -> u32 {
|
|
||||||
self.disk[disk_id as usize].as_ref().expect("attempted to access unmounted disk").current_sector
|
|
||||||
}
|
|
||||||
pub fn set_current_sector(&mut self, disk_id: u8, sector: u32) {
|
|
||||||
let mut disk = self.disk[disk_id as usize].as_mut().expect("attempted to access unmounted disk");
|
|
||||||
disk.current_sector = sector;
|
|
||||||
disk.file.seek(SeekFrom::Start(sector as u64 * 512)).expect("attempted to seek to sector beyond edge of disk");
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn read_into_memory(&mut self, disk_id: u8, ram: &mut MemoryRam) -> usize {
|
|
||||||
let disk = self.disk[disk_id as usize].as_mut().expect("attempted to access unmounted disk");
|
|
||||||
let mut temp_buffer = [0u8; 512];
|
|
||||||
|
|
||||||
let number_of_bytes_read = disk.file.read(&mut temp_buffer).unwrap();
|
|
||||||
ram[self.buffer_pointer..self.buffer_pointer+512].copy_from_slice(&temp_buffer);
|
|
||||||
number_of_bytes_read
|
|
||||||
}
|
|
||||||
pub fn write_from_memory(&mut self, disk_id: u8, ram: &MemoryRam) -> usize {
|
|
||||||
let disk = self.disk[disk_id as usize].as_mut().expect("attempted to access unmounted disk");
|
|
||||||
|
|
||||||
let number_of_bytes_written = disk.file.write(ram.get(self.buffer_pointer..self.buffer_pointer+512).unwrap()).unwrap();
|
|
||||||
number_of_bytes_written
|
|
||||||
}
|
|
||||||
}
|
|
122
src/keyboard.rs
|
@ -1,122 +0,0 @@
|
||||||
// keyboard.rs
|
|
||||||
|
|
||||||
|
|
||||||
use crate::warn;
|
|
||||||
|
|
||||||
use ringbuf::{Consumer, Producer, RingBuffer};
|
|
||||||
use std::sync::mpsc::Sender;
|
|
||||||
use winit::event::{ElementState, VirtualKeyCode};
|
|
||||||
|
|
||||||
pub struct Keyboard {
|
|
||||||
consumer: Consumer<u8>,
|
|
||||||
producer: Producer<u8>,
|
|
||||||
debug_toggle_sender: Sender<()>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Keyboard {
|
|
||||||
pub fn new(debug_toggle_sender: Sender<()>) -> Self {
|
|
||||||
let buffer = RingBuffer::<u8>::new(32);
|
|
||||||
let (producer, consumer) = buffer.split();
|
|
||||||
Keyboard { consumer, producer, debug_toggle_sender }
|
|
||||||
}
|
|
||||||
|
|
||||||
fn keycode_to_scancode(&self, keycode: VirtualKeyCode) -> u8 {
|
|
||||||
match keycode {
|
|
||||||
VirtualKeyCode::Escape => 0x01,
|
|
||||||
VirtualKeyCode::Key1 => 0x02,
|
|
||||||
VirtualKeyCode::Key2 => 0x03,
|
|
||||||
VirtualKeyCode::Key3 => 0x04,
|
|
||||||
VirtualKeyCode::Key4 => 0x05,
|
|
||||||
VirtualKeyCode::Key5 => 0x06,
|
|
||||||
VirtualKeyCode::Key6 => 0x07,
|
|
||||||
VirtualKeyCode::Key7 => 0x08,
|
|
||||||
VirtualKeyCode::Key8 => 0x09,
|
|
||||||
VirtualKeyCode::Asterisk => 0x09,
|
|
||||||
VirtualKeyCode::Key9 => 0x0A,
|
|
||||||
VirtualKeyCode::Key0 => 0x0B,
|
|
||||||
VirtualKeyCode::Minus => 0x0C,
|
|
||||||
VirtualKeyCode::Equals => 0x0D,
|
|
||||||
VirtualKeyCode::Back => 0x0E,
|
|
||||||
VirtualKeyCode::Tab => 0x0F,
|
|
||||||
VirtualKeyCode::Q => 0x10,
|
|
||||||
VirtualKeyCode::W => 0x11,
|
|
||||||
VirtualKeyCode::E => 0x12,
|
|
||||||
VirtualKeyCode::R => 0x13,
|
|
||||||
VirtualKeyCode::T => 0x14,
|
|
||||||
VirtualKeyCode::Y => 0x15,
|
|
||||||
VirtualKeyCode::U => 0x16,
|
|
||||||
VirtualKeyCode::I => 0x17,
|
|
||||||
VirtualKeyCode::O => 0x18,
|
|
||||||
VirtualKeyCode::P => 0x19,
|
|
||||||
VirtualKeyCode::LBracket => 0x1A,
|
|
||||||
VirtualKeyCode::RBracket => 0x1B,
|
|
||||||
VirtualKeyCode::Return => 0x1C,
|
|
||||||
VirtualKeyCode::LControl => 0x1D,
|
|
||||||
VirtualKeyCode::A => 0x1E,
|
|
||||||
VirtualKeyCode::S => 0x1F,
|
|
||||||
VirtualKeyCode::D => 0x20,
|
|
||||||
VirtualKeyCode::F => 0x21,
|
|
||||||
VirtualKeyCode::G => 0x22,
|
|
||||||
VirtualKeyCode::H => 0x23,
|
|
||||||
VirtualKeyCode::J => 0x24,
|
|
||||||
VirtualKeyCode::K => 0x25,
|
|
||||||
VirtualKeyCode::L => 0x26,
|
|
||||||
VirtualKeyCode::Semicolon => 0x27,
|
|
||||||
VirtualKeyCode::Apostrophe => 0x28,
|
|
||||||
VirtualKeyCode::Grave => 0x29,
|
|
||||||
VirtualKeyCode::LShift => 0x2A,
|
|
||||||
VirtualKeyCode::Backslash => 0x2B,
|
|
||||||
VirtualKeyCode::Z => 0x2C,
|
|
||||||
VirtualKeyCode::X => 0x2D,
|
|
||||||
VirtualKeyCode::C => 0x2E,
|
|
||||||
VirtualKeyCode::V => 0x2F,
|
|
||||||
VirtualKeyCode::B => 0x30,
|
|
||||||
VirtualKeyCode::N => 0x31,
|
|
||||||
VirtualKeyCode::M => 0x32,
|
|
||||||
VirtualKeyCode::Comma => 0x33,
|
|
||||||
VirtualKeyCode::Period => 0x34,
|
|
||||||
VirtualKeyCode::Slash => 0x35,
|
|
||||||
VirtualKeyCode::RShift => 0x36,
|
|
||||||
VirtualKeyCode::LAlt => 0x38,
|
|
||||||
VirtualKeyCode::Space => 0x39,
|
|
||||||
VirtualKeyCode::Capital => 0x3A,
|
|
||||||
VirtualKeyCode::F1 => 0x3B,
|
|
||||||
VirtualKeyCode::F2 => 0x3C,
|
|
||||||
VirtualKeyCode::F3 => 0x3D,
|
|
||||||
VirtualKeyCode::F4 => 0x3E,
|
|
||||||
VirtualKeyCode::F5 => 0x3F,
|
|
||||||
VirtualKeyCode::F6 => 0x40,
|
|
||||||
VirtualKeyCode::F7 => 0x41,
|
|
||||||
VirtualKeyCode::F8 => 0x42,
|
|
||||||
VirtualKeyCode::F9 => 0x43,
|
|
||||||
VirtualKeyCode::F10 => 0x44,
|
|
||||||
VirtualKeyCode::F11 => 0x57,
|
|
||||||
VirtualKeyCode::F12 => 0x58,
|
|
||||||
VirtualKeyCode::Up => 0x67,
|
|
||||||
VirtualKeyCode::Down => 0x6C,
|
|
||||||
VirtualKeyCode::Left => 0x69,
|
|
||||||
VirtualKeyCode::Right => 0x6A,
|
|
||||||
_ => 0x00,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn push(&mut self, keycode: Option<VirtualKeyCode>, state: ElementState) {
|
|
||||||
let mut scancode = if let Some(keycode) = keycode {
|
|
||||||
self.keycode_to_scancode(keycode)
|
|
||||||
} else {
|
|
||||||
0x00
|
|
||||||
};
|
|
||||||
if state == ElementState::Released && scancode != 0x00 {
|
|
||||||
scancode |= 0x80; // "break" scancode
|
|
||||||
}
|
|
||||||
if scancode == 0x57 {
|
|
||||||
self.debug_toggle_sender.send(()).unwrap();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
self.producer.push(scancode).unwrap_or_else(|_| warn("keyboard buffer full!"));
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn pop(&mut self) -> u8 {
|
|
||||||
self.consumer.pop().unwrap_or_default()
|
|
||||||
}
|
|
||||||
}
|
|
352
src/main.rs
|
@ -1,352 +0,0 @@
|
||||||
// main.rs
|
|
||||||
|
|
||||||
pub mod memory;
|
|
||||||
pub mod audio;
|
|
||||||
pub mod bus;
|
|
||||||
pub mod cpu;
|
|
||||||
pub mod keyboard;
|
|
||||||
pub mod mouse;
|
|
||||||
pub mod disk;
|
|
||||||
|
|
||||||
use audio::AudioChannel;
|
|
||||||
use bus::Bus;
|
|
||||||
use cpu::{Cpu, Exception, Interrupt};
|
|
||||||
use keyboard::Keyboard;
|
|
||||||
use mouse::Mouse;
|
|
||||||
use disk::DiskController;
|
|
||||||
use memory::{MEMORY_RAM_START, MEMORY_ROM_START, MemoryRam, Memory};
|
|
||||||
|
|
||||||
use std::sync::{Arc, mpsc, Mutex};
|
|
||||||
use std::thread;
|
|
||||||
use std::process::exit;
|
|
||||||
use std::env;
|
|
||||||
use std::fs::{File, read};
|
|
||||||
|
|
||||||
use chrono::prelude::*;
|
|
||||||
use image;
|
|
||||||
use log::error;
|
|
||||||
use pixels::{Pixels, SurfaceTexture};
|
|
||||||
use winit::dpi::LogicalSize;
|
|
||||||
use winit::event::{Event, WindowEvent};
|
|
||||||
use winit::event_loop::{ControlFlow, EventLoop};
|
|
||||||
use winit::window::{WindowBuilder, Icon};
|
|
||||||
use winit_input_helper::WinitInputHelper;
|
|
||||||
|
|
||||||
const WIDTH: usize = 640;
|
|
||||||
const HEIGHT: usize = 480;
|
|
||||||
|
|
||||||
const FRAMEBUFFER_ADDRESS: usize = 0x02000000;
|
|
||||||
|
|
||||||
pub struct Display {
|
|
||||||
background: Vec<u8>,
|
|
||||||
overlays: Arc<Mutex<Vec<Overlay>>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Default)]
|
|
||||||
pub struct Overlay {
|
|
||||||
enabled: bool,
|
|
||||||
width: usize,
|
|
||||||
height: usize,
|
|
||||||
x: usize,
|
|
||||||
y: usize,
|
|
||||||
framebuffer_pointer: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_rom() -> Vec<u8> {
|
|
||||||
read("fox32.rom").unwrap_or_else(|_| {
|
|
||||||
read("../fox32rom/fox32.rom").unwrap_or_else(|_| {
|
|
||||||
println!("fox32.rom file not found, using embedded ROM");
|
|
||||||
include_bytes!("fox32.rom").to_vec()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn error(message: &str) -> ! {
|
|
||||||
println!("Error: {}", message);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn warn(message: &str) {
|
|
||||||
println!("Warning: {}", message);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let version_string = format!("fox32 {} ({})", env!("VERGEN_BUILD_SEMVER"), option_env!("VERGEN_GIT_SHA_SHORT").unwrap_or("unknown"));
|
|
||||||
println!("{}", version_string);
|
|
||||||
|
|
||||||
let args: Vec<String> = env::args().collect();
|
|
||||||
|
|
||||||
let (debug_toggle_sender, debug_toggle_receiver) = mpsc::channel::<()>();
|
|
||||||
|
|
||||||
let mut display = Display::new();
|
|
||||||
let keyboard = Arc::new(Mutex::new(Keyboard::new(debug_toggle_sender)));
|
|
||||||
let mouse = Arc::new(Mutex::new(Mouse::new()));
|
|
||||||
|
|
||||||
let audio_channel_0 = Arc::new(Mutex::new(AudioChannel::new(0)));
|
|
||||||
let audio_channel_1 = Arc::new(Mutex::new(AudioChannel::new(1)));
|
|
||||||
let audio_channel_2 = Arc::new(Mutex::new(AudioChannel::new(2)));
|
|
||||||
let audio_channel_3 = Arc::new(Mutex::new(AudioChannel::new(3)));
|
|
||||||
|
|
||||||
let (exception_sender, exception_receiver) = mpsc::channel::<Exception>();
|
|
||||||
|
|
||||||
let memory = Memory::new(read_rom().as_slice(), exception_sender);
|
|
||||||
let mut bus = Bus {
|
|
||||||
memory: memory.clone(),
|
|
||||||
audio_channel_0: audio_channel_0.clone(),
|
|
||||||
audio_channel_1: audio_channel_1.clone(),
|
|
||||||
audio_channel_2: audio_channel_2.clone(),
|
|
||||||
audio_channel_3: audio_channel_3.clone(),
|
|
||||||
disk_controller: DiskController::new(),
|
|
||||||
keyboard: keyboard.clone(),
|
|
||||||
mouse: mouse.clone(),
|
|
||||||
overlays: display.overlays.clone(),
|
|
||||||
startup_time: Local::now().timestamp_millis(),
|
|
||||||
};
|
|
||||||
|
|
||||||
if args.len() > 1 {
|
|
||||||
let mut args_iter = args.iter();
|
|
||||||
args_iter.next();
|
|
||||||
for (i, arg) in args_iter.enumerate() {
|
|
||||||
bus.disk_controller.insert(File::options().read(true).write(true).open(&arg).expect("failed to load provided disk image"), i as u8);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let memory_cpu = memory.clone();
|
|
||||||
let memory_eventloop = memory.clone();
|
|
||||||
|
|
||||||
let ram_size = memory_cpu.ram().len();
|
|
||||||
let ram_bottom_address = MEMORY_RAM_START;
|
|
||||||
let ram_top_address = ram_bottom_address + ram_size - 1;
|
|
||||||
println!("RAM: {:.2} MiB mapped at physical {:#010X}-{:#010X}", ram_size / 1048576, ram_bottom_address, ram_top_address);
|
|
||||||
|
|
||||||
let rom_size = memory_cpu.rom().len();
|
|
||||||
let rom_bottom_address = MEMORY_ROM_START;
|
|
||||||
let rom_top_address = rom_bottom_address + rom_size - 1;
|
|
||||||
println!("ROM: {:.2} KiB mapped at physical {:#010X}-{:#010X}", rom_size / 1024, rom_bottom_address, rom_top_address);
|
|
||||||
|
|
||||||
let mut cpu = Cpu::new(bus, debug_toggle_receiver);
|
|
||||||
|
|
||||||
let event_loop = EventLoop::new();
|
|
||||||
let mut input = WinitInputHelper::new();
|
|
||||||
let icon = image::load_from_memory(include_bytes!("32.png")).unwrap();
|
|
||||||
let window = {
|
|
||||||
let size = LogicalSize::new(WIDTH as f64, HEIGHT as f64);
|
|
||||||
WindowBuilder::new()
|
|
||||||
.with_title(version_string)
|
|
||||||
.with_inner_size(size)
|
|
||||||
.with_min_inner_size(size)
|
|
||||||
.with_window_icon(Some(Icon::from_rgba(icon.as_bytes().to_vec(), 128, 128).unwrap()))
|
|
||||||
.build(&event_loop)
|
|
||||||
.unwrap()
|
|
||||||
};
|
|
||||||
|
|
||||||
window.set_cursor_visible(false);
|
|
||||||
|
|
||||||
let mut pixels = {
|
|
||||||
let window_size = window.inner_size();
|
|
||||||
let surface_texture = SurfaceTexture::new(window_size.width, window_size.height, &window);
|
|
||||||
Pixels::new(WIDTH as u32, HEIGHT as u32, surface_texture).unwrap()
|
|
||||||
};
|
|
||||||
|
|
||||||
let (interrupt_sender, interrupt_receiver) = mpsc::channel::<Interrupt>();
|
|
||||||
let (exit_sender, exit_receiver) = mpsc::channel::<bool>();
|
|
||||||
|
|
||||||
AudioChannel::spawn_thread(audio_channel_0, interrupt_sender.clone(), memory.clone());
|
|
||||||
AudioChannel::spawn_thread(audio_channel_1, interrupt_sender.clone(), memory.clone());
|
|
||||||
AudioChannel::spawn_thread(audio_channel_2, interrupt_sender.clone(), memory.clone());
|
|
||||||
AudioChannel::spawn_thread(audio_channel_3, interrupt_sender.clone(), memory.clone());
|
|
||||||
|
|
||||||
let builder = thread::Builder::new().name("cpu".to_string());
|
|
||||||
builder.spawn({
|
|
||||||
move || {
|
|
||||||
loop {
|
|
||||||
while !cpu.halted {
|
|
||||||
if let Ok(exception) = exception_receiver.try_recv() {
|
|
||||||
(cpu.next_exception, cpu.next_exception_operand) = cpu.exception_to_vector(exception);
|
|
||||||
} else {
|
|
||||||
if let Ok(interrupt) = interrupt_receiver.try_recv() {
|
|
||||||
if let Interrupt::Request(vector) = interrupt {
|
|
||||||
cpu.next_interrupt = Some(vector);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
cpu.execute_memory_instruction();
|
|
||||||
if let Ok(_) = exit_receiver.try_recv() {
|
|
||||||
// the rest of the VM has exited, stop the CPU thread
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Ok(_) = exit_receiver.try_recv() {
|
|
||||||
// the rest of the VM has exited, stop the CPU thread
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if !cpu.flag.interrupt {
|
|
||||||
// the cpu was halted and interrupts are disabled
|
|
||||||
// at this point, the cpu is dead and cannot resume, break out of the loop
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if let Ok(interrupt) = interrupt_receiver.recv() {
|
|
||||||
if let Interrupt::Request(vector) = interrupt {
|
|
||||||
cpu.next_interrupt = Some(vector);
|
|
||||||
cpu.halted = false;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// sender is closed, break
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
println!("CPU halted");
|
|
||||||
}
|
|
||||||
}).unwrap();
|
|
||||||
|
|
||||||
event_loop.run(move |event, _, control_flow| {
|
|
||||||
*control_flow = ControlFlow::Poll;
|
|
||||||
|
|
||||||
// draw the current frame
|
|
||||||
if let Event::MainEventsCleared = event {
|
|
||||||
// update internal state and request a redraw
|
|
||||||
|
|
||||||
match interrupt_sender.send(Interrupt::Request(0xFF)) { // vsync interrupt
|
|
||||||
Ok(_) => {},
|
|
||||||
Err(_) => {
|
|
||||||
*control_flow = ControlFlow::Exit;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
display.update(memory_eventloop.clone().ram());
|
|
||||||
window.request_redraw();
|
|
||||||
|
|
||||||
display.draw(pixels.get_frame());
|
|
||||||
if pixels
|
|
||||||
.render()
|
|
||||||
.map_err(|e| error!("pixels.render() failed: {}", e))
|
|
||||||
.is_err()
|
|
||||||
{
|
|
||||||
*control_flow = ControlFlow::Exit;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// handle input events
|
|
||||||
if let Event::WindowEvent { ref event, .. } = event {
|
|
||||||
if let WindowEvent::KeyboardInput { input, .. } = event {
|
|
||||||
let mut keyboard_lock = keyboard.lock().unwrap();
|
|
||||||
let keycode = input.virtual_keycode;
|
|
||||||
keyboard_lock.push(keycode, input.state);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if input.update(&event) {
|
|
||||||
// close events
|
|
||||||
if input.quit() {
|
|
||||||
exit_sender.send(true).unwrap();
|
|
||||||
*control_flow = ControlFlow::Exit;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// resize the window
|
|
||||||
if let Some(size) = input.window_resized() {
|
|
||||||
pixels.resize_surface(size.width, size.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mouse_pixel = input.mouse().map(|(mx, my)| {
|
|
||||||
let (x, y) = pixels.window_pos_to_pixel((mx, my)).unwrap_or_else(|pos| pixels.clamp_pixel_pos(pos));
|
|
||||||
(x as u16, y as u16)
|
|
||||||
}).unwrap_or_default();
|
|
||||||
|
|
||||||
// TODO: allow right click
|
|
||||||
let mut mouse_lock = mouse.lock().expect("failed to lock the mouse mutex");
|
|
||||||
mouse_lock.x = mouse_pixel.0;
|
|
||||||
mouse_lock.y = mouse_pixel.1;
|
|
||||||
if mouse_lock.held && !input.mouse_held(0) {
|
|
||||||
// mouse button was released this frame
|
|
||||||
mouse_lock.released = true;
|
|
||||||
}
|
|
||||||
mouse_lock.held = input.mouse_held(0);
|
|
||||||
if input.mouse_pressed(0) {
|
|
||||||
mouse_lock.clicked = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Display {
|
|
||||||
fn new() -> Self {
|
|
||||||
Self {
|
|
||||||
background: vec![0; (HEIGHT*WIDTH*4) as usize],
|
|
||||||
overlays: Arc::new(Mutex::new(vec![Overlay { enabled: false, width: 16, height: 16, x: 0, y: 0, framebuffer_pointer: 0 }; 32])),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn update(&mut self, ram: &MemoryRam) {
|
|
||||||
let overlay_lock = self.overlays.lock().unwrap();
|
|
||||||
|
|
||||||
for i in 0..(HEIGHT*WIDTH*4) as usize {
|
|
||||||
self.background[i] = ram[FRAMEBUFFER_ADDRESS + i];
|
|
||||||
}
|
|
||||||
|
|
||||||
for index in 0..=31 {
|
|
||||||
if overlay_lock[index].enabled {
|
|
||||||
blit_overlay(&mut self.background, &overlay_lock[index], ram);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn draw(&self, frame: &mut [u8]) {
|
|
||||||
for (i, pixel) in frame.chunks_exact_mut(4).enumerate() {
|
|
||||||
//let x = (i % WIDTH as usize) as i16;
|
|
||||||
//let y = (i / WIDTH as usize) as i16;
|
|
||||||
|
|
||||||
let i = i * 4;
|
|
||||||
|
|
||||||
let slice = &self.background[i..i+4];
|
|
||||||
pixel.copy_from_slice(slice);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// modified from https://github.com/parasyte/pixels/blob/main/examples/invaders/simple-invaders/src/sprites.rs
|
|
||||||
fn blit_overlay(framebuffer: &mut [u8], overlay: &Overlay, ram: &[u8]) {
|
|
||||||
//assert!(overlay.x + overlay.width <= WIDTH);
|
|
||||||
//assert!(overlay.y + overlay.height <= HEIGHT);
|
|
||||||
|
|
||||||
let mut width = overlay.width * 4;
|
|
||||||
let mut height = overlay.height;
|
|
||||||
|
|
||||||
// FIXME: this is a hack, and it only allows overlays to go off-screen on the bottom and right sides
|
|
||||||
// it also completely fucks up the image on the right side :p
|
|
||||||
if overlay.x + overlay.width > WIDTH {
|
|
||||||
let difference = (overlay.x + overlay.width) - WIDTH;
|
|
||||||
width = width - (difference * 4);
|
|
||||||
//println!("width: {}, difference: {}", width, difference);
|
|
||||||
}
|
|
||||||
if overlay.y + overlay.height > HEIGHT {
|
|
||||||
let difference = (overlay.y + overlay.height) - HEIGHT;
|
|
||||||
height = height - difference;
|
|
||||||
//println!("height: {}, difference: {}", height, difference);
|
|
||||||
}
|
|
||||||
|
|
||||||
let overlay_framebuffer = &ram[(overlay.framebuffer_pointer as usize)..((overlay.framebuffer_pointer+((width as u32)*(height as u32))) as usize)];
|
|
||||||
|
|
||||||
let mut overlay_framebuffer_index = 0;
|
|
||||||
for y in 0..height {
|
|
||||||
let index = overlay.x * 4 + overlay.y * WIDTH * 4 + y * WIDTH * 4;
|
|
||||||
// merge overlay onto screen
|
|
||||||
// this is such a dumb hack
|
|
||||||
let mut zipped = framebuffer[index..index + width].iter_mut().zip(&overlay_framebuffer[overlay_framebuffer_index..overlay_framebuffer_index + width]);
|
|
||||||
while let Some((left, &right)) = zipped.next() {
|
|
||||||
let (left_0, &right_0) = (left, &right);
|
|
||||||
let (left_1, &right_1) = zipped.next().unwrap();
|
|
||||||
let (left_2, &right_2) = zipped.next().unwrap();
|
|
||||||
let (left_3, &right_3) = zipped.next().unwrap();
|
|
||||||
// ensure that the alpha byte is greater than zero, meaning that this pixel shouldn't be transparent
|
|
||||||
if right_3 > 0 {
|
|
||||||
*left_0 = right_0;
|
|
||||||
*left_1 = right_1;
|
|
||||||
*left_2 = right_2;
|
|
||||||
*left_3 = right_3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
overlay_framebuffer_index += width;
|
|
||||||
}
|
|
||||||
}
|
|
303
src/memory.rs
|
@ -1,303 +0,0 @@
|
||||||
// memory.rs
|
|
||||||
|
|
||||||
use crate::error;
|
|
||||||
use crate::cpu::Exception;
|
|
||||||
|
|
||||||
use std::cell::UnsafeCell;
|
|
||||||
use std::collections::HashMap;
|
|
||||||
use std::sync::Arc;
|
|
||||||
use std::io::Write;
|
|
||||||
use std::fs::File;
|
|
||||||
use std::sync::mpsc::Sender;
|
|
||||||
|
|
||||||
pub const MEMORY_RAM_SIZE: usize = 0x04000000; // 64 MiB
|
|
||||||
pub const MEMORY_ROM_SIZE: usize = 0x00080000; // 512 KiB
|
|
||||||
|
|
||||||
pub const MEMORY_RAM_START: usize = 0x00000000;
|
|
||||||
pub const MEMORY_ROM_START: usize = 0xF0000000;
|
|
||||||
|
|
||||||
pub type MemoryRam = [u8; MEMORY_RAM_SIZE];
|
|
||||||
pub type MemoryRom = [u8; MEMORY_ROM_SIZE];
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
|
||||||
pub struct MemoryPage {
|
|
||||||
physical_address: u32,
|
|
||||||
present: bool,
|
|
||||||
rw: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
struct MemoryInner {
|
|
||||||
ram: Box<MemoryRam>,
|
|
||||||
rom: Box<MemoryRom>,
|
|
||||||
mmu_enabled: Box<bool>,
|
|
||||||
tlb: Box<HashMap<u32, MemoryPage>>,
|
|
||||||
paging_directory_address: Box<u32>,
|
|
||||||
exception_sender: Sender<Exception>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl MemoryInner {
|
|
||||||
pub fn new(rom: &[u8], exception_sender: Sender<Exception>) -> Self {
|
|
||||||
let mut this = Self {
|
|
||||||
// HACK: allocate directly on the heap to avoid a stack overflow
|
|
||||||
// at runtime while trying to move around a 64MB array
|
|
||||||
ram: unsafe { Box::from_raw(Box::into_raw(vec![0u8; MEMORY_RAM_SIZE].into_boxed_slice()) as *mut MemoryRam) },
|
|
||||||
rom: unsafe { Box::from_raw(Box::into_raw(vec![0u8; MEMORY_ROM_SIZE].into_boxed_slice()) as *mut MemoryRom) },
|
|
||||||
mmu_enabled: Box::from(false),
|
|
||||||
tlb: Box::from(HashMap::with_capacity(1024)),
|
|
||||||
paging_directory_address: Box::from(0x00000000),
|
|
||||||
exception_sender,
|
|
||||||
};
|
|
||||||
this.rom.as_mut_slice().write(rom).expect("failed to copy ROM to memory");
|
|
||||||
this
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct Memory(Arc<UnsafeCell<MemoryInner>>);
|
|
||||||
|
|
||||||
// SAFETY: once MemoryInner is initialzed, there is no way to modify the Box
|
|
||||||
// pointers it contains and it does not matter if contents of the byte
|
|
||||||
// arrays are corrupted
|
|
||||||
unsafe impl Send for Memory {}
|
|
||||||
unsafe impl Sync for Memory {}
|
|
||||||
|
|
||||||
impl Memory {
|
|
||||||
pub fn new(rom: &[u8], exception_sender: Sender<Exception>) -> Self {
|
|
||||||
Self(Arc::new(UnsafeCell::new(MemoryInner::new(rom, exception_sender))))
|
|
||||||
}
|
|
||||||
|
|
||||||
fn inner(&self) -> &mut MemoryInner {
|
|
||||||
unsafe { &mut *self.0.get() }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn ram(&self) -> &mut MemoryRam { &mut self.inner().ram }
|
|
||||||
pub fn rom(&self) -> &mut MemoryRom { &mut self.inner().rom }
|
|
||||||
pub fn mmu_enabled(&self) -> &mut bool { &mut self.inner().mmu_enabled }
|
|
||||||
pub fn tlb(&self) -> &mut HashMap<u32, MemoryPage> { &mut self.inner().tlb }
|
|
||||||
pub fn paging_directory_address(&self) -> &mut u32 { &mut self.inner().paging_directory_address }
|
|
||||||
pub fn exception_sender(&self) -> &mut Sender<Exception> { &mut self.inner().exception_sender }
|
|
||||||
|
|
||||||
pub fn dump(&self) {
|
|
||||||
let mut file = File::create("memory.dump").expect("failed to open memory dump file");
|
|
||||||
file.write_all(self.ram()).expect("failed to write memory dump file");
|
|
||||||
}
|
|
||||||
|
|
||||||
// each table contains 1024 entries
|
|
||||||
// the paging directory contains pointers to paging tables with the following format:
|
|
||||||
// bit 0: present
|
|
||||||
// remaining bits are ignored, should be zero
|
|
||||||
// bits 12-31: physical address of paging table
|
|
||||||
|
|
||||||
// the paging table contains pointers to physical memory pages with the following format:
|
|
||||||
// bit 0: present
|
|
||||||
// bit 1: r/w
|
|
||||||
// remaining bits are ignored, should be zero
|
|
||||||
// bits 12-31: physical address
|
|
||||||
|
|
||||||
pub fn flush_tlb(&self, paging_directory_address: Option<u32>) {
|
|
||||||
if let Some(address) = paging_directory_address {
|
|
||||||
*self.paging_directory_address() = address;
|
|
||||||
};
|
|
||||||
|
|
||||||
self.tlb().clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn flush_page(&self, virtual_address: u32) {
|
|
||||||
let virtual_page = virtual_address & 0xFFFFF000;
|
|
||||||
self.tlb().remove(&virtual_page);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn insert_tlb_entry_from_tables(&mut self, page_directory_index: u32, page_table_index: u32) -> bool {
|
|
||||||
let old_state = *self.mmu_enabled();
|
|
||||||
*self.mmu_enabled() = false;
|
|
||||||
let directory_address = *self.paging_directory_address();
|
|
||||||
let directory = self.read_opt_32(directory_address + (page_directory_index * 4));
|
|
||||||
match directory {
|
|
||||||
Some(directory) => {
|
|
||||||
let dir_present = directory & 0b1 != 0;
|
|
||||||
let dir_address = directory & 0xFFFFF000;
|
|
||||||
if dir_present {
|
|
||||||
let table = self.read_opt_32(dir_address + (page_table_index * 4));
|
|
||||||
match table {
|
|
||||||
Some(table) => {
|
|
||||||
let table_present = table & 0b01 != 0;
|
|
||||||
let table_rw = table & 0b10 != 0;
|
|
||||||
let table_address = table & 0xFFFFF000;
|
|
||||||
|
|
||||||
if table_present {
|
|
||||||
let tlb_entry = MemoryPage {
|
|
||||||
physical_address: table_address,
|
|
||||||
present: table_present,
|
|
||||||
rw: table_rw,
|
|
||||||
};
|
|
||||||
self.tlb().entry((page_directory_index << 22) | (page_table_index << 12)).or_insert(tlb_entry);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*self.mmu_enabled() = old_state;
|
|
||||||
dir_present
|
|
||||||
},
|
|
||||||
None => {
|
|
||||||
*self.mmu_enabled() = old_state;
|
|
||||||
false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn virtual_to_physical(&mut self, virtual_address: u32) -> Option<(u32, bool)> {
|
|
||||||
let virtual_page = virtual_address & 0xFFFFF000;
|
|
||||||
let offset = virtual_address & 0x00000FFF;
|
|
||||||
let physical_page = self.tlb().get(&virtual_page);
|
|
||||||
let physical_address = match physical_page {
|
|
||||||
Some(page) => {
|
|
||||||
if page.present {
|
|
||||||
Some((page.physical_address | offset, page.rw))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => {
|
|
||||||
let page_directory_index = virtual_address >> 22;
|
|
||||||
let page_table_index = (virtual_address >> 12) & 0x03FF;
|
|
||||||
let dir_present = self.insert_tlb_entry_from_tables(page_directory_index, page_table_index);
|
|
||||||
if !dir_present {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
// try again after inserting the TLB entry
|
|
||||||
let physical_page = self.tlb().get(&virtual_page);
|
|
||||||
let physical_address = match physical_page {
|
|
||||||
Some(page) => {
|
|
||||||
if page.present {
|
|
||||||
Some((page.physical_address | offset, page.rw))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
},
|
|
||||||
None => None,
|
|
||||||
};
|
|
||||||
physical_address
|
|
||||||
},
|
|
||||||
};
|
|
||||||
physical_address
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn read_opt_8(&mut self, mut address: u32) -> Option<u8> {
|
|
||||||
if *self.mmu_enabled() {
|
|
||||||
let address_maybe = self.virtual_to_physical(address as u32);
|
|
||||||
match address_maybe {
|
|
||||||
Some(addr) => address = addr.0,
|
|
||||||
None => return None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let address = address as usize;
|
|
||||||
|
|
||||||
if address >= MEMORY_ROM_START && address < MEMORY_ROM_START + MEMORY_ROM_SIZE {
|
|
||||||
self.rom().get(address - MEMORY_ROM_START).map(|value| *value)
|
|
||||||
} else {
|
|
||||||
self.ram().get(address - MEMORY_RAM_START).map(|value| *value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn read_opt_16(&mut self, address: u32) -> Option<u16> {
|
|
||||||
Some(self.read_opt_8(address)? as u16 |
|
|
||||||
(self.read_opt_8(address + 1)? as u16) << 8
|
|
||||||
)
|
|
||||||
}
|
|
||||||
pub fn read_opt_32(&mut self, address: u32) -> Option<u32> {
|
|
||||||
Some(self.read_opt_8(address)? as u32 |
|
|
||||||
(self.read_opt_8(address + 1)? as u32) << 8 |
|
|
||||||
(self.read_opt_8(address + 2)? as u32) << 16 |
|
|
||||||
(self.read_opt_8(address + 3)? as u32) << 24
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn read_8(&mut self, address: u32) -> Option<u8> {
|
|
||||||
let mut read_ok = true;
|
|
||||||
let value = self.read_opt_8(address).unwrap_or_else(|| { read_ok = false; 0 });
|
|
||||||
if read_ok {
|
|
||||||
Some(value)
|
|
||||||
} else {
|
|
||||||
self.exception_sender().send(Exception::PageFaultRead(address)).unwrap();
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn read_16(&mut self, address: u32) -> Option<u16> {
|
|
||||||
Some(self.read_8(address)? as u16 |
|
|
||||||
(self.read_8(address + 1)? as u16) << 8
|
|
||||||
)
|
|
||||||
}
|
|
||||||
pub fn read_32(&mut self, address: u32) -> Option<u32> {
|
|
||||||
Some(self.read_8(address)? as u32 |
|
|
||||||
(self.read_8(address + 1)? as u32) << 8 |
|
|
||||||
(self.read_8(address + 2)? as u32) << 16 |
|
|
||||||
(self.read_8(address + 3)? as u32) << 24
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn write_8(&mut self, mut address: u32, byte: u8) -> Option<()> {
|
|
||||||
let original_address = address;
|
|
||||||
let mut writable = true;
|
|
||||||
if *self.mmu_enabled() {
|
|
||||||
(address, writable) = self.virtual_to_physical(address as u32).unwrap_or_else(|| {
|
|
||||||
(0, false)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if writable {
|
|
||||||
let address = address as usize;
|
|
||||||
|
|
||||||
if address >= MEMORY_ROM_START && address < MEMORY_ROM_START + MEMORY_ROM_SIZE {
|
|
||||||
error(&format!("attempting to write to ROM address: {:#010X}", address));
|
|
||||||
}
|
|
||||||
|
|
||||||
match self.ram().get_mut(address - MEMORY_RAM_START) {
|
|
||||||
Some(value) => {
|
|
||||||
*value = byte;
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
self.exception_sender().send(Exception::PageFaultWrite(original_address)).unwrap();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some(())
|
|
||||||
} else {
|
|
||||||
self.exception_sender().send(Exception::PageFaultWrite(original_address)).unwrap();
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pub fn write_16(&mut self, address: u32, half: u16) -> Option<()> {
|
|
||||||
// first check if we can write to all addresses without faulting
|
|
||||||
if *self.mmu_enabled() {
|
|
||||||
let (_, writable_0) = self.virtual_to_physical(address).unwrap_or_else(|| (0, false));
|
|
||||||
let (_, writable_1) = self.virtual_to_physical(address + 1).unwrap_or_else(|| (0, false));
|
|
||||||
if !writable_0 { self.exception_sender().send(Exception::PageFaultWrite(address)).unwrap(); return None }
|
|
||||||
if !writable_1 { self.exception_sender().send(Exception::PageFaultWrite(address + 1)).unwrap(); return None }
|
|
||||||
}
|
|
||||||
|
|
||||||
// then do the actual writes
|
|
||||||
self.write_8(address, (half & 0x00FF) as u8)?;
|
|
||||||
self.write_8(address + 1, (half >> 8) as u8)?;
|
|
||||||
Some(())
|
|
||||||
}
|
|
||||||
pub fn write_32(&mut self, address: u32, word: u32) -> Option<()> {
|
|
||||||
// first check if we can write to all addresses without faulting
|
|
||||||
if *self.mmu_enabled() {
|
|
||||||
let (_, writable_0) = self.virtual_to_physical(address).unwrap_or_else(|| (0, false));
|
|
||||||
let (_, writable_1) = self.virtual_to_physical(address + 1).unwrap_or_else(|| (0, false));
|
|
||||||
let (_, writable_2) = self.virtual_to_physical(address + 2).unwrap_or_else(|| (0, false));
|
|
||||||
let (_, writable_3) = self.virtual_to_physical(address + 3).unwrap_or_else(|| (0, false));
|
|
||||||
if !writable_0 { self.exception_sender().send(Exception::PageFaultWrite(address)).unwrap(); return None }
|
|
||||||
if !writable_1 { self.exception_sender().send(Exception::PageFaultWrite(address + 1)).unwrap(); return None }
|
|
||||||
if !writable_2 { self.exception_sender().send(Exception::PageFaultWrite(address + 2)).unwrap(); return None }
|
|
||||||
if !writable_3 { self.exception_sender().send(Exception::PageFaultWrite(address + 3)).unwrap(); return None }
|
|
||||||
}
|
|
||||||
|
|
||||||
// then do the actual writes
|
|
||||||
self.write_8(address, (word & 0x000000FF) as u8)?;
|
|
||||||
self.write_8(address + 1, ((word & 0x0000FF00) >> 8) as u8)?;
|
|
||||||
self.write_8(address + 2, ((word & 0x00FF0000) >> 16) as u8)?;
|
|
||||||
self.write_8(address + 3, ((word & 0xFF000000) >> 24) as u8)?;
|
|
||||||
Some(())
|
|
||||||
}
|
|
||||||
}
|
|
15
src/mouse.rs
|
@ -1,15 +0,0 @@
|
||||||
// mouse.rs
|
|
||||||
|
|
||||||
pub struct Mouse {
|
|
||||||
pub x: u16,
|
|
||||||
pub y: u16,
|
|
||||||
pub clicked: bool,
|
|
||||||
pub released: bool,
|
|
||||||
pub held: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Mouse {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Mouse { x: 0, y: 0, clicked: false, released: false, held: false }
|
|
||||||
}
|
|
||||||
}
|
|