download current editor file; more apple2

This commit is contained in:
Steven Hugg 2018-08-05 10:00:53 -04:00
parent 0cb8ea7661
commit 6670e27035
14 changed files with 1298 additions and 59 deletions

View File

@ -52,6 +52,7 @@ TODO:
- Verilog compile spins forever?
- how to revert included files?
- go to error in include files
- BOM in upload/download?
WEB WORKER FORMAT

552
presets/apple2/cosmic.c Normal file
View File

@ -0,0 +1,552 @@

#include <string.h>
typedef unsigned char byte;
typedef signed char sbyte;
typedef unsigned short word;
#define POKE(addr,val) (*(unsigned char*) (addr) = (val))
#define POKEW(addr,val) (*(unsigned*) (addr) = (val))
#define PEEK(addr) (*(unsigned char*) (addr))
#define PEEKW(addr) (*(unsigned*) (addr))
#define STROBE(addr) __asm__ ("sta %w", addr)
#define CLICK STROBE(0xc030)
/// HIRES LOOKUP TABLE
#define VHEIGHT 192
#define VBWIDTH 40
#define LUT(x) (byte*)(0x2000|x)
static byte* vidmem[VHEIGHT] = {
LUT(0x0000), LUT(0x0400), LUT(0x0800), LUT(0x0c00), LUT(0x1000), LUT(0x1400), LUT(0x1800), LUT(0x1c00),
LUT(0x0080), LUT(0x0480), LUT(0x0880), LUT(0x0c80), LUT(0x1080), LUT(0x1480), LUT(0x1880), LUT(0x1c80),
LUT(0x0100), LUT(0x0500), LUT(0x0900), LUT(0x0d00), LUT(0x1100), LUT(0x1500), LUT(0x1900), LUT(0x1d00),
LUT(0x0180), LUT(0x0580), LUT(0x0980), LUT(0x0d80), LUT(0x1180), LUT(0x1580), LUT(0x1980), LUT(0x1d80),
LUT(0x0200), LUT(0x0600), LUT(0x0a00), LUT(0x0e00), LUT(0x1200), LUT(0x1600), LUT(0x1a00), LUT(0x1e00),
LUT(0x0280), LUT(0x0680), LUT(0x0a80), LUT(0x0e80), LUT(0x1280), LUT(0x1680), LUT(0x1a80), LUT(0x1e80),
LUT(0x0300), LUT(0x0700), LUT(0x0b00), LUT(0x0f00), LUT(0x1300), LUT(0x1700), LUT(0x1b00), LUT(0x1f00),
LUT(0x0380), LUT(0x0780), LUT(0x0b80), LUT(0x0f80), LUT(0x1380), LUT(0x1780), LUT(0x1b80), LUT(0x1f80),
LUT(0x0028), LUT(0x0428), LUT(0x0828), LUT(0x0c28), LUT(0x1028), LUT(0x1428), LUT(0x1828), LUT(0x1c28),
LUT(0x00a8), LUT(0x04a8), LUT(0x08a8), LUT(0x0ca8), LUT(0x10a8), LUT(0x14a8), LUT(0x18a8), LUT(0x1ca8),
LUT(0x0128), LUT(0x0528), LUT(0x0928), LUT(0x0d28), LUT(0x1128), LUT(0x1528), LUT(0x1928), LUT(0x1d28),
LUT(0x01a8), LUT(0x05a8), LUT(0x09a8), LUT(0x0da8), LUT(0x11a8), LUT(0x15a8), LUT(0x19a8), LUT(0x1da8),
LUT(0x0228), LUT(0x0628), LUT(0x0a28), LUT(0x0e28), LUT(0x1228), LUT(0x1628), LUT(0x1a28), LUT(0x1e28),
LUT(0x02a8), LUT(0x06a8), LUT(0x0aa8), LUT(0x0ea8), LUT(0x12a8), LUT(0x16a8), LUT(0x1aa8), LUT(0x1ea8),
LUT(0x0328), LUT(0x0728), LUT(0x0b28), LUT(0x0f28), LUT(0x1328), LUT(0x1728), LUT(0x1b28), LUT(0x1f28),
LUT(0x03a8), LUT(0x07a8), LUT(0x0ba8), LUT(0x0fa8), LUT(0x13a8), LUT(0x17a8), LUT(0x1ba8), LUT(0x1fa8),
LUT(0x0050), LUT(0x0450), LUT(0x0850), LUT(0x0c50), LUT(0x1050), LUT(0x1450), LUT(0x1850), LUT(0x1c50),
LUT(0x00d0), LUT(0x04d0), LUT(0x08d0), LUT(0x0cd0), LUT(0x10d0), LUT(0x14d0), LUT(0x18d0), LUT(0x1cd0),
LUT(0x0150), LUT(0x0550), LUT(0x0950), LUT(0x0d50), LUT(0x1150), LUT(0x1550), LUT(0x1950), LUT(0x1d50),
LUT(0x01d0), LUT(0x05d0), LUT(0x09d0), LUT(0x0dd0), LUT(0x11d0), LUT(0x15d0), LUT(0x19d0), LUT(0x1dd0),
LUT(0x0250), LUT(0x0650), LUT(0x0a50), LUT(0x0e50), LUT(0x1250), LUT(0x1650), LUT(0x1a50), LUT(0x1e50),
LUT(0x02d0), LUT(0x06d0), LUT(0x0ad0), LUT(0x0ed0), LUT(0x12d0), LUT(0x16d0), LUT(0x1ad0), LUT(0x1ed0),
LUT(0x0350), LUT(0x0750), LUT(0x0b50), LUT(0x0f50), LUT(0x1350), LUT(0x1750), LUT(0x1b50), LUT(0x1f50),
LUT(0x03d0), LUT(0x07d0), LUT(0x0bd0), LUT(0x0fd0), LUT(0x13d0), LUT(0x17d0), LUT(0x1bd0), LUT(0x1fd0)
};
/// SOUND FUNCTIONS
void tone(byte freq, byte dur, sbyte mod) {
word i;
while (dur--) {
for (i=0; i<freq; i++) ;
CLICK;
freq += mod;
}
}
/// GRAPHICS FUNCTIONS
void clrscr() {
STROBE(0xc052); // turn off mixed-mode
STROBE(0xc054); // page 1
STROBE(0xc057); // hi-res
STROBE(0xc050); // set graphics mode
memset((byte*)0x2000, 0, 0x2000); // clear page 1
}
void xor_pixel(byte x, byte y) {
byte* dest = &vidmem[x][y>>3];
*dest ^= 0x1 << (y&7);
}
void draw_vline(byte x, byte y1, byte y2) {
byte yb1 = y1/8;
byte yb2 = y2/8;
byte* dest = &vidmem[x][yb1];
signed char nbytes = yb2 - yb1;
*dest++ ^= 0xff << (y1&7);
if (nbytes > 0) {
while (--nbytes > 0) {
*dest++ ^= 0xff;
}
*dest ^= 0xff >> (~y2&7);
} else {
*--dest ^= 0xff << ((y2+1)&7);
}
}
#define LOCHAR 0x20
#define HICHAR 0x5e
const byte font8x8[HICHAR-LOCHAR+1][8] = {/*{w:8,h:8,bpp:1,count:64,xform:"rotate(-90deg)"}*/
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, { 0x00,0x00,0x00,0x79,0x79,0x00,0x00,0x00 }, { 0x00,0x70,0x70,0x00,0x00,0x70,0x70,0x00 }, { 0x14,0x7f,0x7f,0x14,0x14,0x7f,0x7f,0x14 }, { 0x00,0x12,0x3a,0x6b,0x6b,0x2e,0x24,0x00 }, { 0x00,0x63,0x66,0x0c,0x18,0x33,0x63,0x00 }, { 0x00,0x26,0x7f,0x59,0x59,0x77,0x27,0x05 }, { 0x00,0x00,0x00,0x10,0x30,0x60,0x40,0x00 }, { 0x00,0x00,0x1c,0x3e,0x63,0x41,0x00,0x00 }, { 0x00,0x00,0x41,0x63,0x3e,0x1c,0x00,0x00 }, { 0x08,0x2a,0x3e,0x1c,0x1c,0x3e,0x2a,0x08 }, { 0x00,0x08,0x08,0x3e,0x3e,0x08,0x08,0x00 }, { 0x00,0x00,0x00,0x03,0x03,0x00,0x00,0x00 }, { 0x00,0x08,0x08,0x08,0x08,0x08,0x08,0x00 }, { 0x00,0x00,0x00,0x03,0x03,0x00,0x00,0x00 }, { 0x00,0x01,0x03,0x06,0x0c,0x18,0x30,0x20 }, { 0x00,0x3e,0x7f,0x49,0x51,0x7f,0x3e,0x00 }, { 0x00,0x01,0x11,0x7f,0x7f,0x01,0x01,0x00 }, { 0x00,0x23,0x67,0x45,0x49,0x79,0x31,0x00 }, { 0x00,0x22,0x63,0x49,0x49,0x7f,0x36,0x00 }, { 0x00,0x0c,0x0c,0x14,0x34,0x7f,0x7f,0x04 }, { 0x00,0x72,0x73,0x51,0x51,0x5f,0x4e,0x00 }, { 0x00,0x3e,0x7f,0x49,0x49,0x6f,0x26,0x00 }, { 0x00,0x60,0x60,0x4f,0x5f,0x70,0x60,0x00 }, { 0x00,0x36,0x7f,0x49,0x49,0x7f,0x36,0x00 }, { 0x00,0x32,0x7b,0x49,0x49,0x7f,0x3e,0x00 }, { 0x00,0x00,0x00,0x12,0x12,0x00,0x00,0x00 }, { 0x00,0x00,0x00,0x13,0x13,0x00,0x00,0x00 }, { 0x00,0x08,0x1c,0x36,0x63,0x41,0x41,0x00 }, { 0x00,0x14,0x14,0x14,0x14,0x14,0x14,0x00 }, { 0x00,0x41,0x41,0x63,0x36,0x1c,0x08,0x00 }, { 0x00,0x20,0x60,0x45,0x4d,0x78,0x30,0x00 }, { 0x00,0x3e,0x7f,0x41,0x59,0x79,0x3a,0x00 }, { 0x00,0x1f,0x3f,0x68,0x68,0x3f,0x1f,0x00 }, { 0x00,0x7f,0x7f,0x49,0x49,0x7f,0x36,0x00 }, { 0x00,0x3e,0x7f,0x41,0x41,0x63,0x22,0x00 }, { 0x00,0x7f,0x7f,0x41,0x63,0x3e,0x1c,0x00 }, { 0x00,0x7f,0x7f,0x49,0x49,0x41,0x41,0x00 }, { 0x00,0x7f,0x7f,0x48,0x48,0x40,0x40,0x00 }, { 0x00,0x3e,0x7f,0x41,0x49,0x6f,0x2e,0x00 }, { 0x00,0x7f,0x7f,0x08,0x08,0x7f,0x7f,0x00 }, { 0x00,0x00,0x41,0x7f,0x7f,0x41,0x00,0x00 }, { 0x00,0x02,0x03,0x41,0x7f,0x7e,0x40,0x00 }, { 0x00,0x7f,0x7f,0x1c,0x36,0x63,0x41,0x00 }, { 0x00,0x7f,0x7f,0x01,0x01,0x01,0x01,0x00 }, { 0x00,0x7f,0x7f,0x30,0x18,0x30,0x7f,0x7f }, { 0x00,0x7f,0x7f,0x38,0x1c,0x7f,0x7f,0x00 }, { 0x00,0x3e,0x7f,0x41,0x41,0x7f,0x3e,0x00 }, { 0x00,0x7f,0x7f,0x48,0x48,0x78,0x30,0x00 }, { 0x00,0x3c,0x7e,0x42,0x43,0x7f,0x3d,0x00 }, { 0x00,0x7f,0x7f,0x4c,0x4e,0x7b,0x31,0x00 }, { 0x00,0x32,0x7b,0x49,0x49,0x6f,0x26,0x00 }, { 0x00,0x40,0x40,0x7f,0x7f,0x40,0x40,0x00 }, { 0x00,0x7e,0x7f,0x01,0x01,0x7f,0x7e,0x00 }, { 0x00,0x7c,0x7e,0x03,0x03,0x7e,0x7c,0x00 }, { 0x00,0x7f,0x7f,0x06,0x0c,0x06,0x7f,0x7f }, { 0x00,0x63,0x77,0x1c,0x1c,0x77,0x63,0x00 }, { 0x00,0x70,0x78,0x0f,0x0f,0x78,0x70,0x00 }, { 0x00,0x43,0x47,0x4d,0x59,0x71,0x61,0x00 }, { 0x00,0x00,0x7f,0x7f,0x41,0x41,0x00,0x00 }, { 0x00,0x20,0x30,0x18,0x0c,0x06,0x03,0x01 }, { 0x00,0x00,0x41,0x41,0x7f,0x7f,0x00,0x00 }, { 0x00,0x08,0x18,0x3f,0x3f,0x18,0x08,0x00 }
};
void draw_sprite(const byte* src, byte x, byte y) {
byte i,j;
byte w = *src++;
byte h = *src++;
for (j=0; j<h; j++) {
byte* dest = &vidmem[x++][y];
for (i=0; i<w; i++) {
*dest++ = *src++;
}
}
}
byte xor_sprite(const byte* src, byte x, byte y) {
byte i,j;
byte result = 0;
byte w = *src++;
byte h = *src++;
for (j=0; j<h; j++) {
byte* dest = &vidmem[x++][y];
for (i=0; i<w; i++) {
result |= (*dest++ ^= *src++);
}
}
return result;
}
void erase_sprite(const byte* src, byte x, byte y) {
byte i,j;
byte w = *src++;
byte h = *src++;
for (j=0; j<h; j++) {
byte* dest = &vidmem[x++][y];
for (i=0; i<w; i++) {
*dest++ &= ~(*src++);
}
}
}
void clear_sprite(const byte* src, byte x, byte y) {
byte i,j;
byte w = *src++;
byte h = *src++;
for (j=0; j<h; j++) {
byte* dest = &vidmem[x++][y];
for (i=0; i<w; i++) {
*dest++ = 0;
}
}
}
void draw_char(char ch, byte x, byte y) {
byte i;
const byte* src = &font8x8[(ch-LOCHAR)][0];
x *= 8;
for (i=0; i<8; i++) {
byte* dest = &vidmem[x++][y];
*dest = *src;
src += 1;
}
}
void draw_string(const char* str, byte x, byte y) {
do {
byte ch = *str++;
if (!ch) break;
draw_char(ch, x, y);
x++;
} while (1);
}
void draw_bcd_word(word bcd, byte x, byte y) {
byte j;
x += 3;
for (j=0; j<4; j++) {
draw_char('0'+(bcd&0xf), x, y);
x--;
bcd >>= 4;
}
}
word bcd_add(word a, word b) {
word result;
__asm__ ("sed"); // set decimal (BCD) mode
result = a+b;
__asm__ ("cld"); // clear BCD mode
return result;
}
//
// GAME GRAPHICS
//
const byte player_bitmap[] =
{2,27,/*{w:16,h:27,bpp:1,xform:"rotate(-90deg)"}*/0x0,0x0,0x0,0x0,0x0f,0x00,0x3e,0x00,0xf4,0x07,0xec,0x00,0x76,0x00,0x2b,0x00,0x33,0x00,0x75,0x00,0xf5,0x00,0xeb,0x31,0xbf,0xef,0x3f,0xcf,0xbf,0xef,0xeb,0x31,0xf5,0x00,0x75,0x00,0x33,0x00,0x2b,0x00,0x76,0x00,0xec,0x00,0xf4,0x07,0x3e,0x00,0x0f,0x00,0x00,0x00,0x0,0x0};
const byte bomb_bitmap[] =
{1,5,/*{w:8,h:5,bpp:1,xform:"rotate(-90deg)"}*/0x88,0x55,0x77,0x55,0x88};
const byte bullet_bitmap[] =
{2,2,/*{w:16,h:2,bpp:1,xform:"rotate(-90deg)"}*/0x88,0x88,0x44,0x44};
const byte enemy1_bitmap[] =
{2,17,/*{w:16,h:17,bpp:1,xform:"rotate(-90deg)"}*/0x00,0x00,0x00,0x0c,0x04,0x1e,0x46,0x3f,0xb8,0x7f,0xb0,0x7f,0xba,0x7f,0xfd,0x3f,0xfc,0x07,0xfc,0x07,0xfd,0x3f,0xba,0x7f,0xb0,0x7f,0xb8,0x7f,0x46,0x3f,0x04,0x1e,0x00,0x0c};
const byte enemy2_bitmap[] =
{2,16,/*{w:16,h:16,bpp:1,xform:"rotate(-90deg)"}*/0x26,0x00,0x59,0x10,0x10,0x30,0x33,0x18,0xe6,0x61,0xc4,0x56,0x03,0x03,0xdc,0x03,0xdc,0x03,0x03,0x03,0xc4,0x56,0xe6,0x61,0x33,0x18,0x10,0x30,0x59,0x10,0x26,0x00};
const byte enemy3_bitmap[] =
{2,16,/*{w:16,h:16,bpp:1,xform:"rotate(-90deg)"}*/0x80,0x1f,0xc0,0x03,0xf8,0x3f,0x70,0x00,0xf0,0x01,0xfc,0x07,0xe8,0x01,0xf8,0x03,0xf8,0x03,0xe8,0x01,0xf8,0x07,0xf0,0x01,0x70,0x00,0xf8,0x3f,0xc0,0x03,0x80,0x1f};
const byte enemy4_bitmap[] =
{2,16,/*{w:16,h:16,bpp:1,xform:"rotate(-90deg)"}*/0x06,0x00,0x0c,0x00,0x28,0x00,0x70,0x1f,0x84,0x3f,0xde,0x37,0xbb,0x3f,0xf0,0x3f,0xf0,0x3f,0xbb,0x3f,0xde,0x37,0x84,0x3f,0x70,0x1f,0x28,0x00,0x0c,0x00,0x06,0x00};
const byte* const enemy_bitmaps[4] = {
enemy1_bitmap,
enemy2_bitmap,
enemy3_bitmap,
enemy4_bitmap
};
//
// GAME CODE
//
byte attract;
byte credits;
byte curplayer;
word score;
byte lives;
#define MAXLIVES 5
byte player_x;
byte bullet_x;
byte bullet_y;
byte bomb_x;
byte bomb_y;
typedef struct {
byte x,y;
const byte* shape; // need const here
} Enemy;
#define MAX_ENEMIES 28
Enemy enemies[MAX_ENEMIES];
byte enemy_index;
byte num_enemies;
typedef struct {
int right:1;
int down:1;
} MarchMode;
MarchMode this_mode, next_mode;
void draw_lives(byte player) {
byte i;
byte n = lives;
byte x = player ? (22-MAXLIVES) : 6;
byte y = VBWIDTH-3;
for (i=0; i<MAXLIVES; i++) {
draw_char(i<n?'*':' ', x++, y);
}
}
void draw_score(byte player) {
byte x = player ? 24 : 0;
byte y = VBWIDTH-3;
draw_bcd_word(score, x, y);
}
void add_score(word pts) {
if (attract) return;
score = bcd_add(score, pts);
draw_score(curplayer);
}
void xor_player_derez() {
byte i,j;
byte x = player_x+13;
byte y = 8;
byte* rand = (byte*) &clrscr; // use code as random #'s
for (j=1; j<=0x1f; j++) {
for (i=0; i<50; i++) {
signed char xx = x + (*rand++ & 0x1f) - 15;
signed char yy = y + (*rand++ & j);
xor_pixel(xx, yy);
if ((xx & 0x1f) > j) { CLICK; }
}
}
}
void destroy_player() {
xor_player_derez(); // xor derez pattern
xor_sprite(player_bitmap, player_x, 1); // erase ship via xor
xor_player_derez(); // xor 2x to erase derez pattern
player_x = 0xff;
lives--;
}
void init_enemies() {
byte i,x,y,bm;
x=0;
y=26;
bm=0;
for (i=0; i<MAX_ENEMIES; i++) {
Enemy* e = &enemies[i];
e->x = x;
e->y = y;
e->shape = enemy_bitmaps[bm];
x += 28;
if (x >= VHEIGHT-32) {
x = 0;
y -= 3;
bm++;
}
}
enemy_index = 0;
num_enemies = MAX_ENEMIES;
this_mode.right = 1;
this_mode.down = 0;
next_mode.right = 1;
next_mode.down = 0;
}
void delete_enemy(Enemy* e) {
clear_sprite(e->shape, e->x, e->y);
memmove(e, e+1, sizeof(Enemy)*(enemies-e+MAX_ENEMIES-1));
num_enemies--; // update_next_enemy() will check enemy_index
tone(1,10,10);
}
void update_next_enemy() {
Enemy* e;
if (enemy_index >= num_enemies) {
enemy_index = 0;
memcpy(&this_mode, &next_mode, sizeof(this_mode));
tone(220+num_enemies,3,1);
}
e = &enemies[enemy_index];
clear_sprite(e->shape, e->x, e->y);
if (this_mode.down) {
// if too close to ground, end game
if (--e->y < 5) {
destroy_player();
lives = 0;
}
next_mode.down = 0;
} else {
if (this_mode.right) {
e->x += 2;
if (e->x >= VHEIGHT-32) {
next_mode.down = 1;
next_mode.right = 0;
}
} else {
e->x -= 2;
if (e->x == 0) {
next_mode.down = 1;
next_mode.right = 1;
}
}
}
draw_sprite(e->shape, e->x, e->y);
enemy_index++;
}
void draw_bunker(byte x, byte y, byte y2, byte h, byte w) {
byte i;
for (i=0; i<h; i++) {
draw_vline(x+i, y+i, y+y2+i*2);
draw_vline(x+h*2+w-i-1, y+i, y+y2+i*2);
}
for (i=0; i<w; i++) {
draw_vline(x+h+i, y+h, y+y2+h*2);
}
}
void draw_playfield() {
byte i;
clrscr();
draw_string("PLAYER 1", 0, VBWIDTH-1);
draw_score(0);
draw_lives(0);
for (i=0; i<VHEIGHT; i++)
vidmem[i][0] = 0x7f & 0x55;
draw_bunker(20, 40, 15, 15, 20);
draw_bunker(125, 40, 15, 15, 20);
}
char in_rect(Enemy* e, byte x, byte y, byte w, byte h) {
byte eh = e->shape[0];
byte ew = e->shape[1];
return (x >= e->x-w && x <= e->x+ew && y >= e->y-h && y <= e->y+eh);
}
Enemy* find_enemy_at(byte x, byte y) {
byte i;
for (i=0; i<num_enemies; i++) {
Enemy* e = &enemies[i];
if (in_rect(e, x, y, 2, 0)) {
return e;
}
}
return NULL;
}
void check_bullet_hit(byte x, byte y) {
Enemy* e = find_enemy_at(x,y);
if (e) {
delete_enemy(e);
add_score(0x25);
}
}
void fire_bullet() {
bullet_x = player_x + 13;
bullet_y = 3;
xor_sprite(bullet_bitmap, bullet_x, bullet_y); // draw
}
void move_bullet() {
byte leftover = xor_sprite(bullet_bitmap, bullet_x, bullet_y); // erase
if (leftover || bullet_y > 26) {
clear_sprite(bullet_bitmap, bullet_x, bullet_y);
check_bullet_hit(bullet_x, bullet_y+2);
bullet_y = 0;
} else {
bullet_y++;
tone(bullet_y,3,0);
xor_sprite(bullet_bitmap, bullet_x, bullet_y); // draw
}
}
void drop_bomb() {
Enemy* e = &enemies[enemy_index];
bomb_x = e->x + 7;
bomb_y = e->y - 2;
xor_sprite(bomb_bitmap, bomb_x, bomb_y);
}
void move_bomb() {
byte leftover = xor_sprite(bomb_bitmap, bomb_x, bomb_y); // erase
if (bomb_y < 2) {
bomb_y = 0;
} else if (leftover) {
erase_sprite(bomb_bitmap, bomb_x, bomb_y); // erase bunker
if (bomb_y < 3) {
// player was hit (probably)
destroy_player();
}
bomb_y = 0;
} else {
bomb_y--;
xor_sprite(bomb_bitmap, bomb_x, bomb_y);
}
}
byte frame;
signed char player_dir = 0;
void move_player() {
if (attract) {
if (bullet_y == 0) fire_bullet();
} else {
char key = PEEK(0xc000);
if (key & 0x80) {
switch (key) {
case 0xc1:
player_dir = player_dir < 0 ? 0 : -2;
break;
case 0xda:
player_dir = player_dir > 0 ? 0 : 2;
break;
case 0xa0:
if (bullet_y == 0) {
fire_bullet();
}
break;
}
STROBE(0xc010);
}
if (player_dir < 0 && player_x > 0)
player_x += player_dir;
else if (player_dir > 0 && player_x < VHEIGHT-28)
player_x += player_dir;
}
draw_sprite(player_bitmap, player_x, 1);
}
void play_round() {
draw_playfield();
player_x = VHEIGHT/2-8;
bullet_y = 0;
bomb_y = 0;
frame = 0;
while (player_x != 0xff && num_enemies) {
move_player();
if (bullet_y) {
move_bullet();
}
update_next_enemy();
if (frame & 1) {
if (bomb_y == 0) {
drop_bomb();
} else {
move_bomb();
}
}
frame++;
}
}
void init_game() {
score = 0;
lives = 5;
curplayer = 0;
}
void game_over_msg() {
byte i;
for (i=0; i<50; i++) {
draw_string(" *************** ", 5, 15);
draw_string("*** ***", 5, 16);
draw_string("** GAME OVER **", 5, 17);
draw_string("*** ***", 5, 18);
draw_string(" *************** ", 5, 19);
}
}
void play_game() {
attract = 0;
init_game();
init_enemies();
while (lives) {
play_round();
if (num_enemies == 0) {
init_enemies();
}
}
game_over_msg();
}
void attract_mode() {
attract = 1;
while (1) {
init_enemies();
play_round();
}
}
void main() {
// NOTE: initializers don't get run, so we init here
credits = 0;
while (1) {
//attract_mode();
play_game();
}
}

