From c0e7afd79d3804874499f822acae7b6d2ffcfe6d Mon Sep 17 00:00:00 2001 From: Luxferre <3335173-suborg@users.noreply.gitlab.com> Date: Fri, 29 Jul 2022 00:12:29 +0300 Subject: [PATCH] revamped pixel output draft --- README.md | 10 ++++++---- tal-lib/font.tal | 23 +++++------------------ web/esop-ext.js | 19 ++++++++++++++++++- 3 files changed, 29 insertions(+), 23 deletions(-) diff --git a/README.md b/README.md index 4010acd..a5cef45 100644 --- 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 index 4ca4bd1..0a42f53 100644 --- 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 index 8bda41e..557cf03 100644 --- 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<