add tetris
This commit is contained in:
parent
28a911c706
commit
19a741cfa2
21
apple1.h
21
apple1.h
|
@ -83,3 +83,24 @@ byte woz_getkey() {
|
|||
return key;
|
||||
#endif
|
||||
}
|
||||
|
||||
// non blocking keyboard read
|
||||
// reads a key and return 0 if no key is pressed
|
||||
byte woz_readkey() {
|
||||
#ifdef APPLE1
|
||||
if((PEEK(KEY_CTRL) & 0x80)==0) return 0;
|
||||
else return PEEK(KEY_DATA) & 0x7f;
|
||||
#else
|
||||
byte key;
|
||||
byte const *keyptr = &key;
|
||||
kickasm(uses keyptr, uses GETIN) {{
|
||||
jsr GETIN
|
||||
cmp #0
|
||||
bne __keypress
|
||||
lda #0
|
||||
__keypress:
|
||||
sta keyptr
|
||||
}}
|
||||
return key;
|
||||
#endif
|
||||
}
|
||||
|
|
10
interrupt.h
10
interrupt.h
|
@ -16,6 +16,7 @@ export volatile byte _ticks;
|
|||
export volatile byte _seconds;
|
||||
export volatile byte _minutes;
|
||||
export volatile byte _hours;
|
||||
export volatile byte _irq_trigger;
|
||||
|
||||
// interrupt routine called every 1/60th by the CPU after TMS9918 sets the /INT pin
|
||||
export __interrupt(hardware_all) void interrupt_handler() {
|
||||
|
@ -30,6 +31,8 @@ export __interrupt(hardware_all) void interrupt_handler() {
|
|||
}
|
||||
}
|
||||
}
|
||||
_irq_trigger = 1; // signals that an interrupt has been triggered
|
||||
|
||||
acknowledge_interrupt(); // acknowledge interrupt by reading the status register
|
||||
}
|
||||
|
||||
|
@ -40,3 +43,10 @@ void install_interrupt() {
|
|||
IRQ_JUMP_ADDRESS = (word) &interrupt_handler; // JUMP interrupt_handler
|
||||
asm { cli }; // re-enable 6502 interrupts
|
||||
}
|
||||
|
||||
// waits until IRQ is triggered
|
||||
void wait_interrupt() {
|
||||
// _irq_trigger = 0;
|
||||
// while(_irq_trigger == 0); // waits until it's set to 1 from the interrupt handler
|
||||
}
|
||||
|
||||
|
|
22
test.c
22
test.c
|
@ -2,18 +2,18 @@
|
|||
|
||||
#pragma encoding(ascii) // encode strings in plain ascii
|
||||
|
||||
#include "utils.h"
|
||||
#include "apple1.h"
|
||||
#include "tms9918.h"
|
||||
#include "font8x8.h"
|
||||
#include "tms_screen1.h"
|
||||
#include "tms_screen2.h"
|
||||
#include "interrupt.h"
|
||||
// #include "utils.h"
|
||||
// #include "apple1.h"
|
||||
// #include "tms9918.h"
|
||||
// #include "font8x8.h"
|
||||
// #include "tms_screen1.h"
|
||||
// #include "tms_screen2.h"
|
||||
// #include "interrupt.h"
|
||||
|
||||
#include "demo_amiga_hand.h"
|
||||
#include "demo_interrupt.h"
|
||||
#include "demo_extvid.h"
|
||||
#include "demo_blank.h"
|
||||
// #include "demo_amiga_hand.h"
|
||||
// #include "demo_interrupt.h"
|
||||
// #include "demo_extvid.h"
|
||||
// #include "demo_blank.h"
|
||||
|
||||
void help() {
|
||||
woz_puts(
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
const fs = require('fs');
|
||||
|
||||
let prg = fs.readFileSync("tetris_apple1.prg");
|
||||
|
||||
prg = prg.slice(2);
|
||||
|
||||
fs.writeFileSync("tetris_apple1.bin",prg);
|
||||
|
||||
console.log("bin written");
|
||||
*/
|
||||
|
||||
const fs = require('fs');
|
||||
|
||||
let code = fs.readFileSync("apple1_codeseg.bin");
|
||||
let data = fs.readFileSync("apple1_dataseg.bin");
|
||||
|
||||
let mem = new Uint8Array(65536).fill(0xAA);
|
||||
|
||||
let code_address = 0x4000;
|
||||
let data_address = 0x8000-0x7ff-0x280+1;
|
||||
|
||||
for(let i=0;i<code.length;i++) mem[code_address+i] = code[i];
|
||||
for(let i=0;i<data.length;i++) mem[data_address+i] = data[i];
|
||||
|
||||
let prg = mem.slice(0x4000,0x8000);
|
||||
|
||||
fs.writeFileSync("tetris_apple1.bin", prg);
|
||||
|
||||
console.log("bin written");
|
|
@ -0,0 +1,112 @@
|
|||
#ifndef CKBOARD_H
|
||||
#define CKBOARD_H
|
||||
|
||||
// #include <string.h> // for memcpy()
|
||||
|
||||
// #include "sprite.h"
|
||||
// #include "pieces.h"
|
||||
|
||||
#define BCOLS 10 // number of board columns
|
||||
#define BROWS 20 // number of board rows
|
||||
#define EMPTY NUMPIECES // the empty character is the character after all tetrominoes
|
||||
|
||||
// TODO KickC doesn't allow double arrays[][]
|
||||
|
||||
//byte board[32 /*BROWS*/ ][16 /*BCOLS*/]; // the board
|
||||
byte board[16*BROWS];
|
||||
|
||||
#define BOARD_INDEX(x,y) (((int)(y))*16+((int)(x)))
|
||||
#define WRITE_BOARD(x,y,c) board[BOARD_INDEX(x,y)]=(c)
|
||||
#define READ_BOARD(x,y) board[BOARD_INDEX(x,y)]
|
||||
|
||||
// prototypes
|
||||
void ck_init();
|
||||
void ck_drawpiece(sprite *pl);
|
||||
void ck_erasepiece(sprite *pl);
|
||||
int collides(sprite *pl);
|
||||
byte is_line_filled(byte line);
|
||||
void ck_erase_line(byte line);
|
||||
void ck_scroll_down(byte endline);
|
||||
|
||||
// fills the check board with EMPTY
|
||||
void ck_init() {
|
||||
for(byte r=0;r<BROWS;r++) {
|
||||
ck_erase_line(r);
|
||||
}
|
||||
}
|
||||
|
||||
// draw a piece on the check board
|
||||
void ck_drawpiece(sprite *pl) {
|
||||
tile_offset *data = get_piece_offsets(pl->piece, pl->angle);
|
||||
for(byte t=0; t<4; t++) {
|
||||
int x = pl->x; byte x1 = data->offset_x; x+= (int) x1;
|
||||
int y = pl->y; byte y1 = data->offset_y; y+= (int) y1;
|
||||
/*
|
||||
int x = pl->x + d->offset_x;
|
||||
int y = pl->y + d->offset_y;
|
||||
*/
|
||||
WRITE_BOARD(x,y,pl->piece);
|
||||
data++;
|
||||
}
|
||||
}
|
||||
|
||||
// erase a piece from the check board
|
||||
void ck_erasepiece(sprite *pl) {
|
||||
tile_offset *data = get_piece_offsets(pl->piece, pl->angle);
|
||||
for(byte t=0; t<4; t++) {
|
||||
int x = pl->x; byte x1 = data->offset_x; x+= (int) x1;
|
||||
int y = pl->y; byte y1 = data->offset_y; y+= (int) y1;
|
||||
/*
|
||||
int x = pl->x + (int) data->offset_x;
|
||||
int y = pl->y + (int) data->offset_y;
|
||||
*/
|
||||
WRITE_BOARD(x,y,EMPTY);
|
||||
data++;
|
||||
}
|
||||
}
|
||||
|
||||
// returns 1 if the piece collides with something
|
||||
int collides(sprite *pl) {
|
||||
tile_offset *data = get_piece_offsets(pl->piece, pl->angle);
|
||||
for(byte t=0; t<4; t++) {
|
||||
int x = pl->x; byte x1 = data->offset_x; x+= (int) x1;
|
||||
int y = pl->y; byte y1 = data->offset_y; y+= (int) y1;
|
||||
|
||||
//int x = pl->x + (int) data->offset_x;
|
||||
//int y = pl->y + (int) data->offset_y;
|
||||
if(x<0) return 1; // does it collide with left border?
|
||||
if(x>=BCOLS) return 1; // does it collide with right border?
|
||||
if(y>=BROWS) return 1; // does it collide with bottom?
|
||||
if(READ_BOARD(x,y) != EMPTY) return 1; // does it collide with something?
|
||||
data++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
// returns 1 if the line is all filled
|
||||
byte is_line_filled(byte line) {
|
||||
for(byte t=0;t<BCOLS;t++) {
|
||||
if(READ_BOARD(t,line)==EMPTY) return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// fills the specified line with an empty character
|
||||
void ck_erase_line(byte line) {
|
||||
for(byte t=0; t<BCOLS; t++) {
|
||||
WRITE_BOARD(t,line,EMPTY);
|
||||
}
|
||||
}
|
||||
|
||||
// scroll down the board by 1 position from top to specified line
|
||||
void ck_scroll_down(byte endline) {
|
||||
for(byte line=endline;line>0;line--) {
|
||||
for(byte x=0;x<BCOLS;x++) {
|
||||
WRITE_BOARD(x,line,READ_BOARD(x,line-1));
|
||||
}
|
||||
}
|
||||
// clears the top line
|
||||
ck_erase_line(0);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,768 @@
|
|||
0b11111111,
|
||||
0b10000001,
|
||||
0b10000001,
|
||||
0b10000001,
|
||||
0b10000001,
|
||||
0b10000001,
|
||||
0b10000001,
|
||||
0b11111111,
|
||||
0b11111111,
|
||||
0b10000001,
|
||||
0b10111101,
|
||||
0b10100101,
|
||||
0b10100101,
|
||||
0b10111101,
|
||||
0b10000001,
|
||||
0b11111111,
|
||||
0b11111111,
|
||||
0b10000001,
|
||||
0b10111101,
|
||||
0b10111101,
|
||||
0b10111101,
|
||||
0b10111101,
|
||||
0b10000001,
|
||||
0b11111111,
|
||||
0b11111111,
|
||||
0b10000001,
|
||||
0b10000001,
|
||||
0b10011001,
|
||||
0b10011001,
|
||||
0b10000001,
|
||||
0b10000001,
|
||||
0b11111111,
|
||||
0b11111111,
|
||||
0b10000001,
|
||||
0b10100101,
|
||||
0b10000001,
|
||||
0b10000001,
|
||||
0b10100101,
|
||||
0b10000001,
|
||||
0b11111111,
|
||||
0b11111111,
|
||||
0b11000011,
|
||||
0b10100101,
|
||||
0b10011001,
|
||||
0b10011001,
|
||||
0b10100101,
|
||||
0b11000011,
|
||||
0b11111111,
|
||||
0b11111111,
|
||||
0b00000100,
|
||||
0b00000100,
|
||||
0b00000100,
|
||||
0b11111111,
|
||||
0b01000000,
|
||||
0b01000000,
|
||||
0b01000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b11111111,
|
||||
0b00000000,
|
||||
0b11111111,
|
||||
0b11111111,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00101100,
|
||||
0b00101100,
|
||||
0b00101100,
|
||||
0b00101100,
|
||||
0b00101100,
|
||||
0b00101100,
|
||||
0b00101100,
|
||||
0b00101100,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b11110000,
|
||||
0b00011000,
|
||||
0b11001100,
|
||||
0b11101100,
|
||||
0b00101100,
|
||||
0b00101100,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00001111,
|
||||
0b00010000,
|
||||
0b00100111,
|
||||
0b00101111,
|
||||
0b00101100,
|
||||
0b00101100,
|
||||
0b00101100,
|
||||
0b01101100,
|
||||
0b11001100,
|
||||
0b00011100,
|
||||
0b11111000,
|
||||
0b11110000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00101100,
|
||||
0b00101110,
|
||||
0b00100111,
|
||||
0b00110000,
|
||||
0b00011111,
|
||||
0b00001111,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b11111111,
|
||||
0b11111111,
|
||||
0b11000011,
|
||||
0b11000011,
|
||||
0b11000011,
|
||||
0b11000011,
|
||||
0b11111111,
|
||||
0b11111111,
|
||||
0b11111111,
|
||||
0b10011001,
|
||||
0b10100101,
|
||||
0b11000011,
|
||||
0b11000011,
|
||||
0b10100101,
|
||||
0b10011001,
|
||||
0b11111111,
|
||||
0b11111111,
|
||||
0b10100101,
|
||||
0b11100111,
|
||||
0b10000001,
|
||||
0b10000001,
|
||||
0b11100111,
|
||||
0b10100101,
|
||||
0b11111111,
|
||||
0b10000000,
|
||||
0b10000000,
|
||||
0b10000000,
|
||||
0b10000000,
|
||||
0b10000000,
|
||||
0b10000000,
|
||||
0b10000000,
|
||||
0b11111111,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00011100,
|
||||
0b00011100,
|
||||
0b00011100,
|
||||
0b00011000,
|
||||
0b00011000,
|
||||
0b00000000,
|
||||
0b00011000,
|
||||
0b00000000,
|
||||
0b00110110,
|
||||
0b00110110,
|
||||
0b00100100,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00010011,
|
||||
0b00110011,
|
||||
0b01111110,
|
||||
0b00110110,
|
||||
0b00110111,
|
||||
0b01111110,
|
||||
0b00100100,
|
||||
0b00000000,
|
||||
0b00111100,
|
||||
0b01101110,
|
||||
0b01101000,
|
||||
0b00111110,
|
||||
0b00001011,
|
||||
0b01101011,
|
||||
0b00111110,
|
||||
0b00000000,
|
||||
0b00100001,
|
||||
0b01010010,
|
||||
0b00100100,
|
||||
0b00001000,
|
||||
0b00010010,
|
||||
0b00100101,
|
||||
0b01000010,
|
||||
0b00000000,
|
||||
0b00011000,
|
||||
0b00100100,
|
||||
0b00110100,
|
||||
0b00111000,
|
||||
0b01001101,
|
||||
0b01000110,
|
||||
0b00111001,
|
||||
0b00000000,
|
||||
0b00110000,
|
||||
0b00110000,
|
||||
0b00010000,
|
||||
0b00100000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000100,
|
||||
0b00001000,
|
||||
0b00011000,
|
||||
0b00010000,
|
||||
0b00011000,
|
||||
0b00001000,
|
||||
0b00000100,
|
||||
0b00000000,
|
||||
0b00010000,
|
||||
0b00001000,
|
||||
0b00001100,
|
||||
0b00000100,
|
||||
0b00001100,
|
||||
0b00001000,
|
||||
0b00010000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00010010,
|
||||
0b00001100,
|
||||
0b00111111,
|
||||
0b00001100,
|
||||
0b00010010,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00001000,
|
||||
0b00001000,
|
||||
0b00111110,
|
||||
0b00001000,
|
||||
0b00001000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00011000,
|
||||
0b00011000,
|
||||
0b00110000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00111110,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00110000,
|
||||
0b00110000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000010,
|
||||
0b00000100,
|
||||
0b00001000,
|
||||
0b00010000,
|
||||
0b00100000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00011100,
|
||||
0b00100110,
|
||||
0b01100011,
|
||||
0b01100011,
|
||||
0b01100011,
|
||||
0b00110010,
|
||||
0b00011100,
|
||||
0b00000000,
|
||||
0b00001100,
|
||||
0b00011100,
|
||||
0b00001100,
|
||||
0b00001100,
|
||||
0b00001100,
|
||||
0b00001100,
|
||||
0b00111111,
|
||||
0b00000000,
|
||||
0b00111110,
|
||||
0b01100011,
|
||||
0b00000111,
|
||||
0b00011110,
|
||||
0b00111100,
|
||||
0b01110000,
|
||||
0b01111111,
|
||||
0b00000000,
|
||||
0b00111111,
|
||||
0b00000110,
|
||||
0b00001100,
|
||||
0b00011110,
|
||||
0b00000011,
|
||||
0b01100011,
|
||||
0b00111110,
|
||||
0b00000000,
|
||||
0b00001110,
|
||||
0b00011110,
|
||||
0b00110110,
|
||||
0b01100110,
|
||||
0b01111111,
|
||||
0b00000110,
|
||||
0b00000110,
|
||||
0b00000000,
|
||||
0b01111110,
|
||||
0b01100000,
|
||||
0b01111110,
|
||||
0b00000011,
|
||||
0b00000011,
|
||||
0b01100011,
|
||||
0b00111110,
|
||||
0b00000000,
|
||||
0b00011110,
|
||||
0b00110000,
|
||||
0b01100000,
|
||||
0b01111110,
|
||||
0b01100011,
|
||||
0b01100011,
|
||||
0b00111110,
|
||||
0b00000000,
|
||||
0b01111111,
|
||||
0b00000011,
|
||||
0b00000110,
|
||||
0b00001100,
|
||||
0b00011000,
|
||||
0b00011000,
|
||||
0b00011000,
|
||||
0b00000000,
|
||||
0b00111100,
|
||||
0b01100010,
|
||||
0b01110010,
|
||||
0b00111100,
|
||||
0b01001111,
|
||||
0b01000011,
|
||||
0b00111110,
|
||||
0b00000000,
|
||||
0b00111110,
|
||||
0b01100011,
|
||||
0b01100011,
|
||||
0b00111111,
|
||||
0b00000011,
|
||||
0b00000110,
|
||||
0b00111100,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00011000,
|
||||
0b00011000,
|
||||
0b00000000,
|
||||
0b00011000,
|
||||
0b00011000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00011000,
|
||||
0b00011000,
|
||||
0b00000000,
|
||||
0b00011000,
|
||||
0b00011000,
|
||||
0b00110000,
|
||||
0b00000000,
|
||||
0b00000110,
|
||||
0b00001100,
|
||||
0b00011000,
|
||||
0b00110000,
|
||||
0b00011000,
|
||||
0b00001100,
|
||||
0b00000110,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00111110,
|
||||
0b00000000,
|
||||
0b00111110,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00110000,
|
||||
0b00011000,
|
||||
0b00001100,
|
||||
0b00000110,
|
||||
0b00001100,
|
||||
0b00011000,
|
||||
0b00110000,
|
||||
0b00000000,
|
||||
0b00111110,
|
||||
0b01111111,
|
||||
0b01100011,
|
||||
0b00000110,
|
||||
0b00011100,
|
||||
0b00000000,
|
||||
0b00011100,
|
||||
0b00000000,
|
||||
0b00111100,
|
||||
0b01000010,
|
||||
0b10011001,
|
||||
0b10100001,
|
||||
0b10100001,
|
||||
0b10011001,
|
||||
0b01000010,
|
||||
0b00111100,
|
||||
0b00011100,
|
||||
0b00110110,
|
||||
0b01100011,
|
||||
0b01100011,
|
||||
0b01111111,
|
||||
0b01100011,
|
||||
0b01100011,
|
||||
0b00000000,
|
||||
0b01111110,
|
||||
0b01100011,
|
||||
0b01100011,
|
||||
0b01111110,
|
||||
0b01100011,
|
||||
0b01100011,
|
||||
0b01111110,
|
||||
0b00000000,
|
||||
0b00011110,
|
||||
0b00110011,
|
||||
0b01100000,
|
||||
0b01100000,
|
||||
0b01100000,
|
||||
0b00110011,
|
||||
0b00011110,
|
||||
0b00000000,
|
||||
0b01111100,
|
||||
0b01100110,
|
||||
0b01100011,
|
||||
0b01100011,
|
||||
0b01100011,
|
||||
0b01100110,
|
||||
0b01111100,
|
||||
0b00000000,
|
||||
0b01111111,
|
||||
0b01100000,
|
||||
0b01100000,
|
||||
0b01111110,
|
||||
0b01100000,
|
||||
0b01100000,
|
||||
0b01111111,
|
||||
0b00000000,
|
||||
0b01111111,
|
||||
0b01100000,
|
||||
0b01100000,
|
||||
0b01111110,
|
||||
0b01100000,
|
||||
0b01100000,
|
||||
0b01100000,
|
||||
0b00000000,
|
||||
0b00011111,
|
||||
0b00110000,
|
||||
0b01100000,
|
||||
0b01100111,
|
||||
0b01100011,
|
||||
0b00110011,
|
||||
0b00011111,
|
||||
0b00000000,
|
||||
0b01100011,
|
||||
0b01100011,
|
||||
0b01100011,
|
||||
0b01111111,
|
||||
0b01100011,
|
||||
0b01100011,
|
||||
0b01100011,
|
||||
0b00000000,
|
||||
0b00111111,
|
||||
0b00001100,
|
||||
0b00001100,
|
||||
0b00001100,
|
||||
0b00001100,
|
||||
0b00001100,
|
||||
0b00111111,
|
||||
0b00000000,
|
||||
0b00000011,
|
||||
0b00000011,
|
||||
0b00000011,
|
||||
0b00000011,
|
||||
0b00000011,
|
||||
0b01100011,
|
||||
0b00111110,
|
||||
0b00000000,
|
||||
0b01100011,
|
||||
0b01100110,
|
||||
0b01101100,
|
||||
0b01111000,
|
||||
0b01111100,
|
||||
0b01101110,
|
||||
0b01100111,
|
||||
0b00000000,
|
||||
0b00110000,
|
||||
0b00110000,
|
||||
0b00110000,
|
||||
0b00110000,
|
||||
0b00110000,
|
||||
0b00110000,
|
||||
0b00111111,
|
||||
0b00000000,
|
||||
0b01100011,
|
||||
0b01110111,
|
||||
0b01111111,
|
||||
0b01101011,
|
||||
0b01100011,
|
||||
0b01100011,
|
||||
0b01100011,
|
||||
0b00000000,
|
||||
0b01100011,
|
||||
0b01110011,
|
||||
0b01111011,
|
||||
0b01111111,
|
||||
0b01101111,
|
||||
0b01100111,
|
||||
0b01100011,
|
||||
0b00000000,
|
||||
0b00111110,
|
||||
0b01100011,
|
||||
0b01100011,
|
||||
0b01100011,
|
||||
0b01100011,
|
||||
0b01100011,
|
||||
0b00111110,
|
||||
0b00000000,
|
||||
0b01111110,
|
||||
0b01100011,
|
||||
0b01100011,
|
||||
0b01100011,
|
||||
0b01111110,
|
||||
0b01100000,
|
||||
0b01100000,
|
||||
0b00000000,
|
||||
0b00111110,
|
||||
0b01100011,
|
||||
0b01100011,
|
||||
0b01100011,
|
||||
0b01101111,
|
||||
0b01100110,
|
||||
0b00111101,
|
||||
0b00000000,
|
||||
0b01111110,
|
||||
0b01100011,
|
||||
0b01100011,
|
||||
0b01100111,
|
||||
0b01111100,
|
||||
0b01101110,
|
||||
0b01100111,
|
||||
0b00000000,
|
||||
0b00111100,
|
||||
0b01100110,
|
||||
0b01100000,
|
||||
0b00111110,
|
||||
0b00000011,
|
||||
0b01100011,
|
||||
0b00111110,
|
||||
0b00000000,
|
||||
0b00111111,
|
||||
0b00001100,
|
||||
0b00001100,
|
||||
0b00001100,
|
||||
0b00001100,
|
||||
0b00001100,
|
||||
0b00001100,
|
||||
0b00000000,
|
||||
0b01100011,
|
||||
0b01100011,
|
||||
0b01100011,
|
||||
0b01100011,
|
||||
0b01100011,
|
||||
0b01100011,
|
||||
0b00111110,
|
||||
0b00000000,
|
||||
0b01100011,
|
||||
0b01100011,
|
||||
0b01100011,
|
||||
0b01110111,
|
||||
0b00111110,
|
||||
0b00011100,
|
||||
0b00001000,
|
||||
0b00000000,
|
||||
0b01100011,
|
||||
0b01100011,
|
||||
0b01100011,
|
||||
0b01101011,
|
||||
0b01111111,
|
||||
0b01110111,
|
||||
0b01100011,
|
||||
0b00000000,
|
||||
0b01100011,
|
||||
0b01110111,
|
||||
0b00111110,
|
||||
0b00011100,
|
||||
0b00111110,
|
||||
0b01110111,
|
||||
0b01100011,
|
||||
0b00000000,
|
||||
0b00110011,
|
||||
0b00110011,
|
||||
0b00110011,
|
||||
0b00011110,
|
||||
0b00001100,
|
||||
0b00001100,
|
||||
0b00001100,
|
||||
0b00000000,
|
||||
0b01111111,
|
||||
0b00000111,
|
||||
0b00001110,
|
||||
0b00011100,
|
||||
0b00111000,
|
||||
0b01110000,
|
||||
0b01111111,
|
||||
0b00000000,
|
||||
0b00011110,
|
||||
0b00011000,
|
||||
0b00011000,
|
||||
0b00011000,
|
||||
0b00011000,
|
||||
0b00011000,
|
||||
0b00011110,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00011110,
|
||||
0b00000110,
|
||||
0b00000110,
|
||||
0b00000110,
|
||||
0b00000110,
|
||||
0b00000110,
|
||||
0b00011110,
|
||||
0b00000000,
|
||||
0b00000000,
|
||||
0b00011000,
|
||||
0b00111100,
|
||||
0b01111110,
|
||||
0b00011000,
|
||||
0b00011000,
|
||||
0b00011000,
|
||||
0b00011000,
|
||||
0b00000000,
|
||||
0b00010000,
|
||||
0b00110000,
|
||||
0b01111111,
|
||||
0b01111111,
|
||||
0b00110000,
|
||||
0b00010000,
|
||||
0b00000000,
|
|
@ -0,0 +1,14 @@
|
|||
#ifndef FONTS_H
|
||||
#define FONTS_H
|
||||
|
||||
#pragma data_seg(Code)
|
||||
|
||||
unsigned char FONTS[127*8] = {
|
||||
|
||||
#include "fonts.body.h"
|
||||
|
||||
};
|
||||
|
||||
#pragma data_seg(Data)
|
||||
|
||||
#endif
|
|
@ -0,0 +1,257 @@
|
|||
#include <stdlib.h>
|
||||
|
||||
#define STARTBOARD_X 11 /* X start position of the board on the screen */
|
||||
#define STARTBOARD_Y 2 /* Y start position of the board on the screen */
|
||||
|
||||
#define BOARD_CHAR_LEFT 6
|
||||
#define BOARD_CHAR_RIGHT 6
|
||||
|
||||
//#define NCOLS 32 /* number of screen columns */
|
||||
//#define NROWS 24 /* number of screen rows, also board height */
|
||||
|
||||
#define CRUNCH_CHAR_1 13
|
||||
#define CRUNCH_COLOR_1 FG_BG(COLOR_BLACK, COLOR_GRAY)
|
||||
|
||||
#define CRUNCH_CHAR_2 32
|
||||
#define CRUNCH_COLOR_2 FG_BG(COLOR_BLACK, COLOR_BLACK)
|
||||
|
||||
#define POS_SCORE_X 23
|
||||
#define POS_SCORE_Y 1
|
||||
|
||||
#define POS_LEVEL_X 23
|
||||
#define POS_LEVEL_Y 7
|
||||
|
||||
#define POS_LINES_X 23
|
||||
#define POS_LINES_Y 13
|
||||
|
||||
#define POS_NEXT_X 1
|
||||
#define POS_NEXT_Y 1
|
||||
|
||||
#define NEXT_X (POS_NEXT_X+2)
|
||||
#define NEXT_Y (POS_NEXT_Y+3)
|
||||
|
||||
void bit_fx2(int sound) {
|
||||
// throw not implemented
|
||||
}
|
||||
|
||||
void bit_fx3(int sound) {
|
||||
// throw not implemented
|
||||
}
|
||||
|
||||
void updateScore();
|
||||
void drawPlayground();
|
||||
void gameOver();
|
||||
|
||||
void gr_drawpiece(sprite *p);
|
||||
void gr_erasepiece(sprite *p);
|
||||
|
||||
void gr_update_board();
|
||||
void gr_crunch_line(byte line, byte crunch_char, byte crunch_color);
|
||||
|
||||
// grahpic board
|
||||
// #include <stdio.h> // for sprintf
|
||||
// #include <sound.h>
|
||||
|
||||
#include "keyboard_input.h"
|
||||
#include "fonts.h"
|
||||
#include "pieces.h"
|
||||
#include "ckboard.h"
|
||||
|
||||
extern unsigned long score;
|
||||
|
||||
void right_pad_number(unsigned long number) {
|
||||
ultoa(number, tmp, DECIMAL);
|
||||
|
||||
int l = (int) strlen(tmp);
|
||||
int offset = 6-l;
|
||||
|
||||
for(int i=l;i>=0;i--) tmp[i+offset] = tmp[i]; // move to the right
|
||||
for(int i=0;i<offset;i++) tmp[i] = 32; // fill with spaces
|
||||
}
|
||||
|
||||
// update score table
|
||||
char tmp[32];
|
||||
void updateScore() {
|
||||
byte color = FG_BG(COLOR_WHITE,COLOR_BLACK);
|
||||
|
||||
right_pad_number(score);
|
||||
gr4_prints(POS_SCORE_X+1,POS_SCORE_Y+2,tmp,color);
|
||||
|
||||
right_pad_number((unsigned long)total_lines);
|
||||
gr4_prints(POS_LINES_X+1,POS_LINES_Y+2,tmp,color);
|
||||
|
||||
right_pad_number((unsigned long)level);
|
||||
gr4_prints(POS_LEVEL_X+1,POS_LEVEL_Y+2,tmp,color);
|
||||
}
|
||||
|
||||
#define FRAME_VERT 7
|
||||
#define FRAME_HORIZ 8
|
||||
|
||||
#define FRAME_NW_CORNER 9
|
||||
#define FRAME_NE_CORNER 10
|
||||
#define FRAME_SW_CORNER 11
|
||||
#define FRAME_SE_CORNER 12
|
||||
|
||||
void drawFrame(byte x, byte y, byte w, byte h, byte color) {
|
||||
byte i;
|
||||
for (i=1; i<w-1; i++) {
|
||||
gr4_tile(x+i, y , FRAME_VERT, color);
|
||||
gr4_tile(x+i, y+h-1, FRAME_VERT, color);
|
||||
}
|
||||
for (i=1; i<h-1; i++) {
|
||||
gr4_tile(x , y+i, FRAME_HORIZ, color);
|
||||
gr4_tile(x+w-1, y+i, FRAME_HORIZ, color);
|
||||
}
|
||||
|
||||
gr4_tile(x ,y , FRAME_NE_CORNER, color);
|
||||
gr4_tile(x+w-1 ,y , FRAME_NW_CORNER, color);
|
||||
gr4_tile(x ,y+h-1, FRAME_SE_CORNER, color);
|
||||
gr4_tile(x+w-1 ,y+h-1, FRAME_SW_CORNER, color);
|
||||
}
|
||||
|
||||
void fillFrame(byte x, byte y, byte w, byte h, byte ch, byte color) {
|
||||
byte i,j;
|
||||
for (i=0; i<w; i++) {
|
||||
for (j=0; j<h; j++) {
|
||||
gr4_tile(x+i, y+j, ch, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// draws the board
|
||||
void drawPlayground() {
|
||||
set_color(COLOR_DARK_BLUE);
|
||||
byte frame_color = FG_BG(COLOR_GRAY,COLOR_BLACK);
|
||||
byte text_color = FG_BG(COLOR_LIGHT_YELLOW,COLOR_BLACK);
|
||||
|
||||
// draw tetris board
|
||||
|
||||
byte bg = FG_BG(COLOR_BLACK, COLOR_DARK_BLUE);
|
||||
|
||||
// tetris frame
|
||||
fillFrame(0,0, 10,24, 16, bg);
|
||||
|
||||
fillFrame(STARTBOARD_X,STARTBOARD_Y,BCOLS,BROWS,32,FG_BG(COLOR_BLACK, COLOR_BLACK));
|
||||
drawFrame(STARTBOARD_X-1,STARTBOARD_Y-1,BCOLS+2,BROWS+2, frame_color);
|
||||
|
||||
fillFrame(22,0,10,24, 16, bg);
|
||||
fillFrame(0, 0,32, 1, 16, bg);
|
||||
fillFrame(0,23,32, 1, 16, bg);
|
||||
|
||||
drawFrame(POS_SCORE_X, POS_SCORE_Y, 8, 4, frame_color);
|
||||
drawFrame(POS_LEVEL_X, POS_LEVEL_Y, 8, 4, frame_color);
|
||||
drawFrame(POS_LINES_X, POS_LINES_Y, 8, 4, frame_color);
|
||||
|
||||
drawFrame(POS_NEXT_X , POS_NEXT_Y , 8, 8, frame_color);
|
||||
fillFrame(POS_NEXT_X+1 , POS_NEXT_Y+1 , 6, 6, 32, FG_BG(COLOR_BLACK, COLOR_BLACK));
|
||||
|
||||
gr4_prints(POS_SCORE_X+1, POS_SCORE_Y+1, "SCORE ", text_color);
|
||||
gr4_prints(POS_LEVEL_X+1, POS_LEVEL_Y+1, "LEVEL ", text_color);
|
||||
|
||||
gr4_prints(POS_LINES_X+1, POS_LINES_Y+1,"LINES ", text_color);
|
||||
gr4_prints(POS_NEXT_X +1, POS_NEXT_Y +1,"NEXT" , text_color);
|
||||
}
|
||||
|
||||
// displays "game over" and waits for return key
|
||||
void gameOver() {
|
||||
byte color = FG_BG(COLOR_LIGHT_YELLOW, COLOR_BLACK);
|
||||
byte frame_color = FG_BG(COLOR_GRAY,COLOR_BLACK);
|
||||
|
||||
byte y = (STARTBOARD_Y+BROWS)/2;
|
||||
|
||||
drawFrame(STARTBOARD_X-2, y-1,14,3, frame_color);
|
||||
|
||||
gr4_prints(STARTBOARD_X-1,y-0," GAME OVER ", FG_BG(COLOR_LIGHT_YELLOW,COLOR_BLACK));
|
||||
|
||||
// sound effect
|
||||
bit_fx2(7);
|
||||
|
||||
// since it's game over, there's no next piece
|
||||
gr_erasepiece(&piece_preview);
|
||||
|
||||
byte flip = 0;
|
||||
while(1) {
|
||||
flip++;
|
||||
if(test_key(KEY_RETURN)) break;
|
||||
if(flip < 60 ) color = FG_BG(COLOR_LIGHT_YELLOW ,COLOR_BLACK);
|
||||
else if(flip < 120 ) color = FG_BG(COLOR_DARK_BLUE ,COLOR_BLACK);
|
||||
else flip = 0;
|
||||
gr4_prints(STARTBOARD_X,y-0,"GAME OVER", color);
|
||||
}
|
||||
|
||||
while(test_key(KEY_RETURN));
|
||||
}
|
||||
|
||||
// erase piece from the screen
|
||||
void gr_erasepiece(sprite *p) {
|
||||
tile_offset *data = get_piece_offsets(p->piece, p->angle);
|
||||
int px = p->x;
|
||||
int py = p->y;
|
||||
|
||||
// are we erasing the "next" piece ?
|
||||
if(py==PIECE_IS_NEXT) {
|
||||
px = NEXT_X;
|
||||
py = NEXT_Y;
|
||||
}
|
||||
else {
|
||||
px += STARTBOARD_X;
|
||||
py += STARTBOARD_Y;
|
||||
}
|
||||
|
||||
for(byte t=0; t<4; t++) {
|
||||
int x = px + data->offset_x;
|
||||
int y = py + data->offset_y;
|
||||
data++;
|
||||
gr4_tile((byte)x,(byte)y,EMPTY_GR_CHAR,EMPTY_GR_COLOR);
|
||||
}
|
||||
}
|
||||
|
||||
// draw a piece on the screen
|
||||
void gr_drawpiece(sprite *p) {
|
||||
tile_offset *data = get_piece_offsets(p->piece, p->angle);
|
||||
int px = p->x;
|
||||
int py = p->y;
|
||||
|
||||
// are we drawing the "next" piece ?
|
||||
if(py==PIECE_IS_NEXT) {
|
||||
px = NEXT_X;
|
||||
py = NEXT_Y;
|
||||
}
|
||||
else {
|
||||
px += STARTBOARD_X;
|
||||
py += STARTBOARD_Y;
|
||||
}
|
||||
|
||||
byte piece = p->piece;
|
||||
for(byte t=0; t<4; t++) {
|
||||
int x = px; byte x1 = data->offset_x; x+= (int) x1;
|
||||
int y = py; byte y1 = data->offset_y; y+= (int) y1;
|
||||
data++;
|
||||
/*
|
||||
int x = px + data[t].offset_x;
|
||||
int y = py + data[t].offset_y;
|
||||
*/
|
||||
byte ch = piece_chars[piece]; //piece_chars[p->piece];
|
||||
byte col = piece_colors[piece]; //piece_colors[p->piece];
|
||||
gr4_tile((byte)x,(byte)y,ch,col);
|
||||
}
|
||||
}
|
||||
|
||||
// fills the specified line with an empty character
|
||||
void gr_crunch_line(byte line, byte crunch_char, byte crunch_color) {
|
||||
for(byte i=0; i<BCOLS; i++) {
|
||||
gr4_tile(STARTBOARD_X+i, STARTBOARD_Y+line, crunch_char, crunch_color);
|
||||
}
|
||||
}
|
||||
|
||||
void gr_update_board() {
|
||||
byte tile,ch,col;
|
||||
for(byte line=0;line<BROWS;line++) {
|
||||
for(byte column=0;column<BCOLS;column++) {
|
||||
tile = READ_BOARD(column,line);
|
||||
ch = piece_chars[tile];
|
||||
col = piece_colors[tile];
|
||||
gr4_tile(STARTBOARD_X+column, STARTBOARD_Y+line, ch, col);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
#include <stdlib.h> // for rand()
|
||||
|
||||
#include "keyboard_input.h"
|
||||
|
||||
#pragma data_seg(Code)
|
||||
|
||||
const byte *logo =
|
||||
// 12345678901234567890123456789012
|
||||
"TTTTT EEEE XXXXX RRRR I SSS "
|
||||
" T E X R R I S S"
|
||||
" T E X R R I S "
|
||||
" T EEE X RRRR I SSS "
|
||||
" T E X R R I S"
|
||||
" T E X R R I S S"
|
||||
" T EEEE X R R I SSS ";
|
||||
|
||||
#pragma data_seg(Data)
|
||||
|
||||
void drawLogo() {
|
||||
byte *s = logo;
|
||||
for(byte r=0;r<7;r++) {
|
||||
for(byte c=0;c<32;c++) {
|
||||
byte tile = 0;
|
||||
switch(*s++) {
|
||||
case 'T': tile = 1; break;
|
||||
case 'E': tile = 2; break;
|
||||
case 'X': tile = 3; break;
|
||||
case 'R': tile = 4; break;
|
||||
case 'I': tile = 5; break;
|
||||
case 'S': tile = 6; break;
|
||||
}
|
||||
if(tile) {
|
||||
byte ch = piece_chars[tile];
|
||||
byte col = piece_colors[tile];
|
||||
gr4_tile(c,r+3,ch,col);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// introduction screen
|
||||
void introScreen() {
|
||||
TMS_INIT(SCREEN2_TABLE);
|
||||
SCREEN2_FILL();
|
||||
screen2_square_sprites();
|
||||
set_color(COLOR_BLACK);
|
||||
|
||||
// simulate cls (TODO improve speed)
|
||||
fillFrame(0, 0, 32, 24, 32, FG_BG(COLOR_BLACK, COLOR_BLACK));
|
||||
|
||||
drawLogo();
|
||||
|
||||
gr4_prints(3,13,"(C) 2021 ANTONINO PORCINO" , FG_BG(COLOR_LIGHT_YELLOW,COLOR_BLACK));
|
||||
gr4_prints(2,18,"USE ARROWS+SPACE OR JOYSTICK", FG_BG(COLOR_WHITE ,COLOR_BLACK));
|
||||
gr4_prints(5,20,"PRESS RETURN TO START" , FG_BG(COLOR_WHITE ,COLOR_BLACK));
|
||||
|
||||
// wait for key released
|
||||
while(test_key(KEY_RETURN));
|
||||
|
||||
// wait for key press and do the coloured animation
|
||||
while(!test_key(KEY_RETURN)) {
|
||||
// TODO music
|
||||
rand(); // extract random numbers, making rand() more "random"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
#ifndef KEYBOARD_H
|
||||
#define KEYBOARD_H
|
||||
|
||||
/* keyboard defititions */
|
||||
#define KEY_LEFT 'J'
|
||||
#define KEY_RIGHT 'L'
|
||||
#define KEY_DOWN 'K'
|
||||
#define KEY_DROP ' '
|
||||
#define KEY_ROTATE 'I'
|
||||
#define KEY_RETURN 0x0d
|
||||
|
||||
byte test_key(byte key);
|
||||
byte read_keyboard();
|
||||
byte player_input();
|
||||
|
||||
// test a specific key
|
||||
byte test_key(byte key) {
|
||||
return read_keyboard() == key ? 1 : 0;
|
||||
}
|
||||
|
||||
// reads the keyboard and return the key pressed
|
||||
byte read_keyboard() {
|
||||
return woz_readkey();
|
||||
}
|
||||
|
||||
byte player_input() {
|
||||
return read_keyboard();
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,15 @@
|
|||
|
||||
|
||||
void gr4_tile(byte x, byte y, byte ch, byte col) {
|
||||
byte *source = &FONTS[(word)ch*8];
|
||||
word addr = x*8 + y*256;
|
||||
set_vram_write_addr(SCREEN2_PATTERN_TABLE + addr); for(byte i=0;i<8;i++) { TMS_WRITE_DATA_PORT(source[i]); NOP; /*NOP;*/ /*NOP; NOP;*/ /*NOP; NOP; NOP; NOP;*/ }
|
||||
set_vram_write_addr(SCREEN2_COLOR_TABLE + addr); for(byte i=0;i<8;i++) { TMS_WRITE_DATA_PORT(col); NOP; /*NOP;*/ /*NOP; NOP;*/ /*NOP; NOP; NOP; NOP;*/ }
|
||||
}
|
||||
|
||||
void gr4_prints(byte x, byte y, byte *s, byte color) {
|
||||
byte c;
|
||||
while(c=*s++) {
|
||||
gr4_tile(x++, y, c, color);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
SET COMPILER=SDCC
|
||||
|
||||
@IF %COMPILER%==ZCC zcc +laser500 tetris500.c -o tetris500.bin -I..\lib500 -create-app -Cz--audio --list -m -s -DZCC
|
||||
@IF %COMPILER%==SDCC zcc +laser500 tetris500.c -o tetris500.bin -I..\lib500 -create-app -Cz--audio --list -m -s -DSDCC -compiler sdcc -SO3
|
||||
|
||||
@copy tetris500.bin ..\..\autoload.bin
|
||||
@cd ..
|
||||
@cd ..
|
||||
@call node makeautoload
|
||||
@cd software\tetris
|
||||
|
|
@ -0,0 +1,588 @@
|
|||
function encode(s) {
|
||||
let b = 0;
|
||||
for(let t=0;t<s.length;t++) {
|
||||
|
||||
if(s.charAt(t) != ".") {
|
||||
b |= 1<<t;
|
||||
}
|
||||
}
|
||||
let msg = `00000000`+b.toString(2);
|
||||
console.log(` 0b${msg.substr(msg.length-8)},`);
|
||||
}
|
||||
|
||||
// char $0a.");
|
||||
encode("........");
|
||||
encode("........");
|
||||
encode("........");
|
||||
encode("........");
|
||||
encode("........");
|
||||
encode("........");
|
||||
encode("........");
|
||||
encode("........");
|
||||
// char $0aX");
|
||||
encode("...XXX..");
|
||||
encode("...XXX..");
|
||||
encode("...XXX..");
|
||||
encode("...XX...");
|
||||
encode("...XX...");
|
||||
encode("........");
|
||||
encode("...XX...");
|
||||
encode("........");
|
||||
// char $0a2");
|
||||
encode("..XX.XX.");
|
||||
encode("..XX.XX.");
|
||||
encode("..X..X..");
|
||||
encode("........");
|
||||
encode("........");
|
||||
encode("........");
|
||||
encode("........");
|
||||
encode("........");
|
||||
// char $0a3");
|
||||
encode("...X..XX");
|
||||
encode("..XX..XX");
|
||||
encode(".XXXXXX.");
|
||||
encode("..XX.XX.");
|
||||
encode("..XX.XXX");
|
||||
encode(".XXXXXX.");
|
||||
encode("..X..X..");
|
||||
encode("........");
|
||||
// char $0a4");
|
||||
encode("..XXXX..");
|
||||
encode(".XX.XXX.");
|
||||
encode(".XX.X...");
|
||||
encode("..XXXXX.");
|
||||
encode("....X.XX");
|
||||
encode(".XX.X.XX");
|
||||
encode("..XXXXX.");
|
||||
encode("........");
|
||||
// char $0a5");
|
||||
encode("..X....X");
|
||||
encode(".X.X..X.");
|
||||
encode("..X..X..");
|
||||
encode("....X...");
|
||||
encode("...X..X.");
|
||||
encode("..X..X.X");
|
||||
encode(".X....X.");
|
||||
encode("........");
|
||||
// char $0a6");
|
||||
encode("...XX...");
|
||||
encode("..X..X..");
|
||||
encode("..XX.X..");
|
||||
encode("..XXX...");
|
||||
encode(".X..XX.X");
|
||||
encode(".X...XX.");
|
||||
encode("..XXX..X");
|
||||
encode("........");
|
||||
// char $0a7");
|
||||
encode("..XX....");
|
||||
encode("..XX....");
|
||||
encode("...X....");
|
||||
encode("..X.....");
|
||||
encode("........");
|
||||
encode("........");
|
||||
encode("........");
|
||||
encode("........");
|
||||
// char $0a8");
|
||||
encode(".....X..");
|
||||
encode("....X...");
|
||||
encode("...XX...");
|
||||
encode("...X....");
|
||||
encode("...XX...");
|
||||
encode("....X...");
|
||||
encode(".....X..");
|
||||
encode("........");
|
||||
// char $0a9");
|
||||
encode("...X....");
|
||||
encode("....X...");
|
||||
encode("....XX..");
|
||||
encode(".....X..");
|
||||
encode("....XX..");
|
||||
encode("....X...");
|
||||
encode("...X....");
|
||||
encode("........");
|
||||
// char $0aa");
|
||||
encode("........");
|
||||
encode("...X..X.");
|
||||
encode("....XX..");
|
||||
encode("..XXXXXX");
|
||||
encode("....XX..");
|
||||
encode("...X..X.");
|
||||
encode("........");
|
||||
encode("........");
|
||||
// char $0ab");
|
||||
encode("........");
|
||||
encode("....X...");
|
||||
encode("....X...");
|
||||
encode("..XXXXX.");
|
||||
encode("....X...");
|
||||
encode("....X...");
|
||||
encode("........");
|
||||
encode("........");
|
||||
// char $0ac");
|
||||
encode("........");
|
||||
encode("........");
|
||||
encode("........");
|
||||
encode("........");
|
||||
encode("...XX...");
|
||||
encode("...XX...");
|
||||
encode("..XX....");
|
||||
encode("........");
|
||||
// char $0ad");
|
||||
encode("........");
|
||||
encode("........");
|
||||
encode("........");
|
||||
encode("..XXXXX.");
|
||||
encode("........");
|
||||
encode("........");
|
||||
encode("........");
|
||||
encode("........");
|
||||
// char $0ae");
|
||||
encode("........");
|
||||
encode("........");
|
||||
encode("........");
|
||||
encode("........");
|
||||
encode("........");
|
||||
encode("..XX....");
|
||||
encode("..XX....");
|
||||
encode("........");
|
||||
// char $0af");
|
||||
encode("........");
|
||||
encode("......X.");
|
||||
encode(".....X..");
|
||||
encode("....X...");
|
||||
encode("...X....");
|
||||
encode("..X.....");
|
||||
encode("........");
|
||||
encode("........");
|
||||
// char $0b.");
|
||||
encode("...XXX..");
|
||||
encode("..X..XX.");
|
||||
encode(".XX...XX");
|
||||
encode(".XX...XX");
|
||||
encode(".XX...XX");
|
||||
encode("..XX..X.");
|
||||
encode("...XXX..");
|
||||
encode("........");
|
||||
// char $0bX");
|
||||
encode("....XX..");
|
||||
encode("...XXX..");
|
||||
encode("....XX..");
|
||||
encode("....XX..");
|
||||
encode("....XX..");
|
||||
encode("....XX..");
|
||||
encode("..XXXXXX");
|
||||
encode("........");
|
||||
// char $0b2");
|
||||
encode("..XXXXX.");
|
||||
encode(".XX...XX");
|
||||
encode(".....XXX");
|
||||
encode("...XXXX.");
|
||||
encode("..XXXX..");
|
||||
encode(".XXX....");
|
||||
encode(".XXXXXXX");
|
||||
encode("........");
|
||||
// char $0b3");
|
||||
encode("..XXXXXX");
|
||||
encode(".....XX.");
|
||||
encode("....XX..");
|
||||
encode("...XXXX.");
|
||||
encode("......XX");
|
||||
encode(".XX...XX");
|
||||
encode("..XXXXX.");
|
||||
encode("........");
|
||||
// char $0b4");
|
||||
encode("....XXX.");
|
||||
encode("...XXXX.");
|
||||
encode("..XX.XX.");
|
||||
encode(".XX..XX.");
|
||||
encode(".XXXXXXX");
|
||||
encode(".....XX.");
|
||||
encode(".....XX.");
|
||||
encode("........");
|
||||
// char $0b5");
|
||||
encode(".XXXXXX.");
|
||||
encode(".XX.....");
|
||||
encode(".XXXXXX.");
|
||||
encode("......XX");
|
||||
encode("......XX");
|
||||
encode(".XX...XX");
|
||||
encode("..XXXXX.");
|
||||
encode("........");
|
||||
// char $0b6");
|
||||
encode("...XXXX.");
|
||||
encode("..XX....");
|
||||
encode(".XX.....");
|
||||
encode(".XXXXXX.");
|
||||
encode(".XX...XX");
|
||||
encode(".XX...XX");
|
||||
encode("..XXXXX.");
|
||||
encode("........");
|
||||
// char $0b7");
|
||||
encode(".XXXXXXX");
|
||||
encode("......XX");
|
||||
encode(".....XX.");
|
||||
encode("....XX..");
|
||||
encode("...XX...");
|
||||
encode("...XX...");
|
||||
encode("...XX...");
|
||||
encode("........");
|
||||
// char $0b8");
|
||||
encode("..XXXX..");
|
||||
encode(".XX...X.");
|
||||
encode(".XXX..X.");
|
||||
encode("..XXXX..");
|
||||
encode(".X..XXXX");
|
||||
encode(".X....XX");
|
||||
encode("..XXXXX.");
|
||||
encode("........");
|
||||
// char $0b9");
|
||||
encode("..XXXXX.");
|
||||
encode(".XX...XX");
|
||||
encode(".XX...XX");
|
||||
encode("..XXXXXX");
|
||||
encode("......XX");
|
||||
encode(".....XX.");
|
||||
encode("..XXXX..");
|
||||
encode("........");
|
||||
// char $0ba");
|
||||
encode("........");
|
||||
encode("...XX...");
|
||||
encode("...XX...");
|
||||
encode("........");
|
||||
encode("...XX...");
|
||||
encode("...XX...");
|
||||
encode("........");
|
||||
encode("........");
|
||||
// char $0bb");
|
||||
encode("........");
|
||||
encode("...XX...");
|
||||
encode("...XX...");
|
||||
encode("........");
|
||||
encode("...XX...");
|
||||
encode("...XX...");
|
||||
encode("..XX....");
|
||||
encode("........");
|
||||
// char $0bc");
|
||||
encode(".....XX.");
|
||||
encode("....XX..");
|
||||
encode("...XX...");
|
||||
encode("..XX....");
|
||||
encode("...XX...");
|
||||
encode("....XX..");
|
||||
encode(".....XX.");
|
||||
encode("........");
|
||||
// char $0bd");
|
||||
encode("........");
|
||||
encode("........");
|
||||
encode("..XXXXX.");
|
||||
encode("........");
|
||||
encode("..XXXXX.");
|
||||
encode("........");
|
||||
encode("........");
|
||||
encode("........");
|
||||
// char $0be");
|
||||
encode("..XX....");
|
||||
encode("...XX...");
|
||||
encode("....XX..");
|
||||
encode(".....XX.");
|
||||
encode("....XX..");
|
||||
encode("...XX...");
|
||||
encode("..XX....");
|
||||
encode("........");
|
||||
// char $0bf");
|
||||
encode("..XXXXX.");
|
||||
encode(".XXXXXXX");
|
||||
encode(".XX...XX");
|
||||
encode(".....XX.");
|
||||
encode("...XXX..");
|
||||
encode("........");
|
||||
encode("...XXX..");
|
||||
encode("........");
|
||||
// char $08.");
|
||||
encode("..XXXX..");
|
||||
encode(".X....X.");
|
||||
encode("X..XX..X");
|
||||
encode("X.X....X");
|
||||
encode("X.X....X");
|
||||
encode("X..XX..X");
|
||||
encode(".X....X.");
|
||||
encode("..XXXX..");
|
||||
// char $08X");
|
||||
encode("...XXX..");
|
||||
encode("..XX.XX.");
|
||||
encode(".XX...XX");
|
||||
encode(".XX...XX");
|
||||
encode(".XXXXXXX");
|
||||
encode(".XX...XX");
|
||||
encode(".XX...XX");
|
||||
encode("........");
|
||||
// char $082");
|
||||
encode(".XXXXXX.");
|
||||
encode(".XX...XX");
|
||||
encode(".XX...XX");
|
||||
encode(".XXXXXX.");
|
||||
encode(".XX...XX");
|
||||
encode(".XX...XX");
|
||||
encode(".XXXXXX.");
|
||||
encode("........");
|
||||
// char $083");
|
||||
encode("...XXXX.");
|
||||
encode("..XX..XX");
|
||||
encode(".XX.....");
|
||||
encode(".XX.....");
|
||||
encode(".XX.....");
|
||||
encode("..XX..XX");
|
||||
encode("...XXXX.");
|
||||
encode("........");
|
||||
// char $084");
|
||||
encode(".XXXXX..");
|
||||
encode(".XX..XX.");
|
||||
encode(".XX...XX");
|
||||
encode(".XX...XX");
|
||||
encode(".XX...XX");
|
||||
encode(".XX..XX.");
|
||||
encode(".XXXXX..");
|
||||
encode("........");
|
||||
// char $085");
|
||||
encode(".XXXXXXX");
|
||||
encode(".XX.....");
|
||||
encode(".XX.....");
|
||||
encode(".XXXXXX.");
|
||||
encode(".XX.....");
|
||||
encode(".XX.....");
|
||||
encode(".XXXXXXX");
|
||||
encode("........");
|
||||
// char $086");
|
||||
encode(".XXXXXXX");
|
||||
encode(".XX.....");
|
||||
encode(".XX.....");
|
||||
encode(".XXXXXX.");
|
||||
encode(".XX.....");
|
||||
encode(".XX.....");
|
||||
encode(".XX.....");
|
||||
encode("........");
|
||||
// char $087");
|
||||
encode("...XXXXX");
|
||||
encode("..XX....");
|
||||
encode(".XX.....");
|
||||
encode(".XX..XXX");
|
||||
encode(".XX...XX");
|
||||
encode("..XX..XX");
|
||||
encode("...XXXXX");
|
||||
encode("........");
|
||||
// char $088");
|
||||
encode(".XX...XX");
|
||||
encode(".XX...XX");
|
||||
encode(".XX...XX");
|
||||
encode(".XXXXXXX");
|
||||
encode(".XX...XX");
|
||||
encode(".XX...XX");
|
||||
encode(".XX...XX");
|
||||
encode("........");
|
||||
// char $089");
|
||||
encode("..XXXXXX");
|
||||
encode("....XX..");
|
||||
encode("....XX..");
|
||||
encode("....XX..");
|
||||
encode("....XX..");
|
||||
encode("....XX..");
|
||||
encode("..XXXXXX");
|
||||
encode("........");
|
||||
// char $08a");
|
||||
encode("......XX");
|
||||
encode("......XX");
|
||||
encode("......XX");
|
||||
encode("......XX");
|
||||
encode("......XX");
|
||||
encode(".XX...XX");
|
||||
encode("..XXXXX.");
|
||||
encode("........");
|
||||
// char $08b");
|
||||
encode(".XX...XX");
|
||||
encode(".XX..XX.");
|
||||
encode(".XX.XX..");
|
||||
encode(".XXXX...");
|
||||
encode(".XXXXX..");
|
||||
encode(".XX.XXX.");
|
||||
encode(".XX..XXX");
|
||||
encode("........");
|
||||
// char $08c");
|
||||
encode("..XX....");
|
||||
encode("..XX....");
|
||||
encode("..XX....");
|
||||
encode("..XX....");
|
||||
encode("..XX....");
|
||||
encode("..XX....");
|
||||
encode("..XXXXXX");
|
||||
encode("........");
|
||||
// char $08d");
|
||||
encode(".XX...XX");
|
||||
encode(".XXX.XXX");
|
||||
encode(".XXXXXXX");
|
||||
encode(".XX.X.XX");
|
||||
encode(".XX...XX");
|
||||
encode(".XX...XX");
|
||||
encode(".XX...XX");
|
||||
encode("........");
|
||||
// char $08e");
|
||||
encode(".XX...XX");
|
||||
encode(".XXX..XX");
|
||||
encode(".XXXX.XX");
|
||||
encode(".XXXXXXX");
|
||||
encode(".XX.XXXX");
|
||||
encode(".XX..XXX");
|
||||
encode(".XX...XX");
|
||||
encode("........");
|
||||
// char $08f");
|
||||
encode("..XXXXX.");
|
||||
encode(".XX...XX");
|
||||
encode(".XX...XX");
|
||||
encode(".XX...XX");
|
||||
encode(".XX...XX");
|
||||
encode(".XX...XX");
|
||||
encode("..XXXXX.");
|
||||
encode("........");
|
||||
// char $09.");
|
||||
encode(".XXXXXX.");
|
||||
encode(".XX...XX");
|
||||
encode(".XX...XX");
|
||||
encode(".XX...XX");
|
||||
encode(".XXXXXX.");
|
||||
encode(".XX.....");
|
||||
encode(".XX.....");
|
||||
encode("........");
|
||||
// char $09X");
|
||||
encode("..XXXXX.");
|
||||
encode(".XX...XX");
|
||||
encode(".XX...XX");
|
||||
encode(".XX...XX");
|
||||
encode(".XX.XXXX");
|
||||
encode(".XX..XX.");
|
||||
encode("..XXXX.X");
|
||||
encode("........");
|
||||
// char $092");
|
||||
encode(".XXXXXX.");
|
||||
encode(".XX...XX");
|
||||
encode(".XX...XX");
|
||||
encode(".XX..XXX");
|
||||
encode(".XXXXX..");
|
||||
encode(".XX.XXX.");
|
||||
encode(".XX..XXX");
|
||||
encode("........");
|
||||
// char $093");
|
||||
encode("..XXXX..");
|
||||
encode(".XX..XX.");
|
||||
encode(".XX.....");
|
||||
encode("..XXXXX.");
|
||||
encode("......XX");
|
||||
encode(".XX...XX");
|
||||
encode("..XXXXX.");
|
||||
encode("........");
|
||||
// char $094");
|
||||
encode("..XXXXXX");
|
||||
encode("....XX..");
|
||||
encode("....XX..");
|
||||
encode("....XX..");
|
||||
encode("....XX..");
|
||||
encode("....XX..");
|
||||
encode("....XX..");
|
||||
encode("........");
|
||||
// char $095");
|
||||
encode(".XX...XX");
|
||||
encode(".XX...XX");
|
||||
encode(".XX...XX");
|
||||
encode(".XX...XX");
|
||||
encode(".XX...XX");
|
||||
encode(".XX...XX");
|
||||
encode("..XXXXX.");
|
||||
encode("........");
|
||||
// char $096");
|
||||
encode(".XX...XX");
|
||||
encode(".XX...XX");
|
||||
encode(".XX...XX");
|
||||
encode(".XXX.XXX");
|
||||
encode("..XXXXX.");
|
||||
encode("...XXX..");
|
||||
encode("....X...");
|
||||
encode("........");
|
||||
// char $097");
|
||||
encode(".XX...XX");
|
||||
encode(".XX...XX");
|
||||
encode(".XX...XX");
|
||||
encode(".XX.X.XX");
|
||||
encode(".XXXXXXX");
|
||||
encode(".XXX.XXX");
|
||||
encode(".XX...XX");
|
||||
encode("........");
|
||||
// char $098");
|
||||
encode(".XX...XX");
|
||||
encode(".XXX.XXX");
|
||||
encode("..XXXXX.");
|
||||
encode("...XXX..");
|
||||
encode("..XXXXX.");
|
||||
encode(".XXX.XXX");
|
||||
encode(".XX...XX");
|
||||
encode("........");
|
||||
// char $099");
|
||||
encode("..XX..XX");
|
||||
encode("..XX..XX");
|
||||
encode("..XX..XX");
|
||||
encode("...XXXX.");
|
||||
encode("....XX..");
|
||||
encode("....XX..");
|
||||
encode("....XX..");
|
||||
encode("........");
|
||||
// char $09a");
|
||||
encode(".XXXXXXX");
|
||||
encode(".....XXX");
|
||||
encode("....XXX.");
|
||||
encode("...XXX..");
|
||||
encode("..XXX...");
|
||||
encode(".XXX....");
|
||||
encode(".XXXXXXX");
|
||||
encode("........");
|
||||
// char $09b");
|
||||
encode("...XXXX.");
|
||||
encode("...XX...");
|
||||
encode("...XX...");
|
||||
encode("...XX...");
|
||||
encode("...XX...");
|
||||
encode("...XX...");
|
||||
encode("...XXXX.");
|
||||
encode("........");
|
||||
// char $09c");
|
||||
encode("........");
|
||||
encode("........");
|
||||
encode("........");
|
||||
encode("........");
|
||||
encode("........");
|
||||
encode("........");
|
||||
encode("........");
|
||||
encode("........");
|
||||
// char $09d");
|
||||
encode("...XXXX.");
|
||||
encode(".....XX.");
|
||||
encode(".....XX.");
|
||||
encode(".....XX.");
|
||||
encode(".....XX.");
|
||||
encode(".....XX.");
|
||||
encode("...XXXX.");
|
||||
encode("........");
|
||||
// char $09e");
|
||||
encode("........");
|
||||
encode("...XX...");
|
||||
encode("..XXXX..");
|
||||
encode(".XXXXXX.");
|
||||
encode("...XX...");
|
||||
encode("...XX...");
|
||||
encode("...XX...");
|
||||
encode("...XX...");
|
||||
// char $09f");
|
||||
encode("........");
|
||||
encode("...X....");
|
||||
encode("..XX....");
|
||||
encode(".XXXXXXX");
|
||||
encode(".XXXXXXX");
|
||||
encode("..XX....");
|
||||
encode("...X....");
|
||||
encode("........");
|
|
@ -0,0 +1,58 @@
|
|||
#ifndef PIECES_H
|
||||
#define PIECES_H
|
||||
|
||||
#include "types.h"
|
||||
|
||||
#define NUMPIECES 7 // number of tetrominos in tetris
|
||||
#define NUMTILES 4 // number of tiles in a piece
|
||||
#define NUMROT 4 // number of rotations of a piece
|
||||
|
||||
// offset of a single tile composing a piece
|
||||
typedef struct {
|
||||
byte offset_x;
|
||||
byte offset_y;
|
||||
} tile_offset;
|
||||
|
||||
tile_offset *get_piece_offsets(byte piece, byte angle);
|
||||
|
||||
#pragma data_seg(Code)
|
||||
|
||||
tile_offset pieces_XY[NUMPIECES*NUMTILES*NUMROT] = {
|
||||
{+1,+1} , {+2,+1} , {+3,+1} , {+1,+2} , // L
|
||||
{+2,+0} , {+2,+1} , {+2,+2} , {+3,+2} ,
|
||||
{+3,+0} , {+1,+1} , {+2,+1} , {+3,+1} ,
|
||||
{+1,+0} , {+2,+0} , {+2,+1} , {+2,+2} ,
|
||||
{+1,+1} , {+2,+1} , {+3,+1} , {+3,+2} , // J
|
||||
{+2,+0} , {+3,+0} , {+2,+1} , {+2,+2} ,
|
||||
{+1,+0} , {+1,+1} , {+2,+1} , {+3,+1} ,
|
||||
{+2,+0} , {+2,+1} , {+1,+2} , {+2,+2} ,
|
||||
{+1,+0} , {+0,+1} , {+1,+1} , {+2,+1} , // T
|
||||
{+1,+0} , {+0,+1} , {+1,+1} , {+1,+2} ,
|
||||
{+0,+1} , {+1,+1} , {+2,+1} , {+1,+2} ,
|
||||
{+1,+0} , {+1,+1} , {+2,+1} , {+1,+2} ,
|
||||
{+0,+1} , {+1,+1} , {+2,+1} , {+3,+1} , // I
|
||||
{+1,+0} , {+1,+1} , {+1,+2} , {+1,+3} ,
|
||||
{+0,+1} , {+1,+1} , {+2,+1} , {+3,+1} ,
|
||||
{+1,+0} , {+1,+1} , {+1,+2} , {+1,+3} ,
|
||||
{+1,+0} , {+2,+0} , {+1,+1} , {+2,+1} , // O
|
||||
{+1,+0} , {+2,+0} , {+1,+1} , {+2,+1} ,
|
||||
{+1,+0} , {+2,+0} , {+1,+1} , {+2,+1} ,
|
||||
{+1,+0} , {+2,+0} , {+1,+1} , {+2,+1} ,
|
||||
{+2,+0} , {+3,+0} , {+1,+1} , {+2,+1} , // S
|
||||
{+1,+0} , {+1,+1} , {+2,+1} , {+2,+2} ,
|
||||
{+2,+0} , {+3,+0} , {+1,+1} , {+2,+1} ,
|
||||
{+1,+0} , {+1,+1} , {+2,+1} , {+2,+2} ,
|
||||
{+1,+0} , {+2,+0} , {+2,+1} , {+3,+1} , // Z
|
||||
{+2,+0} , {+1,+1} , {+2,+1} , {+1,+2} ,
|
||||
{+1,+0} , {+2,+0} , {+2,+1} , {+3,+1} ,
|
||||
{+2,+0} , {+1,+1} , {+2,+1} , {+1,+2}
|
||||
};
|
||||
|
||||
#pragma data_seg(Data)
|
||||
|
||||
// given a piece number and an angle returns the 4 byte "offsets" of the piece
|
||||
tile_offset *get_piece_offsets(byte piece, byte angle) {
|
||||
return &pieces_XY[(piece*sizeof(tile_offset)*4*2)+angle*4];
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,16 @@
|
|||
#ifndef SPRITE_H
|
||||
#define SPRITE_H
|
||||
|
||||
// tetromino sprite
|
||||
typedef struct {
|
||||
int x; // signed integers to allow negative board positions
|
||||
int y; // -1 means piece is preview ("next")
|
||||
byte piece;
|
||||
byte angle;
|
||||
} sprite;
|
||||
|
||||
INLINE void sprite_copy(sprite *to, sprite *from) {
|
||||
memcpy(to, from, sizeof(sprite));
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,23 @@
|
|||
@rem === BUILD TETRIS ===
|
||||
|
||||
@SET TARGET=tetris
|
||||
|
||||
|
||||
@rem @echo ======================== VIC20 ===================================================
|
||||
@rem call kickc -t VIC20_8K -D=VIC20 %TARGET%.c -o %TARGET%_vic20.prg -e
|
||||
@rem copy %TARGET%.prg %TARGET%_vic20.prg
|
||||
|
||||
|
||||
@echo ======================== APPLE 1 =================================================
|
||||
call kickc -t apple1 -D=APPLE1 %TARGET%.c -o %TARGET%_apple1.prg -e -Xassembler="-symbolfile"
|
||||
copy %TARGET%.prg %TARGET%_apple1.prg
|
||||
|
||||
@rem call node hexdump > test_apple1.woz
|
||||
call node bindump
|
||||
|
||||
@rem @del *.klog
|
||||
|
||||
@del *.vs
|
||||
@del *.dbg
|
||||
@del tetris.prg
|
||||
@del tetris_apple1.prg
|
|
@ -0,0 +1,404 @@
|
|||
// TODO-KICKC: NPE when -t VIC20_8K is missing
|
||||
// TODO-KICKC: NPE when array initializer contains unesisting macro
|
||||
// TODO-KICKC: #include "keyboard.h" switches to c64 ?
|
||||
// TODO-KICKC: conflict parameter if prototype has different parameter names
|
||||
// TODO-KICKC: missing fragment: int x = pl->x + data[t].offset_x; oppure int x = pl->x + d->offset_x;
|
||||
|
||||
// TODO-ALIGN: read board[] (avoid [], use pointer)
|
||||
// TODO-ALIGN: ck_scroll_down() do not use memcpy, remove <string.h>
|
||||
// TODO-ALIGN: gr_drawpiece: byte piece = p->piece;
|
||||
// TODO-ALIGN: gr_updateboard sfora se 255
|
||||
// TODO-ALIGN: grboard: remove CRUNCH_CHAR1 e 2, BACKGROUND
|
||||
// TODO-ALIGN: score unsigned ?
|
||||
// TODO-ALIGN: int generate_new_piece()
|
||||
// TODO-ALIGN: unsigned int/byte all
|
||||
// TODO-ALIGN: PIECE_IS_NEXT
|
||||
|
||||
// TODO: solve division by counter_factor
|
||||
// TODO: interrupt and wait_interrupt()
|
||||
// TODO: better choice of colors for tiles
|
||||
// TODO: better initial fill/cls
|
||||
|
||||
//
|
||||
// TETRIS for Apple1 + TMS9918 video card by P-LAB
|
||||
// Written by Antonino Porcino, Dec 2021
|
||||
// nino.porcino@gmail.com
|
||||
//
|
||||
// This tetris version has been derived from my
|
||||
// previous implementations for the Laser 310 and Laser 500
|
||||
//
|
||||
|
||||
// standard libraries
|
||||
#include <string.h> // memset, memcopy (memcopy no longer necessary)
|
||||
#include <stdlib.h> // for sprintf, rand
|
||||
|
||||
#define COUNTER_MAX 3000 // the speed counter at level 0
|
||||
#define COUNTER_FACTOR 8 // speed decrease factor: speed -= speed / factor
|
||||
|
||||
// TODO solve division by counter_factor
|
||||
|
||||
// ERASED: #include <lib500.h>
|
||||
#define INLINE inline
|
||||
#define FG_BG(f,b) (((f)<<4)|(b))
|
||||
#include "../utils.h"
|
||||
#include "../apple1.h"
|
||||
#include "../tms9918.h"
|
||||
#include "../font8x8.h"
|
||||
#include "../tms_screen1.h"
|
||||
#include "../tms_screen2.h"
|
||||
#include "../interrupt.h"
|
||||
|
||||
// simulate the calls made in lib500
|
||||
#include "lib500_mock.h"
|
||||
|
||||
#include "pieces.h"
|
||||
|
||||
#define STYLE 3
|
||||
|
||||
#if STYLE == 1
|
||||
byte piece_chars[NUMPIECES] = {
|
||||
16, // L (orange in the original tetris)
|
||||
16, // J
|
||||
16, // T
|
||||
16, // I
|
||||
16, // O
|
||||
16, // S
|
||||
16, // Z
|
||||
};
|
||||
byte piece_colors[NUMPIECES] = {
|
||||
FG_BG( 0 , WHITE ), // L (orange in the original tetris)
|
||||
FG_BG( 0 , VIOLET ), // J
|
||||
FG_BG( 0 , LIGHT_MAGENTA ), // T
|
||||
FG_BG( 0 , LIGHT_CYAN ), // I
|
||||
FG_BG( 0 , YELLOW ), // O
|
||||
FG_BG( 0 , LIGHT_GREEN ), // S
|
||||
FG_BG( 0 , LIGHT_RED ) // Z
|
||||
};
|
||||
#endif
|
||||
|
||||
#if STYLE == 2
|
||||
byte piece_chars[NUMPIECES] = {
|
||||
0, // L (orange in the original tetris)
|
||||
1, // J
|
||||
2, // T
|
||||
3, // I
|
||||
4, // O
|
||||
15, // S
|
||||
14, // Z
|
||||
};
|
||||
byte piece_colors[NUMPIECES] = {
|
||||
FG_BG( WHITE , DARK_GREY ), // L (orange in the original tetris)
|
||||
FG_BG( VIOLET , BLUE ), // J
|
||||
FG_BG( LIGHT_MAGENTA , MAGENTA ), // T
|
||||
FG_BG( LIGHT_CYAN , CYAN ), // I
|
||||
FG_BG( YELLOW , BROWN ), // O
|
||||
FG_BG( LIGHT_GREEN , GREEN ), // S
|
||||
FG_BG( LIGHT_RED , RED ) // Z
|
||||
};
|
||||
#endif
|
||||
|
||||
#define EMPTY_GR_CHAR 32
|
||||
#define EMPTY_GR_COLOR FG_BG(COLOR_BLACK, COLOR_BLACK)
|
||||
|
||||
#if STYLE == 3
|
||||
byte piece_chars[NUMPIECES+1] = {
|
||||
0, // L (orange in the original tetris)
|
||||
1, // J
|
||||
2, // T
|
||||
3, // I
|
||||
2, // O
|
||||
1, // S
|
||||
0, // Z
|
||||
EMPTY_GR_CHAR // space
|
||||
};
|
||||
byte piece_colors[NUMPIECES+1] = {
|
||||
FG_BG( COLOR_GRAY , COLOR_WHITE ), // L (orange in the original tetris)
|
||||
FG_BG( COLOR_LIGHT_BLUE , COLOR_DARK_BLUE ), // J
|
||||
FG_BG( COLOR_MAGENTA , COLOR_WHITE ), // T
|
||||
FG_BG( COLOR_CYAN , COLOR_LIGHT_BLUE ), // I
|
||||
FG_BG( COLOR_LIGHT_YELLOW , COLOR_DARK_YELLOW ), // O
|
||||
FG_BG( COLOR_LIGHT_GREEN , COLOR_DARK_GREEN ), // S
|
||||
FG_BG( COLOR_LIGHT_RED , COLOR_DARK_RED ), // Z
|
||||
EMPTY_GR_COLOR // empty character
|
||||
};
|
||||
#endif
|
||||
|
||||
void check_crunched_lines();
|
||||
|
||||
#define COLLIDES 1
|
||||
#define NOT_COLLIDES 0
|
||||
|
||||
#define PIECE_IS_NEXT 255 /* tells a piece is not on the board but on the "next" display */
|
||||
|
||||
#include "sprite.h"
|
||||
|
||||
sprite piece_preview; // the "next" piece
|
||||
sprite player; // the piece moved by the player
|
||||
sprite new_pos; // new player position when making a 1-step move
|
||||
|
||||
word drop_counter; // counter used to set the pace
|
||||
word drop_counter_max; // maximum value of the counter
|
||||
|
||||
unsigned long score; // player's score
|
||||
unsigned int level; // level
|
||||
unsigned int lines_remaining; // lines to complete the level
|
||||
unsigned int total_lines; // total number of lines
|
||||
|
||||
// game files
|
||||
#include "pieces.h"
|
||||
#include "ckboard.h"
|
||||
#include "fonts.h"
|
||||
#include "keyboard_input.h"
|
||||
#include "grboard.h"
|
||||
#include "intro.h"
|
||||
|
||||
// simulates rand() % 7, since KickC does not support % 7
|
||||
// extracts a random number % 8 and repeats if it's not below < 7
|
||||
byte rand_modulo_7() {
|
||||
for(;;) {
|
||||
byte p = (byte) rand() % 8;
|
||||
if(p!=7) {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// generate a new piece after the last one can no longer move
|
||||
// piece is taken from the "next" which in turn is generated randomly
|
||||
// returns "COLLIDES" if a new piece can't be generated (the board is full)
|
||||
|
||||
byte generate_new_piece() {
|
||||
// move "next" piece onto the board
|
||||
player.piece = piece_preview.piece;
|
||||
player.angle = piece_preview.angle;
|
||||
player.x = 4;
|
||||
player.y = 0;
|
||||
|
||||
// get a new "next" piece
|
||||
gr_erasepiece(&piece_preview);
|
||||
piece_preview.piece = (byte) rand_modulo_7(); // rand() % NUMPIECES;
|
||||
piece_preview.angle = (byte) rand() % NUMROT;
|
||||
gr_drawpiece(&piece_preview);
|
||||
|
||||
if(collides(&player)) {
|
||||
// new piece can't be drawn => game over
|
||||
return COLLIDES;
|
||||
} else {
|
||||
// does not collide, draw it on the board
|
||||
ck_drawpiece(&player);
|
||||
gr_drawpiece(&player);
|
||||
return NOT_COLLIDES;
|
||||
}
|
||||
}
|
||||
|
||||
void handle_player_input() {
|
||||
byte key = player_input();
|
||||
byte allowed = 0;
|
||||
|
||||
if(key == 0) return;
|
||||
|
||||
ck_erasepiece(&player);
|
||||
|
||||
// calculate the new position
|
||||
sprite_copy(&new_pos, &player);
|
||||
|
||||
if(key == KEY_LEFT) {
|
||||
new_pos.x--;
|
||||
if(!collides(&new_pos)) allowed = 1;
|
||||
}
|
||||
else if(key == KEY_RIGHT) {
|
||||
new_pos.x++;
|
||||
if(!collides(&new_pos)) allowed = 1;
|
||||
}
|
||||
else if(key == KEY_ROTATE) {
|
||||
new_pos.angle = (new_pos.angle + 1) & 3;
|
||||
if(!collides(&new_pos)) allowed = 1;
|
||||
}
|
||||
else if(key == KEY_DOWN) {
|
||||
drop_counter = drop_counter_max;
|
||||
return;
|
||||
}
|
||||
else if(key == KEY_DROP) {
|
||||
// animate the falling piece
|
||||
while(1) {
|
||||
ck_erasepiece(&player);
|
||||
sprite_copy(&new_pos, &player);
|
||||
new_pos.y++;
|
||||
if(collides(&new_pos)) {
|
||||
break;
|
||||
}
|
||||
gr_erasepiece(&player);
|
||||
gr_drawpiece(&new_pos);
|
||||
ck_drawpiece(&new_pos);
|
||||
sprite_copy(&player,&new_pos);
|
||||
}
|
||||
drop_counter=drop_counter_max; // force an automatic drop
|
||||
return;
|
||||
}
|
||||
|
||||
if(allowed == 1) {
|
||||
gr_erasepiece(&player);
|
||||
gr_drawpiece(&new_pos);
|
||||
sprite_copy(&player, &new_pos);
|
||||
}
|
||||
ck_drawpiece(&player);
|
||||
}
|
||||
|
||||
// the main game loop, exits when GAME OVER
|
||||
// if the speed counter reaches its max then the piece is automatically pushed down 1 position
|
||||
// else lets the player move the piece with keyboard/joystick commands
|
||||
void gameLoop() {
|
||||
while(1) {
|
||||
if(drop_counter++==drop_counter_max) {
|
||||
// automatic drop down
|
||||
drop_counter = 0;
|
||||
|
||||
// erase from the check board in order to make the move
|
||||
ck_erasepiece(&player);
|
||||
|
||||
// calculate the new position (1 square down)
|
||||
sprite_copy(&new_pos, &player);
|
||||
new_pos.y++;
|
||||
|
||||
if(collides(&new_pos)) {
|
||||
// collides, redraw it again on the check board
|
||||
ck_drawpiece(&player);
|
||||
// check if lines to be crunched
|
||||
check_crunched_lines();
|
||||
// generate a new piece if possible, otherwise exit to game over
|
||||
if(generate_new_piece()==COLLIDES) return;
|
||||
}
|
||||
else {
|
||||
// automatic drop does not collide, simply draw it
|
||||
gr_erasepiece(&player); // erase and draw are as close as possible
|
||||
gr_drawpiece(&new_pos);
|
||||
ck_drawpiece(&new_pos);
|
||||
sprite_copy(&player, &new_pos); // make player new pos
|
||||
}
|
||||
}
|
||||
else {
|
||||
handle_player_input();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int scores[5] = {0, 40, 100, 300, 1200}; // variable score on number of lines crunched
|
||||
|
||||
byte lines_cruched[BROWS]; // stores which lines have been crunched
|
||||
|
||||
// checks if player has made complete lines and "crunches" them
|
||||
void check_crunched_lines() {
|
||||
byte num_lines_crunched = 0;
|
||||
|
||||
// mark completed lines
|
||||
for(byte line=(BROWS-1);line>0;line--) {
|
||||
byte filled = is_line_filled(line);
|
||||
lines_cruched[line] = filled;
|
||||
if(filled) {
|
||||
ck_erase_line(line);
|
||||
gr_crunch_line(line, CRUNCH_CHAR_1, CRUNCH_COLOR_1);
|
||||
num_lines_crunched++;
|
||||
}
|
||||
}
|
||||
|
||||
if(num_lines_crunched == 0) return;
|
||||
|
||||
// wait 5 frames so the effect is visible
|
||||
for(byte t=1; t<5; t++) {
|
||||
wait_interrupt();
|
||||
}
|
||||
|
||||
// assign score
|
||||
|
||||
// does multiplication by repeat sums, as KickC does not support multiplication
|
||||
unsigned int s=0;
|
||||
for(byte t=0;t<(level+1);t++) s += scores[num_lines_crunched];
|
||||
score += (unsigned long) s;
|
||||
|
||||
// score += scores[num_lines_crunched] * (level+1);
|
||||
lines_remaining -= num_lines_crunched;
|
||||
total_lines += num_lines_crunched;
|
||||
|
||||
// advance level
|
||||
if(lines_remaining <= 0) {
|
||||
level = level + 1;
|
||||
lines_remaining += 10;
|
||||
drop_counter_max -= drop_counter_max/COUNTER_FACTOR;
|
||||
// TODO effect when advancing level?
|
||||
}
|
||||
|
||||
// update score
|
||||
updateScore();
|
||||
|
||||
// // marks the lines crunched with another character
|
||||
for(byte line=0; line<BROWS; line++) {
|
||||
if(lines_cruched[line]) {
|
||||
gr_crunch_line(line, CRUNCH_CHAR_2, CRUNCH_COLOR_2);
|
||||
}
|
||||
}
|
||||
|
||||
// wait 5 frames so the effect is visible
|
||||
for(byte t=1; t<5; t++) {
|
||||
wait_interrupt();
|
||||
}
|
||||
|
||||
// compact the heap of tetrominos, removing empty lines
|
||||
for(byte line=0; line<BROWS; line++) {
|
||||
if(lines_cruched[line]) {
|
||||
ck_scroll_down(line);
|
||||
}
|
||||
}
|
||||
|
||||
// update the screen
|
||||
gr_update_board();
|
||||
|
||||
// sound effect
|
||||
// ERASED: bit_fx3(0);
|
||||
}
|
||||
|
||||
// initializes a new game
|
||||
void initGame() {
|
||||
level = 0;
|
||||
score = 0;
|
||||
total_lines = 0;
|
||||
lines_remaining = 10;
|
||||
drop_counter_max = COUNTER_MAX;
|
||||
ck_init();
|
||||
|
||||
drawPlayground();
|
||||
updateScore();
|
||||
|
||||
piece_preview.x = PIECE_IS_NEXT;
|
||||
piece_preview.y = PIECE_IS_NEXT; // piece is on "next" display
|
||||
|
||||
// generate pieces twice: one for "next" and one for player
|
||||
generate_new_piece();
|
||||
ck_erasepiece(&player);
|
||||
gr_erasepiece(&player);
|
||||
generate_new_piece();
|
||||
}
|
||||
|
||||
#ifdef APPLE1
|
||||
#define LOWRAM_START 0x280
|
||||
#define LOWRAM_END 0x7FF
|
||||
#define LOWRAM_SIZE (LOWRAM_END - LOWRAM_START + 1)
|
||||
#define DATAINCODE (0x8000 - LOWRAM_SIZE)
|
||||
#endif
|
||||
|
||||
void main() {
|
||||
|
||||
// install the start-of-frame interrupt detection
|
||||
//install_interrupt();
|
||||
|
||||
#ifdef APPLE1
|
||||
// copy the initializaton data from ROM to lowram where "Data" segment is allocated
|
||||
memcpy(LOWRAM_START, DATAINCODE, LOWRAM_SIZE);
|
||||
#endif
|
||||
|
||||
while(1) {
|
||||
introScreen();
|
||||
initGame();
|
||||
gameLoop();
|
||||
gameOver();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
#ifndef TYPES_H
|
||||
#define TYPES_H
|
||||
|
||||
// ERASED: typedef unsigned char byte;
|
||||
// ERASED: typedef unsigned int word;
|
||||
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue