mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2024-06-10 21:29:33 +00:00
updated apple2 keys, presets
This commit is contained in:
parent
56aab0e6a5
commit
f7129e9fde
3
.gitmodules
vendored
3
.gitmodules
vendored
|
@ -1,9 +1,6 @@
|
||||||
[submodule "javatari.js"]
|
[submodule "javatari.js"]
|
||||||
path = javatari.js
|
path = javatari.js
|
||||||
url = https://github.com/sehugg/javatari.js
|
url = https://github.com/sehugg/javatari.js
|
||||||
[submodule "dasm"]
|
|
||||||
path = dasm
|
|
||||||
url = https://github.com/sehugg/dasm
|
|
||||||
[submodule "codemirror"]
|
[submodule "codemirror"]
|
||||||
path = codemirror
|
path = codemirror
|
||||||
url = https://github.com/codemirror/CodeMirror
|
url = https://github.com/codemirror/CodeMirror
|
||||||
|
|
|
@ -28,7 +28,7 @@ TODO:
|
||||||
- kbd shortcuts
|
- kbd shortcuts
|
||||||
- PC x86 support
|
- PC x86 support
|
||||||
- show errors in list (maybe window list?)
|
- show errors in list (maybe window list?)
|
||||||
- can't see 1st line in editor sometimes
|
- can't see 1st line in editor sometimes (when scrolling cursor past bottom of screen)
|
||||||
- online help
|
- online help
|
||||||
- show self-modifying code insns left of editor
|
- show self-modifying code insns left of editor
|
||||||
- facade/kbd shortcuts for emulators, focus
|
- facade/kbd shortcuts for emulators, focus
|
||||||
|
|
|
@ -3,24 +3,29 @@
|
||||||
#include <conio.h>
|
#include <conio.h>
|
||||||
#include <apple2.h>
|
#include <apple2.h>
|
||||||
|
|
||||||
|
// type aliases for byte/signed byte/unsigned 16-bit
|
||||||
typedef unsigned char byte;
|
typedef unsigned char byte;
|
||||||
typedef signed char sbyte;
|
typedef signed char sbyte;
|
||||||
typedef unsigned short word;
|
typedef unsigned short word;
|
||||||
|
|
||||||
|
// peeks, pokes, and strobes
|
||||||
#define POKE(addr,val) (*(unsigned char*) (addr) = (val))
|
#define POKE(addr,val) (*(unsigned char*) (addr) = (val))
|
||||||
#define POKEW(addr,val) (*(unsigned*) (addr) = (val))
|
#define POKEW(addr,val) (*(unsigned*) (addr) = (val))
|
||||||
#define PEEK(addr) (*(unsigned char*) (addr))
|
#define PEEK(addr) (*(unsigned char*) (addr))
|
||||||
#define PEEKW(addr) (*(unsigned*) (addr))
|
#define PEEKW(addr) (*(unsigned*) (addr))
|
||||||
#define STROBE(addr) __asm__ ("sta %w", addr)
|
#define STROBE(addr) __asm__ ("sta %w", addr)
|
||||||
|
// speaker click
|
||||||
#define CLICK STROBE(0xc030)
|
#define CLICK STROBE(0xc030)
|
||||||
|
|
||||||
/// HIRES LOOKUP TABLE
|
/// HIRES LOOKUP TABLE
|
||||||
|
|
||||||
#define VHEIGHT 192
|
#define VHEIGHT 192 // number of scanlines
|
||||||
#define VBWIDTH 40
|
#define VBWIDTH 40 // number of bytes per scanline
|
||||||
|
#define PIXWIDTH 280 // 7 pixels per byte
|
||||||
|
|
||||||
#define LUT(x) (byte*)(0x2000|x)
|
#define LUT(x) (byte*)(0x2000|x)
|
||||||
|
|
||||||
|
// starting address of each scanline
|
||||||
static byte* const vidmem[VHEIGHT] = {
|
static byte* const vidmem[VHEIGHT] = {
|
||||||
LUT(0x0000), LUT(0x0400), LUT(0x0800), LUT(0x0c00), LUT(0x1000), LUT(0x1400), LUT(0x1800), LUT(0x1c00),
|
LUT(0x0000), LUT(0x0400), LUT(0x0800), LUT(0x0c00), LUT(0x1000), LUT(0x1400), LUT(0x1800), LUT(0x1c00),
|
||||||
LUT(0x0080), LUT(0x0480), LUT(0x0880), LUT(0x0c80), LUT(0x1080), LUT(0x1480), LUT(0x1880), LUT(0x1c80),
|
LUT(0x0080), LUT(0x0480), LUT(0x0880), LUT(0x0c80), LUT(0x1080), LUT(0x1480), LUT(0x1880), LUT(0x1c80),
|
||||||
|
@ -48,20 +53,7 @@ static byte* const vidmem[VHEIGHT] = {
|
||||||
LUT(0x03d0), LUT(0x07d0), LUT(0x0bd0), LUT(0x0fd0), LUT(0x13d0), LUT(0x17d0), LUT(0x1bd0), LUT(0x1fd0)
|
LUT(0x03d0), LUT(0x07d0), LUT(0x0bd0), LUT(0x0fd0), LUT(0x13d0), LUT(0x17d0), LUT(0x1bd0), LUT(0x1fd0)
|
||||||
};
|
};
|
||||||
|
|
||||||
const byte DIV7_140[140] = {
|
// divide-by 7 table
|
||||||
0, 0, 0, 0, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 8, 8, 8, 8,
|
|
||||||
9, 9, 9,10,10,10,10,11,11,11,12,12,12,12,13,13,13,14,14,14,14,15,15,15,16,16,16,16,17,17,17,18,
|
|
||||||
18,18,18,19,19,19,20,20,20,20,21,21,21,22,22,22,22,23,23,23,24,24,24,24,25,25,25,26,26,26,26,27,
|
|
||||||
27,27,28,28,28,28,29,29,29,30,30,30,30,31,31,31,32,32,32,32,33,33,33,34,34,34,34,35,35,35,36,36,
|
|
||||||
36,36,37,37,37,38,38,38,38,39,39,39};
|
|
||||||
|
|
||||||
const byte MOD7_140[140] = {
|
|
||||||
0, 2, 4, 6, 1, 3, 5, 0, 2, 4, 6, 1, 3, 5, 0, 2, 4, 6, 1, 3, 5, 0, 2, 4, 6, 1, 3, 5, 0, 2, 4, 6,
|
|
||||||
1, 3, 5, 0, 2, 4, 6, 1, 3, 5, 0, 2, 4, 6, 1, 3, 5, 0, 2, 4, 6, 1, 3, 5, 0, 2, 4, 6, 1, 3, 5, 0,
|
|
||||||
2, 4, 6, 1, 3, 5, 0, 2, 4, 6, 1, 3, 5, 0, 2, 4, 6, 1, 3, 5, 0, 2, 4, 6, 1, 3, 5, 0, 2, 4, 6, 1,
|
|
||||||
3, 5, 0, 2, 4, 6, 1, 3, 5, 0, 2, 4, 6, 1, 3, 5, 0, 2, 4, 6, 1, 3, 5, 0, 2, 4, 6, 1, 3, 5, 0, 2,
|
|
||||||
4, 6, 1, 3, 5, 0, 2, 4, 6, 1, 3, 5};
|
|
||||||
|
|
||||||
const byte DIV7[256] = {
|
const byte DIV7[256] = {
|
||||||
0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4,
|
0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4,
|
||||||
4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 9,
|
4, 4, 4, 5, 5, 5, 5, 5, 5, 5, 6, 6, 6, 6, 6, 6, 6, 7, 7, 7, 7, 7, 7, 7, 8, 8, 8, 8, 8, 8, 8, 9,
|
||||||
|
@ -72,6 +64,7 @@ const byte DIV7[256] = {
|
||||||
27,27,27,27,28,28,28,28,28,28,28,29,29,29,29,29,29,29,30,30,30,30,30,30,30,31,31,31,31,31,31,31,
|
27,27,27,27,28,28,28,28,28,28,28,29,29,29,29,29,29,29,30,30,30,30,30,30,30,31,31,31,31,31,31,31,
|
||||||
32,32,32,32,32,32,32,33,33,33,33,33,33,33,34,34,34,34,34,34,34,35,35,35,35,35,35,35,36,36,36,36};
|
32,32,32,32,32,32,32,33,33,33,33,33,33,33,34,34,34,34,34,34,34,35,35,35,35,35,35,35,36,36,36,36};
|
||||||
|
|
||||||
|
// modulo-by-7 table
|
||||||
const byte MOD7[256] = {
|
const byte MOD7[256] = {
|
||||||
0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3,
|
0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3,
|
||||||
4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0,
|
4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0,
|
||||||
|
@ -82,18 +75,19 @@ const byte MOD7[256] = {
|
||||||
3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6,
|
3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6,
|
||||||
0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3};
|
0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3, 4, 5, 6, 0, 1, 2, 3};
|
||||||
|
|
||||||
|
// bitmask table
|
||||||
const byte BIT7[7] = { 1, 2, 4, 8, 16, 32, 64 };
|
const byte BIT7[7] = { 1, 2, 4, 8, 16, 32, 64 };
|
||||||
|
|
||||||
#pragma static-locals(on)
|
#pragma static-locals(on)
|
||||||
|
|
||||||
/// SOUND FUNCTIONS
|
/// SOUND FUNCTIONS
|
||||||
|
|
||||||
void tone(byte freq, byte dur, sbyte mod) {
|
void tone(byte period, byte dur, sbyte mod) {
|
||||||
word i;
|
word i;
|
||||||
while (dur--) {
|
while (dur--) {
|
||||||
for (i=0; i<freq; i++) ;
|
for (i=0; i<period; i++) ;
|
||||||
CLICK;
|
CLICK;
|
||||||
freq += mod;
|
period += mod;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,57 +101,49 @@ void clrscr() {
|
||||||
memset((byte*)0x2000, 0, 0x2000); // clear page 1
|
memset((byte*)0x2000, 0, 0x2000); // clear page 1
|
||||||
}
|
}
|
||||||
|
|
||||||
void xor_pixel(byte x, byte y) {
|
void xor_vline(byte x, byte y1, byte y2) {
|
||||||
byte xb = DIV7[x];
|
byte xb = DIV7[x]; // divide x by 7
|
||||||
byte mask = BIT7[MOD7[x]];
|
byte mask = BIT7[MOD7[x]]; // lookup bitmask for remainder
|
||||||
byte* dest = &vidmem[y][xb];
|
|
||||||
*dest ^= mask;
|
|
||||||
}
|
|
||||||
|
|
||||||
void draw_vline(byte x, byte y1, byte y2) {
|
|
||||||
byte xb = DIV7[x];
|
|
||||||
byte mask = BIT7[MOD7[x]];
|
|
||||||
byte y;
|
byte y;
|
||||||
for (y=y1; y<y2; y++) {
|
for (y=y1; y<=y2; y++) {
|
||||||
byte* dest = &vidmem[y][xb];
|
byte* dest = &vidmem[y][xb]; // lookup dest. address
|
||||||
*dest ^= mask;
|
*dest ^= mask; // XOR mask with destination
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define LOCHAR 0x20
|
void xor_pixel(byte x, byte y) {
|
||||||
#define HICHAR 0x7f
|
xor_vline(x, y, y); // draw line with 1-pixel height
|
||||||
|
}
|
||||||
const byte font8x8[HICHAR-LOCHAR+1][8] = {/*{w:8,h:8,bpp:1,count:96}*/
|
|
||||||
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, { 0x18,0x18,0x18,0x18,0x00,0x00,0x18,0x00 }, { 0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x00 }, { 0x66,0x66,0xff,0x66,0xff,0x66,0x66,0x00 }, { 0x18,0x7c,0x06,0x3c,0x60,0x3e,0x18,0x00 }, { 0x46,0x66,0x30,0x18,0x0c,0x66,0x62,0x00 }, { 0x3c,0x66,0x3c,0x1c,0xe6,0x66,0xfc,0x00 }, { 0x60,0x30,0x18,0x00,0x00,0x00,0x00,0x00 }, { 0x30,0x18,0x0c,0x0c,0x0c,0x18,0x30,0x00 }, { 0x0c,0x18,0x30,0x30,0x30,0x18,0x0c,0x00 }, { 0x00,0x66,0x3c,0xff,0x3c,0x66,0x00,0x00 }, { 0x00,0x18,0x18,0x7e,0x18,0x18,0x00,0x00 }, { 0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x0c }, { 0x00,0x00,0x00,0x7e,0x00,0x00,0x00,0x00 }, { 0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00 }, { 0x00,0xc0,0x60,0x30,0x18,0x0c,0x06,0x00 }, { 0x3c,0x66,0x76,0x6e,0x66,0x66,0x3c,0x00 }, { 0x18,0x18,0x1c,0x18,0x18,0x18,0x7e,0x00 }, { 0x3c,0x66,0x60,0x30,0x0c,0x06,0x7e,0x00 }, { 0x3c,0x66,0x60,0x38,0x60,0x66,0x3c,0x00 }, { 0x60,0x70,0x78,0x66,0xfe,0x60,0x60,0x00 }, { 0x7e,0x06,0x3e,0x60,0x60,0x66,0x3c,0x00 }, { 0x3c,0x66,0x06,0x3e,0x66,0x66,0x3c,0x00 }, { 0x7e,0x66,0x30,0x18,0x18,0x18,0x18,0x00 }, { 0x3c,0x66,0x66,0x3c,0x66,0x66,0x3c,0x00 }, { 0x3c,0x66,0x66,0x7c,0x60,0x66,0x3c,0x00 }, { 0x00,0x00,0x18,0x00,0x00,0x18,0x00,0x00 }, { 0x00,0x00,0x18,0x00,0x00,0x18,0x18,0x0c }, { 0x70,0x18,0x0c,0x06,0x0c,0x18,0x70,0x00 }, { 0x00,0x00,0x7e,0x00,0x7e,0x00,0x00,0x00 }, { 0x0e,0x18,0x30,0x60,0x30,0x18,0x0e,0x00 }, { 0x3c,0x66,0x60,0x30,0x18,0x00,0x18,0x00 }, { 0x3c,0x66,0x76,0x76,0x06,0x46,0x3c,0x00 }, { 0x18,0x3c,0x66,0x7e,0x66,0x66,0x66,0x00 }, { 0x3e,0x66,0x66,0x3e,0x66,0x66,0x3e,0x00 }, { 0x3c,0x66,0x06,0x06,0x06,0x66,0x3c,0x00 }, { 0x1e,0x36,0x66,0x66,0x66,0x36,0x1e,0x00 }, { 0x7e,0x06,0x06,0x1e,0x06,0x06,0x7e,0x00 }, { 0x7e,0x06,0x06,0x1e,0x06,0x06,0x06,0x00 }, { 0x3c,0x66,0x06,0x76,0x66,0x66,0x3c,0x00 }, { 0x66,0x66,0x66,0x7e,0x66,0x66,0x66,0x00 }, { 0x3c,0x18,0x18,0x18,0x18,0x18,0x3c,0x00 }, { 0x78,0x30,0x30,0x30,0x30,0x36,0x1c,0x00 }, { 0x66,0x36,0x1e,0x0e,0x1e,0x36,0x66,0x00 }, { 0x06,0x06,0x06,0x06,0x06,0x06,0x7e,0x00 }, { 0xc6,0xee,0xfe,0xd6,0xc6,0xc6,0xc6,0x00 }, { 0x66,0x6e,0x7e,0x7e,0x76,0x66,0x66,0x00 }, { 0x3c,0x66,0x66,0x66,0x66,0x66,0x3c,0x00 }, { 0x3e,0x66,0x66,0x3e,0x06,0x06,0x06,0x00 }, { 0x3c,0x66,0x66,0x66,0x66,0x3c,0x70,0x00 }, { 0x3e,0x66,0x66,0x3e,0x1e,0x36,0x66,0x00 }, { 0x3c,0x66,0x06,0x3c,0x60,0x66,0x3c,0x00 }, { 0x7e,0x18,0x18,0x18,0x18,0x18,0x18,0x00 }, { 0x66,0x66,0x66,0x66,0x66,0x66,0x3c,0x00 }, { 0x66,0x66,0x66,0x66,0x66,0x3c,0x18,0x00 }, { 0xc6,0xc6,0xc6,0xd6,0xfe,0xee,0xc6,0x00 }, { 0x66,0x66,0x3c,0x18,0x3c,0x66,0x66,0x00 }, { 0x66,0x66,0x66,0x3c,0x18,0x18,0x18,0x00 }, { 0x7e,0x60,0x30,0x18,0x0c,0x06,0x7e,0x00 }, { 0x3c,0x0c,0x0c,0x0c,0x0c,0x0c,0x3c,0x00 }, { 0x00,0x06,0x0c,0x18,0x30,0x60,0xc0,0x00 }, { 0x3c,0x30,0x30,0x30,0x30,0x30,0x3c,0x00 }, { 0x00,0x18,0x3c,0x7e,0x18,0x18,0x18,0x18 }, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff }, { 0x06,0x0c,0x18,0x00,0x00,0x00,0x00,0x00 }, { 0x00,0x00,0x3c,0x60,0x7c,0x66,0x7c,0x00 }, { 0x00,0x06,0x06,0x3e,0x66,0x66,0x3e,0x00 }, { 0x00,0x00,0x3c,0x06,0x06,0x06,0x3c,0x00 }, { 0x00,0x60,0x60,0x7c,0x66,0x66,0x7c,0x00 }, { 0x00,0x00,0x3c,0x66,0x7e,0x06,0x3c,0x00 }, { 0x00,0x70,0x18,0x7c,0x18,0x18,0x18,0x00 }, { 0x00,0x00,0x7c,0x66,0x66,0x7c,0x60,0x3e }, { 0x00,0x06,0x06,0x3e,0x66,0x66,0x66,0x00 }, { 0x00,0x18,0x00,0x1c,0x18,0x18,0x3c,0x00 }, { 0x00,0x60,0x00,0x60,0x60,0x60,0x60,0x3c }, { 0x00,0x06,0x06,0x36,0x1e,0x36,0x66,0x00 }, { 0x00,0x1c,0x18,0x18,0x18,0x18,0x3c,0x00 }, { 0x00,0x00,0x66,0xfe,0xfe,0xd6,0xc6,0x00 }, { 0x00,0x00,0x3e,0x66,0x66,0x66,0x66,0x00 }, { 0x00,0x00,0x3c,0x66,0x66,0x66,0x3c,0x00 }, { 0x00,0x00,0x3e,0x66,0x66,0x3e,0x06,0x06 }, { 0x00,0x00,0x7c,0x66,0x66,0x7c,0x60,0x60 }, { 0x00,0x00,0x3e,0x66,0x06,0x06,0x06,0x00 }, { 0x00,0x00,0x7c,0x06,0x3c,0x60,0x3e,0x00 }, { 0x00,0x18,0x7e,0x18,0x18,0x18,0x70,0x00 }, { 0x00,0x00,0x66,0x66,0x66,0x66,0x7c,0x00 }, { 0x00,0x00,0x66,0x66,0x66,0x3c,0x18,0x00 }, { 0x00,0x00,0xc6,0xd6,0xfe,0x7c,0x6c,0x00 }, { 0x00,0x00,0x66,0x3c,0x18,0x3c,0x66,0x00 }, { 0x00,0x00,0x66,0x66,0x66,0x7c,0x30,0x1e }, { 0x00,0x00,0x7e,0x30,0x18,0x0c,0x7e,0x00 }, { 0x38,0x0c,0x0c,0x06,0x0c,0x0c,0x38,0x00 }, { 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18 }, { 0x1c,0x30,0x30,0x60,0x30,0x30,0x1c,0x00 }, { 0x00,0x4c,0x32,0x00,0x00,0x00,0x00,0x00 }, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
OP_DRAW, OP_XOR, OP_ERASE
|
OP_DRAW, OP_XOR, OP_ERASE
|
||||||
};
|
} GraphicsOperation;
|
||||||
|
|
||||||
byte render_sprite(const byte* src, byte x, byte y, byte op) {
|
byte render_sprite(const byte* src, byte x, byte y, byte op) {
|
||||||
byte i,j;
|
byte i,j;
|
||||||
byte w = *src++;
|
byte w = *src++; // get width from 1st byte of sprite
|
||||||
byte h = *src++;
|
byte h = *src++; // get height from 2nd byte of sprite
|
||||||
byte xb = DIV7[x];
|
byte xb = DIV7[x]; // xb = x DIV 7
|
||||||
byte xs = MOD7[x];
|
byte xs = MOD7[x]; // xs = x MOD 7
|
||||||
byte result = 0;
|
byte result = 0; // result (used only with XOR)
|
||||||
for (j=0; j<h; j++) {
|
for (j=0; j<h; j++) {
|
||||||
byte* dest = &vidmem[y++][xb];
|
byte* dest = &vidmem[y++][xb]; // lookup video address
|
||||||
byte rest = 0;
|
byte rest = 0; // rest = leftover bits
|
||||||
for (i=0; i<w; i++) {
|
for (i=0; i<w; i++) {
|
||||||
byte data = *src++;
|
byte data = *src++; // get next sprite byte
|
||||||
byte next = (data << xs) | rest;
|
byte next = (data << xs) | rest; // shift and OR with leftover
|
||||||
|
// compute graphics operation, write to dest
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case OP_DRAW: *dest++ = next; break;
|
case OP_DRAW: *dest++ = next; break;
|
||||||
case OP_XOR: result |= (*dest++ ^= next); break;
|
case OP_XOR: result |= (*dest++ ^= next); break;
|
||||||
case OP_ERASE: *dest++ &= ~next; break;
|
case OP_ERASE: *dest++ &= ~next; break;
|
||||||
}
|
}
|
||||||
rest = data >> (7-xs);
|
rest = data >> (7-xs); // save leftover bits
|
||||||
}
|
}
|
||||||
|
// compute final byte operation
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case OP_DRAW: *dest = rest; break;
|
case OP_DRAW: *dest = rest; break;
|
||||||
case OP_XOR: result |= (*dest ^= rest); break;
|
case OP_XOR: result |= (*dest ^= rest); break;
|
||||||
case OP_ERASE: *dest &= ~rest; break;
|
case OP_ERASE: *dest &= ~rest; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -168,6 +154,7 @@ void draw_sprite(const byte* src, byte x, byte y) {
|
||||||
render_sprite(src, x, y, OP_DRAW);
|
render_sprite(src, x, y, OP_DRAW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XOR returns non-zero if any pixels were overlapped
|
||||||
byte xor_sprite(const byte* src, byte x, byte y) {
|
byte xor_sprite(const byte* src, byte x, byte y) {
|
||||||
return render_sprite(src, x, y, OP_XOR);
|
return render_sprite(src, x, y, OP_XOR);
|
||||||
}
|
}
|
||||||
|
@ -176,6 +163,7 @@ void erase_sprite(const byte* src, byte x, byte y) {
|
||||||
render_sprite(src, x, y, OP_ERASE);
|
render_sprite(src, x, y, OP_ERASE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// clear just sets all bytes to 0, and is fast
|
||||||
void clear_sprite(const byte* src, byte x, byte y) {
|
void clear_sprite(const byte* src, byte x, byte y) {
|
||||||
byte i,j;
|
byte i,j;
|
||||||
byte w = *src++;
|
byte w = *src++;
|
||||||
|
@ -189,36 +177,49 @@ void clear_sprite(const byte* src, byte x, byte y) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_char(char ch, byte x, byte y) {
|
// FONT FUNCTIONS
|
||||||
|
|
||||||
|
#define LOCHAR 0x20 // lowest character value in font
|
||||||
|
#define HICHAR 0x7f // highest character value in font
|
||||||
|
|
||||||
|
const byte font8x8[HICHAR-LOCHAR+1][8] = {/*{w:8,h:8,bpp:1,count:96}*/
|
||||||
|
{ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, { 0x18,0x18,0x18,0x18,0x00,0x00,0x18,0x00 }, { 0x66,0x66,0x66,0x00,0x00,0x00,0x00,0x00 }, { 0x66,0x66,0xff,0x66,0xff,0x66,0x66,0x00 }, { 0x18,0x7c,0x06,0x3c,0x60,0x3e,0x18,0x00 }, { 0x46,0x66,0x30,0x18,0x0c,0x66,0x62,0x00 }, { 0x3c,0x66,0x3c,0x1c,0xe6,0x66,0xfc,0x00 }, { 0x60,0x30,0x18,0x00,0x00,0x00,0x00,0x00 }, { 0x30,0x18,0x0c,0x0c,0x0c,0x18,0x30,0x00 }, { 0x0c,0x18,0x30,0x30,0x30,0x18,0x0c,0x00 }, { 0x00,0x66,0x3c,0xff,0x3c,0x66,0x00,0x00 }, { 0x00,0x18,0x18,0x7e,0x18,0x18,0x00,0x00 }, { 0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x0c }, { 0x00,0x00,0x00,0x7e,0x00,0x00,0x00,0x00 }, { 0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00 }, { 0x00,0xc0,0x60,0x30,0x18,0x0c,0x06,0x00 }, { 0x3c,0x66,0x76,0x6e,0x66,0x66,0x3c,0x00 }, { 0x18,0x18,0x1c,0x18,0x18,0x18,0x7e,0x00 }, { 0x3c,0x66,0x60,0x30,0x0c,0x06,0x7e,0x00 }, { 0x3c,0x66,0x60,0x38,0x60,0x66,0x3c,0x00 }, { 0x60,0x70,0x78,0x66,0xfe,0x60,0x60,0x00 }, { 0x7e,0x06,0x3e,0x60,0x60,0x66,0x3c,0x00 }, { 0x3c,0x66,0x06,0x3e,0x66,0x66,0x3c,0x00 }, { 0x7e,0x66,0x30,0x18,0x18,0x18,0x18,0x00 }, { 0x3c,0x66,0x66,0x3c,0x66,0x66,0x3c,0x00 }, { 0x3c,0x66,0x66,0x7c,0x60,0x66,0x3c,0x00 }, { 0x00,0x00,0x18,0x00,0x00,0x18,0x00,0x00 }, { 0x00,0x00,0x18,0x00,0x00,0x18,0x18,0x0c }, { 0x70,0x18,0x0c,0x06,0x0c,0x18,0x70,0x00 }, { 0x00,0x00,0x7e,0x00,0x7e,0x00,0x00,0x00 }, { 0x0e,0x18,0x30,0x60,0x30,0x18,0x0e,0x00 }, { 0x3c,0x66,0x60,0x30,0x18,0x00,0x18,0x00 }, { 0x3c,0x66,0x76,0x76,0x06,0x46,0x3c,0x00 }, { 0x18,0x3c,0x66,0x7e,0x66,0x66,0x66,0x00 }, { 0x3e,0x66,0x66,0x3e,0x66,0x66,0x3e,0x00 }, { 0x3c,0x66,0x06,0x06,0x06,0x66,0x3c,0x00 }, { 0x1e,0x36,0x66,0x66,0x66,0x36,0x1e,0x00 }, { 0x7e,0x06,0x06,0x1e,0x06,0x06,0x7e,0x00 }, { 0x7e,0x06,0x06,0x1e,0x06,0x06,0x06,0x00 }, { 0x3c,0x66,0x06,0x76,0x66,0x66,0x3c,0x00 }, { 0x66,0x66,0x66,0x7e,0x66,0x66,0x66,0x00 }, { 0x3c,0x18,0x18,0x18,0x18,0x18,0x3c,0x00 }, { 0x78,0x30,0x30,0x30,0x30,0x36,0x1c,0x00 }, { 0x66,0x36,0x1e,0x0e,0x1e,0x36,0x66,0x00 }, { 0x06,0x06,0x06,0x06,0x06,0x06,0x7e,0x00 }, { 0xc6,0xee,0xfe,0xd6,0xc6,0xc6,0xc6,0x00 }, { 0x66,0x6e,0x7e,0x7e,0x76,0x66,0x66,0x00 }, { 0x3c,0x66,0x66,0x66,0x66,0x66,0x3c,0x00 }, { 0x3e,0x66,0x66,0x3e,0x06,0x06,0x06,0x00 }, { 0x3c,0x66,0x66,0x66,0x66,0x3c,0x70,0x00 }, { 0x3e,0x66,0x66,0x3e,0x1e,0x36,0x66,0x00 }, { 0x3c,0x66,0x06,0x3c,0x60,0x66,0x3c,0x00 }, { 0x7e,0x18,0x18,0x18,0x18,0x18,0x18,0x00 }, { 0x66,0x66,0x66,0x66,0x66,0x66,0x3c,0x00 }, { 0x66,0x66,0x66,0x66,0x66,0x3c,0x18,0x00 }, { 0xc6,0xc6,0xc6,0xd6,0xfe,0xee,0xc6,0x00 }, { 0x66,0x66,0x3c,0x18,0x3c,0x66,0x66,0x00 }, { 0x66,0x66,0x66,0x3c,0x18,0x18,0x18,0x00 }, { 0x7e,0x60,0x30,0x18,0x0c,0x06,0x7e,0x00 }, { 0x3c,0x0c,0x0c,0x0c,0x0c,0x0c,0x3c,0x00 }, { 0x00,0x06,0x0c,0x18,0x30,0x60,0xc0,0x00 }, { 0x3c,0x30,0x30,0x30,0x30,0x30,0x3c,0x00 }, { 0x00,0x18,0x3c,0x7e,0x18,0x18,0x18,0x18 }, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff }, { 0x06,0x0c,0x18,0x00,0x00,0x00,0x00,0x00 }, { 0x00,0x00,0x3c,0x60,0x7c,0x66,0x7c,0x00 }, { 0x00,0x06,0x06,0x3e,0x66,0x66,0x3e,0x00 }, { 0x00,0x00,0x3c,0x06,0x06,0x06,0x3c,0x00 }, { 0x00,0x60,0x60,0x7c,0x66,0x66,0x7c,0x00 }, { 0x00,0x00,0x3c,0x66,0x7e,0x06,0x3c,0x00 }, { 0x00,0x70,0x18,0x7c,0x18,0x18,0x18,0x00 }, { 0x00,0x00,0x7c,0x66,0x66,0x7c,0x60,0x3e }, { 0x00,0x06,0x06,0x3e,0x66,0x66,0x66,0x00 }, { 0x00,0x18,0x00,0x1c,0x18,0x18,0x3c,0x00 }, { 0x00,0x60,0x00,0x60,0x60,0x60,0x60,0x3c }, { 0x00,0x06,0x06,0x36,0x1e,0x36,0x66,0x00 }, { 0x00,0x1c,0x18,0x18,0x18,0x18,0x3c,0x00 }, { 0x00,0x00,0x66,0xfe,0xfe,0xd6,0xc6,0x00 }, { 0x00,0x00,0x3e,0x66,0x66,0x66,0x66,0x00 }, { 0x00,0x00,0x3c,0x66,0x66,0x66,0x3c,0x00 }, { 0x00,0x00,0x3e,0x66,0x66,0x3e,0x06,0x06 }, { 0x00,0x00,0x7c,0x66,0x66,0x7c,0x60,0x60 }, { 0x00,0x00,0x3e,0x66,0x06,0x06,0x06,0x00 }, { 0x00,0x00,0x7c,0x06,0x3c,0x60,0x3e,0x00 }, { 0x00,0x18,0x7e,0x18,0x18,0x18,0x70,0x00 }, { 0x00,0x00,0x66,0x66,0x66,0x66,0x7c,0x00 }, { 0x00,0x00,0x66,0x66,0x66,0x3c,0x18,0x00 }, { 0x00,0x00,0xc6,0xd6,0xfe,0x7c,0x6c,0x00 }, { 0x00,0x00,0x66,0x3c,0x18,0x3c,0x66,0x00 }, { 0x00,0x00,0x66,0x66,0x66,0x7c,0x30,0x1e }, { 0x00,0x00,0x7e,0x30,0x18,0x0c,0x7e,0x00 }, { 0x38,0x0c,0x0c,0x06,0x0c,0x0c,0x38,0x00 }, { 0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18 }, { 0x1c,0x30,0x30,0x60,0x30,0x30,0x1c,0x00 }, { 0x00,0x4c,0x32,0x00,0x00,0x00,0x00,0x00 }, { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 },
|
||||||
|
};
|
||||||
|
|
||||||
|
// draw character from column 0..39, row 0..23
|
||||||
|
void draw_char(char ch, byte col, byte row) {
|
||||||
byte i;
|
byte i;
|
||||||
const byte* src = &font8x8[(ch-LOCHAR)][0];
|
const byte* src = &font8x8[(ch-LOCHAR)][0];
|
||||||
x *= 8;
|
byte y = row*8;
|
||||||
for (i=0; i<8; i++) {
|
for (i=0; i<8; i++) {
|
||||||
byte* dest = &vidmem[x++][y];
|
byte* dest = &vidmem[y++][col];
|
||||||
*dest = *src;
|
*dest = *src;
|
||||||
src += 1;
|
src += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_string(const char* str, byte x, byte y) {
|
// draw string starting at row/col (vert 1 = draw vertical)
|
||||||
|
void draw_string(const char* str, byte col, byte row, byte vert) {
|
||||||
do {
|
do {
|
||||||
byte ch = *str++;
|
byte ch = *str++;
|
||||||
if (!ch) break;
|
if (!ch) break;
|
||||||
draw_char(ch, x, y);
|
draw_char(ch, col, row);
|
||||||
x++;
|
if (vert) row++; else col++;
|
||||||
} while (1);
|
} while (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_bcd_word(word bcd, byte x, byte y) {
|
// draw 4-digit BCD word
|
||||||
|
void draw_bcd_word(word bcd, byte col, byte row, byte vert) {
|
||||||
byte j;
|
byte j;
|
||||||
x += 3;
|
if (vert) row+=3; else col+=3; // move to rightmost digit
|
||||||
for (j=0; j<4; j++) {
|
for (j=0; j<4; j++) {
|
||||||
draw_char('0'+(bcd&0xf), x, y);
|
draw_char('0'+(bcd&0xf), col, row);
|
||||||
x--;
|
if (vert) row--; else col--;
|
||||||
bcd >>= 4;
|
bcd >>= 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add two 4-digit BCD words
|
||||||
word bcd_add(word a, word b) {
|
word bcd_add(word a, word b) {
|
||||||
word result;
|
word result;
|
||||||
__asm__ ("sed"); // set decimal (BCD) mode
|
__asm__ ("sed"); // set decimal (BCD) mode
|
||||||
|
@ -258,9 +259,6 @@ const byte* const enemy_bitmaps[4] = {
|
||||||
//
|
//
|
||||||
|
|
||||||
byte attract;
|
byte attract;
|
||||||
byte credits;
|
|
||||||
byte curplayer;
|
|
||||||
|
|
||||||
word score;
|
word score;
|
||||||
byte lives;
|
byte lives;
|
||||||
|
|
||||||
|
@ -290,26 +288,51 @@ typedef struct {
|
||||||
|
|
||||||
MarchMode this_mode, next_mode;
|
MarchMode this_mode, next_mode;
|
||||||
|
|
||||||
void draw_lives(byte player) {
|
void draw_lives() {
|
||||||
byte i;
|
byte i;
|
||||||
byte n = lives;
|
byte n = lives;
|
||||||
byte x = player ? (22-MAXLIVES) : 6;
|
byte y = 18;
|
||||||
byte y = VBWIDTH-3;
|
byte x = VBWIDTH-1;
|
||||||
for (i=0; i<MAXLIVES; i++) {
|
for (i=0; i<MAXLIVES; i++) {
|
||||||
draw_char(i<n?'*':' ', x++, y);
|
draw_char(i<n?'*':' ', x, y++);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_score(byte player) {
|
void draw_score() {
|
||||||
byte x = player ? 24 : 0;
|
byte x = VBWIDTH-1;
|
||||||
byte y = VBWIDTH-3;
|
byte y = 10;
|
||||||
draw_bcd_word(score, x, y);
|
draw_bcd_word(score, x, y, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_bunker(byte x, byte y, byte y2, byte h, byte w) {
|
||||||
|
byte i,a,b;
|
||||||
|
for (i=0; i<h; i++) {
|
||||||
|
a = y-y2-i*2;
|
||||||
|
b = y-i;
|
||||||
|
xor_vline(x+i, a, b);
|
||||||
|
xor_vline(x+h*2+w-i-1, a, b);
|
||||||
|
}
|
||||||
|
for (i=0; i<w; i++) {
|
||||||
|
xor_vline(x+h+i, a, b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void draw_playfield() {
|
||||||
|
byte i;
|
||||||
|
clrscr();
|
||||||
|
draw_string("PLAYER 1", VBWIDTH-1, 0, 1);
|
||||||
|
draw_score();
|
||||||
|
draw_lives();
|
||||||
|
for (i=0; i<VBWIDTH-4; i++)
|
||||||
|
vidmem[191][i] = (i&1) ? 0x55 : 0x2a;
|
||||||
|
draw_bunker(20, 165, 15, 15, 20);
|
||||||
|
draw_bunker(160, 165, 15, 15, 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_score(word pts) {
|
void add_score(word pts) {
|
||||||
if (attract) return;
|
if (attract) return;
|
||||||
score = bcd_add(score, pts);
|
score = bcd_add(score, pts);
|
||||||
draw_score(curplayer);
|
draw_score();
|
||||||
}
|
}
|
||||||
|
|
||||||
void xor_player_derez() {
|
void xor_player_derez() {
|
||||||
|
@ -345,8 +368,8 @@ void init_enemies() {
|
||||||
e->x = x;
|
e->x = x;
|
||||||
e->y = y;
|
e->y = y;
|
||||||
e->shape = enemy_bitmaps[bm];
|
e->shape = enemy_bitmaps[bm];
|
||||||
x += 28;
|
x += 29;
|
||||||
if (x >= 28*7) {
|
if (x >= 200) {
|
||||||
x = 0;
|
x = 0;
|
||||||
y += 20;
|
y += 20;
|
||||||
bm++;
|
bm++;
|
||||||
|
@ -403,32 +426,6 @@ void update_next_enemy() {
|
||||||
enemy_index++;
|
enemy_index++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_bunker(byte x, byte y, byte y2, byte h, byte w) {
|
|
||||||
byte i,a,b;
|
|
||||||
for (i=0; i<h; i++) {
|
|
||||||
a = y-y2-i*2;
|
|
||||||
b = y-i;
|
|
||||||
draw_vline(x+i, a, b);
|
|
||||||
draw_vline(x+h*2+w-i-1, a, b);
|
|
||||||
}
|
|
||||||
for (i=0; i<w; i++) {
|
|
||||||
draw_vline(x+h+i, a, b);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void draw_playfield() {
|
|
||||||
byte i;
|
|
||||||
clrscr();
|
|
||||||
draw_string("PLAYER 1", 0, VBWIDTH-1);
|
|
||||||
draw_string("USE A/Z/SPACE", 11, VBWIDTH-1);
|
|
||||||
draw_score(0);
|
|
||||||
draw_lives(0);
|
|
||||||
for (i=0; i<VBWIDTH-4; i++)
|
|
||||||
vidmem[191][i] = (i&1) ? 0x55 : 0x2a;
|
|
||||||
draw_bunker(20, 165, 15, 15, 20);
|
|
||||||
draw_bunker(160, 165, 15, 15, 20);
|
|
||||||
}
|
|
||||||
|
|
||||||
char in_rect(Enemy* e, byte x, byte y, byte w, byte h) {
|
char in_rect(Enemy* e, byte x, byte y, byte w, byte h) {
|
||||||
byte ew = e->shape[0]*8;
|
byte ew = e->shape[0]*8;
|
||||||
byte eh = e->shape[1];
|
byte eh = e->shape[1];
|
||||||
|
@ -482,7 +479,7 @@ void drop_bomb() {
|
||||||
|
|
||||||
void move_bomb() {
|
void move_bomb() {
|
||||||
byte leftover = xor_sprite(bomb_bitmap, bomb_x, bomb_y); // erase
|
byte leftover = xor_sprite(bomb_bitmap, bomb_x, bomb_y); // erase
|
||||||
if (bomb_y < 192-10) {
|
if (bomb_y > 192-12) {
|
||||||
bomb_y = 0;
|
bomb_y = 0;
|
||||||
} else if (leftover) {
|
} else if (leftover) {
|
||||||
erase_sprite(bomb_bitmap, bomb_x, bomb_y); // erase bunker
|
erase_sprite(bomb_bitmap, bomb_x, bomb_y); // erase bunker
|
||||||
|
@ -510,13 +507,13 @@ void move_player() {
|
||||||
if (kbhit()) {
|
if (kbhit()) {
|
||||||
key = cgetc();
|
key = cgetc();
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 'Z':
|
case 8: // left arrow
|
||||||
player_dir = player_dir < 0 ? 0 : -2;
|
player_dir = player_dir < 0 ? 0 : -2;
|
||||||
break;
|
break;
|
||||||
case 'X':
|
case 21: // right arrow
|
||||||
player_dir = player_dir > 0 ? 0 : 2;
|
player_dir = player_dir > 0 ? 0 : 2;
|
||||||
break;
|
break;
|
||||||
case ' ':
|
case ' ': // space
|
||||||
if (bullet_y == 0) {
|
if (bullet_y == 0) {
|
||||||
fire_bullet();
|
fire_bullet();
|
||||||
}
|
}
|
||||||
|
@ -558,17 +555,18 @@ void play_round() {
|
||||||
void init_game() {
|
void init_game() {
|
||||||
score = 0;
|
score = 0;
|
||||||
lives = 5;
|
lives = 5;
|
||||||
curplayer = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void game_over_msg() {
|
void game_over_msg() {
|
||||||
byte i;
|
byte i;
|
||||||
|
byte x=11;
|
||||||
|
byte y=10;
|
||||||
for (i=0; i<50; i++) {
|
for (i=0; i<50; i++) {
|
||||||
draw_string(" *************** ", 5, 15);
|
draw_string(" *************** ", x, y+0, 0);
|
||||||
draw_string("*** ***", 5, 16);
|
draw_string("*** ***", x, y+1, 0);
|
||||||
draw_string("** GAME OVER **", 5, 17);
|
draw_string("** GAME OVER **", x, y+2, 0);
|
||||||
draw_string("*** ***", 5, 18);
|
draw_string("*** ***", x, y+3, 0);
|
||||||
draw_string(" *************** ", 5, 19);
|
draw_string(" *************** ", x, y+4, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -595,7 +593,6 @@ void attract_mode() {
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
// NOTE: initializers don't get run, so we init here
|
// NOTE: initializers don't get run, so we init here
|
||||||
credits = 0;
|
|
||||||
while (1) {
|
while (1) {
|
||||||
//attract_mode();
|
//attract_mode();
|
||||||
play_game();
|
play_game();
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <conio.h>
|
#include <conio.h>
|
||||||
#include <apple2.h>
|
#include <apple2.h>
|
||||||
#include <joystick.h>
|
|
||||||
|
|
||||||
#define COLS 40
|
#define COLS 40
|
||||||
#define ROWS 24
|
#define ROWS 24
|
||||||
|
@ -12,13 +11,14 @@ typedef unsigned char byte;
|
||||||
typedef signed char sbyte;
|
typedef signed char sbyte;
|
||||||
typedef unsigned short word;
|
typedef unsigned short word;
|
||||||
|
|
||||||
|
// BASL = text address of cursor position
|
||||||
static byte** BASL = (byte**) 0x28;
|
static byte** BASL = (byte**) 0x28;
|
||||||
|
|
||||||
byte getchar(byte x, byte y) {
|
byte getchar(byte x, byte y) {
|
||||||
// JSR VTABZ
|
// JSR VTABZ
|
||||||
// LDA (BASL) ($28)
|
// LDA (BASL) ($28)
|
||||||
gotoxy(x,y);
|
gotoxy(x,y); // set cursor position
|
||||||
return (*BASL)[x];
|
return (*BASL)[x]; // lookup value @ cursor address
|
||||||
}
|
}
|
||||||
|
|
||||||
void delay(byte count) {
|
void delay(byte count) {
|
||||||
|
@ -45,6 +45,7 @@ Player players[2];
|
||||||
|
|
||||||
byte credits = 0;
|
byte credits = 0;
|
||||||
byte frames_per_move;
|
byte frames_per_move;
|
||||||
|
byte gameover;
|
||||||
|
|
||||||
#define START_SPEED 12
|
#define START_SPEED 12
|
||||||
#define MAX_SPEED 5
|
#define MAX_SPEED 5
|
||||||
|
@ -73,22 +74,22 @@ void draw_box(byte x, byte y, byte x2, byte y2, const char* chars) {
|
||||||
|
|
||||||
void draw_playfield() {
|
void draw_playfield() {
|
||||||
draw_box(0,1,COLS-1,ROWS-1,BOX_CHARS);
|
draw_box(0,1,COLS-1,ROWS-1,BOX_CHARS);
|
||||||
cputsxy(0,0,"Plyr1:");
|
cputsxy( 0, 0, "Plyr1:");
|
||||||
cputsxy(20,0,"Plyr2:");
|
cputsxy(20, 0, "Plyr2:");
|
||||||
cputcxy(7,0,players[0].score+'0');
|
cputcxy( 7, 0, players[0].score+'0');
|
||||||
cputcxy(27,0,players[1].score+'0');
|
cputcxy(27, 0, players[1].score+'0');
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef enum { D_RIGHT, D_DOWN, D_LEFT, D_UP } dir_t;
|
typedef enum { D_RIGHT, D_DOWN, D_LEFT, D_UP } dir_t;
|
||||||
const char DIR_X[4] = { 1, 0, -1, 0 };
|
const sbyte DIR_X[4] = { 1, 0, -1, 0 };
|
||||||
const char DIR_Y[4] = { 0, 1, 0, -1 };
|
const sbyte DIR_Y[4] = { 0, 1, 0, -1 };
|
||||||
|
|
||||||
void init_game() {
|
void init_game() {
|
||||||
memset(players, 0, sizeof(players));
|
memset(players, 0, sizeof(players));
|
||||||
players[0].head_attr = '1';
|
players[0].head_attr = '1';
|
||||||
players[1].head_attr = '2';
|
players[1].head_attr = '2';
|
||||||
players[0].tail_attr = 1;
|
players[0].tail_attr = '#';
|
||||||
players[1].tail_attr = 9;
|
players[1].tail_attr = '*';
|
||||||
frames_per_move = START_SPEED;
|
frames_per_move = START_SPEED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,13 +121,14 @@ void human_control(Player* p) {
|
||||||
if (!p->human) return;
|
if (!p->human) return;
|
||||||
if (!kbhit()) return;
|
if (!kbhit()) return;
|
||||||
key = cgetc();
|
key = cgetc();
|
||||||
|
// I/J/K/M cursor movement
|
||||||
switch (key) {
|
switch (key) {
|
||||||
case 'I': dir = D_UP; break;
|
case 'I': dir = D_UP; break;
|
||||||
case 'J': dir = D_LEFT; break;
|
case 'J': dir = D_LEFT; break;
|
||||||
case 'K': dir = D_RIGHT; break;
|
case 'K': dir = D_RIGHT; break;
|
||||||
case 'M': dir = D_DOWN; break;
|
case 'M': dir = D_DOWN; break;
|
||||||
}
|
}
|
||||||
// don't let the player reverse
|
// don't let the player reverse direction
|
||||||
if (dir < 0x80 && dir != (p->dir ^ 2)) {
|
if (dir < 0x80 && dir != (p->dir ^ 2)) {
|
||||||
p->dir = dir;
|
p->dir = dir;
|
||||||
}
|
}
|
||||||
|
@ -159,21 +161,17 @@ void ai_control(Player* p) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
byte gameover;
|
|
||||||
|
|
||||||
void flash_colliders() {
|
void flash_colliders() {
|
||||||
byte i;
|
byte i;
|
||||||
// flash players that collided
|
// flash players that collided
|
||||||
for (i=0; i<56; i++) {
|
for (i=0; i<56; i++) {
|
||||||
//cv_set_frequency(CV_SOUNDCHANNEL_0, 1000+i*8);
|
|
||||||
//cv_set_attenuation(CV_SOUNDCHANNEL_0, i/2);
|
|
||||||
if (players[0].collided) players[0].head_attr ^= 0x80;
|
|
||||||
if (players[1].collided) players[1].head_attr ^= 0x80;
|
|
||||||
delay(2);
|
delay(2);
|
||||||
|
revers(players[0].collided && (i&1));
|
||||||
draw_player(&players[0]);
|
draw_player(&players[0]);
|
||||||
|
revers(players[1].collided && (i&1));
|
||||||
draw_player(&players[1]);
|
draw_player(&players[1]);
|
||||||
}
|
}
|
||||||
//cv_set_attenuation(CV_SOUNDCHANNEL_0, 28);
|
revers(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void make_move() {
|
void make_move() {
|
||||||
|
@ -237,6 +235,5 @@ void play_game() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
joy_install (joy_static_stddrv);
|
|
||||||
play_game();
|
play_game();
|
||||||
}
|
}
|
||||||
|
|
|
@ -152,13 +152,19 @@ var Apple2Platform = function(mainElement) {
|
||||||
audio = new SampleAudio(cpuFrequency);
|
audio = new SampleAudio(cpuFrequency);
|
||||||
video.create();
|
video.create();
|
||||||
video.setKeyboardEvents(function(key,code,flags) {
|
video.setKeyboardEvents(function(key,code,flags) {
|
||||||
// since we're an Apple II+, we don't do lowercase
|
|
||||||
if (flags & 1) {
|
if (flags & 1) {
|
||||||
if (code) {
|
if (code) {
|
||||||
|
// convert to uppercase for Apple ][
|
||||||
if (code >= 0x61 && code <= 0x7a)
|
if (code >= 0x61 && code <= 0x7a)
|
||||||
code -= 0x20;
|
code -= 0x20;
|
||||||
kbdlatch = (code | 0x80) & 0xff;
|
kbdlatch = (code | 0x80) & 0xff;
|
||||||
} else if (key) {
|
} else if (key) {
|
||||||
|
switch (key) {
|
||||||
|
case 37: key=8; break; // left
|
||||||
|
case 39: key=21; break; // right
|
||||||
|
case 38: key=11; break; // up
|
||||||
|
case 40: key=10; break; // down
|
||||||
|
}
|
||||||
kbdlatch = (key | 0x80) & 0xff;
|
kbdlatch = (key | 0x80) & 0xff;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user