Compare commits
No commits in common. "main" and "sasm-linker" have entirely different histories.
main
...
sasm-linke
87 changed files with 589 additions and 6965 deletions
6
.gitignore
vendored
6
.gitignore
vendored
|
|
@ -5,7 +5,6 @@ tests/*.s
|
||||||
examples/*.s
|
examples/*.s
|
||||||
!runtime.s
|
!runtime.s
|
||||||
!stdlibwrap.s
|
!stdlibwrap.s
|
||||||
!sprites.s
|
|
||||||
*.o
|
*.o
|
||||||
*.exe
|
*.exe
|
||||||
*.bin
|
*.bin
|
||||||
|
|
@ -26,7 +25,6 @@ graph1.pas
|
||||||
graph2.pas
|
graph2.pas
|
||||||
chase.pas
|
chase.pas
|
||||||
pcomp/libgen
|
pcomp/libgen
|
||||||
pcomp/shortgen
|
|
||||||
pcomp/lsymgen
|
pcomp/lsymgen
|
||||||
pcomp/pcomp
|
pcomp/pcomp
|
||||||
pcomp/sasm
|
pcomp/sasm
|
||||||
|
|
@ -34,18 +32,16 @@ pcomp/sdis
|
||||||
tridoraemu/tridoraemu
|
tridoraemu/tridoraemu
|
||||||
**/tridoracpu.cache/
|
**/tridoracpu.cache/
|
||||||
**/tridoracpu.hw/
|
**/tridoracpu.hw/
|
||||||
**/tridoracpu.gen/
|
|
||||||
**/tridoracpu.ip_user_files/
|
**/tridoracpu.ip_user_files/
|
||||||
**/tridoracpu.runs/
|
**/tridoracpu.runs/
|
||||||
*.log
|
*.log
|
||||||
*.jou
|
*.jou
|
||||||
**/mig_dram_0/_tmp/*
|
**/mig_dram_0/_tmp/*
|
||||||
**/mig_dram_0/mig_dram_0/*
|
|
||||||
**/mig_dram_0/doc/*
|
**/mig_dram_0/doc/*
|
||||||
|
**/mig_dram_0/mig_dram_0*
|
||||||
**/mig_dram_0/xil_txt.*
|
**/mig_dram_0/xil_txt.*
|
||||||
**/mig_dram_0/*.veo
|
**/mig_dram_0/*.veo
|
||||||
**/mig_dram_0/*.tcl
|
**/mig_dram_0/*.tcl
|
||||||
**/mig_dram_0/*.xml
|
**/mig_dram_0/*.xml
|
||||||
**/mig_dram_0/*.v
|
**/mig_dram_0/*.v
|
||||||
**/mig_dram_0/*.vhdl
|
**/mig_dram_0/*.vhdl
|
||||||
**/mig_dram_0/*.dcp
|
|
||||||
|
|
|
||||||
3
.gitmodules
vendored
3
.gitmodules
vendored
|
|
@ -1,3 +0,0 @@
|
||||||
[submodule "rogue"]
|
|
||||||
path = rogue
|
|
||||||
url = https://gitlab.com/slederer/ecl-rogue-m.git
|
|
||||||
|
|
@ -4,7 +4,7 @@ All files, except where explicitly stated otherwise, are licensed according to t
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
Copyright 2024-2026 Sebastian Lederer
|
Copyright 2024 Sebastian Lederer
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
|
|
||||||
69
README.md
69
README.md
|
|
@ -1,5 +1,5 @@
|
||||||
# Tridora-CPU
|
# Tridora System
|
||||||
The Tridora-CPU is a homebrew CPU written in Verilog and a matching software environment,
|
Tridora is a homebrew CPU written in Verilog and a matching software environment,
|
||||||
including a Pascal compiler and assembler.
|
including a Pascal compiler and assembler.
|
||||||
Everything was created from the ground up (except soldering stuff).
|
Everything was created from the ground up (except soldering stuff).
|
||||||
Everything is as simple as possible while still being reasonably useful.
|
Everything is as simple as possible while still being reasonably useful.
|
||||||
|
|
@ -8,7 +8,7 @@ Everything is open source, so you can read, understand and modify the whole syst
|
||||||
## Overview
|
## Overview
|
||||||
- homebrew CPU written in Verilog implemented on an FPGA
|
- homebrew CPU written in Verilog implemented on an FPGA
|
||||||
- 32-bit word-oriented stack machine architecture
|
- 32-bit word-oriented stack machine architecture
|
||||||
- running at 77 MHz on an Arty-A7 board with four clocks per instruction
|
- running at 83 MHz on an Arty-A7 board with four clocks per instruction
|
||||||
- has its own instruction set architecture, compatible with nothing
|
- has its own instruction set architecture, compatible with nothing
|
||||||
- additional IO controllers on FPGA: UART (serial console), SD-Card, VGA
|
- additional IO controllers on FPGA: UART (serial console), SD-Card, VGA
|
||||||
- Pascal compiler written from zero
|
- Pascal compiler written from zero
|
||||||
|
|
@ -30,59 +30,13 @@ has a strange mixture of features from three different eras of computing:
|
||||||
- speed is like a fast 16-bit CPU, also 16-bit instruction words
|
- speed is like a fast 16-bit CPU, also 16-bit instruction words
|
||||||
- 32-bit word size from the 32-bit era
|
- 32-bit word size from the 32-bit era
|
||||||
|
|
||||||
It might remind you of the UCSD-P-System and early Turbo-Pascal versions.
|
|
||||||
|
|
||||||
Other inspirations were, among others, in no particular order:
|
|
||||||
|
|
||||||
- the Novix 4016 CPU (a stack machine CPU designed for Forth, mainly by Charles Moore)
|
|
||||||
- the J1 CPU by James Bowman (which is not entirely unlike the Novix 4016)
|
|
||||||
- the Lilith computer by Niklaus Wirth and his team (a stack CPU designed for Modula-2)
|
|
||||||
- the PERQ workstation (also a stack CPU designed for Pascal)
|
|
||||||
- the Magic-1 by Bill Buzbee
|
|
||||||
- the OPC by revaldinho
|
|
||||||
|
|
||||||
## October 2025 Update
|
|
||||||
This update introduces a data cache for the Tridora-CPU. It is similar to the instruction cache
|
|
||||||
as it caches the 16 bytes coming from the DRAM memory controller. It is a write-back cache, i.e.
|
|
||||||
when a word inside the cached area is written, it updates the cache instead of invalidating it.
|
|
||||||
|
|
||||||
This is important because there are many idioms in the stack machine assembly language where you
|
|
||||||
store a local variable and then read it again (e.g. updating a loop variable).
|
|
||||||
|
|
||||||
Since for most programs, the user stack and parts of the heap are inside the DRAM area, the data cache
|
|
||||||
has a more noticable impact. In the benchmark program that was already used for the last update,
|
|
||||||
the data cache results in a 50% improvement for the empty loop test. This is in comparison to the version
|
|
||||||
without data cache but with the instruction cache, both running code out of DRAM.
|
|
||||||
|
|
||||||
It is also noticable for compile times: With the data cache, compiling and assembling the
|
|
||||||
"hello,world" program takes 16 seconds instead of 20. With a little tweak of the SD-Card controller
|
|
||||||
that slightly increased the data transfer rate, the build time goes down to 15 seconds.
|
|
||||||
|
|
||||||
Also, an audio controller was added that allows interrupt-driven sample playback via an AMP2 PMOD.
|
|
||||||
|
|
||||||
## April 2025 Update
|
|
||||||
The clock has been reduced to 77 MHz from 83 MHz. Apparently the design was at the limit and
|
|
||||||
timing problems were cropping up seemingly at random. Reducing the clock speed made some
|
|
||||||
enhancements and bugfixes possible. Also, the project files work with Vivado 2024 now.
|
|
||||||
|
|
||||||
Most importantly, the Tridora-CPU now has an instruction cache with a size of 16 bytes or eight instructions.
|
|
||||||
This increases execution speed when running code out of DRAM (that is, above 64KB). In a simple
|
|
||||||
benchmark program, the CPU is about twice as fast.
|
|
||||||
Many programs fit into the lower 64KB of RAM, which can be accessed without latency, and will
|
|
||||||
have no noticable speed increase.
|
|
||||||
|
|
||||||
There have also been a number of bug fixes for the compiler and some for the assembler. This makes
|
|
||||||
compiling even larger and more complex programs possible. An example of this is ECL-Rogue, a variant of Rogue written
|
|
||||||
Pascal, which has been ported to Tridora-Pascal and is now included
|
|
||||||
on the emulator image.
|
|
||||||
|
|
||||||
## Links/Downloads
|
## Links/Downloads
|
||||||
- the [source repository](https://gitlab.com/slederer/Tridora-CPU)
|
- the [source repository](https://gitlab.com/slederer/Tridora-CPU)
|
||||||
- the [Hackaday project](https://hackaday.io/project/198324-tridora-cpu) (mostly copy-paste from this README)
|
- the [Hackaday project](https://hackaday.io/project/198324-tridora-cpu) (mostly copy-paste from this README)
|
||||||
- the [YouTube channel](https://www.youtube.com/@tridoracpu/videos) with some demo videos
|
- the [YouTube channel](https://www.youtube.com/@tridoracpu/videos) with some demo videos
|
||||||
- the [emulator](https://git.insignificance.de/slederer/-/packages/generic/tridoraemu/0.0.5/files/12) (source and windows binary)
|
- the [emulator](https://git.insignificance.de/slederer/-/packages/generic/tridoraemu/0.0.2/files/8) (source and windows binary)
|
||||||
- the [FPGA bitstream](https://git.insignificance.de/slederer/-/packages/generic/tdr-bitstream/0.0.4/files/16) for the Arty-A7-35T board
|
- the [FPGA bitstream](https://git.insignificance.de/slederer/-/packages/generic/tdr-bitstream/0.0.1/files/3) for the Arty-A7-35T board
|
||||||
- an [SD-card image](https://git.insignificance.de/slederer/-/packages/generic/tdr-cardimage/0.0.4/files/13)
|
- an [SD-card image](https://git.insignificance.de/slederer/-/packages/generic/tdr-cardimage/0.0.2/files/7)
|
||||||
|
|
||||||
Contact the author here: tridoracpu [at] insignificance.de
|
Contact the author here: tridoracpu [at] insignificance.de
|
||||||
|
|
||||||
|
|
@ -113,7 +67,7 @@ Two Pmods are used for a complete system:
|
||||||
As the Arty-A7-35T is no longer in production, it should be easy to
|
As the Arty-A7-35T is no longer in production, it should be easy to
|
||||||
use the Arty-A7-100T instead, but this has not been tested yet.
|
use the Arty-A7-100T instead, but this has not been tested yet.
|
||||||
|
|
||||||
Other boards under consideration are the Digilent Nexys-A7 and the Arty-S7.
|
Other boards under consideration are the Digilent Nexys-A7 and the Olimex GateMateA1-EVB.
|
||||||
|
|
||||||
## Pascal Language
|
## Pascal Language
|
||||||
- Wirth Pascal
|
- Wirth Pascal
|
||||||
|
|
@ -122,7 +76,7 @@ Other boards under consideration are the Digilent Nexys-A7 and the Arty-S7.
|
||||||
- safe strings (runtime information about max/current size)
|
- safe strings (runtime information about max/current size)
|
||||||
- tiny sets (machine word sized), that means no SET OF CHAR
|
- tiny sets (machine word sized), that means no SET OF CHAR
|
||||||
- array literals with IN-operator, which can replace most uses of SET OF CHAR
|
- array literals with IN-operator, which can replace most uses of SET OF CHAR
|
||||||
- nested procedures
|
- nested procedures with some limitations
|
||||||
- 32 bit software floating point with low precision (5-6 digits)
|
- 32 bit software floating point with low precision (5-6 digits)
|
||||||
- break and exit statements, no continue yet
|
- break and exit statements, no continue yet
|
||||||
- static variable initialization for global variables
|
- static variable initialization for global variables
|
||||||
|
|
@ -153,7 +107,7 @@ Other boards under consideration are the Digilent Nexys-A7 and the Arty-S7.
|
||||||
- for **rom.mem** and **rommon.prog**, find both files in the **lib** directory after running **make nativeprogs** (or **make.bat**) in the **pcomp** directory (see above)
|
- for **rom.mem** and **rommon.prog**, find both files in the **lib** directory after running **make nativeprogs** (or **make.bat**) in the **pcomp** directory (see above)
|
||||||
|
|
||||||
## Building the FPGA bitstream
|
## Building the FPGA bitstream
|
||||||
- install Vivado (April-2025-Update tested with 2024.2)
|
- install Vivado (known to work with 2020.1, known NOT to work with 2024.1)
|
||||||
- install the package for your board in Vivado (Tools -> Vivado Store -> Boards)
|
- install the package for your board in Vivado (Tools -> Vivado Store -> Boards)
|
||||||
- copy the ROM image (**rom.mem**) into the **tridoracpu** directory (see above)
|
- copy the ROM image (**rom.mem**) into the **tridoracpu** directory (see above)
|
||||||
- start Vivado and open the project file **tridoracpu.xpr** in the **tridoracpu** directory
|
- start Vivado and open the project file **tridoracpu.xpr** in the **tridoracpu** directory
|
||||||
|
|
@ -174,8 +128,3 @@ See the emulator [README](tridoraemu/README.md).
|
||||||
- [The Mostly Missing Pascal Programming Guide](doc/pascalprogramming.md)
|
- [The Mostly Missing Pascal Programming Guide](doc/pascalprogramming.md)
|
||||||
|
|
||||||
More documentation is coming, as time permits.
|
More documentation is coming, as time permits.
|
||||||
|
|
||||||
## Credits
|
|
||||||
The Tridora-CPU uses the UART from the J1 CPU by James Bowman (*uart.v*), see https://github.com/jamesbowman/j1
|
|
||||||
|
|
||||||
The VGA framebuffer uses code from Project F by Will Green, see https://projectf.io
|
|
||||||
|
|
|
||||||
|
|
@ -9,13 +9,12 @@ The interrupt controller uses a single register at address: $980
|
||||||
|
|
||||||
|_bit_ |15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
|
|_bit_ |15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
|
||||||
|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
|
|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
|
||||||
|_Value_|t |t |t |t |t |t |t |t |- |- |- |- |- |p2 |p1 |p0 |
|
|_Value_|t |t |t |t |t |t |t |t |- |- |- |- |- |- |p1 |p0 |
|
||||||
|
|
||||||
|
|
||||||
|Bitfields|Description|
|
|Bitfields|Description|
|
||||||
|---------|-----------|
|
|---------|-----------|
|
||||||
| _t_ | unsigned 24 bit counter of timer ticks since reset
|
| _t_ | unsigned 24 bit counter of timer ticks since reset
|
||||||
| _p2_ | IRQ 2 (audio) interrupt pending if 1
|
|
||||||
| _p1_ | IRQ 1 (timer tick) interrupt pending if 1
|
| _p1_ | IRQ 1 (timer tick) interrupt pending if 1
|
||||||
| _p0_ | IRQ 0 (UART) interrupt pending if 1
|
| _p0_ | IRQ 0 (UART) interrupt pending if 1
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,12 +22,11 @@ The _BSEL_ and _BPLC_ instructions are designed to assist with accessing bytes w
|
||||||
The byte ordering is big-endian.
|
The byte ordering is big-endian.
|
||||||
|
|
||||||
## Accessing the I/O Area
|
## Accessing the I/O Area
|
||||||
The I/O area uses the same word addressing in increments of four to access the registers of the I/O controllers. In practice, only the VGA framebuffer controller and the audio controller use multiple registers.
|
The I/O area organizes memory slightly different. Here, pointing out individual bytes is not very useful, so the I/O controllers use register addresses with increments of one. In practice, there is only the VGA framebuffer controller which uses multiple registers.
|
||||||
For the other controllers, there is a single 32 bit register that is repeated all over the address space of the corresponding I/O slot.
|
|
||||||
|
|
||||||
The individual I/O controllers each have a memory area of 128 bytes, so there is a maximum number of 16 I/O controllers.
|
The individual I/O controllers each have a memory area of 128 bytes, so there is a maximum number of 16 I/O controllers.
|
||||||
|
|
||||||
Currently, only I/O slots 0-4 are being used.
|
Currently, only I/O slots 0-3 are being used.
|
||||||
|
|
||||||
|I/O slot| Address | Controller |
|
|I/O slot| Address | Controller |
|
||||||
|--------|---------|------------|
|
|--------|---------|------------|
|
||||||
|
|
@ -35,4 +34,3 @@ Currently, only I/O slots 0-4 are being used.
|
||||||
| 1 | $880 | SPI-SD |
|
| 1 | $880 | SPI-SD |
|
||||||
| 2 | $900 | VGA |
|
| 2 | $900 | VGA |
|
||||||
| 3 | $980 | IRQC |
|
| 3 | $980 | IRQC |
|
||||||
| 4 | $A00 | TDRAUDIO |
|
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,7 @@ var a:array [1..3] of integer;
|
||||||
|
|
||||||
...
|
...
|
||||||
|
|
||||||
a[1] := 3; a[2] := 2; a[3] := 1;
|
a[1] := 3; a[3] := 2; a[5] := 1;
|
||||||
|
|
||||||
for i in a do
|
for i in a do
|
||||||
writeln(i);
|
writeln(i);
|
||||||
|
|
@ -66,7 +66,7 @@ var c:char;
|
||||||
```
|
```
|
||||||
|
|
||||||
In Tridora Pascal, this syntax also works because `[ 'y', 'n' ]` will not be treated as a set literal, but as an array literal.
|
In Tridora Pascal, this syntax also works because `[ 'y', 'n' ]` will not be treated as a set literal, but as an array literal.
|
||||||
The _in_ operator also works for linear arrays, so the above _if_ statement will have the same result.
|
The _in_ operator also works for linear arrays, so the _if_ statement will have the same result.
|
||||||
|
|
||||||
Note that the array _in_ operator will be more inefficient for larger ranges (i.e. `'A'..'z'`), but more efficient for sparse sets (i.e. `'A','z'`).
|
Note that the array _in_ operator will be more inefficient for larger ranges (i.e. `'A'..'z'`), but more efficient for sparse sets (i.e. `'A','z'`).
|
||||||
|
|
||||||
|
|
@ -103,16 +103,6 @@ Tridora-Pascal only supports the _break_ statement at the moment.
|
||||||
The _exit_ statement can be used to exit the current procedure or function. If it is a function, the return value of the function is undefined if _exit_ is
|
The _exit_ statement can be used to exit the current procedure or function. If it is a function, the return value of the function is undefined if _exit_ is
|
||||||
used before a return value is assigned.
|
used before a return value is assigned.
|
||||||
|
|
||||||
|
|
||||||
## Dynamic Memory Allocation
|
|
||||||
Memory allocation generally works as expected with the *new* and *dispose* special procedures. The variant of *new* with two parameters that is specified in Wirth Pascal is not supported (partial allocation of a variant record). Instead, there is a variant of *new* that has a second parameter for allocating strings (see above).
|
|
||||||
|
|
||||||
If heap allocation fails, *new* does not return and instead causes a runtime error. To avoid this, a different special procedure called *newOrNil* can be used. This procedure sets the pointer
|
|
||||||
variable to *niL* if heap allocation fails.
|
|
||||||
|
|
||||||
The function *MemAvail* returns the number of free bytes on the heap. It does not guarantee that this amount of memory can be allocated with *new*, because heap space can be fragmented.
|
|
||||||
The function *MaxAvail*, which exists in some versions of Turbo Pascal and returns the size of the largest contiguous block of available heap memory, is not (yet) implemented.
|
|
||||||
|
|
||||||
## I/O
|
## I/O
|
||||||
I/O handling in Tridora Pascal is mostly compatible with other Pascal dialects when reading/writing simple variables from/to the console. There are big differences when opening/reading/writing files explicitly.
|
I/O handling in Tridora Pascal is mostly compatible with other Pascal dialects when reading/writing simple variables from/to the console. There are big differences when opening/reading/writing files explicitly.
|
||||||
|
|
||||||
|
|
@ -133,7 +123,7 @@ The implementation also has the following properties:
|
||||||
- _read_/_write_ do ASCII conversion on scalar variables, records and arrays are processed as binary
|
- _read_/_write_ do ASCII conversion on scalar variables, records and arrays are processed as binary
|
||||||
- enums and booleans are treated as integers
|
- enums and booleans are treated as integers
|
||||||
- _readln_/_writeln_ operate as expected, that is, they perform _read_/_write_ and then wait for/write a newline sequence
|
- _readln_/_writeln_ operate as expected, that is, they perform _read_/_write_ and then wait for/write a newline sequence
|
||||||
- other file operations available are _eof_, _eoln_, _seek_ and _filepos_
|
- other file operations available are _eof_, _eoln_ and _seek_
|
||||||
- for error handling there is a function _IOResult_
|
- for error handling there is a function _IOResult_
|
||||||
- terminating the program without calling _close_ on open files will lose data
|
- terminating the program without calling _close_ on open files will lose data
|
||||||
|
|
||||||
|
|
@ -163,12 +153,10 @@ var f:file;
|
||||||
### Error Handling
|
### Error Handling
|
||||||
When an I/O error occurs, the _IOResult_ function can be called to get the error code. Unlike TP, the _IOResult_ function requires a
|
When an I/O error occurs, the _IOResult_ function can be called to get the error code. Unlike TP, the _IOResult_ function requires a
|
||||||
file variable as a parameter. When you call _IOResult_, an error that may have occurred is considered to be _acknowledged_. If an
|
file variable as a parameter. When you call _IOResult_, an error that may have occurred is considered to be _acknowledged_. If an
|
||||||
error is not ackowledged and you do another I/O operation on that file, a runtime error is thrown.
|
error is not ackowledged and you do another I/O operation, a runtime error is thrown.
|
||||||
|
|
||||||
That means you can either write programs without checking for I/O errors, while resting assured that the program will exit if an I/O error occurs. You can also choose to check for errors with _IOResult_ if you want to avoid having runtime errors.
|
That means you can either write programs without checking for I/O errors, while resting assured that the program will exit if an I/O error occurs. You can also choose to check for errors with _IOResult_ if you want to avoid having runtime errors.
|
||||||
|
|
||||||
If an I/O error occurs on a file, it is then considered closed. Closing a file in this state, or a file that has been closed normally, will cause a runtime error.
|
|
||||||
|
|
||||||
The function _ErrorStr_ from the standard library takes an error code as an argument and returns the corresponding textual description as a string.
|
The function _ErrorStr_ from the standard library takes an error code as an argument and returns the corresponding textual description as a string.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
@ -203,8 +191,7 @@ Possible error codes from _IOResult_ are:
|
||||||
| 8 | IOReadOnly | file is readonly | |
|
| 8 | IOReadOnly | file is readonly | |
|
||||||
| 9 | IOInvalidOp | invalid operation | |
|
| 9 | IOInvalidOp | invalid operation | |
|
||||||
| 10 | IOInvalidFormat | invalid format | when parsing numbers with _read_ |
|
| 10 | IOInvalidFormat | invalid format | when parsing numbers with _read_ |
|
||||||
| 11 | IONoMem | not enough memory | heap allocation failed inside the standard library, e.g. open() |
|
| 11 | IOUserIntr | interrupted by user | program terminated by ^C, not visible from _IOResult_ |
|
||||||
| 12 | IOUserIntr | interrupted by user | program terminated by ^C, not visible from _IOResult_ |
|
|
||||||
|
|
||||||
### Read, Readln and Line Input
|
### Read, Readln and Line Input
|
||||||
In Turbo Pascal, using _read_ (and _readln_) from the console always waits until a complete line has been entered.
|
In Turbo Pascal, using _read_ (and _readln_) from the console always waits until a complete line has been entered.
|
||||||
|
|
@ -235,85 +222,6 @@ In Wirth Pascal, labels must be numbers. Other Pascal dialects also allow normal
|
||||||
|
|
||||||
Tridora-Pascal only allows identifiers as labels.
|
Tridora-Pascal only allows identifiers as labels.
|
||||||
|
|
||||||
## Units
|
|
||||||
Units are the method to create libraries in Tridora-Pascal, that is, codes module that can
|
|
||||||
be reused in other programs.
|
|
||||||
|
|
||||||
Tridora-Pascal follows the unit syntax that has been established in UCSD-Pascal and is also
|
|
||||||
used in Turbo Pascal.
|
|
||||||
|
|
||||||
Units are imported with the *USES* keyword, right after the *PROGRAM* statement.
|
|
||||||
Multiple units can be imported by separating the unit names with commas.
|
|
||||||
|
|
||||||
There are some differences: In Tridora-Pascal, the unit file does not contain the interface
|
|
||||||
section, only the implementation section. The interface section is instead placed into a
|
|
||||||
separate file with the extension *.inc*, without any *UNIT* or *INTERFACE* keywords.
|
|
||||||
|
|
||||||
This file will be included by the compiler and should contain
|
|
||||||
procedure or function declarations (as *EXTERNAL*). It can also contain *TYPE*,
|
|
||||||
*CONST* and *VAR* statements.
|
|
||||||
|
|
||||||
All Pascal symbols of the unit are imported into the main program. There
|
|
||||||
is no separate namespace for units.
|
|
||||||
|
|
||||||
### Using an Existing Unit
|
|
||||||
An existing unit is imported with the *USES* statement that must be placed
|
|
||||||
immediately after the *PROGRAM* statement.
|
|
||||||
|
|
||||||
The compiler will look for an include file with the unit name and an *.inc* extension.
|
|
||||||
It will also
|
|
||||||
tell the assembler to include an assembly language file for each
|
|
||||||
unit. The filename must be the unit name plus an *.s* extension.
|
|
||||||
|
|
||||||
Since there is no linker in Tridora-Pascal, all imported units will be
|
|
||||||
assembled together with the main program.
|
|
||||||
|
|
||||||
The compiler looks for unit *.inc* and *.s* files in the current volume or
|
|
||||||
in the *SYSTEM* volume.
|
|
||||||
|
|
||||||
### Compiling a Unit
|
|
||||||
A unit implementation file should start with a *UNIT* statement instead of a *PROGRAM*
|
|
||||||
statement.
|
|
||||||
|
|
||||||
It should be compiled, not assembled.
|
|
||||||
|
|
||||||
When building a program that uses units, the assembler will include an assembly language
|
|
||||||
file for each unit.
|
|
||||||
|
|
||||||
It is possible to write units in assembly language. This is done by
|
|
||||||
directly providing the *.s* file and creating an *.inc* file with
|
|
||||||
the *EXTERNAL* declarations matching the assembly language
|
|
||||||
file.
|
|
||||||
#### Example
|
|
||||||
```pascal
|
|
||||||
(* UnitExamples.pas *)
|
|
||||||
program UnitExample;
|
|
||||||
uses hello;
|
|
||||||
|
|
||||||
begin
|
|
||||||
sayHello('unit');
|
|
||||||
end.
|
|
||||||
```
|
|
||||||
|
|
||||||
#### Example Unit Implementation File
|
|
||||||
```pascal
|
|
||||||
(* hello.pas *)
|
|
||||||
unit hello;
|
|
||||||
|
|
||||||
implementation
|
|
||||||
|
|
||||||
procedure sayHello(s:string);
|
|
||||||
begin
|
|
||||||
writeln('hello, ', s);
|
|
||||||
end;
|
|
||||||
|
|
||||||
end.
|
|
||||||
```
|
|
||||||
#### Example Unit Include File
|
|
||||||
```pascal
|
|
||||||
(* hello.inc *)
|
|
||||||
procedure sayHello(s:string); external;
|
|
||||||
```
|
|
||||||
## Compiler Directives
|
## Compiler Directives
|
||||||
|
|
||||||
Tridora-Pascal understands a small number of compiler directives which are introduced as usual with a comment and a dollar-sign. Both comment styles can be used.
|
Tridora-Pascal understands a small number of compiler directives which are introduced as usual with a comment and a dollar-sign. Both comment styles can be used.
|
||||||
|
|
|
||||||
104
doc/tdraudio.md
104
doc/tdraudio.md
|
|
@ -1,104 +0,0 @@
|
||||||
# Audio Controller
|
|
||||||
The audio controller provides four channels of 16-bit PCM audio playback.
|
|
||||||
|
|
||||||
It uses multiple registers starting at address $A00.
|
|
||||||
|
|
||||||
Each of the four channels has three registers.
|
|
||||||
|
|
||||||
For the first channel the register addresses are:
|
|
||||||
|
|
||||||
|Address|Description|
|
|
||||||
|-------|-----------|
|
|
||||||
| $A00 | Control Register |
|
|
||||||
| $A04 | Clock Divider Register |
|
|
||||||
| $A08 | Amplitude Register |
|
|
||||||
|
|
||||||
The register addresses for the second channel start at $A10,
|
|
||||||
the third channel at $A20
|
|
||||||
and the fourth channel at $A30.
|
|
||||||
|
|
||||||
## Reading the control register
|
|
||||||
|
|
||||||
|_bit_ |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|
|
|
||||||
|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
|
|
||||||
|_Value_|- |- |- |- |- |- |- |- |- |-|- |- |- |- |- |- |
|
|
||||||
|
|
||||||
|_bit_ |15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
|
|
||||||
|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
|
|
||||||
|_Value_|- |- |- |- |- |- |- |- |- |- |- |i |f | e | p | c |
|
|
||||||
|
|
||||||
|
|
||||||
|Bitfields|Description|
|
|
||||||
|---------|-----------|
|
|
||||||
| _i_ | interrupt is enabled for this channel when 1 |
|
|
||||||
| _f_ | sample buffer is full when 1 |
|
|
||||||
| _e_ | sample buffer is empty when 1 |
|
|
||||||
| _p_ | changes from 0 to 1 and vice versa on each sample clock |
|
|
||||||
| _c_ | channel is enabled if 1 |
|
|
||||||
|
|
||||||
## Writing the control register
|
|
||||||
|
|
||||||
|_bit_ |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|
|
|
||||||
|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
|
|
||||||
|_Value_|- |- |- |- |- |- |- |- |- |-|- |- |- |- |- |- |
|
|
||||||
|
|
||||||
|_bit_ |15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
|
|
||||||
|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
|
|
||||||
|_Value_|- |- |- |- |- |- |- |- |- |- |- |i |- | - | - | c |
|
|
||||||
|
|
||||||
|
|
||||||
|Bitfields|Description|
|
|
||||||
|---------|-----------|
|
|
||||||
| _c_ | enable channel if 1, disable if 0 |
|
|
||||||
| _i_ | enable channel interrupt if 1, disable if 0 |
|
|
||||||
|
|
||||||
|
|
||||||
## Writing the clock divider register
|
|
||||||
|
|
||||||
|_bit_ |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|
|
|
||||||
|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
|
|
||||||
|_Value_|d |d |d |d |d |d |d |d |d |d|d |d |d |d |d |d |
|
|
||||||
|
|
||||||
|_bit_ |15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
|
|
||||||
|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
|
|
||||||
|_Value_|d |d |d |d |d |d |d |d |d |d|d |d |d |d |d |d |
|
|
||||||
|
|
||||||
|
|
||||||
|Bitfields|Description|
|
|
||||||
|---------|-----------|
|
|
||||||
| _d_ | an unsigned 32-bit value for the clock divider |
|
|
||||||
|
|
||||||
|
|
||||||
## Writing the amplitude register
|
|
||||||
|
|
||||||
|_bit_ |31|30|29|28|27|26|25|24|23|22|21|20|19|18|17|16|
|
|
||||||
|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
|
|
||||||
|_Value_|- |- |- |- |- |- |- |- |- |-|- |- |- |- |- |- |
|
|
||||||
|
|
||||||
|_bit_ |15|14|13|12|11|10|09|08|07|06|05|04|03|02|01|00|
|
|
||||||
|- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |- |
|
|
||||||
|_Value_|a |a |a |a |a |a |a |a |a |a |a |a |a | a | a | a |
|
|
||||||
|
|
||||||
|
|
||||||
|Bitfields|Description|
|
|
||||||
|---------|-----------|
|
|
||||||
| _a_ | an unsigned 16-bit value for the amplitude (sample) value with a bias of 32768 |
|
|
||||||
|
|
||||||
## Notes
|
|
||||||
The clock divider specifies the number of CPU clock ticks between two samples.
|
|
||||||
|
|
||||||
Writing to the amplitude register adds the sample value to the sample buffer. The sample buffer is organized as a FIFO with 16 elements.
|
|
||||||
|
|
||||||
Amplitude (sample) values are represented as unsigned, biased 16-bit numbers. The bias is 32768, so given an amplitude range of 1.0 to -1.0, a 1.0 is represented by 65535, 0.0 by 32768 and -1.0 by 0.
|
|
||||||
|
|
||||||
Interrupt processing needs to be enabled for each channel if required.
|
|
||||||
|
|
||||||
An interrupt on any channel will be signalled to the interrupt controller
|
|
||||||
as IRQ 2. The interrupt service routine should check all running channels
|
|
||||||
for an emtpy buffer.
|
|
||||||
|
|
||||||
If an audio interrupt has occured on a channel, the interrupt enable flag
|
|
||||||
is cleared for that channel. It needs to be re-enabled in the interrupt service routine.
|
|
||||||
|
|
||||||
Interrupts also need to be enabled on the interrupt controller,
|
|
||||||
and re-enabled there after each interrupt.
|
|
||||||
|
|
@ -37,7 +37,7 @@ It uses a fixed serial configuration of 115200 bps, 8 data bits, 1 stop bit, no
|
||||||
|
|
||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
A 64 byte FIFO is used when receiving data.
|
A 16 byte FIFO is used when receiving data.
|
||||||
|
|
||||||
When reading data, each byte needs to be acknowledged by writing the _C_ flag to the UART register.
|
When reading data, each byte needs to be acknowledged by writing the _C_ flag to the UART register.
|
||||||
|
|
||||||
|
|
|
||||||
68
doc/vga.md
68
doc/vga.md
|
|
@ -4,16 +4,13 @@ Registers
|
||||||
|Name|Address|Description|
|
|Name|Address|Description|
|
||||||
|----|-------|-----------|
|
|----|-------|-----------|
|
||||||
|_FB_RA_ | $900 | Read Address |
|
|_FB_RA_ | $900 | Read Address |
|
||||||
|_FB_WA_ | $904 | Write Address |
|
|_FB_WA_ | $901 | Write Address |
|
||||||
| _FB_IO_ | $908 | I/O Register |
|
| _FB_IO_ | $902 | I/O Register |
|
||||||
| _FB_PS_ | $90C | Palette Select |
|
| _FB_PS_ | $903 | Palette Select |
|
||||||
| _FB_PD_ | $910 | Palette Data |
|
| _FB_PD_ | $904 | Palette Data |
|
||||||
| _FB_CTL_ | $914 | Control Register |
|
| _FB_CTL_ | $905 | Control Register |
|
||||||
| _FB_SHIFTER_ | $918 | Shift Assist Register |
|
|
||||||
| _FB_SHIFTCOUNT_ | $91C | Shift Count Register |
|
|
||||||
| _FB_SHIFTERM_ | $920 | Shifted Mask Register |
|
|
||||||
| _FB_SHIFTERSP_ | $924 | Shifter Spill Register |
|
|
||||||
| _FB_MASKGEN_ | $928 | Mask Generator Register |
|
|
||||||
|
|
||||||
## Pixel Data
|
## Pixel Data
|
||||||
Pixel data is organized in 32-bit-words. With four bits per pixel, one word
|
Pixel data is organized in 32-bit-words. With four bits per pixel, one word
|
||||||
|
|
@ -84,54 +81,3 @@ The control register contains status information. It can only be read.
|
||||||
The _m_ field indicates the current graphics mode. At the time of writing, it is
|
The _m_ field indicates the current graphics mode. At the time of writing, it is
|
||||||
always 1 which denotes a 640x400x4 mode.
|
always 1 which denotes a 640x400x4 mode.
|
||||||
The _vb_ bit is 1 when the video signal generator is in its vertical blank phase.
|
The _vb_ bit is 1 when the video signal generator is in its vertical blank phase.
|
||||||
|
|
||||||
## Shift Assist Register
|
|
||||||
The *shift assist register* can be used to accelerate shifting pixel/bitmap data.
|
|
||||||
Writing a word of pixel data to this register initialises the shifting process.
|
|
||||||
|
|
||||||
After writing to the shift count register (see below), reading the shift assist
|
|
||||||
register retrieves the shifted pixel data.
|
|
||||||
|
|
||||||
Writing to the shift assist register will reset the shift count.
|
|
||||||
|
|
||||||
## Shift Count Register
|
|
||||||
Writing a number from 0-7 to the *shift count register* triggers shifting the
|
|
||||||
contents of the shift assist register. Pixel data is shifted by four bits
|
|
||||||
to the right times the shift count. Bits 31-3 of the shift count are ignored, so you can
|
|
||||||
directly write a horizontal screen coordinate to the register.
|
|
||||||
|
|
||||||
This register cannot be read.
|
|
||||||
|
|
||||||
## Shifter Mask Register
|
|
||||||
The *shifter mask register* contains the shifted pixel data converted into
|
|
||||||
a mask. See the *mask generator register* for an
|
|
||||||
explanation of the mask.
|
|
||||||
|
|
||||||
## Shifter Spill Register
|
|
||||||
The *shifter spill register* contains the pixel data that has
|
|
||||||
been shifted out to the right. For example, if the shift count is two,
|
|
||||||
the spill register contains the two rightmost pixels (bits 7-0) of
|
|
||||||
the original pixel data, placed into the two topmost pixels (bits 31-24).
|
|
||||||
|
|
||||||
The rest of the register is set to zero.
|
|
||||||
|
|
||||||
## Mask Generator Register
|
|
||||||
The *mask generator register* creates a mask from pixel data.
|
|
||||||
For each four bits of a pixel, the corresponding four mask bits
|
|
||||||
are all set to one if the pixel value is not zero.
|
|
||||||
|
|
||||||
This can be used to combine foreground and background pixel data
|
|
||||||
where a pixel value of zero is used to indicate a transparent foreground pixel.
|
|
||||||
|
|
||||||
Usually, the mask will be inverted with a *NOT* instruction.
|
|
||||||
The result can then be used to clear all pixels in the background
|
|
||||||
that are set in the foreground, using an *AND* instruction.
|
|
||||||
As the last step, foreground and masked background data can be combined with an *OR* instruction.
|
|
||||||
|
|
||||||
Example in hexadecimal, each digit is a pixel:
|
|
||||||
| Pixel Data | Mask |
|
|
||||||
|------------|------|
|
|
||||||
| $00000000 | $00000000 |
|
|
||||||
| $00000001 | $0000000F |
|
|
||||||
| $0407000F | $0F0F000F |
|
|
||||||
| $1234ABC0 | $FFFFFFF0 |
|
|
||||||
|
|
|
||||||
|
|
@ -1,97 +0,0 @@
|
||||||
program threedeeplot;
|
|
||||||
const w = 640;
|
|
||||||
h = 400;
|
|
||||||
|
|
||||||
var u0,v0:integer;
|
|
||||||
|
|
||||||
function fun(x0,y0:real):real;
|
|
||||||
const vscale = 50.0;
|
|
||||||
hscale = 20.0;
|
|
||||||
|
|
||||||
var x,y,f:real;
|
|
||||||
begin
|
|
||||||
x := x0 / hscale;
|
|
||||||
y := y0 / hscale;
|
|
||||||
f := sin(sqrt(x*x + y*y));
|
|
||||||
|
|
||||||
fun := f * vscale;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure plot;
|
|
||||||
var maxV,minV:array [0..w] of real;
|
|
||||||
shift:integer;
|
|
||||||
x,y,z:integer;
|
|
||||||
lastZ:integer;
|
|
||||||
numLines:integer;
|
|
||||||
i:integer;
|
|
||||||
u,v,lastU,lastV:integer;
|
|
||||||
color:integer;
|
|
||||||
|
|
||||||
procedure resetCurve;
|
|
||||||
begin
|
|
||||||
lastU := -1;
|
|
||||||
lastV := -1;
|
|
||||||
end;
|
|
||||||
|
|
||||||
begin
|
|
||||||
for i := 0 to w do
|
|
||||||
begin
|
|
||||||
maxV[i] := -10000;
|
|
||||||
minV[i] := 10000;
|
|
||||||
end;
|
|
||||||
|
|
||||||
color := 1;
|
|
||||||
shift := 4;
|
|
||||||
x := 0;
|
|
||||||
numLines := 80;
|
|
||||||
u0 := w div 2;
|
|
||||||
v0 := h div 2;
|
|
||||||
|
|
||||||
for i := -(numLines div 2) to numLines do
|
|
||||||
begin
|
|
||||||
resetCurve;
|
|
||||||
x := i * (w div numLines);
|
|
||||||
for y := -w to w do
|
|
||||||
begin
|
|
||||||
z := round(fun(x,y));
|
|
||||||
u := round(y + u0 + i * shift);
|
|
||||||
v := round(-z + v0 - i * shift);
|
|
||||||
|
|
||||||
if (u >= 0) and (u < w) then
|
|
||||||
begin
|
|
||||||
if (v < maxV[u]) and (v > minV[u]) then
|
|
||||||
resetCurve
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
if (u >= 0) and (u < w) and (v > maxV[u]) then
|
|
||||||
maxV[u] := v;
|
|
||||||
if (u >= 0) and (u < w) and (v < minV[u]) then
|
|
||||||
minV[u] := v;
|
|
||||||
|
|
||||||
if lastZ < z then
|
|
||||||
color := 8
|
|
||||||
else
|
|
||||||
color := 1;
|
|
||||||
|
|
||||||
if (u >= w) or (u < 0) or (v >= h) or (v < 0) then
|
|
||||||
resetCurve
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
if lastU = -1 then
|
|
||||||
putpixel(u,v,color)
|
|
||||||
else
|
|
||||||
drawline(lastU,lastV,u,v,color);
|
|
||||||
end;
|
|
||||||
lastU := u;
|
|
||||||
lastV := v;
|
|
||||||
lastZ := z;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
begin
|
|
||||||
initgraphics;
|
|
||||||
plot;
|
|
||||||
end.
|
|
||||||
|
|
@ -7,9 +7,4 @@ https://commons.wikimedia.org/wiki/File:Ara-Zoo-Muenster-2013.jpg
|
||||||
https://commons.wikimedia.org/wiki/File:Snow_leopard_portrait.jpg
|
https://commons.wikimedia.org/wiki/File:Snow_leopard_portrait.jpg
|
||||||
* shinkansen.pict: 投稿者が撮影, CC BY-SA 3.0 <http://creativecommons.org/licenses/by-sa/3.0/>, via Wikimedia Commons
|
* shinkansen.pict: 投稿者が撮影, CC BY-SA 3.0 <http://creativecommons.org/licenses/by-sa/3.0/>, via Wikimedia Commons
|
||||||
https://commons.wikimedia.org/wiki/File:0key22-86.JPG
|
https://commons.wikimedia.org/wiki/File:0key22-86.JPG
|
||||||
* Toco_Toucan.pict: Bernard DUPONT, CC BY-SA 2.0 <https://creativecommons.org/licenses/by-sa/2.0>, via Wikimedia Commons
|
|
||||||
https://commons.wikimedia.org/wiki/File:Toco_Toucan_(Ramphastos_toco)_-_48153967707.jpg
|
|
||||||
* 1911_Detroit_Electric.pict: Cullen328, CC BY-SA 3.0 <https://creativecommons.org/licenses/by-sa/3.0>, via Wikimedia Commons
|
|
||||||
https://commons.wikimedia.org/wiki/File:1911_Detroit_Electric.jpg
|
|
||||||
* ADDS-Envoy-620.pict: ADDS Envoy-1.jpg from terminals-wiki.org, CC-BY-SA 3.0
|
|
||||||
https://terminals-wiki.org/wiki/index.php/File:ADDS_Envoy-1.jpg
|
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -1,245 +0,0 @@
|
||||||
program animate;
|
|
||||||
uses sprites,pcmaudio;
|
|
||||||
|
|
||||||
type PictData = record
|
|
||||||
magic,mode:integer;
|
|
||||||
palette: array [0..15] of integer;
|
|
||||||
pixeldata: array [0..31999] of integer;
|
|
||||||
end;
|
|
||||||
|
|
||||||
Sprite = record
|
|
||||||
x,y:integer;
|
|
||||||
xdelta,ydelta:integer;
|
|
||||||
curFrame:integer;
|
|
||||||
frameCount:integer;
|
|
||||||
frameTime:integer;
|
|
||||||
frameLeft:integer;
|
|
||||||
moveTime:integer;
|
|
||||||
moveLeft:integer;
|
|
||||||
changed:boolean;
|
|
||||||
frame:array [0..3] of SpritePixels;
|
|
||||||
end;
|
|
||||||
|
|
||||||
var pic:PictData;
|
|
||||||
filename:string;
|
|
||||||
infile:file;
|
|
||||||
ch:char;
|
|
||||||
stickMan:Sprite;
|
|
||||||
rocket:Sprite;
|
|
||||||
rocket2:Sprite;
|
|
||||||
rocket3:Sprite;
|
|
||||||
|
|
||||||
buf:SndBufPtr;
|
|
||||||
|
|
||||||
|
|
||||||
procedure WaitVSync; external;
|
|
||||||
|
|
||||||
function readAudioFile(fname:string):SndBufPtr;
|
|
||||||
var i,size:integer;
|
|
||||||
c:char;
|
|
||||||
buf:SndBufPtr;
|
|
||||||
f:file;
|
|
||||||
begin
|
|
||||||
open(f, fname, ModeReadOnly);
|
|
||||||
size := FileSize(f);
|
|
||||||
new(buf, size);
|
|
||||||
|
|
||||||
buf^ := '';
|
|
||||||
write('Reading ', size, ' bytes from ', fname);
|
|
||||||
for i := 1 to size do
|
|
||||||
begin
|
|
||||||
read(f,c);
|
|
||||||
AppendChar(buf^,c);
|
|
||||||
end;
|
|
||||||
writeln;
|
|
||||||
close(f);
|
|
||||||
readAudioFile := buf;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure loadPalette(var pic:PictData);
|
|
||||||
var i:integer;
|
|
||||||
begin
|
|
||||||
for i := 0 to 15 do
|
|
||||||
setpalette(i, pic.palette[i]);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure showPic(var pic:PictData);
|
|
||||||
begin
|
|
||||||
PutScreen(pic.pixeldata);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure loadSpriteFrame(var aSprite:Sprite;spriteIndex:integer;
|
|
||||||
var sheetFile:file;sheetIndex:integer);
|
|
||||||
begin
|
|
||||||
seek(sheetFile, 8 + sheetIndex * 512);
|
|
||||||
read(sheetFile, aSprite.frame[spriteIndex]);
|
|
||||||
if aSprite.frameCount <= spriteIndex then
|
|
||||||
aSprite.frameCount := spriteIndex + 1;
|
|
||||||
|
|
||||||
aSprite.curFrame := 0;
|
|
||||||
writeln('loaded sprite frame ', spriteIndex, ' from ', sheetIndex);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure animateSprite(var aSprite:Sprite);
|
|
||||||
var frameIndex:integer;
|
|
||||||
frameTime,frameLeft:integer;
|
|
||||||
moveTime,moveLeft:integer;
|
|
||||||
ydelta:integer;
|
|
||||||
begin
|
|
||||||
ydelta := aSprite.ydelta;
|
|
||||||
frameIndex := aSprite.curFrame;
|
|
||||||
frameTime := aSprite.frameTime;
|
|
||||||
frameLeft := aSprite.frameLeft;
|
|
||||||
moveTime := aSprite.moveTime;
|
|
||||||
moveLeft := aSprite.moveLeft;
|
|
||||||
|
|
||||||
frameLeft := frameLeft - 1;
|
|
||||||
if frameLeft <= 0 then
|
|
||||||
begin
|
|
||||||
frameIndex := frameIndex + 1;
|
|
||||||
frameLeft := frameTime;
|
|
||||||
aSprite.curFrame := frameIndex;
|
|
||||||
if frameIndex >= aSprite.frameCount then
|
|
||||||
aSprite.curFrame := 0;
|
|
||||||
end;
|
|
||||||
|
|
||||||
moveLeft := moveLeft - 1;
|
|
||||||
if moveLeft <= 0 then
|
|
||||||
begin
|
|
||||||
aSprite.x := aSprite.x + aSprite.xdelta;
|
|
||||||
aSprite.y := aSprite.y + aSprite.ydelta;
|
|
||||||
moveLeft := moveTime;
|
|
||||||
|
|
||||||
if aSprite.x > 608 then aSprite.x := 0;
|
|
||||||
|
|
||||||
if aSprite.ydelta <> 0 then
|
|
||||||
begin
|
|
||||||
if aSprite.y < 3 then
|
|
||||||
aSprite.ydelta := -aSprite.ydelta
|
|
||||||
else
|
|
||||||
if aSprite.y > 130 then
|
|
||||||
aSprite.ydelta := -aSprite.yDelta;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
aSprite.frameLeft := frameLeft;
|
|
||||||
aSprite.moveLeft := moveLeft;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure animLoop;
|
|
||||||
var i:integer;
|
|
||||||
oldX,oldY:integer;
|
|
||||||
roldX,roldY:integer;
|
|
||||||
r2oldX,r2oldY:integer;
|
|
||||||
r3oldX,r3oldY:integer;
|
|
||||||
begin
|
|
||||||
stickMan.x := 0;
|
|
||||||
stickMan.y := 205;
|
|
||||||
stickMan.frameTime := 6;
|
|
||||||
stickMan.frameLeft := stickMan.frameTime;
|
|
||||||
stickMan.curFrame := 0;
|
|
||||||
stickMan.xdelta := 2;
|
|
||||||
stickMan.ydelta := 0;
|
|
||||||
stickMan.moveTime := 2;
|
|
||||||
stickman.moveLeft := stickMan.moveTime;
|
|
||||||
|
|
||||||
rocket.x := 0;
|
|
||||||
rocket.y := 50;
|
|
||||||
rocket.frameTime := 5;
|
|
||||||
rocket.frameLeft := rocket.frameTime;
|
|
||||||
rocket.curFrame := 0;
|
|
||||||
rocket.xdelta := 3;
|
|
||||||
rocket.ydelta := 1;
|
|
||||||
rocket.moveTime := 1;
|
|
||||||
rocket.moveLeft := rocket.moveTime;
|
|
||||||
|
|
||||||
rocket2.x := 50;
|
|
||||||
rocket2.y := 190;
|
|
||||||
rocket2.frameTime := 5;
|
|
||||||
rocket2.frameLeft := rocket2.frameTime;
|
|
||||||
rocket2.curFrame := 1;
|
|
||||||
rocket2.xdelta := 3;
|
|
||||||
rocket2.ydelta := 0;
|
|
||||||
rocket2.moveTime := 1;
|
|
||||||
rocket2.moveLeft := rocket2.moveTime;
|
|
||||||
|
|
||||||
rocket3.x :=100;
|
|
||||||
rocket3.y := 90;
|
|
||||||
rocket3.frameTime := 5;
|
|
||||||
rocket3.frameLeft := rocket3.frameTime;
|
|
||||||
rocket3.curFrame := 2;
|
|
||||||
rocket3.xdelta := 3;
|
|
||||||
rocket3.ydelta := -1;
|
|
||||||
rocket3.moveTime := 1;
|
|
||||||
rocket3.moveLeft := rocket3.moveTime;
|
|
||||||
|
|
||||||
while not ConAvail do
|
|
||||||
begin
|
|
||||||
oldX := stickMan.x;
|
|
||||||
oldY := stickMan.y;
|
|
||||||
|
|
||||||
roldX := rocket.x;
|
|
||||||
roldY := rocket.y;
|
|
||||||
|
|
||||||
r2oldX := rocket2.x;
|
|
||||||
r2oldY := rocket2.y;
|
|
||||||
|
|
||||||
r3oldX := rocket3.x;
|
|
||||||
r3oldY := rocket3.y;
|
|
||||||
|
|
||||||
PutSprite(roldX, roldY, rocket.frame[rocket.curFrame]);
|
|
||||||
PutSprite(r2oldX, r2oldY, rocket2.frame[rocket2.curFrame]);
|
|
||||||
PutSprite(r3oldX, r3oldY, rocket3.frame[rocket3.curFrame]);
|
|
||||||
PutSprite(oldX, oldY, stickMan.frame[stickMan.curFrame]);
|
|
||||||
|
|
||||||
animateSprite(rocket);
|
|
||||||
animateSprite(rocket2);
|
|
||||||
animateSprite(rocket3);
|
|
||||||
animateSprite(stickMan);
|
|
||||||
|
|
||||||
Delay(10);
|
|
||||||
WaitVSync;
|
|
||||||
|
|
||||||
UndrawSprite(oldX, oldY, pic.pixeldata);
|
|
||||||
UndrawSprite(roldX, roldY, pic.pixeldata);
|
|
||||||
UndrawSprite(r2oldX, r2oldY, pic.pixeldata);
|
|
||||||
UndrawSprite(r3oldX, r3oldY, pic.pixeldata);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
begin
|
|
||||||
filename := 'background.pict';
|
|
||||||
open(infile, filename, ModeReadonly);
|
|
||||||
read(infile, pic);
|
|
||||||
close(infile);
|
|
||||||
|
|
||||||
writeln('magic: ', pic.magic, ' mode:', pic.mode);
|
|
||||||
|
|
||||||
loadPalette(pic);
|
|
||||||
showPic(pic);
|
|
||||||
|
|
||||||
open(infile, 'walking.sprt', ModeReadOnly);
|
|
||||||
loadSpriteFrame(stickMan, 0, infile, 0);
|
|
||||||
loadSpriteFrame(stickMan, 1, infile, 1);
|
|
||||||
loadSpriteFrame(stickMan, 2, infile, 2);
|
|
||||||
loadSpriteFrame(stickMan, 3, infile, 3);
|
|
||||||
close(infile);
|
|
||||||
|
|
||||||
open(infile, 'rocket.sprt', ModeReadOnly);
|
|
||||||
loadSpriteFrame(rocket, 0, infile, 0);
|
|
||||||
loadSpriteFrame(rocket, 1, infile, 1);
|
|
||||||
loadSpriteFrame(rocket, 2, infile, 2);
|
|
||||||
loadSpriteFrame(rocket, 3, infile, 3);
|
|
||||||
close(infile);
|
|
||||||
|
|
||||||
rocket2 := rocket;
|
|
||||||
rocket3 := rocket;
|
|
||||||
|
|
||||||
buf := readAudioFile('footsteps.tdrau');
|
|
||||||
SampleQStart(buf, true, 16000);
|
|
||||||
|
|
||||||
animLoop;
|
|
||||||
|
|
||||||
SampleQStop;
|
|
||||||
dispose(buf);
|
|
||||||
end.
|
|
||||||
Binary file not shown.
|
|
@ -1,299 +0,0 @@
|
||||||
{$H350}
|
|
||||||
program benchmarks;
|
|
||||||
var starttime:DateTime;
|
|
||||||
endtime:DateTime;
|
|
||||||
|
|
||||||
procedure startBench(name:string);
|
|
||||||
begin
|
|
||||||
write(name:35, ' ');
|
|
||||||
starttime := GetTime;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure endBench;
|
|
||||||
var secDelta, minDelta, hourDelta:integer;
|
|
||||||
procedure write2Digits(i:integer);
|
|
||||||
begin
|
|
||||||
if i < 10 then
|
|
||||||
write('0');
|
|
||||||
write(i);
|
|
||||||
end;
|
|
||||||
begin
|
|
||||||
endtime := GetTime;
|
|
||||||
|
|
||||||
hourDelta := endtime.hours - starttime.hours;
|
|
||||||
minDelta := endtime.minutes - starttime.minutes;
|
|
||||||
secDelta := endtime.seconds - starttime.seconds;
|
|
||||||
|
|
||||||
if secDelta < 0 then
|
|
||||||
begin
|
|
||||||
secDelta := 60 + secDelta;
|
|
||||||
minDelta := minDelta - 1;
|
|
||||||
end;
|
|
||||||
|
|
||||||
if minDelta < 0 then
|
|
||||||
begin
|
|
||||||
minDelta := 60 + minDelta;
|
|
||||||
hourDelta := hourDelta - 1;
|
|
||||||
end;
|
|
||||||
|
|
||||||
write2Digits(hourDelta);
|
|
||||||
write(':');
|
|
||||||
write2Digits(minDelta);
|
|
||||||
write(':');
|
|
||||||
write2Digits(secDelta);
|
|
||||||
writeln;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure bench0;
|
|
||||||
var i:integer;
|
|
||||||
begin
|
|
||||||
startBench('empty loop 10M');
|
|
||||||
for i := 1 to 10000000 do;
|
|
||||||
endBench;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure bench1;
|
|
||||||
var i:integer;
|
|
||||||
v:integer;
|
|
||||||
begin
|
|
||||||
startBench('write variable 10M');
|
|
||||||
for i := 1 to 10000000 do
|
|
||||||
v := 0;
|
|
||||||
endBench;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure bench2;
|
|
||||||
var i:integer;
|
|
||||||
v,r:integer;
|
|
||||||
begin
|
|
||||||
v := 4711;
|
|
||||||
startBench('read variable 10M');
|
|
||||||
for i := 1 to 10000000 do
|
|
||||||
r := v;
|
|
||||||
endBench;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure bench3;
|
|
||||||
var i:integer;
|
|
||||||
a,b:integer;
|
|
||||||
begin
|
|
||||||
a := 0;
|
|
||||||
b := 100;
|
|
||||||
|
|
||||||
startBench('integer addition 10M');
|
|
||||||
for i := 1 to 10000000 do
|
|
||||||
a := b + i;
|
|
||||||
endBench;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure bench4;
|
|
||||||
var i:integer;
|
|
||||||
a,b:real;
|
|
||||||
begin
|
|
||||||
a := 0.0;
|
|
||||||
b := 100.0;
|
|
||||||
|
|
||||||
startBench('real addition 1M');
|
|
||||||
for i := 1 to 1000000 do
|
|
||||||
a := b + i;
|
|
||||||
endBench;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure bench5;
|
|
||||||
var i:integer;
|
|
||||||
a,b:integer;
|
|
||||||
begin
|
|
||||||
a := 0;
|
|
||||||
b := 100;
|
|
||||||
|
|
||||||
startBench('integer multiplication 1M');
|
|
||||||
for i := 1 to 1000000 do
|
|
||||||
a := b * i;
|
|
||||||
endBench;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure bench6;
|
|
||||||
var i:integer;
|
|
||||||
a,b:real;
|
|
||||||
begin
|
|
||||||
a := 0;
|
|
||||||
b := 100;
|
|
||||||
|
|
||||||
startBench('real multiplication 1M');
|
|
||||||
for i := 1 to 1000000 do
|
|
||||||
a := b * i;
|
|
||||||
endBench;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure bench7;
|
|
||||||
var i:integer;
|
|
||||||
a,b:integer;
|
|
||||||
begin
|
|
||||||
a := 0;
|
|
||||||
b := 31415926;
|
|
||||||
|
|
||||||
startBench('integer division 1M');
|
|
||||||
for i := 1 to 1000000 do
|
|
||||||
a := b div i;
|
|
||||||
endBench;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure bench8;
|
|
||||||
var i:integer;
|
|
||||||
a,b,c:real;
|
|
||||||
begin
|
|
||||||
a := 0;
|
|
||||||
b := 31415926.0;
|
|
||||||
|
|
||||||
startBench('real division 1M');
|
|
||||||
for i := 1 to 1000000 do
|
|
||||||
a := b / i;
|
|
||||||
endBench;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure bench9;
|
|
||||||
var i,j:integer;
|
|
||||||
s:string[100];
|
|
||||||
c:char;
|
|
||||||
begin
|
|
||||||
s := '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn';
|
|
||||||
|
|
||||||
startBench('string indexing 1M');
|
|
||||||
for i := 1 to 100000 do
|
|
||||||
for j := 1 to 100 do
|
|
||||||
c := s[j];
|
|
||||||
endBench;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure bench10;
|
|
||||||
var i:integer;
|
|
||||||
s:string[100];
|
|
||||||
c,d:char;
|
|
||||||
begin
|
|
||||||
s := '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmn';
|
|
||||||
|
|
||||||
startBench('string iteration 1M');
|
|
||||||
for i := 1 to 100000 do
|
|
||||||
for c in s do
|
|
||||||
d := c;
|
|
||||||
endBench;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure bench11;
|
|
||||||
var ptr: ^array[0..255] of integer;
|
|
||||||
dummy1,dummy2,dummy3: ^array[0..127] of boolean;
|
|
||||||
i:integer;
|
|
||||||
begin
|
|
||||||
new(dummy1);
|
|
||||||
new(dummy2);
|
|
||||||
new(dummy3);
|
|
||||||
dispose(dummy1);
|
|
||||||
|
|
||||||
startBench('new/dispose 1k 1M');
|
|
||||||
for i := 1 to 1000000 do
|
|
||||||
begin
|
|
||||||
new(ptr);
|
|
||||||
dispose(ptr);
|
|
||||||
end;
|
|
||||||
endBench;
|
|
||||||
|
|
||||||
dispose(dummy2);
|
|
||||||
dispose(dummy3);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure bench12;
|
|
||||||
var ptr: ^array[0..32767] of integer;
|
|
||||||
dummy1,dummy2,dummy3: ^array[0..127] of boolean;
|
|
||||||
i:integer;
|
|
||||||
begin
|
|
||||||
new(dummy1);
|
|
||||||
new(dummy2);
|
|
||||||
new(dummy3);
|
|
||||||
dispose(dummy1);
|
|
||||||
|
|
||||||
startBench('new/dispose 128k 1M');
|
|
||||||
for i := 1 to 1000000 do
|
|
||||||
begin
|
|
||||||
new(ptr);
|
|
||||||
dispose(ptr);
|
|
||||||
end;
|
|
||||||
endBench;
|
|
||||||
|
|
||||||
dispose(dummy2);
|
|
||||||
dispose(dummy3);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure bench13;
|
|
||||||
var ptr1: ^array[0..255] of integer;
|
|
||||||
ptr2: ^array[0..255] of integer;
|
|
||||||
i:integer;
|
|
||||||
begin
|
|
||||||
new(ptr1);
|
|
||||||
new(ptr2);
|
|
||||||
startBench('array copy 1k 10K');
|
|
||||||
for i := 1 to 10000 do
|
|
||||||
ptr1^ := ptr2^;
|
|
||||||
endBench;
|
|
||||||
dispose(ptr1);
|
|
||||||
dispose(ptr2);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure bench14;
|
|
||||||
var ptr1: ^array[0..32767] of integer;
|
|
||||||
ptr2: ^array[0..32767] of integer;
|
|
||||||
i:integer;
|
|
||||||
begin
|
|
||||||
new(ptr1);
|
|
||||||
new(ptr2);
|
|
||||||
startBench('array copy 128k 1K');
|
|
||||||
for i := 1 to 1000 do
|
|
||||||
ptr1^ := ptr2^;
|
|
||||||
endBench;
|
|
||||||
dispose(ptr1);
|
|
||||||
dispose(ptr2);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure bench15;
|
|
||||||
var i,j:integer;
|
|
||||||
a:real;
|
|
||||||
begin
|
|
||||||
startBench('exp() 10K');
|
|
||||||
for i := 1 to 1000 do
|
|
||||||
for j := 1 to 10 do
|
|
||||||
a := exp(j);
|
|
||||||
endBench;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure bench16;
|
|
||||||
var i,j:integer;
|
|
||||||
a,b:real;
|
|
||||||
begin
|
|
||||||
startBench('cos() 10K');
|
|
||||||
b := 0.0;
|
|
||||||
for i := 1 to 10000 do
|
|
||||||
begin
|
|
||||||
a := cos(b);
|
|
||||||
b := b + 0.0001;
|
|
||||||
end;
|
|
||||||
endBench;
|
|
||||||
end;
|
|
||||||
|
|
||||||
begin
|
|
||||||
bench0;
|
|
||||||
bench1;
|
|
||||||
bench2;
|
|
||||||
bench3;
|
|
||||||
bench4;
|
|
||||||
bench5;
|
|
||||||
bench6;
|
|
||||||
bench7;
|
|
||||||
bench8;
|
|
||||||
bench9;
|
|
||||||
bench10;
|
|
||||||
bench11;
|
|
||||||
bench12;
|
|
||||||
bench13;
|
|
||||||
bench14;
|
|
||||||
bench15;
|
|
||||||
bench16;
|
|
||||||
end.
|
|
||||||
|
|
@ -1,196 +0,0 @@
|
||||||
------------------------
|
|
||||||
Arty-A7-35T
|
|
||||||
83MHz, 64KB SRAM, 256MB DRAM
|
|
||||||
|
|
||||||
Running benchmarks.prog
|
|
||||||
empty loop 10M 00:00:09
|
|
||||||
write variable 10M 00:00:10
|
|
||||||
read variable 10M 00:00:12
|
|
||||||
integer addition 10M 00:00:16
|
|
||||||
real addition 1M 00:00:27
|
|
||||||
integer multiplication 1M 00:01:07
|
|
||||||
real multiplication 1M 00:00:58
|
|
||||||
integer division 1M 00:01:44
|
|
||||||
real division 1M 00:01:06
|
|
||||||
string indexing 1M 00:00:27
|
|
||||||
string iteration 1M 00:00:11
|
|
||||||
new/dispose 1k 1M 00:00:19
|
|
||||||
new/dispose 128k 1M 00:00:19
|
|
||||||
array copy 1k 10K 00:00:02
|
|
||||||
array copy 128k 1K 00:00:44
|
|
||||||
exp() 10K 00:00:29
|
|
||||||
cos() 10K 00:00:06
|
|
||||||
|
|
||||||
--------------------------------------
|
|
||||||
Arty-A7-35T
|
|
||||||
83MHz, 64KB SRAM, 256MB DRAM
|
|
||||||
running in DRAM (except corelib, stdlib, runtime)
|
|
||||||
|
|
||||||
Running benchmarks.prog
|
|
||||||
empty loop 10M 00:00:30
|
|
||||||
write variable 10M 00:00:37
|
|
||||||
read variable 10M 00:00:40
|
|
||||||
integer addition 10M 00:00:48
|
|
||||||
real addition 1M 00:00:31
|
|
||||||
integer multiplication 1M 00:01:11
|
|
||||||
real multiplication 1M 00:01:03
|
|
||||||
integer division 1M 00:01:48
|
|
||||||
real division 1M 00:01:11
|
|
||||||
string indexing 1M 00:01:13
|
|
||||||
string iteration 1M 00:00:47
|
|
||||||
new/dispose 1k 1M 00:00:27
|
|
||||||
new/dispose 128k 1M 00:00:27
|
|
||||||
array copy 1k 10K 00:00:03
|
|
||||||
array copy 128k 1K 00:00:44
|
|
||||||
exp() 10K 00:00:29
|
|
||||||
cos() 10K 00:00:06
|
|
||||||
|
|
||||||
--------------------------------------
|
|
||||||
Arty-A7-35T
|
|
||||||
76.92MHz, 64KB SRAM, 256MB DRAM
|
|
||||||
running in DRAM (except corelib, stdlib, runtime)
|
|
||||||
|
|
||||||
Running benchmarks.prog
|
|
||||||
empty loop 10M 00:00:32
|
|
||||||
write variable 10M 00:00:40
|
|
||||||
read variable 10M 00:00:43
|
|
||||||
integer addition 10M 00:00:52
|
|
||||||
real addition 1M 00:00:34
|
|
||||||
integer multiplication 1M 00:01:17
|
|
||||||
real multiplication 1M 00:01:08
|
|
||||||
integer division 1M 00:01:57
|
|
||||||
real division 1M 00:01:17
|
|
||||||
string indexing 1M 00:01:19
|
|
||||||
string iteration 1M 00:00:51
|
|
||||||
new/dispose 1k 1M 00:00:29
|
|
||||||
new/dispose 128k 1M 00:00:30
|
|
||||||
array copy 1k 10K 00:00:03
|
|
||||||
array copy 128k 1K 00:00:48
|
|
||||||
exp() 10K 00:00:32
|
|
||||||
cos() 10K 00:00:06
|
|
||||||
|
|
||||||
--------------------------------------
|
|
||||||
Arty-A7-35T
|
|
||||||
76.92MHz, 64KB SRAM, 256MB DRAM, 16B instruction cache
|
|
||||||
running in DRAM (except corelib, stdlib, runtime)
|
|
||||||
|
|
||||||
Running benchmarks.prog
|
|
||||||
empty loop 10M 00:00:16
|
|
||||||
write variable 10M 00:00:17
|
|
||||||
read variable 10M 00:00:19
|
|
||||||
integer addition 10M 00:00:24
|
|
||||||
real addition 1M 00:00:30
|
|
||||||
integer multiplication 1M 00:01:14
|
|
||||||
real multiplication 1M 00:01:05
|
|
||||||
integer division 1M 00:01:53
|
|
||||||
real division 1M 00:01:13
|
|
||||||
string indexing 1M 00:00:41
|
|
||||||
string iteration 1M 00:00:21
|
|
||||||
new/dispose 1k 1M 00:00:25
|
|
||||||
new/dispose 128k 1M 00:00:26
|
|
||||||
array copy 1k 10K 00:00:03
|
|
||||||
array copy 128k 1K 00:00:48
|
|
||||||
exp() 10K 00:00:32
|
|
||||||
cos() 10K 00:00:06
|
|
||||||
|
|
||||||
--------------------------------------
|
|
||||||
Arty-A7-35T
|
|
||||||
76.92MHz, 64KB SRAM, 256MB DRAM,
|
|
||||||
16B instruction cache, 16B wt data cache
|
|
||||||
running in SRAM
|
|
||||||
|
|
||||||
Running benchmarks.prog
|
|
||||||
empty loop 10M 00:00:07
|
|
||||||
write variable 10M 00:00:17
|
|
||||||
read variable 10M 00:00:20
|
|
||||||
integer addition 10M 00:00:20
|
|
||||||
real addition 1M 00:00:28
|
|
||||||
integer multiplication 1M 00:01:11
|
|
||||||
real multiplication 1M 00:00:59
|
|
||||||
integer division 1M 00:01:36
|
|
||||||
real division 1M 00:01:05
|
|
||||||
string indexing 1M 00:00:39
|
|
||||||
string iteration 1M 00:00:19
|
|
||||||
new/dispose 1k 1M 00:00:19
|
|
||||||
new/dispose 128k 1M 00:00:19
|
|
||||||
array copy 1k 10K 00:00:03
|
|
||||||
array copy 128k 1K 00:00:39
|
|
||||||
exp() 10K 00:00:26
|
|
||||||
cos() 10K 00:00:05
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
--------------------------------------
|
|
||||||
Arty-A7-35T
|
|
||||||
76.92MHz, 64KB SRAM, 256MB DRAM,
|
|
||||||
16B instruction cache, 16B wb data cache
|
|
||||||
running in SRAM
|
|
||||||
|
|
||||||
Running benchmarks.prog
|
|
||||||
empty loop 10M 00:00:04
|
|
||||||
write variable 10M 00:00:11
|
|
||||||
read variable 10M 00:00:18
|
|
||||||
integer addition 10M 00:00:18
|
|
||||||
real addition 1M 00:00:27
|
|
||||||
integer multiplication 1M 00:00:49
|
|
||||||
real multiplication 1M 00:00:58
|
|
||||||
integer division 1M 00:01:06
|
|
||||||
real division 1M 00:01:04
|
|
||||||
string indexing 1M 00:00:36
|
|
||||||
string iteration 1M 00:00:19
|
|
||||||
new/dispose 1k 1M 00:00:18
|
|
||||||
new/dispose 128k 1M 00:00:18
|
|
||||||
array copy 1k 10K 00:00:03
|
|
||||||
array copy 128k 1K 00:00:39
|
|
||||||
exp() 10K 00:00:25
|
|
||||||
cos() 10K 00:00:05
|
|
||||||
|
|
||||||
--------------------------------------
|
|
||||||
Arty-A7-35T
|
|
||||||
76.92MHz, 32KB SRAM, 256MB DRAM,
|
|
||||||
16B instruction cache, 16B wb data cache
|
|
||||||
running in SRAM
|
|
||||||
|
|
||||||
Running benchmarks.prog
|
|
||||||
empty loop 10M 00:00:04
|
|
||||||
write variable 10M 00:00:11
|
|
||||||
read variable 10M 00:00:18
|
|
||||||
integer addition 10M 00:00:18
|
|
||||||
real addition 1M 00:00:27
|
|
||||||
integer multiplication 1M 00:00:49
|
|
||||||
real multiplication 1M 00:00:58
|
|
||||||
integer division 1M 00:01:06
|
|
||||||
real division 1M 00:01:04
|
|
||||||
string indexing 1M 00:00:36
|
|
||||||
string iteration 1M 00:00:19
|
|
||||||
new/dispose 1k 1M 00:00:18
|
|
||||||
new/dispose 128k 1M 00:00:18
|
|
||||||
array copy 1k 10K 00:00:03
|
|
||||||
array copy 128k 1K 00:00:39
|
|
||||||
exp() 10K 00:00:25
|
|
||||||
cos() 10K 00:00:05
|
|
||||||
|
|
||||||
--------------------------------------------
|
|
||||||
Arty-A7-35T
|
|
||||||
76.92MHz, 64KB SRAM, 256MB DRAM,
|
|
||||||
16B instruction cache, 16B wb data cache
|
|
||||||
running in DRAM (except corelib, stdlib, runtime)
|
|
||||||
|
|
||||||
Running benchmarks.prog
|
|
||||||
empty loop 10M 00:00:10
|
|
||||||
write variable 10M 00:00:11
|
|
||||||
read variable 10M 00:00:11
|
|
||||||
integer addition 10M 00:00:13
|
|
||||||
real addition 1M 00:00:27
|
|
||||||
integer multiplication 1M 00:00:35
|
|
||||||
real multiplication 1M 00:00:43
|
|
||||||
integer division 1M 00:01:05
|
|
||||||
real division 1M 00:00:51
|
|
||||||
string indexing 1M 00:00:36
|
|
||||||
string iteration 1M 00:00:20
|
|
||||||
new/dispose 1k 1M 00:00:23
|
|
||||||
new/dispose 128k 1M 00:00:23
|
|
||||||
array copy 1k 10K 00:00:03
|
|
||||||
array copy 128k 1K 00:00:48
|
|
||||||
exp() 10K 00:00:28
|
|
||||||
cos() 10K 00:00:04
|
|
||||||
|
|
@ -1,19 +0,0 @@
|
||||||
JASC-PAL
|
|
||||||
0100
|
|
||||||
16
|
|
||||||
0 0 0
|
|
||||||
255 255 255
|
|
||||||
255 0 0
|
|
||||||
0 255 0
|
|
||||||
0 0 255
|
|
||||||
0 255 255
|
|
||||||
255 0 255
|
|
||||||
255 255 0
|
|
||||||
127 127 127
|
|
||||||
160 160 160
|
|
||||||
127 0 0
|
|
||||||
0 127 0
|
|
||||||
0 0 127
|
|
||||||
0 127 127
|
|
||||||
127 0 127
|
|
||||||
127 127 0
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
const FIREWIDTH = 319; FIREHEIGHT = 79; (* keep in sync with fastfire.s! *)
|
|
||||||
type FireBuf = array [0..FIREHEIGHT, 0..FIREWIDTH] of integer;
|
|
||||||
|
|
||||||
procedure FastFireUpdate(var f:FireBuf); external;
|
|
||||||
procedure FastFireDraw(var f:FireBuf;screenx, screeny:integer); external;
|
|
||||||
|
|
@ -1,326 +0,0 @@
|
||||||
; width and height of the fire cell matrix
|
|
||||||
; Be sure to sync this with fastfire.inc!
|
|
||||||
.EQU FIREWIDTH 319
|
|
||||||
.EQU FIREHEIGHT 79
|
|
||||||
|
|
||||||
;
|
|
||||||
; The cell matrix actually has one column
|
|
||||||
; and one row more than FIREWIDTH and
|
|
||||||
; FIREHEIGHT to handle the negative
|
|
||||||
; X offsets when calculating new
|
|
||||||
; cell values.
|
|
||||||
; Likewise, there is one more row.
|
|
||||||
; So rows are processed from 0 to FIREHEIGHT - 2
|
|
||||||
; and columms from 1 to FIREWIDTH - 1.
|
|
||||||
|
|
||||||
; cells considered for calculating new
|
|
||||||
; value for cell O (reference cells):
|
|
||||||
; .....O......
|
|
||||||
; ....123.....
|
|
||||||
; .....4......
|
|
||||||
|
|
||||||
; args: pointer to fire cell buffer
|
|
||||||
.EQU FF_ROW_COUNT 0
|
|
||||||
.EQU FF_COL_COUNT 4
|
|
||||||
.EQU FF_ROW_OFFS 8
|
|
||||||
.EQU FF_OFFS1 12
|
|
||||||
.EQU FF_OFFS2 16
|
|
||||||
.EQU FF_OFFS3 20
|
|
||||||
.EQU FF_OFFS4 24
|
|
||||||
.EQU FF_CELL_PTR 28
|
|
||||||
.EQU FF_FS 32
|
|
||||||
FASTFIREUPDATE:
|
|
||||||
FPADJ -FF_FS
|
|
||||||
STORE FF_CELL_PTR
|
|
||||||
LOADC FIREHEIGHT-1
|
|
||||||
STORE FF_ROW_COUNT
|
|
||||||
|
|
||||||
; calculate offsets for reference cells
|
|
||||||
LOADC FIREWIDTH+1
|
|
||||||
SHL 2
|
|
||||||
DUP
|
|
||||||
STORE FF_ROW_OFFS ; offset to next row: WIDTH*4
|
|
||||||
DEC 4 ; offset to cell 1: row offset - 4
|
|
||||||
DUP
|
|
||||||
STORE FF_OFFS1
|
|
||||||
INC 4
|
|
||||||
DUP
|
|
||||||
STORE FF_OFFS2 ; offset to cell 2: + 4
|
|
||||||
INC 4
|
|
||||||
STORE FF_OFFS3 ; offset to cell 3: + 4
|
|
||||||
LOAD FF_ROW_OFFS
|
|
||||||
SHL 1 ; offset to cell 4: row offset * 2
|
|
||||||
STORE FF_OFFS4
|
|
||||||
|
|
||||||
; start at column 1
|
|
||||||
LOAD FF_CELL_PTR
|
|
||||||
INC 4
|
|
||||||
STORE FF_CELL_PTR
|
|
||||||
FF_ROW:
|
|
||||||
LOADC FIREWIDTH-1
|
|
||||||
STORE FF_COL_COUNT
|
|
||||||
|
|
||||||
FF_COL:
|
|
||||||
LOAD FF_CELL_PTR
|
|
||||||
LOAD FF_OFFS1
|
|
||||||
ADD
|
|
||||||
LOADI
|
|
||||||
|
|
||||||
LOAD FF_CELL_PTR
|
|
||||||
LOAD FF_OFFS2
|
|
||||||
ADD
|
|
||||||
LOADI
|
|
||||||
|
|
||||||
LOAD FF_CELL_PTR
|
|
||||||
LOAD FF_OFFS3
|
|
||||||
ADD
|
|
||||||
LOADI
|
|
||||||
|
|
||||||
LOAD FF_CELL_PTR
|
|
||||||
LOAD FF_OFFS4
|
|
||||||
ADD
|
|
||||||
LOADI
|
|
||||||
|
|
||||||
ADD
|
|
||||||
ADD
|
|
||||||
ADD
|
|
||||||
|
|
||||||
SHR
|
|
||||||
SHR
|
|
||||||
|
|
||||||
; if new cell value > 0, subtract 1 to cool down
|
|
||||||
DUP
|
|
||||||
CBRANCH.Z FF_SKIP
|
|
||||||
DEC 1
|
|
||||||
FF_SKIP:
|
|
||||||
LOAD FF_CELL_PTR ; load cell ptr
|
|
||||||
SWAP ; swap with new value
|
|
||||||
STOREI 4 ; store with postincrement
|
|
||||||
STORE FF_CELL_PTR ; save new ptr value
|
|
||||||
|
|
||||||
LOAD FF_COL_COUNT ; decrement column count
|
|
||||||
DEC 1
|
|
||||||
DUP
|
|
||||||
STORE FF_COL_COUNT
|
|
||||||
CBRANCH.NZ FF_COL ; loop if col count <> 0
|
|
||||||
|
|
||||||
; at the end of a row, go to next row
|
|
||||||
; by adding 8 to the cell pointer,
|
|
||||||
; skipping the first cell of the next row
|
|
||||||
LOAD FF_CELL_PTR
|
|
||||||
INC 8
|
|
||||||
STORE FF_CELL_PTR
|
|
||||||
|
|
||||||
LOAD FF_ROW_COUNT ; decrement row count
|
|
||||||
DEC 1
|
|
||||||
DUP
|
|
||||||
STORE FF_ROW_COUNT
|
|
||||||
CBRANCH.NZ FF_ROW ; loop if row count <> 0
|
|
||||||
|
|
||||||
FF_EXIT:
|
|
||||||
FPADJ FF_FS
|
|
||||||
RET
|
|
||||||
|
|
||||||
; framebuffer controller registers
|
|
||||||
.EQU FB_RA $900
|
|
||||||
.EQU FB_WA $904
|
|
||||||
.EQU FB_IO $908
|
|
||||||
.EQU FB_PS $90C
|
|
||||||
.EQU FB_PD $910
|
|
||||||
.EQU FB_CTL $914
|
|
||||||
.EQU WORDS_PER_LINE 80
|
|
||||||
|
|
||||||
; fire width in vmem words (strict left-to-right evaluation)
|
|
||||||
.EQU FFD_ROW_WORDS 1 + FIREWIDTH / 8
|
|
||||||
|
|
||||||
; draw all fire cells
|
|
||||||
; args: pointer to fire cell buffer, screen x, screen y
|
|
||||||
.EQU FFD_CELL_PTR 0
|
|
||||||
.EQU FFD_X 4
|
|
||||||
.EQU FFD_Y 8
|
|
||||||
.EQU FFD_ROW_COUNT 12
|
|
||||||
.EQU FFD_ROW_WORDCOUNT 16
|
|
||||||
.EQU FFD_VMEM_PTR 20
|
|
||||||
.EQU FFD_FS 24
|
|
||||||
FASTFIREDRAW:
|
|
||||||
FPADJ -FFD_FS
|
|
||||||
STORE FFD_Y
|
|
||||||
STORE FFD_X
|
|
||||||
STORE FFD_CELL_PTR
|
|
||||||
|
|
||||||
; calculate video memory addr
|
|
||||||
; addr = y * 80 + X / 8
|
|
||||||
LOAD FFD_Y
|
|
||||||
SHL 2 ; y * 16
|
|
||||||
SHL 2
|
|
||||||
DUP
|
|
||||||
SHL 2 ; + y * 64
|
|
||||||
ADD ; = y * 80
|
|
||||||
|
|
||||||
LOAD FFD_X
|
|
||||||
SHR
|
|
||||||
SHR
|
|
||||||
SHR
|
|
||||||
ADD ; + x / 8
|
|
||||||
|
|
||||||
DUP
|
|
||||||
STORE FFD_VMEM_PTR
|
|
||||||
LOADC FB_WA ; set vmem write address
|
|
||||||
SWAP
|
|
||||||
STOREI
|
|
||||||
DROP
|
|
||||||
|
|
||||||
LOADC FIREHEIGHT + 1
|
|
||||||
STORE FFD_ROW_COUNT
|
|
||||||
FFD_ROW:
|
|
||||||
LOADC FFD_ROW_WORDS
|
|
||||||
STORE FFD_ROW_WORDCOUNT
|
|
||||||
|
|
||||||
LOADC FB_WA ; set vmem write address
|
|
||||||
LOAD FFD_VMEM_PTR
|
|
||||||
STOREI
|
|
||||||
DROP
|
|
||||||
|
|
||||||
FFD_WORD:
|
|
||||||
LOAD FFD_CELL_PTR ; load cell ptr
|
|
||||||
LOADC 0 ; vmem word, start with 0
|
|
||||||
|
|
||||||
; leftmost pixel (0)
|
|
||||||
OVER ; [ cptr, vmemw, cptr ]
|
|
||||||
LOADI ; load cell value [ cptr, vmemw, cellval ]
|
|
||||||
SHR ; scale it down (from 7 bits to 4)
|
|
||||||
SHR
|
|
||||||
SHR ; [ cptr, vmemw, cellval shr 3 ]
|
|
||||||
OR ; [ cptr, vmemw ]
|
|
||||||
SWAP ; [ vmemw, cptr ]
|
|
||||||
INC 4 ; increment cell ptr on stack [ vmemw, cptr + 4 ]
|
|
||||||
SWAP ; [ cptr + 4, vmemw ]
|
|
||||||
|
|
||||||
SHL 2 ; move bits to left for next pixel
|
|
||||||
SHL 2
|
|
||||||
|
|
||||||
; pixel 1
|
|
||||||
OVER
|
|
||||||
LOADI ; load cell value
|
|
||||||
SHR ; scale it down (from 7 bits to 4)
|
|
||||||
SHR
|
|
||||||
SHR
|
|
||||||
OR
|
|
||||||
SWAP
|
|
||||||
INC 4 ; increment cell ptr on stack
|
|
||||||
SWAP
|
|
||||||
|
|
||||||
SHL 2 ; move bits to left for next pixel
|
|
||||||
SHL 2
|
|
||||||
|
|
||||||
; pixel 2
|
|
||||||
OVER
|
|
||||||
LOADI ; load cell value
|
|
||||||
SHR ; scale it down (from 7 bits to 4)
|
|
||||||
SHR
|
|
||||||
SHR
|
|
||||||
OR
|
|
||||||
SWAP
|
|
||||||
INC 4 ; increment cell ptr on stack
|
|
||||||
SWAP
|
|
||||||
|
|
||||||
SHL 2 ; move bits to left for next pixel
|
|
||||||
SHL 2
|
|
||||||
|
|
||||||
; pixel 3
|
|
||||||
OVER
|
|
||||||
LOADI ; load cell value
|
|
||||||
SHR ; scale it down (from 7 bits to 4)
|
|
||||||
SHR
|
|
||||||
SHR
|
|
||||||
OR
|
|
||||||
SWAP
|
|
||||||
INC 4 ; increment cell ptr on stack
|
|
||||||
SWAP
|
|
||||||
|
|
||||||
SHL 2 ; move bits to left for next pixel
|
|
||||||
SHL 2
|
|
||||||
|
|
||||||
; pixel 4
|
|
||||||
OVER
|
|
||||||
LOADI ; load cell value
|
|
||||||
SHR ; scale it down (from 7 bits to 4)
|
|
||||||
SHR
|
|
||||||
SHR
|
|
||||||
OR
|
|
||||||
SWAP
|
|
||||||
INC 4 ; increment cell ptr on stack
|
|
||||||
SWAP
|
|
||||||
|
|
||||||
SHL 2 ; move bits to left for next pixel
|
|
||||||
SHL 2
|
|
||||||
|
|
||||||
; pixel 5
|
|
||||||
OVER
|
|
||||||
LOADI ; load cell value
|
|
||||||
SHR ; scale it down (from 7 bits to 4)
|
|
||||||
SHR
|
|
||||||
SHR
|
|
||||||
OR
|
|
||||||
SWAP
|
|
||||||
INC 4 ; increment cell ptr on stack
|
|
||||||
SWAP
|
|
||||||
|
|
||||||
SHL 2 ; move bits to left for next pixel
|
|
||||||
SHL 2
|
|
||||||
|
|
||||||
; pixel 6
|
|
||||||
OVER
|
|
||||||
LOADI ; load cell value
|
|
||||||
SHR ; scale it down (from 7 bits to 4)
|
|
||||||
SHR
|
|
||||||
SHR
|
|
||||||
OR
|
|
||||||
SWAP
|
|
||||||
INC 4 ; increment cell ptr on stack
|
|
||||||
SWAP
|
|
||||||
|
|
||||||
SHL 2 ; move bits to left for next pixel
|
|
||||||
SHL 2
|
|
||||||
|
|
||||||
; pixel 7
|
|
||||||
OVER
|
|
||||||
LOADI ; load cell value
|
|
||||||
SHR ; scale it down (from 7 bits to 4)
|
|
||||||
SHR
|
|
||||||
SHR
|
|
||||||
OR
|
|
||||||
SWAP
|
|
||||||
INC 4 ; increment cell ptr on stack
|
|
||||||
SWAP
|
|
||||||
|
|
||||||
; store word to vmem
|
|
||||||
; vmem write addr will autoincrement
|
|
||||||
LOADC FB_IO
|
|
||||||
SWAP
|
|
||||||
STOREI
|
|
||||||
DROP
|
|
||||||
|
|
||||||
STORE FFD_CELL_PTR
|
|
||||||
|
|
||||||
; prepare for next word
|
|
||||||
LOAD FFD_ROW_WORDCOUNT
|
|
||||||
DEC 1
|
|
||||||
DUP
|
|
||||||
STORE FFD_ROW_WORDCOUNT
|
|
||||||
CBRANCH.NZ FFD_WORD
|
|
||||||
|
|
||||||
; prepare for next row
|
|
||||||
LOAD FFD_VMEM_PTR
|
|
||||||
LOADC WORDS_PER_LINE
|
|
||||||
ADD
|
|
||||||
STORE FFD_VMEM_PTR
|
|
||||||
|
|
||||||
LOAD FFD_ROW_COUNT
|
|
||||||
DEC 1
|
|
||||||
DUP
|
|
||||||
STORE FFD_ROW_COUNT
|
|
||||||
CBRANCH.NZ FFD_ROW
|
|
||||||
FFD_EXIT:
|
|
||||||
FPADJ FFD_FS
|
|
||||||
RET
|
|
||||||
|
|
@ -1,76 +0,0 @@
|
||||||
{$H1}
|
|
||||||
{$S2}
|
|
||||||
program fire;
|
|
||||||
const MAXX = 30;
|
|
||||||
MAXY = 50;
|
|
||||||
var firebuf: array [0..MAXY, 0..MAXX] of integer;
|
|
||||||
|
|
||||||
firepalette: array [0..15] of integer =
|
|
||||||
( $FFA, $FF8, $FF4, $FF0, $FE0, $FD0, $FA0, $F90,
|
|
||||||
$F00, $E00, $D00, $A00, $800, $600, $300, $000);
|
|
||||||
x,y:integer;
|
|
||||||
|
|
||||||
procedure createPalette;
|
|
||||||
var i:integer;
|
|
||||||
begin
|
|
||||||
for i := 15 downto 0 do
|
|
||||||
setpalette(15 - i, firepalette[i]);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure fireItUp;
|
|
||||||
var x,y:integer;
|
|
||||||
begin
|
|
||||||
y := MAXY - 1;
|
|
||||||
for x := 1 to MAXX - 1 do
|
|
||||||
firebuf[y, x] := random and 127;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure updateFire;
|
|
||||||
var i,x,y:integer;
|
|
||||||
begin
|
|
||||||
for y := 0 to MAXY - 2 do
|
|
||||||
for x := 1 to MAXX - 1 do
|
|
||||||
begin
|
|
||||||
i :=
|
|
||||||
((firebuf[y + 1, x - 1]
|
|
||||||
+ firebuf[y + 1, x]
|
|
||||||
+ firebuf[y + 1, x + 1]
|
|
||||||
+ firebuf[y + 2, x])
|
|
||||||
) shr 2;
|
|
||||||
if i > 0 then
|
|
||||||
i := i - 1;
|
|
||||||
firebuf[y, x] := i;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure drawFire;
|
|
||||||
var x, y, col:integer;
|
|
||||||
begin
|
|
||||||
for y := 0 to MAXY - 1 do
|
|
||||||
begin
|
|
||||||
x := 0;
|
|
||||||
for col in firebuf[y] do
|
|
||||||
begin
|
|
||||||
putpixel(300 + x, 150 + y, col shr 3);
|
|
||||||
x := x + 1;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
begin
|
|
||||||
randomize;
|
|
||||||
initgraphics;
|
|
||||||
createPalette;
|
|
||||||
while not conavail do
|
|
||||||
begin
|
|
||||||
fireItUp;
|
|
||||||
updateFire;
|
|
||||||
drawFire;
|
|
||||||
end;
|
|
||||||
|
|
||||||
for y := 0 to MAXY do
|
|
||||||
begin
|
|
||||||
x := firebuf[y, 10];
|
|
||||||
drawline(0, y, x, y, 1);
|
|
||||||
end;
|
|
||||||
end.
|
|
||||||
|
|
@ -1,84 +0,0 @@
|
||||||
{$H1}
|
|
||||||
{$S1}
|
|
||||||
program fire2;
|
|
||||||
uses fastfire;
|
|
||||||
|
|
||||||
const MAXX = FIREWIDTH;
|
|
||||||
MAXY = FIREHEIGHT;
|
|
||||||
|
|
||||||
var firecells: FireBuf;
|
|
||||||
|
|
||||||
firepalette: array [0..15] of integer =
|
|
||||||
{ ( $FFA, $FF8, $FF4, $FF0, $FE0, $FD0, $FA0, $F90,
|
|
||||||
$F00, $E00, $D00, $A00, $800, $600, $300, $000); }
|
|
||||||
( $FFA, $FFA, $FFA, $FFA, $FF0, $FF0, $FF0, $FF0,
|
|
||||||
$FF0, $FD0, $FA0, $C00, $A00, $700, $400, $000);
|
|
||||||
x,y:integer;
|
|
||||||
|
|
||||||
procedure createPalette;
|
|
||||||
var i:integer;
|
|
||||||
begin
|
|
||||||
for i := 15 downto 0 do
|
|
||||||
setpalette(15 - i, firepalette[i]);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure fireItUp;
|
|
||||||
var x,y:integer;
|
|
||||||
begin
|
|
||||||
y := MAXY - 1;
|
|
||||||
for x := 1 to MAXX - 1 do
|
|
||||||
firecells[y, x] := random and 127;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
procedure updateFire;
|
|
||||||
var i,x,y:integer;
|
|
||||||
begin
|
|
||||||
for y := 0 to MAXY - 2 do
|
|
||||||
for x := 1 to MAXX - 1 do
|
|
||||||
begin
|
|
||||||
i :=
|
|
||||||
((firecells[y + 1, x - 1]
|
|
||||||
+ firecells[y + 1, x]
|
|
||||||
+ firecells[y + 1, x + 1]
|
|
||||||
+ firecells[y + 2, x])
|
|
||||||
) shr 2;
|
|
||||||
if i > 0 then
|
|
||||||
i := i - 1;
|
|
||||||
firecells[y, x] := i;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure drawFire;
|
|
||||||
var x, y, col:integer;
|
|
||||||
begin
|
|
||||||
for y := 0 to MAXY - 1 do
|
|
||||||
begin
|
|
||||||
x := 0;
|
|
||||||
for col in firecells[y] do
|
|
||||||
begin
|
|
||||||
putpixel(100 + x, 150 + y, col shr 3);
|
|
||||||
x := x + 1;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
begin
|
|
||||||
randomize;
|
|
||||||
initgraphics;
|
|
||||||
createPalette;
|
|
||||||
while not conavail do
|
|
||||||
begin
|
|
||||||
fireItUp;
|
|
||||||
FastFireUpdate(firecells);
|
|
||||||
{ updateFire; }
|
|
||||||
FastFireDraw(firecells, 160, 100);
|
|
||||||
{ drawFire; }
|
|
||||||
end;
|
|
||||||
|
|
||||||
for y := 0 to MAXY do
|
|
||||||
begin
|
|
||||||
x := firecells[y, 10];
|
|
||||||
drawline(0, y, x, y, 1);
|
|
||||||
end;
|
|
||||||
end.
|
|
||||||
|
|
@ -1,125 +0,0 @@
|
||||||
program graphbench;
|
|
||||||
uses sprites;
|
|
||||||
|
|
||||||
var starttime,endtime:DateTime;
|
|
||||||
spriteData:SpritePixels;
|
|
||||||
|
|
||||||
procedure readSpriteData(filename:string);
|
|
||||||
var f:file;
|
|
||||||
begin
|
|
||||||
open(f,filename,ModeReadOnly);
|
|
||||||
seek(f,8); (* skip file header *)
|
|
||||||
read(f,spriteData);
|
|
||||||
close(f);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure startBench(name:string);
|
|
||||||
begin
|
|
||||||
write(name:20, ' ');
|
|
||||||
starttime := GetTime;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure endBench;
|
|
||||||
var secDelta, minDelta, hourDelta:integer;
|
|
||||||
procedure write2Digits(i:integer);
|
|
||||||
begin
|
|
||||||
if i < 10 then
|
|
||||||
write('0');
|
|
||||||
write(i);
|
|
||||||
end;
|
|
||||||
begin
|
|
||||||
endTime := GetTime;
|
|
||||||
|
|
||||||
hourDelta := endtime.hours - starttime.hours;
|
|
||||||
minDelta := endtime.minutes - starttime.minutes;
|
|
||||||
secDelta := endtime.seconds - starttime.seconds;
|
|
||||||
|
|
||||||
if secDelta < 0 then
|
|
||||||
begin
|
|
||||||
secDelta := 60 + secDelta;
|
|
||||||
minDelta := minDelta - 1;
|
|
||||||
end;
|
|
||||||
|
|
||||||
if minDelta < 0 then
|
|
||||||
begin
|
|
||||||
minDelta := 60 + minDelta;
|
|
||||||
hourDelta := hourDelta - 1;
|
|
||||||
end;
|
|
||||||
|
|
||||||
write2Digits(hourDelta);
|
|
||||||
write(':'); write2Digits(minDelta);
|
|
||||||
write(':'); write2Digits(secDelta);
|
|
||||||
writeln;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function randint(lessthan:integer):integer;
|
|
||||||
var r:integer;
|
|
||||||
begin
|
|
||||||
r := random and 511;
|
|
||||||
if r >= lessthan then
|
|
||||||
r := r - lessthan;
|
|
||||||
randint := r;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure drawsprites(count:integer);
|
|
||||||
var i,col,x,y:integer;
|
|
||||||
begin
|
|
||||||
col := 1;
|
|
||||||
for i := 1 to count do
|
|
||||||
begin
|
|
||||||
x := randint(350);
|
|
||||||
y := randint(350);
|
|
||||||
PutSprite(x,y,spriteData);
|
|
||||||
col := col + 1;
|
|
||||||
if col > 15 then col := 1;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure drawlines(count:integer);
|
|
||||||
var i,col,x1,y1,x2,y2:integer;
|
|
||||||
begin
|
|
||||||
col := 1;
|
|
||||||
for i := 1 to count do
|
|
||||||
begin
|
|
||||||
x1 := randint(500);
|
|
||||||
y1 := randint(400);
|
|
||||||
x2 := randint(500);
|
|
||||||
y2 := randint(400);
|
|
||||||
DrawLine(x1,y1,x2,y2,col);
|
|
||||||
col := col + 1;
|
|
||||||
if col > 15 then col := 1;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure drawpoints(count:integer);
|
|
||||||
var i,col,x,y:integer;
|
|
||||||
begin
|
|
||||||
col := 1;
|
|
||||||
for i := 1 to count do
|
|
||||||
begin
|
|
||||||
x := randint(500);
|
|
||||||
y := randint(400);
|
|
||||||
PutPixel(x,y,col);
|
|
||||||
col := col + 1;
|
|
||||||
if col > 15 then col := 1;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
begin
|
|
||||||
readSpriteData('sprite-testcard.sprt');
|
|
||||||
|
|
||||||
InitGraphics;
|
|
||||||
startBench('points 200K');
|
|
||||||
drawpoints(200000);
|
|
||||||
endBench;
|
|
||||||
|
|
||||||
InitGraphics;
|
|
||||||
startBench('lines 10K');
|
|
||||||
drawlines(10000);
|
|
||||||
endBench;
|
|
||||||
|
|
||||||
InitGraphics;
|
|
||||||
startBench('sprites 50K');
|
|
||||||
drawsprites(50000);
|
|
||||||
endBench;
|
|
||||||
end.
|
|
||||||
Binary file not shown.
|
|
@ -1,56 +0,0 @@
|
||||||
{$H2560}
|
|
||||||
program pcmtest2;
|
|
||||||
uses pcmaudio;
|
|
||||||
|
|
||||||
var filename:string;
|
|
||||||
buf:SndBufPtr;
|
|
||||||
sampleRate:integer;
|
|
||||||
err:integer;
|
|
||||||
done:boolean;
|
|
||||||
c:char;
|
|
||||||
|
|
||||||
function readAudioFile(fname:string):SndBufPtr;
|
|
||||||
var i,size:integer;
|
|
||||||
c:char;
|
|
||||||
buf:SndBufPtr;
|
|
||||||
f:file;
|
|
||||||
begin
|
|
||||||
open(f, fname, ModeReadOnly);
|
|
||||||
size := FileSize(f);
|
|
||||||
new(buf, size);
|
|
||||||
|
|
||||||
buf^ := '';
|
|
||||||
write('Reading ', size, ' bytes...');
|
|
||||||
for i := 1 to size do
|
|
||||||
begin
|
|
||||||
read(f,c);
|
|
||||||
AppendChar(buf^,c);
|
|
||||||
end;
|
|
||||||
writeln;
|
|
||||||
|
|
||||||
close(f);
|
|
||||||
|
|
||||||
readAudioFile := buf;
|
|
||||||
end;
|
|
||||||
|
|
||||||
begin
|
|
||||||
if ParamCount > 0 then
|
|
||||||
filename := ParamStr(1)
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
write('Filename> ');
|
|
||||||
readln(filename);
|
|
||||||
end;
|
|
||||||
|
|
||||||
err := 1;
|
|
||||||
if ParamCount > 1 then
|
|
||||||
val(ParamStr(2), sampleRate, err);
|
|
||||||
if err > 0 then
|
|
||||||
sampleRate := 22050;
|
|
||||||
|
|
||||||
buf := readAudioFile(filename);
|
|
||||||
|
|
||||||
PlaySample(buf, sampleRate);
|
|
||||||
|
|
||||||
dispose(buf);
|
|
||||||
end.
|
|
||||||
|
|
@ -1,74 +0,0 @@
|
||||||
{$H2560}
|
|
||||||
program pcmtest2;
|
|
||||||
uses pcmaudio;
|
|
||||||
|
|
||||||
var filename:string;
|
|
||||||
buf:SndBufPtr;
|
|
||||||
sampleRate:integer;
|
|
||||||
err:integer;
|
|
||||||
done:boolean;
|
|
||||||
c:char;
|
|
||||||
|
|
||||||
function readAudioFile(fname:string):SndBufPtr;
|
|
||||||
var i,size:integer;
|
|
||||||
c:char;
|
|
||||||
buf:SndBufPtr;
|
|
||||||
f:file;
|
|
||||||
begin
|
|
||||||
open(f, fname, ModeReadOnly);
|
|
||||||
size := FileSize(f);
|
|
||||||
new(buf, size);
|
|
||||||
|
|
||||||
buf^ := '';
|
|
||||||
write('Reading ', size, ' bytes...');
|
|
||||||
for i := 1 to size do
|
|
||||||
begin
|
|
||||||
read(f,c);
|
|
||||||
AppendChar(buf^,c);
|
|
||||||
end;
|
|
||||||
writeln;
|
|
||||||
|
|
||||||
close(f);
|
|
||||||
|
|
||||||
readAudioFile := buf;
|
|
||||||
end;
|
|
||||||
|
|
||||||
begin
|
|
||||||
if ParamCount > 0 then
|
|
||||||
filename := ParamStr(1)
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
write('Filename> ');
|
|
||||||
readln(filename);
|
|
||||||
end;
|
|
||||||
|
|
||||||
err := 1;
|
|
||||||
if ParamCount > 1 then
|
|
||||||
val(ParamStr(2), sampleRate, err);
|
|
||||||
if err > 0 then
|
|
||||||
sampleRate := 32000;
|
|
||||||
|
|
||||||
buf := readAudioFile(filename);
|
|
||||||
|
|
||||||
SampleQStart(buf, false, sampleRate);
|
|
||||||
|
|
||||||
write('Press ESC to stop> ');
|
|
||||||
done := false;
|
|
||||||
while not done do
|
|
||||||
begin
|
|
||||||
read(c);
|
|
||||||
if c = #27 then
|
|
||||||
begin
|
|
||||||
done := true; writeln(';');
|
|
||||||
end
|
|
||||||
else
|
|
||||||
if c = '?' then
|
|
||||||
begin
|
|
||||||
writeln; writeln('Queue: ', SampleQSize);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
SampleQStop;
|
|
||||||
|
|
||||||
dispose(buf);
|
|
||||||
end.
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -1,5 +0,0 @@
|
||||||
type SpritePixels = array[0..128] of integer;
|
|
||||||
type BackgroundPixels = array[0..31999] of integer;
|
|
||||||
|
|
||||||
procedure PutSprite(x,y:integer; var sprite: SpritePixels); external;
|
|
||||||
procedure UndrawSprite(x,y:integer; var background: BackgroundPixels); external;
|
|
||||||
|
|
@ -1,287 +0,0 @@
|
||||||
.EQU SPRITE_HEIGHT 32 ; height in lines
|
|
||||||
.EQU SPRITE_STRIPES 4 ; width in words i.e. 8-pixel stripes
|
|
||||||
|
|
||||||
.EQU WORDS_PER_LINE 80
|
|
||||||
.EQU FB_RA $900
|
|
||||||
.EQU FB_WA $904
|
|
||||||
.EQU FB_IO $908
|
|
||||||
.EQU FB_PS $90C
|
|
||||||
.EQU FB_PD $910
|
|
||||||
.EQU FB_CTL $914
|
|
||||||
.EQU FB_SHIFTER $918
|
|
||||||
.EQU FB_SHIFTCOUNT $91C
|
|
||||||
.EQU FB_SHIFTERM $920
|
|
||||||
.EQU FB_SHIFTERSP $924
|
|
||||||
.EQU FB_MASKGEN $928
|
|
||||||
|
|
||||||
; calculate vmem address from coordinates
|
|
||||||
; args: x,y
|
|
||||||
; returns: vmem word number
|
|
||||||
CALC_VMEM_ADDR:
|
|
||||||
; only works if WORDS_PER_LINE is 80
|
|
||||||
; and pixels per word is 8
|
|
||||||
|
|
||||||
DUP
|
|
||||||
; y
|
|
||||||
SHL 2
|
|
||||||
SHL 2
|
|
||||||
SHL 2 ; * 64
|
|
||||||
|
|
||||||
SWAP
|
|
||||||
; + y
|
|
||||||
SHL 2
|
|
||||||
SHL 2 ; * 16
|
|
||||||
ADD
|
|
||||||
|
|
||||||
SWAP
|
|
||||||
; word offset = X/8
|
|
||||||
SHR
|
|
||||||
SHR
|
|
||||||
SHR
|
|
||||||
ADD
|
|
||||||
|
|
||||||
RET
|
|
||||||
|
|
||||||
; put a sprite on screen
|
|
||||||
; arg: x,y pointer to sprite data
|
|
||||||
.EQU PS_VMEM_ADDR 0
|
|
||||||
.EQU PS_SPRITE_DATA 4
|
|
||||||
.EQU PS_SPRITE_LINES 8
|
|
||||||
.EQU PS_X 12
|
|
||||||
.EQU PS_Y 16
|
|
||||||
.EQU PS_SHIFT_C 20
|
|
||||||
.EQU PS_SPILL 24
|
|
||||||
.EQU PS_STRIPE_C 28
|
|
||||||
.EQU PS_BPSAVE 32
|
|
||||||
.EQU PS_FS_ 36
|
|
||||||
PUTSPRITE:
|
|
||||||
FPADJ -PS_FS_
|
|
||||||
STORE PS_SPRITE_DATA
|
|
||||||
STORE PS_Y
|
|
||||||
STORE PS_X
|
|
||||||
|
|
||||||
LOADREG BP
|
|
||||||
STORE PS_BPSAVE
|
|
||||||
LOADC 0
|
|
||||||
STOREREG BP
|
|
||||||
|
|
||||||
; calculate vmem address
|
|
||||||
LOAD PS_X
|
|
||||||
LOAD PS_Y
|
|
||||||
LOADCP CALC_VMEM_ADDR
|
|
||||||
CALL
|
|
||||||
STORE PS_VMEM_ADDR
|
|
||||||
|
|
||||||
LOADC SPRITE_HEIGHT
|
|
||||||
STORE PS_SPRITE_LINES
|
|
||||||
|
|
||||||
; loop over each line of the sprite
|
|
||||||
PS_LOOP1:
|
|
||||||
; set read and write address
|
|
||||||
; in the vga controller
|
|
||||||
LOAD PS_VMEM_ADDR
|
|
||||||
DUP
|
|
||||||
STORE.B FB_RA
|
|
||||||
STORE.B FB_WA
|
|
||||||
|
|
||||||
LOAD PS_SPRITE_DATA ; address of sprite data
|
|
||||||
DUP
|
|
||||||
INC 4 ; increment pointer
|
|
||||||
STORE PS_SPRITE_DATA ; and store it again
|
|
||||||
LOADI ; load word from orig. address
|
|
||||||
|
|
||||||
; ------- one word of sprite pixels on stack
|
|
||||||
|
|
||||||
STORE.B FB_SHIFTER
|
|
||||||
LOAD PS_X
|
|
||||||
STORE.B FB_SHIFTCOUNT
|
|
||||||
|
|
||||||
LOAD.B FB_SHIFTERM ; get shifted mask
|
|
||||||
NOT
|
|
||||||
LOAD.B FB_IO ; and background pixel data
|
|
||||||
AND ; remove foreground pixels
|
|
||||||
|
|
||||||
LOAD.B FB_SHIFTER ; get shifted pixels
|
|
||||||
OR ; combine with background
|
|
||||||
STORE.B FB_IO ; store into vmem
|
|
||||||
|
|
||||||
; set counter for remaining stripes
|
|
||||||
LOADC SPRITE_STRIPES - 1
|
|
||||||
STORE PS_STRIPE_C
|
|
||||||
|
|
||||||
;
|
|
||||||
; process spilled bits and next vertical stripe of sprite data
|
|
||||||
;
|
|
||||||
PS_NEXT_STRIPE:
|
|
||||||
;use spill bits from first column
|
|
||||||
LOAD.B FB_SHIFTERSP
|
|
||||||
|
|
||||||
LOAD PS_SPRITE_DATA ; address of sprite data
|
|
||||||
DUP
|
|
||||||
INC 4 ; increment pointer
|
|
||||||
STORE PS_SPRITE_DATA ; and store it again
|
|
||||||
LOADI ; load word from orig. address
|
|
||||||
|
|
||||||
STORE.B FB_SHIFTER ; store into shifter
|
|
||||||
LOAD PS_X
|
|
||||||
STORE.B FB_SHIFTCOUNT ; shift stuff
|
|
||||||
LOAD.B FB_SHIFTER ; get shifted pixels
|
|
||||||
OR ; combine with spill bits (see above)
|
|
||||||
DUP
|
|
||||||
STORE.B FB_MASKGEN ; store to mask reg to get new mask
|
|
||||||
|
|
||||||
LOAD.B FB_MASKGEN ; get mask for spill bits + shifted pixels
|
|
||||||
NOT
|
|
||||||
LOAD.B FB_IO ; get vmem data
|
|
||||||
AND ; remove foreground pixels from bg
|
|
||||||
|
|
||||||
OR ; combine with shifted pixels
|
|
||||||
STORE.B FB_IO ; write to vmem
|
|
||||||
|
|
||||||
LOAD PS_STRIPE_C ; decrement stripe count
|
|
||||||
DEC 1
|
|
||||||
DUP
|
|
||||||
STORE PS_STRIPE_C
|
|
||||||
CBRANCH.NZ PS_NEXT_STRIPE ; if non-zero, next stripe
|
|
||||||
|
|
||||||
; write spilled bits of the last stripe into next vmem word
|
|
||||||
LOAD.B FB_SHIFTERSP ; get spill bits
|
|
||||||
DUP
|
|
||||||
STORE.B FB_MASKGEN
|
|
||||||
LOAD.B FB_MASKGEN ; get sprite mask for spill bits
|
|
||||||
NOT
|
|
||||||
|
|
||||||
LOAD.B FB_IO ; load next vmem word
|
|
||||||
AND ; apply sprite mask
|
|
||||||
|
|
||||||
OR ; OR in spill bits
|
|
||||||
|
|
||||||
STORE.B FB_IO ; write to vmem
|
|
||||||
|
|
||||||
LOAD PS_SPRITE_LINES ; decrement lines count
|
|
||||||
DEC 1
|
|
||||||
DUP
|
|
||||||
CBRANCH.Z PS_L_XT ; exit if zero
|
|
||||||
STORE PS_SPRITE_LINES
|
|
||||||
; prepare next line
|
|
||||||
LOAD PS_VMEM_ADDR
|
|
||||||
LOADC WORDS_PER_LINE ; increment to next screen line
|
|
||||||
ADD
|
|
||||||
STORE PS_VMEM_ADDR
|
|
||||||
BRANCH PS_LOOP1
|
|
||||||
PS_L_XT:
|
|
||||||
DROP
|
|
||||||
|
|
||||||
LOAD PS_BPSAVE
|
|
||||||
STOREREG BP
|
|
||||||
|
|
||||||
FPADJ PS_FS_
|
|
||||||
RET
|
|
||||||
|
|
||||||
; undraw a sprite, i.e. draw background data
|
|
||||||
; over a sprite location
|
|
||||||
; args: x,y, ptr to background data
|
|
||||||
.EQU UD_S_X 0
|
|
||||||
.EQU UD_S_Y 4
|
|
||||||
.EQU UD_S_PXS 8
|
|
||||||
.EQU UD_S_BGDATA 12
|
|
||||||
.EQU UD_S_OFFSET 16
|
|
||||||
.EQU UD_S_BGORIG 20
|
|
||||||
.EQU UD_STRIPE_C 24
|
|
||||||
.EQU UD_S_FS 28
|
|
||||||
UNDRAWSPRITE:
|
|
||||||
FPADJ -UD_S_FS
|
|
||||||
STORE UD_S_BGORIG
|
|
||||||
STORE UD_S_Y
|
|
||||||
STORE UD_S_X
|
|
||||||
|
|
||||||
; calculate pixel shift
|
|
||||||
LOAD UD_S_X
|
|
||||||
LOADC $7
|
|
||||||
AND
|
|
||||||
STORE UD_S_PXS
|
|
||||||
|
|
||||||
; calculate vmem offset
|
|
||||||
LOAD UD_S_X
|
|
||||||
LOAD UD_S_Y
|
|
||||||
LOADCP CALC_VMEM_ADDR
|
|
||||||
CALL
|
|
||||||
|
|
||||||
DUP
|
|
||||||
STORE UD_S_OFFSET
|
|
||||||
|
|
||||||
; calculate background data address from offset
|
|
||||||
SHL 2
|
|
||||||
LOAD UD_S_BGORIG
|
|
||||||
ADD
|
|
||||||
STORE UD_S_BGDATA
|
|
||||||
|
|
||||||
LOADC SPRITE_HEIGHT ; line count
|
|
||||||
UD_S_L1:
|
|
||||||
; store vmem offset into write addr reg
|
|
||||||
LOADCP FB_WA
|
|
||||||
LOAD UD_S_OFFSET
|
|
||||||
STOREI 4 ; ugly but fast: reuse addr
|
|
||||||
; with postincrement to
|
|
||||||
; get to FB_IO for STOREI below
|
|
||||||
|
|
||||||
; load a word of background data
|
|
||||||
LOAD UD_S_BGDATA
|
|
||||||
LOADI
|
|
||||||
; and write it to vmem
|
|
||||||
STOREI
|
|
||||||
; reuse addr from STOREI
|
|
||||||
|
|
||||||
LOADC SPRITE_STRIPES - 1 ; set remaining stripe count
|
|
||||||
STORE UD_STRIPE_C
|
|
||||||
|
|
||||||
UD_NEXT_STRIPE:
|
|
||||||
; load next word of background data
|
|
||||||
LOAD UD_S_BGDATA
|
|
||||||
INC 4
|
|
||||||
DUP
|
|
||||||
STORE UD_S_BGDATA
|
|
||||||
LOADI
|
|
||||||
STOREI ; and write it to vmem
|
|
||||||
; reuse addr from STOREI
|
|
||||||
|
|
||||||
LOAD UD_STRIPE_C ; decrease remaining stripe count
|
|
||||||
DEC 1
|
|
||||||
DUP
|
|
||||||
STORE UD_STRIPE_C
|
|
||||||
CBRANCH.NZ UD_NEXT_STRIPE ; if non-zero, next stripe
|
|
||||||
|
|
||||||
DROP ; remove addr from STOREI
|
|
||||||
|
|
||||||
; if pixel shift is zero, no spill word
|
|
||||||
LOAD UD_S_PXS
|
|
||||||
CBRANCH.Z UD_S_L2
|
|
||||||
|
|
||||||
; load next word of background data
|
|
||||||
LOADCP FB_IO
|
|
||||||
LOAD UD_S_BGDATA
|
|
||||||
INC 4
|
|
||||||
LOADI
|
|
||||||
STOREI ; and write it to vmem
|
|
||||||
DROP
|
|
||||||
|
|
||||||
UD_S_L2:
|
|
||||||
LOAD UD_S_OFFSET
|
|
||||||
LOADCP WORDS_PER_LINE
|
|
||||||
ADD
|
|
||||||
DUP
|
|
||||||
STORE UD_S_OFFSET
|
|
||||||
SHL 2
|
|
||||||
LOAD UD_S_BGORIG
|
|
||||||
ADD
|
|
||||||
STORE UD_S_BGDATA
|
|
||||||
|
|
||||||
DEC 1 ; decrement counter
|
|
||||||
DUP
|
|
||||||
CBRANCH.NZ UD_S_L1 ; check for zero
|
|
||||||
|
|
||||||
DROP ; remove counter
|
|
||||||
|
|
||||||
FPADJ UD_S_FS
|
|
||||||
RET
|
|
||||||
|
|
||||||
Binary file not shown.
|
|
@ -1,4 +1,4 @@
|
||||||
program pictviewer;
|
program viewpict;
|
||||||
type PictData = record
|
type PictData = record
|
||||||
magic, mode:integer;
|
magic, mode:integer;
|
||||||
palette: array [0..15] of integer;
|
palette: array [0..15] of integer;
|
||||||
|
|
@ -40,4 +40,5 @@ begin
|
||||||
|
|
||||||
loadPalette(pic);
|
loadPalette(pic);
|
||||||
loadPic(pic);
|
loadPic(pic);
|
||||||
|
read(ch);
|
||||||
end.
|
end.
|
||||||
Binary file not shown.
|
|
@ -1,224 +0,0 @@
|
||||||
(* This program does not work anymore, because
|
|
||||||
it uses the old sprite routines with 16x16 sprites.
|
|
||||||
It is only included for historical reasons.
|
|
||||||
*)
|
|
||||||
program XmasAnimation;
|
|
||||||
uses sprites;
|
|
||||||
|
|
||||||
type PictData = record
|
|
||||||
magic, mode:integer;
|
|
||||||
palette: array [0..15] of integer;
|
|
||||||
pixeldata: array [0..31999] of integer;
|
|
||||||
end;
|
|
||||||
|
|
||||||
Sprite = record
|
|
||||||
x,y:integer;
|
|
||||||
oldX,oldY:integer;
|
|
||||||
xdelta,ydelta:integer;
|
|
||||||
curFrame:integer;
|
|
||||||
frameCount:integer;
|
|
||||||
frameTime:integer;
|
|
||||||
frameLeft:integer;
|
|
||||||
changed:boolean;
|
|
||||||
frame:array [0..3] of SpritePixels;
|
|
||||||
end;
|
|
||||||
|
|
||||||
var pic:PictData;
|
|
||||||
filename:string;
|
|
||||||
infile:file;
|
|
||||||
ch:char;
|
|
||||||
santaSprite: Sprite;
|
|
||||||
deerSprite: Sprite;
|
|
||||||
ohDeerSprite: Sprite;
|
|
||||||
rudolfSprite: Sprite;
|
|
||||||
smokeSprite: Sprite;
|
|
||||||
|
|
||||||
procedure WaitVSync; external;
|
|
||||||
|
|
||||||
procedure loadPalette(var pic:PictData);
|
|
||||||
var i:integer;
|
|
||||||
begin
|
|
||||||
for i := 0 to 15 do
|
|
||||||
setpalette(i, pic.palette[i]);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure showPic(var pic:PictData);
|
|
||||||
begin
|
|
||||||
PutScreen(pic.pixeldata);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure loadSpriteFrame(var aSprite:Sprite;spriteIndex:integer;
|
|
||||||
var sheetFile:file;sheetIndex:integer);
|
|
||||||
begin
|
|
||||||
seek(sheetFile, 8 + sheetIndex * 128);
|
|
||||||
read(sheetFile, aSprite.frame[spriteIndex]);
|
|
||||||
if aSprite.frameCount <= spriteIndex then
|
|
||||||
aSprite.frameCount := spriteIndex + 1;
|
|
||||||
|
|
||||||
aSprite.curFrame := 0;
|
|
||||||
writeln('loaded sprite frame ', spriteIndex, ' from ', sheetIndex);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure animateSprite(var aSprite:Sprite);
|
|
||||||
var frameIndex:integer;
|
|
||||||
frameTime,frameLeft:integer;
|
|
||||||
ydelta:integer;
|
|
||||||
oldX,oldY:integer;
|
|
||||||
begin
|
|
||||||
ydelta := aSprite.ydelta;
|
|
||||||
frameIndex := aSprite.curFrame;
|
|
||||||
frameTime := aSprite.frameTime;
|
|
||||||
frameLeft := aSprite.frameLeft;
|
|
||||||
oldX := aSprite.x; oldY := aSprite.y;
|
|
||||||
aSprite.oldX := oldX; aSprite.oldY := oldY;
|
|
||||||
|
|
||||||
frameLeft := frameLeft - 1;
|
|
||||||
if frameLeft <= 0 then
|
|
||||||
begin
|
|
||||||
frameIndex := frameIndex + 1;
|
|
||||||
frameLeft := aSprite.frameTime;
|
|
||||||
aSprite.frameLeft := frameLeft;
|
|
||||||
aSprite.curFrame := frameIndex;
|
|
||||||
if frameIndex >= aSprite.frameCount
|
|
||||||
then
|
|
||||||
aSprite.curFrame := 0;
|
|
||||||
|
|
||||||
if frameIndex = 1 then
|
|
||||||
begin
|
|
||||||
ydelta := - ydelta;
|
|
||||||
aSprite.ydelta := ydelta;
|
|
||||||
end;
|
|
||||||
aSprite.y := aSprite.y + ydelta;
|
|
||||||
end;
|
|
||||||
|
|
||||||
aSprite.frameLeft := frameLeft;
|
|
||||||
|
|
||||||
aSprite.x := aSprite.x + aSprite.xdelta;
|
|
||||||
if aSprite.x > 620 then aSprite.x := 0;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure animate;
|
|
||||||
var i:integer;
|
|
||||||
ydelta:integer;
|
|
||||||
frameIndex:integer;
|
|
||||||
frameTime:integer;
|
|
||||||
oldX,oldY:integer;
|
|
||||||
begin
|
|
||||||
santaSprite.x := 0;
|
|
||||||
santaSprite.y := 60;
|
|
||||||
santaSprite.frameTime := 10;
|
|
||||||
santaSprite.xdelta := 2;
|
|
||||||
santaSprite.ydelta := 1;
|
|
||||||
|
|
||||||
smokeSprite.x := 434;
|
|
||||||
smokeSprite.y := 252;
|
|
||||||
smokeSprite.frameTime := 20;
|
|
||||||
|
|
||||||
deerSprite.x := 18;
|
|
||||||
deerSprite.y := 60;
|
|
||||||
deerSprite.frameTime := 10;
|
|
||||||
deerSprite.xdelta := 2;
|
|
||||||
deerSprite.ydelta := 1;
|
|
||||||
|
|
||||||
ohDeerSprite.x := 33;
|
|
||||||
ohDeerSprite.y := 61;
|
|
||||||
ohDeerSprite.frameTime := 10;
|
|
||||||
ohDeerSprite.xdelta := 2;
|
|
||||||
ohDeerSprite.ydelta := 1;
|
|
||||||
|
|
||||||
rudolfSprite.x := 49;
|
|
||||||
rudolfSprite.y := 60;
|
|
||||||
rudolfSprite.frameTime := 10;
|
|
||||||
rudolfSprite.xdelta := 2;
|
|
||||||
rudolfSprite.ydelta := 1;
|
|
||||||
|
|
||||||
ydelta := 1;
|
|
||||||
|
|
||||||
frameTime := santaSprite.frameTime;
|
|
||||||
|
|
||||||
while not ConAvail do
|
|
||||||
begin
|
|
||||||
frameIndex := santaSprite.curFrame;
|
|
||||||
oldX := santaSprite.x; oldY := santaSprite.y;
|
|
||||||
PutSprite(oldX, oldY, santaSprite.frame[frameIndex]);
|
|
||||||
i := i + 1;
|
|
||||||
frameTime := frameTime - 1;
|
|
||||||
if frameTime = 0 then
|
|
||||||
begin
|
|
||||||
frameTime := santaSprite.frameTime;
|
|
||||||
santaSprite.curFrame := frameIndex + 1;
|
|
||||||
if frameIndex >= santaSprite.frameCount
|
|
||||||
then
|
|
||||||
santaSprite.curFrame := 0;
|
|
||||||
|
|
||||||
if frameIndex = 0 then ydelta := - ydelta;
|
|
||||||
santaSprite.y := santaSprite.y + ydelta;
|
|
||||||
end;
|
|
||||||
santaSprite.x := santaSprite.x + 2;
|
|
||||||
if santaSprite.x > 620 then santaSprite.x := 0;
|
|
||||||
|
|
||||||
PutSprite(deerSprite.x, deerSprite.y,
|
|
||||||
deerSprite.frame[deerSprite.curFrame]);
|
|
||||||
|
|
||||||
PutSprite(ohDeerSprite.x, ohDeerSprite.y,
|
|
||||||
ohDeerSprite.frame[ohDeerSprite.curFrame]);
|
|
||||||
|
|
||||||
PutSprite(rudolfSprite.x, rudolfSprite.y,
|
|
||||||
rudolfSprite.frame[rudolfSprite.curFrame]);
|
|
||||||
|
|
||||||
PutSprite(smokeSprite.x, smokeSprite.y,
|
|
||||||
smokeSprite.frame[smokeSprite.curFrame]);
|
|
||||||
|
|
||||||
animateSprite(deerSprite);
|
|
||||||
animateSprite(ohDeerSprite);
|
|
||||||
animateSprite(rudolfSprite);
|
|
||||||
animateSprite(smokeSprite);
|
|
||||||
|
|
||||||
Delay(10);
|
|
||||||
WaitVSync;
|
|
||||||
|
|
||||||
UndrawSprite(oldX, oldY, pic.pixeldata);
|
|
||||||
UndrawSprite(deerSprite.oldX, deerSprite.oldY, pic.pixeldata);
|
|
||||||
UndrawSprite(ohDeerSprite.oldX, ohDeerSprite.oldY, pic.pixeldata);
|
|
||||||
UndrawSprite(rudolfSprite.oldX, rudolfSprite.oldY, pic.pixeldata);
|
|
||||||
UndrawSprite(smokeSprite.oldX, smokeSprite.oldY, pic.pixeldata);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
begin
|
|
||||||
filename := 'background.pict';
|
|
||||||
open(infile, filename, ModeReadonly);
|
|
||||||
read(infile, pic);
|
|
||||||
close(infile);
|
|
||||||
|
|
||||||
writeln('magic: ', pic.magic, ' mode:', pic.mode);
|
|
||||||
|
|
||||||
loadPalette(pic);
|
|
||||||
showPic(pic);
|
|
||||||
|
|
||||||
open(infile, 'sprites.sprt', ModeReadOnly);
|
|
||||||
loadSpriteFrame(santaSprite, 0, infile, 0);
|
|
||||||
loadSpriteFrame(santaSprite, 1, infile, 1);
|
|
||||||
|
|
||||||
loadSpriteFrame(deerSprite, 0, infile, 5);
|
|
||||||
loadSpriteFrame(deerSprite, 1, infile, 6);
|
|
||||||
loadSpriteFrame(deerSprite, 2, infile, 7);
|
|
||||||
|
|
||||||
loadSpriteFrame(ohDeerSprite, 0, infile, 7);
|
|
||||||
loadSpriteFrame(ohDeerSprite, 1, infile, 5);
|
|
||||||
loadSpriteFrame(ohDeerSprite, 2, infile, 6);
|
|
||||||
|
|
||||||
loadSpriteFrame(rudolfSprite, 0, infile, 3);
|
|
||||||
loadSpriteFrame(rudolfSprite, 1, infile, 4);
|
|
||||||
loadSpriteFrame(rudolfSprite, 2, infile, 2);
|
|
||||||
|
|
||||||
loadSpriteFrame(smokeSprite, 0, infile, 8);
|
|
||||||
loadSpriteFrame(smokeSprite, 1, infile, 9);
|
|
||||||
loadSpriteFrame(smokeSprite, 2, infile, 10);
|
|
||||||
loadSpriteFrame(smokeSprite, 3, infile, 11);
|
|
||||||
|
|
||||||
close(infile);
|
|
||||||
|
|
||||||
animate;
|
|
||||||
end.
|
|
||||||
|
|
@ -1,251 +0,0 @@
|
||||||
{$H2560}
|
|
||||||
{$S8}
|
|
||||||
program xmas252;
|
|
||||||
uses pcmaudio, fastfire, tiles;
|
|
||||||
|
|
||||||
const MAXX = FIREWIDTH;
|
|
||||||
MAXY = FIREHEIGHT;
|
|
||||||
|
|
||||||
(* type PixelData = array[0..31999] of integer; *)
|
|
||||||
|
|
||||||
type Picture = record
|
|
||||||
magic:integer;
|
|
||||||
mode:integer;
|
|
||||||
palette: array[0..15] of integer;
|
|
||||||
pixels: PixelData;
|
|
||||||
end;
|
|
||||||
|
|
||||||
var firecells: FireBuf;
|
|
||||||
|
|
||||||
firepalette: array [0..15] of integer =
|
|
||||||
{ ( $FFA, $FF8, $FF4, $FF0, $FE0, $FD0, $FA0, $F90,
|
|
||||||
$F00, $E00, $D00, $A00, $800, $600, $300, $000); }
|
|
||||||
{ ( $FFA, $FFA, $FFA, $FFA, $FF0, $FF0, $FF0, $FF0, }
|
|
||||||
( $00F, $00F, $00F, $00F, $00F, $00F, $00F, $00F,
|
|
||||||
$FF0, $FD0, $FA0, $C00, $A00, $700, $400, $000);
|
|
||||||
x,y:integer;
|
|
||||||
infile:file;
|
|
||||||
pic:^Picture;
|
|
||||||
tilesheet:^Picture;
|
|
||||||
animationTick:integer;
|
|
||||||
animationHold:integer;
|
|
||||||
animationState:integer;
|
|
||||||
|
|
||||||
filename: string;
|
|
||||||
|
|
||||||
audiodata: SndBufPtr;
|
|
||||||
|
|
||||||
procedure createPalette;
|
|
||||||
var i:integer;
|
|
||||||
begin
|
|
||||||
for i := 15 downto 0 do
|
|
||||||
setpalette(15 - i, firepalette[i]);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure fireItUp;
|
|
||||||
var x,y:integer;
|
|
||||||
begin
|
|
||||||
y := MAXY - 1;
|
|
||||||
for x := 1 to MAXX - 1 do
|
|
||||||
firecells[y, x] := random and 127;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
procedure updateFire;
|
|
||||||
var i,x,y:integer;
|
|
||||||
begin
|
|
||||||
for y := 0 to MAXY - 2 do
|
|
||||||
for x := 1 to MAXX - 1 do
|
|
||||||
begin
|
|
||||||
i :=
|
|
||||||
((firecells[y + 1, x - 1]
|
|
||||||
+ firecells[y + 1, x]
|
|
||||||
+ firecells[y + 1, x + 1]
|
|
||||||
+ firecells[y + 2, x])
|
|
||||||
) shr 2;
|
|
||||||
if i > 0 then
|
|
||||||
i := i - 1;
|
|
||||||
firecells[y, x] := i;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure drawFire(startX,startY:integer);
|
|
||||||
var x, y, col, col2:integer;
|
|
||||||
begin
|
|
||||||
for y := 0 to MAXY - 1 do
|
|
||||||
begin
|
|
||||||
x := 0;
|
|
||||||
for col in firecells[y] do
|
|
||||||
begin
|
|
||||||
{ scale and clamp color value }
|
|
||||||
col2 := col shr 3;
|
|
||||||
if col2 > FIREMAXCOLOR then col2 := FIREMAXCOLOR;
|
|
||||||
|
|
||||||
putpixel(startX + x, startY + y, col2);
|
|
||||||
x := x + 1;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure readBackgroundPic(filename:string);
|
|
||||||
var i:integer;
|
|
||||||
begin
|
|
||||||
open(infile, filename, ModeReadonly);
|
|
||||||
read(infile, pic^);
|
|
||||||
close(infile);
|
|
||||||
|
|
||||||
for i := 0 to 15 do
|
|
||||||
SetPalette(i, pic^.palette[i]);
|
|
||||||
|
|
||||||
PutScreen(pic^.pixels);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure animate;
|
|
||||||
var tileSrcX,tilesrcY:integer;
|
|
||||||
begin
|
|
||||||
animationTick := animationTick + 1;
|
|
||||||
|
|
||||||
if animationHold = 0 then
|
|
||||||
animationHold := 40;
|
|
||||||
|
|
||||||
if animationTick < animationHold then
|
|
||||||
exit;
|
|
||||||
|
|
||||||
animationTick := 0;
|
|
||||||
|
|
||||||
case animationState of
|
|
||||||
0: begin
|
|
||||||
tileSrcX := 0;
|
|
||||||
tileSrcY := 0;
|
|
||||||
animationHold := 40;
|
|
||||||
end;
|
|
||||||
1: begin
|
|
||||||
tileSrcX := 19;
|
|
||||||
tileSrcY := 0;
|
|
||||||
animationHold := 20;
|
|
||||||
|
|
||||||
if random and 7 > 4 then
|
|
||||||
animationState := -1;
|
|
||||||
end;
|
|
||||||
2: begin
|
|
||||||
tileSrcX := 38;
|
|
||||||
tileSrcY := 0;
|
|
||||||
animationHold := 2;
|
|
||||||
end;
|
|
||||||
3: begin;
|
|
||||||
tileSrcX := 57;
|
|
||||||
tileSrcY := 0;
|
|
||||||
animationHold := 2;
|
|
||||||
end;
|
|
||||||
4: begin
|
|
||||||
tileSrcX := 0;
|
|
||||||
tileSrcY := 13;
|
|
||||||
animationHold := 15;
|
|
||||||
end;
|
|
||||||
5: begin
|
|
||||||
tileSrcX := 57;
|
|
||||||
tileSrcY := 0;
|
|
||||||
animationHold := 2;
|
|
||||||
end;
|
|
||||||
6: begin
|
|
||||||
tileSrcX := 38;
|
|
||||||
tileSrcY := 0;
|
|
||||||
animationHold := 2;
|
|
||||||
end;
|
|
||||||
7: begin
|
|
||||||
tileSrcX := 0;
|
|
||||||
tileSrcY := 0;
|
|
||||||
animationHold := 2;
|
|
||||||
animationState := -1;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
CopyTilesScr(tilesheet^.pixels,
|
|
||||||
tileSrcX, tileSrcY,
|
|
||||||
34,34,
|
|
||||||
19,13);
|
|
||||||
|
|
||||||
animationState := animationState + 1;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
procedure readTilesheet;
|
|
||||||
var filename:string;
|
|
||||||
i:integer;
|
|
||||||
begin
|
|
||||||
filename := 'tilesheet.pict';
|
|
||||||
open(infile, filename, ModeReadonly);
|
|
||||||
read(infile, tilesheet^);
|
|
||||||
close(infile);
|
|
||||||
end;
|
|
||||||
|
|
||||||
function newAudioData(fname:string):SndBufPtr;
|
|
||||||
var i,size:integer;
|
|
||||||
c:char;
|
|
||||||
buf:SndBufPtr;
|
|
||||||
f:file;
|
|
||||||
begin
|
|
||||||
open(f, fname, ModeReadOnly);
|
|
||||||
size := FileSize(f);
|
|
||||||
new(buf, size);
|
|
||||||
|
|
||||||
buf^ := '';
|
|
||||||
write('Reading ', size, ' bytes...');
|
|
||||||
for i := 1 to size do
|
|
||||||
begin
|
|
||||||
read(f,c);
|
|
||||||
AppendChar(buf^,c);
|
|
||||||
end;
|
|
||||||
writeln;
|
|
||||||
|
|
||||||
close(f);
|
|
||||||
|
|
||||||
newAudioData := buf;
|
|
||||||
end;
|
|
||||||
|
|
||||||
|
|
||||||
begin
|
|
||||||
if ParamCount > 0 then
|
|
||||||
filename := ParamStr(1)
|
|
||||||
else
|
|
||||||
filename := 'xmas25bg.pict';
|
|
||||||
|
|
||||||
Randomize;
|
|
||||||
|
|
||||||
audiodata := newAudioData('fireplace-loop.tdrau');
|
|
||||||
|
|
||||||
InitGraphics;
|
|
||||||
|
|
||||||
new(pic);
|
|
||||||
readBackgroundPic(filename);
|
|
||||||
|
|
||||||
new(tilesheet);
|
|
||||||
readTilesheet;
|
|
||||||
|
|
||||||
SampleQStart(audiodata, true, 22050);
|
|
||||||
|
|
||||||
while not ConAvail do
|
|
||||||
begin
|
|
||||||
fireItUp;
|
|
||||||
FastFireUpdate(firecells);
|
|
||||||
{ updateFire; }
|
|
||||||
FastFireDraw(firecells, 216, 165);
|
|
||||||
{ drawFire(216, 165); }
|
|
||||||
animate;
|
|
||||||
end;
|
|
||||||
|
|
||||||
SampleQStop;
|
|
||||||
|
|
||||||
for y := 0 to MAXY do
|
|
||||||
begin
|
|
||||||
x := firecells[y, 10];
|
|
||||||
drawline(0, y, x, y, 1);
|
|
||||||
|
|
||||||
end;
|
|
||||||
|
|
||||||
InitGraphics;
|
|
||||||
|
|
||||||
dispose(tilesheet);
|
|
||||||
dispose(pic);
|
|
||||||
dispose(audiodata);
|
|
||||||
end.
|
|
||||||
239
lib/corelib.s
239
lib/corelib.s
|
|
@ -588,19 +588,13 @@ DIVU_END:
|
||||||
|
|
||||||
; wait approx. 1 millisecond
|
; wait approx. 1 millisecond
|
||||||
;
|
;
|
||||||
; the ROM at address 4
|
; 83.333 MHz Clock, three instructions a 4 cycles
|
||||||
; contains the cpu clock freq in KHz
|
; 83333 / 12 = 6944.4166
|
||||||
.EQU CLK_KHZ_ADDR 4
|
; works only if executed without wait states (i.e.
|
||||||
|
; from BRAM/SRAM)
|
||||||
WAIT1MSEC:
|
WAIT1MSEC:
|
||||||
LOADC CLK_KHZ_ADDR
|
LOADCP 6944
|
||||||
LOADI
|
|
||||||
; divide by 16
|
|
||||||
SHR
|
|
||||||
SHR
|
|
||||||
SHR
|
|
||||||
SHR
|
|
||||||
WAIT1LOOP:
|
WAIT1LOOP:
|
||||||
INC 0 ; NOP to make the loop 16 cycles long
|
|
||||||
DEC 1
|
DEC 1
|
||||||
DUP
|
DUP
|
||||||
CBRANCH.NZ WAIT1LOOP
|
CBRANCH.NZ WAIT1LOOP
|
||||||
|
|
@ -612,9 +606,6 @@ WAIT1LOOP:
|
||||||
; length must be multiple of wordsize.
|
; length must be multiple of wordsize.
|
||||||
; if it is not, the last (partial) word is not cleared.
|
; if it is not, the last (partial) word is not cleared.
|
||||||
_CLEARMEM:
|
_CLEARMEM:
|
||||||
OVER ; check for null pointer
|
|
||||||
CBRANCH.Z CLEARMEM_X
|
|
||||||
|
|
||||||
SHR
|
SHR
|
||||||
SHR ; calculate length in words
|
SHR ; calculate length in words
|
||||||
|
|
||||||
|
|
@ -701,37 +692,113 @@ CMPWORDS_XT2:
|
||||||
; --------- Graphics Library ---------------
|
; --------- Graphics Library ---------------
|
||||||
; vga controller registers
|
; vga controller registers
|
||||||
.EQU FB_RA $900
|
.EQU FB_RA $900
|
||||||
.EQU FB_WA $904
|
.EQU FB_WA $901
|
||||||
.EQU FB_IO $908
|
.EQU FB_IO $902
|
||||||
.EQU FB_PS $90C
|
.EQU FB_PS $903
|
||||||
.EQU FB_PD $910
|
.EQU FB_PD $904
|
||||||
.EQU FB_CTL $914
|
.EQU FB_CTL $905
|
||||||
.EQU FB_SHIFTER $918
|
; set a pixel in fb memory
|
||||||
.EQU FB_SHIFTCOUNT $91C
|
; parameters: x,y - coordinates
|
||||||
.EQU FB_SHIFTERM $920
|
PUTPIXEL_1BPP:
|
||||||
.EQU FB_SHIFTERSP $924
|
; calculate vmem address:
|
||||||
.EQU FB_MASKGEN $928
|
OVER ; duplicate x
|
||||||
|
; divide x by 32
|
||||||
|
SHR
|
||||||
|
SHR
|
||||||
|
SHR
|
||||||
|
SHR
|
||||||
|
SHR
|
||||||
|
SWAP
|
||||||
|
; multiply y by words per line
|
||||||
|
SHL 2
|
||||||
|
SHL 2
|
||||||
|
SHL
|
||||||
|
|
||||||
; draw a single pixel
|
ADD ; add results together for vmem addr
|
||||||
; args: x, y, color
|
|
||||||
|
|
||||||
|
DUP
|
||||||
|
LOADCP FB_WA
|
||||||
|
SWAP
|
||||||
|
STOREI ; store to framebuffer write addr register
|
||||||
|
DROP
|
||||||
|
LOADCP FB_RA ; and to framebuffer read addr register
|
||||||
|
SWAP
|
||||||
|
STOREI
|
||||||
|
DROP
|
||||||
|
|
||||||
|
; x is now at top of stack
|
||||||
|
; get bit value from x modulo 32
|
||||||
|
LOADC 31
|
||||||
|
AND
|
||||||
|
SHL 2 ; (x & 31) * 4 = offset into table
|
||||||
|
LOADCP INT_TO_PIX_TABLE
|
||||||
|
ADD
|
||||||
|
LOADI
|
||||||
|
|
||||||
|
LOADCP FB_IO
|
||||||
|
; read old vmem value
|
||||||
|
LOADCP FB_IO
|
||||||
|
LOADI
|
||||||
|
; or in new bit
|
||||||
|
OR
|
||||||
|
; write new value
|
||||||
|
STOREI
|
||||||
|
DROP
|
||||||
|
|
||||||
|
RET
|
||||||
|
|
||||||
|
INT_TO_PIX_TABLE:
|
||||||
|
.WORD %10000000_00000000_00000000_00000000
|
||||||
|
.WORD %01000000_00000000_00000000_00000000
|
||||||
|
.WORD %00100000_00000000_00000000_00000000
|
||||||
|
.WORD %00010000_00000000_00000000_00000000
|
||||||
|
.WORD %00001000_00000000_00000000_00000000
|
||||||
|
.WORD %00000100_00000000_00000000_00000000
|
||||||
|
.WORD %00000010_00000000_00000000_00000000
|
||||||
|
.WORD %00000001_00000000_00000000_00000000
|
||||||
|
.WORD %00000000_10000000_00000000_00000000
|
||||||
|
.WORD %00000000_01000000_00000000_00000000
|
||||||
|
.WORD %00000000_00100000_00000000_00000000
|
||||||
|
.WORD %00000000_00010000_00000000_00000000
|
||||||
|
.WORD %00000000_00001000_00000000_00000000
|
||||||
|
.WORD %00000000_00000100_00000000_00000000
|
||||||
|
.WORD %00000000_00000010_00000000_00000000
|
||||||
|
.WORD %00000000_00000001_00000000_00000000
|
||||||
|
.WORD %00000000_00000000_10000000_00000000
|
||||||
|
.WORD %00000000_00000000_01000000_00000000
|
||||||
|
.WORD %00000000_00000000_00100000_00000000
|
||||||
|
.WORD %00000000_00000000_00010000_00000000
|
||||||
|
.WORD %00000000_00000000_00001000_00000000
|
||||||
|
.WORD %00000000_00000000_00000100_00000000
|
||||||
|
.WORD %00000000_00000000_00000010_00000000
|
||||||
|
.WORD %00000000_00000000_00000001_00000000
|
||||||
|
.WORD %00000000_00000000_00000000_10000000
|
||||||
|
.WORD %00000000_00000000_00000000_01000000
|
||||||
|
.WORD %00000000_00000000_00000000_00100000
|
||||||
|
.WORD %00000000_00000000_00000000_00010000
|
||||||
|
.WORD %00000000_00000000_00000000_00001000
|
||||||
|
.WORD %00000000_00000000_00000000_00000100
|
||||||
|
.WORD %00000000_00000000_00000000_00000010
|
||||||
|
.WORD %00000000_00000000_00000000_00000001
|
||||||
|
|
||||||
|
PUTMPIXEL:
|
||||||
|
LOADC 1
|
||||||
|
; set a pixel in fb memory
|
||||||
|
; parameters: x,y,color - coordinates, color value (0-15)
|
||||||
PUTPIXEL:
|
PUTPIXEL:
|
||||||
PUTPIXEL_4BPP:
|
PUTPIXEL_4BPP:
|
||||||
.EQU PUTPIXEL_X 0
|
.EQU PUTPIXEL_X 0
|
||||||
.EQU PUTPIXEL_Y 4
|
.EQU PUTPIXEL_Y 4
|
||||||
.EQU PUTPIXEL_COLOR 8
|
.EQU PUTPIXEL_COLOR 8
|
||||||
.EQU PUTPIXEL_BPSAV 12
|
.EQU PUTPIXEL_PIXPOS 12
|
||||||
.EQU PUTPIXEL_FS 16
|
.EQU PUTPIXEL_FS 16
|
||||||
|
|
||||||
FPADJ -PUTPIXEL_FS
|
FPADJ -PUTPIXEL_FS
|
||||||
|
|
||||||
STORE PUTPIXEL_COLOR
|
STORE PUTPIXEL_COLOR
|
||||||
STORE PUTPIXEL_Y
|
STORE PUTPIXEL_Y
|
||||||
STORE PUTPIXEL_X
|
STORE PUTPIXEL_X
|
||||||
|
|
||||||
LOADREG BP
|
|
||||||
STORE PUTPIXEL_BPSAV
|
|
||||||
LOADC 0
|
|
||||||
STOREREG BP
|
|
||||||
|
|
||||||
; calculate vmem address: (x / 8) + (y * 80)
|
; calculate vmem address: (x / 8) + (y * 80)
|
||||||
LOAD PUTPIXEL_X
|
LOAD PUTPIXEL_X
|
||||||
|
|
@ -746,60 +813,86 @@ PUTPIXEL_4BPP:
|
||||||
SHL 2 ; * 16
|
SHL 2 ; * 16
|
||||||
DUP
|
DUP
|
||||||
SHL 2; * 64
|
SHL 2; * 64
|
||||||
ADD ; y*16 + y*64
|
ADD ; x*16 + x*64
|
||||||
|
|
||||||
ADD ; add results together for vmem addr
|
ADD ; add results together for vmem addr
|
||||||
|
|
||||||
DUP
|
LOADCP FB_WA
|
||||||
STORE.B FB_WA ; set as write and read addresses
|
OVER
|
||||||
STORE.B FB_RA
|
STOREI ; store to framebuffer write addr register
|
||||||
|
DROP
|
||||||
|
LOADCP FB_RA ; and to framebuffer read addr register
|
||||||
|
SWAP ; swap addr and value for STOREI
|
||||||
|
STOREI
|
||||||
|
DROP
|
||||||
|
|
||||||
|
LOAD PUTPIXEL_X
|
||||||
|
; |0000.0000|0000.0000|0000.0000|0000.1111|
|
||||||
|
LOADC 7
|
||||||
|
AND ; calculate pixel position in word
|
||||||
|
LOADC 7
|
||||||
|
SWAP
|
||||||
|
SUB ; pixpos = 7 - (x & 7)
|
||||||
|
STORE PUTPIXEL_PIXPOS
|
||||||
|
|
||||||
LOAD PUTPIXEL_COLOR
|
LOAD PUTPIXEL_COLOR
|
||||||
CBRANCH.Z PUTPX_CLR ; color 0 is special case
|
LOAD PUTPIXEL_PIXPOS
|
||||||
|
SHR ; rcount = pixpos / 2
|
||||||
; create pixel data from color value in
|
ROTLOOP_:
|
||||||
; leftmost pixel data bits (31-28)
|
DUP ; exit loop if rcount is 0
|
||||||
LOADC 0
|
CBRANCH.Z ROTLOOP_END
|
||||||
LOAD PUTPIXEL_COLOR
|
SWAP ; pixel value is now on top of stack
|
||||||
BPLC
|
BROT ; value = value << 8
|
||||||
|
SWAP ; rcount is now on top of stack
|
||||||
|
DEC 1 ; rcount = rcount - 1
|
||||||
|
BRANCH ROTLOOP_
|
||||||
|
ROTLOOP_END:
|
||||||
|
DROP ; drop rcount
|
||||||
|
; shifted pixel value is now at top of stack
|
||||||
|
LOAD PUTPIXEL_PIXPOS
|
||||||
|
LOADC 1
|
||||||
|
AND
|
||||||
|
CBRANCH.Z EVEN_PIXPOS
|
||||||
|
SHL 2 ; if pixpos is odd, shift by 4 bits
|
||||||
SHL 2
|
SHL 2
|
||||||
SHL 2
|
EVEN_PIXPOS:
|
||||||
STORE.B FB_SHIFTER ; store pixel into shifter
|
LOAD PUTPIXEL_X
|
||||||
|
; get bit value from x modulo 8
|
||||||
|
LOADC 7
|
||||||
|
AND
|
||||||
|
SHL 2 ; (x & 7) * 4 = offset into table
|
||||||
|
LOADCP INT_TO_MASK_TABLE
|
||||||
|
ADD
|
||||||
|
LOADI
|
||||||
|
|
||||||
LOAD PUTPIXEL_X ; use x coord as shift count
|
; read old vmem value
|
||||||
STORE.B FB_SHIFTCOUNT ; writing triggers shifting
|
LOADCP FB_IO
|
||||||
|
LOADI
|
||||||
|
; mask bits
|
||||||
|
AND
|
||||||
|
; or in shifted pixel value
|
||||||
|
OR
|
||||||
|
|
||||||
LOAD.B FB_SHIFTERM ; get shift result as mask
|
; write new value
|
||||||
NOT ; invert to get background mask
|
LOADCP FB_IO
|
||||||
LOAD.B FB_IO ; get background pixel data
|
SWAP
|
||||||
AND ; remove bits for new pixel from bg
|
STOREI
|
||||||
|
DROP
|
||||||
LOAD.B FB_SHIFTER ; load shifted pixel
|
|
||||||
OR ; OR in new pixel bits
|
|
||||||
STORE.B FB_IO ; write new pixel data word to vmem
|
|
||||||
|
|
||||||
PUTPX_XT:
|
|
||||||
LOAD PUTPIXEL_BPSAV
|
|
||||||
STOREREG BP
|
|
||||||
|
|
||||||
FPADJ PUTPIXEL_FS
|
FPADJ PUTPIXEL_FS
|
||||||
RET
|
RET
|
||||||
|
|
||||||
PUTPX_CLR:
|
.CPOOL
|
||||||
LOADCP $F0000000 ; mask for leftmost pixel
|
|
||||||
STORE.B FB_SHIFTER ; shift accordingly
|
|
||||||
LOAD PUTPIXEL_X
|
|
||||||
STORE.B FB_SHIFTCOUNT
|
|
||||||
|
|
||||||
LOAD.B FB_SHIFTER ; get shifted value
|
|
||||||
NOT ; invert for real mask
|
|
||||||
LOAD.B FB_IO ; get background pixels
|
|
||||||
AND ; clear pixel with mask
|
|
||||||
STORE.B FB_IO ; no need to OR in new pixel, just store to vmem
|
|
||||||
|
|
||||||
BRANCH PUTPX_XT
|
|
||||||
|
|
||||||
|
|
||||||
|
INT_TO_MASK_TABLE:
|
||||||
|
.WORD %00001111_11111111_11111111_11111111
|
||||||
|
.WORD %11110000_11111111_11111111_11111111
|
||||||
|
.WORD %11111111_00001111_11111111_11111111
|
||||||
|
.WORD %11111111_11110000_11111111_11111111
|
||||||
|
.WORD %11111111_11111111_00001111_11111111
|
||||||
|
.WORD %11111111_11111111_11110000_11111111
|
||||||
|
.WORD %11111111_11111111_11111111_00001111
|
||||||
|
.WORD %11111111_11111111_11111111_11110000
|
||||||
|
|
||||||
; draw a line between two points
|
; draw a line between two points
|
||||||
; parameters: x0, y0, x1, y1, color
|
; parameters: x0, y0, x1, y1, color
|
||||||
|
|
@ -977,7 +1070,7 @@ SETPALETTE:
|
||||||
|
|
||||||
DEFAULT_PALETTE:
|
DEFAULT_PALETTE:
|
||||||
.WORD 0, $FFF, $F00, $0F0, $00F, $0FF, $F0F, $FF0
|
.WORD 0, $FFF, $F00, $0F0, $00F, $0FF, $F0F, $FF0
|
||||||
.WORD $777, $AAA, $700, $070, $007, $077, $707, $770
|
.WORD $777, $777, $700, $070, $007, $077, $707, $770
|
||||||
|
|
||||||
; set whole video memory to zero
|
; set whole video memory to zero
|
||||||
CLEARGRAPHICS:
|
CLEARGRAPHICS:
|
||||||
|
|
|
||||||
|
|
@ -1,7 +0,0 @@
|
||||||
type SndBuf = string[32768];
|
|
||||||
type SndBufPtr = ^SndBuf;
|
|
||||||
|
|
||||||
procedure PlaySample(buf:SndBufPtr;sampleRate:integer); external;
|
|
||||||
procedure SampleQStart(buf:SndBufPtr;loop:boolean;sampleRate:integer); external;
|
|
||||||
procedure SampleQStop; external;
|
|
||||||
function SampleQSize:integer; external;
|
|
||||||
304
lib/pcmaudio.s
304
lib/pcmaudio.s
|
|
@ -1,304 +0,0 @@
|
||||||
.EQU AUDIO_BASE $A00
|
|
||||||
.EQU IRQC_REG $980
|
|
||||||
.EQU IRQC_EN $80
|
|
||||||
.EQU CPU_FREQ 77000000
|
|
||||||
|
|
||||||
; args: sample rate
|
|
||||||
START_PCMAUDIO:
|
|
||||||
; calculate clock divider
|
|
||||||
LOADCP CPU_FREQ
|
|
||||||
SWAP
|
|
||||||
LOADCP _DIV
|
|
||||||
CALL
|
|
||||||
|
|
||||||
LOADC AUDIO_BASE + 4
|
|
||||||
SWAP ; put clock divider on ToS
|
|
||||||
STOREI 4
|
|
||||||
LOADCP 32768 ; set amplitude to biased 0
|
|
||||||
STOREI
|
|
||||||
DROP
|
|
||||||
|
|
||||||
LOADC AUDIO_BASE
|
|
||||||
LOADC 1 ; enable channel
|
|
||||||
STOREI
|
|
||||||
DROP
|
|
||||||
RET
|
|
||||||
|
|
||||||
STOP_AUDIO:
|
|
||||||
LOADC AUDIO_BASE
|
|
||||||
LOADC 0
|
|
||||||
STOREI
|
|
||||||
DROP
|
|
||||||
RET
|
|
||||||
|
|
||||||
; args: pointer to pascal string, sample rate
|
|
||||||
.EQU PS_PTR 0
|
|
||||||
.EQU PS_COUNT 4
|
|
||||||
.EQU PS_FS 12
|
|
||||||
PLAYSAMPLE:
|
|
||||||
FPADJ -PS_FS
|
|
||||||
|
|
||||||
LOADCP START_PCMAUDIO
|
|
||||||
CALL
|
|
||||||
|
|
||||||
DUP
|
|
||||||
LOADI ; get string size from header
|
|
||||||
SHR ; divide by 4 to get word count
|
|
||||||
SHR
|
|
||||||
|
|
||||||
STORE PS_COUNT
|
|
||||||
INC 8 ; skip rest of header
|
|
||||||
STORE PS_PTR ; store sample data pointer
|
|
||||||
|
|
||||||
PS_L0:
|
|
||||||
LOAD PS_PTR ; load pointer
|
|
||||||
INC.S1.X2Y 4 ; increment and keep old value
|
|
||||||
STORE PS_PTR ; store incremented value
|
|
||||||
|
|
||||||
LOADI ; load 32 bit word
|
|
||||||
DUP
|
|
||||||
BROT ; get upper 16 bit word
|
|
||||||
BROT
|
|
||||||
LOADCP $FFFF
|
|
||||||
AND
|
|
||||||
|
|
||||||
LOADCP PLAY_1SAMPLE
|
|
||||||
CALL
|
|
||||||
|
|
||||||
LOADCP $FFFF ; get lower 16 bit word
|
|
||||||
AND
|
|
||||||
LOADCP PLAY_1SAMPLE
|
|
||||||
CALL
|
|
||||||
|
|
||||||
LOAD PS_COUNT ; load word count
|
|
||||||
DEC 1 ; decrement
|
|
||||||
DUP
|
|
||||||
STORE PS_COUNT
|
|
||||||
CBRANCH.NZ PS_L0 ; loop if not zero
|
|
||||||
|
|
||||||
LOADCP STOP_AUDIO
|
|
||||||
CALL
|
|
||||||
|
|
||||||
FPADJ PS_FS
|
|
||||||
RET
|
|
||||||
|
|
||||||
; play one sample, waiting
|
|
||||||
; for the clock divider, which
|
|
||||||
; is visible via the phase flag
|
|
||||||
; args: 16-bit unsigned sample
|
|
||||||
PLAY_1SAMPLE:
|
|
||||||
|
|
||||||
PLAY1_L0:
|
|
||||||
LOADC AUDIO_BASE
|
|
||||||
LOADI
|
|
||||||
LOADC 8 ; get fifo_full flag
|
|
||||||
AND
|
|
||||||
CBRANCH.NZ PLAY1_L0 ; loop if fifo is full
|
|
||||||
|
|
||||||
LOADC AUDIO_BASE+8 ; store amplitude value
|
|
||||||
SWAP
|
|
||||||
STOREI
|
|
||||||
DROP
|
|
||||||
RET
|
|
||||||
|
|
||||||
; set sample queue count and pointer from string header
|
|
||||||
; args: pointer to string/SndBufPtr
|
|
||||||
_STR2SMPLQPTR:
|
|
||||||
LOADCP SMPLQ_COUNT
|
|
||||||
OVER
|
|
||||||
LOADI ; get string size from header
|
|
||||||
SHR ; divide by 4 to get word count
|
|
||||||
SHR
|
|
||||||
STOREI
|
|
||||||
DROP
|
|
||||||
|
|
||||||
LOADCP SMPLQ_PTR
|
|
||||||
SWAP
|
|
||||||
INC 8 ; skip rest of header
|
|
||||||
STOREI ; store sample data pointer
|
|
||||||
DROP
|
|
||||||
RET
|
|
||||||
|
|
||||||
; start interrupt-driven sample playback
|
|
||||||
; args: pointer to pascal string, loop flag, sample rate
|
|
||||||
SAMPLEQSTART:
|
|
||||||
LOADCP START_PCMAUDIO ; sample rate is on ToS as arg to subroutine
|
|
||||||
CALL
|
|
||||||
|
|
||||||
SWAP ; swap loop flag and buf ptr
|
|
||||||
|
|
||||||
LOADCP _STR2SMPLQPTR
|
|
||||||
CALL
|
|
||||||
|
|
||||||
; loop flag is now on ToS
|
|
||||||
CBRANCH.Z SQ_S_1
|
|
||||||
; if nonzero, set loop ptr
|
|
||||||
LOADCP SMPLQ_PTR
|
|
||||||
LOADI
|
|
||||||
DEC 8 ; subtract offset for string header again
|
|
||||||
BRANCH SQ_S_0
|
|
||||||
SQ_S_1:
|
|
||||||
LOADC 0
|
|
||||||
SQ_S_0:
|
|
||||||
LOADCP SMPLQ_NEXT
|
|
||||||
SWAP
|
|
||||||
STOREI
|
|
||||||
DROP
|
|
||||||
|
|
||||||
LOADC AUDIO_BASE
|
|
||||||
LOADC 17 ; enable channel, enable interrupt
|
|
||||||
STOREI
|
|
||||||
DROP
|
|
||||||
|
|
||||||
LOADCP SMPLQ_ISR ; set interrupt handler
|
|
||||||
STOREREG IV
|
|
||||||
|
|
||||||
LOADC IRQC_REG ; enable irq
|
|
||||||
LOADC IRQC_EN
|
|
||||||
STOREI
|
|
||||||
DROP
|
|
||||||
|
|
||||||
RET
|
|
||||||
|
|
||||||
SAMPLEQSTOP:
|
|
||||||
LOADCP SMPLQ_PTR
|
|
||||||
LOADC 0
|
|
||||||
STOREI
|
|
||||||
DROP
|
|
||||||
|
|
||||||
LOADCP STOP_AUDIO
|
|
||||||
CALL
|
|
||||||
|
|
||||||
LOADC IRQC_REG ; disable irq
|
|
||||||
LOADC 0
|
|
||||||
STOREI
|
|
||||||
DROP
|
|
||||||
RET
|
|
||||||
|
|
||||||
SAMPLEQSIZE:
|
|
||||||
LOADCP SMPLQ_COUNT
|
|
||||||
LOADI
|
|
||||||
RET
|
|
||||||
|
|
||||||
SMPLQ_PTR: .WORD 0
|
|
||||||
SMPLQ_COUNT: .WORD 0
|
|
||||||
SMPLQ_NEXT: .WORD 0
|
|
||||||
|
|
||||||
SMPLQ_ISR:
|
|
||||||
LOADC IRQC_REG
|
|
||||||
LOADI
|
|
||||||
LOADC 4 ; check for audio interrupt
|
|
||||||
AND
|
|
||||||
CBRANCH.Z SMPLQ_I_XT ; if flag not set, exit
|
|
||||||
|
|
||||||
SMPLQ_I_L:
|
|
||||||
LOADCP SMPLQ_PTR
|
|
||||||
LOADI ; load word pointer
|
|
||||||
DUP
|
|
||||||
CBRANCH.NZ SMPLQ_I_B ; check for null pointer
|
|
||||||
DROP
|
|
||||||
BRANCH SMPLQ_I_XT ; if null, end interrupt routine
|
|
||||||
SMPLQ_I_B:
|
|
||||||
LOADI ; load next word which contains two samples
|
|
||||||
DUP
|
|
||||||
|
|
||||||
BROT ; get high half-word
|
|
||||||
BROT
|
|
||||||
LOADCP $FFFF
|
|
||||||
AND
|
|
||||||
|
|
||||||
LOADC AUDIO_BASE+8
|
|
||||||
SWAP
|
|
||||||
STOREI ; write sample, keep addr
|
|
||||||
|
|
||||||
SWAP ; addr to NoS, lower halfword on ToS
|
|
||||||
LOADCP $FFFF
|
|
||||||
AND
|
|
||||||
STOREI ; write sample
|
|
||||||
DROP
|
|
||||||
|
|
||||||
; decrement word count
|
|
||||||
LOADCP SMPLQ_COUNT
|
|
||||||
LOADI.S1.X2Y ; load counter, keep addr
|
|
||||||
DEC 1
|
|
||||||
DUP
|
|
||||||
CBRANCH.Z SMPLQ_I_END ; end if zero
|
|
||||||
|
|
||||||
STOREI ; store new counter value
|
|
||||||
DROP
|
|
||||||
|
|
||||||
; increment pointer
|
|
||||||
LOADCP SMPLQ_PTR
|
|
||||||
LOADI.S1.X2Y
|
|
||||||
INC 4
|
|
||||||
STOREI
|
|
||||||
DROP
|
|
||||||
|
|
||||||
; put up to 16 samples into the sample queue
|
|
||||||
LOADCP SMPLQ_COUNT
|
|
||||||
LOADI ; load word counter again
|
|
||||||
LOADC 7 ; check if count modulo 7 = 0
|
|
||||||
AND
|
|
||||||
CBRANCH.NZ SMPLQ_I_L ; if not, next two samples
|
|
||||||
|
|
||||||
; check if fifo is full
|
|
||||||
; does not work reliably when running in DRAM,
|
|
||||||
; maybe because at least one sample has already played
|
|
||||||
; since start of ISR?
|
|
||||||
; LOADC AUDIO_BASE
|
|
||||||
; LOADI
|
|
||||||
; LOADC 8 ; fifo_full
|
|
||||||
; AND
|
|
||||||
; CBRANCH.Z SMPLQ_I_L ; next sample if not full
|
|
||||||
|
|
||||||
BRANCH SMPLQ_I_XT
|
|
||||||
|
|
||||||
; end of sample buffer, check for next
|
|
||||||
SMPLQ_I_END:
|
|
||||||
DROP
|
|
||||||
DROP
|
|
||||||
|
|
||||||
LOADCP SMPLQ_NEXT ; skip to end
|
|
||||||
LOADI ; if NEXT ptr is zero
|
|
||||||
DUP
|
|
||||||
CBRANCH.Z SMPLQ_I_END1
|
|
||||||
|
|
||||||
LOADCP _STR2SMPLQPTR
|
|
||||||
CALL
|
|
||||||
|
|
||||||
BRANCH SMPLQ_I_XT
|
|
||||||
|
|
||||||
; end playback, set ptr and counter to zero
|
|
||||||
SMPLQ_I_END1:
|
|
||||||
DROP
|
|
||||||
LOADCP SMPLQ_PTR
|
|
||||||
LOADC 0
|
|
||||||
STOREI
|
|
||||||
DROP
|
|
||||||
LOADCP SMPLQ_COUNT
|
|
||||||
LOADC 0
|
|
||||||
STOREI
|
|
||||||
DROP
|
|
||||||
|
|
||||||
; set amplitude out to zero (biased)
|
|
||||||
LOADC AUDIO_BASE+8
|
|
||||||
LOADCP 32768
|
|
||||||
STOREI
|
|
||||||
DROP
|
|
||||||
|
|
||||||
; exit without enabling interrupts for this channel
|
|
||||||
BRANCH SMPLQ_I_XT2
|
|
||||||
|
|
||||||
SMPLQ_I_XT:
|
|
||||||
LOADC AUDIO_BASE
|
|
||||||
LOADC 17 ; re-enable channel interrupt
|
|
||||||
STOREI
|
|
||||||
DROP
|
|
||||||
|
|
||||||
SMPLQ_I_XT2:
|
|
||||||
LOADC IRQC_REG ; re-enable interrupts
|
|
||||||
LOADC IRQC_EN
|
|
||||||
STOREI
|
|
||||||
DROP
|
|
||||||
LOADREG IR ; jump via interrupt return register
|
|
||||||
JUMP
|
|
||||||
24
lib/rommon.s
24
lib/rommon.s
|
|
@ -7,16 +7,8 @@
|
||||||
.EQU UART_REG 2048
|
.EQU UART_REG 2048
|
||||||
.EQU MON_ADDR 64512
|
.EQU MON_ADDR 64512
|
||||||
|
|
||||||
.EQU CLK_KHZ 76923
|
|
||||||
|
|
||||||
BRANCH 2 ; the very first instruction is not
|
BRANCH 2 ; the very first instruction is not
|
||||||
; executed correctly
|
; executed correctly
|
||||||
BRANCH MON_START ; branch over constant
|
|
||||||
|
|
||||||
CLK_KHZ_ADDR:
|
|
||||||
.WORD CLK_KHZ ; to calibrate the delay loop
|
|
||||||
|
|
||||||
MON_START:
|
|
||||||
LOADCP 65020 ; initialise FP and RP registers
|
LOADCP 65020 ; initialise FP and RP registers
|
||||||
STOREREG FP
|
STOREREG FP
|
||||||
LOADCP 65024
|
LOADCP 65024
|
||||||
|
|
@ -790,17 +782,13 @@ COPY_BLK1:
|
||||||
|
|
||||||
; wait approx. 1 millisecond
|
; wait approx. 1 millisecond
|
||||||
;
|
;
|
||||||
|
; 83.333 MHz Clock, three instructions a 4 cycles
|
||||||
|
; 83333 / 12 = 6944.4166
|
||||||
|
; works only if executed without wait states (i.e.
|
||||||
|
; from BRAM/SRAM)
|
||||||
WAIT1MSEC:
|
WAIT1MSEC:
|
||||||
; get clock freq in khz
|
LOADCP 6944
|
||||||
LOADC CLK_KHZ_ADDR
|
|
||||||
LOADI
|
|
||||||
; divide by 16
|
|
||||||
SHR
|
|
||||||
SHR
|
|
||||||
SHR
|
|
||||||
SHR
|
|
||||||
WAIT1LOOP:
|
WAIT1LOOP:
|
||||||
INC 0 ; NOP to make loop 16 cycles long
|
|
||||||
DEC 1
|
DEC 1
|
||||||
DUP
|
DUP
|
||||||
CBRANCH.NZ WAIT1LOOP
|
CBRANCH.NZ WAIT1LOOP
|
||||||
|
|
@ -810,7 +798,7 @@ WAIT1LOOP:
|
||||||
%include "sdcardboot.s"
|
%include "sdcardboot.s"
|
||||||
.CPOOL
|
.CPOOL
|
||||||
MESSAGE:
|
MESSAGE:
|
||||||
.BYTE 13,10,"ROM Monitor v3.1.0", 13, 10,
|
.BYTE 13,10,"ROM Monitor v3.0.3", 13, 10,
|
||||||
"Set A)ddress D)eposit eX)amine L)oad G)o B)oot",13,10,0
|
"Set A)ddress D)eposit eX)amine L)oad G)o B)oot",13,10,0
|
||||||
PROMPT2:
|
PROMPT2:
|
||||||
.BYTE "]> ",0
|
.BYTE "]> ",0
|
||||||
|
|
|
||||||
|
|
@ -1616,7 +1616,7 @@ MEM_FREE_XT:
|
||||||
; Since the return stack is no longer valid afterwards, directly
|
; Since the return stack is no longer valid afterwards, directly
|
||||||
; jumps to _MAIN instead of using RET.
|
; jumps to _MAIN instead of using RET.
|
||||||
|
|
||||||
; parameters: [ start of heap address ]
|
; parameters: [ _MAIN entry point, start of heap address ]
|
||||||
_MEM_INIT:
|
_MEM_INIT:
|
||||||
; initialize anchor chunk with start of heap address
|
; initialize anchor chunk with start of heap address
|
||||||
; and heap size - header size
|
; and heap size - header size
|
||||||
|
|
@ -1764,34 +1764,6 @@ MEM_DUMP_L0:
|
||||||
DROP
|
DROP
|
||||||
RET
|
RET
|
||||||
|
|
||||||
; calculate total free heap space
|
|
||||||
; args: none
|
|
||||||
; returns: cumulative size of all free chunks in bytes
|
|
||||||
MEMAVAIL:
|
|
||||||
FPADJ -4
|
|
||||||
LOADC 0
|
|
||||||
STORE 0 ; start with zero as result
|
|
||||||
|
|
||||||
LOADCP _HEAP_ANCHOR
|
|
||||||
MAV_L:
|
|
||||||
DUP ; dup chunk ptr for later
|
|
||||||
INC 4 ; move to size field
|
|
||||||
LOADI ; load chunk size
|
|
||||||
LOAD 0 ; add to current result value
|
|
||||||
ADD
|
|
||||||
STORE 0
|
|
||||||
|
|
||||||
LOADI ; load next ptr
|
|
||||||
DUP
|
|
||||||
LOADCP _HEAP_ANCHOR ; compare with anchor
|
|
||||||
CMPU NE
|
|
||||||
CBRANCH MAV_L ; if not equal, loop
|
|
||||||
MAX_XT:
|
|
||||||
DROP ; drop chunk ptr
|
|
||||||
LOAD 0 ; put result value on stack
|
|
||||||
FPADJ 4
|
|
||||||
RET
|
|
||||||
|
|
||||||
; check if a pointer is part of the free list
|
; check if a pointer is part of the free list
|
||||||
; args: pointer returned by MEM_ALLOC
|
; args: pointer returned by MEM_ALLOC
|
||||||
; throws runtime error if the pointer is found
|
; throws runtime error if the pointer is found
|
||||||
|
|
@ -1931,12 +1903,6 @@ _CLEARESTACK_XT:
|
||||||
; Terminate program: clear estack and
|
; Terminate program: clear estack and
|
||||||
; jump to coreloader
|
; jump to coreloader
|
||||||
PTERM:
|
PTERM:
|
||||||
; just to be safe, disable interrupts
|
|
||||||
LOADC $980
|
|
||||||
LOADC 0
|
|
||||||
STOREI
|
|
||||||
DROP
|
|
||||||
|
|
||||||
LOADCP _CLEARESTACK
|
LOADCP _CLEARESTACK
|
||||||
CALL
|
CALL
|
||||||
LOADCP LOADER_START
|
LOADCP LOADER_START
|
||||||
|
|
|
||||||
|
|
@ -264,8 +264,8 @@ CARD_OK:
|
||||||
; set fast transfer rate
|
; set fast transfer rate
|
||||||
CARDFASTCLK:
|
CARDFASTCLK:
|
||||||
LOADC SPIREG
|
LOADC SPIREG
|
||||||
; set clock divider to ~2.75MHz
|
; set clock divider to ~2,6MHz
|
||||||
LOADCP SPI_CLK_DIV_WR,7 ; using the LOADCP with offset syntax here
|
LOADCP SPI_CLK_DIV_WR,10 ; using the LOADCP with offset syntax here
|
||||||
STOREI
|
STOREI
|
||||||
DROP
|
DROP
|
||||||
RET
|
RET
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,8 @@ const IONoError = 0;
|
||||||
IOReadOnly = 8;
|
IOReadOnly = 8;
|
||||||
IOInvalidOp = 9;
|
IOInvalidOp = 9;
|
||||||
IOInvalidFormat = 10;
|
IOInvalidFormat = 10;
|
||||||
IONoMem = 11;
|
IOUserIntr = 11;
|
||||||
IOUserIntr = 12;
|
IOMaxErr = 11;
|
||||||
IOMaxErr = 12;
|
|
||||||
|
|
||||||
const PArgMax = 7;
|
const PArgMax = 7;
|
||||||
|
|
||||||
|
|
@ -149,11 +148,10 @@ procedure appendchar(var s:string; aChar:char); external;
|
||||||
procedure strmoveup(var s:string;index,length,delta:integer); external;
|
procedure strmoveup(var s:string;index,length,delta:integer); external;
|
||||||
procedure strmovedown(var s:string;index,length,delta:integer); external;
|
procedure strmovedown(var s:string;index,length,delta:integer); external;
|
||||||
procedure RuntimeError(var s:string); external;
|
procedure RuntimeError(var s:string); external;
|
||||||
function MemAvail:integer; external;
|
|
||||||
|
|
||||||
(* from stdlib *)
|
(* from stdlib *)
|
||||||
function copy(s:string[256];index,count:integer):string[256]; external;
|
function copy(s:string;index,count:integer):string; external;
|
||||||
procedure insert(ins:string[256]; var dest:string[256]; position:integer); external;
|
procedure insert(ins: string; var dest: string; position:integer); external;
|
||||||
procedure delete(var s:string; from:integer; count:integer); external;
|
procedure delete(var s:string; from:integer; count:integer); external;
|
||||||
function pos(substr:string;var s:string):integer; external;
|
function pos(substr:string;var s:string):integer; external;
|
||||||
function pwroften(exp:integer):real; external;
|
function pwroften(exp:integer):real; external;
|
||||||
|
|
@ -207,7 +205,7 @@ procedure readvolumeblks(volumeid:integer; destbuf:^iobuffer; blkno:integer; blk
|
||||||
procedure writevolumeblks(volumeid:integer; srcbuf:^iobuffer; blkno:integer; blkCount: integer; var error:integer);
|
procedure writevolumeblks(volumeid:integer; srcbuf:^iobuffer; blkno:integer; blkCount: integer; var error:integer);
|
||||||
external;
|
external;
|
||||||
function findvolume(name:string):integer; external;
|
function findvolume(name:string):integer; external;
|
||||||
procedure openvolumeid(volid:integer;var error:integer); external;
|
procedure openvolumeid(volid:integer); external;
|
||||||
procedure closevolumeid(volid:integer); external;
|
procedure closevolumeid(volid:integer); external;
|
||||||
function IOResult(var fil:file):integer; external;
|
function IOResult(var fil:file):integer; external;
|
||||||
function ErrorStr(err:integer):string; external;
|
function ErrorStr(err:integer):string; external;
|
||||||
|
|
@ -242,7 +240,6 @@ procedure freadreal(var v:real;var f:file); external;
|
||||||
procedure openchannel(name:filenamestr; var f:file; mode:filemode; var error:integer); external;
|
procedure openchannel(name:filenamestr; var f:file; mode:filemode; var error:integer); external;
|
||||||
procedure open(var f:file; name:pathnamestr; mode: filemode); external;
|
procedure open(var f:file; name:pathnamestr; mode: filemode); external;
|
||||||
procedure noecho(var f:file; noecho:boolean; var old:boolean); external;
|
procedure noecho(var f:file; noecho:boolean; var old:boolean); external;
|
||||||
procedure nointr(var f:file; aBool:boolean; var old:boolean); external;
|
|
||||||
|
|
||||||
procedure intstr(v:integer; fieldWith:integer; var rbuf:string);
|
procedure intstr(v:integer; fieldWith:integer; var rbuf:string);
|
||||||
external;
|
external;
|
||||||
|
|
@ -272,8 +269,8 @@ procedure TextDefault; external;
|
||||||
|
|
||||||
procedure PTerm; external; (* from runtime.s *)
|
procedure PTerm; external; (* from runtime.s *)
|
||||||
procedure PExec(prgfile:pathnamestr; var args:PArgVec; argCount:integer;var error:integer); external;
|
procedure PExec(prgfile:pathnamestr; var args:PArgVec; argCount:integer;var error:integer); external;
|
||||||
procedure PExec1(prgfile:pathnamestr; arg1:string; var error:integer); external;
|
procedure PExec2(prgfile:pathnamestr; arg1:string; var error:integer); external;
|
||||||
procedure PExec2(prgfile:pathnamestr; arg1, arg2:string; var error:integer); external;
|
procedure PExec3(prgfile:pathnamestr; arg1, arg2:string; var error:integer); external;
|
||||||
function ParamStr(i:integer):string; external;
|
function ParamStr(i:integer):string; external;
|
||||||
function ParamCount():integer; external;
|
function ParamCount():integer; external;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,9 +26,8 @@ const IONoError = 0;
|
||||||
IOReadOnly = 8;
|
IOReadOnly = 8;
|
||||||
IOInvalidOp = 9;
|
IOInvalidOp = 9;
|
||||||
IOInvalidFormat = 10;
|
IOInvalidFormat = 10;
|
||||||
IONoMem = 11;
|
IOUserIntr = 11;
|
||||||
IOUserIntr = 12;
|
IOMaxErr = 11;
|
||||||
IOMaxErr = 12;
|
|
||||||
|
|
||||||
const PArgMax = 7;
|
const PArgMax = 7;
|
||||||
|
|
||||||
|
|
@ -48,7 +47,7 @@ type file = record
|
||||||
ateof:boolean;
|
ateof:boolean;
|
||||||
noecho:boolean; (* read chars are not echoed *)
|
noecho:boolean; (* read chars are not echoed *)
|
||||||
raw:boolean; (* turn off backspace processing on input, CR processing on output *)
|
raw:boolean; (* turn off backspace processing on input, CR processing on output *)
|
||||||
nointr:boolean); (* turn off keyboard interrupt character processing *)
|
nointr: boolean); (* turn off keyboard interrupt character processing *)
|
||||||
|
|
||||||
IODiskFile: (volumeid: integer;fileno: integer; filpos:integer; bufStart:integer;
|
IODiskFile: (volumeid: integer;fileno: integer; filpos:integer; bufStart:integer;
|
||||||
size:integer; sizeExtents:integer;
|
size:integer; sizeExtents:integer;
|
||||||
|
|
@ -134,7 +133,7 @@ var DefaultVolumeId:integer;
|
||||||
character to the runtime error routine
|
character to the runtime error routine
|
||||||
which takes null-terminated strings.
|
which takes null-terminated strings.
|
||||||
*)
|
*)
|
||||||
var ioerrordesc: array [0..IOMaxErr] of string[20] = (
|
var ioerrordesc: array [0..11] of string[20] = (
|
||||||
'No error',
|
'No error',
|
||||||
'File not found',
|
'File not found',
|
||||||
'Volume not found',
|
'Volume not found',
|
||||||
|
|
@ -146,14 +145,13 @@ var ioerrordesc: array [0..IOMaxErr] of string[20] = (
|
||||||
'File is readonly',
|
'File is readonly',
|
||||||
'Invalid operation',
|
'Invalid operation',
|
||||||
'Invalid format',
|
'Invalid format',
|
||||||
'Not enough memory',
|
|
||||||
'Interrupted by user'
|
'Interrupted by user'
|
||||||
);
|
);
|
||||||
|
|
||||||
matherror:string[38] = 'Invalid argument to sqrt/ln/tan/cotan';
|
matherror:string[38] = 'Invalid argument to sqrt/ln/tan/cotan';
|
||||||
pexecerror:string[28]= 'Invalid arguments for PExec';
|
pexecerror:string[28]= 'Invalid arguments for PExec';
|
||||||
|
|
||||||
random_state:integer = -42;
|
random_state:integer;
|
||||||
|
|
||||||
PArgs:array [0..PArgMax] of string external;
|
PArgs:array [0..PArgMax] of string external;
|
||||||
PArgCount:integer external;
|
PArgCount:integer external;
|
||||||
|
|
@ -404,7 +402,7 @@ begin
|
||||||
GetCurTimestamp := GetTimestamp(now);
|
GetCurTimestamp := GetTimestamp(now);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function copy(s:string[256];index,count:integer):string[256];
|
function copy(s:string;index,count:integer):string;
|
||||||
var len:integer;
|
var len:integer;
|
||||||
begin
|
begin
|
||||||
copy := '';
|
copy := '';
|
||||||
|
|
@ -418,7 +416,7 @@ begin
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure insert(ins:string[256]; var dest:string[256]; position:integer);
|
procedure insert(ins: string; var dest: string; position:integer);
|
||||||
var i,count,from,to_:integer;
|
var i,count,from,to_:integer;
|
||||||
begin
|
begin
|
||||||
if position < 1 then position := 1;
|
if position < 1 then position := 1;
|
||||||
|
|
@ -482,9 +480,6 @@ end;
|
||||||
That means you cannot use pos to search inside a string
|
That means you cannot use pos to search inside a string
|
||||||
literal. Hopefully this is not something you want to do.
|
literal. Hopefully this is not something you want to do.
|
||||||
*)
|
*)
|
||||||
|
|
||||||
(* TODO: UCSD-Pascal and TP3.0 specs say, searched string
|
|
||||||
is a string expression so cannot be var parameter *)
|
|
||||||
function pos(substr:string;var s:string):integer;
|
function pos(substr:string;var s:string):integer;
|
||||||
var substrlen:integer;
|
var substrlen:integer;
|
||||||
slen:integer;
|
slen:integer;
|
||||||
|
|
@ -1184,18 +1179,8 @@ ext:
|
||||||
v := x;
|
v := x;
|
||||||
code := 0;
|
code := 0;
|
||||||
end
|
end
|
||||||
else
|
|
||||||
begin
|
|
||||||
if i = 1 then (* empty string gives error position 1 *)
|
|
||||||
code := 1
|
|
||||||
else
|
else
|
||||||
code := i - 1;
|
code := i - 1;
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure errorhalt(var fil:file);
|
|
||||||
begin
|
|
||||||
RuntimeError(ioerrordesc[fil.lastError]);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure checkerror(var fil:file);
|
procedure checkerror(var fil:file);
|
||||||
|
|
@ -1203,7 +1188,7 @@ begin
|
||||||
if fil.lastError <> 0 then
|
if fil.lastError <> 0 then
|
||||||
begin
|
begin
|
||||||
if not fil.errorAck then
|
if not fil.errorAck then
|
||||||
errorhalt(fil)
|
RuntimeError(ioerrordesc[fil.lastError])
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
fil.lastError := 0;
|
fil.lastError := 0;
|
||||||
|
|
@ -1346,16 +1331,12 @@ procedure freadreal(var v:real;var f:file);
|
||||||
var buf:string[40];
|
var buf:string[40];
|
||||||
errpos:integer;
|
errpos:integer;
|
||||||
begin
|
begin
|
||||||
errpos := -1;
|
|
||||||
fskipwhite(f);
|
fskipwhite(f);
|
||||||
fscanbuf(f,ScanReal, buf);
|
fscanbuf(f,ScanReal, buf);
|
||||||
if f.lastError = 0 then
|
if f.lastError = 0 then
|
||||||
val(buf, v, errpos);
|
val(buf, v, errpos);
|
||||||
if errpos <> 0 then
|
if errpos <> 0 then
|
||||||
begin
|
|
||||||
fileerror(f, IOInvalidFormat);
|
fileerror(f, IOInvalidFormat);
|
||||||
checkerror(f);
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure freadstring(var s:string; var f:file);
|
procedure freadstring(var s:string; var f:file);
|
||||||
|
|
@ -1368,7 +1349,7 @@ var aChar:char;
|
||||||
begin
|
begin
|
||||||
repeat
|
repeat
|
||||||
aChar := freadchar(aFile);
|
aChar := freadchar(aFile);
|
||||||
until eoln(aFile); (* eoln checks for cr, lf and eof *)
|
until (aChar = #13) or eof(aFile);
|
||||||
|
|
||||||
(*
|
(*
|
||||||
If it is a disk file, try to read the
|
If it is a disk file, try to read the
|
||||||
|
|
@ -1556,17 +1537,13 @@ begin
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure openvolumeid(volid:integer;var error:integer);
|
procedure openvolumeid(volid:integer);
|
||||||
begin
|
begin
|
||||||
error := 0;
|
|
||||||
with volumeTable[volid] do
|
with volumeTable[volid] do
|
||||||
begin
|
begin
|
||||||
if dirCache = nil then
|
if dirCache = nil then
|
||||||
newOrNil(dirCache);
|
new(dirCache);
|
||||||
if dirCache <> nil then
|
openFilesCount := openFilesCount + 1;
|
||||||
openFilesCount := openFilesCount + 1
|
|
||||||
else
|
|
||||||
error := IONoMem;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
@ -1685,21 +1662,12 @@ begin
|
||||||
{ writeln(' readbuf data: ', fil.buffer^[0][0]); }
|
{ writeln(' readbuf data: ', fil.buffer^[0][0]); }
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure close(var aFile:file); forward;
|
|
||||||
|
|
||||||
(* Set error state on file and close it.
|
|
||||||
Buffer will not be flushed as that might
|
|
||||||
have caused the error.
|
|
||||||
*)
|
|
||||||
procedure fileerror(var fil:file; error:integer);
|
procedure fileerror(var fil:file; error:integer);
|
||||||
begin
|
begin
|
||||||
|
(* should check if there was an error already
|
||||||
|
and throw a runtime error in that case *)
|
||||||
fil.lastError := error;
|
fil.lastError := error;
|
||||||
fil.errorAck := false;
|
fil.errorAck := false;
|
||||||
if fil.buffer <> nil then
|
|
||||||
begin
|
|
||||||
fil.needsflush := false;
|
|
||||||
close(fil);
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function IOResult(var fil:file):integer;
|
function IOResult(var fil:file):integer;
|
||||||
|
|
@ -1844,8 +1812,6 @@ end;
|
||||||
|
|
||||||
function filesize(var fil:file):integer;
|
function filesize(var fil:file):integer;
|
||||||
begin
|
begin
|
||||||
checkerror(fil);
|
|
||||||
|
|
||||||
if fil.typ = IOChannel then
|
if fil.typ = IOChannel then
|
||||||
filesize := -1
|
filesize := -1
|
||||||
else
|
else
|
||||||
|
|
@ -2044,11 +2010,7 @@ begin
|
||||||
|
|
||||||
aFile.typ := IODiskFile;
|
aFile.typ := IODiskFile;
|
||||||
aFile.mode := mode;
|
aFile.mode := mode;
|
||||||
newOrNil(aFile.buffer);
|
new(aFile.buffer);
|
||||||
if aFile.buffer = nil then
|
|
||||||
fileerror(aFile, IONoMem)
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
aFile.bufpos := 0;
|
aFile.bufpos := 0;
|
||||||
aFile.bufsize := DefaultBufSize;
|
aFile.bufsize := DefaultBufSize;
|
||||||
aFile.needsflush := false;
|
aFile.needsflush := false;
|
||||||
|
|
@ -2065,7 +2027,6 @@ begin
|
||||||
aFile.extentBlocks := extentSize div 512;
|
aFile.extentBlocks := extentSize div 512;
|
||||||
|
|
||||||
seek(aFile,0);
|
seek(aFile,0);
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure updatedirslot(var aFile:file);
|
procedure updatedirslot(var aFile:file);
|
||||||
|
|
@ -2088,22 +2049,19 @@ procedure close(var aFile:file);
|
||||||
begin
|
begin
|
||||||
if aFile.typ = IODiskFile then
|
if aFile.typ = IODiskFile then
|
||||||
begin
|
begin
|
||||||
if aFile.lastError = IOFileClosed then
|
|
||||||
errorhalt(aFile);
|
|
||||||
{ writeln('close needsflush:', aFile.needsflush, ' changed:', aFile.changed, ' error:', aFile.lastError); }
|
{ writeln('close needsflush:', aFile.needsflush, ' changed:', aFile.changed, ' error:', aFile.lastError); }
|
||||||
if aFile.needsflush then
|
if aFile.needsflush then
|
||||||
flushfile(aFile);
|
flushfile(aFile);
|
||||||
|
if aFile.lastError = 0 then
|
||||||
|
begin
|
||||||
|
fileerror(aFile, IOFileClosed);
|
||||||
{ writeln('close f.buffer:', aFile.buffer); }
|
{ writeln('close f.buffer:', aFile.buffer); }
|
||||||
dispose(aFile.buffer);
|
dispose(aFile.buffer);
|
||||||
aFile.buffer := nil;
|
aFile.buffer := nil;
|
||||||
|
|
||||||
if aFile.lastError = 0 then
|
|
||||||
begin
|
|
||||||
if aFile.changed then
|
if aFile.changed then
|
||||||
updatedirslot(aFile);
|
updatedirslot(aFile);
|
||||||
if aFile.lastError = 0 then
|
|
||||||
fileerror(aFile, IOFileClosed);
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
closevolumeid(aFile.volumeid);
|
closevolumeid(aFile.volumeid);
|
||||||
|
|
@ -2282,8 +2240,7 @@ begin
|
||||||
|
|
||||||
if volid > 0 then
|
if volid > 0 then
|
||||||
begin
|
begin
|
||||||
openvolumeid(volid, error);
|
openvolumeid(volid);
|
||||||
if error = 0 then
|
|
||||||
slotno := findfile(volid, fname, dirs, error)
|
slotno := findfile(volid, fname, dirs, error)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
|
@ -2603,16 +2560,6 @@ begin
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure nointr(var f:file;aBool:boolean;var old:boolean);
|
|
||||||
begin
|
|
||||||
if f.typ <> IOChannel then
|
|
||||||
fileerror(f, IOInvalidOp)
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
old := f.nointr;
|
|
||||||
f.nointr := aBool;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
(*
|
(*
|
||||||
implementation of Xorshift algorithm by George Marsaglia,
|
implementation of Xorshift algorithm by George Marsaglia,
|
||||||
see: Marsaglia, George (July 2003).
|
see: Marsaglia, George (July 2003).
|
||||||
|
|
@ -2649,7 +2596,6 @@ begin
|
||||||
if ord(aChar) <= ord('z') then
|
if ord(aChar) <= ord('z') then
|
||||||
upcase := chr(ord(aChar) - 32)
|
upcase := chr(ord(aChar) - 32)
|
||||||
else
|
else
|
||||||
upcase := aChar
|
|
||||||
else
|
else
|
||||||
upcase := aChar;
|
upcase := aChar;
|
||||||
end;
|
end;
|
||||||
|
|
@ -2715,14 +2661,14 @@ begin
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure PExec1(prgfile:pathnamestr; arg1:string; var error:integer);
|
procedure PExec2(prgfile:pathnamestr; arg1:string; var error:integer);
|
||||||
var args:PArgVec;
|
var args:PArgVec;
|
||||||
begin
|
begin
|
||||||
args[0] := arg1;
|
args[0] := arg1;
|
||||||
PExec(prgfile, args, 1, error);
|
PExec(prgfile, args, 1, error);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure PExec2(prgfile:pathnamestr; arg1, arg2:string; var error:integer);
|
procedure PExec3(prgfile:pathnamestr; arg1, arg2:string; var error:integer);
|
||||||
var args:PArgVec;
|
var args:PArgVec;
|
||||||
begin
|
begin
|
||||||
args[0] := arg1;
|
args[0] := arg1;
|
||||||
|
|
|
||||||
|
|
@ -1,45 +1,47 @@
|
||||||
PCOMP=./pcomp
|
PCOMP=./pcomp
|
||||||
SASM=./sasm
|
SASM=./sasm
|
||||||
LSYMGEN=./lsymgen
|
LSYMGEN=./lsymgen
|
||||||
|
LIBGEN=./libgen
|
||||||
|
|
||||||
.SUFFIXES:
|
.SUFFIXES:
|
||||||
.SUFFIXES: .pas .o .s .prog
|
.SUFFIXES: .pas .o
|
||||||
|
|
||||||
.pas.s:
|
|
||||||
$(PCOMP) $<
|
|
||||||
.s.prog:
|
|
||||||
$(SASM) $<
|
|
||||||
|
|
||||||
.pas:
|
.pas:
|
||||||
fpc -Mobjfpc -gl $<
|
fpc -Mobjfpc -gl $<
|
||||||
|
|
||||||
all: libs pcomp sasm sdis lsymgen shortgen nativecomp nativeprogs
|
all: pcomp sasm sdis libgen lsymgen
|
||||||
|
|
||||||
libs: pcomp sasm lsymgen shortgen
|
libs: pcomp sasm lsymgen libgen
|
||||||
$(SASM) ../lib/coreloader.s
|
$(SASM) ../lib/coreloader.s
|
||||||
$(LSYMGEN) ../lib/coreloader.sym
|
$(LSYMGEN) ../lib/coreloader.sym
|
||||||
$(PCOMP) -n ../lib/stdlib.pas
|
$(PCOMP) -n ../lib/stdlib.pas
|
||||||
$(SASM) ../lib/stdlibwrap.s ../lib/stdlib.lib
|
$(LIBGEN) ../lib/stdlib.s
|
||||||
$(LSYMGEN) ../lib/stdlibwrap.sym ../lib/stdlib.lsym
|
$(LIBGEN) ../lib/runtime.s
|
||||||
|
$(LIBGEN) ../lib/float32.s
|
||||||
|
|
||||||
test: libs sasm.s pcomp.s lsymgen.s shortgen.s
|
nativecomp: pcomp sasm libs
|
||||||
|
$(PCOMP) sasm.pas
|
||||||
|
$(PCOMP) pcomp.pas
|
||||||
|
$(PCOMP) lsymgen.pas
|
||||||
|
$(PCOMP) libgen.pas
|
||||||
|
|
||||||
testprgs: libs sasm.prog pcomp.prog lsymgen.prog shortgen.prog
|
nativeprogs: nativecomp
|
||||||
|
$(PCOMP) ../progs/shell.pas
|
||||||
nativecomp: libs pcomp.prog sasm.prog lsymgen.prog shortgen.prog
|
$(PCOMP) ../progs/editor.pas
|
||||||
|
$(PCOMP) ../progs/reclaim.pas
|
||||||
nativeprogs: pcomp ../progs/shell.prog ../progs/editor.prog ../progs/reclaim.prog \
|
$(PCOMP) ../progs/dumpdir.pas
|
||||||
../progs/dumpdir.prog ../progs/partmgr.prog ../progs/xfer.prog \
|
$(PCOMP) ../progs/partmgr.pas
|
||||||
../progs/recover.prog ../progs/changemem.prog
|
$(PCOMP) ../progs/xfer.pas
|
||||||
$(SASM) ../lib/rommon.s
|
$(SASM) ../lib/rommon.s
|
||||||
$(SASM) -A ../lib/rommon.s ../lib/rom.mem
|
$(SASM) -A ../lib/rommon.s ../lib/rom.mem
|
||||||
|
examples: nativecomp
|
||||||
examples: nativecomp ../tests/readtest.prog ../tests/readchartest.prog ../tests/timetest.prog \
|
$(PCOMP) ../tests/readtest.pas
|
||||||
../tests/test133.prog ../tests/cchangetest.prog ../tests/tree.prog
|
$(PCOMP) ../tests/readchartest.pas
|
||||||
|
$(PCOMP) ../tests/timetest.pas
|
||||||
|
$(PCOMP) ../tests/test133.pas
|
||||||
-$(PCOMP) ../examples/chase.pas
|
-$(PCOMP) ../examples/chase.pas
|
||||||
-$(SASM) ../examples/chase.s
|
$(PCOMP) ../tests/cchangetest.pas
|
||||||
-$(MAKE) -C ../rogue -f Makefile.tridoracpu
|
$(PCOMP) ../tests/tree.pas
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f pcomp sasm sdis libgen lsymgen shortgen*.o *.s *.prog \
|
rm -f pcomp sasm sdis libgen lsymgen *.o *.s
|
||||||
../lib/stdlib.s ../lib/stdlib.lib ../lib/stdlib.lsym
|
|
||||||
|
|
|
||||||
|
|
@ -111,7 +111,7 @@ begin
|
||||||
emitIns2('BRANCH','@+2'); (* NOP, to make alignment explicit *)
|
emitIns2('BRANCH','@+2'); (* NOP, to make alignment explicit *)
|
||||||
emitIns('.CPOOL'); (* header/prologue + 2 constants is 32 bytes *)
|
emitIns('.CPOOL'); (* header/prologue + 2 constants is 32 bytes *)
|
||||||
|
|
||||||
if useStdlib and not useStandalone then
|
if useStdlib then
|
||||||
begin
|
begin
|
||||||
writeln(outfile, '%include "stdlib.lsym"');
|
writeln(outfile, '%include "stdlib.lsym"');
|
||||||
writeln(outfile, '%incbin "stdlib.lib"');
|
writeln(outfile, '%incbin "stdlib.lib"');
|
||||||
|
|
@ -312,21 +312,14 @@ begin
|
||||||
emitArrayConsts;
|
emitArrayConsts;
|
||||||
|
|
||||||
if useStandalone then
|
if useStandalone then
|
||||||
begin
|
emitInclude('corelib.s')
|
||||||
emitInclude('corelib.s');
|
|
||||||
emitInclude('runtime.s');
|
|
||||||
emitInclude('float32.s');
|
|
||||||
emitInclude('stdlib.s');
|
|
||||||
end
|
|
||||||
else
|
else
|
||||||
emitInclude('coreloader.lsym');
|
emitInclude('coreloader.lsym');
|
||||||
|
|
||||||
rewindStringList(usedUnits);
|
rewindStringList(usedUnits);
|
||||||
while nextStringListItem(usedUnits, unitName) do
|
while nextStringListItem(usedUnits, unitName) do
|
||||||
emitInclude(unitName + UnitSuffix2);
|
emitInclude(unitName + UnitSuffix2);
|
||||||
(* _END label needs to be word-aligned because
|
|
||||||
it is used as the start of the heap *)
|
|
||||||
emitIns('.ALIGN');
|
|
||||||
emitLabelRaw('_END');
|
emitLabelRaw('_END');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
@ -1066,7 +1059,6 @@ end;
|
||||||
*)
|
*)
|
||||||
procedure emitProcedureCall(aProc: ProcRef);
|
procedure emitProcedureCall(aProc: ProcRef);
|
||||||
var procLabel: IdentString;
|
var procLabel: IdentString;
|
||||||
i:integer;
|
|
||||||
begin
|
begin
|
||||||
(* pass pointer to stackframe of caller for nested procedures *)
|
(* pass pointer to stackframe of caller for nested procedures *)
|
||||||
if aProc^.isNested then
|
if aProc^.isNested then
|
||||||
|
|
@ -1077,17 +1069,9 @@ begin
|
||||||
if aProc^.level > curProcedure^.level then
|
if aProc^.level > curProcedure^.level then
|
||||||
emitIns2('LOADREG','FP')
|
emitIns2('LOADREG','FP')
|
||||||
else
|
else
|
||||||
begin
|
(* TODO: calling nested aProc with a lower nesting level.
|
||||||
(* Calling nested aProc with a lower nesting level.
|
need to chase a chain of old BP pointers. *)
|
||||||
Need to chase a chain of old BP pointers. *)
|
errorExit2('internal error: outward call of nested aProc not implemented', '');
|
||||||
emitIns2('LOADREG', 'BP');
|
|
||||||
(* BP points to the stackframe of the outer procedure,
|
|
||||||
@BP contains the stackframe of the procedure one step further
|
|
||||||
outwards, and so on.
|
|
||||||
*)
|
|
||||||
for i := aProc^.level + 1 to curProcedure^.level do
|
|
||||||
emitIns('LOADI');
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
emitFpAdjust(-curProcedure^.tempsSize);
|
emitFpAdjust(-curProcedure^.tempsSize);
|
||||||
|
|
@ -1266,7 +1250,7 @@ begin
|
||||||
(* nothing to do *)
|
(* nothing to do *)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if (amount > 0) and (amount <= MaxTinyOffset) then
|
if amount <= MaxTinyOffset then
|
||||||
emitIns2Int('INC', amount)
|
emitIns2Int('INC', amount)
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
|
|
@ -1282,7 +1266,7 @@ begin
|
||||||
(* nothing to do *)
|
(* nothing to do *)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if (amount > 0) and (amount <= MaxTinyOffset) then
|
if amount <= MaxTinyOffset then
|
||||||
emitIns2Int('DEC', amount)
|
emitIns2Int('DEC', amount)
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@ rem exit /b
|
||||||
py pcomp.py sasm.pas
|
py pcomp.py sasm.pas
|
||||||
py pcomp.py pcomp.pas
|
py pcomp.py pcomp.pas
|
||||||
py pcomp.py lsymgen.pas
|
py pcomp.py lsymgen.pas
|
||||||
py pcomp.py shortgen.pas
|
py pcomp.py libgen.pas
|
||||||
|
|
||||||
rem exit /b
|
rem exit /b
|
||||||
|
|
||||||
|
|
@ -27,8 +27,6 @@ py pcomp.py ..\progs\reclaim.pas
|
||||||
py pcomp.py ..\progs\dumpdir.pas
|
py pcomp.py ..\progs\dumpdir.pas
|
||||||
py pcomp.py ..\progs\partmgr.pas
|
py pcomp.py ..\progs\partmgr.pas
|
||||||
py pcomp.py ..\progs\xfer.pas
|
py pcomp.py ..\progs\xfer.pas
|
||||||
py pcomp.py ..\progs\recover.pas
|
|
||||||
py pcomp.py ..\progs\changemem.pas
|
|
||||||
sasm ..\lib\rommon.s
|
sasm ..\lib\rommon.s
|
||||||
sasm -A ..\lib\rommon.s ..\lib\rom.mem
|
sasm -A ..\lib\rommon.s ..\lib\rom.mem
|
||||||
|
|
||||||
|
|
@ -41,11 +39,3 @@ py pcomp.py ..\tests\test133.pas
|
||||||
py pcomp.py ..\examples\chase.pas
|
py pcomp.py ..\examples\chase.pas
|
||||||
py pcomp.py ..\tests\cchangetest.pas
|
py pcomp.py ..\tests\cchangetest.pas
|
||||||
py pcomp.py ..\tests\tree.pas
|
py pcomp.py ..\tests\tree.pas
|
||||||
|
|
||||||
if not exist ..\rogue\rogue.pas exit /b
|
|
||||||
|
|
||||||
cd ..\rogue
|
|
||||||
..\pcomp\pcomp rogue.pas
|
|
||||||
..\pcomp\sasm rogue.s
|
|
||||||
|
|
||||||
cd ..\pcomp
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,4 @@
|
||||||
(* Copyright 2021-2024 Sebastian Lederer. See the file LICENSE.md for details *)
|
(* Copyright 2021-2024 Sebastian Lederer. See the file LICENSE.md for details *)
|
||||||
{$H600}
|
|
||||||
{$S64}
|
|
||||||
program PascalCompiler;
|
program PascalCompiler;
|
||||||
{$R+}
|
{$R+}
|
||||||
{$!}{$ifdef FPC}uses math,crt;{$endif}
|
{$!}{$ifdef FPC}uses math,crt;{$endif}
|
||||||
|
|
@ -43,7 +41,7 @@ type TokenType = (
|
||||||
ArrayType, RecordType, PointerType, StringCharType, EnumType,
|
ArrayType, RecordType, PointerType, StringCharType, EnumType,
|
||||||
SetType, UnresolvedType );
|
SetType, UnresolvedType );
|
||||||
|
|
||||||
SpecialProc = ( NoSP, NewSP, New0SP, DisposeSP, ReadSP, WriteSP, ReadlnSP, WritelnSP,
|
SpecialProc = ( NoSP, NewSP, DisposeSP, ReadSP, WriteSP, ReadlnSP, WritelnSP,
|
||||||
SetlengthSP, ValSP, StrSP, ExitSP );
|
SetlengthSP, ValSP, StrSP, ExitSP );
|
||||||
SpecialFunc = ( NoSF, TruncSF, FracSF, IntSF, SqrSF, SuccSF, PredSF,
|
SpecialFunc = ( NoSF, TruncSF, FracSF, IntSF, SqrSF, SuccSF, PredSF,
|
||||||
OddSF, ChrSF, OrdSF, AbsSF);
|
OddSF, ChrSF, OrdSF, AbsSF);
|
||||||
|
|
@ -263,7 +261,7 @@ const insSize = 2;
|
||||||
MaxIncludes = 4;
|
MaxIncludes = 4;
|
||||||
StdLibName = 'stdlib';
|
StdLibName = 'stdlib';
|
||||||
UnitSuffix1 = '.inc';
|
UnitSuffix1 = '.inc';
|
||||||
UnitSuffix2 = '.s';
|
UnitSuffix2 = '.lib';
|
||||||
FilenameSuffix = '.pas';
|
FilenameSuffix = '.pas';
|
||||||
OutfileSuffix = '.s';
|
OutfileSuffix = '.s';
|
||||||
InputFileName = 'INPUT';
|
InputFileName = 'INPUT';
|
||||||
|
|
@ -291,7 +289,7 @@ var
|
||||||
'UNIT', 'IMPLEMENTATION', 'INTERFACE', 'USES',
|
'UNIT', 'IMPLEMENTATION', 'INTERFACE', 'USES',
|
||||||
'_' );
|
'_' );
|
||||||
specialprocnames: array [SpecialProc] of string[12] = (
|
specialprocnames: array [SpecialProc] of string[12] = (
|
||||||
'_', 'NEW', 'NEWORNIL', 'DISPOSE', 'READ', 'WRITE', 'READLN', 'WRITELN', 'SETLENGTH',
|
'_', 'NEW', 'DISPOSE', 'READ', 'WRITE', 'READLN', 'WRITELN', 'SETLENGTH',
|
||||||
'VAL','STR', 'EXIT');
|
'VAL','STR', 'EXIT');
|
||||||
specialfuncnames: array [SpecialFunc] of string[8] = (
|
specialfuncnames: array [SpecialFunc] of string[8] = (
|
||||||
'_', 'TRUNC', 'FRAC', 'INT', 'SQR', 'SUCC', 'PRED', 'ODD',
|
'_', 'TRUNC', 'FRAC', 'INT', 'SQR', 'SUCC', 'PRED', 'ODD',
|
||||||
|
|
@ -2186,7 +2184,7 @@ begin
|
||||||
if ch = '!' then
|
if ch = '!' then
|
||||||
(* special comment till end of line *)
|
(* special comment till end of line *)
|
||||||
begin
|
begin
|
||||||
while not (nextChar in [#13, #10]) do (* nothing *);
|
while not (nextChar = #13) do (* nothing *);
|
||||||
readNextToken;
|
readNextToken;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
|
|
@ -2456,7 +2454,10 @@ begin
|
||||||
begin
|
begin
|
||||||
digits := curToken.tokenText;
|
digits := curToken.tokenText;
|
||||||
if matchTokenOrNot(MinusToken) then
|
if matchTokenOrNot(MinusToken) then
|
||||||
|
begin
|
||||||
|
readNextToken;
|
||||||
digits := digits + curToken.tokenText;
|
digits := digits + curToken.tokenText;
|
||||||
|
end;
|
||||||
parseInteger := integerFromString(digits);
|
parseInteger := integerFromString(digits);
|
||||||
end;
|
end;
|
||||||
readNextToken;
|
readNextToken;
|
||||||
|
|
@ -2809,8 +2810,6 @@ begin
|
||||||
|
|
||||||
if checkToken(CommaToken) then
|
if checkToken(CommaToken) then
|
||||||
begin
|
begin
|
||||||
(* TODO: handle comma syntax for indexing a char
|
|
||||||
from an array of strings *)
|
|
||||||
if elType.baseType <> ArrayType then
|
if elType.baseType <> ArrayType then
|
||||||
errorExit2('invalid array subscript for', name)
|
errorExit2('invalid array subscript for', name)
|
||||||
end;
|
end;
|
||||||
|
|
@ -3230,22 +3229,10 @@ begin
|
||||||
readNextToken;
|
readNextToken;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
(* Handle an array range part. Very similar to parseInteger
|
|
||||||
but additionally handles Boolean, Enum and Char types which
|
|
||||||
can be used for array indices *)
|
|
||||||
procedure getRangePart(var value:integer; var typeReturn: TypeSpec);
|
procedure getRangePart(var value:integer; var typeReturn: TypeSpec);
|
||||||
var cnst: ConstRef;
|
var cnst: ConstRef;
|
||||||
negate:boolean;
|
|
||||||
digits: string[12];
|
|
||||||
begin
|
begin
|
||||||
setBaseType(typeReturn, NoType);
|
setBaseType(typeReturn, NoType);
|
||||||
negate := false;
|
|
||||||
|
|
||||||
if checkToken(MinusToken) then
|
|
||||||
begin
|
|
||||||
negate := true;
|
|
||||||
readNextToken;
|
|
||||||
end;
|
|
||||||
|
|
||||||
if checkToken(IdentToken) then
|
if checkToken(IdentToken) then
|
||||||
begin
|
begin
|
||||||
|
|
@ -3279,11 +3266,7 @@ begin
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
setBaseType(typeReturn, IntegerType);
|
setBaseType(typeReturn, IntegerType);
|
||||||
digits := curToken.tokenText;
|
value := parseInteger;
|
||||||
if negate then
|
|
||||||
insert('-', digits, 1);
|
|
||||||
value := integerFromString(digits);
|
|
||||||
readNextToken;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
@ -3448,9 +3431,9 @@ begin
|
||||||
if savedType.baseType = NoType then
|
if savedType.baseType = NoType then
|
||||||
savedType := elementType;
|
savedType := elementType;
|
||||||
emitLoadConstantInt(cnst^.intValue);
|
emitLoadConstantInt(cnst^.intValue);
|
||||||
readNextToken;
|
|
||||||
end;
|
end;
|
||||||
emitAddToSet;
|
emitAddToSet;
|
||||||
|
readNextToken;
|
||||||
end
|
end
|
||||||
else if checkToken(NumberToken) then
|
else if checkToken(NumberToken) then
|
||||||
begin
|
begin
|
||||||
|
|
@ -4014,8 +3997,6 @@ begin
|
||||||
begin
|
begin
|
||||||
readNextToken;
|
readNextToken;
|
||||||
length := parseInteger;
|
length := parseInteger;
|
||||||
if length < 1 then
|
|
||||||
errorExit2('invalid string length', '');
|
|
||||||
matchToken(RBracketToken);
|
matchToken(RBracketToken);
|
||||||
end;
|
end;
|
||||||
typSpec.size := getStringMemSize(length);
|
typSpec.size := getStringMemSize(length);
|
||||||
|
|
@ -4500,7 +4481,7 @@ begin
|
||||||
isFunction := aProc^.returnType.baseType <> NoType;
|
isFunction := aProc^.returnType.baseType <> NoType;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure parseNew(checkNil:boolean);
|
procedure parseNew;
|
||||||
var memLoc: MemLocation;
|
var memLoc: MemLocation;
|
||||||
typeReturn: TypeSpec;
|
typeReturn: TypeSpec;
|
||||||
begin
|
begin
|
||||||
|
|
@ -4526,17 +4507,17 @@ begin
|
||||||
emitLoadConstantInt(memLoc.typ.pointedType^.size);
|
emitLoadConstantInt(memLoc.typ.pointedType^.size);
|
||||||
emitMemAlloc;
|
emitMemAlloc;
|
||||||
|
|
||||||
|
if typeContainsString(memLoc.typ.pointedType^) then
|
||||||
|
emitClearAlloc(memLoc.typ.pointedType);
|
||||||
|
end;
|
||||||
|
emitCheckAlloc;
|
||||||
|
|
||||||
(*We need to call CLEARMEM when the allocated type
|
(*We need to call CLEARMEM when the allocated type
|
||||||
contains strings.
|
contains strings.
|
||||||
INITSTRING checks if the header is non-zero to see if
|
INITSTRING checks if the header is non-zero to see if
|
||||||
the string is already initialized, and the allocated
|
the string is already initialized, and the allocated
|
||||||
chunk might contain random data so it would look
|
chunk might contain random data so it would look
|
||||||
like an initialized string. *)
|
like an initialized string. *)
|
||||||
if typeContainsString(memLoc.typ.pointedType^) then
|
|
||||||
emitClearAlloc(memLoc.typ.pointedType);
|
|
||||||
end;
|
|
||||||
if checkNil then
|
|
||||||
emitCheckAlloc;
|
|
||||||
|
|
||||||
writeVariable(memLoc);
|
writeVariable(memLoc);
|
||||||
|
|
||||||
|
|
@ -5017,9 +4998,7 @@ begin
|
||||||
NoSP:
|
NoSP:
|
||||||
errorExit2('internal error in parseSpecialProcCall', lastToken.tokenText);
|
errorExit2('internal error in parseSpecialProcCall', lastToken.tokenText);
|
||||||
NewSP:
|
NewSP:
|
||||||
parseNew(true);
|
parseNew;
|
||||||
New0SP:
|
|
||||||
parseNew(false);
|
|
||||||
DisposeSP:
|
DisposeSP:
|
||||||
parseDispose;
|
parseDispose;
|
||||||
ReadSP:
|
ReadSP:
|
||||||
|
|
@ -5832,19 +5811,6 @@ begin
|
||||||
matchToken(ColonToken);
|
matchToken(ColonToken);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure parseGotoStatement;
|
|
||||||
var aLabl: LablRef;
|
|
||||||
begin
|
|
||||||
readNextToken;
|
|
||||||
matchToken(IdentToken);
|
|
||||||
aLabl := findLabel(curProcedure, lastToken.tokenText);
|
|
||||||
if aLabl = nil then
|
|
||||||
errorExit2('GOTO to undefined label', lastToken.tokenText);
|
|
||||||
if curProcedure^.estackCleanup > 0 then
|
|
||||||
errorExit2('GOTO not allowed inside FOR or CASE', '');
|
|
||||||
emitLabelJump(aLabl);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure parseStatement;
|
procedure parseStatement;
|
||||||
var sym: SymblRef;
|
var sym: SymblRef;
|
||||||
cnst: ConstRef;
|
cnst: ConstRef;
|
||||||
|
|
@ -5870,7 +5836,13 @@ begin
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if checkToken(GotoToken) then
|
if checkToken(GotoToken) then
|
||||||
parseGotoStatement
|
begin
|
||||||
|
readNextToken;
|
||||||
|
matchToken(IdentToken);
|
||||||
|
aLabl := findLabel(curProcedure, lastToken.tokenText);
|
||||||
|
if aLabl = nil then errorExit2('GOTO to undefined label', lastToken.tokenText);
|
||||||
|
emitLabelJump(aLabl);
|
||||||
|
end
|
||||||
else
|
else
|
||||||
if checkToken(IfToken) then
|
if checkToken(IfToken) then
|
||||||
parseIfStatement
|
parseIfStatement
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
(* Copyright 2021-2024 Sebastian Lederer. See the file LICENSE.md for details *)
|
(* Copyright 2021-2024 Sebastian Lederer. See the file LICENSE.md for details *)
|
||||||
{$MODE objfpc}
|
{$MODE objfpc}
|
||||||
{$H600}
|
{$H600}
|
||||||
{$S32}
|
{$S4}
|
||||||
program sasm;
|
program sasm;
|
||||||
{$!}{$ifdef FPC}uses math,crt;{$endif}
|
{$!}{$ifdef FPC}uses math,crt;{$endif}
|
||||||
{$R+}
|
{$R+}
|
||||||
|
|
@ -1515,6 +1515,8 @@ begin
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if dref^.symboldata.value <> value then
|
if dref^.symboldata.value <> value then
|
||||||
|
(* writeln('////// label changed value ', keyword, ' ',
|
||||||
|
dref^.symboldata.value, ' -> ', value); *)
|
||||||
dref^.symboldata.value := value;
|
dref^.symboldata.value := value;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
@ -1870,9 +1872,9 @@ begin
|
||||||
if (pc and 3) = 0 then (* no padding *)
|
if (pc and 3) = 0 then (* no padding *)
|
||||||
begin
|
begin
|
||||||
pad := false;
|
pad := false;
|
||||||
(* total size 10 bytes *)
|
(* total size 8 bytes *)
|
||||||
offset := 4; (* offset for LOADREL *)
|
offset := 4; (* offset for LOADREL *)
|
||||||
shrinkage := 8; (* difference to short form size *)
|
shrinkage := 6; (* difference to short form size *)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
|
|
@ -1890,17 +1892,9 @@ begin
|
||||||
encodeInstruction('JUMP', 0, encoded);
|
encodeInstruction('JUMP', 0, encoded);
|
||||||
emitInstructionWord(encoded);
|
emitInstructionWord(encoded);
|
||||||
|
|
||||||
(* Padding is always done, so the length of the sequence does
|
|
||||||
not change depending on the position. The pad is either
|
|
||||||
placed before the address to align it on a word address,
|
|
||||||
or after, if it is already aligned. *)
|
|
||||||
if pad then
|
if pad then
|
||||||
emitInstructionWord(0);
|
emitInstructionWord(0);
|
||||||
|
|
||||||
emitWord(value);
|
emitWord(value);
|
||||||
|
|
||||||
if not pad then
|
|
||||||
emitInstructionWord(0);
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
|
|
@ -1943,9 +1937,9 @@ begin
|
||||||
if (pc and 3) = 2 then (* no padding *)
|
if (pc and 3) = 2 then (* no padding *)
|
||||||
begin
|
begin
|
||||||
pad := false;
|
pad := false;
|
||||||
(* total size 12 bytes *)
|
(* total size 10 bytes *)
|
||||||
offset := 4; (* offset for LOADREL *)
|
offset := 4; (* offset for LOADREL *)
|
||||||
shrinkage := 10; (* difference to short form size *)
|
shrinkage := 8; (* difference to short form size *)
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
|
|
@ -1973,17 +1967,9 @@ begin
|
||||||
encodeInstruction('JUMP', 0, encoded);
|
encodeInstruction('JUMP', 0, encoded);
|
||||||
emitInstructionWord(encoded);
|
emitInstructionWord(encoded);
|
||||||
|
|
||||||
(* Padding is always done, so the length of the sequence does
|
|
||||||
not change depending on the position. The pad is either
|
|
||||||
placed before the address to align it on a word address,
|
|
||||||
or after, if it is already aligned. *)
|
|
||||||
if pad then
|
if pad then
|
||||||
emitInstructionWord(0);
|
emitInstructionWord(0);
|
||||||
|
|
||||||
emitWord(value);
|
emitWord(value);
|
||||||
|
|
||||||
if not pad then
|
|
||||||
emitInstructionWord(0);
|
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
|
|
@ -2056,9 +2042,6 @@ begin
|
||||||
operandValue := 0;
|
operandValue := 0;
|
||||||
emitBlock(count, operandValue);
|
emitBlock(count, operandValue);
|
||||||
end
|
end
|
||||||
else
|
|
||||||
if lastToken.tokenText = '.ALIGN' then
|
|
||||||
alignOutput(wordSize)
|
|
||||||
else
|
else
|
||||||
errorExit2('Unrecognized directive', lastToken.tokenText);
|
errorExit2('Unrecognized directive', lastToken.tokenText);
|
||||||
end;
|
end;
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ const shortcutChar = '`';
|
||||||
firstShCChar = 'A';
|
firstShCChar = 'A';
|
||||||
lastShCChar = 'i';
|
lastShCChar = 'i';
|
||||||
|
|
||||||
OutfileSuffix = '.cs';
|
OutfileSuffix = '.lib';
|
||||||
|
|
||||||
{$I 'platfile-types+.pas'}
|
{$I 'platfile-types+.pas'}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,173 +0,0 @@
|
||||||
program changemem;
|
|
||||||
const ProgramMagic = $00100AFE;
|
|
||||||
type ProgramHeader = record
|
|
||||||
magic:integer;
|
|
||||||
heapSize:integer;
|
|
||||||
stackSize:integer;
|
|
||||||
mainPtr:integer;
|
|
||||||
end;
|
|
||||||
|
|
||||||
var filename:string;
|
|
||||||
h:ProgramHeader;
|
|
||||||
|
|
||||||
procedure showHex(value:integer);
|
|
||||||
var i:integer;
|
|
||||||
digit:integer;
|
|
||||||
digits:array[1..8] of char;
|
|
||||||
ch:char;
|
|
||||||
begin
|
|
||||||
for i := 1 to 8 do
|
|
||||||
begin
|
|
||||||
digit := value and 15;
|
|
||||||
value := value shr 4;
|
|
||||||
|
|
||||||
if digit < 10 then
|
|
||||||
ch := chr(digit + ord('0'))
|
|
||||||
else
|
|
||||||
ch := chr(digit - 10 + ord('A'));
|
|
||||||
digits[i] := ch;
|
|
||||||
end;
|
|
||||||
for i := 8 downto 1 do
|
|
||||||
write(digits[i]);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure showValue(labl:string; value:integer);
|
|
||||||
begin
|
|
||||||
write(labl:20, ' ');
|
|
||||||
write(value:8, ' (');
|
|
||||||
showHex(value);
|
|
||||||
writeln(')');
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure showHeader(var h:ProgramHeader);
|
|
||||||
begin
|
|
||||||
showValue('heap size', h.heapSize);
|
|
||||||
showValue('stack size', h.stackSize);
|
|
||||||
showValue('main entry point', h.mainPtr);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure readHeader(var filename:string;var h:ProgramHeader);
|
|
||||||
var f:file;
|
|
||||||
begin
|
|
||||||
writeln('reading file ', filename);
|
|
||||||
open(f, filename, ModeReadOnly);
|
|
||||||
if IOResult(f) <> 0 then
|
|
||||||
begin
|
|
||||||
writeln('Error opening file: ', ErrorStr(IOResult(f)));
|
|
||||||
halt;
|
|
||||||
end
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
read(f, h);
|
|
||||||
if IOResult(f) <> 0 then
|
|
||||||
begin
|
|
||||||
writeln('Error reading header: ', ErrorStr(IOResult(f)));
|
|
||||||
halt;
|
|
||||||
end;
|
|
||||||
close(f);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure writeHeader(var filename:string;var h:ProgramHeader);
|
|
||||||
var f:file;
|
|
||||||
begin
|
|
||||||
writeln('writing file ', filename);
|
|
||||||
open(f, filename, ModeModify);
|
|
||||||
if IOResult(f) <> 0 then
|
|
||||||
begin
|
|
||||||
writeln('Error opening file: ', ErrorStr(IOResult(f)));
|
|
||||||
halt;
|
|
||||||
end
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
write(f, h);
|
|
||||||
if IOResult(f) <> 0 then
|
|
||||||
begin
|
|
||||||
writeln('Error writing header: ', ErrorStr(IOResult(f)));
|
|
||||||
halt;
|
|
||||||
end;
|
|
||||||
close(f);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure modifyHeader(var filename:string;var h:ProgramHeader);
|
|
||||||
var done:boolean;
|
|
||||||
ch:char;
|
|
||||||
changed:boolean;
|
|
||||||
|
|
||||||
function getNewValue(descr:string):integer;
|
|
||||||
var buf:string;
|
|
||||||
v,e:integer;
|
|
||||||
begin
|
|
||||||
getNewValue := 0;
|
|
||||||
write('New ',descr, ' size (decimal)> ');
|
|
||||||
readln(buf);
|
|
||||||
val(buf, v, e);
|
|
||||||
if(e > 0 ) or (v <= 0) then
|
|
||||||
writeln('invalid size')
|
|
||||||
else
|
|
||||||
getNewValue := v;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure changeStackSize;
|
|
||||||
var v:integer;
|
|
||||||
begin
|
|
||||||
v := getNewValue('stack');
|
|
||||||
if v > 0 then
|
|
||||||
begin
|
|
||||||
h.stackSize := v;
|
|
||||||
changed := true;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure changeHeapSize;
|
|
||||||
var v:integer;
|
|
||||||
begin
|
|
||||||
v := getNewValue('heap');
|
|
||||||
if v > 0 then
|
|
||||||
begin
|
|
||||||
h.heapSize := v;
|
|
||||||
changed := true;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
begin
|
|
||||||
changed := false; done := false;
|
|
||||||
|
|
||||||
while not done do
|
|
||||||
begin
|
|
||||||
writeln(filename, ' header:');
|
|
||||||
showHeader(h);
|
|
||||||
writeln('Change H)eap size Change S)tack size eX)it');
|
|
||||||
write('> ');
|
|
||||||
read(ch);
|
|
||||||
writeln;
|
|
||||||
case upcase(ch) of
|
|
||||||
'S': changeStackSize;
|
|
||||||
'H': changeHeapSize;
|
|
||||||
'X': done := true;
|
|
||||||
else
|
|
||||||
writeln('invalid command');
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
if changed then
|
|
||||||
writeHeader(filename, h);
|
|
||||||
end;
|
|
||||||
|
|
||||||
begin
|
|
||||||
if ParamCount > 0 then
|
|
||||||
filename := ParamStr(1)
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
write('File name> ');
|
|
||||||
readln(filename);
|
|
||||||
end;
|
|
||||||
|
|
||||||
readHeader(filename, h);
|
|
||||||
|
|
||||||
if h.magic <> ProgramMagic then
|
|
||||||
writeln('invalid magic value ', h.magic)
|
|
||||||
else
|
|
||||||
modifyHeader(filename, h);
|
|
||||||
end.
|
|
||||||
|
|
@ -14,8 +14,8 @@ var dirs:DirectorySlot;
|
||||||
error:integer;
|
error:integer;
|
||||||
begin
|
begin
|
||||||
lastSlot := volumeTable[volid].part.dirSize - 1;
|
lastSlot := volumeTable[volid].part.dirSize - 1;
|
||||||
openvolumeid(volid, error); (* we just ignore error here because
|
openvolumeid(volid);
|
||||||
we should always have enough heap space *)
|
|
||||||
for i := 0 to lastSlot do
|
for i := 0 to lastSlot do
|
||||||
begin
|
begin
|
||||||
getdirslot(volid, i, dirs, error);
|
getdirslot(volid, i, dirs, error);
|
||||||
|
|
|
||||||
102
progs/editor.pas
102
progs/editor.pas
|
|
@ -8,7 +8,7 @@ const COMPILERPROG = '#SYSTEM:pcomp.prog';
|
||||||
const MAX_LENGTH = 512;
|
const MAX_LENGTH = 512;
|
||||||
MAX_LINES = 10000;
|
MAX_LINES = 10000;
|
||||||
MAX_SCREENH = 256;
|
MAX_SCREENH = 256;
|
||||||
MAX_KEYWORD = 33;
|
MAX_KEYWORD = 31;
|
||||||
|
|
||||||
MAX_CLIPB_SIZE = 300;
|
MAX_CLIPB_SIZE = 300;
|
||||||
|
|
||||||
|
|
@ -94,14 +94,14 @@ var lines: array [1..MAX_LINES] of ^linestr;
|
||||||
catColors: array [Unknown..StrLit] of integer =
|
catColors: array [Unknown..StrLit] of integer =
|
||||||
( TEXT_FG, 0, KEYWORD_FG, IDENT_FG, NUM_FG, PUNCT_FG, COMMENT_FG, STRLIT_FG );
|
( TEXT_FG, 0, KEYWORD_FG, IDENT_FG, NUM_FG, PUNCT_FG, COMMENT_FG, STRLIT_FG );
|
||||||
|
|
||||||
keywords: array [0..MAX_KEYWORD] of string[12] = (
|
keywords: array [0..MAX_KEYWORD] of string[20] = (
|
||||||
'AND', 'ARRAY', 'BEGIN', 'BOOLEAN', 'CASE', 'CHAR', 'CONST',
|
'VAR', 'IF', 'THEN', 'ELSE', 'BEGIN', 'END', 'PROCEDURE', 'FUNCTION',
|
||||||
'DIV', 'DO', 'ELSE', 'END', 'FOR', 'FUNCTION', 'IF', 'IN', 'INTEGER',
|
'WHILE', 'FOR', 'DO', 'IN', 'OF', 'CASE', 'TO', 'REPEAT', 'UNTIL',
|
||||||
'MOD', 'NOT', 'OF', 'OR', 'PROCEDURE', 'PROGRAM',
|
'CHAR', 'INTEGER', 'REAL', 'BOOLEAN', 'ARRAY', 'RECORD', 'STRING',
|
||||||
'REAL', 'RECORD', 'REPEAT', 'STRING', 'THEN', 'TO', 'TYPE',
|
'MOD', 'DIV', 'AND', 'OR', 'NOT',
|
||||||
'UNIT', 'UNTIL', 'USES', 'VAR', 'WHILE'
|
'TYPE', 'CONST',
|
||||||
|
'PROGRAM'
|
||||||
);
|
);
|
||||||
keywordIdx: array ['A'..'Z'] of integer;
|
|
||||||
paramPos:integer;
|
paramPos:integer;
|
||||||
errorLine:integer;
|
errorLine:integer;
|
||||||
errorMsg:string;
|
errorMsg:string;
|
||||||
|
|
@ -137,8 +137,7 @@ end;
|
||||||
procedure getScreenSize;
|
procedure getScreenSize;
|
||||||
var c:char;
|
var c:char;
|
||||||
begin
|
begin
|
||||||
(* empty keyboard buffer to make sure GetTermSize
|
(* empty keyboard buffer *)
|
||||||
can read the response from the terminal *)
|
|
||||||
while conavail do read(con, c);
|
while conavail do read(con, c);
|
||||||
|
|
||||||
GetTermSize(screenW, screenH);
|
GetTermSize(screenW, screenH);
|
||||||
|
|
@ -678,6 +677,30 @@ begin
|
||||||
hscroll;
|
hscroll;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function isKeyword(var s:string):boolean;
|
||||||
|
var i:integer;
|
||||||
|
c:char;
|
||||||
|
upBuf:string[MAX_LENGTH];
|
||||||
|
begin
|
||||||
|
isKeyword := false;
|
||||||
|
|
||||||
|
if highlight then
|
||||||
|
begin
|
||||||
|
upBuf := '';
|
||||||
|
for c in s do appendchar(upBuf,upcase(c));
|
||||||
|
|
||||||
|
|
||||||
|
for i := 0 to MAX_KEYWORD do
|
||||||
|
begin
|
||||||
|
if keywords[i] = upBuf then
|
||||||
|
begin
|
||||||
|
isKeyword := true;
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
function isalpha(c:char):boolean;
|
function isalpha(c:char):boolean;
|
||||||
begin
|
begin
|
||||||
isalpha := ((ord(c) >= ord('A')) and (ord(c) <= ord('Z'))) or
|
isalpha := ((ord(c) >= ord('A')) and (ord(c) <= ord('Z'))) or
|
||||||
|
|
@ -692,39 +715,6 @@ begin
|
||||||
((ord(c) >= ord('[')) and (ord(c) <= ord('^')));
|
((ord(c) >= ord('[')) and (ord(c) <= ord('^')));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function isKeyword(var s:string):boolean;
|
|
||||||
var i:integer;
|
|
||||||
start:integer;
|
|
||||||
c,f:char;
|
|
||||||
upBuf:string[MAX_LENGTH];
|
|
||||||
begin
|
|
||||||
isKeyword := false;
|
|
||||||
|
|
||||||
if highlight then
|
|
||||||
begin
|
|
||||||
upBuf := '';
|
|
||||||
for c in s do appendchar(upBuf,upcase(c));
|
|
||||||
|
|
||||||
(* use the first letter of the search string
|
|
||||||
for our starting index *)
|
|
||||||
c := upBuf[1];
|
|
||||||
if isalpha(c) then
|
|
||||||
begin
|
|
||||||
start := keywordIdx[c];
|
|
||||||
for i := start to MAX_KEYWORD do
|
|
||||||
begin
|
|
||||||
f := keywords[i][1];
|
|
||||||
if c <> f then break;
|
|
||||||
if keywords[i] = upBuf then
|
|
||||||
begin
|
|
||||||
isKeyword := true;
|
|
||||||
break;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function getCat(c:char):HiliteCat;
|
function getCat(c:char):HiliteCat;
|
||||||
begin
|
begin
|
||||||
if isalpha(c) then
|
if isalpha(c) then
|
||||||
|
|
@ -1662,10 +1652,11 @@ end;
|
||||||
|
|
||||||
procedure gotoLine(l:integer);
|
procedure gotoLine(l:integer);
|
||||||
begin
|
begin
|
||||||
|
if l < 1 then
|
||||||
|
l := 1
|
||||||
|
else
|
||||||
if l > lineCount then
|
if l > lineCount then
|
||||||
l := lineCount;
|
l := lineCount;
|
||||||
if l < 1 then
|
|
||||||
l := 1;
|
|
||||||
|
|
||||||
topY := l - (screenH div 2);
|
topY := l - (screenH div 2);
|
||||||
if topY < 1 then
|
if topY < 1 then
|
||||||
|
|
@ -1713,7 +1704,7 @@ var error:integer;
|
||||||
begin
|
begin
|
||||||
success := true;
|
success := true;
|
||||||
if isModified then
|
if isModified then
|
||||||
writeFile(success);
|
save;
|
||||||
if success then
|
if success then
|
||||||
begin
|
begin
|
||||||
if isAsmFile(filename) then
|
if isAsmFile(filename) then
|
||||||
|
|
@ -2426,23 +2417,6 @@ begin
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure initKeywordIdx;
|
|
||||||
var i:integer;
|
|
||||||
ch, lastCh:char;
|
|
||||||
begin
|
|
||||||
lastCh := #0;
|
|
||||||
|
|
||||||
for i := 0 to MAX_KEYWORD do
|
|
||||||
begin
|
|
||||||
ch := keywords[i][1];
|
|
||||||
if ch <> lastCh then
|
|
||||||
begin
|
|
||||||
keywordIdx[ch] := i;
|
|
||||||
lastCh := ch;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
begin
|
begin
|
||||||
errorLine := 0;
|
errorLine := 0;
|
||||||
paramPos := 1;
|
paramPos := 1;
|
||||||
|
|
@ -2450,8 +2424,6 @@ begin
|
||||||
autoindent := true;
|
autoindent := true;
|
||||||
keepClips := false;
|
keepClips := false;
|
||||||
|
|
||||||
initKeywordIdx;
|
|
||||||
|
|
||||||
while paramPos <= ParamCount do
|
while paramPos <= ParamCount do
|
||||||
begin
|
begin
|
||||||
if paramStr(paramPos) = '-l' then
|
if paramStr(paramPos) = '-l' then
|
||||||
|
|
|
||||||
|
|
@ -62,13 +62,8 @@ begin
|
||||||
begin
|
begin
|
||||||
if lastUsed < endSlot then
|
if lastUsed < endSlot then
|
||||||
begin
|
begin
|
||||||
(* if the volume is empty mark the first slot *)
|
|
||||||
if lastUsed = 0 then
|
|
||||||
slotNo := reservedCount
|
|
||||||
else
|
|
||||||
slotNo := lastUsed + 1;
|
|
||||||
|
|
||||||
writeln('Updating directory...');
|
writeln('Updating directory...');
|
||||||
|
slotNo := lastUsed + 1;
|
||||||
getdirslot(volid, slotNo, dirslot, error);
|
getdirslot(volid, slotNo, dirslot, error);
|
||||||
if error <> IONoError then
|
if error <> IONoError then
|
||||||
begin
|
begin
|
||||||
|
|
@ -123,9 +118,8 @@ begin
|
||||||
freeAreaCount := 0;
|
freeAreaCount := 0;
|
||||||
lastUsed := 0;
|
lastUsed := 0;
|
||||||
|
|
||||||
openvolumeid(volid, error);
|
openvolumeid(volid);
|
||||||
(* ignoring theoretically possible out-of-heap-error *)
|
i := volumeTable[volid].startSlot;
|
||||||
i := 0;
|
|
||||||
endSlot := volumeTable[volid].part.dirSize - 1;
|
endSlot := volumeTable[volid].part.dirSize - 1;
|
||||||
|
|
||||||
if verbose then
|
if verbose then
|
||||||
|
|
@ -309,7 +303,7 @@ begin
|
||||||
writeln('Volume ', volname, ' not found.')
|
writeln('Volume ', volname, ' not found.')
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
openvolumeid(volid, error);
|
openvolumeid(volid);
|
||||||
|
|
||||||
endSlot := volumeTable[volid].part.dirSize - 1;
|
endSlot := volumeTable[volid].part.dirSize - 1;
|
||||||
extentSize := volumeTable[volid].part.extentSize;
|
extentSize := volumeTable[volid].part.extentSize;
|
||||||
|
|
|
||||||
|
|
@ -1,167 +0,0 @@
|
||||||
(* Copyright 2025 Sebastian Lederer. See the file LICENSE.md for details *)
|
|
||||||
program recover;
|
|
||||||
const PageMargin = 4;
|
|
||||||
var filename:string;
|
|
||||||
volid:integer;
|
|
||||||
|
|
||||||
(* we use some stuff internal to stdlib.pas *)
|
|
||||||
procedure getdirslot(volumeid:integer;slotNo:integer;var result:DirectorySlot;var error:integer);
|
|
||||||
external;
|
|
||||||
procedure openfile(volid:integer; slotno:integer; var dirslot:DirectorySlot; var aFile:File; mode:filemode);
|
|
||||||
external;
|
|
||||||
|
|
||||||
function openvolume:integer;
|
|
||||||
var volid:integer;
|
|
||||||
begin
|
|
||||||
openvolume := -1;
|
|
||||||
|
|
||||||
volid := findvolume(DefaultVolume);
|
|
||||||
if volid < 1 then
|
|
||||||
writeln('Volume ', DefaultVolume, ' not found.')
|
|
||||||
else
|
|
||||||
openvolume := volid;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure waitForKey;
|
|
||||||
var c:char;
|
|
||||||
begin
|
|
||||||
writeln;
|
|
||||||
writeln('-- press any key to continue --');
|
|
||||||
c := conin;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure copyfile(volid:integer;slotno:integer;oldname,newname:string);
|
|
||||||
var srcfile,destfile:file;
|
|
||||||
dirslot:DirectorySlot;
|
|
||||||
error:integer;
|
|
||||||
ch:char;
|
|
||||||
count:integer;
|
|
||||||
begin
|
|
||||||
(* to open the deleted source file, we emulate parts
|
|
||||||
of the open procedure from stdlib *)
|
|
||||||
getdirslot(volid, slotno, dirslot, error);
|
|
||||||
if not (SlotDeleted in dirslot.flags) or (dirslot.name <> oldname) then
|
|
||||||
writeln('Invalid slot ', slotno)
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
openfile(volid, slotno, dirslot, srcfile, ModeReadOnly);
|
|
||||||
if error <> 0 then
|
|
||||||
writeln('Error opening file from slot ', slotno,
|
|
||||||
': ', ErrorStr(error))
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
open(destfile, newname, ModeCreate);
|
|
||||||
if IOResult(destfile) = IOFileExists then
|
|
||||||
begin
|
|
||||||
write('File ', newname, ' already exists, overwrite? [y/n] ');
|
|
||||||
readln(ch);
|
|
||||||
if ch in ['Y', 'y'] then
|
|
||||||
open(destfile, newname, ModeOverwrite);
|
|
||||||
end;
|
|
||||||
if IOResult(destfile) <> 0 then
|
|
||||||
writeln('Error opening ', newname, ': ',
|
|
||||||
ErrorStr(IOResult(destfile)))
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
(* taken from shell.pas copyFile *)
|
|
||||||
write('Recovering from slot ', slotno, ' to ', newname, '...');
|
|
||||||
count := 0;
|
|
||||||
while not eof(srcfile) do
|
|
||||||
begin
|
|
||||||
read(srcfile,ch);
|
|
||||||
write(destfile,ch);
|
|
||||||
count := count + 1;
|
|
||||||
if (count and 8191) = 0 then write('.');
|
|
||||||
end;
|
|
||||||
writeln;
|
|
||||||
close(destfile);
|
|
||||||
end;
|
|
||||||
close(srcfile);
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure recoverfile(volid:integer;wantedname:string);
|
|
||||||
var dirs:DirectorySlot;
|
|
||||||
i:integer;
|
|
||||||
lastSlot:integer;
|
|
||||||
error:integer;
|
|
||||||
screenW,screenH:integer;
|
|
||||||
count:integer;
|
|
||||||
datestr:string;
|
|
||||||
ftime:DateTime;
|
|
||||||
wantedslot:integer;
|
|
||||||
newname:string;
|
|
||||||
foundsomething:boolean;
|
|
||||||
begin
|
|
||||||
writeln('Files available for recovery:');
|
|
||||||
foundsomething := false;
|
|
||||||
newname := '';
|
|
||||||
|
|
||||||
GetTermSize(screenW, screenH);
|
|
||||||
count := PageMargin;
|
|
||||||
|
|
||||||
lastSlot := volumeTable[volid].part.dirSize - 1;
|
|
||||||
openvolumeid(volid, error);
|
|
||||||
(* ignoring theoretically possible out-of-heap-space error *)
|
|
||||||
for i := 0 to lastSlot do
|
|
||||||
begin
|
|
||||||
getdirslot(volid, i, dirs, error);
|
|
||||||
with dirs do
|
|
||||||
begin
|
|
||||||
if (SlotFirst in flags) or (SlotDeleted in flags) then
|
|
||||||
if name = wantedname then
|
|
||||||
begin
|
|
||||||
ftime := GetDateTime(dirs.modTime);
|
|
||||||
datestr := DateStr(ftime) + ' ' + TimeStr(ftime, true);
|
|
||||||
write('slot ', i:4, name:34, sizeBytes:8, datestr:21, ' ');
|
|
||||||
if SlotFirst in flags then write('Cur');
|
|
||||||
if SlotExtent in flags then write('Extent');
|
|
||||||
if SlotReserved in flags then write('Resvd');
|
|
||||||
if SlotDeleted in flags then write('Del');
|
|
||||||
if SlotFree in flags then write('Free');
|
|
||||||
if SlotEndScan in flags then write('End');
|
|
||||||
writeln;
|
|
||||||
foundsomething := true;
|
|
||||||
count := count + 1;
|
|
||||||
if count >= screenH then
|
|
||||||
begin
|
|
||||||
count := PageMargin;
|
|
||||||
waitForKey;
|
|
||||||
end;
|
|
||||||
if SlotEndScan in flags then break;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
if foundsomething then
|
|
||||||
begin
|
|
||||||
write('Slot no to recover> ');
|
|
||||||
readln(wantedslot);
|
|
||||||
if (wantedslot < 1) or (wantedslot >= volumeTable[volid].part.dirSize) then
|
|
||||||
writeln('Invalid slot number.')
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
write('New filename> ');
|
|
||||||
readln(newname);
|
|
||||||
end;
|
|
||||||
|
|
||||||
if length(newname) > 0 then
|
|
||||||
copyfile(volid, wantedslot, wantedname, newname);
|
|
||||||
end;
|
|
||||||
|
|
||||||
closevolumeid(volid);
|
|
||||||
end;
|
|
||||||
|
|
||||||
begin
|
|
||||||
if ParamCount > 0 then
|
|
||||||
filename := ParamStr(1)
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
write('Filename to recover> ');
|
|
||||||
readln(filename);
|
|
||||||
end;
|
|
||||||
volid := openvolume;
|
|
||||||
if volid > 0 then
|
|
||||||
recoverfile(volid, filename);
|
|
||||||
end.
|
|
||||||
|
|
@ -149,7 +149,7 @@ begin
|
||||||
count := PageMargin;
|
count := PageMargin;
|
||||||
|
|
||||||
writeln('reading directory of ', DefaultVolume);
|
writeln('reading directory of ', DefaultVolume);
|
||||||
openvolumeid(volid, error);
|
openvolumeid(volid);
|
||||||
readdirfirst(volid, index, dirs, error);
|
readdirfirst(volid, index, dirs, error);
|
||||||
while index > 0 do
|
while index > 0 do
|
||||||
begin
|
begin
|
||||||
|
|
@ -324,7 +324,7 @@ begin
|
||||||
PExec(EDITORPROG, args, 3, error);
|
PExec(EDITORPROG, args, 3, error);
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
PExec1(EDITORPROG, ShellWorkFile, error);
|
PExec2(EDITORPROG, ShellWorkFile, error);
|
||||||
writeln('PExec error ', error);
|
writeln('PExec error ', error);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
@ -334,7 +334,7 @@ var filename:filenamestr;
|
||||||
begin
|
begin
|
||||||
requireWorkfile;
|
requireWorkfile;
|
||||||
filename := replaceExtension(ShellWorkFile, '.s');
|
filename := replaceExtension(ShellWorkFile, '.s');
|
||||||
PExec1(ASMPROG, filename, error);
|
PExec2(ASMPROG, filename, error);
|
||||||
writeln('PExec error ', error);
|
writeln('PExec error ', error);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
@ -344,7 +344,7 @@ var filename:filenamestr;
|
||||||
begin
|
begin
|
||||||
requireWorkfile;
|
requireWorkfile;
|
||||||
filename := replaceExtension(ShellWorkFile, '.pas');
|
filename := replaceExtension(ShellWorkFile, '.pas');
|
||||||
PExec2(COMPILERPROG, '-S', filename, error);
|
PExec3(COMPILERPROG, '-S', filename, error);
|
||||||
writeln('PExec error ', error);
|
writeln('PExec error ', error);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
@ -354,7 +354,7 @@ var filename:filenamestr;
|
||||||
begin
|
begin
|
||||||
requireWorkfile;
|
requireWorkfile;
|
||||||
filename := replaceExtension(ShellWorkFile, '.pas');
|
filename := replaceExtension(ShellWorkFile, '.pas');
|
||||||
PExec1(COMPILERPROG, filename, error);
|
PExec2(COMPILERPROG, filename, error);
|
||||||
writeln('PExec error ', error);
|
writeln('PExec error ', error);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
@ -373,7 +373,7 @@ end;
|
||||||
procedure krunch;
|
procedure krunch;
|
||||||
var error:integer;
|
var error:integer;
|
||||||
begin
|
begin
|
||||||
PExec1(RECLAIMPROG, DefaultVolume, error);
|
PExec2(RECLAIMPROG, DefaultVolume, error);
|
||||||
writeln('PExec error ', error);
|
writeln('PExec error ', error);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -226,7 +226,6 @@ begin
|
||||||
if not invalid then
|
if not invalid then
|
||||||
begin
|
begin
|
||||||
open(xferFile, filename, ModeOverwrite);
|
open(xferFile, filename, ModeOverwrite);
|
||||||
blockNo := 0;
|
|
||||||
done := false;
|
done := false;
|
||||||
repeat
|
repeat
|
||||||
serReadBlock(ok);
|
serReadBlock(ok);
|
||||||
|
|
@ -399,7 +398,7 @@ begin
|
||||||
writeln('Volume ', DefaultVolume, ' not found.')
|
writeln('Volume ', DefaultVolume, ' not found.')
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
openvolumeid(volid, error);
|
openvolumeid(volid);
|
||||||
readdirfirst(volid, index, dirs, error);
|
readdirfirst(volid, index, dirs, error);
|
||||||
while (index > 0) and (error = 0) do
|
while (index > 0) and (error = 0) do
|
||||||
begin
|
begin
|
||||||
|
|
|
||||||
1
rogue
1
rogue
|
|
@ -1 +0,0 @@
|
||||||
Subproject commit 73936b4167bad01642675252e53a096d80fa6b35
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
program arraytest;
|
|
||||||
var arr:array[-5..5] of integer;
|
|
||||||
var s:string[5];
|
|
||||||
begin
|
|
||||||
arr[-5] := 10;
|
|
||||||
arr[5] := 11;
|
|
||||||
writeln(arr[-5], ' ', arr[5]);
|
|
||||||
end.
|
|
||||||
|
|
@ -1,22 +0,0 @@
|
||||||
program gototest;
|
|
||||||
var i:integer;
|
|
||||||
label l1,l2;
|
|
||||||
begin
|
|
||||||
goto l1;
|
|
||||||
writeln('skipped');
|
|
||||||
l1: writeln('goto destination 1');
|
|
||||||
{
|
|
||||||
for i := 1 to 10 do
|
|
||||||
begin
|
|
||||||
goto l2;
|
|
||||||
end;
|
|
||||||
}
|
|
||||||
{
|
|
||||||
case i of
|
|
||||||
1: writeln('1');
|
|
||||||
2: goto l2;
|
|
||||||
3..10: writeln('3 - 10');
|
|
||||||
end;
|
|
||||||
l2: writeln('goto destination 2');
|
|
||||||
}
|
|
||||||
end.
|
|
||||||
|
|
@ -1,49 +0,0 @@
|
||||||
program NestedTest;
|
|
||||||
var g:integer;
|
|
||||||
|
|
||||||
procedure first;
|
|
||||||
var f:integer;
|
|
||||||
|
|
||||||
procedure second;
|
|
||||||
var s:integer;
|
|
||||||
|
|
||||||
procedure third1;
|
|
||||||
var t1:integer;
|
|
||||||
begin
|
|
||||||
t1 := 310;
|
|
||||||
s := 31;
|
|
||||||
writeln('t1:', t1);
|
|
||||||
end;
|
|
||||||
|
|
||||||
procedure third2;
|
|
||||||
var t2:integer;
|
|
||||||
begin
|
|
||||||
t2 := 320;
|
|
||||||
s := 32;
|
|
||||||
writeln('t2:', t2);
|
|
||||||
if g <> 21 then
|
|
||||||
begin
|
|
||||||
g := 21;
|
|
||||||
second;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
begin
|
|
||||||
f := 2;
|
|
||||||
writeln('g:',g);
|
|
||||||
third1;
|
|
||||||
writeln('g:', g);
|
|
||||||
third2;
|
|
||||||
writeln('s:',s);
|
|
||||||
end;
|
|
||||||
|
|
||||||
begin
|
|
||||||
second;
|
|
||||||
writeln('f:', f);
|
|
||||||
end;
|
|
||||||
|
|
||||||
begin
|
|
||||||
g := 0;
|
|
||||||
first;
|
|
||||||
writeln('g:', g);
|
|
||||||
end.
|
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
program settest2;
|
|
||||||
type weekday = (Mon,Tue,Wed,Thu,Fri,Sat,Sun);
|
|
||||||
days = set of weekday;
|
|
||||||
|
|
||||||
var s:days;
|
|
||||||
d:weekday;
|
|
||||||
|
|
||||||
begin
|
|
||||||
s := [Sat,Sun]; (* set literal *)
|
|
||||||
|
|
||||||
d := Sun;
|
|
||||||
if d in [Sat,Sun] then (* array literal *)
|
|
||||||
writeln('weekend');
|
|
||||||
|
|
||||||
if d in s then
|
|
||||||
writeln('also weekend');
|
|
||||||
|
|
||||||
d := Mon;
|
|
||||||
s := s + [d];
|
|
||||||
end.
|
|
||||||
|
|
@ -8,8 +8,8 @@ set_property -dict {PACKAGE_PIN E3 IOSTANDARD LVCMOS33} [get_ports clk]
|
||||||
create_clock -period 10.000 -name sys_clk_pin -waveform {0.000 5.000} -add [get_ports clk]
|
create_clock -period 10.000 -name sys_clk_pin -waveform {0.000 5.000} -add [get_ports clk]
|
||||||
|
|
||||||
## Switches
|
## Switches
|
||||||
#set_property -dict {PACKAGE_PIN A8 IOSTANDARD LVCMOS33} [get_ports sw0]
|
set_property -dict {PACKAGE_PIN A8 IOSTANDARD LVCMOS33} [get_ports sw0]
|
||||||
#set_property -dict {PACKAGE_PIN C11 IOSTANDARD LVCMOS33} [get_ports sw1]
|
set_property -dict {PACKAGE_PIN C11 IOSTANDARD LVCMOS33} [get_ports sw1]
|
||||||
#set_property -dict { PACKAGE_PIN C10 IOSTANDARD LVCMOS33 } [get_ports { sw[2] }]; #IO_L13N_T2_MRCC_16 Sch=sw[2]
|
#set_property -dict { PACKAGE_PIN C10 IOSTANDARD LVCMOS33 } [get_ports { sw[2] }]; #IO_L13N_T2_MRCC_16 Sch=sw[2]
|
||||||
#set_property -dict { PACKAGE_PIN A10 IOSTANDARD LVCMOS33 } [get_ports { sw[3] }]; #IO_L14P_T2_SRCC_16 Sch=sw[3]
|
#set_property -dict { PACKAGE_PIN A10 IOSTANDARD LVCMOS33 } [get_ports { sw[3] }]; #IO_L14P_T2_SRCC_16 Sch=sw[3]
|
||||||
|
|
||||||
|
|
@ -34,7 +34,7 @@ set_property -dict {PACKAGE_PIN T9 IOSTANDARD LVCMOS33} [get_ports led2]
|
||||||
set_property -dict {PACKAGE_PIN T10 IOSTANDARD LVCMOS33} [get_ports led3]
|
set_property -dict {PACKAGE_PIN T10 IOSTANDARD LVCMOS33} [get_ports led3]
|
||||||
|
|
||||||
## Buttons
|
## Buttons
|
||||||
#set_property -dict {PACKAGE_PIN D9 IOSTANDARD LVCMOS33} [get_ports btn0]
|
set_property -dict {PACKAGE_PIN D9 IOSTANDARD LVCMOS33} [get_ports btn0]
|
||||||
#set_property -dict { PACKAGE_PIN C9 IOSTANDARD LVCMOS33 } [get_ports { btn1 }]; #IO_L11P_T1_SRCC_16 Sch=btn[1]
|
#set_property -dict { PACKAGE_PIN C9 IOSTANDARD LVCMOS33 } [get_ports { btn1 }]; #IO_L11P_T1_SRCC_16 Sch=btn[1]
|
||||||
#set_property -dict { PACKAGE_PIN B9 IOSTANDARD LVCMOS33 } [get_ports { btn[2] }]; #IO_L11N_T1_SRCC_16 Sch=btn[2]
|
#set_property -dict { PACKAGE_PIN B9 IOSTANDARD LVCMOS33 } [get_ports { btn[2] }]; #IO_L11N_T1_SRCC_16 Sch=btn[2]
|
||||||
#set_property -dict { PACKAGE_PIN B8 IOSTANDARD LVCMOS33 } [get_ports { btn[3] }]; #IO_L12P_T1_MRCC_16 Sch=btn[3]
|
#set_property -dict { PACKAGE_PIN B8 IOSTANDARD LVCMOS33 } [get_ports { btn[3] }]; #IO_L12P_T1_MRCC_16 Sch=btn[3]
|
||||||
|
|
@ -70,10 +70,10 @@ set_property -dict {PACKAGE_PIN V14 IOSTANDARD LVCMOS33} [get_ports VGA_VS_O]
|
||||||
#set_property -dict { PACKAGE_PIN U13 IOSTANDARD LVCMOS33 } [get_ports { jc[7] }]; #IO_L23N_T3_A02_D18_14 Sch=jc_n[4]
|
#set_property -dict { PACKAGE_PIN U13 IOSTANDARD LVCMOS33 } [get_ports { jc[7] }]; #IO_L23N_T3_A02_D18_14 Sch=jc_n[4]
|
||||||
|
|
||||||
## Pmod Header JD
|
## Pmod Header JD
|
||||||
set_property -dict { PACKAGE_PIN D4 IOSTANDARD LVCMOS33 } [get_ports { amp2_ain }]; #IO_L11N_T1_SRCC_35 Sch=jd[1]
|
#set_property -dict { PACKAGE_PIN D4 IOSTANDARD LVCMOS33 } [get_ports { jd[0] }]; #IO_L11N_T1_SRCC_35 Sch=jd[1]
|
||||||
set_property -dict { PACKAGE_PIN D3 IOSTANDARD LVCMOS33 } [get_ports { amp2_gain }]; #IO_L12N_T1_MRCC_35 Sch=jd[2]
|
#set_property -dict { PACKAGE_PIN D3 IOSTANDARD LVCMOS33 } [get_ports { jd[1] }]; #IO_L12N_T1_MRCC_35 Sch=jd[2]
|
||||||
#set_property -dict { PACKAGE_PIN F4 IOSTANDARD LVCMOS33 } [get_ports { jd[2] }]; #IO_L13P_T2_MRCC_35 Sch=jd[3]
|
#set_property -dict { PACKAGE_PIN F4 IOSTANDARD LVCMOS33 } [get_ports { jd[2] }]; #IO_L13P_T2_MRCC_35 Sch=jd[3]
|
||||||
set_property -dict { PACKAGE_PIN F3 IOSTANDARD LVCMOS33 } [get_ports { amp2_shutdown_n }]; #IO_L13N_T2_MRCC_35 Sch=jd[4]
|
#set_property -dict { PACKAGE_PIN F3 IOSTANDARD LVCMOS33 } [get_ports { jd[3] }]; #IO_L13N_T2_MRCC_35 Sch=jd[4]
|
||||||
#set_property -dict { PACKAGE_PIN E2 IOSTANDARD LVCMOS33 } [get_ports { jd[4] }]; #IO_L14P_T2_SRCC_35 Sch=jd[7]
|
#set_property -dict { PACKAGE_PIN E2 IOSTANDARD LVCMOS33 } [get_ports { jd[4] }]; #IO_L14P_T2_SRCC_35 Sch=jd[7]
|
||||||
#set_property -dict { PACKAGE_PIN D2 IOSTANDARD LVCMOS33 } [get_ports { jd[5] }]; #IO_L14N_T2_SRCC_35 Sch=jd[8]
|
#set_property -dict { PACKAGE_PIN D2 IOSTANDARD LVCMOS33 } [get_ports { jd[5] }]; #IO_L14N_T2_SRCC_35 Sch=jd[8]
|
||||||
#set_property -dict { PACKAGE_PIN H2 IOSTANDARD LVCMOS33 } [get_ports { jd[6] }]; #IO_L15P_T2_DQS_35 Sch=jd[9]
|
#set_property -dict { PACKAGE_PIN H2 IOSTANDARD LVCMOS33 } [get_ports { jd[6] }]; #IO_L15P_T2_DQS_35 Sch=jd[9]
|
||||||
|
|
@ -216,5 +216,3 @@ set_property -dict {PACKAGE_PIN C2 IOSTANDARD LVCMOS33} [get_ports rst]
|
||||||
#set_property -dict { PACKAGE_PIN A15 IOSTANDARD LVCMOS33 } [get_ports { isns0v95_p }]; #IO_L8P_T1_AD10P_15 Sch=ad_p[10]
|
#set_property -dict { PACKAGE_PIN A15 IOSTANDARD LVCMOS33 } [get_ports { isns0v95_p }]; #IO_L8P_T1_AD10P_15 Sch=ad_p[10]
|
||||||
|
|
||||||
set_property BITSTREAM.GENERAL.COMPRESS True [current_design]
|
set_property BITSTREAM.GENERAL.COMPRESS True [current_design]
|
||||||
|
|
||||||
set_max_delay -from [get_pins vgafb0/display_timings_inst/o_vblank_reg/C] -to [get_pins vgafb0/vblank_xfer_reg/D] 3.000
|
|
||||||
|
|
|
||||||
|
|
@ -17,9 +17,7 @@ module cpu_clkgen(
|
||||||
.CLKFBOUT_PHASE(0.0), // Phase offset in degrees of CLKFB (-360.000-360.000).
|
.CLKFBOUT_PHASE(0.0), // Phase offset in degrees of CLKFB (-360.000-360.000).
|
||||||
.CLKIN1_PERIOD(10.0), // Input clock period in ns to ps resolution (i.e. 33.333 is 30 MHz).
|
.CLKIN1_PERIOD(10.0), // Input clock period in ns to ps resolution (i.e. 33.333 is 30 MHz).
|
||||||
// CLKOUT0_DIVIDE - CLKOUT6_DIVIDE: Divide amount for each CLKOUT (1-128)
|
// CLKOUT0_DIVIDE - CLKOUT6_DIVIDE: Divide amount for each CLKOUT (1-128)
|
||||||
// CPU Clock: 12.0 = 83.33MHz CPU Clock, 333.33MHz Memory Clock
|
.CLKOUT0_DIVIDE_F(12.0), // Divide amount for CLKOUT0 (1.000-128.000).
|
||||||
// 13.0 = 76.92MHz CPU Clock, 307.69MHz Memory Clock
|
|
||||||
.CLKOUT0_DIVIDE_F(13.0), // Divide amount for CLKOUT0 (1.000-128.000).
|
|
||||||
.CLKOUT1_DIVIDE(5),
|
.CLKOUT1_DIVIDE(5),
|
||||||
.CLKOUT2_DIVIDE(40), // 40 = 25MHz pixel clock (should be 25.175MHz per spec) for 640x480
|
.CLKOUT2_DIVIDE(40), // 40 = 25MHz pixel clock (should be 25.175MHz per spec) for 640x480
|
||||||
//.CLKOUT2_DIVIDE(25), // 25 = 40MHz pixel clock for 800x600
|
//.CLKOUT2_DIVIDE(25), // 25 = 40MHz pixel clock for 800x600
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ module dram_bridge #(ADDR_WIDTH = 32, WIDTH = 32)
|
||||||
input wire [WIDTH-1:0] mem_write_data,
|
input wire [WIDTH-1:0] mem_write_data,
|
||||||
input wire mem_read_enable,
|
input wire mem_read_enable,
|
||||||
input wire mem_write_enable,
|
input wire mem_write_enable,
|
||||||
input wire mem_read_ins,
|
|
||||||
output wire mem_wait,
|
output wire mem_wait,
|
||||||
|
|
||||||
input wire rst_n,
|
input wire rst_n,
|
||||||
|
|
@ -106,57 +105,39 @@ module dram_bridge #(ADDR_WIDTH = 32, WIDTH = 32)
|
||||||
.sys_rst (rst_n)
|
.sys_rst (rst_n)
|
||||||
);
|
);
|
||||||
|
|
||||||
(*KEEP*) reg [DRAM_DATA_WIDTH-1:0] ins_cache;
|
// reg [DRAM_DATA_WIDTH-1:0] read_cache;
|
||||||
(*KEEP*) reg [DRAM_ADDR_WIDTH-1:4] icached_addr;
|
// reg [ADDR_WIDTH-1:0] cached_addr;
|
||||||
(*KEEP*) wire icache_hit = mem_read_enable && mem_read_ins && (icached_addr == mem_addr[DRAM_ADDR_WIDTH-1:4]);
|
// wire cache_hit = cached_addr == mem_addr;
|
||||||
|
// wire [DRAM_DATA_WIDTH-1:0] read_data_wrapper = cache_hit ? read_cache : app_rd_data;
|
||||||
(*KEEP*) reg [DRAM_DATA_WIDTH-1:0] d_cache;
|
|
||||||
(*KEEP*) reg [DRAM_ADDR_WIDTH-1:4] dcached_addr;
|
|
||||||
(*KEEP*) wire dcache_hit = mem_read_enable && !mem_read_ins && (dcached_addr == mem_addr[DRAM_ADDR_WIDTH-1:4]);
|
|
||||||
|
|
||||||
wire cache_hit = icache_hit | dcache_hit;
|
|
||||||
|
|
||||||
reg [WIDTH-1:0] read_buf;
|
reg [WIDTH-1:0] read_buf;
|
||||||
reg read_inprogress = 0;
|
reg read_inprogress = 0;
|
||||||
wire dram_read_enable = mem_read_enable && !cache_hit;
|
|
||||||
|
|
||||||
assign app_rd_data_end = 1'b1;
|
assign app_rd_data_end = 1'b1;
|
||||||
|
//assign app_wdf_mask = 16'b1111111111111100;
|
||||||
|
|
||||||
// addresses on the memory interface are aligned to 16 bytes
|
// addresses on the memory interface are aligned to 16 bytes
|
||||||
// and 28 bits wide (=256MB)
|
// and 28 bits wide (=256MB)
|
||||||
assign app_addr = { mem_addr[DRAM_ADDR_WIDTH:4], 4'b0000 };
|
assign app_addr = { mem_addr[DRAM_ADDR_WIDTH:4], 4'b0000 };
|
||||||
|
//assign app_addr = { 28'b0 };
|
||||||
|
|
||||||
// select a word from the 128 bits transferred by the dram controller
|
// select a word from the 128 bits transferred by the dram controller
|
||||||
// according to the lower bits of the address (ignoring bits 1:0)
|
// according to the lower bits of the address (ignoring bits 1:0)
|
||||||
|
wire [WIDTH-1:0] read_word;
|
||||||
wire [1:0] word_sel = mem_addr[3:2];
|
wire [1:0] word_sel = mem_addr[3:2];
|
||||||
|
|
||||||
wire [WIDTH-1:0] read_word =
|
assign read_word = word_sel == 3'b11 ? app_rd_data[31:0] :
|
||||||
word_sel == 2'b11 ? app_rd_data[31:0] :
|
word_sel == 3'b10 ? app_rd_data[63:32] :
|
||||||
word_sel == 2'b10 ? app_rd_data[63:32] :
|
word_sel == 3'b01 ? app_rd_data[95:64] :
|
||||||
word_sel == 2'b01 ? app_rd_data[95:64] :
|
|
||||||
app_rd_data[127:96];
|
app_rd_data[127:96];
|
||||||
|
|
||||||
wire [WIDTH-1:0] read_icached_word =
|
assign mem_read_data = app_rd_data_valid ? read_word : read_buf;
|
||||||
word_sel == 2'b11 ? ins_cache[31:0] :
|
|
||||||
word_sel == 2'b10 ? ins_cache[63:32] :
|
|
||||||
word_sel == 2'b01 ? ins_cache[95:64] :
|
|
||||||
ins_cache[127:96];
|
|
||||||
|
|
||||||
wire [WIDTH-1:0] read_dcached_word =
|
|
||||||
word_sel == 2'b11 ? d_cache[31:0] :
|
|
||||||
word_sel == 2'b10 ? d_cache[63:32] :
|
|
||||||
word_sel == 2'b01 ? d_cache[95:64] :
|
|
||||||
d_cache[127:96];
|
|
||||||
|
|
||||||
(*KEEP*) assign mem_read_data = icache_hit ? read_icached_word :
|
|
||||||
dcache_hit ? read_dcached_word :
|
|
||||||
app_rd_data_valid ? read_word : read_buf;
|
|
||||||
|
|
||||||
// set the write mask according to the lower bits of the address
|
// set the write mask according to the lower bits of the address
|
||||||
// (ignoring bit 0)
|
// (ignoring bit 0)
|
||||||
assign app_wdf_mask = word_sel == 2'b11 ? 16'b1111111111110000 :
|
assign app_wdf_mask = word_sel == 3'b11 ? 16'b1111111111110000 :
|
||||||
word_sel == 2'b10 ? 16'b1111111100001111 :
|
word_sel == 3'b10 ? 16'b1111111100001111 :
|
||||||
word_sel == 2'b01 ? 16'b1111000011111111 :
|
word_sel == 3'b01 ? 16'b1111000011111111 :
|
||||||
16'b0000111111111111 ;
|
16'b0000111111111111 ;
|
||||||
|
|
||||||
wire write_ready = mem_write_enable & app_wdf_rdy & app_rdy;
|
wire write_ready = mem_write_enable & app_wdf_rdy & app_rdy;
|
||||||
|
|
@ -164,67 +145,21 @@ module dram_bridge #(ADDR_WIDTH = 32, WIDTH = 32)
|
||||||
assign app_wdf_end = mem_write_enable & write_ready;
|
assign app_wdf_end = mem_write_enable & write_ready;
|
||||||
assign app_wdf_data = { {4{mem_write_data}} };
|
assign app_wdf_data = { {4{mem_write_data}} };
|
||||||
|
|
||||||
assign mem_wait = (dram_read_enable & ~read_inprogress) |
|
assign mem_wait = (mem_read_enable & ~read_inprogress) |
|
||||||
(mem_write_enable & (~app_wdf_rdy | ~app_rdy)) |
|
(mem_write_enable & (~app_wdf_rdy | ~app_rdy)) |
|
||||||
(read_inprogress & ~app_rd_data_valid);
|
(read_inprogress & ~app_rd_data_valid);
|
||||||
|
|
||||||
assign app_en = (dram_read_enable & ~read_inprogress) |
|
assign app_en = (mem_read_enable & ~read_inprogress) |
|
||||||
(mem_write_enable & write_ready);
|
(mem_write_enable & write_ready);
|
||||||
assign app_cmd = dram_read_enable ? CMD_READ : CMD_WRITE;
|
assign app_cmd = mem_read_enable ? CMD_READ : CMD_WRITE;
|
||||||
|
|
||||||
|
|
||||||
/* set instruction cache */
|
|
||||||
always @(posedge dram_front_clk)
|
always @(posedge dram_front_clk)
|
||||||
begin
|
begin
|
||||||
if(dram_read_enable && mem_read_ins && app_rd_data_valid)
|
if(mem_read_enable & ~read_inprogress & app_rdy)
|
||||||
begin
|
|
||||||
ins_cache <= app_rd_data;
|
|
||||||
icached_addr <= mem_addr[DRAM_ADDR_WIDTH-1:4];
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
/* set data cache */
|
|
||||||
always @(posedge dram_front_clk)
|
|
||||||
begin
|
|
||||||
if(dram_read_enable && !mem_read_ins && app_rd_data_valid)
|
|
||||||
begin
|
|
||||||
d_cache <= app_rd_data;
|
|
||||||
dcached_addr <= mem_addr[DRAM_ADDR_WIDTH-1:4];
|
|
||||||
end
|
|
||||||
|
|
||||||
/* write-through cache - invalidate on write */
|
|
||||||
/* invalidate data cache on write */
|
|
||||||
// if(mem_write_enable && dcached_addr == mem_addr[DRAM_ADDR_WIDTH-1:4])
|
|
||||||
// dcached_addr <= {DRAM_ADDR_WIDTH-4{1'b1}};
|
|
||||||
|
|
||||||
/* write-back cache - update cache on write */
|
|
||||||
// write back to data cache on mem_write
|
|
||||||
if(mem_write_enable && dcached_addr == mem_addr[DRAM_ADDR_WIDTH-1:4])
|
|
||||||
begin
|
|
||||||
case(word_sel)
|
|
||||||
2'b11: d_cache[31:0] <= mem_write_data;
|
|
||||||
2'b10: d_cache[63:32] <= mem_write_data;
|
|
||||||
2'b01: d_cache[95:64] <= mem_write_data;
|
|
||||||
2'b00: d_cache[127:96] <= mem_write_data;
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
/* transfer read data, either from cache or from DRAM */
|
|
||||||
always @(posedge dram_front_clk)
|
|
||||||
begin
|
|
||||||
if(dram_read_enable & ~read_inprogress & app_rdy)
|
|
||||||
read_inprogress <= 1;
|
read_inprogress <= 1;
|
||||||
if(read_inprogress & app_rd_data_valid)
|
if(read_inprogress & app_rd_data_valid)
|
||||||
read_inprogress <= 0;
|
read_inprogress <= 0;
|
||||||
|
if(mem_read_enable & app_rd_data_valid)
|
||||||
if(dram_read_enable & app_rd_data_valid)
|
|
||||||
read_buf <= mem_read_data;
|
read_buf <= mem_read_data;
|
||||||
else
|
|
||||||
if (mem_read_enable & icache_hit)
|
|
||||||
read_buf <= read_icached_word;
|
|
||||||
else
|
|
||||||
if (mem_read_enable & dcache_hit)
|
|
||||||
read_buf <= read_dcached_word;
|
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
`timescale 1ns / 1ps
|
`timescale 1ns / 1ps
|
||||||
|
|
||||||
module irqctrl #(IRQ_LINES = 3, IRQ_DELAY_WIDTH = 8) (
|
module irqctrl #(IRQ_LINES = 2, IRQ_DELAY_WIDTH = 4) (
|
||||||
input wire clk,
|
input wire clk,
|
||||||
input wire [IRQ_LINES-1:0] irq_in,
|
input wire [IRQ_LINES-1:0] irq_in,
|
||||||
input wire cs,
|
input wire cs,
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ module rom32 #(parameter ADDR_WIDTH = 11, DATA_WIDTH = 32)
|
||||||
input wire read_enable
|
input wire read_enable
|
||||||
);
|
);
|
||||||
|
|
||||||
wire [ADDR_WIDTH-2:0] internal_addr = addr[ADDR_WIDTH-1:2]; // -> ignore bits 1-0
|
wire [ADDR_WIDTH-2:0] internal_addr = addr[ADDR_WIDTH-1:2]; // -> ignore bit 0
|
||||||
reg [DATA_WIDTH-1:0] rom [0:(2**(ADDR_WIDTH-2))-1];
|
reg [DATA_WIDTH-1:0] rom [0:(2**(ADDR_WIDTH-2))-1];
|
||||||
|
|
||||||
initial begin
|
initial begin
|
||||||
|
|
@ -51,7 +51,7 @@ module ram32 #(parameter ADDR_WIDTH = 16, DATA_WIDTH = 32)
|
||||||
);
|
);
|
||||||
|
|
||||||
reg [DATA_WIDTH-1:0] ram [0:(2**(ADDR_WIDTH-2))-1]; // 32bit words with byte addressing
|
reg [DATA_WIDTH-1:0] ram [0:(2**(ADDR_WIDTH-2))-1]; // 32bit words with byte addressing
|
||||||
wire [ADDR_WIDTH-2:0] internal_addr = addr[ADDR_WIDTH-1:2]; // -> ignore bits 1-0
|
wire [ADDR_WIDTH-2:0] internal_addr = addr[ADDR_WIDTH-1:2]; // -> ignore bit 1-0
|
||||||
|
|
||||||
always @(posedge clk)
|
always @(posedge clk)
|
||||||
begin
|
begin
|
||||||
|
|
@ -91,10 +91,8 @@ module mem #(parameter ADDR_WIDTH = 32,
|
||||||
// RAM1 $1000 - $FFFF 60K
|
// RAM1 $1000 - $FFFF 60K
|
||||||
// RAM2 $10000 - $FFFFFFFF ~4GB
|
// RAM2 $10000 - $FFFFFFFF ~4GB
|
||||||
|
|
||||||
localparam RAM1_ADDR_WIDTH = 16;
|
|
||||||
|
|
||||||
wire ram_cs = addr[ADDR_WIDTH-1:12] != { {(ADDR_WIDTH-12){1'b0}}};
|
wire ram_cs = addr[ADDR_WIDTH-1:12] != { {(ADDR_WIDTH-12){1'b0}}};
|
||||||
wire ram1_cs = ram_cs && (addr[ADDR_WIDTH-1:RAM1_ADDR_WIDTH] == { {(ADDR_WIDTH-RAM1_ADDR_WIDTH){1'b0}}});
|
wire ram1_cs = ram_cs && (addr[ADDR_WIDTH-1:16] == { {(ADDR_WIDTH-16){1'b0}}});
|
||||||
wire ram2_cs = ram_cs && !ram1_cs;
|
wire ram2_cs = ram_cs && !ram1_cs;
|
||||||
wire rom_cs = !ram_cs && addr[11] == 1'b0;
|
wire rom_cs = !ram_cs && addr[11] == 1'b0;
|
||||||
wire io_cs = !ram_cs && addr[11] == 1'b1;
|
wire io_cs = !ram_cs && addr[11] == 1'b1;
|
||||||
|
|
@ -118,10 +116,10 @@ module mem #(parameter ADDR_WIDTH = 32,
|
||||||
// test
|
// test
|
||||||
reg [1:0] wait_state;
|
reg [1:0] wait_state;
|
||||||
|
|
||||||
ram32 #(.ADDR_WIDTH(RAM1_ADDR_WIDTH)) ram0 // 64KB RAM
|
ram32 #(.ADDR_WIDTH(16)) ram0 // 64KB RAM
|
||||||
(
|
(
|
||||||
.clk(clk),
|
.clk(clk),
|
||||||
.addr(addr[RAM1_ADDR_WIDTH-1:0]),
|
.addr(addr[15:0]),
|
||||||
.data_out(ram_out),
|
.data_out(ram_out),
|
||||||
.read_enable(ram_read),
|
.read_enable(ram_read),
|
||||||
.data_in(data_in),
|
.data_in(data_in),
|
||||||
|
|
|
||||||
|
|
@ -39,12 +39,12 @@
|
||||||
|
|
||||||
<Controller number="0">
|
<Controller number="0">
|
||||||
<MemoryDevice>DDR3_SDRAM/Components/MT41K128M16XX-15E</MemoryDevice>
|
<MemoryDevice>DDR3_SDRAM/Components/MT41K128M16XX-15E</MemoryDevice>
|
||||||
<TimePeriod>3300</TimePeriod>
|
<TimePeriod>3000</TimePeriod>
|
||||||
<VccAuxIO>1.8V</VccAuxIO>
|
<VccAuxIO>1.8V</VccAuxIO>
|
||||||
<PHYRatio>4:1</PHYRatio>
|
<PHYRatio>4:1</PHYRatio>
|
||||||
<InputClkFreq>75.757</InputClkFreq>
|
<InputClkFreq>83.333</InputClkFreq>
|
||||||
<UIExtraClocks>0</UIExtraClocks>
|
<UIExtraClocks>0</UIExtraClocks>
|
||||||
<MMCM_VCO>606</MMCM_VCO>
|
<MMCM_VCO>666</MMCM_VCO>
|
||||||
<MMCMClkOut0> 1.000</MMCMClkOut0>
|
<MMCMClkOut0> 1.000</MMCMClkOut0>
|
||||||
<MMCMClkOut1>1</MMCMClkOut1>
|
<MMCMClkOut1>1</MMCMClkOut1>
|
||||||
<MMCMClkOut2>1</MMCMClkOut2>
|
<MMCMClkOut2>1</MMCMClkOut2>
|
||||||
|
|
|
||||||
|
|
@ -39,12 +39,12 @@
|
||||||
|
|
||||||
<Controller number="0">
|
<Controller number="0">
|
||||||
<MemoryDevice>DDR3_SDRAM/Components/MT41K128M16XX-15E</MemoryDevice>
|
<MemoryDevice>DDR3_SDRAM/Components/MT41K128M16XX-15E</MemoryDevice>
|
||||||
<TimePeriod>3250</TimePeriod>
|
<TimePeriod>3000</TimePeriod>
|
||||||
<VccAuxIO>1.8V</VccAuxIO>
|
<VccAuxIO>1.8V</VccAuxIO>
|
||||||
<PHYRatio>4:1</PHYRatio>
|
<PHYRatio>4:1</PHYRatio>
|
||||||
<InputClkFreq>76.923</InputClkFreq>
|
<InputClkFreq>83.333</InputClkFreq>
|
||||||
<UIExtraClocks>0</UIExtraClocks>
|
<UIExtraClocks>0</UIExtraClocks>
|
||||||
<MMCM_VCO>615</MMCM_VCO>
|
<MMCM_VCO>666</MMCM_VCO>
|
||||||
<MMCMClkOut0> 1.000</MMCMClkOut0>
|
<MMCMClkOut0> 1.000</MMCMClkOut0>
|
||||||
<MMCMClkOut1>1</MMCMClkOut1>
|
<MMCMClkOut1>1</MMCMClkOut1>
|
||||||
<MMCMClkOut2>1</MMCMClkOut2>
|
<MMCMClkOut2>1</MMCMClkOut2>
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -107,7 +107,7 @@ module sdspi(
|
||||||
tx_fifo_empty
|
tx_fifo_empty
|
||||||
);
|
);
|
||||||
|
|
||||||
fifo #(.ADDR_WIDTH(10)) rx_fifo(clk, reset,
|
fifo #(.ADDR_WIDTH(8)) rx_fifo(clk, reset,
|
||||||
rx_fifo_wr_en, rx_fifo_rd_en,
|
rx_fifo_wr_en, rx_fifo_rd_en,
|
||||||
rx_shifter, rx_fifo_out,
|
rx_shifter, rx_fifo_out,
|
||||||
rx_fifo_full,
|
rx_fifo_full,
|
||||||
|
|
|
||||||
|
|
@ -11,14 +11,20 @@ module stackcpu #(parameter ADDR_WIDTH = 32, WIDTH = 32,
|
||||||
output reg [ADDR_WIDTH-1:0] addr,
|
output reg [ADDR_WIDTH-1:0] addr,
|
||||||
input wire [WIDTH-1:0] data_in,
|
input wire [WIDTH-1:0] data_in,
|
||||||
output wire read_enable,
|
output wire read_enable,
|
||||||
output wire read_ins,
|
|
||||||
output wire [WIDTH-1:0] data_out,
|
output wire [WIDTH-1:0] data_out,
|
||||||
output wire write_enable,
|
output wire write_enable,
|
||||||
input wire mem_wait,
|
input wire mem_wait,
|
||||||
|
|
||||||
output wire debug1,
|
output wire led1,
|
||||||
output wire debug2,
|
output wire led2,
|
||||||
output wire debug3
|
output wire led3,
|
||||||
|
|
||||||
|
output wire [WIDTH-1:0] debug_out1,
|
||||||
|
output wire [WIDTH-1:0] debug_out2,
|
||||||
|
output wire [WIDTH-1:0] debug_out3,
|
||||||
|
output wire [WIDTH-1:0] debug_out4,
|
||||||
|
output wire [WIDTH-1:0] debug_out5,
|
||||||
|
output wire [WIDTH-1:0] debug_out6
|
||||||
);
|
);
|
||||||
|
|
||||||
localparam EVAL_STACK_INDEX_WIDTH = 6;
|
localparam EVAL_STACK_INDEX_WIDTH = 6;
|
||||||
|
|
@ -90,6 +96,7 @@ module stackcpu #(parameter ADDR_WIDTH = 32, WIDTH = 32,
|
||||||
wire mem_write;
|
wire mem_write;
|
||||||
|
|
||||||
wire x_is_zero;
|
wire x_is_zero;
|
||||||
|
// wire [WIDTH-1:0] y_plus_operand = Y + operand;
|
||||||
|
|
||||||
wire x_equals_y = X == Y;
|
wire x_equals_y = X == Y;
|
||||||
wire y_lessthan_x = $signed(Y) < $signed(X);
|
wire y_lessthan_x = $signed(Y) < $signed(X);
|
||||||
|
|
@ -104,10 +111,16 @@ module stackcpu #(parameter ADDR_WIDTH = 32, WIDTH = 32,
|
||||||
assign write_enable = mem_write_enable;
|
assign write_enable = mem_write_enable;
|
||||||
|
|
||||||
// debug output ------------------------------------------------------------------------------------
|
// debug output ------------------------------------------------------------------------------------
|
||||||
assign debug1 = reset;
|
assign led1 = reset;
|
||||||
assign debug2 = ins_loadc;
|
assign led2 = ins_loadc;
|
||||||
assign debug3 = ins_branch;
|
assign led3 = ins_branch;
|
||||||
|
// assign debug_out1 = { mem_read_enable, mem_write_enable, x_is_zero,
|
||||||
|
// ins_branch, ins_aluop, y_lessthan_x, x_equals_y, {7{1'b0}}, seq_state};
|
||||||
|
// assign debug_out2 = data_in;
|
||||||
|
// assign debug_out3 = nX;
|
||||||
|
// assign debug_out4 = nPC;
|
||||||
|
// assign debug_out5 = ins;
|
||||||
|
// assign debug_out6 = IV;
|
||||||
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
// instruction decoding
|
// instruction decoding
|
||||||
|
|
@ -169,8 +182,6 @@ module stackcpu #(parameter ADDR_WIDTH = 32, WIDTH = 32,
|
||||||
assign mem_read_enable = (seq_state == FETCH) || (seq_state == EXEC && mem_read);
|
assign mem_read_enable = (seq_state == FETCH) || (seq_state == EXEC && mem_read);
|
||||||
assign mem_write_enable = (seq_state == MEM && mem_write);
|
assign mem_write_enable = (seq_state == MEM && mem_write);
|
||||||
|
|
||||||
assign read_ins = (seq_state == FETCH) || (seq_state == DECODE);
|
|
||||||
|
|
||||||
initial
|
initial
|
||||||
begin
|
begin
|
||||||
PC <= 0; nPC <= 0; seq_state <= MEM;
|
PC <= 0; nPC <= 0; seq_state <= MEM;
|
||||||
|
|
@ -399,10 +410,7 @@ module stackcpu #(parameter ADDR_WIDTH = 32, WIDTH = 32,
|
||||||
// process irq
|
// process irq
|
||||||
always @(posedge clk)
|
always @(posedge clk)
|
||||||
begin
|
begin
|
||||||
// in MEM state, clear irq_pending, when nPC has been set to IV
|
if(seq_state == MEM && irq_pending && !(ins_xfer & xfer_r2p)) // in FETCH state, clear irq_pending.
|
||||||
// RET instruction is a special case because we need to use
|
|
||||||
// the new PC that is in mem_data
|
|
||||||
if(seq_state == MEM && irq_pending && !(ins_xfer && xfer_r2p))
|
|
||||||
irq_pending <= 0;
|
irq_pending <= 0;
|
||||||
else
|
else
|
||||||
irq_pending <= irq_pending || irq; // else set irq_pending when irq is high
|
irq_pending <= irq_pending || irq; // else set irq_pending when irq is high
|
||||||
|
|
|
||||||
|
|
@ -1,270 +0,0 @@
|
||||||
`timescale 1ns / 1ps
|
|
||||||
|
|
||||||
// waveform generator module (PCM)
|
|
||||||
module wavegen #(DATA_WIDTH=32, CLOCK_DIV_WIDTH=22,
|
|
||||||
AMP_WIDTH=16, AMP_BIAS=32768) (
|
|
||||||
input wire clk,
|
|
||||||
input wire reset,
|
|
||||||
input wire [1:0] reg_sel,
|
|
||||||
output wire [DATA_WIDTH-1:0] rd_data,
|
|
||||||
input wire [AMP_WIDTH-1:0] wr_data,
|
|
||||||
input wire rd_en,
|
|
||||||
input wire wr_en,
|
|
||||||
|
|
||||||
output wire [AMP_WIDTH-1:0] amp_val,
|
|
||||||
output wire running,
|
|
||||||
output wire irq
|
|
||||||
);
|
|
||||||
|
|
||||||
localparam TDRAU_REG_CTL = 0; /* control register */
|
|
||||||
localparam TDRAU_REG_CLK = 1; /* clock divider register */
|
|
||||||
localparam TDRAU_REG_AMP = 2; /* amplitude (volume) register */
|
|
||||||
|
|
||||||
/* avoid warning about unconnected port */
|
|
||||||
(* keep="soft" *) wire _unused = rd_en;
|
|
||||||
|
|
||||||
reg channel_enable;
|
|
||||||
reg [CLOCK_DIV_WIDTH-1:0] clock_div;
|
|
||||||
reg [CLOCK_DIV_WIDTH-1:0] div_count;
|
|
||||||
reg amp_phase;
|
|
||||||
reg [AMP_WIDTH-1:0] amp_out;
|
|
||||||
|
|
||||||
|
|
||||||
wire fifo_wr_en;
|
|
||||||
wire fifo_rd_en, fifo_full, fifo_empty;
|
|
||||||
wire [AMP_WIDTH-1:0] fifo_rd_data;
|
|
||||||
|
|
||||||
fifo #(.ADDR_WIDTH(4), .DATA_WIDTH(16)) sample_buf(
|
|
||||||
clk, reset,
|
|
||||||
fifo_wr_en, fifo_rd_en,
|
|
||||||
wr_data[AMP_WIDTH-1:0], fifo_rd_data,
|
|
||||||
fifo_full,
|
|
||||||
fifo_empty
|
|
||||||
);
|
|
||||||
|
|
||||||
assign fifo_rd_en = (div_count == 0) && channel_enable && ~fifo_empty;
|
|
||||||
assign fifo_wr_en = wr_en && (reg_sel == TDRAU_REG_AMP);
|
|
||||||
|
|
||||||
reg irq_buf, irq_enable;
|
|
||||||
assign irq = channel_enable && irq_buf;
|
|
||||||
|
|
||||||
reg [DATA_WIDTH-1:0] rd_data_buf;
|
|
||||||
assign rd_data = rd_data_buf;
|
|
||||||
|
|
||||||
assign amp_val = amp_out;
|
|
||||||
assign running = channel_enable;
|
|
||||||
|
|
||||||
wire ctl_reg_write = wr_en && (reg_sel == TDRAU_REG_CTL);
|
|
||||||
|
|
||||||
/* update read data buffer */
|
|
||||||
always @(posedge clk)
|
|
||||||
begin
|
|
||||||
rd_data_buf <= {{DATA_WIDTH-8{1'b0}},
|
|
||||||
{3{1'b0}}, irq_enable, fifo_full, fifo_empty, amp_phase, channel_enable};
|
|
||||||
end
|
|
||||||
|
|
||||||
/* irq signal to interrupt controller */
|
|
||||||
always @(posedge clk)
|
|
||||||
begin
|
|
||||||
if(reset)
|
|
||||||
irq_buf <= 0;
|
|
||||||
else
|
|
||||||
if(fifo_empty && irq_enable)
|
|
||||||
irq_buf <= 1;
|
|
||||||
else
|
|
||||||
irq_buf <= 0;
|
|
||||||
end
|
|
||||||
|
|
||||||
/* interrupt enable flag */
|
|
||||||
always @(posedge clk)
|
|
||||||
begin
|
|
||||||
if(reset)
|
|
||||||
irq_enable <= 0;
|
|
||||||
else
|
|
||||||
if(ctl_reg_write)
|
|
||||||
irq_enable <= wr_data[4];
|
|
||||||
else
|
|
||||||
if(irq_buf)
|
|
||||||
irq_enable <= 0; // disable interrupts after an interrupt
|
|
||||||
end
|
|
||||||
|
|
||||||
/* channel enable flag */
|
|
||||||
always @(posedge clk)
|
|
||||||
begin
|
|
||||||
if(reset)
|
|
||||||
channel_enable <= 0;
|
|
||||||
else if (ctl_reg_write)
|
|
||||||
channel_enable <= wr_data[0];
|
|
||||||
end
|
|
||||||
|
|
||||||
/* clock divider register */
|
|
||||||
always @(posedge clk)
|
|
||||||
begin
|
|
||||||
if(reset)
|
|
||||||
clock_div <= 0;
|
|
||||||
else
|
|
||||||
if (wr_en && (reg_sel == TDRAU_REG_CLK))
|
|
||||||
clock_div <= wr_data;
|
|
||||||
end
|
|
||||||
|
|
||||||
/* divider counter */
|
|
||||||
always @(posedge clk)
|
|
||||||
begin
|
|
||||||
if(channel_enable)
|
|
||||||
begin
|
|
||||||
if(div_count == 0) // reset counter if it reaches zero
|
|
||||||
div_count <= clock_div;
|
|
||||||
else
|
|
||||||
div_count <= div_count - 1; // else just decrement it
|
|
||||||
end
|
|
||||||
else
|
|
||||||
if (wr_en && (reg_sel == TDRAU_REG_CLK)) // when setting divider,
|
|
||||||
div_count <= 1; // start cycle on next clock tick
|
|
||||||
end
|
|
||||||
|
|
||||||
/* amplitude out */
|
|
||||||
always @(posedge clk)
|
|
||||||
begin
|
|
||||||
if (reset)
|
|
||||||
begin
|
|
||||||
amp_out <= AMP_BIAS;
|
|
||||||
amp_phase <= 1;
|
|
||||||
end
|
|
||||||
else
|
|
||||||
if (channel_enable)
|
|
||||||
begin
|
|
||||||
if (div_count == 0) // invert amplitude on clock tick
|
|
||||||
begin
|
|
||||||
amp_out <= fifo_rd_data;
|
|
||||||
amp_phase <= ~amp_phase;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
amp_out <= AMP_BIAS;
|
|
||||||
|
|
||||||
// reset phase bit when enabling the channel
|
|
||||||
if (ctl_reg_write && wr_data[0] && ~channel_enable)
|
|
||||||
// when channel is being enabled, phase will be flipped on next tick
|
|
||||||
// because div_count will become zero
|
|
||||||
amp_phase <= 1;
|
|
||||||
end
|
|
||||||
endmodule
|
|
||||||
|
|
||||||
module tdraudio #(DATA_WIDTH=32) (
|
|
||||||
input wire clk,
|
|
||||||
input wire reset,
|
|
||||||
input wire [6:0] io_addr,
|
|
||||||
output wire [DATA_WIDTH-1:0] rd_data,
|
|
||||||
input wire [DATA_WIDTH-1:0] wr_data,
|
|
||||||
input wire rd_en,
|
|
||||||
input wire wr_en,
|
|
||||||
output wire irq_out,
|
|
||||||
output wire pdm_out,
|
|
||||||
output wire gain_sel,
|
|
||||||
output wire shutdown_n
|
|
||||||
);
|
|
||||||
|
|
||||||
localparam CLOCK_DIV_WIDTH = 22;
|
|
||||||
localparam AMP_WIDTH = 16;
|
|
||||||
localparam AMP_BIAS = 32768;
|
|
||||||
localparam DAC_WIDTH = 18;
|
|
||||||
|
|
||||||
/* avoid warning about unconnected port */
|
|
||||||
(* keep="soft" *) wire [DATA_WIDTH-1:AMP_WIDTH] _unused = wr_data[DATA_WIDTH-1:AMP_WIDTH];
|
|
||||||
|
|
||||||
wire [4:0] chan_sel = io_addr[6:2];
|
|
||||||
wire [1:0] reg_sel = io_addr[1:0];
|
|
||||||
|
|
||||||
wire [AMP_WIDTH-1:0] amp_wr_data = wr_data[AMP_WIDTH-1:0];
|
|
||||||
|
|
||||||
wire [AMP_WIDTH-1:0] chan0_amp;
|
|
||||||
wire [DATA_WIDTH-1:0] chan0_rd_data;
|
|
||||||
wire chan0_running;
|
|
||||||
wire chan0_irq;
|
|
||||||
wire chan0_sel = chan_sel == 5'd0;
|
|
||||||
wire chan0_rd_en = chan0_sel && rd_en;
|
|
||||||
wire chan0_wr_en = chan0_sel && wr_en;
|
|
||||||
|
|
||||||
wire [AMP_WIDTH-1:0] chan1_amp;
|
|
||||||
wire [DATA_WIDTH-1:0] chan1_rd_data;
|
|
||||||
wire chan1_running;
|
|
||||||
wire chan1_irq;
|
|
||||||
wire chan1_sel = chan_sel == 5'd1;
|
|
||||||
wire chan1_rd_en = chan1_sel && rd_en;
|
|
||||||
wire chan1_wr_en = chan1_sel && wr_en;
|
|
||||||
|
|
||||||
wire [AMP_WIDTH-1:0] chan2_amp;
|
|
||||||
wire [DATA_WIDTH-1:0] chan2_rd_data;
|
|
||||||
wire chan2_running;
|
|
||||||
wire chan2_irq;
|
|
||||||
wire chan2_sel = chan_sel == 5'd2;
|
|
||||||
wire chan2_rd_en = chan2_sel && rd_en;
|
|
||||||
wire chan2_wr_en = chan2_sel && wr_en;
|
|
||||||
|
|
||||||
wire [AMP_WIDTH-1:0] chan3_amp;
|
|
||||||
wire [DATA_WIDTH-1:0] chan3_rd_data;
|
|
||||||
wire chan3_running;
|
|
||||||
wire chan3_irq;
|
|
||||||
wire chan3_sel = chan_sel == 5'd3;
|
|
||||||
wire chan3_rd_en = chan3_sel && rd_en;
|
|
||||||
wire chan3_wr_en = chan3_sel && wr_en;
|
|
||||||
|
|
||||||
wire running = chan0_running || chan1_running || chan2_running || chan3_running;
|
|
||||||
|
|
||||||
assign rd_data = chan0_sel ? chan0_rd_data :
|
|
||||||
chan1_sel ? chan1_rd_data :
|
|
||||||
chan2_sel ? chan2_rd_data :
|
|
||||||
chan3_sel ? chan3_rd_data :
|
|
||||||
{DATA_WIDTH{1'b1}};
|
|
||||||
|
|
||||||
wavegen chan0(clk, reset, reg_sel,
|
|
||||||
chan0_rd_data, amp_wr_data,
|
|
||||||
chan0_rd_en, chan0_wr_en,
|
|
||||||
chan0_amp,
|
|
||||||
chan0_running, chan0_irq);
|
|
||||||
|
|
||||||
wavegen chan1(clk, reset, reg_sel,
|
|
||||||
chan1_rd_data, amp_wr_data,
|
|
||||||
chan1_rd_en, chan1_wr_en,
|
|
||||||
chan1_amp,
|
|
||||||
chan1_running, chan1_irq);
|
|
||||||
|
|
||||||
wavegen chan2(clk, reset, reg_sel,
|
|
||||||
chan2_rd_data, amp_wr_data,
|
|
||||||
chan2_rd_en, chan2_wr_en,
|
|
||||||
chan2_amp,
|
|
||||||
chan2_running, chan2_irq);
|
|
||||||
|
|
||||||
wavegen chan3(clk, reset, reg_sel,
|
|
||||||
chan3_rd_data, amp_wr_data,
|
|
||||||
chan3_rd_en, chan3_wr_en,
|
|
||||||
chan3_amp,
|
|
||||||
chan3_running, chan3_irq);
|
|
||||||
|
|
||||||
reg [DAC_WIDTH:0] deltasigma_acc; // one extra bit
|
|
||||||
wire [DAC_WIDTH:0] amp_sum = chan0_amp + chan1_amp + chan2_amp + chan3_amp; // also one overflow bit here
|
|
||||||
assign gain_sel = 1; // gain select: 0 -> 12dB, 1 -> 6dB
|
|
||||||
|
|
||||||
// assign shutdown_n = running;
|
|
||||||
assign shutdown_n = 1; /* don't enable shutdown mode, it creates a mains hum */
|
|
||||||
|
|
||||||
reg irq_out_buf;
|
|
||||||
assign irq_out = irq_out_buf;
|
|
||||||
|
|
||||||
always @(posedge clk) irq_out_buf <= chan0_irq || chan1_irq || chan2_irq || chan3_irq;
|
|
||||||
|
|
||||||
/* delta-sigma DAC */
|
|
||||||
always @(posedge clk)
|
|
||||||
begin
|
|
||||||
if(reset)
|
|
||||||
deltasigma_acc <= 0;
|
|
||||||
else
|
|
||||||
// if (running)
|
|
||||||
deltasigma_acc <= deltasigma_acc[DAC_WIDTH-1:0] + amp_sum;
|
|
||||||
// else
|
|
||||||
// deltasigma_acc <= deltasigma_acc[DAC_WIDTH-1:0] + (4*AMP_BIAS);
|
|
||||||
end
|
|
||||||
|
|
||||||
/* 1-bit audio output */
|
|
||||||
assign pdm_out = deltasigma_acc[DAC_WIDTH];
|
|
||||||
endmodule
|
|
||||||
|
|
@ -3,18 +3,19 @@
|
||||||
// or as clk_1hz for debugging
|
// or as clk_1hz for debugging
|
||||||
|
|
||||||
`define clock cpuclk
|
`define clock cpuclk
|
||||||
//`define clkfreq 83333333
|
`define clkfreq 83333333
|
||||||
`define clkfreq 76923076
|
|
||||||
//`define clock clk
|
//`define clock clk
|
||||||
//`define clkfreq 100000000
|
//`define clkfreq 100000000
|
||||||
//`define clock clk_1hz
|
//`define clock clk_1hz
|
||||||
`define ENABLE_VGAFB
|
`define ENABLE_VGAFB
|
||||||
`define ENABLE_MICROSD
|
`define ENABLE_MICROSD
|
||||||
`define ENABLE_TDRAUDIO
|
|
||||||
|
|
||||||
module top(
|
module top(
|
||||||
input wire clk,
|
input wire clk,
|
||||||
input wire rst,
|
input wire rst,
|
||||||
|
input wire btn0,
|
||||||
|
input wire sw0,
|
||||||
|
input wire sw1,
|
||||||
output wire led0,
|
output wire led0,
|
||||||
output wire led1,
|
output wire led1,
|
||||||
output wire led2,
|
output wire led2,
|
||||||
|
|
@ -58,13 +59,6 @@ module top(
|
||||||
output wire sd_sck,
|
output wire sd_sck,
|
||||||
input wire sd_cd
|
input wire sd_cd
|
||||||
`endif
|
`endif
|
||||||
|
|
||||||
`ifdef ENABLE_TDRAUDIO
|
|
||||||
,
|
|
||||||
output wire amp2_ain,
|
|
||||||
output wire amp2_gain,
|
|
||||||
output wire amp2_shutdown_n
|
|
||||||
`endif
|
|
||||||
);
|
);
|
||||||
|
|
||||||
reg clk_1hz;
|
reg clk_1hz;
|
||||||
|
|
@ -73,11 +67,10 @@ module top(
|
||||||
localparam ADDR_WIDTH = 32, WIDTH = 32,
|
localparam ADDR_WIDTH = 32, WIDTH = 32,
|
||||||
ROMADDR_WIDTH = 11, IOADDR_WIDTH = 11, IOADDR_SEL = 4;
|
ROMADDR_WIDTH = 11, IOADDR_WIDTH = 11, IOADDR_SEL = 4;
|
||||||
|
|
||||||
(* KEEP *) wire [ADDR_WIDTH-1:0] mem_addr;
|
wire [ADDR_WIDTH-1:0] mem_addr;
|
||||||
wire [WIDTH-1:0] mem_read_data;
|
wire [WIDTH-1:0] mem_read_data;
|
||||||
wire [WIDTH-1:0] mem_write_data;
|
wire [WIDTH-1:0] mem_write_data;
|
||||||
(* KEEP *) wire mem_wait;
|
(* KEEP *) wire mem_wait;
|
||||||
assign led0 = mem_wait;
|
|
||||||
|
|
||||||
(* KEEP *) wire mem_read_enable;
|
(* KEEP *) wire mem_read_enable;
|
||||||
(* KEEP *) wire mem_write_enable;
|
(* KEEP *) wire mem_write_enable;
|
||||||
|
|
@ -87,6 +80,14 @@ module top(
|
||||||
|
|
||||||
wire irq;
|
wire irq;
|
||||||
|
|
||||||
|
// assign led0 = mem_wait;
|
||||||
|
|
||||||
|
wire [WIDTH-1:0] debug_data1, debug_data2,
|
||||||
|
debug_data3, debug_data4,
|
||||||
|
debug_data5, debug_data6;
|
||||||
|
|
||||||
|
assign led0 = debug_data6[0];
|
||||||
|
|
||||||
wire cpuclk, cpuclk_locked;
|
wire cpuclk, cpuclk_locked;
|
||||||
wire dram_refclk200;
|
wire dram_refclk200;
|
||||||
wire pixclk;
|
wire pixclk;
|
||||||
|
|
@ -96,11 +97,9 @@ module top(
|
||||||
wire [ADDR_WIDTH-1:0] dram_addr;
|
wire [ADDR_WIDTH-1:0] dram_addr;
|
||||||
wire [WIDTH-1:0] dram_read_data, dram_write_data;
|
wire [WIDTH-1:0] dram_read_data, dram_write_data;
|
||||||
wire dram_read_enable, dram_write_enable, dram_wait;
|
wire dram_read_enable, dram_write_enable, dram_wait;
|
||||||
(* KEEP *) wire dram_read_ins;
|
|
||||||
|
|
||||||
dram_bridge dram_bridge0 (dram_addr,
|
dram_bridge dram_bridge0 (dram_addr,
|
||||||
dram_read_data, dram_write_data, dram_read_enable, dram_write_enable,
|
dram_read_data, dram_write_data, dram_read_enable, dram_write_enable, dram_wait,
|
||||||
dram_read_ins, dram_wait,
|
|
||||||
rst, cpuclk, dram_refclk200,
|
rst, cpuclk, dram_refclk200,
|
||||||
ddr3_dq, ddr3_dqs_n, ddr3_dqs_p, ddr3_addr,
|
ddr3_dq, ddr3_dqs_n, ddr3_dqs_p, ddr3_addr,
|
||||||
ddr3_ba, ddr3_ras_n, ddr3_cas_n, ddr3_we_n,
|
ddr3_ba, ddr3_ras_n, ddr3_cas_n, ddr3_we_n,
|
||||||
|
|
@ -137,7 +136,7 @@ module top(
|
||||||
assign fb_wr_data = mem_write_data;
|
assign fb_wr_data = mem_write_data;
|
||||||
|
|
||||||
vgafb vgafb0(`clock, pixclk, rst,
|
vgafb vgafb0(`clock, pixclk, rst,
|
||||||
mem_addr[5:2], fb_rd_data, fb_wr_data,
|
mem_addr[3:0], fb_rd_data, fb_wr_data,
|
||||||
fb_rd_en, fb_wr_en,
|
fb_rd_en, fb_wr_en,
|
||||||
VGA_HS_O, VGA_VS_O, VGA_R, VGA_G, VGA_B);
|
VGA_HS_O, VGA_VS_O, VGA_R, VGA_G, VGA_B);
|
||||||
`endif
|
`endif
|
||||||
|
|
@ -225,44 +224,11 @@ module top(
|
||||||
assign uart_tx_data = mem_write_data[7:0];
|
assign uart_tx_data = mem_write_data[7:0];
|
||||||
assign uart_rd_data = { {WIDTH-10{1'b1}}, uart_rx_avail, uart_tx_busy, uart_rx_data };
|
assign uart_rd_data = { {WIDTH-10{1'b1}}, uart_rx_avail, uart_tx_busy, uart_rx_data };
|
||||||
|
|
||||||
wire audio_irq;
|
|
||||||
|
|
||||||
buart #(.CLKFREQ(`clkfreq)) uart0(`clock, rst,
|
|
||||||
uart_baud,
|
|
||||||
uart_txd_in, uart_rxd_out,
|
|
||||||
uart_rx_clear, uart_tx_en,
|
|
||||||
uart_rx_avail, uart_tx_busy,
|
|
||||||
uart_tx_data, uart_rx_data);
|
|
||||||
|
|
||||||
// audio controller
|
|
||||||
`ifdef ENABLE_TDRAUDIO
|
|
||||||
wire [WIDTH-1:0] tdraudio_wr_data;
|
|
||||||
wire [WIDTH-1:0] tdraudio_rd_data;
|
|
||||||
wire tdraudio_rd_en, tdraudio_wr_en;
|
|
||||||
wire tdraudio_irq;
|
|
||||||
|
|
||||||
wire tdraudio_cs_en = io_enable && (io_slot == 4);
|
|
||||||
assign tdraudio_rd_en = tdraudio_cs_en && mem_read_enable;
|
|
||||||
assign tdraudio_wr_en = tdraudio_cs_en && mem_write_enable;
|
|
||||||
assign tdraudio_wr_data = mem_write_data;
|
|
||||||
|
|
||||||
tdraudio tdraudio0(`clock, ~rst,
|
|
||||||
mem_addr[8:2],
|
|
||||||
tdraudio_rd_data,
|
|
||||||
tdraudio_wr_data,
|
|
||||||
tdraudio_rd_en,
|
|
||||||
tdraudio_wr_en,
|
|
||||||
tdraudio_irq,
|
|
||||||
amp2_ain, amp2_gain, amp2_shutdown_n);
|
|
||||||
assign audio_irq = tdraudio_irq;
|
|
||||||
`endif
|
|
||||||
|
|
||||||
// interrupt controller
|
|
||||||
reg timer_tick;
|
reg timer_tick;
|
||||||
reg[23:0] tick_count;
|
reg[23:0] tick_count;
|
||||||
wire [2:0] irq_in = { audio_irq, timer_tick, uart_rx_avail };
|
wire [1:0] irq_in = { timer_tick, uart_rx_avail };
|
||||||
wire [2:0] irqc_rd_data0;
|
wire [1:0] irqc_rd_data0;
|
||||||
wire [WIDTH-1:0] irqc_rd_data = { tick_count, 5'b0, irqc_rd_data0 };
|
wire [WIDTH-1:0] irqc_rd_data = { tick_count, 6'b0, irqc_rd_data0 };
|
||||||
wire irqc_seten = mem_write_data[7];
|
wire irqc_seten = mem_write_data[7];
|
||||||
wire irqc_cs = io_enable && (io_slot == 3);
|
wire irqc_cs = io_enable && (io_slot == 3);
|
||||||
|
|
||||||
|
|
@ -274,23 +240,34 @@ module top(
|
||||||
(io_slot == 2) ? fb_rd_data :
|
(io_slot == 2) ? fb_rd_data :
|
||||||
`endif
|
`endif
|
||||||
(io_slot == 3) ? irqc_rd_data:
|
(io_slot == 3) ? irqc_rd_data:
|
||||||
`ifdef ENABLE_TDRAUDIO
|
|
||||||
(io_slot == 4) ? tdraudio_rd_data:
|
|
||||||
`endif
|
|
||||||
-1;
|
-1;
|
||||||
irqctrl irqctrl0(`clock, irq_in, irqc_cs, mem_write_enable,
|
|
||||||
irqc_seten, irqc_rd_data0,
|
buart #(.CLKFREQ(`clkfreq)) uart0(`clock, rst,
|
||||||
irq);
|
uart_baud,
|
||||||
|
uart_txd_in, uart_rxd_out,
|
||||||
|
uart_rx_clear, uart_tx_en,
|
||||||
|
uart_rx_avail, uart_tx_busy,
|
||||||
|
uart_tx_data, uart_rx_data);
|
||||||
|
|
||||||
// CPU -----------------------------------------------------------------
|
// CPU -----------------------------------------------------------------
|
||||||
stackcpu cpu0(.clk(`clock), .rst(rst), .irq(irq),
|
stackcpu cpu0(.clk(`clock), .rst(rst), .irq(irq),
|
||||||
.addr(mem_addr),
|
.addr(mem_addr),
|
||||||
.data_in(mem_read_data), .read_enable(mem_read_enable),
|
.data_in(mem_read_data), .read_enable(mem_read_enable),
|
||||||
.read_ins(dram_read_ins),
|
|
||||||
.data_out(mem_write_data), .write_enable(mem_write_enable),
|
.data_out(mem_write_data), .write_enable(mem_write_enable),
|
||||||
.mem_wait(mem_wait),
|
.mem_wait(mem_wait),
|
||||||
.debug1(led1), .debug2(led2), .debug3(led3));
|
.led1(led1), .led2(led2), .led3(led3),
|
||||||
|
.debug_out1(debug_data1),
|
||||||
|
.debug_out2(debug_data2),
|
||||||
|
.debug_out3(debug_data3),
|
||||||
|
.debug_out4(debug_data4),
|
||||||
|
.debug_out5(debug_data5),
|
||||||
|
.debug_out6(debug_data6));
|
||||||
|
|
||||||
|
// Interrupt Controller
|
||||||
|
irqctrl irqctrl0(`clock, irq_in, irqc_cs, mem_write_enable,
|
||||||
|
irqc_seten, irqc_rd_data0,
|
||||||
|
irq);
|
||||||
|
|
||||||
// count clock ticks
|
// count clock ticks
|
||||||
// generate interrupt every 20nth of a second
|
// generate interrupt every 20nth of a second
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,13 @@
|
||||||
`timescale 1ns / 1ps
|
`timescale 1ns / 1ps
|
||||||
`default_nettype none
|
`default_nettype none
|
||||||
|
|
||||||
// enable shifter/masker registers
|
|
||||||
`define ENABLE_FB_ACCEL
|
|
||||||
|
|
||||||
// Project F: Display Timings
|
// Project F: Display Timings
|
||||||
// (C)2019 Will Green, Open Source Hardware released under the MIT License
|
// (C)2019 Will Green, Open Source Hardware released under the MIT License
|
||||||
// Learn more at https://projectf.io
|
// Learn more at https://projectf.io
|
||||||
|
|
||||||
//128K video memory is not enough for 640x480x4
|
//128K video memory is not enough for 640x480x4
|
||||||
//`define RES_640_400
|
`define RES_640_400
|
||||||
//`define RES_1024_768
|
//`define RES_1024_768
|
||||||
// RES_640_480 mode displays 400 lines with 640x480/60 video timings,
|
|
||||||
// adding blank lines at the bottom
|
|
||||||
`define RES_640_480
|
|
||||||
|
|
||||||
module display_timings #(
|
module display_timings #(
|
||||||
H_RES=640, // horizontal resolution (pixels)
|
H_RES=640, // horizontal resolution (pixels)
|
||||||
|
|
@ -68,11 +62,10 @@ module display_timings #(
|
||||||
// o_scanline: high for one tick at the start of each visible scanline
|
// o_scanline: high for one tick at the start of each visible scanline
|
||||||
assign o_scanline = (o_sy >= VA_STA) && (o_sy <= VA_END) && (o_sx == H_STA);
|
assign o_scanline = (o_sy >= VA_STA) && (o_sy <= VA_END) && (o_sx == H_STA);
|
||||||
|
|
||||||
// set vblank at end of frame, clear at start
|
|
||||||
always @(posedge i_pix_clk)
|
always @(posedge i_pix_clk)
|
||||||
begin
|
begin
|
||||||
if(o_sy == VA_END) o_vblank <= 1;
|
if(o_frame) o_vblank <= 1;
|
||||||
else if (o_sy == -1) o_vblank <= 0;
|
else if (o_de) o_vblank <= 0;
|
||||||
end
|
end
|
||||||
|
|
||||||
always @ (posedge i_pix_clk)
|
always @ (posedge i_pix_clk)
|
||||||
|
|
@ -129,19 +122,9 @@ module vgafb #(VMEM_ADDR_WIDTH = 15, VMEM_DATA_WIDTH = 32) (
|
||||||
localparam REG_PAL_SLOT = 3; localparam REG_PAL_DATA = 4;
|
localparam REG_PAL_SLOT = 3; localparam REG_PAL_DATA = 4;
|
||||||
localparam REG_CTL = 5;
|
localparam REG_CTL = 5;
|
||||||
|
|
||||||
`ifdef ENABLE_FB_ACCEL
|
|
||||||
localparam REG_SHIFTER = 6;
|
|
||||||
localparam REG_SHIFTCOUNT = 7;
|
|
||||||
localparam REG_SHIFTERM = 8;
|
|
||||||
localparam REG_SHIFTERSP = 09;
|
|
||||||
localparam REG_MASKGEN = 10;
|
|
||||||
`endif
|
|
||||||
|
|
||||||
localparam COLOR_WIDTH = 12;
|
localparam COLOR_WIDTH = 12;
|
||||||
localparam PALETTE_WIDTH = 4;
|
localparam PALETTE_WIDTH = 4;
|
||||||
|
|
||||||
localparam signed PIC_LINES = 400; // visible picture lines
|
|
||||||
|
|
||||||
// Display Clocks
|
// Display Clocks
|
||||||
wire pix_clk = CLK; // pixel clock
|
wire pix_clk = CLK; // pixel clock
|
||||||
wire clk_lock = 1; // clock locked?
|
wire clk_lock = 1; // clock locked?
|
||||||
|
|
@ -156,32 +139,12 @@ module vgafb #(VMEM_ADDR_WIDTH = 15, VMEM_DATA_WIDTH = 32) (
|
||||||
wire pix_rd;
|
wire pix_rd;
|
||||||
wire [VMEM_DATA_WIDTH-1:0] status;
|
wire [VMEM_DATA_WIDTH-1:0] status;
|
||||||
|
|
||||||
`ifdef ENABLE_FB_ACCEL
|
|
||||||
reg [VMEM_DATA_WIDTH-1:0] acc_shifter_in;
|
|
||||||
reg [(VMEM_DATA_WIDTH*2)-1:0] acc_shifter_out;
|
|
||||||
reg [4:0] acc_shift_count;
|
|
||||||
reg acc_start_shift;
|
|
||||||
reg [VMEM_DATA_WIDTH-1:0] acc_mask_in;
|
|
||||||
reg [VMEM_DATA_WIDTH-1:0] acc_mask_buf;
|
|
||||||
reg [VMEM_DATA_WIDTH-1:0] acc_shiftmask_buf;
|
|
||||||
wire [VMEM_DATA_WIDTH-1:0] acc_shifter_mask = acc_shiftmask_buf;
|
|
||||||
wire [VMEM_DATA_WIDTH-1:0] acc_shifter_out_h = acc_shifter_out[(VMEM_DATA_WIDTH*2)-1:VMEM_DATA_WIDTH];
|
|
||||||
wire [VMEM_DATA_WIDTH-1:0] acc_shifter_out_l = acc_shifter_out[VMEM_DATA_WIDTH-1:0];
|
|
||||||
|
|
||||||
`endif
|
|
||||||
|
|
||||||
assign vmem_rd_en = rd_en;
|
assign vmem_rd_en = rd_en;
|
||||||
assign vmem_wr_en = (reg_sel == REG_VMEM) && wr_en;
|
assign vmem_wr_en = (reg_sel == REG_VMEM) && wr_en;
|
||||||
assign rd_data = (reg_sel == REG_VMEM) ? vmem_rd_data :
|
assign rd_data = (reg_sel == REG_VMEM) ? vmem_rd_data :
|
||||||
(reg_sel == REG_RD_ADDR) ? cpu_rd_addr :
|
(reg_sel == REG_RD_ADDR) ? cpu_rd_addr :
|
||||||
(reg_sel == REG_WR_ADDR) ? cpu_wr_addr :
|
(reg_sel == REG_WR_ADDR) ? cpu_wr_addr :
|
||||||
(reg_sel == REG_CTL) ? status :
|
(reg_sel == REG_CTL) ? status :
|
||||||
`ifdef ENABLE_FB_ACCEL
|
|
||||||
(reg_sel == REG_SHIFTER) ? acc_shifter_out_h:
|
|
||||||
(reg_sel == REG_SHIFTERM) ? acc_shiftmask_buf :
|
|
||||||
(reg_sel == REG_SHIFTERSP) ? acc_shifter_out_l :
|
|
||||||
(reg_sel == REG_MASKGEN) ? acc_mask_buf :
|
|
||||||
`endif
|
|
||||||
32'hFFFFFFFF;
|
32'hFFFFFFFF;
|
||||||
|
|
||||||
wire [VMEM_ADDR_WIDTH-1:0] cpu_addr = vmem_wr_en ? cpu_wr_addr : cpu_rd_addr;
|
wire [VMEM_ADDR_WIDTH-1:0] cpu_addr = vmem_wr_en ? cpu_wr_addr : cpu_rd_addr;
|
||||||
|
|
@ -212,7 +175,6 @@ module vgafb #(VMEM_ADDR_WIDTH = 15, VMEM_DATA_WIDTH = 32) (
|
||||||
wire scanline; // scanline start
|
wire scanline; // scanline start
|
||||||
wire vblank; // vertical blank
|
wire vblank; // vertical blank
|
||||||
reg vblank_buf; // vertical blank in cpu clock domain
|
reg vblank_buf; // vertical blank in cpu clock domain
|
||||||
reg vblank_xfer; // vertical blank clock domain crossing
|
|
||||||
|
|
||||||
display_timings #( // 640x480 800x600 1280x720 1920x1080
|
display_timings #( // 640x480 800x600 1280x720 1920x1080
|
||||||
`ifdef RES_1024_768
|
`ifdef RES_1024_768
|
||||||
|
|
@ -238,18 +200,6 @@ module vgafb #(VMEM_ADDR_WIDTH = 15, VMEM_DATA_WIDTH = 32) (
|
||||||
.V_BP(35),
|
.V_BP(35),
|
||||||
.H_POL(0),
|
.H_POL(0),
|
||||||
.V_POL(1)
|
.V_POL(1)
|
||||||
`endif
|
|
||||||
`ifdef RES_640_480
|
|
||||||
.H_RES(640), // 640 800 1280 1920
|
|
||||||
.V_RES(480), // 480 600 720 1080
|
|
||||||
.H_FP(16), // 16 40 110 88
|
|
||||||
.H_SYNC(96), // 96 128 40 44
|
|
||||||
.H_BP(48), // 48 88 220 148
|
|
||||||
.V_FP(10), // 10 1 5 4
|
|
||||||
.V_SYNC(2), // 2 4 5 5
|
|
||||||
.V_BP(33), // 33 23 20 36
|
|
||||||
.H_POL(0), // 0 1 1 1
|
|
||||||
.V_POL(0) // 0 1 1 1
|
|
||||||
`endif
|
`endif
|
||||||
)
|
)
|
||||||
display_timings_inst (
|
display_timings_inst (
|
||||||
|
|
@ -265,8 +215,6 @@ module vgafb #(VMEM_ADDR_WIDTH = 15, VMEM_DATA_WIDTH = 32) (
|
||||||
.o_sy(sy)
|
.o_sy(sy)
|
||||||
);
|
);
|
||||||
|
|
||||||
wire pic_enable = (sy >= 0) && (sy < PIC_LINES); // when to display pixels from VRAM
|
|
||||||
|
|
||||||
wire [7:0] red;
|
wire [7:0] red;
|
||||||
wire [7:0] green;
|
wire [7:0] green;
|
||||||
wire [7:0] blue;
|
wire [7:0] blue;
|
||||||
|
|
@ -285,7 +233,7 @@ module vgafb #(VMEM_ADDR_WIDTH = 15, VMEM_DATA_WIDTH = 32) (
|
||||||
|
|
||||||
always @(posedge pix_clk) frame_d <= frame;
|
always @(posedge pix_clk) frame_d <= frame;
|
||||||
|
|
||||||
always @(posedge cpu_clk) { vblank_buf, vblank_xfer } <= { vblank_xfer, vblank };
|
always @(posedge cpu_clk) vblank_buf <= vblank;
|
||||||
|
|
||||||
always @(posedge cpu_clk)
|
always @(posedge cpu_clk)
|
||||||
begin
|
begin
|
||||||
|
|
@ -302,74 +250,6 @@ module vgafb #(VMEM_ADDR_WIDTH = 15, VMEM_DATA_WIDTH = 32) (
|
||||||
if(rd_en && reg_sel == REG_VMEM) cpu_rd_addr <= cpu_rd_addr + 1; // auto-increment read addr on read
|
if(rd_en && reg_sel == REG_VMEM) cpu_rd_addr <= cpu_rd_addr + 1; // auto-increment read addr on read
|
||||||
end
|
end
|
||||||
|
|
||||||
`ifdef ENABLE_FB_ACCEL
|
|
||||||
//
|
|
||||||
// shifter/masker registers
|
|
||||||
//
|
|
||||||
always @(posedge cpu_clk)
|
|
||||||
begin
|
|
||||||
if(wr_en && reg_sel == REG_SHIFTER)
|
|
||||||
acc_shifter_in <= wr_data;
|
|
||||||
end
|
|
||||||
|
|
||||||
always @(posedge cpu_clk)
|
|
||||||
begin
|
|
||||||
if(wr_en && reg_sel == REG_SHIFTCOUNT)
|
|
||||||
begin
|
|
||||||
acc_shift_count <= { wr_data[2:0], 2'b0};
|
|
||||||
acc_start_shift <= 1;
|
|
||||||
end
|
|
||||||
|
|
||||||
if(acc_start_shift)
|
|
||||||
acc_start_shift <= 0;
|
|
||||||
end
|
|
||||||
|
|
||||||
always @(posedge cpu_clk)
|
|
||||||
begin
|
|
||||||
if (acc_start_shift)
|
|
||||||
acc_shifter_out <= {acc_shifter_in, {VMEM_DATA_WIDTH{1'b0}}} >> acc_shift_count;
|
|
||||||
end
|
|
||||||
|
|
||||||
// mask register
|
|
||||||
always @(posedge cpu_clk)
|
|
||||||
begin
|
|
||||||
if (wr_en && reg_sel == REG_MASKGEN)
|
|
||||||
acc_mask_in <= wr_data;
|
|
||||||
end
|
|
||||||
|
|
||||||
// mask output is buffered to avoid timing problems
|
|
||||||
always @(posedge cpu_clk)
|
|
||||||
begin
|
|
||||||
acc_mask_buf <= {
|
|
||||||
{4{|{acc_mask_in[31:28]}}},
|
|
||||||
{4{|{acc_mask_in[27:24]}}},
|
|
||||||
{4{|{acc_mask_in[23:20]}}},
|
|
||||||
{4{|{acc_mask_in[19:16]}}},
|
|
||||||
{4{|{acc_mask_in[15:12]}}},
|
|
||||||
{4{|{acc_mask_in[11:8]}}},
|
|
||||||
{4{|{acc_mask_in[7:4]}}},
|
|
||||||
{4{|{acc_mask_in[3:0]}}}
|
|
||||||
};
|
|
||||||
end
|
|
||||||
|
|
||||||
always @(posedge cpu_clk)
|
|
||||||
begin
|
|
||||||
acc_shiftmask_buf = {
|
|
||||||
{4{|{acc_shifter_out_h[31:28]}}},
|
|
||||||
{4{|{acc_shifter_out_h[27:24]}}},
|
|
||||||
{4{|{acc_shifter_out_h[23:20]}}},
|
|
||||||
{4{|{acc_shifter_out_h[19:16]}}},
|
|
||||||
{4{|{acc_shifter_out_h[15:12]}}},
|
|
||||||
{4{|{acc_shifter_out_h[11:8]}}},
|
|
||||||
{4{|{acc_shifter_out_h[7:4]}}},
|
|
||||||
{4{|{acc_shifter_out_h[3:0]}}}
|
|
||||||
};
|
|
||||||
end
|
|
||||||
`endif
|
|
||||||
|
|
||||||
//
|
|
||||||
// shifting pixels at pixel clock
|
|
||||||
//
|
|
||||||
always @(posedge pix_clk)
|
always @(posedge pix_clk)
|
||||||
begin
|
begin
|
||||||
if(scanline || shift_count == MAX_SHIFT_COUNT) // before start of a line
|
if(scanline || shift_count == MAX_SHIFT_COUNT) // before start of a line
|
||||||
|
|
@ -406,7 +286,7 @@ module vgafb #(VMEM_ADDR_WIDTH = 15, VMEM_DATA_WIDTH = 32) (
|
||||||
// 12 bit RGB palette
|
// 12 bit RGB palette
|
||||||
assign VGA_HS = h_sync;
|
assign VGA_HS = h_sync;
|
||||||
assign VGA_VS = v_sync;
|
assign VGA_VS = v_sync;
|
||||||
assign VGA_R = (pic_enable && de) ? color_data[11:8] : 4'b0;
|
assign VGA_R = de ? color_data[11:8] : 4'b0;
|
||||||
assign VGA_G = (pic_enable && de) ? color_data[7:4] : 4'b0;
|
assign VGA_G = de ? color_data[7:4] : 4'b0;
|
||||||
assign VGA_B = (pic_enable && de) ? color_data[3:0] : 4'b0;
|
assign VGA_B = de ? color_data[3:0] : 4'b0;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,9 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!-- Product Version: Vivado v2024.2.2 (64-bit) -->
|
<!-- Product Version: Vivado v2020.1 (64-bit) -->
|
||||||
<!-- -->
|
<!-- -->
|
||||||
<!-- Copyright 1986-2022 Xilinx, Inc. All Rights Reserved. -->
|
<!-- Copyright 1986-2020 Xilinx, Inc. All Rights Reserved. -->
|
||||||
<!-- Copyright 2022-2025 Advanced Micro Devices, Inc. All Rights Reserved. -->
|
|
||||||
|
|
||||||
<Project Product="Vivado" Version="7" Minor="68" Path="C:/Users/sebastian/develop/Tridora/tridoracpu/tridoracpu.xpr">
|
<Project Version="7" Minor="49" Path="./tridoracpu.xpr">
|
||||||
<DefaultLaunch Dir="$PRUNDIR"/>
|
<DefaultLaunch Dir="$PRUNDIR"/>
|
||||||
<Configuration>
|
<Configuration>
|
||||||
<Option Name="Id" Val="ab60beb5e7ec4efc9a7b17699b9c3b13"/>
|
<Option Name="Id" Val="ab60beb5e7ec4efc9a7b17699b9c3b13"/>
|
||||||
|
|
@ -13,48 +12,29 @@
|
||||||
<Option Name="CompiledLibDirXSim" Val=""/>
|
<Option Name="CompiledLibDirXSim" Val=""/>
|
||||||
<Option Name="CompiledLibDirModelSim" Val="$PCACHEDIR/compile_simlib/modelsim"/>
|
<Option Name="CompiledLibDirModelSim" Val="$PCACHEDIR/compile_simlib/modelsim"/>
|
||||||
<Option Name="CompiledLibDirQuesta" Val="$PCACHEDIR/compile_simlib/questa"/>
|
<Option Name="CompiledLibDirQuesta" Val="$PCACHEDIR/compile_simlib/questa"/>
|
||||||
|
<Option Name="CompiledLibDirIES" Val="$PCACHEDIR/compile_simlib/ies"/>
|
||||||
<Option Name="CompiledLibDirXcelium" Val="$PCACHEDIR/compile_simlib/xcelium"/>
|
<Option Name="CompiledLibDirXcelium" Val="$PCACHEDIR/compile_simlib/xcelium"/>
|
||||||
<Option Name="CompiledLibDirVCS" Val="$PCACHEDIR/compile_simlib/vcs"/>
|
<Option Name="CompiledLibDirVCS" Val="$PCACHEDIR/compile_simlib/vcs"/>
|
||||||
<Option Name="CompiledLibDirRiviera" Val="$PCACHEDIR/compile_simlib/riviera"/>
|
<Option Name="CompiledLibDirRiviera" Val="$PCACHEDIR/compile_simlib/riviera"/>
|
||||||
<Option Name="CompiledLibDirActivehdl" Val="$PCACHEDIR/compile_simlib/activehdl"/>
|
<Option Name="CompiledLibDirActivehdl" Val="$PCACHEDIR/compile_simlib/activehdl"/>
|
||||||
<Option Name="SimulatorInstallDirModelSim" Val=""/>
|
<Option Name="SimulatorInstallDirModelSim" Val=""/>
|
||||||
<Option Name="SimulatorInstallDirQuesta" Val=""/>
|
<Option Name="SimulatorInstallDirQuesta" Val=""/>
|
||||||
|
<Option Name="SimulatorInstallDirIES" Val=""/>
|
||||||
<Option Name="SimulatorInstallDirXcelium" Val=""/>
|
<Option Name="SimulatorInstallDirXcelium" Val=""/>
|
||||||
<Option Name="SimulatorInstallDirVCS" Val=""/>
|
<Option Name="SimulatorInstallDirVCS" Val=""/>
|
||||||
<Option Name="SimulatorInstallDirRiviera" Val=""/>
|
<Option Name="SimulatorInstallDirRiviera" Val=""/>
|
||||||
<Option Name="SimulatorInstallDirActiveHdl" Val=""/>
|
<Option Name="SimulatorInstallDirActiveHdl" Val=""/>
|
||||||
<Option Name="SimulatorGccInstallDirModelSim" Val=""/>
|
<Option Name="BoardPart" Val="digilentinc.com:arty-a7-35:part0:1.0"/>
|
||||||
<Option Name="SimulatorGccInstallDirQuesta" Val=""/>
|
<Option Name="BoardPartRepoPaths" Val="$PPRDIR/../../../../AppData/Roaming/Xilinx/Vivado/2020.1/xhub/board_store/xilinx_board_store"/>
|
||||||
<Option Name="SimulatorGccInstallDirXcelium" Val=""/>
|
|
||||||
<Option Name="SimulatorGccInstallDirVCS" Val=""/>
|
|
||||||
<Option Name="SimulatorGccInstallDirRiviera" Val=""/>
|
|
||||||
<Option Name="SimulatorGccInstallDirActiveHdl" Val=""/>
|
|
||||||
<Option Name="SimulatorVersionXsim" Val="2024.2"/>
|
|
||||||
<Option Name="SimulatorVersionModelSim" Val="2024.1"/>
|
|
||||||
<Option Name="SimulatorVersionQuesta" Val="2024.1"/>
|
|
||||||
<Option Name="SimulatorVersionXcelium" Val="23.03.002"/>
|
|
||||||
<Option Name="SimulatorVersionVCS" Val="U-2023.03-1"/>
|
|
||||||
<Option Name="SimulatorVersionRiviera" Val="2024.04"/>
|
|
||||||
<Option Name="SimulatorVersionActiveHdl" Val="15.0"/>
|
|
||||||
<Option Name="SimulatorGccVersionXsim" Val="9.3.0"/>
|
|
||||||
<Option Name="SimulatorGccVersionModelSim" Val="7.4.0"/>
|
|
||||||
<Option Name="SimulatorGccVersionQuesta" Val="7.4.0"/>
|
|
||||||
<Option Name="SimulatorGccVersionXcelium" Val="9.3.0"/>
|
|
||||||
<Option Name="SimulatorGccVersionVCS" Val="9.2.0"/>
|
|
||||||
<Option Name="SimulatorGccVersionRiviera" Val="9.3.0"/>
|
|
||||||
<Option Name="SimulatorGccVersionActiveHdl" Val="9.3.0"/>
|
|
||||||
<Option Name="BoardPart" Val=""/>
|
|
||||||
<Option Name="SourceMgmtMode" Val="DisplayOnly"/>
|
<Option Name="SourceMgmtMode" Val="DisplayOnly"/>
|
||||||
<Option Name="ActiveSimSet" Val="sim_sdspi"/>
|
<Option Name="ActiveSimSet" Val="sim_sdspi"/>
|
||||||
<Option Name="DefaultLib" Val="xil_defaultlib"/>
|
<Option Name="DefaultLib" Val="xil_defaultlib"/>
|
||||||
<Option Name="ProjectType" Val="Default"/>
|
<Option Name="ProjectType" Val="Default"/>
|
||||||
<Option Name="IPOutputRepo" Val="$PCACHEDIR/ip"/>
|
<Option Name="IPOutputRepo" Val="$PCACHEDIR/ip"/>
|
||||||
<Option Name="IPDefaultOutputPath" Val="$PGENDIR/sources_1"/>
|
<Option Name="IPDefaultOutputPath" Val="$PSRCDIR/sources_1"/>
|
||||||
<Option Name="IPCachePermission" Val="read"/>
|
<Option Name="IPCachePermission" Val="read"/>
|
||||||
<Option Name="IPCachePermission" Val="write"/>
|
<Option Name="IPCachePermission" Val="write"/>
|
||||||
<Option Name="EnableCoreContainer" Val="FALSE"/>
|
<Option Name="EnableCoreContainer" Val="FALSE"/>
|
||||||
<Option Name="EnableResourceEstimation" Val="FALSE"/>
|
|
||||||
<Option Name="SimCompileState" Val="TRUE"/>
|
|
||||||
<Option Name="CreateRefXciForCoreContainers" Val="FALSE"/>
|
<Option Name="CreateRefXciForCoreContainers" Val="FALSE"/>
|
||||||
<Option Name="IPUserFilesDir" Val="$PIPUSERFILESDIR"/>
|
<Option Name="IPUserFilesDir" Val="$PIPUSERFILESDIR"/>
|
||||||
<Option Name="IPStaticSourceDir" Val="$PIPUSERFILESDIR/ipstatic"/>
|
<Option Name="IPStaticSourceDir" Val="$PIPUSERFILESDIR/ipstatic"/>
|
||||||
|
|
@ -67,13 +47,13 @@
|
||||||
<Option Name="WTVcsLaunchSim" Val="0"/>
|
<Option Name="WTVcsLaunchSim" Val="0"/>
|
||||||
<Option Name="WTRivieraLaunchSim" Val="0"/>
|
<Option Name="WTRivieraLaunchSim" Val="0"/>
|
||||||
<Option Name="WTActivehdlLaunchSim" Val="0"/>
|
<Option Name="WTActivehdlLaunchSim" Val="0"/>
|
||||||
<Option Name="WTXSimExportSim" Val="6"/>
|
<Option Name="WTXSimExportSim" Val="4"/>
|
||||||
<Option Name="WTModelSimExportSim" Val="6"/>
|
<Option Name="WTModelSimExportSim" Val="4"/>
|
||||||
<Option Name="WTQuestaExportSim" Val="6"/>
|
<Option Name="WTQuestaExportSim" Val="4"/>
|
||||||
<Option Name="WTIesExportSim" Val="4"/>
|
<Option Name="WTIesExportSim" Val="4"/>
|
||||||
<Option Name="WTVcsExportSim" Val="6"/>
|
<Option Name="WTVcsExportSim" Val="4"/>
|
||||||
<Option Name="WTRivieraExportSim" Val="6"/>
|
<Option Name="WTRivieraExportSim" Val="4"/>
|
||||||
<Option Name="WTActivehdlExportSim" Val="6"/>
|
<Option Name="WTActivehdlExportSim" Val="4"/>
|
||||||
<Option Name="GenerateIPUpgradeLog" Val="TRUE"/>
|
<Option Name="GenerateIPUpgradeLog" Val="TRUE"/>
|
||||||
<Option Name="XSimRadix" Val="hex"/>
|
<Option Name="XSimRadix" Val="hex"/>
|
||||||
<Option Name="XSimTimeUnit" Val="ns"/>
|
<Option Name="XSimTimeUnit" Val="ns"/>
|
||||||
|
|
@ -85,11 +65,9 @@
|
||||||
<Option Name="SimTypes" Val="tlm_dpi"/>
|
<Option Name="SimTypes" Val="tlm_dpi"/>
|
||||||
<Option Name="MEMEnableMemoryMapGeneration" Val="TRUE"/>
|
<Option Name="MEMEnableMemoryMapGeneration" Val="TRUE"/>
|
||||||
<Option Name="DcpsUptoDate" Val="TRUE"/>
|
<Option Name="DcpsUptoDate" Val="TRUE"/>
|
||||||
<Option Name="UseInlineHdlIP" Val="TRUE"/>
|
|
||||||
<Option Name="LocalIPRepoLeafDirName" Val="ip_repo"/>
|
|
||||||
</Configuration>
|
</Configuration>
|
||||||
<FileSets Version="1" Minor="32">
|
<FileSets Version="1" Minor="31">
|
||||||
<FileSet Name="sources_1" Type="DesignSrcs" RelSrcDir="$PSRCDIR" RelGenDir="$PGENDIR/sources_1">
|
<FileSet Name="sources_1" Type="DesignSrcs" RelSrcDir="$PSRCDIR">
|
||||||
<Filter Type="Srcs"/>
|
<Filter Type="Srcs"/>
|
||||||
<File Path="$PSRCDIR/cpuclk.v">
|
<File Path="$PSRCDIR/cpuclk.v">
|
||||||
<FileInfo>
|
<FileInfo>
|
||||||
|
|
@ -111,7 +89,7 @@
|
||||||
<Attr Name="UsedIn" Val="implementation"/>
|
<Attr Name="UsedIn" Val="implementation"/>
|
||||||
</FileInfo>
|
</FileInfo>
|
||||||
</File>
|
</File>
|
||||||
<File Path="$PSRCDIR/stack.v" Mode="RelativeOnly">
|
<File Path="$PSRCDIR/stack.v">
|
||||||
<FileInfo>
|
<FileInfo>
|
||||||
<Attr Name="UsedIn" Val="synthesis"/>
|
<Attr Name="UsedIn" Val="synthesis"/>
|
||||||
<Attr Name="UsedIn" Val="implementation"/>
|
<Attr Name="UsedIn" Val="implementation"/>
|
||||||
|
|
@ -142,7 +120,7 @@
|
||||||
</FileInfo>
|
</FileInfo>
|
||||||
</File>
|
</File>
|
||||||
<File Path="$PSRCDIR/testbench.v"/>
|
<File Path="$PSRCDIR/testbench.v"/>
|
||||||
<File Path="$PPRDIR/rom.mem" Mode="RelativeOnly">
|
<File Path="$PPRDIR/rom.mem">
|
||||||
<FileInfo>
|
<FileInfo>
|
||||||
<Attr Name="UsedIn" Val="synthesis"/>
|
<Attr Name="UsedIn" Val="synthesis"/>
|
||||||
<Attr Name="UsedIn" Val="simulation"/>
|
<Attr Name="UsedIn" Val="simulation"/>
|
||||||
|
|
@ -173,14 +151,14 @@
|
||||||
<Attr Name="UsedIn" Val="simulation"/>
|
<Attr Name="UsedIn" Val="simulation"/>
|
||||||
</FileInfo>
|
</FileInfo>
|
||||||
</File>
|
</File>
|
||||||
<File Path="$PSRCDIR/bram_tdp.v" Mode="RelativeOnly">
|
<File Path="$PSRCDIR/bram_tdp.v">
|
||||||
<FileInfo>
|
<FileInfo>
|
||||||
<Attr Name="UsedIn" Val="synthesis"/>
|
<Attr Name="UsedIn" Val="synthesis"/>
|
||||||
<Attr Name="UsedIn" Val="implementation"/>
|
<Attr Name="UsedIn" Val="implementation"/>
|
||||||
<Attr Name="UsedIn" Val="simulation"/>
|
<Attr Name="UsedIn" Val="simulation"/>
|
||||||
</FileInfo>
|
</FileInfo>
|
||||||
</File>
|
</File>
|
||||||
<File Path="$PSRCDIR/palette.v" Mode="RelativeOnly">
|
<File Path="$PSRCDIR/palette.v">
|
||||||
<FileInfo>
|
<FileInfo>
|
||||||
<Attr Name="UsedIn" Val="synthesis"/>
|
<Attr Name="UsedIn" Val="synthesis"/>
|
||||||
<Attr Name="UsedIn" Val="implementation"/>
|
<Attr Name="UsedIn" Val="implementation"/>
|
||||||
|
|
@ -205,19 +183,12 @@
|
||||||
<Attr Name="UsedIn" Val="simulation"/>
|
<Attr Name="UsedIn" Val="simulation"/>
|
||||||
</FileInfo>
|
</FileInfo>
|
||||||
</File>
|
</File>
|
||||||
<File Path="$PSRCDIR/tdraudio.v">
|
|
||||||
<FileInfo>
|
|
||||||
<Attr Name="UsedIn" Val="synthesis"/>
|
|
||||||
<Attr Name="UsedIn" Val="implementation"/>
|
|
||||||
<Attr Name="UsedIn" Val="simulation"/>
|
|
||||||
</FileInfo>
|
|
||||||
</File>
|
|
||||||
<Config>
|
<Config>
|
||||||
<Option Name="DesignMode" Val="RTL"/>
|
<Option Name="DesignMode" Val="RTL"/>
|
||||||
<Option Name="TopModule" Val="top"/>
|
<Option Name="TopModule" Val="top"/>
|
||||||
</Config>
|
</Config>
|
||||||
</FileSet>
|
</FileSet>
|
||||||
<FileSet Name="constrs_1" Type="Constrs" RelSrcDir="$PSRCDIR" RelGenDir="$PGENDIR/constrs_1">
|
<FileSet Name="constrs_1" Type="Constrs" RelSrcDir="$PSRCDIR">
|
||||||
<Filter Type="Constrs"/>
|
<Filter Type="Constrs"/>
|
||||||
<File Path="$PSRCDIR/Arty-A7-35-Master.xdc">
|
<File Path="$PSRCDIR/Arty-A7-35-Master.xdc">
|
||||||
<FileInfo>
|
<FileInfo>
|
||||||
|
|
@ -230,7 +201,7 @@
|
||||||
<Option Name="ConstrsType" Val="XDC"/>
|
<Option Name="ConstrsType" Val="XDC"/>
|
||||||
</Config>
|
</Config>
|
||||||
</FileSet>
|
</FileSet>
|
||||||
<FileSet Name="sim_1" Type="SimulationSrcs" RelSrcDir="$PSRCDIR" RelGenDir="$PGENDIR/sim_1">
|
<FileSet Name="sim_1" Type="SimulationSrcs" RelSrcDir="$PSRCDIR">
|
||||||
<Filter Type="Srcs"/>
|
<Filter Type="Srcs"/>
|
||||||
<File Path="$PSRCDIR/uart_tb.v"/>
|
<File Path="$PSRCDIR/uart_tb.v"/>
|
||||||
<File Path="$PPRDIR/testbench_behav1.wcfg">
|
<File Path="$PPRDIR/testbench_behav1.wcfg">
|
||||||
|
|
@ -253,19 +224,28 @@
|
||||||
<Option Name="SrcSet" Val="sources_1"/>
|
<Option Name="SrcSet" Val="sources_1"/>
|
||||||
<Option Name="XSimWcfgFile" Val="$PPRDIR/testbench_behav.wcfg"/>
|
<Option Name="XSimWcfgFile" Val="$PPRDIR/testbench_behav.wcfg"/>
|
||||||
<Option Name="XSimWcfgFile" Val="$PPRDIR/testbench_behav1.wcfg"/>
|
<Option Name="XSimWcfgFile" Val="$PPRDIR/testbench_behav1.wcfg"/>
|
||||||
<Option Name="CosimPdi" Val=""/>
|
|
||||||
<Option Name="CosimPlatform" Val=""/>
|
|
||||||
<Option Name="CosimElf" Val=""/>
|
|
||||||
<Option Name="NLNetlistMode" Val="funcsim"/>
|
<Option Name="NLNetlistMode" Val="funcsim"/>
|
||||||
</Config>
|
</Config>
|
||||||
</FileSet>
|
</FileSet>
|
||||||
<FileSet Name="utils_1" Type="Utils" RelSrcDir="$PSRCDIR/utils_1" RelGenDir="$PGENDIR/utils_1">
|
<FileSet Name="utils_1" Type="Utils" RelSrcDir="$PSRCDIR/utils_1">
|
||||||
<Filter Type="Utils"/>
|
<Filter Type="Utils"/>
|
||||||
<Config>
|
<Config>
|
||||||
<Option Name="TopAutoSet" Val="TRUE"/>
|
<Option Name="TopAutoSet" Val="TRUE"/>
|
||||||
</Config>
|
</Config>
|
||||||
</FileSet>
|
</FileSet>
|
||||||
<FileSet Name="sim_fifo" Type="SimulationSrcs" RelSrcDir="$PSRCDIR/sim_fifo" RelGenDir="$PGENDIR/sim_fifo">
|
<FileSet Name="mig_dram_0" Type="BlockSrcs" RelSrcDir="$PSRCDIR/mig_dram_0">
|
||||||
|
<File Path="$PSRCDIR/mig_dram_0/mig_dram_0.xci">
|
||||||
|
<FileInfo>
|
||||||
|
<Attr Name="UsedIn" Val="synthesis"/>
|
||||||
|
<Attr Name="UsedIn" Val="implementation"/>
|
||||||
|
</FileInfo>
|
||||||
|
</File>
|
||||||
|
<Config>
|
||||||
|
<Option Name="TopModule" Val="mig_dram_0"/>
|
||||||
|
<Option Name="UseBlackboxStub" Val="1"/>
|
||||||
|
</Config>
|
||||||
|
</FileSet>
|
||||||
|
<FileSet Name="sim_fifo" Type="SimulationSrcs" RelSrcDir="$PSRCDIR/sim_fifo">
|
||||||
<Filter Type="Srcs"/>
|
<Filter Type="Srcs"/>
|
||||||
<File Path="$PSRCDIR/fifo.v">
|
<File Path="$PSRCDIR/fifo.v">
|
||||||
<FileInfo>
|
<FileInfo>
|
||||||
|
|
@ -292,12 +272,9 @@
|
||||||
<Option Name="PamSignalDriverFile" Val="xil_bypass_driver"/>
|
<Option Name="PamSignalDriverFile" Val="xil_bypass_driver"/>
|
||||||
<Option Name="PamPseudoTop" Val="pseudo_tb"/>
|
<Option Name="PamPseudoTop" Val="pseudo_tb"/>
|
||||||
<Option Name="SrcSet" Val="sources_1"/>
|
<Option Name="SrcSet" Val="sources_1"/>
|
||||||
<Option Name="CosimPdi" Val=""/>
|
|
||||||
<Option Name="CosimPlatform" Val=""/>
|
|
||||||
<Option Name="CosimElf" Val=""/>
|
|
||||||
</Config>
|
</Config>
|
||||||
</FileSet>
|
</FileSet>
|
||||||
<FileSet Name="sim_sdspi" Type="SimulationSrcs" RelSrcDir="$PSRCDIR/sim_sdspi" RelGenDir="$PGENDIR/sim_sdspi">
|
<FileSet Name="sim_sdspi" Type="SimulationSrcs" RelSrcDir="$PSRCDIR/sim_sdspi">
|
||||||
<Filter Type="Srcs"/>
|
<Filter Type="Srcs"/>
|
||||||
<File Path="$PPRDIR/sdspi_testbench_behav.wcfg">
|
<File Path="$PPRDIR/sdspi_testbench_behav.wcfg">
|
||||||
<FileInfo>
|
<FileInfo>
|
||||||
|
|
@ -318,24 +295,9 @@
|
||||||
<Option Name="PamPseudoTop" Val="pseudo_tb"/>
|
<Option Name="PamPseudoTop" Val="pseudo_tb"/>
|
||||||
<Option Name="SrcSet" Val="sources_1"/>
|
<Option Name="SrcSet" Val="sources_1"/>
|
||||||
<Option Name="XSimWcfgFile" Val="$PPRDIR/sdspi_testbench_behav.wcfg"/>
|
<Option Name="XSimWcfgFile" Val="$PPRDIR/sdspi_testbench_behav.wcfg"/>
|
||||||
<Option Name="CosimPdi" Val=""/>
|
|
||||||
<Option Name="CosimPlatform" Val=""/>
|
|
||||||
<Option Name="CosimElf" Val=""/>
|
|
||||||
<Option Name="xsim.simulate.runtime" Val="10ms"/>
|
<Option Name="xsim.simulate.runtime" Val="10ms"/>
|
||||||
</Config>
|
</Config>
|
||||||
</FileSet>
|
</FileSet>
|
||||||
<FileSet Name="mig_dram_0" Type="BlockSrcs" RelSrcDir="$PSRCDIR/mig_dram_0" RelGenDir="$PGENDIR/mig_dram_0">
|
|
||||||
<File Path="$PSRCDIR/mig_dram_0/mig_dram_0.xci">
|
|
||||||
<FileInfo>
|
|
||||||
<Attr Name="UsedIn" Val="synthesis"/>
|
|
||||||
<Attr Name="UsedIn" Val="implementation"/>
|
|
||||||
</FileInfo>
|
|
||||||
</File>
|
|
||||||
<Config>
|
|
||||||
<Option Name="TopModule" Val="mig_dram_0"/>
|
|
||||||
<Option Name="UseBlackboxStub" Val="1"/>
|
|
||||||
</Config>
|
|
||||||
</FileSet>
|
|
||||||
</FileSets>
|
</FileSets>
|
||||||
<Simulators>
|
<Simulators>
|
||||||
<Simulator Name="XSim">
|
<Simulator Name="XSim">
|
||||||
|
|
@ -355,34 +317,56 @@
|
||||||
<Option Name="Description" Val="Active-HDL Simulator"/>
|
<Option Name="Description" Val="Active-HDL Simulator"/>
|
||||||
</Simulator>
|
</Simulator>
|
||||||
</Simulators>
|
</Simulators>
|
||||||
<Runs Version="1" Minor="22">
|
<Runs Version="1" Minor="11">
|
||||||
<Run Id="synth_1" Type="Ft3:Synth" SrcSet="sources_1" Part="xc7a35ticsg324-1L" ConstrsSet="constrs_1" Description="Vivado Synthesis Defaults" AutoIncrementalCheckpoint="false" WriteIncrSynthDcp="false" State="current" Dir="$PRUNDIR/synth_1" IncludeInArchive="true" IsChild="false" AutoIncrementalDir="$PSRCDIR/utils_1/imports/synth_1" AutoRQSDir="$PSRCDIR/utils_1/imports/synth_1" ParallelReportGen="true">
|
<Run Id="synth_1" Type="Ft3:Synth" SrcSet="sources_1" Part="xc7a35ticsg324-1L" ConstrsSet="constrs_1" Description="Vivado Synthesis Defaults" AutoIncrementalCheckpoint="false" WriteIncrSynthDcp="false" State="current" Dir="$PRUNDIR/synth_1" IncludeInArchive="true">
|
||||||
<Strategy Version="1" Minor="2">
|
<Strategy Version="1" Minor="2">
|
||||||
<StratHandle Name="Vivado Synthesis Defaults" Flow="Vivado Synthesis 2024">
|
<StratHandle Name="Vivado Synthesis Defaults" Flow="Vivado Synthesis 2020"/>
|
||||||
<Desc>Vivado Synthesis Defaults</Desc>
|
|
||||||
</StratHandle>
|
|
||||||
<Step Id="synth_design"/>
|
<Step Id="synth_design"/>
|
||||||
</Strategy>
|
</Strategy>
|
||||||
<GeneratedRun Dir="$PRUNDIR" File="gen_run.xml"/>
|
<GeneratedRun Dir="$PRUNDIR" File="gen_run.xml"/>
|
||||||
<ReportStrategy Name="Vivado Synthesis Default Reports" Flow="Vivado Synthesis 2024"/>
|
<ReportStrategy Name="Vivado Synthesis Default Reports" Flow="Vivado Synthesis 2020"/>
|
||||||
<Report Name="ROUTE_DESIGN.REPORT_METHODOLOGY" Enabled="1"/>
|
<Report Name="ROUTE_DESIGN.REPORT_METHODOLOGY" Enabled="1"/>
|
||||||
<RQSFiles/>
|
<RQSFiles/>
|
||||||
</Run>
|
</Run>
|
||||||
<Run Id="mig_dram_0_synth_1" Type="Ft3:Synth" SrcSet="mig_dram_0" Part="xc7a35ticsg324-1L" ConstrsSet="mig_dram_0" Description="Vivado Synthesis Defaults" AutoIncrementalCheckpoint="false" WriteIncrSynthDcp="false" Dir="$PRUNDIR/mig_dram_0_synth_1" IncludeInArchive="true" IsChild="false" AutoIncrementalDir="$PSRCDIR/utils_1/imports/mig_dram_0_synth_1" AutoRQSDir="$PSRCDIR/utils_1/imports/mig_dram_0_synth_1" ParallelReportGen="true">
|
<Run Id="mig_dram_0_synth_1" Type="Ft3:Synth" SrcSet="mig_dram_0" Part="xc7a35ticsg324-1L" ConstrsSet="mig_dram_0" Description="Vivado Synthesis Defaults" AutoIncrementalCheckpoint="false" WriteIncrSynthDcp="false" Dir="$PRUNDIR/mig_dram_0_synth_1" IncludeInArchive="true">
|
||||||
<Strategy Version="1" Minor="2">
|
<Strategy Version="1" Minor="2">
|
||||||
<StratHandle Name="Vivado Synthesis Defaults" Flow="Vivado Synthesis 2024"/>
|
<StratHandle Name="Vivado Synthesis Defaults" Flow="Vivado Synthesis 2020"/>
|
||||||
<Step Id="synth_design"/>
|
<Step Id="synth_design"/>
|
||||||
</Strategy>
|
</Strategy>
|
||||||
<GeneratedRun Dir="$PRUNDIR" File="gen_run.xml"/>
|
<GeneratedRun Dir="$PRUNDIR" File="gen_run.xml"/>
|
||||||
<ReportStrategy Name="Vivado Synthesis Default Reports" Flow="Vivado Synthesis 2024"/>
|
<ReportStrategy Name="Vivado Synthesis Default Reports" Flow="Vivado Synthesis 2020"/>
|
||||||
<Report Name="ROUTE_DESIGN.REPORT_METHODOLOGY" Enabled="1"/>
|
<Report Name="ROUTE_DESIGN.REPORT_METHODOLOGY" Enabled="1"/>
|
||||||
<RQSFiles/>
|
<RQSFiles/>
|
||||||
</Run>
|
</Run>
|
||||||
<Run Id="impl_1" Type="Ft2:EntireDesign" Part="xc7a35ticsg324-1L" ConstrsSet="constrs_1" Description="Default settings for Implementation." AutoIncrementalCheckpoint="false" WriteIncrSynthDcp="false" State="current" Dir="$PRUNDIR/impl_1" SynthRun="synth_1" IncludeInArchive="true" IsChild="false" GenFullBitstream="true" AutoIncrementalDir="$PSRCDIR/utils_1/imports/impl_1" LaunchOptions="-jobs 6 " AutoRQSDir="$PSRCDIR/utils_1/imports/impl_1" ParallelReportGen="true">
|
<Run Id="impl_1" Type="Ft2:EntireDesign" Part="xc7a35ticsg324-1L" ConstrsSet="constrs_1" Description="Increase placer effort in the post-placement optimization phase, and disable timing relaxation in the router." AutoIncrementalCheckpoint="false" WriteIncrSynthDcp="false" State="current" Dir="$PRUNDIR/impl_1" SynthRun="synth_1" IncludeInArchive="true" GenFullBitstream="true">
|
||||||
<Strategy Version="1" Minor="2">
|
<Strategy Version="1" Minor="2">
|
||||||
<StratHandle Name="Vivado Implementation Defaults" Flow="Vivado Implementation 2024">
|
<StratHandle Name="Performance_RefinePlacement" Flow="Vivado Implementation 2020"/>
|
||||||
<Desc>Default settings for Implementation.</Desc>
|
<Step Id="init_design"/>
|
||||||
</StratHandle>
|
<Step Id="opt_design"/>
|
||||||
|
<Step Id="power_opt_design"/>
|
||||||
|
<Step Id="place_design">
|
||||||
|
<Option Id="Directive">7</Option>
|
||||||
|
</Step>
|
||||||
|
<Step Id="post_place_power_opt_design"/>
|
||||||
|
<Step Id="phys_opt_design">
|
||||||
|
<Option Id="Directive">0</Option>
|
||||||
|
</Step>
|
||||||
|
<Step Id="route_design">
|
||||||
|
<Option Id="Directive">0</Option>
|
||||||
|
</Step>
|
||||||
|
<Step Id="post_route_phys_opt_design"/>
|
||||||
|
<Step Id="write_bitstream">
|
||||||
|
<Option Id="BinFile">1</Option>
|
||||||
|
</Step>
|
||||||
|
</Strategy>
|
||||||
|
<GeneratedRun Dir="$PRUNDIR" File="gen_run.xml"/>
|
||||||
|
<ReportStrategy Name="Vivado Implementation Default Reports" Flow="Vivado Implementation 2020"/>
|
||||||
|
<Report Name="ROUTE_DESIGN.REPORT_METHODOLOGY" Enabled="1"/>
|
||||||
|
<RQSFiles/>
|
||||||
|
</Run>
|
||||||
|
<Run Id="mig_dram_0_impl_1" Type="Ft2:EntireDesign" Part="xc7a35ticsg324-1L" ConstrsSet="mig_dram_0" Description="Default settings for Implementation." AutoIncrementalCheckpoint="false" WriteIncrSynthDcp="false" SynthRun="mig_dram_0_synth_1" IncludeInArchive="false" GenFullBitstream="true">
|
||||||
|
<Strategy Version="1" Minor="2">
|
||||||
|
<StratHandle Name="Vivado Implementation Defaults" Flow="Vivado Implementation 2020"/>
|
||||||
<Step Id="init_design"/>
|
<Step Id="init_design"/>
|
||||||
<Step Id="opt_design"/>
|
<Step Id="opt_design"/>
|
||||||
<Step Id="power_opt_design"/>
|
<Step Id="power_opt_design"/>
|
||||||
|
|
@ -393,30 +377,14 @@
|
||||||
<Step Id="post_route_phys_opt_design"/>
|
<Step Id="post_route_phys_opt_design"/>
|
||||||
<Step Id="write_bitstream"/>
|
<Step Id="write_bitstream"/>
|
||||||
</Strategy>
|
</Strategy>
|
||||||
<GeneratedRun Dir="$PRUNDIR" File="gen_run.xml"/>
|
<ReportStrategy Name="Vivado Implementation Default Reports" Flow="Vivado Implementation 2020"/>
|
||||||
<ReportStrategy Name="Vivado Implementation Default Reports" Flow="Vivado Implementation 2024"/>
|
|
||||||
<Report Name="ROUTE_DESIGN.REPORT_METHODOLOGY" Enabled="1"/>
|
|
||||||
<RQSFiles/>
|
|
||||||
</Run>
|
|
||||||
<Run Id="mig_dram_0_impl_1" Type="Ft2:EntireDesign" Part="xc7a35ticsg324-1L" ConstrsSet="mig_dram_0" Description="Default settings for Implementation." AutoIncrementalCheckpoint="false" WriteIncrSynthDcp="false" SynthRun="mig_dram_0_synth_1" IncludeInArchive="false" IsChild="false" GenFullBitstream="true" AutoIncrementalDir="$PSRCDIR/utils_1/imports/mig_dram_0_impl_1" AutoRQSDir="$PSRCDIR/utils_1/imports/mig_dram_0_impl_1" ParallelReportGen="true">
|
|
||||||
<Strategy Version="1" Minor="2">
|
|
||||||
<StratHandle Name="Vivado Implementation Defaults" Flow="Vivado Implementation 2024"/>
|
|
||||||
<Step Id="init_design"/>
|
|
||||||
<Step Id="opt_design"/>
|
|
||||||
<Step Id="power_opt_design"/>
|
|
||||||
<Step Id="place_design"/>
|
|
||||||
<Step Id="post_place_power_opt_design"/>
|
|
||||||
<Step Id="phys_opt_design"/>
|
|
||||||
<Step Id="route_design"/>
|
|
||||||
<Step Id="post_route_phys_opt_design"/>
|
|
||||||
<Step Id="write_bitstream"/>
|
|
||||||
</Strategy>
|
|
||||||
<ReportStrategy Name="Vivado Implementation Default Reports" Flow="Vivado Implementation 2024"/>
|
|
||||||
<Report Name="ROUTE_DESIGN.REPORT_METHODOLOGY" Enabled="1"/>
|
<Report Name="ROUTE_DESIGN.REPORT_METHODOLOGY" Enabled="1"/>
|
||||||
<RQSFiles/>
|
<RQSFiles/>
|
||||||
</Run>
|
</Run>
|
||||||
</Runs>
|
</Runs>
|
||||||
<Board/>
|
<Board>
|
||||||
|
<Jumpers/>
|
||||||
|
</Board>
|
||||||
<DashboardSummary Version="1" Minor="0">
|
<DashboardSummary Version="1" Minor="0">
|
||||||
<Dashboards>
|
<Dashboards>
|
||||||
<Dashboard Name="default_dashboard">
|
<Dashboard Name="default_dashboard">
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -5,7 +5,7 @@
|
||||||
- written in Golang
|
- written in Golang
|
||||||
|
|
||||||
## Getting started
|
## Getting started
|
||||||
Download this zipfile: [tridoraemu.zip](https://git.insignificance.de/api/packages/slederer/generic/tridoraemu/0.0.5/tridoraemu.zip)
|
Download this zipfile: [tridoraemu.zip](https://git.insignificance.de/api/packages/slederer/generic/tridoraemu/0.0.1/tridoraemu.zip)
|
||||||
|
|
||||||
It contains the sources, the ROM image, an SD-card image and a precompiled windows binary.
|
It contains the sources, the ROM image, an SD-card image and a precompiled windows binary.
|
||||||
|
|
||||||
|
|
@ -40,7 +40,7 @@ On the ROM monitor prompt, press *B* to boot from the SD-card image. This should
|
||||||
|
|
||||||
In the shell, try the *L* command to list directories and the *V* command to change volumes. The *Examples* volume contains some example programs in source form.
|
In the shell, try the *L* command to list directories and the *V* command to change volumes. The *Examples* volume contains some example programs in source form.
|
||||||
|
|
||||||
The programs *lines*, *conway* and *mandelbrot*, among others, show some (hopefully) interesting VGA graphics. The *pictviewer* program can show image files (*.pict files) which contain 640x400x4 bitmaps. A few sample image files are provided.
|
The programs *lines*, *conway* and *mandelbrot*, among others, show some (hopefully) interesting VGA graphics. The *viewpict* program can show image files (*.pict files) which contain 640x400x4 bitmaps. A few sample image files are provided.
|
||||||
|
|
||||||
To compile a program, set the file name (e.g. *lines.pas*) with the *W* command in the shell. Then, use *B* and *R* to build and run the program.
|
To compile a program, set the file name (e.g. *lines.pas*) with the *W* command in the shell. Then, use *B* and *R* to build and run the program.
|
||||||
|
|
||||||
|
|
@ -50,9 +50,6 @@ The volume *Testvolume 1* (note the space) contains a precompiled game called *c
|
||||||
|
|
||||||
You can run the program with the *O* command in the shell (just press Return for the program arguments), or you can set the workfile name with *W* and then use the *R* command.
|
You can run the program with the *O* command in the shell (just press Return for the program arguments), or you can set the workfile name with *W* and then use the *R* command.
|
||||||
|
|
||||||
The volume *Rogue* contains a compiled version of ECL-Rogue, a Pascal variant of the
|
|
||||||
classic Rogue game.
|
|
||||||
|
|
||||||
The *K* command in the shell is used to reclaim the space occupied by deleted or overwritten files.
|
The *K* command in the shell is used to reclaim the space occupied by deleted or overwritten files.
|
||||||
|
|
||||||
A running program can be terminated by pressing Control-C, but only if the program is expecting keyboard input at that time.
|
A running program can be terminated by pressing Control-C, but only if the program is expecting keyboard input at that time.
|
||||||
|
|
|
||||||
|
|
@ -125,7 +125,7 @@ func (c *CPU) step() error {
|
||||||
|
|
||||||
Y := c.estack[c.ESP]
|
Y := c.estack[c.ESP]
|
||||||
|
|
||||||
insWord, err := c.mem.readIns(c.PC)
|
insWord, err := c.mem.read(c.PC)
|
||||||
if err != nil { return err }
|
if err != nil { return err }
|
||||||
if c.PC % 4 == 0 {
|
if c.PC % 4 == 0 {
|
||||||
insWord = insWord >> 16
|
insWord = insWord >> 16
|
||||||
|
|
@ -249,7 +249,6 @@ func (c *CPU) step() error {
|
||||||
var name string
|
var name string
|
||||||
if (insWord & 1) == 1 {
|
if (insWord & 1) == 1 {
|
||||||
name = "STORE.B"
|
name = "STORE.B"
|
||||||
operand &= ^1
|
|
||||||
ea = c.BP + word(operand)
|
ea = c.BP + word(operand)
|
||||||
} else {
|
} else {
|
||||||
name = "STORE"
|
name = "STORE"
|
||||||
|
|
|
||||||
|
|
@ -10,16 +10,11 @@ import (
|
||||||
const VmemWords = 32768
|
const VmemWords = 32768
|
||||||
const PaletteSlots = 16
|
const PaletteSlots = 16
|
||||||
const FB_RA = 0
|
const FB_RA = 0
|
||||||
const FB_WA = 4
|
const FB_WA = 1
|
||||||
const FB_IO = 8
|
const FB_IO = 2
|
||||||
const FB_PS = 12
|
const FB_PS = 3
|
||||||
const FB_PD = 16
|
const FB_PD = 4
|
||||||
const FB_CTL= 20
|
const FB_CTL= 5
|
||||||
const FB_SHIFTER = 24
|
|
||||||
const FB_SHIFTCOUNT = 28
|
|
||||||
const FB_SHIFTERM = 32
|
|
||||||
const FB_SHIFTERSP = 36
|
|
||||||
const FB_MASKGEN = 40
|
|
||||||
|
|
||||||
const PixelMask = 0b11110000000000000000000000000000
|
const PixelMask = 0b11110000000000000000000000000000
|
||||||
const PixelPerWord = 8
|
const PixelPerWord = 8
|
||||||
|
|
@ -37,10 +32,6 @@ type Framebuffer struct {
|
||||||
paletteSlot word
|
paletteSlot word
|
||||||
vmem [VmemWords]word
|
vmem [VmemWords]word
|
||||||
readCount int
|
readCount int
|
||||||
paletteChanged bool
|
|
||||||
shiftAssistData word
|
|
||||||
shiftAssistCount int
|
|
||||||
maskGenData word
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Framebuffer) initialize() {
|
func (f *Framebuffer) initialize() {
|
||||||
|
|
@ -61,11 +52,6 @@ func (f *Framebuffer) read(byteaddr word) (word, error) {
|
||||||
case FB_PS: result = f.paletteSlot
|
case FB_PS: result = f.paletteSlot
|
||||||
case FB_PD: result = f.readPalette()
|
case FB_PD: result = f.readPalette()
|
||||||
case FB_CTL: result = f.readCtl()
|
case FB_CTL: result = f.readCtl()
|
||||||
case FB_SHIFTER: result = f.readShiftAssist()
|
|
||||||
case FB_SHIFTCOUNT: result = 0xFFFFFFF
|
|
||||||
case FB_SHIFTERM: result = f.readShifterM()
|
|
||||||
case FB_SHIFTERSP: result = f.readShifterSp()
|
|
||||||
case FB_MASKGEN: result = f.readMaskGen()
|
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
return result, nil
|
return result, nil
|
||||||
|
|
@ -80,11 +66,6 @@ func (f *Framebuffer) write(value word, byteaddr word) (error) {
|
||||||
case FB_PS: f.paletteSlot = value
|
case FB_PS: f.paletteSlot = value
|
||||||
case FB_PD: f.writePalette(value)
|
case FB_PD: f.writePalette(value)
|
||||||
case FB_CTL: f.writeCtl(value)
|
case FB_CTL: f.writeCtl(value)
|
||||||
case FB_SHIFTER: f.writeShiftAssist(value)
|
|
||||||
case FB_SHIFTCOUNT: f.writeShiftCount(value)
|
|
||||||
case FB_SHIFTERM:
|
|
||||||
case FB_SHIFTERSP:
|
|
||||||
case FB_MASKGEN: f.writeMaskGen(value)
|
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -123,26 +104,6 @@ func (f *Framebuffer) readPalette() word {
|
||||||
return word(0)
|
return word(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Framebuffer) startFrame() {
|
|
||||||
// when the palette changes, we
|
|
||||||
// need to redraw every pixel
|
|
||||||
// to get the new colors
|
|
||||||
if f.paletteChanged {
|
|
||||||
oldRAddr := f.readAddr
|
|
||||||
oldWAddr := f.writeAddr
|
|
||||||
f.readAddr = 0
|
|
||||||
f.writeAddr = 0
|
|
||||||
|
|
||||||
for i := 0; i < VmemWords; i++ {
|
|
||||||
f.writeVmem(f.readVmem())
|
|
||||||
}
|
|
||||||
|
|
||||||
f.readAddr = oldRAddr
|
|
||||||
f.writeAddr = oldWAddr
|
|
||||||
f.paletteChanged = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *Framebuffer) writePalette(value word) {
|
func (f *Framebuffer) writePalette(value word) {
|
||||||
// 4 bits per color channel
|
// 4 bits per color channel
|
||||||
r := uint8((value & 0b111100000000) >> 8)
|
r := uint8((value & 0b111100000000) >> 8)
|
||||||
|
|
@ -155,7 +116,6 @@ func (f *Framebuffer) writePalette(value word) {
|
||||||
b = b << 4
|
b = b << 4
|
||||||
|
|
||||||
f.palette[f.paletteSlot] = color.RGBA{r,g,b,0}
|
f.palette[f.paletteSlot] = color.RGBA{r,g,b,0}
|
||||||
f.paletteChanged = true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Framebuffer) readCtl() word {
|
func (f *Framebuffer) readCtl() word {
|
||||||
|
|
@ -170,47 +130,3 @@ func (f *Framebuffer) readCtl() word {
|
||||||
|
|
||||||
func (f *Framebuffer) writeCtl(value word) {
|
func (f *Framebuffer) writeCtl(value word) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Framebuffer) writeShiftAssist(value word) {
|
|
||||||
f.shiftAssistData = value
|
|
||||||
f.shiftAssistCount = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *Framebuffer) readShiftAssist() word {
|
|
||||||
return f.shiftAssistData >> (f.shiftAssistCount * 4)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *Framebuffer) writeShiftCount(value word) {
|
|
||||||
f.shiftAssistCount = int(value & 0x7)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *Framebuffer) readShifterM() word {
|
|
||||||
return convertToMask(f.readShiftAssist())
|
|
||||||
}
|
|
||||||
|
|
||||||
func pixelToMask(pixels word, mask word) word {
|
|
||||||
if (pixels & mask) != 0 { return mask } else { return 0 }
|
|
||||||
}
|
|
||||||
|
|
||||||
func convertToMask(pixels word) word {
|
|
||||||
return pixelToMask(pixels, 0xF0000000) |
|
|
||||||
pixelToMask(pixels, 0x0F000000) |
|
|
||||||
pixelToMask(pixels, 0x00F00000) |
|
|
||||||
pixelToMask(pixels, 0x000F0000) |
|
|
||||||
pixelToMask(pixels, 0x0000F000) |
|
|
||||||
pixelToMask(pixels, 0x00000F00) |
|
|
||||||
pixelToMask(pixels, 0x000000F0) |
|
|
||||||
pixelToMask(pixels, 0x0000000F)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *Framebuffer) readShifterSp() word {
|
|
||||||
return word(f.shiftAssistData << ((8-f.shiftAssistCount)*4))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *Framebuffer) writeMaskGen(value word) {
|
|
||||||
f.maskGenData = value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *Framebuffer) readMaskGen() word {
|
|
||||||
return convertToMask(f.maskGenData)
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -17,12 +17,6 @@ const IOSlotSize = 128
|
||||||
|
|
||||||
const IOSlotCount = 16
|
const IOSlotCount = 16
|
||||||
|
|
||||||
const DRAMStart = 65536
|
|
||||||
|
|
||||||
const CacheAddrShift = 8
|
|
||||||
|
|
||||||
const CacheWriteThrough = true
|
|
||||||
|
|
||||||
type Mem struct {
|
type Mem struct {
|
||||||
ram [] word
|
ram [] word
|
||||||
iohandler [IOSlotCount] IOHandler
|
iohandler [IOSlotCount] IOHandler
|
||||||
|
|
@ -85,7 +79,7 @@ func (m *Mem) attachIO(h IOHandler, slot int) {
|
||||||
m.iohandler[slot] = h
|
m.iohandler[slot] = h
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mem) readRaw(byteaddr word) (word, error) {
|
func (m *Mem) read(byteaddr word) (word, error) {
|
||||||
if byteaddr >= IOStartAddr && byteaddr < RAMStartAddr {
|
if byteaddr >= IOStartAddr && byteaddr < RAMStartAddr {
|
||||||
ioslot := (byteaddr - IOStartAddr) / IOSlotSize
|
ioslot := (byteaddr - IOStartAddr) / IOSlotSize
|
||||||
if m.iohandler[ioslot] != nil {
|
if m.iohandler[ioslot] != nil {
|
||||||
|
|
@ -102,14 +96,6 @@ func (m *Mem) readRaw(byteaddr word) (word, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Mem) read(byteaddr word) (word, error) {
|
|
||||||
return m.readRaw(byteaddr);
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Mem) readIns(byteaddr word) (word, error) {
|
|
||||||
return m.readRaw(byteaddr);
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *Mem) write(value word, byteaddr word) error {
|
func (m *Mem) write(value word, byteaddr word) error {
|
||||||
if byteaddr < IOStartAddr {
|
if byteaddr < IOStartAddr {
|
||||||
return fmt.Errorf("Write to ROM area at %08X value %08X", byteaddr, value)
|
return fmt.Errorf("Write to ROM area at %08X value %08X", byteaddr, value)
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,7 @@ import (
|
||||||
"flag"
|
"flag"
|
||||||
"time"
|
"time"
|
||||||
"github.com/hajimehoshi/ebiten/v2"
|
"github.com/hajimehoshi/ebiten/v2"
|
||||||
"github.com/hajimehoshi/ebiten/v2/ebitenutil"
|
// "github.com/hajimehoshi/ebiten/v2/ebitenutil"
|
||||||
"github.com/hajimehoshi/ebiten/v2/inpututil"
|
|
||||||
// "image/color"
|
// "image/color"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -36,7 +35,6 @@ func idle(canGoIdle bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Game struct{
|
type Game struct{
|
||||||
debug bool
|
|
||||||
x,y int
|
x,y int
|
||||||
stepsPerFrame int
|
stepsPerFrame int
|
||||||
lastFrameDuration time.Duration
|
lastFrameDuration time.Duration
|
||||||
|
|
@ -45,7 +43,6 @@ type Game struct{
|
||||||
func (g *Game) Update() error {
|
func (g *Game) Update() error {
|
||||||
startTime := time.Now()
|
startTime := time.Now()
|
||||||
|
|
||||||
framebuffer.startFrame()
|
|
||||||
for i := 0; i < g.stepsPerFrame; i++ {
|
for i := 0; i < g.stepsPerFrame; i++ {
|
||||||
err := cpu.step()
|
err := cpu.step()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -60,23 +57,16 @@ func (g *Game) Update() error {
|
||||||
}
|
}
|
||||||
g.lastFrameDuration = time.Since(startTime)
|
g.lastFrameDuration = time.Since(startTime)
|
||||||
|
|
||||||
if inpututil.IsKeyJustReleased(ebiten.KeyF12) {
|
|
||||||
g.debug = !g.debug
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *Game) Draw(screen *ebiten.Image) {
|
func (g *Game) Draw(screen *ebiten.Image) {
|
||||||
screen.DrawImage(framebuffer.framebuffer, nil)
|
screen.DrawImage(framebuffer.framebuffer, nil)
|
||||||
|
|
||||||
if g.debug {
|
|
||||||
buf := fmt.Sprintf("PC: %08X FP: %08X RP: %08X ESP: %2X %v",
|
|
||||||
cpu.PC, cpu.FP, cpu.RP, cpu.ESP, g.lastFrameDuration)
|
|
||||||
ebitenutil.DebugPrint(screen, buf)
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
buf := fmt.Sprintf("PC: %08X FP: %08X RP: %08X ESP: %2X\n%v", cpu.PC, cpu.FP, cpu.RP, cpu.ESP, g.lastFrameDuration)
|
||||||
|
ebitenutil.DebugPrint(screen, buf)
|
||||||
|
|
||||||
screen.Set(g.x, g.y, color.RGBA{255,0,0,0})
|
screen.Set(g.x, g.y, color.RGBA{255,0,0,0})
|
||||||
screen.Set(g.x, g.y+1, color.RGBA{0,255,0,0})
|
screen.Set(g.x, g.y+1, color.RGBA{0,255,0,0})
|
||||||
screen.Set(g.x, g.y+2, color.RGBA{0,255,255,0})
|
screen.Set(g.x, g.y+2, color.RGBA{0,255,255,0})
|
||||||
|
|
|
||||||
|
|
@ -1,118 +0,0 @@
|
||||||
#!/usr/bin/python3
|
|
||||||
import sys
|
|
||||||
import png
|
|
||||||
|
|
||||||
sprite_width = 32
|
|
||||||
sprite_height = 32
|
|
||||||
|
|
||||||
def process_pixdata(outfile, pixdata, frameindex = 0, pix_w=640, pix_h=400):
|
|
||||||
|
|
||||||
pixmask = 15
|
|
||||||
y = pix_h * frameindex
|
|
||||||
max_y = y + pix_h - 1
|
|
||||||
|
|
||||||
while y <= max_y:
|
|
||||||
x = 0
|
|
||||||
max_x = pix_w - 1
|
|
||||||
pixline = pixdata[y]
|
|
||||||
while x <= max_x:
|
|
||||||
px1 = pixline[x+0] & pixmask
|
|
||||||
px2 = pixline[x+1] & pixmask
|
|
||||||
px3 = pixline[x+2] & pixmask
|
|
||||||
px4 = pixline[x+3] & pixmask
|
|
||||||
px5 = pixline[x+4] & pixmask
|
|
||||||
px6 = pixline[x+5] & pixmask
|
|
||||||
px7 = pixline[x+6] & pixmask
|
|
||||||
px8 = pixline[x+7] & pixmask
|
|
||||||
vmem_word = (px1 << 28) | (px2 << 24) | (px3 << 20) | (px4 << 16) | \
|
|
||||||
(px5 << 12) | (px6 << 8) | (px7 << 4) | px8
|
|
||||||
|
|
||||||
outfile.write(vmem_word.to_bytes(4, 'big'))
|
|
||||||
x += 8
|
|
||||||
y += 1
|
|
||||||
|
|
||||||
def write_palette_word(outfile, r, g, b):
|
|
||||||
r4 = r >> 4
|
|
||||||
g4 = g >> 4
|
|
||||||
b4 = b >> 4
|
|
||||||
c12 = r4 << 8 | g4 << 4 | b4
|
|
||||||
|
|
||||||
outfile.write(c12.to_bytes(4, 'big'))
|
|
||||||
|
|
||||||
|
|
||||||
def process_palette(outfile, palette):
|
|
||||||
if len(palette[0]) == 4:
|
|
||||||
for r,g,b,a in palette:
|
|
||||||
write_palette_word(outfile, r, g, b)
|
|
||||||
else:
|
|
||||||
for r,g,b in palette:
|
|
||||||
write_palette_word(outfile, r, g, b)
|
|
||||||
|
|
||||||
|
|
||||||
def write_header(outfile):
|
|
||||||
magic = b'PIct'
|
|
||||||
mode = 1
|
|
||||||
outfile.write(magic);
|
|
||||||
outfile.write(mode.to_bytes(4, 'big'))
|
|
||||||
|
|
||||||
|
|
||||||
def write_sprite_header(outfile):
|
|
||||||
magic = b'SPRT'
|
|
||||||
mode = 1
|
|
||||||
outfile.write(magic);
|
|
||||||
outfile.write(mode.to_bytes(4, 'big'))
|
|
||||||
|
|
||||||
|
|
||||||
def write_pict_file(width, height, px, metadata, outfile):
|
|
||||||
print("processing as PICT file...")
|
|
||||||
if width != 640:
|
|
||||||
print("width must be 640, aborting")
|
|
||||||
sys.exit(1)
|
|
||||||
pixdata = list(px)
|
|
||||||
palette = metadata['palette']
|
|
||||||
|
|
||||||
if len(palette) != 16:
|
|
||||||
print("palette must have 16 colors, aborting")
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
with open(outfile,'wb') as f:
|
|
||||||
write_header(f)
|
|
||||||
process_palette(f, palette)
|
|
||||||
process_pixdata(f, pixdata)
|
|
||||||
|
|
||||||
|
|
||||||
def write_sprite_file(width, height, px, metadata, outfile):
|
|
||||||
print("processing as SPRT file with {} sprites...".format(height//sprite_height))
|
|
||||||
if width != sprite_width:
|
|
||||||
print("width must be {}, aborting".format(sprite_width))
|
|
||||||
sys.exit(1)
|
|
||||||
pixdata = list(px)
|
|
||||||
palette = metadata['palette']
|
|
||||||
|
|
||||||
if len(palette) != 16:
|
|
||||||
print("palette must have 16 colors instead of {}, aborting".format(len(palette)))
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
with open(outfile,'wb') as f:
|
|
||||||
write_sprite_header(f)
|
|
||||||
process_pixdata(f, pixdata, pix_w=sprite_width, pix_h=height)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
if len(sys.argv) != 3:
|
|
||||||
print("Usage: {} <infile> <outfile>".format(sys.argv[0]))
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
infile = sys.argv[1]
|
|
||||||
outfile = sys.argv[2]
|
|
||||||
|
|
||||||
r = png.Reader(infile)
|
|
||||||
p = r.read()
|
|
||||||
width, height, px, metadata = p
|
|
||||||
if width == 640:
|
|
||||||
write_pict_file(width, height, px, metadata, outfile)
|
|
||||||
elif width == sprite_width:
|
|
||||||
write_sprite_file(width, height, px, metadata, outfile)
|
|
||||||
else:
|
|
||||||
print("Can't handle this file, need a width of\n640 or {} pixels with 16 color palette.".format(sprite_width))
|
|
||||||
|
|
||||||
398
utils/serload.py
398
utils/serload.py
|
|
@ -1,398 +0,0 @@
|
||||||
#!/usr/bin/python3
|
|
||||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
|
||||||
#
|
|
||||||
# Copyright 2021 Sebastian Lederer
|
|
||||||
#
|
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
# you may not use this file except in compliance with the License.
|
|
||||||
# You may obtain a copy of the License at
|
|
||||||
#
|
|
||||||
# http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
#
|
|
||||||
# Unless required by applicable law or agreed to in writing, software
|
|
||||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
# See the License for the specific language governing permissions and
|
|
||||||
# limitations under the License.
|
|
||||||
|
|
||||||
import sys
|
|
||||||
import os
|
|
||||||
import serial
|
|
||||||
import time
|
|
||||||
import random
|
|
||||||
import platform
|
|
||||||
import argparse
|
|
||||||
|
|
||||||
blocksize = 32
|
|
||||||
BEL = 7
|
|
||||||
ACK = 6
|
|
||||||
NAK = 21
|
|
||||||
ENQ = 5
|
|
||||||
SOH = 1
|
|
||||||
STX = 2
|
|
||||||
EOT = 4
|
|
||||||
wordmask = 0xFFFFFFFF
|
|
||||||
pattern = 0xAFFECAFE
|
|
||||||
|
|
||||||
|
|
||||||
def get_default_device():
|
|
||||||
if platform.system() == 'Windows':
|
|
||||||
return 'COM4:'
|
|
||||||
else:
|
|
||||||
return '/dev/ttyUSB1'
|
|
||||||
|
|
||||||
|
|
||||||
def checksum(databytes):
|
|
||||||
i = 0
|
|
||||||
cksum = 0
|
|
||||||
while i < len(databytes):
|
|
||||||
word = databytes[i] << 24 | \
|
|
||||||
databytes[i+1] << 16 | \
|
|
||||||
databytes[i+2] << 8 | \
|
|
||||||
databytes[i+3]
|
|
||||||
# print("word:{0:08x}".format(word))
|
|
||||||
i += 4
|
|
||||||
|
|
||||||
cksum = (((cksum + word) ^ pattern) << 1) & wordmask
|
|
||||||
|
|
||||||
return cksum
|
|
||||||
|
|
||||||
|
|
||||||
def sendchar(char, ser):
|
|
||||||
ser.write(char.to_bytes(1, 'big'))
|
|
||||||
|
|
||||||
|
|
||||||
def sendcommand(ser, cmd=b'L', verbose=False):
|
|
||||||
verbose = True
|
|
||||||
ser.write(cmd)
|
|
||||||
resp = ser.read_until()
|
|
||||||
if verbose:
|
|
||||||
print(cmd,"sent, response:", str(resp))
|
|
||||||
return resp
|
|
||||||
|
|
||||||
|
|
||||||
# send command and wait for echo
|
|
||||||
def commandwait(ser, cmd):
|
|
||||||
resp = sendcommand(ser, cmd, verbose=False)
|
|
||||||
if len(resp) == 0:
|
|
||||||
print("timeout sending '{}' command".format(cmd))
|
|
||||||
return None
|
|
||||||
|
|
||||||
if resp.startswith(b"> "):
|
|
||||||
resp = resp[2:]
|
|
||||||
|
|
||||||
if resp != bytearray(cmd + b"\r\n"):
|
|
||||||
print("invalid response to '{}' command".format(cmd))
|
|
||||||
return None
|
|
||||||
|
|
||||||
return resp
|
|
||||||
|
|
||||||
|
|
||||||
def send_size_header(ser, filesize):
|
|
||||||
ser.write(b'\x05') # ENQ
|
|
||||||
resp = ser.read(1)
|
|
||||||
if resp != b'\x15': # NAK
|
|
||||||
# print("ENQ response:",str(resp))
|
|
||||||
ser.write(b'\x01') # SOH
|
|
||||||
|
|
||||||
databytes = filesize.to_bytes(4, 'big')
|
|
||||||
chksum = ~filesize & 0xFFFFFFFF
|
|
||||||
|
|
||||||
#print(str(databytes), len(databytes), type(filesize), filesize)
|
|
||||||
#print(str(chksum.to_bytes(4,'big')), len(databytes))
|
|
||||||
|
|
||||||
ser.write(databytes)
|
|
||||||
ser.write(chksum.to_bytes(4,'big'))
|
|
||||||
|
|
||||||
resp = ser.read(1)
|
|
||||||
if len(resp) == 0:
|
|
||||||
print("timeout waiting for ACK on size header")
|
|
||||||
return False
|
|
||||||
char = resp[0]
|
|
||||||
# print("response to size header:", str(resp), repr(char))
|
|
||||||
return char == ACK # ACK
|
|
||||||
else:
|
|
||||||
print("Not using size header.")
|
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
def serload_bin(datafile, ser):
|
|
||||||
resp = sendcommand(ser)
|
|
||||||
if len(resp) == 0:
|
|
||||||
print("timeout sending 'L' command")
|
|
||||||
return
|
|
||||||
|
|
||||||
sentblocks = 0
|
|
||||||
resend = 0
|
|
||||||
|
|
||||||
data = []
|
|
||||||
|
|
||||||
if datafile.endswith('.mem'):
|
|
||||||
with open(datafile) as f:
|
|
||||||
for l in f.readlines():
|
|
||||||
b3 = l[0:8]
|
|
||||||
b2 = l[8:16]
|
|
||||||
b1 = l[16:24]
|
|
||||||
b0 = l[24:32]
|
|
||||||
data.extend([ int(b,2) for b in [b3,b2,b1,b0]])
|
|
||||||
else:
|
|
||||||
with open(datafile, 'rb') as f:
|
|
||||||
data = f.read()
|
|
||||||
|
|
||||||
filesize = len(data)
|
|
||||||
|
|
||||||
if filesize % blocksize > 0:
|
|
||||||
l = len(data)
|
|
||||||
pad = blocksize - (l % blocksize)
|
|
||||||
|
|
||||||
print("padding {} bytes with {} to {}".format(l, pad, l+pad))
|
|
||||||
|
|
||||||
data += bytearray(pad)
|
|
||||||
|
|
||||||
print("{} total blocks".format((len(data) + blocksize - 1) // blocksize))
|
|
||||||
|
|
||||||
if not send_size_header(ser, filesize):
|
|
||||||
print("Error sending size header.")
|
|
||||||
return
|
|
||||||
|
|
||||||
while len(data) > 0:
|
|
||||||
block = data[0:32]
|
|
||||||
databytes = bytearray(block)
|
|
||||||
|
|
||||||
sendchar(STX, ser)
|
|
||||||
#print("block:",databytes)
|
|
||||||
chksum = checksum(databytes)
|
|
||||||
#print("checksum: {0:08x}".format(chksum))
|
|
||||||
#if random.randrange(2) == 0:
|
|
||||||
# databytes[random.randrange(len(databytes))] = 0
|
|
||||||
ser.write(databytes)
|
|
||||||
#print(chksum.to_bytes(4, 'big'))
|
|
||||||
ser.write(chksum.to_bytes(4,'big'))
|
|
||||||
|
|
||||||
resp = ser.read(1)
|
|
||||||
if len(resp) == 0:
|
|
||||||
print("timeout waiting for ACK")
|
|
||||||
break
|
|
||||||
char = resp[0]
|
|
||||||
|
|
||||||
if char == ACK:
|
|
||||||
#print("ACK received")
|
|
||||||
sentblocks += 1
|
|
||||||
data = data[32:] # ack received, send next block
|
|
||||||
elif char == NAK: # nak received, send same block
|
|
||||||
# print("NAK received")
|
|
||||||
resend += 1
|
|
||||||
pass
|
|
||||||
else:
|
|
||||||
print("garbage received: ",char)
|
|
||||||
print(ser.read(80))
|
|
||||||
break # anything else, give up
|
|
||||||
|
|
||||||
print("{} blocks sent, {} retries".format(sentblocks, resend), end='\r')
|
|
||||||
|
|
||||||
sendchar(EOT, ser)
|
|
||||||
print()
|
|
||||||
|
|
||||||
|
|
||||||
def word_from_bytes(b):
|
|
||||||
w = b[0] << 24 | b[1] << 16 | b[2] << 8 | b[3]
|
|
||||||
return w
|
|
||||||
|
|
||||||
|
|
||||||
def read_word(ser):
|
|
||||||
b = ser.read(4)
|
|
||||||
if len(b) != 4:
|
|
||||||
return None
|
|
||||||
return word_from_bytes(b)
|
|
||||||
|
|
||||||
|
|
||||||
def serdownload(fname, ser):
|
|
||||||
resp = sendcommand(ser, b'D')
|
|
||||||
if len(resp) == 0:
|
|
||||||
print("timeout sending 'D' command")
|
|
||||||
return
|
|
||||||
|
|
||||||
sendchar(BEL, ser);
|
|
||||||
|
|
||||||
resp = ser.read(1)
|
|
||||||
if len(resp) == 0:
|
|
||||||
print("Timeout receiving size header.")
|
|
||||||
return
|
|
||||||
if resp[0] != SOH:
|
|
||||||
print("Error receiving size header.", resp[0])
|
|
||||||
return
|
|
||||||
|
|
||||||
size = read_word(ser)
|
|
||||||
cksize = read_word(ser)
|
|
||||||
if (~cksize & 0xFFFFFFFF) != size:
|
|
||||||
print("Invalid size header received.")
|
|
||||||
return
|
|
||||||
|
|
||||||
sendchar(ACK, ser)
|
|
||||||
|
|
||||||
print("File size: {} bytes".format(size))
|
|
||||||
|
|
||||||
count = size
|
|
||||||
with open(fname, "wb") as f:
|
|
||||||
while count > 0:
|
|
||||||
startbyte = ser.read(1)
|
|
||||||
if len(startbyte) == 0:
|
|
||||||
print("Timeout receiving STX.")
|
|
||||||
return
|
|
||||||
if startbyte[0] != STX:
|
|
||||||
print("Error receiving STX.", resp[0])
|
|
||||||
return
|
|
||||||
|
|
||||||
block = ser.read(32)
|
|
||||||
if len(block) != 32:
|
|
||||||
print("Error receiving block")
|
|
||||||
return
|
|
||||||
|
|
||||||
cksum = read_word(ser)
|
|
||||||
if cksum is None:
|
|
||||||
print("Error receiving block checksum")
|
|
||||||
return
|
|
||||||
|
|
||||||
mysum = checksum(block)
|
|
||||||
if cksum != mysum:
|
|
||||||
print("Checksum error, retry block")
|
|
||||||
sendchar(NAK, ser)
|
|
||||||
continue
|
|
||||||
|
|
||||||
print(".", end="", flush=True)
|
|
||||||
count -= 32
|
|
||||||
f.write(block)
|
|
||||||
sendchar(ACK, ser)
|
|
||||||
|
|
||||||
resp = ser.read(1)
|
|
||||||
if len(resp) == 0:
|
|
||||||
print("Timeout receiving EOT.")
|
|
||||||
if resp[0] != EOT:
|
|
||||||
print("Error receiving EOT.", resp[0])
|
|
||||||
|
|
||||||
print("\nEnd of transmission, {} bytes received.".format(size))
|
|
||||||
f.truncate(size)
|
|
||||||
f.close()
|
|
||||||
|
|
||||||
|
|
||||||
def mput(filenames, ser):
|
|
||||||
for f in filenames:
|
|
||||||
resp = set_filename(f, ser)
|
|
||||||
if resp is None:
|
|
||||||
return
|
|
||||||
serload_bin(f, ser)
|
|
||||||
|
|
||||||
resp = ser.read_until()
|
|
||||||
|
|
||||||
time.sleep(2)
|
|
||||||
|
|
||||||
|
|
||||||
def set_filename(f, ser):
|
|
||||||
f_encoded = f.encode('utf8')
|
|
||||||
print("Setting filename", f)
|
|
||||||
resp = commandwait(ser, b'S')
|
|
||||||
if resp is None:
|
|
||||||
return None
|
|
||||||
resp = sendcommand(ser, f_encoded + b'\r')
|
|
||||||
if not f_encoded in resp:
|
|
||||||
print("unrecognized response to filename, aborting")
|
|
||||||
return None
|
|
||||||
return resp
|
|
||||||
|
|
||||||
|
|
||||||
def getnamedfile(filename, ser):
|
|
||||||
resp = set_filename(filename, ser)
|
|
||||||
if resp is None:
|
|
||||||
return None
|
|
||||||
serdownload(filename, ser)
|
|
||||||
|
|
||||||
|
|
||||||
def putnamedfile(filename, ser):
|
|
||||||
resp = set_filename(filename, ser)
|
|
||||||
if resp is None:
|
|
||||||
return None
|
|
||||||
serload_bin(filename, ser)
|
|
||||||
print("Remote status:")
|
|
||||||
showdata(ser)
|
|
||||||
|
|
||||||
|
|
||||||
def showdata(ser):
|
|
||||||
|
|
||||||
promptseen = False
|
|
||||||
|
|
||||||
while not promptseen:
|
|
||||||
c = ser.read(1)
|
|
||||||
if c == b'>':
|
|
||||||
promptseen = True
|
|
||||||
else:
|
|
||||||
print(c.decode('utf8'), end='')
|
|
||||||
rest = ser.read(1) # read trailing space of prompt
|
|
||||||
|
|
||||||
|
|
||||||
def localdir():
|
|
||||||
result = os.walk(".")
|
|
||||||
for dirpath, dirnames, filenames in os.walk("."):
|
|
||||||
for f in filenames:
|
|
||||||
print(f)
|
|
||||||
break
|
|
||||||
|
|
||||||
|
|
||||||
def interactive(ser):
|
|
||||||
done = False
|
|
||||||
while not done:
|
|
||||||
args = input("> ").strip().split()
|
|
||||||
if len(args) > 0:
|
|
||||||
cmd = args[0]
|
|
||||||
args.pop(0)
|
|
||||||
if cmd == 'dir':
|
|
||||||
if commandwait(ser, b'Y') is None:
|
|
||||||
return
|
|
||||||
showdata(ser)
|
|
||||||
elif cmd == 'get':
|
|
||||||
if len(args) > 1:
|
|
||||||
print("exactly one argument required (filename)")
|
|
||||||
else:
|
|
||||||
getnamedfile(args[0], ser)
|
|
||||||
elif cmd == 'put':
|
|
||||||
if len(args) > 1:
|
|
||||||
print("exactly one argument required (filename)")
|
|
||||||
else:
|
|
||||||
putnamedfile(args[0], ser)
|
|
||||||
elif cmd == 'ldir':
|
|
||||||
if len(args) > 0:
|
|
||||||
print("superfluous argument")
|
|
||||||
else:
|
|
||||||
localdir()
|
|
||||||
elif cmd == 'exit' or cmd == 'x':
|
|
||||||
done = True
|
|
||||||
else:
|
|
||||||
print("Unknown command. Valid commands are: dir get ldir put exit")
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
argparser = argparse.ArgumentParser(
|
|
||||||
description='transfer files from/to the Tridora-CPU')
|
|
||||||
argparser.add_argument('-d', '--device', help='serial device', default=get_default_device())
|
|
||||||
argparser.add_argument('command', choices=['get', 'put', 'mput', 'interactive'])
|
|
||||||
argparser.add_argument('filename', nargs='*')
|
|
||||||
args = argparser.parse_args()
|
|
||||||
|
|
||||||
cmd = args.command
|
|
||||||
serial_port = args.device
|
|
||||||
filenames = args.filename
|
|
||||||
|
|
||||||
ser = serial.Serial(serial_port,115200, timeout=3)
|
|
||||||
|
|
||||||
if cmd == 'get':
|
|
||||||
serdownload(filenames[0], ser)
|
|
||||||
elif cmd == 'put':
|
|
||||||
serload_bin(filenames[0], ser)
|
|
||||||
elif cmd == 'mput':
|
|
||||||
mput(filenames, ser)
|
|
||||||
elif cmd == 'interactive':
|
|
||||||
interactive(ser)
|
|
||||||
else:
|
|
||||||
print("should not get here")
|
|
||||||
|
|
||||||
#if cmd is not None:
|
|
||||||
# ser.close()
|
|
||||||
127
utils/tdrimg.py
127
utils/tdrimg.py
|
|
@ -1,6 +1,6 @@
|
||||||
#!/usr/bin/python3
|
#!/usr/bin/python3
|
||||||
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
# vim: tabstop=8 expandtab shiftwidth=4 softtabstop=4
|
||||||
# Copyright 2021-2025 Sebastian Lederer. See the file LICENSE.md for details
|
# Copyright 2021-2024 Sebastian Lederer. See the file LICENSE.md for details
|
||||||
|
|
||||||
import struct
|
import struct
|
||||||
import sys
|
import sys
|
||||||
|
|
@ -239,7 +239,7 @@ def listvolumes(img):
|
||||||
return firstvolume
|
return firstvolume
|
||||||
|
|
||||||
|
|
||||||
def listdir(img, part, verbose=False, deleted=False):
|
def listdir(img, part, verbose=False):
|
||||||
print("Directory of {}:".format(part.name))
|
print("Directory of {}:".format(part.name))
|
||||||
slotno = 0
|
slotno = 0
|
||||||
done = False
|
done = False
|
||||||
|
|
@ -247,8 +247,6 @@ def listdir(img, part, verbose=False, deleted=False):
|
||||||
slot = getdirslot(img, part, slotno)
|
slot = getdirslot(img, part, slotno)
|
||||||
if (slot.flags & SlotFirst):
|
if (slot.flags & SlotFirst):
|
||||||
print(slot.name, slot.sizeBytes, slotno)
|
print(slot.name, slot.sizeBytes, slotno)
|
||||||
elif deleted and (slot.flags & SlotDeleted):
|
|
||||||
print(slot.name, slot.sizeBytes, slotno, slot.generation)
|
|
||||||
else:
|
else:
|
||||||
if verbose:
|
if verbose:
|
||||||
print(flags2str(slot.flags))
|
print(flags2str(slot.flags))
|
||||||
|
|
@ -274,21 +272,6 @@ def findfile(img, part, name):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def finddeleted(img, part, name, gen):
|
|
||||||
slotno = 0
|
|
||||||
done = False
|
|
||||||
while not done:
|
|
||||||
slot = getdirslot(img, part, slotno)
|
|
||||||
if slot.flags & SlotDeleted:
|
|
||||||
if slot.name == name and slot.generation == gen:
|
|
||||||
return slotno
|
|
||||||
slotno += 1
|
|
||||||
if (slot.flags & SlotEndScan) or (slotno >= part.dirSize):
|
|
||||||
done = True
|
|
||||||
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def readfile(img, part, slotno):
|
def readfile(img, part, slotno):
|
||||||
pos = part.startBlock * 512 + slotno * part.extentSize
|
pos = part.startBlock * 512 + slotno * part.extentSize
|
||||||
dirslot = getdirslot(img, part, slotno)
|
dirslot = getdirslot(img, part, slotno)
|
||||||
|
|
@ -334,24 +317,6 @@ def readfromimg(img, pathname,outfilepath):
|
||||||
f.write(data)
|
f.write(data)
|
||||||
|
|
||||||
|
|
||||||
def recoverfromimg(img, pathname, gen, outfilepath):
|
|
||||||
vol, filename = parsepath(img, pathname)
|
|
||||||
if vol is None:
|
|
||||||
return
|
|
||||||
|
|
||||||
listdir(img, vol, deleted=True)
|
|
||||||
|
|
||||||
slotno = finddeleted(img, vol, filename, gen)
|
|
||||||
if slotno is None:
|
|
||||||
print("File", filename,"not found with generation no", gen)
|
|
||||||
return
|
|
||||||
|
|
||||||
data = readfile(img, vol, slotno)
|
|
||||||
|
|
||||||
with open(outfilepath, "wb") as f:
|
|
||||||
f.write(data)
|
|
||||||
|
|
||||||
|
|
||||||
def writetoimg(img, pathname, infilepath):
|
def writetoimg(img, pathname, infilepath):
|
||||||
vol, filename = parsepath(img, pathname)
|
vol, filename = parsepath(img, pathname)
|
||||||
if vol is None:
|
if vol is None:
|
||||||
|
|
@ -372,32 +337,8 @@ def writetoimg(img, pathname, infilepath):
|
||||||
putfile(infilepath, filename, img, vol, vol.startBlock, slotno)
|
putfile(infilepath, filename, img, vol, vol.startBlock, slotno)
|
||||||
|
|
||||||
|
|
||||||
def initfs(f, partno):
|
def create_image_with_stuff():
|
||||||
part = getpartslot(f, partno)
|
imgfile = "sdcard.img"
|
||||||
partstart = part.startBlock
|
|
||||||
dir_slots = part.dirSize
|
|
||||||
extent_size = part.extentSize
|
|
||||||
slots_per_extent = extent_size // 64
|
|
||||||
reserved_slots = dir_slots // slots_per_extent
|
|
||||||
|
|
||||||
print()
|
|
||||||
print("Partition {} at {}".format(part.name, part.startBlock))
|
|
||||||
|
|
||||||
print("creating",reserved_slots, "reserved directory slots")
|
|
||||||
for a in range(0,reserved_slots):
|
|
||||||
d = createdirslot("DIR", SlotReserved, 0, 0, 0, 0, 0)
|
|
||||||
putdirslot(f, partstart, a, d)
|
|
||||||
|
|
||||||
print("creating", dir_slots - reserved_slots, "free slots")
|
|
||||||
|
|
||||||
for a in range(reserved_slots, dir_slots):
|
|
||||||
d = createdirslot("", SlotFree, 0, 0, 0, 0, 0)
|
|
||||||
putdirslot(f, partstart, a, d)
|
|
||||||
|
|
||||||
return (part, partstart, reserved_slots)
|
|
||||||
|
|
||||||
|
|
||||||
def create_image_with_stuff(imgfile):
|
|
||||||
bootimage = "../lib/coreloader.prog"
|
bootimage = "../lib/coreloader.prog"
|
||||||
dir_slots = 256
|
dir_slots = 256
|
||||||
extent_size = 8192
|
extent_size = 8192
|
||||||
|
|
@ -406,27 +347,22 @@ def create_image_with_stuff(imgfile):
|
||||||
|
|
||||||
f = open(imgfile,"w+b")
|
f = open(imgfile,"w+b")
|
||||||
|
|
||||||
b = createpart("PHYS", PartPhysical, 0, 16384, 4096, 0, 0)
|
b = createpart("PHYS", PartPhysical, 0, 12288, 4096, 0, 0)
|
||||||
#print(b)
|
#print(b)
|
||||||
f.write(b)
|
f.write(b)
|
||||||
|
|
||||||
with open(bootimage, "rb") as bf:
|
with open(bootimage, "rb") as bf:
|
||||||
bootdata = bf.read()
|
bootdata = bf.read()
|
||||||
bootBlocks = len(bootdata) // 512 + 1
|
bootBlocks = len(bootdata) // 512 + 1
|
||||||
|
|
||||||
b = createpart("BOOT", PartBoot, 16, 112, 0, 0, bootBlocks)
|
b = createpart("BOOT", PartBoot, 16, 112, 0, 0, bootBlocks)
|
||||||
f.write(b)
|
f.write(b)
|
||||||
|
|
||||||
b = createpart("Testvolume 1", PartEnabled, 128, 3968, 8192, 248)
|
b = createpart("Testvolume 1", PartEnabled, 128, 3968, 8192, 248)
|
||||||
f.write(b)
|
f.write(b)
|
||||||
|
|
||||||
b = createpart("SYSTEM", PartEnabled, 4096, 4096, 8192, 256)
|
b = createpart("SYSTEM", PartEnabled, 4096, 4096, 8192, 256)
|
||||||
f.write(b)
|
f.write(b)
|
||||||
|
|
||||||
b = createpart("Examples", PartEnabled, 8192, 4096, 8192, 256)
|
b = createpart("Examples", PartEnabled + PartLast, 8192, 4096, 8192, 256)
|
||||||
f.write(b)
|
|
||||||
|
|
||||||
b = createpart("Rogue", PartEnabled + PartLast, 12288, 4096, 8192, 256)
|
|
||||||
f.write(b)
|
f.write(b)
|
||||||
|
|
||||||
part = getpartslot(f, 2)
|
part = getpartslot(f, 2)
|
||||||
|
|
@ -535,11 +471,6 @@ def create_image_with_stuff(imgfile):
|
||||||
slotnr = putfile("../progs/editor.pas", None , f, part, partstart, slotnr)
|
slotnr = putfile("../progs/editor.pas", None , f, part, partstart, slotnr)
|
||||||
slotnr = putfile("../progs/editor.prog", None , f, part, partstart, slotnr)
|
slotnr = putfile("../progs/editor.prog", None , f, part, partstart, slotnr)
|
||||||
slotnr = putfile("../progs/xfer.prog", None , f, part, partstart, slotnr)
|
slotnr = putfile("../progs/xfer.prog", None , f, part, partstart, slotnr)
|
||||||
slotnr = putfile("../progs/recover.prog", None , f, part, partstart, slotnr)
|
|
||||||
slotnr = putfile("../progs/changemem.prog", None , f, part, partstart, slotnr)
|
|
||||||
|
|
||||||
slotnr = putfile("../lib/pcmaudio.s", None , f, part, partstart, slotnr)
|
|
||||||
slotnr = putfile("../lib/pcmaudio.inc", None , f, part, partstart, slotnr)
|
|
||||||
|
|
||||||
listdir(f, part)
|
listdir(f, part)
|
||||||
|
|
||||||
|
|
@ -575,10 +506,10 @@ def create_image_with_stuff(imgfile):
|
||||||
# slotnr = putfile("../tests/timetest.prog", None , f, part, partstart, slotnr)
|
# slotnr = putfile("../tests/timetest.prog", None , f, part, partstart, slotnr)
|
||||||
|
|
||||||
slotnr = putfile("../tests/readtest.pas", None , f, part, partstart, slotnr)
|
slotnr = putfile("../tests/readtest.pas", None , f, part, partstart, slotnr)
|
||||||
#slotnr = putfile("../tests/readtest.prog", None , f, part, partstart, slotnr)
|
slotnr = putfile("../tests/readtest.prog", None , f, part, partstart, slotnr)
|
||||||
|
|
||||||
slotnr = putfile("../tests/readchartest.pas", None , f, part, partstart, slotnr)
|
slotnr = putfile("../tests/readchartest.pas", None , f, part, partstart, slotnr)
|
||||||
#slotnr = putfile("../tests/readchartest.prog", None , f, part, partstart, slotnr)
|
slotnr = putfile("../tests/readchartest.prog", None , f, part, partstart, slotnr)
|
||||||
|
|
||||||
# slotnr = putfile("cchangetest.pas", None , f, part, partstart, slotnr)
|
# slotnr = putfile("cchangetest.pas", None , f, part, partstart, slotnr)
|
||||||
# slotnr = putfile("cchangetest.prog", None , f, part, partstart, slotnr)
|
# slotnr = putfile("cchangetest.prog", None , f, part, partstart, slotnr)
|
||||||
|
|
@ -588,13 +519,16 @@ def create_image_with_stuff(imgfile):
|
||||||
slotnr = putfile("../tests/test133.pas", None , f, part, partstart, slotnr)
|
slotnr = putfile("../tests/test133.pas", None , f, part, partstart, slotnr)
|
||||||
# slotnr = putfile("../tests/test133.prog", None , f, part, partstart, slotnr)
|
# slotnr = putfile("../tests/test133.prog", None , f, part, partstart, slotnr)
|
||||||
|
|
||||||
# slotnr = putfile("../tests/test159.pas", None , f, part, partstart, slotnr)
|
slotnr = putfile("../tests/test159.pas", None , f, part, partstart, slotnr)
|
||||||
# slotnr = putfile("../tests/test159.prog", None , f, part, partstart, slotnr)
|
# slotnr = putfile("../tests/test159.prog", None , f, part, partstart, slotnr)
|
||||||
|
|
||||||
slotnr = putfile("../tests/umlaut.pas", None , f, part, partstart, slotnr)
|
slotnr = putfile("../tests/umlaut.pas", None , f, part, partstart, slotnr)
|
||||||
|
|
||||||
slotnr = putfile("../examples/rtpair.pas", None , f, part, partstart, slotnr)
|
slotnr = putfile("../examples/rtpair.pas", None , f, part, partstart, slotnr)
|
||||||
|
|
||||||
|
slotnr = putfile("../examples/5cubes.pas", None , f, part, partstart, slotnr)
|
||||||
|
# slotnr = putfile("../examples/5cubes.prog", None , f, part, partstart, slotnr)
|
||||||
|
|
||||||
slotnr = putfile("../examples/3dcube.pas", None , f, part, partstart, slotnr)
|
slotnr = putfile("../examples/3dcube.pas", None , f, part, partstart, slotnr)
|
||||||
|
|
||||||
slotnr = putfile("../examples/conway.pas", None , f, part, partstart, slotnr)
|
slotnr = putfile("../examples/conway.pas", None , f, part, partstart, slotnr)
|
||||||
|
|
@ -603,33 +537,11 @@ def create_image_with_stuff(imgfile):
|
||||||
|
|
||||||
slotnr = putfile("../examples/lines.pas", None , f, part, partstart, slotnr)
|
slotnr = putfile("../examples/lines.pas", None , f, part, partstart, slotnr)
|
||||||
|
|
||||||
slotnr = putfile("../examples/pcmtest2.pas", None , f, part, partstart, slotnr)
|
slotnr = putfile("../examples/viewpict.pas", None , f, part, partstart, slotnr)
|
||||||
|
# slotnr = putfile("viewpict.prog", None , f, part, partstart, slotnr)
|
||||||
slotnr = putfile("../examples/pictviewer.pas", None , f, part, partstart, slotnr)
|
slotnr = putfile("../examples/ara.pict", "ara.pict" , f, part, partstart, slotnr)
|
||||||
slotnr = putfile("../examples/Toco_Toucan.pict", None , f, part, partstart, slotnr)
|
slotnr = putfile("../examples/shinkansen.pict", "shinkansen.pict" , f, part, partstart, slotnr)
|
||||||
slotnr = putfile("../examples/shinkansen.pict", None , f, part, partstart, slotnr)
|
slotnr = putfile("../examples/snow_leopard.pict", "snow_leopard.pict" , f, part, partstart, slotnr)
|
||||||
slotnr = putfile("../examples/snow_leopard.pict", None , f, part, partstart, slotnr)
|
|
||||||
slotnr = putfile("../examples/ADDS-Envoy-620.pict", None , f, part, partstart, slotnr)
|
|
||||||
|
|
||||||
slotnr = putfile("../examples/benchmarks.pas", None , f, part, partstart, slotnr)
|
|
||||||
|
|
||||||
slotnr = putfile("../examples/animate.pas", None , f, part, partstart, slotnr)
|
|
||||||
slotnr = putfile("../examples/graphbench.pas", None , f, part, partstart, slotnr)
|
|
||||||
slotnr = putfile("../examples/sprites.inc", None , f, part, partstart, slotnr)
|
|
||||||
slotnr = putfile("../examples/sprites.s", None , f, part, partstart, slotnr)
|
|
||||||
slotnr = putfile("../examples/background.pict", None , f, part, partstart, slotnr)
|
|
||||||
slotnr = putfile("../examples/walking.sprt", None , f, part, partstart, slotnr)
|
|
||||||
slotnr = putfile("../examples/rocket.sprt", None , f, part, partstart, slotnr)
|
|
||||||
slotnr = putfile("../examples/sprite-testcard.sprt", None , f, part, partstart, slotnr)
|
|
||||||
slotnr = putfile("../examples/tiles.inc", None , f, part, partstart, slotnr)
|
|
||||||
slotnr = putfile("../examples/tiles.s", None , f, part, partstart, slotnr)
|
|
||||||
|
|
||||||
listdir(f, part)
|
|
||||||
|
|
||||||
part, partstart, slotnr = initfs(f, 5)
|
|
||||||
slotnr = putfile("../rogue/rogue.init", None, f, part, partstart, slotnr)
|
|
||||||
slotnr = putfile("../rogue/rogue.message", None, f, part, partstart, slotnr)
|
|
||||||
slotnr = putfile("../rogue/rogue.prog", None, f, part, partstart, slotnr)
|
|
||||||
|
|
||||||
listdir(f, part)
|
listdir(f, part)
|
||||||
|
|
||||||
|
|
@ -643,14 +555,11 @@ if __name__ == "__main__":
|
||||||
if sys.argv[1] == "get":
|
if sys.argv[1] == "get":
|
||||||
f = open(sys.argv[2], "rb")
|
f = open(sys.argv[2], "rb")
|
||||||
readfromimg(f, sys.argv[3], sys.argv[4])
|
readfromimg(f, sys.argv[3], sys.argv[4])
|
||||||
elif sys.argv[1] == "recover":
|
|
||||||
f = open(sys.argv[2], "rb")
|
|
||||||
recoverfromimg(f, sys.argv[3], int(sys.argv[4]), sys.argv[5])
|
|
||||||
elif sys.argv[1] == "put":
|
elif sys.argv[1] == "put":
|
||||||
imgfile = open(sys.argv[2], "r+b")
|
imgfile = open(sys.argv[2], "r+b")
|
||||||
infilepath = sys.argv[3]
|
infilepath = sys.argv[3]
|
||||||
destfilename = sys.argv[4]
|
destfilename = sys.argv[4]
|
||||||
writetoimg(imgfile, destfilename, infilepath)
|
writetoimg(imgfile, destfilename, infilepath)
|
||||||
elif sys.argv[1] == "createimg":
|
elif sys.argv[1] == "createimg":
|
||||||
create_image_with_stuff(sys.argv[2])
|
create_image_with_stuff()
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
|
||||||
|
|
@ -1,29 +0,0 @@
|
||||||
import sys
|
|
||||||
import random, struct
|
|
||||||
import wave
|
|
||||||
|
|
||||||
freq = 16000
|
|
||||||
BIAS = 32768
|
|
||||||
def convert(srcpath, destpath):
|
|
||||||
outdata = bytearray()
|
|
||||||
with wave.open(srcpath, mode="rb") as f:
|
|
||||||
params = f.getparams()
|
|
||||||
print(params.nchannels, params.sampwidth, params.framerate)
|
|
||||||
|
|
||||||
frames = f.readframes(2*1024*1024)
|
|
||||||
for i in range(0, len(frames), 2):
|
|
||||||
v = int.from_bytes(frames[i:i+2], "little", signed=True)
|
|
||||||
v += BIAS
|
|
||||||
hi = (v & 0xFF00) >> 8
|
|
||||||
lo = (v & 0x00FF)
|
|
||||||
outdata.append(hi)
|
|
||||||
outdata.append(lo)
|
|
||||||
|
|
||||||
with open(destpath, mode="wb") as f:
|
|
||||||
f.write(outdata)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
sourcefilename = sys.argv[1]
|
|
||||||
destfilename = sys.argv[2]
|
|
||||||
convert(sourcefilename, destfilename)
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue