From 01b01b169acd694279e6d792fa7d76a478167641 Mon Sep 17 00:00:00 2001 From: Steven Hugg Date: Tue, 9 Jun 2020 10:05:46 -0500 Subject: [PATCH] vectrex: got xasm and c working --- presets/vectrex/hello.c | 22 ++ presets/vectrex/hello.xasm | 48 ++++ src/common/baseplatform.ts | 3 - src/common/cpu/6809.js | 1 + src/common/emu.ts | 2 + src/platform/vectrex.ts | 93 ++++-- src/worker/lib/vectrex/assert.h | 20 ++ src/worker/lib/vectrex/bios.h | 203 +++++++++++++ src/worker/lib/vectrex/cmoc.h | 345 +++++++++++++++++++++++ src/worker/lib/vectrex/libcmoc-crt-vec.a | Bin 0 -> 14815 bytes src/worker/lib/vectrex/libcmoc-std-vec.a | Bin 0 -> 24060 bytes src/worker/lib/vectrex/stdarg.h | 22 ++ src/worker/lib/vectrex/stdlib.h | 13 + src/worker/lib/vectrex/vectrex.h | 27 ++ src/worker/lib/vectrex/vectrex.scr | 17 ++ src/worker/workermain.ts | 11 +- 16 files changed, 794 insertions(+), 33 deletions(-) create mode 100644 presets/vectrex/hello.c create mode 100644 presets/vectrex/hello.xasm create mode 100644 src/worker/lib/vectrex/assert.h create mode 100644 src/worker/lib/vectrex/bios.h create mode 100644 src/worker/lib/vectrex/cmoc.h create mode 100644 src/worker/lib/vectrex/libcmoc-crt-vec.a create mode 100644 src/worker/lib/vectrex/libcmoc-std-vec.a create mode 100644 src/worker/lib/vectrex/stdarg.h create mode 100644 src/worker/lib/vectrex/stdlib.h create mode 100644 src/worker/lib/vectrex/vectrex.h create mode 100644 src/worker/lib/vectrex/vectrex.scr diff --git a/presets/vectrex/hello.c b/presets/vectrex/hello.c new file mode 100644 index 00000000..b1a43eab --- /dev/null +++ b/presets/vectrex/hello.c @@ -0,0 +1,22 @@ + +#pragma vx_copyright "2020" +#pragma vx_title_pos -100, -80 +#pragma vx_title_size -8, 80 +#pragma vx_title "HELLO WORLD" +#pragma vx_music vx_music_1 + +#include "vectrex.h" +#include "bios.h" + +int main() +{ + while(1) + { + wait_retrace(); + intensity(0x7f); + print_str_c( 0x10, -0x50, (char*)"HELLO WORLD!" ); + intensity(0x3f); + print_str_c( -0x10, -0x50, (char*)"THIS IS CMOC" ); + } + return 0; +} diff --git a/presets/vectrex/hello.xasm b/presets/vectrex/hello.xasm new file mode 100644 index 00000000..70ddd9f2 --- /dev/null +++ b/presets/vectrex/hello.xasm @@ -0,0 +1,48 @@ +; http://vide.malban.de/help/vectrex-tutorial-ii-starting-with-bios +;*************************************************************************** +; DEFINE SECTION +;*************************************************************************** +Intensity_5F EQU $F2A5 ; BIOS Intensity routine +Print_Str_d EQU $F37A ; BIOS print routine +Wait_Recal EQU $F192 ; BIOS recalibration +music1 EQU $FF8F ; address of a (BIOS ROM) + ; music +; start of vectrex memory with cartridge name... + ORG 0 +;*************************************************************************** +; HEADER SECTION +;*************************************************************************** + FCC "g GCE 1982" + DB $80 ; 'g' is copyright sign + DW music1 ; music from the rom + DB $F8 + DB $50 + DB $20 + DB -$56 ; height, width, rel y, rel x + ; (from 0,0) + FCC "HELLO WORLD PROG 1" + DB $80 ; some game information, + ; ending with $80 + DB 0 ; end of game header +;*************************************************************************** +; CODE SECTION +;*************************************************************************** +; here the cartridge program starts off +main: + JSR Wait_Recal ; Vectrex BIOS recalibration + JSR Intensity_5F ; Sets the intensity of the + ; vector beam to $5f + LDU #hello ; address of string + LDA #$10 ; Text position relative Y + LDB #-$50 ; Text position relative X + JSR Print_Str_d ; Vectrex BIOS print routine + BRA main ; and repeat forever +;*************************************************************************** +; DATA SECTION +;*************************************************************************** +hello: + FCC "HELLO WORLD" ; only capital letters + DB $80 ; $80 is end of string +;*************************************************************************** + END main +;*************************************************************************** diff --git a/src/common/baseplatform.ts b/src/common/baseplatform.ts index d267ade1..32e7b3b9 100644 --- a/src/common/baseplatform.ts +++ b/src/common/baseplatform.ts @@ -589,9 +589,6 @@ export abstract class Base6809Platform extends BaseZ80Platform { return cpu; } - getPC() { return this._cpu.PC; } - getSP() { return this._cpu.SP; } - cpuStateToLongString(c:CpuState) { return cpuStateToLongString_6809(c); } diff --git a/src/common/cpu/6809.js b/src/common/cpu/6809.js index 687b3d12..d90ff16a 100644 --- a/src/common/cpu/6809.js +++ b/src/common/cpu/6809.js @@ -2371,6 +2371,7 @@ return { reset(); }, getPC: function() { return PC; }, + getSP: function() { return rS; }, saveState: function() { return { PC:PC, diff --git a/src/common/emu.ts b/src/common/emu.ts index 69711583..4aa30d0f 100644 --- a/src/common/emu.ts +++ b/src/common/emu.ts @@ -349,6 +349,8 @@ export const Keys = { B: {c: 16, n: "Shift", plyr:0, button:1}, GP_A: {c: 88, n: "X", plyr:0, button:0}, GP_B: {c: 90, n: "Z", plyr:0, button:1}, + GP_C: {c: 83, n: "S", plyr:0, button:2}, + GP_D: {c: 65, n: "A", plyr:0, button:3}, SELECT: {c: 220, n: "\\", plyr:0, button:8}, START: {c: 13, n: "Enter", plyr:0, button:9}, // gamepad and keyboard (player 1) diff --git a/src/platform/vectrex.ts b/src/platform/vectrex.ts index 45570daf..788a1b5d 100644 --- a/src/platform/vectrex.ts +++ b/src/platform/vectrex.ts @@ -3,6 +3,8 @@ import { Platform, BaseZ80Platform, Base6502Platform, Base6809Platform } from ". import { PLATFORMS, newAddressDecoder, padBytes, noise, setKeyboardFromMap, AnimationTimer, VectorVideo, Keys, makeKeycodeMap } from "../common/emu"; import { hex, lzgmini, stringToByteArray, safe_extend } from "../common/util"; import { MasterAudio, AY38910_Audio } from "../common/audio"; +import { ProbeRecorder } from "../common/recorder"; +import { NullProbe, Probeable, ProbeAll } from "../common/devices"; // emulator from https://github.com/raz0red/jsvecx // https://roadsidethoughts.com/vectrex/vectrex-memory-map.htm @@ -14,19 +16,19 @@ import { MasterAudio, AY38910_Audio } from "../common/audio"; var VECTREX_PRESETS = [ { id: 'hello.xasm', name: 'Hello World (ASM)' }, + { id: 'hello.c', name: 'Hello World (CMOC)' }, ] +// TODO: player 2 var VECTREX_KEYCODE_MAP = makeKeycodeMap([ - [Keys.B, 3, 0xff], - [Keys.A, 4, 0xff], - [Keys.SELECT, 8, 0xff], - [Keys.VK_6, 9, 0xff], - [Keys.VK_7, 10, 0xff], - [Keys.START, 11, 0xff], - [Keys.P2_START, 12, 0xff], - [Keys.UP, 13, 0xff], - [Keys.RIGHT, 14, 0xff], - [Keys.LEFT, 15, 0xff], + [Keys.LEFT, 0, 0x01], + [Keys.RIGHT, 0, 0x02], + [Keys.DOWN, 0, 0x04], + [Keys.UP, 0, 0x08], + [Keys.GP_A, 2, 0x01], + [Keys.GP_B, 2, 0x02], + [Keys.GP_C, 2, 0x04], + [Keys.GP_D, 2, 0x08], ]); // @@ -137,7 +139,7 @@ class VIA6522 { /* continuous interrupt mode */ this.ifr |= 0x40; this.int_update(); - this.t1pb7 = 0x80 - this.t1pb7; + this.t1pb7 ^= 0x80; /* reload counter */ this.t1c = (this.t1lh << 8) | this.t1ll; } @@ -284,6 +286,7 @@ class VIA6522 { if ((this.orb & 0x18) == 0x08) { /* the snd chip is driving port a */ data = this.vectrex.psg.readData(); + //console.log(this.vectrex.psg.currentRegister(), data); } else { data = this.ora; @@ -484,10 +487,14 @@ const Globals = VECTREX_COLORS: 128, /* number of possible colors ... grayscale */ ALG_MAX_X: 33000, ALG_MAX_Y: 41000, - VECTREX_PDECAY: 30, /* phosphor decay rate */ - VECTOR_HASH: 65521, - SCREEN_X_DEFAULT: 330, - SCREEN_Y_DEFAULT: 410 + //VECTREX_PDECAY: 30, /* phosphor decay rate */ + //VECTOR_HASH: 65521, + SCREEN_X_DEFAULT: 900, + SCREEN_Y_DEFAULT: 1100, + BOUNDS_MIN_X: 0, + BOUNDS_MAX_X: 30000, + BOUNDS_MIN_Y: 41000, + BOUNDS_MAX_Y: 0, }; class VectrexAnalog { @@ -616,14 +623,14 @@ class VectrexAnalog { var sig_ramp = 0; var sig_blank = 0; - if ((via.acr & 0x10) == 0x10) { + if (via.acr & 0x10) { sig_blank = via.cb2s; } else { sig_blank = via.cb2h; } - if (via.ca2) // pulse mode + if (via.ca2 == 0) { /* need to force the current point to the 'orgin' so just * calculate distance to origin and use that as dx,dy. @@ -648,6 +655,7 @@ class VectrexAnalog { sig_dy = 0; } } + //if (sig_dx || sig_dy) console.log(via.ca2, this.curr_x, this.curr_y, this.dx, this.dy, sig_dx, sig_dy, sig_ramp, sig_blank); if (!this.vectoring) { if (sig_blank == 1 && @@ -724,6 +732,11 @@ class VectrexAnalog { addline(x0, y0, x1, y1, color) { // TODO //console.log(x0, y0, x1, y1, color); + x0 = (x0 - Globals.BOUNDS_MIN_X) / (Globals.BOUNDS_MAX_X - Globals.BOUNDS_MIN_X) * Globals.SCREEN_X_DEFAULT; + x1 = (x1 - Globals.BOUNDS_MIN_X) / (Globals.BOUNDS_MAX_X - Globals.BOUNDS_MIN_X) * Globals.SCREEN_X_DEFAULT; + y0 = (y0 - Globals.BOUNDS_MIN_Y) / (Globals.BOUNDS_MAX_Y - Globals.BOUNDS_MIN_Y) * Globals.SCREEN_Y_DEFAULT; + y1 = (y1 - Globals.BOUNDS_MIN_Y) / (Globals.BOUNDS_MAX_Y - Globals.BOUNDS_MIN_Y) * Globals.SCREEN_Y_DEFAULT; + this.vectrex.video.drawLine(x0, y0, x1, y1, color, 7); } saveState() { @@ -772,9 +785,8 @@ class VectrexPlatform extends Base6809Platform { this.alg = new VectrexAnalog(this); this.bios = padBytes(new lzgmini().decode(stringToByteArray(atob(VECTREX_FASTROM_LZG))), 0x2000); this.ram = new Uint8Array(0x400); - this.inputs = new Uint8Array(16); - this.bus = { - + this.inputs = new Uint8Array(4); + var mbus = { read: newAddressDecoder([ [0x0000, 0x7fff, 0, (a) => { return this.rom && this.rom[a]; }], [0xc800, 0xcfff, 0x3ff, (a) => { return this.ram[a]; }], @@ -787,26 +799,43 @@ class VectrexPlatform extends Base6809Platform { [0xd000, 0xd7ff, 0x3ff, (a, v) => { this.via.write(a & 0xf, v); }], [0xd800, 0xdfff, 0x3ff, (a, v) => { this.ram[a] = v; this.via.write(a & 0xf, v); }], ]) - + }; + this.bus = { + read: (a) => { var v = mbus.read(a); this.probe.logRead(a,v); return v; }, + write: (a,v) => { this.probe.logWrite(a,v); mbus.write(a,v); } }; this._cpu = this.newCPU(this.bus); // create video/audio - this.video = new VectorVideo(this.mainElement, 660, 820); + this.video = new VectorVideo(this.mainElement, Globals.SCREEN_X_DEFAULT, Globals.SCREEN_Y_DEFAULT); + this.video.persistenceAlpha = 0.2; this.audio = new MasterAudio(); this.psg = new AY38910_Audio(this.audio); this.video.create(); this.timer = new AnimationTimer(60, this.nextFrame.bind(this)); - setKeyboardFromMap(this.video, this.inputs, VECTREX_KEYCODE_MAP); + setKeyboardFromMap(this.video, this.inputs, VECTREX_KEYCODE_MAP); // true = always send function); } - advance() { + updateControls() { + // joystick (analog simulation) + this.alg.jch0 = (this.inputs[0] & 0x1) ? 0x00 : (this.inputs[0] & 0x2) ? 0xff : 0x80; + this.alg.jch1 = (this.inputs[0] & 0x4) ? 0x00 : (this.inputs[0] & 0x8) ? 0xff : 0x80; + // buttons (digital) + this.psg.psg.register[14] = ~this.inputs[2]; + } + + advance(novideo:boolean) { + if (!novideo) this.video.clear(); + this.updateControls(); + this.probe.logNewFrame(); var cycles = 1500000 / 60; while (cycles > 0) { + this.probe.logExecute(this.getPC(), this.getSP()); if (this.via.ifr & 0x80) { this._cpu.interrupt(); } var n = this.runCPU(this._cpu, 1); if (n == 0) n = 1; // TODO? + this.probe.logClocks(n); cycles -= n; for (; n > 0; n--) { this.via.step0(); @@ -919,6 +948,22 @@ class VectrexPlatform extends Base6809Platform { default: return super.getDebugInfo(category, state); } } + + // probing + nullProbe = new NullProbe(); + probe : ProbeAll = this.nullProbe; + + startProbing?() : ProbeRecorder { + var rec = new ProbeRecorder(this); + this.connectProbe(rec); + return rec; + } + stopProbing?() : void { + this.connectProbe(null); + } + connectProbe(probe:ProbeAll) { + this.probe = probe || this.nullProbe; + } } // diff --git a/src/worker/lib/vectrex/assert.h b/src/worker/lib/vectrex/assert.h new file mode 100644 index 00000000..45d9fba0 --- /dev/null +++ b/src/worker/lib/vectrex/assert.h @@ -0,0 +1,20 @@ +/* assert.h - Assert macro for CMOC + + By Pierre Sarrazin . + This file is in the public domain. +*/ + +#ifndef _ASSERT_H +#define _ASSERT_H + +#include "cmoc.h" + +#ifdef NDEBUG +#define assert(cond) +#else +#define assert(cond) do { if (!(cond)) { \ + printf("***ASSERT FAILED: %s:%u: %s\n", __FILE__, __LINE__, #cond); \ + for (;;); } } while (0) +#endif + +#endif /* _ASSERT_H */ diff --git a/src/worker/lib/vectrex/bios.h b/src/worker/lib/vectrex/bios.h new file mode 100644 index 00000000..f9c9b9d1 --- /dev/null +++ b/src/worker/lib/vectrex/bios.h @@ -0,0 +1,203 @@ +#ifndef __vectrex_bios_h__ +#define __vectrex_bios_h__ + +#include "vectrex.h" + +// Expose Vectrex music addreses +#define vx_music_1 (char*) 0xFD0D +#define vx_music_2 (char*) 0xFD1D +#define vx_music_3 (char*) 0xFD81 +#define vx_music_4 (char*) 0xFDD3 +#define vx_music_5 (char*) 0xFE38 +#define vx_music_6 (char*) 0xFE76 +#define vx_music_7 (char*) 0xFEC6 +#define vx_music_8 (char*) 0xFEF8 +#define vx_music_9 (char*) 0xFF26 +#define vx_music_10 (char*) 0xFF44 +#define vx_music_11 (char*) 0xFF62 +#define vx_music_12 (char*) 0xFF7A +#define vx_music_13 (char*) 0xFF8F + +#define JOY1_BTN1 0 +#define JOY1_BTN2 1 +#define JOY1_BTN3 2 +#define JOY1_BTN4 3 + +#define JOY2_BTN1 4 +#define JOY2_BTN2 5 +#define JOY2_BTN3 6 +#define JOY2_BTN4 7 + +#define JOY1_BTN1_MASK (1<. +// This file is in the public domain. +// +// Functions not documented here should be assumed to behave as in C. + +#ifndef _H_CMOC +#define _H_CMOC + +#ifndef __GNUC__ + +#ifndef NULL +#define NULL ((void *) 0) +#endif + + +#ifndef _CMOC_CONST_ +#define _CMOC_CONST_ const +#endif + + +// Gives the offset in bytes of the specified 'member' in the struct +// or union named 'Type'. +// +#define offsetof(Type, member) ((unsigned) &((Type *) 0)->member) + +typedef unsigned size_t; + + +#ifndef VECTREX +// Supports %u, %d, %x, %X, %p, %s, %c and %%. Specifying a field width is +// allowed, but a left justification is only supported for strings, i.e., +// %-15s will work, but %-6u will not. Zero padding for a number is supported +// (e.g., %04x). +// +int printf(_CMOC_CONST_ char *format, ...); +#endif + + +// Writes to 'dest'. Not thread-safe. Does not check for buffer overflow. +int sprintf(char *dest, _CMOC_CONST_ char *format, ...); + + +#ifndef VECTREX +// Writes the first 'n' characters designated by 's', regardless of any +// null characters encountered among them. +// +void putstr(_CMOC_CONST_ char *s, size_t n); + +void putchar(int c); +#endif + +int strcmp(_CMOC_CONST_ char *s1, _CMOC_CONST_ char *s2); +int stricmp(_CMOC_CONST_ char *s1, _CMOC_CONST_ char *s2); +int memcmp(_CMOC_CONST_ void *s1, _CMOC_CONST_ void *s2, size_t n); +int memicmp(_CMOC_CONST_ void *s1, _CMOC_CONST_ void *s2, size_t n); +void *memcpy(void *dest, _CMOC_CONST_ void *src, size_t n); +void *memset(void *s, int c, size_t n); +size_t strlen(_CMOC_CONST_ char *s); +char *strcpy(char *dest, _CMOC_CONST_ char *src); +char *strcat(char *dest, _CMOC_CONST_ char *src); +char *strncpy(char *dest, _CMOC_CONST_ char *src, size_t n); +char *strchr(_CMOC_CONST_ char *s, int c); +char *strstr(const char *haystack, const char *needle); +char *strlwr(char *s); +char *strupr(char *s); + + +// Converts an ASCII unsigned decimal string into an unsigned word. +// +unsigned atoui(_CMOC_CONST_ char *s); + + +// Converts an ASCII signed decimal string into a signed word. +// +int atoi(_CMOC_CONST_ char *s); + + +// Converts an integer to a NUL-terminated ASCII signed decimal string. +// Returns 'str'. +// The caller must be careful to pass an array of sufficient size, +// including room for the terminating '\0'. +// +char *itoa10(int value, char *str); + + +// Converts an integer to a NUL-terminated ASCII signed decimal string. +// N.B.: 'base' must be 10. No other base is supported by this implementation. +// Returns 'str'. +// The caller must be careful to pass an array of sufficient size, +// including room for the terminating '\0'. +// +#define itoa(value, str, base) (itoa10((value), (str))) + + +// Like itoa10(), but 'value' can be in the range 32768..65535. +// +char *utoa10(unsigned value, char *str); + + +// Like itoa(), but 'value' can be in the range 32768..65535. +// N.B.: 'base' must be 10. No other base is supported by this implementation. +// +#define utoa(value, str, base) (utoa10((value), (str))) + + +// Like itoa10(), but 'value' can be 32 bits. +// +char *ltoa10(long value, char *str); + + +// Like itoa(), but 'value' can be 32 bits. +// N.B.: 'base' must be 10. No other base is supported by this implementation. +// +#define ltoa(value, str, base) (ltoa10((value), (str))) + + +// Like utoa10(), but 'value' can be 32 bits. +// +char *ultoa10(unsigned long value, char *str); + + +// Like utoa(), but 'value' can be 32 bits. +// N.B.: 'base' must be 10. No other base is supported by this implementation. +// +#define ultoa(value, str, base) (ultoa10((value), (str))) + + +// Double-word to ASCII. +// Converts the unsigned 32-bit integer formed by hi * 65536 + lo into +// an ASCII decimal representation that gets written to 'out'. +// 'out' must point to at least 11 bytes. The string written there will +// be terminated by a null character. +// Returns the address of the first non-'0' character in the 11-byte +// buffer, or to "0" if hi and lo are both zero. +// Example: char s[11]; char *p = dwtoa(s, 1, 2); +// s will get the string " +// NOTE: This operation can also be done with the 'long' type and by +// calling sprintf() with the "%lu" or "%ld" placeholders. +// +char *dwtoa(char *out, unsigned hi, unsigned lo); + + +// Returns the integer part of the square root of n. +// +unsigned char sqrt16(unsigned n); + + +// Returns the quotient and remainder of a 16-bit unsigned division +// in a single operation. +// +void divmod16(unsigned dividend, unsigned divisor, + unsigned *quotient, unsigned *remainder); + + +// Returns the quotient and remainder of an 8-bit unsigned division +// in a single operation. +// +void divmod8(unsigned char dividend, unsigned char divisor, + unsigned char *quotient, unsigned char *remainder); + + +// Divides an unsigned 32-bit integer by an unsigned 8-bit integer. +// The two words designated by 'dividendInQuotientOut' are the input dividend. +// The 32-bit quotient is left in those two words. +// +void divdwb(unsigned dividendInQuotientOut[2], unsigned char divisor); + + +// Previous name of divdwb(). +// +#define div328 divdwb + + +// Divides an unsigned 32-bit integer by an unsigned 16-bit integer. +// The two words designated by 'dividendInQuotientOut' are the input dividend. +// The 32-bit quotient is left in those two words. +// +void divdww(unsigned dividendInQuotientOut[2], unsigned divisor); + + +// Multiply a word by a byte. +// Stores the high word of the product in *hi and returns the low word. +// +unsigned mulwb(unsigned char *hi, unsigned wordFactor, unsigned char byteFactor); + + +// Similar to mulwb(). +unsigned mulww(unsigned *hi, unsigned factor0, unsigned factor1); + + +// Stores 0 in twoWords[0], twoWords[1]. +// +void zerodw(unsigned *twoWords); + + +// Adds the 16-bit integer 'term' to the 32-bit integer designated by +// twoWords[0] and twoWords[1]. +// +void adddww(unsigned *twoWords, unsigned term); + + +// Subtracts the 16-bit integer 'term' from the 32-bit integer designated by +// twoWords[0] and twoWords[1]. +// +void subdww(unsigned *twoWords, unsigned term); + + +// Returns 0 if the 32-bit unsigned word composed of left[0] and left[1] +// (where left[0] is the high word) is equal to 'right'; +// returns +1 if left > right; -1 if left < right. +// +char cmpdww(unsigned left[2], unsigned right); + + +#ifdef _COCO_BASIC_ + +// Converts an ASCII decimal floating point number to a float. +// The string is allowed to contain a suffix (e.g., "1.2E6XYZ"); +// endptr: Receives the address where the parsing stopped. +// Caution: Passing a string whose value does not fit in a float +// may have undefined behavior. +// An 'E' used in exponential notation must be in upper-case. +// +float strtof(_CMOC_CONST_ char *nptr, char **endptr); + + +// Like strtof(), but does not return the end pointer. +// +float atoff(_CMOC_CONST_ char *nptr); + + +// Writes an ASCII decimal representation of 'f' in the buffer +// at 'out' which must contain at least 38 bytes. +// Returns 'out' upon success, or null upon failure. +// +char *ftoa(char out[38], float f); + +#endif /* _COCO_BASIC_ */ + + +// CAUTION: base is ignored, only base 10 is supported. +// +unsigned long strtoul(_CMOC_CONST_ char *nptr, char **endptr, int base); + +unsigned long atoul(_CMOC_CONST_ char *nptr); + +// CAUTION: base is ignored, only base 10 is supported. +// +long strtol(_CMOC_CONST_ char *nptr, char **endptr, int base); + +long atol(_CMOC_CONST_ char *nptr); + +int tolower(int c); +int toupper(int c); +void exit(int status); + +#define RAND_MAX 0x7FFF +void srand(unsigned seed); +int rand(); + +// See the CMOC manual. +void *sbrk(size_t increment); +size_t sbrkmax(); +void set_null_ptr_handler(void (*newHandler)(void *)); +void set_stack_overflow_handler(void (*newHandler)(void *, void *)); + + +// Function pointer type used by setConsoleOutHook(). +// +typedef void (*ConsoleOutHook)(); + + +// Redirect printf() et al. to the function at 'routine', which will +// receive each character to be printed in register A. +// +// That routine MUST preserve registers B, X, Y and U. +// +// If this function is never called, printf() et al. write to the +// system's standard character output routine. +// +// Returns the original output routine address. +// To uninstall the new routine, call this function again with +// the original routine address. +// +ConsoleOutHook setConsoleOutHook(ConsoleOutHook routine); + + +#ifndef VECTREX + +// Blocks the execution for the specified time in 60ths of a second. +// +void delay(size_t sixtiethsOfASecond); + + +// Reads a line from standard input, converts an expected 16-bit decimal +// number and returns it. Not thread-safe. +// +unsigned readword(); + + +// Reads a line from standard input and returns it. +// Not thread-safe. +// Returns a null pointer if the operation failed (e.g., end of file +// encountered). +// +char *readline(); + +#endif /* ndef VECTREX */ + + +// Sorts an array that starts at 'base', that has 'nmemb' elements, whose +// elements are 'size' bytes each. +// compar: Pointer to a function that receives pointers to two array elements +// and that returns -1, 0 or +1 depending on whether the first element +// comes before, is equal to, or comes after the second element. +// This function is recursive and will thus use stack space. +// +void qsort(void *base, size_t nmemb, size_t size, int (*compar)(_CMOC_CONST_ void *, _CMOC_CONST_ void *)); + + +// Searches for the value pointed to by 'key' in the array starting at 'base', +// that has 'nmemb' elements, whose elements are 'size' bytes each. +// compar: Pointer to a function that receives pointers to the targeted key and +// to an array element. It must return -1, 0 or +1 depending on whether +// the targeted key comes before, is equal to, or comes after the second element. +// Returns a pointer to the element of the array that matches the targeted key, +// or NULL if none is found. +// The time taken by this function is proportional to the logarithm of the array size. +// This function is recursive and will thus use stack space. +// +void *bsearch(const void *key, const void *base, size_t nmemb, size_t size, + int (*compar)(_CMOC_CONST_ void *key, _CMOC_CONST_ void *element)); + + +#else + +#include +#include +#include + +#endif /* __GNUC__ */ + +#endif /* _H_CMOC */ diff --git a/src/worker/lib/vectrex/libcmoc-crt-vec.a b/src/worker/lib/vectrex/libcmoc-crt-vec.a new file mode 100644 index 0000000000000000000000000000000000000000..79aa2eaccba687bcbc1f0680ec4c82b520b779d4 GIT binary patch literal 14815 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 literal 0 HcmV?d00001 diff --git a/src/worker/lib/vectrex/libcmoc-std-vec.a b/src/worker/lib/vectrex/libcmoc-std-vec.a new file mode 100644 index 0000000000000000000000000000000000000000..7d093bd5e2c0603d6e014609dcacbd6c65e50535 GIT binary patch literal 24060 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 literal 0 HcmV?d00001 diff --git a/src/worker/lib/vectrex/stdarg.h b/src/worker/lib/vectrex/stdarg.h new file mode 100644 index 00000000..e3d0b345 --- /dev/null +++ b/src/worker/lib/vectrex/stdarg.h @@ -0,0 +1,22 @@ +/* stdarg.h - Support for variable argument functions + + By Pierre Sarrazin . + This file is in the public domain. +*/ + +#ifndef _stdarg_h_ +#define _stdarg_h_ + + +typedef char *va_list; + + +char *__va_arg(va_list *app, unsigned int sizeInBytes); + + +#define va_start(ap, lastFixed) do { (ap) = (char *) &(lastFixed) + sizeof(lastFixed); } while (0) +#define va_arg(ap, type) (* (type *) __va_arg(&(ap), sizeof(type))) +#define va_end(ap) do {} while (0) + + +#endif /* _stdarg_h_ */ diff --git a/src/worker/lib/vectrex/stdlib.h b/src/worker/lib/vectrex/stdlib.h new file mode 100644 index 00000000..e24bdcce --- /dev/null +++ b/src/worker/lib/vectrex/stdlib.h @@ -0,0 +1,13 @@ +#ifndef __vectrex_stdlib_h__ +#define __vectrex_stdlib_h__ + +/** + * Most stdlib functions are supported on the Vectrex, except those that imply having a keyboard and console: + * printf, putsr, putchar, readword, readline. + * Also delay is not implemented as it does not seem to make much sense to have a delay function on the Vectrex. + */ + +#include "vectrex.h" +#include "cmoc.h" + +#endif // __vectrex_stdlib_h__ diff --git a/src/worker/lib/vectrex/vectrex.h b/src/worker/lib/vectrex/vectrex.h new file mode 100644 index 00000000..589f0221 --- /dev/null +++ b/src/worker/lib/vectrex/vectrex.h @@ -0,0 +1,27 @@ +// This file is in the public domain. + +#ifndef __vectrex_h__ +#define __vectrex_h__ + +enum { FALSE, TRUE }; + +#ifndef _CMOC_BASIC_TYPES_ +#define _CMOC_BASIC_TYPES_ + +typedef unsigned char byte; +typedef signed char sbyte; +typedef unsigned int word; +typedef signed int sword; +typedef unsigned long dword; +typedef signed long sdword; + +#endif + +typedef unsigned char uint8_t; +typedef signed char int8_t; +typedef unsigned int uint16_t; +typedef signed int int16_t; +typedef unsigned long uint32_t; +typedef signed long int32_t; + +#endif diff --git a/src/worker/lib/vectrex/vectrex.scr b/src/worker/lib/vectrex/vectrex.scr new file mode 100644 index 00000000..4cfe78bf --- /dev/null +++ b/src/worker/lib/vectrex/vectrex.scr @@ -0,0 +1,17 @@ +define basesympat s_%s +define lensympat l_%s +section start load 0 +section code +section constructors_start +section constructors +section constructors_end +section destructors_start +section destructors +section destructors_end +section initgl_start +section initgl +section initgl_end +section rodata +section rwdata load c880 +section bss,bss +entry program_start diff --git a/src/worker/workermain.ts b/src/worker/workermain.ts index bf391e21..ad87fa34 100644 --- a/src/worker/workermain.ts +++ b/src/worker/workermain.ts @@ -253,7 +253,9 @@ var PLATFORM_PARAMS = { data_start: 0xc880, data_size: 0x380, stack_end: 0xcc00, + extra_compile_files: ['assert.h','cmoc.h','stdarg.h','vectrex.h','stdlib.h','bios.h'], extra_link_files: ['vectrex.scr', 'libcmoc-crt-vec.a', 'libcmoc-std-vec.a'], + extra_compile_args: ['--vectrex'], extra_link_args: ['-svectrex.scr', '-lcmoc-crt-vec', '-lcmoc-std-vec'], }, }; @@ -2099,12 +2101,6 @@ function compileCMOC(step:BuildStep) { //logReadFiles:true, print:match_fn, printErr:match_fn, - //arguments:args, - /* - locateFile: (path,prefix) => { - return prefix + 'wasm/' + path; - } - */ }); // load source file and preprocess var code = getWorkFileAsString(step.path); @@ -2117,6 +2113,9 @@ function compileCMOC(step:BuildStep) { populateFiles(step, FS); FS.writeFile(step.path, code); fixParamsWithDefines(step.path, params); + if (params.extra_compile_args) { + args.unshift.apply(args, params.extra_compile_args); + } execMain(step, CMOC, args); if (errors.length) return {errors:errors};