Import of version 2.9.0

This commit is contained in:
Vince Weaver 1998-03-07 15:37:00 -05:00
parent 6d72b8cbfd
commit e1c4761d2d
54 changed files with 9366 additions and 18 deletions

5
BUGS Normal file
View File

@ -0,0 +1,5 @@
Known Bugs:
% svgalib needs -force8bpp option
% weird colors at times in 8bpp X mode
% Enlightenment window manager screws up 8bpp colors
% game is not finished

44
CHANGES Normal file
View File

@ -0,0 +1,44 @@
7 March 1998
* Added Level 2, mostly working
6 March 1998
* Added load game support
5 March 1998
* Fixed typo in credits [Yes I had "linux torvalds" by mistake]. Thanks
to my friend John C. for catching that one.
* Added save game support.
3 March 1998
* Really cleaned up level1.c Mostly cleaned
* Modularized and actually re-wrote some code, instead of translating it.
* Lots of really minor tweaks trying to up performance.
1 March 1998
* Got little opener slowed down
* Got credits working
* Got pause to work
* Got sidebar reporting hiscore.
29 February 1998
* OK, there was no 29th. But I did more work later and it felt
like a new day.
* Cleaned up the tb1.c majorly
* Added support for having the data files searched for in many directories.
* Cleaned out the directory structure and removed cruft.
* Got sound support working!
* added -force8bpp option so SVGA target works
* Other miscelaneous things
28 February 1998
* AWESOME!! WORKING BETTER THAN IT WAS BEFORE!
* Moved over to fast DirectBuffer Calls. FAST!
* Got gameplay working, GETTING SCROLLING STARS
* added vmwCrossBlit functions. FAST! Thanks to andy at the ggi-list
* Fixed lots of minor bugs
27 February 1998
* Started this file
* Today converted from 320x600 virtual to 3 320x200s [2 are in memory]
* Added support so it can (almost) run in both 8bpp and 16bpp mode.
* Broke a lot more than I fixed.

28
COMPILING Normal file
View File

