started on vector-ataricolor target (for 6502)
This commit is contained in:
parent
f71c8602e0
commit
0e47e7d035
|
@ -123,6 +123,7 @@ TODO:
|
||||||
- toolbar overlaps scope
|
- toolbar overlaps scope
|
||||||
- CPU debugging
|
- CPU debugging
|
||||||
- disassemble more code around breakpoint
|
- disassemble more code around breakpoint
|
||||||
|
- single-stepping vector games makes screen fade
|
||||||
|
|
||||||
WEB WORKER FORMAT
|
WEB WORKER FORMAT
|
||||||
|
|
||||||
|
|
|
@ -125,6 +125,7 @@ if (window.location.host.endsWith('8bitworkshop.com')) {
|
||||||
<ul class="dropdown-menu">
|
<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=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=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>
|
<li><a class="dropdown-item" href="?platform=markdown" id="item_platform_markdown">Markdown</a></li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
|
|
|
@ -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++;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
|
@ -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++;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
|
@ -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
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
|
@ -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);
|
||||||
|
}
|
|
@ -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 */
|
|
@ -294,7 +294,7 @@ sbyte isin(byte x0) {
|
||||||
byte x = x0;
|
byte x = x0;
|
||||||
if (x0 & 0x40) x = 127-x;
|
if (x0 & 0x40) x = 127-x;
|
||||||
if (x0 & 0x80) {
|
if (x0 & 0x80) {
|
||||||
return -sintbl[x+128];
|
return -sintbl[x-128];
|
||||||
} else {
|
} else {
|
||||||
return sintbl[x];
|
return sintbl[x];
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,7 +155,7 @@ sbyte isin(byte x0) {
|
||||||
byte x = x0;
|
byte x = x0;
|
||||||
if (x0 & 0x40) x = 127-x;
|
if (x0 & 0x40) x = 127-x;
|
||||||
if (x0 & 0x80) {
|
if (x0 & 0x80) {
|
||||||
return -sintbl[x+128];
|
return -sintbl[x-128];
|
||||||
} else {
|
} else {
|
||||||
return sintbl[x];
|
return sintbl[x];
|
||||||
}
|
}
|
||||||
|
|
|
@ -199,6 +199,7 @@ var AtariColorVectorPlatform = function(mainElement) {
|
||||||
var earom_offset, earom_data;
|
var earom_offset, earom_data;
|
||||||
|
|
||||||
this.__proto__ = new (Base6502Platform as any)();
|
this.__proto__ = new (Base6502Platform as any)();
|
||||||
|
//this.debugPCDelta = 0;
|
||||||
|
|
||||||
this.getPresets = function() {
|
this.getPresets = function() {
|
||||||
return VECTOR_PRESETS;
|
return VECTOR_PRESETS;
|
||||||
|
@ -235,6 +236,7 @@ var AtariColorVectorPlatform = function(mainElement) {
|
||||||
write: newAddressDecoder([
|
write: newAddressDecoder([
|
||||||
[0x0, 0x7ff, 0x7ff, function(a,v) { cpuram.mem[a] = v; }],
|
[0x0, 0x7ff, 0x7ff, function(a,v) { cpuram.mem[a] = v; }],
|
||||||
[0x2000, 0x27ff, 0x7ff, function(a,v) { dvgram.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); }],
|
[0x6000, 0x67ff, 0xf, function(a,v) { audio.pokey1.setRegister(a, v); }],
|
||||||
[0x6800, 0x6fff, 0xf, function(a,v) { audio.pokey2.setRegister(a, v); }],
|
[0x6800, 0x6fff, 0xf, function(a,v) { audio.pokey2.setRegister(a, v); }],
|
||||||
[0x8800, 0x8800, 0, function(a,v) { /* LEDs, etc */ }],
|
[0x8800, 0x8800, 0, function(a,v) { /* LEDs, etc */ }],
|
||||||
|
@ -286,7 +288,8 @@ var AtariColorVectorPlatform = function(mainElement) {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.loadROM = function(title, data) {
|
this.loadROM = function(title, data) {
|
||||||
rom = padBytes(data, 0x7000);
|
rom = data.slice(0, 0x7000);
|
||||||
|
vecrom = padBytes(data.slice(0x7000), 0x3800);
|
||||||
this.reset();
|
this.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -307,7 +310,9 @@ var AtariColorVectorPlatform = function(mainElement) {
|
||||||
}
|
}
|
||||||
|
|
||||||
this.loadState = function(state) {
|
this.loadState = function(state) {
|
||||||
|
this.unfixPC(state.c);
|
||||||
cpu.loadState(state.c);
|
cpu.loadState(state.c);
|
||||||
|
this.fixPC(state.c);
|
||||||
cpuram.mem.set(state.b);
|
cpuram.mem.set(state.b);
|
||||||
dvgram.mem.set(state.db);
|
dvgram.mem.set(state.db);
|
||||||
switches.set(state.sw);
|
switches.set(state.sw);
|
||||||
|
@ -315,7 +320,7 @@ var AtariColorVectorPlatform = function(mainElement) {
|
||||||
}
|
}
|
||||||
this.saveState = function() {
|
this.saveState = function() {
|
||||||
return {
|
return {
|
||||||
c:cpu.saveState(),
|
c:this.getCPUState(),
|
||||||
b:cpuram.mem.slice(0),
|
b:cpuram.mem.slice(0),
|
||||||
db:dvgram.mem.slice(0),
|
db:dvgram.mem.slice(0),
|
||||||
sw:switches.slice(0),
|
sw:switches.slice(0),
|
||||||
|
@ -331,7 +336,7 @@ var AtariColorVectorPlatform = function(mainElement) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.getCPUState = function() {
|
this.getCPUState = function() {
|
||||||
return cpu.saveState();
|
return this.fixPC(cpu.saveState());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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 {
|
export class DisassemblerView implements ProjectView {
|
||||||
disasmview;
|
disasmview;
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -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
|
@ -57,8 +57,8 @@ SEGMENTS {
|
||||||
DATA: load = PRG6, run = RAM, type = rw, define = yes;
|
DATA: load = PRG6, run = RAM, type = rw, define = yes;
|
||||||
STARTUP: load = PRG6, type = ro, define = yes;
|
STARTUP: load = PRG6, type = ro, define = yes;
|
||||||
CODE: load = PRG7, type = ro, define = yes;
|
CODE: load = PRG7, type = ro, define = yes;
|
||||||
VECTORS: load = VECTORS, type = rw;
|
VECTORS: load = VECTORS, type = ro;
|
||||||
CHARS: load = CHR, type = rw;
|
CHARS: load = CHR, type = ro;
|
||||||
BSS: load = SRAM, type = bss, define = yes;
|
BSS: load = SRAM, type = bss, define = yes;
|
||||||
}
|
}
|
||||||
FEATURES {
|
FEATURES {
|
||||||
|
|
Binary file not shown.
|
@ -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
|
|
@ -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__;
|
||||||
|
}
|
|
@ -128,6 +128,17 @@ var PLATFORM_PARAMS = {
|
||||||
{name:'DVG RAM',start:0xa000,size:0x4000,type:'ram'},
|
{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': {
|
'sound_williams-z80': {
|
||||||
code_start: 0x0,
|
code_start: 0x0,
|
||||||
rom_size: 0x4000,
|
rom_size: 0x4000,
|
||||||
|
@ -497,6 +508,7 @@ function loadNative(modulename:string) {
|
||||||
// mount the filesystem at /share
|
// mount the filesystem at /share
|
||||||
function setupFS(FS, name:string) {
|
function setupFS(FS, name:string) {
|
||||||
var WORKERFS = FS.filesystems['WORKERFS'];
|
var WORKERFS = FS.filesystems['WORKERFS'];
|
||||||
|
if (name === '65-vector') name = '65-sim6502'; // TODO
|
||||||
if (!fsMeta[name]) throw "No filesystem for '" + name + "'";
|
if (!fsMeta[name]) throw "No filesystem for '" + name + "'";
|
||||||
FS.mkdir('/share');
|
FS.mkdir('/share');
|
||||||
FS.mount(WORKERFS, {
|
FS.mount(WORKERFS, {
|
||||||
|
@ -893,7 +905,6 @@ function assembleCA65(step:BuildStep) {
|
||||||
function linkLD65(step:BuildStep) {
|
function linkLD65(step:BuildStep) {
|
||||||
loadNative("ld65");
|
loadNative("ld65");
|
||||||
var params = step.params;
|
var params = step.params;
|
||||||
var platform = step.platform;
|
|
||||||
gatherFiles(step);
|
gatherFiles(step);
|
||||||
var binpath = "main";
|
var binpath = "main";
|
||||||
if (staleFiles(step, [binpath])) {
|
if (staleFiles(step, [binpath])) {
|
||||||
|
@ -906,7 +917,7 @@ function linkLD65(step:BuildStep) {
|
||||||
printErr:function(s) { errors.push({msg:s,line:0}); }
|
printErr:function(s) { errors.push({msg:s,line:0}); }
|
||||||
});
|
});
|
||||||
var FS = LD65['FS'];
|
var FS = LD65['FS'];
|
||||||
setupFS(FS, '65-'+getRootBasePlatform(platform));
|
setupFS(FS, '65-'+getRootBasePlatform(step.platform));
|
||||||
populateFiles(step, FS);
|
populateFiles(step, FS);
|
||||||
populateExtraFiles(step, FS, params.extra_link_files);
|
populateExtraFiles(step, FS, params.extra_link_files);
|
||||||
var libargs = params.libargs;
|
var libargs = params.libargs;
|
||||||
|
@ -960,8 +971,8 @@ function linkLD65(step:BuildStep) {
|
||||||
let seglast = symbolmap['__'+seg+'_LAST__'];
|
let seglast = symbolmap['__'+seg+'_LAST__'];
|
||||||
if (segstart >= 0 && segsize > 0 && !seg.startsWith('PRG') && seg != 'RAM') { // TODO
|
if (segstart >= 0 && segsize > 0 && !seg.startsWith('PRG') && seg != 'RAM') { // TODO
|
||||||
var type = null;
|
var type = null;
|
||||||
if (seg.startsWith('CODE') || seg == 'STARTUP' || seg == 'RODATA') type = 'rom';
|
if (seg.startsWith('CODE') || seg == 'STARTUP' || seg == 'RODATA' || seg.endsWith('ROM')) type = 'rom';
|
||||||
else if (seg == 'ZP' || seg == 'RAM' || seg == 'DATA' || seg == 'BSS') type = 'ram';
|
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});
|
segments.push({name:seg, start:segstart, size:segsize, last:seglast, type:type});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1894,6 +1905,8 @@ var TOOL_PRELOADFS = {
|
||||||
'ca65-nes': '65-nes',
|
'ca65-nes': '65-nes',
|
||||||
'cc65-atari8': '65-atari8',
|
'cc65-atari8': '65-atari8',
|
||||||
'ca65-atari8': '65-atari8',
|
'ca65-atari8': '65-atari8',
|
||||||
|
'cc65-vector': '65-sim6502',
|
||||||
|
'ca65-vector': '65-sim6502',
|
||||||
'sdasz80': 'sdcc',
|
'sdasz80': 'sdcc',
|
||||||
'sdcc': 'sdcc',
|
'sdcc': 'sdcc',
|
||||||
'sccz80': 'sccz80',
|
'sccz80': 'sccz80',
|
||||||
|
|
|
@ -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");
|
||||||
|
}
|
Loading…
Reference in New Issue