Merge remote-tracking branch 'origin/main' into android

This commit is contained in:
Sigrid Solveig Haflínudóttir 2022-01-05 22:55:23 +01:00
commit 544d2f2a86
10 changed files with 314 additions and 73 deletions

View File

@ -14,6 +14,8 @@ then
echo "Formatting.."
clang-format -i src/uxn.h
clang-format -i src/uxn.c
clang-format -i src/devices/system.h
clang-format -i src/devices/system.c
clang-format -i src/devices/screen.h
clang-format -i src/devices/screen.c
clang-format -i src/devices/audio.h
@ -62,8 +64,8 @@ fi
echo "Building.."
${CC} ${CFLAGS} src/uxnasm.c -o bin/uxnasm
${CC} ${CFLAGS} ${CORE} src/devices/file.c src/devices/mouse.c src/devices/controller.c src/devices/screen.c src/devices/audio.c src/uxnemu.c ${UXNEMU_LDFLAGS} -o bin/uxnemu
${CC} ${CFLAGS} ${CORE} src/devices/file.c src/uxncli.c -o bin/uxncli
${CC} ${CFLAGS} ${CORE} src/devices/system.c src/devices/file.c src/devices/mouse.c src/devices/controller.c src/devices/screen.c src/devices/audio.c src/uxnemu.c ${UXNEMU_LDFLAGS} -o bin/uxnemu
${CC} ${CFLAGS} ${CORE} src/devices/system.c src/devices/file.c src/uxncli.c -o bin/uxncli
if [ -d "$HOME/bin" ]
then

View File

@ -22,9 +22,9 @@
( devices )
|00 @System &vector $2 &wst $1 &rst $1 &pad $4 &r $2 &g $2 &b $2 &debug $1 &halt $1
|00 @System &vector $2 &wst $1 &rst $1 &eaddr $2 &ecode $1 &pad $1 &r $2 &g $2 &b $2 &debug $1 &halt $1
|10 @Console &vector $2 &read $1 &pad $5 &write $1 &error $1
|20 @Screen &vector $2 &width $2 &height $2 &auto $1 &pad $1 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1
|20 @Screen &vector $2 &width $2 &height $2 &auto $1 &pad $1 &x $2 &y $2 &addr $2 &pixel $1 &sprite $1
|30 @Audio0 &vector $2 &position $2 &output $1 &pad $3 &adsr $2 &length $2 &addr $2 &volume $1 &pitch $1
|40 @Audio1 &vector $2 &position $2 &output $1 &pad $3 &adsr $2 &length $2 &addr $2 &volume $1 &pitch $1
|50 @Audio2 &vector $2 &position $2 &output $1 &pad $3 &adsr $2 &length $2 &addr $2 &volume $1 &pitch $1

View File

@ -0,0 +1,16 @@
( devices )
|00 @System &vector $2 &wst $1 &rst $1 &eaddr $2 &ecode $1 &pad $1 &r $2 &g $2 &b $2 &debug $1 &halt $1
|10 @Console &vector $2 &read $1 &pad $5 &write $1 &error $1
( program )
|0100 @Reset ( -> )
~projects/library/debugger.tal
#0123 #4567 #89ab #cdef
LIT2r 1234 LIT2r 5678 LIT2r 9abc LIT2r def0
( BREAKPOINT )
( LIT2r 0000 DIVr )
&loop INCk ,&loop JMP
BRK

View File