@ -0,0 +1,28 @@
First you have to get the ggi graphics library.
* for newest updates/info check out http://www.ggi-project.org
* Get a new snapshot from ftp://synergy.caltech.edu/pub/ggi/ggi-snapshots
* Get a newer one --> I developed it with ggi-980226.tar.gz
* save it
* uncompress it "tar -xzvf ggi-980226.tar.gz"
* "cd ggi" "cd lib" "cd libggi" "make"
* this brings up a menu. be sure to choose "xserv","svga" and "mem"
you can choose others if you wish, but these are all needed.
* exit the menu
* "make"
* should compile w/o problems [hopefully]
* "su" "make install"
* link your ~/ggi/include/ggi directory to /usr/local/include/ggi
[or however you want to get the files in the right place]
* copy the files ~/ggi/lib/libggi/include/ggi/*.h into
/usr/local/include/ggi
* should be all set up
Now compile TB1
* Uncompress the .tar.gz file
* "make"
* all should go OK.. you will get errors on some of the sound stuff,
but as long as the "tb1" file is created, you are good to go.
* It is known to work under 8bpp and 16bpp x-targets. Let me know if
it doesn't work under all of them
Vince Weaver weave@eng.umd.edu http://www.glue.umd.edu/~weave/tb1

51
Makefile Normal file
View File

@ -0,0 +1,51 @@
##############################################################
# Makefile for Seabattle 1.0 -- by Vince Weaver #
# #
# Written on Linux 2.1.35 #
# #
# To modify for your configuration, add or remove the # #
# #
##############################################################
#Your compiler. If gcc doesn't work, try CC
CC = gcc
#CC = cc
#On Linux, uncomment the following
#
PLATFORM = Linux
C_OPTS = -O2 -Wall -DHAVE_LINUX_SOUND
L_OPTS = -lggi
######################################################################
# THERE IS NO NEED TO EDIT ANYTHING BELOW THIS LINE #
######################################################################
all: tb1
clean:
rm -f *.o
rm -f tb1
rm -f *~
tb1: tb1.o svmwgrap.o tblib.o level1.o level2.o soundIt.o
$(CC) $(C_OPTS) -o tb1 tb1.o svmwgrap.o tblib.o level1.o level2.o soundIt.o $(L_OPTS)
@strip tb1
soundIt.o: soundIt.c
$(CC) $(C_OPTS) -c soundIt.c
tb1.o: tb1.c
$(CC) $(C_OPTS) -c tb1.c
tblib.o: tblib.c
$(CC) $(C_OPTS) -c tblib.c
level1.o: level1.c
$(CC) $(C_OPTS) -c level1.c
level2.o: level2.c
$(CC) $(C_OPTS) -c level2.c
svmwgrap.o: svmwgrap.c
$(CC) $(C_OPTS) -c svmwgrap.c

319
README Normal file
View File

@ -0,0 +1,319 @@
what follows is the old dos readme... I'll update it one of these days..
°°°°°² °°°°°² °² °² °°°°² °°°°°² °² °² °°°°² °°°°°² °² °²
°² °² °² °°²°°² °² °² °² °² °°²°°² °² °² °² °°²°°²
°² °² °² °²°²°² °°°°² °² °² °²°²°² °°°°² °°°°² °²°²°²
°² °² °² °² °² °² °² °² °² °² °² °² °² °² °² °²
°² °°°°°² °² °² °°°°² °°°°°² °² °² °°°°² °°°°°² °² °²
AND THE INVASION OF THE INANIMATE OBJECTS
by
Vince Weaver
Version 2.4a
---------------------------------------------------------------------
Contents
--------
1.0 SYSTEM REQUIREMENTS
2.0 STARTING THE GAME
3.0 THE STORY
4.0 GAME PLAY
5.0 SAVING/LOADING GAMES
6.0 TROUBLESHOOTING
7.0 REGISTERING
8.0 ACKNOWLEDGEMENTS
9.0 CURRENT BUGS (FEATURES)
10.0 PRAISE/ACCOMPLISHMENTS
1.0 SYSTEM REQUIREMENTS
---------------------------------------------------------------------
Bare Minimum:
286/ 400K RAM/ 500K disk space
To run at a reasonable speed:
386 33Mhz or better
For Digitized Sound:
XMS RAM, Sound Blaster or Compatible sound card
(I have been developing this on a 386 33Mhz and it runs
passibly. It runs so much smoother on a 486. I'll try
to optimize the code some more...)
2.0 STARTING THE GAME
---------------------------------------------------------------------
Make sure all the files are in the same directory (list below)
[if any are missing, you will get a run-time error]
Run the TBSETUP configuration utility. Pick the appropriate
options.
Type TB1 to run the game. See "TROUBLESHOOTING" if you encounter
any errors.
To run Tom Bombem off of a CD-ROM:
Either type "tb1 -cdrom" to start the program in read-only
mode, or say "y" when prompted if you want read-only mode.
In this mode there are no saved games and the high score
list will not change.
Files Needed:
TB1.EXE - Main executable
TBSETUP.EXE - Setup Program
CONFIG.TB1 - Config File Created by Setup Program
TBSOUND.EXE - Cool sound tester
MOON2.TB1 ¿
REGISTER.TB1 ³
TBGORG.TB1 ³
TBCRASH.TB1 ³
TBSOBJ.TB1 ³
SHIPS.TB1 Ã Graphics files in PAINTPRO 5.0 format
TBOMB1.TB1 ³
TBMA1.TB1 ³
VIEWSCR.TB1 ³
TBSHAPES.TB1 ³
TBCOBJ.TB1 ³
TBCHIEF.TB1 ³
TBASHIP.TB1 ³
TBL2SHIP.TB1 ³
TBLEV3.TB1 ³
TBL3INTR.TB1 ³
TBEERM.TB1 ³
TBCONSOL.TB1 ³
TBPIT.TB1 ³
TBASH.TB1 ³
TBCOBJ.TB1 ³
TBTRACT.TB1 Ù
LEVEL2.TB1 - Level Two Database
LEVEL4.TB1 - Level Four Database
FILE_ID.DIZ - Info file for BBS's
TBFONT.TB1 - Fonts for the game (a standard VGA font)
HISCORE.TB1 - The High Score List
TB1.DOC - The file you're reading
SOUNDS.TB1 - Sound effects
SGx.TB1 - Where x is a number... these are saved games
3.0 THE STORY
---------------------------------------------------------------------
To understand the game, pick the "Story" option off of the
main menu. This part of the game took a lot of time in
itself, and is fun to read.
The "Audio Error!" is not a real error. I just saved myself
the trouble of recording a voice-track for the game. As many
friends have said, "That's cheating!" but anyway unless I had
a lot of time and a CD-ROM, it is not practical.
Anyway in the story, any key will speed up most scenes, and
escape will quit the whole thing.
4.0 GAME PLAY
--------------------------------------------------------------------
To begin the game, select "NEW GAME" at the main menu.
A little humorous movie will show; press <esc> to skip.
The game itself is pretty simplistic as of yet. Basically
shoot the things coming at you. The arrow keys manuever...
the manuevering takes a little bit of practice to master.
Space shoots. You can shoot up to two missiles at once.
"S" toggles sound. "P" pauses. If the game play is too fast,
try the "+" and "-" keys to adjust. Sorry, if it runs too
slow at the onset, then your computer is too slow.
The first level culminates with a "boss" character. Read the
story and see what happens. The dialog will clue you into
what's happening.
The second level is now totally finished. Be sure to save
your games whenever you start a new level!
Levels three and four are currently under development. In
level three, use the arrow keys to "walk" around. The space
bar will fire a weapon if you've picked one up. To activate/
pick up things, walk into them.
Level four is similar to level two. (Actually they are based
on the same game engine). They will be finished by version 2.5.
An undocumented featue: when your score reaches a multiple of
400 your shields are increased by one.
Basic Summary of Keyboard Commands:
ARROWS Manuever
SPACE Fires
<ESC> Exits
P Pauses
S Toggles sound on/off
+ Slows down game speed
- Increases game speed
F1 Shows help message
F2 Saves the Game (see "SAVING/LOADING GAMES")
5.0 SAVING/ LOADING GAMES
---------------------------------------------------------------------
You can save games. However the only part that is saved is
how you begin the level. Therefore there is no real purpose
to saving your game until you reach level two.
This might seem annoying, but at this point it is the only
practical way to implement saved games.
6.0 TROUBLESHOOTING
---------------------------------------------------------------------
This program usually runs fine on most computers. Occasionally
it will lock up on my brother for some inexplicable reason.
If it locks up frequently, try playing without sound blaster
sounds.
Possible Problems:
RUNTIME ERRORS: (Characterized by a "Rumtime Error at 4454:3434"
message.) Either a genuine bug or else one of
the ".TB1" graphics files is missing.
LOCKING UP : If you have a sound blaster, try configuring
without SOUND, using the "TBSETUP" utility.
MEMORY ERRORS : If you want soundblaster sound, HIMEM.SYS must
be loaded. Check DOS documentation.
SOUND ERRORS : If you have a sound blaster and you are not
getting sound, be sure your "SET BLASTER"
command in your autoexec.bat is set properly.
HARSH GRATING SOUND: This has happened occassionally at a
certain point on level two. I've tried to
fix it. If it's annoying, turn the sound
off.
MISC ERRORS : Contact me at vmweaver@wam.umd.edu
7.0 REGISTERING
---------------------------------------------------------------------
My game is freeware. There is no copy protection. Hopefully
if you like it you will let me know, by mail or by e-mail.
A donation is not required, but if you want to you can send
me one.
I will be attending college soon (Fall of 1996) so my e-mail
address, has changed from what it was earlier to:
vmweaver@wam.umd.edu
You can get Tom Bombem at its web site,
http://www.wam.umd.edu/~vmweaver/tb1/
Also, a college education is expensive, so any donations would
be a big help.
Vince Weaver vmweaver@wam.umd.edu
[real home]
326 Foster Knoll Dr.
Joppa, MD 21085-4706
8.0 ACKNOWLEDGEMENTS
---------------------------------------------------------------------
I would like to thank many people who helped on this project.
Ethan Brodsky for his excelent sound blaster routines.
Get them at http://www.pobox.com/~ebrodsky/smix/smix.html
There would be no sound blaster sound without them.
The authors of PCGPE. This program started out as a
"flying toaster" demonstration from the Asphixia
VGA tutorials. I gradually replaced most of their code,
but I still use their putpixel, waitretrace, setmcga and
settext routines.
I would also like to thank all my friends who have supported
me, especially Gus Thompson, because she went to Spain and
gave me time to work on this. Also Marie Prosser for
inspiration, and she also went away for three weeks
allowing me to work on this. Thanks to Nick Attanasio
who actually plays this game a lot, and whose comments
have hastened work on level 3.
FUTURE ENHANCEMENTS:
I am going to learn how to use Mode X vga programming.
Supposedly this will speed up the code. Unless you
have a 386 like me, you probably won't notice.
I'm also going to try to get some music in the
background, and of course add more levels.
Also watch for a SGI gl port and possibly some
sort of Linux port. The only problem is that
they'll have to be in C. ( :-( )
9.0 CURRENT BUGS (FEATURES)
-------------------------------------------------------------------
Level One: No Known Ones
Level Two: Locks up for no reason near end sometimes?
Level Three: Many. This level still is under development.
Sometimes doors will not activate, sometimes
they send you to the wrong room.
Laser doesn't work, nor do enemies or
radioactive flooring. It is possible to
beat it though.
Level Four:Not done. Right now is level two with different
shape table.
LOOK FOR NEWER RELEASES TO HAVE FEWER BUGS.
If you find a unique bug, e-mail me describing it.
10.0 PRAISE/ACCOMPLISHMENTS OF TOM BOMBEM
___________________________________________________________________
Supposedly it will be on one of Pacific Hi-Tech's
"Gamehead" CD's. We'll see.
A German book company has offered to put it in a CD included
with a Shareware Games book.
Now Praise:
"I just like it when it says 'Ahhh... Mr. Bombem.'"
----Greg Grabowski, Bel Air, MD
"It's simplicity reminded me of the early computer
shooters... Kind of nostalgic... But the nice
side [is] the very clever cinematic text."
---->> Delance <<
"The game is well designed but does not fit
our current product line."
----Apogee Software Productions
Remember: Watch for the newest version of Tom Bombem... and have fun.
Vince Weaver 14 July 1996 18:12:59 EDT

4
TODO Normal file
View File

@ -0,0 +1,4 @@
Finish the game [or at least get it on-par with the dos version]
Requires:
Levels2-4
Highscore list

0
data/data_files_here Normal file
View File

View File

@ -1,22 +1,22 @@
31 31 31 31 31 31 31 31 31 31 31 31
5 7 5 5 5 5 5 5 5 5 7 5
5 5 3 5 30 30 30 30 5 3 5 5
5 5 5 5 4 4 4 4 5 5 5 5
15 15 15 15 31 31 31 31 15 15 15 15
17 17 17 17 16 16 16 16 17 17 17 17
9 9 9 9 9 9 9 9 9 9 9 9
9 9 9 9 9 9 9 9 9 9 9 9
9 9 9 9 9 9 9 9 9 9 9 9
9 9 9 9 9 9 9 9 9 9 9 9
9 9 9 9 9 9 9 9 9 9 9 9
9 9 9 9 9 9 9 9 9 9 9 9
7 9 9 9 9 9 9 9 9 9 9 7
9 9 9 9 9 9 9 9 9 9 9 9
9 9 9 9 9 9 9 9 9 9 9 9
12 9 9 9 12 9 9 12 9 9 9 12
9 9 9 9 9 9 9 9 9 9 9 9
9 9 9 9 9 9 9 9 9 9 9 9
0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0
15 15 15 15 0 0 0 0 15 15 15 15
0 0 0 0 0 0 0 0 0 0 0 0
30 30 30 30 30 30 30 30 30 30 30 30
5 5 5 5 5 5 5 5 5 5 5 5
5 5 5 5 5 5 5 5 5 5 5 5
5 4 5 5 5 5 5 5 5 5 5 5
5 5 5 5 5 5 5 5 5 5 5 5
5 5 5 5 5 4 5 5 5 5 5 5
5 12 5 5 5 5 5 5 5 5 12 5
5 5 5 5 14 5 14 5 5 5 5 5
5 5 5 5 5 5 5 5 5 5 5 5
12 5 5 5 12 5 5 12 5 5 5 12
5 5 5 5 5 5 5 5 5 5 5 5
5 5 5 5 5 5 5 5 5 5 5 5
31 31 31 31 31 31 31 31 31 31 31 31
0 0 0 0 0 0 0 0 0 0 0 0
2 2 18 19 0 0 0 0 19 18 2 2
0 0 0 0 0 0 0 0 0 0 0 0

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

1
data/tbahh.raw Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

1
data/tbbonk.raw Normal file

File diff suppressed because one or more lines are too long

1
data/tbcc.raw Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

BIN
data/tbclick.raw Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

1
data/tbkapow.raw Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

1
data/tbow.raw Normal file

File diff suppressed because one or more lines are too long

Binary file not shown.

BIN
data/tbscream.raw Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
data/tbzrrp.raw Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

20
hiscore.tb1 Normal file
View File

@ -0,0 +1,20 @@
Vince!;!
Vince;
Vince
KEVIN
KEVIN!@#%&
Vince
Vince
KEVIN
MREE
kevin
2210
2000
1900
1860
1860
1850
1810
1790
1790
1790

703
level1.c Normal file
View File

@ -0,0 +1,703 @@
/*
Level 1 Engine Code for Tom Bombem
*/
/* The Includes */
#include <stdio.h>
#include <sys/time.h>
#include <unistd.h>
#include <ggi/libggi.h>
#include <stdlib.h>
#include "svmwgrap.h"
#include "levels.h"
#include "tblib.h"
#include "soundIt.h"
/* Define this to get a frames per second readout */
/* #define DEBUG_ON */
/* The sounds */
#define NUM_SAMPLES 4
#define SND_CC 0
#define SND_BONK 1
#define SND_KAPOW 2
#define SND_ZRRP 3
/* The global variables ;) I like global variables hehe */
extern vmw_font *tb1_font;
extern ggi_visual_t vis;
extern ggi_visual_t vaddr;
extern ggi_visual_t vaddr2;
extern ggi_color eight_bit_pal[256];
extern ggi_pixel tb1_pal[256];
extern ggi_directbuffer_t dbuf_vis;
extern ggi_directbuffer_t dbuf_vaddr;
extern ggi_directbuffer_t dbuf_vaddr2;
extern ggi_pixellinearbuffer *plb_vis;
extern ggi_pixellinearbuffer *plb_vaddr;
extern ggi_pixellinearbuffer *plb_vaddr2;
extern int sound_possible;
extern int sound_enabled;
extern int color_depth;
extern int stride_factor;
/* I like structures also ;) */
struct enemyinfo {
int x,y;
int kind;
int out,exploding,boundarycheck,dead;
int explodeprogress;
int minx,maxx,xspeed,yspeed;
int hitsneeded;
};
struct bulletinfo {
int out,x,y;
};
/* Define how many sound effects there are */
Sample sound_effects[NUM_SAMPLES];
/* o/~ more structures o/~ */
struct enemyinfo enemy[5];
struct bulletinfo bullet[3];
struct timeval timing_info;
struct timezone dontcare;
/* This seemed like a good idea to modularize things */
int level_one_wave_behavior[]=
{0,0,0,0,0, 1,1,1,1,1,
1,1,2,2,2, 2,2,2,2,2,
3,3,3,3,3, 3,3,3,3,3,
2,2,2,2,2, 2,3,3,3,3,
3,3,3,3,3, 3,1,1,1,1,
1,3,3,3,3, 3,3,3,3,3,
3,2,2,2,2, 2,2,2,2,2,
2,2,2,2,2, 2,1,1,1,1,
1,1,1,3,3, 3,2,2,2,2,
2,2,2,2,2, 2,1,1,1,1,
1,4,4,4,4};
/* Yes I was too lazy to re-arrange the order of the functions */
void beforeboss();
/* Defines the behavior of the objects in level 1 */
int level_one_behavior(int reset)
{
int what,temp,whichone,need_to_pause=0;
static int wave=0;
static int saucersout=0;
if (reset) {
wave=0;
saucersout=0;
}
if (level_one_wave_behavior[wave]!=4) wave++;
saucersout--;
if (saucersout<0) saucersout=0;
if (saucersout>5) saucersout=5;
/* **START NEW WAVE ***/
switch(level_one_wave_behavior[wave]) {
/* STANDARD */
case 0: if (saucersout==0) {
saucersout=5;
what=(3+rand()%8);
for(temp=0; temp<5; temp++) {
enemy[temp].kind=what;
enemy[temp].x=0;
enemy[temp].y=0;
enemy[temp].xspeed=5;
enemy[temp].x=temp*20;
enemy[temp].minx=(temp*20);
enemy[temp].maxx=(temp*20)+120;
enemy[temp].boundarycheck=1;
enemy[temp].yspeed=10;
enemy[temp].out=1;
enemy[temp].exploding=0;
enemy[temp].hitsneeded=1;
enemy[temp].dead=0;
}
} break;
/* *FALLING STRAIGHT* */
case 3:
for (temp=0; temp<5;temp++)
if (!enemy[temp].out) {
enemy[temp].kind=rand()%8+3;
enemy[temp].x=rand()%200+1;
enemy[temp].y=0;
enemy[temp].xspeed=0;
enemy[temp].minx=enemy[temp].x;
enemy[temp].maxx=enemy[temp].x;
enemy[temp].boundarycheck=1;
enemy[temp].yspeed=5+(wave/40);
enemy[temp].out=1;
enemy[temp].exploding=0;
enemy[temp].hitsneeded=1;
enemy[temp].dead=0;
saucersout++;
} break;
/* *FALLING GRADUALLY SIDEWAYS* */
case 2:
for(temp=0;temp<5;temp++)
if (!enemy[temp].out) {
enemy[temp].kind=rand()%8+3;
enemy[temp].y=0;
enemy[temp].xspeed=5;
enemy[temp].minx=rand()%100;
enemy[temp].maxx=rand()%100+120;
enemy[temp].x=enemy[temp].minx;
enemy[temp].boundarycheck=0;
enemy[temp].yspeed=1;
enemy[temp].out=1;
enemy[temp].exploding=0;
enemy[temp].hitsneeded=1;
enemy[temp].dead=0;
saucersout++;
} break;
/**ZIG-ZAG**/
case 1: if (!saucersout) {
saucersout=5;
whichone=rand()%8+3;
for(temp=0;temp<5;temp++)
if (!enemy[temp].out) {
enemy[temp].kind=whichone;
enemy[temp].y=temp*10;
enemy[temp].xspeed=5;
enemy[temp].minx=0;
enemy[temp].maxx=220;
enemy[temp].x=temp*20;
enemy[temp].boundarycheck=0;
enemy[temp].yspeed=1;
enemy[temp].out=1;
enemy[temp].exploding=0;
enemy[temp].hitsneeded=1;
enemy[temp].dead=0;
}
} break;
/* Beginning of Boss */
case 4:
if (!saucersout) {
beforeboss();
need_to_pause=1;
enemy[0].kind=15;
enemy[1].kind=15;
enemy[2].kind=14;
for(temp=0;temp<3;temp++) {
enemy[temp].x=(temp*20)+10;
enemy[temp].y=0;
enemy[temp].xspeed=5;
enemy[temp].minx=0;
enemy[temp].maxx=220;
enemy[temp].boundarycheck=1;
enemy[temp].yspeed=0;
enemy[temp].out=1;
enemy[temp].exploding=0;
enemy[temp].hitsneeded=3;
enemy[temp].dead=0;
saucersout++;
}
} break;
default: break;
}
/* Objects Cast off by the Boss */
if (enemy[1].kind==15) {
/* Detect if Level One is Over */
if ((enemy[0].dead) && (enemy[1].dead) && (enemy[2].dead)) return 9;
for(temp=3;temp<5;temp++) {
saucersout++;
if ((!enemy[temp].out) && (enemy[temp-3].out)) {
enemy[temp].kind=rand()%8+3;
enemy[temp].x=enemy[temp-3].x;
enemy[temp].y=20;
enemy[temp].xspeed=0;
enemy[temp].minx=enemy[temp].x;
enemy[temp].maxx=enemy[temp].x;
enemy[temp].boundarycheck=0;
enemy[temp].yspeed=4;
enemy[temp].out=1;
enemy[temp].exploding=0;
enemy[temp].hitsneeded=1;
enemy[temp].dead=0;
}
}
}
return need_to_pause;
}
/* The little Sequence Before you hit the Boss */
void beforeboss()
{
char *tempst[300];
clear_keyboard_buffer();
GGILoadPicPacked(0,0,vaddr,0,1,
tb1_data_file("viewscr.tb1",(char *)tempst),
(ggi_color *)&eight_bit_pal,
(ggi_pixel *)&tb1_pal,color_depth);
ggiSetGCForeground(vis,0);
ggiDrawBox(vis,0,0,320,200);
vmwArbitraryCrossBlit(plb_vaddr->read,0,5,58,37,
plb_vis->write,10,10,plb_vis->stride,stride_factor);
VMWsmalltextxy("HUMAN!",70,10,tb1_pal[2],tb1_pal[0],1,tb1_font,vis);
VMWsmalltextxy("WHAT ARE YOU DOING?!",70,20,tb1_pal[2],
tb1_pal[0],1,tb1_font,vis);
VMWsmalltextxy("YOUR SPECIES MUST BE TERMINATED!",70,30,tb1_pal[2],
tb1_pal[0],1,tb1_font,vis);
pauseawhile(5);
vmwArbitraryCrossBlit(plb_vaddr->read,0,42,58,37,
plb_vis->write,10,50,plb_vis->stride,stride_factor);
VMWsmalltextxy("I'M SORRY.",70,50,tb1_pal[9],tb1_pal[0],1,tb1_font,vis);
VMWsmalltextxy("WE DIDN'T MEAN TO DESTROY YOUR ENVOY.",70,60,tb1_pal[9],
tb1_pal[0],1,tb1_font,vis);
VMWsmalltextxy("WILL YOU FORGIVE US AND TRY PEACE?",70,70,tb1_pal[9],
tb1_pal[0],1,tb1_font,vis);
pauseawhile(5);
vmwArbitraryCrossBlit(plb_vaddr->read,0,5,58,37,
plb_vis->write,10,90,plb_vis->stride,stride_factor);
VMWsmalltextxy("NO! YOU MUST BE DESTROYED!",70,90,tb1_pal[2],
tb1_pal[0],1,tb1_font,vis);
VMWsmalltextxy("OUR FUNDING ... OUR ENVOY WAS DAMAGED BY",70,100,
tb1_pal[2],tb1_pal[0],1,tb1_font,vis);
VMWsmalltextxy("YOU! VENGEANCE WILL BE OURS! YOUR PUNY",70,110,
tb1_pal[2],tb1_pal[0],1,tb1_font,vis);
VMWsmalltextxy("PRIMITIVE SPACECRAFT WITH ITS INFERIOR",70,120,
tb1_pal[2],tb1_pal[0],1,tb1_font,vis);
VMWsmalltextxy("WEAPONS WOULD HAVE TO SCORE 9 DIRECT HITS",70,130,
tb1_pal[2],tb1_pal[0],1,tb1_font,vis);
VMWsmalltextxy("TO DESTROY MY SHIP! DIE EARTH SCUM!!!!",70,140,
tb1_pal[2],tb1_pal[0],1,tb1_font,vis);
pauseawhile(5);
}
/* The Sequence After You Defeat (hopefully) the Boss */
void afterboss()
{
char *tempst[300];
GGILoadPicPacked(0,0,vaddr,0,1,
tb1_data_file("viewscr.tb1",(char *)tempst),
(ggi_color *)&eight_bit_pal,
(ggi_pixel *)&tb1_pal,color_depth);
ggiSetGCForeground(vis,tb1_pal[0]);
ggiDrawBox(vis,0,0,320,200);
vmwArbitraryCrossBlit(plb_vaddr->read,0,42,58,37,
plb_vis->write,10,10,plb_vis->stride,stride_factor);
VMWsmalltextxy("HMM.. THEY DON'T BUILD SUPERIOR",70,10,
tb1_pal[9],tb1_pal[0],1,tb1_font,vis);
VMWsmalltextxy("TECHNOLOGY LIKE THEY USED TO.",70,20,
tb1_pal[9],tb1_pal[0],1,tb1_font,vis);
VMWsmalltextxy("I GUESS I CAN GO HOME NOW.",70,30,
tb1_pal[9],tb1_pal[0],1,tb1_font,vis);
pauseawhile(5);
vmwArbitraryCrossBlit(plb_vaddr->read,0,5,58,37,
plb_vis->write,10,50,plb_vis->stride,stride_factor);
VMWsmalltextxy("NOT SO FAST! YOU JUST DESTROYED AN ANTIQUATED",70,50,
tb1_pal[2],tb1_pal[0],1,tb1_font,vis);
VMWsmalltextxy("DEFENSE SYSTEM THAT WAS PROGRAMMED BY A 16",70,60,
tb1_pal[2],tb1_pal[0],1,tb1_font,vis);
VMWsmalltextxy("YEAR OLD! OUR MAIN DEFENSE PROGRAMMER HAS ",70,70,
tb1_pal[2],tb1_pal[0],1,tb1_font,vis);
VMWsmalltextxy("MUCH MORE SKILL NOW! UNLESS YOU DESTROY OUR",70,80,
tb1_pal[2],tb1_pal[0],1,tb1_font,vis);
VMWsmalltextxy("ENTIRE XENOCIDE... I MEAN PEACE... ENVOY",70,90,
tb1_pal[2],tb1_pal[0],1,tb1_font,vis);
VMWsmalltextxy("WE WILL STILL DESTROY YOUR HOME PLANET.",70,100,
tb1_pal[2],tb1_pal[0],1,tb1_font,vis);
VMWsmalltextxy("NICE TRY PUNY EARTHLING!",70,110,tb1_pal[2],
tb1_pal[0],1,tb1_font,vis);
pauseawhile(7);
vmwArbitraryCrossBlit(plb_vaddr->read,0,42,58,37,
plb_vis->write,10,130,plb_vis->stride,stride_factor);
VMWsmalltextxy("HMM.. I GUESS I BETTER SAVE THE EARTH.",70,130,
tb1_pal[9],tb1_pal[0],1,tb1_font,vis);
VMWsmalltextxy("I'D BETTER SAVE MY GAME TOO.",70,140,
tb1_pal[9],tb1_pal[0],1,tb1_font,vis);
VMWsmalltextxy("D'OH! I''M OUT OF BIG MISSILES! ",70,150,
tb1_pal[9],tb1_pal[0],1,tb1_font,vis);
VMWsmalltextxy("WELL AT LEAST I HAVE SOME SMALLER SPARES.",70,160,
tb1_pal[9],tb1_pal[0],1,tb1_font,vis);
pauseawhile(5);
}
/* The Main Level One */
void levelone(int *level,int *shields,int *score)
{
int ch=0;
int i,j,grapherror;
char tempst[300];
int itemp,whatdelay=1,levelover=0;
int shipx=36,shipadd=0,shipframe=1;
int bigship1[1500],bigship2[1500],bigship3[1500];
int shapetable[20][400];
long oldsec,oldusec,time_spent;
int howmuchscroll=0;
int speed_factor=1,game_paused=0;
int beginscore,beginshield;
/* Set this up for Save Game */
beginscore=*score;
beginshield=*shields;
/* Load All The Sounds */
if (sound_possible) {
Snd_loadRawSample(tb1_data_file("tbcc.raw",(char *)&tempst),
&sound_effects[0],0);
Snd_loadRawSample(tb1_data_file("tbbonk.raw",(char *)&tempst),
&sound_effects[1],0);
Snd_loadRawSample(tb1_data_file("tbkapow.raw",(char *)&tempst),
&sound_effects[2],0);
Snd_loadRawSample(tb1_data_file("tbzrrp.raw",(char *)&tempst),
&sound_effects[3],0);
/* Initialize Sound, if Possible */
if (Snd_init( NUM_SAMPLES,sound_effects,22050,4,
"/dev/dsp")==EXIT_FAILURE) {
printf("ERROR! Cannot init sound.\n");
sound_enabled=0;
}
}
/* Load Sprites (or whatever you want to call them) */
grapherror=GGILoadPicPacked(0,0,vaddr,1,1,
tb1_data_file("ships.tb1",(char *)&tempst),
(ggi_color *)&eight_bit_pal,
(ggi_pixel *)&tb1_pal,color_depth);
vmwGetSprite(vaddr,0,0,48,30,(int *)&bigship1);
vmwGetSprite(vaddr,0,32,48,30,(int *)&bigship2);
vmwGetSprite(vaddr,0,64,48,30,(int *)&bigship3);
grapherror=GGILoadPicPacked(0,0,vaddr,1,1,
tb1_data_file("tbshapes.tb1",(char *)&tempst),
(ggi_color *)&eight_bit_pal,
(ggi_pixel *)&tb1_pal,color_depth);
for(j=0;j<2;j++)
for(i=0;i<10;i++)
vmwGetSprite(vaddr,1+(i*19),1+(j*19),18,20,
(int *)&shapetable[(j*10)+i]);
/* Set up initial Enemy Structs */
for(i=0;i<5;i++) {
enemy[i].exploding=0;
enemy[i].out=0;
enemy[i].dead=0;
}
for(i=0;i<2;i++) {
bullet[i].out=0;
bullet[i].x=0;
bullet[i].y=0;
}
/* Setup and draw the sidebar */
setupsidebar(*score,0,*shields);
ggiSetGCForeground(vis,tb1_pal[0]);
vmwCrossBlit(plb_vaddr->write,plb_vaddr2->read,plb_vaddr->stride,200);
sprintf(tempst,"%d",*level);
ggiDrawBox(vaddr2,251,52,63,7);
VMWtextxy(tempst,307,51,tb1_pal[12],tb1_pal[0],0,tb1_font,vaddr2);
/* Clear the screen and draw the stars */
ggiSetGCForeground(vaddr2,tb1_pal[0]);
ggiDrawBox(vaddr2,0,0,320,400);
for(i=0;i<100;i++) {
vmwPutSprite(shapetable[11],18,18,stride_factor,
plb_vaddr2->write,rand()%238,
rand()%400,plb_vaddr2->stride);
vmwPutSprite(shapetable[12],18,18,stride_factor,
plb_vaddr2->write,rand()%238,
rand()%400,plb_vaddr2->stride);
}
change_shields(shields);
/* Draw the Little Box announcing the Start of the Level */
ggiSetGCForeground(vis,tb1_pal[0]);
ggiDrawBox(vis,0,0,320,200);
coolbox(70,85,240,120,1,vis);
VMWtextxy(" LEVEL ONE:",84,95,tb1_pal[4],tb1_pal[7],0,tb1_font,vis);
VMWtextxy("INANIMATE OBJECTS",84,105,tb1_pal[4],tb1_pal[7],0,tb1_font,vis);
/* Initiate some last variables */
level_one_behavior(1);
pauseawhile(5);
gettimeofday(&timing_info,&dontcare);
oldsec=timing_info.tv_sec; oldusec=timing_info.tv_usec;
/* MAIN GAME LOOP */
while(!levelover) {
ch=0;
/* Scroll the Stars */
if (speed_factor>1) howmuchscroll-=speed_factor;
else howmuchscroll--;
if (howmuchscroll<0) howmuchscroll=399;
if (howmuchscroll>199) {
vmwArbitraryCrossBlit(plb_vaddr2->read,0,howmuchscroll,240,
400-howmuchscroll,
plb_vaddr->write,0,0,plb_vaddr->stride,
stride_factor);
vmwArbitraryCrossBlit(plb_vaddr2->read,0,0,240,howmuchscroll-200,
plb_vaddr->write,0,400-howmuchscroll,
plb_vaddr->stride,
stride_factor);
}
else {
vmwArbitraryCrossBlit(plb_vaddr2->read,0,howmuchscroll,240,200,
plb_vaddr->write,0,0,plb_vaddr->stride,
stride_factor);
}
/* Check for Collisions */
for(i=0;i<5;i++) {
if (!enemy[i].dead) {
for(itemp=0;itemp<2;itemp++) {
if (bullet[itemp].out)
if (collision(bullet[itemp].x,bullet[itemp].y,10,10,
enemy[i].x,enemy[i].y,9,9)) {
if (sound_enabled) Snd_effect(SND_KAPOW,2);
enemy[i].hitsneeded--;
if (enemy[i].hitsneeded<1) enemy[i].dead=1;
else enemy[i].dead=0;
enemy[i].exploding=1;
enemy[i].explodeprogress=0;
bullet[itemp].out=0;
(*score)+=10;
changescore(*score,shields);
}
}
}
}
/* Explode the things that are exploding */
for(i=0;i<5;i++) {
if (enemy[i].exploding) {
enemy[i].explodeprogress++;
if (enemy[i].explodeprogress<=5)
vmwPutSprite(shapetable[enemy[i].explodeprogress+14],
18,18,stride_factor,
plb_vaddr->write,enemy[i].x,enemy[i].y,
plb_vaddr->stride);
else if (enemy[i].dead) {
enemy[i].out=0;
enemy[i].exploding=0;
game_paused=level_one_behavior(0);
}
else enemy[i].exploding=0;
}
}
/* Move the Missiles */
for(i=0;i<2;i++) {
if (bullet[i].out) {
if (speed_factor>1) bullet[i].y-=(5*speed_factor);
else bullet[i].y-=5;
if (bullet[i].y<5) bullet[i].out=0;
else vmwPutSprite(shapetable[0],18,18,stride_factor,
plb_vaddr->write,bullet[i].x,bullet[i].y,
plb_vaddr->stride);
}
}
/* MOVE ENEMIES */
for(i=0;i<5;i++) {
if ((enemy[i].out) && (!enemy[i].dead)) {
vmwPutSprite(shapetable[enemy[i].kind-1],18,18,stride_factor,
plb_vaddr->write,enemy[i].x,enemy[i].y,
plb_vaddr->stride);
if (speed_factor==1) enemy[i].x+=enemy[i].xspeed;
else enemy[i].x+=(enemy[i].xspeed*speed_factor);
/* Check Position */
/* Check Position */
if (!enemy[i].boundarycheck)
if (speed_factor>1) enemy[i].y+=(enemy[i].yspeed*speed_factor);
else enemy[i].y+=enemy[i].yspeed;
if ((enemy[i].x<=enemy[i].minx) || (enemy[i].x>=enemy[i].maxx)) {
enemy[i].xspeed=-enemy[i].xspeed;
if (speed_factor>1) enemy[i].x+=(enemy[i].xspeed*speed_factor);
else enemy[i].x+=enemy[i].xspeed;
if (speed_factor>1) enemy[i].y+=(enemy[i].yspeed*speed_factor);
else enemy[i].y+=enemy[i].yspeed;
}
/* Too Low */
/* Too Low */
if (enemy[i].y>179) {
enemy[i].out=0;
game_paused=level_one_behavior(0);
}
if (enemy[i].y>140) {
if (collision(shipx,165,24,15,enemy[i].x,enemy[i].y,9,9)) {
if (sound_enabled) Snd_effect(SND_BONK,1);
enemy[i].hitsneeded--;
if (enemy[i].hitsneeded==0) enemy[i].dead=1;
else enemy[i].dead=0;
enemy[i].exploding=1;
enemy[i].explodeprogress=0;
(*shields)--;
if (*shields<0) levelover=1;
if (*shields>0) change_shields(shields);
}
}
}
}
/* See if beat the level. Yes, bad variable name. Oh well */
if (game_paused==9) {
afterboss();
*level=2;
levelover=1;
}
/* **READ KEYBOARD** */
if ( (ch=get_input())!=0) {
switch(ch){
case TB_ESC: levelover=1; break;
case TB_RIGHT: if (shipadd>=0) shipadd+=3; else shipadd=0; break;
case TB_LEFT: if (shipadd<=0) shipadd-=3; else shipadd=0; break;
case TB_F1: game_paused=1; help(); break;
case '+': whatdelay++; if (whatdelay>25) whatdelay=25; break;
case 'P': case 'p': game_paused=1;
coolbox(65,85,175,110,1,vis);
VMWtextxy("GAME PAUSED",79,95,tb1_pal[4],tb1_pal[7],
0,tb1_font,vis);
while (get_input()==0) {
usleep(30000);
}
break;
case '-': whatdelay--; if (whatdelay<1) whatdelay=1; break;
case 'S':
case 's': if(sound_possible) sound_enabled=!(sound_enabled); break;
case TB_F2: game_paused=1; savegame(*level,beginscore,beginshield);
break;
case ' ': for(j=0;j<2;j++)
if (!bullet[j].out) {
if (sound_enabled) Snd_effect(SND_CC,0);
bullet[j].out=1;
bullet[j].x=shipx+15;
bullet[j].y=165;
vmwPutSprite(shapetable[0],18,18,stride_factor,
plb_vaddr->write,bullet[j].x,
bullet[j].y,plb_vaddr->stride);
j=3;
}
}
}
/* **MOVE SHIP** */
if (speed_factor>1) shipx+=(shipadd*speed_factor);
else shipx+=shipadd;
if (shipx<1) shipx=1;
if (shipx>190) shipx=190;
switch(shipframe) {
case 1: vmwPutSprite(bigship1,48,30,stride_factor,
plb_vaddr->write,shipx,165,
plb_vaddr->stride); break;
case 3: vmwPutSprite(bigship2,48,30,stride_factor,
plb_vaddr->write,shipx,165,
plb_vaddr->stride); break;
case 2:
case 4: vmwPutSprite(bigship3,48,30,stride_factor,
plb_vaddr->write,shipx,165,
plb_vaddr->stride); break;
}
shipframe++;
if (shipframe==5) shipframe=1;
/* Flip Pages */
vmwCrossBlit(plb_vis->write,plb_vaddr->read,plb_vis->stride,200);
ggiFlush(vis);
/* Calculate how much time has passed */
gettimeofday(&timing_info,&dontcare);
time_spent=timing_info.tv_usec-oldusec;
if (timing_info.tv_sec-oldsec) time_spent+=1000000;
#ifdef DEBUG_ON
printf("%f\n",1000000/(float)time_spent);
#endif
/* If time passed was too little, wait a bit */
while (time_spent<33000){
gettimeofday(&timing_info,&dontcare);
usleep(5);
time_spent=timing_info.tv_usec-oldusec;
if (timing_info.tv_sec-oldsec) time_spent+=1000000;
}
/* It game is paused, don't keep track of time */
if (!game_paused) speed_factor=(time_spent/30000);
oldusec=timing_info.tv_usec;
oldsec=timing_info.tv_sec;
if (game_paused) {
gettimeofday(&timing_info,&dontcare);
oldusec=timing_info.tv_usec;
oldsec=timing_info.tv_sec;
game_paused=0;
}
}
/* All Done. Close up sound */
Snd_restore();
}
/* The little opener before Level 1 */
void littleopener()
{
int ship1[400],ship2[400];
int i;
char *tempst[300];
ggiSetGCForeground(vaddr,tb1_pal[0]);
ggiDrawBox(vaddr,0,0,320,200);
GGILoadPicPacked(0,0,vaddr,1,1,
tb1_data_file("moon2.tb1",(char *)tempst),
(ggi_color *)&eight_bit_pal,
(ggi_pixel *)&tb1_pal,color_depth);
GGILoadPicPacked(0,0,vis,1,0,
tb1_data_file("moon2.tb1",(char *)tempst),
(ggi_color *)&eight_bit_pal,
(ggi_pixel *)&tb1_pal,color_depth);
vmwGetSprite(vaddr,9,178,15,18,ship1);
vmwGetSprite(vaddr,30,178,15,18,ship2);
ggiSetGCForeground(vis,tb1_pal[0]);
ggiDrawBox(vaddr,0,178,319,21);
vmwCrossBlit(plb_vis->write,plb_vaddr->read,plb_vis->stride,200);
vmwCrossBlit(plb_vaddr2->write,plb_vaddr->read,plb_vaddr->stride,200);
for(i=100;i>0;i--) {
vmwArbitraryCrossBlit(plb_vaddr2->read,0,95,320,40,
plb_vaddr->write,0,95,
plb_vaddr->stride,stride_factor);
vmwPutSprite(ship2,15,18,stride_factor,
plb_vaddr->write,i*2,100,plb_vaddr->stride);
vmwArbitraryCrossBlit(plb_vaddr->read,0,95,320,40,
plb_vis->write,0,95,plb_vaddr->stride,
stride_factor);
usleep(30000);
if (get_input()!=0) break;
}
vmwCrossBlit(plb_vis->write,plb_vaddr2->read,plb_vis->stride,200);
VMWtextxy(">KCHK< TOM! WHERE ARE YOU GOING?",5,180,tb1_pal[15],tb1_pal[0],1,tb1_font,vis);
ggiFlush(vis);
pauseawhile(3);
ggiDrawBox(vis,0,178,319,21);
VMWtextxy("Ooops. ",5,180,tb1_pal[24],tb1_pal[0],1,tb1_font,vis);
pauseawhile(3);
for(i=0;i<151;i++) {
vmwArbitraryCrossBlit(plb_vaddr2->read,0,95,320,40,
plb_vaddr->write,0,95,plb_vaddr->stride,
stride_factor);
vmwPutSprite(ship1,15,18,stride_factor,
plb_vaddr->write,i*2,100,plb_vaddr->stride);
vmwArbitraryCrossBlit(plb_vaddr->read,0,95,320,40,
plb_vis->write,0,95,plb_vaddr->stride,
stride_factor);
usleep(30000);
if (get_input()!=0) break;
}
vmwCrossBlit(plb_vis->write,plb_vaddr2->read,plb_vis->stride,200);
ggiSetGCForeground(vis,tb1_pal[0]);
ggiDrawBox(vis,0,0,320,200);
GGILoadPicPacked(0,0,vis,1,0,
tb1_data_file("tbgorg.tb1",(char *)tempst),
(ggi_color *)&eight_bit_pal,
(ggi_pixel *)&tb1_pal,color_depth);
}

