mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2025-02-21 06:29:02 +00:00
started on vector-ataricolor target (for 6502)
This commit is contained in:
parent
f71c8602e0
commit
0e47e7d035
@ -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
|
||||
|
||||
|
@ -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>
|
||||
|
38
presets/vector-ataricolor/font.c
Normal file
38
presets/vector-ataricolor/font.c
Normal 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++;
|
||||
}
|
||||
}
|
397
presets/vector-ataricolor/game.c
Normal file
397
presets/vector-ataricolor/game.c
Normal 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();
|
||||
}
|
21
presets/vector-ataricolor/skeleton.cc65
Normal file
21
presets/vector-ataricolor/skeleton.cc65
Normal 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();
|
||||
}
|
33
presets/vector-ataricolor/threed.c
Normal file
33
presets/vector-ataricolor/threed.c
Normal 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++;
|
||||
}
|
||||
}
|
112
presets/vector-ataricolor/vec3d.c
Normal file
112
presets/vector-ataricolor/vec3d.c
Normal 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);
|
||||
}
|
36
presets/vector-ataricolor/vec3d.h
Normal file
36
presets/vector-ataricolor/vec3d.h
Normal 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
|
79
presets/vector-ataricolor/vecfont.c
Normal file
79
presets/vector-ataricolor/vecfont.c
Normal 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);
|
||||
}
|
||||
}
|
||||
|
12
presets/vector-ataricolor/vecfont.h
Normal file
12
presets/vector-ataricolor/vecfont.h
Normal 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
|
69
presets/vector-ataricolor/vecops.c
Normal file
69
presets/vector-ataricolor/vecops.c
Normal 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);
|
||||
}
|
49
presets/vector-ataricolor/vecops.h
Normal file
49
presets/vector-ataricolor/vecops.h
Normal 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 */
|
@ -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];
|
||||
}
|
||||
|
@ -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];
|
||||
}
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
26184
src/worker/fs/fs65-sim6502.data
Normal file
26184
src/worker/fs/fs65-sim6502.data
Normal file
File diff suppressed because it is too large
Load Diff
209
src/worker/fs/fs65-sim6502.js
Normal file
209
src/worker/fs/fs65-sim6502.js
Normal 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);
|
||||
}
|
||||
|
||||
})();
|
1
src/worker/fs/fs65-sim6502.js.metadata
Normal file
1
src/worker/fs/fs65-sim6502.js.metadata
Normal file
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;
|
||||
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 {
|
||||
|
BIN
src/worker/lib/vector-ataricolor/crt0.o
Normal file
BIN
src/worker/lib/vector-ataricolor/crt0.o
Normal file
Binary file not shown.
43
src/worker/lib/vector-ataricolor/crt0.s
Normal file
43
src/worker/lib/vector-ataricolor/crt0.s
Normal 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
|
49
src/worker/lib/vector-ataricolor/vector-color.cfg
Normal file
49
src/worker/lib/vector-ataricolor/vector-color.cfg
Normal 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__;
|
||||
}
|
@ -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
118
tools/vector/dvgfonts.c
Normal 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");
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user