@ -0,0 +1,180 @@
( in-Uxn debugger )
( To use, include this file just before the BRK in the program reset routine, e.g.:
|0100 ( -> )
( theme )
#0fe5 .System/r DEO2
#0fc5 .System/g DEO2
#0f25 .System/b DEO2
~projects/library/debugger.tal
BRK
The debugger will catch stack errors that arise after that point.
)
%BREAKPOINT { LIT2r :debug JSR2r }
@debug-start
;debug-vector .System/vector DEO2
;debug-end JMP2
@debug ( pc* -- )
#0001 SUB2 .System/eaddr DEO2
.System/ecode DEIk #f8 AND #06 EOR SWP DEO
,debug-vector/main JMP
@debug-vector ( -> )
STH STH STH STH ( <- only run in case of working stack overflow )
&main
( flush the working stack )
.System/wst DEI ;debug-wst/ptr STA
&flush-wst
.System/wst DEI #00 EQU ,&end-flush-wst JCN
#00 .System/wst DEI #0002 SUB2 ;debug-wst/dat ADD2 STA
,&flush-wst JMP
&end-flush-wst
( in case of working stack overflow, we need to append the four return stack bytes )
.System/ecode DEI #02 NEQ ,&skip-wst-append JCN
#00 ;debug-wst/ptr LDAk ( 00 ptr-hi ptr-lo ptr / ... z y x w )
DUP #04 ADD OVR2 STA
ROT ROT ADD2 ( start* / ... z y x w )
INC2 DUP2 #0004 ADD2 SWP2 ( end* start* / ... z y x w )
&loop
DUP2 STHr ROT ROT STA
INC2
GTH2k ,&loop JCN
POP2 POP2
&skip-wst-append
( flush the return stack )
.System/rst DEI ;debug-rst/ptr STA
&flush-rst
.System/rst DEI #00 EQU ,&end-flush-rst JCN
STHr #00 .System/rst DEI ;debug-rst/dat ADD2 STA
,&flush-rst JMP
&end-flush-rst
( Version 0.1 functionality: print the error and exit )
;debug-print-error JSR2
#01 .System/halt DEO
BRK
@debug-print-opcode ( instr -- )
DUP ,&not-brk JCN
POP ;&brk-msg ;debug-print JMP2 ( tail call )
&brk-msg "BRK 00
&not-brk
#00 OVR #1f AND #03 MUL ;&opcode-names ADD2 ( instr addr* )
LDAk .Console/write DEO INC2
LDAk .Console/write DEO INC2
LDA .Console/write DEO
DUP #1f AND ,&not-lit JCN
#7f AND
&not-lit
DUP #20 AND #00 EQU ,&not-2 JCN
LIT '2 .Console/write DEO
&not-2
DUP #80 AND #00 EQU ,&not-k JCN
LIT 'k .Console/write DEO
&not-k
#40 AND #00 EQU ,&not-r JCN
LIT 'r .Console/write DEO
&not-r
JMP2r
&opcode-names
"LITINCPOPDUPNIPSWPOVRROT
"EQUNEQGTHLTHJMPJCNJSRSTH
"LDZSTZLDRSTRLDASTADEIDEO
"ADDSUBMULDIVANDORAEORSFT
@debug-print ( addr* -- )
LDAk #00 EQU ,&end JCN
LDAk .Console/write DEO
INC2
,debug-print JMP
&end POP2 JMP2r
@debug-print-error
;&halted-msg ,debug-print JSR
#00 .System/ecode DEI #07 AND #20 SFT2 ;&messages-table ADD2
LDA2k ,debug-print JSR
INC2 INC2 LDA2 ,debug-print JSR
;&executing-msg ,debug-print JSR
.System/eaddr DEI2 LDA ;debug-print-opcode JSR2
;&at-msg ,debug-print JSR
.System/eaddr DEI2 ;debug-print-hex-short JSR2
#0a .Console/write DEO
;&wst-msg ,debug-print JSR
;&contents-msg ,debug-print JSR
;debug-wst ;debug-print-stack JSR2
#0a .Console/write DEO
;&rst-msg ,debug-print JSR
;&contents-msg ,debug-print JSR
;debug-rst ;debug-print-stack JSR2
#0a .Console/write DEO
JMP2r
&messages-table
:&wst-msg :&underflow-msg
:&rst-msg :&underflow-msg
:&wst-msg :&overflow-msg
:&rst-msg :&overflow-msg
:&wst-msg :&divzero-msg
:&rst-msg :&divzero-msg
:&userdef-msg :&breakpoint-msg
:&userdef-msg :&custom-msg
&halted-msg "Halted: 2000 ( #0002, at 0x0100 )
&wst-msg "Working-stack 2000
&rst-msg "Return-stack 2000
&userdef-msg "User-defined 2000
&underflow-msg "underflow 00
&overflow-msg "overflow 00
&divzero-msg "division 20 "by 20 "zero 00
&breakpoint-msg "breakpoint 00
&custom-msg "custom 20 "error 00
&executing-msg 20 "executing 2000
&at-msg 20 "at 20 "0x 00
&contents-msg "contents: 00
@debug-print-hex-short ( value* -- )
SWP ,debug-print-hex-byte JSR
( fall through )
@debug-print-hex-byte ( value -- )
DUP #04 SFT ,debug-print-hex-nibble JSR
#0f AND
( fall through )
@debug-print-hex-nibble ( value -- )
#30 ADD DUP #39 GTH #27 MUL ADD
.Console/write DEO
JMP2r
@debug-print-stack ( addr* -- )
LDAk ,&not-empty JCN
POP2 ;&empty-msg ;debug-print JMP2 ( tail call )
&not-empty
LDAk STH INC2 ( dat* / count )
&loop
STHkr #00 EQU ,&end JCN
#20 .Console/write DEO
LDAk ,debug-print-hex-byte JSR
INC2
LITr 01 SUBr
,&loop JMP
&end
POP2 POPr
JMP2r
&empty-msg 20 "(empty) 00
@debug-wst &ptr $1 &dat $ff
@debug-rst &ptr $1 &dat $ff
@debug-end