416
presets/apple2/lz4fh.a Normal file
View File

@ -0,0 +1,416 @@

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; LZ4FH uncompression for 6502 ;
; By Andy McFadden ;
; Version 1.0.1, August 2015 ;
; ;
; Refactored for size & speed ;
; by Peter Ferrie. ;
; ;
; Developed with Merlin-16 ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
processor 6502
org $0803
;
; Constants
;
lz4fh_magic equ $66 ;ascii 'f'
tok_empty equ 253
tok_eod equ 254
;
; Variable storage
;
srcptr equ $3c ;2b a1l
dstptr equ $3e ;2b a1h
copyptr equ $00 ;2b
savmix equ $02 ;1b
savlen equ $03 ;1b
;
; ROM routines
;
bell equ $ff3a
monitor equ $ff69
entry
sta $c050
sta $c052
sta $c057
jsr ClrScr
jsr UnpackLZ4FH
.endless
jmp .endless
UnpackLZ4FH:
lda #<LZDATA ;copy source address to zero page
sta srcptr
lda #>LZDATA
sta srcptr+1
lda #0 ;copy destination address to zero page
sta dstptr
lda #$20
sta dstptr+1
sta _desthi+1
ldy #$00
lda (srcptr),y
cmp #lz4fh_magic ;does magic match?
beq goodmagic
fail
jsr bell
jmp monitor
; These stubs increment the high byte and then jump
; back. This saves a cycle because branch-not-taken
; becomes the common case. We assume that we're not
; unpacking data at $FFxx, so BNE is branch-always.
hi2
inc srcptr+1
bne nohi2
hi3
inc srcptr+1
clc
bcc nohi3
hi4
inc dstptr+1
bne nohi4
notempty
cmp #tok_eod
bne fail
rts ;success!
; handle "special" match values (value in A)
specialmatch
cmp #tok_empty
bne notempty
tya ;empty match, advance srcptr
adc srcptr ; past and jump to main loop
sta srcptr
bcc mainloop
inc srcptr+1
bne mainloop
hi5
inc srcptr+1
clc
bcc nohi5
goodmagic
inc srcptr
bne mainloop
inc srcptr+1
mainloop
; Get the mixed-length byte and handle the literal.
ldy #$00
lda (srcptr),y ;get mixed-length byte
sta savmix
lsr ;get the literal length
lsr
lsr
lsr
beq noliteral
cmp #$0f ;sets carry for >= 15
bne shortlit
inc srcptr
beq hi2
nohi2
lda (srcptr),y ;get length extension
adc #14 ;(carry set) add 15 - will not exceed 255
; at this point, srcptr holds the address of the "mix"
; word or the length extension, and dstptr holds the
; address of the next output location. So we want to
; read from (srcptr),y+1 and write to (dstptr),y.
; we can do this by sticking the DEY between the LDa
; and STa.
;
; We could save a couple of cycles by substituting
; addr,y in place of (dp),y, but the added setup cost
; would only benefit longer literal strings.
shortlit tax
tay
.litloop
lda (srcptr),y ;5
dey ;2 if len is 255, copy 0-254
sta (dstptr),y ;6
bne .litloop ;3 -> 16 cycles/byte
; advance srcptr by savlen+1, and dstptr by savlen
txa
sec ;this gets us the +1
adc srcptr
sta srcptr
bcs hi3
nohi3 ;carry cleared by hi3
txa
adc dstptr
sta dstptr
bcs hi4
nohi4
dey ;Y=0; DEY so next INY goes to 0
; Handle match. Y holds an offset into srcptr such
; that we need to increment it once to get the next
; interesting byte.
noliteral
lda savmix
and #$0f
cmp #$0f
bcc .shortmatch ;BCC
iny
lda (srcptr),y ;get length extension
cmp #237 ;"normal" values are 0-236
bcs specialmatch ;BCS
adc #15 ;will not exceed 255
; Put the destination address into copyptr.
.shortmatch
adc #4 ;min match; won't exceed 255
sta savlen ;save match len for later
tax ;and keep it in X
iny
lda (srcptr),y ;match offset, lo
sta copyptr
iny
lda (srcptr),y ;match offset, hi
_desthi ora #$00 ;OR in hi-res page
sta copyptr+1
; advance srcptr past the encoded match while we still
; remember how many bytes it took to encode. Y is
; indexing the last value used, so we want to go
; advance srcptr by Y+1.
tya
sec
adc srcptr
sta srcptr
bcs hi5
nohi5 ;hi5 clears carry
; Copy the match. The length is in X. Note this
; must be a forward copy so overlapped data works.
;
; We know the match is at least 4 bytes long, so
; we could save a few cycles by not doing the
; aDC #4 earlier, and unrolling the first 4
; load/store operations here.
ldy #$00
.copyloop
lda (copyptr),y ;5
sta (dstptr),y ;6
iny ;2
dex ;2
bne .copyloop ;3 -> 18 cycles/byte
; advance dstptr past copied data
lda dstptr
adc savlen ;carry is clear
sta dstptr
bcc mainloop
inc dstptr+1
bne mainloop ;always (not unpacking at $FFxx)
ClrScr:
lda #$20
sta .clrloop+2
ldy #0
lda #0
.clrloop sta $2000,y
iny
bne .clrloop
inc .clrloop+2
ldx .clrloop+2
cpx #$40
bne .clrloop
rts
LZDATA:
hex 661f7f1400002001002900b040014019
hex 0000007c000008290041030600032a00
hex 43065433002900980000403f00002603
hex 0059005102000000202a000668000249
hex 002f0100128100134080001536770011
hex 042900213c6429001a0f9f006760004b
hex 0000025900536000000008e2002f3066
hex 27740025043c5900170ca30083106040
hex 1370472102a5005a1000000018810014
hex 0357014f0600071c2674005844780300
hex 007800140ce0004510000004a3005a20
hex 781f0030810014017f003f0818000e73
hex 00430c003010350137700106a2000958
hex 00576003044003f201420a607c0fa600
hex 121e290017059d000a2c020875001030
hex 6e0134000e075900617c7f01007c0157
hex 011306590010222c005a0e0c20030c9a
hex 002270063d021220400192030c000440
hex 01000660d90008ad021b30d8010f0176
hex 00f2031e18400100400700067f1f6a38
hex 0c4001000f630150387e00002c0c034a
hex 39005000810022700f3f0014014a005f
hex 604001000c017e004f330000600ceb02
hex 2400042c026230005c1b00422802162c
hex 49002d1f0380001403bc0113082a021f
hex 401580000f2178005001006000403800
hex 133e5601223e029b02477805541fa100
hex 6f7e03007e0702425a002a3200b10021
hex 204428001a079f007a30004e00000208
hex 6d0204ea002f1c22267400260e06ad02
hex 04ea000141016830003f647c204c013a
hex 1000005a00190885030f1077002d7001
hex 9c0029047cdc0104c404762038007031
hex 0006cb012c0e30570523016080002f78
hex 0f0ef20153381800781fb50037304003
hex a20019092e024702040001f201750e40
hex 1738004001c3002770079d002f400105
hex 6902581f0000637109027702407b7f07
hex 0010c304aa3360034001023860000e9a
hex 00130f210212234001210206cd021a02
hex d8000440050a9b000f01770012707f00
hex a37c71004f2008400040014803401e00
hex 00070c031d332c034630060006c20412
hex 404c001f08017e001f3e0ee802340660
hex 07a700621800761e004e7b0016244900
hex 5c0703011800d90124003cc2032f4001
hex 4ccc0311402c04210c03c40012303606
hex 22000cec052a7400a10038380f0a5900
hex 110691030348030f2973001c13b00424
hex 7c01b500431e704301a6007a10004c01
hex 0000049d00130c6b001f0627f3043a0a
hex 030c300513303f057f10006e07002006
hex 094d05140cb3001f021373004d401f7f
hex 019d051a0cb303250001330535730f03
hex a3006a6003600018009b001f3017e903
hex 537830037801350136607101a2002a40
hex 0d59001706df006200001c0033604e00
hex 0288022850015c060f06e80267010060
hex 3f5f038103857f466a7d0d001000d800
hex ba4013205e4101037840010e81002518
hex 3c9e0200e3022f420307cd061f1810e8
hex 0634400107df00523078410070d10060
hex 40471f0000034f001d132c0346600700
hex 0cd60212604c004f180040011fd60373
hex 40073000400118c20343460300789a07
hex 151e4a005a0e420108039b0045030000
hex 68c2071f004fcc074240134004750002
hex 72080367054a481b0700a10038000e08
hex 590014045501000c030f2973002a1100
hex b100246001b40044701b1066cd083a18
hex 0000d80805d70c4f4000000227f30436
hex 3b010cb30a02d10804e10a5766050020
hex 044d011c3059051f04186a097f607f7f
hex 417f00400b9c09044c0902e700451e78
hex 0160cc095a00400008006b021f1007e9
hex 021c1c2e0b4460030e0f350d205b0310
hex 0603ce090aad06560606600300c00242
hex 140020204e0002580018589c091f6009
hex 680a45010f037c58006966434f3a6d39
hex 970a8c19307e4001014000ac0a227020
hex 49001223e100226300cd020f01d3061f
hex 0c11e80324410fdf0280103c41001c00
hex 7e016900137f4b004c200f6071810012
hex 04980b2418783a096f40010010004020
hex d50382600c1f0000077c1f900723043a
hex c30235016c1f4a00241e42ef0508b503
hex 234007d10c1f604dcb0b00e805101653
hex 0a1570240a0367013a685101a0002c38
hex 3006020336001340640e0f2477003a40
hex 1104b1002238033401644003100c1027
hex cd084d0f000003b0071f062feb0c1725
hex ac0a17303a0d5a300840630f4a0d1c20
hex 5905140633010f107205933f00784118
hex 007041038e071403a6051a005b10255e
hex 013301560c40006001a5105f070c0040
hex 0114dc0d2a76012e0200390a14073501
hex 01ad06102e2d004a03003c0e310f3704
hex 700f3f0e303c0020a50605bd0c186cdb
hex 001f2006e8021107290d2506065f0786
hex 0f583f0f60007000d800321f103ea70e
hex 2a1c009a0018273e0a40003f00001703
hex 1f0400d3062f300410e8032438479c02
hex 901c1c644101060003011e06133a4b00
hex 4e300b30012e0f01a70033704f0f5101
hex 0027132f006020d50382266c0100002f
hex 3c70d10823042e590026314821065d3c
hex 5e007818b00723000c3a091f204dcb0b
hex 1178470e560320000400c80311100f06
hex 2a7300a0002a6e388100150867104f01
hex 0040702774003a601807b100237c0145
hex 066306101c506101ce0900e7100acf03
hex 23010071091f0129f1083567010b5900
hex 17203a0d8f607f1f0378066006094d11
hex 1302ea012f40010e7300406001004e22
hex 0f137f58002f4c0701a6115638007833
hex 01b3004640072001a5002a0404fe0a2f
hex 001c06e902393803073103775e61637e
hex 037f01d702aa403b0040016002600700
hex 0702370c071f3f0e31680020d7143260
hex 677daa000759001f2007e70201210270
hex 6a037c07001c003d1292180e106c0c40
hex 036001520e70601f00007c300ea70e4a
hex 030138008100192c71024f7301000804
hex cf123f600c0e0fe903246c44db04e37e
hex 040c000102004101001860033e4b003d
hex 700a1880004506000003340d13184803
hex 2f38301fd503307c3f361006023c0242
hex 10000c66290036033f0c210a5e287000
hex 7870b0131338c0020f4eca1300571430
hex 3440011b0f069902121c9f120a9f003a
hex 404f28a911181867141f582774003a20
hex 7801b1001236380364037e0c187070cc
hex 1116306d1106780023600362012f0432
hex 2674003946410ddd00240018b5066710
hex 0040074003cd180f0758150f0ff20121
hex 7c0332182340738b02147da515190631
hex 0323000ce805022b1636072003a50058
hex 3c0700000f5c021f0605690220406f2e
hex 0d163d3403517347637f01c504160836
hex 0379400130062003007800471848055c
hex bf0231580130cd0231387c4728001812
hex 5b161f100b6816f3040e00000c703f00
hex 1c780770030630587c030660cd08613c
hex 700300602fa6124a4701280081003728
hex 7003a300511e01000841d0121d039700
hex 1f0810e803244747c600606f7c180001
hex 03210f440e70011c4703131fa0170a5b
hex 002406003a0d130c6c0c2f6f1f1fd503
hex 1106591a232006650804701948062c64
hex 0122142a60438000140167001f6050c8
hex 1313002c1808b3002f783f0241182a40
hex 69d602173067102f604c2774003a3c28
hex 00b1001203400177406319184021034d
hex 013a080002db011530610d1f1627f418
hex 2a61069e001708e00d07ca010e551114
hex 032c022f08700ff201430403601fd10c
hex 64707f03007818a5001a02ae19053c02
hex 1103c20023201ea5005906000078012b
hex 0a3f4000020569022060063801263f03
hex 5e0146076307011b1200510410018b0b
hex 490420070c7800577058044006c00221
hex 0118cd02410c70010306030f135b1a14
hex 040c0ad0130e0007007c1c7e7f215e3b
hex 0e3c0612786c01500e407f793ca70e3d
hex 6d00780406277e017c0032010078cf1a
hex 0d80000030001f300d6b031406ac0662
hex 6039403c0003a81d157849003f401706
hex 012d1b1504340d1f0628cc0331030013
hex c21821000cbc0c130c711536047c6621
hex 0a005a062c0343b1031a006a000f1500
hex 000ffe

