|
|
|
@ -2,22 +2,17 @@
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <nes.h>
|
|
|
|
|
#include <joystick.h>
|
|
|
|
|
|
|
|
|
|
#include "neslib.h"
|
|
|
|
|
|
|
|
|
|
#pragma bss-name (push,"ZEROPAGE")
|
|
|
|
|
unsigned char oam_off;
|
|
|
|
|
#pragma bss-name (pop)
|
|
|
|
|
|
|
|
|
|
#pragma data-name (push,"CHARS")
|
|
|
|
|
#pragma data-name(pop)
|
|
|
|
|
|
|
|
|
|
#pragma static-locals (1);
|
|
|
|
|
|
|
|
|
|
#define COLS 32
|
|
|
|
|
#define ROWS 28
|
|
|
|
|
|
|
|
|
|
//#define DEBUG_FRAMERATE
|
|
|
|
|
|
|
|
|
|
typedef unsigned char byte;
|
|
|
|
|
typedef signed char sbyte;
|
|
|
|
|
typedef unsigned short word;
|
|
|
|
@ -47,14 +42,16 @@ const char PALETTE[32] = {
|
|
|
|
|
#define COLOR_EXPLOSION 3
|
|
|
|
|
|
|
|
|
|
const char TILESET[128*8*2] = {/*{w:8,h:8,bpp:1,count:128,brev:1,np:2,pofs:8,remap:[0,1,2,4,5,6,7,8,9,10,11,12]}*/
|
|
|
|
|
// font (0..63)
|
|
|
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x7C,0x7C,0x7C,0x38,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6C,0x6C,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6C,0xFE,0x6C,0xFE,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x10,0xFE,0xD0,0xFE,0x16,0xFE,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCE,0xDC,0x38,0x76,0xE6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x6C,0x7C,0xEC,0xEE,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x38,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x70,0x70,0x70,0x70,0x70,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x38,0x38,0x38,0x38,0x38,0x30,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x6C,0x38,0x6C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x38,0xFE,0x38,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x1E,0x3C,0x78,0xF0,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
|
|
|
0x00,0x7C,0xEE,0xEE,0xEE,0xEE,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x38,0x78,0x38,0x38,0x38,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x0E,0x7C,0xE0,0xEE,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0x0E,0x3C,0x0E,0x0E,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x3E,0x7E,0xEE,0xEE,0xFE,0x0E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0xE0,0xFC,0x0E,0xEE,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xE0,0xFC,0xEE,0xEE,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xEE,0x1C,0x1C,0x38,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xEE,0x7C,0xEE,0xEE,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xEE,0xEE,0x7E,0x0E,0x3C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00,0x60,0x60,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1C,0x38,0x70,0x70,0x38,0x1C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x00,0x00,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x70,0x38,0x1C,0x1C,0x38,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xEE,0x1C,0x38,0x00,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
|
|
|
0x00,0x7C,0xEE,0xEE,0xEE,0xE0,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xEE,0xEE,0xEE,0xFE,0xEE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0xEE,0xFC,0xEE,0xEE,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xEE,0xE0,0xE0,0xEE,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0xEC,0xEE,0xEE,0xEE,0xFC,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xE0,0xF0,0xE0,0xE0,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0xE0,0xF8,0xE0,0xE0,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xE0,0xEE,0xEE,0xEE,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0xEE,0xFE,0xEE,0xEE,0xEE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0x38,0x38,0x38,0x38,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0E,0x0E,0x0E,0x0E,0xEE,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0xFC,0xF8,0xEC,0xEE,0xEE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xE0,0xE0,0xE0,0xE0,0xEE,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC6,0xEE,0xFE,0xFE,0xEE,0xEE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xCE,0xEE,0xFE,0xFE,0xEE,0xE6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xEE,0xEE,0xEE,0xEE,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
|
|
|
0x00,0xFC,0xEE,0xEE,0xEE,0xFC,0xE0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xEE,0xEE,0xEE,0xEC,0x7E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFC,0xEE,0xEE,0xEE,0xFC,0xEE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7C,0xE0,0x7C,0x0E,0xEE,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x38,0x38,0x38,0x38,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0xEE,0xEE,0xEE,0xEE,0x7C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0xEE,0xEE,0x6C,0x38,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0xEE,0xFE,0xFE,0xEE,0xC6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0x7C,0x38,0x7C,0xEE,0xEE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xEE,0xEE,0xEE,0x7C,0x38,0x38,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFE,0x1C,0x38,0x70,0xE0,0xFE,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
|
|
|
|
|
|
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
|
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
|
|
|
// formation enemy (66)
|
|
|
|
|
// formation enemy (64,66)
|
|
|
|
|
0x0F,0x13,0x03,0x03,0x01,0x01,0x00,0x00,0x0C,0x11,0x04,0x08,0x12,0x04,0x08,0x08,
|
|
|
|
|
0xF8,0xE4,0xE0,0xE0,0xC0,0xC0,0x80,0x00,0x18,0x44,0x10,0x08,0x24,0x10,0x08,0x08,
|
|
|
|
|
|
|
|
|
|
0x0C,0x13,0x03,0x03,0x03,0x01,0x01,0x00,0x0C,0x10,0x01,0x0C,0x30,0x02,0x04,0x18,
|
|
|
|
|
0x18,0x64,0xE0,0xE0,0xE0,0xC0,0xC0,0x80,0x18,0x04,0x40,0x18,0x06,0x20,0x10,0x0C,
|
|
|
|
|
// attackers (68)
|
|
|
|
@ -68,16 +65,16 @@ const char TILESET[128*8*2] = {/*{w:8,h:8,bpp:1,count:128,brev:1,np:2,pofs:8,rem
|
|
|
|
|
0x00,0x00,0x00,0x08,0x08,0x10,0xE0,0xE0,0x00,0x00,0x00,0x08,0x08,0x10,0x00,0x40,
|
|
|
|
|
0xE0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x10,0x0C,0x02,0x20,0x10,0x0C,0x00,0x00,
|
|
|
|
|
|
|
|
|
|
0x00,0x00,0x0C,0x04,0x02,0x03,0x07,0x27,0x00,0x00,0x0C,0x04,0x00,0x00,0x01,0x20,
|
|
|
|
|
0x3F,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x32,0x00,0x04,0x08,0x10,0x01,0x00,0x00,
|
|
|
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0xE0,0x00,0x00,0x00,0x20,0x40,0x84,0x08,0x10,
|
|
|
|
|
0xE0,0xF0,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x80,0x00,0x00,0x00,
|
|
|
|
|
|
|
|
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x07,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
|
|
|
0x07,0x03,0x03,0x01,0x00,0x00,0x00,0x00,0x00,0x18,0x21,0x44,0x08,0x08,0x00,0x00,
|
|
|
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xC0,0x00,0x00,0x20,0x40,0x80,0x98,0x20,0x00,
|
|
|
|
|
0xE0,0xFC,0xC4,0x80,0x80,0x80,0xC0,0x00,0x40,0x0C,0x04,0x00,0x00,0x80,0xC0,0x00,
|
|
|
|
|
0x00,0x00,0x02,0x04,0x04,0x03,0x03,0x03,0x00,0x00,0x02,0x04,0x04,0x20,0x11,0x0C,
|
|
|
|
|
0x03,0x07,0x03,0x03,0x02,0x00,0x00,0x00,0x00,0x20,0x1C,0x00,0x00,0x00,0x00,0x00,
|
|
|
|
|
0x00,0x00,0x00,0x08,0x08,0x10,0xE0,0xE0,0x00,0x00,0x00,0x08,0x08,0x10,0x00,0x40,
|
|
|
|
|
0xE0,0xC0,0xC0,0x00,0x00,0x00,0x00,0x00,0x10,0x0C,0x02,0x20,0x10,0x0C,0x00,0x00,
|
|
|
|
|
|
|
|
|
|
0x00,0x00,0x01,0x01,0x01,0x01,0x03,0x03,0x00,0x00,0x01,0x11,0x08,0x04,0x01,0x20,
|
|
|
|
|
0x07,0x07,0x03,0x02,0x00,0x00,0x00,0x00,0x10,0x08,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
|
|
|
0x00,0x00,0x80,0x00,0x04,0xCC,0xF0,0xE0,0x00,0x00,0x80,0x00,0x04,0x0C,0x00,0x40,
|
|
|
|
|
0xC0,0xC0,0x80,0x00,0x00,0x00,0x00,0x00,0x20,0x10,0x08,0x80,0x40,0x20,0x00,0x00,
|
|
|
|
|
|
|
|
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x04,0x02,0x11,0x08,0x04,
|
|
|
|
|
0x03,0x03,0x07,0x01,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
|
|
|
0x00,0x00,0x00,0x30,0x20,0x60,0xF0,0xFC,0x00,0x00,0x00,0x30,0x20,0x00,0x40,0x04,
|
|
|
|
@ -97,15 +94,22 @@ const char TILESET[128*8*2] = {/*{w:8,h:8,bpp:1,count:128,brev:1,np:2,pofs:8,rem
|
|
|
|
|
0x11,0x16,0x1E,0x15,0x10,0x10,0x10,0x10,0x3F,0x3F,0x3F,0x3D,0x3B,0x3C,0x28,0x28,
|
|
|
|
|
0x40,0x40,0xC0,0x00,0x00,0x40,0x44,0x44,0xC0,0xC0,0x20,0xF0,0xC0,0xC2,0xC2,0xEA,
|
|
|
|
|
0x44,0x34,0x3C,0x54,0x04,0x04,0x04,0x04,0xFE,0xFE,0xFE,0xDE,0xEE,0x1E,0x0A,0x0A,
|
|
|
|
|
|
|
|
|
|
// player ship (96)
|
|
|
|
|
0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
|
|
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
|
|
|
0x08,0x18,0x08,0x18,0x08,0x18,0x18,0x10,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,
|
|
|
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,
|
|
|
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
|
|
|
|
|
|
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
|
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
|
|
|
// explosions
|
|
|
|
|
// bullet (100)
|
|
|
|
|
0x00,0x00,0x00,0x00,0x00,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
|
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
|
|
|
// stars (102)
|
|
|
|
|
0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08,0x00,0x00,0x00,0x00,
|
|
|
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
|
|
|
0x00,0x00,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
|
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
|
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
|
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
|
|
|
|
|
// explosions (112)
|
|
|
|
|
0x00,0x00,0x00,0x08,0x04,0x03,0x06,0x05,0x00,0x00,0x00,0x0C,0x06,0x04,0x00,0x18,
|
|
|
|
|
0x05,0x06,0x07,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x08,0x09,0x00,0x00,0x00,0x00,
|
|
|
|
|
0x00,0x00,0x00,0x08,0x90,0xE0,0x90,0xD0,0x00,0x00,0x00,0x18,0x30,0x10,0x00,0x0C,
|
|
|
|
@ -132,7 +136,7 @@ const char TILESET[128*8*2] = {/*{w:8,h:8,bpp:1,count:128,brev:1,np:2,pofs:8,rem
|
|
|
|
|
|
|
|
|
|
// VRAM UPDATE BUFFER
|
|
|
|
|
|
|
|
|
|
#define VBUFSIZE 64
|
|
|
|
|
#define VBUFSIZE 96
|
|
|
|
|
byte updbuf[VBUFSIZE];
|
|
|
|
|
byte updptr = 0;
|
|
|
|
|
|
|
|
|
@ -226,18 +230,24 @@ word bcd_add(word a, word b) {
|
|
|
|
|
|
|
|
|
|
// GAME CODE
|
|
|
|
|
|
|
|
|
|
#define NSPRITES 16
|
|
|
|
|
#define NMISSILES 8
|
|
|
|
|
#define YOFFSCREEN 239
|
|
|
|
|
#define NSPRITES 8 // max number of sprites
|
|
|
|
|
#define NMISSILES 8 // max number of missiles
|
|
|
|
|
#define YOFFSCREEN 240 // offscreen y position (hidden)
|
|
|
|
|
|
|
|
|
|
#define SPRI_SHIP 96
|
|
|
|
|
#define SPRI_MISSILE 100
|
|
|
|
|
#define SPRI_BOMB 104
|
|
|
|
|
#define SPRI_EXPLODE 112
|
|
|
|
|
#define SPRI_ENEMY 68
|
|
|
|
|
// sprite indexes
|
|
|
|
|
#define PLYRMISSILE 7 // player missile
|
|
|
|
|
#define PLYRSPRITE 7 // player sprite
|
|
|
|
|
#define BOOMSPRITE 6 // explosion sprite
|
|
|
|
|
|
|
|
|
|
#define SSRC_FORM1 66
|
|
|
|
|
#define SDST_FORM1 128
|
|
|
|
|
// nametable entries
|
|
|
|
|
#define NAME_SHIP 96
|
|
|
|
|
#define NAME_MISSILE 100
|
|
|
|
|
#define NAME_BOMB 104
|
|
|
|
|
#define NAME_EXPLODE 112
|
|
|
|
|
#define NAME_ENEMY 68
|
|
|
|
|
|
|
|
|
|
#define SSRC_FORM1 64 // name for formation source sprites
|
|
|
|
|
#define SDST_FORM1 128 // start of shifted formation table
|
|
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
|
byte shape;
|
|
|
|
@ -286,11 +296,10 @@ byte player_exploding;
|
|
|
|
|
byte enemy_exploding;
|
|
|
|
|
byte enemies_left;
|
|
|
|
|
word player_score;
|
|
|
|
|
byte framecount;
|
|
|
|
|
|
|
|
|
|
void copy_sprites() {
|
|
|
|
|
byte i;
|
|
|
|
|
byte oamid = 0;
|
|
|
|
|
byte oamid = 128; // so we don't clear stars...
|
|
|
|
|
for (i=0; i<NSPRITES; i++) {
|
|
|
|
|
Sprite* spr = &vsprites[i];
|
|
|
|
|
if (spr->y != YOFFSCREEN) {
|
|
|
|
@ -307,7 +316,7 @@ void copy_sprites() {
|
|
|
|
|
for (i=0; i<NMISSILES; i++) {
|
|
|
|
|
Missile* mis = &missiles[i];
|
|
|
|
|
if (mis->ypos != YOFFSCREEN) {
|
|
|
|
|
oamid = oam_spr(mis->xpos, mis->ypos, SPRI_MISSILE,
|
|
|
|
|
oamid = oam_spr(mis->xpos, mis->ypos, NAME_MISSILE,
|
|
|
|
|
(i==7)?COLOR_MISSILE:COLOR_BOMB,
|
|
|
|
|
oamid);
|
|
|
|
|
}
|
|
|
|
@ -345,12 +354,11 @@ void setup_formation() {
|
|
|
|
|
|
|
|
|
|
void draw_row(byte row) {
|
|
|
|
|
static char buf[32];
|
|
|
|
|
byte i;
|
|
|
|
|
byte x = formation_offset_x / 8;
|
|
|
|
|
register byte i;
|
|
|
|
|
register byte x = formation_offset_x / 8;
|
|
|
|
|
byte xd = (formation_offset_x & 7) * 3;
|
|
|
|
|
byte y = 3 + row * 2;
|
|
|
|
|
for (i=0; i<x; i++)
|
|
|
|
|
buf[i] = BLANK;
|
|
|
|
|
memset(buf, BLANK, sizeof(buf));
|
|
|
|
|
for (i=0; i<ENEMIES_PER_ROW; i++) {
|
|
|
|
|
byte shape = formation[i + row*ENEMIES_PER_ROW].shape;
|
|
|
|
|
if (shape) {
|
|
|
|
@ -358,13 +366,9 @@ void draw_row(byte row) {
|
|
|
|
|
buf[x] = shape;
|
|
|
|
|
buf[x+1] = shape+1;
|
|
|
|
|
buf[x+2] = shape+2;
|
|
|
|
|
} else {
|
|
|
|
|
buf[x] = buf[x+1] = buf[x+2] = BLANK;
|
|
|
|
|
}
|
|
|
|
|
x += 3;
|
|
|
|
|
}
|
|
|
|
|
for (; x<COLS; x++)
|
|
|
|
|
buf[x] = BLANK;
|
|
|
|
|
putbytes(0, y, buf, sizeof(buf));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -388,9 +392,9 @@ void draw_next_row() {
|
|
|
|
|
|
|
|
|
|
const byte DIR_TO_CODE[32] = {
|
|
|
|
|
0, 1, 2, 3, 4, 5, 6, 6,
|
|
|
|
|
6|FLIPXY, 6|FLIPXY, 5|FLIPXY, 4|FLIPXY, 3|FLIPXY, 2|FLIPXY, 1|FLIPXY, 0|FLIPXY,
|
|
|
|
|
0|FLIPX, 1|FLIPX, 2|FLIPX, 3|FLIPX, 4|FLIPX, 5|FLIPX, 6|FLIPX, 6|FLIPX,
|
|
|
|
|
6|FLIPY, 6|FLIPY, 5|FLIPY, 4|FLIPY, 3|FLIPY, 2|FLIPY, 1|FLIPY, 0|FLIPY,
|
|
|
|
|
0|FLIPXY, 1|FLIPXY, 2|FLIPXY, 3|FLIPXY, 4|FLIPXY, 5|FLIPXY, 6|FLIPXY, 6|FLIPXY,
|
|
|
|
|
6|FLIPX, 6|FLIPX, 5|FLIPX, 4|FLIPX, 3|FLIPX, 2|FLIPX, 1|FLIPX, 0|FLIPX,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const byte SINTBL[32] = {
|
|
|
|
@ -426,9 +430,9 @@ byte get_attacker_y(byte formation_index) {
|
|
|
|
|
void draw_attacker(byte i) {
|
|
|
|
|
AttackingEnemy* a = &attackers[i];
|
|
|
|
|
if (a->findex) {
|
|
|
|
|
byte code = DIR_TO_CODE[(a->dir)&31];
|
|
|
|
|
vsprites[i].name = SPRI_ENEMY + (code&7)*4; // tile
|
|
|
|
|
vsprites[i].tag = code & 0xc0; // flip h/v
|
|
|
|
|
byte code = DIR_TO_CODE[a->dir & 31];
|
|
|
|
|
vsprites[i].name = NAME_ENEMY + (code & 7)*4; // tile
|
|
|
|
|
vsprites[i].tag = code & FLIPXY; // flip h/v
|
|
|
|
|
vsprites[i].x = a->x >> 8;
|
|
|
|
|
vsprites[i].y = a->y >> 8;
|
|
|
|
|
} else {
|
|
|
|
@ -443,7 +447,7 @@ void draw_attackers() {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void return_attacker(AttackingEnemy* a) {
|
|
|
|
|
void return_attacker(register AttackingEnemy* a) {
|
|
|
|
|
byte fi = a->findex-1;
|
|
|
|
|
byte destx = get_attacker_x(fi);
|
|
|
|
|
byte desty = get_attacker_y(fi);
|
|
|
|
@ -460,9 +464,15 @@ void return_attacker(AttackingEnemy* a) {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void fly_attacker(AttackingEnemy* a) {
|
|
|
|
|
a->x += isin(a->dir) * 2;
|
|
|
|
|
a->y += icos(a->dir) * 2;
|
|
|
|
|
void fly_attacker(register AttackingEnemy* a) {
|
|
|
|
|
byte dir = a->dir;
|
|
|
|
|
#if 1
|
|
|
|
|
a->x += SINTBL[dir & 31] * 2;
|
|
|
|
|
a->y += SINTBL[(dir+8) & 31] * 2;
|
|
|
|
|
#else
|
|
|
|
|
a->x += isin(dir) * 2;
|
|
|
|
|
a->y += icos(dir) * 2;
|
|
|
|
|
#endif
|
|
|
|
|
if ((a->y >> 8) == 0) {
|
|
|
|
|
a->returning = 1;
|
|
|
|
|
}
|
|
|
|
@ -534,24 +544,24 @@ void formation_to_attacker(byte formation_index) {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void draw_player() {
|
|
|
|
|
vsprites[7].x = player_x;
|
|
|
|
|
vsprites[7].y = player_y;
|
|
|
|
|
vsprites[7].name = SPRI_SHIP;
|
|
|
|
|
vsprites[7].tag = COLOR_PLAYER;
|
|
|
|
|
vsprites[PLYRSPRITE].x = player_x;
|
|
|
|
|
vsprites[PLYRSPRITE].y = player_y;
|
|
|
|
|
vsprites[PLYRSPRITE].name = NAME_SHIP;
|
|
|
|
|
vsprites[PLYRSPRITE].tag = COLOR_PLAYER;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void move_player() {
|
|
|
|
|
byte joy = joy_read(JOY_1);
|
|
|
|
|
byte joy = pad_poll(0);
|
|
|
|
|
// move left/right?
|
|
|
|
|
if ((joy & JOY_LEFT_MASK) && player_x > 16) player_x--;
|
|
|
|
|
if ((joy & JOY_RIGHT_MASK) && player_x < 224) player_x++;
|
|
|
|
|
if ((joy & PAD_LEFT) && player_x > 16) player_x--;
|
|
|
|
|
if ((joy & PAD_RIGHT) && player_x < 224) player_x++;
|
|
|
|
|
// shoot missile?
|
|
|
|
|
if ((joy & JOY_BTN_A_MASK) && missiles[7].ypos == YOFFSCREEN) {
|
|
|
|
|
missiles[7].ypos = player_y-8; // must be multiple of missile speed
|
|
|
|
|
missiles[7].xpos = player_x; // player X position
|
|
|
|
|
missiles[7].dy = -4; // player missile speed
|
|
|
|
|
if ((joy & PAD_A) && missiles[PLYRMISSILE].ypos == YOFFSCREEN) {
|
|
|
|
|
missiles[PLYRMISSILE].ypos = player_y-8; // must be multiple of missile speed
|
|
|
|
|
missiles[PLYRMISSILE].xpos = player_x+4; // player X position
|
|
|
|
|
missiles[PLYRMISSILE].dy = -4; // player missile speed
|
|
|
|
|
}
|
|
|
|
|
vsprites[7].x = player_x;
|
|
|
|
|
vsprites[PLYRMISSILE].x = player_x;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void move_missiles() {
|
|
|
|
@ -567,10 +577,10 @@ void move_missiles() {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void blowup_at(byte x, byte y) {
|
|
|
|
|
vsprites[6].tag = COLOR_EXPLOSION;
|
|
|
|
|
vsprites[6].name = SPRI_EXPLODE; // TODO
|
|
|
|
|
vsprites[6].x = x;
|
|
|
|
|
vsprites[6].y = y;
|
|
|
|
|
vsprites[BOOMSPRITE].tag = COLOR_EXPLOSION;
|
|
|
|
|
vsprites[BOOMSPRITE].name = NAME_EXPLODE; // TODO
|
|
|
|
|
vsprites[BOOMSPRITE].x = x;
|
|
|
|
|
vsprites[BOOMSPRITE].y = y;
|
|
|
|
|
enemy_exploding = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -579,9 +589,9 @@ void animate_enemy_explosion() {
|
|
|
|
|
// animate next frame
|
|
|
|
|
if (enemy_exploding >= 8) {
|
|
|
|
|
enemy_exploding = 0; // hide explosion after 4 frames
|
|
|
|
|
vsprites[6].y = YOFFSCREEN;
|
|
|
|
|
vsprites[BOOMSPRITE].y = YOFFSCREEN;
|
|
|
|
|
} else {
|
|
|
|
|
vsprites[6].name = SPRI_EXPLODE + (enemy_exploding += 4); // TODO
|
|
|
|
|
vsprites[BOOMSPRITE].name = NAME_EXPLODE + (enemy_exploding += 4); // TODO
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -590,21 +600,23 @@ void animate_player_explosion() {
|
|
|
|
|
byte z = player_exploding;
|
|
|
|
|
if (z <= 3) {
|
|
|
|
|
if (z == 3) {
|
|
|
|
|
vsprites[7].y = YOFFSCREEN;
|
|
|
|
|
vsprites[PLYRSPRITE].y = YOFFSCREEN;
|
|
|
|
|
} else {
|
|
|
|
|
vsprites[7].name = SPRI_EXPLODE + z*4;
|
|
|
|
|
vsprites[PLYRSPRITE].name = NAME_EXPLODE + z*4;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void hide_player_missile() {
|
|
|
|
|
missiles[7].ypos = YOFFSCREEN;
|
|
|
|
|
missiles[PLYRMISSILE].ypos = YOFFSCREEN;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void does_player_shoot_formation() {
|
|
|
|
|
byte mx = missiles[7].xpos + 8;
|
|
|
|
|
byte my = missiles[7].ypos;
|
|
|
|
|
byte mx = missiles[PLYRMISSILE].xpos + 4;
|
|
|
|
|
byte my = missiles[PLYRMISSILE].ypos;
|
|
|
|
|
signed char row = (my - FORMATION_Y0) / FORMATION_YSPACE;
|
|
|
|
|
if (missiles[PLYRMISSILE].ypos == YOFFSCREEN)
|
|
|
|
|
return;
|
|
|
|
|
if (row >= 0 && row < ENEMY_ROWS) {
|
|
|
|
|
// ok if unsigned (in fact, must be due to range)
|
|
|
|
|
byte xoffset = mx - FORMATION_X0 - formation_offset_x;
|
|
|
|
@ -624,9 +636,11 @@ void does_player_shoot_formation() {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void does_player_shoot_attacker() {
|
|
|
|
|
byte mx = missiles[7].xpos + 8;
|
|
|
|
|
byte my = missiles[7].ypos;
|
|
|
|
|
byte mx = missiles[PLYRMISSILE].xpos + 4;
|
|
|
|
|
byte my = missiles[PLYRMISSILE].ypos;
|
|
|
|
|
byte i;
|
|
|
|
|
if (missiles[PLYRMISSILE].ypos == YOFFSCREEN)
|
|
|
|
|
return;
|
|
|
|
|
for (i=0; i<MAX_ATTACKERS; i++) {
|
|
|
|
|
AttackingEnemy* a = &attackers[i];
|
|
|
|
|
if (a->findex && in_rect(mx, my, a->x >> 8, a->y >> 8, 16, 16)) {
|
|
|
|
@ -715,13 +729,31 @@ void set_sounds() {
|
|
|
|
|
*/
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void wait_for_frame() {
|
|
|
|
|
ppu_wait_nmi();
|
|
|
|
|
static char starx[32];
|
|
|
|
|
static byte starofs;
|
|
|
|
|
|
|
|
|
|
void init_stars() {
|
|
|
|
|
byte i;
|
|
|
|
|
for (i=0; i<sizeof(starx); i++) {
|
|
|
|
|
starx[i] = rand();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void draw_stars() {
|
|
|
|
|
byte i;
|
|
|
|
|
byte oamid = 0; // 32 slots = 128 bytes
|
|
|
|
|
byte yofs = starofs;
|
|
|
|
|
for (i=0; i<32; i++) {
|
|
|
|
|
oamid = oam_spr(starx[i], yofs, 102+(i&3), 0, oamid);
|
|
|
|
|
yofs += 8; // 32*8 = 256, wraps around
|
|
|
|
|
}
|
|
|
|
|
starofs++;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void play_round() {
|
|
|
|
|
register byte framecount;
|
|
|
|
|
register byte t0;
|
|
|
|
|
byte end_timer = 255;
|
|
|
|
|
player_score = 0;
|
|
|
|
|
add_score(0);
|
|
|
|
|
putstring(0, 0, "PLAYER 1");
|
|
|
|
|
setup_formation();
|
|
|
|
@ -738,27 +770,42 @@ void play_round() {
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
if ((framecount & 0x7f) == 0 || enemies_left < 8) {
|
|
|
|
|
if (framecount == 0 || enemies_left < 8) {
|
|
|
|
|
new_attack_wave();
|
|
|
|
|
}
|
|
|
|
|
move_player();
|
|
|
|
|
does_missile_hit_player();
|
|
|
|
|
}
|
|
|
|
|
if ((framecount & 3) == 2) animate_enemy_explosion();
|
|
|
|
|
move_attackers();
|
|
|
|
|
move_missiles();
|
|
|
|
|
if (framecount & 1)
|
|
|
|
|
does_player_shoot_formation();
|
|
|
|
|
else
|
|
|
|
|
does_player_shoot_attacker();
|
|
|
|
|
draw_next_row();
|
|
|
|
|
draw_attackers();
|
|
|
|
|
if ((framecount & 0xf) == 0) think_attackers();
|
|
|
|
|
set_sounds();
|
|
|
|
|
framecount++;
|
|
|
|
|
if (!enemies_left) end_timer--;
|
|
|
|
|
cflushnow();
|
|
|
|
|
if ((framecount & 0xf) == 0) {
|
|
|
|
|
think_attackers();
|
|
|
|
|
} else {
|
|
|
|
|
switch (framecount & 3) {
|
|
|
|
|
case 1: animate_enemy_explosion(); // continue...
|
|
|
|
|
case 3: does_missile_hit_player(); break;
|
|
|
|
|
case 2: draw_stars(); break;
|
|
|
|
|
}
|
|
|
|
|
set_sounds();
|
|
|
|
|
if (!enemies_left) end_timer--;
|
|
|
|
|
draw_next_row();
|
|
|
|
|
}
|
|
|
|
|
//cflushnow();
|
|
|
|
|
copy_sprites();
|
|
|
|
|
#ifdef DEBUG_FRAMERATE
|
|
|
|
|
putchar(t0 & 31, 27, CHAR(' '));
|
|
|
|
|
putchar(framecount & 31, 27, CHAR(' '));
|
|
|
|
|
#endif
|
|
|
|
|
framecount++;
|
|
|
|
|
t0 = nesclock();
|
|
|
|
|
#ifdef DEBUG_FRAMERATE
|
|
|
|
|
putchar(t0 & 31, 27, CHAR('C'));
|
|
|
|
|
putchar(framecount & 31, 27, CHAR('F'));
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -790,19 +837,22 @@ void setup_tileset() {
|
|
|
|
|
src = SSRC_FORM1*16;
|
|
|
|
|
dest = SDST_FORM1*16;
|
|
|
|
|
for (i=0; i<8; i++) {
|
|
|
|
|
if (i==4) src += 32;
|
|
|
|
|
set_shifted_pattern(&TILESET[src], dest, i);
|
|
|
|
|
dest += 3*16;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void main() {
|
|
|
|
|
joy_install (joy_static_stddrv);
|
|
|
|
|
setup_tileset();
|
|
|
|
|
pal_all(PALETTE);
|
|
|
|
|
oam_clear();
|
|
|
|
|
oam_size(1); // 8x16 sprites
|
|
|
|
|
clrscr();
|
|
|
|
|
play_round();
|
|
|
|
|
main();
|
|
|
|
|
init_stars();
|
|
|
|
|
player_score = 0;
|
|
|
|
|
while (1) {
|
|
|
|
|
pal_all(PALETTE);
|
|
|
|
|
oam_clear();
|
|
|
|
|
oam_size(1); // 8x16 sprites
|
|
|
|
|
clrscr();
|
|
|
|
|
play_round();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|