mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2025-02-20 14:29:16 +00:00
astrocade: updated presets, added memory bus contention, palette layout
This commit is contained in:
parent
8e19a65968
commit
c93ba6fd75
95
presets/astrocade-bios/biosasm.s
Normal file
95
presets/astrocade-bios/biosasm.s
Normal file
@ -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
|
@ -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
|
||||
|
@ -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<h; j++) {
|
||||
EXIT_CLIPDEST(dest);
|
||||
for (i=0; i<w; i++) {
|
||||
*dest++ = *src++;
|
||||
}
|
||||
*dest = 0; // rest of shifted byte
|
||||
dest += VBWIDTH-w; // dest address to next scanline
|
||||
// y clipping off bottom
|
||||
if (y+h >= 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<h; j++) {
|
||||
EXIT_CLIPDEST(dest);
|
||||
for (i=0; i<w; i++) {
|
||||
*dest++ = 0;
|
||||
// memory copy loop
|
||||
if (op != M_ERASE) {
|
||||
for (j=0; j<h; j++) {
|
||||
for (i=0; i<w; i++) {
|
||||
*dest++ = *src++;
|
||||
}
|
||||
*dest = 0; // rest of shifted byte
|
||||
dest += VBWIDTH-w; // dest address to next scanline
|
||||
}
|
||||
// erase sprite loop
|
||||
} else {
|
||||
for (j=0; j<h; j++) {
|
||||
for (i=0; i<w; i++) {
|
||||
*dest++ = 0;
|
||||
}
|
||||
*dest = 0; // rest of shifted byte
|
||||
dest += VBWIDTH-w; // dest address to next scanline
|
||||
}
|
||||
*dest = 0; // rest of shifted byte
|
||||
dest += VBWIDTH-w; // dest address to next scanline
|
||||
}
|
||||
}
|
||||
|
||||
@ -79,8 +88,12 @@ void draw_char(byte ch, byte x, byte y, byte op) {
|
||||
EXIT_CLIPDEST(dest);
|
||||
*dest++ = b; // expand lower nibble -> 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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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<MAXLIVES; i++) {
|
||||
draw_char(i<n?'|':' ', x, y, M_MOVE);
|
||||
|
32
presets/astrocade/hello.c
Normal file
32
presets/astrocade/hello.c
Normal file
@ -0,0 +1,32 @@
|
||||
|
||||
#include "aclib.h"
|
||||
//#link "aclib.c"
|
||||
//#link "acheader.s"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
/*{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) {
|
||||
}
|
||||
}
|
@ -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
|
||||
|
50
presets/astrocade/lines.c
Normal file
50
presets/astrocade/lines.c
Normal file
@ -0,0 +1,50 @@
|
||||
|
||||
#include "aclib.h"
|
||||
//#link "aclib.c"
|
||||
//#link "acheader.s"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
void draw_line(int x0, int y0, int x1, int y1, byte color) {
|
||||
int dx = abs(x1-x0);
|
||||
int sx = x0<x1 ? 1 : -1;
|
||||
int dy = abs(y1-y0);
|
||||
int sy = y0<y1 ? 1 : -1;
|
||||
int err = (dx>dy ? 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);
|
||||
}
|
||||
}
|
@ -1,8 +1,29 @@
|
||||
|
||||
#include "aclib.h"
|
||||
//#link "aclib.c"
|
||||
//#link "acheader.s"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
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) {
|
||||
}
|
||||
}
|
||||
|
34
presets/astrocade/sprites.c
Normal file
34
presets/astrocade/sprites.c
Normal file
@ -0,0 +1,34 @@
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#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++;
|
||||
}
|
||||
}
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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; sl<sheight; sl++) {
|
||||
//console.log(sl, hex(cpu.getPC(),4), cpu.saveState());
|
||||
this.runCPU(cpu, cpuCyclesPerLine);
|
||||
for (var sl=0; sl<131; sl++) {
|
||||
this.scanline = sl;
|
||||
vidactive = sl < verbl;
|
||||
this.runCPU(cpu, cpuCyclesPerLine*2); // TODO?
|
||||
if (sl == inlin && (inmod & 0x8)) {
|
||||
this.requestInterrupt(cpu, infbk);
|
||||
}
|
||||
if (refreshlines>0) {
|
||||
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,
|
||||
];
|
||||
|
@ -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 = {
|
||||
|
@ -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) {
|
||||
|
@ -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];
|
||||
|
@ -78,7 +78,6 @@ class MSXPlatform extends BasicZ80ScanlinePlatform implements Platform {
|
||||
let slot = this.slots[slotnum];
|
||||
if (slot) slot.write(a, v);
|
||||
},
|
||||
isContended: () => { return false; },
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -62,7 +62,6 @@ class Midway8080BWPlatform extends BasicZ80ScanlinePlatform implements Platform
|
||||
//if (displayPCs) displayPCs[a] = cpu.getPC(); // save program counter
|
||||
}],
|
||||
]),
|
||||
isContended: function() { return false; },
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -78,7 +78,6 @@ class SG1000Platform extends BasicZ80ScanlinePlatform implements Platform {
|
||||
write: newAddressDecoder([
|
||||
[0xc000, 0xffff, 0x3ff, (a,v) => { this.ram[a] = v; }],
|
||||
]),
|
||||
isContended: () => { return false; },
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -136,7 +136,6 @@ class VicDualPlatform extends BasicZ80ScanlinePlatform implements Platform {
|
||||
write: newAddressDecoder([
|
||||
[0x8000, 0xffff, 0x0fff, (a, v) => { this.ram[a] = v; }],
|
||||
]),
|
||||
isContended: () => { return false; },
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -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 = $('<tr/>').appendTo(atable);
|
||||
$('<td/>').text(name).appendTo(arow);
|
||||
var inds = [];
|
||||
for (var k=start; k<start+len; k++)
|
||||
for (var k=start; k<start+Math.abs(len); k++)
|
||||
inds.push(k);
|
||||
if (len < 0)
|
||||
inds.reverse();
|
||||
inds.forEach( (i) => {
|
||||
var cell = $('<td/>').addClass('asset_cell asset_editable').appendTo(arow);
|
||||
updateCell(cell, i);
|
||||
|
Loading…
x
Reference in New Issue
Block a user