63
src/devices/system.c Normal file
View File

@ -0,0 +1,63 @@
#include "../uxn.h"
#include "system.h"
#include <stdio.h>
/*
Copyright (c) 2022 Devine Lu Linvega, Andrew Alderwick
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE.
*/
static const char *errors[] = {
"Working-stack underflow",
"Return-stack underflow",
"Working-stack overflow",
"Return-stack overflow",
"Working-stack division by zero",
"Return-stack division by zero"};
int
uxn_halt(Uxn *u, Uint8 error, Uint16 addr)
{
Device *d = &u->dev[0];
Uint16 vec = d->vector;
if(vec) {
d->vector = 0; /* need to rearm to run System/vector again */
DEVPOKE16(0x4, addr);
d->dat[0x6] = error;
if(error != 2) /* working stack overflow has special treatment */
vec += 0x0004;
return uxn_eval(u, vec);
}
fprintf(stderr, "Halted: %s#%04x, at 0x%04x\n", errors[error], u->ram[addr], addr);
return 0;
}
/* IO */
Uint8
system_dei(Device *d, Uint8 port)
{
switch(port) {
case 0x2: return d->u->wst.ptr;
case 0x3: return d->u->rst.ptr;
default: return d->dat[port];
}
}
void
system_deo(Device *d, Uint8 port)
{
switch(port) {
case 0x1: DEVPEEK16(d->vector, 0x0); break;
case 0x2: d->u->wst.ptr = d->dat[port]; break;
case 0x3: d->u->rst.ptr = d->dat[port]; break;
default: system_deo_special(d, port);
}
}

14
src/devices/system.h Normal file
View File

@ -0,0 +1,14 @@
/*
Copyright (c) 2022 Devine Lu Linvega, Andrew Alderwick
Permission to use, copy, modify, and distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE.
*/
Uint8 system_dei(Device *d, Uint8 port);
void system_deo(Device *d, Uint8 port);
void system_deo_special(Device *d, Uint8 port);

View File

@ -17,12 +17,11 @@ WITH REGARD TO THIS SOFTWARE.
pc: program counter. sp: ptr to src stack ptr. kptr: "keep" mode copy of src stack ptr.
x,y: macro in params. d: macro in device. j,k,dev: macro temp variables. o: macro out param. */
#define FAULT(s, n) { errcode = n * 2 + (s == &u->rst); goto fault; }
#define PUSH8(s, x) { if(s->ptr == 0xff) { FAULT(s, 2) } s->dat[s->ptr++] = (x); }
#define PUSH16(s, x) { if((j = s->ptr) >= 0xfe) { FAULT(s, 2) } k = (x); s->dat[j] = k >> 8; s->dat[j + 1] = k; s->ptr = j + 2; }
#define PUSH8(s, x) { if(s->ptr == 0xff) { errcode = 2; goto err; } s->dat[s->ptr++] = (x); }
#define PUSH16(s, x) { if((j = s->ptr) >= 0xfe) { errcode = 2; goto err; } k = (x); s->dat[j] = k >> 8; s->dat[j + 1] = k; s->ptr = j + 2; }
#define PUSH(s, x) { if(bs) { PUSH16(s, (x)) } else { PUSH8(s, (x)) } }
#define POP8(o) { if(!(j = *sp)) { FAULT(src, 1) } o = (Uint16)src->dat[--j]; *sp = j; }
#define POP16(o) { if((j = *sp) <= 1) { FAULT(src, 1) } o = src->dat[j - 1]; o += src->dat[j - 2] << 8; *sp = j - 2; }
#define POP8(o) { if(!(j = *sp)) { errcode = 0; goto err; } o = (Uint16)src->dat[--j]; *sp = j; }
#define POP16(o) { if((j = *sp) <= 1) { errcode = 0; goto err; } o = src->dat[j - 1]; o += src->dat[j - 2] << 8; *sp = j - 2; }
#define POP(o) { if(bs) { POP16(o) } else { POP8(o) } }
#define POKE(x, y) { if(bs) { u->ram[(x)] = (y) >> 8; u->ram[(x) + 1] = (y); } else { u->ram[(x)] = y; } }
#define PEEK16(o, x) { o = (u->ram[(x)] << 8) + u->ram[(x) + 1]; }
@ -90,7 +89,7 @@ uxn_eval(Uxn *u, Uint16 pc)
case 0x18: /* ADD */ POP(a) POP(b) PUSH(src, b + a) break;
case 0x19: /* SUB */ POP(a) POP(b) PUSH(src, b - a) break;
case 0x1a: /* MUL */ POP(a) POP(b) PUSH(src, (Uint32)b * a) break;
case 0x1b: /* DIV */ POP(a) POP(b) if(a == 0) { FAULT(src, 3) } PUSH(src, b / a) break;
case 0x1b: /* DIV */ POP(a) POP(b) if(a == 0) { errcode = 4; goto err; } PUSH(src, b / a) break;
case 0x1c: /* AND */ POP(a) POP(b) PUSH(src, b & a) break;
case 0x1d: /* ORA */ POP(a) POP(b) PUSH(src, b | a) break;
case 0x1e: /* EOR */ POP(a) POP(b) PUSH(src, b ^ a) break;
@ -99,8 +98,11 @@ uxn_eval(Uxn *u, Uint16 pc)
}
return 1;
fault:
return uxn_halt(u, errcode >> 1, (errcode & 1) == 0 ? "Working-stack" : "Return-stack", pc - 1);
err:
/* set 1 in errcode if it involved the return stack instead of the working stack */
/* (stack overflow & ( opcode was STH / JSR )) ^ Return Mode */
errcode |= ((errcode >> 1 & ((instr & 0x1e) == 0x0e)) ^ instr >> 6) & 1;
return uxn_halt(u, errcode, pc - 1);
}
/* clang-format on */

