dos33fsprogs/utils/gr-sim/hgr/fw_purple.c

314 lines
5.8 KiB
C
Raw Normal View History

2018-09-05 02:34:52 +00:00
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <math.h>
2018-09-05 17:54:36 +00:00
#include "6502_emulate.h"
2018-09-05 02:34:52 +00:00
#include "gr-sim.h"
// Based on BASIC program posted by FozzTexx, originally written in 1987
//140 REM MS is max steps, CS is current step, X/Y/X1/Y1/X2/Y2 is rocket position
//150 REM CL is Apple II hi-res color group
const int ysize=160,xsize=280,margin=24;
2018-09-05 17:54:36 +00:00
2018-09-05 19:04:31 +00:00
int xpos;
2018-09-05 17:54:36 +00:00
2018-09-05 19:04:31 +00:00
signed char o,i;
2018-09-05 17:54:36 +00:00
signed char color_group,x_velocity,cs,max_steps;
2018-09-05 19:04:31 +00:00
unsigned char xpos_l;
2018-09-05 17:54:36 +00:00
unsigned char ypos_h,ypos_l;
signed char y_velocity_h;
unsigned char y_velocity_l;
unsigned char y_old=0,y_even_older;
unsigned char x_old=0,x_even_older;
unsigned char peak;
2018-09-05 19:04:31 +00:00
#define NUMSTARS 16
struct star_type {
unsigned char x;
unsigned char y;
} stars[NUMSTARS] = {
// even x so they are purple
{28,107},
{108,88},
{126,88},
{136,95},
{150,105},
{148,120},
{172,124},
{180,109},
{216,21},
{164,40},
{124,18},
{60,12},
{240,124},
{94,125},
{12,22},
{216,116},
};
2018-09-05 17:54:36 +00:00
#define SEED 0
#define MAGIC "vW" // $7657
/* based on Linear feedback shift register type of PRNG by White Flame */
/* http://codebase64.org/doku.php?id=base:small_fast_16-bit_prng */
void random_6502(void) {
lda(SEED); // lda seed
if (A==0) goto lowZero; // beq lowZero ; $0000 and $8000 are special values to test for
2018-09-05 17:54:36 +00:00
// ; Do a normal shift
asl_mem(SEED); // asl seed
lda(SEED+1); // lda seed+1
rol(); // rol
if (C==0) goto noEor; // bcc noEor
2018-09-05 17:54:36 +00:00
doEor:
// ; high byte is in .A
A=A^0x76; // eor #>magic
ram[SEED+1]=A; // sta seed+1
2018-09-05 17:54:36 +00:00
lda(SEED); // lda seed
A=A^0x57; // eor #<magic
ram[SEED]=A; // sta seed
2018-09-05 17:54:36 +00:00
return; // rts
lowZero:
lda(SEED+1); // lda seed+1
if (A==0) goto doEor;
2018-09-05 17:54:36 +00:00
// beq doEor ; High byte is also zero, so apply the EOR
// ; For speed, you could store 'magic' into 'seed' directly
// ; instead of running the EORs
// ; wasn't zero, check for $8000
asl(); // asl
if (A==0) goto noEor;
2018-09-05 17:54:36 +00:00
// beq noEor ; if $00 is left after the shift, then it was $80
if (C==1) goto doEor;
2018-09-05 17:54:36 +00:00
// bcs doEor ; else, do the EOR based on the carry bit as usual
noEor:
ram[SEED+1]=A; // sta seed+1
2018-09-05 17:54:36 +00:00
return; // rts
}
static void add16(unsigned char *a1h, unsigned char *a1l,
unsigned char a2h,unsigned char a2l) {
short i,j;
i=(*a1h<<8)|(*a1l);
j=(a2h<<8)|(a2l);
i+=j;
*a1h=i>>8;
*a1l=i&0xff;
return;
}
static void sadd16(signed char *a1h, unsigned char *a1l,
unsigned char a2h,unsigned char a2l) {
short i,j;
i=(*a1h<<8)|(*a1l);
j=(a2h<<8)|(a2l);
i+=j;
*a1h=i>>8;
*a1l=i&0xff;
return;
}
2018-09-05 02:34:52 +00:00
void routine_370(void) {
2018-09-05 17:54:36 +00:00
hplot(xpos+o,ypos_h+o); // NE
hplot(xpos-o,ypos_h-o); // SW
2018-09-05 02:34:52 +00:00
2018-09-05 17:54:36 +00:00
hplot(xpos+o,ypos_h-o); // SE
hplot(xpos-o,ypos_h+o); // NW
2018-09-05 02:34:52 +00:00
2018-09-05 17:54:36 +00:00
hplot(xpos,ypos_h+(o*1.5)); // N
hplot(xpos+(o*1.5),ypos_h); // E
2018-09-05 02:34:52 +00:00
2018-09-05 17:54:36 +00:00
hplot(xpos,ypos_h-(o*1.5)); // S
hplot(xpos-(o*1.5),ypos_h); // W
2018-09-05 02:34:52 +00:00
}
int main(int argc, char **argv) {
int ch;
grsim_init();
2018-09-05 17:54:36 +00:00
for(i=0;i<100;i++) {
random_6502();
printf("%02x%02x\n",ram[SEED+1],ram[SEED]);
}
2018-09-05 02:34:52 +00:00
home();
hgr();
soft_switch(MIXCLR); // Full screen
2018-09-05 19:04:31 +00:00
2018-09-05 02:34:52 +00:00
label_180:
2018-09-05 17:54:36 +00:00
random_6502();
color_group=ram[SEED]&1; // HGR color group (PG or BO)
random_6502();
x_velocity=(ram[SEED]&0x3)+1; // x velocity = 1..4
random_6502();
y_velocity_h=-((ram[SEED]&0x3)+3); // y velocity = -3..-6
y_velocity_l=0;
random_6502();
max_steps=(ram[SEED]&0x1f)+33; // 33..64
/* launch from the two hills */
random_6502();
2018-09-05 19:04:31 +00:00
xpos_l=ram[SEED]&0x3f;
2018-09-05 17:54:36 +00:00
random_6502();
if (ram[SEED]&1) {
2018-09-05 19:04:31 +00:00
xpos_l+=24; // 24-88 (64)
2018-09-05 17:54:36 +00:00
}
else {
2018-09-05 19:04:31 +00:00
xpos_l+=191; // 191-255 (64)
2018-09-05 17:54:36 +00:00
}
2018-09-05 02:34:52 +00:00
2018-09-05 17:54:36 +00:00
ypos_h=ysize; // start at ground
ypos_l=0;
2018-09-05 02:34:52 +00:00
2018-09-05 17:54:36 +00:00
peak=ypos_h; // peak starts at ground?
2018-09-05 02:34:52 +00:00
/* Aim towards center of screen */
2018-09-05 17:54:36 +00:00
/* TODO: merge this with hill location? */
2018-09-05 19:04:31 +00:00
if (xpos_l>xsize/2) {
2018-09-05 17:54:36 +00:00
x_velocity=-x_velocity;
}
2018-09-05 02:34:52 +00:00
/* Draw rocket */
for(cs=1;cs<=max_steps;cs++) {
y_even_older=y_old;
2018-09-05 17:54:36 +00:00
y_old=ypos_h;
2018-09-05 02:34:52 +00:00
x_even_older=x_old;
2018-09-05 19:04:31 +00:00
x_old=xpos_l;
2018-09-05 02:34:52 +00:00
/* Move rocket */
2018-09-05 19:04:31 +00:00
xpos_l=xpos_l+x_velocity;
2018-09-05 17:54:36 +00:00
/* 16 bit add */
add16(&ypos_h,&ypos_l,y_velocity_h,y_velocity_l);
2018-09-05 02:34:52 +00:00
/* adjust Y velocity, slow it down */
2018-09-05 17:54:36 +00:00
// c=0;
// a=y_velocity_l;
// adc(0x20); // 0x20 = 0.125
// y_velocity_l=a;
// a=y_velocity_h;
// adc(0);
// y_velocity_h=a;
sadd16(&y_velocity_h,&y_velocity_l,0x00,0x20);
2018-09-05 02:34:52 +00:00
/* if we went higher, adjust peak */
2018-09-05 17:54:36 +00:00
if (ypos_h<peak) peak=ypos_h;
2018-09-05 02:34:52 +00:00
/* check if out of bounds and stop moving */
2018-09-05 19:04:31 +00:00
if (xpos_l<=margin) {
2018-09-05 02:34:52 +00:00
cs=max_steps; // too far left
}
2018-09-05 19:04:31 +00:00
if (xpos_l>=(xsize-margin)) {
2018-09-05 02:34:52 +00:00
cs=max_steps; // too far right
}
2018-09-05 17:54:36 +00:00
if (ypos_h<=margin) {
2018-09-05 02:34:52 +00:00
cs=max_steps; // too far up
}
// if falling downward
2018-09-05 17:54:36 +00:00
if (y_velocity_h>0) {
2018-09-05 02:34:52 +00:00
// if too close to ground, explode
2018-09-05 17:54:36 +00:00
if (ypos_h>=ysize-margin) {
2018-09-05 02:34:52 +00:00
cs=max_steps;
}
// if fallen a bit past peak, explode
2018-09-05 17:54:36 +00:00
if (ypos_h>ysize-(ysize-peak)/2) {
2018-09-05 02:34:52 +00:00
cs=max_steps;
}
}
// if not done, draw rocket
if (cs<max_steps) {
hcolor_equals(color_group*4+3);
hplot(x_old,y_old);
2018-09-05 19:04:31 +00:00
hplot_to(xpos_l,ypos_h);
2018-09-05 02:34:52 +00:00
}
// erase with proper color black
hcolor_equals(color_group*4);
hplot(x_even_older,y_even_older);
hplot_to(x_old,y_old);
grsim_update();
ch=grsim_input();
if (ch=='q') exit(0);
2018-09-05 17:54:36 +00:00
usleep(50000);
2018-09-05 02:34:52 +00:00
}
label_290:
/* Draw explosion near x_old, y_old */
2018-09-05 19:04:31 +00:00
xpos=x_old;
2018-09-05 04:37:58 +00:00
xpos+=(random()%20)-10; // x +/- 10
2018-09-05 19:04:31 +00:00
ypos_h=y_old;
2018-09-05 17:54:36 +00:00
ypos_h+=(random()%20)-10; // y +/- 10
2018-09-05 04:32:53 +00:00
2018-09-05 02:34:52 +00:00
hcolor_equals(color_group*4+3); // draw white (with fringes)
2018-09-05 17:54:36 +00:00
hplot(xpos,ypos_h); // draw at center of explosion
2018-09-05 02:34:52 +00:00
/* Spread the explosion */
for(i=1;i<=9;i++) {
/* Draw spreading dots in white */
if (i<9) {
2018-09-05 17:54:36 +00:00
o=i;
2018-09-05 02:34:52 +00:00
hcolor_equals(color_group*4+3);
routine_370();
}
/* erase old */
2018-09-05 17:54:36 +00:00
o=i-1;
2018-09-05 02:34:52 +00:00
hcolor_equals(color_group*4);
routine_370();
grsim_update();
ch=grsim_input();
if (ch=='q') break;
2018-09-05 17:54:36 +00:00
usleep(50000);
2018-09-05 02:34:52 +00:00
}
/* randomly draw more explosions */
2018-09-05 19:04:31 +00:00
random_6502();
if (ram[SEED]&1) goto label_290;
2018-09-05 02:34:52 +00:00
2018-09-05 19:04:31 +00:00
hcolor_equals(3);
for(i=0;i<NUMSTARS;i++) {
hplot(stars[i].x,stars[i].y);
}
2018-09-05 02:34:52 +00:00
2018-09-05 19:04:31 +00:00
goto label_180;
2018-09-05 02:34:52 +00:00
return 0;
}