From b3861f3361a67be97d0de72c6c01ead2770e9739 Mon Sep 17 00:00:00 2001 From: Steven Hugg Date: Sun, 2 Jun 2019 10:53:39 -0400 Subject: [PATCH] astrocade: split bios into .c files; check rom_size on sdcc targets (not yet) --- doc/notes.txt | 10 +- presets/astrocade-bios/bios.c | 561 +++--------------------------- presets/astrocade-bios/bios.h | 158 +++++++++ presets/astrocade-bios/bmusic.c | 8 +- presets/astrocade-bios/gfx.c | 244 +++++++++++++ presets/astrocade-bios/input.c | 144 ++++++++ presets/astrocade/aclib.c | 2 - presets/astrocade/hdr_autostart.s | 2 + presets/astrocade/hello.c | 20 +- src/pixed/pixeleditor.ts | 2 +- src/platform/astrocade.ts | 1 + src/worker/workermain.ts | 21 +- test/cli/testworker.js | 2 +- 13 files changed, 651 insertions(+), 524 deletions(-) create mode 100644 presets/astrocade-bios/bios.h create mode 100644 presets/astrocade-bios/gfx.c create mode 100644 presets/astrocade-bios/input.c diff --git a/doc/notes.txt b/doc/notes.txt index 7a4ada6d..d196f1b1 100644 --- a/doc/notes.txt +++ b/doc/notes.txt @@ -35,7 +35,6 @@ TODO: - go to error in include files - online tools for music etc - text log debugging script -- NES crt should mark raster pos when debugging - intro/help text for each platform - vscode/atom extension? - VCS asm library @@ -63,7 +62,10 @@ TODO: - what if .c and .s names collide? - maybe put stuff in examples/ dir? - error msg when #link doesn't work - - sdcc: can't link asm files before c files (e.g. acheader.s must be last) + - warning when ROM too big +- sdcc: + - can't link asm files before c files (e.g. acheader.s must be last) + - figure out area names ordering - live coding URL - resize memory browser when vertical div resize - preroll the emulator so optimizer does its thing before loading rom @@ -87,7 +89,6 @@ TODO: - show player controls for each platform, allow touch support, navigator.getGamepads - better undo/diff for mistakes? - ide bug/feature visualizer for sponsors -- optimization flags for sdcc (oldralloc) - global undo/redo at checkpoints (when rom changes) - pulldown shows wrong file if preset not present - landscape mode for arcade ports @@ -104,7 +105,6 @@ TODO: - parse .incbin directives? - can't replace in hex directives - should maybe use same single-canvas editor for map + char editor - - Uncaught Expected 12 bytes; image has 6 (380:13): Expected 12 bytes; image has 6 ... over and over ... editing BALL - crt0.s compiled each time? - debug highlight doesn't go away when debugging -> running - show breakpoint of PC or highest address on stack @@ -133,6 +133,7 @@ TODO: - nes debug view toolbar - support NES_HEADER_16K? - PPU/TIA register write visualization + - NES crt should mark raster pos when debugging - vcs - vcs sound continues when paused - vcs: INPTx needs to be added to control state @@ -157,6 +158,7 @@ TODO: - support projects with subdirectories, file list? - emulator needs reset shortcut for nes - switching platform of a repo? + - make sure to flatten subdirs - ctrl+alt+l on ubuntu locks screen WEB WORKER FORMAT diff --git a/presets/astrocade-bios/bios.c b/presets/astrocade-bios/bios.c index 3bbc8acb..3ab56744 100644 --- a/presets/astrocade-bios/bios.c +++ b/presets/astrocade-bios/bios.c @@ -21,86 +21,18 @@ See: http://creativecommons.org/publicdomain/zero/1.0/ // music processor //#link "bmusic.c" +// input +//#link "input.c" + +// graphics +//#link "gfx.c" + #include +#include "bios.h" + // uncomment to make code better, but slower compile -//#pragma opt_code_speed - -typedef unsigned char byte; -typedef signed char sbyte; -typedef unsigned short word; -typedef signed short sword; - -/// HARDWARE - -__sfr __at(0x00) hw_col0r; // palette 0 -__sfr __at(0x01) hw_col1r; -__sfr __at(0x02) hw_col2r; -__sfr __at(0x03) hw_col3r; -__sfr __at(0x04) hw_col0l; -__sfr __at(0x05) hw_col1l; -__sfr __at(0x06) hw_col2l; -__sfr __at(0x07) hw_col3l; // palette 7 - -__sfr __at(0x08) hw_intst; // intercept test feedback -__sfr __at(0x09) hw_horcb; // horiz color boundary -__sfr __at(0x0a) hw_verbl; // vertical blanking line * 2 -__sfr __at(0x0c) hw_magic; // magic register -__sfr __at(0x0d) hw_infbk; // interrupt feedback -__sfr __at(0x0e) hw_inmod; // interrupt enable -__sfr __at(0x0f) hw_inlin; // interrupt line -__sfr __at(0x19) hw_xpand; // expander register - -__sfr __at(0x10) hw_p1ctrl; // player controls -__sfr __at(0x11) hw_p2ctrl; // player controls -__sfr __at(0x12) hw_p3ctrl; // player controls -__sfr __at(0x13) hw_p4ctrl; // player controls -__sfr __at(0x14) hw_keypad0; -__sfr __at(0x15) hw_keypad1; -__sfr __at(0x16) hw_keypad2; -__sfr __at(0x17) hw_keypad3; -__sfr __at(0x1c) hw_p1pot; // player pot -__sfr __at(0x1d) hw_p2pot; // player pot -__sfr __at(0x1e) hw_p3pot; // player pot -__sfr __at(0x1f) hw_p4pot; // player pot - -#define M_SHIFT0 0x00 -#define M_SHIFT1 0x01 -#define M_SHIFT2 0x02 -#define M_SHIFT3 0x03 -#define M_XPAND 0x08 -#define M_MOVE 0x00 -#define M_OR 0x10 -#define M_XOR 0x20 -#define M_FLOP 0x40 -#define M_SHIFT(x) ((x)&3) -#define XPAND_COLORS(off,on) (((off)&3) | (((on)&3)<<2)) - -// font options -#define OPT_1x1 0x00 -#define OPT_2x2 0x40 -#define OPT_4x4 0x80 -#define OPT_8x8 0xc0 -#define OPT_XOR 0x20 -#define OPT_OR 0x10 -#define OPT_ON(n) ((n)<<2) -#define OPT_OFF(n) ((n)) - -// bcd options -#define DISBCD_SML 0x40 -#define DISBCD_NOZERO 0x80 - -/// GRAPHICS FUNCTIONS - -#define VHEIGHT 102 // number of scanlines -#define VBWIDTH 40 // number of bytes per scanline -#define PIXWIDTH 160 // 4 pixels per byte - -//#define EXIT_CLIPDEST(addr) if ((((word)addr)&0xfff) >= 0xe10) return -#define EXIT_CLIPDEST(addr) - -byte __at (0x0000) vmagic[VHEIGHT][VBWIDTH]; -byte __at (0x4000) vidmem[VHEIGHT][VBWIDTH]; +#pragma opt_code_speed // start @ $4FCE volatile word MUZPC; // music PC @@ -136,35 +68,7 @@ byte SENFLG; // sentry control byte* UMARGT; // user mask table (-64 bytes) word* USERTB; // user routine table (-128 bytes) -typedef enum { - SNUL, - SCT0,SCT1,SCT2,SCT3,SCT4,SCT5,SCT6,SCT7, - SF0,SF1,SF2,SF3,SF4,SF5,SF6,SF7, - SSEC, - SKYU,SKYD, - ST0,SJ0,ST1,SJ1,ST2,SJ2,ST3,SJ3, - SP0,SP1,SP2,SP3 -} SENTRYCode; - -typedef struct { - byte base_ch; // first char - byte frame_x; // frame width - byte frame_y; // frame height - byte pattern_x; // pattern width - byte pattern_y; // pattern height - const byte* chartab; // pointer to char data -} FontDescriptor; - -#define LOCHAR 0x20 -#define HICHAR 0x63 - -extern const char BIGFONT[HICHAR-LOCHAR+1][7]; -extern const char SMLFONT[HICHAR-LOCHAR+1][5]; - -const FontDescriptor __at(0x206) FNTSYS; // = { 0x20, 8, 8, 1, 7, (byte*)BIGFONT }; -const FontDescriptor __at(0x20d) FNTSML; // = { 0xa0, 4, 6, 1, 5, (byte*)SMLFONT }; - - +// from bmusic.c extern void music_update(void); // INTERRUPT HANDLERS @@ -231,59 +135,6 @@ void TIMEY() { void TIMEX() { } -///// INTERPRETER - -typedef struct { - union { - struct { - word iy,ix,de,bc,af,hl; - } w; - struct { - byte iyl,iyh,ixl,ixh,e,d,c,b,f,a,l,h; - } b; - } regs; - byte* params; -} ContextBlock; - -#define REG_IY 0x1 -#define REG_E 0x2 -#define REG_D 0x4 -#define REG_C 0x8 -#define REG_B 0x10 -#define REG_IX 0x20 -#define REG_A 0x40 -#define REG_HL 0x80 -#define REG_DE (REG_D|REG_E) -#define REG_BC (REG_B|REG_C) - -#define _IY (ctx->regs.w.iy) -#define _IX (ctx->regs.w.ix) -#define _DE (ctx->regs.w.de) -#define _BC (ctx->regs.w.bc) -#define _AF (ctx->regs.w.af) -#define _HL (ctx->regs.w.hl) -#define _IXL (ctx->regs.b.ixl) -#define _IXH (ctx->regs.b.ixh) -#define _IYL (ctx->regs.b.iyl) -#define _IYH (ctx->regs.b.iyh) -#define _E (ctx->regs.b.e) -#define _D (ctx->regs.b.d) -#define _C (ctx->regs.b.c) -#define _B (ctx->regs.b.b) -#define _A (ctx->regs.b.a) -#define _L (ctx->regs.b.l) -#define _H (ctx->regs.b.h) - -typedef void (Routine)(); -typedef void (SysRoutine)(ContextBlock *ctx); - -typedef struct { - SysRoutine* routine; - byte argmask; -} SysCallEntry; - -void SYSCALL(ContextBlock *ctx); - void INTPC(ContextBlock *ctx) { while (ctx->params[0] != 2) { // 2 = exit SYSCALL(ctx); @@ -302,7 +153,10 @@ void RCALL(ContextBlock *ctx) { // start interpreting at HL void MCALL(ContextBlock *ctx) { - ctx; // TODO + ctx->params = (byte*)_HL; + while (ctx->params[0] != 8) { // 8 = MRET + SYSCALL(ctx); + } } // exit MCALL loop @@ -369,17 +223,19 @@ void SETOUT(ContextBlock *ctx) { hw_inmod = _A; } +// set entire palette at once (8 bytes to port 0xb) +// bytes in array should be in reverse +void set_palette(byte palette[8]) __z88dk_fastcall { + palette; +__asm + ld bc,#0x80b ; B -> 8, C -> 0xb + otir ; write C bytes from HL to port[B] +__endasm; +} + // sets color palettes from (HL) void COLSET(ContextBlock *ctx) { - byte* palette = (byte*) _HL; - hw_col3l = *palette++; - hw_col2l = *palette++; - hw_col1l = *palette++; - hw_col0l = *palette++; - hw_col3r = *palette++; - hw_col2r = *palette++; - hw_col1r = *palette++; - hw_col0r = *palette++; + set_palette((byte*)_HL); } // Stores A in BC bytes starting at location DE. @@ -390,248 +246,6 @@ void FILL(ContextBlock *ctx) { memset(dest, val, count); } -void hline(byte x1, byte x2, byte y, byte pattern) { - byte xb1 = x1/4; - byte xb2 = x2/4; - byte* dest = &vmagic[y][xb1]; - signed char nbytes = xb2 - xb1; - hw_magic = M_SHIFT(x1) | M_XOR; - while (--nbytes > 0) { - *dest++ = pattern; - } - if (x2&3) *dest = 0; - // TODO -} - -// Fill rect (E,D,C,B) color A -void RECTAN(const ContextBlock *ctx) { - for (byte y=_D; y<_D+_B; y++) { - hline(_E, _E+_C, y, _A); - } -} - -const char BIGFONT[HICHAR-LOCHAR+1][7] = {/*{count:68,w:8,h:7,brev:1}*/ -{0x00,0x00,0x00,0x00,0x00,0x00,0x00},{0x20,0x20,0x20,0x20,0x00,0x00,0x20},{0x50,0x50,0x00,0x00,0x00,0x00,0x00},{0x48,0xFC,0x48,0x48,0x48,0xFC,0x48},{0x20,0x78,0x80,0x70,0x08,0xF0,0x20},{0x00,0x48,0x10,0x20,0x40,0x90,0x00},{0x60,0x90,0x60,0xA0,0xA8,0x90,0x68},{0x60,0x60,0x20,0x00,0x00,0x00,0x00},{0x20,0x40,0x40,0x40,0x40,0x40,0x20},{0x40,0x20,0x20,0x20,0x20,0x20,0x40},{0x00,0xA8,0x70,0xF8,0x70,0xA8,0x00},{0x00,0x20,0x20,0xF8,0x20,0x20,0x00},{0x00,0x00,0x00,0x00,0x60,0x20,0x40},{0x00,0x00,0x00,0xF0,0x00,0x00,0x00},{0x00,0x00,0x00,0x00,0x00,0x60,0x60},{0x00,0x08,0x10,0x20,0x40,0x80,0x00},{0x70,0x88,0x88,0xA8,0x88,0x88,0x70},{0x20,0x60,0x20,0x20,0x20,0x20,0x70},{0x70,0x88,0x08,0x30,0x40,0x80,0xF8},{0x70,0x88,0x08,0x70,0x08,0x88,0x70},{0x10,0x30,0x50,0x90,0xF8,0x10,0x10},{0xF8,0x80,0x80,0x70,0x08,0x88,0x70},{0x70,0x88,0x80,0xF0,0x88,0x88,0x70},{0xF8,0x88,0x10,0x20,0x20,0x20,0x20},{0x70,0x88,0x88,0x70,0x88,0x88,0x70},{0x70,0x88,0x88,0x78,0x08,0x88,0x70},{0x00,0x00,0x60,0x00,0x60,0x00,0x00},{0x00,0x00,0x60,0x00,0x60,0x20,0x40},{0x10,0x20,0x40,0x80,0x40,0x20,0x10},{0x00,0x00,0xF8,0x00,0xF8,0x00,0x00},{0x40,0x20,0x10,0x08,0x10,0x20,0x40},{0x70,0x08,0x08,0x30,0x20,0x00,0x20},{0x70,0x88,0xB8,0xA8,0x90,0x80,0x70},{0x70,0x88,0x88,0xF8,0x88,0x88,0x88},{0xF0,0x88,0x88,0xF0,0x88,0x88,0xF0},{0x70,0x88,0x80,0x80,0x80,0x88,0x70},{0xF0,0x88,0x88,0x88,0x88,0x88,0xF0},{0xF8,0x80,0x80,0xF0,0x80,0x80,0xF8},{0xF8,0x80,0x80,0xF0,0x80,0x80,0x80},{0x70,0x88,0x80,0xB0,0x88,0x88,0x70},{0x88,0x88,0x88,0xF8,0x88,0x88,0x88},{0x70,0x20,0x20,0x20,0x20,0x20,0x70},{0x08,0x08,0x08,0x08,0x88,0x88,0x70},{0x88,0x90,0xA0,0xC0,0xA0,0x90,0x88},{0x80,0x80,0x80,0x80,0x80,0x80,0xF8},{0x88,0xD8,0xA8,0x88,0x88,0x88,0x88},{0x88,0xC8,0xA8,0xA8,0x98,0x88,0x88},{0xF8,0x88,0x88,0x88,0x88,0x88,0xF8},{0xF0,0x88,0x88,0xF0,0x80,0x80,0x80},{0x70,0x88,0x88,0xA8,0xA8,0x90,0x68},{0xF0,0x88,0x88,0xF0,0x90,0x90,0x88},{0x70,0x88,0x80,0x70,0x08,0x88,0x70},{0xF8,0x20,0x20,0x20,0x20,0x20,0x20},{0x88,0x88,0x88,0x88,0x88,0x88,0x70},{0x88,0x88,0x88,0x88,0x88,0x50,0x20},{0x88,0x88,0x88,0x88,0xA8,0xD8,0x88},{0x88,0x88,0x50,0x20,0x50,0x88,0x88},{0x88,0x88,0x50,0x20,0x20,0x20,0x20},{0xF8,0x08,0x10,0x20,0x40,0x80,0xF8},{0x70,0x40,0x40,0x40,0x40,0x40,0x70},{0x00,0x80,0x40,0x20,0x10,0x08,0x00},{0x70,0x10,0x10,0x10,0x10,0x10,0x70},{0x20,0x70,0xA8,0x20,0x20,0x20,0x00},{0x00,0x20,0x40,0xF8,0x40,0x20,0x00},{0x00,0x20,0x20,0x20,0xA8,0x70,0x20},{0x00,0x20,0x10,0xF8,0x10,0x20,0x00},{0x00,0x88,0x50,0x20,0x50,0x88,0x00},{0x00,0x20,0x00,0xF8,0x00,0x20,0x00}}; - -const char SMLFONT[HICHAR-LOCHAR+1][5] = {/*{count:68,w:5,h:5,brev:1}*/ -{ 0x00,0x00,0x00,0x00,0x00 },{ 0x40,0x40,0x00,0x40,0x00 },{ 0xA0,0xA0,0x00,0x00,0x00 },{ 0x60,0xF0,0xF0,0x60,0x00 },{ 0x40,0xE0,0xE0,0x40,0x00 },{ 0x90,0x20,0x40,0x90,0x00 },{ 0xC0,0xB0,0xE0,0xD0,0x00 },{ 0x20,0x40,0x00,0x00,0x00 },{ 0x20,0x40,0x40,0x20,0x00 },{ 0x40,0x20,0x20,0x40,0x00 },{ 0x40,0xE0,0x40,0xA0,0x00 },{ 0x00,0x40,0xE0,0x40,0x00 },{ 0x00,0x00,0x00,0x60,0x20 },{ 0x00,0x00,0xE0,0x00,0x00 },{ 0x00,0x00,0x00,0x40,0x00 },{ 0x20,0x20,0x40,0x40,0x00 },{ 0xE0,0xA0,0xA0,0xA0,0xE0 },{ 0xC0,0x40,0x40,0x40,0xE0 },{ 0xE0,0x20,0xE0,0x80,0xE0 },{ 0xE0,0x20,0x60,0x20,0xE0 },{ 0xA0,0xA0,0xE0,0x20,0x20 },{ 0xE0,0x80,0xE0,0x20,0xE0 },{ 0xE0,0x80,0xE0,0xA0,0xE0 },{ 0xE0,0x20,0x40,0x40,0x40 },{ 0xE0,0xA0,0xE0,0xA0,0xE0 },{ 0xE0,0xA0,0xE0,0x20,0xE0 },{ 0x00,0x40,0x00,0x40,0x00 },{ 0x00,0x40,0x00,0x60,0x20 },{ 0x00,0x20,0x40,0x20,0x00 },{ 0x00,0xE0,0x00,0xE0,0x00 },{ 0x00,0x40,0x20,0x40,0x00 },{ 0xE0,0x20,0x60,0x00,0x40 },{ 0xF0,0x90,0x10,0xD0,0xF0 },{ 0x60,0xA0,0xE0,0xA0,0x00 },{ 0xC0,0xE0,0xA0,0xE0,0x00 },{ 0x60,0x80,0x80,0xE0,0x00 },{ 0xC0,0xA0,0xA0,0xC0,0x00 },{ 0xE0,0xC0,0x80,0xE0,0x00 },{ 0xE0,0xC0,0x80,0x80,0x00 },{ 0x60,0x80,0xA0,0xE0,0x00 },{ 0xA0,0xA0,0xE0,0xA0,0x00 },{ 0xE0,0x40,0x40,0xE0,0x00 },{ 0x60,0x20,0xA0,0xE0,0x00 },{ 0xA0,0xC0,0xC0,0xA0,0x00 },{ 0x80,0x80,0x80,0xE0,0x00 },{ 0xE0,0xE0,0xE0,0xA0,0x00 },{ 0xE0,0xA0,0xA0,0xA0,0x00 },{ 0xE0,0xA0,0xA0,0xE0,0x00 },{ 0xE0,0xA0,0xE0,0x80,0x00 },{ 0xE0,0xA0,0xE0,0xF0,0x00 },{ 0xE0,0xA0,0xC0,0xA0,0x00 },{ 0xE0,0x80,0x60,0xE0,0x00 },{ 0xE0,0x40,0x40,0x40,0x00 },{ 0xA0,0xA0,0xA0,0xE0,0x00 },{ 0xA0,0xA0,0xC0,0x80,0x00 },{ 0xA0,0xE0,0xE0,0xE0,0x00 },{ 0xA0,0x40,0xA0,0xA0,0x00 },{ 0xA0,0xE0,0x40,0x40,0x00 },{ 0xE0,0x20,0x40,0xE0,0x00 },{ 0x60,0x40,0x40,0x60,0x00 },{ 0x40,0x40,0x20,0x20,0x00 },{ 0x60,0x20,0x20,0x60,0x00 },{ 0x40,0xA0,0x00,0x00,0x00 },{ 0x00,0x00,0x00,0x00,0xF0 },{ 0x80,0x40,0x00,0x00,0x00 },{ 0x00,0x60,0xA0,0xE0,0x00 },{ 0x80,0xE0,0xA0,0xE0,0x00 },{ 0x00,0x60,0x80,0xE0,0x00 }}; - -// draw a letter -byte draw_char(const FontDescriptor* font, byte ch, byte x, byte y, byte op) { - const byte* src = font->chartab + (ch-font->base_ch)*font->pattern_y; - byte* dest = &vmagic[y][x>>2];// destination address - byte magic = M_SHIFT(x) | M_XPAND | (op & 0x30); - // big sizes? - if (op & 0xc0) { - char buf[8]; // expansion buffer - char* mbuf = (buf - 0x4000);// make it magic - byte sc = 1 << (op >> 6); // 2x2 = 2, 4x4 = 4, 8x8 = 8 - for (byte i=0; ipattern_y; i++) { - // expand into magic buffer onto stack - hw_magic = M_XPAND; - hw_xpand = 0b1100; // on = 11, off = 00 - // 2x2 size - mbuf[1] = mbuf[0] = *src++; - // 4x4 size - if (op & 0x80) { - byte b = buf[0]; - mbuf[3] = mbuf[2] = buf[1]; - mbuf[1] = mbuf[0] = b; - } - // 8x8 size - if ((op & 0xc0) == 0xc0) { - byte b = buf[0]; - mbuf[7] = mbuf[6] = buf[3]; - mbuf[5] = mbuf[4] = buf[2]; - mbuf[3] = mbuf[2] = buf[1]; - mbuf[1] = mbuf[0] = b; - } - // draw to screen (magic, again) - hw_xpand = op & 0xf; - for (byte j=0; jpattern_y; i++) { - char b = *src++; - EXIT_CLIPDEST(dest); - hw_magic = magic; // reset flip flop - *dest++ = b; // expand lower nibble -> 1st byte - *dest++ = b; // expand upper nibble -> 2nd byte - *dest++ = 0; // leftover -> 3rd byte - dest += VBWIDTH-3; // we incremented 3 bytes for this line - } - } - return font->frame_x << (op >> 6); -} - -#define FONT_IX ((const FontDescriptor*)ctx->regs.w.ix) - -void draw_string(ContextBlock *ctx, const char* str, byte x, byte y, byte op) { - do { - byte ch = *str++; - if (!ch) { - _E = x; - break; - } - if (ch < 0x20) { - x += draw_char(&FNTSYS, ' ', x, y, op); // TODO - } else if (ch < 0x64) { - x += draw_char(&FNTSYS, ch, x, y, op); - } else if (ch >= 0x80) { - x += draw_char(FONT_IX, ch, x, y, op); - } else { - /* - if (ch & 0x10) { - ctx->regs.b.ixl = *str++; - ctx->regs.b.ixh = *str++; - } - if (ch & 0x1) - _E = *str++; - if (ch & 0x2) - _D = *str++; - if (ch & 0x4) - _C = *str++; - */ - // TODO: only can change font - } - } while (1); -} - -// String display routine (pass pointer to string) -void STRDIS2(ContextBlock *ctx, char *str) { - byte opts = _C; - byte x = _E; - byte y = _D; - void* fontdesc = (void*) ctx->regs.w.ix; - draw_string(ctx, str, x, y, opts); // TODO: opts -} - -// String display routine -void STRDIS(ContextBlock *ctx) { - char* str = (char*) _HL; - STRDIS2(ctx, str); -} - -// Character display routine -void CHRDIS(ContextBlock *ctx) { - char chstr[2]; - chstr[0] = _A; - chstr[1] = 0; - STRDIS2(ctx, chstr); -} - -// BCD routine -const char BCDTAB[17] = "0123456789*+,-./"; - -// DISNUM - (E.D) x/y (C) options (B) ext (HL) BCD-addr -void DISNUM(ContextBlock *ctx) { - // TODO: options, B - byte x = _E; - byte y = _D; - byte opt = _C; - byte ext = _B; - byte ndigits = ext & 63; - const FontDescriptor* font = (ext&64) ? &FNTSML : &FNTSYS; - byte add = (ext&64) ? 128 : 0; - byte noleadingzero = ext & 128; - byte* pbcd = (byte*) _HL; - pbcd += (ndigits-1)/2; - while (ndigits--) { - byte val = *pbcd; - if (ndigits & 1) { - val >>= 4; - } else { - val &= 15; - pbcd--; - } - x += draw_char(font, BCDTAB[val]+add, x, y, opt); - } -} - -typedef struct { - sbyte xofs, yofs; - byte xsize, ysize; - byte pattern[0]; -} PatternBlock; - -// write pattern (E,D,C,B) magic A @ HL -void WRIT(ContextBlock *ctx) { - byte magic = _A; - byte w = _C; - byte h = _B; - byte x = _E; - byte y = _D; - byte* src = (byte*) _HL; - byte* dest = &vmagic[y][0]; // destination address - byte xb = (magic & M_FLOP) ? (39-(x>>2)) : (x>>2); - byte i,j,b; - // iterate through all lines - for (j=0; j>= 1; - } - } - } - // key up? - if (key && key != KEYSEX) { - B = KEYSEX = key; - A = SKYD; - } - else if (!key && KEYSEX) { - if (KEYSEX & 0x80) { - A = SSEC; // second timer - } else { - A = SKYU; - } - B = 0; - KEYSEX = 0; - } - // pots - val[0] = hw_p1pot; - val[1] = hw_p2pot; - val[2] = hw_p3pot; - val[3] = hw_p4pot; - for (i=0; i<4; i++) { - if (val[i] != OPOT[i]) { - A = SP0+i; - B = val[i]; - } - } - memcpy(OPOT, val, 4); // update previous state - // semiphores - if (SEMI4S) { - B = SEMI4S; - for (i=7; i>=0; i--) { - if (B & 0x80) { - A = SF0+i; - SEMI4S ^= 1 << i; - break; - } - B <<= 1; - } - } - // counters - if (SENFLG) { - B = SENFLG; - for (i=7; i>=0; i--) { - if (B & 0x80) { - A = SF0+i; - SENFLG ^= 1 << i; - break; - } - B <<= 1; - } - } - // clear timeout counter (TODO) - if (A >= SKYU) { - TIMOUT = 0xff; - } - _A = A; - _B = B; +const byte KCTASC_TABLE[25] = { + 0x00, + 0x43, 0x5e, 0x5c, 0x25, 0x52, 0x53, 0x3b, 0x2f, + 0x37, 0x38, 0x39, 0x2a, 0x34, 0x35, 0x36, 0x2d, + 0x31, 0x32, 0x33, 0x2b, 0x26, 0x30, 0x2e, 0x3d +}; + +void KCTASC(ContextBlock *ctx) { + _A = KCTASC_TABLE[_B]; } +// music + void BMUSIC(ContextBlock *ctx) { VOICES = _A; MUZPC = _HL; @@ -800,6 +333,22 @@ void EMUSIC(ContextBlock *ctx) { VOICES = 0; } +// externals + +extern void SENTRY(ContextBlock *ctx); +extern void DOIT(ContextBlock *ctx); +extern void DOITB(ContextBlock *ctx); + +extern void RECTAN(const ContextBlock *ctx); +extern void WRITR(const ContextBlock *ctx); +extern void WRITP(const ContextBlock *ctx); +extern void WRIT(const ContextBlock *ctx); +extern void CHRDIS(const ContextBlock *ctx); +extern void STRDIS(const ContextBlock *ctx); +extern void DISNUM(const ContextBlock *ctx); + +// table + const SysCallEntry SYSCALL_TABLE[64] = { /* 0 */ { &INTPC, 0 }, @@ -840,11 +389,11 @@ const SysCallEntry SYSCALL_TABLE[64] = { /* 60 */ { 0, 0 }, { 0, 0 }, - { 0, 0 }, + { &KCTASC, 0 }, { &SENTRY, REG_DE }, - { 0, 0 }, + { &DOIT, REG_HL }, /* 70 */ - { 0, 0 }, + { &DOITB, REG_HL }, { 0, 0 }, { 0, 0 }, { 0, 0 }, diff --git a/presets/astrocade-bios/bios.h b/presets/astrocade-bios/bios.h new file mode 100644 index 00000000..6b93b272 --- /dev/null +++ b/presets/astrocade-bios/bios.h @@ -0,0 +1,158 @@ + +typedef unsigned char byte; +typedef signed char sbyte; +typedef unsigned short word; +typedef signed short sword; + +/// HARDWARE + +__sfr __at(0x00) hw_col0r; // palette 0 +__sfr __at(0x01) hw_col1r; +__sfr __at(0x02) hw_col2r; +__sfr __at(0x03) hw_col3r; +__sfr __at(0x04) hw_col0l; +__sfr __at(0x05) hw_col1l; +__sfr __at(0x06) hw_col2l; +__sfr __at(0x07) hw_col3l; // palette 7 + +__sfr __at(0x08) hw_intst; // intercept test feedback +__sfr __at(0x09) hw_horcb; // horiz color boundary +__sfr __at(0x0a) hw_verbl; // vertical blanking line * 2 +__sfr __at(0x0c) hw_magic; // magic register +__sfr __at(0x0d) hw_infbk; // interrupt feedback +__sfr __at(0x0e) hw_inmod; // interrupt enable +__sfr __at(0x0f) hw_inlin; // interrupt line +__sfr __at(0x19) hw_xpand; // expander register + +__sfr __at(0x10) hw_p1ctrl; // player controls +__sfr __at(0x11) hw_p2ctrl; // player controls +__sfr __at(0x12) hw_p3ctrl; // player controls +__sfr __at(0x13) hw_p4ctrl; // player controls +__sfr __at(0x14) hw_keypad0; +__sfr __at(0x15) hw_keypad1; +__sfr __at(0x16) hw_keypad2; +__sfr __at(0x17) hw_keypad3; +__sfr __at(0x1c) hw_p1pot; // player pot +__sfr __at(0x1d) hw_p2pot; // player pot +__sfr __at(0x1e) hw_p3pot; // player pot +__sfr __at(0x1f) hw_p4pot; // player pot + +#define M_SHIFT0 0x00 +#define M_SHIFT1 0x01 +#define M_SHIFT2 0x02 +#define M_SHIFT3 0x03 +#define M_XPAND 0x08 +#define M_MOVE 0x00 +#define M_OR 0x10 +#define M_XOR 0x20 +#define M_FLOP 0x40 +#define M_SHIFT(x) ((x)&3) +#define XPAND_COLORS(off,on) (((off)&3) | (((on)&3)<<2)) + +// font options +#define OPT_1x1 0x00 +#define OPT_2x2 0x40 +#define OPT_4x4 0x80 +#define OPT_8x8 0xc0 +#define OPT_XOR 0x20 +#define OPT_OR 0x10 +#define OPT_ON(n) ((n)<<2) +#define OPT_OFF(n) ((n)) + +// bcd options +#define DISBCD_SML 0x40 +#define DISBCD_NOZERO 0x80 + +/// GRAPHICS FUNCTIONS + +#define VHEIGHT 102 // number of scanlines +#define VBWIDTH 40 // number of bytes per scanline +#define PIXWIDTH 160 // 4 pixels per byte + +//#define EXIT_CLIPDEST(addr) if ((((word)addr)&0xfff) >= 0xe10) return +#define EXIT_CLIPDEST(addr) + +byte __at (0x0000) vmagic[VHEIGHT][VBWIDTH]; +byte __at (0x4000) vidmem[VHEIGHT][VBWIDTH]; + +typedef enum { + SNUL, + SCT0,SCT1,SCT2,SCT3,SCT4,SCT5,SCT6,SCT7, + SF0,SF1,SF2,SF3,SF4,SF5,SF6,SF7, + SSEC, + SKYU,SKYD, + ST0,SJ0,ST1,SJ1,ST2,SJ2,ST3,SJ3, + SP0,SP1,SP2,SP3 +} SENTRYCode; + +typedef struct { + byte base_ch; // first char + byte frame_x; // frame width + byte frame_y; // frame height + byte pattern_x; // pattern width + byte pattern_y; // pattern height + const byte* chartab; // pointer to char data +} FontDescriptor; + +typedef struct { + sbyte xofs, yofs; + byte xsize, ysize; + byte pattern[0]; +} PatternBlock; + +const FontDescriptor __at(0x206) FNTSYS; // = { 0x20, 8, 8, 1, 7, (byte*)BIGFONT }; +const FontDescriptor __at(0x20d) FNTSML; // = { 0xa0, 4, 6, 1, 5, (byte*)SMLFONT }; + +///// INTERPRETER + +typedef struct { + union { + struct { + word iy,ix,de,bc,af,hl; + } w; + struct { + byte iyl,iyh,ixl,ixh,e,d,c,b,f,a,l,h; + } b; + } regs; + byte* params; +} ContextBlock; + +#define REG_IY 0x1 +#define REG_E 0x2 +#define REG_D 0x4 +#define REG_C 0x8 +#define REG_B 0x10 +#define REG_IX 0x20 +#define REG_A 0x40 +#define REG_HL 0x80 +#define REG_DE (REG_D|REG_E) +#define REG_BC (REG_B|REG_C) + +#define _IY (ctx->regs.w.iy) +#define _IX (ctx->regs.w.ix) +#define _DE (ctx->regs.w.de) +#define _BC (ctx->regs.w.bc) +#define _AF (ctx->regs.w.af) +#define _HL (ctx->regs.w.hl) +#define _IXL (ctx->regs.b.ixl) +#define _IXH (ctx->regs.b.ixh) +#define _IYL (ctx->regs.b.iyl) +#define _IYH (ctx->regs.b.iyh) +#define _E (ctx->regs.b.e) +#define _D (ctx->regs.b.d) +#define _C (ctx->regs.b.c) +#define _B (ctx->regs.b.b) +#define _A (ctx->regs.b.a) +#define _L (ctx->regs.b.l) +#define _H (ctx->regs.b.h) + +typedef void (Routine)(); +typedef void (SysRoutine)(ContextBlock *ctx); + +typedef struct { + SysRoutine* routine; + byte argmask; +} SysCallEntry; + +void SYSCALL(ContextBlock *ctx); + diff --git a/presets/astrocade-bios/bmusic.c b/presets/astrocade-bios/bmusic.c index c89a086d..0da4d59e 100644 --- a/presets/astrocade-bios/bmusic.c +++ b/presets/astrocade-bios/bmusic.c @@ -1,10 +1,7 @@ #pragma opt_code_speed -typedef unsigned char byte; -typedef signed char sbyte; -typedef unsigned short word; -typedef signed short sword; +#include "bios.h" extern byte* MUZPC; // music PC extern byte* MUZSP; // music SP @@ -68,8 +65,9 @@ void music_update(void) { } else if (op < 0x88) { portOut( NEXT() | ((op-0x70)<<8) ); } else if (op == 0x88) { - for (byte i=0; i<8; i++) + for (byte i=0; i<8; i++) { portOut( NEXT() | (0x17-i) ); + } } else switch (op & 0xf0) { case 0x90: VOICES = NEXT(); diff --git a/presets/astrocade-bios/gfx.c b/presets/astrocade-bios/gfx.c new file mode 100644 index 00000000..70962ed8 --- /dev/null +++ b/presets/astrocade-bios/gfx.c @@ -0,0 +1,244 @@ + +#include "bios.h" + +#pragma opt_code_speed + +#define LOCHAR 0x20 +#define HICHAR 0x63 + +static void hline(byte x1, byte x2, byte y, byte pattern) { + byte xb1 = x1/4; + byte xb2 = x2/4; + byte* dest = &vmagic[y][xb1]; + signed char nbytes = xb2 - xb1; + hw_magic = M_SHIFT(x1) | M_XOR; + while (--nbytes > 0) { + *dest++ = pattern; + } + if (x2&3) *dest = 0; + // TODO +} + +// Fill rect (E,D,C,B) color A +void RECTAN(const ContextBlock *ctx) { + for (byte y=_D; y<_D+_B; y++) { + hline(_E, _E+_C, y, _A); + } +} + +const char BIGFONT[HICHAR-LOCHAR+1][7] = {/*{count:68,w:8,h:7,brev:1}*/ +{0x00,0x00,0x00,0x00,0x00,0x00,0x00},{0x20,0x20,0x20,0x20,0x00,0x00,0x20},{0x50,0x50,0x00,0x00,0x00,0x00,0x00},{0x48,0xFC,0x48,0x48,0x48,0xFC,0x48},{0x20,0x78,0x80,0x70,0x08,0xF0,0x20},{0x00,0x48,0x10,0x20,0x40,0x90,0x00},{0x60,0x90,0x60,0xA0,0xA8,0x90,0x68},{0x60,0x60,0x20,0x00,0x00,0x00,0x00},{0x20,0x40,0x40,0x40,0x40,0x40,0x20},{0x40,0x20,0x20,0x20,0x20,0x20,0x40},{0x00,0xA8,0x70,0xF8,0x70,0xA8,0x00},{0x00,0x20,0x20,0xF8,0x20,0x20,0x00},{0x00,0x00,0x00,0x00,0x60,0x20,0x40},{0x00,0x00,0x00,0xF0,0x00,0x00,0x00},{0x00,0x00,0x00,0x00,0x00,0x60,0x60},{0x00,0x08,0x10,0x20,0x40,0x80,0x00},{0x70,0x88,0x88,0xA8,0x88,0x88,0x70},{0x20,0x60,0x20,0x20,0x20,0x20,0x70},{0x70,0x88,0x08,0x30,0x40,0x80,0xF8},{0x70,0x88,0x08,0x70,0x08,0x88,0x70},{0x10,0x30,0x50,0x90,0xF8,0x10,0x10},{0xF8,0x80,0x80,0x70,0x08,0x88,0x70},{0x70,0x88,0x80,0xF0,0x88,0x88,0x70},{0xF8,0x88,0x10,0x20,0x20,0x20,0x20},{0x70,0x88,0x88,0x70,0x88,0x88,0x70},{0x70,0x88,0x88,0x78,0x08,0x88,0x70},{0x00,0x00,0x60,0x00,0x60,0x00,0x00},{0x00,0x00,0x60,0x00,0x60,0x20,0x40},{0x10,0x20,0x40,0x80,0x40,0x20,0x10},{0x00,0x00,0xF8,0x00,0xF8,0x00,0x00},{0x40,0x20,0x10,0x08,0x10,0x20,0x40},{0x70,0x08,0x08,0x30,0x20,0x00,0x20},{0x70,0x88,0xB8,0xA8,0x90,0x80,0x70},{0x70,0x88,0x88,0xF8,0x88,0x88,0x88},{0xF0,0x88,0x88,0xF0,0x88,0x88,0xF0},{0x70,0x88,0x80,0x80,0x80,0x88,0x70},{0xF0,0x88,0x88,0x88,0x88,0x88,0xF0},{0xF8,0x80,0x80,0xF0,0x80,0x80,0xF8},{0xF8,0x80,0x80,0xF0,0x80,0x80,0x80},{0x70,0x88,0x80,0xB0,0x88,0x88,0x70},{0x88,0x88,0x88,0xF8,0x88,0x88,0x88},{0x70,0x20,0x20,0x20,0x20,0x20,0x70},{0x08,0x08,0x08,0x08,0x88,0x88,0x70},{0x88,0x90,0xA0,0xC0,0xA0,0x90,0x88},{0x80,0x80,0x80,0x80,0x80,0x80,0xF8},{0x88,0xD8,0xA8,0x88,0x88,0x88,0x88},{0x88,0xC8,0xA8,0xA8,0x98,0x88,0x88},{0xF8,0x88,0x88,0x88,0x88,0x88,0xF8},{0xF0,0x88,0x88,0xF0,0x80,0x80,0x80},{0x70,0x88,0x88,0xA8,0xA8,0x90,0x68},{0xF0,0x88,0x88,0xF0,0x90,0x90,0x88},{0x70,0x88,0x80,0x70,0x08,0x88,0x70},{0xF8,0x20,0x20,0x20,0x20,0x20,0x20},{0x88,0x88,0x88,0x88,0x88,0x88,0x70},{0x88,0x88,0x88,0x88,0x88,0x50,0x20},{0x88,0x88,0x88,0x88,0xA8,0xD8,0x88},{0x88,0x88,0x50,0x20,0x50,0x88,0x88},{0x88,0x88,0x50,0x20,0x20,0x20,0x20},{0xF8,0x08,0x10,0x20,0x40,0x80,0xF8},{0x70,0x40,0x40,0x40,0x40,0x40,0x70},{0x00,0x80,0x40,0x20,0x10,0x08,0x00},{0x70,0x10,0x10,0x10,0x10,0x10,0x70},{0x20,0x70,0xA8,0x20,0x20,0x20,0x00},{0x00,0x20,0x40,0xF8,0x40,0x20,0x00},{0x00,0x20,0x20,0x20,0xA8,0x70,0x20},{0x00,0x20,0x10,0xF8,0x10,0x20,0x00},{0x00,0x88,0x50,0x20,0x50,0x88,0x00},{0x00,0x20,0x00,0xF8,0x00,0x20,0x00}}; + +const char SMLFONT[HICHAR-LOCHAR+1][5] = {/*{count:68,w:5,h:5,brev:1}*/ +{ 0x00,0x00,0x00,0x00,0x00 },{ 0x40,0x40,0x00,0x40,0x00 },{ 0xA0,0xA0,0x00,0x00,0x00 },{ 0x60,0xF0,0xF0,0x60,0x00 },{ 0x40,0xE0,0xE0,0x40,0x00 },{ 0x90,0x20,0x40,0x90,0x00 },{ 0xC0,0xB0,0xE0,0xD0,0x00 },{ 0x20,0x40,0x00,0x00,0x00 },{ 0x20,0x40,0x40,0x20,0x00 },{ 0x40,0x20,0x20,0x40,0x00 },{ 0x40,0xE0,0x40,0xA0,0x00 },{ 0x00,0x40,0xE0,0x40,0x00 },{ 0x00,0x00,0x00,0x60,0x20 },{ 0x00,0x00,0xE0,0x00,0x00 },{ 0x00,0x00,0x00,0x40,0x00 },{ 0x20,0x20,0x40,0x40,0x00 },{ 0xE0,0xA0,0xA0,0xA0,0xE0 },{ 0xC0,0x40,0x40,0x40,0xE0 },{ 0xE0,0x20,0xE0,0x80,0xE0 },{ 0xE0,0x20,0x60,0x20,0xE0 },{ 0xA0,0xA0,0xE0,0x20,0x20 },{ 0xE0,0x80,0xE0,0x20,0xE0 },{ 0xE0,0x80,0xE0,0xA0,0xE0 },{ 0xE0,0x20,0x40,0x40,0x40 },{ 0xE0,0xA0,0xE0,0xA0,0xE0 },{ 0xE0,0xA0,0xE0,0x20,0xE0 },{ 0x00,0x40,0x00,0x40,0x00 },{ 0x00,0x40,0x00,0x60,0x20 },{ 0x00,0x20,0x40,0x20,0x00 },{ 0x00,0xE0,0x00,0xE0,0x00 },{ 0x00,0x40,0x20,0x40,0x00 },{ 0xE0,0x20,0x60,0x00,0x40 },{ 0xF0,0x90,0x10,0xD0,0xF0 },{ 0x60,0xA0,0xE0,0xA0,0x00 },{ 0xC0,0xE0,0xA0,0xE0,0x00 },{ 0x60,0x80,0x80,0xE0,0x00 },{ 0xC0,0xA0,0xA0,0xC0,0x00 },{ 0xE0,0xC0,0x80,0xE0,0x00 },{ 0xE0,0xC0,0x80,0x80,0x00 },{ 0x60,0x80,0xA0,0xE0,0x00 },{ 0xA0,0xA0,0xE0,0xA0,0x00 },{ 0xE0,0x40,0x40,0xE0,0x00 },{ 0x60,0x20,0xA0,0xE0,0x00 },{ 0xA0,0xC0,0xC0,0xA0,0x00 },{ 0x80,0x80,0x80,0xE0,0x00 },{ 0xE0,0xE0,0xE0,0xA0,0x00 },{ 0xE0,0xA0,0xA0,0xA0,0x00 },{ 0xE0,0xA0,0xA0,0xE0,0x00 },{ 0xE0,0xA0,0xE0,0x80,0x00 },{ 0xE0,0xA0,0xE0,0xF0,0x00 },{ 0xE0,0xA0,0xC0,0xA0,0x00 },{ 0xE0,0x80,0x60,0xE0,0x00 },{ 0xE0,0x40,0x40,0x40,0x00 },{ 0xA0,0xA0,0xA0,0xE0,0x00 },{ 0xA0,0xA0,0xC0,0x80,0x00 },{ 0xA0,0xE0,0xE0,0xE0,0x00 },{ 0xA0,0x40,0xA0,0xA0,0x00 },{ 0xA0,0xE0,0x40,0x40,0x00 },{ 0xE0,0x20,0x40,0xE0,0x00 },{ 0x60,0x40,0x40,0x60,0x00 },{ 0x40,0x40,0x20,0x20,0x00 },{ 0x60,0x20,0x20,0x60,0x00 },{ 0x40,0xA0,0x00,0x00,0x00 },{ 0x00,0x00,0x00,0x00,0xF0 },{ 0x80,0x40,0x00,0x00,0x00 },{ 0x00,0x60,0xA0,0xE0,0x00 },{ 0x80,0xE0,0xA0,0xE0,0x00 },{ 0x00,0x60,0x80,0xE0,0x00 }}; + +// draw a letter +static byte draw_char(const FontDescriptor* font, byte ch, byte x, byte y, byte op) { + const byte* src = font->chartab + (ch-font->base_ch)*font->pattern_y; + byte* dest = &vmagic[y][x>>2];// destination address + byte magic = M_SHIFT(x) | M_XPAND | (op & 0x30); + // big sizes? + if (op & 0xc0) { + char buf[8]; // expansion buffer + char* mbuf = (buf - 0x4000);// make it magic + byte sc = 1 << (op >> 6); // 2x2 = 2, 4x4 = 4, 8x8 = 8 + for (byte i=0; ipattern_y; i++) { + // expand into magic buffer onto stack + hw_magic = M_XPAND; + hw_xpand = 0b1100; // on = 11, off = 00 + // 2x2 size + mbuf[1] = mbuf[0] = *src++; + // 4x4 size + if (op & 0x80) { + byte b = buf[0]; + mbuf[3] = mbuf[2] = buf[1]; + mbuf[1] = mbuf[0] = b; + } + // 8x8 size + if ((op & 0xc0) == 0xc0) { + byte b = buf[0]; + mbuf[7] = mbuf[6] = buf[3]; + mbuf[5] = mbuf[4] = buf[2]; + mbuf[3] = mbuf[2] = buf[1]; + mbuf[1] = mbuf[0] = b; + } + // draw to screen (magic, again) + hw_xpand = op & 0xf; + for (byte j=0; jpattern_y; i++) { + char b = *src++; + EXIT_CLIPDEST(dest); + hw_magic = magic; // reset flip flop + *dest++ = b; // expand lower nibble -> 1st byte + *dest++ = b; // expand upper nibble -> 2nd byte + *dest++ = 0; // leftover -> 3rd byte + dest += VBWIDTH-3; // we incremented 3 bytes for this line + } + } + return font->frame_x << (op >> 6); +} + +#define FONT_IX ((const FontDescriptor*)ctx->regs.w.ix) + +static void draw_string(ContextBlock *ctx, const char* str, byte x, byte y, byte op) { + do { + byte ch = *str++; + if (!ch) { + _E = x; + break; + } + if (ch < 0x20) { + x += draw_char(&FNTSYS, ' ', x, y, op); // TODO + } else if (ch < 0x64) { + x += draw_char(&FNTSYS, ch, x, y, op); + } else if (ch >= 0x80) { + x += draw_char(FONT_IX, ch, x, y, op); + } else { + /* + if (ch & 0x10) { + ctx->regs.b.ixl = *str++; + ctx->regs.b.ixh = *str++; + } + if (ch & 0x1) + _E = *str++; + if (ch & 0x2) + _D = *str++; + if (ch & 0x4) + _C = *str++; + */ + // TODO: only can change font + } + } while (1); +} + +// String display routine (pass pointer to string) +void STRDIS2(ContextBlock *ctx, char *str) { + byte opts = _C; + byte x = _E; + byte y = _D; + void* fontdesc = (void*) ctx->regs.w.ix; + draw_string(ctx, str, x, y, opts); // TODO: opts +} + +// String display routine +void STRDIS(ContextBlock *ctx) { + char* str = (char*) _HL; + STRDIS2(ctx, str); +} + +// Character display routine +void CHRDIS(ContextBlock *ctx) { + char chstr[2]; + chstr[0] = _A; + chstr[1] = 0; + STRDIS2(ctx, chstr); +} + +// BCD routine +const char BCDTAB[17] = "0123456789*+,-./"; + +// DISNUM - (E.D) x/y (C) options (B) ext (HL) BCD-addr +void DISNUM(ContextBlock *ctx) { + // TODO: options, B + byte x = _E; + byte y = _D; + byte opt = _C; + byte ext = _B; + byte ndigits = ext & 63; + const FontDescriptor* font = (ext&64) ? &FNTSML : &FNTSYS; + byte add = (ext&64) ? 128 : 0; + byte noleadingzero = ext & 128; + byte* pbcd = (byte*) _HL; + pbcd += (ndigits-1)/2; + while (ndigits--) { + byte val = *pbcd; + if (ndigits & 1) { + val >>= 4; + } else { + val &= 15; + pbcd--; + } + x += draw_char(font, BCDTAB[val]+add, x, y, opt); + } +} + +// write pattern (E,D,C,B) magic A @ HL +void WRIT(ContextBlock *ctx) { + byte magic = _A; + byte w = _C; + byte h = _B; + byte x = _E; + byte y = _D; + byte* src = (byte*) _HL; + byte* dest = &vmagic[y][0]; // destination address + byte xb = (magic & M_FLOP) ? (39-(x>>2)) : (x>>2); + byte i,j,b; + // iterate through all lines + for (j=0; j + +#pragma opt_code_speed + +// for SENTRY +extern volatile byte CNT; +extern volatile byte SEMI4S; +extern volatile byte OPOT[4]; +extern volatile byte KEYSEX; +extern volatile byte OSW[4]; +extern volatile word COLLST; +extern volatile byte SENFLG; +extern volatile byte TIMOUT; + +void RCALL(ContextBlock *ctx); +void MCALL(ContextBlock *ctx); + +void SENTRY(ContextBlock *ctx) { + byte i; + byte A = SNUL; + byte B = 0; + byte key = 0; + byte val[4]; + // joysticks and switches + val[0] = hw_p1ctrl; + val[1] = hw_p2ctrl; + val[2] = hw_p3ctrl; + val[3] = hw_p4ctrl; + for (i=0; i<4; i++) { + if (val[i] != OSW[i]) { + A = SJ0+i*2; + if ((val[i] ^ OSW[i]) & 0x10) { + A++; + } + B = val[i]; + } + } + memcpy(OSW, val, 4); // update previous state + // keypad + val[0] = hw_keypad0; + val[1] = hw_keypad1; + val[2] = hw_keypad2; + val[3] = hw_keypad3; + for (i=0; i<4; i++) { + // key down? and with mask + if (val[i] && (val[i] &= ((byte*)_DE)[i])) { + key = i+1; + while (val[i]) { + key += 4; + val[i] >>= 1; + } + } + } + // key up? + if (key && key != KEYSEX) { + B = KEYSEX = key; + A = SKYD; + } + else if (!key && KEYSEX) { + if (KEYSEX & 0x80) { + A = SSEC; // second timer + } else { + A = SKYU; + } + B = 0; + KEYSEX = 0; + } + // pots + val[0] = hw_p1pot; + val[1] = hw_p2pot; + val[2] = hw_p3pot; + val[3] = hw_p4pot; + for (i=0; i<4; i++) { + if (val[i] != OPOT[i]) { + A = SP0+i; + B = val[i]; + } + } + memcpy(OPOT, val, 4); // update previous state + // semiphores + if (SEMI4S) { + B = SEMI4S; + for (i=7; i>=0; i--) { + if (B & 0x80) { + A = SF0+i; + SEMI4S ^= 1 << i; + break; + } + B <<= 1; + } + } + // counters + if (SENFLG) { + B = SENFLG; + for (i=7; i>=0; i--) { + if (B & 0x80) { + A = SF0+i; + SENFLG ^= 1 << i; + break; + } + B <<= 1; + } + } + // clear timeout counter (TODO) + if (A >= SKYU) { + TIMOUT = 0xff; + } + _A = A; + _B = B; +} + +void DOIT(ContextBlock *ctx) { + byte* list = (byte*) _HL; + byte code = _A; + byte op; + while ((op = *list) < 0xc0) { + if ((op & 0x3f) == code) { + _HL = *(word*)(list+1); + switch (op & 0xc0) { + // TODO: JMP + case 0x00: + // RCALL + case 0x40: + RCALL(ctx); + break; + // MCALL + case 0x80: + MCALL(ctx); + break; + } + return; + } + list += 3; + } +} + +void DOITB(ContextBlock *ctx) { + _A = _B; + DOIT(ctx); +} + diff --git a/presets/astrocade/aclib.c b/presets/astrocade/aclib.c index 5fb2ddbf..c079292f 100644 --- a/presets/astrocade/aclib.c +++ b/presets/astrocade/aclib.c @@ -11,7 +11,6 @@ void set_palette(byte palette[8]) __z88dk_fastcall { __asm ld bc,#0x80b ; B -> 8, C -> 0xb otir ; write C bytes from HL to port[B] - ret ; return __endasm; } @@ -22,7 +21,6 @@ void set_sound_registers(byte regs[8]) __z88dk_fastcall { __asm ld bc,#0x818 ; B -> 8, C -> 0x18 otir ; write C bytes from HL to port[B] - ret ; return __endasm; } diff --git a/presets/astrocade/hdr_autostart.s b/presets/astrocade/hdr_autostart.s index 788b22ed..837baf7b 100644 --- a/presets/astrocade/hdr_autostart.s +++ b/presets/astrocade/hdr_autostart.s @@ -17,6 +17,8 @@ Start: ldir ; clear RAM ; initialize INITIALIZED segment ld BC, #l__INITIALIZER + ld a,c + or b jp z,.nomeminit ld A, B ld DE, #s__INITIALIZED diff --git a/presets/astrocade/hello.c b/presets/astrocade/hello.c index b2efc7ae..6a009e73 100644 --- a/presets/astrocade/hello.c +++ b/presets/astrocade/hello.c @@ -27,8 +27,26 @@ const byte BALL[] = { 0b01111000, }; +const byte BALL2[] = { + 0, 0, // x and y offset + 1, 6, // width (bytes) and height (lines) + /*{w:16,h:6,brev:1}*/ + 0b1111000, + 0b11011100, + 0b10111000, + 0b110100, + 0b11100000, + 0b1111000, + 0b1000000, + 0b11010100, + 0b10111100, + 0b10110100, + 0b11111000, + 0b1111000, +}; + // BCD number -static byte bcdnum[3] = {0x56,0x34,0x12}; +byte bcdnum[3] = {0x56,0x34,0x12}; const byte bcdinc[3] = {0x01,0x00,0x00}; const byte keypadMask[4] = { 0x3f,0x3f,0x3f,0x3f }; diff --git a/src/pixed/pixeleditor.ts b/src/pixed/pixeleditor.ts index c7d6ba7c..440402c3 100644 --- a/src/pixed/pixeleditor.ts +++ b/src/pixed/pixeleditor.ts @@ -967,11 +967,11 @@ class PixEditor extends Viewer { this.setPixel(pos.x, pos.y, this.currgba); dragging = true; $(document).mouseup( (e) => { + $(document).off('mouseup'); var pos = this.getPositionFromEvent(e); this.setPixel(pos.x, pos.y, dragcol); dragging = false; this.commit(); - $(document).off('mouseup'); }); }) .mousemove( (e) => { diff --git a/src/platform/astrocade.ts b/src/platform/astrocade.ts index 05e2018e..9a311e14 100644 --- a/src/platform/astrocade.ts +++ b/src/platform/astrocade.ts @@ -477,6 +477,7 @@ const _BallyAstrocadePlatform = function(mainElement, arcade) { ///// +// TODO: https://github.com/mamedev/mame/blob/master/src/devices/sound/astrocde.cpp class AstrocadeAudio extends AY38910_Audio { setACRegister(addr : number, val : number) { addr &= 0x7; diff --git a/src/worker/workermain.ts b/src/worker/workermain.ts index 673da13d..43fc1043 100644 --- a/src/worker/workermain.ts +++ b/src/worker/workermain.ts @@ -242,6 +242,7 @@ var PLATFORM_PARAMS = { //{name:'Cart ROM',start:0x2000,size:0x2000,type:'rom'}, //{name:'Magic RAM',start:0x0,size:0x4000,type:'ram'}, {name:'Screen RAM',start:0x4000,size:0x1000,type:'ram'}, + {name:'BIOS Variables',start:0x4fce,size:0x5000-0x4fce,type:'ram'}, ], }, 'astrocade-arcade': { @@ -1133,26 +1134,33 @@ function hexToArray(s, ofs) { return arr; } -function parseIHX(ihx, rom_start, rom_size) { +function parseIHX(ihx, rom_start, rom_size, errors) { var output = new Uint8Array(new ArrayBuffer(rom_size)); + var high_size = 0; for (var s of ihx.split("\n")) { if (s[0] == ':') { var arr = hexToArray(s, 1); var count = arr[0]; var address = (arr[1]<<8) + arr[2] - rom_start; var rectype = arr[3]; + //console.log(rectype,address.toString(16),count,arr); if (rectype == 0) { for (var i=0; i high_size) high_size = i+address; } else if (rectype == 1) { - return output; + break; } else { console.log(s); // unknown record type } } } + // TODO: return ROM anyway? + if (high_size > rom_size) { + //errors.push({line:0, msg:"ROM size too large: 0x" + high_size.toString(16) + " > 0x" + rom_size.toString(16)}); + } return output; } @@ -1268,6 +1276,10 @@ function linkSDLDZ80(step:BuildStep) if (!anyTargetChanged(step, ["main.ihx", "main.noi"])) return; + var binout = parseIHX(hexout, params.rom_start!==undefined?params.rom_start:params.code_start, params.rom_size, errors); + if (errors.length) { + return {errors:errors}; + } var listings = {}; for (var fn of step.files) { if (fn.endsWith('.lst')) { @@ -1304,7 +1316,8 @@ function linkSDLDZ80(step:BuildStep) let segsize = symbolmap['l__'+seg]; // l__SEG if (segstart >= 0 && segsize > 0) { var type = null; - if (['CODE','INITIALIZER','GSINIT','GSFINAL'].includes(seg)) type = 'rom'; + if (['INITIALIZER','GSINIT','GSFINAL'].includes(seg)) type = 'rom'; + else if (seg.startsWith('CODE')) type = 'rom'; else if (['DATA','INITIALIZED'].includes(seg)) type = 'ram'; if (type == 'rom' || segstart > 0) // ignore HEADER0, CABS0, etc (TODO?) segments.push({name:seg, start:segstart, size:segsize, type:type}); @@ -1312,7 +1325,7 @@ function linkSDLDZ80(step:BuildStep) } } return { - output:parseIHX(hexout, params.rom_start!==undefined?params.rom_start:params.code_start, params.rom_size), + output:binout, listings:listings, errors:errors, symbolmap:symbolmap, diff --git a/test/cli/testworker.js b/test/cli/testworker.js index 5b1dfe90..90cc21bf 100644 --- a/test/cli/testworker.js +++ b/test/cli/testworker.js @@ -301,7 +301,7 @@ describe('Worker', function() { }); it('should compile vicdual skeleton', function(done) { var files = ['skeleton.sdcc', 'cp437.c']; - compileFiles('sdcc', files, 'vicdual', done, 16416, [0,45], 0); // TODO? + compileFiles('sdcc', files, 'vicdual', done, 16416, [2048,45], 0); // TODO? }); it('should compile apple2 skeleton with CC65', function(done) { var csource = ab2str(fs.readFileSync('presets/apple2/skeleton.cc65'));