View File

@ -1,4 +1,3 @@

;;;;; CONSTANTS

View File

@ -36,6 +36,23 @@ Start:
.endless
jmp .endless ;endless loop
; fill video RAM
FillVRAM: subroutine
txa
ldy #$20
sty PPU_ADDR
sta PPU_ADDR
ldy #$10
.loop:
sta PPU_DATA
adc #7
inx
bne .loop
dey
bne .loop
rts
;
InitSprites: subroutine
lda #1
ldx #0
@ -46,6 +63,7 @@ InitSprites: subroutine
bne .loop
rts
;
MoveSprites: subroutine
lda #1
ldx #0

225
presets/nes/helloworld.asm Normal file
View File

@ -0,0 +1,225 @@

include "nesdefs.asm"
;;;;; ZERO-PAGE VARIABLES
seg.u Zeropage
org $0
RLEPtr word
Temp1 byte
NES_HEADER 0,2,1,0 ; mapper 0, 2 PRGs, 1 CHR, horizontal
Start:
NES_INIT ; set up stack pointer, turn off PPU
jsr WaitSync
jsr WaitSync ;wait for PPU warmup
jsr ClearRAM ;clear CPU memory
jsr ClearVRAM ;set PPU RAM
jsr SetPalette ;set colors
lda #0
sta PPU_ADDR
sta PPU_ADDR ;PPU addr = 0
sta PPU_SCROLL
sta PPU_SCROLL ;scroll = 0
lda #$90
sta PPU_CTRL ;enable NMI
lda #$1e
sta PPU_MASK ;enable rendering
.endless
jmp .endless ;endless loop, NMI only
; fill video RAM
ClearVRAM: subroutine
lda #$20
sta PPU_ADDR
lda #$00
sta PPU_ADDR ; PPU addr = $2000
tax ; X = 0 (inner loop)
ldy #8 ; Y = 8 (outer loop)
lda #$2f ; A = value to write to VRAM
.loop:
sta PPU_DATA
inx
bne .loop ; repeat 256 times
dey
bne .loop ; repeat 8 times
rts
; set palette colors
SetPalette: subroutine
ldy #$00
lda #$3f
sta PPU_ADDR
sty PPU_ADDR
ldx #32
.loop:
lda Palette,y
sta PPU_DATA
iny
dex
bne .loop
rts
; load RLE-compressed data to VRAM
WriteRLE: subroutine
sta RLEPtr
sty RLEPtr+1
.nextspan
ldy #0
lda (RLEPtr),y ; length
beq .done
tax ; X = length in bytes
iny
lda (RLEPtr),y ; lo byte
pha
iny
lda (RLEPtr),y ; hi byte
sta PPU_ADDR ; write hi byte
pla
sta PPU_ADDR ; write lo byte
jsr RLEDoText
tya
sec ; + 1 (we didn't iny on last loop)
adc RLEPtr ; add Y to RLEPtr
sta RLEPtr
bcc .nextspan ; no overflow
inc RLEPtr+1
bne .nextspan ; branch almost always taken
.done
rts
; translate ASCII to tiles and copy to VRAM
RLEDoText:
iny
lda (RLEPtr),y ; hi byte
stx Temp1
sec
sbc #$20
tax
lda ASCII2Tile,x
ldx Temp1
sta PPU_DATA
dex
bne RLEDoText
rts
ASCII2Tile:
hex 2f242d2b 252d2d29 2d2d2d2d 2a27282d ; 20
hex 00010203 04050607 08092600 00000000 ; 30
hex 2f0a0b0c 0d0e0f10 11121314 15161718 ; 40
hex 191a1b1c 1d1e1f20 2122232d 2d2d2d2c ; 50
;;;;; COMMON SUBROUTINES
include "nesppu.asm"
;;;;; INTERRUPT HANDLERS
NMIHandler: subroutine
lda #<HelloWorld
ldy #>HelloWorld
jsr WriteRLE ;write "hello world" message
; restore PPU
lda #0
sta PPU_ADDR
lda #0
sta PPU_ADDR
rti
;;;;; CONSTANT DATA
Palette:
hex 1f ;background
hex 0909191f ;bg0
hex 0909191f ;bg1
hex 0909191f ;bg2
hex 0909191f ;bg3
hex 14243400 ;sp0
hex 15253500 ;sp1
hex 16263600 ;sp2
hex 17273700 ;sp3
HelloWorld:
byte 12
word $2000 + (32*12) + 11
byte "HELLO WORLD!"
byte 32
word $2041
byte "ABCDEF0123456789"
byte "$!:-.',#_ "
byte 0
;;;;; CPU VECTORS
NES_VECTORS
;;;;; TILE SETS
org $10000
; OAM (sprite) pattern table
REPEAT 256
hex 00000000000000000000000000000000
REPEND
; background (tile) pattern table
REPEAT 5
;;{w:8,h:8,bpp:1,count:48,brev:1,np:2,pofs:8,remap:[0,1,2,4,5,6,7,8,9,10,11,12]};;
hex 7e42424646467e007e42424646467e00
hex 08080818181818000808081818181800
hex 3e22023e30303e003e22023e30303e00
hex 3c24041e06263e003c24041e06263e00
hex 4444447e0c0c0c004444447e0c0c0c00
hex 3c20203e06263e003c20203e06263e00
hex 3e22203e26263e003e22203e26263e00
hex 3e020206060606003e02020606060600
hex 3c24247e46467e003c24247e46467e00
hex 3e22223e060606003e22223e06060600
hex 3c24247e626262003c24247e62626200
hex 7c44447e62627e007c44447e62627e00
hex 7e42406060627e007e42406060627e00
hex 7e42426262627e007e42426262627e00
hex 7c40407c60607c007c40407c60607c00
hex 3c20203c303030003c20203c30303000
hex 7e42406e62627e007e42406e62627e00
hex 4242427e626262004242427e62626200
hex 10101018181818001010101818181800
hex 0404040606467e000404040606467e00
hex 4444447e626262004444447e62626200
hex 2020203030303e002020203030303e00
hex fe9292d2d2d2d200fe9292d2d2d2d200
hex 7e424262626262007e42426262626200
hex 7e46464242427e007e46464242427e00
hex 7e42427e606060007e42427e60606000
hex 7e424242424e7e007e424242424e7e00
hex 7c44447e626262007c44447e62626200
hex 7e42407e06467e007e42407e06467e00
hex 7e101018181818007e10101818181800
hex 4242426262627e004242426262627e00
hex 646464642c2c3c00646464642c2c3c00
hex 4949494969697f004949494969697f00
hex 4242423c626262004242423c62626200
hex 4242427e181818004242427e18181800
hex 7e42027e60627e007e42027e60427e00
hex 10101818180018001010181818001800
hex 187e407e067e1800187e407e067e1800
hex 00180018180000000018001818000000
hex 00003c3c0000000000003c3c00000000
hex 00000018180000000000001818000000
hex 18180810000000001818081000000000
hex 00000018180810000000001818081000
hex 7c7c7c7c7c7c7c007c7c7c7c7c7c7c00
hex 0000000000007c000000000000007c00
hex 00000000000000000000000000000000
hex 00000000000000000000000000000000
hex 00000000000000000000000000000000
;;
REPEND
REPEAT 15
hex 00000000000000000000000000000000
REPEND
hex 00000000000000000000000000000000

View File

@ -3,24 +3,37 @@
;;;;; CONSTANTS
PPU_CTRL equ $2000
PPU_MASK equ $2001
PPU_STATUS equ $2002
OAM_ADDR equ $2003
OAM_DATA equ $2004
PPU_SCROLL equ $2005
PPU_ADDR equ $2006
PPU_DATA equ $2007
PPU_OAM_DMA equ $4014
DMC_FREQ equ $4010
APU_STATUS equ $4015
PPU_CTRL = $2000
PPU_MASK = $2001
PPU_STATUS = $2002
OAM_ADDR = $2003
OAM_DATA = $2004
PPU_SCROLL = $2005
PPU_ADDR = $2006
PPU_DATA = $2007
PPU_OAM_DMA = $4014
DMC_FREQ = $4010
APU_STATUS = $4015
APU_NOISE_VOL = $400C
APU_NOISE_FREQ = $400E
APU_NOISE_TIMER = $400F
APU_DMC_CTRL = $4010
APU_CHAN_CTRL = $4015
APU_FRAME = $4017
; NOTE: I've put this outside of the PPU & APU, because it is a feature
; of the APU that is primarily of use to the PPU.
OAM_DMA = $4014
; OAM local RAM copy goes from $0200-$02FF:
OAM_RAM = $0200
;;;;; CARTRIDGE FILE HEADER
NES_MIRR_HORIZ equ 0
NES_MIRR_VERT equ 1
NES_MIRR_QUAD equ 8
NES_MIRR_HORIZ = 0
NES_MIRR_VERT = 1
NES_MIRR_QUAD = 8
MAC NES_HEADER
seg Header
@ -51,6 +64,11 @@ NES_MIRR_QUAD equ 8
stx DMC_FREQ ;disable DMC interrupts
stx PPU_CTRL ;disable NMI interrupts
bit PPU_STATUS ;clear VBL flag
bit APU_CHAN_CTRL ;ack DMC IRQ bit 7
lda #$40
sta APU_FRAME ;disable APU Frame IRQ
lda #$0F
sta APU_CHAN_CTRL ;disable DMC, enable/init other channels.
ENDM
;;;;; NES_VECTORS - CPU vectors at end of address space

View File

@ -19,22 +19,6 @@ ClearRAM: subroutine
bne .clearRAM
rts
; fill video RAM
FillVRAM: subroutine
txa
ldy #$20
sty PPU_ADDR
sta PPU_ADDR
ldy #$10
.loop:
sta PPU_DATA
adc #7
inx
bne .loop
dey
bne .loop
rts
; wait for VSYNC to start
WaitSync:
bit PPU_STATUS

View File

@ -221,17 +221,20 @@ function PixelEditor(parentDiv:HTMLElement, fmt, palette, initialData, thumbnail
var pixel_re = /([0#]?)([x$%]|\d'[bh])([0-9a-f]+)/gi;
function parseHexBytes(s) {
var arr = [];
var m;
function convertToHexStatements(s) {
// convert 'hex ....' asm format
s = s.replace(/(\shex\s+)([0-9a-f]+)/ig, function(m,hexprefix,hexstr) {
return s.replace(/(\shex\s+)([0-9a-f]+)/ig, function(m,hexprefix,hexstr) {
var rtn = hexprefix;
for (var i=0; i<hexstr.length; i+=2) {
rtn += '0x'+hexstr.substr(i,2)+',';
}
return rtn;
});
}
function parseHexBytes(s) {
var arr = [];
var m;
while (m = pixel_re.exec(s)) {
var n;
if (m[2].startsWith('%') || m[2].endsWith("b"))
@ -270,7 +273,7 @@ function replaceHexBytes(s, bytes) {
// convert 'hex ....' asm format
result = result.replace(/(\shex\s+)([,x0-9a-f]+)/ig, function(m,hexprefix,hexstr) {
var rtn = hexprefix + hexstr;
rtn = rtn.replace(/0x/,'').replace(',','')
rtn = rtn.replace(/0x/ig,'').replace(/,/ig,'')
return rtn;
});
return result;
@ -397,10 +400,10 @@ function pixelEditorDecodeMessage(e) {
parentSource = e.source;
parentOrigin = e.origin;
currentFormat = e.data.fmt;
currentByteStr = e.data.bytestr;
currentPaletteFmt = e.data.palfmt;
currentPaletteStr = e.data.palstr;
var bytes = parseHexBytes(e.data.bytestr);
currentByteStr = convertToHexStatements(e.data.bytestr);
var bytes = parseHexBytes(currentByteStr);
allimages = convertBytesToImages(bytes, e.data.fmt);
palette = [0xff000000, 0xffffffff]; // TODO
if (currentPaletteStr) {

View File

@ -1,12 +1,14 @@
"use strict";
var APPLE2_PRESETS = [
{id:'sieve.c', name:'Sieve (C)'},
{id:'mandel.c', name:'Mandelbrot (C)'},
{id:'tgidemo.c', name:'TGI Graphics Demo (C)'},
{id:'siegegame.c', name:'Siege Game (C)'},
{id:'hgrtest.a', name:"HGR Test (asm)"},
{id:'conway.a', name:"Conway's Game of Life (asm)"},
{id:'sieve.c', name:'Sieve'},
{id:'mandel.c', name:'Mandelbrot'},
{id:'tgidemo.c', name:'TGI Graphics Demo'},
{id:'siegegame.c', name:'Siege Game'},
{id:'cosmic.c', name:'Cosmic Impalas'},
{id:'hgrtest.a', name:"HGR Test"},
{id:'conway.a', name:"Conway's Game of Life"},
{id:'lz4fh.a', name:"LZ4FH Graphics Compression"},
// {id:'tb_6502.s', name:'Tom Bombem (assembler game)'},
];
@ -153,7 +155,7 @@ var Apple2Platform = function(mainElement) {
// since we're an Apple II+, we don't do lowercase
if (flags & 1) {
if (code) {
if (code >= 0xe1 && code <= 0xfa)
if (code >= 0x61 && code <= 0x7a)
code -= 0x20;
kbdlatch = (code | 0x80) & 0xff;
} else if (key) {
@ -169,17 +171,26 @@ var Apple2Platform = function(mainElement) {
// 262.5 scanlines per frame
var clock = 0;
var debugCond = self.getDebugCallback();
var rendered = false;
for (var sl=0; sl<262; sl++) {
for (var i=0; i<cpuCyclesPerLine; i++) {
if (debugCond && debugCond()) { debugCond = null; }
if (debugCond && debugCond()) {
grparams.dirty = grdirty;
grparams.grswitch = grswitch;
ap2disp.updateScreen();
debugCond = null;
rendered = true;
}
clock++;
cpu.clockPulse();
audio.feedSample(soundstate, 1);
}
}
grparams.dirty = grdirty;
grparams.grswitch = grswitch;
ap2disp.updateScreen();
if (!rendered) {
grparams.dirty = grdirty;
grparams.grswitch = grswitch;
ap2disp.updateScreen();
}
video.updateFrame();
soundstate = 0; // to prevent clicking
self.restartDebugState(); // reset debug start state
@ -509,7 +520,7 @@ var Apple2Display = function(pixels, apple) {
pixels[yb+i] = colors_lut[d1*7+i];
var d2 = (((b1&0x40)<<2) | b2 | b3<<9) & 0x3ff;
for (var i=0; i<7; i++)
pixels[yb+7+i] = colors_lut[d1*7+7168+i];
pixels[yb+7+i] = colors_lut[d2*7+7168+i];
yb += 14;
base += 2;
b = b2;

View File

@ -116,6 +116,8 @@ function refreshWindowList() {
var a = document.createElement("a");
a.setAttribute("class", "dropdown-item");
a.setAttribute("href", "#");
if (id == projectWindows.getActiveID())
$(a).addClass("dropdown-item-checked");
a.appendChild(document.createTextNode(name));
li.appendChild(a);
ul.append(li);
@ -197,7 +199,7 @@ function loadProject(preset_id:string) {
// we need this to build create functions for the editor (TODO?)
refreshWindowList();
// show main file
projectWindows.createOrShow(preset_id); // TODO: add checkmark
projectWindows.createOrShow(preset_id);
// build project
current_project.setMainFile(preset_id);
}
@ -276,9 +278,12 @@ function handleFileUpload(files: File[]) {
if (files) uploadNextFile();
}
function getCurrentFilename() : string {
var toks = main_file_id.split("/");
return toks[toks.length-1];
function getCurrentMainFilename() : string {
return getFilenameForPath(main_file_id);
}
function getCurrentEditorFilename() : string {
return getFilenameForPath(projectWindows.getActiveID());
}
function _shareFile(e) {
@ -290,7 +295,7 @@ function _shareFile(e) {
if (!text) return false;
var github = new Octokat();
var files = {};
files[getCurrentFilename()] = {"content": text};
files[getCurrentEditorFilename()] = {"content": text};
var gistdata = {
"description": '8bitworkshop.com {"platform":"' + platform_id + '"}',
"public": true,
@ -321,14 +326,14 @@ function _downloadROMImage(e) {
return true;
}
var blob = new Blob([current_output], {type: "application/octet-stream"});
saveAs(blob, getCurrentFilename()+".rom");
saveAs(blob, getCurrentMainFilename()+".rom");
}
function _downloadSourceFile(e) {
var text = projectWindows.getCurrentText();
if (!text) return false;
var blob = new Blob([text], {type: "text/plain;charset=utf-8"});
saveAs(blob, getCurrentFilename());
saveAs(blob, getCurrentEditorFilename());
}
function populateExamples(sel) {

View File

@ -289,3 +289,10 @@ function lzgmini() {
return str;
}
}
function stringToByteArray(s:string) : Uint8Array {
var a = new Uint8Array(s.length);
for (var i=0; i<s.length; i++)
a[i] = s.charCodeAt(i);
return a;
}

View File

@ -197,7 +197,7 @@ export class SourceEditor implements ProjectView {
setGutter(type:string, line:number, text:string) {
var lineinfo = this.editor.lineInfo(line);
if (lineinfo.gutterMarkers && lineinfo.gutterMarkers[type]) {
if (lineinfo && lineinfo.gutterMarkers && lineinfo.gutterMarkers[type]) {
// do not replace existing marker
} else {
var textel = document.createTextNode(text);

View File

@ -85,7 +85,7 @@ export class ProjectWindows {
getActive() : ProjectView { return this.activewnd; }
getActiveID() : string { return this.activeid; }
getCurrentText() : string {
if (this.activewnd && this.activewnd.getValue)
return this.activewnd.getValue();