commit c0e7afd79d3804874499f822acae7b6d2ffcfe6d
parent 61018ab06d16db370386948d77fc40a98c6e578d
Author: Luxferre <3335173-suborg@users.noreply.gitlab.com>
Date: Fri, 29 Jul 2022 00:12:29 +0300
revamped pixel output draft
Diffstat:
3 files changed, 29 insertions(+), 23 deletions(-)
diff --git a/README.md b/README.md
@@ -35,13 +35,13 @@ Unlike Uxn/Varvara or Uxn/SPARTA, Uxn/ESOP only exposes the control block ports
In Uxntal, the ESOP's control block would be described as follows:
```
-|00 @Control [ &framevec $2 &input $2 &random $1 &status $1 &sound $1 &syscall $1 ]
+|00 @Control [ &framevec $2 &io $2 &random $1 &status $1 &sound $1 &syscall $1 ]
```
The fields of the control block are:
- Frame vector (`00-01`) - the port to set the vector to be run on each frame (60 frames per second);
-- Input (`02-03`) - the port to read input status bits of every key on the keypad;
+- Input/output (`02-03`) - the port to read input status bits of every key on the keypad and to output pixels at given coordinates;
- Random/debug port (`04`) - the port to trace debug information on output and retrieve a random byte value on input;
- Status port (`05`) - the port to get the information on battery and get/set screen brightness level;
- Sound port (`06`) - the port to perform mono audio beeper operations;
@@ -51,15 +51,17 @@ Implementation note: direct writing to or reading from the control block memory
## Screen output
-All the 4032 pixels of 84x48 screen are allocated in the 504-byte video memory of ESOP (`#fe00-#fff7`) in the left-to-right, top-to-bottom, high-to-low order. To output a pixel at the given coordinates, the app must calculate the appropriate byte position itself.
+All the 4032 pixels of 84x48 screen are allocated in the 504-byte video memory of ESOP (`#fe00-#fff7`) in the left-to-right, top-to-bottom, high-to-low order. To output a pixel at the given coordinates using memory manipulation routines, the app must calculate the appropriate byte position itself. This process is made easier by reusing I/O port `02-03` with the `DEO2` instruction where you can directly pass X and Y coordinates of the pixel.
The actual screen contents get updated 60 times per second according to the video memory. Before this process, the frame vector is run, if set in the corresponding control port (`00-01`). All graphics operations must be performed within this frame vector.
+Due to shared nature of the I/O device port, the handler responsible for pixel output in the ESOP implementaion must preserve the input state between port write calls, i.e. save it before the processing and restore afterwards.
+
Standard input/output ports are not supported.
## Keypad input
-The 16 bits of the input ports (`02` and `03`) have the following mapping:
+When in input mode, the 16 bits of the input ports (`02` and `03`) have the following mapping:
Bit|15 |14 |13|12|11|10|9|8|7|6|5|4|3|2|1|0
---|---|---|--|--|--|--|-|-|-|-|-|-|-|-|-|-
diff --git a/tal-lib/font.tal b/tal-lib/font.tal
@@ -1,6 +1,6 @@
( ESOP stdlib )
-|00 @Control [ &framevec $2 &input $2 &random $1 &status $1 &sound $1 &syscall $1 ]
+|00 @Control [ &framevec $2 &io $2 &random $1 &status $1 &sound $1 &syscall $1 ]
( byte to short )
( x -- 00 x )
@@ -12,36 +12,23 @@
%RND { .Control/random DEI }
%STACKTRACE { #ff .Control/random DEO }
%SYS { .Control/syscall DEO }
-%INKEY { .Control/input DEI2 }
+%INKEY { .Control/io DEI2 }
+%PXL { .Control/io DEO2 }
%DBG { #20 SYS SYS }
%SND { .Control/sound DEO }
-( x y -- ref* )
-%COORD { BTS ROT BTS SWP2 #0054 MUL2 ADD2 }
-( x y -- bitshift byteptr* )
-%PXLOFFSET { COORD DUP2 #03 SFT2 DUP2 #30 SFT2 ROT2 SWP2 SUB2 SWP POP ROT #fe00 ADD2 }
-
-( x y -- )
-%PXL { PXLOFFSET DUP2 LDA #01 ROT #40 SFT SFT ORA ROT ROT STA }
-
( subtract #20 from the ASCII code and you get the offset from the nanofont label )
%CHAR-TO-NF { #20 SUB ;nanofont ADD }
|0100
- #03 #02 #01
- ROT
- DBG DBG DBG
;on-frame SETSCRVEC
- #30
+ #10 #12
BRK
@on-frame
- DUP SND
- INC
- ( #10 #12 PXL )
+ DUP2 INC PXL
BRK
-
@putc
JMP2r
diff --git a/web/esop-ext.js b/web/esop-ext.js
@@ -39,8 +39,25 @@ function ESOPExtensions() {
height = 48,
vramOffset = vm.videoMemOffset,
vramSize = vm.videoMemSize,
- ctx = cnv.getContext('2d', {alpha: false})
+ ctx = cnv.getContext('2d', {alpha: false}),
+ xval = null, yval = null
ctx.globalAlpha = 1
+ //setup pixel drawing ports
+ function pixelHook(port, coord, prev) {
+ if(port === 2) xval = coord
+ else if(port === 3) yval = coord
+ if(xval !== null && yval !== null) { //both coordinates set, update the pixel
+ var pxlOffset = yval * width + xval,
+ byteOffset = pxlOffset >>> 3,
+ bitOffset = 7 - pxlOffset + (byteOffset << 3),
+ vramvalue = vm.getram(vramOffset + byteOffset, 1)[0]
+ vm.setram(vramOffset + byteOffset, vramvalue | (1<<bitOffset))
+ xval = yval = null
+ }
+ vm.setdev(port, prev) //preserve the input value
+ }
+ vm.setWriteHook(2, pixelHook) //X
+ vm.setWriteHook(3, pixelHook) //Y
//setup screen renderer
function renderScreen() {
var vram = vm.getram(vramOffset, vramSize),