Extended write hooks and debugged sound

This commit is contained in:
Luxferre
2022-07-28 22:55:10 +03:00
parent 1d68fc8d4a
commit 61018ab06d
5 changed files with 82 additions and 30 deletions
+1 -1
View File
@@ -53,7 +53,7 @@ Implementation note: direct writing to or reading from the control block memory
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.
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`).
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.
Standard input/output ports are not supported.
+46
View File
@@ -1,9 +1,55 @@
( ESOP stdlib )
|00 @Control [ &framevec $2 &input $2 &random $1 &status $1 &sound $1 &syscall $1 ]
( byte to short )
( x -- 00 x )
%BTS { #00 SWP }
( screen is #54 x #30 )
%SETSCRVEC { .Control/framevec DEO2 }
%RND { .Control/random DEI }
%STACKTRACE { #ff .Control/random DEO }
%SYS { .Control/syscall DEO }
%INKEY { .Control/input DEI2 }
%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
BRK
@on-frame
DUP SND
INC
( #10 #12 PXL )
BRK
@putc
JMP2r
@draw-str ( s* -> )
&loop LDAk #00 EQU ,&eof JCN ( did we reach \0 ? )
LDAk ;putc JSR2 INC2 ,&loop JMP ( no so emit a char and repeat )
&eof POP2 JMP2r ( yes so return )
( nanofont glyphs for ESOP, courtesy of Michaelangel007 )
+21 -15
View File
@@ -44,13 +44,13 @@ function ESOPExtensions() {
//setup screen renderer
function renderScreen() {
var vram = vm.getram(vramOffset, vramSize),
vdata = ctx.getImageData(0,0,width,height),
vdata = ctx.createImageData(width,height),
ppos, pval, vbval, i, j
for(i=0;i<vRamSize;i++) {
for(i=0;i<vramSize;i++) {
vbval = vram[i]
for(j=0;j<8;j++) { //iterate from highest to lowest
ppos = ((i<<3) + j) << 2
pval = (vbval>>>(7-j))&1 ? 255 : 0
pval = (vbval>>>(7-j))&1 ? 0 : 0xee
vdata.data[ppos] = pval
vdata.data[ppos+1] = pval
vdata.data[ppos+2] = pval
@@ -129,18 +129,24 @@ function ESOPExtensions() {
function setupAudio(vm, actx) {
var osc = null //keep the existing oscillator reference here
vm.setdev(6,0)
vm.setWriteHook(6, function(port, portval) {
if(osc && !portval) { //stop the note
osc.stop()
osc.disconnect()
osc = null
}
else if(portval < sfl) { //start the note
osc = actx.createOscillator()
osc.type = 'square'
osc.frequency = soundFreqs[portval]
osc.connect(actx.destination)
osc.start(0)
vm.setWriteHook(6, function(port, portval, prev) {
if(portval !== prev) {
if(osc && !portval) { //stop the note
osc.stop()
osc.disconnect()
osc = null
}
if(portval && portval < sfl) { //start the note
if(osc)
osc.frequency.value = soundFreqs[portval]
else {
osc = actx.createOscillator()
osc.type = 'square'
osc.connect(actx.destination)
osc.frequency.value = soundFreqs[portval]
osc.start(0)
}
}
}
})
}
+2 -1
View File
@@ -2,7 +2,7 @@
function main() {
var devCfg = {
audio: window.audioContext || window.webkitAudioContext,
audio: null,
canvas: document.getElementById('C') //JS-specific implementation canvas DOM reference
}
@@ -13,6 +13,7 @@ function main() {
rdr.onload = function() {
var vm = UxnCore()
var ext = ESOPExtensions()
devCfg.audio = new (window.AudioContext || window.webkitAudioContext)
vm.boot()
ext.setup(vm, devCfg)
vm.load(new Uint8Array(rdr.result))
+12 -13
View File
@@ -26,14 +26,9 @@ function UxnCore() {
//helper methods
function trapout(errcode) { //error reporting with vector execution
var vec = (mem.dev[0] << 8) | mem.dev[1]
if(vec)
uxnstart(vec)
else {
console.error('Error code: '+errcode+' at instruction #'+pc)
console.log('Working stack: ', mem.wst.dat)
console.log('Return stack: ', mem.rst.dat)
}
console.error('Error code: '+errcode+' at instruction #'+pc)
console.log('Working stack: ', mem.wst.dat)
console.log('Return stack: ', mem.rst.dat)
pc = 0
}
@@ -60,18 +55,22 @@ function UxnCore() {
function PEEK(x) {return bs ? PEEK16(x) : mem.ram[x]}
function DEVR(x) {if(x in devReadHooks) devReadHooks[x]();return bs ? (mem.dev[x] << 8)|mem.dev[x+1] : mem.dev[x]}
function DEVW(x, y) {
var p, p2
if(bs) {
p = mem.dev[x]
p2 = mem.dev[x+1]
mem.dev[x] = y>>8
if(x in devWriteHooks)
devWriteHooks[x](x, mem.dev[x])
devWriteHooks[x](x, mem.dev[x], p)
mem.dev[x+1] = y&255
if((x+1) in devWriteHooks)
devWriteHooks[x+1](x+1, mem.dev[x+1])
devWriteHooks[x+1](x+1, mem.dev[x+1], p2)
}
else {
p = mem.dev[x]
mem.dev[x] = y
if(x in devWriteHooks)
devWriteHooks[x](x, y)
devWriteHooks[x](x, y, p)
}
}
@@ -80,7 +79,7 @@ function UxnCore() {
function uxnstart(startaddr, vmTrace) {
pc = startaddr & 65535
var instr, src, dst, a, b, c, tmpTrace = !!vmTrace
if(!pc || mem.dev[0x0f]) {
if(!pc) {
this.active = false
return 0
}
@@ -132,7 +131,7 @@ function UxnCore() {
case 0x18: /* ADD */ a = POP(src); b = POP(src); PUSH(src, b + a); break;
case 0x19: /* SUB */ a = POP(src); b = POP(src); PUSH(src, b - a); break;
case 0x1a: /* MUL */ a = POP(src); b = POP(src); PUSH(src, b * a); break;
case 0x1b: /* DIV */ a = POP(src); b = POP(src); if(!a) trapout(3); PUSH(src, b / a); break;
case 0x1b: /* DIV */ a = POP(src); b = POP(src); if(!a) trapout(3); PUSH(src, 0|(b / a)); break;
case 0x1c: /* AND */ a = POP(src); b = POP(src); PUSH(src, b & a); break;
case 0x1d: /* ORA */ a = POP(src); b = POP(src); PUSH(src, b | a); break;
case 0x1e: /* EOR */ a = POP(src); b = POP(src); PUSH(src, b ^ a); break;