williams: working on cmoc
This commit is contained in:
parent
c7f0fd4cd0
commit
2d02b64464
|
@ -208,6 +208,8 @@ if (window.location.host.endsWith('8bitworkshop.com')) {
|
||||||
<li><a class="dropdown-item" href="?platform=vcs.mame">Atari 2600 (MAME)</a></li>
|
<li><a class="dropdown-item" href="?platform=vcs.mame">Atari 2600 (MAME)</a></li>
|
||||||
<li><a class="dropdown-item" href="?platform=coleco.mame">ColecoVision (MAME)</a></li>
|
<li><a class="dropdown-item" href="?platform=coleco.mame">ColecoVision (MAME)</a></li>
|
||||||
<li><a class="dropdown-item" href="?platform=nes.mame">NES (MAME)</a></li>
|
<li><a class="dropdown-item" href="?platform=nes.mame">NES (MAME)</a></li>
|
||||||
|
<hr>
|
||||||
|
<li><a class="dropdown-item" href="?platform=williams">Williams (6809)</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
|
||||||
|
#include "williams.h"
|
||||||
|
//#link "williams.c"
|
||||||
|
|
||||||
|
// 256x304x4bpp video memory
|
||||||
|
|
||||||
|
#define LOCHAR 0x21
|
||||||
|
#define HICHAR 0x5e
|
||||||
|
|
||||||
|
const byte font8x8[HICHAR-LOCHAR+1][8] = {
|
||||||
|
{ 0x18,0x18,0x18,0x18,0x00,0x00,0x18,0x00 }, { 0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x00 }, { 0x66,0x66,0xff,0x66,0xff,0x66,0x66,0x00 }, { 0x18,0x3e,0x60,0x3c,0x06,0x7c,0x18,0x00 }, { 0x62,0x66,0x0c,0x18,0x30,0x66,0x46,0x00 }, { 0x3c,0x66,0x3c,0x38,0x67,0x66,0x3f,0x00 }, { 0x06,0x0c,0x18,0x00,0x00,0x00,0x00,0x00 }, { 0x0c,0x18,0x30,0x30,0x30,0x18,0x0c,0x00 }, { 0x30,0x18,0x0c,0x0c,0x0c,0x18,0x30,0x00 }, { 0x00,0x66,0x3c,0xff,0x3c,0x66,0x00,0x00 }, { 0x00,0x18,0x18,0x7e,0x18,0x18,0x00,0x00 }, { 0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x30 }, { 0x00,0x00,0x00,0x7e,0x00,0x00,0x00,0x00 }, { 0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00 }, { 0x00,0x03,0x06,0x0c,0x18,0x30,0x60,0x00 }, { 0x3c,0x66,0x6e,0x76,0x66,0x66,0x3c,0x00 }, { 0x18,0x18,0x38,0x18,0x18,0x18,0x7e,0x00 }, { 0x3c,0x66,0x06,0x0c,0x30,0x60,0x7e,0x00 }, { 0x3c,0x66,0x06,0x1c,0x06,0x66,0x3c,0x00 }, { 0x06,0x0e,0x1e,0x66,0x7f,0x06,0x06,0x00 }, { 0x7e,0x60,0x7c,0x06,0x06,0x66,0x3c,0x00 }, { 0x3c,0x66,0x60,0x7c,0x66,0x66,0x3c,0x00 }, { 0x7e,0x66,0x0c,0x18,0x18,0x18,0x18,0x00 }, { 0x3c,0x66,0x66,0x3c,0x66,0x66,0x3c,0x00 }, { 0x3c,0x66,0x66,0x3e,0x06,0x66,0x3c,0x00 }, { 0x00,0x00,0x18,0x00,0x00,0x18,0x00,0x00 }, { 0x00,0x00,0x18,0x00,0x00,0x18,0x18,0x30 }, { 0x0e,0x18,0x30,0x60,0x30,0x18,0x0e,0x00 }, { 0x00,0x00,0x7e,0x00,0x7e,0x00,0x00,0x00 }, { 0x70,0x18,0x0c,0x06,0x0c,0x18,0x70,0x00 }, { 0x3c,0x66,0x06,0x0c,0x18,0x00,0x18,0x00 }, { 0x3c,0x66,0x6e,0x6e,0x60,0x62,0x3c,0x00 }, { 0x18,0x3c,0x66,0x7e,0x66,0x66,0x66,0x00 }, { 0x7c,0x66,0x66,0x7c,0x66,0x66,0x7c,0x00 }, { 0x3c,0x66,0x60,0x60,0x60,0x66,0x3c,0x00 }, { 0x78,0x6c,0x66,0x66,0x66,0x6c,0x78,0x00 }, { 0x7e,0x60,0x60,0x78,0x60,0x60,0x7e,0x00 }, { 0x7e,0x60,0x60,0x78,0x60,0x60,0x60,0x00 }, { 0x3c,0x66,0x60,0x6e,0x66,0x66,0x3c,0x00 }, { 0x66,0x66,0x66,0x7e,0x66,0x66,0x66,0x00 }, { 0x3c,0x18,0x18,0x18,0x18,0x18,0x3c,0x00 }, { 0x1e,0x0c,0x0c,0x0c,0x0c,0x6c,0x38,0x00 }, { 0x66,0x6c,0x78,0x70,0x78,0x6c,0x66,0x00 }, { 0x60,0x60,0x60,0x60,0x60,0x60,0x7e,0x00 }, { 0x63,0x77,0x7f,0x6b,0x63,0x63,0x63,0x00 }, { 0x66,0x76,0x7e,0x7e,0x6e,0x66,0x66,0x00 }, { 0x3c,0x66,0x66,0x66,0x66,0x66,0x3c,0x00 }, { 0x7c,0x66,0x66,0x7c,0x60,0x60,0x60,0x00 }, { 0x3c,0x66,0x66,0x66,0x66,0x3c,0x0e,0x00 }, { 0x7c,0x66,0x66,0x7c,0x78,0x6c,0x66,0x00 }, { 0x3c,0x66,0x60,0x3c,0x06,0x66,0x3c,0x00 }, { 0x7e,0x18,0x18,0x18,0x18,0x18,0x18,0x00 }, { 0x66,0x66,0x66,0x66,0x66,0x66,0x3c,0x00 }, { 0x66,0x66,0x66,0x66,0x66,0x3c,0x18,0x00 }, { 0x63,0x63,0x63,0x6b,0x7f,0x77,0x63,0x00 }, { 0x66,0x66,0x3c,0x18,0x3c,0x66,0x66,0x00 }, { 0x66,0x66,0x66,0x3c,0x18,0x18,0x18,0x00 }, { 0x7e,0x06,0x0c,0x18,0x30,0x60,0x7e,0x00 }, { 0x3c,0x30,0x30,0x30,0x30,0x30,0x3c,0x00 }, { 0x00,0x60,0x30,0x18,0x0c,0x06,0x03,0x00 }, { 0x3c,0x0c,0x0c,0x0c,0x0c,0x0c,0x3c,0x00 }, { 0x00,0x18,0x3c,0x7e,0x18,0x18,0x18,0x18 }
|
||||||
|
};
|
||||||
|
|
||||||
|
const byte sprite1[] = {
|
||||||
|
8,16,
|
||||||
|
0x00,0x09,0x99,0x00,0x00,0x99,0x90,0x00,
|
||||||
|
0x00,0x94,0x94,0x90,0x09,0x49,0x49,0x00,
|
||||||
|
0x04,0x49,0x49,0x90,0x09,0x94,0x94,0x90,
|
||||||
|
0x94,0x99,0x94,0x90,0x09,0x49,0x99,0x49,
|
||||||
|
0x99,0x99,0x49,0x93,0x39,0x94,0x99,0x99,
|
||||||
|
0x04,0x49,0x99,0x94,0x49,0x99,0x94,0x90,
|
||||||
|
0x00,0x94,0x94,0x43,0x34,0x49,0x49,0x00,
|
||||||
|
0x00,0x09,0x43,0x94,0x49,0x34,0x90,0x00,
|
||||||
|
0x00,0x90,0x00,0x39,0x93,0x00,0x09,0x00,
|
||||||
|
0x00,0x09,0x83,0x33,0x33,0x33,0x90,0x00,
|
||||||
|
0x00,0x09,0x32,0x23,0x32,0x23,0x90,0x00,
|
||||||
|
0x00,0x03,0x03,0x23,0x82,0x30,0x30,0x00,
|
||||||
|
0x03,0x30,0x00,0x33,0x33,0x00,0x03,0x30,
|
||||||
|
0x00,0x30,0x03,0x00,0x00,0x30,0x03,0x00,
|
||||||
|
0x00,0x00,0x00,0x30,0x03,0x00,0x00,0x00,
|
||||||
|
0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,
|
||||||
|
};
|
||||||
|
|
||||||
|
void draw_char(char ch, byte x, byte y, byte color) {
|
||||||
|
byte data[8][4];
|
||||||
|
const byte* src = &font8x8[ch-LOCHAR][0];
|
||||||
|
int i,j,pixels;
|
||||||
|
if (ch < LOCHAR || ch > HICHAR) return;
|
||||||
|
for (i=0; i<8; i++) {
|
||||||
|
byte b = *src++;
|
||||||
|
for (j=0; j<4; j++) {
|
||||||
|
pixels = 0;
|
||||||
|
if (b & 0x80) pixels |= color & 0xf0;
|
||||||
|
if (b & 0x40) pixels |= color & 0x0f;
|
||||||
|
data[i][j] = (byte)pixels;
|
||||||
|
b <<= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
blit_copy(x, y, 4, 8, (byte*)data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_string(const char* str, byte x, byte y, byte color) {
|
||||||
|
char ch;
|
||||||
|
do {
|
||||||
|
ch = *str++;
|
||||||
|
draw_char(ch, x, y, color);
|
||||||
|
x += 4;
|
||||||
|
} while (ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
byte i;
|
||||||
|
rom_select = 1;
|
||||||
|
blit_solid(0, 0, 152, 255, 0x00);
|
||||||
|
for (i=0; i<16; i++)
|
||||||
|
palette[i] = (byte)(i*7);
|
||||||
|
for (i=0; i<152; i++) {
|
||||||
|
vidmem[0][i] = 16;
|
||||||
|
vidmem[i][2] = 32;
|
||||||
|
blit_pixel(i, i, 0x77);
|
||||||
|
blit_pixel(i+1, i, 0x33);
|
||||||
|
}
|
||||||
|
while (1) {
|
||||||
|
watchdog0x39 = 0x39;
|
||||||
|
draw_sprite(sprite1, 35, 20);
|
||||||
|
draw_sprite_solid(sprite1, 55, 20, 0x24);
|
||||||
|
blit_solid(75, 20, 40, 20, 0x35);
|
||||||
|
draw_string("HELLO WORLD", 20, 5, 0x88);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
|
||||||
|
#include "williams.h"
|
||||||
|
|
||||||
|
// x1: 0-151
|
||||||
|
// y1: 0-255
|
||||||
|
void blit_solid(byte x1, byte y1, byte w, byte h, byte color) {
|
||||||
|
blitter.width = w^4;
|
||||||
|
blitter.height = h^4;
|
||||||
|
blitter.dstart = ((word)x1<<8)+y1; // swapped
|
||||||
|
blitter.solid = color;
|
||||||
|
blitter.flags = DSTSCREEN|SOLID;
|
||||||
|
}
|
||||||
|
|
||||||
|
void blit_copy(byte x1, byte y1, byte w, byte h, const byte* data) {
|
||||||
|
blitter.width = w^4;
|
||||||
|
blitter.height = h^4;
|
||||||
|
blitter.sstart = (word)data;
|
||||||
|
blitter.dstart = ((word)x1<<8)+y1; // swapped
|
||||||
|
blitter.solid = 0;
|
||||||
|
blitter.flags = DSTSCREEN|FGONLY;
|
||||||
|
}
|
||||||
|
|
||||||
|
void blit_copy_solid(byte x1, byte y1, byte w, byte h, const byte* data, byte solid) {
|
||||||
|
blitter.width = w^4;
|
||||||
|
blitter.height = h^4;
|
||||||
|
blitter.sstart = (word)data;
|
||||||
|
blitter.dstart = ((word)x1<<8)+y1; // swapped
|
||||||
|
blitter.solid = solid;
|
||||||
|
blitter.flags = DSTSCREEN|FGONLY|SOLID;
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_sprite(const byte* data, byte x, byte y) {
|
||||||
|
blitter.width = data[0]^4;
|
||||||
|
blitter.height = data[1]^4;
|
||||||
|
blitter.sstart = (word)(data+2);
|
||||||
|
blitter.dstart = ((word)x<<8)+y; // swapped
|
||||||
|
blitter.solid = 0;
|
||||||
|
blitter.flags = DSTSCREEN|FGONLY;
|
||||||
|
}
|
||||||
|
|
||||||
|
void blit_pixel(word xx, byte y, byte color) {
|
||||||
|
blitter.width = 1^4;
|
||||||
|
blitter.height = 1^4;
|
||||||
|
blitter.dstart = (((xx>>1)&0xff)<<8)+y; // swapped
|
||||||
|
blitter.solid = color;
|
||||||
|
blitter.flags = (xx&1) ? SOLID|ODDONLY : SOLID|EVENONLY;
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_sprite_solid(const byte* data, byte x, byte y, byte color) {
|
||||||
|
blitter.width = data[0]^4;
|
||||||
|
blitter.height = data[1]^4;
|
||||||
|
blitter.sstart = (word)(data+2);
|
||||||
|
blitter.dstart = ((word)x<<8)+y; // swapped
|
||||||
|
blitter.solid = color;
|
||||||
|
blitter.flags = DSTSCREEN|FGONLY|SOLID;
|
||||||
|
}
|
||||||
|
|
||||||
|
void erase_sprite_rect(const byte* data, byte x, byte y) {
|
||||||
|
blitter.width = data[0]^4;
|
||||||
|
blitter.height = data[1]^4;
|
||||||
|
blitter.dstart = ((word)x<<8)+y; // swapped
|
||||||
|
blitter.solid = 0;
|
||||||
|
blitter.flags = DSTSCREEN|SOLID;
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_sprite_strided(const byte* data, byte x, byte y, byte stride) {
|
||||||
|
const byte* src = data+2;
|
||||||
|
byte height = data[1]^4;
|
||||||
|
byte width = data[0]^4;
|
||||||
|
while (height--) {
|
||||||
|
blit_copy(x, y, width, 1, src);
|
||||||
|
y += stride;
|
||||||
|
src += width;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,100 @@
|
||||||
|
|
||||||
|
#ifndef _WILLIAMS_H
|
||||||
|
#define _WILLIAMS_H
|
||||||
|
|
||||||
|
typedef unsigned char byte;
|
||||||
|
typedef unsigned short word;
|
||||||
|
|
||||||
|
byte* palette = 0xc000;
|
||||||
|
byte* nvram = 0xcc00;
|
||||||
|
|
||||||
|
#define input0 (*(byte*)0xc804)
|
||||||
|
#define input1 (*(byte*)0xc806)
|
||||||
|
#define input2 (*(byte*)0xc80c)
|
||||||
|
#define sound_pia (*(byte*)0xc80c)
|
||||||
|
#define rom_select *((byte*)0xc900)
|
||||||
|
#define video_counter *((byte*)0xcb00)
|
||||||
|
#define watchdog0x39 *((byte*)0xcbff)
|
||||||
|
|
||||||
|
// switch flags
|
||||||
|
|
||||||
|
#define UP1 (input0 & 0x1)
|
||||||
|
#define DOWN1 (input0 & 0x2)
|
||||||
|
#define LEFT1 (input0 & 0x4)
|
||||||
|
#define RIGHT1 (input0 & 0x8)
|
||||||
|
#define START1 (input0 & 0x10)
|
||||||
|
#define START2 (input0 & 0x20)
|
||||||
|
#define UP2 (input0 & 0x40)
|
||||||
|
#define DOWN2 (input0 & 0x80)
|
||||||
|
#define LEFT2 (input1 & 0x1)
|
||||||
|
#define RIGHT2 (input1 & 0x2)
|
||||||
|
#define AUTOUP (input2 & 0x1)
|
||||||
|
#define ADVANCE (input2 & 0x2)
|
||||||
|
#define COIN2 (input2 & 0x4)
|
||||||
|
#define HIGHSCORERESET (input2 & 0x8)
|
||||||
|
#define COIN1 (input2 & 0x10)
|
||||||
|
#define COIN3 (input2 & 0x20)
|
||||||
|
#define TILTSWITCH (input2 & 0x40)
|
||||||
|
#define SOUNDACK (input2 & 0x80)
|
||||||
|
|
||||||
|
// blitter flags
|
||||||
|
#define SRCSCREEN 0x1
|
||||||
|
#define DSTSCREEN 0x2
|
||||||
|
#define ESYNC 0x4
|
||||||
|
#define FGONLY 0x8
|
||||||
|
#define SOLID 0x10
|
||||||
|
#define RSHIFT 0x20
|
||||||
|
#define EVENONLY 0x40
|
||||||
|
#define ODDONLY 0x80
|
||||||
|
|
||||||
|
struct {
|
||||||
|
byte flags;
|
||||||
|
byte solid;
|
||||||
|
word sstart;
|
||||||
|
word dstart;
|
||||||
|
byte width;
|
||||||
|
byte height;
|
||||||
|
} *_blitter = 0xca00;
|
||||||
|
|
||||||
|
#define blitter (*_blitter)
|
||||||
|
|
||||||
|
struct {
|
||||||
|
byte mem[152][256];
|
||||||
|
} *_vid = 0x0;
|
||||||
|
|
||||||
|
#define vidmem (_vid->mem)
|
||||||
|
|
||||||
|
#define BLIT_OP(_x,_y,_w,_h,_src,_color,_flags) do {\
|
||||||
|
blitter.width = (_w)^4; \
|
||||||
|
blitter.height = (_h)^4; \
|
||||||
|
blitter.sstart = (word)(_src); \
|
||||||
|
blitter.dstart = ((word)(_x)<<8)+(_y); \
|
||||||
|
blitter.solid = (_color); \
|
||||||
|
blitter.flags = (_flags); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define BLIT_SOLID(x, y, w, h, color) \
|
||||||
|
BLIT_OP(x, y, w, h, 0, color, DSTSCREEN|SOLID)
|
||||||
|
|
||||||
|
|
||||||
|
// x1: 0-151
|
||||||
|
// y1: 0-255
|
||||||
|
void blit_solid(byte x1, byte y1, byte w, byte h, byte color);
|
||||||
|
|
||||||
|
void blit_copy(byte x1, byte y1, byte w, byte h, const byte* data);
|
||||||
|
|
||||||
|
void blit_copy_solid(byte x1, byte y1, byte w, byte h, const byte* data, byte solid);
|
||||||
|
|
||||||
|
void draw_sprite(const byte* data, byte x, byte y);
|
||||||
|
|
||||||
|
void draw_sprite_solid(const byte* data, byte x, byte y, byte color);
|
||||||
|
|
||||||
|
void erase_sprite_rect(const byte* data, byte x, byte y);
|
||||||
|
|
||||||
|
void draw_sprite_strided(const byte* data, byte x, byte y, byte stride);
|
||||||
|
|
||||||
|
// x1: 0-303
|
||||||
|
// y1: 0-255
|
||||||
|
void blit_pixel(word xx, byte y, byte color);
|
||||||
|
|
||||||
|
#endif
|
|
@ -98,7 +98,7 @@ var WilliamsPlatform = function(mainElement, proto, isDefender) {
|
||||||
|
|
||||||
var iowrite_defender = newAddressDecoder([
|
var iowrite_defender = newAddressDecoder([
|
||||||
[0x0, 0xf, 0xf, setPalette],
|
[0x0, 0xf, 0xf, setPalette],
|
||||||
[0x3fc, 0x3ff, 0, function(a, v) { if (v == 0x38) watchdog_counter = INITIAL_WATCHDOG; }],
|
[0x3fc, 0x3ff, 0, function(a, v) { if (v == 0x38) watchdog_counter = INITIAL_WATCHDOG; watchdog_enabled=true; }],
|
||||||
[0x400, 0x5ff, 0x1ff, function(a, v) { nvram.mem[a] = v; }],
|
[0x400, 0x5ff, 0x1ff, function(a, v) { nvram.mem[a] = v; }],
|
||||||
[0xc02, 0xc02, 0x1, function(a, v) { if (worker) worker.postMessage({ command: v & 0x3f }); }],
|
[0xc02, 0xc02, 0x1, function(a, v) { if (worker) worker.postMessage({ command: v & 0x3f }); }],
|
||||||
[0xc00, 0xc07, 0x7, function(a, v) { pia6821[a] = v; }],
|
[0xc00, 0xc07, 0x7, function(a, v) { pia6821[a] = v; }],
|
||||||
|
@ -145,7 +145,7 @@ var WilliamsPlatform = function(mainElement, proto, isDefender) {
|
||||||
//[0x80c, 0x80f, 0x3, function(a,v) { console.log('iowrite',a+4); }], // TODO: sound
|
//[0x80c, 0x80f, 0x3, function(a,v) { console.log('iowrite',a+4); }], // TODO: sound
|
||||||
[0x900, 0x9ff, 0, function(a, v) { banksel = v & 0x1; }],
|
[0x900, 0x9ff, 0, function(a, v) { banksel = v & 0x1; }],
|
||||||
[0xa00, 0xa07, 0x7, setBlitter],
|
[0xa00, 0xa07, 0x7, setBlitter],
|
||||||
[0xbff, 0xbff, 0, function(a, v) { if (v == 0x39) watchdog_counter = INITIAL_WATCHDOG; }],
|
[0xbff, 0xbff, 0, function(a, v) { if (v == 0x39) { watchdog_counter = INITIAL_WATCHDOG; watchdog_enabled=true; } }],
|
||||||
[0xc00, 0xfff, 0x3ff, function(a, v) { nvram.mem[a] = v; }],
|
[0xc00, 0xfff, 0x3ff, function(a, v) { nvram.mem[a] = v; }],
|
||||||
//[0x0, 0xfff, 0, function(a,v) { console.log('iowrite',hex(a),hex(v)); }],
|
//[0x0, 0xfff, 0, function(a,v) { console.log('iowrite',hex(a),hex(v)); }],
|
||||||
]);
|
]);
|
||||||
|
@ -418,6 +418,7 @@ var WilliamsPlatform = function(mainElement, proto, isDefender) {
|
||||||
this.reset = function() {
|
this.reset = function() {
|
||||||
cpu.reset();
|
cpu.reset();
|
||||||
watchdog_counter = INITIAL_WATCHDOG;
|
watchdog_counter = INITIAL_WATCHDOG;
|
||||||
|
watchdog_enabled = false;
|
||||||
banksel = 1;
|
banksel = 1;
|
||||||
}
|
}
|
||||||
this.scaleCPUFrequency = function(scale) {
|
this.scaleCPUFrequency = function(scale) {
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
/* assert.h - Assert macro for CMOC
|
||||||
|
|
||||||
|
By Pierre Sarrazin <http://sarrazip.com/>.
|
||||||
|
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 */
|
|
@ -0,0 +1,345 @@
|
||||||
|
// cmoc.h - CMOC's standard library functions.
|
||||||
|
//
|
||||||
|
// By Pierre Sarrazin <http://sarrazip.com/>.
|
||||||
|
// 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 <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#endif /* __GNUC__ */
|
||||||
|
|
||||||
|
#endif /* _H_CMOC */
|
|
@ -0,0 +1,22 @@
|
||||||
|
/* stdarg.h - Support for variable argument functions
|
||||||
|
|
||||||
|
By Pierre Sarrazin <http://sarrazip.com/>.
|
||||||
|
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_ */
|
|
@ -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__
|
|
@ -116,6 +116,9 @@ export function compileCMOC(step: BuildStep): BuildStepResult {
|
||||||
if (errors.length)
|
if (errors.length)
|
||||||
return { errors: errors };
|
return { errors: errors };
|
||||||
var asmout = FS.readFile(destpath, { encoding: 'utf8' });
|
var asmout = FS.readFile(destpath, { encoding: 'utf8' });
|
||||||
|
if (step.params.set_stack_end)
|
||||||
|
asmout = asmout.replace('stack space in bytes', `\n lds #${step.params.set_stack_end}\n`)
|
||||||
|
console.log(asmout);
|
||||||
putWorkFile(destpath, asmout);
|
putWorkFile(destpath, asmout);
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
|
@ -240,6 +243,8 @@ export function linkLWLINK(step: BuildStep): BuildStepResult {
|
||||||
// * Line //threed.c:117: init of variable e
|
// * Line //threed.c:117: init of variable e
|
||||||
var srclines = parseSourceLines(lstout, /Line .+?:(\d+)/i, /^([0-9A-F]{4})/i);
|
var srclines = parseSourceLines(lstout, /Line .+?:(\d+)/i, /^([0-9A-F]{4})/i);
|
||||||
putWorkFile(fn, lstout);
|
putWorkFile(fn, lstout);
|
||||||
|
// strip out left margin
|
||||||
|
lstout = lstout.split('\n').map(l => l.substring(0,15) + l.substring(56)).join('\n')
|
||||||
// TODO: you have to get rid of all source lines to get asm listing
|
// TODO: you have to get rid of all source lines to get asm listing
|
||||||
listings[fn] = {
|
listings[fn] = {
|
||||||
asmlines: srclines.length ? asmlines : null,
|
asmlines: srclines.length ? asmlines : null,
|
||||||
|
|
|
@ -127,9 +127,11 @@ var PLATFORM_PARAMS = {
|
||||||
data_start: 0x9800,
|
data_start: 0x9800,
|
||||||
data_size: 0x2800,
|
data_size: 0x2800,
|
||||||
stack_end: 0xc000,
|
stack_end: 0xc000,
|
||||||
|
set_stack_end: 0xc000,
|
||||||
extra_link_files: ['williams.scr', 'libcmoc-crt-vec.a', 'libcmoc-std-vec.a'],
|
extra_link_files: ['williams.scr', 'libcmoc-crt-vec.a', 'libcmoc-std-vec.a'],
|
||||||
extra_link_args: ['-swilliams.scr', '-lcmoc-crt-vec', '-lcmoc-std-vec'],
|
extra_link_args: ['-swilliams.scr', '-lcmoc-crt-vec', '-lcmoc-std-vec'],
|
||||||
extra_compile_files: ['assert.h','cmoc.h','stdarg.h','vectrex.h','stdlib.h','bios.h'],
|
extra_compile_files: ['assert.h','cmoc.h','stdarg.h','stdlib.h'],
|
||||||
|
//extra_compile_args: ['--vectrex'],
|
||||||
},
|
},
|
||||||
'williams-defender': {
|
'williams-defender': {
|
||||||
arch: '6809',
|
arch: '6809',
|
||||||
|
|
Loading…
Reference in New Issue