summaryrefslogtreecommitdiff
path: root/hardwire
diff options
context:
space:
mode:
authorIan C <ianc@noddybox.co.uk>2019-06-25 18:37:47 +0000
committerIan C <ianc@noddybox.co.uk>2019-06-25 18:37:47 +0000
commitb2f86e20e052d9923523e29743172ea98266d28f (patch)
tree43399e99e34fcb20188cc4d1dea3644dada13b3b /hardwire
parentad1c73e9ff2580236887019ec176224f820c4c62 (diff)
Added original Hardwire code.HEADmaster
Diffstat (limited to 'hardwire')
-rw-r--r--hardwire/DEADJIM.WAVbin0 -> 10597 bytes
-rw-r--r--hardwire/FONT8.PCXbin0 -> 4707 bytes
-rw-r--r--hardwire/HWPAL.H40
-rw-r--r--hardwire/HW_GAME.MIDbin0 -> 3472 bytes
-rw-r--r--hardwire/HW_SCORE.MIDbin0 -> 6289 bytes
-rw-r--r--hardwire/HW_TITLE.MIDbin0 -> 5829 bytes
-rw-r--r--hardwire/MAKEFILE11
-rw-r--r--hardwire/SPRITE16.PCXbin0 -> 7609 bytes
-rw-r--r--hardwire/SPRITE8.PCXbin0 -> 4707 bytes
-rw-r--r--hardwire/allegro.cfg134
-rw-r--r--hardwire/click.wavbin0 -> 3530 bytes
-rw-r--r--hardwire/endline.wavbin0 -> 26422 bytes
-rw-r--r--hardwire/font8.pdsbin0 -> 30728 bytes
-rw-r--r--hardwire/hardwire.c2720
-rw-r--r--hardwire/hardwire.datbin0 -> 61395 bytes
-rw-r--r--hardwire/hardwire.txt140
-rw-r--r--hardwire/hwdat.h45
-rw-r--r--hardwire/hwscoresbin0 -> 180 bytes
-rw-r--r--hardwire/keystr.h141
-rw-r--r--hardwire/pathway.wavbin0 -> 33342 bytes
-rw-r--r--hardwire/pause_bmp.pcxbin0 -> 1843 bytes
-rw-r--r--hardwire/piecemap.h222
-rw-r--r--hardwire/popsound.wavbin0 -> 9112 bytes
-rw-r--r--hardwire/readme.h109
-rw-r--r--hardwire/sprite16.pdsbin0 -> 30728 bytes
-rw-r--r--hardwire/sprite8.pdsbin0 -> 30728 bytes
26 files changed, 3562 insertions, 0 deletions
diff --git a/hardwire/DEADJIM.WAV b/hardwire/DEADJIM.WAV
new file mode 100644
index 0000000..473a4df
--- /dev/null
+++ b/hardwire/DEADJIM.WAV
Binary files differ
diff --git a/hardwire/FONT8.PCX b/hardwire/FONT8.PCX
new file mode 100644
index 0000000..88e05fd
--- /dev/null
+++ b/hardwire/FONT8.PCX
Binary files differ
diff --git a/hardwire/HWPAL.H b/hardwire/HWPAL.H
new file mode 100644
index 0000000..5f66a6b
--- /dev/null
+++ b/hardwire/HWPAL.H
@@ -0,0 +1,40 @@
+/*
+ Auto generated by pcxdes.exe
+*/
+
+#define BLACK 0
+#define WHITE 1
+#define BLUE 2
+#define RED 3
+#define GREEN 4
+#define CYAN 5
+#define YELLOW 6
+#define PURPLE 7
+#define GREY7 8
+#define GREY6 9
+#define GREY5 10
+#define GREY4 11
+#define GREY3 12
+#define GREY2 13
+#define GREY1 14
+#define BLACKDRAW 15
+#define BASHI 16
+#define BASMID 17
+#define BASLO 18
+#define CHANCOL 19
+#define POINTCOL 20
+#define FILLCHANCOL 21
+#define BLOCK1COL 64
+#define BLOCK2COL 67
+#define BLOCK3COL 70
+#define BLOCK4COL 73
+#define BLOCK5COL 76
+#define BLOCK6COL 79
+#define BLOCK7COL 82
+#define BLOCK8COL 85
+#define PARTCOLMIN 128
+#define PARTCOLMAX 149
+#define STARCOLMIN 150
+#define STARCOLMAX 199
+#define MELTOMIN 200
+#define MELTOMAX 255
diff --git a/hardwire/HW_GAME.MID b/hardwire/HW_GAME.MID
new file mode 100644
index 0000000..e73f7f4
--- /dev/null
+++ b/hardwire/HW_GAME.MID
Binary files differ
diff --git a/hardwire/HW_SCORE.MID b/hardwire/HW_SCORE.MID
new file mode 100644
index 0000000..3be56f4
--- /dev/null
+++ b/hardwire/HW_SCORE.MID
Binary files differ
diff --git a/hardwire/HW_TITLE.MID b/hardwire/HW_TITLE.MID
new file mode 100644
index 0000000..9e60ed9
--- /dev/null
+++ b/hardwire/HW_TITLE.MID
Binary files differ
diff --git a/hardwire/MAKEFILE b/hardwire/MAKEFILE
new file mode 100644
index 0000000..cff0d4d
--- /dev/null
+++ b/hardwire/MAKEFILE
@@ -0,0 +1,11 @@
+# $Id$
+#
+OPTS=-Wall -O -fomit-frame-pointer
+OBJ=hardwire
+LIB=-lalleg
+HEADER=hwpal.h hwdat.h piecemap.h readme.h keystr.h
+
+ALL: $(OBJ).exe
+
+$(OBJ).exe: $(OBJ).c $(HEADER)
+ $(CC) $(OPTS) -o $(OBJ).exe $(OBJ).c $(LIB)
diff --git a/hardwire/SPRITE16.PCX b/hardwire/SPRITE16.PCX
new file mode 100644
index 0000000..ed438d5
--- /dev/null
+++ b/hardwire/SPRITE16.PCX
Binary files differ
diff --git a/hardwire/SPRITE8.PCX b/hardwire/SPRITE8.PCX
new file mode 100644
index 0000000..7af2ec5
--- /dev/null
+++ b/hardwire/SPRITE8.PCX
Binary files differ
diff --git a/hardwire/allegro.cfg b/hardwire/allegro.cfg
new file mode 100644
index 0000000..b053233
--- /dev/null
+++ b/hardwire/allegro.cfg
@@ -0,0 +1,134 @@
+#
+# Configuration file for the Allegro library.
+#
+# If you leave a parameter blank, Allegro will autodetect (ie. guess :-)
+#
+# This file should be kept either in the same directory as your program,
+# or in a location pointed to by the "ALLEGRO" environment variable.
+
+
+# graphics driver (there is usually no need to set this)
+# 1 = VGA mode 13h 2 = Mode-X
+# 3 = VESA 1.x 4 = VBE 2.0 (banked)
+# 5 = VBE 2.0 (linear) 6 = VBE/AF
+# 7 = Xtended mode 8 = ATI 18800/28800
+# 9 = ATI mach64 10 = Cirrus 64xx
+# 11 = Cirrus 54xx 12 = Paradise
+# 13 = S3 14 = Trident
+# 15 = Tseng ET3000 16 = Tseng ET4000
+# 17 = Video-7
+gfx_card =
+
+
+# name of the keyboard scancode mapping file (this can be a disk .cfg
+# file or an object from keyboard.dat). Currently available layouts are:
+# BE - Belgium
+# DE - Germany
+# DVORAK - Dvorak
+# ES - Spain
+# FI - Finland
+# FR - France
+# PT - Portugal
+# UK - United Kingdom
+# US - United States
+keyboard =
+
+
+# mouse type: Microsoft, Logitech, or NT (only change if you have problems)
+mouse =
+
+
+
+[sound]
+
+
+# digital sound output driver
+# 0 = none 1 = SB (autodetect breed)
+# 2 = SB 1.0 3 = SB 1.5
+# 4 = SB 2.0 5 = SB Pro
+# 6 = SB16 7 = GUS (unfinished)
+digi_card =
+
+
+# music output driver
+# 0 = none 1 = Adlib (autodetect OPL version)
+# 2 = OPL2 3 = Dual OPL2 (SB Pro-1)
+# 4 = OPL3 5 = SB MIDI interface
+# 6 = MPU-401 7 = GUS (unfinished)
+# 8 = DIGMID 9 = AWE32
+midi_card =
+
+
+# how many voices to reserve for each driver
+digi_voices =
+midi_voices =
+
+
+# how loud? (range 0-255)
+digi_volume =
+midi_volume =
+
+
+# toggling this between 0 and 1 reverses the left/right panning of samples
+flip_pan =
+
+
+# SB port address (usually 220)
+sb_port =
+
+
+# SB DMA channel (usually 1)
+sb_dma =
+
+
+# SB IRQ number (usually 7)
+sb_irq =
+
+
+# SB sample frequency (11906, 16129, 22727 or 45454)
+sb_freq =
+
+
+# FM synth port address (usually 388)
+fm_port =
+
+
+# MPU-401 port address (usually 330)
+mpu_port =
+
+
+# instrument definitions for the Adlib driver
+ibk_file =
+ibk_drum_file =
+
+
+# patch set for the DIGMID driver
+patches =
+
+
+
+[grabber]
+
+
+# should we make .bak files when saving datafiles?
+backups = n
+
+
+# default grid size for grabbing images
+xgrid = 16
+ygrid = 16
+
+
+# edit these shell commands to whatever helper programs you want to use...
+data = start /w notepad
+bmp = start /w "c:\program files\accessories\mspaint.exe"
+rle = start /w "c:\program files\accessories\mspaint.exe"
+cmp = start /w "c:\program files\accessories\mspaint.exe"
+xcmp = start /w "c:\program files\accessories\mspaint.exe"
+pal = start /w "c:\program files\accessories\mspaint.exe"
+font = start /w "c:\program files\accessories\mspaint.exe"
+samp = start /w "c:\program files\cooledit\cool.exe"
+midi = start /w "c:\program files\cakewalk\wincake.exe"
+
+
+
diff --git a/hardwire/click.wav b/hardwire/click.wav
new file mode 100644
index 0000000..74a37bb
--- /dev/null
+++ b/hardwire/click.wav
Binary files differ
diff --git a/hardwire/endline.wav b/hardwire/endline.wav
new file mode 100644
index 0000000..32b4a6c
--- /dev/null
+++ b/hardwire/endline.wav
Binary files differ
diff --git a/hardwire/font8.pds b/hardwire/font8.pds
new file mode 100644
index 0000000..af4fa29
--- /dev/null
+++ b/hardwire/font8.pds
Binary files differ
diff --git a/hardwire/hardwire.c b/hardwire/hardwire.c
new file mode 100644
index 0000000..f6b5871
--- /dev/null
+++ b/hardwire/hardwire.c
@@ -0,0 +1,2720 @@
+/*
+ Hardwire
+ (c) 1997 Noddybox
+ Written using DJGPP v2 and Allegro 3.0
+
+ Allegro written by Shawn Hargreaves
+
+*/
+static char version[]="1.0";
+
+/* Includes
+*/
+#include <stdio.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <allegro.h>
+#include "hwpal.h"
+#include "hwdat.h"
+#include "keystr.h"
+
+
+/* Macros
+*/
+#define RND(x) (rand()%(x))
+#define CENTRE(s,y,col) textout_centre(img,font8,s,CX,y,col)
+
+
+/* Types and stuff
+*/
+#define HISC 5
+#define HISCFILE "hwscores"
+
+#define GAME_TYPES 3
+#define TETRIS_WIRE 0
+#define COLUMNS_WIRE 1
+#define TETRIS_CLASSIC 2
+
+#define SPRSIZE 8
+#define MAXPITWIDTH 12
+#define MINPITWIDTH 6
+#define PITDEPTH 17
+#define PITXOFF (SPRSIZE*2+((MAXPITWIDTH-PITWIDTH)*SPRSIZE/2))
+#define PITYOFF SPRSIZE*4
+
+#define PITX(x) (((x)*SPRSIZE)+PITXOFF)
+#define PITY(y) (((y)*SPRSIZE)+PITYOFF)
+
+#define SCOREPX 200
+#define SCOREX (SCOREPX+50)
+#define SCOREY 20
+
+#define LEVELPX 200
+#define LEVELX (LEVELPX+50)
+#define LEVELY 40
+
+#define NEXTPX 200
+#define NEXTX (NEXTPX+50)
+#define NEXTY 100
+
+#define BASECTR (SLOW ? (MODE==TETRIS_CLASSIC ? 30 : 100) : \
+ (MODE==TETRIS_CLASSIC ? 50 : 150))
+
+#define WEIGHTCTR (SLOW ? (MODE==TETRIS_CLASSIC ? 2 : 8) : \
+ (MODE==TETRIS_CLASSIC ? 4 : 12))
+
+
+#define LEVELCTR(x) (MAX((BASECTR-(x)*WEIGHTCTR),3))
+
+#define BOUNCEVAL 10
+
+#define KEYBOUNCE(k,x) if (!key[k]) \
+ x=0; \
+ else \
+ if (x) \
+ x--
+
+#define NODIR -1
+#define LEFT 0
+#define UP 1
+#define RIGHT 2
+#define DOWN 3
+#define PATHLEN (MAXPITWIDTH*PITDEPTH)
+
+#define ROR(x) ((x) ? ((x)-1) : (3))
+#define ROL(x) (((x)+1)%4)
+#define REV(x) (((x)+2)%4)
+
+int xi[4]={-1,0,1,0};
+int yi[4]={0,-1,0,1};
+
+char *modetxt[GAME_TYPES]={"TETRIS WIRE",
+ "COLUMNS WIRE",
+ "TETRIS CLASSIC"};
+
+typedef struct
+ {
+ int data[PITDEPTH][MAXPITWIDTH];
+ int id[PITDEPTH][MAXPITWIDTH];
+ } Pit;
+
+Pit pit;
+
+typedef struct
+ {
+ int x,y;
+ } PathElem;
+
+typedef struct
+ {
+ int len;
+ PathElem p[PATHLEN];
+ } Path;
+
+typedef struct
+ {
+ int score;
+ int level;
+ char name[4];
+ } Hisc;
+
+Hisc hisc[GAME_TYPES][HISC] =
+ {
+ {
+ {500,5,"S.V"},
+ {250,4,"S.V"},
+ {200,3,"S.V"},
+ {150,2,"S.V"},
+ {100,1,"S.V"},
+ },
+ {
+ {500,5,"S.V"},
+ {250,4,"S.V"},
+ {200,3,"S.V"},
+ {150,2,"S.V"},
+ {100,1,"S.V"},
+ },
+ {
+ {500,5,"S.V"},
+ {250,4,"S.V"},
+ {200,3,"S.V"},
+ {150,2,"S.V"},
+ {100,1,"S.V"},
+ },
+ };
+
+/* Key controls
+*/
+#define KQUIT KEY_ESC
+#define KREADME KEY_I
+#define KDEFINE KEY_R
+#define KTOGGLE_MODE KEY_F1
+#define KTOGGLE_LEVEL KEY_F2
+#define KTOGGLE_WIDTH KEY_F3
+#define KTOGGLE_MOTION KEY_F4
+#define KTOGGLE_MUSIC KEY_F5
+#define KBORED KEY_F9
+#define DEF_KLEFT KEY_LEFT
+#define DEF_KRIGHT KEY_RIGHT
+#define DEF_KROTATER KEY_DOWN
+#define DEF_KROTATEL KEY_UP
+#define DEF_KDROP KEY_SPACE
+#define DEF_KPAUSE KEY_P
+
+int KLEFT= KEY_LEFT;
+int KRIGHT= KEY_RIGHT;
+int KROTATER= KEY_DOWN;
+int KROTATEL= KEY_UP;
+int KDROP= KEY_SPACE;
+int KPAUSE= DEF_KPAUSE;
+
+#define GETKEY (keypressed() ? (readkey()>>8) : (-1))
+
+int used_keys[129];
+
+
+/* Object types - defines from less obvious names from DAT file
+*/
+#define PIT_TL SPRITE8_000
+#define PIT_ML SPRITE8_001
+#define PIT_BL SPRITE8_002
+#define PIT_BM SPRITE8_003
+#define PIT_BR SPRITE8_004
+#define PIT_MR SPRITE8_005
+#define PIT_TR SPRITE8_006
+
+#define CLASSIC_WALL SPRITE8_024
+
+#define SPECIAL SPRITE8_007
+#define CROSS SPRITE8_008
+#define UPDOWN SPRITE8_009
+#define ACROSS SPRITE8_010
+#define LEFTDOWN SPRITE8_011
+#define RIGHTDOWN SPRITE8_012
+#define RIGHTUP SPRITE8_013
+#define LEFTUP SPRITE8_014
+#define PATH SPRITE8_015
+
+#define BLOCK1SPR SPRITE8_016
+#define BLOCK2SPR SPRITE8_017
+#define BLOCK3SPR SPRITE8_018
+#define BLOCK4SPR SPRITE8_019
+#define BLOCK5SPR SPRITE8_020
+#define BLOCK6SPR SPRITE8_021
+#define BLOCK7SPR SPRITE8_022
+#define BLOCK8SPR SPRITE8_023
+
+#define HISC_CURS1 SPRITE16_000
+#define HISC_CURS2 SPRITE16_001
+#define HISC_CURS3 SPRITE16_002
+
+#define BLANK (-1)
+
+#define RNDPIECE (RND((RIGHTUP-CROSS))+CROSS)
+
+#define SPR(x) (RLE_SPRITE*)dfile[(x)].dat
+#define SAM(x) (SAMPLE*)dfile[(x)].dat
+
+
+/* Object and game type control types
+*/
+void GenTetrisWirePiece(int special),
+ RotTetrisWirePiece(int dir);
+void GenColumnsWirePiece(int special),
+ RotColumnsWirePiece(int dir);
+void GenTetrisClassicPiece(int special),
+ RotTetrisClassicPiece(int dir);
+void CheckWirePaths(void),
+ CheckClassicPaths(void);
+
+typedef struct
+ {
+ int ox,oy;
+ int data[4][4];
+ } Piece;
+
+typedef struct
+ {
+ int no;
+ int piece[5];
+ } PieceSet;
+
+typedef struct
+ {
+ void (*gen_piece)(int);
+ void (*rot_piece)(int);
+ void (*do_paths)(void);
+ int special_count;
+ } GameDefinition;
+
+typedef struct
+ {
+ int x,y;
+ int level;
+ int score;
+ int rotate;
+ int is_special;
+ int current_type;
+ Piece current;
+ int next_is_special;
+ int next_type;
+ Piece next;
+ } Game;
+
+GameDefinition gamedef[GAME_TYPES]=
+ {
+ {
+ GenTetrisWirePiece,
+ RotTetrisWirePiece,
+ CheckWirePaths,
+ 40
+ },
+ {
+ GenColumnsWirePiece,
+ RotColumnsWirePiece,
+ CheckWirePaths,
+ 60
+ },
+ {
+ GenTetrisClassicPiece,
+ RotTetrisClassicPiece,
+ CheckClassicPaths,
+ 99
+ }
+ };
+
+
+/* Game piece maps - In a seperate include to maintain some semblance
+ of neatness. Include file must have these arrays :
+
+ PieceSet piece_set[NO_PIECE_SET];
+ Piece tetris_map[NO_TETRIS_PIECE];
+ int tetris_height[NO_TETRIS_PIECE];
+ {anon} tetris_off[NO_TETRIS_PIECE][4].(x|y);
+
+ Note that the columns mapping is handled in an hard coded
+ way, thanks to it's easiness.
+
+ Also note that the same maps are used for both TETRIS
+ modes, but the classic mode replaces the wiring sprites
+ with simple block sprites.
+*/
+#include "piecemap.h"
+
+
+
+/* Control vars
+*/
+int SOUND =TRUE; /* TRUE on doing sound code */
+int MUSIC =TRUE;
+int PITWIDTH=MAXPITWIDTH;
+int LEVEL =1;
+int SCORE =0;
+int MODE =TETRIS_WIRE;
+int MOTION =TRUE;
+int SLOW =FALSE;
+
+
+/* Function defs
+*/
+void TitlePage(void);
+
+void Error(char *msg);
+
+void ReadMe(void);
+
+void DefineKeys(void);
+
+void PlayGame(void);
+void GameOver(void);
+void EnterHisc(void);
+
+void SoundFX(int fx);
+
+void LoadHisc(void);
+void SaveHisc(void);
+
+void Redraw(void);
+void Melt(int x1,int y1,int x2,int y2);
+
+void InitStars(void);
+void RemoveStars(void);
+void UpdateStars(void);
+
+void InitParticles(void);
+void RemoveParticles(void);
+void UpdateParticles(void);
+void AddParticle(int x,int y,int xi,int yi);
+
+void InitScores(void);
+void AddScore(char *s,int sc);
+void UpdateScores(void);
+
+int ROL_Piece(int tile);
+int ROR_Piece(int tile);
+
+int FindPathFrom(int sx,int sy,int dir,Path *p);
+int FindPath(Path *p);
+int FindLoopFrom(int ox,int oy,int x,int y,int dir,Path *p);
+int FindLoop(Path *p);
+void GetSpecialPath(Path *p);
+void DrawPath(Path *p);
+
+void DrawGameScreen(void);
+void RedrawPit(void);
+void DrawPiece(void);
+void ErasePiece(void);
+void DrawInfo(void);
+
+int MoveOK(int x,int y);
+int AddAndCheckIsDead(int id);
+void CompressPath(void);
+void CompressBlanks(void);
+void GameRedraw(void);
+void DoPause(void);
+
+
+/* Allegro vars
+*/
+#define CX (SCREEN_W/2)
+#define CY (SCREEN_H/2)
+
+BITMAP *img;
+BITMAP *workimg;
+DATAFILE *dfile;
+PALETTE pal;
+FONT *font8;
+MIDI *title_midi,*game_midi,*score_midi;
+
+
+/* Global vars
+*/
+int quit=FALSE;
+Game game;
+
+
+
+/* -------------------------------------------------------------------------
+ MAIN
+ ------------------------------------------------------------------------- */
+
+int main(int argc,char **argv)
+
+{
+ int x,y;
+ int arg;
+ int f;
+
+ srand(getpid());
+
+ /* Parse switchs
+ */
+ arg=1;
+ while(arg<argc)
+ {
+ if (*argv[arg]=='-')
+ switch (*(argv[arg]+1))
+ {
+ case 'v':
+ printf("version : %s\n",version);
+ exit(0);
+ break;
+
+ case 'q':
+ SOUND=FALSE;
+ MUSIC=FALSE;
+ break;
+
+ case 'm':
+ MUSIC=FALSE;
+ break;
+
+ case 's':
+ SLOW=TRUE;
+ MOTION=FALSE;
+ break;
+
+ default:
+ Error("usage : hardwire [-v] [-q]");
+ break;
+ }
+ arg++;
+ }
+
+ /* Initialise Allegro
+ */
+ allegro_init();
+ install_timer();
+ install_keyboard();
+
+ /* Load in datafile
+ */
+ if (!(dfile=load_datafile("hardwire.dat")))
+ Error("Error reading datafile HARDWIRE.DAT");
+
+ memcpy(&pal,dfile[HWPAL].dat,sizeof(PALETTE));
+
+ font8=(FONT *)dfile[HWFONT].dat;
+
+ title_midi=(MIDI *)dfile[TITLEMIDI].dat;
+ game_midi=(MIDI *)dfile[GAMEMIDI].dat;
+ score_midi=(MIDI *)dfile[SCOREMIDI].dat;
+
+ /* Set up sound
+ */
+ if (SOUND)
+ if (install_sound(DIGI_AUTODETECT,MIDI_AUTODETECT,NULL)==-1)
+ Error(allegro_error);
+
+ /* Set up defined keys array
+ */
+ for(f=0;f<129;f++)
+ used_keys[f]=FALSE;
+
+ used_keys[KQUIT]=TRUE;
+ used_keys[KPAUSE]=TRUE;
+ used_keys[KREADME]=TRUE;
+ used_keys[KDEFINE]=TRUE;
+ used_keys[KTOGGLE_MODE]=TRUE;
+ used_keys[KTOGGLE_LEVEL]=TRUE;
+ used_keys[KTOGGLE_WIDTH]=TRUE;
+ used_keys[KTOGGLE_MOTION]=TRUE;
+ used_keys[KTOGGLE_MUSIC]=TRUE;
+ used_keys[KBORED]=TRUE;
+ used_keys[KLEFT]=TRUE;
+ used_keys[KRIGHT]=TRUE;
+ used_keys[KROTATER]=TRUE;
+ used_keys[KROTATEL]=TRUE;
+ used_keys[KDROP]=TRUE;
+
+ /* Set up VGA graphics mode
+ */
+ if (set_gfx_mode(GFX_AUTODETECT,320,200,0,0)<0)
+ Error(allegro_error);
+
+ img=create_bitmap(SCREEN_W,SCREEN_H);
+ workimg=create_bitmap(SCREEN_W,SCREEN_H);
+
+ /* Main control loop of game
+ */
+ clear(img);
+ set_palette(pal);
+
+ LoadHisc();
+
+ TitlePage();
+
+ while(!quit)
+ {
+ game.score=SCORE;
+ game.level=LEVEL;
+
+ for(x=0;x<PITWIDTH;x++)
+ for(y=0;y<PITDEPTH;y++)
+ {
+ pit.data[y][x]=BLANK;
+ pit.id[y][x]=0;
+ }
+
+ (*gamedef[MODE].gen_piece)(FALSE);
+ (*gamedef[MODE].gen_piece)(FALSE);
+
+ DrawGameScreen();
+ PlayGame();
+ GameOver();
+
+ if (game.score>hisc[MODE][HISC-1].score)
+ {
+ EnterHisc();
+ SaveHisc();
+ }
+
+ TitlePage();
+ }
+
+ return (0);
+}
+
+
+
+/* -------------------------------------------------------------------------
+ UTILS
+ ------------------------------------------------------------------------- */
+
+void Error(char *s)
+{
+ allegro_exit();
+ fprintf(stderr,"%s\n",s);
+ exit(1);
+}
+
+
+/* -------------------------------------------------------------------------
+ WIRE ROTATE PIECE UTILS
+ ------------------------------------------------------------------------- */
+
+int ROL_Piece(int tile)
+{
+ /* This should be in a table, but using sprite numbers for the tile
+ codes makes that not so neat
+ */
+ switch(tile)
+ {
+ case CROSS:
+ return(CROSS);
+ break;
+
+ case UPDOWN:
+ return(ACROSS);
+ break;
+
+ case ACROSS:
+ return(UPDOWN);
+ break;
+
+ case LEFTDOWN:
+ return(LEFTUP);
+ break;
+
+ case RIGHTDOWN:
+ return(LEFTDOWN);
+ break;
+
+ case LEFTUP:
+ return(RIGHTUP);
+ break;
+
+ case RIGHTUP:
+ return(RIGHTDOWN);
+ break;
+
+ default:
+ return(BLANK);
+ break;
+ }
+}
+
+
+int ROR_Piece(int tile)
+{
+ /* This should be in a table, but using sprite numbers for the tile
+ codes makes that not so neat
+ */
+ switch(tile)
+ {
+ case CROSS:
+ return(CROSS);
+ break;
+
+ case UPDOWN:
+ return(ACROSS);
+ break;
+
+ case ACROSS:
+ return(UPDOWN);
+ break;
+
+ case LEFTDOWN:
+ return(RIGHTDOWN);
+ break;
+
+ case RIGHTDOWN:
+ return(RIGHTUP);
+ break;
+
+ case LEFTUP:
+ return(LEFTDOWN);
+ break;
+
+ case RIGHTUP:
+ return(LEFTUP);
+ break;
+
+ default:
+ return(BLANK);
+ break;
+ }
+}
+
+
+/* -------------------------------------------------------------------------
+ WIRE PATH UTILS
+ ------------------------------------------------------------------------- */
+
+int Dir(int tile,int dir)
+{
+ switch(tile) /* This should be in a table, but */
+ { /* using sprite numbers for the tile */
+ case CROSS: /* codes makes that not so neat */
+ return(dir);
+ break;
+
+ case UPDOWN:
+ if ((dir==UP)||(dir==DOWN))
+ return(dir);
+ else
+ return(NODIR);
+ break;
+
+ case ACROSS:
+ if ((dir==LEFT)||(dir==RIGHT))
+ return(dir);
+ else
+ return(NODIR);
+ break;
+
+ case LEFTDOWN:
+ if (dir==RIGHT)
+ return(DOWN);
+ else if (dir==UP)
+ return(LEFT);
+ else
+ return(NODIR);
+ break;
+
+ case RIGHTDOWN:
+ if (dir==LEFT)
+ return(DOWN);
+ else if (dir==UP)
+ return(RIGHT);
+ else
+ return(NODIR);
+ break;
+
+ case LEFTUP:
+ if (dir==RIGHT)
+ return(UP);
+ else if (dir==DOWN)
+ return(LEFT);
+ else
+ return(NODIR);
+ break;
+
+ case RIGHTUP:
+ if (dir==LEFT)
+ return(UP);
+ else if (dir==DOWN)
+ return(RIGHT);
+ else
+ return(NODIR);
+ break;
+
+ default:
+ return(NODIR);
+ break;
+ }
+}
+
+
+int FindPathFrom(int sx,int sy,int dir,Path *p)
+{
+ dir=Dir(pit.data[sy][sx],dir);
+
+ if (dir==NODIR)
+ {
+ p->len=0;
+ return (FALSE);
+ }
+
+ p->p[p->len].x=sx;
+ p->p[p->len].y=sy;
+ p->len++;
+
+ sx+=xi[dir];
+ sy+=yi[dir];
+
+ if (sy==-1)
+ {
+ return (FALSE);
+ p->len=0;
+ }
+
+ if ((sx==-1)||(sx==PITWIDTH)||(sy==PITDEPTH))
+ return (TRUE);
+ else
+ return (FindPathFrom(sx,sy,dir,p));
+}
+
+
+int FindPath(Path *p)
+{
+ int f;
+
+ p->len=0;
+
+ for(f=PITDEPTH-1;f>=0;f--)
+ {
+ if (FindPathFrom(0,f,RIGHT,p))
+ return (TRUE);
+
+ if (FindPathFrom(PITWIDTH-1,f,LEFT,p))
+ return (TRUE);
+ }
+
+ for(f=0;f<PITWIDTH;f++)
+ if (FindPathFrom(f,PITDEPTH-1,UP,p))
+ return (TRUE);
+
+ return (FALSE);
+}
+
+
+int FindLoopFrom(int ox,int oy,int x,int y,int dir,Path *p)
+{
+ dir=Dir(pit.data[y][x],dir);
+
+ if (dir==NODIR)
+ {
+ p->len=0;
+ return (FALSE);
+ }
+
+ p->p[p->len].x=x;
+ p->p[p->len].y=y;
+ p->len++;
+
+ x+=xi[dir];
+ y+=yi[dir];
+
+ if ((x==ox)&&(y==oy))
+ return (TRUE);
+ else
+ return (FindLoopFrom(ox,oy,x,y,dir,p));
+}
+
+
+int FindLoop(Path *p)
+{
+ int x,y;
+
+ p->len=0;
+
+ for(y=PITDEPTH-1;y>=0;y--)
+ for(x=0;x<PITWIDTH;x++)
+ switch(pit.data[y][x])
+ {
+ case CROSS:
+ case ACROSS:
+ case LEFTDOWN:
+ case LEFTUP:
+ if (FindLoopFrom(x,y,x,y,LEFT,p))
+ return(TRUE);
+ default:
+ break;
+ }
+
+ return(FALSE);
+}
+
+
+void GetSpecialPathFromTile(int tile,Path *p)
+{
+ int x,y;
+
+ if (tile==BLANK)
+ return;
+
+ for(x=0;x<PITWIDTH;x++)
+ for(y=0;y<PITDEPTH;y++)
+ if (pit.data[y][x]==tile)
+ {
+ p->p[p->len].x=x;
+ p->p[p->len].y=y;
+ p->len++;
+ }
+}
+
+
+void GetSpecialPath(Path *p)
+{
+ p->len=0;
+
+ if (game.y>0)
+ GetSpecialPathFromTile(pit.data[game.y-1][game.x],p);
+
+ if (game.y<(PITDEPTH-1))
+ GetSpecialPathFromTile(pit.data[game.y+1][game.x],p);
+
+ if (game.x>0)
+ GetSpecialPathFromTile(pit.data[game.y][game.x-1],p);
+
+ if (game.x<(PITWIDTH-1))
+ GetSpecialPathFromTile(pit.data[game.y][game.x+1],p);
+}
+
+
+void DrawPath(Path *p)
+{
+ int f,r;
+
+ SoundFX(PATH_FX);
+
+ for(f=0;f<p->len;f++)
+ {
+ pit.data[p->p[f].y][p->p[f].x]=PATH;
+
+ for(r=0;r<5;r++)
+ AddParticle(PITX(p->p[f].x)+RND(SPRSIZE),
+ PITY(p->p[f].y)+RND(SPRSIZE),
+ RND(5)-2,RND(5)-2);
+ }
+}
+
+
+/* -------------------------------------------------------------------------
+ SCORE UTILS
+ ------------------------------------------------------------------------- */
+
+#define DSNO 3
+#define DSFADE (SLOW ? (10) : (20))
+
+struct
+ {
+ char p[80];
+ int sc;
+ int col;
+ int cnt;
+ } dispsc[DSNO];
+
+void InitScores(void)
+{
+ int f;
+
+ for(f=0;f<DSNO;f++)
+ {
+ strcpy(dispsc[f].p,"X");
+ dispsc[f].sc=0;
+ dispsc[f].col=BLACK;
+ dispsc[DSNO-1].cnt=DSFADE;
+ }
+}
+
+
+void AddScore(char *s,int sc)
+{
+ int f;
+
+ for(f=DSNO-2;f>=0;f--)
+ dispsc[f+1]=dispsc[f];
+
+ strcpy(dispsc[0].p,s);
+ dispsc[0].sc=sc;
+ dispsc[0].col=MELTOMAX-1;
+ dispsc[0].cnt=DSFADE;
+}
+
+
+void UpdateScores(void)
+{
+ int f;
+ char s[80];
+
+ for(f=0;f<DSNO;f++)
+ {
+ sprintf(s,"%-7s %5d",dispsc[f].p,dispsc[f].sc);
+
+ textout(img,font8,s,SCOREPX,SCREEN_H-(8*f+8),dispsc[f].col);
+
+ if (dispsc[f].col!=BLACK)
+ if (--dispsc[f].cnt==0)
+ {
+ dispsc[f].cnt=DSFADE;
+ if (--dispsc[f].col==MELTOMIN)
+ dispsc[f].col=BLACK;
+ }
+ }
+}
+
+
+/* -------------------------------------------------------------------------
+ SOUND UTILS
+ ------------------------------------------------------------------------- */
+
+void SoundFX(int fx)
+{
+ if (SOUND)
+ play_sample(SAM(fx),200,128,1000,FALSE);
+}
+
+
+/* -------------------------------------------------------------------------
+ HISCORE FILE CODE
+ ------------------------------------------------------------------------- */
+
+void LoadHisc(void)
+{
+ int fd;
+ int f,r;
+
+ if ((fd=open(HISCFILE,O_RDONLY|O_BINARY))!=-1)
+ {
+ for(f=0;f<GAME_TYPES;f++)
+ for(r=0;r<HISC;r++)
+ read(fd,&hisc[f][r],sizeof(Hisc));
+ close(fd);
+ }
+}
+
+
+void SaveHisc(void)
+{
+ int fd;
+ int f,r;
+
+ if ((fd=open(HISCFILE,O_WRONLY|O_CREAT|O_TRUNC|O_BINARY,
+ S_IRUSR|S_IWUSR))!=-1)
+ {
+ for(f=0;f<GAME_TYPES;f++)
+ for(r=0;r<HISC;r++)
+ write(fd,&hisc[f][r],sizeof(Hisc));
+ close(fd);
+ }
+}
+
+
+/* -------------------------------------------------------------------------
+ GRAPHICS UTILS
+ ------------------------------------------------------------------------- */
+
+void Redraw(void)
+{
+ vsync();
+ blit(img,screen,0,0,0,0,SCREEN_W,SCREEN_H);
+}
+
+
+void Melt(int x1, int y1, int x2, int y2)
+{
+ int c,x,y,xi,yi,mx,my;
+
+ mx=x2-1;
+ my=y2-1;
+
+ for(y=y1;y<y2;y++)
+ for(x=x1;x<x2;x++)
+ if (((c=img->line[y][x])<=MELTOMAX)&&(c>MELTOMIN))
+ {
+ xi=x+RND(4)-1;
+ yi=y+RND(5)-3;
+
+ xi=MID(x1,xi,mx);
+ yi=MID(y1,yi,my);
+
+ img->line[yi][xi]=c-1;
+ }
+}
+
+
+void DrawGameScreen(void)
+{
+ int x,y;
+ RLE_SPRITE *spr;
+
+ clear(img);
+
+ if (MODE==TETRIS_CLASSIC)
+ {
+ for(x=-1;x<=PITWIDTH;x++)
+ draw_rle_sprite(img,SPR(CLASSIC_WALL),PITX(x),PITY(PITDEPTH));
+
+ for(y=0;y<PITDEPTH;y++)
+ {
+ draw_rle_sprite(img,SPR(CLASSIC_WALL),PITX(PITWIDTH),PITY(y));
+ draw_rle_sprite(img,SPR(CLASSIC_WALL),PITX(-1),PITY(y));
+ }
+ }
+ else
+ {
+ for(x=-1;x<=PITWIDTH;x++)
+ {
+ if (x==-1)
+ spr=SPR(PIT_BL);
+ else if (x==PITWIDTH)
+ spr=SPR(PIT_BR);
+ else
+ spr=SPR(PIT_BM);
+
+ draw_rle_sprite(img,spr,PITX(x),PITY(PITDEPTH));
+ }
+
+ for(y=0;y<PITDEPTH;y++)
+ {
+ if (y==0)
+ spr=SPR(PIT_TL);
+ else
+ spr=SPR(PIT_ML);
+
+ draw_rle_sprite(img,spr,PITX(-1),PITY(y));
+
+ if (y==0)
+ spr=SPR(PIT_TR);
+ else
+ spr=SPR(PIT_MR);
+
+ draw_rle_sprite(img,spr,PITX(PITWIDTH),PITY(y));
+ }
+ }
+
+ textout(img,font8,"SCORE",SCOREPX,SCOREY,WHITE);
+ textout(img,font8,"LEVEL",LEVELPX,LEVELY,WHITE);
+ textout(img,font8,"NEXT",NEXTPX,NEXTY,WHITE);
+
+ DrawInfo();
+}
+
+
+void RedrawPit(void)
+{
+ int x,y;
+
+ for(x=0;x<PITWIDTH;x++)
+ for(y=0;y<PITDEPTH;y++)
+ if (pit.data[y][x]==BLANK)
+ rectfill(img,PITX(x),PITY(y),
+ PITX(x)+SPRSIZE-1,PITY(y)+SPRSIZE-1,BLACK);
+ else
+ draw_rle_sprite(img,SPR(pit.data[y][x]),PITX(x),PITY(y));
+}
+
+
+void DrawPiece(void)
+{
+ int x,y;
+
+ for(x=0;x<4;x++)
+ for(y=0;y<4;y++)
+ if (game.current.data[y][x]!=BLANK)
+ draw_rle_sprite(img,SPR(game.current.data[y][x]),
+ PITX(game.x+x-game.current.ox),
+ PITY(game.y+y-game.current.oy));
+}
+
+
+void ErasePiece(void)
+{
+ int x,y;
+
+ for(x=0;x<4;x++)
+ for(y=0;y<4;y++)
+ if (game.current.data[y][x]!=BLANK)
+ rectfill(img,PITX(game.x+x-game.current.ox),
+ PITY(game.y+y-game.current.oy),
+ PITX(game.x+x-game.current.ox)+SPRSIZE-1,
+ PITY(game.y+y-game.current.oy)+SPRSIZE-1,
+ BLACK);
+}
+
+
+void DrawInfo(void)
+{
+ char sc[80];
+ int x,y,px,py;
+
+ sprintf(sc,"%7d",game.score);
+ textout(img,font8,sc,SCOREX,SCOREY,WHITE);
+
+ sprintf(sc,"%7d",game.level);
+ textout(img,font8,sc,LEVELX,LEVELY,WHITE);
+
+ for(x=0;x<4;x++)
+ for(y=0;y<4;y++)
+ {
+ px=NEXTX+x*SPRSIZE;
+ py=NEXTY+y*SPRSIZE;
+
+ if (game.next.data[y][x]==BLANK)
+ rectfill(img,px,py,px+SPRSIZE,py+SPRSIZE,BLACK);
+ else
+ draw_rle_sprite(img,SPR(game.next.data[y][x]),px,py);
+ }
+}
+
+
+/* -------------------------------------------------------------------------
+ STARFIELD
+ ------------------------------------------------------------------------- */
+#define NOSTAR 1000
+#define STARCUBEXY 256000 /* 64000 */
+#define STARCUBEZ 256000
+#define MAXSTINC 1000.0
+#define STARCNT 20
+
+typedef struct {
+ float x,y,z;
+ int col;
+ } Star;
+
+Star star[NOSTAR];
+
+float st_inc_x,st_inc_xi;
+float st_inc_y,st_inc_yi;
+float st_inc_z,st_inc_zi;
+unsigned int st_cnt;
+
+void InitStars(void)
+{
+ int f;
+
+ set_projection_viewport(0,0,SCREEN_W,SCREEN_H);
+
+ for(f=0;f<NOSTAR;f++)
+ {
+ star[f].x=(float)RND(STARCUBEXY*2)-STARCUBEXY;
+ star[f].y=(float)RND(STARCUBEXY*2)-STARCUBEXY;
+ star[f].z=(float)RND(STARCUBEZ);
+ star[f].col=RND(STARCOLMAX-STARCOLMIN)+STARCOLMIN;
+ }
+
+ st_inc_x=0.0;
+ st_inc_xi=40.0;
+
+ st_inc_y=0.0;
+ st_inc_yi=80.0;
+
+ st_inc_z=MAXSTINC;
+ st_inc_zi=-80.0;
+
+ st_cnt=0;
+}
+
+
+void StarPos(Star *s,int *x,int *y)
+{
+ float fx,fy;
+
+ persp_project_f(s->x,s->y,s->z,&fx,&fy);
+ *x=(int)fx;
+ *y=(int)fy;
+}
+
+
+void RemoveStars(void)
+{
+ int x,y;
+ int f;
+
+ for(f=0;f<NOSTAR;f++)
+ {
+ StarPos(star+f,&x,&y);
+
+ if (getpixel(img,x,y)==star[f].col)
+ putpixel(img,x,y,BLACK);
+ }
+}
+
+
+void UpdateStars(void)
+{
+ int x,y;
+ int f;
+
+ if (!(++st_cnt%STARCNT))
+ {
+ st_inc_x+=st_inc_xi;
+
+ if ((st_inc_x<=-MAXSTINC)||(st_inc_x>=MAXSTINC))
+ st_inc_xi=-st_inc_xi;
+
+ st_inc_y+=st_inc_yi;
+
+ if ((st_inc_y<=-MAXSTINC)||(st_inc_y>=MAXSTINC))
+ st_inc_yi=-st_inc_yi;
+
+ st_inc_z+=st_inc_zi;
+
+ if ((st_inc_z<=-MAXSTINC)||(st_inc_z>=MAXSTINC))
+ st_inc_zi=-st_inc_zi;
+ }
+
+ for(f=0;f<NOSTAR;f++)
+ {
+ StarPos(star+f,&x,&y);
+
+ if (getpixel(img,x,y)==star[f].col)
+ putpixel(img,x,y,BLACK);
+
+ star[f].x+=st_inc_x;
+
+ if (star[f].x<(float)-STARCUBEXY)
+ star[f].x+=STARCUBEXY*2;
+
+ if (star[f].x>(float)STARCUBEXY)
+ star[f].x-=STARCUBEXY*2;
+
+ star[f].y+=st_inc_y;
+
+ if (star[f].y<(float)-STARCUBEXY)
+ star[f].y+=STARCUBEXY*2;
+
+ if (star[f].y>(float)STARCUBEXY)
+ star[f].y-=STARCUBEXY*2;
+
+ star[f].z+=st_inc_z;
+
+ if (star[f].z<=0.0)
+ star[f].z+=STARCUBEZ;
+
+ if (star[f].z>(float)STARCUBEZ)
+ star[f].z-=STARCUBEZ;
+
+ StarPos(star+f,&x,&y);
+
+ if (getpixel(img,x,y)==BLACK)
+ putpixel(img,x,y,star[f].col);
+ }
+}
+
+
+/* -------------------------------------------------------------------------
+ PARTCLE ROUTINES
+ ------------------------------------------------------------------------- */
+#define PARTICLELIFE 25
+
+typedef struct Particle
+ {
+ int x,y;
+ int xi,yi;
+ int col;
+ int old_col;
+ int life;
+ struct Particle *next;
+ } Particle;
+
+Particle *part_head=NULL;
+Particle *part_tail=NULL;
+unsigned int part_cnt;
+
+void InitParticles(void)
+{
+ Particle *p;
+
+ while(part_head)
+ {
+ p=part_head;
+ part_head=part_head->next;
+ free(p);
+ }
+
+ part_head=NULL;
+ part_tail=NULL;
+}
+
+
+void RemoveParticles(void)
+{
+ Particle *p;
+
+ p=part_head;
+
+ while(p)
+ {
+ if (getpixel(img,p->x,p->y)==p->col)
+ putpixel(img,p->x,p->y,p->old_col);
+ p=p->next;
+ }
+}
+
+
+void UpdateParticles(void)
+{
+ Particle *p;
+
+ /* May as well check, as there'll be more often no particles to do
+ */
+ if (!(p=part_head))
+ return;
+
+ /* Looks naff, but it's better in seperate passes to make sure we don't
+ leave any aftifacts and make the particle routines entirely transparent.
+ Having said that it does clash with the starfield anyway!
+ */
+ while(p)
+ {
+ if (getpixel(img,p->x,p->y)==p->col)
+ putpixel(img,p->x,p->y,p->old_col);
+
+ p=p->next;
+ }
+
+ p=part_head;
+
+ while(p)
+ {
+ p->x+=p->xi;
+ p->y+=p->yi;
+ p->life--;
+ p->old_col=getpixel(img,p->x,p->y);
+
+ p=p->next;
+ }
+
+ p=part_head;
+
+ while(p)
+ {
+ if (p->life)
+ putpixel(img,p->x,p->y,p->col);
+
+ p=p->next;
+ }
+
+ /* Remove dead particles from the list
+ */
+ while((part_head)&&(part_head->life==0))
+ {
+ p=part_head;
+ part_head=part_head->next;
+ free(p);
+ }
+
+ if (!part_head)
+ part_tail=NULL;
+}
+
+
+void AddParticle(int x, int y, int xi, int yi)
+{
+ Particle *p;
+
+ if (!(p=(Particle *)malloc(sizeof(Particle))))
+ Error("malloc(Particle) failed");
+
+ if ((!xi)&&(!yi))
+ xi=1;
+
+ p->x=x;
+ p->y=y;
+ p->xi=xi;
+ p->yi=yi;
+ p->col=RND(PARTCOLMAX-PARTCOLMIN)+PARTCOLMIN;
+ p->life=PARTICLELIFE;
+ p->next=NULL;
+
+ if (part_head)
+ {
+ part_tail->next=p;
+ part_tail=p;
+ }
+ else
+ {
+ part_head=p;
+ part_tail=p;
+ }
+}
+
+
+/* -------------------------------------------------------------------------
+ DEFINE KEYS
+ ------------------------------------------------------------------------- */
+
+void DefineKeys(void)
+{
+ static struct {int *key; char *prompt;} kdef[]=
+ {
+ {&KLEFT, "Left "},
+ {&KRIGHT, "Right "},
+ {&KROTATEL,"Rotate clockwise/up "},
+ {&KROTATER,"Rotate clockwise/down "},
+ {&KDROP, "Drop/fire "},
+ {&KPAUSE, "Pause "},
+ };
+ int k;
+ int f;
+ int tx,kx,ty;
+
+ used_keys[KLEFT]=FALSE;
+ used_keys[KRIGHT]=FALSE;
+ used_keys[KROTATER]=FALSE;
+ used_keys[KROTATEL]=FALSE;
+ used_keys[KDROP]=FALSE;
+ used_keys[KPAUSE]=FALSE;
+
+ text_mode(0);
+ f=0;
+ clear(img);
+ clear_keybuf();
+
+ CENTRE("_____________",2,WHITE);
+ CENTRE("REDEFINE KEYS",0,WHITE);
+
+ while(f<6)
+ {
+ tx=10;
+ kx=10+text_length(font8,kdef[f].prompt);
+ ty=50+f*16;
+
+ textout(img,font8,kdef[f].prompt,tx,ty,YELLOW);
+
+ Redraw();
+
+ while((k=GETKEY)==-1);
+
+ *kdef[f].key=k;
+
+ rectfill(img,kx,ty,319,ty+8,BLACK);
+ textout(img,font8,keystr[k],kx,ty,WHITE);
+
+ if (used_keys[k])
+ {
+ CENTRE("KEY ALREADY USED!",SCREEN_H-8,RED);
+ Redraw();
+ }
+ else
+ {
+ CENTRE(" ",SCREEN_H-8,BLACK);
+ Redraw();
+ used_keys[k]=TRUE;
+ while (key[k]);
+ clear_keybuf();
+ f++;
+ }
+ }
+
+ while(GETKEY!=KEY_SPACE)
+ {
+ CENTRE("PRESS SPACE",SCREEN_H-8,RND(16)+1);
+ Redraw();
+ }
+
+ clear_keybuf();
+}
+
+
+/* -------------------------------------------------------------------------
+ README FILE
+ ------------------------------------------------------------------------- */
+
+void ReadMe(void)
+{
+ static char *readme[]=
+ {
+# include "readme.h"
+ NULL
+ };
+
+ char *t;
+ int l=0;
+ int p;
+ int py;
+ int f;
+ int y;
+
+ for(f=0;readme[f];f++)
+ l=f;
+
+ p=l-2;
+ py=-8;
+
+ while(GETKEY!=KEY_SPACE)
+ {
+ clear(img);
+
+ text_mode(BLACK);
+ for(y=py,f=0;y<SCREEN_H+8;f++,y+=8)
+ if (*(t=readme[(p+f)%l])!='@')
+ textout_centre(img,font8,t,CX,y,GREY3);
+ else
+ textout_centre(img,font8,t+1,CX,y,WHITE);
+
+ rectfill(img,0,0,SCREEN_W-1,8,BLUE);
+ rectfill(img,0,SCREEN_H-9,SCREEN_W-1,SCREEN_H-1,BLUE);
+
+ text_mode(BLUE);
+ textout_centre(img,font8,"CURSOR KEYS to MOVE",CX,1,BLACK);
+ textout_centre(img,font8,"SPACE to return to title page",
+ CX,SCREEN_H-8,BLACK);
+
+ Redraw();
+
+ if (key[KEY_DOWN])
+ {
+ if (SLOW)
+ py-=4;
+ else
+ py--;
+
+ if (py==-16)
+ {
+ py=-8;
+
+ if (++p==l)
+ p=0;
+ }
+ }
+ else if (key[KEY_UP])
+ {
+ if (SLOW)
+ py+=4;
+ else
+ py++;
+
+ if (py==0)
+ {
+ py=-8;
+
+ if (--p<0)
+ p=l-1;
+ }
+ }
+ }
+
+ clear(img);
+ clear_keybuf();
+
+}
+
+
+/* -------------------------------------------------------------------------
+ TITLE PAGE
+ ------------------------------------------------------------------------- */
+
+void TitlePage(void)
+{
+ static char *title[]={"(c) Noddybox 1998",
+ "Press SPACE to start",
+ "This game helped along by",
+ "The Prodigy - NiN",
+ "Suzanne Vega - Texas",
+ "FSOL - Placebo",
+ "Garbage - Meridith Brooks",
+ "Babylon 5 - Castlevania CD",
+ "This game not at ALL helped by",
+ "3Dfx - Tomb Raider II",
+ "Diddy Kong Racing - PS Castlevania",
+ "Goldeneye 64",
+ " ",
+ "Shaken, not stirred...",
+ " ",
+ "Hello to anyone who may know me",
+ " ",
+ NULL};
+
+ static char *footer[]={"Written using Allegro 3.0",
+ "Allegro written by Shawn Hargreaves",
+ NULL};
+
+ static char *instruct[]={"PRESS SPACE TO PLAY",
+ "PRESS I FOR INSTRUCTIONS",
+ "PRESS R TO REDFINE KEYS",
+ NULL};
+
+ char s[80];
+ unsigned int ctr=0;
+ int tpos=0;
+ int fpos=0;
+ int ipos=0;
+ int done=FALSE;
+ int f;
+ int hisc_mode=MODE;
+ int meltcol;
+
+ clear(img);
+ clear_keybuf();
+
+ if (SLOW)
+ text_mode(0);
+ else
+ text_mode(-1);
+
+ if (MUSIC)
+ play_midi(title_midi,TRUE);
+
+ while (!done)
+ {
+ if (SLOW)
+ clear(img);
+ else
+ Melt(0,0,SCREEN_W-1,SCREEN_H-1);
+
+ if (ctr&1)
+ meltcol=MELTOMAX;
+ else
+ meltcol=WHITE;
+
+ CENTRE(title[tpos],8,meltcol);
+ CENTRE("HARDWIRE",CY/2-8,meltcol);
+
+ sprintf(s,"GAME MODE - %s",modetxt[MODE]);
+ CENTRE(s,CY-30,meltcol);
+
+ sprintf(s,"LEVEL - %-2d WIDTH - %-2d",LEVEL,PITWIDTH);
+ CENTRE(s,CY-22,meltcol);
+
+ sprintf(s,"MOTION SICKNESS - %3s MUSIC - %3s",
+ (MOTION ? "YES" : "NO "),
+ (MUSIC ? "YES" : "NO "));
+ CENTRE(s,CY-14,meltcol);
+
+ CENTRE(instruct[ipos],CY,meltcol);
+
+ sprintf(s,"BEST %s SCORES",modetxt[hisc_mode]);
+ CENTRE(s,CY+16,meltcol);
+
+ for(f=0;f<HISC;f++)
+ {
+ sprintf(s,"%d %-3s %3d %7d", f+1,
+ hisc[hisc_mode][f].name,
+ hisc[hisc_mode][f].level,
+ hisc[hisc_mode][f].score);
+ CENTRE(s,CY+34+f*8,meltcol);
+ }
+
+ CENTRE(footer[fpos],SCREEN_H-12,WHITE);
+
+ line(img,0,SCREEN_H-2,SCREEN_W-1,SCREEN_H-2,meltcol);
+
+ ctr++;
+
+ if (!(ctr%50))
+ if (!instruct[++ipos])
+ ipos=0;
+
+ if (!(ctr%30))
+ if (!title[++tpos])
+ tpos=0;
+
+ if (!(ctr%75))
+ if (!footer[++fpos])
+ fpos=0;
+
+ if (!(ctr%150))
+ if (++hisc_mode==GAME_TYPES)
+ hisc_mode=0;
+
+ Redraw();
+
+ switch(GETKEY)
+ {
+ case KQUIT:
+ quit=TRUE;
+ done=TRUE;
+ break;
+ case KTOGGLE_MODE:
+ if (++MODE==GAME_TYPES)
+ MODE=0;
+ break;
+ case KTOGGLE_LEVEL:
+ if (++LEVEL==11)
+ LEVEL=1;
+ break;
+ case KTOGGLE_MOTION:
+ MOTION=!MOTION;
+ break;
+ case KTOGGLE_MUSIC:
+ if (SOUND)
+ {
+ MUSIC=!MUSIC;
+
+ if (MUSIC)
+ play_midi(title_midi,TRUE);
+ else
+ stop_midi();
+ }
+ break;
+ case KTOGGLE_WIDTH:
+ if (--PITWIDTH<MINPITWIDTH)
+ PITWIDTH=MAXPITWIDTH;
+ break;
+ case KREADME:
+ ReadMe();
+
+ if (SLOW)
+ text_mode(0);
+ else
+ text_mode(-1);
+
+ clear(img);
+ break;
+ case KDEFINE:
+ DefineKeys();
+
+ if (SLOW)
+ text_mode(0);
+ else
+ text_mode(-1);
+
+ clear(img);
+ break;
+ case KEY_SPACE:
+ done=TRUE;
+ break;
+ }
+ }
+
+ if (MUSIC)
+ stop_midi();
+}
+
+
+/* -------------------------------------------------------------------------
+ TETRIS WIRE SPECIFIC CODE
+ ------------------------------------------------------------------------- */
+
+void GenTetrisWirePiece(int special)
+{
+ PieceSet *ps;
+ int x,y;
+
+ game.current=game.next;
+ game.current_type=game.next_type;
+ game.is_special=game.next_is_special;
+
+ game.x=PITWIDTH/2;
+
+ if (game.is_special)
+ game.y=-1;
+ else
+ game.y=-tetris_height[game.current_type]+game.current.oy;
+
+ game.rotate=0;
+
+ game.next_is_special=special;
+
+ if (special)
+ {
+ game.next_type=-1;
+ for(x=0;x<4;x++)
+ for(y=0;y<4;y++)
+ if ((x)||(y))
+ game.next.data[y][x]=BLANK;
+ else
+ game.next.data[y][x]=SPECIAL;
+
+ game.next.ox=0;
+ game.next.oy=0;
+ }
+ else
+ {
+ game.next_type=RND(NO_TETRIS_PIECE);
+
+ for(x=0;x<4;x++)
+ for(y=0;y<4;y++)
+ if (tetris_map[game.next_type].data[y][x]==BLANK)
+ game.next.data[y][x]=BLANK;
+ else
+ {
+ ps=piece_set+tetris_map[game.next_type].data[y][x];
+ game.next.data[y][x]=ps->piece[RND(ps->no)];
+ }
+
+ game.next.ox=tetris_off[game.next_type][0].x;
+ game.next.oy=tetris_off[game.next_type][0].y;
+ }
+}
+
+
+void RotTetrisWirePiece(int dir)
+{
+ int x,y;
+ Piece p;
+
+ if (game.is_special)
+ return;
+
+ if (dir==LEFT)
+ {
+ game.rotate=ROL(game.rotate);
+
+ for(x=0;x<4;x++)
+ for(y=0;y<4;y++)
+ p.data[x][3-y]=ROL_Piece(game.current.data[y][x]);
+
+ p.ox=tetris_off[game.current_type][game.rotate].x;
+ p.oy=tetris_off[game.current_type][game.rotate].y;
+ }
+ else
+ {
+ game.rotate=ROR(game.rotate);
+
+ for(x=0;x<4;x++)
+ for(y=0;y<4;y++)
+ p.data[3-x][y]=ROR_Piece(game.current.data[y][x]);
+
+ p.ox=tetris_off[game.current_type][game.rotate].x;
+ p.oy=tetris_off[game.current_type][game.rotate].y;
+ }
+
+ game.current=p;
+}
+
+
+/* -------------------------------------------------------------------------
+ TETRIS CLASSIC SPECIFIC CODE
+ ------------------------------------------------------------------------- */
+
+void GenTetrisClassicPiece(int special)
+{
+ static int type_map[NO_TETRIS_PIECE]={BLOCK1SPR,
+ BLOCK2SPR,
+ BLOCK3SPR,
+ BLOCK4SPR,
+ BLOCK5SPR,
+ BLOCK6SPR,
+ BLOCK7SPR};
+ int x,y;
+
+ game.current=game.next;
+ game.current_type=game.next_type;
+ game.is_special=game.next_is_special;
+
+ game.x=PITWIDTH/2;
+
+ if (game.is_special)
+ game.y=-1;
+ else
+ game.y=-tetris_height[game.current_type]+game.current.oy;
+
+ game.rotate=0;
+
+ game.next_is_special=FALSE;
+
+ game.next_type=RND(NO_TETRIS_PIECE);
+
+ for(x=0;x<4;x++)
+ for(y=0;y<4;y++)
+ if (tetris_map[game.next_type].data[y][x]==BLANK)
+ game.next.data[y][x]=BLANK;
+ else
+ game.next.data[y][x]=type_map[game.next_type];
+
+ game.next.ox=tetris_off[game.next_type][0].x;
+ game.next.oy=tetris_off[game.next_type][0].y;
+}
+
+
+void RotTetrisClassicPiece(int dir)
+{
+ int x,y;
+ Piece p;
+
+ if (game.is_special)
+ return;
+
+ if (dir==LEFT)
+ {
+ game.rotate=ROL(game.rotate);
+
+ for(x=0;x<4;x++)
+ for(y=0;y<4;y++)
+ p.data[x][3-y]=game.current.data[y][x];
+
+ p.ox=tetris_off[game.current_type][game.rotate].x;
+ p.oy=tetris_off[game.current_type][game.rotate].y;
+ }
+ else
+ {
+ game.rotate=ROR(game.rotate);
+
+ for(x=0;x<4;x++)
+ for(y=0;y<4;y++)
+ p.data[3-x][y]=game.current.data[y][x];
+
+ p.ox=tetris_off[game.current_type][game.rotate].x;
+ p.oy=tetris_off[game.current_type][game.rotate].y;
+ }
+
+ game.current=p;
+}
+
+
+/* -------------------------------------------------------------------------
+ COLUMNS SPECIFIC CODE
+ ------------------------------------------------------------------------- */
+
+void GenColumnsWirePiece(int special)
+{
+ int x,y;
+
+ game.current=game.next;
+ game.current_type=game.next_type;
+ game.is_special=game.next_is_special;
+
+ game.x=PITWIDTH/2;
+
+ if (game.is_special)
+ game.y=-1;
+ else
+ game.y=-3;
+
+ game.rotate=0;
+
+ game.next.ox=0;
+ game.next.oy=0;
+
+ game.next_is_special=special;
+
+ if (special)
+ {
+ for(x=0;x<4;x++)
+ for(y=0;y<4;y++)
+ if ((x)||(y))
+ game.next.data[y][x]=BLANK;
+ else
+ game.next.data[y][x]=SPECIAL;
+ }
+ else
+ {
+ for(x=0;x<4;x++)
+ for(y=0;y<4;y++)
+ if ((x)||(y==3))
+ game.next.data[y][x]=BLANK;
+ else
+ game.next.data[y][x]=RNDPIECE;
+ }
+}
+
+
+void RotColumnsWirePiece(int dir)
+{
+ int y,t;
+
+ if (game.is_special)
+ return;
+
+ if (dir==LEFT)
+ {
+ t=game.current.data[0][0];
+
+ for(y=0;y<2;y++)
+ game.current.data[y][0]=game.current.data[y+1][0];
+
+ game.current.data[2][0]=t;
+ }
+ else
+ {
+ t=game.current.data[2][0];
+
+ for(y=2;y>0;y--)
+ game.current.data[y][0]=game.current.data[y-1][0];
+
+ game.current.data[0][0]=t;
+ }
+}
+
+
+/* -------------------------------------------------------------------------
+ PLAY GAME UTILS
+ ------------------------------------------------------------------------- */
+
+int MoveOK(int x, int y)
+{
+ int cx,cy,nx,ny;
+
+ for(cx=0;cx<4;cx++)
+ for(cy=0;cy<4;cy++)
+ if (game.current.data[cy][cx]!=BLANK)
+ {
+ nx=x+cx-game.current.ox;
+ ny=y+cy-game.current.oy;
+
+ if ((nx<0)||(nx>=PITWIDTH)||(ny>=PITDEPTH))
+ return(FALSE);
+
+ if ((ny>=0)&&(pit.data[ny][nx]!=BLANK))
+ return(FALSE);
+ }
+
+ return(TRUE);
+}
+
+
+int AddAndCheckIsDead(int id)
+{
+ int cx,cy,nx,ny;
+
+ if (game.is_special)
+ return(game.y<0);
+ else
+ for(cx=0;cx<4;cx++)
+ for(cy=0;cy<4;cy++)
+ if (game.current.data[cy][cx]!=BLANK)
+ {
+ nx=game.x+cx-game.current.ox;
+ ny=game.y+cy-game.current.oy;
+
+ if ((nx<0)||(nx>=PITWIDTH)||(ny<0)||(ny>=PITDEPTH))
+ return(TRUE);
+
+ pit.data[ny][nx]=game.current.data[cy][cx];
+ pit.id[ny][nx]=id;
+ }
+
+ return(FALSE);
+}
+
+
+void UnglueID(int id)
+{
+ int x,y;
+
+ for(x=0;x<PITWIDTH;x++)
+ for(y=0;y<PITDEPTH;y++)
+ if (pit.id[y][x]==id)
+ pit.id[y][x]=0;
+}
+
+
+void CompressPath(void)
+{
+ int x,y,ny;
+
+ for(x=0;x<PITWIDTH;x++)
+ {
+ y=PITDEPTH-1;
+
+ while(y)
+ {
+ if (pit.data[y][x]==PATH)
+ {
+ if (pit.id[y][x])
+ UnglueID(pit.id[y][x]);
+
+ for(ny=y;ny;ny--)
+ {
+ pit.data[ny][x]=pit.data[ny-1][x];
+ pit.id[ny][x]=pit.id[ny-1][x];
+
+ if (pit.id[ny][x])
+ UnglueID(pit.id[ny][x]);
+ }
+
+ pit.data[0][x]=BLANK;
+ pit.id[0][x]=0;
+ }
+ else
+ y--;
+ }
+ }
+}
+
+
+int IsDropPieceAbove(int x, int y)
+{
+ while(y>=0)
+ if (pit.data[y][x]!=BLANK)
+ return (pit.id[y][x]==0);
+ else
+ y--;
+ return(FALSE);
+}
+
+
+void CompressBlanks(void)
+{
+ int x,y,ny;
+
+ for(x=0;x<PITWIDTH;x++)
+ {
+ y=PITDEPTH-1;
+
+ while(y)
+ /* This is a bit wasteful, but will ensure that no checks are missed
+ out...
+ */
+ if ((pit.data[y][x]==BLANK)&&(IsDropPieceAbove(x,y-1)))
+ {
+ for(ny=y;(ny)&&(!pit.id[ny][x]);ny--)
+ {
+ pit.data[ny][x]=pit.data[ny-1][x];
+ pit.id[ny][x]=pit.id[ny-1][x];
+ }
+
+ if (ny!=y)
+ {
+ pit.data[ny][x]=BLANK;
+ pit.id[ny][x]=0;
+ }
+ else
+ y--;
+ }
+ else
+ y--;
+ }
+}
+
+
+void GameRedraw(void)
+{
+ if (MOTION)
+ RemoveStars();
+
+ UpdateScores();
+
+ UpdateParticles();
+
+ if (MOTION)
+ UpdateStars();
+
+ Redraw();
+}
+
+
+void DoPause(void)
+{
+ BITMAP *pause;
+ fixed rot,scale,scalei;
+
+ pause=(BITMAP *)dfile[PAUSE_BMP].dat;
+
+ blit(img,workimg,0,0,0,0,SCREEN_W,SCREEN_H);
+
+ clear_keybuf();
+
+ rot=0;
+ scale=1<<16;
+ scalei=0x0400;
+
+ while(GETKEY!=KPAUSE)
+ {
+ draw_character(img,workimg,0,0,MELTOMAX-1);
+
+ rotate_scaled_sprite(img,pause,60,70,rot<<16,scale);
+
+ if (++rot==256)
+ rot=0;
+
+ scale+=scalei;
+
+ if ((scale>=(2<<16))||(scale<=(0x4000)))
+ scalei=-scalei;
+
+ Redraw();
+ }
+
+ clear_keybuf();
+ blit(workimg,img,0,0,0,0,SCREEN_W,SCREEN_H);
+ Redraw();
+}
+
+
+/* -------------------------------------------------------------------------
+ PATH AND SCORE CHECKERS
+ ------------------------------------------------------------------------- */
+
+void CheckWirePaths(void)
+{
+ int sc;
+ Path path;
+
+ game.score+=game.level;
+
+ if (game.is_special)
+ {
+ GetSpecialPath(&path);
+
+ /* Shouldn't be false anyway...
+ */
+ if (path.len)
+ {
+ sc=(path.len*game.level);
+ game.score+=sc;
+ AddScore("SPECIAL",sc);
+ DrawPath(&path);
+ RedrawPit();
+ DrawInfo();
+ GameRedraw();
+ CompressPath();
+ RedrawPit();
+ GameRedraw();
+ CompressBlanks();
+ RedrawPit();
+ GameRedraw();
+ }
+ }
+
+ /* Check for paths
+ */
+ while (FindPath(&path))
+ {
+ sc=(path.len*game.level)*10;
+ game.score+=sc;
+ AddScore("CIRCUIT",sc);
+ DrawPath(&path);
+ RedrawPit();
+ DrawInfo();
+ GameRedraw();
+ CompressPath();
+ RedrawPit();
+ GameRedraw();
+ CompressBlanks();
+ RedrawPit();
+ GameRedraw();
+ }
+
+ /* Check for loops
+ */
+ while (FindLoop(&path))
+ {
+ sc=(path.len*game.level)*10;
+ game.score+=sc;
+ AddScore("LOOP",sc);
+ DrawPath(&path);
+ RedrawPit();
+ DrawInfo();
+ GameRedraw();
+ CompressPath();
+ RedrawPit();
+ GameRedraw();
+ CompressBlanks();
+ RedrawPit();
+ GameRedraw();
+ }
+
+}
+
+
+void CheckClassicPaths(void)
+{
+ Path path;
+ int x,y;
+ int rows;
+ int is_row;
+ int sc;
+
+ game.score+=game.level;
+
+ /* Check for rows
+ */
+ rows=0;
+ path.len=0;
+
+ for(y=0;y<PITDEPTH;y++)
+ {
+ is_row=TRUE;
+
+ for(x=0;x<PITWIDTH;x++)
+ if (pit.data[y][x]==BLANK)
+ is_row=FALSE;
+
+ if (is_row)
+ {
+ rows++;
+ for(x=0;x<PITWIDTH;x++)
+ {
+ path.p[path.len].x=x;
+ path.p[path.len].y=y;
+ path.len++;
+ }
+ }
+ }
+
+ if (rows>0)
+ {
+ sc=(game.level<<(rows-1))*10;
+ game.score+=sc;
+ switch(rows)
+ {
+ case 1:
+ AddScore("Single",sc);
+ break;
+ case 2:
+ AddScore("Double",sc);
+ break;
+ case 3:
+ AddScore("Triple",sc);
+ break;
+ case 4:
+ AddScore("TETRIS!",sc);
+ break;
+ }
+
+ DrawPath(&path);
+ RedrawPit();
+ DrawInfo();
+ GameRedraw();
+ CompressPath();
+ RedrawPit();
+ GameRedraw();
+ }
+}
+
+
+/* -------------------------------------------------------------------------
+ PLAY GAME
+ ------------------------------------------------------------------------- */
+
+void PlayGame(void)
+{
+ struct {int rot_r,rot_l,left,right,drop;} bounce;
+ int mvctr;
+ int dead;
+ int no;
+ int id;
+ int k;
+
+ bounce.rot_r=0;
+ bounce.rot_l=0;
+ bounce.left=0;
+ bounce.right=0;
+ bounce.drop=0;
+
+ no=0;
+ id=1;
+ dead=FALSE;
+ mvctr=LEVELCTR(game.level);
+
+ text_mode(0);
+ clear_keybuf();
+
+ if (MUSIC)
+ play_midi(game_midi,TRUE);
+
+ if (MOTION)
+ InitStars();
+
+ InitParticles();
+
+ InitScores();
+
+ while(!dead)
+ {
+ /* Not a switch as some are variables now
+ */
+ k=GETKEY;
+
+ if (k==KQUIT)
+ dead=TRUE;
+
+ if (k==KPAUSE)
+ DoPause();
+
+ if (k==KBORED)
+ {
+ game.level++;
+ DrawInfo();
+ }
+
+ /* See if it's time for the block to drop
+ */
+ if (!(mvctr--))
+ {
+ ErasePiece();
+
+ /* See if piece can move down
+ */
+ if (MoveOK(game.x,game.y+1))
+ {
+ SoundFX(CLICK_FX);
+ game.y++;
+ mvctr=LEVELCTR(game.level);
+ DrawPiece();
+ GameRedraw();
+ }
+ else
+ {
+ SoundFX(POP_FX);
+
+ if (AddAndCheckIsDead(id++))
+ {
+ /* If dead, setup exit of loop.
+ */
+ dead=TRUE;
+ DrawPiece();
+ }
+ else
+ {
+ /* Check for scoring and paths
+ */
+ (*gamedef[MODE].do_paths)();
+
+ /* Generate new piece and reset counters
+ */
+ (*gamedef[MODE].gen_piece)
+ ((id%gamedef[MODE].special_count)==0);
+
+ bounce.rot_r=0;
+ bounce.rot_l=0;
+ bounce.left=0;
+ bounce.right=0;
+ bounce.drop=0;
+
+ if (++no==(game.level*5))
+ {
+ game.level++;
+ no=0;
+ }
+
+ mvctr=LEVELCTR(game.level);
+
+ RedrawPit();
+ DrawInfo();
+ GameRedraw();
+ }
+ }
+ }
+ else
+ /* If it's not block dropping time, allow it to move
+ */
+ {
+ ErasePiece();
+
+ /* Check left/right
+ */
+ if ((key[KLEFT])&&(!bounce.left))
+ {
+ bounce.left=BOUNCEVAL;
+
+ if (MoveOK(game.x-1,game.y))
+ game.x--;
+ }
+ else if ((key[KRIGHT])&&(!bounce.right))
+ {
+ bounce.right=BOUNCEVAL;
+
+ if (MoveOK(game.x+1,game.y))
+ game.x++;
+ }
+
+ if ((key[KDROP])&&(!bounce.drop))
+ {
+ bounce.drop=BOUNCEVAL;
+ mvctr=0;
+ }
+
+ if ((key[KROTATEL])&&(!bounce.rot_l))
+ {
+ (*gamedef[MODE].rot_piece)(LEFT);
+
+ if (MoveOK(game.x,game.y))
+ bounce.rot_l=BOUNCEVAL;
+ else
+ (*gamedef[MODE].rot_piece)(RIGHT);
+ }
+ else if ((key[KROTATER])&&(!bounce.rot_r))
+ {
+ (*gamedef[MODE].rot_piece)(RIGHT);
+
+ if (MoveOK(game.x,game.y))
+ bounce.rot_r=BOUNCEVAL;
+ else
+ (*gamedef[MODE].rot_piece)(LEFT);
+ }
+
+ DrawPiece();
+ GameRedraw();
+ }
+
+ /* Bounce keys
+ */
+ KEYBOUNCE(KROTATEL,bounce.rot_l);
+ KEYBOUNCE(KROTATER,bounce.rot_r);
+ KEYBOUNCE(KLEFT,bounce.left);
+ KEYBOUNCE(KRIGHT,bounce.right);
+ KEYBOUNCE(KDROP,bounce.drop);
+ }
+
+ if (MUSIC)
+ stop_midi();
+
+ SoundFX(GAMEOVER_FX);
+}
+
+
+/* -------------------------------------------------------------------------
+ GAME OVER
+ ------------------------------------------------------------------------- */
+
+void GameOver(void)
+{
+ int f;
+ int ctr;
+ int k;
+
+ clear_keybuf();
+ text_mode(-1);
+
+ /* Copy game screen to work screen and do some stuff
+ */
+ if (MOTION)
+ RemoveStars();
+
+ blit(img,workimg,0,0,0,0,SCREEN_W,SCREEN_H);
+
+ f=0;
+
+ if (SLOW)
+ ctr=20;
+ else
+ ctr=100;
+
+ while((f<(SCREEN_H/2)-1)&&(!((k=GETKEY)==KDROP))&&(!(k==KEY_SPACE)))
+ {
+ textout_centre(workimg,font8,"game over",CX,SCREEN_H/2-4,RND(255));
+
+ stretch_blit(workimg,img,f,f,SCREEN_W-f*2,SCREEN_H-f*2,
+ 0,0,SCREEN_W,SCREEN_H);
+ if (SLOW)
+ {
+ if (ctr)
+ ctr--;
+ else
+ f+=8;
+ }
+ else
+ {
+ if (ctr)
+ ctr--;
+ else
+ f+=2;
+ }
+
+ if (MOTION)
+ UpdateStars();
+
+ Redraw();
+ }
+
+}
+
+
+/* -------------------------------------------------------------------------
+ ENTER HISCORE
+ ------------------------------------------------------------------------- */
+
+void EnterHisc(void)
+{
+ static char hisc_let[]="ABCDEFGHIJKLMNOPQRSTUVXYZ. ~<>";
+
+ char s[80];
+ int sc;
+ int f;
+ int sl;
+ int sbx;
+ int done;
+ int curs;
+ int len;
+ int spr;
+ int ctr;
+ int k;
+
+ clear(img);
+ sl=strlen(hisc_let);
+ sbx=CX-text_length(font8,hisc_let)/2-3;
+ len=0;
+ done=FALSE;
+ curs=0;
+ spr=HISC_CURS1;
+ ctr=0;
+
+ /* Work out which hiscore to use
+ */
+ for(f=0,sc=-1;(f<HISC)&&(sc==-1);f++)
+ if (game.score>hisc[MODE][f].score)
+ sc=f;
+
+ for(f=HISC-1;f>sc;f--)
+ hisc[MODE][f]=hisc[MODE][f-1];
+
+ strcpy(hisc[MODE][sc].name,"");
+ hisc[MODE][sc].level=LEVEL;
+ hisc[MODE][sc].score=game.score;
+
+ if (MUSIC)
+ play_midi(score_midi,TRUE);
+
+ text_mode(0);
+
+ /* Go and do entry
+ */
+ while(!done)
+ {
+ rectfill(img,0,0,SCREEN_W-1,50,BLACK);
+
+ CENTRE(hisc_let,20,WHITE);
+
+ draw_rle_sprite(img,SPR(spr),sbx+curs*8,17);
+
+ if ((ctr++%10)==0)
+ if (++spr>HISC_CURS3)
+ spr=HISC_CURS1;
+
+ CENTRE("ENTER YOUR INITIALS",CY,CYAN);
+
+ k=GETKEY;
+
+ if ((k==KLEFT)||(k==KEY_LEFT))
+ {
+ SoundFX(CLICK_FX);
+ if (len==3)
+ {
+ if (curs==sl-2)
+ curs=sl-1;
+ else
+ curs=sl-2;
+ }
+ else
+ {
+ if (curs)
+ curs--;
+ else
+ curs=sl-1;
+ }
+ }
+
+ else if((k==KRIGHT)||(k==KEY_RIGHT))
+ {
+ SoundFX(CLICK_FX);
+ if (len==3)
+ {
+ if (curs==sl-2)
+ curs=sl-1;
+ else
+ curs=sl-2;
+ }
+ else
+ {
+ if (curs==(sl-1))
+ curs=0;
+ else
+ curs++;
+ }
+ }
+ else if ((k==KDROP)||(k==KEY_SPACE))
+ {
+ SoundFX(POP_FX);
+ switch(hisc_let[curs])
+ {
+ case '<':
+ if (len)
+ {
+ len--;
+ hisc[MODE][sc].name[len]=0;
+ }
+ break;
+
+ case '>':
+ done=TRUE;
+ break;
+
+ default:
+ hisc[MODE][sc].name[len]=hisc_let[curs];
+ hisc[MODE][sc].name[++len]=0;
+
+ if (len==3)
+ curs=sl-1;
+ break;
+ }
+ }
+
+ for(f=0;f<HISC;f++)
+ {
+ sprintf(s,"%d %-3s %3d %7d", f+1,
+ hisc[MODE][f].name,
+ hisc[MODE][f].level,
+ hisc[MODE][f].score);
+ if (f==sc)
+ CENTRE(s,150+f*8,WHITE);
+ else
+ CENTRE(s,150+f*8,RED);
+ }
+
+ if (MOTION)
+ UpdateStars();
+
+ Redraw();
+ }
+
+ if (MUSIC)
+ stop_midi();
+}
diff --git a/hardwire/hardwire.dat b/hardwire/hardwire.dat
new file mode 100644
index 0000000..797b656
--- /dev/null
+++ b/hardwire/hardwire.dat
Binary files differ
diff --git a/hardwire/hardwire.txt b/hardwire/hardwire.txt
new file mode 100644
index 0000000..86807b4
--- /dev/null
+++ b/hardwire/hardwire.txt
@@ -0,0 +1,140 @@
+===============================================================================
+
+ HARDWIRE
+ Version 1.0
+
+ Presented by noddybox '98
+ Written using DJGPP v2 and Allegro 3.0
+
+ Allegro written by Shawn Hargreaves
+
+===============================================================================
+
+
+USAGE
+-----
+
+ hardwire [-v] [-q]
+
+ -v Report version number
+ -q Disable sound (in case you can't stand it or the autodetection
+ messes up)
+ -m Disable music (if you suddenly discover you have good taste)
+ -s Trim some special FX off to try and make it run acceptebly on
+ slower (486) machines.
+
+
+RULES FOR WIRE MODE
+-------------------
+
+Blocks (or columns) will descend the screen in the time honoured tradition, but
+with the slight twist of being made up of pieces of circuit board. Rather than
+making complete horizontal lines it's your jobs to make connections between
+any of the connectors lining the sides and bottom of the pit. A complete
+connection will cause the circuitry to burn up, making more room for the never
+ending supply from upstairs. Likewise makeing a completely enclosed circuit
+will induce a current that destroys those pieces of circuit.
+
+Every so often a special block will fall that once layed in place will blow up
+all circuit pieces that match the ones surrounding it.
+
+If the blocks (even a special) overflow the top of the pit, it's game over and
+back to the dole office.
+
+
+RULES FOR TETRIS CLASSIC MODE
+-----------------------------
+
+Blocks drop down into the pit. Complete horizontal line disappear, causing the
+above lines to move down. The game is over once the pit overflows. I'm sure
+you've heard of the idea... :-)
+
+
+
+
+KEYS (title)
+------------
+
+ F1 Change between TETRIS WIRE, COLUMNS WIRE and TETRIS CLASSIC mode
+ F2 Change game level. Anyone who can play past 10 has my sympathies!
+ F3 Alter pit width.
+ F4 Toggle motion sickness. (Go on, waste those spare CPU cycles!)
+ F5 Toggle music on/off
+ I View instructions and README.
+ R Redefine keys
+ SPACE Play game
+ ESC Quit back to DOS
+
+
+
+KEYS (game)
+-----------
+
+ RIGHT Move block right
+ LEFT Move block left
+ UP Spin block clockwise / rotate column up
+ DOWN Spin block anti-clockwise / rotate column up
+ SPACE Drop block (hold down to keep dropping)
+ P Pause
+ F9 Frankly I'm bored, and may as well goto the next level.
+ ESC Quit back to title (in a rash act of kindness you also get to keep
+ your current score...)
+
+ The movement, rotate, drop and pause keys can be redefined.
+
+
+HINTS
+-----
+
+If you find the graphical frippery of the GAME OVER screen tiresome, it can be
+sped up with the DROP key.
+
+In TETRIS mode blocks will become 'unglued' and drop if there is space below if
+one of it's member pieces is destroyed in a connection, or if it is above a
+piece that gets destroyed in a connection... It should make more sense when
+you see it... Hopefully!
+
+In COLUMNS mode the blocks are always 'unglued'.
+
+If it helps the order of checks is to see if any of the side connectors are the
+start of a circuit, then the bottom ones and then see if any loops have been
+made.
+
+
+
+CONTENTS
+--------
+
+The archive should include :
+
+HARDWIRE.TXT This file
+HARDWIRE.EXE The executable
+CWSDPMI.EXE DOS virtual memory type thingy... You shouldn't need this for
+ Windows 95
+HARDWIRE.DAT The Allegro datafile holding the sprites, sounds, etc.
+ALLEGRO.CFG Setup file for Allegro. If you have troubles with the sound or
+ graphics try editing this (the file is as supplied with Allegro
+ and is reasonably self-documenting)
+
+MAKEFILE. Makefile. Requires GNU make, DJGPP and Allegro
+HARDWIRE.C The source
+PIECEMAP.H Source file defining the tetris piece maps.
+HWPAL.H Definitions for the palette
+HWDAT.H Definitions for the datafile
+KEYSTR.H Scan code -> strings array
+README.H Arrayed version of this file for internal README
+
+
+
+-------------------------------------------------------------------------------
+email: ianc@noddybox.demon.co.uk
+URL: http://www.noddybox.demon.co.uk/
+
+Please send any bug reports or incompatabilities to the above address. Run
+'hardwire -v' to find version number when reporting bugs. TVM.
+
+You are free to do whatever you want with this code, aside from claim
+responsibility for it and charge for it.
+
+
+(c) 1998 noddybox
diff --git a/hardwire/hwdat.h b/hardwire/hwdat.h
new file mode 100644
index 0000000..33014b0
--- /dev/null
+++ b/hardwire/hwdat.h
@@ -0,0 +1,45 @@
+/* Allegro datafile object indexes, produced by grabber v3.0 */
+/* Datafile: c:\src\c\hardwire\v1.0\hardwire.dat */
+/* Date: Sat Feb 14 01:03:08 1998 */
+/* Do not hand edit! */
+
+#define CLICK_FX 0 /* SAMP */
+#define GAMEMIDI 1 /* MIDI */
+#define GAMEOVER_FX 2 /* SAMP */
+#define GAMEQUIT_FX 3 /* SAMP */
+#define HWFONT 4 /* FONT */
+#define HWPAL 5 /* PAL */
+#define PATH_FX 6 /* SAMP */
+#define PAUSE_BMP 7 /* BMP */
+#define POP_FX 8 /* SAMP */
+#define SCOREMIDI 9 /* MIDI */
+#define SPRITE16_000 10 /* RLE */
+#define SPRITE16_001 11 /* RLE */
+#define SPRITE16_002 12 /* RLE */
+#define SPRITE8_000 13 /* RLE */
+#define SPRITE8_001 14 /* RLE */
+#define SPRITE8_002 15 /* RLE */
+#define SPRITE8_003 16 /* RLE */
+#define SPRITE8_004 17 /* RLE */
+#define SPRITE8_005 18 /* RLE */
+#define SPRITE8_006 19 /* RLE */
+#define SPRITE8_007 20 /* RLE */
+#define SPRITE8_008 21 /* RLE */
+#define SPRITE8_009 22 /* RLE */
+#define SPRITE8_010 23 /* RLE */
+#define SPRITE8_011 24 /* RLE */
+#define SPRITE8_012 25 /* RLE */
+#define SPRITE8_013 26 /* RLE */
+#define SPRITE8_014 27 /* RLE */
+#define SPRITE8_015 28 /* RLE */
+#define SPRITE8_016 29 /* RLE */
+#define SPRITE8_017 30 /* RLE */
+#define SPRITE8_018 31 /* RLE */
+#define SPRITE8_019 32 /* RLE */
+#define SPRITE8_020 33 /* RLE */
+#define SPRITE8_021 34 /* RLE */
+#define SPRITE8_022 35 /* RLE */
+#define SPRITE8_023 36 /* RLE */
+#define SPRITE8_024 37 /* RLE */
+#define TITLEMIDI 38 /* MIDI */
+
diff --git a/hardwire/hwscores b/hardwire/hwscores
new file mode 100644
index 0000000..bf2f52c
--- /dev/null
+++ b/hardwire/hwscores
Binary files differ
diff --git a/hardwire/keystr.h b/hardwire/keystr.h
new file mode 100644
index 0000000..61f8398
--- /dev/null
+++ b/hardwire/keystr.h
@@ -0,0 +1,141 @@
+/*
+ General purpose mapping of keycodes to key presses
+*/
+
+#ifndef _KEYSTRH
+
+#define _KEYSTRH
+
+/* 128 string scan code table
+*/
+static char *keystr[128]=
+ {
+ "Code 0", /* 0 */
+ "Esc", /* KEY_ESC 1 */
+ "1", /* KEY_1 2 */
+ "2", /* KEY_2 3 */
+ "3", /* KEY_3 4 */
+ "4", /* KEY_4 5 */
+ "5", /* KEY_5 6 */
+ "6", /* KEY_6 7 */
+ "7", /* KEY_7 8 */
+ "8", /* KEY_8 9 */
+ "9", /* KEY_9 10 */
+ "0", /* KEY_0 11 */
+ "-", /* KEY_MINUS 12 */
+ "=", /* KEY_EQUALS 13 */
+ "Backspace", /* KEY_BACKSPACE 14 */
+ "Tab", /* KEY_TAB 15 */
+ "Q", /* KEY_Q 16 */
+ "W", /* KEY_W 17 */
+ "E", /* KEY_E 18 */
+ "R", /* KEY_R 19 */
+ "T", /* KEY_T 20 */
+ "Y", /* KEY_Y 21 */
+ "U", /* KEY_U 22 */
+ "I", /* KEY_I 23 */
+ "O", /* KEY_O 24 */
+ "P", /* KEY_P 25 */
+ "[", /* KEY_OPENBRACE 26 */
+ "]", /* KEY_CLOSEBRACE 27 */
+ "Enter", /* KEY_ENTER 28 */
+ "Left Ctrl", /* KEY_LCONTROL 29 */
+ "A", /* KEY_A 30 */
+ "S", /* KEY_S 31 */
+ "D", /* KEY_D 32 */
+ "F", /* KEY_F 33 */
+ "G", /* KEY_G 34 */
+ "H", /* KEY_H 35 */
+ "J", /* KEY_J 36 */
+ "K", /* KEY_K 37 */
+ "L", /* KEY_L 38 */
+ ";", /* KEY_COLON 39 */
+ "'", /* KEY_QUOTE 40 */
+ "`", /* KEY_TILDE 41 */
+ "Left Shift", /* KEY_LSHIFT 42 */
+ "#", /* KEY_BACKSLASH 43 */
+ "Z", /* KEY_Z 44 */
+ "X", /* KEY_X 45 */
+ "C", /* KEY_C 46 */
+ "V", /* KEY_V 47 */
+ "B", /* KEY_B 48 */
+ "N", /* KEY_N 49 */
+ "M", /* KEY_M 50 */
+ ",", /* KEY_COMMA 51 */
+ ".", /* KEY_STOP 52 */
+ "/", /* KEY_SLASH 53 */
+ "Right Shift", /* KEY_RSHIFT 54 */
+ "KP *", /* KEY_ASTERISK 55 */
+ "Alt", /* KEY_ALT 56 */
+ "Space", /* KEY_SPACE 57 */
+ "Caps Lock", /* KEY_CAPSLOCK 58 */
+ "F1", /* KEY_F1 59 */
+ "F2", /* KEY_F2 60 */
+ "F3", /* KEY_F3 61 */
+ "F4", /* KEY_F4 62 */
+ "F5", /* KEY_F5 63 */
+ "F6", /* KEY_F6 64 */
+ "F7", /* KEY_F7 65 */
+ "F8", /* KEY_F8 66 */
+ "F9", /* KEY_F9 67 */
+ "F10", /* KEY_F10 68 */
+ "Num Lock", /* KEY_NUMLOCK 69 */
+ "Scroll Lock", /* KEY_SCRLOCK 70 */
+ "Home", /* KEY_HOME 71 */
+ "Up", /* KEY_UP 72 */
+ "Page Up", /* KEY_PGUP 73 */
+ "KP -", /* KEY_MINUS_PAD 74 */
+ "Left", /* KEY_LEFT 75 */
+ "KP 5", /* KEY_5_PAD 76 */
+ "Right", /* KEY_RIGHT 77 */
+ "KP +", /* KEY_PLUS_PAD 78 */
+ "End", /* KEY_END 79 */
+ "Down", /* KEY_DOWN 80 */
+ "Page Down", /* KEY_PGDN 81 */
+ "Ins", /* KEY_INSERT 82 */
+ "Del", /* KEY_DEL 83 */
+ "Prt Scr", /* KEY_PRTSCR 84 */
+ "F11", /* KEY_F11 87 */
+ "F12", /* KEY_F12 88 */
+ "Code 89", /* 89 */
+ "Code 90", /* 90 */
+ "Left Window", /* KEY_LWIN 91 */
+ "Right Window", /* KEY_RWIN 92 */
+ "Menu", /* KEY_MENU 93 */
+ "Code 94", /* 94 */
+ "Code 95", /* 95 */
+ "Code 96", /* 96 */
+ "Code 97", /* 97 */
+ "Code 98", /* 98 */
+ "Code 99", /* 99 */
+ "Pad", /* KEY_PAD 100 */
+ "Code 101", /* 101 */
+ "Code 102", /* 102 */
+ "Code 103", /* 103 */
+ "Code 104", /* 104 */
+ "Code 105", /* 105 */
+ "Code 106", /* 106 */
+ "Code 107", /* 107 */
+ "Code 108", /* 108 */
+ "Code 109", /* 109 */
+ "Code 110", /* 110 */
+ "Code 111", /* 111 */
+ "Code 112", /* 112 */
+ "Code 113", /* 113 */
+ "Code 114", /* 114 */
+ "Code 115", /* 115 */
+ "Code 116", /* 116 */
+ "Code 117", /* 117 */
+ "Code 118", /* 118 */
+ "Code 119", /* 119 */
+ "Right Ctrl", /* KEY_RCONTROL 120 */
+ "Alt Gr", /* KEY_ALTGR 121 */
+ "KP /", /* KEY_SLASH2 122 */
+ "Pause", /* KEY_PAUSE 123 */
+ "Code 124", /* 124 */
+ "Code 125", /* 125 */
+ "Code 126", /* 126 */
+ "Code 127", /* 127 */
+ };
+
+#endif
diff --git a/hardwire/pathway.wav b/hardwire/pathway.wav
new file mode 100644
index 0000000..ed14b28
--- /dev/null
+++ b/hardwire/pathway.wav
Binary files differ
diff --git a/hardwire/pause_bmp.pcx b/hardwire/pause_bmp.pcx
new file mode 100644
index 0000000..e4b1c16
--- /dev/null
+++ b/hardwire/pause_bmp.pcx
Binary files differ
diff --git a/hardwire/piecemap.h b/hardwire/piecemap.h
new file mode 100644
index 0000000..1844663
--- /dev/null
+++ b/hardwire/piecemap.h
@@ -0,0 +1,222 @@
+
+/*
+ Define TETRIS mode piece maps
+
+ Object types :
+
+ SPECIAL
+ CROSS
+ UPDOWN
+ ACROSS
+ LEFTDOWN
+ RIGHTDOWN
+ LEFTUP
+ RIGHTUP
+ BLANK
+
+*/
+
+#define NO_TETRIS_PIECE 7
+
+#define NO_PIECE_SET 11
+
+#define TOP_PS 0
+#define BOT_PS 1
+#define LFT_PS 2
+#define RGT_PS 3
+#define L_R_PS 4
+#define U_D_PS 5
+#define CRS_PS 6
+#define L_U_PS 7
+#define L_D_PS 8
+#define R_U_PS 9
+#define R_D_PS 10
+
+PieceSet piece_set[NO_PIECE_SET]=
+ {
+ { /* TOP_PS */
+ 4,
+ {UPDOWN,CROSS,LEFTDOWN,RIGHTDOWN,BLANK}
+ },
+
+ { /* BOT_PS */
+ 4,
+ {UPDOWN,CROSS,LEFTUP,RIGHTUP,BLANK}
+ },
+
+ { /* LFT_PS */
+ 4,
+ {ACROSS,CROSS,RIGHTDOWN,RIGHTUP,BLANK}
+ },
+
+ { /* RGT_PS */
+ 4,
+ {ACROSS,CROSS,LEFTDOWN,LEFTUP,BLANK}
+ },
+
+ { /* L_R_PS */
+ 2,
+ {ACROSS,CROSS,BLANK,BLANK,BLANK}
+ },
+
+ { /* U_D_PS */
+ 2,
+ {UPDOWN,CROSS,BLANK,BLANK,BLANK}
+ },
+
+ { /* CRS_PS */
+ 1,
+ {CROSS,BLANK,BLANK,BLANK,BLANK}
+ },
+
+ { /* L_U_PS */
+ 2,
+ {LEFTUP,CROSS,BLANK,BLANK,BLANK}
+ },
+
+ { /* L_D_PS */
+ 2,
+ {LEFTDOWN,CROSS,BLANK,BLANK,BLANK}
+ },
+
+ { /* R_U_PS */
+ 2,
+ {RIGHTUP,CROSS,BLANK,BLANK,BLANK}
+ },
+
+ { /* R_D_PS */
+ 2,
+ {RIGHTDOWN,CROSS,BLANK,BLANK,BLANK}
+ }
+ };
+
+
+Piece tetris_map[NO_TETRIS_PIECE]=
+ {
+ { /* PIECE 1 - LONG */
+ 0,0,
+ {
+ {BLANK, TOP_PS, BLANK, BLANK},
+ {BLANK, U_D_PS, BLANK, BLANK},
+ {BLANK, U_D_PS, BLANK, BLANK},
+ {BLANK, BOT_PS, BLANK, BLANK},
+ }
+ },
+ { /* PIECE 2 - BOX */
+ 0,0,
+ {
+ {CRS_PS, CRS_PS, BLANK, BLANK},
+ {CRS_PS, CRS_PS, BLANK, BLANK},
+ {BLANK, BLANK, BLANK, BLANK},
+ {BLANK, BLANK, BLANK, BLANK},
+ }
+ },
+ { /* PIECE 3 - TEE */
+ 0,0,
+ {
+ {BLANK, TOP_PS, BLANK, BLANK},
+ {LFT_PS, CRS_PS, RGT_PS, BLANK},
+ {BLANK, BLANK, BLANK, BLANK},
+ {BLANK, BLANK, BLANK, BLANK},
+ }
+ },
+ { /* PIECE 4 - LEFT DOGLEG */
+ 0,0,
+ {
+ {LFT_PS, L_D_PS, BLANK, BLANK},
+ {BLANK, U_D_PS, BLANK, BLANK},
+ {BLANK, U_D_PS, BLANK, BLANK},
+ {BLANK, BLANK, BLANK, BLANK},
+ }
+ },
+ { /* PIECE 5 - RIGHT DOGLEG */
+ 0,0,
+ {
+ {BLANK, R_D_PS, RGT_PS, BLANK},
+ {BLANK, U_D_PS, BLANK, BLANK},
+ {BLANK, U_D_PS, BLANK, BLANK},
+ {BLANK, BLANK, BLANK, BLANK},
+ }
+ },
+ { /* PIECE 6 - LEFT S */
+ 0,0,
+ {
+ {LFT_PS, L_D_PS, BLANK, BLANK},
+ {BLANK, R_U_PS, RGT_PS, BLANK},
+ {BLANK, BLANK, BLANK, BLANK},
+ {BLANK, BLANK, BLANK, BLANK},
+ }
+ },
+ { /* PIECE 7 - RIGHT S */
+ 0,0,
+ {
+ {BLANK, R_D_PS, RGT_PS, BLANK},
+ {LFT_PS, L_U_PS, BLANK, BLANK},
+ {BLANK, BLANK, BLANK, BLANK},
+ {BLANK, BLANK, BLANK, BLANK},
+ }
+ }
+ };
+
+
+struct
+ {
+ int x,y;
+ } tetris_off[NO_TETRIS_PIECE][4]=
+ {
+ { /* PIECE 1 - LONG */
+ {1,1},
+ {1,1},
+ {2,1},
+ {1,2}
+ },
+ { /* PIECE 2 - BOX */
+ {0,0},
+ {2,0},
+ {2,2},
+ {0,2}
+ },
+ { /* PIECE 3 - TEE */
+ {1,1},
+ {2,1},
+ {2,2},
+ {1,2}
+ },
+ { /* PIECE 4 - LEFT DOGLEG */
+ {1,1},
+ {2,1},
+ {2,2},
+ {1,2}
+ },
+ { /* PIECE 5 - RIGHT DOGLEG */
+ {1,1},
+ {2,1},
+ {2,2},
+ {1,2}
+ },
+ { /* PIECE 6 - LEFT S */
+ {1,1},
+ {2,1},
+ {2,2},
+ {1,2}
+ },
+ { /* PIECE 7 - RIGHT S */
+ {1,1},
+ {2,1},
+ {2,2},
+ {1,2}
+ }
+ };
+
+
+
+int tetris_height[NO_TETRIS_PIECE]=
+ {
+ 4, /* PIECE 1 - LONG */
+ 2, /* PIECE 2 - BOX */
+ 2, /* PIECE 3 - TEE */
+ 3, /* PIECE 4 - LEFT DOGLEG */
+ 3, /* PIECE 5 - RIGHT DOGLEG */
+ 2, /* PIECE 6 - LEFT S */
+ 2 /* PIECE 7 - RIGHT S */
+ };
diff --git a/hardwire/popsound.wav b/hardwire/popsound.wav
new file mode 100644
index 0000000..e9a4523
--- /dev/null
+++ b/hardwire/popsound.wav
Binary files differ
diff --git a/hardwire/readme.h b/hardwire/readme.h
new file mode 100644
index 0000000..5a49d12
--- /dev/null
+++ b/hardwire/readme.h
@@ -0,0 +1,109 @@
+/*
+ 1234567890123456789012345678901234567890
+*/
+
+"@_____________________________________",
+"",
+"@HARDWIRE",
+"@Version 1.0",
+"@",
+"@Presented by noddybox '98",
+"@Written using DJGPP and Allegro 3.0",
+"@",
+"@Allegro written by Shawn Hargreaves",
+"",
+"@_____________________________________",
+"",
+"",
+"@RULES FOR WIRE MODE",
+"",
+"Blocks (or columns) will descend the",
+"screen in the time honoured tradition,",
+"but with the slight twist of being made",
+"up of pieces of circuit board.",
+"",
+"Rather than making complete horizontal",
+"lines you have to make connections",
+"between any of the connectors lining",
+"the sides and bottom of the pit.",
+"",
+"A complete connection will cause the",
+"circuitry to burn up, making more room",
+"for the never ending supply from",
+"upstairs.",
+"",
+"Likewise makeing a completely enclosed",
+"loop will induce a current that destroys",
+"those pieces of circuit.",
+"",
+"Every so often a special block will fall",
+"that once layed in place will blow up",
+"all circuit pieces that match the ones",
+"surrounding it.",
+"",
+"If the blocks (even a special) overflow",
+"the top of the pit, it's game over and",
+"back to the dole office.",
+"",
+"",
+"@RULES FOR TETRIS CLASSIC MODE",
+"",
+"Blocks drop down into a pit.",
+"",
+"Complete horizontal line disappear,",
+"causing the lines above to move down.",
+"",
+"The game is over once the pit overflows.",
+"",
+"I'm sure you've heard of the idea...",
+"",
+"",
+"",
+"@KEYS ON TITLE SCREEN",
+"",
+"F1 Change game mode ",
+"F2 Change game level ",
+"F3 Alter pit width ",
+"F4 Toggle motion sickness ",
+"F5 Toggle music ",
+"I View instructions ",
+"R Redefine keys ",
+"SPACE Play game ",
+"ESC Quit back to DOS ",
+"",
+"",
+"",
+"@DEFAULT KEYS DURING GAME",
+"",
+"RIGHT Move block right ",
+"LEFT Move block left ",
+"UP Rotate block clockwise/up ",
+"DOWN Rotate block anti-clockwise/down",
+"SPACE Drop block ",
+"P Pause ",
+"F9 I'm bored. Next level please. ",
+"ESC Give up ",
+"",
+"Movement, Rotate, Drop and Pause keys",
+"can be redefined from the title page",
+"",
+"",
+"@HINTS",
+"",
+"THINK! HARD!!!",
+"",
+"",
+"@-------------------------------------",
+"@email: ianc@noddybox.demon.co.uk",
+"@URL: http://www.noddybox.demon.co.uk/",
+"",
+"You are free to do whatever you want",
+"with this code, aside from claim",
+"responsibility for it and charge for it",
+"",
+"",
+"@(c) 1998 noddybox",
+"",
+"",
+"",
+"",
diff --git a/hardwire/sprite16.pds b/hardwire/sprite16.pds
new file mode 100644
index 0000000..be2341a
--- /dev/null
+++ b/hardwire/sprite16.pds
Binary files differ
diff --git a/hardwire/sprite8.pds b/hardwire/sprite8.pds
new file mode 100644
index 0000000..a13ec4e
--- /dev/null
+++ b/hardwire/sprite8.pds
Binary files differ