started on vector-ataricolor target (for 6502)

This commit is contained in:
Steven Hugg 2019-04-24 16:56:53 -04:00
parent f71c8602e0
commit 0e47e7d035
25 changed files with 27482 additions and 12 deletions

View File

@ -123,6 +123,7 @@ TODO:
- toolbar overlaps scope
- CPU debugging
- disassemble more code around breakpoint
- single-stepping vector games makes screen fade
WEB WORKER FORMAT

View File

@ -125,6 +125,7 @@ if (window.location.host.endsWith('8bitworkshop.com')) {
<ul class="dropdown-menu">
<li><a class="dropdown-item" href="?platform=vcs.mame" id="item_platform_vcs_mame">Atari 2600/VCS (MAME)</a></li>
<li><a class="dropdown-item" href="?platform=nes.mame" id="item_platform_nes_mame">NES (MAME)</a></li>
<li><a class="dropdown-item" href="?platform=vector-ataricolor" id="item_platform_nes_mame">Atari Color Vector (6502)</a></li>
<li><a class="dropdown-item" href="?platform=markdown" id="item_platform_markdown">Markdown</a></li>
</ul>
</li>

View File

@ -0,0 +1,38 @@
#include <string.h>
#include "vecops.h"
//#link "vecops.c"
#include "vecfont.h"
//#link "vecfont.c"
////
static int frame = 0;
void main(void) {
int r = 512;
dvgclear();
dvgwrofs = 0x200;
draw_string("HELLO, WORLD!", 0);
RTSL();
while (1) {
dvgreset();
CNTR();
SCAL(0x7f);
STAT(RED, 0);
VCTR(r, r, 1);
VCTR(-r*2, 0, 3);
VCTR(0, -r*2, 5);
VCTR(r*2, 0, 7);
VCTR(0, r*2, 7);
CNTR();
STAT(GREEN, 0);
VCTR(100, -100, 0);
JSRL(0x200);
HALT();
dvgstart();
frame++;
}
}

View File

@ -0,0 +1,397 @@
#include <stdlib.h>
#include <string.h>
#include <cc65.h>
#include "vecops.h"
//#link "vecops.c"
#include "vecfont.h"
//#link "vecfont.c"
#include "vec3d.h"
//#link "vec3d.c"
#define input0 (*(byte*)0x7800)
#define input1 (*(byte*)0x8000)
#define watchdog (*(byte*)0x8980)
#define vidframe (*(byte*)0x0)
#define LEFT1 !(input1 & 0x8)
#define RIGHT1 !(input1 & 0x4)
#define UP1 !(input1 & 0x10)
#define DOWN1 !(input1 & 0x20)
#define FIRE1 !(input1 & 0x2)
#define BOMB1 !(input1 & 0x1)
#define COIN1 (input0 & 0x2)
#define COIN2 (input0 & 0x1)
#define START1 (input2 & 0x20)
#define START2 (input2 & 0x40)
// SHAPE CACHE
const Vector8 tetra_v[] = { {0,-86,86},{86,86,86},{-86,86,86},{0,0,-86} };
const sbyte tetra_e[] = { 0, 1, 2, 0, 3, 1, -1, 3, 2, -2 };
const Wireframe tetra_wf = { 4, tetra_v, tetra_e };
const Vector8 octa_v[] = { {86,0,0},{0,86,0},{-86,0,0},{0,-86,0},{0,0,86},{0,0,-86} };
const sbyte octa_e[] = { 0, 1, 2, 3, 0, 4, 1, 5, 0, -1, 2, 4, 3, 5, 2, -2 };
const Wireframe octa_wf = { 6, octa_v, octa_e };
const Vector8 ship_v[] = { {0,86,0},{-30,-30,0},{-50,0,0},{50,0,0},{30,-30,0} };
const sbyte ship_e[] = { 0, 1, 2, 3, 4, 0, -2 };
const Wireframe ship_wf = { 5, ship_v, ship_e };
const Vector8 thrust_v[] = { {-20,-30,0},{-30,-50,0},{0,-86,0},{30,-50,0},{20,-30,0} };
const sbyte thrust_e[] = { 0, 1, 2, 3, 4, -2 };
const Wireframe thrust_wf = { 5, thrust_v, thrust_e };
const Vector8 torpedo_v[] = { {-86,0,0},{86,0,0},{-40,-40,0},{40,40,0},{0,-20,0},{0,20,0} };
const sbyte torpedo_e[] = { 0, 1, -1, 2, 3, -1, 4, 5, -2 };
const Wireframe torpedo_wf = { 6, torpedo_v, torpedo_e };
word ship_shapes[32];
word thrust_shapes[32];
word tetra_shapes[32];
word torpedo_shapes[16];
word explosion_shape[1];
void draw_explosion() {
byte i;
for (i=0; i<30; i++) {
byte angle = rand();
sbyte xd = isin(angle) >> 4;
sbyte yd = icos(angle) >> 4;
SVEC(xd, yd, 2);
SVEC(-xd, -yd, 2);
}
}
void make_cached_shapes() {
Matrix mat;
byte i;
for (i=0; i<32; i++) {
//watchdog = 0;
ship_shapes[i] = dvgwrofs;
mat_rotate(&mat, 2, i<<3);
draw_wireframe_ortho(&ship_wf, &mat);
RTSL();
thrust_shapes[i] = dvgwrofs;
draw_wireframe_ortho(&thrust_wf, &mat);
RTSL();
tetra_shapes[i] = dvgwrofs;
mat_rotate(&mat, 0, i<<3);
draw_wireframe_ortho(&octa_wf, &mat);
RTSL();
}
for (i=0; i<16; i++) {
torpedo_shapes[i] = dvgwrofs;
mat_rotate(&mat, 2, i<<4);
draw_wireframe_ortho(&torpedo_wf, &mat);
RTSL();
}
explosion_shape[0] = dvgwrofs;
STAT_sparkle(15);
draw_explosion();
RTSL();
}
// MAIN PROGRAM
struct Actor;
typedef void ActorUpdateFn(struct Actor*);
typedef struct Actor {
word* shapes;
ActorUpdateFn* update_fn;
byte angshift;
byte scale;
byte color;
byte intens;
byte collision_flags;
byte angle;
word xx;
word yy;
int velx;
int vely;
struct Actor* next;
byte removed;
} Actor;
#define WORLD_SCALE 0x2c0
void draw_actor(const Actor* a) {
CNTR(); // center beam (0,0)
SCAL(WORLD_SCALE); // world scale
VCTR(a->xx>>3, a->yy>>3, 0); // go to object center
SCAL(a->scale); // object scale
STAT(a->color, a->intens); // set color/intensity
JSRL(a->shapes[a->angle >> a->angshift]); // draw
}
void move_actor(Actor* a) {
a->xx += a->velx;
a->yy += a->vely;
}
static Actor* first_actor = NULL;
Actor* new_actor(const Actor* base) {
Actor* a = (Actor*) malloc(sizeof(Actor));
memcpy(a, base, sizeof(Actor));
a->next = first_actor;
first_actor = a;
return a;
}
void draw_and_update_actors() {
Actor* a = first_actor;
while (a) {
draw_actor(a);
move_actor(a);
if (a->update_fn) a->update_fn(a);
a = a->next;
}
}
void remove_expired_actors() {
Actor* a;
// get address of first pointer
Actor** prev = &first_actor;
while ((a = *prev)) {
// was actor removed?
if (a->removed) {
// set previous pointer to skip this actor
*prev = a->next;
// free memory
free(a);
} else {
// get address of next pointer
prev = &a->next;
}
}
}
void draw_actor_rect(Actor* a) {
CNTR(); // center beam (0,0)
SCAL(WORLD_SCALE); // world scale
VCTR(a->xx>>3, a->yy>>3, 0); // go to object center
SCAL(a->scale); // object scale
STAT(RED, 7); // set color/intensity
VCTR(-86,-86,0);
VCTR(86*2,0,2);
VCTR(0,86*2,2);
VCTR(-86*2,0,2);
VCTR(0,-86*2,2);
}
word get_distance_squared(byte dx, byte dy) {
return cc65_imul8x8r16(dx,dx) + cc65_imul8x8r16(dy,dy);
}
typedef void ActorCollisionFn(struct Actor*, struct Actor*);
byte test_actor_distance(ActorCollisionFn* fn, Actor* act1, byte mindist, byte flags) {
Actor* a = first_actor;
byte xx1 = act1->xx >> 8;
byte yy1 = act1->yy >> 8;
byte count = 0;
word mindist2 = mindist * mindist;
// go through list of actors
while (a) {
// only compare against actors with certain flags
// (that haven't been removed)
if ((a->collision_flags & flags) && !a->removed) {
byte dx = abs(xx1 - (a->xx >> 8));
byte dy = abs(yy1 - (a->yy >> 8));
if (dx+dy < mindist) {
word dist2 = get_distance_squared(dx, dy);
if (dist2 < mindist2) {
if (fn) fn(act1, a);
count++;
}
}
}
a = a->next;
}
return count;
}
void explode_at(Actor* base);
void explode_actor(Actor* a, Actor* b) {
a->removed = 1;
explode_at(b);
b->removed = 1;
}
void obstacle_update_fn(struct Actor* a) {
a->angle += 1;
}
void torpedo_update_fn(struct Actor* a) {
// expire?
if ((a->angle += 60) == 0) {
a->removed = 1;
} else {
// check for torpedo hits
test_actor_distance(explode_actor, a, 12, 0x2);
}
}
void explosion_update_fn(struct Actor* a) {
a->scale -= 2;
if (a->scale < 8) {
a->removed = 1;
}
}
const Actor ship_actor = {
ship_shapes, NULL, 3, 0xb0, WHITE, 7, 0x1,
};
const Actor tetra_actor = {
tetra_shapes, obstacle_update_fn, 3, 0x80, CYAN, 7, 0x2,
};
const Actor torpedo_actor = {
torpedo_shapes, torpedo_update_fn, 4, 0xe0, YELLOW, 15, 0x4,
};
const Actor explosion_actor = {
explosion_shape, explosion_update_fn, 8, 0xa0, WHITE, 15, 0,
};
void create_obstacle() {
Actor* a = new_actor(&tetra_actor);
a->xx = rand() | 0x8000;
a->yy = rand();
a->velx = (int)rand()<<8>>8;
a->vely = (int)rand()<<8>>8;
}
void create_obstacles(byte count) {
while (count--) {
create_obstacle();
}
}
static int frame = 0;
static Actor* curship = NULL;
void draw_thrust() {
word rnd = rand();
// save old values in actor
byte oldcolor = curship->color;
byte oldintens = curship->intens;
// temporarily give new thrust values
curship->shapes = thrust_shapes;
curship->scale ^= rnd; // random thrust scale
curship->intens = 15;
curship->color = (rnd&1) ? RED : YELLOW;
// draw thrust using player's ship actor
draw_actor(curship);
// restore previous values
curship->shapes = ship_shapes;
curship->scale ^= rnd;
curship->color = oldcolor;
curship->intens = oldintens;
}
void thrust_ship() {
sbyte sin = isin(curship->angle);
sbyte cos = icos(curship->angle);
curship->velx += sin>>3;
curship->vely += cos>>3;
}
int apply_friction(int vel) {
int delta = vel >> 8;
if (delta == 0 && vel > 0) delta++;
return vel - delta;
}
void shoot_torpedo() {
sbyte sin = isin(curship->angle);
sbyte cos = icos(curship->angle);
Actor* torp = new_actor(&torpedo_actor);
torp->velx = sin << 2;
torp->vely = cos << 2;
torp->xx = curship->xx + torp->velx*4;
torp->yy = curship->yy + torp->vely*4;
}
static byte can_fire;
static byte newship_timer;
void new_player_ship() {
if (curship == NULL) {
curship = new_actor(&ship_actor);
}
}
void explode_at(Actor* base) {
Actor* a = new_actor(&explosion_actor);
a->xx = base->xx;
a->yy = base->yy;
}
void control_player() {
if (newship_timer && --newship_timer == 0) {
new_player_ship();
}
if (!curship) return;
if (LEFT1) curship->angle -= 2;
if (RIGHT1) curship->angle += 2;
if ((frame&1)==1) {
curship->velx = apply_friction(curship->velx);
curship->vely = apply_friction(curship->vely);
}
if (UP1) {
// draw flame
draw_thrust();
// thrust every 4 frames, to avoid precision issues
if (!(frame&3)) thrust_ship();
}
if (FIRE1) {
// must release fire button before firing again
if (can_fire) {
shoot_torpedo();
can_fire = 0;
}
} else {
can_fire = 1;
}
// ship ran into something?
if (test_actor_distance(NULL, curship, 16, 0x2)) {
explode_at(curship);
curship->removed = 1;
curship = NULL;
newship_timer = 255;
}
}
byte just_one_actor_left() {
return first_actor != NULL && first_actor->next == NULL;
}
void main() {
dvgclear();
dvgwrofs = 0x800; //write into the middle of VEC ROM (TODO)
make_cached_shapes();
create_obstacles(5);
new_player_ship();
while (!just_one_actor_left()) {
dvgreset();
control_player();
draw_and_update_actors();
CNTR();
HALT();
dvgstart();
remove_expired_actors();
frame++;
watchdog=0;
// while (vidframe == (frame & 0x3)) {}
}
main();
}

View File

@ -0,0 +1,21 @@
#include <string.h>
#include "vecops.h"
//#link "vecops.c"
void main() {
while (1) {
dvgreset();
CNTR();
VCTR(100,0,1);
VCTR(0,100,2);
VCTR(-100,0,3);
VCTR(0,-100,4);
CNTR();
HALT();
dvgstart();
}
main();
}

View File

@ -0,0 +1,33 @@
#include "vecops.h"
//#link "vecops.c"
#include "vec3d.h"
//#link "vec3d.c"
const Vector8 tetra_v[] = { {0,-86,86},{86,86,86},{-86,86,86},{0,0,-86} };
const sbyte tetra_e[] = { 0, 1, 2, 0, 3, 1, -1, 3, 2, -2 };
const Wireframe tetra = { 4, tetra_v, tetra_e };
word frame;
void main() {
int x,y;
Matrix m;
mat_identity(&m);
while (1) {
dvgreset();
CNTR();
SCAL(0x1f);
STAT(RED, 5);
x = isin(frame/8);
y = icos(frame/8);
VCTR(x, y, 2);
STAT(GREEN, 15);
mat_rotate(&m, (frame>>8)&3, frame);
draw_wireframe_ortho(&tetra, &m);
HALT();
dvgstart();
frame++;
}
}

View File

@ -0,0 +1,112 @@
#include <string.h>
#include <cc65.h>
#include "vec3d.h"
const Matrix IDENTITY = {{{127,0,0},{0,127,0},{0,0,127}}};
void mat_identity(Matrix* m) {
*m = IDENTITY;
}
void vec_mat_transform(Vector16* dest, const Vector8* v, const Matrix* m) {
byte i;
int* result = &dest->x;
const sbyte* mval = &m->m[0][0];
for (i=0; i<3; i++) {
*result++ = cc65_imul8x8r16(*mval++, v->x)
+ cc65_imul8x8r16(*mval++, v->y)
+ cc65_imul8x8r16(*mval++, v->z);
}
}
/*
void vec_mat_transform2(Vector16* dest, const Vector8* v, const Matrix* m) {
dest->x = v->x*m->m[0][0] + v->y*m->m[0][1] + v->z*m->m[0][2];
dest->y = v->x*m->m[1][0] + v->y*m->m[1][1] + v->z*m->m[1][2];
dest->z = v->x*m->m[2][0] + v->y*m->m[2][1] + v->z*m->m[2][2];
}
*/
const sbyte sintbl[64] = {
0, 3, 6, 9, 12, 16, 19, 22, 25, 28, 31, 34, 37, 40, 43, 46,
49, 51, 54, 57, 60, 63, 65, 68, 71, 73, 76, 78, 81, 83, 85, 88,
90, 92, 94, 96, 98, 100, 102, 104, 106, 107, 109, 111, 112, 113, 115, 116,
117, 118, 120, 121, 122, 122, 123, 124, 125, 125, 126, 126, 126, 127, 127, 127,
};
sbyte isin(byte x0) {
byte x = x0;
if (x0 & 0x40) x = 127-x;
if (x0 & 0x80) {
return -sintbl[x-128];
} else {
return sintbl[x];
}
}
sbyte icos(byte x) {
return isin(x+64);
}
void mat_rotate(Matrix* m, byte axis, byte angle) {
sbyte sin = isin(angle);
sbyte cos = icos(angle);
mat_identity(m);
switch (axis) {
case 0:
m->m[1][1] = cos;
m->m[2][1] = sin;
m->m[1][2] = -sin;
m->m[2][2] = cos;
break;
case 1:
m->m[2][2] = cos;
m->m[0][2] = sin;
m->m[2][0] = -sin;
m->m[0][0] = cos;
break;
case 2:
m->m[0][0] = cos;
m->m[1][0] = sin;
m->m[0][1] = -sin;
m->m[1][1] = cos;
break;
}
}
void xform_vertices(Vector16* dest, const Vector8* src, const Matrix* m, byte nv) {
byte i;
for (i=0; i<nv; i++) {
vec_mat_transform(dest++, src++, m);
}
}
void draw_wireframe(const Wireframe* wf, Vector16* scrnverts) {
const sbyte* e = wf->edges;
byte bright = 0;
int x1 = 0;
int y1 = 0;
do {
sbyte i = *e++;
if (i == -1)
bright = 0;
else if (i == -2)
break;
else {
int x2 = scrnverts[i].x>>8;
int y2 = scrnverts[i].y>>8;
VCTR(x2-x1, y2-y1, bright);
x1 = x2;
y1 = y2;
}
bright = 2;
} while (1);
}
void draw_wireframe_ortho(const Wireframe* wf, const Matrix* m) {
Vector16 scrnverts[16];
xform_vertices(scrnverts, wf->verts, m, wf->numverts);
draw_wireframe(wf, scrnverts);
}

View File

@ -0,0 +1,36 @@
#ifndef _VEC3D_H
#define _VEC3D_H
#include "vecops.h"
typedef struct {
sbyte m[3][3];
} Matrix;
typedef struct {
sbyte x,y,z;
} Vector8;
typedef struct {
int x,y,z;
} Vector16;
typedef struct {
byte numverts;
const Vector8* verts; // array of vertices
const sbyte* edges; // array of vertex indices (edges)
} Wireframe;
extern const Matrix IDENTITY;
void mat_identity(Matrix* m);
void vec_mat_transform(Vector16* dest, const Vector8* v, const Matrix* m);
sbyte isin(byte x0);
sbyte icos(byte x);
void mat_rotate(Matrix* m, byte axis, byte angle);
void xform_vertices(Vector16* dest, const Vector8* src, const Matrix* m, byte nv);
void draw_wireframe(const Wireframe* wf, Vector16* scrnverts);
void draw_wireframe_ortho(const Wireframe* wf, const Matrix* m);
#endif

View File

@ -0,0 +1,79 @@
#include "vecops.h"
#pragma rodata-name(push,"DVGROM")
const word VECFONT_32[] = { _SVEC(12,0,0), _RTSL() };
const word VECFONT_33[] = { _SVEC(4,0,0), _SVEC(-1,2,4), _SVEC(2,0,4), _SVEC(-1,-2,4), _SVEC(0,4,0), _SVEC(0,8,4), _SVEC(8,-12,0), _RTSL() };
const word VECFONT_34[] = { _SVEC(2,10,0), _SVEC(0,-4,4), _SVEC(4,4,0), _SVEC(0,-4,4), _SVEC(6,-6,0), _RTSL() };
const word VECFONT_35[] = { _SVEC(0,4,0), _SVEC(8,0,4), _SVEC(-2,-2,4), _SVEC(0,8,4), _SVEC(2,-2,4), _SVEC(-8,0,4), _SVEC(2,2,4), _SVEC(0,-8,4), _SVEC(10,-2,0), _RTSL() };
const word VECFONT_36[] = { _SVEC(6,2,0), _SVEC(-4,4,4), _SVEC(4,4,4), _SVEC(-2,2,0), _SVEC(0,-12,4), _SVEC(8,0,0), _RTSL() };
const word VECFONT_37[] = { _SVEC(0,0,0), _SVEC(8,12,4), _SVEC(-6,-2,0), _SVEC(0,-2,4), _SVEC(4,-4,0), _SVEC(0,-2,4), _SVEC(6,-2,0), _RTSL() };
const word VECFONT_38[] = { _SVEC(8,0,0), _SVEC(-4,12,4), _SVEC(4,-4,4), _SVEC(-8,-4,4), _SVEC(4,-4,4), _SVEC(4,4,4), _SVEC(4,-4,0), _RTSL() };
const word VECFONT_39[] = { _SVEC(0,12,0), _SVEC(8,-12,4), _SVEC(4,0,0), _RTSL() };
const word VECFONT_40[] = { _SVEC(6,0,0), _SVEC(-4,4,4), _SVEC(0,4,4), _SVEC(4,4,4), _SVEC(6,-12,0), _RTSL() };
const word VECFONT_41[] = { _SVEC(2,0,0), _SVEC(4,4,4), _SVEC(0,4,4), _SVEC(-4,4,4), _SVEC(10,-12,0), _RTSL() };
const word VECFONT_42[] = { _SVEC(0,0,0), _SVEC(4,12,4), _SVEC(4,-12,4), _SVEC(-8,8,4), _SVEC(8,0,4), _SVEC(-8,-8,4), _SVEC(12,0,0), _RTSL() };
const word VECFONT_43[] = { _SVEC(1,6,0), _SVEC(6,0,4), _SVEC(-3,3,0), _SVEC(0,-6,4), _SVEC(8,-3,0), _RTSL() };
const word VECFONT_44[] = { _SVEC(2,0,0), _SVEC(2,2,4), _SVEC(8,-2,0), _RTSL() };
const word VECFONT_45[] = { _SVEC(2,6,0), _SVEC(4,0,4), _SVEC(6,-6,0), _RTSL() };
const word VECFONT_46[] = { _SVEC(3,0,0), _SVEC(1,0,4), _SVEC(8,0,0), _RTSL() };
const word VECFONT_47[] = { _SVEC(0,0,0), _SVEC(8,12,4), _SVEC(4,-12,0), _RTSL() };
const word VECFONT_48[] = { _SVEC(0,0,0), _SVEC(8,0,4), _SVEC(0,12,4), _SVEC(-8,0,4), _SVEC(0,-12,4), _SVEC(8,12,4), _SVEC(4,-12,0), _RTSL() };
const word VECFONT_49[] = { _SVEC(4,0,0), _SVEC(0,12,4), _SVEC(-1,-2,4), _SVEC(9,-10,0), _RTSL() };
const word VECFONT_50[] = { _SVEC(0,12,0), _SVEC(8,0,4), _SVEC(0,-5,4), _SVEC(-8,-2,4), _SVEC(0,-5,4), _SVEC(8,0,4), _SVEC(4,0,0), _RTSL() };
const word VECFONT_51[] = { _SVEC(0,12,0), _SVEC(8,0,4), _SVEC(0,-12,4), _SVEC(-8,0,4), _SVEC(0,6,0), _SVEC(8,0,4), _SVEC(4,-6,0), _RTSL() };
const word VECFONT_52[] = { _SVEC(0,12,0), _SVEC(0,-6,4), _SVEC(8,0,4), _SVEC(0,6,0), _SVEC(0,-12,4), _SVEC(4,0,0), _RTSL() };
const word VECFONT_53[] = { _SVEC(0,0,0), _SVEC(8,0,4), _SVEC(0,6,4), _SVEC(-8,1,4), _SVEC(0,5,4), _SVEC(8,0,4), _SVEC(4,-12,0), _RTSL() };
const word VECFONT_54[] = { _SVEC(0,12,0), _SVEC(0,-12,4), _SVEC(8,0,4), _SVEC(0,5,4), _SVEC(-8,2,4), _SVEC(12,-7,0), _RTSL() };
const word VECFONT_55[] = { _SVEC(0,12,0), _SVEC(8,0,4), _SVEC(0,-6,4), _SVEC(-4,-6,4), _SVEC(8,0,0), _RTSL() };
const word VECFONT_56[] = { _SVEC(0,0,0), _SVEC(8,0,4), _SVEC(0,12,4), _SVEC(-8,0,4), _SVEC(0,-12,4), _SVEC(0,6,0), _SVEC(8,0,4), _SVEC(4,-6,0), _RTSL() };
const word VECFONT_57[] = { _SVEC(8,0,0), _SVEC(0,12,4), _SVEC(-8,0,4), _SVEC(0,-5,4), _SVEC(8,-2,4), _SVEC(4,-5,0), _RTSL() };
const word VECFONT_58[] = { _SVEC(4,9,0), _SVEC(0,-2,4), _SVEC(0,-2,0), _SVEC(0,-2,4), _SVEC(8,-3,0), _RTSL() };
const word VECFONT_59[] = { _SVEC(4,9,0), _SVEC(0,-2,4), _SVEC(0,-2,0), _SVEC(-3,-3,4), _SVEC(11,-2,0), _RTSL() };
const word VECFONT_60[] = { _SVEC(6,0,0), _SVEC(-4,6,4), _SVEC(4,6,4), _SVEC(6,-12,0), _RTSL() };
const word VECFONT_61[] = { _SVEC(1,4,0), _SVEC(6,0,4), _SVEC(-6,4,0), _SVEC(6,0,4), _SVEC(5,-8,0), _RTSL() };
const word VECFONT_62[] = { _SVEC(2,0,0), _SVEC(4,6,4), _SVEC(-4,6,4), _SVEC(10,-12,0), _RTSL() };
const word VECFONT_63[] = { _SVEC(0,8,0), _SVEC(4,4,4), _SVEC(4,-4,4), _SVEC(-4,-4,4), _SVEC(0,-3,0), _SVEC(0,-1,4), _SVEC(8,0,0), _RTSL() };
const word VECFONT_64[] = { _SVEC(8,4,0), _SVEC(-4,-4,4), _SVEC(-4,4,4), _SVEC(0,4,4), _SVEC(4,4,4), _SVEC(4,-4,4), _SVEC(-4,-4,4), _SVEC(-1,2,4), _SVEC(9,-6,0), _RTSL() };
const word VECFONT_65[] = { _SVEC(0,0,0), _SVEC(0,8,4), _SVEC(4,4,4), _SVEC(4,-4,4), _SVEC(0,-8,4), _SVEC(-8,4,0), _SVEC(8,0,4), _SVEC(4,-4,0), _RTSL() };
const word VECFONT_66[] = { _SVEC(0,0,0), _SVEC(0,12,4), _SVEC(4,0,4), _SVEC(4,-2,4), _SVEC(-4,-4,4), _SVEC(4,-4,4), _SVEC(-4,-2,4), _SVEC(-4,0,4), _SVEC(12,0,0), _RTSL() };
const word VECFONT_67[] = { _SVEC(8,0,0), _SVEC(-8,0,4), _SVEC(0,12,4), _SVEC(8,0,4), _SVEC(4,-12,0), _RTSL() };
const word VECFONT_68[] = { _SVEC(0,0,0), _SVEC(0,12,4), _SVEC(4,0,4), _SVEC(4,-4,4), _SVEC(0,-4,4), _SVEC(-4,-4,4), _SVEC(-4,0,4), _SVEC(12,0,0), _RTSL() };
const word VECFONT_69[] = { _SVEC(8,0,0), _SVEC(-8,0,4), _SVEC(0,12,4), _SVEC(8,0,4), _SVEC(-8,-6,0), _SVEC(6,0,4), _SVEC(6,-6,0), _RTSL() };
const word VECFONT_70[] = { _SVEC(0,0,0), _SVEC(0,12,4), _SVEC(8,0,4), _SVEC(-8,-6,0), _SVEC(6,0,4), _SVEC(6,-6,0), _RTSL() };
const word VECFONT_71[] = { _SVEC(6,6,0), _SVEC(2,-2,4), _SVEC(0,-4,4), _SVEC(-8,0,4), _SVEC(0,12,4), _SVEC(8,0,4), _SVEC(4,-12,0), _RTSL() };
const word VECFONT_72[] = { _SVEC(0,0,0), _SVEC(0,12,4), _SVEC(0,-6,0), _SVEC(8,0,4), _SVEC(0,6,0), _SVEC(0,-12,4), _SVEC(4,0,0), _RTSL() };
const word VECFONT_73[] = { _SVEC(0,0,0), _SVEC(8,0,4), _SVEC(-4,0,0), _SVEC(0,12,4), _SVEC(-4,0,0), _SVEC(8,0,4), _SVEC(4,-12,0), _RTSL() };
const word VECFONT_74[] = { _SVEC(0,4,0), _SVEC(4,-4,4), _SVEC(4,0,4), _SVEC(0,12,4), _SVEC(4,-12,0), _RTSL() };
const word VECFONT_75[] = { _SVEC(0,0,0), _SVEC(0,12,4), _SVEC(8,0,0), _SVEC(-8,-6,4), _SVEC(6,-6,4), _SVEC(6,0,0), _RTSL() };
const word VECFONT_76[] = { _SVEC(8,0,0), _SVEC(-8,0,4), _SVEC(0,12,4), _SVEC(12,-12,0), _RTSL() };
const word VECFONT_77[] = { _SVEC(0,0,0), _SVEC(0,12,4), _SVEC(4,-4,4), _SVEC(4,4,4), _SVEC(0,-12,4), _SVEC(4,0,0), _RTSL() };
const word VECFONT_78[] = { _SVEC(0,0,0), _SVEC(0,12,4), _SVEC(8,-12,4), _SVEC(0,12,4), _SVEC(4,-12,0), _RTSL() };
const word VECFONT_79[] = { _SVEC(0,0,0), _SVEC(0,12,4), _SVEC(8,0,4), _SVEC(0,-12,4), _SVEC(-8,0,4), _SVEC(12,0,0), _RTSL() };
const word VECFONT_80[] = { _SVEC(0,0,0), _SVEC(0,12,4), _SVEC(8,0,4), _SVEC(0,-6,4), _SVEC(-8,-1,4), _SVEC(12,-5,0), _RTSL() };
const word VECFONT_81[] = { _SVEC(0,0,0), _SVEC(0,12,4), _SVEC(8,0,4), _SVEC(0,-8,4), _SVEC(-8,-4,4), _SVEC(4,4,0), _SVEC(4,-4,4), _SVEC(4,0,0), _RTSL() };
const word VECFONT_82[] = { _SVEC(0,0,0), _SVEC(0,12,4), _SVEC(8,0,4), _SVEC(0,-6,4), _SVEC(-8,-1,4), _SVEC(4,0,0), _SVEC(4,-5,4), _SVEC(4,0,0), _RTSL() };
const word VECFONT_83[] = { _SVEC(0,2,0), _SVEC(2,-2,4), _SVEC(6,0,4), _SVEC(0,5,4), _SVEC(-8,2,4), _SVEC(0,5,4), _SVEC(6,0,4), _SVEC(2,-2,4), _SVEC(4,-10,0), _RTSL() };
const word VECFONT_84[] = { _SVEC(0,12,0), _SVEC(8,0,4), _SVEC(-4,0,0), _SVEC(0,-12,4), _SVEC(8,0,0), _RTSL() };
const word VECFONT_85[] = { _SVEC(0,12,0), _SVEC(0,-10,4), _SVEC(4,-2,4), _SVEC(4,2,4), _SVEC(0,10,4), _SVEC(4,-12,0), _RTSL() };
const word VECFONT_86[] = { _SVEC(0,12,0), _SVEC(4,-12,4), _SVEC(4,12,4), _SVEC(4,-12,0), _RTSL() };
const word VECFONT_87[] = { _SVEC(0,12,0), _SVEC(2,-12,4), _SVEC(2,4,4), _SVEC(2,-4,4), _SVEC(2,12,4), _SVEC(4,-12,0), _RTSL() };
const word VECFONT_88[] = { _SVEC(0,0,0), _SVEC(8,12,4), _SVEC(-8,0,0), _SVEC(8,-12,4), _SVEC(4,0,0), _RTSL() };
const word VECFONT_89[] = { _SVEC(0,12,0), _SVEC(4,-6,4), _SVEC(4,6,4), _SVEC(-4,-6,0), _SVEC(0,-6,4), _SVEC(8,0,0), _RTSL() };
const word VECFONT_90[] = { _SVEC(0,12,0), _SVEC(8,0,4), _SVEC(-8,-12,4), _SVEC(8,0,4), _SVEC(-6,6,0), _SVEC(4,0,4), _SVEC(6,-6,0), _RTSL() };
const word* const VECFONT[] = { VECFONT_32,VECFONT_33,VECFONT_34,VECFONT_35,VECFONT_36,VECFONT_37,VECFONT_38,VECFONT_39,VECFONT_40,VECFONT_41,VECFONT_42,VECFONT_43,VECFONT_44,VECFONT_45,VECFONT_46,VECFONT_47,VECFONT_48,VECFONT_49,VECFONT_50,VECFONT_51,VECFONT_52,VECFONT_53,VECFONT_54,VECFONT_55,VECFONT_56,VECFONT_57,VECFONT_58,VECFONT_59,VECFONT_60,VECFONT_61,VECFONT_62,VECFONT_63,VECFONT_64,VECFONT_65,VECFONT_66,VECFONT_67,VECFONT_68,VECFONT_69,VECFONT_70,VECFONT_71,VECFONT_72,VECFONT_73,VECFONT_74,VECFONT_75,VECFONT_76,VECFONT_77,VECFONT_78,VECFONT_79,VECFONT_80,VECFONT_81,VECFONT_82,VECFONT_83,VECFONT_84,VECFONT_85,VECFONT_86,VECFONT_87,VECFONT_88,VECFONT_89,VECFONT_90, };
#pragma rodata-name(pop)
void draw_char(char ch) {
const word* vec = VECFONT[ch - ' '];
if (ch < ' ' || ch > 'Z') return;
JSRPTR(vec);
}
void draw_string(const char* str, byte spacing) {
while (*str) {
draw_char(*str++);
if (spacing) SVEC(spacing, 0, 0);
}
}

View File

@ -0,0 +1,12 @@
#ifndef _VECFONT_H
#define _VECFONT_H
#include "vecops.h"
const word* const VECFONT[];
void draw_char(char ch);
void draw_string(const char* str, byte spacing);
#endif

View File

@ -0,0 +1,69 @@
#include <string.h>
#include "vecops.h"
word dvgwrofs; // write offset for DVG buffer
#define dvgram ((word*)0x2000)
void dvgclear(void) {
memset(dvgram, 0x20, 0x800); // HALTs
}
void dvgreset(void) {
dvgwrofs = 0;
}
void dvgstart(void) {
asm("sta $8840"); // strobe DVGSTART
}
void dvgwrite(word w) {
dvgram[dvgwrofs] = w;
++dvgwrofs;
}
void VCTR(int dx, int dy, byte bright) {
dvgwrite((dy & 0x1fff));
dvgwrite(((bright & 7) << 13) | (dx & 0x1fff));
}
void SVEC(signed char dx, signed char dy, byte bright) {
dvgwrite(0x4000 | (dx & 0x1f) | ((bright&7)<<5) | ((dy & 0x1f)<<8));
}
void JSRL(word offset) {
dvgwrite(0xa000 | offset);
}
void JMPL(word offset) {
dvgwrite(0xe000 | offset);
}
void RTSL(void) {
dvgwrite(0xc000);
}
void CNTR(void) {
dvgwrite(0x8000);
}
void HALT(void) {
dvgwrite(0x2000);
}
void STAT(byte rgb, byte intens) {
dvgwrite(0x6000 | ((intens & 0xf)<<4) | (rgb & 7));
}
void STAT_sparkle(byte intens) {
dvgwrite(0x6800 | ((intens & 0xf)<<4));
}
void SCAL(word scale) {
dvgwrite(0x7000 | scale);
}
void JSRPTR(const word* dvgrom) {
JSRL(((word)dvgrom - 0x2000) >> 1);
}

View File

@ -0,0 +1,49 @@
#ifndef _VECOPS_H
#define _VECOPS_H
typedef unsigned char byte;
typedef signed char sbyte;
typedef unsigned short word;
extern word dvgwrofs; // write offset for DVG buffer
// DVG operation functions
typedef enum {
BLACK, BLUE, GREEN, CYAN, RED, MAGENTA, YELLOW, WHITE
} Color;
void dvgclear(void);
void dvgreset(void);
void dvgstart(void);
void dvgwrite(word w);
void VCTR(int dx, int dy, byte bright);
void SVEC(signed char dx, signed char dy, byte bright);
void JSRL(word offset);
void JMPL(word offset);
void RTSL(void);
void CNTR(void);
void HALT(void);
void STAT(byte rgb, byte intens);
void STAT_sparkle(byte intens);
void SCAL(word scale);
// jump to pointer in DVG ROM
void JSRPTR(const word* dvgrom);
// macro versions for DVG ROM constants
#define _VCTR(dx,dy,bright) \
(dy & 0x1fff), \
(((bright & 7) << 13) | (dx & 0x1fff))
#define _SVEC(dx,dy,bright) (0x4000 | (dx & 0x1f) | ((bright&7)<<5) | ((dy & 0x1f)<<8))
#define _JSRL(offset) (0xa000 | offset)
#define _JMPL(offset) (0xe000 | offset)
#define _RTSL() (0xc000)
#define _CNTR() (0x8000)
#define _HALT() (0x2000)
#define _STAT(rgb,intens) (0x6000 | ((intens & 0xf)<<4) | (rgb & 7))
#define _SCAL(scale) (0x7000 | scale)
#endif /* _VECOPS_H */

View File

@ -294,7 +294,7 @@ sbyte isin(byte x0) {
byte x = x0;
if (x0 & 0x40) x = 127-x;
if (x0 & 0x80) {
return -sintbl[x+128];
return -sintbl[x-128];
} else {
return sintbl[x];
}

View File

@ -155,7 +155,7 @@ sbyte isin(byte x0) {
byte x = x0;
if (x0 & 0x40) x = 127-x;
if (x0 & 0x80) {
return -sintbl[x+128];
return -sintbl[x-128];
} else {
return sintbl[x];
}

View File

@ -199,6 +199,7 @@ var AtariColorVectorPlatform = function(mainElement) {
var earom_offset, earom_data;
this.__proto__ = new (Base6502Platform as any)();
//this.debugPCDelta = 0;
this.getPresets = function() {
return VECTOR_PRESETS;
@ -235,6 +236,7 @@ var AtariColorVectorPlatform = function(mainElement) {
write: newAddressDecoder([
[0x0, 0x7ff, 0x7ff, function(a,v) { cpuram.mem[a] = v; }],
[0x2000, 0x27ff, 0x7ff, function(a,v) { dvgram.mem[a] = v; }],
[0x2800, 0x5fff, 0x7fff, function(a,v) { vecrom[a - 0x2800] = v; }], // TODO: remove (it's ROM!)
[0x6000, 0x67ff, 0xf, function(a,v) { audio.pokey1.setRegister(a, v); }],
[0x6800, 0x6fff, 0xf, function(a,v) { audio.pokey2.setRegister(a, v); }],
[0x8800, 0x8800, 0, function(a,v) { /* LEDs, etc */ }],
@ -286,7 +288,8 @@ var AtariColorVectorPlatform = function(mainElement) {
}
this.loadROM = function(title, data) {
rom = padBytes(data, 0x7000);
rom = data.slice(0, 0x7000);
vecrom = padBytes(data.slice(0x7000), 0x3800);
this.reset();
}
@ -307,7 +310,9 @@ var AtariColorVectorPlatform = function(mainElement) {
}
this.loadState = function(state) {
this.unfixPC(state.c);
cpu.loadState(state.c);
this.fixPC(state.c);
cpuram.mem.set(state.b);
dvgram.mem.set(state.db);
switches.set(state.sw);
@ -315,7 +320,7 @@ var AtariColorVectorPlatform = function(mainElement) {
}
this.saveState = function() {
return {
c:cpu.saveState(),
c:this.getCPUState(),
b:cpuram.mem.slice(0),
db:dvgram.mem.slice(0),
sw:switches.slice(0),
@ -331,7 +336,7 @@ var AtariColorVectorPlatform = function(mainElement) {
}
}
this.getCPUState = function() {
return cpu.saveState();
return this.fixPC(cpu.saveState());
}
}

View File

@ -375,7 +375,7 @@ export class SourceEditor implements ProjectView {
///
const disasmWindow = 512; // disassemble this many bytes around cursor
const disasmWindow = 1024; // disassemble this many bytes around cursor
export class DisassemblerView implements ProjectView {
disasmview;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,209 @@
var Module = typeof Module !== 'undefined' ? Module : {};
if (!Module.expectedDataFileDownloads) {
Module.expectedDataFileDownloads = 0;
Module.finishedDataFileDownloads = 0;
}
Module.expectedDataFileDownloads++;
(function() {
var loadPackage = function(metadata) {
var PACKAGE_PATH;
if (typeof window === 'object') {
PACKAGE_PATH = window['encodeURIComponent'](window.location.pathname.toString().substring(0, window.location.pathname.toString().lastIndexOf('/')) + '/');
} else if (typeof location !== 'undefined') {
// worker
PACKAGE_PATH = encodeURIComponent(location.pathname.toString().substring(0, location.pathname.toString().lastIndexOf('/')) + '/');
} else {
throw 'using preloaded data can only be done on a web page or in a web worker';
}
var PACKAGE_NAME = 'fs65-sim6502.data';
var REMOTE_PACKAGE_BASE = 'fs65-sim6502.data';
if (typeof Module['locateFilePackage'] === 'function' && !Module['locateFile']) {
Module['locateFile'] = Module['locateFilePackage'];
err('warning: you defined Module.locateFilePackage, that has been renamed to Module.locateFile (using your locateFilePackage for now)');
}
var REMOTE_PACKAGE_NAME = Module['locateFile'] ? Module['locateFile'](REMOTE_PACKAGE_BASE, '') : REMOTE_PACKAGE_BASE;
var REMOTE_PACKAGE_SIZE = metadata.remote_package_size;
var PACKAGE_UUID = metadata.package_uuid;
function fetchRemotePackage(packageName, packageSize, callback, errback) {
var xhr = new XMLHttpRequest();
xhr.open('GET', packageName, true);
xhr.responseType = 'arraybuffer';
xhr.onprogress = function(event) {
var url = packageName;
var size = packageSize;
if (event.total) size = event.total;
if (event.loaded) {
if (!xhr.addedTotal) {
xhr.addedTotal = true;
if (!Module.dataFileDownloads) Module.dataFileDownloads = {};
Module.dataFileDownloads[url] = {
loaded: event.loaded,
total: size
};
} else {
Module.dataFileDownloads[url].loaded = event.loaded;
}
var total = 0;
var loaded = 0;
var num = 0;
for (var download in Module.dataFileDownloads) {
var data = Module.dataFileDownloads[download];
total += data.total;
loaded += data.loaded;
num++;
}
total = Math.ceil(total * Module.expectedDataFileDownloads/num);
if (Module['setStatus']) Module['setStatus']('Downloading data... (' + loaded + '/' + total + ')');
} else if (!Module.dataFileDownloads) {
if (Module['setStatus']) Module['setStatus']('Downloading data...');
}
};
xhr.onerror = function(event) {
throw new Error("NetworkError for: " + packageName);
}
xhr.onload = function(event) {
if (xhr.status == 200 || xhr.status == 304 || xhr.status == 206 || (xhr.status == 0 && xhr.response)) { // file URLs can return 0
var packageData = xhr.response;
callback(packageData);
} else {
throw new Error(xhr.statusText + " : " + xhr.responseURL);
}
};
xhr.send(null);
};
function handleError(error) {
console.error('package error:', error);
};
var fetchedCallback = null;
var fetched = Module['getPreloadedPackage'] ? Module['getPreloadedPackage'](REMOTE_PACKAGE_NAME, REMOTE_PACKAGE_SIZE) : null;
if (!fetched) fetchRemotePackage(REMOTE_PACKAGE_NAME, REMOTE_PACKAGE_SIZE, function(data) {
if (fetchedCallback) {
fetchedCallback(data);
fetchedCallback = null;
} else {
fetched = data;
}
}, handleError);
function runWithFS() {
function assert(check, msg) {
if (!check) throw msg + new Error().stack;
}
Module['FS_createPath']('/', 'include', true, true);
Module['FS_createPath']('/include', 'em', true, true);
Module['FS_createPath']('/include', 'mouse', true, true);
Module['FS_createPath']('/include', 'tgi', true, true);
Module['FS_createPath']('/include', 'geos', true, true);
Module['FS_createPath']('/include', 'sys', true, true);
Module['FS_createPath']('/include', 'joystick', true, true);
Module['FS_createPath']('/', 'asminc', true, true);
Module['FS_createPath']('/', 'cfg', true, true);
Module['FS_createPath']('/', 'lib', true, true);
function DataRequest(start, end, audio) {
this.start = start;
this.end = end;
this.audio = audio;
}
DataRequest.prototype = {
requests: {},
open: function(mode, name) {
this.name = name;
this.requests[name] = this;
Module['addRunDependency']('fp ' + this.name);
},
send: function() {},
onload: function() {
var byteArray = this.byteArray.subarray(this.start, this.end);
this.finish(byteArray);
},
finish: function(byteArray) {
var that = this;
Module['FS_createDataFile'](this.name, null, byteArray, true, true, true); // canOwn this data in the filesystem, it is a slide into the heap that will never change
Module['removeRunDependency']('fp ' + that.name);
this.requests[this.name] = null;
}
};
var files = metadata.files;
for (var i = 0; i < files.length; ++i) {
new DataRequest(files[i].start, files[i].end, files[i].audio).open('GET', files[i].filename);
}
function processPackageData(arrayBuffer) {
Module.finishedDataFileDownloads++;
assert(arrayBuffer, 'Loading data file failed.');
assert(arrayBuffer instanceof ArrayBuffer, 'bad input to processPackageData');
var byteArray = new Uint8Array(arrayBuffer);
var curr;
// copy the entire loaded file into a spot in the heap. Files will refer to slices in that. They cannot be freed though
// (we may be allocating before malloc is ready, during startup).
var ptr = Module['getMemory'](byteArray.length);
Module['HEAPU8'].set(byteArray, ptr);
DataRequest.prototype.byteArray = Module['HEAPU8'].subarray(ptr, ptr+byteArray.length);
var files = metadata.files;
for (var i = 0; i < files.length; ++i) {
DataRequest.prototype.requests[files[i].filename].onload();
}
Module['removeRunDependency']('datafile_fs65-sim6502.data');
};
Module['addRunDependency']('datafile_fs65-sim6502.data');
if (!Module.preloadResults) Module.preloadResults = {};
Module.preloadResults[PACKAGE_NAME] = {fromCache: false};
if (fetched) {
processPackageData(fetched);
fetched = null;
} else {
fetchedCallback = processPackageData;
}
}
if (Module['calledRun']) {
runWithFS();
} else {
if (!Module['preRun']) Module['preRun'] = [];
Module["preRun"].push(runWithFS); // FS is not initialized yet, wait for it
}
Module['removeRunDependency']('fs65-sim6502.js.metadata');
}
function runMetaWithFS() {
Module['addRunDependency']('fs65-sim6502.js.metadata');
var REMOTE_METADATA_NAME = Module['locateFile'] ? Module['locateFile']('fs65-sim6502.js.metadata', '') : 'fs65-sim6502.js.metadata';
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
loadPackage(JSON.parse(xhr.responseText));
}
}
xhr.open('GET', REMOTE_METADATA_NAME, true);
xhr.overrideMimeType('application/json');
xhr.send(null);
}
if (Module['calledRun']) {
runMetaWithFS();
} else {
if (!Module['preRun']) Module['preRun'] = [];
Module["preRun"].push(runMetaWithFS);
}
})();

File diff suppressed because one or more lines are too long

View File

@ -57,8 +57,8 @@ SEGMENTS {
DATA: load = PRG6, run = RAM, type = rw, define = yes;
STARTUP: load = PRG6, type = ro, define = yes;
CODE: load = PRG7, type = ro, define = yes;
VECTORS: load = VECTORS, type = rw;
CHARS: load = CHR, type = rw;
VECTORS: load = VECTORS, type = ro;
CHARS: load = CHR, type = ro;
BSS: load = SRAM, type = bss, define = yes;
}
FEATURES {

Binary file not shown.

View File

@ -0,0 +1,43 @@
;
; Oliver Schmidt, 2013-05-16
;
; Startup code for cc65 (sim6502 version)
;
.export _exit
.export __STARTUP__ : absolute = 1 ; Mark as startup
.import zerobss, callmain
.import initlib, donelib, copydata
.import exit
.import __PRGRAM_START__, __PRGRAM_SIZE__ ; Linker generated
; .import __STACKSIZE__ ; Linker generated
.include "zeropage.inc"
.segment "STARTUP"
start:
cld
ldx #$FF
txs
lda #<(__PRGRAM_START__ + __PRGRAM_SIZE__)
ldx #>(__PRGRAM_START__ + __PRGRAM_SIZE__)
sta sp
stx sp+1
jsr zerobss
jsr copydata
jsr initlib
jsr callmain
_exit: pha
jsr donelib
pla
jmp exit
nmi:
inc $0
rti
.segment "VECTORS"
.word nmi ; $fffa nmi
.word start ; $fffc reset
.word nmi ; $fffe irq / brk

View File

@ -0,0 +1,49 @@
SYMBOLS {
__STACKSIZE__: type = weak, value = $0200;
}
MEMORY {
ZP: file = "", start = $0002, size = $00FE, type = rw, define = yes;
PRGRAM: file = "", start = $0200, size = $600, define = yes;
DVGRAM: file = "", start = $2000, size = $800, define = yes;
# PRG ROM @ $9000 - $FFFF
# - startup
# - code
# - rodata
# - data (load)
MAIN: file = %O, start = $9000, size = $6FFA, fill = yes, define = yes;
# CPU vectors
VECTORS: file = %O, start = $FFFA, size = $0006, fill = yes;
# DVG ROM @ $2800 - $5FFF
DVGROM: file = %O, start = $2800, size = $3800, fill = yes, define = yes;
}
SEGMENTS {
ZEROPAGE: load = ZP, type = zp;
STARTUP: load = MAIN, type = ro, define = yes;
LOWCODE: load = MAIN, type = ro, optional = yes;
CODE: load = MAIN, type = ro, define = yes;
RODATA: load = MAIN, type = ro, define = yes;
DATA: load = MAIN, run = PRGRAM, type = rw, define = yes;
ONCE: load = MAIN, type = ro, define = yes, optional = yes;
VECTORS: load = VECTORS, type = ro;
DVGROM: load = DVGROM, type = ro, optional = yes;
BSS: load = PRGRAM, type = bss, define = yes;
}
FEATURES {
CONDES: type = constructor,
label = __CONSTRUCTOR_TABLE__,
count = __CONSTRUCTOR_COUNT__,
segment = ONCE;
CONDES: type = destructor,
label = __DESTRUCTOR_TABLE__,
count = __DESTRUCTOR_COUNT__,
segment = RODATA;
CONDES: type = interruptor,
label = __INTERRUPTOR_TABLE__,
count = __INTERRUPTOR_COUNT__,
segment = RODATA,
import = __CALLIRQ__;
}

View File

@ -128,6 +128,17 @@ var PLATFORM_PARAMS = {
{name:'DVG RAM',start:0xa000,size:0x4000,type:'ram'},
],
},
'vector-ataricolor': { //TODO
define: '__VECTOR__',
cfgfile: 'vector-color.cfg',
libargs: ['crt0.o', 'sim6502.lib'],
extra_link_files: ['crt0.o', 'vector-color.cfg'],
extra_segments:[
{name:'Switches/POKEY I/O',start:0x7800,size:0x1000,type:'io'},
{name:'DVG I/O',start:0x8800,size:0x100,type:'io'},
{name:'EAROM',start:0x8900,size:0x100,type:'ram'},
],
},
'sound_williams-z80': {
code_start: 0x0,
rom_size: 0x4000,
@ -497,6 +508,7 @@ function loadNative(modulename:string) {
// mount the filesystem at /share
function setupFS(FS, name:string) {
var WORKERFS = FS.filesystems['WORKERFS'];
if (name === '65-vector') name = '65-sim6502'; // TODO
if (!fsMeta[name]) throw "No filesystem for '" + name + "'";
FS.mkdir('/share');
FS.mount(WORKERFS, {
@ -893,7 +905,6 @@ function assembleCA65(step:BuildStep) {
function linkLD65(step:BuildStep) {
loadNative("ld65");
var params = step.params;
var platform = step.platform;
gatherFiles(step);
var binpath = "main";
if (staleFiles(step, [binpath])) {
@ -906,7 +917,7 @@ function linkLD65(step:BuildStep) {
printErr:function(s) { errors.push({msg:s,line:0}); }
});
var FS = LD65['FS'];
setupFS(FS, '65-'+getRootBasePlatform(platform));
setupFS(FS, '65-'+getRootBasePlatform(step.platform));
populateFiles(step, FS);
populateExtraFiles(step, FS, params.extra_link_files);
var libargs = params.libargs;
@ -960,8 +971,8 @@ function linkLD65(step:BuildStep) {
let seglast = symbolmap['__'+seg+'_LAST__'];
if (segstart >= 0 && segsize > 0 && !seg.startsWith('PRG') && seg != 'RAM') { // TODO
var type = null;
if (seg.startsWith('CODE') || seg == 'STARTUP' || seg == 'RODATA') type = 'rom';
else if (seg == 'ZP' || seg == 'RAM' || seg == 'DATA' || seg == 'BSS') type = 'ram';
if (seg.startsWith('CODE') || seg == 'STARTUP' || seg == 'RODATA' || seg.endsWith('ROM')) type = 'rom';
else if (seg == 'ZP' || seg == 'DATA' || seg == 'BSS' || seg.endsWith('RAM')) type = 'ram';
segments.push({name:seg, start:segstart, size:segsize, last:seglast, type:type});
}
}
@ -1894,6 +1905,8 @@ var TOOL_PRELOADFS = {
'ca65-nes': '65-nes',
'cc65-atari8': '65-atari8',
'ca65-atari8': '65-atari8',
'cc65-vector': '65-sim6502',
'ca65-vector': '65-sim6502',
'sdasz80': 'sdcc',
'sdcc': 'sdcc',
'sccz80': 'sccz80',

118
tools/vector/dvgfonts.c Normal file
View File

@ -0,0 +1,118 @@
#include <string.h>
#include <stdio.h>
typedef unsigned char byte;
typedef unsigned short word;
#define P(x,y) ((((x) & 0xF) << 4) | (((y) & 0xF) << 0))
#define FONT_UP 0xFE
#define FONT_LAST 0xFF
const byte vecfont[59][8] = {
/*' '*/{ FONT_LAST },
/*'!'*/{ P(4,0), P(3,2), P(5,2), P(4,0), FONT_UP, P(4,4), P(4,12), FONT_LAST },
/*'"'*/{ P(2,10), P(2,6), FONT_UP, P(6,10), P(6,6), FONT_LAST },
/*'#'*/{ P(0,4), P(8,4), P(6,2), P(6,10), P(8,8), P(0,8), P(2,10), P(2,2) },
/*'$'*/{ P(6,2), P(2,6), P(6,10), FONT_UP, P(4,12), P(4,0), FONT_LAST },
/*'%'*/{ P(0,0), P(8,12), FONT_UP, P(2,10), P(2,8), FONT_UP, P(6,4), P(6,2) },
/*'&'*/{ P(8,0), P(4,12), P(8,8), P(0,4), P(4,0), P(8,4), FONT_LAST },
/*'''*/{ P(0,12), P(8,0), FONT_LAST },
/*'('*/{ P(6,0), P(2,4), P(2,8), P(6,12), FONT_LAST },
/*')'*/{ P(2,0), P(6,4), P(6,8), P(2,12), FONT_LAST },
/*'*'*/{ P(0,0), P(4,12), P(8,0), P(0,8), P(8,8), P(0,0), FONT_LAST },
/*'+'*/{ P(1,6), P(7,6), FONT_UP, P(4,9), P(4,3), FONT_LAST },
/*','*/{ P(2,0), P(4,2), FONT_LAST },
/*'-'*/{ P(2,6), P(6,6), FONT_LAST },
/*'.'*/{ P(3,0), P(4,0), FONT_LAST },
/*'/'*/{ P(0,0), P(8,12), FONT_LAST },
/*'0'*/{ P(0,0), P(8,0), P(8,12), P(0,12), P(0,0), P(8,12), FONT_LAST },
/*'1'*/{ P(4,0), P(4,12), P(3,10), FONT_LAST },
/*'2'*/{ P(0,12), P(8,12), P(8,7), P(0,5), P(0,0), P(8,0), FONT_LAST },
/*'3'*/{ P(0,12), P(8,12), P(8,0), P(0,0), FONT_UP, P(0,6), P(8,6), FONT_LAST },
/*'4'*/{ P(0,12), P(0,6), P(8,6), FONT_UP, P(8,12), P(8,0), FONT_LAST },
/*'5'*/{ P(0,0), P(8,0), P(8,6), P(0,7), P(0,12), P(8,12), FONT_LAST },
/*'6'*/{ P(0,12), P(0,0), P(8,0), P(8,5), P(0,7), FONT_LAST },
/*'7'*/{ P(0,12), P(8,12), P(8,6), P(4,0), FONT_LAST },
/*'8'*/{ P(0,0), P(8,0), P(8,12), P(0,12), P(0,0), FONT_UP, P(0,6), P(8,6), },
/*'9'*/{ P(8,0), P(8,12), P(0,12), P(0,7), P(8,5), FONT_LAST },
/*':'*/{ P(4,9), P(4,7), FONT_UP, P(4,5), P(4,3), FONT_LAST },
/*';'*/{ P(4,9), P(4,7), FONT_UP, P(4,5), P(1,2), FONT_LAST },
/*'<'*/{ P(6,0), P(2,6), P(6,12), FONT_LAST },
/*'='*/{ P(1,4), P(7,4), FONT_UP, P(1,8), P(7,8), FONT_LAST },
/*'>'*/{ P(2,0), P(6,6), P(2,12), FONT_LAST },
/*'?'*/{ P(0,8), P(4,12), P(8,8), P(4,4), FONT_UP, P(4,1), P(4,0), FONT_LAST },
/*'@'*/{ P(8,4), P(4,0), P(0,4), P(0,8), P(4,12), P(8,8), P(4,4), P(3,6) },
/*'A'*/{ P(0,0), P(0,8), P(4,12), P(8,8), P(8,0), FONT_UP, P(0,4), P(8,4) },
/*'B'*/{ P(0,0), P(0,12), P(4,12), P(8,10), P(4,6), P(8,2), P(4,0), P(0,0) },
/*'C'*/{ P(8,0), P(0,0), P(0,12), P(8,12), FONT_LAST },
/*'D'*/{ P(0,0), P(0,12), P(4,12), P(8,8), P(8,4), P(4,0), P(0,0), FONT_LAST },
/*'E'*/{ P(8,0), P(0,0), P(0,12), P(8,12), FONT_UP, P(0,6), P(6,6), FONT_LAST },
/*'F'*/{ P(0,0), P(0,12), P(8,12), FONT_UP, P(0,6), P(6,6), FONT_LAST },
/*'G'*/{ P(6,6), P(8,4), P(8,0), P(0,0), P(0,12), P(8,12), FONT_LAST },
/*'H'*/{ P(0,0), P(0,12), FONT_UP, P(0,6), P(8,6), FONT_UP, P(8,12), P(8,0) },
/*'I'*/{ P(0,0), P(8,0), FONT_UP, P(4,0), P(4,12), FONT_UP, P(0,12), P(8,12) },
/*'J'*/{ P(0,4), P(4,0), P(8,0), P(8,12), FONT_LAST },
/*'K'*/{ P(0,0), P(0,12), FONT_UP, P(8,12), P(0,6), P(6,0), FONT_LAST },
/*'L'*/{ P(8,0), P(0,0), P(0,12), FONT_LAST },
/*'M'*/{ P(0,0), P(0,12), P(4,8), P(8,12), P(8,0), FONT_LAST },
/*'N'*/{ P(0,0), P(0,12), P(8,0), P(8,12), FONT_LAST },
/*'O'*/{ P(0,0), P(0,12), P(8,12), P(8,0), P(0,0), FONT_LAST },
/*'P'*/{ P(0,0), P(0,12), P(8,12), P(8,6), P(0,5), FONT_LAST },
/*'Q'*/{ P(0,0), P(0,12), P(8,12), P(8,4), P(0,0), FONT_UP, P(4,4), P(8,0) },
/*'R'*/{ P(0,0), P(0,12), P(8,12), P(8,6), P(0,5), FONT_UP, P(4,5), P(8,0) },
/*'S'*/{ P(0,2), P(2,0), P(8,0), P(8,5), P(0,7), P(0,12), P(6,12), P(8,10) },
/*'T'*/{ P(0,12), P(8,12), FONT_UP, P(4,12), P(4,0), FONT_LAST },
/*'U'*/{ P(0,12), P(0,2), P(4,0), P(8,2), P(8,12), FONT_LAST },
/*'V'*/{ P(0,12), P(4,0), P(8,12), FONT_LAST },
/*'W'*/{ P(0,12), P(2,0), P(4,4), P(6,0), P(8,12), FONT_LAST },
/*'X'*/{ P(0,0), P(8,12), FONT_UP, P(0,12), P(8,0), FONT_LAST },
/*'Y'*/{ P(0,12), P(4,6), P(8,12), FONT_UP, P(4,6), P(4,0), FONT_LAST },
/*'Z'*/{ P(0,12), P(8,12), P(0,0), P(8,0), FONT_UP, P(2,6), P(6,6), FONT_LAST },
};
////
static int frame = 0;
void draw_char(char ch) {
const byte* p = vecfont[ch - ' '];
byte bright = 0;
byte x = 0;
byte y = 0;
byte i;
if (ch < ' ' || ch > 'Z') return;
printf("const word VECFONT_%d[] = { ", ch);
for (i=0; i<8; i++) {
byte b = *p++;
if (b == FONT_LAST) break; // last move
else if (b == FONT_UP) bright = 0; // pen up
else {
byte x2 = b>>4;
byte y2 = b&15;
printf("_SVEC(%d,%d,%d), ", (char)(x2-x), (char)(y2-y), bright);
bright = 4;
x = x2;
y = y2;
}
}
printf("_SVEC(%d,%d,%d), _RTSL() };\n", (char)12-x, (char)-y, 0);
}
void main(void) {
for (int i=' '; i<='Z'; i++) {
draw_char(i);
}
printf("const word* const VECFONT[] = { ");
for (int i=' '; i<='Z'; i++) {
printf("VECFONT_%d,", i);
}
printf(" };\n");
}