608
level2.c Normal file
View File

@ -0,0 +1,608 @@
/*
* Level 2 Engine Code for Tom Bombem
* */
/* The Includes */
#include <stdio.h>
#include <sys/time.h>
#include <unistd.h>
#include <ggi/libggi.h>
#include <stdlib.h>
#include "svmwgrap.h"
#include "levels.h"
#include "tblib.h"
#include "soundIt.h"
/* Define this to get a frames per second readout */
/* #define DEBUG_ON */
/* The sounds */
#define NUM_SAMPLES 4
#define SND_CC 0
#define SND_BONK 1
#define SND_KAPOW 2
#define SND_ZRRP 3
/* The global variables ;) I like global variables hehe */
extern vmw_font *tb1_font;
extern ggi_visual_t vis;
extern ggi_visual_t vaddr;
extern ggi_visual_t vaddr2;
extern ggi_color eight_bit_pal[256];
extern ggi_pixel tb1_pal[256];
extern ggi_directbuffer_t dbuf_vis;
extern ggi_directbuffer_t dbuf_vaddr;
extern ggi_directbuffer_t dbuf_vaddr2;
extern ggi_pixellinearbuffer *plb_vis;
extern ggi_pixellinearbuffer *plb_vaddr;
extern ggi_pixellinearbuffer *plb_vaddr2;
extern int sound_possible;
extern int sound_enabled;
extern int color_depth;
extern int stride_factor;
struct enemyinfo {
int x,y;
int kind;
int out,exploding,boundarycheck,dead;
int explodeprogress;
int minx,maxx,xspeed,yspeed;
int hitsneeded;
};
struct bulletinfo {
int out,x,y;
};
struct obstruction {
int x,y;
int shooting,dead,exploding;
int explodeprogress;
int howmanyhits;
int kind,lastshot;
};
/* Define how many sound effects there are */
Sample sound_effects[NUM_SAMPLES];
void leveltwoengine(int *level, int *shields, int *score)
{
int ch,i;
char tempst[300];
int k,game_paused=0,speed_factor=1;
int shipx=36;
int whatdelay=1,beginscore,beginshield;
FILE *f=NULL;
int levelover=0,j,backrow=0;
int background[201][13];
struct enemyinfo enemy[10];
struct bulletinfo bullet[4];
struct timeval timing_info;
struct timezone dontcare;
long oldsec,oldusec,time_spent;
int howmuchscroll=0;
struct obstruction passive[50];
int shipadd=0,shipframe=1;
int our_row,our_shape,rows_goneby=0;
int ship_shape[3][1600];
int shape_table[40][200];
int enemies_drawn[200];
/* Set this up for Save Game */
beginscore=*score;
beginshield=*shields;
/* Load All The Sounds */
if (sound_possible) {
Snd_loadRawSample(tb1_data_file("tbcc.raw",(char *)&tempst),
&sound_effects[0],0);
Snd_loadRawSample(tb1_data_file("tbbonk.raw",(char *)&tempst),
&sound_effects[1],0);
Snd_loadRawSample(tb1_data_file("tbkapow.raw",(char *)&tempst),
&sound_effects[2],0);
Snd_loadRawSample(tb1_data_file("tbzrrp.raw",(char *)&tempst),
&sound_effects[3],0);
/* Initialize Sound, if Possible */
if (Snd_init( NUM_SAMPLES,sound_effects,22050,4,
"/dev/dsp")==EXIT_FAILURE) {
printf("ERROR! Cannot init sound.\n");
sound_enabled=0;
}
}
/* Load Sprites (or whatever you want to call them) */
GGILoadPicPacked(0,0,vaddr,1,1,
tb1_data_file("ships.tb1",(char *)tempst),
(ggi_color *)&eight_bit_pal,
(ggi_pixel *)&tb1_pal,color_depth);
vmwGetSprite(vaddr,0,0,48,30,(int *)&ship_shape[0]);
vmwGetSprite(vaddr,0,32,48,30,(int *)&ship_shape[1]);
vmwGetSprite(vaddr,0,64,48,30,(int *)&ship_shape[2]);
if (*level==2) GGILoadPicPacked(0,0,vaddr,1,1,
tb1_data_file("tbaship.tb1",(char *)tempst),
(ggi_color *)&eight_bit_pal,
(ggi_pixel *)&tb1_pal,color_depth);
if (*level==4) GGILoadPicPacked(0,0,vaddr,1,1,
tb1_data_file("tbeerm.tb1",(char *)tempst),
(ggi_color *)&eight_bit_pal,
(ggi_pixel *)&tb1_pal,color_depth);
for(j=0;j<4;j++)
for(i=0;i<10;i++)
vmwGetSprite(vaddr,1+i*21,1+j*11,20,10,(int *)&shape_table[j*10+i]);
/* Load Background Data */
if (*level==2) f=fopen(tb1_data_file("level2.dat",(char *)tempst),"r");
if (*level==4) f=fopen(tb1_data_file("level4.dat",(char *)tempst),"r");
if (f==NULL) printf("ERROR! Could't open level %d data!\n",*level);
for(j=0;j<200;j++)
for(i=0;i<12;i++) fscanf(f,"%d",&background[j][i]);
fclose(f);
/* Initialize Structures for enemy, bullets, and background */
for(i=0;i<50;i++) {
passive[i].dead=1;
passive[i].exploding=0;
}
for(i=0;i<10;i++) enemy[i].out=0;
for(i=0;i<3;i++) {
bullet[i].out=0;
bullet[i].x=0;
bullet[i].y=0;
}
for(i=0;i<200;i++) enemies_drawn[i]=0;
/* Setup and draw the sidebar */
setupsidebar(*score,0,*shields);
ggiSetGCForeground(vis,tb1_pal[0]);
vmwCrossBlit(plb_vaddr->write,plb_vaddr2->read,plb_vaddr->stride,200);
sprintf(tempst,"%d",*level);
ggiDrawBox(vaddr2,251,52,63,7);
VMWtextxy(tempst,307,51,tb1_pal[12],tb1_pal[0],0,tb1_font,vaddr2);
/* Clear the screen and draw the stars */
ggiSetGCForeground(vaddr2,tb1_pal[0]);
ggiDrawBox(vaddr2,0,0,320,400);
for(i=0;i<100;i++) {
vmwPutSprite(shape_table[32],20,10,stride_factor,
plb_vaddr2->write,rand()%238,
rand()%400,plb_vaddr2->stride);
vmwPutSprite(shape_table[33],20,10,stride_factor,
plb_vaddr2->write,rand()%238,
rand()%400,plb_vaddr2->stride);
}
change_shields(shields);
/* Announce the Start of the Level */
ggiSetGCForeground(vis,tb1_pal[0]);
ggiDrawBox(vis,0,0,320,200);
coolbox(70,85,240,120,1,vis);
if (*level==2) {
VMWtextxy(" LEVEL TWO:",84,95,tb1_pal[4],tb1_pal[7],0,tb1_font,vis);
VMWtextxy("THE \"PEACE ENVOY\"",84,105,tb1_pal[4],tb1_pal[7],0,tb1_font,vis);
}
if (*level==4) {
VMWtextxy(" LEVEL FOUR:",84,95,tb1_pal[4],tb1_pal[7],0,tb1_font,vis);
VMWtextxy(" THE PLANET EERM",84,105,tb1_pal[4],tb1_pal[7],0,tb1_font,vis);
}
clear_keyboard_buffer();
pauseawhile(5);
gettimeofday(&timing_info,&dontcare);
oldsec=timing_info.tv_sec; oldusec=timing_info.tv_usec;
/**** GAME LOOP ****/
while (!levelover) {
ch=0;
/* Scroll the Background */
if (speed_factor>1) howmuchscroll-=speed_factor;
else howmuchscroll--;
if (howmuchscroll<0) {
howmuchscroll=200+howmuchscroll;
ggiCopyBox(vaddr2,0,0,240,200,0,200);
for(i=0;i<12;i++)
for(j=19;j>=0;j--) {
our_shape=background[backrow+(19-j)][i];
vmwPutSprite(shape_table[our_shape],
20,10,stride_factor,
plb_vaddr2->write,i*20,j*10,
plb_vaddr2->stride);
}
backrow+=20;
}
/* Setup Obstructions */
our_row=rows_goneby/10;
if (!enemies_drawn[our_row]) {
enemies_drawn[our_row]=1;
for(i=0;i<12;i++) {
our_shape=background[our_row][i];
if ((our_shape>9)&&(our_shape<20)) {
k=0;
while ((!passive[k].dead) && (k<40)) k++;
passive[k].dead=0;
passive[k].kind=our_shape;
if ((our_shape>10) && (our_shape<15)) passive[k].shooting=1;
else passive[k].shooting=0;
passive[k].exploding=0;
passive[k].x=i*20;
passive[k].y=(rows_goneby%10)-9;
passive[k].howmanyhits=1;
passive[k].lastshot=0;
}
}
}
/* Flip the far background to vaddr */
vmwArbitraryCrossBlit(plb_vaddr2->read,0,0+howmuchscroll,240,200,
plb_vaddr->write,0,0,plb_vaddr->stride,
stride_factor);
/***Collision Check***/
for(i=0;i<40;i++)
if ((!passive[i].dead) && (!passive[i].exploding)) {
for(j=0;j<3;j++) {
if ((bullet[j].out) &&
(collision(bullet[j].x,bullet[j].y,3,4,passive[i].x,
passive[i].y,10,5))){
if (passive[i].kind!=10) {
if (sound_enabled) Snd_effect(SND_KAPOW,2);
passive[i].exploding=1;
passive[i].explodeprogress=0;
bullet[j].out=0;
*score+=10;
changescore(*score,shields);
}
else {
bullet[j].out=0;
k=0;
while ((!enemy[k].out) && (k<10)) k++;
if (k<9) {
enemy[k].out=1;
enemy[k].y=bullet[j].y;
enemy[k].x=bullet[j].x;
enemy[k].yspeed=7;
enemy[k].kind=21;
}
}
}
}
/* See if ship is hitting any Obstructions*/
if ((passive[i].y>155) && (passive[i].kind!=10)) {
if ((collision(passive[i].x,passive[i].y,10,5,shipx+16,165,5,5))||
(collision(passive[i].x,passive[i].y,10,5,shipx+6,175,18,8))) {
if (sound_enabled) Snd_effect(SND_BONK,1);
passive[i].dead=1;
(*shields)--;
if(*shields<0) levelover=1;
vmwPutSprite(shape_table[34],
20,10,stride_factor,plb_vaddr2->write,
passive[i].x,passive[i].y+howmuchscroll,
plb_vaddr2->stride);
change_shields(shields);
}
}
}
/* See if hit by lasers */
for (i=0;i<10;i++)
if (enemy[i].out) {
if ((collision(enemy[i].x,enemy[i].y,2,5,shipx+16,165,5,5)) ||
(collision(enemy[i].x,enemy[i].y,2,5,shipx+6,175,18,8))) {
if (sound_enabled) Snd_effect(SND_BONK,1);
enemy[i].out=0;
(*shields)--;
if (*shields<0) levelover=1;
change_shields(shields);
}
}
/***DO EXPLOSIONS***/
for(i=0;i<40;i++)
if (passive[i].exploding) {
passive[i].explodeprogress++;
vmwPutSprite(shape_table[35+passive[i].explodeprogress],
20,10,stride_factor,plb_vaddr2->write,
passive[i].x,passive[i].y+howmuchscroll,
plb_vaddr2->stride);
if (passive[i].explodeprogress>4) {
passive[i].dead=1;
passive[i].exploding=0;
vmwPutSprite(shape_table[34],20,10,stride_factor,
plb_vaddr2->write,passive[i].x,
passive[i].y+howmuchscroll,
plb_vaddr2->stride);
}
}
/***MOVE BULLET***/
for(i=0;i<3;i++) {
if (bullet[i].out) {
if (speed_factor>1) bullet[i].y-=(5*speed_factor);
else bullet[i].y-=5;
if (bullet[i].y<5) bullet[i].out=0;
else vmwPutSprite(shape_table[20],20,10,stride_factor,
plb_vaddr->write,bullet[i].x,bullet[i].y,
plb_vaddr->stride);
}
}
/***MOVE ENEMIES***/
for(j=0;j<40;j++) {
if (!passive[j].dead) {
if (speed_factor==1) passive[j].y++;
else passive[j].y+=speed_factor;
if (passive[j].y>190) passive[j].dead=1;
}
if (passive[j].lastshot>0) passive[j].lastshot--;
if ((!passive[j].dead) && (passive[j].shooting)
&& (!passive[j].lastshot) && (passive[j].y>0)) {
k=0;
while ((enemy[k].out) && (k<10)) k++;
if (k<9) {
passive[j].lastshot=30;
enemy[k].out=1;
enemy[k].y=passive[j].y;
enemy[k].x=passive[j].x+5;
enemy[k].yspeed=5;
enemy[k].kind=25;
if (passive[j].kind==11) enemy[k].kind=26;
}
}
}
for(j=0;j<10;j++) {
if (enemy[j].out) {
vmwPutSprite(shape_table[enemy[j].kind],20,10,stride_factor,
plb_vaddr->write,enemy[j].x,enemy[j].y,
plb_vaddr->stride);
if (speed_factor==1) enemy[j].y+=enemy[j].yspeed;
else enemy[j].y+=(enemy[j].yspeed*speed_factor);
if (enemy[j].y>189) enemy[j].out=0;
}
}
/***READ KEYBOARD***/
if ((ch=get_input())!=0) {
switch(ch) {
case TB_ESC: levelover=1; break;
case TB_RIGHT: if (shipadd>=0) shipadd+=3; else shipadd=0; break;
case TB_LEFT: if (shipadd<=0) shipadd-=3; else shipadd=0; break;
case TB_F1: game_paused=1; help(); break;
case '+': whatdelay++; break;
case 'P': case 'p': game_paused=1;
coolbox(65,85,175,110,1,vis);
VMWtextxy("GAME PAUSED",79,95,tb1_pal[4],tb1_pal[7],
0,tb1_font,vis);
while (get_input()==0) usleep(30000);
break;
case '-': whatdelay--; break;
case 'S':
case 's': if(sound_possible) sound_enabled=!(sound_enabled); break;
case TB_F2: game_paused=1; savegame(*level,beginscore,beginshield);
break;
case ' ': for(j=0;j<3;j++)
if (!bullet[j].out) {
if (sound_enabled) Snd_effect(SND_CC,0);
bullet[j].out=1;
bullet[j].x=shipx+21;
bullet[j].y=165;
vmwPutSprite(shape_table[20],20,10,stride_factor,
plb_vaddr->write,bullet[j].x,
bullet[j].y,plb_vaddr->stride);
j=4;
}
}
}
/***MOVE SHIP***/
if (speed_factor>1) {
shipx+=(shipadd*speed_factor);
rows_goneby+=(speed_factor);
}
else {
shipx+=shipadd;
rows_goneby++;
}
if (shipx<1) shipx=1;
if (shipx>190) shipx=190;
switch(shipframe) {
case 1: vmwPutSprite(ship_shape[0],48,30,stride_factor,
plb_vaddr->write,shipx,165,
plb_vaddr->stride); break;
case 3: vmwPutSprite(ship_shape[1],48,30,stride_factor,
plb_vaddr->write,shipx,165,
plb_vaddr->stride); break;
case 2:
case 4: vmwPutSprite(ship_shape[2],48,30,stride_factor,
plb_vaddr->write,shipx,165,
plb_vaddr->stride); break;
}
shipframe++;
if (shipframe==5) shipframe=1;
/* Flip Pages */
vmwCrossBlit(plb_vis->write,plb_vaddr->read,plb_vis->stride,200);
ggiFlush(vis);
/* Calculate how much time has passed */
gettimeofday(&timing_info,&dontcare);
time_spent=timing_info.tv_usec-oldusec;
if (timing_info.tv_sec-oldsec) time_spent+=1000000;
#ifdef DEBUG_ON
printf("%f\n",1000000/(float)time_spent);
#endif
/* If time passed was too little, wait a bit */
while (time_spent<33000){
gettimeofday(&timing_info,&dontcare);
usleep(5);
time_spent=timing_info.tv_usec-oldusec;
if (timing_info.tv_sec-oldsec) time_spent+=1000000;
}
/* It game is paused, don't keep track of time */
if (game_paused) {
gettimeofday(&timing_info,&dontcare);
oldusec=timing_info.tv_usec;
oldsec=timing_info.tv_sec;
game_paused=0;
speed_factor=1;
}
else {
speed_factor=(time_spent/30000);
oldusec=timing_info.tv_usec;
oldsec=timing_info.tv_sec;
}
/*printf("%i\n",rows_goneby);*/
if (rows_goneby>1950) {
printf("%i\n",rows_goneby);
/*
clearkeyboardbuffer;
pauseawhile(200);
fade;
grapherror:=Mode13LoadPicPacked(0,0,vaddr,false,true,'viewscr.tb1');
cls(0,vga);
blockmove(0,79,58,116,vaddr,10,10,vga);
clearkeyboardbuffer;
outsmalltextxy('UNIDENTIFIED SPACECRAFT!',70,10,2,0,vga,true);
outsmalltextxy('DO YOU WISH TO DEACTIVATE ',70,20,2,0,vga,true);
outsmalltextxy('THIS SHIP''S SECURITY SYSTEMS? (Y/N)',70,30,2,0,vga,true);
unfade;
clearkeyboardbuffer;
ch:='!';
repeat
if keypressed then ch:=readkey;
until (upcase(ch)='Y') or (upcase(ch)='N');
if upcase(ch)='N' then begin
blockmove(0,79,58,116,vaddr,10,50,vga);
outsmalltextxy('NO? AFFIRMATIVE. ',70,50,9,0,vga,true);
outsmalltextxy('ARMING REMOTE DESTRUCTION RAY.',70,60,9,0,vga,true);
outsmalltextxy('GOOD-BYE.',70,70,9,0,vga,true);
pauseawhile(400);
fade;
end;
if upcase(ch)='Y' then begin
blockmove(0,79,58,116,vaddr,10,50,vga);
outsmalltextxy('"Y"=CORRECT PASSWORD. ',70,50,2,0,vga,true);
outsmalltextxy('WELCOME SUPREME TENTACLEE COMMANDER.',70,60,2,0,vga,true);
outsmalltextxy('INITIATING TRACTOR BEAM AND AUTOMATIC',70,70,2,0,vga,true);
outsmalltextxy('LANDING PROCEDURE.',70,80,2,0,vga,true);
outsmalltextxy('WE WILL BE DEPARTING FOR THE PLANET',70,90,2,0,vga,true);
outsmalltextxy('EERM IN THREE MICROCYCLE UNITS.',70,100,2,0,vga,true);
pauseawhile(550);
level:=3;
clearkeyboardbuffer;
blockmove(0,42,58,79,vaddr,10,110,vga);
outsmalltextxy('Wha? Wait!',70,110,9,0,vga,true);
outsmalltextxy('What''s happening?',70,120,9,0,vga,true);
pauseawhile(550);
fade;
end;
grapherror:=Mode13LoadPicPacked(0,0,vaddr,false,true,'tbtract.tb1');
for i:=0 to 239 do
for j:=0 to 49 do
putpixel240(i,j,getpixel(i,j,vaddr),vaddr2);
cls(0,vga);
unfade;
for howmuchscroll:=50 downto 1 do begin
flipd240(howmuchscroll,vaddr,vaddr2);
putshape (bigship3off,vaddr,43,30,shipx,165);
waitretrace;
flipd320(vaddr,vga);
end;
if upcase(ch)='N' then begin
clearkeyboardbuffer;
line(7,6,shipx+10,180,4,vga);
line(shipx+37,180,231,6,4,vga);
pauseawhile(50);
clearkeyboardbuffer;
for i:=shipx to shipx+48 do
verticalline(165,195,i,4,vga);
pauseawhile(200);
flipd240(howmuchscroll,vaddr,vaddr2);
flipd320(vaddr,vga);
pauseawhile(150);
end;
if upcase(ch)='Y' then begin;
shipadd:=sgn(shipx-95);
shipy:=165;
repeat
if shipx<>95 then shipx:=shipx-shipadd;
if shipy>9 then dec(shipy);
flipd240(howmuchscroll,vaddr,vaddr2);
line(7,6,shipx+10,shipy+15,2,vaddr);
line(shipx+37,shipy+15,231,6,2,vaddr);
putshape (bigship3off,vaddr,43,30,shipx,shipy);
waitretrace;
flipd320(vaddr,vga);
until (shipx=95) and (shipy=9);
clearkeyboardbuffer;
pauseawhile(850);
fade;
cls(0,vga);
while keypressed do ch:=readkey;
if level=4 then begin
outsmalltextxy('THE PLANET EERM?',20,20,10,0,vga,true);
outsmalltextxy('XENOCIDE FLEET?',20,30,10,0,vga,true);
outsmalltextxy('WHAT''S GOING ON?',20,40,10,0,vga,true);
outsmalltextxy('A MAJOR GOVERNMENT CONSPIRACY? MASS HALUCINATIONS?',20,50,10,0,vga,true);
outsmalltextxy('WATCH FOR TOM BOMBEM LEVEL 3 (CURRENTLY IN THE DESIGN PHASE).',10,70,12,0,vga,true);
outsmalltextxy('ALL THESE QUESTIONS WILL BE ANSWERED!',10,80,12,0,vga,true);
outsmalltextxy('ALSO MORE FEATURES WILL BE ADDED:',10,90,12,0,vga,true);
outsmalltextxy(' BETTER GRAPHICS, SOUND AND SPEED.',10,100,12,0,vga,true);
outsmalltextxy('TO HASTEN COMPLETION, SEND QUESTIONS/COMMENTS/DONATIONS TO ',9,120,9,0,vga,true);
outsmalltextxy('THE AUTHOR (SEE THE REGISTER MESSAGE FOR RELEVANT ADDRESSES).',9,130,9,0,vga,true);
outsmalltextxy('THANK YOU FOR PLAYING TOM BOMBEM',80,150,14,0,vga,true);
unfade;
pauseawhile(1800);
end; */
levelover=1;
}
}
Snd_restore();
}
void littleopener2()
{
char tempst[300];
ggiSetGCForeground(vis,tb1_pal[0]);
ggiDrawBox(vis,0,0,320,200);
ggiSetGCForeground(vaddr,tb1_pal[0]);
ggiDrawBox(vaddr,0,0,320,200);
GGILoadPicPacked(0,0,vis,1,1,
tb1_data_file("tbl2ship.tb1",(char *)tempst),
(ggi_color *)&eight_bit_pal,
(ggi_pixel *)&tb1_pal,color_depth);
VMWtextxy("Hmmmm... ",10,10,tb1_pal[4],tb1_pal[0],0,tb1_font,vis);
VMWtextxy("This Might Be Harder Than I Thought.",10,20,tb1_pal[4],tb1_pal[0],0,tb1_font,vis);
pauseawhile(13);
ggiSetGCForeground(vis,tb1_pal[0]);
ggiDrawBox(vis,0,0,320,200);
}