View File

@ -45,5 +45,5 @@ typedef struct Uxn {
int uxn_boot(Uxn *c, Uint8 *memory);
int uxn_eval(Uxn *u, Uint16 pc);
int uxn_halt(Uxn *u, Uint8 error, char *name, Uint16 addr);
int uxn_halt(Uxn *u, Uint8 error, Uint16 addr);
Device *uxn_port(Uxn *u, Uint8 id, Uint8 (*deifn)(Device *, Uint8), void (*deofn)(Device *, Uint8));

View File

@ -3,6 +3,7 @@
#include <unistd.h>
#include <time.h>
#include "uxn.h"
#include "devices/system.h"
#include "devices/file.h"
/*
@ -45,26 +46,12 @@ inspect(Stack *s, char *name)
#pragma mark - Devices
static Uint8
system_dei(Device *d, Uint8 port)
void
system_deo_special(Device *d, Uint8 port)
{
switch(port) {
case 0x2: return d->u->wst.ptr;
case 0x3: return d->u->rst.ptr;
default: return d->dat[port];
}
}
static void
system_deo(Device *d, Uint8 port)
{
switch(port) {
case 0x2: d->u->wst.ptr = d->dat[port]; break;
case 0x3: d->u->rst.ptr = d->dat[port]; break;
case 0xe:
if(port == 0xe) {
inspect(&d->u->wst, "Working-stack");
inspect(&d->u->rst, "Return-stack");
break;
}
}
@ -115,15 +102,6 @@ nil_deo(Device *d, Uint8 port)
#pragma mark - Generics
static const char *errors[] = {"underflow", "overflow", "division by zero"};
int
uxn_halt(Uxn *u, Uint8 error, char *name, Uint16 addr)
{
fprintf(stderr, "Halted: %s %s#%04x, at 0x%04x\n", name, errors[error - 1], u->ram[addr], addr);
return 0;
}
static int
console_input(Uxn *u, char c)
{
@ -155,13 +133,16 @@ load(Uxn *u, char *filepath)
return 1;
}
static Uint8 *memory;
int
main(int argc, char **argv)
{
Uxn u;
int i, loaded = 0;
if(!uxn_boot(&u, (Uint8 *)calloc(0xffff, sizeof(Uint8))))
memory = (Uint8 *)calloc(0xffff, sizeof(Uint8));
if(!uxn_boot(&u, memory))
return error("Boot", "Failed");
/* system */ devsystem = uxn_port(&u, 0x0, system_dei, system_deo);

View File

@ -17,6 +17,7 @@
#pragma GCC diagnostic ignored "-Wpedantic"
#pragma clang diagnostic ignored "-Wtypedef-redefinition"
#include <SDL.h>
#include "devices/system.h"
#include "devices/screen.h"
#include "devices/audio.h"
#include "devices/file.h"
@ -144,7 +145,10 @@ set_size(Uint16 width, Uint16 height, int is_resize)
gRect.w = uxn_screen.width;
gRect.h = uxn_screen.height;
if(gTexture != NULL) SDL_DestroyTexture(gTexture);
gTexture = SDL_CreateTexture(gRenderer, SDL_PIXELFORMAT_ARGB8888, SDL_TEXTUREACCESS_STATIC, uxn_screen.width + PAD * 2, uxn_screen.height + PAD * 2);
#ifndef __ANDROID__
SDL_RenderSetLogicalSize(gRenderer, uxn_screen.width + PAD * 2, uxn_screen.height + PAD * 2);
#endif
gTexture = SDL_CreateTexture(gRenderer, SDL_PIXELFORMAT_XRGB8888, SDL_TEXTUREACCESS_STATIC, uxn_screen.width, uxn_screen.height);
if(gTexture == NULL || SDL_SetTextureBlendMode(gTexture, SDL_BLENDMODE_NONE))
return error("gTexture", SDL_GetError());
if(SDL_UpdateTexture(gTexture, NULL, uxn_screen.pixels, sizeof(Uint32)) != 0)
@ -161,12 +165,12 @@ redraw(Uxn *u)
if(devsystem->dat[0xe])
screen_debug(&uxn_screen, u->wst.dat, u->wst.ptr, u->rst.ptr, u->ram);
screen_redraw(&uxn_screen, uxn_screen.pixels);
if(SDL_UpdateTexture(gTexture, &gRect, uxn_screen.pixels, uxn_screen.width * sizeof(Uint32)) != 0)
if(SDL_UpdateTexture(gTexture, NULL, uxn_screen.pixels, uxn_screen.width * sizeof(Uint32)) != 0)
error("SDL_UpdateTexture", SDL_GetError());
SDL_RenderClear(gRenderer);
#ifdef __ANDROID__
gScrDst.x = 0;
gScrDst.y = 0;
#ifdef __ANDROID__
if(gScrSize.y > gScrSize.x) { /* portrait */
gScrDst.w = gScrSize.x;
gScrDst.h = gScrSize.x * uxn_screen.height / uxn_screen.width;
@ -175,11 +179,10 @@ redraw(Uxn *u)
gScrDst.w = gScrSize.y * uxn_screen.width / uxn_screen.height;
gScrDst.x = (gScrSize.x - gScrDst.w) / 2;
}
#else
gScrDst.w = gScrSize.x;
gScrDst.h = gScrSize.y;
#endif
SDL_RenderCopy(gRenderer, gTexture, NULL, &gScrDst);
#else
SDL_RenderCopy(gRenderer, gTexture, NULL, &gRect);
#endif
SDL_RenderPresent(gRenderer);
}
@ -209,6 +212,7 @@ init(void)
gRenderer = SDL_CreateRenderer(gWindow, -1, 0);
if(gRenderer == NULL)
return error("sdl_renderer", SDL_GetError());
SDL_SetRenderDrawColor(gRenderer, 0x00, 0x00, 0x00, 0xff);
audio_id = SDL_OpenAudioDevice(NULL, 0, &as, NULL, 0);
if(!audio_id)
error("sdl_audio", SDL_GetError());
@ -225,23 +229,9 @@ init(void)
#pragma mark - Devices
static Uint8
system_dei(Device *d, Uint8 port)
void
system_deo_special(Device *d, Uint8 port)
{
switch(port) {
case 0x2: return d->u->wst.ptr;
case 0x3: return d->u->rst.ptr;
default: return d->dat[port];
}
}
static void
system_deo(Device *d, Uint8 port)
{
switch(port) {
case 0x2: d->u->wst.ptr = d->dat[port]; break;
case 0x3: d->u->rst.ptr = d->dat[port]; break;
}
if(port > 0x7 && port < 0xe)
screen_palette(&uxn_screen, &d->dat[0x8]);
}
@ -340,10 +330,12 @@ load(Uxn *u, char *rom)
return 1;
}
static Uint8 *memory;
static int
start(Uxn *u, char *rom)
{
Uint8 *memory = (Uint8 *)calloc(0xffff, sizeof(Uint8));
memory = (Uint8 *)calloc(0xffff, sizeof(Uint8));
if(!uxn_boot(u, memory))
return error("Boot", "Failed to start uxn.");
if(!load(u, rom))
@ -473,15 +465,6 @@ do_shortcut(Uxn *u, SDL_Event *event)
restart(u);
}
static const char *errors[] = {"underflow", "overflow", "division by zero"};
int
uxn_halt(Uxn *u, Uint8 error, char *name, Uint16 addr)
{
fprintf(stderr, "Halted: %s %s#%04x, at 0x%04x\n", name, errors[error - 1], u->ram[addr], addr);
return 0;
}
static int
console_input(Uxn *u, char c)
{