diff --git a/tb_asm/Changelog.tb_asm b/tb_asm/Changelog.tb_asm new file mode 100644 index 0000000..5d0b947 --- /dev/null +++ b/tb_asm/Changelog.tb_asm @@ -0,0 +1,86 @@ +25 December 2002 ++ Get idea from friend ++ Start implementing in C + +?? January 2003 ++ Finish title, about, story options + +?? January 2003 ++ Add "quit, are you sure" display + +?? February 2003 ++ Port all of C version at time to assembler + +?? February 2003 ++ Add help screen to C version ++ Add help screen to asm version + +?? February 2003 ++ Add ansi-code sound effects to C version + +?? February 2003 ++ Finish varied enemies and boss on C version + +?? February 2003 ++ Add save game support to C version + +4 March 2003 ++ Started adding actual game support to assembler ++ Frame limiter and pause/sound/help work + +6 March 2003 ++ Added pseudo-random number generator ++ Added scrolling star background ++ Added missiles + +10 March 2003 ++ Added int->ascii routine ++ Added bottom status bar + +11 March 2003 ++ Simple enemy movement. + +12 March 2003 ++ Added collision detection. + +17 March 2003 ++ Added enemy behavior + +18 March 2003 ++ Added sound ++ Added hi-score support ++ Added level announce + +19 March 2003 ++ Added boss ++ Polished a bit ++ Put rep / stosb on separate lines so works with as 2.9.1 + +20 March 2003 ++ Added "restore colors" at exit time ++ Removed extra spaces from strings... saves 100 bytes ++ Lots of infrastructute to compress data segment... saves 2k ++ Change all the cool "bt/btr/bts/btc" op-codes to equivelant + or/and/xor. The former was cool, but slightly longer. Sad, sad. ++ Found if I remove ".data" the text+data segments are merged saving + 3k. Cool, especially as I don't write to the data segment at all anymore. ++ Use sstrip. There are random file lengths that either "strip" or + "sstrip" don't handle well. May have to pad things out in the end + +21 March 2003 ++ convert "get_char" and "get_a_char" to return status in the carry flag. ++ Much optimization. See "optimization" file. ++ Now under 8k ;) + +23 March 2003 ++ Extensive play-testing to make sure optimization didn't break game. ++ Fix "sstrip" program so it puts the bss on the proper boundry. + Hope this isn't "as" version specific. ++ Game balancing. Moved up to 6 enemies. Slight shifts in + game engine constants. ++ Fix problem where enemies get stuck at level 4. As a result + level 7 never ends, as we do tricks where we use level*16 and + over 7 that overflows to negative. ++ Play tested. Seems ok. Release 0.32! + + diff --git a/tb_asm/FAQ.tb_asm b/tb_asm/FAQ.tb_asm new file mode 100644 index 0000000..94e4913 --- /dev/null +++ b/tb_asm/FAQ.tb_asm @@ -0,0 +1,168 @@ +Q. Why? + +A. My friend John got a Gameboy + Advance for Christmas. He suggested I port my game + Tom Bombem to it. + + In actuality the specs of the GBA are similar to the machine I + originally wrote TB1 on. It was on a 386-33 with 320x200x256 graphics + and constrained to 640kB of RAM. The game was written in 16-bit + PASCAL with some 32-bit assembly. + + I thought I should attempt a x86 assembly version before I go and learn + ARM assembly. + + + +Q. How did you do the graphics. + +A. With The Gimp. Used 16 color indexed + palette. Saved as xpm. Edited with text editor. + + + +Q. Why text mode? + +A. Because doing graphics in Linux is a pain. And I didn't feel like + messing with the framebuffer. This was a proof-of-concept, not a + designed-for-release game. + + + +Q. Why 40x20 resolution? + +A. Because I'd like to port it to Apple IIe low-res graphics mode. + + + +Q. Why not a DOS version? + +A. Should be technically possible, although it's been a while and gas + isn't the best assembler for it. Also doing things like reading + the keyboard/getting timestamps/speaker noise are more complicated. + + More interesting would be a version using Windows console syscalls. + + + +Q. What is the high score? + +A. A bit of a silly question as anyone can edit a text file and lie. The + highest score I've gotten is 14170 on level 4. + But this isn't saying much, I tend to be debugging more than playing. + + The highest _possible_ score is 2^31 or about 2 billion. Actually + it might be 4 billion, I am not sure how my int->ascii code handles + signed numbers. + + +Q. Why does the ship have its engines constantly on, even though + it is moving at a constant velocity? + +A. Ummmm... friction. Yeah... space friction. + + + +Q. Why are the stars moving so quickly? Are you going faster than light? + +A. If you look closely you'll notice the stars repeat. Hence you + are really flying very fast in a big circle. Hey, maybe that's + why the engine is constantly firing! + + + +Q. Where in that tiny ship are all of those missiles stored? + +A. In the seventh dimension. + + +Q. Why the seventh dimension? + +A. The others were all full. + + +Q. Why is there a guinea pig in the game? + +A. A local guinea pig threatened me with violence if I did not include + a picture of her. + + +Q. What have you learned from all this assembly programming? + +A. I'm just reminded what Professor Jacob always said... + A computer is just a state machine. + + +Q. What do you hate most about the GNU Assembler "gas"? + +A. It doesn't warn you when a "loop" instruction overflows + 128 thus causing your program to go off into la-la land. + It also doesn't do type checking causing you headaches if + you forget the "b" on cmpb. + + But you can't really blame it, it's used to dealing with + gcc which is a very good and proper assembler-producer, + unlike the author. + + +Q. Why are there only 6 enemies / 2 missiles / shields go up at 320/ etc? + +A. Game balance. Just trying to keep it challenging yet not overwhlmingly + so. [For the original tb1 it was "because my 386 can't keep up" but + that should be less of a problem these days]. + + If you _must_ have it some other way, feel free to mess with the constants + on the first page of the tb_asm.s file, but I cannot guarantee what + the consequences might be! + + +Q. Will there be a sequel? + +A. Yes, it will be released shortly before either the release of + "Duke Nukem Forever (tm)" or the heat death of the universe, + which ever happens first. + + +Q. Why can't Vince stay consitent between "HISCORE" and "HIGH SCORE" + including all possibly variations of "HI-SCORE" "HIGH_SCORE" usw? + +A. The world may never know. + + +Q. What does "usw" mean? + +A. Und So Weiter. + + +Q. That wasn't helpful. + +A. This isn't a question. + + +Q. What's the highest level you can get to? + +A. No matter how you try, once you get to level 7 it will + keep repeating. This is because I multiply the level + by 16 in various places for enemy movement, and it it goes + above 7 then the byte will be negative causing + Bad Things(tm) to happen. + + +Q. Well why don't you modify the code so it doesn't go haywire + after level 7? + +A. I am lazy. Also it should be too hard to get to level 7 anyway + + +Q. What are the enemies supposed to be? + +A. An envelope, a clip-board, a cigarette, a telephone, a dollar-bill, + and an un-identified yellow thing, possibly a banana. All things + malicious marketers might have in excess. + + +Q. How come the stars appear in straight bands insteas of scattered in the + sky? + +A. Because my pseudo-random number algorithm is at times more pseudo + than random. diff --git a/tb_asm/Makefile b/tb_asm/Makefile new file mode 100644 index 0000000..0e81412 --- /dev/null +++ b/tb_asm/Makefile @@ -0,0 +1,47 @@ +CC=gcc +CFLAGS = -Wall -O2 +LFLAGS = + +all: tb_asm configure compress_data + +./sstrip/sstrip: + cd sstrip && make + +compress_data: compress_data.o lzss.o + $(CC) $(LFLAGS) -o compress_data compress_data.o lzss.o + +compress_data.o: compress_data.c + $(CC) $(CFLAGS) -c compress_data.c + + +lzss.o: lzss.c + gcc -O2 -Wall -c lzss.c + +lzss_new.o: lzss_new.c + gcc -O2 -Wall -c lzss_new.c + + +tb_asm: tb_asm.o ./sstrip/sstrip + ld -o tb_asm tb_asm.o + ./sstrip/sstrip tb_asm + +tb_asm.o: tb_asm.s data.lzss data.labels + as -o tb_asm.o tb_asm.s + +tb_asm.s: configure + ./configure + +data.labels: compress_data + ./compress_data + +data.lzss: compress_data data.inc + ./compress_data + + + +configure: configure.c + gcc -O2 -Wall -o configure configure.c + +clean: + rm -f *~ *.o tb_asm tb_asm.s core configure compress_data data.lzss data.header data.raw data.labels + cd sstrip && $(MAKE) clean diff --git a/tb_asm/README.tb_asm b/tb_asm/README.tb_asm new file mode 100644 index 0000000..519adfe --- /dev/null +++ b/tb_asm/README.tb_asm @@ -0,0 +1,99 @@ +TOM BOMBEM: Merciless Marauding Malicious Marketers +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +http://www.deater.net/weave/vmwprod/tb1/tb_asm.html + + by Vince Weaver + + version 0.24 -- 19 March 2003 + + +Background: +~~~~~~~~~~~ +You are Tom Bombem, a shy new intern on Moonbase Alpha. +Somewhat against your will it has become your job to +defend Earth! See the "Story" option in the game +for the rest of the story. + +tb_asm comes before "tb1: Invasion of the Inanimate Objects" +chronologically, for those who might care. + + +Compiling / Running: +~~~~~~~~~~~~~~~~~~~~ + Just run "make". If you have a supported architecture "tb_asm" + will be created. + + If you don't have an ix86 or ppc computer, you can try in the + "c" subdirectory and do "make" there to run a "C" version of the game + that should run on and architecture. The "C" version is not + as feature-complete. + + After compiling just run "./tb_asm" + + tb_asm will run _ONLY_ on Linux. A DOS/w32 port could be possible + but I really don't have the time or desire to mess with it. + + tb_asm should be run at the text_console [if in X press CTRL-ALT-F1]. + It will run to some extent in an x-term, but w/o sound. + + +Keybindings: +~~~~~~~~~~~ + Use arrow keys, or i,j,k,m to manuever and navigate menus. + ' ' shoots and selects. + 'h' displays help. 's' toggles sound 'p' pauses + +Options/Hiscore File: +~~~~~~~~~~~~~~~~~~~~~ + tb_asm will create the file "/tmp/tb_asm.hsc" to store the hiscore. + + tb_asm will only write the file if it's not there, or if there + is a file there that is at least 12 bytes long and starts + with "tb". + + Besides the hiscore tb_asm also stores the "sound on/sound off" + state in this file. + +Game Play: +~~~~~~~~~~ + Manuever your ship avoiding the falling objects. Shoot them. + + Only 2 missiles can be in the air at the time [this is _not_ a bug. + it's a limit of your ship's missile guidance system]. + + Every 320 points your shields will increase. + + There are special bonuses you can earn at the end of each level. + + No Shields Hit : going through an entire level without + having an enemy hit your ship + + All Enemies Destroyed : all enemies were destroyed before + scrolling off the screen. [Note, + ramming an enemy with your ship + _DOES_ count as destroying it. Just + don't let them get by you] + + Perfect Shot: Every missile fired hits an enemy. + + + At the end each level you fight the boss. Then the game starts over + with the enemies moving faster! + + +About: +~~~~~~ + (see also the FAQ.asm file) + + This was done as an exercise to see if I could make a Tom-Bombem + class game entirely in assembly language. I've optimized for + size rather than speed. And most likely it's not _completely_ + optimized for size yet. + + The hope is maybe eventually using this as a stepping-board to + creating a Game Boy Advance TomBombem game. + +Author: +~~~~~~~ + Vince Weaver + http://www.deater.net/weave/ + Special Thanks to KRG + 19 March 2003 + diff --git a/tb_asm/TODO b/tb_asm/TODO new file mode 100644 index 0000000..4211866 --- /dev/null +++ b/tb_asm/TODO @@ -0,0 +1,2 @@ +have the boss go away before final explosion +"demo" mode of self playing diff --git a/tb_asm/arch.h b/tb_asm/arch.h new file mode 100644 index 0000000..9e91ad7 --- /dev/null +++ b/tb_asm/arch.h @@ -0,0 +1,32 @@ +#define ARCH_UNKNOWN 0 +#define ARCH_ALPHA 1 +#define ARCH_ARM 2 +#define ARCH_CRIS 3 +#define ARCH_IA64 4 +#define ARCH_IX86 5 +#define ARCH_M68K 6 +#define ARCH_MIPS 7 +#define ARCH_PARISC 8 +#define ARCH_PPC 9 +#define ARCH_S390 10 +#define ARCH_SH3 11 +#define ARCH_SPARC 12 +#define ARCH_VAX 13 + + +char *arch_names[]={ + "Unknown", + "alpha", + "arm", + "cris", + "ia64", + "ix86", + "m68k", + "mips", + "parisc", + "ppc", + "s390", + "sh3", + "sparc", + "vax" +}; diff --git a/tb_asm/c/Makefile b/tb_asm/c/Makefile new file mode 100644 index 0000000..1c89736 --- /dev/null +++ b/tb_asm/c/Makefile @@ -0,0 +1,12 @@ +C_FLAGS=-Wall -O2 -g + +all: tb_asm + +tb_asm: tb_asm.o + gcc $(L_FLAGS) -o tb_asm tb_asm.o + +tb_asm.o: tb_asm.c game_sprites.h + gcc $(C_FLAGS) -c tb_asm.c + +clean: + rm -f *~ *.o tb_asm core diff --git a/tb_asm/c/boss.h b/tb_asm/c/boss.h new file mode 100644 index 0000000..2062f67 --- /dev/null +++ b/tb_asm/c/boss.h @@ -0,0 +1,34 @@ +/* XPM */ +/* Boss */ + +/* 3x2 */ +char smoke_sprites[3][6]={ +{0x0,0x8,0x0, + 0x0,0x0,0x0, +}, +{0x8,0x7,0x8, + 0x8,0x8,0x8, +}, +{0x7,0x4,0x7, + 0x7,0x7,0x7, +}, + +}; + +/* 13x3 */ +char boss_sprite[]={ +0xf,0x7,0x4,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0x4,0x7,0xf, +0xf,0x8,0x7,0x4,0x4,0x3,0xb,0x3,0x4,0x4,0x7,0x8,0xf, +0xf,0x0,0x8,0x7,0x3,0xb,0xe,0xb,0x3,0x7,0x8,0x0,0xf, +}; + +/* 1x2 */ +char laser_sprite[2][2]={ +{0xd, +0x5, +}, +{0x5, +0xd, +} +}; + diff --git a/tb_asm/c/dump_to_ansi.c b/tb_asm/c/dump_to_ansi.c new file mode 100644 index 0000000..87f00cc --- /dev/null +++ b/tb_asm/c/dump_to_ansi.c @@ -0,0 +1,33 @@ +#include + +int main(int argc, char **argv) { + + int ch,vt102mode=0,inAnsi=0; + + while(!feof(stdin)) { + + ch=getchar(); + + if (ch<0) break; + + if (ch==27) inAnsi=1; + if ((inAnsi) && (ch=='m')) inAnsi=0; + if ((inAnsi) && (ch=='H')) inAnsi=0; + + if (ch==14) { + vt102mode=1; + goto skip_print; + } + + if (ch==15) { + vt102mode=0; + goto skip_print; + } + + if ((vt102mode)&&(ch=='0')&&(!inAnsi)) putchar('\333'); + else putchar(ch); + +skip_print: + } + +} diff --git a/tb_asm/c/ending.h b/tb_asm/c/ending.h new file mode 100644 index 0000000..78c4456 --- /dev/null +++ b/tb_asm/c/ending.h @@ -0,0 +1,34 @@ +/* Ending */ + +/* 7x7*/ +char tom_head_sprite[]={ +0x0,0x1,0x1,0x1,0x9,0x9,0x0, +0x0,0x1,0x0,0x0,0x8,0x9,0x0, +0x0,0x1,0x0,0x0,0x8,0x9,0x0, +0x0,0x1,0x0,0x0,0x8,0x9,0x0, +0x0,0x1,0x0,0x0,0x8,0x9,0x0, +0x0,0x0,0x1,0x1,0x9,0x0,0x0, +0x1,0x1,0x1,0x1,0x9,0x9,0x9, +}; + +/* 5x6 */ +char earth_sprite[]={ +0x0,0x7,0xf,0xf,0x0, +0x2,0xA,0xA,0x9,0x9, +0x1,0xA,0x9,0x9,0x9, +0x1,0x9,0xA,0xA,0x9, +0x1,0x9,0xA,0x9,0x9, +0x0,0x7,0xf,0xf,0x0, +}; + +/* 19x7 */ +char susie_sprite[]={ +/*0x7,0x7,0x7,0x7,0x7,0x7,0x7,0x7,0x7,0x7,0x7,0x7,0x7,0x7,0x7,0x7,0x7,0x7,0x7,*/ +0x7,0x7,0x7,0x7,0x7,0x7,0x7,0x7,0x7,0x7,0x7,0x8,0x0,0xf,0xf,0x0,0x7,0x7,0x7, +0x7,0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x8,0x0,0x0,0x8,0x0,0x0,0x7,0x7, +0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7, +0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7, +0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0x7,0x7, +0x7,0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0x7,0x7,0x7,0x7, +0x7,0x7,0x7,0x7,0x8,0x8,0x8,0x7,0x7,0x7,0x7,0x7,0x8,0x8,0x8,0x7,0x7,0x7,0x7, +}; diff --git a/tb_asm/c/game_sprites.h b/tb_asm/c/game_sprites.h new file mode 100644 index 0000000..aa20343 --- /dev/null +++ b/tb_asm/c/game_sprites.h @@ -0,0 +1,57 @@ + /* 8x4 */ +char ship_sprite[]= +{ +0x0,0x0,0x9,0x9,0x9,0x0,0x0,0x0, +0x0,0x7,0xf,0xf,0xf,0x7,0x0,0x0, +0x7,0x7,0xf,0x7,0xf,0x7,0x7,0x0, +0x0,0x0,0x0,0xe,0x0,0x0,0x0,0x0 +}; + +/* 1x3 */ +char missile_sprite[]={ +0x7, +0x7, +0xe, +}; + + /* 3x2 */ +char enemy_sprites[6][6]={ + {0xf,0xf,0x4, + 0xf,0xf,0xf, + } + , + {0x9,0x0,0x9, + 0x0,0x9,0x0, + } + , + {0x2,0xa,0x2, + 0x2,0xa,0x2, + } + , + {0x3,0x6,0x6, + 0x3,0x6,0x6, + } + , + {0x0,0xe,0x0, + 0xe,0x0,0xe, + } + , + {0xc,0xf,0xf, + 0xc,0x7,0x7 + } + , +}; + +char explosion_sprites[3][6]={ + { 0xe,0xe,0xc, + 0xc,0xe,0x8, + }, + { 0x7,0x7,0x4, + 0x4,0x7,0x0, + }, + + { 0x8,0x8,0x0, + 0x0,0x8,0x8, + }, +}; + diff --git a/tb_asm/c/guess.c b/tb_asm/c/guess.c new file mode 100644 index 0000000..7ae1a9c --- /dev/null +++ b/tb_asm/c/guess.c @@ -0,0 +1,41 @@ + +#include +#include +#include + +int main(int argc, char **argv) { + int result,guess,secret,tries; + + srand(time(NULL)); + +new_game: + secret=rand()%65536; + tries=0; + printf("Guess a number between 0 and 65536!\n"); + printf(" Or -1 to quit\n"); +guess_again: + result=scanf("%d",&guess); + if (result<1) { + scanf("%*s"); + goto guess_again; + } + if (guess==-1) goto end; + tries++; + if (guesssecret) { + printf("%i is too high! Try again!\n",guess); + goto guess_again; + } + + if (guess==secret) { + printf("Correct! It took you %i tries!\n",tries); + goto new_game; + } + +end: + printf("Thanks for playing!\n\n"); + return 0; +} diff --git a/tb_asm/c/int_random.c b/tb_asm/c/int_random.c new file mode 100644 index 0000000..85a59f1 --- /dev/null +++ b/tb_asm/c/int_random.c @@ -0,0 +1,56 @@ +#include +#include + +/* default beep is 750Hz/125ms */ + + +/* The following algorithm from the Hewlett Packard HP-20S */ +/* Scientific Calculator manual, September 1998, p75-76 */ + +/* The algorithm r = FractionalPart (997r ) */ +/* i+1 i */ +/* */ +/* Where r0 is a starting value between 0 and 1. */ +/* The generator passes the chi-square frequency test for */ +/* uniformity, and serial and run tests for randomness. */ +/* The more significant digits are more random than the */ +/* less significant. If r0 * 10e7 is not divisible */ +/* by 2 or 5 you get 500,000 numbers w/o repeating. */ + +/* modified to be fixed-point integer only by Vince Weaver */ + +int int_random(int seed) { + + static int ri; + + /* Be sure doesn't end in multiple of 2, 5 and is ~<=7 digits */ + if (seed!=0) { + ri=seed; + while ((ri%2==0) || (ri%5==0)) ri++; + ri=ri&0xffffff; + return ri; + } + + ri*=997; + ri&=0xffffff; + + return ri; +} + +int random_word() { + int i; + + i=(int_random(0)>>8)&0xffff; + return i; +} + +int main(int argc,char **argv) { + + int i; + + int_random(time(NULL)); + + for(i=0;i<1000;i++) printf("%i\n",random_word()%1000); + + return 0; +} diff --git a/tb_asm/c/open_test.c b/tb_asm/c/open_test.c new file mode 100644 index 0000000..80186d4 --- /dev/null +++ b/tb_asm/c/open_test.c @@ -0,0 +1,12 @@ +#include + +int main(int argc, char **argv) { + FILE *fff; + + fff=fopen("bob","w"); + if (fff!=NULL) { + fprintf(fff,"HELLO\n"); + fclose(fff); + } + return 0; +} diff --git a/tb_asm/c/opener.h b/tb_asm/c/opener.h new file mode 100644 index 0000000..20da632 --- /dev/null +++ b/tb_asm/c/opener.h @@ -0,0 +1,28 @@ +/* opener.h */ +/* 40x20 */ + +/* 0,5 Merciless Marauding Malicious Marketers */ + +char opener_sprite[]= +{ +0x9,0x9,0x9,0x0,0x9,0x9,0x9,0x0,0x9,0x0,0x0,0x0,0x9,0x0,0xC,0xC,0x0,0x0,0xC,0xC,0xC,0x0,0xC,0x0,0x0,0x0,0xC,0x0,0xC,0xC,0x0,0x0,0xC,0xC,0x0,0xC,0x0,0x0,0x0,0xC, +0x0,0x9,0x0,0x0,0x9,0x0,0x9,0x0,0x9,0x9,0x0,0x9,0x9,0x0,0xC,0x0,0xC,0x0,0xC,0x0,0xC,0x0,0xC,0xC,0x0,0xC,0xC,0x0,0xC,0x0,0xC,0x0,0xC,0x0,0x0,0xC,0xC,0x0,0xC,0xC, +0x0,0x9,0x0,0x0,0x9,0x0,0x9,0x0,0x9,0x0,0x9,0x0,0x9,0x0,0xC,0xC,0x0,0x0,0xC,0x0,0xC,0x0,0xC,0x0,0xC,0x0,0xC,0x0,0xC,0xC,0x0,0x0,0xC,0xC,0x0,0xC,0x0,0xC,0x0,0xC, +0x0,0x9,0x0,0x0,0x9,0x0,0x9,0x0,0x9,0x0,0x0,0x0,0x9,0x0,0xC,0x0,0xC,0x0,0xC,0x0,0xC,0x0,0xC,0x0,0x0,0x0,0xC,0x0,0xC,0x0,0xC,0x0,0xC,0x0,0x0,0xC,0x0,0x0,0x0,0xC, +0x0,0x9,0x0,0x0,0x9,0x9,0x9,0x0,0x9,0x0,0x0,0x0,0x9,0x0,0xC,0xC,0x0,0x0,0xC,0xC,0xC,0x0,0xC,0x0,0x0,0x0,0xC,0x0,0xC,0xC,0x0,0x0,0xC,0xC,0x0,0xC,0x0,0x0,0x0,0xC, +0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, +0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0x0,0x0,0x0, +0x0,0x0,0x0,0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xF,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, +0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, +0x0,0x0,0x0,0x0,0x0,0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xF,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, +0x0,0x0,0x0,0x0,0x0,0x7,0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xB,0x0,0x0,0x0, +0x0,0xE,0x0,0x0,0x0,0x7,0x7,0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xB,0x4,0x4, +0x0,0xE,0xE,0xE,0x9,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0x9,0x9,0x9,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xB,0xC,0xC, +0xE,0xE,0x4,0xC,0x9,0xF,0x4,0x2,0x9,0x2,0x9,0xF,0xF,0x9,0x9,0x9,0x9,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xB,0x0,0xC,0xC, +0x0,0xE,0xE,0xC,0x9,0xF,0x4,0x2,0x9,0x2,0x9,0xF,0xF,0x9,0x9,0x9,0x9,0x9,0x0,0x0,0x0,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xC,0xC, +0x0,0x0,0x0,0xE,0x9,0x7,0x7,0x7,0x7,0x7,0x7,0x7,0x7,0xF,0xF,0xF,0xF,0xF,0xF,0x0,0x0,0x0,0x0,0xE,0x7,0x7,0x7,0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xC,0xC, +0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xF,0x0,0x0,0x0,0x0,0x4,0x4, +0x0,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x0,0x0,0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, +0x0,0xF,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xF,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, +0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0x0, +}; diff --git a/tb_asm/c/organ.c b/tb_asm/c/organ.c new file mode 100644 index 0000000..3eed833 --- /dev/null +++ b/tb_asm/c/organ.c @@ -0,0 +1,71 @@ +#include +#include /* pow */ +#include /* fcntl */ +#include + + + +int main(int argc, char **argv) { + + int frequency[127],i,ch,note=60; + + static struct termios new_tty,old_tty; + + + /* setup non-blocking non-echo mode */ + + tcgetattr(0,&old_tty); + + new_tty=old_tty; + new_tty.c_lflag&=~ICANON; + new_tty.c_cc[VMIN]=1; + new_tty.c_lflag&=~ECHO; + tcsetattr(0,TCSANOW,&new_tty); + + fcntl(0,F_SETFL,fcntl(0,F_GETFL) | O_NONBLOCK); + + + + for (i=0;i<127;i++) frequency[i]=(440.0/32.0)*(pow(2.0,(i-9.0)/12.0)); + + for(i=0;i<127;i++) printf("%i\n",frequency[i]); + + while ((ch=getchar())!='q') { + if (ch==-1) goto loop; + switch(ch) + { + + case 'a': note=60; break; + case 'w': note=61; break; + case 's': note=62; break; + case 'e': note=63; break; + case 'd': note=64; break; + case 'f': note=65; break; + case 't': note=66; break; + case 'g': note=67; break; + case 'y': note=68; break; + case 'h': note=69; break; + case 'u': note=70; break; + case 'j': note=71; break; + case 'k': note=72; break; + + } + + + + printf("%c[10;%i]\n",27,frequency[note]); +// write(1, "\33[11;200]", 9) length = 200 + printf("%c",ch); + printf("\a"); + usleep(150000); + loop: + + + } + + tcsetattr(0,TCSANOW,&old_tty); + + + + +} diff --git a/tb_asm/c/phobos.h b/tb_asm/c/phobos.h new file mode 100644 index 0000000..a996919 --- /dev/null +++ b/tb_asm/c/phobos.h @@ -0,0 +1,26 @@ + + /* 40x16 */ + +char phobos_sprite[]={ +0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, +0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, +0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf,0x0,0x0,0x0, +0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, +0x0,0x0,0x0,0x0,0x0,0x7,0xf,0xf,0xf,0xf,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, +0x0,0x0,0x0,0x0,0x4,0xc,0xc,0xc,0xc,0xc,0xc,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, +0x0,0x0,0x0,0x4,0xc,0xc,0xc,0xc,0xc,0x4,0xc,0xc,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, +0x0,0x0,0x0,0x4,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, +0x0,0x0,0x0,0x4,0xc,0xc,0xc,0x4,0xc,0xc,0xc,0xc,0x0,0x0,0x0,0x0,0x0,0x8,0x6,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, +0x0,0x0,0x0,0x4,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0x0,0x0,0x0,0x0,0x0,0x6,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, +0x0,0x0,0x0,0x4,0xc,0xc,0xc,0xc,0xc,0x4,0xc,0xc,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, +0x0,0x0,0x0,0x0,0x4,0xc,0xc,0xc,0xc,0xc,0xc,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, +0x0,0x0,0x0,0x0,0x0,0x7,0xf,0xf,0xf,0xf,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, +0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, +0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, +0x0,0x0,0x0,0xf,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, +}; + + /* 3x1 */ +char evil_ship_sprite[]={ +0x3,0xb,0x3, +}; diff --git a/tb_asm/c/tb_asm.c b/tb_asm/c/tb_asm.c new file mode 100644 index 0000000..6ef0a91 --- /dev/null +++ b/tb_asm/c/tb_asm.c @@ -0,0 +1,1278 @@ +#include +#include +#include +#include +#include +#include + +#include +#include + +#define SCREEN_WIDTH 40 +#define SCREEN_HEIGHT 24 +#define BYTES_PER_PIXEL 2 +#include "vmwsoft.h" +#include "opener.h" +#include "vince.h" +#include "tom.h" +#include "phobos.h" +#include "game_sprites.h" +#include "boss.h" +#include "ending.h" + +int play_sound=0; +char hi_player[4]="KRG"; +int hiscore=100; +int dump_screen=0; + +void load_hi_score() { + FILE *hi_score; + + hi_score=fopen("/tmp/tb_asm.hsc","r"); + if (hi_score!=NULL) { + fscanf(hi_score,"%i\n",&hiscore); + fgets(hi_player,4,hi_score); + fclose(hi_score); + } +} + + + +int clear_framebuffer(char *buffer,char color,char value) { + + int i=0; + + while(i=xsize) { + offset+=((SCREEN_WIDTH-xsize)*BYTES_PER_PIXEL); + xx=0; + yy++; + } + } + + return 0; +} + +int put_text_xy(char *text,int x,int y,int color, char *framebuffer) { + + int offset,i; + + offset=(y*SCREEN_WIDTH+x)*BYTES_PER_PIXEL; + + i=0; + + while(i7,colors[color&7]); + old_color=color; + } + temp_string[0]=framebuffer[((i+j*SCREEN_WIDTH)*BYTES_PER_PIXEL)+1]; + if (temp_string[0]==219) { + if (!block_mode){ + block_mode=1; + size+=to_buffer(out_buffer,"\016"); + } + temp_string[0]='0'; + } + else { + if (block_mode) { + block_mode=0; + size+=to_buffer(out_buffer,"\017"); + + } + } + + size+=to_buffer(out_buffer,temp_string); + } + size+=to_buffer(out_buffer,"\n"); + } + + if (size>40*44*10) { + + printf("\a\a\a\n"); + exit(10); + } + + + write(1,out_buffer,size); + if (dump_screen) { + int fd; + fd=creat("screen",0x666); + write(fd,out_buffer,size); + close(fd); + dump_screen=0; + } + +// fdatasync(1); + + return 0; +} + +int get_timer() { + + static int initialized=0; + static int startseconds,startusecs; + + struct timeval our_time; + + int temp_time; + + if (!initialized) { + gettimeofday(&our_time,NULL); + + startseconds=time(NULL); + startusecs=our_time.tv_usec; + + initialized=1; + } + gettimeofday(&our_time,NULL); + temp_time=(time(NULL)-startseconds)*1000; + temp_time+=(our_time.tv_usec/1000); + + return temp_time; + +} + + +void clear_keyboard_buffer() +{ + int ch; + + while(read(0,&ch,1)==1); +} + + +void pause_a_while(int msecs) { + + int ch,our_time; + + our_time=get_timer(); + + while ( read(0,&ch,1)!=1) { + usleep(1); + + if ( (get_timer()-our_time) > msecs ) break; + } + clear_keyboard_buffer(); + +} + +int get_char() { + + char ch; + int result; + + result=read(0,&ch,1); + + if (result<1) return 0; + else return ch; +} + + +int get_a_char() { + + char ch,ch1,ch2,ch3; + + ch=get_char(); + + if (ch==27) { + ch1=get_char(); + ch2=get_char(); + ch3=get_char(); + + if ((ch1==0) && (ch2==0)) return 'q'; + if ((ch1==91) && (ch2==66)) return 'm'; + if ((ch1==91) && (ch2==65)) return 'i'; + if ((ch1==91) && (ch2==67)) return 'k'; + if ((ch1==91) && (ch2==68)) return 'j'; + if ((ch1==91) && (ch2==91)) { + if (ch3==65) return 'h'; + } + { + FILE *fff; + fff=fopen("bob","w"); + fprintf(fff,"%i %i %i\n",ch1,ch2,ch3); + fclose(fff); + } +// } + } + return ch; +} + + + + +void null() +{ +} + + +void put_attention_block(char *framebuffer,int color) { + + int i,j; + + for(i=5;i<12;i++) + for(j=0;j<40;j++) + put_text_xy("*",j,i,color,framebuffer); + +} + + +int verify_quit(char *framebuffer) { + + int quit_bar=0; + char ch; + + put_attention_block(framebuffer,14); + put_text_xy(" QUIT? Are you sure? ",9,7,12,framebuffer); + put_text_xy(" NO!",9,8,12,framebuffer); + put_text_xy(" YES!",9,9,12,framebuffer); + quit_loop: + + if (quit_bar==0) { + put_text_xy(" --> NO! ",9,8,13,framebuffer); + put_text_xy(" YES ",9,9,5,framebuffer); + } + else { + put_text_xy(" NO ",9,8,5,framebuffer); + put_text_xy(" --> YES! ",9,9,13,framebuffer); + } + + dump_to_screen(framebuffer); + while ((ch=get_a_char())==0) usleep(5000); + + if ((ch=='i') || (ch=='j') || (ch=='k') || (ch=='m')) quit_bar=!quit_bar; + + if (ch=='y') quit_bar=1; + if (ch=='n') quit_bar=0; + + if (ch=='\n') { + return quit_bar; + } + + goto quit_loop; + + return 0; + +} + +int ending(char *framebuffer) { + + sleep(3); + + clear_keyboard_buffer(); + + clear_framebuffer(framebuffer,0,' '); + + blit(earth_sprite,framebuffer,219,32,0,5,6); + put_text_xy("INCOMING MESSAGE FROM",0,0,15,framebuffer); + put_text_xy(" ** EARTH **",0,1,15,framebuffer); + + put_text_xy("Congratulations Tom!",0,3,14,framebuffer); + put_text_xy("You've destroyed the",0,4,14,framebuffer); + put_text_xy(" Marketing Menace!!",0,5,14,framebuffer); + + put_text_xy("But wait...",0,7,14,framebuffer); + put_text_xy("Our sensors detect another batch of",0,8,14,framebuffer); + put_text_xy(" enemies, moving even faster!",0,9,14,framebuffer); + put_text_xy("Feel free to quit at any time, but",0,11,14,framebuffer); + put_text_xy(" remember no paycheck bonus unless",0,12,14,framebuffer); + put_text_xy(" all are destroyed.",0,13,14,framebuffer); + put_text_xy("PS Your pet guinea",0,15,14,framebuffer); + put_text_xy(" pig is doing",0,16,14,framebuffer); + put_text_xy(" well. -->",0,17,14,framebuffer); + blit(susie_sprite,framebuffer,219,20,15,19,7); + put_text_xy("** END TRANSMISSION **",0,22,15,framebuffer); + + dump_to_screen(framebuffer); + + while(get_char()==0) usleep(30); + + clear_framebuffer(framebuffer,0,' '); + + blit(tom_head_sprite,framebuffer,219,0,0,7,7); + put_text_xy("Tom: *Sigh*",10,0,9,framebuffer); + + put_text_xy("Press Any Key to Resume Fighting",0,10,15,framebuffer); + + dump_to_screen(framebuffer); + + while(get_char()==0) usleep(30); + + return 0; +} + +int help(char *framebuffer) { + + clear_framebuffer(framebuffer,0,' '); + + put_text_xy("TOM BOMBEM",10,0,15,framebuffer); + + put_text_xy("by",14,1,7,framebuffer); + put_text_xy("Vince Weaver",9,2,15,framebuffer); + + put_text_xy("Key Bindings:",0,4,15,framebuffer); + put_text_xy("UP or 'i' : Move menu up",2,6,7,framebuffer); + put_text_xy("DOWN or 'm' : Move menu down",2,7,7,framebuffer); + put_text_xy("ENTER : Selects current option",2,8,7,framebuffer); + + put_text_xy("RIGHT or 'k' : Move ship right",2,10,7,framebuffer); + put_text_xy("LEFT or 'j' : Move ship left",2,11,7,framebuffer); + put_text_xy("SPACEBAR : Shoots",2,12,7,framebuffer); + + put_text_xy("F1 or 'h' : Displays help",2,14,7,framebuffer); + put_text_xy("ESC or 'q' : Quits",2,15,7,framebuffer); + put_text_xy("'p' : Pauses",2,16,7,framebuffer); + put_text_xy("'s' : Toggles sound",2,17,7,framebuffer); + + dump_to_screen(framebuffer); + + while(get_char()==0) usleep(30); + + return 0; +} + + + +int hi_score(char *framebuffer) { + + char temp_string[BUFSIZ]; + + load_hi_score(); + + put_attention_block(framebuffer,12); + put_text_xy("HIGH SCORE",15,7,14,framebuffer); + + sprintf(temp_string," %s %i ",hi_player,hiscore); + put_text_xy(temp_string,(40-strlen(temp_string))/2,9,15,framebuffer); + + dump_to_screen(framebuffer); + + + + return 0; +} + +int new_hi_score(char *framebuffer) { + + FILE *hi_score; + char temp_name[4]="AAA"; + int char_num=0,ch; + + put_attention_block(framebuffer,9); + put_text_xy("NEW HIGH SCORE",13,5,13,framebuffer); + put_text_xy("Use the arrows to pick your initials",2,7,14,framebuffer); + put_text_xy("Press ENTER when you are done",5,8,14,framebuffer); + + hi_score_loop: + put_text_xy(" ",17,10,15,framebuffer); + put_text_xy(" ",18,11,15,framebuffer); + + put_text_xy(temp_name,18,10,15,framebuffer); + put_text_xy("^",18+char_num,11,15,framebuffer); + + dump_to_screen(framebuffer); + + while ((ch=get_a_char())==0) usleep(5000); + + if (ch=='k') { + char_num++; + if (char_num>2) char_num=0; + } + if (ch=='j') { + char_num--; + if (char_num<0) char_num=2; + } + + if (ch=='i') { + temp_name[char_num]--; + if (temp_name[char_num]<64) temp_name[char_num]=126; + } + + if (ch=='m') { + temp_name[char_num]++; + if (temp_name[char_num]>126) temp_name[char_num]=64; + } + + if (ch!='\n') goto hi_score_loop; + + strncpy(hi_player,temp_name,3); + + hi_score=fopen("/tmp/tb_asm.hsc","w"); + if (hi_score!=NULL) { + fprintf(hi_score,"%i\n",hiscore); + fprintf(hi_score,"%s\n",hi_player); + fclose(hi_score); + } + + return 0; +} + + + + +void set_sound(int freq,int duration) { + printf("%c[10;%i]%c[11;%i]\n",27,freq,27,duration); + play_sound=1; +} + + + +#define UP_SHIELDS 200 + +int new_game(char *framebuffer) { + + + int i,j,xadd=0,scroll=0,quit=0,x=20,bigx=20<<8,y=16; + int sound=1,shields=8,score=0; + int game_paused=0,current_enemy_type=0 /*0*/,current_enemy_kind=-1,current_init_x=-1, + total_enemies_out=0,level=1,enemies_spawned=1,enemy_wave=0; + + char temp_string[BUFSIZ]; + + int done_waiting; + struct timeval timing_info; + int time_spent,oldusec=0,oldsec=0; + + struct boss_type { + int x,xadd,count; + int waiting,hits,smoke,exploding; + int shooting; + } boss; + + struct missile_type { + int out,x,y; + } missile[2]; + + struct enemy_type { + int x,y,out,kind; + int xadd,yadd,xmin,xmax; + int hitsneeded; + int exploding; + } enemies[5]; + + int enemy_wait=30,enemy_count=0; + + + char ch; + + char *background; + + FILE *debug; + + debug=fopen("debug","w"); + + + load_hi_score(); + + clear_keyboard_buffer(); + clear_framebuffer(framebuffer,0x0,' '); + + background=calloc(1600,sizeof(char)); + + missile[0].out=0; + missile[1].out=0; + + for(i=0;i<5;i++) enemies[i].out=0; + + + /* RANDOMIZE TIMER */ + srand(time(NULL)); + + /* Draw the Stars */ + for(i=0;i<50;i++) { + *(background+(rand()%40)*40+rand()%40)=7; + *(background+(rand()%40)*40+rand()%40)=8; + } + + + while(!quit) { + + + clear_framebuffer(framebuffer,0x0,' '); + + /* Scrolling Stars */ + scroll-=1; + if (scroll<0) scroll=78; + + if (scroll/2<20) { + blit(background+(scroll/2*40),framebuffer,'.',0,0,40,20); + } + else { + blit(background+(scroll/2*40),framebuffer,'.',0,0,40,40-scroll/2); + blit(background,framebuffer,'.',0,40-scroll/2,40,scroll/2-20); + } + + + /* Put out new enemies */ + + /* Type 0: "Diagonal No Wait" x_init=rand, xadd=1, yadd=1 + * Type 1: "horiz then fall" xadd=1. After random, xadd=0 yadd=1 + * Type 2: "diagonal, wait" wait(all_free) then 0 with same type + * Type 4: "Wiggle" x=rand() + * Type 5: "Rain" x=rand() xadd=0 yadd=1 + * Type 6: Wait for Boss + * Type 7: BOSS + * + * + * After enemies_destroyed>20 switch types + * After enemies_destroyed>500? Wait till all destroyed then BOSS + * After boss keep going, knocking up speed each 100 + */ + + /* Keep a level indicator? */ + + /* Keep a count of how close to place enemies */ + /* Don't want all to appear at once */ + + + enemy_count++; + if (enemy_count==enemy_wait) { + enemy_count=0; + + if (current_enemy_type==7) enemies_spawned=1; + + /* make length random? */ + if (enemies_spawned%15==0) { + + enemies_spawned++; /* hack to keep from getting stuck */ + current_enemy_type=rand()%6; + + enemy_wave++; + if (enemy_wave==15) current_enemy_type=6; + + + if ((current_enemy_type==0) || (current_enemy_type==1)) + enemy_wait=30; + else enemy_wait=10; + current_enemy_kind=-1; + current_init_x=-1; + + } + + + i=0; + while (i<5) { + if (!enemies[i].out) break; + i++; + } + + if (current_enemy_type==2) { + if (total_enemies_out>0) goto move_enemies; + current_enemy_type=3; + current_enemy_kind=rand()%6; + current_init_x=rand()%300; + enemy_wait=10; + } + + if (current_enemy_type==6) { + if (total_enemies_out>0) goto move_enemies; + boss.x=13; + boss.xadd=1; + boss.count=10+rand()%40; + boss.waiting=1; + boss.hits=20+(5*level); + boss.smoke=0; + boss.exploding=0; + current_enemy_type=7; + enemy_wait=10; + } + + if ((current_enemy_type==7) && (boss.waiting)) goto move_enemies; + + if (i<5) { + enemies_spawned++; + enemies[i].out=1; + enemies[i].exploding=0; + total_enemies_out++; + enemies[i].y=0; + enemies[i].hitsneeded=0; + enemies[i].xmin=0; + enemies[i].xmax=37; + + if (current_enemy_kind<0) enemies[i].kind=rand()%6; + else enemies[i].kind=current_enemy_kind; + + if (current_init_x<0) enemies[i].x=rand()%300; + else enemies[i].x=current_init_x; + + switch(current_enemy_type) { + case 0: enemies[i].xadd=level; + enemies[i].yadd=level; + break; + case 1: enemies[i].xadd=5; + enemies[i].yadd=-(rand()%100); + break; + case 3: enemies[i].xadd=3; + enemies[i].yadd=level; + break; + case 4: enemies[i].xadd=4; + enemies[i].yadd=level; + enemies[i].xmin=2+rand()%34; + enemies[i].xmax=enemies[i].xmin+(rand()%20); + if (enemies[i].xmax>35) enemies[i].xmax=35; + enemies[i].x=enemies[i].xmin*8; +// fprintf(debug,"%i %i\n",enemies[i].xmin,enemies[i].xmax) + break; + case 5: enemies[i].xadd=0; enemies[i].yadd=2; + if (rand()%3==0) enemies[i].x=x; + break; + case 7: enemies[i].xadd=0; enemies[i].yadd=2; + enemies[i].x=(boss.x+5)*8; + enemies[i].y=3*8; + break; + } + + } + + } + +move_enemies: + + + /* Move the enemies */ + for(i=0;i<5;i++) { + if (enemies[i].out) { + + /* Move on x */ + if (enemies[i].xadd!=0) { + enemies[i].x+=enemies[i].xadd; + + if ((enemies[i].x/8>37) || (enemies[i].x/8<0)) { + enemies[i].xadd=-enemies[i].xadd; + enemies[i].x+=enemies[i].xadd; + } + + if (current_enemy_type==4) { + if ((enemies[i].x/8>enemies[i].xmax) || (enemies[i].x/80) { + enemies[i].y+=enemies[i].yadd; + if (enemies[i].y/8>18) { + enemies[i].out=0; + total_enemies_out--; + } + + } + + + /* Ship <-> Enemies Collision Detection */ + if (!enemies[i].exploding) { + if ( ( (enemies[i].x/8+2 >= x) && (enemies[i].x/8+2 <= x +6) ) + || ( (enemies[i].x/8 >=x) && (enemies[i].x/8 <= x+6))) { + + if ( ((enemies[i].y/8 >= y) && (enemies[i].y/8 <=y+2)) + || ( (enemies[i].y/8+1 >=y) && (enemies[i].y/8+1 <=y+2)) ) { + + enemies[i].exploding=1; + shields--; + set_sound(120,50); + + } + + } + + + } + + + + } + } + + + + + + + /* Draw the enemies */ + for(i=0;i<5;i++) { + if (enemies[i].out) { + if (enemies[i].exploding) { + blit(explosion_sprites[enemies[i].exploding/2-1],framebuffer,219,enemies[i].x/8,enemies[i].y/8,3,2); + enemies[i].exploding++; + if (enemies[i].exploding>7) { + enemies[i].out=0; + total_enemies_out--; + } + + + } + else { + blit(enemy_sprites[enemies[i].kind],framebuffer,219,enemies[i].x/8,enemies[i].y/8,3,2); + } + } + + } + + + /* Draw the Boss */ + if (current_enemy_type==7) { + if (boss.exploding!=1) blit(boss_sprite,framebuffer,219,boss.x,0,13,3); + if (boss.smoke) { + blit(smoke_sprites[boss.smoke/4],framebuffer,219,boss.x+5,3,3,1); + blit(smoke_sprites[boss.smoke/4],framebuffer,219,boss.x+5-boss.xadd,4,3,1); + boss.smoke--; + } + + if (boss.shooting) { + boss.shooting--; + for(i=0;i<8;i++) { + blit(laser_sprite[boss.shooting%2],framebuffer,219,boss.x,3+(i*2),1,2); + blit(laser_sprite[boss.shooting%2],framebuffer,219,boss.x+12,3+(i*2),1,2); + set_sound(200+boss.shooting,20); + } + } + + if (boss.exploding) { + boss.waiting=1; + for(i=0;i<30;i++) { + blit(smoke_sprites[boss.exploding/8],framebuffer,219,boss.x+rand()%11,rand()%4,3,1); + } + set_sound(120,20); + boss.exploding--; + if (boss.exploding==0) { + level++; + boss.shooting=0; + for(i=0;i<5;i++) enemies[i].exploding=2; + ending(framebuffer); + current_enemy_type=2; + enemy_wave=0; + } + } + + else { + + boss.count--; + if (boss.count<0) { + if (boss.waiting) { + boss.waiting=0; + boss.count=40+rand()%320; + } + + else { + boss.waiting=1; + boss.count=30+rand()%40; + boss.shooting=30; + + } + + } + } + + + if (!boss.waiting) { + boss.x+=boss.xadd; + if ((boss.x>26) || (boss.x<0)) { + boss.xadd=-boss.xadd; + boss.x+=boss.xadd; + } + + } + + /* Collision detection for lasers */ + if (boss.shooting) { + if (((boss.x < x+6) && (boss.x>=x)) || + ((boss.x+12=x))) { + if (boss.shooting%7==0) shields--; + + } + } + } + + + + + /* Move the missiles */ + for(i=0;i<2;i++) { + if (missile[i].out) { + missile[i].y--; + if (missile[i].y<0) missile[i].out=0; + + /* Missile Collision Detection */ + for(j=0;j<5;j++) { + + /* Missile <-> Enemy Collision Detection */ + if ((enemies[j].out)&&(!enemies[j].exploding)) { + if ((missile[i].x >=enemies[j].x/8) && (missile[i].x < enemies[j].x/8+3)) { + if ((missile[i].y >= enemies[j].y/8) && (missile[i].y <=enemies[j].y/8+1) ) { + missile[i].out=0; + enemies[j].exploding=2; + set_sound(150,40); + score+=10; + if (score%UP_SHIELDS==0) { + shields++; + set_sound(220,50); + if (shields>9) shields=9; + } + + } + } + } + } + + /* Missile <-> Boss Collision Detection */ + if ((current_enemy_type==7) && (!boss.exploding)) { + if ((missile[i].x >= boss.x) && (missile[i].x < boss.x+13)) { + if ((missile[i].y>= 0) && (missile[i].y <=2)) { + missile[i].out=0; + boss.smoke=11; + set_sound(150,50); + boss.hits--; + + if (boss.hits<0) boss.exploding=23; + } + } + } + } + } + + /* Draw the missiles */ + for(i=0;i<2;i++) { + if (missile[i].out) blit(missile_sprite,framebuffer,219,missile[i].x,missile[i].y,1,3); + } + + + + + ch=0; + + while( (ch=get_a_char()) ) { + + switch(ch) { + case 'd': dump_screen=1; break; + case 'q': case 'Q': + if (verify_quit(framebuffer)) { + quit=1; + } + else { + game_paused=1; + } + break; + case 'j': if (xadd<=0) xadd-=128; else xadd=0; break; + case 'k': if (xadd>=0) xadd+=128; else xadd=0; break; + case 'p': + put_attention_block(framebuffer,14); + put_text_xy(" GAME PAUSED! ",13,8,12,framebuffer); + dump_to_screen(framebuffer); + + while (get_char()==0) usleep(5000); + game_paused=1; + break; + case 's': sound=!sound; /*level++;*/ break; + case 'h': help(framebuffer); /*game_paused=1;*/ break; + case ' ': if (!missile[0].out) { + missile[0].out=1; + missile[0].x=x+3; + missile[0].y=y; + set_sound(110,30); + } else if (!missile[1].out) { + missile[1].out=1; + missile[1].x=x+3; + missile[1].y=y; + set_sound(110,30); + + } + break; + } + } + + bigx+=xadd; + if (bigx<0) { + bigx=0; + xadd=0; + } + + if (bigx>(32<<8)) { + bigx=32<<8; + xadd=0; + } + + x=bigx>>8; + + + blit(ship_sprite,framebuffer,219,x,y,8,4); + + put_text_xy("SHIELDS: ",0,21,shields?12:14,framebuffer); + + for(i=0;i<10;i++) { + if (ihiscore) { + hiscore=score; + fprintf(debug,"score=%i hiscore=%i\n",score,hiscore); + new_hi_score(framebuffer); + } + hi_score(framebuffer); + + pause_a_while(5000); + + return 0; +} + +int about(char *framebuffer) { + + clear_framebuffer(framebuffer,0,' '); + + blit(vince_sprite,framebuffer,219,24,0,16,20); + put_text_xy("TOM BOMBEM",7,0,13,framebuffer); + + put_text_xy("by",11,1,14,framebuffer); + put_text_xy("Vince Weaver",6,2,9,framebuffer); + put_text_xy("author if you squint ->",0,3,12,framebuffer); + + put_text_xy("* Testing my asm skills",0,5,11,framebuffer); + + put_text_xy("* Based on Tom Bombem: ",0,7,10,framebuffer); + put_text_xy(" Invasion of Inanimate",0,8,10,framebuffer); + put_text_xy(" Objects, a game I ",0,9,10,framebuffer); + put_text_xy(" started 10 years ago ",0,10,10,framebuffer); + put_text_xy(" in Pascal/asm and is ",0,11,10,framebuffer); + put_text_xy(" still languishing ",0,12,10,framebuffer); + put_text_xy(" uncompleted in C/SDL.",0,13,10,framebuffer); + + put_text_xy("Contact Vince:",0,17,5,framebuffer); + put_text_xy("vince@deater.net",0,18,9,framebuffer); + put_text_xy("http://www.deater.net/weave/",0,19,9,framebuffer); + + dump_to_screen(framebuffer); + + while(get_char()==0) usleep(30); + + return 0; +} + + +int story(char *framebuffer) { + + int x; + + clear_framebuffer(framebuffer,0,' '); + blit(phobos_sprite,framebuffer,219,0,0,40,16); + /* 0 5 0 5 0 5 0 5 0 */ + put_text_xy("It is the year 2025. All telemarketers",0,17,15,framebuffer); + put_text_xy("and unsolicited bulk e-mailers have ",0,18,15,framebuffer); + put_text_xy("been exiled to Phobos.",0,19,15,framebuffer); + + dump_to_screen(framebuffer); + pause_a_while(7000); + + put_text_xy("Right before being trapped forever they",0,17,10,framebuffer); + put_text_xy("manage to launch one last marketing ",0,18,10,framebuffer); + put_text_xy("droid. ",0,19,10,framebuffer); + + dump_to_screen(framebuffer); + pause_a_while(4000); + + x=19; + while(x<37) { + blit(evil_ship_sprite,framebuffer,219,x,9,3,1); + dump_to_screen(framebuffer); + pause_a_while(250); + put_text_xy(" ",x,9,0,framebuffer); + x++; + + } + pause_a_while(2000); + + clear_framebuffer(framebuffer,0,' '); + blit(tom_sprite,framebuffer,219,24,1,16,18); + + /*0 5 0 5 0 */ + put_text_xy("You are Tom Bombem.",0,0,9,framebuffer); + + put_text_xy("You drew the short straw.",0,2,9,framebuffer); + + put_text_xy("So it is up to you to",0,4,9,framebuffer); + put_text_xy(" fight through the ads",0,5,9,framebuffer); + put_text_xy(" and destroy the evil ",0,6,9,framebuffer); + put_text_xy(" marketing robot, thus",0,7,9,framebuffer); + put_text_xy(" restoring harmony to ",0,8,9,framebuffer); + put_text_xy(" the space lanes.",0,9,9,framebuffer); + + put_text_xy(" GOOD LUCK!",0,12,11,framebuffer); + + dump_to_screen(framebuffer); + pause_a_while(20000); + + return 0; +} + + +int main(int argc, char **argv) { + + static struct termios new_tty,old_tty; + + char *framebuffer; + + + int i,menu_item; + char ch; + + framebuffer=calloc(SCREEN_WIDTH*SCREEN_HEIGHT*BYTES_PER_PIXEL,sizeof(char)); + + /* setup non-blocking non-echo mode */ + + tcgetattr(0,&old_tty); + + new_tty=old_tty; + new_tty.c_lflag&=~ICANON; + new_tty.c_cc[VMIN]=1; + new_tty.c_lflag&=~ECHO; + tcsetattr(0,TCSANOW,&new_tty); + + fcntl(0,F_SETFL,fcntl(0,F_GETFL) | O_NONBLOCK); + + + /* clear screen */ + printf("\033[2J\n"); + + clear_framebuffer(framebuffer,0,' '); + + blit(vmw_sprite,framebuffer,219,8,6,23,8); + put_text_xy("A VMW Software Production",7,15,15,framebuffer); + dump_to_screen(framebuffer); + pause_a_while(3000); + + + opening_screen: + + clear_framebuffer(framebuffer,0,' '); + blit(opener_sprite,framebuffer,219,0,0,40,20); + put_text_xy("Merciless Marauding Malicious Marketers",0,5,14,framebuffer); + + dump_to_screen(framebuffer); + + pause_a_while(10000); + + + menu_item=0; + + put_attention_block(framebuffer,0); + + while(1) { + put_text_xy("New Game",15,6,(menu_item==0)?13:5,framebuffer); + put_text_xy("About",15,7,(menu_item==1)?13:5,framebuffer); + put_text_xy("Story",15,8,(menu_item==2)?13:5,framebuffer); + put_text_xy("Hi Score",15,9,(menu_item==3)?13:5,framebuffer); + put_text_xy("Quit",15,10,(menu_item==4)?13:5,framebuffer); + put_text_xy("F1 or 'h' for HELP",0,20,7,framebuffer); + + for(i=0;i<5;i++) + if (i==menu_item) put_text_xy("-->",12,6+menu_item,14,framebuffer); + else put_text_xy(" ",12,6+i,0,framebuffer); + dump_to_screen(framebuffer); + + while( !(ch=get_a_char()) ) usleep(30); + + switch(ch) { + case 'q': case 'Q': menu_item=4; ch='\n'; break; + + case 'i': case 'j': menu_item--; + if (menu_item<0) menu_item=4; + break; + case 'm': case 'k': menu_item++; + if (menu_item>4) menu_item=0; break; + case 'h': menu_item=5; ch='\n'; break; + + + case 10: case 13: case 32: break; + + + + } + + if ((ch==10) || (ch==13) || (ch==32)) { + switch(menu_item) { + case 0: new_game(framebuffer); break; + case 1: about(framebuffer); break; + case 2: story(framebuffer); break; + case 3: hi_score(framebuffer); + while(get_char()==0) usleep(30); + break; + case 4: if (verify_quit(framebuffer)) goto done_the_game; break; + case 5: help(framebuffer); break; + } + goto opening_screen; + } + + } + + + + + + done_the_game: + printf("%c\n",15); + set_sound(750,125); /* The default. No way I know of to save/restore */ + tcsetattr(0,TCSANOW,&old_tty); + + return 0; +} diff --git a/tb_asm/c/tom.h b/tb_asm/c/tom.h new file mode 100644 index 0000000..f4388f3 --- /dev/null +++ b/tb_asm/c/tom.h @@ -0,0 +1,23 @@ +/* 16x18 */ + +char tom_sprite[]= +{ +0x0,0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x9,0x9,0x9,0x9,0x0,0x0,0x0,0x0, +0x0,0x0,0x1,0x1,0x0,0x0,0x0,0x0,0x8,0x8,0x9,0x9,0x0,0x0,0x0,0x0, +0x0,0x0,0x1,0x1,0x0,0x0,0x0,0x0,0x8,0x8,0x9,0x9,0x0,0x0,0x0,0x0, +0x0,0x0,0x1,0x1,0x0,0x0,0x0,0x0,0x8,0x8,0x9,0x9,0x0,0x0,0x0,0x0, +0x0,0x0,0x1,0x1,0x0,0x0,0x0,0x0,0x8,0x8,0x9,0x9,0x0,0x0,0x0,0x0, +0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x9,0x9,0x0,0x0,0x0,0x0,0x0,0x0, +0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x9,0x9,0x9,0x9,0x9,0x9,0x9,0x9, +0x1,0x1,0x9,0x9,0x1,0x1,0x1,0x1,0x9,0x9,0xc,0xc,0x1,0x1,0x9,0x9, +0x1,0x1,0x9,0x9,0x1,0x1,0x1,0x1,0x9,0x9,0x9,0x9,0x1,0x1,0x9,0x9, +0x1,0x1,0x9,0x9,0x1,0x1,0x1,0x1,0x9,0x9,0x9,0x9,0x1,0x1,0x9,0x9, +0x1,0x1,0x9,0x9,0x1,0x1,0x1,0x1,0x9,0x9,0x9,0x9,0x1,0x1,0x9,0x9, +0x1,0x1,0x9,0x9,0x1,0x1,0x1,0x1,0x9,0x9,0x9,0x9,0x1,0x1,0x9,0x9, +0x3,0x3,0xb,0xb,0x1,0x1,0x9,0x9,0x1,0x1,0x9,0x9,0x3,0x3,0xb,0xb, +0x0,0x0,0x0,0x0,0x1,0x1,0x9,0x9,0x1,0x1,0x9,0x9,0x0,0x0,0x0,0x0, +0x0,0x0,0x0,0x0,0x1,0x1,0x9,0x9,0x1,0x1,0x9,0x9,0x0,0x0,0x0,0x0, +0x0,0x0,0x0,0x0,0x1,0x1,0x9,0x9,0x1,0x1,0x9,0x9,0x0,0x0,0x0,0x0, +0x0,0x0,0x0,0x0,0x3,0x3,0xb,0xb,0x3,0x3,0xb,0xb,0x0,0x0,0x0,0x0, +0x0,0x0,0x0,0x0,0x8,0x8,0x7,0x7,0x8,0x8,0x7,0x7,0x0,0x0,0x0,0x0, +}; diff --git a/tb_asm/c/vince.h b/tb_asm/c/vince.h new file mode 100644 index 0000000..fb48836 --- /dev/null +++ b/tb_asm/c/vince.h @@ -0,0 +1,26 @@ +/* Vince */ + +/* 16x20 */ + +char vince_sprite[]={ +0x0,0x0,0x8,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x8,0x0,0x0,0x0,0x0, +0x0,0x8,0x7,0xf,0xf,0xf,0xf,0x7,0xf,0xf,0xf,0xf,0x7,0x7,0x0,0x0, +0x8,0x7,0x7,0x7,0x7,0x7,0x8,0x7,0xf,0x7,0x7,0xf,0xf,0xf,0x7,0x0, +0x7,0x8,0x0,0x8,0x7,0x7,0x7,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x8, +0x7,0x0,0x8,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x7, +0x8,0x0,0x7,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x7,0xf,0x7,0x7,0x8,0x8, +0x8,0x8,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x8,0x8,0x0,0x8,0x7, +0x8,0x7,0xf,0xf,0xf,0xf,0x7,0xf,0xf,0xf,0x7,0x0,0x8,0x0,0x8,0x7, +0x7,0x8,0x8,0x7,0xf,0x8,0x0,0x8,0x7,0xf,0x7,0x0,0x0,0x0,0x0,0x8, +0x0,0x7,0x0,0x8,0xf,0x0,0x0,0x8,0x0,0x8,0xf,0x8,0x0,0x0,0x0,0x8, +0x0,0x7,0x8,0x7,0xf,0x8,0x0,0x0,0x7,0xf,0xf,0x7,0x0,0x0,0x0,0x7, +0x0,0xf,0x8,0xf,0xf,0xf,0x7,0x7,0xf,0xf,0xf,0xf,0x0,0x0,0x0,0x7, +0x0,0xf,0x7,0x8,0x8,0x7,0xf,0xf,0xf,0xf,0xf,0x8,0x8,0x8,0x7,0x7, +0x0,0xf,0xf,0x8,0x0,0x7,0xf,0xf,0xf,0xf,0x7,0x0,0x7,0x7,0x7,0x0, +0x0,0xf,0xf,0x7,0x8,0x7,0x7,0xf,0xf,0xf,0x7,0x0,0x7,0x7,0x8,0x0, +0x0,0x7,0x7,0x0,0x8,0x0,0x0,0x7,0x7,0x0,0x0,0xf,0x8,0x7,0x0,0x0, +0x0,0x8,0xf,0xf,0x8,0xf,0xf,0x7,0x0,0x0,0x8,0x7,0x7,0x8,0x0,0x0, +0x0,0x0,0xf,0x7,0x7,0x7,0xf,0x7,0x7,0x8,0x8,0xf,0x7,0x0,0x0,0x0, +0x0,0x0,0x7,0xf,0xf,0xf,0xf,0x8,0x8,0x0,0x8,0xf,0x8,0x0,0x0,0x0, +0x0,0x0,0x0,0x8,0x8,0x0,0x0,0x0,0x0,0x0,0x7,0xf,0x8,0x0,0x0,0x0, +}; diff --git a/tb_asm/c/vmwsoft.h b/tb_asm/c/vmwsoft.h new file mode 100644 index 0000000..bb555b1 --- /dev/null +++ b/tb_asm/c/vmwsoft.h @@ -0,0 +1,14 @@ +/*vmw @ 8,6 +"A VMW Software Production" @ 7,15 +*/ + +char vmw_sprite[]={ +0x4,0x4,0x4,0x4,0x4,0x4,0x4,0x2,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x2,0x1,0x1,0x1,0x1,0x1,0x1,0x1, +0x4,0x4,0x4,0x4,0x4,0x4,0x4,0x2,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x2,0x1,0x1,0x1,0x1,0x1,0x1,0x1, +0x0,0x4,0x4,0x4,0x4,0x4,0x2,0x2,0x2,0x1,0x1,0x1,0x1,0x1,0x2,0x2,0x2,0x1,0x1,0x1,0x1,0x1,0x0, +0x0,0x4,0x4,0x4,0x4,0x4,0x2,0x2,0x2,0x1,0x1,0x1,0x1,0x1,0x2,0x2,0x2,0x1,0x1,0x1,0x1,0x1,0x0, +0x0,0x0,0x4,0x4,0x4,0x2,0x2,0x2,0x2,0x2,0x1,0x1,0x1,0x2,0x2,0x2,0x2,0x2,0x1,0x1,0x1,0x0,0x0, +0x0,0x0,0x4,0x4,0x4,0x2,0x2,0x2,0x2,0x2,0x1,0x1,0x1,0x2,0x2,0x2,0x2,0x2,0x1,0x1,0x1,0x0,0x0, +0x0,0x0,0x0,0x4,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x1,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x1,0x0,0x0,0x0, +0x0,0x0,0x0,0x4,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x1,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x1,0x0,0x0,0x0, +}; diff --git a/tb_asm/compress_data.c b/tb_asm/compress_data.c new file mode 100644 index 0000000..0a6486a --- /dev/null +++ b/tb_asm/compress_data.c @@ -0,0 +1,274 @@ +/* The following code is UGLY. Read at your own risk. --vmw */ + +#include +#include /* strncpy() */ +#include /* isdigit() */ +#include /* open() */ +#include /* close() */ + +#include "lzss.h" + +int write_ascii(char *string,int output_fd) { + + int pointer=0,count=0,octal=0; + unsigned char byte; + + while(string[pointer]!='\"') pointer++; + pointer++; + + while(string[pointer]!='\"') { + if (string[pointer]=='\\') { + pointer++; + + if (isdigit(string[pointer])) { + octal=0; + while(isdigit(string[pointer])) { + octal=8*octal+(string[pointer]-'0'); + pointer++; + } + if (octal>255) { + fprintf(stderr,"BYTE OUT OF RANGE\n"); + } + else { + byte=octal; + } + pointer--; + } + + else { + switch(string[pointer]) { + case 'n': byte='\n'; break; + case 't': byte='\t'; break; + case '\\': byte='\\'; break; + case '\"': byte='\"'; break; + } + } + } + + else byte=string[pointer]; + + write(output_fd,&byte,1); + + pointer++; + count++; + } + + return count; + +} + +int get_number(char *string, int *pointer) { + + int temp_number; + + if (string[*pointer]=='0') { + + /* Hexadecimal */ + if (string[*pointer+1]=='x') { + (*pointer)++; + (*pointer)++; + temp_number=0; + while(isxdigit(string[*pointer])) { + if ((string[*pointer]>='a') && (string[*pointer]<='f')) + temp_number=16*temp_number+(10+(string[*pointer]-'a')); + if ((string[*pointer]>='A') && (string[*pointer]<='F')) + temp_number=16*temp_number+(10+(string[*pointer]-'A')); + if ((string[*pointer]>='0') && (string[*pointer]<='9')) + temp_number=16*temp_number+(string[*pointer]-'0'); + (*pointer)++; + } + } + else { + /* Octal */ + temp_number=0; + while(isdigit(string[*pointer])) { + temp_number=8*temp_number+(string[*pointer]-'0'); + (*pointer)++; + } + } + + } + else { + /* Decimal */ + temp_number=0; + while(isdigit(string[*pointer])) { + temp_number=10*temp_number+(string[*pointer]-'0'); + (*pointer)++; + } + } + + return temp_number; + +} + +int write_bytes(char *string, int output_fd) { + + int pointer=0,count=0,number=0; + unsigned char temp_byte; + + while(1) { + + while(!isdigit(string[pointer])) { + if (string[pointer]=='\n') goto done_byte; + pointer++; + } + + number=get_number(string,&pointer); + + if (number>255) { + fprintf(stderr,"Byte too big!\n"); + } + else { + temp_byte=number; + write(output_fd,&temp_byte,1); + count++; + } + + } + +done_byte: + return count; + +} + +int write_32bits(char *string, int output_fd) { + + int pointer=0,count=0,number=0; +// unsigned char temp_int[4]; + + while(1) { + + while(!isdigit(string[pointer])) { + if (string[pointer]=='\n') goto done_32; + pointer++; + } + + number=get_number(string,&pointer); + + write(output_fd,&number,4); + count+=4; + } +done_32: + return count; + +} + + + + +int main(int argc, char **argv) { + + FILE *input,*header,*labels,*output; + int output_fd,byte_count; + char input_filename[]="data.inc"; + char output_raw_filename[]="data.raw"; + char output_lzss_filename[]="data.lzss"; + char output_header_filename[]="data.header"; + char output_labels_filename[]="data.labels"; + int offset=0,pointer,temp_pointer; + char input_line[BUFSIZ]; + char temp_label_string[BUFSIZ]; + + input=fopen(input_filename,"r"); + if (input==NULL) goto file_error; + + output_fd=open(output_raw_filename,O_WRONLY|O_CREAT|O_TRUNC,0666); + if (output_fd<0) goto file_error; + + labels=fopen(output_labels_filename,"w"); + if (labels==NULL) goto file_error; + + while(1) { + + if ( fgets(input_line,BUFSIZ,input) ==NULL) goto close_file; + + pointer=0; + + while(pointer0) && + (input_line[temp_pointer]!='\t') && + (input_line[temp_pointer]!=' ')) temp_pointer--; + + memcpy(temp_label_string,input_line+temp_pointer, + pointer-temp_pointer); + temp_label_string[pointer-temp_pointer]='\0'; + fprintf(labels,".equ %s,%i+DATA_OFFSET\n",temp_label_string,offset); + } + + + + + pointer++; + } +done_with_string: ; + + + } + + + +close_file: + fclose(labels); + close(output_fd); + fclose(input); + + printf("Original size of data segment = %i bytes\n",offset); + + input=fopen(output_raw_filename,"r"); + if (input==NULL) goto file_error; + + output=fopen(output_lzss_filename,"w"); + if (output==NULL) goto file_error; + + header=fopen(output_header_filename,"w"); + if (header==NULL) goto file_error; + + byte_count=lzss_encode_better(input,header,output,'\0',1024,2); + + printf("Compressed data segment = %i bytes\n",byte_count); + + fprintf(header,".equ TB_DATA_SIZE,%i\n",offset); + fclose(header); + fclose(input); + fclose(output); + +file_error: + return 0; +} diff --git a/tb_asm/configure.c b/tb_asm/configure.c new file mode 100644 index 0000000..e2e2186 --- /dev/null +++ b/tb_asm/configure.c @@ -0,0 +1,71 @@ +#include + +#include /* strncpy */ +#include /* uname */ +#include /* system */ + +#include "arch.h" + +int linux_detect_arch(void) { + + /* Yes this is a bit messy, but it cleans up the makefile a bit *\ + \* The C-Preproccessor can be out friend ;) */ + +/* return ARCH_SPARC; */ + +#if defined(__alpha__) + return ARCH_ALPHA; +#elif defined(__arm__) + return ARCH_ARM; +#elif defined(__cris__) + return ARCH_CRIS; +#elif defined(__ia64__) + return ARCH_IA64; +#elif defined(i386) + return ARCH_IX86; +#elif (defined(mc68000) || #cpu(m68k)) + return ARCH_M68K; +#elif defined(__mips__) + return ARCH_MIPS; +#elif defined(__parisc__) + return ARCH_PARISC; +#elif defined(__PPC__) + return ARCH_PPC; +#elif defined(__s390__) + return ARCH_S390; +#elif defined(__sh3__) || defined(__sh2__) || defined(__sh4) + return ARCH_SH3 +#elif defined(__sparc__) + return ARCH_SPARC; +#elif defined(__vax__) + return ARCH_VAX; +#else + return ARCH_UNKNOWN; +#endif + +} + +int main(int argc, char **argv) { + + struct utsname buf; + char temp_string[256],arch[65]; + int command_override=0; + + if (argc>1) { + command_override=1; + } + + uname(&buf); + + sprintf(temp_string,"rm -f tb_asm.s"); + system(temp_string); + + + strncpy(arch,arch_names[linux_detect_arch()],63); + printf("+ compiling for %s architecture\n",arch); + + sprintf(temp_string,"ln -n -s tb_asm.%s.s tb_asm.s",arch); + system(temp_string); + + return 0; +} diff --git a/tb_asm/data.inc b/tb_asm/data.inc new file mode 100644 index 0000000..738852d --- /dev/null +++ b/tb_asm/data.inc @@ -0,0 +1,488 @@ +clear_screen: .ascii "\033[2J\n\0" +default_colors: .ascii "\017\033[0m\n\0" +score_file: .ascii "/tmp/tb_asm.hsc\0" + +menu_arrow: .ascii " --> \0" +menu_blank: .ascii " \0" +menu_pointer: .ascii "^\0" + +title_string: .byte 14,5,0 + .ascii "Merciless Marauding Malicious Marketers\0" + +vmw_string: .byte 15,15,7 + .ascii "A VMW Software Production\0" + +menu_new_string: .ascii "New Game\0" +menu_about_string: .ascii "About\0\0\0\0" +menu_story_string: .ascii "Story\0\0\0\0" +menu_hi_string: .ascii "Hi Score\0" +menu_quit_string: .ascii "Quit\0\0\0\0\0" +menu_no_string: .ascii "NO! \0\0\0" +menu_yes_string: .ascii "YES! \0\0\0" + +menu_help_string: .byte 7,20,0 + .ascii "F1 or 'h' for HELP\0" + +bonus_points_line: .byte 15,5,14 + .ascii "BONUS POINTS\0" +no_bonus_line: .byte 14,7,5 + .ascii "NO BONUSES THIS LEVEL\0" +no_shield_line: .byte 14,7,5 + .ascii "NO SHIELD HITS = +1000\0" +shot_every_line: .byte 14,8,5 + .ascii "DESTROYED EVERY ENEMY = +5000\0" +perfect_shot_line: .byte 14,9,5 + .ascii "PERFECT SHOT = +5000\0" + + +about_line_0: .byte 13,0,7 + .ascii "TOM BOMBEM\0" + .byte 14,1,11 + .ascii "by\0" + .byte 9,2,6 + .ascii "Vince Weaver\0" + .byte 12,3,0 + .ascii "author if you squint ->\0" + .byte 11,5,0 + .ascii "* Testing my asm skills\0" + .byte 10,7,0 + .ascii "* Based on Tom Bombem:\0" + .byte 10,8,2 + .ascii "Invasion of Inanimate\0" + .byte 10,9,2 + .ascii "Objects, a game I\0" + .byte 10,10,2 + .ascii "started 10 years ago\0" + .byte 10,11,2 + .ascii "in Pascal/asm and is\0" + .byte 10,12,2 + .ascii "still languishing\0" + .byte 10,13,2 + .ascii "uncompleted in C/SDL.\0" + .byte 5,17,0 + .ascii "Contact Vince:\0" + .byte 9,18,0 + .ascii "vince@deater.net\0" + .byte 9,19,0 + .ascii "http://www.deater.net/weave/\0" + + + +story_line_0: .byte 15,17,0 + .ascii "It is the year 2025. All telemarketers\0" + .byte 15,18,0 + .ascii "and unsolicited bulk e-mailers have\0" + .byte 15,19,0 + .ascii "been exiled to Phobos.\0" + +story_line_1: .byte 10,17,0 + .ascii "Right before being trapped forever they\0" + .byte 10,18,0 + .ascii "manage to launch one last marketing\0" + .byte 10,19,0 + .ascii "droid. \0" + # note spaces needed to overwrite old text? + +story_line_2: + .byte 9,0,0 + .ascii "You are Tom Bombem.\0" + .byte 9,2,0 + .ascii "You drew the short straw.\0" + .byte 9,4,0 + .ascii "So it is up to you to\0" + .byte 9,5,2 + .ascii "fight through the ads\0" + .byte 9,6,2 + .ascii "and destroy the evil\0" + .byte 9,7,2 + .ascii "marketing robot, thus\0" + .byte 9,8,2 + .ascii "restoring harmony to\0" + .byte 9,9,2 + .ascii "the space lanes.\0" + .byte 11,12,7 + .ascii "GOOD LUCK!\0" + +ending_line: + .byte 15,0,0 + .ascii "INCOMING MESSAGE FROM\0" + .byte 15,1,5 + .ascii "** EARTH **\0" + .byte 14,3,0 + .ascii "Congratulations Tom!\0" + .byte 14,4,0 + .ascii "You've destroyed the\0" + .byte 14,5,2 + .ascii "Marketing Menace!!\0" + .byte 14,7,0 + .ascii "But wait...\0" + .byte 14,8,0 + .ascii "Our sensors detect another batch of\0" + .byte 14,9,2 + .ascii "enemies, moving even faster!\0" + .byte 14,11,0 + .ascii "Feel free to quit at any time, but\0" + .byte 14,12,2 + .ascii "remember no paycheck bonus unless\0" + .byte 14,13,2 + .ascii "all are destroyed.\0" + .byte 14,15,0 + .ascii "PS Your pet guinea\0" + .byte 14,16,3 + .ascii "pig is doing\0" + .byte 14,17,3 + .ascii "well.\0" + .byte 14,17,16 + .ascii "-->\0" + .byte 15,22,0 + .ascii "** END TRANSMISSION **\0" +ending_line_2: + .byte 9,0,10 + .ascii "Tom: *Sigh*\0" + .byte 15,10,0 + .ascii "Press Any Key to Resume Fighting\0" + + +help_line_0: .byte 15,0,10 + .ascii "TOM BOMBEM\0" + .byte 7,1,14 + .ascii "by\0" + .byte 15,2,9 + .ascii "Vince Weaver\0" + .byte 15,4,0 + .ascii "Key Bindings:\0" + .byte 7,6,2 + .ascii "UP or 'i' : Move menu up\0" + .byte 7,7,2 + .ascii "DOWN or 'm' : Move menu down\0" + .byte 7,8,2 + .ascii "ENTER\0" + .byte 7,8,15 + .ascii ": Selects current option\0" + .byte 7,10,2 + .ascii "RIGHT or 'k' : Move ship right\0" + .byte 7,11,2 + .ascii "LEFT of 'j' : Move ship left\0" + .byte 7,12,2 + .ascii "SPACEBAR\0" + .byte 7,12,15 + .ascii ": Shoots\0" + .byte 7,14,2 + .ascii "F1 or 'h' : Displays help\0" + .byte 7,15,2 + .ascii "ESC or 'q' : Quits\0" + .byte 7,16,2 + .ascii "'p'\0" + .byte 7,16,15 + .ascii ": Pauses\0" + .byte 7,17,2 + .ascii "'s'\0" + .byte 7,17,15 + .ascii ": Toggles sound\0" +game_over_line: .byte 12,8,14 + .ascii " GAME OVER! \0" +game_paused_line: .byte 12,8,13 + .ascii " GAME PAUSED! \0" +quit_line: .byte 12,7,9 + .ascii " QUIT? Are you sure? \0" +block: .byte 219,0 +underscore: .ascii "_\0" + +shields_line: .byte 0,21,0 + .ascii "SHIELDS:\0" +score_line: .byte 15,22,0 + .ascii "SCORE:\0" +hiscore_line: .byte 15,22,20 + .ascii "HISCORE:\0" +level_line: .byte 15,23,0 + .ascii "LEVEL:\0" + +high_score_line: .byte 14,7,15 + .ascii "HIGH SCORE\0" + +new_high_line: .byte 13,5,13 + .ascii "NEW HIGH SCORE\0" + .byte 14,7,2 + .ascii "Use the arrows to pick your initials\0" + .byte 14,8,5 + .ascii "Press ENTER when you are done\0" + +hiscore: .long 500 +hi_player: .ascii "KRG\0" + +game_flags: .byte 2 # bit 0 = Previously Paused + # bit 1 = Sound On/Off + # bit 2 = Shield/Score change? + +# timespec for nanosleep +milisecond: .long 0 + .long 1000000 +hundred_microsecond: .long 0 + .long 100000 +# + +# vmw_soft.h +# vmw @ 8,6 +# A VMW Software Production" @ 7,15 + +vmw_sprite: +.byte 23,8 +.byte 0x4,0x4,0x4,0x4,0x4,0x4,0x4,0x2,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x2,0x1,0x1,0x1,0x1,0x1,0x1,0x1 +.byte 0x4,0x4,0x4,0x4,0x4,0x4,0x4,0x2,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x2,0x1,0x1,0x1,0x1,0x1,0x1,0x1 +.byte 0x0,0x4,0x4,0x4,0x4,0x4,0x2,0x2,0x2,0x1,0x1,0x1,0x1,0x1,0x2,0x2,0x2,0x1,0x1,0x1,0x1,0x1,0x0 +.byte 0x0,0x4,0x4,0x4,0x4,0x4,0x2,0x2,0x2,0x1,0x1,0x1,0x1,0x1,0x2,0x2,0x2,0x1,0x1,0x1,0x1,0x1,0x0 +.byte 0x0,0x0,0x4,0x4,0x4,0x2,0x2,0x2,0x2,0x2,0x1,0x1,0x1,0x2,0x2,0x2,0x2,0x2,0x1,0x1,0x1,0x0,0x0 +.byte 0x0,0x0,0x4,0x4,0x4,0x2,0x2,0x2,0x2,0x2,0x1,0x1,0x1,0x2,0x2,0x2,0x2,0x2,0x1,0x1,0x1,0x0,0x0 +.byte 0x0,0x0,0x0,0x4,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x1,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x1,0x0,0x0,0x0 +.byte 0x0,0x0,0x0,0x4,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x1,0x2,0x2,0x2,0x2,0x2,0x2,0x2,0x1,0x0,0x0,0x0 + +# opener.h +# 40x20 +# 0,5 Merciless Marauding Malicious Marketers + +opener_sprite: +.byte 40,20 +.byte 0x9,0x9,0x9,0x0,0x9,0x9,0x9,0x0,0x9,0x0,0x0,0x0,0x9,0x0,0xC,0xC,0x0,0x0,0xC,0xC,0xC,0x0,0xC,0x0,0x0,0x0,0xC,0x0,0xC,0xC,0x0,0x0,0xC,0xC,0x0,0xC,0x0,0x0,0x0,0xC +.byte 0x0,0x9,0x0,0x0,0x9,0x0,0x9,0x0,0x9,0x9,0x0,0x9,0x9,0x0,0xC,0x0,0xC,0x0,0xC,0x0,0xC,0x0,0xC,0xC,0x0,0xC,0xC,0x0,0xC,0x0,0xC,0x0,0xC,0x0,0x0,0xC,0xC,0x0,0xC,0xC +.byte 0x0,0x9,0x0,0x0,0x9,0x0,0x9,0x0,0x9,0x0,0x9,0x0,0x9,0x0,0xC,0xC,0x0,0x0,0xC,0x0,0xC,0x0,0xC,0x0,0xC,0x0,0xC,0x0,0xC,0xC,0x0,0x0,0xC,0xC,0x0,0xC,0x0,0xC,0x0,0xC +.byte 0x0,0x9,0x0,0x0,0x9,0x0,0x9,0x0,0x9,0x0,0x0,0x0,0x9,0x0,0xC,0x0,0xC,0x0,0xC,0x0,0xC,0x0,0xC,0x0,0x0,0x0,0xC,0x0,0xC,0x0,0xC,0x0,0xC,0x0,0x0,0xC,0x0,0x0,0x0,0xC +.byte 0x0,0x9,0x0,0x0,0x9,0x9,0x9,0x0,0x9,0x0,0x0,0x0,0x9,0x0,0xC,0xC,0x0,0x0,0xC,0xC,0xC,0x0,0xC,0x0,0x0,0x0,0xC,0x0,0xC,0xC,0x0,0x0,0xC,0xC,0x0,0xC,0x0,0x0,0x0,0xC +.byte 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0 +.byte 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0x0,0x0,0x0 +.byte 0x0,0x0,0x0,0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xF,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0 +.byte 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0 +.byte 0x0,0x0,0x0,0x0,0x0,0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xF,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0 +.byte 0x0,0x0,0x0,0x0,0x0,0x7,0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xB,0x0,0x0,0x0 +.byte 0x0,0xE,0x0,0x0,0x0,0x7,0x7,0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xB,0x4,0x4 +.byte 0x0,0xE,0xE,0xE,0x9,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0xF,0x9,0x9,0x9,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xB,0xC,0xC +.byte 0xE,0xE,0x4,0xC,0x9,0xF,0x4,0x2,0x9,0x2,0x9,0xF,0xF,0x9,0x9,0x9,0x9,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xB,0x0,0xC,0xC +.byte 0x0,0xE,0xE,0xC,0x9,0xF,0x4,0x2,0x9,0x2,0x9,0xF,0xF,0x9,0x9,0x9,0x9,0x9,0x0,0x0,0x0,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xC,0xC +.byte 0x0,0x0,0x0,0xE,0x9,0x7,0x7,0x7,0x7,0x7,0x7,0x7,0x7,0xF,0xF,0xF,0xF,0xF,0xF,0x0,0x0,0x0,0x0,0xE,0x7,0x7,0x7,0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xC,0xC +.byte 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x4,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xF,0x0,0x0,0x0,0x0,0x4,0x4 +.byte 0x0,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x0,0x0,0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0 +.byte 0x0,0xF,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xF,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x8,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0 +.byte 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0x0 + + +# vince.h +# 16x20 + +vince_sprite: +.byte 16,20 +.byte 0x0,0x0,0x8,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x8,0x0,0x0,0x0,0x0 +.byte 0x0,0x8,0x7,0xf,0xf,0xf,0xf,0x7,0xf,0xf,0xf,0xf,0x7,0x7,0x0,0x0 +.byte 0x8,0x7,0x7,0x7,0x7,0x7,0x8,0x7,0xf,0x7,0x7,0xf,0xf,0xf,0x7,0x0 +.byte 0x7,0x8,0x0,0x8,0x7,0x7,0x7,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x8 +.byte 0x7,0x0,0x8,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x7 +.byte 0x8,0x0,0x7,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x7,0xf,0x7,0x7,0x8,0x8 +.byte 0x8,0x8,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0xf,0x8,0x8,0x0,0x8,0x7 +.byte 0x8,0x7,0xf,0xf,0xf,0xf,0x7,0xf,0xf,0xf,0x7,0x0,0x8,0x0,0x8,0x7 +.byte 0x7,0x8,0x8,0x7,0xf,0x8,0x0,0x8,0x7,0xf,0x7,0x0,0x0,0x0,0x0,0x8 +.byte 0x0,0x7,0x0,0x8,0xf,0x0,0x0,0x8,0x0,0x8,0xf,0x8,0x0,0x0,0x0,0x8 +.byte 0x0,0x7,0x8,0x7,0xf,0x8,0x0,0x0,0x7,0xf,0xf,0x7,0x0,0x0,0x0,0x7 +.byte 0x0,0xf,0x8,0xf,0xf,0xf,0x7,0x7,0xf,0xf,0xf,0xf,0x0,0x0,0x0,0x7 +.byte 0x0,0xf,0x7,0x8,0x8,0x7,0xf,0xf,0xf,0xf,0xf,0x8,0x8,0x8,0x7,0x7 +.byte 0x0,0xf,0xf,0x8,0x0,0x7,0xf,0xf,0xf,0xf,0x7,0x0,0x7,0x7,0x7,0x0 +.byte 0x0,0xf,0xf,0x7,0x8,0x7,0x7,0xf,0xf,0xf,0x7,0x0,0x7,0x7,0x8,0x0 +.byte 0x0,0x7,0x7,0x0,0x8,0x0,0x0,0x7,0x7,0x0,0x0,0xf,0x8,0x7,0x0,0x0 +.byte 0x0,0x8,0xf,0xf,0x8,0xf,0xf,0x7,0x0,0x0,0x8,0x7,0x7,0x8,0x0,0x0 +.byte 0x0,0x0,0xf,0x7,0x7,0x7,0xf,0x7,0x7,0x8,0x8,0xf,0x7,0x0,0x0,0x0 +.byte 0x0,0x0,0x7,0xf,0xf,0xf,0xf,0x8,0x8,0x0,0x8,0xf,0x8,0x0,0x0,0x0 +.byte 0x0,0x0,0x0,0x8,0x8,0x0,0x0,0x0,0x0,0x0,0x7,0xf,0x8,0x0,0x0,0x0 + + +# phobos.h + +# 40x16 + +phobos_sprite: +.byte 40,15 +.byte 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0 +.byte 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf,0x0,0x0,0x0 +.byte 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0 +.byte 0x0,0x0,0x0,0x0,0x0,0x7,0xf,0xf,0xf,0xf,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0 +.byte 0x0,0x0,0x0,0x0,0x4,0xc,0xc,0xc,0xc,0xc,0xc,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0 +.byte 0x0,0x0,0x0,0x4,0xc,0xc,0xc,0xc,0xc,0x4,0xc,0xc,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0 +.byte 0x0,0x0,0x0,0x4,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0 +.byte 0x0,0x0,0x0,0x4,0xc,0xc,0xc,0x4,0xc,0xc,0xc,0xc,0x0,0x0,0x0,0x0,0x0,0x8,0x6,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0 +.byte 0x0,0x0,0x0,0x4,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0x0,0x0,0x0,0x0,0x0,0x6,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0 +.byte 0x0,0x0,0x0,0x4,0xc,0xc,0xc,0xc,0xc,0x4,0xc,0xc,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0xf,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0 +.byte 0x0,0x0,0x0,0x0,0x4,0xc,0xc,0xc,0xc,0xc,0xc,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0 +.byte 0x0,0x0,0x0,0x0,0x0,0x7,0xf,0xf,0xf,0xf,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0 +.byte 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0 +.byte 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0 +.byte 0x0,0x0,0x0,0xf,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0 + + +# 3x1 +evil_ship_sprite: +.byte 3,1 +.byte 0x3,0xb,0x3 + +# tom.h +# 16x18 + +tom_sprite: +.byte 16,18 +.byte 0x0,0x0,0x1,0x1,0x1,0x1,0x1,0x1,0x9,0x9,0x9,0x9,0x0,0x0,0x0,0x0 +.byte 0x0,0x0,0x1,0x1,0x0,0x0,0x0,0x0,0x8,0x8,0x9,0x9,0x0,0x0,0x0,0x0 +.byte 0x0,0x0,0x1,0x1,0x0,0x0,0x0,0x0,0x8,0x8,0x9,0x9,0x0,0x0,0x0,0x0 +.byte 0x0,0x0,0x1,0x1,0x0,0x0,0x0,0x0,0x8,0x8,0x9,0x9,0x0,0x0,0x0,0x0 +.byte 0x0,0x0,0x1,0x1,0x0,0x0,0x0,0x0,0x8,0x8,0x9,0x9,0x0,0x0,0x0,0x0 +.byte 0x0,0x0,0x0,0x0,0x1,0x1,0x1,0x1,0x9,0x9,0x0,0x0,0x0,0x0,0x0,0x0 +.byte 0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x1,0x9,0x9,0x9,0x9,0x9,0x9,0x9,0x9 +.byte 0x1,0x1,0x9,0x9,0x1,0x1,0x1,0x1,0x9,0x9,0xc,0xc,0x1,0x1,0x9,0x9 +.byte 0x1,0x1,0x9,0x9,0x1,0x1,0x1,0x1,0x9,0x9,0x9,0x9,0x1,0x1,0x9,0x9 +.byte 0x1,0x1,0x9,0x9,0x1,0x1,0x1,0x1,0x9,0x9,0x9,0x9,0x1,0x1,0x9,0x9 +.byte 0x1,0x1,0x9,0x9,0x1,0x1,0x1,0x1,0x9,0x9,0x9,0x9,0x1,0x1,0x9,0x9 +.byte 0x1,0x1,0x9,0x9,0x1,0x1,0x1,0x1,0x9,0x9,0x9,0x9,0x1,0x1,0x9,0x9 +.byte 0x3,0x3,0xb,0xb,0x1,0x1,0x9,0x9,0x1,0x1,0x9,0x9,0x3,0x3,0xb,0xb +.byte 0x0,0x0,0x0,0x0,0x1,0x1,0x9,0x9,0x1,0x1,0x9,0x9,0x0,0x0,0x0,0x0 +.byte 0x0,0x0,0x0,0x0,0x1,0x1,0x9,0x9,0x1,0x1,0x9,0x9,0x0,0x0,0x0,0x0 +.byte 0x0,0x0,0x0,0x0,0x1,0x1,0x9,0x9,0x1,0x1,0x9,0x9,0x0,0x0,0x0,0x0 +.byte 0x0,0x0,0x0,0x0,0x3,0x3,0xb,0xb,0x3,0x3,0xb,0xb,0x0,0x0,0x0,0x0 +.byte 0x0,0x0,0x0,0x0,0x8,0x8,0x7,0x7,0x8,0x8,0x7,0x7,0x0,0x0,0x0,0x0 + +# game_sprites.h + +# 8x4 +ship_sprite: +.byte 0x8,0x4 +.byte 0x0,0x0,0x9,0x9,0x9,0x0,0x0,0x0 +.byte 0x0,0x7,0xf,0xf,0xf,0x7,0x0,0x0 +.byte 0x7,0x7,0xf,0x7,0xf,0x7,0x7,0x0 +.byte 0x0,0x0,0x0,0xe,0x0,0x0,0x0,0x0 + + +# 1x3 +missile_sprite: +.byte 0x1,0x3 +.byte 0x7 +.byte 0x7 +.byte 0xe + +# 3x2 +enemy_sprites: + +enemy_sprite0: +.byte 0x3,0x2 +.byte 0xf,0xf,0x4 +.byte 0xf,0xf,0xf + +enemy_sprite1: +.byte 0x3,0x2 +.byte 0x9,0x0,0x9 +.byte 0x0,0x9,0x0 + +enemy_sprite2: +.byte 0x3,0x2 +.byte 0x2,0xa,0x2 +.byte 0x2,0xa,0x2 + +enemy_sprite3: +.byte 0x3,0x2 +.byte 0x3,0x6,0x6 +.byte 0x3,0x6,0x6 + +enemy_sprite4: +.byte 0x3,0x2 +.byte 0x0,0xe,0x0 +.byte 0xe,0x0,0xe + +enemy_sprite5: +.byte 0x3,0x2 +.byte 0xc,0xf,0xf +.byte 0xc,0x7,0x7 + + +explosion_sprites: + +explosion_sprite0: +.byte 0x3,0x2 +.byte 0xe,0xe,0xc +.byte 0xc,0xe,0x8 + +explosion_sprite1: +.byte 0x3,0x2 +.byte 0x7,0x7,0x4 +.byte 0x4,0x7,0x0 + +explosion_sprite2: +.byte 0x3,0x2 +.byte 0x8,0x8,0x0 +.byte 0x0,0x8,0x8 + + +# boss.h + +# 3x2 + +smoke_sprites: + +smoke_sprite0: +.byte 0x3,0x1 +.byte 0x0,0x8,0x0 + +smoke_sprite1: +.byte 0x3,0x1 +.byte 0x8,0x7,0x8 + +smoke_sprite2: +.byte 0x3,0x1 +.byte 0x7,0x4,0x7 + +# 13x3 +boss_sprite: +.byte 0xd,0x3 +.byte 0xf,0x7,0x4,0xc,0xc,0xc,0xc,0xc,0xc,0xc,0x4,0x7,0xf +.byte 0xf,0x8,0x7,0x4,0x4,0x3,0xb,0x3,0x4,0x4,0x7,0x8,0xf +.byte 0xf,0x0,0x8,0x7,0x3,0xb,0xe,0xb,0x3,0x7,0x8,0x0,0xf + + +# 1x2 +laser_sprites: + +laser_sprite0: +.byte 0x1,0x2 +.byte 0xd +.byte 0x5 + +laser_sprite1: +.byte 0x1,0x2 +.byte 0x5 +.byte 0xd + +# ending.h + +# 7x7 +tom_head_sprite: +.byte 0x7,0x7 +.byte 0x0,0x1,0x1,0x1,0x9,0x9,0x0 +.byte 0x0,0x1,0x0,0x0,0x8,0x9,0x0 +.byte 0x0,0x1,0x0,0x0,0x8,0x9,0x0 +.byte 0x0,0x1,0x0,0x0,0x8,0x9,0x0 +.byte 0x0,0x1,0x0,0x0,0x8,0x9,0x0 +.byte 0x0,0x0,0x1,0x1,0x9,0x0,0x0 +.byte 0x1,0x1,0x1,0x1,0x9,0x9,0x9 + + +# 5x6 +earth_sprite: +.byte 0x5,0x6 +.byte 0x0,0x7,0xf,0xf,0x0 +.byte 0x2,0xA,0xA,0x9,0x9 +.byte 0x1,0xA,0x9,0x9,0x9 +.byte 0x1,0x9,0xA,0xA,0x9 +.byte 0x1,0x9,0xA,0x9,0x9 +.byte 0x0,0x7,0xf,0xf,0x0 + +# 19x7 +susie_sprite: +.byte 0x13,0x7 +.byte 0x7,0x7,0x7,0x7,0x7,0x7,0x7,0x7,0x7,0x7,0x7,0x8,0x0,0xf,0xf,0x0,0x7,0x7,0x7 +.byte 0x7,0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x8,0x0,0x0,0x8,0x0,0x0,0x7,0x7 +.byte 0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7 +.byte 0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7 +.byte 0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0x7,0x7 +.byte 0x7,0x7,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x7,0x7,0x7,0x7,0x7 +.byte 0x7,0x7,0x7,0x7,0x8,0x8,0x8,0x7,0x7,0x7,0x7,0x7,0x8,0x8,0x8,0x7,0x7,0x7,0x7 diff --git a/tb_asm/lzss.c b/tb_asm/lzss.c new file mode 100644 index 0000000..7ec9aa4 --- /dev/null +++ b/tb_asm/lzss.c @@ -0,0 +1,320 @@ +/************************************************************** + LZSS.C -- A Data Compression Program + (tab = 4 spaces) +*************************************************************** + 4/6/1989 Haruhiko Okumura + Use, distribute, and modify this program freely. + Please send me your improved versions. + PC-VAN SCIENCE + NIFTY-Serve PAF01022 + CompuServe 74050,1022 +************************************************************** + + WARNING: order of match_position and match_lenght changed! + see lines 178 to 182 + Mofication by + + + Also modified to have N,F,etc, etc to be parameters, not + hard-coded -- vmw + */ + + + +#include +#include +#include +#include + + +#define num_trees 256 + + /* initialize trees */ +void newInitTree(int ring_buffer_size,int binary_search_index, + int *rson, int *dad) { + + int i; + + /* For i = 0 to N - 1, rson[i] and lson[i] will be the right and + left children of node i. These nodes need not be initialized. + Also, dad[i] is the parent of node i. These are initialized to + NIL (= N), which stands for 'not used.' + For i = 0 to 255, rson[N + i + 1] is the root of the tree + for strings that begin with character i. These are initialized + to NIL. Note there are 256 trees. */ + + for (i=ring_buffer_size+1; i<=ring_buffer_size+num_trees; i++) + rson[i] = binary_search_index; + for (i=0; i= 0) { + if (rson[p] != binary_search_index) p = rson[p]; + else { + rson[p] = r; + dad[r] = p; + return; + } + } + + else { + if (lson[p] != binary_search_index) p = lson[p]; + else { + lson[p] = r; + dad[r] = p; + return; + } + } + + for(i = 1; i < match_length_limit; i++) + if ((cmp = key[i] - text_buf[p + i]) != 0) break; + if (i > *match_length) { + *match_position = p; + if ((*match_length = i) >= match_length_limit) break; + } + + } + + dad[r] = dad[p]; + lson[r] = lson[p]; + rson[r] = rson[p]; + dad[lson[p]] = r; + dad[rson[p]] = r; + + if (rson[dad[p]] == p) rson[dad[p]] = r; + else lson[dad[p]] = r; + dad[p] = binary_search_index; /* remove p */ + +} + + /* deletes node p from tree */ +void newDeleteNode(int p, int binary_search_index, + int *dad, int *rson, int *lson) { + + int q; + + if (dad[p] == binary_search_index) return; /* not in tree */ + if (rson[p] == binary_search_index) q = lson[p]; + else if (lson[p] == binary_search_index) q = rson[p]; + else { + q = lson[p]; + if (rson[q] != binary_search_index) { + do { q = rson[q]; } while (rson[q] != binary_search_index); + rson[dad[q]] = lson[q]; + dad[lson[q]] = dad[q]; + lson[q] = lson[p]; + dad[lson[p]] = q; + } + rson[q] = rson[p]; dad[rson[p]] = q; + } + dad[q] = dad[p]; + if (rson[dad[p]] == p) rson[dad[p]] = q; + else lson[dad[p]] = q; + dad[p] = binary_search_index; +} + +int lzss_encode_better(FILE *infile,FILE *header,FILE *outfile, + unsigned char frequent_char, + int ring_buffer_size, int position_length_threshold) { + +// unsigned char frequent_char='#'; +// int ring_buffer_size=1024; /* N */ + int match_length_limit; //=64; /* F */ + /*int position_length_threshold=2; THRESHOLD */ + int binary_search_index=ring_buffer_size; /* NIL */ + int position_bits; //=10; +// int length_bits=16-position_bits; + + unsigned long int codesize = 0; /* code size counter */ + + int i, c, len, r, s, last_match_length, code_buf_ptr; + + unsigned char code_buf[8*2+1], mask; + + unsigned char *text_buf; + + int match_position, match_length; /* of longest match. These are + set by the InsertNode() procedure. */ + int *lson, *rson, *dad; /* left & right children & + parents -- These constitute + binary search trees. */ + + + /* determine stuff from ring_buffer_size */ + /* fake log2 algorithm */ + + i=1; + while (((ring_buffer_size-1)>>i) >=1) { + i++; + }; + + position_bits=i; + match_length_limit=1<<(16-position_bits); +// printf("%i, %i %i %i '%c'\n",ring_buffer_size,position_bits,match_length_limit +// ,position_length_threshold,frequent_char); + + + + + + + /* ring buffer of size N, with extra F-1 + bytes to facilitate string comparison */ + text_buf=calloc(ring_buffer_size+match_length_limit-1,sizeof(unsigned char)); + lson=calloc(ring_buffer_size+1,sizeof(int)); + rson=calloc(ring_buffer_size+num_trees+1,sizeof(int)); + dad=calloc(ring_buffer_size+1,sizeof(int)); + + newInitTree(ring_buffer_size,binary_search_index,rson,dad); /* initialize trees */ + + code_buf[0] = 0; /* code_buf[1..16] saves eight units of code, and + code_buf[0] works as eight flags, "1" representing + that the unit is an unencoded letter (1 byte), + "0" a position-and-length pair (2 bytes). + Thus, eight units require at most 16 bytes of code. */ + code_buf_ptr = mask = 1; + s = 0; + r = ring_buffer_size - match_length_limit; + + if (header!=NULL) { + fprintf(header,".equ FREQUENT_CHAR,'%c'\n",frequent_char); + fprintf(header,".equ N,%i\n",ring_buffer_size); + fprintf(header,".equ F,%i\n",match_length_limit); + fprintf(header,".equ THRESHOLD,%i\n",position_length_threshold); + fprintf(header,".equ P_BITS,%i\n",position_bits); + fprintf(header,".equ POSITION_MASK,%i\n",(0xff>>(8-(position_bits-8)))); + } + if (outfile!=NULL) { + fprintf(outfile,"tb_data_begin:\n"); + } + /* Clear the buffer with any character that will appear often. */ + for(i=0; i<(ring_buffer_size-match_length_limit); i++) + text_buf[i]=frequent_char; + +// printf("%i to %i = %i\n",0,ring_buffer_size-match_length_limit,frequent_char); + +// printf("%i to %i = ",r,r+match_length_limit); + for(len=0; len len) match_length = len; /* match_length + may be spuriously long near the end of text. */ + if (match_length <= position_length_threshold) { + match_length=1; /* Not long enough match. Send one byte. */ + code_buf[0] |= mask; /* 'send one byte' flag */ + code_buf[code_buf_ptr++] = text_buf[r]; /* Send uncoded. */ +// printf("single: %i @ %i\n",text_buf[r],r); + } else { +// printf("pos : %i\tlen : %i\n",match_position,match_length); + + code_buf[code_buf_ptr++] = (unsigned char) match_position; + + + code_buf[code_buf_ptr++] = (unsigned char) + ( ((match_position>>8) & (0xff >> (8-(position_bits-8)))) | + ((match_length-(position_length_threshold+1))<<(position_bits-8)) ); + +// code_buf[code_buf_ptr++] = (unsigned char) +// (((match_position >> 8) & 7) | +// (match_length - (position_length_threshold+1))<<3); + + } + if ((mask <<= 1) == 0) { /* Shift mask left one bit. */ + if (outfile!=NULL) { + fprintf(outfile,"\t.byte\t"); + for(i = 0; i < code_buf_ptr; i++) { /* Send at most 8 units of */ + fprintf(outfile,"%d%c",code_buf[i],(i==code_buf_ptr-1)?'\n':','); + } + } + codesize += code_buf_ptr; + code_buf[0] = 0; code_buf_ptr = mask = 1; + } + last_match_length = match_length; + for (i = 0; i < last_match_length && (c = getc(infile)) != EOF; i++) { + newDeleteNode(s,binary_search_index, + dad,rson,lson); /* Delete old strings and */ + text_buf[s] = c; /* read new bytes */ + if (s < match_length_limit - 1) text_buf[s + ring_buffer_size] = c; /* If the position is + near the end of buffer, extend the buffer to make + string comparison easier. */ + s = (s + 1) & (ring_buffer_size - 1); + r = (r + 1) & (ring_buffer_size - 1); + /* Since this is a ring buffer, increment the position + modulo N. */ + newInsertNode(r,ring_buffer_size,binary_search_index, + match_length_limit,text_buf,rson,lson,dad, + &match_length,&match_position); + /* Register the string in text_buf[r..r+F-1] */ + } + + while (i++ < last_match_length) { /* After the end of text, */ + newDeleteNode(s,binary_search_index, + dad,rson,lson); /* no need to read, but */ + s = (s + 1) & (ring_buffer_size - 1); + r = (r + 1) & (ring_buffer_size - 1); + if (--len) newInsertNode(r,ring_buffer_size,binary_search_index, + match_length_limit,text_buf,rson,lson,dad, + &match_length,&match_position); + /* buffer may not be empty. */ + } + } while (len > 0); /* until length of string to be processed is zero */ + + if (code_buf_ptr > 1) { /* Send remaining code. */ + if (outfile!=NULL) { + fprintf(outfile,"\t.byte\t"); + for(i = 0; i < code_buf_ptr; i++) { + fprintf(outfile,"%d%c",code_buf[i],(i==code_buf_ptr-1)?'\n':','); + } + } + codesize += code_buf_ptr; + } + + if (outfile!=NULL) fprintf(outfile,"tb_data_end:\n"); + free(text_buf); + free(lson); + free(rson); + free(dad); + return codesize; +} diff --git a/tb_asm/lzss.h b/tb_asm/lzss.h new file mode 100644 index 0000000..2d8f3b9 --- /dev/null +++ b/tb_asm/lzss.h @@ -0,0 +1,4 @@ +int lzss_encode(FILE *infile,FILE *outfile); +int lzss_encode_better(FILE *infile,FILE *header,FILE *outfile, + unsigned char frequent_char, + int ring_buffer_size, int position_length_threshold); diff --git a/tb_asm/optimization b/tb_asm/optimization new file mode 100644 index 0000000..aeb42fa --- /dev/null +++ b/tb_asm/optimization @@ -0,0 +1,57 @@ +Chart of size optimization +Using gas 2.11.93.0.2 + +goal = 8192 bytes + +Version Size (bytes) Notes +~~~~~~~~ ~~~~~~~~~~~~~ ~~~~~~ + 0.26 25422 First working version + 0.26 13260 Stripped + 0.27 13172 Removing extraneous spaces from strings + 0.27 11076 Compressed Data Segment + 0.28 8940 Removed ".data" line to force data+text in same segment + 0.28 8668 Using sstrip "super-strip" + 0.29 8656 move get_char to return status in carry flag + 1 byte immediate moves -> push/pop + 0.29 8620 make "blit_219" + 0.29 8592 Optimizing "do_story" routine to remove %bp use + 0.29 8556 Optimize "do_menu" to use lea + 0.29 8544 convert verify_quit to use zero flag result + 0.29 8528 convert check_inside to use carry flag for status + 0.29 8452 move sound_freq to one 32bit value rather than 16 f/d pair + 0.29 8448 optimize high score routines + 0.29 8440 change cmp $0/jl to just js + 0.30 8312 messing with new_game + 0.30 8283 more removal of bx->bp in new_game + 0.30 8231 cheat, have functions called at end of other functions instead have them follow and thus shave the end saving a call + 0.30 8228 remove extraneous phobos_sprite line + 0.30 8193 Messing with jmping midway into functions for code re-use + 0.30 8187 merging the ioctl commands ;) + 0.31 8151 fixing the game to work again, culling unneeded code + 0.32 8174 Added some game balancing stuff bloating it back up a bit + +I am guessing with further code manipulation could get another 100-200 +bytes off. But have become lazy. + +Why optimize for size? It makes you realize how wasteful high level +code is even with optimizing compilers. Also on x86 optimizing for size is +the same from 386 on up. Optimizing for speed is so convoluted you have to +pick a particular generation of processor and even then it takes lots +of tuning because speed can depent on other things such as cache hits. +One nice thing about programs under 8k, they most likely fit in +the icache entirely ;) + +Big lessons here. Function calls are killer! They take up 6 bytes! +Avoid them whenever possible. + +Also, loading 32bit constants is also a pain. Also take 6 bytes! +Not as bad as on RISC where can take up to 8 bytes. Luckily x86 +allows push imm/pop reg to load 8bit constant into 32 bit register +in 3 bytes. + +Doing anything in memory rather than register is at least 6+ bytes! +Not as bad as RISC where you must often load/modify/store (12bytes) +but still a pain. Would possibly be mitigated if more registers +available, but that would probably make code-size bigger to accomodate +extra opcodes [waiting for x86-64 to see]. + diff --git a/tb_asm/sstrip/Makefile b/tb_asm/sstrip/Makefile new file mode 100644 index 0000000..cb4e92e --- /dev/null +++ b/tb_asm/sstrip/Makefile @@ -0,0 +1,11 @@ +# Makefile for sstrip + +ifeq ($(ARCH),) + ARCH = $(shell uname -m) +endif + +sstrip: sstrip.c + gcc -ggdb -Wall -W -DARCHITECTURE=\"asm_elf_$(ARCH).h\" -o sstrip sstrip.c + +clean: + rm -f sstrip *~ *.o diff --git a/tb_asm/sstrip/README b/tb_asm/sstrip/README new file mode 100644 index 0000000..218376c --- /dev/null +++ b/tb_asm/sstrip/README @@ -0,0 +1,40 @@ +sstrip is a small utility that removes the contents at the end of an +ELF file that are not part of the program's memory image. + +Most ELF executables are built with both a program header table and a +section header table. However, only the former is required in order +for the OS to load, link and execute a program. sstrip attempts to +extract the ELF header, the program header table, and its contents, +leaving everything else in the bit bucket. It can only remove parts of +the file that occur at the end, after the parts to be saved. However, +this almost always includes the section header table, and occasionally +a few random sections that are not used when running a program. + +It should be noted that the GNU bfd library is (understandably) +dependent on the section header table as an index to the file's +contents. Thus, an executable file that has no section header table +cannot be used with gdb, objdump, or any other program based upon the +bfd library, at all. In fact, the program will not even recognize the +file as a valid executable. (This limitation is noted in the source +code comments for bfd, and is marked "FIXME", so this may change at +some future date. However, I would imagine that it is a pretty +low-priority item, as executables without a section header table are +rare in the extreme.) This probably also explains why strip doesn't +offer the option to do this. + +Shared library files may also have their section header table removed. +Such a library will still function; however, it will no longer be +possible for a compiler to link a new program against it. + +As an added bonus, sstrip also tries to removes trailing zero bytes +from the end of the file. (This normally cannot be done with an +executable that has a section header table.) + +sstrip is a very simplistic program. It depends upon the common +practice of putting the parts of the file that contribute to the +memory image at the front, and the remaining material at the end. This +permits it to discard the latter material without affecting file +offsets and memory addresses in what remains. Of course, the ELF +standard permits files to be organized in almost any order, so if a +pathological linker decided to put its section headers at the top, +sstrip would be useless on such executables. diff --git a/tb_asm/sstrip/README.MORE b/tb_asm/sstrip/README.MORE new file mode 100644 index 0000000..2e0234e --- /dev/null +++ b/tb_asm/sstrip/README.MORE @@ -0,0 +1,5 @@ +This utility by Brian Raiter +Available at his web-site +http://www.muppetlabs.com/~breadbox/software/elfkickers.html +Included here as per the GPL. + diff --git a/tb_asm/sstrip/asm_elf_RiSC.h b/tb_asm/sstrip/asm_elf_RiSC.h new file mode 100644 index 0000000..5d294ff --- /dev/null +++ b/tb_asm/sstrip/asm_elf_RiSC.h @@ -0,0 +1,3 @@ +#define ELF_CLASS ELFCLASS32 +#define ELF_DATA ELFDATA2LSB +#define ELF_ARCH 0xffff diff --git a/tb_asm/sstrip/asm_elf_alpha.h b/tb_asm/sstrip/asm_elf_alpha.h new file mode 100644 index 0000000..403e169 --- /dev/null +++ b/tb_asm/sstrip/asm_elf_alpha.h @@ -0,0 +1,6 @@ +/* + * These are used to set parameters in the core dumps. + */ +#define ELF_CLASS ELFCLASS64 +#define ELF_DATA ELFDATA2LSB +#define ELF_ARCH EM_ALPHA diff --git a/tb_asm/sstrip/asm_elf_arm.h b/tb_asm/sstrip/asm_elf_arm.h new file mode 100644 index 0000000..8a5a1f1 --- /dev/null +++ b/tb_asm/sstrip/asm_elf_arm.h @@ -0,0 +1,10 @@ +/* + * These are used to set parameters in the core dumps. + */ +#define ELF_CLASS ELFCLASS32 +//#ifdef __ARMEB__ +//#define ELF_DATA ELFDATA2MSB +//#else +#define ELF_DATA ELFDATA2LSB +//#endif +#define ELF_ARCH EM_ARM diff --git a/tb_asm/sstrip/asm_elf_armbe.h b/tb_asm/sstrip/asm_elf_armbe.h new file mode 100644 index 0000000..8a5a1f1 --- /dev/null +++ b/tb_asm/sstrip/asm_elf_armbe.h @@ -0,0 +1,10 @@ +/* + * These are used to set parameters in the core dumps. + */ +#define ELF_CLASS ELFCLASS32 +//#ifdef __ARMEB__ +//#define ELF_DATA ELFDATA2MSB +//#else +#define ELF_DATA ELFDATA2LSB +//#endif +#define ELF_ARCH EM_ARM diff --git a/tb_asm/sstrip/asm_elf_armv5tel.h b/tb_asm/sstrip/asm_elf_armv5tel.h new file mode 100644 index 0000000..8a5a1f1 --- /dev/null +++ b/tb_asm/sstrip/asm_elf_armv5tel.h @@ -0,0 +1,10 @@ +/* + * These are used to set parameters in the core dumps. + */ +#define ELF_CLASS ELFCLASS32 +//#ifdef __ARMEB__ +//#define ELF_DATA ELFDATA2MSB +//#else +#define ELF_DATA ELFDATA2LSB +//#endif +#define ELF_ARCH EM_ARM diff --git a/tb_asm/sstrip/asm_elf_avr32.h b/tb_asm/sstrip/asm_elf_avr32.h new file mode 100644 index 0000000..c7d9d6c --- /dev/null +++ b/tb_asm/sstrip/asm_elf_avr32.h @@ -0,0 +1,7 @@ +/* + * These are used to set parameters in the core dumps. + */ +#define ELF_CLASS ELFCLASS32 +#define ELF_DATA ELFDATA2LSB +//#define ELF_DATA ELFDATA2MSB +#define ELF_ARCH EM_AVR32 diff --git a/tb_asm/sstrip/asm_elf_blackfin.h b/tb_asm/sstrip/asm_elf_blackfin.h new file mode 100644 index 0000000..0ff41b4 --- /dev/null +++ b/tb_asm/sstrip/asm_elf_blackfin.h @@ -0,0 +1,6 @@ +/* + * These are used to set parameters in the core dumps. + */ +#define ELF_CLASS ELFCLASS32 +#define ELF_DATA ELFDATA2LSB +#define ELF_ARCH EM_BLACKFIN diff --git a/tb_asm/sstrip/asm_elf_crisv32.h b/tb_asm/sstrip/asm_elf_crisv32.h new file mode 100644 index 0000000..01407f3 --- /dev/null +++ b/tb_asm/sstrip/asm_elf_crisv32.h @@ -0,0 +1,6 @@ +/* + * These are used to set parameters in the core dumps. + */ +#define ELF_CLASS ELFCLASS32 +#define ELF_DATA ELFDATA2LSB +#define ELF_ARCH EM_CRIS diff --git a/tb_asm/sstrip/asm_elf_frv.h b/tb_asm/sstrip/asm_elf_frv.h new file mode 100644 index 0000000..f40d06e --- /dev/null +++ b/tb_asm/sstrip/asm_elf_frv.h @@ -0,0 +1,6 @@ +/* + * These are used to set parameters in the core dumps. + */ +#define ELF_CLASS ELFCLASS32 +#define ELF_DATA ELFDATA2MSB +#define ELF_ARCH EM_FRV diff --git a/tb_asm/sstrip/asm_elf_h8300.h b/tb_asm/sstrip/asm_elf_h8300.h new file mode 100644 index 0000000..3d04b96 --- /dev/null +++ b/tb_asm/sstrip/asm_elf_h8300.h @@ -0,0 +1,6 @@ +/* + * These are used to set parameters in the core dumps. + */ +#define ELF_CLASS ELFCLASS32 +#define ELF_DATA ELFDATA2MSB +#define ELF_ARCH EM_H8_300 diff --git a/tb_asm/sstrip/asm_elf_i686.h b/tb_asm/sstrip/asm_elf_i686.h new file mode 100644 index 0000000..74c343f --- /dev/null +++ b/tb_asm/sstrip/asm_elf_i686.h @@ -0,0 +1,5 @@ +/* These are used to set parameters in the core dumps. + */ +#define ELF_CLASS ELFCLASS32 +#define ELF_DATA ELFDATA2LSB +#define ELF_ARCH EM_386 diff --git a/tb_asm/sstrip/asm_elf_ia64.h b/tb_asm/sstrip/asm_elf_ia64.h new file mode 100644 index 0000000..e44b218 --- /dev/null +++ b/tb_asm/sstrip/asm_elf_ia64.h @@ -0,0 +1,6 @@ +/* These are used to set parameters in the core dumps. + */ +#define ELF_CLASS ELFCLASS64 +#define ELF_DATA ELFDATA2LSB +#define ELF_ARCH EM_IA_64 + diff --git a/tb_asm/sstrip/asm_elf_m32r.h b/tb_asm/sstrip/asm_elf_m32r.h new file mode 100644 index 0000000..37effc9 --- /dev/null +++ b/tb_asm/sstrip/asm_elf_m32r.h @@ -0,0 +1,7 @@ +/* + * These are used to set parameters in the core dumps. + */ +#define ELF_CLASS ELFCLASS32 +#define ELF_DATA ELFDATA2LSB +//#define ELF_DATA ELFDATA2MSB +#define ELF_ARCH EM_M32R diff --git a/tb_asm/sstrip/asm_elf_m68k.h b/tb_asm/sstrip/asm_elf_m68k.h new file mode 100644 index 0000000..f15efc8 --- /dev/null +++ b/tb_asm/sstrip/asm_elf_m68k.h @@ -0,0 +1,6 @@ +/* + * These are used to set parameters in the core dumps. + */ +#define ELF_CLASS ELFCLASS32 +#define ELF_DATA ELFDATA2MSB +#define ELF_ARCH EM_68K diff --git a/tb_asm/sstrip/asm_elf_microblaze.h b/tb_asm/sstrip/asm_elf_microblaze.h new file mode 100644 index 0000000..46a0cef --- /dev/null +++ b/tb_asm/sstrip/asm_elf_microblaze.h @@ -0,0 +1,8 @@ +/* + * These are used to set parameters in the core dumps. + */ +#define EM_XILINX_MICROBLAZE 0xbaab +#define ELF_ARCH EM_XILINX_MICROBLAZE +#define ELF_CLASS ELFCLASS32 +//#define ELF_DATA ELFDATA2LSB +#define ELF_DATA ELFDATA2MSB diff --git a/tb_asm/sstrip/asm_elf_mips.h b/tb_asm/sstrip/asm_elf_mips.h new file mode 100644 index 0000000..f2844c0 --- /dev/null +++ b/tb_asm/sstrip/asm_elf_mips.h @@ -0,0 +1,8 @@ +/* + * These are used to set parameters in the core dumps. + */ +#define ELF_CLASS ELFCLASS32 +//#define ELF_CLASS ELFCLASS64 +#define ELF_DATA ELFDATA2MSB +//#define ELF_DATA ELFDATA2LSB +#define ELF_ARCH EM_MIPS diff --git a/tb_asm/sstrip/asm_elf_mips64.h b/tb_asm/sstrip/asm_elf_mips64.h new file mode 100644 index 0000000..f2844c0 --- /dev/null +++ b/tb_asm/sstrip/asm_elf_mips64.h @@ -0,0 +1,8 @@ +/* + * These are used to set parameters in the core dumps. + */ +#define ELF_CLASS ELFCLASS32 +//#define ELF_CLASS ELFCLASS64 +#define ELF_DATA ELFDATA2MSB +//#define ELF_DATA ELFDATA2LSB +#define ELF_ARCH EM_MIPS diff --git a/tb_asm/sstrip/asm_elf_mipsel.h b/tb_asm/sstrip/asm_elf_mipsel.h new file mode 100644 index 0000000..936e086 --- /dev/null +++ b/tb_asm/sstrip/asm_elf_mipsel.h @@ -0,0 +1,7 @@ +/* + * These are used to set parameters in the core dumps. + */ +#define ELF_CLASS ELFCLASS32 +//#define ELF_CLASS ELFCLASS64 +#define ELF_DATA ELFDATA2LSB +#define ELF_ARCH EM_MIPS diff --git a/tb_asm/sstrip/asm_elf_mn10300.h b/tb_asm/sstrip/asm_elf_mn10300.h new file mode 100644 index 0000000..bcdc504 --- /dev/null +++ b/tb_asm/sstrip/asm_elf_mn10300.h @@ -0,0 +1,6 @@ +/* + * These are used to set parameters in the core dumps. + */ +#define ELF_CLASS ELFCLASS32 +#define ELF_DATA ELFDATA2LSB +#define ELF_ARCH EM_MN10300 diff --git a/tb_asm/sstrip/asm_elf_parisc.h b/tb_asm/sstrip/asm_elf_parisc.h new file mode 100644 index 0000000..2d84866 --- /dev/null +++ b/tb_asm/sstrip/asm_elf_parisc.h @@ -0,0 +1,8 @@ +/* + * These are used to set parameters in the core dumps. + */ +#define ELF_DATA ELFDATA2MSB +#define ELF_ARCH EM_PARISC + +//#define ELF_CLASS ELFCLASS64 +#define ELF_CLASS ELFCLASS32 diff --git a/tb_asm/sstrip/asm_elf_ppc.h b/tb_asm/sstrip/asm_elf_ppc.h new file mode 100644 index 0000000..f2fe3ad --- /dev/null +++ b/tb_asm/sstrip/asm_elf_ppc.h @@ -0,0 +1,7 @@ +# define ELF_ARCH EM_PPC +# define ELF_CLASS ELFCLASS32 +# define ELF_DATA ELFDATA2MSB + +//# define ELF_ARCH EM_PPC64 +//# define ELF_CLASS ELFCLASS64 +//# define ELF_DATA ELFDATA2MSB diff --git a/tb_asm/sstrip/asm_elf_s390.h b/tb_asm/sstrip/asm_elf_s390.h new file mode 100644 index 0000000..d3a5218 --- /dev/null +++ b/tb_asm/sstrip/asm_elf_s390.h @@ -0,0 +1,7 @@ +/* + * These are used to set parameters in the core dumps. + */ +#define ELF_CLASS ELFCLASS32 +//#define ELF_CLASS ELFCLASS64 +#define ELF_DATA ELFDATA2MSB +#define ELF_ARCH EM_S390 diff --git a/tb_asm/sstrip/asm_elf_sh3.h b/tb_asm/sstrip/asm_elf_sh3.h new file mode 100644 index 0000000..3c38330 --- /dev/null +++ b/tb_asm/sstrip/asm_elf_sh3.h @@ -0,0 +1,7 @@ +/* + * These are used to set parameters in the core dumps. + */ +#define ELF_CLASS ELFCLASS32 +#define ELF_DATA ELFDATA2LSB +//#define ELF_DATA ELFDATA2MSB +#define ELF_ARCH EM_SH diff --git a/tb_asm/sstrip/asm_elf_sparc.h b/tb_asm/sstrip/asm_elf_sparc.h new file mode 100644 index 0000000..4079fee --- /dev/null +++ b/tb_asm/sstrip/asm_elf_sparc.h @@ -0,0 +1,6 @@ +/* + * These are used to set parameters in the core dumps. + */ +#define ELF_ARCH EM_SPARC +#define ELF_CLASS ELFCLASS32 +#define ELF_DATA ELFDATA2MSB diff --git a/tb_asm/sstrip/asm_elf_sparc64.h b/tb_asm/sstrip/asm_elf_sparc64.h new file mode 100644 index 0000000..4079fee --- /dev/null +++ b/tb_asm/sstrip/asm_elf_sparc64.h @@ -0,0 +1,6 @@ +/* + * These are used to set parameters in the core dumps. + */ +#define ELF_ARCH EM_SPARC +#define ELF_CLASS ELFCLASS32 +#define ELF_DATA ELFDATA2MSB diff --git a/tb_asm/sstrip/asm_elf_vax.h b/tb_asm/sstrip/asm_elf_vax.h new file mode 100644 index 0000000..d373256 --- /dev/null +++ b/tb_asm/sstrip/asm_elf_vax.h @@ -0,0 +1,6 @@ +/* These are used to set parameters in the core dumps. + */ +#define ELF_CLASS ELFCLASS32 +#define ELF_DATA ELFDATA2LSB +#define ELF_ARCH EM_VAX + diff --git a/tb_asm/sstrip/asm_elf_x86_64.h b/tb_asm/sstrip/asm_elf_x86_64.h new file mode 100644 index 0000000..a3a16e7 --- /dev/null +++ b/tb_asm/sstrip/asm_elf_x86_64.h @@ -0,0 +1,6 @@ +/* + * These are used to set parameters in the core dumps. + */ +#define ELF_CLASS ELFCLASS64 +#define ELF_DATA ELFDATA2LSB +#define ELF_ARCH EM_X86_64 diff --git a/tb_asm/sstrip/asm_elf_xtensa.h b/tb_asm/sstrip/asm_elf_xtensa.h new file mode 100644 index 0000000..fd85aa3 --- /dev/null +++ b/tb_asm/sstrip/asm_elf_xtensa.h @@ -0,0 +1,8 @@ +/* + * These are used to set parameters in the core dumps. + */ + +# define ELF_DATA ELFDATA2LSB +//# define ELF_DATA ELFDATA2MSB +#define ELF_CLASS ELFCLASS32 +#define ELF_ARCH EM_XTENSA diff --git a/tb_asm/sstrip/sstrip.c b/tb_asm/sstrip/sstrip.c new file mode 100644 index 0000000..6119640 --- /dev/null +++ b/tb_asm/sstrip/sstrip.c @@ -0,0 +1,498 @@ +/* sstrip: Copyright (C) 1999-2001 by Brian Raiter, under the GNU + * General Public License. No warranty. See COPYING for details. + * Various changes by Vince Weaver + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include ARCHITECTURE /* made local as new distros don't have it */ + +#if ELF_CLASS == ELFCLASS32 +#define Elf_Ehdr Elf32_Ehdr +#define Elf_Phdr Elf32_Phdr +#else +#define Elf_Ehdr Elf64_Ehdr +#define Elf_Phdr Elf64_Phdr +#endif + +/* Endianess of the host */ +#if __BYTE_ORDER == __LITTLE_ENDIAN +static int little_endian=1; +#else +static int little_endian=0; +#endif + +static int swap_bytes=0; + +/* The name of the program. + */ +static char const *progname; + +/* The name of the current file. + */ +static char const *filename; + + +/* A simple error-handling function. 0 is always returned for the + * convenience of the caller. + */ +static int err(char const *errmsg) +{ + fprintf(stderr, "%s: %s: %s\n", progname, filename, errmsg); + return 0; +} + +/* A macro for I/O errors: The given error message is used only when + * errno is not set. + */ +#define ferr(msg) (err(errno ? strerror(errno) : (msg))) + +/* readelfheader() reads the ELF header into our global variable, and + * checks to make sure that this is in fact a file that we should be + * munging. + */ +static int readelfheader(int fd, Elf_Ehdr *ehdr) { + errno = 0; + if (read(fd, ehdr, sizeof *ehdr) != sizeof *ehdr) { + return ferr("missing or incomplete ELF header."); + } + + /* Check the ELF signature. + */ + if (!(ehdr->e_ident[EI_MAG0] == ELFMAG0 && + ehdr->e_ident[EI_MAG1] == ELFMAG1 && + ehdr->e_ident[EI_MAG2] == ELFMAG2 && + ehdr->e_ident[EI_MAG3] == ELFMAG3)) { + printf("missing ELF signature."); + exit(0); + } + + /* Compare the file's class and endianness with the program's. + */ + + if (ELF_DATA == ELFDATA2LSB) { /* 2's complement, little endian */ + if (!little_endian) { + fprintf(stderr,"Warning! Host and target endianess don't match!\n"); + swap_bytes=1; + } + } + else if (ELF_DATA == ELFDATA2MSB) { /* 2's complement, big endian */ + if (little_endian) { + fprintf(stderr,"Warning! Host and target endianess don't match!\n"); + swap_bytes=1; + } + } + else { + err("Unknown endianess type."); + } + + if (ELF_CLASS == ELFCLASS64) { + if (sizeof(void *)!=8) err("host!=elf word size not supported"); + } + else if (ELF_CLASS == ELFCLASS32) { + if (sizeof(void *)!=4) err("host!=elf word size not supported"); + } + else { + err("Unknown word size"); + } + + if (ehdr->e_ident[EI_DATA] != ELF_DATA) { + err("ELF file has different endianness."); + } + + if (ehdr->e_ident[EI_CLASS] != ELF_CLASS) { + err("ELF file has different word size."); + } + + /* Check the target architecture. + */ + { unsigned short machine; + machine=ehdr->e_machine; + if (swap_bytes) machine=bswap_16(machine); + + if (machine != ELF_ARCH) { + fprintf(stderr, "Warning! " + "ELF file created for different architecture: %d\n", + ehdr->e_machine); + } + } + + /* Verify the sizes of the ELF header and the program segment + * header table entries. + */ + { short ehsize; + ehsize=ehdr->e_ehsize; + if (swap_bytes) ehsize=bswap_16(ehsize); + + if (ehsize != sizeof(Elf_Ehdr)) { + fprintf(stderr,"Warning! " + "unrecognized ELF header size: %d != %ld\n", + ehdr->e_ehsize,(long)sizeof(Elf_Ehdr)); + } + } + + { + short phentsize; + phentsize=ehdr->e_phentsize; + if (swap_bytes) phentsize=bswap_16(phentsize); + + if (phentsize != sizeof(Elf_Phdr)) { + fprintf(stderr,"Warning! " + "unrecognized program segment header size: %d != %ld\n", + ehdr->e_phentsize,(long)sizeof(Elf_Phdr)); + } + } + + /* Finally, check the file type. + */ + {short e_type; + e_type=ehdr->e_type; + if (swap_bytes) e_type=bswap_16(e_type); + + if (e_type != ET_EXEC && e_type != ET_DYN) { + return err("not an executable or shared-object library."); + } + } + + return 1; +} + +/* readphdrtable() loads the program segment header table into memory. + */ +static int readphdrtable(int fd, Elf_Ehdr const *ehdr, Elf_Phdr **phdrs) { + + size_t size; + + short e_phnum; + + /* should be endian safe, as zero is the same in all endianesses */ + if (!ehdr->e_phoff || !ehdr->e_phnum) { + return err("ELF file has no program header table."); + } + + e_phnum=ehdr->e_phnum; + if (swap_bytes) e_phnum=bswap_16(e_phnum); + + size = e_phnum * sizeof **phdrs; + + if (!(*phdrs = malloc(size))) { + return err("Out of memory!"); + } + + errno = 0; + + if (read(fd, *phdrs, size) != (ssize_t)size) { + return ferr("missing or incomplete program segment header table."); + } + + return 1; +} + +/* getmemorysize() determines the offset of the last byte of the file + * that is referenced by an entry in the program segment header table. + * (Anything in the file after that point is not used when the program + * is executing, and thus can be safely discarded.) + */ +static int getmemorysize(Elf_Ehdr const *ehdr, Elf_Phdr *phdrs, + unsigned long *newsize) +{ + Elf_Phdr *phdr; + unsigned long size, n ,end=0; + int i; + + unsigned long e_phoff; + short e_phnum; + + unsigned long p_offset,p_filesz; + + e_phoff=ehdr->e_phoff; + +#if (ELF_CLASS==ELFCLASS64) + if (swap_bytes) e_phoff=bswap_64(e_phoff); +#else + if (swap_bytes) e_phoff=bswap_32(e_phoff); +#endif + + e_phnum=ehdr->e_phnum; + if (swap_bytes) e_phnum=bswap_16(e_phnum); + + /* Start by setting the size to include the ELF header and the + * complete program segment header table. + */ + size = e_phoff + e_phnum * sizeof *phdrs; + + if (size < sizeof *ehdr) { + size = sizeof *ehdr; + printf("-> Adjusting that to %ld\n",size); + } + + /* Then keep extending the size to include whatever data the + * program segment header table references. + */ + for (i = 0, phdr = phdrs ; i < e_phnum ; ++i, ++phdr) { + /* endian safe as PT_NULL is zero */ + if (phdr->p_type != PT_NULL) { + + p_offset=phdr->p_offset; + p_filesz=phdr->p_filesz; +#if (ELF_CLASS==ELFCLASS64) + if (swap_bytes) { + p_offset=bswap_64(p_offset); + p_filesz=bswap_64(p_filesz); + } +#else + if (swap_bytes) { + p_offset=bswap_32(p_offset); + p_filesz=bswap_32(p_filesz); + } +#endif + + n = p_offset + p_filesz; + if (n > size) + size = n; + end=size; + } + } + + *newsize = size; + return 1; +} + +/* truncatezeros() examines the bytes at the end of the file's + * size-to-be, and reduces the size to exclude any trailing zero + * bytes. + */ +static int truncatezeros(int fd, unsigned long *newsize) +{ + unsigned char contents[1024]; + unsigned long size, n; + + size = *newsize; + do { + n = sizeof contents; + if (n > size) + n = size; + if (lseek(fd, size - n, SEEK_SET) == (off_t)-1) + return ferr("cannot seek in file."); + if (read(fd, contents, n) != (ssize_t)n) + return ferr("cannot read file contents"); + while (n && !contents[--n]) + --size; + } while (size && !n); + + /* Sanity check. + */ + if (!size) + return err("ELF file is completely blank!"); + + *newsize = size; + return 1; +} + +/* modifyheaders() removes references to the section header table if + * it was stripped, and reduces program header table entries that + * included truncated bytes at the end of the file. + */ +static int modifyheaders(Elf_Ehdr *ehdr, Elf_Phdr *phdrs, + unsigned long newsize) +{ + Elf_Phdr *phdr; + int i; + + unsigned long e_shoff; + short e_phnum; + unsigned long p_offset,p_filesz; + + e_shoff=ehdr->e_shoff; +#if (ELF_CLASS==ELFCLASS64) + if (swap_bytes) { + e_shoff=bswap_64(e_shoff); + } +#else + if (swap_bytes) { + e_shoff=bswap_32(e_shoff); + } +#endif + + e_phnum=ehdr->e_phnum; + if (swap_bytes) e_phnum=bswap_16(e_phnum); + + + /* If the section header table is gone, then remove all references + * to it in the ELF header. + */ + if (e_shoff >= newsize) { + ehdr->e_shoff = 0; /* all OK because 0 is endian neutral */ + ehdr->e_shnum = 0; + ehdr->e_shentsize = 0; + ehdr->e_shstrndx = 0; + } + + /* The program adjusts the file size of any segment that was + * truncated. The case of a segment being completely stripped out + * is handled separately. + */ + for (i = 0, phdr = phdrs ; i < e_phnum ; ++i, ++phdr) { + + p_offset=phdr->p_offset; + p_filesz=phdr->p_filesz; +#if (ELF_CLASS==ELFCLASS64) + if (swap_bytes) { + p_offset=bswap_64(p_offset); + p_filesz=bswap_64(p_filesz); + } +#else + if (swap_bytes) { + p_offset=bswap_32(p_offset); + p_filesz=bswap_32(p_filesz); + } +#endif + + if (p_offset >= newsize) { + p_offset = newsize; +#if (ELF_CLASS==ELFCLASS64) + if (swap_bytes) { + phdr->p_offset=bswap_64(p_offset); + } +#else + if (swap_bytes) { + phdr->p_offset=bswap_32(p_offset); + } +#endif + phdr->p_filesz = 0; + } else if (p_offset + p_filesz > newsize) { + p_filesz = newsize - p_offset; +#if (ELF_CLASS==ELFCLASS64) + if (swap_bytes) { + phdr->p_filesz=bswap_64(p_filesz); + } +#else + if (swap_bytes) { + phdr->p_filesz=bswap_32(p_filesz); + } +#endif + + } + } + + return 1; +} + +/* commitchanges() writes the new headers back to the original file + * and sets the file to its new size. + */ +static int commitchanges(int fd, Elf_Ehdr const *ehdr, Elf_Phdr *phdrs, + unsigned long newsize) +{ + size_t n; + unsigned long e_phoff; + short e_phnum; + + e_phnum=ehdr->e_phnum; + if (swap_bytes) e_phnum=bswap_16(e_phnum); + + e_phoff=ehdr->e_phoff; +#if (ELF_CLASS==ELFCLASS64) + if (swap_bytes) { + e_phoff=bswap_64(e_phoff); + } +#else + if (swap_bytes) { + e_phoff=bswap_32(e_phoff); + } +#endif + + + /* Save the changes to the ELF header, if any. + */ + if (lseek(fd, 0, SEEK_SET)) + return ferr("could not rewind file"); + errno = 0; + if (write(fd, ehdr, sizeof *ehdr) != sizeof *ehdr) + return err("could not modify file"); + + /* Save the changes to the program segment header table, if any. + */ + if (lseek(fd, e_phoff, SEEK_SET) == (off_t)-1) { + err("could not seek in file."); + goto warning; + } + n = e_phnum * sizeof *phdrs; + if (write(fd, phdrs, n) != (ssize_t)n) { + err("could not write to file"); + goto warning; + } + + /* Eleventh-hour sanity check: don't truncate before the end of + * the program segment header table. + */ + if (newsize < e_phoff + n) + newsize = e_phoff + n; + + /* Chop off the end of the file. + */ + if (ftruncate(fd, newsize)) { + err("could not resize file"); + goto warning; + } + + return 1; + + warning: + return err("ELF file may have been corrupted!"); +} + +/* main() loops over the cmdline arguments, leaving all the real work + * to the other functions. + */ +int main(int argc, char *argv[]) { + + int fd; + Elf_Ehdr ehdr; + Elf_Phdr *phdrs; + unsigned long newsize; + char **arg; + int failures = 0; + + if (argc < 2 || argv[1][0] == '-') { + printf("Usage: sstrip FILE...\n" + "sstrip discards all nonessential bytes from an executable.\n\n" + "Version 2.0 Copyright (C) 2000,2001 Brian Raiter.\n" + "This program is free software, licensed under the GNU\n" + "General Public License. There is absolutely no warranty.\n"); + return EXIT_SUCCESS; + } + + progname = argv[0]; + + for (arg = argv + 1 ; *arg != NULL ; ++arg) { + + filename = *arg; + + fd = open(*arg, O_RDWR); + if (fd < 0) { + ferr("can't open"); + ++failures; + continue; + } + + if (!(readelfheader(fd, &ehdr) && + readphdrtable(fd, &ehdr, &phdrs) && + getmemorysize(&ehdr, phdrs, &newsize) && + truncatezeros(fd, &newsize) && + modifyheaders(&ehdr, phdrs, newsize) && + commitchanges(fd, &ehdr, phdrs, newsize))) + ++failures; + + close(fd); + } + + return failures ? EXIT_FAILURE : EXIT_SUCCESS; +} diff --git a/tb_asm/tb_asm.ix86.s b/tb_asm/tb_asm.ix86.s new file mode 100644 index 0000000..fbebf75 --- /dev/null +++ b/tb_asm/tb_asm.ix86.s @@ -0,0 +1,3543 @@ +# Tom Bombem in x86 Assmbler version 0.32 +# +# by Vince Weaver +# +# assemble with "as -o tb_asm.o tb_asm.ix86.s" +# link with "ld -o tb_asm tb_asm.o" + + +# GAME CONSTANTS + +.equ SCREEN_WIDTH, 40 +.equ SCREEN_HEIGHT, 24 +.equ BYTES_PER_PIXEL, 2 +.equ NUM_MISSILES, 2 +.equ NUM_ENEMIES, 6 +.equ SCROLL_SPEED, 2 +.equ UP_SHIELDS, 32 +.equ WAVE_SIZE, 16 # power of 2 +.equ WAVES_TILL_BOSS, 6 # plus level*2 + + # from ~/linux/include/asm/unistd.h +.equ SYSCALL_READ, 3 +.equ SYSCALL_WRITE, 4 +.equ SYSCALL_OPEN, 5 +.equ SYSCALL_CLOSE, 6 +.equ SYSCALL_IOCTL, 54 +.equ SYSCALL_FCNTL, 55 +.equ SYSCALL_GETTIMEOFDAY, 78 +.equ SYSCALL_NANOSLEEP, 162 + + # from ~/linux/include/asm/ioctls.h +.equ TCGETS, 0x5401 +.equ TCSETS, 0x5402 + + # from ~/linux/include/asm/fcntl.h +.equ F_GETFL, 3 +.equ F_SETFL, 4 +.equ O_NONBLOCK, 0x0800 +.equ O_RDONLY, 0x000 +.equ O_WRONLY, 0x001 +.equ O_CREAT, 0x040 +.equ O_TRUNC, 0x200 +.equ SIXSIXSIX, 0666 + + + + # from ~/linux/include/asm/termbits.h +.equ C_LFLAG_OFF, 12 +.equ VMIN_OFF, 23 +.equ ICANON, 2 +.equ ECHO, 8 + + # struct offsets +.equ ENEMIES_OUT, 0 +.equ ENEMIES_EXPLODING, 1 +.equ ENEMIES_XADD, 2 +.equ ENEMIES_YADD, 3 +.equ ENEMIES_XMIN, 4 +.equ ENEMIES_XMAX, 5 +.equ ENEMIES_KIND, 6 +.equ ENEMIES_X, 7 +.equ ENEMIES_Y, 9 +.equ ENEMIES_SIZE, 11 + +.equ MISSILE_OUT, 0 +.equ MISSILE_X, 1 +.equ MISSILE_Y, 2 + + + # game_flags bit +.equ PAUSED, 0x01 +.equ SOUND, 0x02 +.equ SOUND_PENDING, 0x04 +.equ PERFECT_SHIELD, 0x08 +.equ PERFECT_ENEMY, 0x10 +.equ PERFECT_SHOT, 0x20 +.equ ALL_THREE, PERFECT_SHIELD|PERFECT_ENEMY|PERFECT_SHOT + +.include "data.header" + + .globl _start +_start: + + ##################################### + # decompress data segment + +# LZSS decompression algorithm implementation +# by Stephan Walter 2002, based on LZSS.C by Haruhiko Okumura 1989 +# optimized some more by Vince Weaver + + # we used to fill the buffer with FREQUENT_CHAR + # but, that only gains us one byte of space in the lzss image. + # the lzss algorithm does automatic RLE... pretty clever + # so we compress with NUL as FREQUENT_CHAR and it is pre-done for us + + + mov $(N-F), %bp # R + mov $tb_data_begin, %esi # %esi points to logo (for lodsb) + mov $DATA_OFFSET, %edi # point to out_buffer + +decompression_loop: + lodsb # load in a byte + + mov $0xff, %bh # re-load top as a hackish 8-bit counter + mov %al, %bl # move in the flags + +test_flags: + cmp $tb_data_end, %esi # have we reached the end? + jge done_decompress # if so, exit + + shr $1, %ebx # shift bottom bit into carry flag + jc discreet_char # if set, we jump to discreet char + +offset_length: + lodsw # get match_length and match_position + mov %eax,%edx # copy to edx + # no need to mask dx, as we do it + # by default in output_loop + + shr $(P_BITS),%eax + add $(THRESHOLD+1),%al + + mov %al,%cl # cl = (ax >> P_BITS) + THRESHOLD + 1 + # (=match_length) + +output_loop: + and $POSITION_MASK,%dh # mask it + mov text_buf(%edx), %al # load byte from text_buf[] + inc %edx # advance pointer in text_buf +store_byte: + stosb # store it + + mov %al, text_buf(%ebp) # store also to text_buf[r] + inc %ebp # r++ + and $(N-1), %bp # mask r + + loop output_loop # repeat until k>j + + or %bh,%bh # if 0 we shifted through 8 and must + jnz test_flags # re-load flags + + jmp decompression_loop + +discreet_char: + lodsb # load a byte + inc %ecx # we set ecx to one so byte + # will be output once + # (how do we know ecx is zero?) + + jmp store_byte # and cleverly store it + +done_decompress: +# end of LZSS code + + + ##################################### + # setup non-echo mode + # + + # ioctl(0,TCGETS,&old_tty) + # AKA tcgetattr(0,&old_tty); + + mov $old_tty,%edx # save values to retstore at end + call tcgetattr + + mov $new_tty,%edx # get values to modify + call tcgetattr + + # turn off "canonical mode" + # by clearing ICANON bit + # new_tty.c_lflag&=~ICANON; + + andl $(~ICANON),(new_tty+C_LFLAG_OFF) + + # turn off "echo mode" + # by clearing ECHO bit + # new_tty.c_lflag&=~ECHO; + + andl $(~ECHO),(new_tty+C_LFLAG_OFF) + + # set minimum number of characters + # to read as 1 + # new_tty.c_cc[VMIN]=1; + + movb $1,(new_tty+VMIN_OFF) + + # apply our new tty values + call tcsetattr # %edx still points to new_tty + + + ################################## + # make stdin non-blocking + # + # use fctl rather than fctl64 + push $SYSCALL_FCNTL # for compatibility (no need of 2GB) + pop %eax + xor %ebx,%ebx # stdin = 0 + push $F_GETFL # we want to get flags + pop %ecx + int $0x80 + + mov %eax,%edx # copy result of GETFL to edx + orw $O_NONBLOCK,%dx # set the NONBLOCK bit + + push $SYSCALL_FCNTL + pop %eax # use fctl again + xor %ebx,%ebx # stdin = 0 + push $F_SETFL # want to set flags this time + pop %ecx + int $0x80 + + ############################### + # clear the framebuffer + + call clear_framebuffer + + ############################### + # clear the screen + + mov $clear_screen,%ecx # send the escape code to clear screen + call write_stdout + + ############################## + # draw VMW logo + + mov $vmw_sprite,%esi # Load in sprite + mov $((0x8<<8)+0x6),%ax # Load in x and y co-ords + call blit_219 + + # put "A VMW Software Production" + # white, x=7, y=15 + mov $vmw_string,%esi + call put_text_line_inline + + call dump_to_screen # dump framebuffer to screen + + push $3 + pop %ecx # Pause 3 seconds + call pause_a_while + + ################################ + # Main Menu Loop + +opening_screen: + + ############################### + # clear the framebuffer + + call clear_framebuffer + + ############################## + # title screen + + mov $opener_sprite,%esi # load the title sprite + xor %eax,%eax # at 0,0 + call blit_219 + # Yellow, title_string,x=0 y=5 + mov $title_string,%esi # Malicious Marketers + call put_text_line_inline + + call dump_to_screen # copy to screen + + ######################### + # pause for 10 seconds + # or less if key pressed + + push $10 + pop %ecx + call pause_a_while + + ######################### + # set variables + + xor %ebp,%ebp # menu-item=0 + + ######################### + # draw attention block + # + + xor %bl,%bl # color = 0 + call put_attention_block + + #################################### + # put the "press F1 for help" string + + mov $menu_help_string,%esi # color grey x=0 y=20 + call put_text_line_inline + + #################################### + # draw the menu + + mov $((5<<16)+(10<<8)+6),%eax # x=10 y=6 + call do_menu + + cmp $0,%bp + jne check_1 + call new_game + jmp opening_screen +check_1: + cmp $1,%bp + jne check_2 + call do_about +check_2: + cmp $2,%bp + jne check_3 + call do_story + jmp opening_screen +check_3: + cmp $3,%bp + jne check_4 + call do_hi_score + call wait_until_keypressed + +check_4: + cmp $4,%bp + jne check_5 + call verify_quit + jnz exit + jmp opening_screen +check_5: + cmp $5,%bp + jne end_handle_lf + call display_help + +end_handle_lf: + jmp opening_screen + + + ################################# + # Exit + ################################# +exit: + + mov $default_colors,%ecx # restore from line-draw mode + call write_stdout + + andb $(~SOUND),game_flags # turn sound off + mov $(750<<16)+125,%ebx # default sound=750Hz 125ms + call play_sound # No way I know of to save/restore + # actual values + + mov $old_tty,%edx # restore the saved tty values + call tcsetattr + + xor %ebx,%ebx # set return value as zero + xor %eax,%eax + inc %eax # put exit syscall number (1) in eax + int $0x80 # and exit + + + + ################################# + # verify quit + ################################# + # zero flag clear if we do want to quit +verify_quit: + + mov $15,%bl + call put_attention_block # put a white attention block + + mov $quit_line,%esi + call put_text_line_inline # put the text + + xor %ebp,%ebp + mov $(5<<24)+(2<<16)+(9<<8)+8,%eax + # offset 5, 2 lines + # at 9,8 + + # slide into do_menu + + + ######################### + # Do menu + ######################### + # ax= x,y dx=label_offset,num_options + # returns %bp=option + # destroys %ecx +do_menu: + push %eax + +write_menu_loop: + xor %ecx,%ecx # clear line counter + pop %eax # restore x,y,label_offset,num_options + push %eax + +do_menu_loop: + mov %eax,%edx + ror $16,%edx # move label_offset,num_options -> dx + + cmp %ecx,%ebp # are we the selected menu? + jne menu_no_arrow # if not, no_arrow + + mov $menu_arrow,%esi # if so, arrow + mov $13,%bh # set text color pink + + jmp write_menu_text + +menu_no_arrow: + mov $menu_blank,%esi # not selected, so blank + mov $5,%bh # set text color purple + +write_menu_text: + mov $14,%bl # yellow arrow + call put_text_xy # write out the arrow or blank + + mov %bh,%bl # swap in text color + + # point to the proper string + + add %dh,%cl + lea menu_new_string(%ecx,%ecx,8),%esi + sub %dh,%cl + + add $5,%ah # text 5 right of arrow + + call put_text_xy # put the text + + inc %al # increment y + sub $5,%ah # restore x + inc %ecx # increment the count + + cmp %dl,%cl # have we shown them all? + jne do_menu_loop # if not, loop + + call dump_to_screen # dump results to screen + +menu_key_loop: + call get_a_char # get a character + jnc menu_check_key # if valid key, check it + call milisec_nanosleep + jmp menu_key_loop + +menu_check_key: + pop %edx # convoluted way + push %edx # to get num_options into %dl + shr $16,%edx + xor %dh,%dh + +check_q: + cmp $'q',%al # are we 'q'? + jne check_h + mov %dx,%bp # if so move to last menu item + dec %bp +check_h: + cmp $'h',%al # are we 'h'? + jne check_i + mov $5,%bp # if so move beyond and + mov $'\n',%al # trigger enter + +check_i: + cmp $'i',%al # are we up? + jne check_m +dec_menu: + sub $1,%bp + jns write_menu_loop # if not, ok + mov %dx,%bp # if so, wrap + dec %bp + jmp write_menu_loop + +check_m: + cmp $'m',%al # are we down? + jne check_j +inc_menu: + inc %bp # move down + cmp %dx,%bp # are we too far? + jne write_menu_loop # if not ok + xor %bp,%bp # if so, wrap + jmp write_menu_loop + +check_j: + cmp $'j',%al # are we right? + je dec_menu # then pretend we are down + +check_k: + cmp $'k',%al # are we left? + je inc_menu # then pretend we are up + +check_LF: + cmp $'\n',%al # check for enter/space + je exit_menu + cmp $'\r',%al + je exit_menu + cmp $' ',%al + je exit_menu + + jmp write_menu_loop # unknown key, loop + +exit_menu: + pop %eax # clean up stack + xor $0,%ebp # set zero flag with result + + ret + + + + + + ###################### + # NEW GAME + ###################### + # + +new_game: + + # re-clear all bss variables to zero + + xor %eax,%eax + mov $(game_vars),%edi + mov $(end_game_vars-game_vars),%ecx + + rep + stosb + + call load_hi_score # load hi_score + + ########################### + # init vars that need to be initialized + + movw $(18<<8),x # ship's x=18 + movb $8,shields # shields start as 8 + movb $1,level # level starts as 1 + + ########################## + # Starting a new level! + +new_level: + call clear_framebuffer # clear screen + + mov $8,%bl + call put_attention_block # put attention block + + mov $menu_blank,%esi + mov $15,%bl + mov $8,%al + mov %bl,%ah + call put_text_xy + mov $menu_blank,%esi + mov $20,%ah + call put_text_xy # clear an opening + + + mov $level_line+3,%esi + mov $16,%ah + call put_text_xy # print "LEVEL:" + + xor %eax,%eax + movb level,%al # Convert level to ascii + mov $level_string,%edi + call num_to_ascii + + mov $level_string,%esi # print level_string + mov $((23<<8)+8),%eax + mov $15,%bl + call put_text_xy + + call dump_to_screen + + push $2 # Pause 2 seconds or until keypress + pop %ecx + call pause_a_while + + ############################## + # set new_level variables + # hackish but decreses code size + + mov $enemies_spawned,%edi + xor %eax,%eax + inc %eax # eax = 1 + stosw # enemies_spawned = 1 + neg %ax # ax=-1 + stosw # current_init_x = -1 + stosb # current_enemy_kind = -1 + push $30 + pop %eax # al=30 + stosb # enemy_wait=30 + xor %eax,%eax # al=0 + +# add $6,%al + + stosb # current_enemy_type=0 + +# xor %eax,%eax + stosb # enemy_wave=0 + + orb $ALL_THREE,game_flags # set the three bonuses to ON + + movb level,%al # mave waves_till_boss + add %al,%al # equal WAVES_TILL_BOSS + 2*level + addb $WAVES_TILL_BOSS,%al + mov %al,waves_till_boss + + ######################## + # RANDOMIZE TIMER + + call randomize_timer + + # Draw the Stars + + xor %eax,%eax # clear eax + + mov $1600,%ecx # clear the background + mov $background,%edi + push %edi + rep + stosb + + mov $100,%ecx # we want to draw 100 stars +draw_stars: + pop %edi # point to "background" + push %edi + push $40 + pop %ebx # move 40 into bx + call random # call rand()%40 (y) + imulb %bl # multiply result by 40 (screen width) + add %eax,%edi # add to background pointer + + call random # call rand()%40 again (x) + add %eax,%edi # add this to background pointer + + push $2 + pop %ebx # call rand()%2 + call random + + add $7,%al # put either light or dark grey star + + stosb # and store it + + loop draw_stars # loop + pop %edi + +main_game_loop: + + ############ + # clear screen + ############ + + call clear_framebuffer # clear the screen + + ########### + # Scroll the Stars + ########### + + mov scroll_frames,%bx # get scroll val from memory + mov scroll,%ax # get scroll value + inc %bx # increment frames + cmp $SCROLL_SPEED,%bx # have we had enough frames to scroll? + jge scroll_it # if so move ahead + mov %bx,scroll_frames # else store scroll back + jmp show_stars # and jump to the stars + +scroll_it: + movw $0,scroll_frames # clear scroll_frames + + sub $40,%ax # decrement it + jns write_scroll # is it less than zero? + mov $(40*40-40),%ax # if so wrap to (40*40-40) +write_scroll: + movw %ax,scroll # store new scroll value to RAM + +show_stars: + mov $background,%esi # background as src + mov $40,%bl # 40 wide + mov $'.',%dl # stars are dots + + cmp $(20*40),%ax # do we have to wrap? + jg half_scroll # if so we need 2 blits + + ######### + # plain 40x20 blit + + add %eax,%esi # else just offset into background + xor %eax,%eax # put at 0,0 + mov $20,%dh # 20 high + + call blit_already_know_xsize_ysize + jmp done_scrolling # done putting stars + +half_scroll: + + ############## + # top half of wrap blit + + add %eax,%esi # offset into background + idiv %bl # divide offset by 40 to get scroll + + push %eax # store this offset + + # scroll=%al + # we want x=0,y=0 + # we want xsize=40,ysize=40-scroll + # we want framebuffer=background+40*scroll + + mov $40,%dh + sub %al,%dh # ysize=40-scroll + + xor %eax,%eax # x=0,y=0 + + call blit_already_know_xsize_ysize + + ################ + # bottom half of wrap bit + + mov $background,%esi # start at top of background + pop %eax # restore scroll value + + # scroll=%al + # we want y=40-scroll + # we want ysize=scroll-20 + + mov %al,%dh + sub $20,%dh # ysize=scroll-20 + + neg %al + add $40,%al # y=40-scroll + xor %ah,%ah # x=0 + + call blit_already_know_xsize_ysize + + +done_scrolling: + + ############# + # Put out new enemies + ############# + + ################################################# + # Keep a count of how close to place enemies + # Don't want all to appear at once + + incb between_enemy_delay # between_enemy_delay++ + movb enemy_wait,%al # get time to wait + cmp %al,between_enemy_delay # is delay>wait? + jne move_enemies # if not, no enemies this frame + + movb $0,between_enemy_delay # reset between_enemy_delay + + ########################### + # See if we want to change the current enemy type + + cmpb $7,current_enemy_type + jne not_boss + movw $1,enemies_spawned # don't keep enemy count w boss +not_boss: + + # each wave is WAVE_SIZE-1. Should we make this random? + + mov enemies_spawned,%ax + test $(WAVE_SIZE-1),%al # See if multiple of 16 + jnz same_enemy_type + + + ############################### + # CHANGE THE ENEMY TYPE + + incw enemies_spawned # if we keep at multiple of 16 + # we have problems if enemy + # not output right away. so inc + + push $6 + pop %ebx + call random + mov %al,current_enemy_type # current_enemy_type=rand()%6 + + incb enemy_wave # increment which wave we are on + + movb waves_till_boss,%al + cmpb %al,enemy_wave # have we reached boss yet? + jl not_boss_yet # if not, no boss yet + + movb $6,current_enemy_type # if so, set type to prepare_for_boss + +not_boss_yet: + + ##################################### + # Set some constants + # These can be over-ridden later? + +set_enemy_constants: + + ################# + # issue speed + + mov $25,%ah # enemy wait standard is 25 + + mov level,%al + dec %al # 1 -> 0 for better math + shl $3,%al + sub %al,%ah # adjust for level + + cmp $5,current_enemy_type + jne check_wait_underflow + sub $10,%ah +check_wait_underflow: + cmp $0,%ah + jge write_out_enemy_wait + xor %ah,%ah + +write_out_enemy_wait: + movb %ah,enemy_wait + + + movb $-1,current_enemy_kind + movw $-1,current_init_x + +same_enemy_type: + + ############################# + # Find an empty enemy slot + + mov $enemy_0,%ebp # point to first enemy + push $NUM_ENEMIES + pop %ecx # loop through all enemies + +find_enemy_slot: + mov %ebp,%esi + lodsb # get enemy[i].out + test $1,%al # is the enemy out? + jz add_enemy # if not keep going + + add $ENEMIES_SIZE,%ebp # move to next enemy struct + loop find_enemy_slot # and loop + + jmp move_enemies + +add_enemy: + + ################## + # first see if need to wait till all enemies gone + # (types 2 and 6 do this) + + cmpb $2,current_enemy_type + jne check_type_6 + + movb total_enemies_out,%al # are total enemies_out >0? + cmp $0,%al + jne move_enemies # if so, wait longer + + + movb $3,current_enemy_type # all gone, so move on to type 3 + + push $6 + pop %ebx + call random + mov %al,current_enemy_kind # current_enemy_kind=rand()%6; + + push $36 + pop %ebx + call random + mov %al,%ah # ah is the significant part + mov %ax,current_init_x # current_init_x=rand()%36 + jmp setup_enemy_defaults + +check_type_6: + cmpb $6,current_enemy_type + jne check_type_7 + + ################ + # before boss stuff + + movb total_enemies_out,%al # are total enemies_out >0? + cmp $0,%al + jne move_enemies # if so, wait longer + + mov $9,%bl + call put_attention_block # put up a text_box + + mov $bonus_points_line,%esi # print bonus point title + call put_text_line_inline + + testb $(ALL_THREE),game_flags # see if we have a bonus + jz no_bonus_at_all + + testb $(PERFECT_SHIELD),game_flags # do we have perfect shields? + jz no_pshield_bonus + + mov $no_shield_line,%esi # if so print message + call put_text_line_inline + addl $1000,score # add 1000 to score + +no_pshield_bonus: + + testb $(PERFECT_ENEMY),game_flags # did we kill all enemies? + jz no_penemy_bonus + + mov $shot_every_line,%esi # if so print message + call put_text_line_inline + addl $5000,score # add 5000 to score + +no_penemy_bonus: + + testb $(PERFECT_SHOT),game_flags # did we never miss a shot? + jz no_pshot_bonus + + mov $perfect_shot_line,%esi # if so, print message + call put_text_line_inline + addl $5000,score # add 5000 to score + +no_pshot_bonus: + jmp done_showing_bonus + +no_bonus_at_all: + mov $no_bonus_line,%esi # print no bonus message + call put_text_line_inline + +done_showing_bonus: + call dump_to_screen + + call wait_long_time + call wait_until_keypressed + + ################# + # setup boss + + mov $boss_x,%edi + xor %eax,%eax + mov $13,%ah + stosw # movw $(13<<8),boss_x + mov $1,%ah + stosw # movw $(1<<8),boss_xadd + + push $40 + pop %ebx + call random + add $10,%ax + stosw # movw %ax,boss_count + + xor %al,%al + stosb # movb $0,boss_smoke + stosb # movb $0,boss_exploding + inc %al + stosb # movb $1,boss_waiting + + mov level,%al + shl $2,%al + add $20,%al + stosb # movb %al,boss_hits + + movb $7,current_enemy_type + movb $20,enemy_wait + jmp move_enemies + +check_type_7: + + # if boss, and he's waiting, don't produce enemies + + cmpb $7,current_enemy_type + jne setup_enemy_defaults + cmpb $0,boss_waiting + jne move_enemies + + + ############################### + # setup enemy defaults +setup_enemy_defaults: + incw enemies_spawned # enemies_spawned++ + incw total_enemies_out # total_enemies_out++; + + mov %ebp,%edi + mov $1,%al + stosb # movb $1,ENEMIES_OUT(%ebp) + # enemies[i].out=1 + xor %al,%al + stosb # movb $0,ENEMIES_EXPLODING(%ebp) + # enemies[i].exploding=0; + + + add $2,%edi # skip xadd,yadd + + stosb # movb $0,ENEMIES_XMIN(%ebp) + # enemies[i].xmin=0; + mov $37,%al + stosb # movb $37,ENEMIES_XMAX(%ebp) + # enemies[i].xmax=37; + + + + ########################################## + # if enemy_kind < 0 then kind=random()%6 + # else use enemy_kind value + + movb current_enemy_kind,%al # get enemy_kind + cmp $0,%al # is it less than 0? + jge no_random_kind # if not move ahead + push $6 + pop %ebx # get rand()%6 + call random +no_random_kind: + stosb # movb %al,ENEMIES_KIND(%ebp) + # enemies[i].kind=enemy_kind + + ###################################### + # if init_x < 0 then x=random()%37 + # else, use the "init_x" value + + movw current_init_x,%ax # get init_x + cmp $0,%ax # is it less than zero? + jge no_random_x # if so skip ahead +random_x: + push $36 + pop %ebx # get random%36 + call random + mov %al,%ah # high byte is significant +no_random_x: + stosw # movw %ax,ENEMIES_X(%ebp) + # store enemies[i].x + xor %eax,%eax + stosw # movw $0,ENEMIES_Y(%ebp) + # enemies[i].y=0; + + + ################################# + # enemy type specific inits + + movb current_enemy_type,%bl + movb level,%dl + shl $4,%dl + cmp $0,%bl + jne enemy_type_1 + + ##################### + # ENEMY_TYPE 0 + # diagonal, no wait, movement proportional to level + +enemy_type_0: + movb %dl,ENEMIES_XADD(%ebp) # xadd = level*8 + movb %dl,ENEMIES_YADD(%ebp) # yadd = level*8 + jmp move_enemies + + ########################## + # ENEMY_TYPE 1 + # Horizontal, then fall. + +enemy_type_1: + sub $1,%bl + jnz enemy_type_3 + + mov $5*8,%al + movb %al,ENEMIES_XADD(%ebp) # enemies[i].xadd=5*8; + + push $100 + pop %ebx + call random + neg %al + movb %al,ENEMIES_YADD(%ebp) # enemies[i].yadd=-(rand()%100); + + jmp move_enemies + + ########################## + # Enemy Type 3 + # type two waits for clear + # then diagonal, all of same type + +enemy_type_3: # skip type 2 + sub $2,%bl + jnz enemy_type_4 + + mov $5*8,%al + movb %al,ENEMIES_XADD(%ebp) # enemies[i].xadd=5; + + movb %dl,ENEMIES_YADD(%ebp) # enemies[i].yadd=level; + + jmp move_enemies + + + ########################### + # Enemy Type 4 + # "wiggle" + +enemy_type_4: + sub $1,%bl + jnz enemy_type_5 + + mov $4*8,%al + movb %al,ENEMIES_XADD(%ebp) # enemies[i].xadd=4; + + movb %dl,ENEMIES_YADD(%ebp) # enemies[i].yadd=level; + + push $34 + pop %ebx + call random + add $2,%al + + movb %al,ENEMIES_XMIN(%ebp) # enemies[i].xmin=2+rand()%34; + shl $8,%ax + movw %ax,ENEMIES_X(%ebp) # enemies[i].x=enemies[i].xmin*8; + + push $20 + pop %ebx + call random + mov %al,%dl + mov ENEMIES_XMIN(%ebp),%al + add %dl,%al + + cmp $35,%al + jle xmax_ok + mov $35,%al + +xmax_ok: + mov %al,ENEMIES_XMAX(%ebp) # enemies[i].xmax=enemies[i].xmin+(rand()%20); + + jmp move_enemies + + ######################### + # Enemy Type 5 + # "rain" + +enemy_type_5: + sub $1,%bl + jnz enemy_type_7 + + push $4 + pop %ebx + call random # get rand()%4 + + test $3,%al # see if bottom two bits 00 + jnz no_use_own_x # ak, one chance in 4 + + mov x,%ax # one chance in 4 use + mov %ax,ENEMIES_X(%ebp) # enemies[i].x=x; + +no_use_own_x: + + movb $0,ENEMIES_XADD(%ebp) # enemies[i].xadd=0; + movb %dl,ENEMIES_YADD(%ebp) # enemies[i].yadd=2; + + jmp move_enemies + + ######################### + # Enemy Type 7 + # things flung by boss + +enemy_type_7: + movb $0,ENEMIES_XADD(%ebp) # enemies[i].xadd=0; + movb %dl,ENEMIES_YADD(%ebp) # enemies[i].yadd=2; + + mov boss_x,%ax + add $5,%ah + mov %ax,ENEMIES_X(%ebp) # enemies[i].x=(boss.x+5)*8; + movw $(3<<8),ENEMIES_Y(%ebp) # enemies[i].y=3*8; + + ####################### + # Move Enemies + ####################### + +move_enemies: + + mov $enemy_0,%ebp # point to first enemy + push $NUM_ENEMIES + pop %ecx # loop through all enemies + +move_enemies_loop: + mov %ebp,%esi + lodsb # get enemy[i].out + test $1,%al # is the enemy out? + jz loop_move_enemies # if so keep looping + +move_enemies_x: + xor %eax,%eax + inc %esi # point to xadd + + lodsb + cmp $0,%al # is it zero? + je move_enemies_y # if so, move along to y + + cbw # sign extend al to ax + addw %ax,ENEMIES_X(%ebp) # enemies[i].x+=enemies[i].xadd + + # check x bounds + + mov ENEMIES_X(%ebp),%dx + cmp ENEMIES_XMAX(%ebp),%dh # is enemies[i].x>enemies[i].xmax? + jg switch_x_dir # if so, switch direction + cmp ENEMIES_XMIN(%ebp),%dh # is enemies[i].x now fall + shl $4,%al # + mov %al,ENEMIES_YADD(%ebp) # enemies[i].yadd=2*level; + movb $0,ENEMIES_XADD(%ebp) # enemies[i].xadd=0; + + jmp ship_enemy_collision_detect + +no_special_case: + + add %ax,ENEMIES_Y(%ebp) # enemies[i].y+=yadd + + cmpb $18,ENEMIES_Y+1(%ebp) # is y>18? + jle ship_enemy_collision_detect # if not move ahead + + decb total_enemies_out # we are off screen. remove + movb $0,ENEMIES_OUT(%ebp) # enemies[i].out=0 + andb $~PERFECT_ENEMY,game_flags + +ship_enemy_collision_detect: + + ########################################## + # Ship <-> Enemies Collision Detection + ########################################## + + cmpb $0,ENEMIES_EXPLODING(%ebp) # if enemy is exploding + jne loop_move_enemies # don't check for collision + + movw x,%ax # check x + mov %ah,%al + add $6,%al # through x+6 + + movw ENEMIES_X(%ebp),%dx # check enemies[i].x + mov %dh,%dl + add $2,%dl # through enemies[i].x+2 + + call check_inside + jnc loop_move_enemies + + mov $16,%ah # check y + mov %ah,%al + add $2,%al # through y+2 + + movw ENEMIES_Y(%ebp),%dx # check enemies[i].y + mov %dh,%dl + add $1,%dl # through enemies[i].y+1 + + call check_inside + jnc loop_move_enemies + + movb $1,ENEMIES_EXPLODING(%ebp) + decb shields + + andb $~PERFECT_SHIELD,game_flags + + movl $(120<<16+50),sound_freq + orb $SOUND_PENDING,game_flags # set_sound(120,50); + +loop_move_enemies: + add $ENEMIES_SIZE,%ebp # move to next enemy struct + sub $1,%ecx # loop, but more than 128 away + jnz move_enemies_loop # so have to do it by hand + + ################### + # Draw the Enemies + ################### + + # Make out,exploding flags? + # out,exploding,kind,x,y + # xadd,yadd,xmin,xmax + + mov $enemy_0,%ebp # point to first enemy + push $NUM_ENEMIES + pop %ecx # loop through all enemies + +draw_enemies: + mov %ebp,%esi + lodsb # get enemy[i].out + test $1,%al # is the enemy out? + jz loop_draw_enemies # if so keep looping + + xor %eax,%eax + lodsb # load "exploding" info + cmp $0,%al + je not_exploding + +handle_exploding: + push %eax + shr $1,%al + # *2 for slow-down reasons) + lea explosion_sprites(,%eax,8),%edx + # base+offset*8 + pop %eax # restore exploding + inc %al # increment exploding + mov %al,ENEMIES_EXPLODING(%ebp) # store back exploding + + cmp $7,%al # is exploding > 7? + jle cont_handle_exploding + + movb $0,0(%ebp) # enemy[i].out=0 + decb total_enemies_out # enemies_out-- + +cont_handle_exploding: + add $5,%esi # skip to enemies_x + jmp enemies_xy + +not_exploding: + xor %eax,%eax + add $4,%esi # skip to kind + lodsb # get kind + lea enemy_sprites(,%eax,8),%edx + # kind muliplied by 8 and added on + +enemies_xy: + lodsw # load xh + lodsb # + lodsb # load yh (little endian) + + mov %edx,%esi # proper sprite + + push %ecx + call blit_219 # actually blit things + pop %ecx + +loop_draw_enemies: + add $ENEMIES_SIZE,%ebp # move to next enemy struct + loop draw_enemies # and loop + + + ########################## + # Draw the Boss + ########################## +draw_the_boss: + + cmpb $7,current_enemy_type # are we at end-of-level boss? + jne done_with_boss # if not skip all this nonsense + + + cmpb $1,boss_exploding # if boss is exploding + je skip_draw_boss # don't draw it + + mov $boss_sprite,%esi + movw boss_x,%ax + xor %al,%al + call blit_219 # blit(boss_sprite,framebuffer,219,boss.x,0,13,3); + +skip_draw_boss: + + ######################## + # Draw Smoke + + cmpb $0,boss_smoke # is the boss smoking? + je skip_draw_smoke # if not skip ahead + + + xor %eax,%eax + movb boss_smoke,%al + shr $2,%al + lea smoke_sprites(%eax,%eax,4),%esi + push %esi + movw boss_x,%ax + add $5,%ah + mov $3,%al + push %eax + call blit # blit(smoke_sprites[boss.smoke/4],framebuffer,219,boss.x+5,3,3,1); + + pop %eax + subw boss_xadd,%ax + mov $4,%al + pop %esi + call blit # blit(smoke_sprites[boss.smoke/4],framebuffer,219,boss.x+5-boss.xadd,4,3,1); + + decb boss_smoke # boss.smoke--; + + +skip_draw_smoke: + + ######################## + # Boss Laser Shoot + + cmpb $0,boss_shooting # is the boss shooting? + je skip_boss_shooting # if not skip ahead + + decb boss_shooting # boss.shooting-- + + xor %eax,%eax + movb boss_shooting,%al # move boss.shooting into %eax + push %eax # saveon stack + + add $200,%ax # add 200 + movw %ax,sound_freq+2 # save as sound_freq + movw $20,sound_freq + orb $SOUND_PENDING,game_flags # set sound to play + + pop %eax # restore boss_shooting + + and $1,%eax # get low bit of boss shooting + lea laser_sprites(,%eax,4),%esi # point to proper laser sprite + + xor %ecx,%ecx # clear ecx counter + +boss_shoot_loop: + + mov boss_x,%ax # get boss_x into ax + mov %cl,%al + shl $1,%al + add $3,%al + + push %eax + push %ecx + push %esi + call blit_219 # blit(laser_sprite[boss.shooting%2],framebuffer,219,boss.x,3+(i*2),1,2); + pop %esi + pop %ecx + pop %eax + + add $12,%ah + push %ecx + push %esi + call blit # blit(laser_sprite[boss.shooting%2],framebuffer,219,boss.x+12,3+(i*2),1,2); + pop %esi + pop %ecx + + add $1,%ecx + cmp $8,%ecx + jl boss_shoot_loop + +skip_boss_shooting: + + ####################### + # boss dead + + cmpb $0,boss_exploding + je boss_is_not_exploding + + movb $1,boss_waiting + + push $30 # 30 random smokes + pop %ecx +big_explosion: + xor %eax,%eax + movb boss_exploding,%al # get exploding amount + shr $3,%al # div 3 + lea smoke_sprites(%eax,%eax,4),%esi # and that much smoke + + push $4 + pop %ebx + call random + mov %al,%dl # y=rand()%4 + + push $11 + pop %ebx + call random + mov %al,%dh # x=rand()%11 + + movw boss_x,%ax + add %dh,%ah # boss_x+x + mov %dl,%al + + push %ecx + push %esi + call blit_219 + pop %esi + pop %ecx + + loop big_explosion + + movl $(120<<16+20),sound_freq + orb $SOUND_PENDING,game_flags # set_sound(120,20); + + decb boss_exploding + + cmpb $0,boss_exploding # are we done exploding? + jne not_dead_yet + + cmpb $1,level # only show ending + jne no_ending # after level1 + + call do_ending +no_ending: + + addl $1000,score # 1000 points for killing boss + + cmpb $7,level + je new_level # can't go past level 7! + + incb level # level++ + + + jmp new_level # start new level + +not_dead_yet: + + jmp move_boss + +boss_is_not_exploding: + + decw boss_count + cmpw $0,boss_count + jge move_boss + + ############################################# + # toggle boss waiting state if count is up + + cmpb $0,boss_waiting + je make_boss_wait +stop_boss_waiting: + movb $0,boss_waiting # boss.waiting=0; + mov $320,%ebx + call random + add $40,%ax + mov %ax,boss_count # boss.count=40+rand()%320; + jmp move_boss + +make_boss_wait: + movb $1,boss_waiting + push $40 + pop %ebx + call random + add $30,%ax + mov %ax,boss_count # boss.count=30+rand()%40; + movb $30,boss_shooting # boss.shooting=30; + +move_boss: + cmpb $0,boss_waiting + jne laser_collision + + movw boss_x,%ax + addw boss_xadd,%ax # boss.x+=boss.xadd; + mov %ax,boss_x + + cmp $26,%ah + jg boss_reverse +boss_under: + cmp $0,%ah + jge laser_collision + +boss_reverse: + negw boss_xadd + addw boss_xadd,%ax + mov %ax,boss_x + +laser_collision: + ####################### + # Collision detection for lasers + + cmpb $0,boss_shooting + je done_with_boss + + movw boss_x,%dx + mov %dh,%dl + + movw x,%ax + mov %ah,%al + add $6,%al + call check_inside + + jc laser_hit + + add $12,%dh + mov %dh,%dl + + movw x,%ax + mov %ah,%al + add $6,%al + call check_inside + + jnc done_with_boss + +laser_hit: + testb $3,boss_shooting + jnz done_with_boss + decb shields # if (boss.shooting%7==0) shields--; + +done_with_boss: + + + + ######################## + # Move the Missiles + ######################## + + mov $missile_0,%ebp # point to first missile + push $NUM_MISSILES + pop %ecx # loop through all missiles + +move_missiles: + mov %ebp,%esi + lodsb # get missile[i].out + test $1,%al # is the missile out? + jz loop_move_missiles # if not keep looping + + lodsb # load x + lodsb # load y + dec %al # y-- + mov %esi,%edi + dec %edi + stosb # store y back out + + cmp $0,%al # is y<0? + jg missile_collision_detection # if not keep going + + andb $(~PERFECT_SHOT),game_flags # not a perfect shot + mov %ebp,%edi # destroy missile + xor %al,%al + stosb + jmp loop_move_missiles + + ################################# + # Missile Collision Detection + +missile_collision_detection: + push %ecx # save missile count + mov MISSILE_X(%ebp),%dh # move missile[i].x -> dh + mov MISSILE_Y(%ebp),%dl # move missile[i].y -> dl + push %edx # save missile info for later + + mov $enemy_0,%ebx + mov $NUM_ENEMIES,%ecx +check_missile_enemy: + cmpb $0,ENEMIES_OUT(%ebx) + je loop_missile_enemy + + cmpb $0,ENEMIES_EXPLODING(%ebx) + jne loop_missile_enemy + + pop %edx # restore missile x,y + push %edx + + mov %dh,%dl # missile x is 1 wide + + movw ENEMIES_X(%ebx),%ax # get enemies x + mov %ah,%al + add $2,%al # enemy x is two wide + call check_inside + jnc loop_missile_enemy + + pop %edx + push %edx + mov %dl,%dh # only check head of missile? + + movw ENEMIES_Y(%ebx),%ax + mov %ah,%al + add $1,%al + call check_inside + jnc loop_missile_enemy + + + # Collision! + + movb $1,ENEMIES_EXPLODING(%ebx) + addl $10,score + + movl $(150<<16+40),sound_freq + orb $SOUND_PENDING,game_flags # set_sound(150,40); + + addb $1,shield_up_count # add 1 to shield bonus count + cmpb $UP_SHIELDS,shield_up_count # have we hit limit? + jl no_shield_bonus # if not move on + + movb $0,shield_up_count # reset shield_up_count to 0 + addb $1,shields # add one to shields + + movl $(220<<16+50),sound_freq + orb $SOUND_PENDING,game_flags # set_sound(220,50); + + cmpb $10,shields # are we greater than 10? + jle no_shield_bonus + movb $10,shields # if so, set to 10 + +no_shield_bonus: + + movb $0,MISSILE_OUT(%ebp) # set missile out to 0 + +loop_missile_enemy: + add $ENEMIES_SIZE,%ebx + dec %ecx + cmp $0,%ecx + jnz check_missile_enemy + + +check_missile_boss: + + pop %edx # missile[i].x,missile[i].y + pop %ecx # missile count + + # Missile <-> Boss Collision Detection + + cmpb $7,current_enemy_type # see if boss is out + jne done_missile_collision + + cmpb $1,boss_exploding # be sure boss is not exploding + je done_missile_collision + + movw boss_x,%ax + mov %ah,%al + add $13,%al + + push %edx + mov %dh,%dl + call check_inside + pop %edx + + jnc done_missile_collision + +check_boss_y: + + xor %eax,%eax + add $2,%al + + mov %dl,%dh + call check_inside + + jnc done_missile_collision + + movl $(150<<16+50),sound_freq + orb $SOUND_PENDING,game_flags # set_sound(150,50); + + movb $0,MISSILE_OUT(%ebp) + movb $11,boss_smoke + + decb boss_hits # decrement hits left + cmpb $0,boss_hits # are we done? + jge done_missile_collision # if not, go on + + movb $23,boss_exploding # start boss exploding + movb $0,boss_shooting # have him stop shooting + + # destroy all extant missiles + + push %ecx + + mov $enemy_0,%ebx # point to first missile + mov $NUM_ENEMIES,%ecx # loop through all missiles +destroy_enemies: + movb $2,ENEMIES_EXPLODING(%ebx) + add $ENEMIES_SIZE,%ebx + loop destroy_enemies + + pop %ecx + +done_missile_collision: + + +loop_move_missiles: + add $3,%ebp + dec %ecx + cmp $0,%ecx + jnz move_missiles + +done_move_missiles: + + + + ######################## + # Draw the Missiles + ######################## + + mov $missile_0,%ebp # point to first missile + push $NUM_MISSILES + pop %ecx # loop through all missiles + +draw_missiles: + mov %ebp,%esi + lodsb # get missile[i].out + test $1,%al # is the missile out? + jz loop_draw_missiles # if so keep looping + + lodsb # load x + shl $8,%ax + lodsb # load y + + mov $missile_sprite,%esi # missile sprite + push %ecx + call blit_219 # actually blit things + pop %ecx + +loop_draw_missiles: + add $3,%ebp # move to next missile struct + loop draw_missiles # and loop + + + ############################# + # Read the keyboard + ############################# + +game_read_keyboard: + + call get_a_char + jc move_ship + +game_q: + cmp $'q',%al # are we 'q'? + jne game_j # if not, move on + + call verify_quit # pop up "sure you want to quit" + jnz done_game # then game over + + jmp set_pause_flag # if not act like paused then cont + +game_j: + cmp $'j',%al # are we "j" [right] ? + jne game_k # if not keep going + + mov xadd,%bx # load in xadd from RAM + cmp $0,%bx # are we less than zero? + jg game_j_0 # if not go ahead + add $(-128),%bx # add -128 to xadd + jmp game_j_done +game_j_0: + xor %ebx,%ebx # switching direction, make xadd 0 +game_j_done: + mov %bx,xadd # store back to RAM + jmp game_read_keyboard # done + + +game_k: + cmp $'k',%al # are we 'k'? [left] + jne game_p # if not move ahead + + mov xadd,%bx # load in xadd from RAM + cmp $0,%bx # are we less than zero? + jl game_j_0 # then changing direction + # set to 0 ( OPT reuse game_j) + + add $(128),%bx # add 128 to xadd + jmp game_j_done # (OPT reuse game_j code) + +game_p: + cmp $'p',%al # did we press 'p'? + jne game_s # if not, move on + + mov $14,%bl # put attention block + call put_attention_block + + mov $game_paused_line,%esi # print "GAME PAUSED!" + + push $1 + pop %ecx + + call text_screen_keypressed_ret + # call put_text_inline + # call dump_to_screen + # call wait_until_keypressed + + + jmp set_pause_flag + +game_s: + cmp $'s',%al # did we press 's'? + jne game_h # if not, move on + xorb $SOUND,game_flags # toggle sound bit + jmp game_read_keyboard + +game_h: + cmp $'h',%al # Did we press 'h'? + jne game_space # if not, move on + call display_help # display help +set_pause_flag: + orb $PAUSED,game_flags # set the "paused" flag + jmp game_read_keyboard + +game_space: + cmp $' ',%al # Did we press ' '? + jne game_unknown # If not, move on + + mov $missile_0,%esi # point to first missile + push $NUM_MISSILES + pop %ecx # loop through all missiles +fire_missiles: + lodsb # get missile[i].out + cmp $0,%al # is it empty? + jne end_fire_loop # if not keep looping + + mov %esi,%edi # point to missile[i].out + dec %edi + mov $1,%al # indicate that it's out + stosb + + mov x,%ax + shr $8,%ax + add $3,%al + stosb # missile[i].x=shipx+3 + + mov $16,%al + stosb # missile[i].y=shipy + + movl $(110<<16+30),sound_freq + orb $SOUND_PENDING,game_flags # set_sound(110,30); + + jmp game_read_keyboard # finished shooting + +end_fire_loop: + add $2,%esi # point to next missile + loop fire_missiles # loop + +game_unknown: + jmp game_read_keyboard + + + ######################## + # move the ship + ######################## + +move_ship: + mov x,%ax # restore x from memory + mov xadd,%bx # restore xadd from memory + + add %bx,%ax # x+=xadd + +check_x_under: + jns check_x_over # if not go ahead + xor %ax,%ax # if under clear x and xadd + xor %bx,%bx +check_x_over: + cmp $33,%ah # are we over 33? + jle blit_ship # if not draw ship + mov $33,%ah # x=33, xadd=0 + xor %bx,%bx +blit_ship: + mov %ax,x # write updated values out to RAM + mov %bx,xadd + + mov $ship_sprite,%esi # load the ship-centric pic + mov $16,%al # x already in ah, 16=y + call blit_219 + + ########################### + # draw the info bar + ########################### + + + cmpb $0,shields # are shields <0? + jl done_game # if so, GAME OVER + + movb $12,shields_line # make SHIELDS line red + jg draw_shields_bar # are we at zero shields? + movb $14,shields_line # if so make SHIELDS line yellow + +draw_shields_bar: + xor %ecx,%ecx # clear count + movb shields,%dl # move shields into dl + mov $21,%al # y=21 + mov $10,%ah # x starts at 10 + +shield_bar_loop: + cmp %dl,%cl # is count greater than shields? + jge shield_empty # if so, put empty + + mov $block,%esi # if not, put a block + + mov $4,%bl # color=dark red + cmp $4,%ecx # if less than 4 + jl draw_shield + + mov $12,%bl # color=light red + cmp $8,%ecx # if 48 + + jmp draw_shield + +shield_empty: + + mov $underscore,%esi # put a dark grey underscore + mov $8,%bl + +draw_shield: + + call put_text_xy # put the char + add $2,%ah # move x over by 2 + + inc %ecx # increment counter + cmp $10,%ecx # are we less than 10? + jne shield_bar_loop # if so keep looping + + + # Should convert to ascii at score changetime + # And not update score string here + + mov $shields_line,%esi # print "SHIELDS:","SCORE:", + push $4 # "HISCORE:","LEVEL:" + pop %ecx + call put_text_inline + + mov score,%eax # Convert score to ascii + mov $score_string,%edi + call num_to_ascii + + mov $score_string,%esi # print score_string + mov $((8<<8)+22),%eax + mov $15,%bl + call put_text_xy + + xor %eax,%eax + movb level,%al # Convert level to ascii + mov $level_string,%edi + call num_to_ascii + + mov $level_string,%esi # print level_string + mov $((8<<8)+23),%eax + mov $15,%bl + call put_text_xy + + mov hiscore,%eax # Convert hiscore to ascii + mov $hiscore_string,%edi + call num_to_ascii + + mov $hiscore_string,%esi # print hiscore_string + mov $((32<<8)+22),%eax + mov $15,%bl + call put_text_xy + + testb $SOUND_PENDING,game_flags # is a sound pending? + jz no_sound_effect # if not, move ahead + andb $~SOUND_PENDING,game_flags # clear sound_pending flag + movl sound_freq,%ebx + call play_sound # play the sound + + +no_sound_effect: + + ################################################# + # Finally draw it all to the screen + ################################################# + + call dump_to_screen + + ################################################## + # Frame limit... keep it at ~30 frames/sec + ################################################## + # Assumes we don't lag more than a second + # Seriously, if we lag more than 10ms we are screwed anyway + +frame_limit: + mov $game_time,%ebx # get current time + call gettimeofday + + mov game_time+4,%ebx # move usecs to %ebx + mov game_old_time,%eax # mov old usecs to %eax + + mov %ebx,%ecx + + sub %eax,%ebx # time delta in %ebx + + cmp $0,%ebx + jge time_no_adjust + add $1000000,%ebx # correct for underflow + +time_no_adjust: + + cmp $30000,%ebx # have we waited 30ms? + jg done_frame_limit # if so, move on + + call hundred_usec_nanosleep # else, sleep a bit + + jmp frame_limit + + +done_frame_limit: + mov %ecx,game_old_time # store as old time + + + testb $PAUSED,game_flags # were we paused? + jz game_not_paused + + andb $(~PAUSED),game_flags # clear PAUSED flag + mov $game_time,%ebx # get current time + call gettimeofday + + mov game_time+4,%ebx # move usecs to %ebx + +game_not_paused: + + ######################## + # LOOP until FINISHED + ######################## + + jmp main_game_loop # LOOP until finished + +done_game: + + ######################## + # GAME OVER + ######################## + + mov $14,%bl # put attention block + call put_attention_block + + mov $game_over_line,%esi # print "GAME OVER!" + call put_text_line_inline + + call dump_to_screen + + call wait_long_time + + ############################# + # Play sad music + + cmpb $0,shields + jg no_bum_bum + + testb $SOUND,game_flags + jz no_bum_bum + + call wait_long_time + + mov $(164<<16+500),%ebx + call play_sound # set_sound(164,500); + + call dump_to_screen + + call wait_long_time + + mov $(130<<16+500),%ebx + call play_sound # set_sound(130,500); + + call dump_to_screen + + jmp show_hi_score + +no_bum_bum: + push $3 + pop %ecx # Pause 3 seconds or until keypress + call pause_a_while + +show_hi_score: + + call clear_framebuffer # clear screen + + mov score,%eax # get score + mov hiscore,%ebx # get hiscore + cmp %ebx,%eax # is score less than hiscore? + jle no_new_hiscore # if so skip ahead + + mov %eax,hiscore # score is the new hiscore + + call new_hi_score + +no_new_hiscore: + call save_hi_score + call do_hi_score # show the hiscore + call wait_long_time + + push $5 + pop %ecx # Pause 5 seconds or until keypress + call pause_a_while + + ret + + + + ###################### + # RANDOMIZE TIMER + ###################### + # We want a seed that is not divisible by 2 or 5 + # to enhance the quality of subsequent pseudo-random + # numbers + ############### + # destroys eax,ebx,ecx,edx + +randomize_timer: + mov $random_seed,%ebx # get current time + call gettimeofday + + mov random_seed,%eax # use seconds since 1970 as seed + + push $5 + pop %ecx # we will be dividing by 5 later + +try_again: + inc %eax # hackish way, but keeps logic simple + # and we only have 50/50 of even anyway + + test $0x1,%al # check if even + jz try_again # if so inc and try again + + xor %edx,%edx # clear out top 32 bits + idivl %ecx # divide edx:eax by 5 + + cmp $0,%edx # check if remainder is zero + je try_again # if so inc by 1 and try again + + and $0xffffff,%eax # we're doing fixed point so + # trim some high-order digits + + mov %eax,random_seed # store back to memory + + ret + + + ###################### + # RANDOM + ###################### + # pseudo-random number generator + ###################### + # bx = mod [aka high range] + # ax returned with random number + +random: + + # The following algorithm from the Hewlett Packard HP-20S + # Scientific Calculator manual, September 1998, p75-76 + # + # The algorithm r = FractionalPart (997r ) + # i+1 i + # + # Where r0 is a starting value between 0 and 1. + # The generator passes the chi-square frequency test for + # uniformity, and serial and run tests for randomness. + # The more significant digits are more random than the + # less significant. If r0 * 10e7 is not divisible + # by 2 or 5 you get 500,000 numbers w/o repeating. + # + # modified to be fixed-point integer only by Vince Weaver + + push %edx + push %ecx + push %ebx + + mov random_seed,%eax # get current seed + + mov $997,%ecx + mull %ecx # multiply by 997 + + and $0xffffff,%eax # keep to ~7 digits + mov %eax,random_seed # store back the seed + + + shr $8,%eax # high order most random + and $0xffff,%eax # we limit random nums to 0-65535 range + + pop %ebx # get high limit + cdq # clear dx + divw %bx # divide by limit + mov %dx,%ax # move remainder to ax + + pop %ecx + pop %edx + + ret + + ######################## + # wait_long_time + ######################## +wait_long_time: + push $5 + pop %ecx +wait_loop: + push %ecx + call inflection_point + pop %ecx + loop wait_loop + ret + + + ######################## + # inflection_point + ######################## + # pause hard, and clear keypresses + # used in a sudden stop of action +inflection_point: + mov $150,%ecx +sleep_250ms: + call milisec_nanosleep + loop sleep_250ms + + # slide in and also + # clear keyboard buffer + + ########################## + # clear_keyboard_buffer + ########################## +clear_keyboard_buffer: + + call get_char + jnc clear_keyboard_buffer + + ret + + + ################################# + # do_ending + ################################# +do_ending: + call wait_long_time # pause a sop up keyboard in case + # still firing keys at boss + + call clear_framebuffer # clear screen + + push $16 # want to write 16 lines of text + pop %ecx + + mov $ending_line,%esi + call put_text_inline + + mov $earth_sprite,%esi # Draw Picture of Earth + mov $(32<<8),%ax + call blit_219 + + # draw picture of Susie + # %esi follows that of earth + mov $(20<<8+15),%ax + call blit + + call dump_to_screen + + call wait_long_time + + call wait_until_keypressed + + call clear_framebuffer + + mov $tom_head_sprite,%esi # put head picture + xor %eax,%eax # at 0,0 + call blit_219 + + + mov $ending_line_2,%esi + + push $2 # put two lines of text + + jmp pop_text_screen_keypressed_ret + + # insane code reuse + # pop %ecx + # call put_text_inline + # call dump_to_screen + # call wait_until_keypressed + # ret + + + ################################# + # do_about + ################################# +do_about: + + call clear_framebuffer + + mov $vince_sprite,%esi # load the ego-centric pic + mov $(24<<8),%eax # at 24,0 + call blit_219 + + mov $about_line_0,%esi + push $15 + + jmp pop_text_screen_keypressed_ret + + # insane code re-use + #pop %ecx + #call put_text_inline + #call dump_to_screen + #call wait_until_keypressed + #ret + + + + ################################# + # do_story + ################################# +do_story: + + call clear_framebuffer + + mov $phobos_sprite,%esi # load the mars pic + xor %eax,%eax # at 0,0 + inc %eax + call blit_219 + + mov $story_line_0,%esi # write the story text + push $3 + pop %ecx + call put_text_inline + + push %esi + call dump_to_screen + pop %esi + + push $8 + pop %ecx + + call pause_a_while # pause for up to 8 seconds + + # esi points at story_line_1 + # saved from before + push $3 + pop %ecx + call put_text_inline + + call dump_to_screen + + push $4 + pop %ecx + call pause_a_while # pause for up to 4 seconds + + mov $(19<<8+9),%ax + push %eax + +phobos_loop: + mov $evil_ship_sprite,%esi # load the evil ship + call blit_219 # and draw it to the screen + + call dump_to_screen + + push $30 + pop %ecx + +phobos_delay: + call milisec_nanosleep # delay 30ms + loop phobos_delay + + mov $menu_blank+2,%esi # erase the ship + pop %eax + push %eax + call put_text_xy + + pop %eax # increment x + inc %ah + push %eax + + cmp $37,%ah # have we reached end of screen? + jne phobos_loop # if not, loop + + pop %eax # restore stack + + push $4 + pop %ecx + call pause_a_while # pause for up to 4 seconds + + call clear_framebuffer + + mov $tom_sprite,%esi # load the tom pic + mov $(24<<8)+1,%eax # at 24,1 + call blit_219 + + mov $story_line_2,%esi # put the tom related story + push $9 + pop %ecx + call put_text_inline + + call dump_to_screen + + push $20 + pop %ecx # pause for up to 20 seconds + + # cheat and slide into + # pause a while + + + ############################ + # Pause a While + ############################ + # ecx = seconds + # +pause_a_while: + mov $time_of_day,%ebx # get starting time + call gettimeofday + + mov (time_of_day),%eax # store usecs in eax + +pause_loop: + push %eax + push %ebx + push %ecx + call get_char + pop %ecx + pop %ebx + pop %eax + jnc pause_end # if keypressed, end + + call milisec_nanosleep # sleep a bit + + mov $time_of_day,%ebx # get current time + call gettimeofday + + mov (time_of_day),%ebx # put usecs in ebx + + sub %eax,%ebx # ebx=new-old + + cmp %ebx,%ecx + jg pause_loop +pause_end: + + ret + + + ###################### + # Help + ###################### + # + +display_help: + call clear_framebuffer + + mov $help_line_0,%esi + push $18 + +pop_text_screen_keypressed_ret: + pop %ecx +text_screen_keypressed_ret: + call put_text_inline + + call dump_to_screen + + # cheat and slide into + # wait until keypressed + + ####################### + # Wait until keypressed + ####################### + # +wait_until_keypressed: + + call get_char + jnc wait_exit + call milisec_nanosleep + jmp wait_until_keypressed + +wait_exit: + ret + + + ################## + # mov_edi_x_y + ################## + # makes edi point to framebuffer + # plus proper x,y offset + # + # ah=x al=y + # %eax,%ecx,%edi destroyed + +mov_edi_x_y: + mov $framebuffer,%edi # point to frame buffer + xor %ecx,%ecx # clear cx + mov %al,%cl # want to offset by y + + cmp $0,%cl # if at x,0 don't offset + je offset_x + +offset_y: + add $(SCREEN_WIDTH*2),%edi # offset by y*2 + loop offset_y + +offset_x: + and $0xffff,%eax # make sure top of eax clear + shr $7,%eax # add in x*2 + add %eax,%edi + + ret + + ################## + # BLIT + ################## + # esi=source + # ah=x al=y + # (for already_know_only) bl=xsize,dh=ysize + # dl=char to write + # destroyed: %eax,%ebx,%ecx,%edx,%edi + +blit_219: + mov $219,%dl + +blit: + push %eax # save x,y + lodsb # get x-size from sprite + mov %al,%bl + lodsb # get y-size from sprite + mov %al,%dh + pop %eax # restore x,y + +blit_already_know_xsize_ysize: + + and $0xff,%ebx # clear high bits of ebx + + call mov_edi_x_y # point edi to proper place in framebuf + +blit_y_loop: + mov %bl,%cl # restore x-size counter + +blit_x_loop: + + lodsb # get color info + cmp $0,%al # is it zero? + jz no_color # if so skip the write + + mov %dl,%ah # get character + stosw # store char/color + jmp check_x + +no_color: + inc %edi # increment pointer + inc %edi +check_x: + loop blit_x_loop # do while x<0 + + add $(SCREEN_WIDTH*2),%edi # move to next line + sub %ebx,%edi # by adding y-size then + sub %ebx,%edi # subtracting x-offset + + sub $1,%dh # decrement y counter + jnz blit_y_loop # if not zero we loop + + ret + + + + + + ##################### + # do_hi_score + ##################### + +do_hi_score: + call load_hi_score # load hi-score from disk + + mov $12,%bl # color light-red + call put_attention_block # put an attention block + + mov $high_score_line,%esi # write "HIGH SCORE" + call put_text_line_inline + + mov $hiscore_buffer,%edi # point to temp buffer + mov $' ',%al # space + stosb + + mov $hi_player,%esi # put the high-players name + mov $3,%ecx + rep + movsb + + mov $' ',%al # pad with ' ' + stosb + stosb + + mov hiscore,%eax # Convert hiscore to ascii + call num_to_ascii + mov $' ',%ax + stosw + + mov $hiscore_buffer,%esi # point to buffer again + mov $15,%bl # white + mov $9,%al # y=9 + + mov $40,%ah # Center... start with 40 + mov %esi,%edx +strlen: + cmp $0,0(%edx) # repeat till end + je done_strlen + inc %edx + dec %ah # subtracting from the 40 + + jmp strlen +done_strlen: + shr $1,%ah # divide by 2 + + call put_text_xy # put hiscore name/score + + # cheat and slide into + # dump_to_screen + + + ################## + # dump_to_screen + ################## + # eax,ebx,ecx,edx,esi,edi trashed + # ebp= ^[ + # eax = scratch + # bl = block_mode + # dl = old_color + # dh = ysize + # ecx = xsize + +dump_to_screen: + push %ebp # we save ebp + + mov $framebuffer,%esi # setup pointers + mov $out_buffer,%edi + + mov $('['<<8+27),%bp # store ^[[ as it will be useful later + + + # write ^[[0;0H to home the cursor + mov %ebp,%eax + stosw + mov $( ('H'<<24)+('0'<<16)+ (';'<<8)+('0')),%eax + stosl + + xor %bl,%bl # set block_mode + mov $17,%dl # set old_color + + mov $(SCREEN_HEIGHT),%dh # load in y size + +dump_y_loop: + push $SCREEN_WIDTH + pop %ecx # restore x size +dump_x_loop: + + lodsw # load ascii/color + + cmp %dl,%al # compare to current color + je blit_block # if the same, skip ahead + + mov %al,%dl # store color as old_color + + push %eax # save ascii/color on stack + + mov %ebp,%eax + stosw # print ^[[ + + mov %dl,%al # restore color + + shr $3,%al # get intensity bit + add $0x30,%al # convert to ascii + stosb # store + + mov %dl,%ah # restore color + and $7,%ah # mask off intensity bit + + # swap bits 3 and 1 + # we use rgb, ansi does bgr. annoying + # There's probably a better way. + # Maybe a lookup table? + xor %al,%al + rcr $1,%ah + rcl $1,%al + + rcr $1,%ah + rcl $1,%al + + rcr $1,%ah + rcl $1,%al + + add $0x30,%al # convert to ascii + + mov $'m',%ah # tack on trailing m + + shl $16,%eax + mov $(('3'<<8)+';'),%ax + + stosl # finish writing out color + + pop %eax # restore ascii/color + +blit_block: + cmp $219,%ah # are we the block char? + jne regular_char # if not skip ahead + + cmp $1,%bl # are we in block mode? + je change_block_zero # if yes, skip ahead + + mov $14,%al # switch to vt102 line-draw mode + stosb # with ^N + mov $1,%bl # set block mode flag + +change_block_zero: + mov $'0',%ah # 0 = block in vt102 line-draw + jmp blit_char + +regular_char: + cmp $1,%bl # are we in block mode? + jne blit_char # if we aren't, skip ahead + + push %eax # switch to normal mode + mov $15,%al # with ^O + stosb + xor %bl,%bl # clear block mode flag + pop %eax + +blit_char: + shr $8,%ax # write out the ascii char + stosb + +blit_char_done: + + loop dump_x_loop # loop until x done + + mov $10,%al # write a line-feed + stosb + + sub $1,%dh # loop until y done + jnz dump_y_loop + + mov $0,%al # store terminating 0 char + stosb + + mov $out_buffer,%ecx # write to stdout + + pop %ebp + + # hijack our way into + # write_stdout + + + + ################################# + # WRITE_STDOUT + ################################# + # ecx has string + # eax,ebx,ecx,edx trashed +write_stdout: + + cdq # clear edx (depends on high bit + # of eax being 0) + +str_loop1: + inc %edx + cmpb $0,(%ecx,%edx) # repeat till zero + jne str_loop1 + +write_stdout_dx_set: + + push $SYSCALL_WRITE # put 4 in eax (write syscall) + pop %eax # in 3 bytes of code + + xor %ebx,%ebx # put 1 in ebx (stdout) + inc %ebx # in 3 bytes of code + + int $0x80 # run the syscall + + ret + + + + + ######################### + # Clear Framebuffer + ######################### + # eax,ecx,edi trashed + +clear_framebuffer: + xor %eax,%eax + mov $' ',%ah # clear with black spaces + mov $framebuffer,%edi + mov $(SCREEN_WIDTH*SCREEN_HEIGHT),%ecx + rep + stosw + ret + + ############################ + # gettimeofday() + ############################ + # ebx points to buffer +gettimeofday: + push %eax + push %ecx + push $SYSCALL_GETTIMEOFDAY + pop %eax + xor %ecx,%ecx # NULL timezone + int $0x80 # run the syscall + pop %ecx + pop %eax + ret + + ########################### + # nanosleep() + ########################### + # time to sleep in buffer pointed by ebx + +milisec_nanosleep: + push %ebx + mov $milisecond,%ebx + jmp mid_nanosecond + +hundred_usec_nanosleep: + push %ebx + mov $hundred_microsecond,%ebx +mid_nanosecond: + call nanosleep + pop %ebx + ret + +nanosleep: + push %eax + push %ecx + push $SYSCALL_NANOSLEEP + pop %eax + # ebx=req or &time_we_want_to_sleep + xor %ecx,%ecx # ecx=rem or &remainder (if interrupted) + int $0x80 # run the syscall + pop %ecx + pop %eax + ret + + ############################ + # tcgetattr + ############################ + # pointer to result in edx + # eax,ebx,ecx trashed +tcgetattr: + mov $TCGETS,%ecx + jmp do_ioctl + + + ############################ + # tcsetattr + ############################ + # pointer to parameters in edx + # eax,ebx,ecx trashed +tcsetattr: + mov $TCSETS,%ecx # TCSETS (or SNDCTL_TMR_TIMEBASE :( ) +do_ioctl: + push $SYSCALL_IOCTL + pop %eax # someone set up us the ioctl + xor %ebx,%ebx # STDIN + int $0x80 # syscall! + ret + + + + ############################# + # put_text_inline + ############################# + # esi = data + # ecx = number of strings + # + # first color, then y, then x, then string + +put_text_line_inline: + push $1 # convenience function + pop %ecx # for those only wanting 1 line of text +put_text_inline: + lodsb # get color + mov %al,%bl + lodsw # then get x,y + call put_text_xy + loop put_text_inline + ret + + + ############################# + # put_text_xy + ############################# + # esi = string + # ah=x al=y + # bl=color + + # ebx trashed esi points to end of string + +put_text_xy: + push %eax + push %ecx # edi_x_y destroys this + call mov_edi_x_y # point to x,y in framebuffer + pop %ecx +p_loop: + lodsb # load char + cmp $0,%al # is it zero? + je p_done # if so we are done + + push %eax + mov %bl,%al # output color + stosb + pop %eax + stosb # output character + jmp p_loop +p_done: + pop %eax + ret + + ####################### + # get_char + ####################### + # + # returns char in al. carry set if invalid + # eax,ebx,ecx,edx all trashed + +get_char: + + push $SYSCALL_READ + pop %eax + xor %ebx,%ebx # stdin + mov $in_char,%ecx # in_char + push $1 + pop %edx # try to read 1 byte + int $0x80 + + cmp $1,%eax + jl no_char + + movb (in_char),%al + clc + ret +no_char: + stc + ret + + + ####################### + # get_a_char + ####################### + # cooks up get_char for arrows and F keys + # carry set it invalid, or cooked char in al + +get_a_char: + call get_char # grab a character + jc get_a_char_unknown + + cmp $27,%al # see if escape + jne get_a_char_over # if not we are done + + call get_char # get another character + jnc extended_char + + mov $'q',%al # if was just esc return q + jmp get_a_char_over + +extended_char: + cmp $'[',%al # check if was ^[[ + jne get_a_char_unknown + + call get_char # get yet another character + jc get_a_char_unknown +check_up: + cmp $'A',%al + jne check_down + mov $'i',%al + jmp get_a_char_over + +check_down: + cmp $'B',%al + jne check_right + mov $'m',%al + jmp get_a_char_over + +check_right: + cmp $'C',%al + jne check_left + mov $'k',%al + jmp get_a_char_over + +check_left: + cmp $'D',%al + jne check_f1 + mov $'j',%al + jmp get_a_char_over + +check_f1: + cmp $'[',%al + jne get_a_char_unknown + call get_char # get yet _another_ char + jc get_a_char_unknown + cmp $'A',%al + jne get_a_char_unknown + mov $'h',%al + jmp get_a_char_over +get_a_char_over: + clc + ret + +get_a_char_unknown: + stc + ret + + + + + ####################### + # put_attention_block + ####################### + # color is in bl + +put_attention_block: + push $5 + pop %eax # x=0 y=5 + call mov_edi_x_y + + mov $'*',%ah + mov %bl,%al + + mov $(40*7),%ecx + + rep + stosw + + ret + + + #################### + # num_to_ascii + #################### + # eax = value to print + # edi points to where we want it + # ebx,ecx,edx trashed + + +num_to_ascii: + push $10 + pop %ebx + xor %ecx,%ecx # clear ecx + div_by_10: + cdq # clear edx + div %ebx # divide + push %edx # save for later + inc %ecx # add to length counter + or %eax,%eax # was Q zero? + jnz div_by_10 # if not divide again + +write_out: + pop %eax # restore in reverse order + add $0x30, %al # convert to ASCII + stosb # save digit + loop write_out # loop till done + ret + + ########################## + # check_inside + ########################## + # see if line dh -> dl ovelaps bigger line ah -> al + # used as half of 2d rectangular collision detection + # carry flag set if true, unset if not +check_inside: + + cmp %ah,%dl + jl ar_not_in + cmp %al,%dl + jle inside +ar_not_in: + cmp %ah,%dh + jl outside + cmp %al,%dh + jg outside +inside: + stc + ret +outside: + clc + ret + + + ######################## + # play_sound + ######################## + # ebx=freq(hertz) / duration (ms) +play_sound: + + ########################## + # To set frequency + # ESC[10;FFF] where FFF=frequency in hertz + ###################### + # To set duration + # ESC[11;DDD] where DDD = Duration + + mov $sound_buffer,%edi + push $'0' + pop %ecx + +freq_loop: + mov %cl,%al + shl $24,%eax + add $('1'<<16 + '['<<8 + 27),%eax + stosl + + mov $';',%al + stosb + + xor %eax,%eax + ror $16,%ebx + mov %bx,%ax + + push %ebx + push %ecx + call num_to_ascii + pop %ecx + pop %ebx + + mov $']',%al + stosb + + inc %cl + cmp $'2',%cl + jne freq_loop + + testb $SOUND,game_flags # Check if sound on + jz no_bell + + + ################## + # and ^G is BEL as always + mov $7,%al + stosb +no_bell: + xor %al,%al + stosb # NUL string termination + + mov $sound_buffer,%ecx + + jmp write_stdout # cheat and jmp instead of call + # write_stdout will ret for us + + + + + ######################### + # Load Hi Score + ######################### + # +load_hi_score: + + call check_existing_hi_score + + jnc done_load_hiscore # if invalid/no file, jump ahead + + btl $29,%eax # is 4th char "S" or "s"? + jc hiscore_clear_sound # if "s" we turn off sound + +hiscore_set_sound: + orb $SOUND,game_flags # and turn on sound + jmp hiscore_get_initials + +hiscore_clear_sound: + andb $(~SOUND),game_flags # and turn off sound +hiscore_get_initials: + + movl hiscore_buffer+4,%eax # get 4 bytes + movl %eax,hi_player # first 3 are initials + + movl hiscore_buffer+8,%eax # get next 4 bytes + movl %eax,hiscore # which is 32 bit int + +done_load_hiscore: + ret + + + ##################### + # Check Existing Hi Score + ##################### + # cf=1 if valid previously existing file + # cf=0 file problem + # dl=0 file not found + # d1=1 file_invalid + +check_existing_hi_score: + + push $SYSCALL_OPEN + pop %eax + mov $score_file,%ebx # "/tmp/tb_asm.hsc" + xor %ecx,%ecx # 0 = O_RDONLY + cdq # clear edx + int $0x80 + + cmp $0,%eax # see if fd opened + jl file_not_found # if not, exit + + mov %eax,%ebx # move fd to %ebx + + push $SYSCALL_READ # read + pop %eax + mov $hiscore_buffer,%ecx # into hiscore_buffer + mov $12,%dx # 12 bytes + int $0x80 + + push %eax + + call close_file # close the file + + pop %eax + + cmp $12,%eax # did we read 12 bytes? + jne invalid_file # if not, invalid + + movl hiscore_buffer,%eax # get first 4 bytes into eax + cmp $('b'<<8 + 't'),%ax # are first 2 chars "tb"? + jne invalid_file # if not, close + + stc # valid file + ret + +file_not_found: + xor %dl,%dl # file_not_found + jmp file_done +invalid_file: + mov $1,%dl # invalid file +file_done: + clc # file problem + ret + + + ############################### + # New High Score + ############################### + # + +new_hi_score: + + mov $9,%bl + call put_attention_block # make a bright blue attention block + + mov $new_high_line,%esi # output the high score directions + push $3 + pop %ecx + call put_text_inline + + xor %edx,%edx # we use dx as a counter + movl $('A'<<16+'A'<<8+'A'),hi_player + # clear the hi-score initials + + hiscore_loop: + mov $menu_blank,%esi # clear the initials line + mov $15,%bl + mov $17,%ah + mov $10,%al + push %esi + call put_text_xy + + pop %esi # clear the pointer line + inc %al # y=11 + call put_text_xy + + mov $hi_player,%esi # put the initials + inc %ah # x=18 + dec %al # y=10 + call put_text_xy + + mov $menu_pointer,%esi # "^" + mov %dl,%ah # dl is x + add $18,%ah + inc %al # y=11 + call put_text_xy + + push %edx + call dump_to_screen # print to screen + pop %edx + +hiscore_get_char: + call hundred_usec_nanosleep # sleep so don't use all CPU + push %edx + call get_a_char # call get_a_char + pop %edx + + jc hiscore_get_char # then loop + +hiscore_k: + cmp $'k',%al # were we a right? + jne hiscore_j # if not move on + + inc %dl # x++ + cmp $2,%dl # is x > 2? + jle hiscore_loop # if not keep going + mov $0,%dl # otherwise wrap so x=0 + +hiscore_j: + cmp $'j',%al # are we left? + jne hiscore_i # if not move on + + sub $1,%dl # x-- + # is x < 0? + jns hiscore_loop # if not keep going + mov $2,%dl # otherwise wrap so x=2 + +hiscore_i: + cmp $'i',%al # are we up? + jne hiscore_m # if not move on + + movb hi_player(%edx),%bl # get initial + dec %bl # decrement + cmp $64,%bl # are we less than '@'? + jge write_initial + mov $126,%bl # if so wrap to '~' +write_initial: + movb %bl,hi_player(%edx) # write back inital + jmp hiscore_loop + +hiscore_m: + cmp $'m',%al # are we down? + jne hiscore_enter # if not, move on + + movb hi_player(%edx),%bl # get initial + inc %bl # incrememnt it + cmp $126,%bl # are we > "~"? + jle write_initial + mov $64,%bl # if so wrap to "@" + jmp write_initial + +hiscore_enter: + cmp $'\n',%al # once we hit enter we are done + jne hiscore_loop + + ret + + ###################### + # Save Hi Score + ###################### + # also saves sound on/off + +save_hi_score: + call check_existing_hi_score + jc ok_to_write + + cmp $1,%dl # we won't write if invalid file + je done_save_hi # we will if ours, or not there + +ok_to_write: + + push $SYSCALL_OPEN + pop %eax + mov $score_file,%ebx # "/tmp/tb_asm.hsc" + mov $(O_WRONLY|O_CREAT|O_TRUNC),%ecx + mov $(SIXSIXSIX),%edx + int $0x80 + + cmp $0,%eax # see if fd opened + jl done_save_hi # if not, exit + + mov %eax,%ebx # save fd + + movl $('s'<<24+'a'<<16+'b'<<8+'t'),%eax + + testb $SOUND,game_flags + jz no_save_sound + btrl $29,%eax +no_save_sound: + + mov %eax,hiscore_buffer + movl hi_player,%eax + mov %eax,hiscore_buffer+4 + movl hiscore,%eax + mov %eax,hiscore_buffer+8 + + push $SYSCALL_WRITE # put 4 in eax (write syscall) + pop %eax # in 3 bytes of code + + mov $hiscore_buffer,%ecx + mov $12,%edx + + int $0x80 # run the syscall + + # cheat and run into close_file + + + ##################### + # Close File + ##################### + # fd=ebx + +close_file: + push $SYSCALL_CLOSE # close the file + pop %eax + int $0x80 +done_save_hi: + ret + + + +################################################ +# DATA SEGMENT +################################################ + +# .data + +.include "data.labels" +data_compressed: +.include "data.lzss" + + +################################################## +# BSS SEGMENT +################################################## + +#.bss +.lcomm text_buf, (N+F-1) +.lcomm DATA_OFFSET, TB_DATA_SIZE + + # +1 for any wrap-around blits +.lcomm framebuffer, SCREEN_WIDTH*(SCREEN_HEIGHT+1)*BYTES_PER_PIXEL +.lcomm out_buffer, SCREEN_WIDTH*(SCREEN_HEIGHT+5)*10 + +.lcomm sound_buffer, 12 +.lcomm sound_freq, 4 + +.lcomm hiscore_buffer, 16 + +.lcomm in_char, 1 + +.lcomm random_seed, 8 + +.lcomm old_time, 8 +.lcomm time_of_day, 8 + +.lcomm game_old_time, 8 +.lcomm game_time, 8 + + +.lcomm game_vars,1 + +.lcomm x, 2 +.lcomm xadd, 2 +.lcomm scroll, 2 +.lcomm scroll_frames, 2 + +.lcomm missile_0, 3*NUM_MISSILES # out,x,y +.lcomm enemy_0, ENEMIES_SIZE*NUM_ENEMIES + # out,exploding,kind,xw,yw + # xadd,yadd,xmin,xmax + + +.lcomm score, 4 +.lcomm score_string, 10 +.lcomm hiscore_string,10 +.lcomm level, 1 +.lcomm level_string, 10 + +.lcomm shields, 1 +.lcomm shield_up_count, 1 + + +.lcomm total_enemies_out, 1 + +# next bunch in order to smallen init code +.lcomm enemies_spawned, 2 +.lcomm current_init_x, 2 +.lcomm current_enemy_kind, 1 +.lcomm enemy_wait, 1 +.lcomm current_enemy_type, 1 +.lcomm enemy_wave, 1 + + +.lcomm between_enemy_delay,1 +.lcomm waves_till_boss,1 + + +# FIXME move some of these to be flags? +.lcomm boss_x,2 +.lcomm boss_xadd,2 +.lcomm boss_count,2 +.lcomm boss_smoke,1 +.lcomm boss_exploding,1 +.lcomm boss_waiting,1 +.lcomm boss_hits,1 +.lcomm boss_shooting,1 + +.lcomm background,1600 + +.lcomm end_game_vars,1 + + +# From ~/linux/include/asm/termbits.h +# struct termios { +# unsigned int c_iflag; /* input mode flags */ +# unsigned int c_oflag; /* output mode flags */ +# unsigned int c_cflag; /* control mode flags */ +# unsigned int c_lflag; /* local mode flags */ +# unsigned char c_line; /* line discipline */ +# unsigned char c_cc[19]; /* control characters */ +# }; + +.lcomm old_tty 40 +.lcomm new_tty 40 diff --git a/tb_asm/xpm/boss.xpm b/tb_asm/xpm/boss.xpm new file mode 100644 index 0000000..eb43442 --- /dev/null +++ b/tb_asm/xpm/boss.xpm @@ -0,0 +1,35 @@ +/* XPM */ +static char * boss_xpm[] = { +"40 20 12 1", +" c None", +". c #000000", +"+ c #FC54FC", +"@ c #A800A8", +"# c #A8A8A8", +"$ c #545454", +"% c #FC5454", +"& c #A80000", +"* c #FCFCFC", +"= c #00A8A8", +"- c #54FCFC", +"; c #FCFC54", +"....$#$.......*#&%%%%%%%&#*.............", +"....#$#.......*$#&&=-=&&#$*.............", +"..............*.$#=-;-=#$.*.............", +"..............+...........+.............", +"..............@...........@.............", +"..............+...........+.............", +"..............@...........@.............", +"..............+...........+.............", +"..............@...........@.............", +"..............+...........+.............", +"..............@...........@.............", +"..............+...........+.............", +"..............@...........@.............", +"..............+...........+.............", +"..............@...........@.............", +"..............+...........+.............", +"..............@...........@.............", +"..............+...........+.............", +"..............@...........@.............", +"..............+...........+............."}; diff --git a/tb_asm/xpm/default.xpm b/tb_asm/xpm/default.xpm new file mode 100644 index 0000000..10872f5 --- /dev/null +++ b/tb_asm/xpm/default.xpm @@ -0,0 +1,40 @@ +/* XPM */ +static char * default_xpm[] = { +"40 20 17 1", +" c None", +"0 c #000000", +"1 c #0000A8", +"2 c #00A800", +"3 c #00A8A8", +"4 c #A80000", +"5 c #A800A8", +"6 c #A85400", +"7 c #A8A8A8", +"8 c #545454", +"9 c #5454FC", +"A c #54FC54", +"B c #54FCFC", +"C c #FC5454", +"D c #FC54FC", +"E c #FCFC54", +"F c #FCFCFC", +"0123456789ABCDEF000000000000000000000000", +"0000000000000000000000000000000000000000", +"0000000000000000000000000000000000000000", +"0000000000000000000000000000000000000000", +"0000000000000000000000000000000000000000", +"0000000000000000000000000000000000000000", +"0000000000000000000000000000000000000000", +"0000000000000000000000000000000000000000", +"0000000000000000000000000000000000000000", +"0000000000000000000000000000000000000000", +"0000000000000000000000000000000000000000", +"0000000000000000000000000000000000000000", +"0000000000000000000000000000000000000000", +"0000000000000000000000000000000000000000", +"0000000000000000000000000000000000000000", +"0000000000000000000000000000000000000000", +"0000000000000000000000000000000000000000", +"0000000000000000000000000000000000000000", +"0000000000000000000000000000000000000000", +"0000000000000000000000000000000000000000"}; diff --git a/tb_asm/xpm/ending.xpm b/tb_asm/xpm/ending.xpm new file mode 100644 index 0000000..2e18423 --- /dev/null +++ b/tb_asm/xpm/ending.xpm @@ -0,0 +1,35 @@ +/* XPM */ +static char * ending_xpm[] = { +"40 20 12 1", +" c None", +". c #000000", +"+ c #A8A8A8", +"@ c #5454FC", +"# c #0000A8", +"$ c #545454", +"% c #54FC54", +"& c #FCFCFC", +"* c #00A8A8", +"= c #54FCFC", +"- c #00A800", +"; c #A80000", +"...###@@............+&&.................", +"...#..$@...........-%%@@................", +"...#..$@...........#%@@@................", +"...#..$@...........#@%%@................", +"...#..$@...........#@%@@................", +"....##@.............+&&.................", +"..####@@@@..............................", +"..#@##@;#@..............................", +"..#@##@@#@...+++++++++++++++++++........", +"..#@##@@#@...+++++++++++$.&&.+++........", +"..#@##@@#@...++.........$..$..++........", +"..#@##@@#@...+.................+........", +"..*=#@#@*=...+.................+........", +"....#@#@.....+...............+++........", +"....#@#@.....++............+++++........", +"....#@#@.....++++$$$+++++$$$++++........", +"....*=*=................................", +"....$+$+................................", +"........................................", +"........................................"}; diff --git a/tb_asm/xpm/missile.xpm b/tb_asm/xpm/missile.xpm new file mode 100644 index 0000000..9da8c7f --- /dev/null +++ b/tb_asm/xpm/missile.xpm @@ -0,0 +1,40 @@ +/* XPM */ +static char * missile_xpm[] = { +"40 20 17 1", +" c None", +". c #000000", +"+ c #A8A8A8", +"@ c #FCFCFC", +"# c #FCFC54", +"$ c #5454FC", +"% c #A80000", +"& c #545454", +"* c #00A800", +"= c #A85400", +"- c #FC5454", +"; c #00A8A8", +"> c #54FC54", +", c #0000A8", +"' c #A800A8", +") c #54FCFC", +"! c #FC54FC", +".,*;#'=+&$>)-!#@........................", +"........................................", +"........................................", +"........................................", +"........................................", +"........................................", +"........................................", +"....+..........@@%...$.$...##-..........", +"....+..........@@@....$....-#&..........", +"....+...................................", +"...%%%.........*>*...;==...++%..........", +"....#..........*>*...;==...%+...........", +"........................................", +".........+......#....-@@...&&...........", +".........+.....#.#...-++....&&..........", +".........#..............................", +"..............$$$.......................", +".............+@@@+......................", +"............++@+@++.....................", +"...............#........................"}; diff --git a/tb_asm/xpm/opener.xpm b/tb_asm/xpm/opener.xpm new file mode 100644 index 0000000..dda6340 --- /dev/null +++ b/tb_asm/xpm/opener.xpm @@ -0,0 +1,38 @@ +/* XPM */ +static char * opener_xpm[] = { +"40 20 15 1", +" c None", +". c #0000A8", +"+ c #54FCFC", +"@ c #00A8A8", +"# c #FC5454", +"$ c #000000", +"% c #A8A8A8", +"& c #FCFCFC", +"* c #545454", +"= c #00FCFC", +"- c #FCFC00", +"; c #A80000", +"> c #0000FC", +", c #FC0000", +"' c #00A800", +"...+...+.+++.@##@@###@#@@@#@##@@##@#@@@#", +"+.++.+.+..+..@#@#@#@#@##@##@#@#@#@@##@##", +"+.++.+.+.+.+.@##@@#@#@#@#@#@##@@##@#@#@#", +"+.++.+.+.+++.@#@#@#@#@#@@@#@#@#@#@@#@@@#", +"+.++...+.+++.@##@@###@#@@@#@##@@##@#@@@#", +"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$", +"$$$$$$$$$$$$$$$$$$$$$$$$$%$$$$$$$$$$%$$$", +"$$$%$$$$$$$&$$$$$$$$$$$$$$$$$$$*$$$$$$$$", +"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$", +"$$$$$%$$$$$$$$$$*$$$$$$$$$$$$&$$$$$$$$$$", +"$$$$$%%$$$$$$$$$$$$$$$%$$$$$$$$$$$$$=$$$", +"$-$$$%%%$$$$$$$$$$$$$$$$$$$$$$$$$$$$$=;;", +"$--->&&&&&&&&>>>$$$$$$$$$$$$$$$$$$$$$=,,", +"--;,.&;'.'.&&>>>>$$$$$$$$$$$$$$$$$$$=$,,", +"$--,>&;'.'.&&>>>>>$$$$$$;$$$$$$$$$$$$$,,", +"$$$-.%%%%%%%%&&&&&&$$$$-%%%%$$$$$$$$$$,,", +"$$$$$$$$$$$$$$$$$$$$$$$$;$$$$$$$$&$$$$;;", +"$$$$*$$$$$%$$$$$$$$$$$$$$$$$$$$$$$$$$$$$", +"$&$$$$$$$$$$$$$$$&$$$$$$$$$*$$$$$$$$$$$$", +"$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$%$"}; diff --git a/tb_asm/xpm/phobos.xpm b/tb_asm/xpm/phobos.xpm new file mode 100644 index 0000000..cdf3ef9 --- /dev/null +++ b/tb_asm/xpm/phobos.xpm @@ -0,0 +1,33 @@ +/* XPM */ +static char * phobos_xpm[] = { +"40 20 10 1", +" c None", +". c #000000", +"+ c #FC0000", +"@ c #FCFCFC", +"# c #A80000", +"$ c #A8A8A8", +"% c #00A8A8", +"& c #A85400", +"* c #545454", +"= c #00FCFC", +"........................................", +"..................$.....................", +"....................................@...", +"........................................", +".....$@@@@..............................", +"....#++++++..............@..............", +"...#+++++#++............................", +"...#++++++++............................", +"...#+++#++++.....*&.....................", +"...#++++++++.....&......................", +"...#+++++#++...................@........", +"....#++++++...............$.............", +".....$@@@@..............................", +"........................................", +"........................................", +"...@.............$............$.........", +"........................................", +".%=%....................................", +"........................................", +"........................................"}; diff --git a/tb_asm/xpm/tom.xpm b/tb_asm/xpm/tom.xpm new file mode 100644 index 0000000..ecb83a7 --- /dev/null +++ b/tb_asm/xpm/tom.xpm @@ -0,0 +1,32 @@ +/* XPM */ +static char * tom_xpm[] = { +"40 20 9 1", +" c None", +". c #000000", +"+ c #0000A8", +"@ c #0000FC", +"# c #545454", +"$ c #00A8A8", +"% c #00FCFC", +"& c #A8A8A8", +"* c #FC0000", +"...+++@@................................", +"...+..#@................................", +"...+..#@................................", +"...+..#@................................", +"...+..#@................................", +"....++@.................................", +"..++++@@@@..............................", +"..+@++@*+@..............................", +"..+@++@@+@..............................", +"..+@++@@+@..............................", +"..+@++@@+@..............................", +"..+@++@@+@..............................", +"..$%+@+@$%..............................", +"....+@+@................................", +"....+@+@................................", +"....+@+@................................", +"....$%$%................................", +"....#&#&................................", +"........................................", +"........................................"}; diff --git a/tb_asm/xpm/vince_minimal.xpm b/tb_asm/xpm/vince_minimal.xpm new file mode 100644 index 0000000..f0f8632 --- /dev/null +++ b/tb_asm/xpm/vince_minimal.xpm @@ -0,0 +1,28 @@ +/* XPM */ +static char * vince_minimal_xpm[] = { +"16 20 5 1", +" c None", +". c #000000", +"+ c #A8A8A8", +"@ c #545454", +"# c #FCFCFC", +"..@########@....", +".@+####+####++..", +"@+++++@+#++###+.", +"+@.@+++########@", +"+.@############+", +"@.+#######+#++@@", +"@@#########@@.@+", +"@+####+###+.@.@+", +"+@@+#@.@+#+....@", +".+.@#..@.@#@...@", +".+@+#@..+##+...+", +".#@###++####...+", +".#+@@+#####@@@++", +".##@.+####+.+++.", +".##+@++###+.++@.", +".++.@..++..#@+..", +".@##@##+..@++@..", +"..#+++#++@@#+...", +"..+####@@.@#@...", +"...@@.....+#@..."}; diff --git a/tb_asm/xpm/vmwsoft_orig.xpm b/tb_asm/xpm/vmwsoft_orig.xpm new file mode 100644 index 0000000..a935d3a --- /dev/null +++ b/tb_asm/xpm/vmwsoft_orig.xpm @@ -0,0 +1,40 @@ +/* XPM */ +static char * vmwsoft_xpm[] = { +"40 20 17 1", +" c None", +". c #000000", +"+ c #0000A8", +"@ c #00A800", +"# c #00A8A8", +"$ c #A80000", +"% c #A800A8", +"& c #A85400", +"* c #A8A8A8", +"= c #545454", +"- c #5454FC", +"; c #54FC54", +"> c #54FCFC", +", c #FC5454", +"' c #FC54FC", +") c #FCFC54", +"! c #FCFCFC", +"........................................", +"........................................", +"........................................", +"........................................", +"........................................", +"........................................", +"........$$$$$$$@+++++++@+++++++.........", +"........$$$$$$$@+++++++@+++++++.........", +".........$$$$$@@@+++++@@@+++++..........", +".........$$$$$@@@+++++@@@+++++..........", +"..........$$$@@@@@+++@@@@@+++...........", +"..........$$$@@@@@+++@@@@@+++...........", +"...........$@@@@@@@+@@@@@@@+............", +"...........$@@@@@@@+@@@@@@@+............", +"........................................", +"........................................", +"........................................", +"........................................", +"........................................", +"........................................"};