4
levels.h Normal file
View File

@ -0,0 +1,4 @@
void levelone(int *level, int *shields,int *score);
void littleopener();
void leveltwoengine(int *level, int *shields, int *score);
void littleopener2();

4142
procs.c Normal file

File diff suppressed because it is too large Load Diff

713
soundIt.c Normal file
View File

@ -0,0 +1,713 @@
/* SoundIt library 0.04
Copyright 1994 Brad Pitzel pitzel@cs.sfu.ca
Adapted to Solaris/SunOS and HPUX by Peter Ekberg.
Feel free to use/distribute/modify as long as proper credits
are included.
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#if defined(HAVE_LINUX_SOUND)
# include <linux/soundcard.h>
#elif defined(HAVE_SUN_SOUND)
# if defined(HAVE_SYS_AUDIOIO_H)
# include <sys/audioio.h>
# elif defined(HAVE_SUN_AUDIOIO_H)
# include <sun/audioio.h>
# endif
#elif defined(HAVE_HP_SOUND)
# include <sys/audio.h>
#endif
#include "soundIt.h"
#include <malloc.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
/*==========================================================================*/
/* the mix buff, where the channels are mixed into. The mix buffer is then
dumped to the sound device (/dev/dsp). Samples are mixed in
Vunclipbuf (buffer of ints), then the values in Vunclipbuf are clipped to
values between 0 and 255, and stored into Vclippedbuf (buffer of unsigned
chars).
*/
typedef struct {
#if defined(HAVE_LINUX_SOUND)
unsigned char *Vclippedbuf;
#elif defined(HAVE_16BIT_SOUND)
short *Vclippedbuf;
#endif
int *Vunclipbuf;
int Vsize;
} Mix;
/*==========================================================================*/
typedef struct {
unsigned char *Vstart, *Vcurrent; /* ptr's into a playing sample */
int Vlen; /* length of sample in bytes */
int Vleft; /* bytes left of sample to play */
int Vloop; /* loop=0 : play sample once */
/* loop=1 : loop sample */
} Channel;
/*==========================================================================*/
/* variables prefixed with S_ are static */
/* 0 if mixer isn't initialized or init failed, 1 if mixer is good */
static int S_mixerStatus = 0;
static const Sample *S_sounds = NULL; /* ptr to array of samples */
static int S_num_sounds = 0; /* size of 'sounds' array above */
static int S_fd_snddev = -1; /* file # for sound device once open */
static int S_fd_pipe[2] = { -1, -1 }; /* pipe to talk to child process */
static int S_son_pid = -1; /* process ID for the forked sound mixer */
static const char *S_snddev = NULL; /* char string for device, ie "/dev/dsp" */
static int S_num_channels = 6; /* number of channels to mix */
static int S_playback_freq = 0; /* playback frequency (in Hz) */
/*==========================================================================*/
/* non-public functions, used only within this file*/
int Snd_init_dev(void);
int Snd_restore_dev(void);
void Chan_reset(Channel *chan); /* init channel structure */
/* start a sample playing on a channel */
void Chan_assign(Channel *chan, const Sample *snd);
/* mix all channels together into the 'mix' structure */
int Chan_mixAll(Mix *mix, Channel *ch);
/* used by Chan_mixAll to mix the 1st channel */
int Chan_copyIn(Channel *chan, Mix *mix);
/* used by Chan_mixAll to mix a loop in the 1st channel */
int Chan_copyIn_loop(Channel *chan, Mix *mix);
/* used by Chan_mixAll to mix the middle channels */
int Chan_mixIn(Channel *chan, Mix *mix);
/* used by Chan_mixAll to mix the last channel */
int Chan_finalMixIn(Channel *chan, Mix *mix);
/* alloc mem for mix buffer, and deallocate function */
/* The sound channels are mixed together into the mix buffer */
/* then the mix buffer data is sent directly to the sound device */
void Mix_alloc(Mix *mix, int size);
void Mix_dealloc(Mix *mix);
/*==========================================================================*/
/* justing for testing, normally not called */
void
dump_snd_list(void)
{
int i=0;
for(i=0; i<S_num_sounds; i++) {
printf("snd %d: len = %d \n", i, S_sounds[i].len );
}
}
/*==========================================================================*/
int
Snd_init(int num_snd, const Sample *sa, int frequency,
int channels, const char *dev)
{
int result;
S_num_sounds = num_snd;
S_sounds = sa; /* array of sound samples*/
S_playback_freq = frequency;
S_num_channels = channels;
S_snddev= dev; /* sound device, eg /dev/dsp*/
if (S_sounds==NULL)
return EXIT_FAILURE;
result=Snd_init_dev();
if (result==EXIT_SUCCESS) {
S_mixerStatus=1;
}
else {
S_mixerStatus=0;
}
return result;
}
/*==========================================================================*/
int
Snd_restore(void)
{
int result;
if(!S_mixerStatus)
return EXIT_FAILURE;
result=Snd_restore_dev();
if (result==EXIT_SUCCESS) {
S_mixerStatus=0;
}
else {
S_mixerStatus=0;
}
return result;
}
/*==========================================================================*/
/* volume control not implemented yet.*/
int
Snd_effect(int sound_num, int channel)
{
if(!S_mixerStatus)
return EXIT_FAILURE;
/* make sure a valid sound # was passed in */
if(sound_num<0 || sound_num>=S_num_sounds)
return EXIT_FAILURE;
/* make sure a valid channel # was passed in */
if(channel<0 || channel>=S_num_channels)
return EXIT_FAILURE;
if(S_sounds[sound_num].data != NULL) {
write(S_fd_pipe[1], &sound_num, sizeof(sound_num));
write(S_fd_pipe[1], &channel, sizeof(channel));
}
else {
fprintf(stderr,"Referencing NULL sound entry\n");
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
/*============================================================================*/
int
Snd_init_dev(void)
{
int whoami;
S_fd_snddev = -1;
S_son_pid = 0;
if(access(S_snddev,W_OK) != 0) {
perror("no access to sound device");
return EXIT_FAILURE;
}
S_fd_snddev = open(S_snddev,O_WRONLY);
if(S_fd_snddev < 0) {
perror("cannot open sound device");
return EXIT_FAILURE;
}
close(S_fd_snddev);
if(pipe(S_fd_pipe) < 0) {
perror("cannot create pipe for sound control");
return EXIT_FAILURE;
}
/* now setup 2nd process for writing the data... */
if((whoami = fork()) < 0) {
perror("cannot fork sound driver\n");
return EXIT_FAILURE;
}
if(whoami != 0) { /* successfully created son */
close(S_fd_pipe[0]); /* close end for reading */
S_son_pid = whoami;
return EXIT_SUCCESS;
}
/* Here is the code for the son... */
{
int sound_num,ch,i;
struct timeval tval = {0L,0L};
fd_set readfds,dsp;
Mix mix;
int fragsize;
Channel *chan;
chan = (Channel *)malloc(sizeof(Channel) * S_num_channels);
for(i=0; i<S_num_channels; i++)
Chan_reset( chan+i );
S_fd_snddev = open(S_snddev,O_WRONLY);
if(S_fd_snddev < 0) {
perror("Cannot open sound device");
exit(1);
}
#if defined(HAVE_LINUX_SOUND)
{
int frag;
frag = FRAG_SPEC; /*defined in soundIt.h */
ioctl(S_fd_snddev, SNDCTL_DSP_SETFRAGMENT, &frag);
if(ioctl(S_fd_snddev,SNDCTL_DSP_SPEED, &S_playback_freq)==-1)
perror("Sound driver ioctl");
fragsize=0;
if(ioctl(S_fd_snddev,SNDCTL_DSP_GETBLKSIZE, &fragsize)==-1)
perror("Sound driver ioctl");
}
#elif defined(HAVE_SUN_SOUND)
{
audio_info_t ainfo;
AUDIO_INITINFO(&ainfo);
ainfo.play.precision = 16;
ainfo.play.sample_rate = S_playback_freq;
ainfo.play.encoding = AUDIO_ENCODING_LINEAR;
ainfo.play.channels = 1;
ainfo.play.port = AUDIO_LINE_OUT|AUDIO_HEADPHONE|AUDIO_SPEAKER;
if(ioctl(S_fd_snddev,AUDIO_SETINFO, &ainfo)==-1)
perror("Sound driver ioctl");
fragsize=512;
}
#elif defined(HAVE_HP_SOUND)
{
struct audio_describe adescribe;
struct audio_gain again;
struct audio_limits alimits;
int i;
int best_rate;
int temp;
if(ioctl(S_fd_snddev, AUDIO_DESCRIBE, &adescribe)==-1)
perror("Sound driver ioctl: Audio Describe");
/*
printf("Audio Device: ");
switch(adescribe.audio_id) {
case AUDIO_ID_PSB2160:
printf("PSB 2160\n");
break;
case AUDIO_ID_CS4215:
printf("CS 4215\n");
break;
default:
printf("Unknown\n");
break;
}
printf("Samplerates:");
for(i=0; i<adescribe.nrates; i++)
printf(" %d", adescribe.sample_rate[i]);
printf("\nMax bits per sample: %d\n", adescribe.max_bits_per_sample);
printf("Channels: %d\n", adescribe.nchannels);
*/
if(adescribe.max_bits_per_sample < 16)
printf("Not enough bits\n");
temp = AUDIO_FORMAT_LINEAR16BIT;
if(ioctl(S_fd_snddev, AUDIO_SET_DATA_FORMAT, temp)==-1)
perror("Sound driver ioctl: Audio Set Data Format");
best_rate = 0;
for(i=0; i<adescribe.nrates; i++)
if(abs(adescribe.sample_rate[i]-S_playback_freq)
< abs(best_rate-S_playback_freq))
best_rate = adescribe.sample_rate[i];
if(abs(best_rate-S_playback_freq) > 1050)
printf("No good sample rate\n");
if(ioctl(S_fd_snddev, AUDIO_SET_SAMPLE_RATE, best_rate)==-1)
perror("Sound driver ioctl: Audio Set Sample Rate");
/* AUDIO_OUT_LINE | AUDIO_OUT_INTERNAL | AUDIO_OUT_EXTERNAL */
if(ioctl(S_fd_snddev, AUDIO_SET_OUTPUT, AUDIO_OUT_EXTERNAL)==-1)
perror("Sound driver ioctl: Audio Set Output");
again.cgain[0].transmit_gain = AUDIO_MAX_GAIN;
again.cgain[0].monitor_gain = AUDIO_OFF_GAIN;
again.cgain[1].transmit_gain = AUDIO_MAX_GAIN;
again.cgain[1].monitor_gain = AUDIO_OFF_GAIN;
again.channel_mask = AUDIO_CHANNEL_LEFT | AUDIO_CHANNEL_RIGHT;
if(ioctl(S_fd_snddev, AUDIO_SET_GAINS, &again)==-1)
perror("Sound driver ioctl: Audio Set Gain");
/*
alimits.max_transmit_buffer_size = 512;
alimits.max_receive_buffer_size = 512;
if(ioctl(S_fd_snddev, AUDIO_SET_LIMITS, &alimits)==-1)
perror("Sound driver ioctl: Audio Set Limits");
if(ioctl(S_fd_snddev, AUDIO_GET_LIMITS, &alimits)==-1)
perror("Sound driver ioctl: Audio Get Limits");
fragsize=alimits.max_transmit_buffer_size;
*/
fragsize = 1024;
}
#endif
/*printf("after: block size: %d \n", fragsize);*/
/* init mixer object*/
Mix_alloc(&mix, fragsize);
close(S_fd_pipe[1]); /* close end for writing */
FD_ZERO(&dsp);
FD_SET(S_fd_snddev, &dsp);
FD_ZERO(&readfds);
FD_SET(S_fd_pipe[0], &readfds);
/* printf("soundIt library v"SOUNDIT_VERS" initialized.\n");*/
for(;;) {
FD_SET(S_fd_pipe[0], &readfds);
tval.tv_sec=0L;
tval.tv_usec=0L;
select(S_fd_pipe[0]+1, &readfds,NULL,NULL,&tval);
if(FD_ISSET(S_fd_pipe[0], &readfds)) {
if(read(S_fd_pipe[0], &sound_num, sizeof(int))==0)
break;
read(S_fd_pipe[0], &ch, sizeof(int));
/*printf("chan=%d snd=%d len=%d\n",
ch, sound_num, S_sounds[sound_num].len);*/
Chan_assign(&(chan[ch]), &(S_sounds[sound_num]));
}
Chan_mixAll(&mix,chan);
#if defined(HAVE_LINUX_SOUND)
write(S_fd_snddev, mix.Vclippedbuf, fragsize);
#elif defined(HAVE_SUN_SOUND)
{
int stat;
audio_info_t ainfo;
static unsigned int samplecount=0;
do {
stat = ioctl(S_fd_snddev, AUDIO_GETINFO, &ainfo);
if(samplecount-ainfo.play.samples<fragsize)
stat = 1;
} while(!stat);
write(S_fd_snddev, (char *)mix.Vclippedbuf, sizeof(short)*fragsize);
samplecount+=fragsize;
}
#elif defined(HAVE_HP_SOUND)
{
struct audio_status astatus;
int stat;
do {
stat = ioctl(S_fd_snddev, AUDIO_GET_STATUS, &astatus);
if(astatus.transmit_exact_count<2*fragsize)
stat = 1;
} while(!stat);
write(S_fd_snddev, (char *)mix.Vclippedbuf, sizeof(short)*fragsize);
}
#endif
}
Mix_dealloc( &mix );
/* printf("soundIt process exiting.\n");*/
close(S_fd_pipe[0]);
close(S_fd_pipe[1]);
exit (0);
} /* end of child process */
}
/*==========================================================================*/
int
Snd_restore_dev(void)
{
close(S_fd_pipe[0]);
close(S_fd_pipe[1]);
/* wait for child process to die*/
wait(NULL);
return EXIT_SUCCESS;
}
/*==========================================================================*/
/* CHANNEL MIXING FUNCTIONS */
/*==========================================================================*/
void
Chan_reset(Channel *chan)
{
chan->Vstart=NULL;
chan->Vcurrent=NULL;
chan->Vlen=0;
chan->Vleft=0;
chan->Vloop=0;
}
/*==========================================================================*/
void
Chan_assign(Channel *chan, const Sample *snd)
{
chan->Vstart = snd->data;
chan->Vcurrent= chan->Vstart;
chan->Vlen = snd->len;
chan->Vleft = snd->len;
chan->Vloop = snd->loop;
}
/*==========================================================================*/
int
Chan_copyIn(Channel *chan, Mix *mix)
{
int i, *p = mix->Vunclipbuf, result, min;
result = (chan->Vleft>0) ? 1 : 0;
min = (chan->Vleft < mix->Vsize) ? chan->Vleft : mix->Vsize;
for(i=0; i<min; i++) {
*p++ = (int)*chan->Vcurrent++;
}
chan->Vleft -= i;
/* fill the remaining (if any) part of the mix buffer with silence */
while(i<mix->Vsize) {
*p++ = 128;
i++;
}
return result;
}
/*==========================================================================*/
int
Chan_copyIn_loop(Channel *chan, Mix *mix)
{
int i=0;
int *p = mix->Vunclipbuf;
int left_mix_vsize=mix->Vsize;
if (chan->Vleft==0)
chan->Vleft=chan->Vlen;
if(left_mix_vsize > chan->Vleft) {
/* fill the rest of the sample first */
for(i=0; i<chan->Vleft; i++)
*p++ = (int)*chan->Vcurrent++;
left_mix_vsize -= chan->Vleft;
chan->Vleft = chan->Vlen;
/* loop the sample by writing it repeatedly */
while(left_mix_vsize > chan->Vlen) {
chan->Vcurrent=chan->Vstart;
for(i=0; i<chan->Vleft; i++)
*p++ = (int) *chan->Vcurrent++;
left_mix_vsize-=chan->Vlen;
}
/* Return to the start of the Sample */
chan->Vcurrent=chan->Vstart;
/* If there is some space left, then fill it up :-) */
for(i=0;i<left_mix_vsize;i++)
*p++=(int)*chan->Vcurrent++;
chan->Vleft=chan->Vlen - left_mix_vsize;
}
else {
/* fill in all that fits, no looping to be done ! */
for(i=0; i<mix->Vsize; i++)
*p++ = (int) *chan->Vcurrent++;
chan->Vleft -= i;
}
return 1;
}
/*==========================================================================*/
int
Chan_mixIn(Channel *chan, Mix *mix)
{
int i,*p = mix->Vunclipbuf, result, min;
result = (chan->Vleft>0) ? 1 : 0;
min = (chan->Vleft < mix->Vsize) ? chan->Vleft : mix->Vsize;
for(i=0; i<min; i++)
*p++ += (int)(*chan->Vcurrent++) - 128;
chan->Vleft -= i;
return result;
}
/*========================================================================*/
/* clip an int to a value between 0 and 255 */
#ifdef HAVE_16BIT_SOUND
/*
static inline short
clip(int i)
{
return ((i<0) ? 0 : ( (i>255) ? 255 : i )) * 257 - 32768;
}
*/
#define clip(i) ((short)((((i)<0) ? 0 : ( ((i)>255) ? 255 : (i) )) * 257 - 128*257))
#else
static inline unsigned char
clip(int i)
{
return (i<0) ? 0 : ( (i>255) ? 255 : i );
}
#endif
/*==========================================================================*/
int
Chan_finalMixIn(Channel *chan, Mix *mix)
{
int i;
int *p = mix->Vunclipbuf, result, min;
#ifdef HAVE_16BIT_SOUND
short *final = mix->Vclippedbuf;
#else
unsigned char *final = mix->Vclippedbuf;
#endif
result = (chan->Vleft>0) ? 1 : 0;
min = (chan->Vleft < mix->Vsize) ? chan->Vleft : mix->Vsize;
for(i=0; i<min; i++) {
*p += (int)(*chan->Vcurrent++) - 128;
*final++ = clip(*p);
p++;
}
chan->Vleft -= i;
/* copy rest of Vunclipbuf over to Vclippedbuf */
while (i<mix->Vsize) {
*final++ = clip(*p);
p++;
i++;
}
return result;
}
/*==========================================================================*/
void
Mix_alloc(Mix *mix, int size)
{
#ifdef HAVE_16BIT_SOUND
mix->Vclippedbuf = (short *)calloc( sizeof(short), size);
#else
mix->Vclippedbuf = (unsigned char *)calloc( sizeof(char), size);
#endif
mix->Vunclipbuf = (int *)calloc( sizeof(int), size);
mix->Vsize = size;
if((mix->Vclippedbuf==NULL) || (mix->Vunclipbuf==NULL)) {
printf("Unable to allocate memory for mixer buffer.\n");
exit(-1);
}
}
/*==========================================================================*/
void
Mix_dealloc(Mix *mix)
{
if(mix->Vclippedbuf)
free(mix->Vclippedbuf);
if(mix->Vunclipbuf)
free(mix->Vunclipbuf);
}
/*==========================================================================*/
/* Mixes together the channels into one sound.
Returns # of channels currently playing *any* sound
Therefore, return 0 means to channels have a sample, therefore no
sound is playing
*/
int
Chan_mixAll(Mix *mix, Channel *chan)
{
int result=0, i=0;
/* Loop in the first channel ? */
if (chan->Vloop==0)
result = Chan_copyIn(chan, mix);
else
result = Chan_copyIn_loop(chan, mix);
/* we want to loop for S_num_channels-2 */
for(i=2; i<S_num_channels; i++)
result += Chan_mixIn(++chan, mix);
result += Chan_finalMixIn(++chan, mix);
return result;
}
/*==========================================================================*/
/* given the name of a .raw sound file, load it into the Sample struct */
/* pointed to by 'sample' */
/* Returns -1 couldn't open/read file */
/* -2 couldn't alloc memory) */
int
Snd_loadRawSample(const char *file, Sample *sample, int loop)
{
FILE *fp;
sample->data = NULL;
sample->len = 0;
sample->loop = loop;
fp = fopen(file,"r");
if(fp==NULL)
return -1;
/* get length of the file */
sample->len = lseek(fileno(fp), 0, SEEK_END);
/* go back to beginning of file */
lseek(fileno(fp), 0, SEEK_SET);
/* alloc memory for sample */
sample->data = (unsigned char *)malloc(sample->len);
if(sample->data==NULL) {
fclose(fp);
return -2;
}
fread(sample->data, 1, sample->len, fp);
fclose(fp);
return 0;
}

91
soundIt.h Normal file
View File

@ -0,0 +1,91 @@
/* SoundIt library 0.04
Copyright 1994 Brad Pitzel pitzel@cs.sfu.ca
Adapted to Solaris/SunOS by Peter Ekberg.
Feel free to use/distribute/modify as long as proper credits
are included.
*/
/* Designed for digital sound effects in interactive apps (games, drum
machines, digital organs, ???)
Will mix channels of mono 8-bit raw samples, & play back in "real-time".
Each channel can only play one sample at a time, but all
channels can play a different sample simultaneously.
If you have sox, use the ' -t .ub ' option to make samples
that this library will play properly.
*/
#ifndef SOUNDIT_VERS
#define SOUNDIT_VERS "0.04"
#include <stdlib.h>
#include <stdio.h>
#ifndef EXIT_FAILURE
#define EXIT_FAILURE 1
#endif
#ifndef EXIT_SUCCESS
#define EXIT_SUCCESS 0
#endif
/* 00002 = 2 fragments */
/* 00007 = means each fragment is 2^7 or 128 bytes */
/* See voxware docs (in /usr/src/linux/drivers/sound) for more info */
#define FRAG_SPEC 0x00020007
/*==========================================================================*/
typedef struct {
unsigned char *data; /* unsigned 8-bit raw samples */
int len; /* length of sample in bytes */
int loop; /* loop=0 : play sample once, */
/* loop=1 : loop sample */
} Sample;
void dump_snd_list(void);
/*==========================================================================*/
/* given the name of a .raw sound file, load it into the Sample struct */
/* pointed to by 'sample' */
int
Snd_loadRawSample(const char *file, Sample *sample, int loop);
/*==========================================================================*/
/* init sound device, etc.. */
/* num_snd = the number of samples in the sample array *sa */
/* sa = the sample array */
/* freq = the rate (Hz) to play back the samples */
/* channels = # of channels to mix */
/* sound_device = a char string for the sound device, eg, "/dev/dsp" */
/* returns: 0=success, -1=failure.*/
int
Snd_init(int num_snd, const Sample *sa, int freq,
int channels, const char *sound_device);
/* shutdown sample player, free mem, etc/etc..*/
int
Snd_restore(void);
/* play a sound effect in the given channel 1..n*/
/* volume = integers from 0 (off) to 100 (full volume)*/
int
Snd_effect(int nr, int channel);
/* stop a channel (1..n) from playing*/
/*void
Snd_reset(enum snd_channel channel);*/
/* stop all channels from playing*/
/*void
Snd_reset(void);*/
#endif

799
svmwgrap.c Normal file
View File

@ -0,0 +1,799 @@
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <ggi/libggi.h>
/*var unfadered:array[0..255] of byte;
unfadeblue:array[0..255] of byte;
unfadegreen:array[0..255] of byte;
fontline:array[0..255] of byte;
charset:array[0..255,0..15] of byte;
charheight:byte;
fontseg,fontoff:word;
*/
typedef struct {
char *font_data;
int width;
int height;
int numchars;
} vmw_font;
int vmwCrossBlit(char *dest,char *src,int stride,int ysize)
{
int y;
for (y = 0; y < ysize; y++) {
memcpy (dest, src, stride);
src += stride;
dest += stride;
}
return 0;
}
int vmwCrossBlit240(char *dest,char *src,int stride,int stride_factor,
int ysize)
{
int y;
for (y = 0; y < ysize; y++) {
memcpy (dest, src, (240*stride_factor));
src += stride;
dest += stride;
}
return 0;
}
int vmwArbitraryCrossBlit(char *src,int x1,int y1,int w,int h,
char *dest,int x2,int y2,int stride,
int stride_factor)
{
int y;
src+=(stride*y1);
dest+=(stride*y2);
for(y=0;y<h;y++) {
memcpy ((dest+x2),(src+x1),(w*stride_factor));
src+=stride;
dest+=stride;
}
return 0;
}
int vmwPutSprite(int *src,int w,int h,int stride_factor,
char *dest,int x,int y,int dest_stride)
{
int xx,yy;
dest+=(dest_stride*y);
for(yy=0;yy<h;yy++){
for(xx=0;xx<w;xx++)
if(*(src+xx)) memcpy(dest+(stride_factor*(xx+x)),(src+xx),stride_factor);
/**(dest+xx+x)=15;*/
src+=w;
dest+=dest_stride;
}
return 0;
}
int vmwGetSprite(ggi_visual_t visual,int x,int y,int w,int h,
int *sprite)
{
int width,xx;
xx=x;
while(h--) {
x=xx;width=w;
while(width--) ggiGetPixel(visual,x++,y,sprite++);
y++;
}
return 0;
}
/*
int vmwPutSprite(ggi_visual_t visual,int x,int y,int w,int h,
int transparent_color,int *sprite)
{
int width,xx;
xx=x;
while(h--) {
x=xx; width=w;
while(width--){
if ( *(sprite)!=transparent_color )
ggiPutPixel(visual,x,y,*(sprite));
x++;
sprite++;
}
y++;
}
return 0;
}
*/
/*
function Mode13SavePicPacked(x1,y1,x2,y2,numcolors:integer;where:word;filename:string):byte;
function Mode13LoadPicPacked(x1,y1:integer;where:word;LoadPal,LoadPic:boolean;FileName:string):byte;
procedure cls32(col:byte;where:word);
procedure flipd320(source,dest:word);
procedure flipd240(hm,va,va2:word);
procedure flipd50(fromwhere,off1,whereto,off2:word);
Procedure SetMCGA;
Procedure SetText; { This procedure returns you to text mode. }
Procedure LoadFont(namest:string);
Procedure Putpixel (X,Y : Integer; Col : Byte; where:word);
Procedure Putpixel240 (X,Y : Integer; Col : Byte; where:word);
function getpixel(x,y,where:word):byte;
Procedure Pal(Col,R,G,B : Byte);
Procedure GetPal(Col : Byte; Var R,G,B : Byte);
procedure WaitRetrace;
procedure outtextlineover(st:string;x,y:integer;col,background:byte;line:integer;where:word);
procedure outtextline(st:string;x,y:integer;col,background:byte;line:integer;where:word);
procedure outtextxy(st:string;x,y,col,background:integer;where:word;overwrite:boolean);
procedure outsmalltextlineover(st:string;x,y:integer;col,background:byte;line:integer;where:word);
procedure outsmalltextline(st:string;x,y:integer;col,background:byte;line:integer;where:word);
procedure outsmalltextxy(st:string;x,y,col,background:integer;where:word;overwrite:boolean);
function sgn(a:real):integer;
procedure line(a,b,c,d,col:integer;where:word);
procedure horizontalline(FromX1,ToX2,AtY,col:integer;where:word);
procedure verticalline(FromY1,ToY2,AtX,col:integer;where:word);
procedure fade;
procedure unfade;
procedure box(x1,y1,x2,y2,col:integer;where:word);
procedure vdelay(howlong:integer);
procedure setupvmwgraph;
procedure setuptb1;
{Errors: 0=No Errors
1=File Not Found
2=Not a Paintpro File (no PAINTPROVX.XX header)
3=Improper Version (less then 6)
}
*/
int GGILoadPicPacked(int x1,int y1,ggi_visual_t vis
,int LoadPal,int LoadPic,char *FileName,
ggi_color *eight_bit_pal,ggi_pixel *tb1_pal,
int color_depth)
/*Loads a paintpro image, filename, at location x1,y1 *\
\*to offset where (vga=$A000) and loadspal if LOADPAL=true */
/*Loadsapicture if Loadpic=true and returns error} */
{
unsigned char temp1,temp2,temp3;
int errorlev;
int int1,int2,i,x,y;
char buffer[300];
int lastread=0;
int buffpointer=0;
int picwidth,picheight;
FILE *fff;
char header[10];
int xsize;
int ysize;
int numcolors;
int col,numacross;
/* Open the file */
fff=fopen(FileName,"rb");
if (fff==NULL){
printf("PPRO error... File \"%s\" not found.\n",FileName);
exit(1);
}
errorlev=fread(buffer,1,300,fff);
/* Check to see if its really a Paintpro File */
for (i=0;i<9;i++) {
header[i]=buffer[i];
}
header[9]='\0';
if (strcmp(header,"PAINTPROV")) {
printf("PPRO error... %s is NOT a paintpro file!\n",FileName);
exit(2);
}
/*printf("Paintpro Confirmed\n");*/
/* Check to see if it is the proper version (currently 6.0) */
header[0]=buffer[9];
header[1]=buffer[10];
header[2]=buffer[11];
header[3]='\0';
if (strcmp(header,"6.0")) {
printf("PPRO error... Version %s unsupported, must be >6\n",header);
exit(3);
}
buffpointer=12;
/* Read X and Y sizes */
temp1=buffer[buffpointer];
temp2=buffer[buffpointer+1];
temp3=buffer[buffpointer+2];
buffpointer+=3;
if (buffpointer>=errorlev) {
printf("PPRO error... Early end of file.\n");
exit(3);
}
xsize=(temp2>>4)+(temp1<<4);
ysize=((temp2-((temp2>>4)<<4))<<16)+temp3;
/* being old 6 bytes 2 two int*/
temp1=buffer[buffpointer];
temp2=buffer[buffpointer+1];
temp3=buffer[buffpointer+2];
buffpointer+=3;
if (buffpointer>=errorlev) {
printf("PPRO error... Early end of file.\n");
exit(3);
}
numcolors=(temp2>>4)+(temp1<<4);
/*int2=((temp2-((temp2>>4)<<4))*256)+temp3;*/
picwidth=xsize+1;
picheight=ysize+1;
/*Load Palette*/
if (numcolors!=256) printf("%d colors is not supported yet.\n",numcolors);
for (i=0;i<256;i++) {
eight_bit_pal[i].r=(buffer[buffpointer]*0x100);
eight_bit_pal[i].g=(buffer[buffpointer+1]*0x100);
eight_bit_pal[i].b=(buffer[buffpointer+2]*0x100);
buffpointer+=3;
if (buffpointer>=errorlev) {
if (errorlev==300) {
errorlev=fread(buffer,1,300,fff);
buffpointer=0;
}
else {
lastread=1;
}
}
}
if(LoadPal) {
if(color_depth!=8) {
for(i=0;i<256;i++)
tb1_pal[i]=ggiMapColor(vis,&eight_bit_pal[i]);
}
else {
for(i=0;i<256;i++) tb1_pal[i]=(ggi_pixel)i;
ggiSetPaletteVec(vis,0,256,eight_bit_pal);
}
}
x=x1;
y=y1;
while ((!lastread)&&(LoadPic)) {
temp1=buffer[buffpointer];
temp2=buffer[buffpointer+1];
temp3=buffer[buffpointer+2];
buffpointer+=3;
if (buffpointer>=errorlev) {
if (errorlev==300) {
errorlev=fread(buffer,1,300,fff);
buffpointer=0;
}
else lastread=1;
}
int1=(temp2>>4)+(temp1<<4);
int2=((temp2-((temp2>>4)<<4))*256)+temp3;
if (int1>2047) {
ggiPutPixel(vis,x,y,tb1_pal[int1-2048]);
x++;
if (x>xsize+x1) {
x=x1; y++;
}
ggiPutPixel(vis,x,y,tb1_pal[int2-2048]);
x++;
if (x>xsize+x1){
x=x1;y++;
}
}
else {
col=int1;
numacross=int2;
while ((x+numacross)>(xsize+x1)) {
ggiSetGCForeground(vis,tb1_pal[col]);
ggiDrawHLine(vis,x,y,((xsize+x1)-x));
numacross=numacross-((xsize+1)-x);
x=x1;
y++;
}
if (numacross!=0) {
ggiSetGCForeground(vis,tb1_pal[col]);
ggiDrawHLine(vis,x,y,numacross);
}
x=x+numacross;
}
}
ggiFlush(vis);
if (fff!=NULL) fclose(fff);
return 0;
}
vmw_font *LoadVMWFont(char *namest,int xsize,int ysize,int numchars)
{
unsigned char buff[16];
FILE *f;
int i,fonty,numloop;
vmw_font *font;
char *data;
font=(vmw_font *)malloc(sizeof(vmw_font));
data=(char *)calloc(numchars*ysize,(sizeof(char)));
f=fopen(namest,"r");
if (f==NULL) {
printf("ERROR loading font file %s.\n",namest);
return NULL;
}
numloop=(numchars*ysize);
font->width=xsize;
font->height=ysize;
font->numchars=numchars;
font->font_data=data;
fonty=0;
while ( (!feof(f))&&(fonty<=numloop)) {
fread(buff,1,16,f);
for(i=0;i<16;i++) font->font_data[fonty+i]=buff[i];
fonty+=16;
}
fclose(f);
return font;
}
/*int bit(unsigned char mree,int whichbit)
{
return mree&(128>>whichbit);
}
*/
void VMWtextlineover(char *st,int x,int y,int col,int background,int line,
vmw_font *font,ggi_visual_t vis)
{
int i,xx,len;
len=strlen(st);
for(i=0;i<len;i++)
for(xx=0;xx<8;xx++){
if ( (font->font_data[(st[i]*font->height)+line])&(128>>xx) )
ggiPutPixel(vis,(x+(i*8)+xx),y,col);
else
ggiPutPixel(vis,(x+(i*8)+xx),y,background);
}
}
void VMWtextline(char *st,int x,int y,int col,int background,int line,
vmw_font *font,ggi_visual_t vis)
{
int i,len,xx;
len=strlen(st);
for(i=0;i<len;i++)
for(xx=0;xx<8;xx++)
if( ((unsigned char) (font->font_data[(st[i]*16)+line]))
&(128>>xx) ) {
ggiPutPixel(vis,x+(i*8)+xx,y,col);
}
}
void VMWtextxy(char *st,int x,int y,int col,int background,int overwrite,
vmw_font *font,ggi_visual_t vis)
{
int lineon,i,xx,len;
len=strlen(st);
for(lineon=0;lineon<8;lineon++){
for(i=0;i<len;i++)
for(xx=0;xx<8;xx++){
if ( (font->font_data[(st[i]*font->height)+lineon])&(128>>xx) )
ggiPutPixel(vis,(x+(i*8)+xx),y+lineon,col);
else
if(overwrite) ggiPutPixel(vis,(x+(i*8)+xx),y+lineon,background);
}
}
/*VMWtextlineover(st,x,y+lineon,col,background,lineon,font,vis);*/
/* VMWtextline(st,x,y+lineon,col,background,lineon,font,vis);*/
}
void VMWsmalltextxy(char *st,int x,int y,int col,int background,int overwrite,
vmw_font *font,ggi_visual_t vis)
{
int lineon,i,xx,len;
/* This will print out a small 4x5 font located in chars */
/* 128-255 in a normal VGA font. These are custom made */
/* fonts they are non-standard */
len=strlen(st);
for(lineon=0;lineon<5;lineon++) {
for(i=0;i<len;i++)
for(xx=0;xx<5;xx++) {
if ( (font->font_data[((st[i]+128)*font->height)+lineon])&(128>>xx) )
ggiPutPixel(vis,(x+(i*5)+xx),y+lineon,col);
else
if(overwrite) ggiPutPixel(vis,(x+(i*5)+xx),y+lineon,background);
}
}
}
/*
var i,len:word;
begin
len:=length(St);
for i:=1 to (len div 2)+1 do begin
fontline[(i-1)*2]:=charset[(ord(st[(i*2)]))+128,line];
fontline[((i-1)*2)+1]:=charset[(ord(st[(i*2)-1]))+128,line];
end;
asm
push ds
push si
push es
push di
mov ax,[fontseg]
mov ds,ax
mov ax,[fontoff]
mov si,ax
mov dh,[col]
mov dl,[background]
mov ax,[y] {multiplies y value by 320}
shl ax,5
mov cx,ax
shl ax,1
shl cx,3
add ax,cx
add ax,[x] {adds the x-value to get offset}
mov di,ax
mov ax,[where]
mov es,ax
mov bx,[len]
gus1:
xor ax,ax
cmp bx,02
jnge gus4
mov cx,10
lodsb
push bx
mov bl,al
xor bh,bh
lodsb
shl ax,5
add ax,bx
shl ax,3
pop bx
jmp gus5
gus4:
mov cx,5
lodsw
gus5:
shl ax,1
push ax
jc gus7
mov al,dl
jmp gus8
gus7:
mov al,dh
gus8:
xor ah,ah
stosb
pop ax
loop gus5
cmp bx,2
jng gus3
dec bx
dec bx
jmp gus1
gus3:
pop di
pop es
pop si
pop ds
end;
end;
procedure outsmalltextline(st:string;x,y:integer;col,background:byte;line:integer;where:word);
label gus1,gus4,gus6,gus5,gus7,gus8,gus3;
var i,len:word;
begin
len:=length(St);
for i:=1 to (len div 2)+1 do begin
fontline[(i-1)*2]:=charset[(ord(st[(i*2)]))+128,line];
fontline[((i-1)*2)+1]:=charset[(ord(st[(i*2)-1]))+128,line];
end;
asm
push ds
push si
push es
push di
mov ax,[fontseg]
mov ds,ax
mov ax,[fontoff]
mov si,ax
mov dh,[col]
mov bl,[background]
mov ax,[y] {multiplies y value by 320}
shl ax,5
mov cx,ax
shl ax,1
shl cx,3
add ax,cx
add ax,[x] {adds the x-value to get offset}
mov di,ax
mov ax,[where]
mov es,ax
mov bx,[len]
gus1:
xor ax,ax
cmp bx,02
jnge gus4
mov cx,10
lodsb
push bx
mov bl,al
xor bh,bh
lodsb
shl ax,5
add ax,bx
shl ax,3
pop bx
jmp gus5
gus4:
mov cx,5
lodsw
gus5:
shl ax,1
push ax
jc gus7
inc di
jmp gus8
gus7:
mov al,dh
xor ah,ah
stosb
gus8:
pop ax
loop gus5
cmp bx,2
jng gus3
dec bx
dec bx
jmp gus1
gus3:
pop di
pop es
pop si
pop ds
end;
end;
procedure outsmalltextxy(st:string;x,y,col,background:integer;where:word;overwrite:boolean);
label l0105;
var l,len,i,xadd,yadd,lineon:integer;
n,k,o,min,max,qwerty:byte;
begin
for lineon:=0 to 4 do
if overwrite then
outsmalltextlineover(st,x,y+lineon,col,background,lineon,where)
else
outsmalltextline(st,x,y+lineon,col,background,lineon,where);
end;
function sgn(a:real):integer;
begin
if a>0 then sgn:=+1;
if a<0 then sgn:=-1;
if a=0 then sgn:=0;
end;
procedure line(a,b,c,d,col:integer;where:word);
var u,s,v,d1x,d1y,d2x,d2y,m,n:real;
i:integer;
begin
u:= c - a;
v:= d - b;
d1x:= SGN(u);
d1y:= SGN(v);
d2x:= SGN(u);
d2y:= 0;
m:= ABS(u);
n := ABS(v);
IF NOT (M>N) then
BEGIN
d2x := 0 ;
d2y := SGN(v);
m := ABS(v);
n := ABS(u);
END;
s := INT(m / 2);
FOR i := 0 TO round(m) DO
BEGIN
putpixel(a,b,col,where);
s := s + n;
IF not (s<m) THEN
BEGIN
s := s - m;
a:= a +round(d1x);
b := b + round(d1y);
END
ELSE
BEGIN
a := a + round(d2x);
b := b + round(d2y);
END;
end;
END;
procedure horizontalline(FromX1,ToX2,AtY,col:integer;where:word);
begin
asm
push es
push di
mov ax,[aty] {multiplies y value by 320}
shl ax,5
mov cx,ax
shl ax,1
shl cx,3
add ax,cx
add ax,[fromx1] {adds the x-value to get offset}
mov di,ax
mov ax,[where]
mov es,ax
mov cx,[tox2]
sub cx,[fromx1] {how long line is}
xor ax,ax {load color}
mov ax,col
rep stosb {draw it}
pop di
pop es
end;
end;
procedure verticalline(FromY1,ToY2,AtX,col:integer;where:word);
label mree2,mree3,mree,mree4;
begin
asm
push es
push di
xor dx,dx
mov bx,[toy2] {this mess saves you}
mov ax,[fromy1] {if you put a y1 value}
{lower than y2. It is}
cmp bx,ax {probably unnecessary}
jz mree3
jl Mree2
sub bx,ax {how long line is}
mov dx,bx
jmp mree3
mree2:
sub ax,bx
mov dx,ax
mov ax,[toy2]
mree3:
{mov ax,[FromY1]} {multiplies y value by 320}
shl ax,5
mov cx,ax
shl ax,1
shl cx,3
add ax,cx
add ax,[atX] {adds the x-value to get offset}
mov di,ax
mov ax,[where]
mov es,ax
mov cx,dx
inc cx
xor ax,ax {load color}
mov ax,col
Mree:
stosb {draw it}
add di,319
loop mree
mree4:
pop di
pop es
end;
end;
procedure fade;
var i,j:integer;
r,g,b:byte;
begin
for i:=0 to 255 do begin
getpal(i,r,g,b);
unfadered[i]:=r;
unfadeblue[i]:=b;
unfadegreen[i]:=g;
end;
for i:=0 to 63 do begin
for j:=0 to 255 do begin
getpal(j,r,g,b);
if r>0 then dec(r);
if g>0 then dec(g);
if b>0 then dec(b);
pal(j,r,g,b);
end;
end;
end;
procedure unfade;
var i,j:integer;
r,g,b:byte;
begin
for i:=0 to 63 do begin
for j:=0 to 255 do begin
getpal(j,r,g,b);
if r<unfadered[j] then inc(r);
if g<unfadegreen[j] then inc(g);
if b<unfadeblue[j] then inc(b);
pal(j,r,g,b);
end;
end;
end;
procedure box(x1,y1,x2,y2,col:integer;where:word);
begin
line(x1,y1,x1,y2,col,where);
horizontalline(x1,x2,y2,col,where);
line(x2,y2,x2,y1,col,where);
horizontalline(x1,x2,y1,col,where);
end;
procedure vdelay(howlong:integer);
var i:integer;
begin
for i:=1 to howlong do waitretrace;
end;
procedure setupvmwgraph;
begin
loadfont('8x8font.tb1');
charheight:=8;
fontseg:=seg(fontline[0]);
fontoff:=ofs(fontline[0]);
end;
procedure setuptb1;
begin
loadfont('tbfont.tb1');
charheight:=8;
fontseg:=seg(fontline[0]);
fontoff:=ofs(fontline[0]);
end;
begin
end.
*/

43
svmwgrap.h Normal file
View File

@ -0,0 +1,43 @@
typedef struct {
char *font_data;
int width;
int height;
int numchars;
} vmw_font;
int vmwCrossBlit(char *dest,char *src,int stride,int ysize);
int vmwCrossBlit240(char *dest,char *src,int stride,int stride_factor,
int ysize);
int vmwArbitraryCrossBlit(char *src,int x1,int y1,int w,int h,
char *dest,int x2,int y2,int stride,
int stridesfactor);
/*int vmwPutSprite(ggi_visual_t visual,int x,int y,int w,int h,
int transparent_color,int *sprite);
*/
int vmwPutSprite(int *src,int w,int h,int stride_factor,
char *dest,int x,int y,int dest_stride);
int vmwGetSprite(ggi_visual_t visual,int x,int y,int w,int h,
int *sprite);
int GGILoadPicPacked(int x1,int y1,ggi_visual_t vis
,int LoadPal,int LoadPic,char *FileName,
ggi_color *eight_bit_pal,ggi_pixel *tb1_pal,
int color_depth);
vmw_font *LoadVMWFont(char *namest,int xsize,int ysize,int numchars);
void VMWtextlineover(char *st,int x,int y,int col,int background,int line,
vmw_font *font,ggi_visual_t vis);
void VMWtextline(char *st,int x,int y,int col,int background,int line,
vmw_font *font,ggi_visual_t vis);
void VMWtextxy(char *st,int x,int y,int col,int background,int overwrite,
vmw_font *font,ggi_visual_t vis);
void VMWsmalltextxy(char *st,int x,int y,int col, int background, int overwrite,
vmw_font *font,ggi_visual_t vis);

16
tb1-2.9.0.lsm Normal file
View File

@ -0,0 +1,16 @@
Begin3
Title: tb1
Version: 2.9.0
Entered-date: 28FEB98
Description: A really cool arcade game.
Shoot the aliens, save the world.
Keywords: tom bombem alien game arcade ggi
Author: weave@eng.umd.edu (Vince Weaver)
Maintained-by: weave@eng.umd.edu (Vince Weaver)
Primary-site: sunsite.unc.edu /pub/Linux/games/arcade
100kB tb1-2.9.0.tar.gz
Alternate-site: http://www.glue.umd.edu/~weave/tb1
Original-site:
Platforms: Any that have gcc and support ggi
Copying-policy: GPL
End

418
tb1.c Normal file
View File

@ -0,0 +1,418 @@
/****************************************************************\
\* TOM BOMBEM AND THE INVASION OF THE INANIMATE_OBJECTS */
/* version 2.9.0 February 28, 1998 *\
\* by Vince Weaver weave@eng.umd.edu */
/* *\
\* Originally written in Pascal and x86 assembly for DOS */
/* Ported to Linux, C, and ggi late 1997-early 1998 *\
\* This source is released under the GPL */
/****************************************************************/
#define TB1_VERSION "2.9.0"
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
#include <sys/time.h>
#include <ggi/libggi.h>
#include "svmwgrap.h"
#include "tblib.h"
/* Exported Global Variables */
ggi_visual_t vis,vaddr,vaddr2;
vmw_font *tb1_font;
uint white;
ggi_color eight_bit_pal[256];
ggi_pixel tb1_pal[256];
int color_depth;
ggi_directbuffer_t dbuf_vis,dbuf_vaddr,dbuf_vaddr2;
ggi_pixellinearbuffer *plb_vis = NULL,*plb_vaddr= NULL,*plb_vaddr2=NULL;
int stride_factor=1;
int sound_enabled=1,sound_possible=1,read_only_mode=0;
char path_to_data[256];
struct timeval time_info;
struct timezone dontcare;
/* Setup the Graphics */
int setup_graphics(int force_8bpp)
{
int err;
ggi_mode mode;
int vx,vy,sx,sy;
ggiInit();
vis=ggiOpen(NULL);
if (force_8bpp)
err=ggiSetGraphMode(vis,320,200,320,200,GT_8BIT);
else
err=ggiSetGraphMode(vis,320,200,320,200,GGI_AUTO);
if (err) {
fprintf(stderr,"ERROR! Problem opening 320x200 vis\n\n");
return 2;
}
ggiGetMode(vis,&mode);
vx=mode.virt.x; vy=mode.virt.y;
sx=mode.visible.x;sy=mode.visible.y;
switch (mode.graphtype) {
case GT_1BIT: color_depth=1;break;
case GT_4BIT: color_depth=4;break;
case GT_8BIT: color_depth=8;break;
case GT_15BIT: color_depth=15;break;
case GT_16BIT: color_depth=16;break;
case GT_24BIT: color_depth=24;break;
case GT_32BIT: color_depth=32;break;
default: break;
}
printf(" + Opened a %d x %d (%d x %d) mode with %d bpp\n",
sx,sy,vx,vy,color_depth);
err = ggiDBGetBuffer (vis, &dbuf_vis);
if (err) {
printf("Error! Could not get directbuffer\n");
return 2;
}
if (!(ggiDBGetLayout (dbuf_vis) == blPixelLinearBuffer)) {
printf("Error! Nonlinear Display Buffer.\n");
return 2;
}
if (!(plb_vis = ggiDBGetPLB (dbuf_vis)) ) {
printf("Error! Problem getting pixel linear buffer.\n");
return 2;
}
vaddr=ggiOpen("display-memory",NULL);
err=ggiSetGraphMode(vaddr,320,200,320,200,mode.graphtype);
if (err) {
printf("ERROR! Problem opening 320x200x%d vaddr\n",color_depth);
return 2;
}
err = ggiDBGetBuffer (vaddr, &dbuf_vaddr);
if (err) {
printf("Error! Could not get directbuffer\n");
return 2;
}
if (!(ggiDBGetLayout (dbuf_vaddr) == blPixelLinearBuffer)) {
printf("Error! Nonlinear Display Buffer.\n");
return 2;
}
if (!(plb_vaddr = ggiDBGetPLB (dbuf_vaddr)) ) {
printf("Error! Problem getting pixel linear buffer.\n");
return 2;
}
vaddr2=ggiOpen("display-memory",NULL);
err=ggiSetGraphMode(vaddr2,320,400,320,400,mode.graphtype);
if (err){
printf("ERROR! Problem opening 320x400x%d vaddr2\n",color_depth);
return 2;
}
err = ggiDBGetBuffer (vaddr2, &dbuf_vaddr2);
if (err) {
printf("Error! Could not get directbuffer\n");
return 2;
}
if (!(ggiDBGetLayout (dbuf_vaddr2) == blPixelLinearBuffer)) {
printf("Error! Nonlinear Display Buffer.\n");
return 2;
}
if (!(plb_vaddr2 = ggiDBGetPLB (dbuf_vaddr2)) ) {
printf("Error! Problem getting pixel linear buffer.\n");
return 2;
}
stride_factor=(plb_vis->stride)/320;
printf(" + Using a stride factor of %d\n",stride_factor);
printf(" + GGI Graphics Initialization successful...\n");
printf(" + Running TB1 in %dbpp Mode...\n",color_depth);
return 0;
}
int command_line_help(int show_version,char *runas)
{
if (!show_version) {
printf("Usage: %s [-force8bpp] [-nosound] [-readonly]"
" [-version] [-?]\n\n",runas);
printf(" -force8bpp : force to run in 8bpp mode\n");
printf(" -nosound : disables sound within game\n");
printf(" -readonly : don't try to write files to disk\n");
printf(" -version : print version\n");
printf(" -? : print this help message\n");
printf("\n");
}
return 0;
}
int main(int argc,char **argv)
{
int i,grapherror,reloadpic=0,force_8bpp=0;
int ch,ch2,x,barpos,time_sec;
char *tempst[300];
FILE *fff;
printf("\nTom Bombem v%s by Vince Weaver weave@eng.umd.edu\n",TB1_VERSION);
printf(" http://www.glue.umd.edu/~weave/tb1\n\n");
/* Parse Command Line Arguments */
i=1;
while(i<argc) {
if (argv[i][0]=='-') {
switch (argv[i][1]) {
case 'h': case '?':
command_line_help(0,argv[0]); return 5; break;
case 'v':
command_line_help(1,argv[0]); return 5; break;
case 'f':
force_8bpp=1; break;
case 'n':
sound_enabled=0;
sound_possible=0;
printf(" + Sound totally disabled\n");
break;
case 'r':
read_only_mode=1;
printf(" + Read Only mode enabled\n");
break;
default : command_line_help(0,argv[0]);
printf("Unknown Option: %s\n\n",argv[i]);
return 5;
}
}
else {
command_line_help(0,argv[0]);
printf("Unknown Option: %s\n\n",argv[i]);
return 5;
}
i++;
}
/* Find the Data */
/* FIXME : User Defined Path Info*/
if ( (fff=fopen("./data/data_files_here","r"))!=NULL) {
strncpy(path_to_data,"./data/",20);
}
else if ( (fff=fopen("/usr/local/games/tb1/data/data_files_here","r"))
!=NULL) {
strncpy(path_to_data,"/usr/local/games/tb1/data/",40);
}
else {
char tempst[200];
sprintf(tempst,"%s/.tb1/data/data_files_here",getenv("HOME"));
if ( (fff=fopen(tempst,"r"))!=NULL) {
sprintf(path_to_data,"%s/.tb1/data/",getenv("HOME"));
}
else {
printf("ERROR! Could not find tb1 data!\n");
printf(" Checked ./data, /usr/local/games/tb1/data\n");
printf(" and %s/.tb1/data\n\n",getenv("HOME"));
return 9;
}
}
printf(" + Found tb1 data in %s\n",path_to_data);
/* FIXME : find where writing info out to */
/* REMNANT OPERATION BOTTLECAP STUFF---> *\
\* No 9-22-94 Back to yes 10-6-94 uh_oh 2-21-95 */
/* gone for real long time 10-12-95 *\
\* 11-95 not Amy anymore, but Gus */
/* 3-96 oh well... gave up on Gus finally *\
\* 5-11-96 Now Marie... what fun life is */
/* Randomize random number generator */
srandom(time(NULL));
/* Load the tom bombem font */
tb1_font=LoadVMWFont(tb1_data_file("tbfont.tb1",(char *)tempst),8,16,256);
/* Setup Graphics */
if (setup_graphics(force_8bpp)==2) {
fprintf(stderr,"ERROR: Couldn't get display set up properly.\n");
return 2;
}
/* Do the VMW Software Production Logo */
for(x=0;x<=40;x++){
eight_bit_pal[100+x].r=((x+20)*4)*0x100;
eight_bit_pal[100+x].g=0;
eight_bit_pal[100+x].b=0;
eight_bit_pal[141+x].r=0;
eight_bit_pal[141+x].g=0;
eight_bit_pal[141+x].b=((x+20)*4)*0x100;
eight_bit_pal[182+x].r=0;
eight_bit_pal[182+x].g=((x+20)*4)*0x100;;
eight_bit_pal[182+x].b=0;
if (color_depth!=8) {
tb1_pal[100+x]=ggiMapColor(vis,&eight_bit_pal[100+x]);
tb1_pal[141+x]=ggiMapColor(vis,&eight_bit_pal[141+x]);
tb1_pal[182+x]=ggiMapColor(vis,&eight_bit_pal[182+x]);
}
else {
for(i=0;i<256;i++) tb1_pal[i]=(ggi_pixel)i;
}
}
/* Set the white color */
eight_bit_pal[15].r=255*0x100;
eight_bit_pal[15].g=255*0x100;
eight_bit_pal[15].b=255*0x100;
/* Finalize Pallette Stuff */
if (color_depth!=8) {
tb1_pal[15]=ggiMapColor(vis,&eight_bit_pal[15]);
}
else ggiSetPaletteVec(vis,0,256,eight_bit_pal);
/* Actually draw the stylized VMW */
for(x=0;x<=40;x++){
ggiSetGCForeground(vis,tb1_pal[100+x]);
ggiDrawVLine(vis,x+40,45,2*x);
ggiSetGCForeground(vis,tb1_pal[141+x]);
ggiDrawVLine(vis,x+120,45,2*x);
ggiDrawVLine(vis,x+200,45,2*x);
ggiSetGCForeground(vis,tb1_pal[182+x]);
ggiDrawVLine(vis,x+80,125-(2*x),2*x);
ggiDrawVLine(vis,x+160,125-(2*x),2*x);
}
for(x=40;x>0;x--){
ggiSetGCForeground(vis,tb1_pal[140-x]);
ggiDrawVLine(vis,x+80,45,80-(2*x));
ggiSetGCForeground(vis,tb1_pal[181-x]);
ggiDrawVLine(vis,x+160,45,80-(2*x));
ggiDrawVLine(vis,x+240,45,80-(2*x));
ggiSetGCForeground(vis,tb1_pal[222-x]);
ggiDrawVLine(vis,x+120,45+(2*x),80-(2*x));
ggiDrawVLine(vis,x+200,45+(2*x),80-(2*x));
}
ggiSetGCForeground(vis,tb1_pal[15]);
VMWtextxy("A VMW SOFTWARE PRODUCTION",60,140,
tb1_pal[15],tb1_pal[15],0,tb1_font,vis);
ggiFlush(vis);
pauseawhile(5);
/* Clear the Screen and get ready for the Menu */
ggiSetGCForeground(vis,tb1_pal[0]);
ggiFillscreen(vis);
/* Load the title screen */
grapherror=GGILoadPicPacked(0,0,vis,1,1,
tb1_data_file("tbomb1.tb1",(char *)tempst),
(ggi_color *)&eight_bit_pal,
(ggi_pixel *)&tb1_pal,color_depth);
grapherror=GGILoadPicPacked(0,0,vaddr2,1,1,
tb1_data_file("tbomb1.tb1",(char *)tempst),
(ggi_color *)&eight_bit_pal,
(ggi_pixel *)&tb1_pal,color_depth);
ggiFlush(vis);
ggiFlush(vaddr2);
pauseawhile(5);
/* Main Menu Loop */
while (1) {
if (reloadpic) {
grapherror=GGILoadPicPacked(0,0,vaddr2,1,1,
tb1_data_file("tbomb1.tb1",(char *)tempst),
(ggi_color *)&eight_bit_pal,
(ggi_pixel *)&tb1_pal,color_depth);
ggiFlush(vaddr2);
reloadpic=0;
}
vmwCrossBlit(plb_vis->write,plb_vaddr2->read,plb_vis->stride,200);
ggiFlush(vis);
barpos=0;
VMWtextxy("F1 HELP",0,190,tb1_pal[9],tb1_pal[7],0,tb1_font,vis);
coolbox(117,61,199,140,1,vis);
ggiFlush(vis);
ch=0;
while(ch!=TB_ENTER){
if (barpos==0) VMWtextxy("NEW GAME",123,67,
tb1_pal[32],tb1_pal[0],1,tb1_font,vis);
else VMWtextxy("NEW GAME",123,67,
tb1_pal[32],tb1_pal[7],1,tb1_font,vis);
if (barpos==1) VMWtextxy("OPTIONS",123,77,
tb1_pal[32],tb1_pal[0],1,tb1_font,vis);
else VMWtextxy("OPTIONS",123,77,
tb1_pal[32],tb1_pal[7],1,tb1_font,vis);
if (barpos==2) VMWtextxy("ABOUT",123,87,
tb1_pal[32],tb1_pal[0],1,tb1_font,vis);
else VMWtextxy("ABOUT",123,87,
tb1_pal[32],tb1_pal[7],1,tb1_font,vis);
if (barpos==3) VMWtextxy("LOAD GAME",123,97,
tb1_pal[32],tb1_pal[0],1,tb1_font,vis);
else VMWtextxy("LOAD GAME",123,97,
tb1_pal[32],tb1_pal[7],1,tb1_font,vis);
if (barpos==4) VMWtextxy("STORY",123,107,
tb1_pal[32],tb1_pal[0],1,tb1_font,vis);
else VMWtextxy("STORY",123,107,
tb1_pal[32],tb1_pal[7],1,tb1_font,vis);
if (barpos==5) VMWtextxy("CREDITS",123,117,
tb1_pal[32],tb1_pal[0],1,tb1_font,vis);
else VMWtextxy("CREDITS",123,117,
tb1_pal[32],tb1_pal[7],1,tb1_font,vis);
if (barpos==6) VMWtextxy("QUIT",123,127,
tb1_pal[32],tb1_pal[0],1,tb1_font,vis);
else VMWtextxy("QUIT",123,127,
tb1_pal[32],tb1_pal[7],1,tb1_font,vis);
ggiFlush(vis);
/* If at title screen too long, run credits */
gettimeofday(&time_info,&dontcare);
time_sec=time_info.tv_sec;
while( ((ch=get_input())==0)) {
usleep(10);
gettimeofday(&time_info,&dontcare);
if (time_info.tv_sec-time_sec>40) {
credits();
ch=TB_ENTER;
barpos=9;
reloadpic=1;
gettimeofday(&time_info,&dontcare);
time_sec=time_info.tv_sec;
}
}
/* Change menu position based on key pressed */
ch2=toupper(ch);
if ((ch==TB_DOWN)||(ch==TB_RIGHT)) barpos++;
if ((ch==TB_UP) || (ch==TB_LEFT)) barpos--;
if (ch==TB_F1) {barpos=10; ch=TB_ENTER;} /*F1*/
if (ch2=='N') barpos=0; /*N*/
if (ch2=='O') barpos=1; /*O*/
if (ch2=='A') barpos=2; /*A*/
if (ch2=='L') barpos=3; /*L*/
if (ch2=='S') barpos=4; /*S*/
if (ch2=='C') barpos=5; /*C*/
if (ch2=='Q') barpos=6; /*Q*/
if (ch==27){ /* escape */
barpos=6;
ch=TB_ENTER;
}
if(barpos==7) barpos=0;
if(barpos<0) barpos=6;
}
/* Run whatever it was that the person pressed */
switch (barpos) {
case 0: playthegame(0,0,12); reloadpic=1; break;
case 1: options(vis); reloadpic=1; break;
case 2: about(vis); reloadpic=1; break;
case 3: loadgame(); reloadpic=1; break;
case 4: story(); reloadpic=1; break;
case 5: credits(); reloadpic=1; break;
case 6: barpos=quit(vis); break;
case 10: help(vis); break;
}
}
}

1301
tblib.c Normal file

File diff suppressed because it is too large Load Diff

34
tblib.h Normal file
View File

@ -0,0 +1,34 @@
#define TB_ESC 27
#define TB_ENTER 1024
#define TB_F1 1025
#define TB_F2 1026
#define TB_UP 1027
#define TB_DOWN 1028
#define TB_LEFT 1029
#define TB_RIGHT 1030
#define TB_PGUP 1031
#define TB_PGDOWN 1032
int change_shields(int *shields);
int changescore(int score,int *shields);
int collision(int x1,int y1,int xsize,int ysize,int x2,int y2,int x2size,int y2size);
char *tb1_data_file(char *name,char *store);
int get_input();
void coolbox(int x1,int y1,int x2,int y2,int fill,ggi_visual_t page);
int close_graphics();
int quit();
void ReadConfigFile(int CDROMmode);
int showhiscore(int showchart);
void clear_keyboard_buffer();
void write_hs_list(int score,char *hiname);
void help();
void setupsidebar(int score,int hiscore,int shields);
void shadowrite(char *st,int x,int y,int forecol,int backcol,ggi_visual_t vis);
void pauseawhile(int howlong);
void options();
void savegame(int level,int begin_score,int begin_shields);
void loadgame();
void story();
void credits();
void about();
void playthegame(int level,int sc,int sh);