diff --git a/presets/astrocade-bios/biosasm.s b/presets/astrocade-bios/biosasm.s new file mode 100644 index 00000000..5e75fa4d --- /dev/null +++ b/presets/astrocade-bios/biosasm.s @@ -0,0 +1,95 @@ + + .module biosasm + .globl _STIMER,_CTIMER,_BIGFONT,_SMLFONT + + .area BIOSSTART (ABS) + .org 0x0 +BIOSStart: + di ; disable interrupts + ld HL,#0x2000 + ld A,(HL) ; A <- mem[0x2000] + cp #0x55 ; found sentinel byte? ($55) + jp Z,FoundSentinel ; yes, load program +.if 1 + jp 0x2000 ; jump to $2000 +.else + jp _main ; jump to test program +.endif +FoundSentinel: + ld SP,#0x4fce ; position stack below BIOS vars + call _bios_init ; misc. bios init routines + ld HL,#0x2005 ; cartridge start vector + ld A,(HL) + inc HL + ld H,(HL) + ld L,A + jp (HL) ; jump to cart start vector + +SYSCALL38: + .org 0x38 + push hl + push af + push bc + push de + push ix + push iy + ld hl,#0 + add hl,sp + push hl ; HL points to context block + call _SYSCALL ; syscall handler + pop hl + pop iy + pop ix + pop de + pop bc + pop af + pop hl + ret + +DOPEVector: + .org 0x200 + JP _STIMER + JP _CTIMER + .db 0x20, 8, 8, 1, 7 ; Font descriptor (big font) + .dw _BIGFONT + .db 0xa0, 4, 6, 1, 5 ; Font descriptor (small font) + .dw _SMLFONT + +ReloadRegs: + ld c,(hl) + inc hl + ld b,(hl) + inc hl + push bc + pop iy + ld c,(hl) + inc hl + ld b,(hl) + inc hl + push bc + pop ix + ld c,(hl) + inc hl + ld b,(hl) + inc hl + push bc + pop de + ld c,(hl) + inc hl + ld b,(hl) + inc hl + push bc + ld c,(hl) + inc hl + ld b,(hl) + inc hl + push bc + pop af + ld c,(hl) + inc hl + ld b,(hl) + inc hl + push bc + pop hl + pop bc + ret diff --git a/presets/astrocade/01-helloworlds.asm b/presets/astrocade/01-helloworlds.asm index 7f9868eb..17cd9938 100644 --- a/presets/astrocade/01-helloworlds.asm +++ b/presets/astrocade/01-helloworlds.asm @@ -13,6 +13,7 @@ PrgName: DB "HELLO, WORLDS!"; String DB 0 ; ... which must be followed by 0 PrgStart: DI ; Disable interrupts +; db $ed,$ff SYSTEM INTPC ; Begin interpreter mode DO SETOUT ; Set output ports DB 100*2 ; ... with VBLANK line set to line 100 diff --git a/presets/astrocade/aclib.c b/presets/astrocade/aclib.c index e89b9440..e14bdb9f 100644 --- a/presets/astrocade/aclib.c +++ b/presets/astrocade/aclib.c @@ -9,6 +9,17 @@ void clrscr() { memset(vidmem, 0, VHEIGHT*VBWIDTH); // clear page 1 } +// set entire palette at once (8 bytes to port 0xb) +// bytes in array should be in reverse +void set_palette(byte palette[8]) __naked { + palette; +__asm + ld bc,#0x80b ; B -> 8, C -> 0xb + otir ; write C bytes to B + ret ; return +__endasm; +} + // draw vertical line void vline(byte x, byte y1, byte y2, byte col, byte op) { byte xb = x>>2; // divide x by 4 @@ -33,33 +44,31 @@ void render_sprite(const byte* src, byte x, byte y, byte op) { byte i,j; byte w = *src++; // get width from 1st byte of sprite byte h = *src++; // get height from 2nd byte of sprite - byte xb = x>>2; // divide x by 4 - byte* dest = &vmagic[y][xb]; // destination address + byte* dest = &vmagic[y][x>>2];// destination address hw_magic = M_SHIFT(x) | op; // set magic register - for (j=0; j= VHEIGHT) { + if (y >= VHEIGHT) return; + h = VHEIGHT-y; } -} - -// erase a sprite -void erase_sprite(const byte* src, byte x, byte y) { - byte i,j; - byte w = *src++; // get width from 1st byte of sprite - byte h = *src++; // get height from 2nd byte of sprite - byte xb = x>>2; // divide x by 4 - byte* dest = &vidmem[y][xb]; // destination address - for (j=0; j 1st byte *dest++ = b; // expand upper nibble -> 2nd byte - *dest++ = 0; // leftover -> 3rd byte - *dest = 0; // reset upper/lower flag + if (x & 3) { + *dest++ = 0; // leftover -> 3rd byte + *dest = 0; // reset upper/lower flag + } else { + dest++; + } dest += VBWIDTH-3; // we incremented 3 bytes for this line } } @@ -89,7 +102,7 @@ void draw_string(const char* str, byte x, byte y) { do { byte ch = *str++; if (!ch) break; - draw_char(ch, x, y, M_MOVE); + draw_char(ch, x, y, M_XOR); x += 8; } while (1); } @@ -105,24 +118,24 @@ void draw_bcd_word(word bcd, byte x, byte y, byte op) { } // add two 16-bit BCD values -word bcd_add(word a, word b) { +word bcd_add(word a, word b) __naked { a; b; // to avoid warning __asm - ld hl,#4 - add hl,sp - ld iy,#2 - add iy,sp - ld a,0 (iy) - add a, (hl) - daa - ld c,a - ld a,1 (iy) - inc hl - adc a, (hl) - daa - ld b,a - ld l, c - ld h, b + push ix + ld ix,#0 + add ix,sp + ld a,4 (ix) + add a, 6 (ix) + daa + ld c,a + ld a,5 (ix) + adc a, 7 (ix) + daa + ld b,a + ld l, c + ld h, b + pop ix + ret __endasm; } diff --git a/presets/astrocade/aclib.h b/presets/astrocade/aclib.h index ee83c145..f539fbf9 100644 --- a/presets/astrocade/aclib.h +++ b/presets/astrocade/aclib.h @@ -2,11 +2,14 @@ #ifndef _ACLIB_H #define _ACLIB_H +// convenient type definitions + typedef unsigned char byte; typedef signed char sbyte; typedef unsigned short word; +typedef enum { false, true } bool; -/// HARDWARE +/// registers __sfr __at(0x00) hw_col0r; // palette 0 __sfr __at(0x01) hw_col1r; @@ -24,10 +27,12 @@ __sfr __at(0x19) hw_xpand; // expander register __sfr __at(0x08) hw_intst; // intercept test feedback -__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(0x10) hw_p1ctrl; // player 1 controls +__sfr __at(0x11) hw_p2ctrl; // player 2 controls +__sfr __at(0x12) hw_p3ctrl; // player 3 controls +__sfr __at(0x13) hw_p4ctrl; // player 4 controls + +// flags #define M_SHIFT0 0x00 #define M_SHIFT1 0x01 @@ -40,14 +45,19 @@ __sfr __at(0x13) hw_p4ctrl; // player controls #define M_FLOP 0x40 #define M_SHIFT(x) ((x)&3) #define XPAND_COLORS(off,on) (((off)&3) | (((on)&3)<<2)) +#define M_ERASE 0x04 // special case for draw_sprite() -#define VHEIGHT 89 // number of scanlines +#define VTOTAL 102 // number of total scanlines +#define VHEIGHT 89 // number of scanlines in use #define VBWIDTH 40 // number of bytes per scanline #define PIXWIDTH 160 // 4 pixels per byte -byte __at (0x0000) vmagic[VHEIGHT][VBWIDTH]; -byte __at (0x4000) vidmem[VHEIGHT][VBWIDTH]; +// magic register active area +byte __at (0x0000) vmagic[VTOTAL][VBWIDTH]; +// regular frame buffer RAM +byte __at (0x4000) vidmem[VTOTAL][VBWIDTH]; +// font constants #define LOCHAR 32 #define HICHAR 127 #define FONT_BWIDTH 1 @@ -56,13 +66,15 @@ byte __at (0x4000) vidmem[VHEIGHT][VBWIDTH]; /// GRAPHICS FUNCTIONS void clrscr(); +void set_palette(byte palette[8]); // palette in reverse order void vline(byte x, byte y1, byte y2, byte col, byte op); void pixel(byte x, byte y, byte col, byte op); void render_sprite(const byte* src, byte x, byte y, byte op); -void erase_sprite(const byte* src, byte x, byte y); void draw_char(byte ch, byte x, byte y, byte op); void draw_string(const char* str, byte x, byte y); void draw_bcd_word(word bcd, byte x, byte y, byte op); word bcd_add(word a, word b); +#define erase_sprite(src,x,y) render_sprite(src,x,y,M_ERASE); + #endif diff --git a/presets/astrocade/cosmic.c b/presets/astrocade/cosmic.c index 089bdebd..ea6e0a0c 100644 --- a/presets/astrocade/cosmic.c +++ b/presets/astrocade/cosmic.c @@ -21,17 +21,17 @@ const byte player_bitmap[] = {3,14,/*{w:12,h:16,bpp:2,brev:1}*/0x00,0x3C,0x00,0x00,0x18,0x00,0x00,0x3C,0x00,0x00,0x18,0x00,0x04,0x18,0x20,0x0C,0x3C,0x30,0x3C,0x3C,0x3C,0x1F,0xE7,0xF4,0x1F,0x66,0xF4,0x17,0xE7,0xE4,0x17,0xE7,0xE4,0x1C,0x7E,0x34,0x1C,0xFF,0x34,0x3C,0x18,0x3C,0x0C,0x18,0x30,0x04,0x18,0x20}; const byte bomb_bitmap[] = -{1,5,/*{w:8,h:5,bpp:2,brev:1}*/0x88,0x55,0x77,0x55,0x88}; +{1,5,/*{w:4,h:5,bpp:2,brev:1}*/0x88,0x55,0x77,0x55,0x88}; const byte bullet_bitmap[] = -{1,5,/*{w:8,h:5,bpp:2,brev:1}*/0x14,0x28,0x14,0x14,0x28}; +{1,5,/*{w:4,h:5,bpp:2,brev:1}*/0x14,0x28,0x14,0x14,0x28}; const byte enemy1_bitmap[] = -{2,8,/*{w:16,h:8,bpp:2,brev:1}*/0x00,0x00,0x70,0x38,0xF8,0x7C,0xFC,0xFC,0xFE,0xFC,0xFE,0xFF,0xFC,0xFF,0xF8,0x7F,0xF0,0x3F,0x88,0x47,0xF0,0x3F,0xF0,0x3F,0xD0,0x2F,0x8C,0xC7,0x48,0x48,0x80,0x04}; +{2,8,/*{w:8,h:8,bpp:2,brev:1}*/0x00,0x00,0x70,0x38,0xF8,0x7C,0xFC,0xFC,0xFE,0xFC,0xFE,0xFF,0xFC,0xFF,0xF8,0x7F,0xF0,0x3F,0x88,0x47,0xF0,0x3F,0xF0,0x3F,0xD0,0x2F,0x8C,0xC7,0x48,0x48,0x80,0x04}; const byte enemy2_bitmap[] = -{2,8,/*{w:16,h:8,bpp:2,brev:1}*/0x00,0x00,0x30,0x0C,0x14,0x28,0x2E,0x74,0x08,0x10,0x20,0x04,0xE0,0x07,0xD0,0x0B,0xB0,0x0D,0xB2,0x4D,0x19,0x98,0x8E,0x71,0x82,0x41,0xB1,0x8D,0x59,0x9A,0x4A,0x52}; +{2,8,/*{w:8,h:8,bpp:2,brev:1}*/0x00,0x00,0x30,0x0C,0x14,0x28,0x2E,0x74,0x08,0x10,0x20,0x04,0xE0,0x07,0xD0,0x0B,0xB0,0x0D,0xB2,0x4D,0x19,0x98,0x8E,0x71,0x82,0x41,0xB1,0x8D,0x59,0x9A,0x4A,0x52}; const byte enemy3_bitmap[] = -{2,8,/*{w:16,h:8,bpp:2,brev:1}*/0x00,0x00,0x00,0x00,0x04,0x20,0x05,0xA0,0x05,0xA0,0x25,0xA4,0xA7,0xE5,0xF7,0xEF,0xF7,0xEF,0xFE,0x7F,0xFC,0x3F,0xBC,0x3D,0xE4,0x27,0x20,0x00,0x00,0x00,0x00,0x00}; +{2,8,/*{w:8,h:8,bpp:2,brev:1}*/0x00,0x00,0x00,0x00,0x04,0x20,0x05,0xA0,0x05,0xA0,0x25,0xA4,0xA7,0xE5,0xF7,0xEF,0xF7,0xEF,0xFE,0x7F,0xFC,0x3F,0xBC,0x3D,0xE4,0x27,0x20,0x00,0x00,0x00,0x00,0x00}; const byte enemy4_bitmap[] = -{2,8,/*{w:16,h:8,bpp:2,brev:1}*/0x00,0x00,0x00,0x00,0xF0,0x0F,0xF8,0x1F,0xD8,0x1B,0xF8,0x1F,0xF8,0x1F,0xF8,0x1F,0xF0,0x0F,0xA8,0x15,0xCC,0x33,0xE8,0x17,0x66,0x66,0x33,0xCC,0x61,0x86,0x40,0x02}; +{2,8,/*{w:8,h:8,bpp:2,brev:1}*/0x00,0x00,0x00,0x00,0xF0,0x0F,0xF8,0x1F,0xD8,0x1B,0xF8,0x1F,0xF8,0x1F,0xF8,0x1F,0xF0,0x0F,0xA8,0x15,0xCC,0x33,0xE8,0x17,0x66,0x66,0x33,0xCC,0x61,0x86,0x40,0x02}; const byte* const enemy_bitmaps[4] = { enemy1_bitmap, @@ -88,7 +88,7 @@ void draw_lives() { byte i; byte n = lives; byte y = 0; - byte x = PIXWIDTH-4*5; + byte x = PIXWIDTH-4*6; hw_xpand = XPAND_COLORS(0, COLOR_SCORE); for (i=0; i +#include + +/*{pal:"astrocade",layout:"astrocade"}*/ +const byte palette[8] = { + 0x06, 0x62, 0xF1, 0x04, + 0x07, 0xD4, 0x35, 0x00, +}; + +void setup_registers() { + // setup colors + set_palette(palette); + // horizontal palette split + hw_horcb = 12; + // height of screen + hw_verbl = VHEIGHT*2; +} + +void main() { + setup_registers(); + clrscr(); + hw_xpand = XPAND_COLORS(0, 2); + draw_string("Hello, World!", 2, 0); + // infinite loop + while (1) { + } +} diff --git a/presets/astrocade/hvglib.h b/presets/astrocade/hvglib.h index 368005e7..b05e47e7 100644 --- a/presets/astrocade/hvglib.h +++ b/presets/astrocade/hvglib.h @@ -10,7 +10,6 @@ ; > Version 2.6 - March 2, 2004 - as seen on BallyAlley.com ; > Version 3.0 - 2009 ; > Version 3.01 - Changed "FonT BASE character" comment -; > (also patched for latest zmac with default args) ; > ; > This file contains the equates and macros that Bally ; > programs require for assembly. This file has been diff --git a/presets/astrocade/lines.c b/presets/astrocade/lines.c new file mode 100644 index 00000000..6784384b --- /dev/null +++ b/presets/astrocade/lines.c @@ -0,0 +1,50 @@ + +#include "aclib.h" +//#link "aclib.c" +//#link "acheader.s" + +#include +#include + +void draw_line(int x0, int y0, int x1, int y1, byte color) { + int dx = abs(x1-x0); + int sx = x0dy ? dx : -dy)>>1; + int e2; + for(;;) { + pixel(x0, y0, color, M_XOR); + if (x0==x1 && y0==y1) break; + e2 = err; + if (e2 > -dx) { err -= dy; x0 += sx; } + if (e2 < dy) { err += dx; y0 += sy; } + } +} + +/*{pal:"astrocade",layout:"astrocade"}*/ +const byte palette[8] = { + 0x06, 0x62, 0xF1, 0x04, + 0x07, 0xD4, 0x35, 0x00, +}; + +void setup_registers() { + set_palette(palette); + // horizontal palette split + hw_horcb = 20; + // height of screen + hw_verbl = VHEIGHT*2; +} + +void main() { + setup_registers(); + clrscr(); + hw_xpand = XPAND_COLORS(0, 2); + draw_string("Hello, Lines!", 2, 80); + draw_line(0, 0, 159, 95, 1); + // infinite loop + srand(1); + while(1) { + draw_line(rand()%159, rand()%79, rand()%159, rand()%79, rand()&3); + } +} diff --git a/presets/astrocade/skeleton.sdcc b/presets/astrocade/skeleton.sdcc index 340e0e49..5aa6244e 100644 --- a/presets/astrocade/skeleton.sdcc +++ b/presets/astrocade/skeleton.sdcc @@ -1,8 +1,29 @@ +#include "aclib.h" +//#link "aclib.c" //#link "acheader.s" +#include #include -void main() { - memset((void*)0x4000, 0, 0xe00); // clear screen, avoid vars and stack (1e00-1fff) +void setup_registers() { + // setup colors + hw_col0r = 0x00; + hw_col1r = 0x2f; + hw_col2r = 0xef; + hw_col3r = 0xaf; + // horizontal palette split + hw_horcb = 12; + // height of screen + hw_verbl = VHEIGHT*2; +} + +void main() { + setup_registers(); + clrscr(); + hw_xpand = XPAND_COLORS(0, 2); + draw_string("Hello, World!", 2, 0); + // infinite loop + while (1) { + } } diff --git a/presets/astrocade/sprites.c b/presets/astrocade/sprites.c new file mode 100644 index 00000000..225e951d --- /dev/null +++ b/presets/astrocade/sprites.c @@ -0,0 +1,34 @@ + +#include + +#include "aclib.h" +//#link "aclib.c" +//#link "acheader.s" + +const byte player_bitmap[] = +{3,14,/*{w:12,h:16,bpp:2,brev:1}*/0x00,0x3C,0x00,0x00,0x18,0x00,0x00,0x3C,0x00,0x00,0x18,0x00,0x04,0x18,0x20,0x0C,0x3C,0x30,0x3C,0x3C,0x3C,0x1F,0xE7,0xF4,0x1F,0x66,0xF4,0x17,0xE7,0xE4,0x17,0xE7,0xE4,0x1C,0x7E,0x34,0x1C,0xFF,0x34,0x3C,0x18,0x3C,0x0C,0x18,0x30,0x04,0x18,0x20}; + +/*{pal:"astrocade",layout:"astrocade"}*/ +const byte palette[8] = { + 0x06, 0x62, 0xF1, 0x04, + 0x07, 0xD4, 0x35, 0x00, +}; + +void setup_registers() { + set_palette(palette); + hw_horcb = 0; + hw_verbl = VHEIGHT*2; +} + +void main() { + byte x,y; + x=10; + y=10; + setup_registers(); + clrscr(); + while (1) { + render_sprite(player_bitmap, x, y, M_MOVE); + x++; + y++; + } +} diff --git a/src/baseplatform.ts b/src/baseplatform.ts index 5d205013..8ea6b4c9 100644 --- a/src/baseplatform.ts +++ b/src/baseplatform.ts @@ -118,6 +118,8 @@ export interface Preset { export interface MemoryBus { read : (address:number) => number; write : (address:number, value:number) => void; + contend?: (address:number, cycles:number) => number; + isContended?: (address:number) => boolean; } export type DebugCondition = () => boolean; @@ -508,6 +510,12 @@ export function BusProbe(bus : MemoryBus) { } bus.write(a,v); } + this.contend = function(addr,cyc) { + return bus.contend(addr,cyc); + } + this.isContended = function(addr) { + return bus.isContended(addr); + } } export abstract class BaseZ80Platform extends BaseDebugPlatform { @@ -515,10 +523,9 @@ export abstract class BaseZ80Platform extends BaseDebugPlatform { _cpu; probe; - newCPU(membus : MemoryBus, iobus : MemoryBus) { + newCPU(membus : MemoryBus, iobus : MemoryBus, z80opts? : {}) { this.probe = new BusProbe(membus); - var z80opts = {}; - this._cpu = buildZ80(z80opts)({ + this._cpu = buildZ80(z80opts || {})({ display: {}, memory: this.probe, ioBus: iobus diff --git a/src/pixed/pixeleditor.ts b/src/pixed/pixeleditor.ts index 6c942f31..5b18b7df 100644 --- a/src/pixed/pixeleditor.ts +++ b/src/pixed/pixeleditor.ts @@ -299,7 +299,8 @@ var PREDEF_PALETTES = { 0x003814,0x003814, 0x1c5c34,0x1c5c34, 0x387c50,0x387c50, 0x50986c,0x50986c, 0x68b484,0x68b484, 0x7ccc9c,0x7ccc9c, 0x90e4b4,0x90e4b4, 0xa4fcc8,0xa4fcc8, 0x00302c,0x00302c, 0x1c504c,0x1c504c, 0x347068,0x347068, 0x4c8c84,0x4c8c84, 0x64a89c,0x64a89c, 0x78c0b4,0x78c0b4, 0x88d4cc,0x88d4cc, 0x9cece0,0x9cece0, 0x002844,0x002844, 0x184864,0x184864, 0x306884,0x306884, 0x4484a0,0x4484a0, 0x589cb8,0x589cb8, 0x6cb4d0,0x6cb4d0, 0x7ccce8,0x7ccce8, 0x8ce0fc,0x8ce0fc - ] + ], + 'astrocade':[0,2368548,4737096,7171437,9539985,11974326,14342874,16777215,12255269,14680137,16716142,16725394,16734903,16744155,16753663,16762879,11534409,13959277,16318866,16721334,16730842,16740095,16749311,16758783,10420330,12779662,15138995,16718039,16727291,16736767,16745983,16755199,8847495,11206827,13631696,15994612,16724735,16733951,16743423,16752639,6946975,9306307,11731175,14092287,16461055,16732415,16741631,16751103,4784304,7143637,9568505,11929087,14297599,16731647,16741119,16750335,2425019,4784352,7209215,9570047,12004095,14372863,16741375,16750847,191,2359523,4718847,7146495,9515263,11949311,14318079,16752127,187,224,2294015,4658431,7092735,9461247,11895551,14264063,176,213,249,2367999,4736511,7105279,9539327,11908095,159,195,3303,209151,2577919,4946431,7380735,9749247,135,171,7888,17140,681983,3050495,5484543,7853311,106,3470,12723,22231,31483,1548031,3916799,6285311,73,8557,17810,27318,36570,373759,2742271,5176575,4389,13641,23150,32402,41911,51163,2026495,4456447,9472,18724,27976,37485,46737,56246,1834970,4194303,14080,23296,32803,42055,51564,60816,2031541,4456409,18176,27648,36864,46116,55624,392556,2752401,5177269,21760,30976,40192,49667,58919,1572683,3932016,6291348,24320,33536,43008,52224,716810,3079982,5504851,7864183,25856,35328,44544,250368,2619136,4980503,7405371,9764703,26624,35840,45312,2413824,4782336,7143173,9568041,11927374,26112,35584,2338560,4707328,7141376,9502464,11927326,14286659,24832,2393344,4762112,7196160,9564928,11992832,14352155,16711487,2447360,4815872,7250176,9618688,12052992,14417664,16776990,16777027,4803328,7172096,9606144,11974912,14343424,16776965,16777001,16777038,6962176,9330688,11764992,14133504,16502272,16773655,16777019,16777055,8858112,11226880,13660928,16029440,16759818,16769070,16777043,16777079,10426112,12794624,15163392,16745475,16754727,16764235,16773488,16777108,11534848,13969152,16337664,16740388,16749640,16759148,16768401,16777141,12255232,14684928,16725795,16735047,16744556,16753808,16763317,16772569], }; var PREDEF_LAYOUTS : {[id:string]:PixelEditorPaletteLayout} = { @@ -314,6 +315,10 @@ var PREDEF_LAYOUTS : {[id:string]:PixelEditorPaletteLayout} = { ['Sprite 2', 0x19, 3], ['Sprite 3', 0x1d, 3] ], + 'astrocade':[ + ['Left', 0x04, -4], + ['Right', 0x00, -4] + ], }; ///// @@ -587,7 +592,6 @@ function dedupPalette(cols : UintArray) : Uint32Array { } export class PaletteFormatToRGB extends PixNode { - words : UintArray; rgbimgs : Uint32Array[]; palette : Uint32Array; diff --git a/src/platform/astrocade.ts b/src/platform/astrocade.ts index 017664ca..ffacd20c 100644 --- a/src/platform/astrocade.ts +++ b/src/platform/astrocade.ts @@ -11,6 +11,9 @@ const ASTROCADE_PRESETS = [ {id:'01-helloworlds.asm', name:'Hello World'}, {id:'02-telephone.asm', name:'Telephone'}, {id:'03-horcbpal.asm', name:'Paddle Demo'}, + {id:'hello.c', name:'Hello World'}, + {id:'lines.c', name:'Lines'}, + {id:'sprites.c', name:'Sprites'}, {id:'cosmic.c', name:'Cosmic Impalas Game'}, ]; @@ -68,7 +71,7 @@ const _BallyAstrocadePlatform = function(mainElement, arcade) { const sheight = arcade ? 204 : 102; const swbytes = Math.floor(swidth / 4); const cpuFrequency = 1789000; - const cpuCyclesPerLine = cpuFrequency/(60*sheight); // TODO: wait states? + const cpuCyclesPerLine = cpuFrequency/(60*262); const INITIAL_WATCHDOG = 256; const PIXEL_ON = 0xffeeeeee; const PIXEL_OFF = 0xff000000; @@ -90,6 +93,7 @@ const _BallyAstrocadePlatform = function(mainElement, arcade) { palette[i] = ASTROCADE_PALETTE[i]; var refreshlines = 0; + var vidactive = false; function ramwrite(a:number, v:number) { ram.mem[a] = v; @@ -176,6 +180,8 @@ const _BallyAstrocadePlatform = function(mainElement, arcade) { } class BallyAstrocadePlatform extends BaseZ80Platform implements Platform { + + scanline : number; getPresets() { return ASTROCADE_PRESETS; @@ -196,7 +202,10 @@ const _BallyAstrocadePlatform = function(mainElement, arcade) { [0x4000, 0x4fff, 0xfff, ramwrite], [0x0000, 0x3fff, 0x3fff, magicwrite], ]), - isContended: function() { return false; }, + // TODO: correct values? + // TODO: no contention on hblank + isContended: () => { return true; }, + contend: () => { return vidactive ? 1 : 0; }, }; } else { // arcade game @@ -211,10 +220,17 @@ const _BallyAstrocadePlatform = function(mainElement, arcade) { [0xd000, 0xdfff, 0xfff, function(a,v) { ramwrite(a+0x4000, v); } ], // static RAM [0x0000, 0x3fff, 0x3fff, magicwrite], ]), - isContended: function() { return false; }, + isContended: () => { return true; }, + contend: () => { return vidactive ? 1 : 0; }, }; } iobus = { + isULAPort: function(addr) { + return false; // TODO? + }, + contend: function(addr) { + return 0; // TODO? + }, read: function(addr) { addr &= 0x1f; var rtn = inputs[addr]; @@ -285,7 +301,7 @@ const _BallyAstrocadePlatform = function(mainElement, arcade) { } } }; - cpu = this.newCPU(membus, iobus); + cpu = this.newCPU(membus, iobus, {applyContention:true}); audio = new MasterAudio(); psg = new AstrocadeAudio(audio); video = new RasterVideo(mainElement,swidth,sheight,{}); @@ -308,13 +324,14 @@ const _BallyAstrocadePlatform = function(mainElement, arcade) { advance(novideo : boolean) { this.loadControls(); - for (var sl=0; sl0) { + if (sl < sheight && refreshlines>0) { refreshline(sl); refreshlines--; } @@ -329,6 +346,8 @@ const _BallyAstrocadePlatform = function(mainElement, arcade) { } */ } + + getRasterScanline() { return this.scanline; } loadROM(title, data) { rom = padBytes(data, arcade ? 0xb000 : 0x2000); @@ -476,7 +495,7 @@ for (var i=0; i<256; i++) { 0004 7E [ 7] 198 LD A,(HL) ; A <- mem[0x2000] 0005 FE 55 [ 7] 199 CP #0x55 ; found sentinel byte? ($55) 0007 CA 0D 00 [10] 200 JP Z,FoundSentinel ; yes, load program -000A C3 AB 0E [10] 201 JP _main ; jump to test program +000A C3 00 20 [10] 201 JP _main ; jump to test program 000D 202 FoundSentinel: 000D 31 CE 4F [10] 203 LD SP,#0x4fce ; position stack below BIOS vars 0010 CD 84 02 [17] 204 CALL _bios_init ; misc. bios init routines @@ -488,7 +507,7 @@ for (var i=0; i<256; i++) { 001A E9 [ 4] 210 JP (HL) ; jump to cart start vector */ var ASTROCADE_MINIMAL_BIOS = [ - 0xf3, 0x21, 0x00, 0x20, 0x7e, 0xfe, 0x55, 0xca, 0x0d, 0x00, 0xc3, 0xab, 0x0e, + 0xf3, 0x21, 0x00, 0x20, 0x7e, 0xfe, 0x55, 0xca, 0x0d, 0x00, 0xc3, 0x00, 0x20, 0x31, 0xce, 0x4f, 0xcd, 0x84, 0x02, 0x21, 0x05, 0x20, 0x7e, 0x23, 0x66, 0x6f, 0xe9, ]; diff --git a/src/platform/base_z80.ts b/src/platform/base_z80.ts index d35048e3..aa671b46 100644 --- a/src/platform/base_z80.ts +++ b/src/platform/base_z80.ts @@ -32,7 +32,6 @@ var Base_Z80Platform = function(mainElement) { write: newAddressDecoder([ [0x8000, 0xffff, 0x7fff, function(a,v) { ram.mem[a] = v; }], ]), - isContended: function() { return false; }, }; this.readAddress = membus.read; iobus = { diff --git a/src/platform/coleco.ts b/src/platform/coleco.ts index 6ddb07a0..7b8e67d3 100644 --- a/src/platform/coleco.ts +++ b/src/platform/coleco.ts @@ -89,7 +89,6 @@ const _ColecoVisionPlatform = function(mainElement) { write: newAddressDecoder([ [0x6000, 0x7fff, 0x3ff, function(a,v) { ram.mem[a] = v; }], ]), - isContended: function() { return false; }, }; iobus = { read: function(addr) { diff --git a/src/platform/galaxian.ts b/src/platform/galaxian.ts index b7010cc3..2bb12cca 100644 --- a/src/platform/galaxian.ts +++ b/src/platform/galaxian.ts @@ -249,7 +249,6 @@ const _GalaxianPlatform = function(mainElement, options) { //[0x8200, 0x8203, 0, function(a,v){ /* PPI 1 */ }], //[0, 0xffff, 0, function(a,v) { console.log(hex(a),hex(v)); }] ]), - isContended: function() { return false; }, }; } else { inputs = [0xe,0x8,0x0]; diff --git a/src/platform/msx.ts b/src/platform/msx.ts index da2c79a1..977bd49a 100644 --- a/src/platform/msx.ts +++ b/src/platform/msx.ts @@ -78,7 +78,6 @@ class MSXPlatform extends BasicZ80ScanlinePlatform implements Platform { let slot = this.slots[slotnum]; if (slot) slot.write(a, v); }, - isContended: () => { return false; }, }; } diff --git a/src/platform/mw8080bw.ts b/src/platform/mw8080bw.ts index d2dc225d..1fe710cb 100644 --- a/src/platform/mw8080bw.ts +++ b/src/platform/mw8080bw.ts @@ -62,7 +62,6 @@ class Midway8080BWPlatform extends BasicZ80ScanlinePlatform implements Platform //if (displayPCs) displayPCs[a] = cpu.getPC(); // save program counter }], ]), - isContended: function() { return false; }, }; } diff --git a/src/platform/sms.ts b/src/platform/sms.ts index 052d18a6..5344c059 100644 --- a/src/platform/sms.ts +++ b/src/platform/sms.ts @@ -78,7 +78,6 @@ class SG1000Platform extends BasicZ80ScanlinePlatform implements Platform { write: newAddressDecoder([ [0xc000, 0xffff, 0x3ff, (a,v) => { this.ram[a] = v; }], ]), - isContended: () => { return false; }, }; } diff --git a/src/platform/sound_williams.ts b/src/platform/sound_williams.ts index f6509443..825ab02f 100644 --- a/src/platform/sound_williams.ts +++ b/src/platform/sound_williams.ts @@ -72,7 +72,6 @@ var WilliamsSoundPlatform = function(mainElement) { write: newAddressDecoder([ [0x4000, 0x7fff, 0x3ff, function(a,v) { ram.mem[a] = v; }], ]), - isContended: function() { return false; }, }; iobus = { read: function(addr) { diff --git a/src/platform/vicdual.ts b/src/platform/vicdual.ts index 4f420aab..234111c9 100644 --- a/src/platform/vicdual.ts +++ b/src/platform/vicdual.ts @@ -136,7 +136,6 @@ class VicDualPlatform extends BasicZ80ScanlinePlatform implements Platform { write: newAddressDecoder([ [0x8000, 0xffff, 0x0fff, (a, v) => { this.ram[a] = v; }], ]), - isContended: () => { return false; }, }; } diff --git a/src/views.ts b/src/views.ts index 4c998662..1e500590 100644 --- a/src/views.ts +++ b/src/views.ts @@ -955,6 +955,10 @@ export class AssetEditorView implements ProjectView, pixed.EditorContext { if (len == matchlen) { var rgbs = palette.slice(start, start+len); result.push({node:node, name:name, palette:rgbs}); + } else if (-len == matchlen) { // reverse order + var rgbs = palette.slice(start, start-len); + rgbs.reverse(); + result.push({node:node, name:name, palette:rgbs}); } else if (len+1 == matchlen) { var rgbs = new Uint32Array(matchlen); rgbs[0] = palette[0]; @@ -1107,8 +1111,10 @@ export class AssetEditorView implements ProjectView, pixed.EditorContext { var arow = $('').appendTo(atable); $('').text(name).appendTo(arow); var inds = []; - for (var k=start; k { var cell = $('').addClass('asset_cell asset_editable').appendTo(arow); updateCell(cell, i);