Compare commits
4 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
56458af5fc | ||
|
187ec1a68e | ||
|
7e9fbaf5d2 | ||
|
eb78414668 |
29
.clang-format
Normal file
29
.clang-format
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
---
|
||||||
|
BasedOnStyle: LLVM
|
||||||
|
IndentWidth: 4
|
||||||
|
TabWidth: 4
|
||||||
|
---
|
||||||
|
Language: Cpp
|
||||||
|
AccessModifierOffset: -4
|
||||||
|
AlignAfterOpenBracket: AlwaysBreak
|
||||||
|
AlignOperands: false
|
||||||
|
AlignTrailingComments: false
|
||||||
|
AllowAllParametersOfDeclarationOnNextLine: false
|
||||||
|
AllowShortBlocksOnASingleLine: true
|
||||||
|
AllowShortFunctionsOnASingleLine: Empty
|
||||||
|
AllowShortIfStatementsOnASingleLine: true
|
||||||
|
AllowShortLoopsOnASingleLine: true
|
||||||
|
AlwaysBreakTemplateDeclarations: true
|
||||||
|
BinPackArguments: false
|
||||||
|
BinPackParameters: false
|
||||||
|
BreakConstructorInitializersBeforeComma: true
|
||||||
|
ColumnLimit: 160
|
||||||
|
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||||
|
ConstructorInitializerIndentWidth: 0
|
||||||
|
MaxEmptyLinesToKeep: 2
|
||||||
|
NamespaceIndentation: All
|
||||||
|
PointerAlignment: Left
|
||||||
|
SpaceAfterCStyleCast: true
|
||||||
|
Standard: Cpp11
|
||||||
|
UseTab: Always
|
||||||
|
...
|
5
AUTHORS
5
AUTHORS
@ -1,7 +1,6 @@
|
|||||||
David Ashley
|
David Ashley
|
||||||
dashxdr@gmail.com
|
dashxdr@gmail.com
|
||||||
http://www.xdr.com/dash
|
https://www.linuxmotors.com/linux/SDL_bomber/
|
||||||
http://www.linuxmotors.com
|
|
||||||
|
|
||||||
Stefan Bühler
|
Stefan Bühler
|
||||||
http://stbuehler.de/
|
https://stbuehler.de/
|
||||||
|
41
Makefile
41
Makefile
@ -1,41 +0,0 @@
|
|||||||
DBG = -g
|
|
||||||
CC = gcc
|
|
||||||
WARNFLAGS = -Wall -Wmissing-declarations -Wdeclaration-after-statement -Wcast-align -Winline -Wsign-compare -Wnested-externs -Wpointer-arith -Wformat-security
|
|
||||||
override CFLAGS += -D_REENTRANT $(shell sdl-config --cflags) $(DBG) $(WARNFLAGS)
|
|
||||||
|
|
||||||
.PHONY: all clean install
|
|
||||||
all: sdlbomber
|
|
||||||
|
|
||||||
sdlbomber: announce.o bomber.o draw.o game.o gfx.o sound.o list.o network.o menu.o utils.o
|
|
||||||
gcc $(LDFLAGS) -o $@ $^ $(shell sdl-config --libs) -lavahi-common -lavahi-client $(DBG)
|
|
||||||
|
|
||||||
matcher: matcher.c
|
|
||||||
|
|
||||||
announce.o: announce.c announce.h network.h
|
|
||||||
|
|
||||||
bomber.o: bomber.c announce.h bomber.h draw.h game.h gfx.h list.h menu.h network.h sound.h utils.h
|
|
||||||
|
|
||||||
draw.o: draw.c draw.h bomber.h gfx.h
|
|
||||||
|
|
||||||
game.o: game.c announce.h bomber.h draw.h game.h gfx.h list.h menu.h network.h sound.h utils.h
|
|
||||||
|
|
||||||
gfx.o: gfx.c gfx.h bomber.h
|
|
||||||
|
|
||||||
list.o: list.c bomber.h list.h utils.h
|
|
||||||
|
|
||||||
menu.o: menu.c announce.h bomber.h draw.h game.h gfx.h list.h menu.h network.h sound.h utils.h
|
|
||||||
|
|
||||||
network.o: network.c announce.h bomber.h draw.h game.h menu.h network.h utils.h
|
|
||||||
|
|
||||||
sound.o: sound.c sound.h
|
|
||||||
|
|
||||||
utils.o: utils.c bomber.h utils.h gfx.h
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f *.o matcher sdlbomber
|
|
||||||
|
|
||||||
install: sdlbomber
|
|
||||||
echo "Installing into $(DESTDIR)"
|
|
||||||
mkdir -p "$(DESTDIR)/usr/bin/" "$(DESTDIR)/usr/share/sdlbomber/"
|
|
||||||
install -m 0755 sdlbomber "$(DESTDIR)/usr/bin/"
|
|
||||||
install -m 0644 data/*.pcx data/*.raw "$(DESTDIR)/usr/share/sdlbomber/"
|
|
26
Makefile.osx
26
Makefile.osx
@ -1,26 +0,0 @@
|
|||||||
#DBG += -g
|
|
||||||
#DBG += -pg
|
|
||||||
CC = gcc
|
|
||||||
CFLAGS = -O2 -Wall -I/Library/Frameworks/SDL.framework/Headers $(DBG)
|
|
||||||
|
|
||||||
LDFLAGS += -framework SDL -framework Cocoa -o $@ -lavahi-client
|
|
||||||
|
|
||||||
|
|
||||||
all: sdlbomber
|
|
||||||
sdlbomber: gfx.o bomber.o sound.o SDLMain.o announce.o
|
|
||||||
|
|
||||||
|
|
||||||
SDLMain.o: SDLmain.m
|
|
||||||
bomber.o: bomber.c bomber.h gfx.h sound.h announce.h
|
|
||||||
gfx.o: gfx.c bomber.h gfx.h
|
|
||||||
sound.o: sound.c bomber.h sound.h
|
|
||||||
announce.o: announce.c announce.h
|
|
||||||
|
|
||||||
clean:
|
|
||||||
rm -f *.o sdlbomber matcher
|
|
||||||
|
|
||||||
test: all
|
|
||||||
./sdlbomber
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1,9 +0,0 @@
|
|||||||
# Makefile for bomber
|
|
||||||
#
|
|
||||||
|
|
||||||
TARGET = sdlbomber
|
|
||||||
USEINET = true
|
|
||||||
|
|
||||||
include ../GNUmake
|
|
||||||
|
|
||||||
$(TARGET): bomber.o gfx.o sound.o announce.o
|
|
472
draw.c
472
draw.c
@ -1,472 +0,0 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <netdb.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <stdarg.h>
|
|
||||||
|
|
||||||
#include "bomber.h"
|
|
||||||
#include "draw.h"
|
|
||||||
#include "game.h"
|
|
||||||
#include "gfx.h"
|
|
||||||
#include "utils.h"
|
|
||||||
|
|
||||||
#ifndef DATADIR
|
|
||||||
#define DATADIR "data"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define NUMCHARACTERS 50
|
|
||||||
|
|
||||||
static figure font[NUMCHARACTERS];
|
|
||||||
static figure bigfont[NUMCHARACTERS];
|
|
||||||
|
|
||||||
gfxset gfxsets[NUMGFX];
|
|
||||||
static char walkingname[256];
|
|
||||||
static char colorsetname[256];
|
|
||||||
static char backgroundname[256];
|
|
||||||
static char blocksname[256];
|
|
||||||
static char blocksxname[256];
|
|
||||||
static char bombs1name[256];
|
|
||||||
static char bombs2name[256];
|
|
||||||
static char flamesname[256];
|
|
||||||
static char tilesname[256];
|
|
||||||
static char deathname[256];
|
|
||||||
static char fontname[256];
|
|
||||||
static char bigfontname[256];
|
|
||||||
|
|
||||||
figure blocks[3];
|
|
||||||
figure blocksx[9];
|
|
||||||
figure bombs1[MAXSETS][NUMBOMBFRAMES];
|
|
||||||
figure bombs2[MAXSETS][NUMBOMBFRAMES];
|
|
||||||
figure flamefigs[MAXSETS][NUMFLAMEFRAMES];
|
|
||||||
figure tiles[15];
|
|
||||||
figure death[NUMDEATHFRAMES];
|
|
||||||
|
|
||||||
int fontxsize,fontysize;
|
|
||||||
int bigfontxsize,bigfontysize,bigfontyspace;
|
|
||||||
|
|
||||||
static int textx,texty;
|
|
||||||
|
|
||||||
static const unsigned char *remapstring = (const unsigned char*) "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ.:!?\177/\\*-,>< =";
|
|
||||||
static char asciiremap[256];
|
|
||||||
|
|
||||||
/* On screen array variables */
|
|
||||||
int arraynumx=15;
|
|
||||||
int arraynumy=11;
|
|
||||||
int arraystartx=20;
|
|
||||||
int arraystarty=70;
|
|
||||||
int arrayspacex=40;
|
|
||||||
int arrayspacey=36;
|
|
||||||
|
|
||||||
static sprite sprites[MAXSPRITES];
|
|
||||||
static int spritesused=0;
|
|
||||||
|
|
||||||
#define IBUFFLEN 1024
|
|
||||||
int ileft=0,ihand=0,byteswide;
|
|
||||||
unsigned char ibuff[IBUFFLEN],*itake;
|
|
||||||
|
|
||||||
static void freegfxset(gfxset *gs) {
|
|
||||||
if(gs->gs_pic) free(gs->gs_pic);
|
|
||||||
gs->gs_pic=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int myci() {
|
|
||||||
if (!ileft) {
|
|
||||||
ileft=read(ihand,ibuff,IBUFFLEN);
|
|
||||||
|
|
||||||
if(!ileft) return -1;
|
|
||||||
itake=ibuff;
|
|
||||||
}
|
|
||||||
ileft--;
|
|
||||||
return *itake++;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int dopcxreal(char *name,gfxset *gs) {
|
|
||||||
int xs,ys;
|
|
||||||
int i,j,k;
|
|
||||||
int totalsize;
|
|
||||||
int width,height;
|
|
||||||
unsigned char *bm,*lp;
|
|
||||||
char tname[256];
|
|
||||||
|
|
||||||
memset(gs,0,sizeof(gfxset));
|
|
||||||
ileft=0;
|
|
||||||
snprintf(tname,sizeof(tname),DATADIR "/%s",name);
|
|
||||||
ihand=open(tname,O_RDONLY);
|
|
||||||
if(ihand<0) {
|
|
||||||
char tname2[260];
|
|
||||||
snprintf(tname2,sizeof(tname2),"%s.pcx",tname);
|
|
||||||
ihand=open(tname2,O_RDONLY);
|
|
||||||
if(ihand<0)
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
if(myci()!=10) {close(ihand);return 2;} // 10=zsoft .pcx
|
|
||||||
if(myci()!=5) {close(ihand);return 3;} // version 3.0
|
|
||||||
if(myci()!=1) {close(ihand);return 4;} //encoding method
|
|
||||||
if(myci()!=8) {close(ihand);return 5;} //bpp
|
|
||||||
xs=myci();
|
|
||||||
xs|=myci()<<8;
|
|
||||||
ys=myci();
|
|
||||||
ys|=myci()<<8;
|
|
||||||
width=myci();
|
|
||||||
width|=myci()<<8;
|
|
||||||
height=myci();
|
|
||||||
height|=myci()<<8;
|
|
||||||
width=width+1-xs;
|
|
||||||
height=height+1-ys;
|
|
||||||
for(i=0;i<48+4;++i) myci();
|
|
||||||
myci();
|
|
||||||
if(myci()!=1) {close(ihand);return 6;} // # of planes
|
|
||||||
byteswide=myci();
|
|
||||||
byteswide|=myci()<<8;
|
|
||||||
i=myci();
|
|
||||||
i|=myci()<<8;
|
|
||||||
// if(i!=1) {close(ihand);return 7;} // 1=color/bw,2=grey
|
|
||||||
for(i=0;i<58;++i) myci();
|
|
||||||
totalsize=height*byteswide;
|
|
||||||
bm=malloc(totalsize+1);
|
|
||||||
if(!bm) {close(ihand);return 8;} // no memory
|
|
||||||
gs->gs_pic=bm;
|
|
||||||
gs->gs_xsize=width;
|
|
||||||
gs->gs_ysize=height;
|
|
||||||
while(height--) {
|
|
||||||
lp=bm;
|
|
||||||
i=byteswide;
|
|
||||||
while(i>0) {
|
|
||||||
j=myci();
|
|
||||||
if(j<0xc0) {
|
|
||||||
*lp++=j;
|
|
||||||
--i;
|
|
||||||
} else {
|
|
||||||
j&=0x3f;
|
|
||||||
k=myci();
|
|
||||||
while(j-- && i) {
|
|
||||||
*lp++=k;
|
|
||||||
--i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bm+=width;
|
|
||||||
}
|
|
||||||
lseek(ihand,-0x300,SEEK_END);
|
|
||||||
read(ihand,gs->gs_colormap,0x300);
|
|
||||||
close(ihand);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int dopcx(char *name,gfxset *gs) {
|
|
||||||
int err;
|
|
||||||
|
|
||||||
err=dopcxreal(name,gs);
|
|
||||||
if(err)
|
|
||||||
printf("Error loading \"%s\":code %d\n",name,err);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void getgroup(char *name,gfxset *colorgs,figure *fig,int count) {
|
|
||||||
int err;
|
|
||||||
int i;
|
|
||||||
gfxset gs;
|
|
||||||
|
|
||||||
err=dopcx(name,&gs);
|
|
||||||
if(err) exit(1000+err);
|
|
||||||
createinout(&gs);
|
|
||||||
for(i=0;i<MAXSETS;++i,fig+=count,++colorgs) {
|
|
||||||
if(!colorgs->gs_pic) continue;
|
|
||||||
memmove(gs.gs_colormap,colorgs->gs_colormap,
|
|
||||||
sizeof(gs.gs_colormap));
|
|
||||||
createinout(&gs);
|
|
||||||
gfxfetch(&gs,fig,count);
|
|
||||||
}
|
|
||||||
freegfxset(&gs);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void getsingle(char *name,figure *fig,int count) {
|
|
||||||
gfxset gs;
|
|
||||||
int err;
|
|
||||||
|
|
||||||
err=dopcx(name,&gs);
|
|
||||||
if(err) exit(1000+err);
|
|
||||||
createinout(&gs);
|
|
||||||
gfxfetch(&gs,fig,count);
|
|
||||||
freegfxset(&gs);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void texthome(void) {
|
|
||||||
textx=texty=10;
|
|
||||||
}
|
|
||||||
|
|
||||||
void drawstring(int xpos, int ypos, const char *str) {
|
|
||||||
char ch;
|
|
||||||
|
|
||||||
while((ch=*str++)) {
|
|
||||||
drawfigure(xpos,ypos,font+asciiremap[toupper(ch)]);
|
|
||||||
xpos+=fontxsize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void drawbigstring(int xpos, int ypos, const char *str) {
|
|
||||||
char ch;
|
|
||||||
|
|
||||||
while('\0' != (ch=*str++)) {
|
|
||||||
drawfigure(xpos,ypos,bigfont+asciiremap[toupper(ch)]);
|
|
||||||
xpos+=bigfontxsize;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void centerbig(int y, const char *str) {
|
|
||||||
int w;
|
|
||||||
|
|
||||||
w=strlen(str)*bigfontxsize;
|
|
||||||
drawbigstring((IXSIZE-w)>>1,y,str);
|
|
||||||
}
|
|
||||||
|
|
||||||
// static void scrprintf(char *str,...) {
|
|
||||||
// char output[256],*p,*p2;
|
|
||||||
// va_list ap;
|
|
||||||
//
|
|
||||||
// va_start(ap, str);
|
|
||||||
//
|
|
||||||
// vsprintf(output,str,ap);
|
|
||||||
// p=output;
|
|
||||||
// for(;;) {
|
|
||||||
// p2=p;
|
|
||||||
// while(*p2 && *p2!='\n') ++p2;
|
|
||||||
// if(*p2) {
|
|
||||||
// *p2=0;
|
|
||||||
// drawstring(textx,texty,p);
|
|
||||||
// texty+=fontysize;
|
|
||||||
// textx=10;
|
|
||||||
// p=p2+1;
|
|
||||||
// } else {
|
|
||||||
// drawstring(textx,texty,p);
|
|
||||||
// textx+=fontxsize*(p2-p);
|
|
||||||
// break;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// copyup();
|
|
||||||
// }
|
|
||||||
|
|
||||||
static void bigscrprintf(char *str,...) {
|
|
||||||
char output[256],*p,*p2;
|
|
||||||
va_list ap;
|
|
||||||
|
|
||||||
va_start(ap, str);
|
|
||||||
vsnprintf(output,sizeof(output),str,ap);
|
|
||||||
p=output;
|
|
||||||
for(;;) {
|
|
||||||
p2=p;
|
|
||||||
while(*p2 && *p2!='\n') ++p2;
|
|
||||||
if(*p2) {
|
|
||||||
*p2=0;
|
|
||||||
drawbigstring(textx,texty,p);
|
|
||||||
texty+=bigfontysize;
|
|
||||||
textx=10;
|
|
||||||
p=p2+1;
|
|
||||||
} else {
|
|
||||||
drawbigstring(textx,texty,p);
|
|
||||||
textx+=bigfontxsize*(p2-p);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
copyup();
|
|
||||||
}
|
|
||||||
|
|
||||||
void addsprite(int x,int y,figure *fig) {
|
|
||||||
sprite *sp;
|
|
||||||
|
|
||||||
if(spritesused==MAXSPRITES) return;
|
|
||||||
sp=sprites+spritesused++;
|
|
||||||
sp->flags=0;
|
|
||||||
sp->xpos=x;
|
|
||||||
sp->ypos=y;
|
|
||||||
sp->fig=fig;
|
|
||||||
}
|
|
||||||
|
|
||||||
void plotsprites(void) {
|
|
||||||
int i;
|
|
||||||
sprite *sp;
|
|
||||||
|
|
||||||
sp=sprites;
|
|
||||||
for(i=0;i<spritesused;++i) {
|
|
||||||
drawfigure(sp->xpos,sp->ypos,sp->fig);
|
|
||||||
++sp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void erasesprites(void) {
|
|
||||||
int i;
|
|
||||||
sprite *sp;
|
|
||||||
figure *fig;
|
|
||||||
|
|
||||||
sp=sprites;
|
|
||||||
for(i=0;i<spritesused;++i) {
|
|
||||||
fig=sp->fig;
|
|
||||||
|
|
||||||
solidcopy(&background,
|
|
||||||
sp->xpos+fig->xdelta,sp->ypos+fig->ydelta,
|
|
||||||
fig->xsize,fig->ysize);
|
|
||||||
++sp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void clearsprites(void) {
|
|
||||||
int i;
|
|
||||||
sprite *sp;
|
|
||||||
figure *fig;
|
|
||||||
|
|
||||||
sp=sprites;
|
|
||||||
for(i=0;i<spritesused;++i) {
|
|
||||||
fig=sp->fig;
|
|
||||||
|
|
||||||
clearrect(sp->xpos+fig->xdelta,sp->ypos+fig->ydelta,
|
|
||||||
fig->xsize,fig->ysize);
|
|
||||||
++sp;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void clearspritelist(void) {
|
|
||||||
spritesused=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int tovideox(int x) {
|
|
||||||
return (x>>FRACTION)+arraystartx;
|
|
||||||
}
|
|
||||||
|
|
||||||
int tovideoy(int y) {
|
|
||||||
return (y>>FRACTION)+arraystarty;
|
|
||||||
}
|
|
||||||
|
|
||||||
int screentoarrayx(int x) {
|
|
||||||
x+=arrayspacex << (FRACTION+2);
|
|
||||||
return ((x>>FRACTION)+(arrayspacex>>1))/arrayspacex-4;
|
|
||||||
}
|
|
||||||
|
|
||||||
int screentoarrayy(int y) {
|
|
||||||
y+=arrayspacey << (FRACTION+2);
|
|
||||||
return ((y>>FRACTION)+(arrayspacey>>1))/arrayspacey-4;
|
|
||||||
}
|
|
||||||
|
|
||||||
int arraytoscreenx(int x) {
|
|
||||||
return arrayspacex*x<<FRACTION;
|
|
||||||
}
|
|
||||||
|
|
||||||
int arraytoscreeny(int y) {
|
|
||||||
return arrayspacey*y<<FRACTION;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void loadfonts(void) {
|
|
||||||
int i,j;
|
|
||||||
const unsigned char *p;
|
|
||||||
|
|
||||||
getsingle(fontname,font,NUMCHARACTERS);
|
|
||||||
getsingle(bigfontname,bigfont,NUMCHARACTERS);
|
|
||||||
fontxsize=8;
|
|
||||||
fontysize=12;
|
|
||||||
bigfontxsize=16;
|
|
||||||
bigfontysize=24;
|
|
||||||
bigfontyspace=32;
|
|
||||||
p=remapstring;
|
|
||||||
j=0;while(*p && *p!=' ') ++p,++j;
|
|
||||||
memset(asciiremap,j,sizeof(asciiremap));
|
|
||||||
p=remapstring;
|
|
||||||
i=0;
|
|
||||||
while(*p && i<NUMCHARACTERS)
|
|
||||||
asciiremap[(int)*p++]=i++;
|
|
||||||
}
|
|
||||||
|
|
||||||
void loadgfx() {
|
|
||||||
gfxset *gs;
|
|
||||||
gfxset *colorgs;
|
|
||||||
int err;
|
|
||||||
int i;
|
|
||||||
char name[267];
|
|
||||||
|
|
||||||
strcpy(walkingname,"walk");
|
|
||||||
strcpy(colorsetname,"pal");
|
|
||||||
strcpy(backgroundname,"field0");
|
|
||||||
strcpy(blocksname,"blocks3");
|
|
||||||
strcpy(blocksxname,"blocks3x");
|
|
||||||
strcpy(bombs1name,"bomb1");
|
|
||||||
strcpy(bombs2name,"bomb2");
|
|
||||||
strcpy(flamesname,"flames");
|
|
||||||
strcpy(tilesname,"tiles");
|
|
||||||
strcpy(deathname,"death1");
|
|
||||||
strcpy(fontname,"font");
|
|
||||||
strcpy(bigfontname,"bigfont");
|
|
||||||
|
|
||||||
gs=malloc((MAXSETS+1)*sizeof(gfxset));
|
|
||||||
if(!gs)
|
|
||||||
nomem("loadgfx");
|
|
||||||
colorgs=gs+1;
|
|
||||||
|
|
||||||
for(i=0;i<MAXSETS;++i) {
|
|
||||||
snprintf(name,sizeof(name),"%s%d",colorsetname,i);
|
|
||||||
err=dopcx(name,colorgs+i);
|
|
||||||
if(err) continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
loadfonts();
|
|
||||||
texthome();
|
|
||||||
bigscrprintf("Loading graphics...\n");
|
|
||||||
|
|
||||||
err=dopcx(backgroundname,gs);
|
|
||||||
if(err) exit(1000+err);
|
|
||||||
createinout(gs);
|
|
||||||
solidfetch(gs,&background);
|
|
||||||
solidfetch(gs,&backgroundoriginal);
|
|
||||||
freegfxset(gs);
|
|
||||||
|
|
||||||
bigscrprintf("Loading blocks\n");
|
|
||||||
getsingle(blocksname,blocks,3);
|
|
||||||
bigscrprintf("Loading block explosions\n");
|
|
||||||
getsingle(blocksxname,blocksx,9);
|
|
||||||
bigscrprintf("Loading walking figures\n");
|
|
||||||
getgroup(walkingname,colorgs,walking[0],NUMWALKFRAMES);
|
|
||||||
bigscrprintf("Loading normal bombs\n");
|
|
||||||
getgroup(bombs1name,colorgs,bombs1[0],NUMBOMBFRAMES);
|
|
||||||
bigscrprintf("Loading controlled bombs\n");
|
|
||||||
getgroup(bombs2name,colorgs,bombs2[0],NUMBOMBFRAMES);
|
|
||||||
bigscrprintf("Loading flames\n");
|
|
||||||
// getgroup(flamesname,colorgs,flamefigs[0],NUMFLAMEFRAMES);
|
|
||||||
getsingle(flamesname,flamefigs[0],NUMFLAMEFRAMES);
|
|
||||||
bigscrprintf("Loading bonus tiles\n");
|
|
||||||
getsingle(tilesname,tiles,15);
|
|
||||||
bigscrprintf("Loading death sequence\n");
|
|
||||||
getsingle(deathname,death,NUMDEATHFRAMES);
|
|
||||||
|
|
||||||
for(i=0;i<MAXSETS;++i)
|
|
||||||
freegfxset(colorgs+i);
|
|
||||||
free(gs);
|
|
||||||
bigscrprintf("Done loading graphics\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
void failure(char *str,...) {
|
|
||||||
char output[256];
|
|
||||||
va_list ap;
|
|
||||||
int len;
|
|
||||||
long now;
|
|
||||||
|
|
||||||
va_start(ap, str);
|
|
||||||
|
|
||||||
len = vsnprintf(output, sizeof(output), str, ap);
|
|
||||||
if (len >= 256) len = 255; /* truncated string */
|
|
||||||
clear();
|
|
||||||
drawbigstring((IXSIZE - len*bigfontxsize) / 2, (IYSIZE-bigfontysize) / 2, output);
|
|
||||||
copyup();
|
|
||||||
|
|
||||||
now = longtime();
|
|
||||||
while (!exitflag && longtime()-now < 3) {
|
|
||||||
scaninput();
|
|
||||||
if (anydown()) {
|
|
||||||
takedown();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
980
game.c
980
game.c
@ -1,980 +0,0 @@
|
|||||||
|
|
||||||
#include "bomber.h"
|
|
||||||
#include "game.h"
|
|
||||||
#include "gfx.h"
|
|
||||||
#include "network.h"
|
|
||||||
#include "draw.h"
|
|
||||||
#include "utils.h"
|
|
||||||
#include "sound.h"
|
|
||||||
#include "menu.h"
|
|
||||||
#include "list.h"
|
|
||||||
|
|
||||||
static int gameframe;
|
|
||||||
|
|
||||||
static listhead activebombs;
|
|
||||||
static listhead activedecays;
|
|
||||||
static listhead activebonus;
|
|
||||||
static listhead activegeneric;
|
|
||||||
static listhead detonatebombs;
|
|
||||||
static listhead activeflames;
|
|
||||||
static listhead activeplayers;
|
|
||||||
static listhead allplayers;
|
|
||||||
|
|
||||||
figure walking[MAXSETS][NUMWALKFRAMES];
|
|
||||||
solid background, backgroundoriginal;
|
|
||||||
|
|
||||||
/* The playfield array, contains FIELD_* equates */
|
|
||||||
unsigned char field[32][32];
|
|
||||||
void *info[32][32];
|
|
||||||
|
|
||||||
volatile char exitflag = 0;
|
|
||||||
static int framecount = 0;
|
|
||||||
|
|
||||||
char playername[16];
|
|
||||||
|
|
||||||
static int mycount;
|
|
||||||
|
|
||||||
static int bonustotal;
|
|
||||||
static const int bonuschances[]= {
|
|
||||||
TILE_BOMB,20,
|
|
||||||
TILE_FLAME,20,
|
|
||||||
TILE_TRIGGER,2,
|
|
||||||
TILE_GOLDFLAME,2,
|
|
||||||
TILE_SKATES,20,
|
|
||||||
TILE_TURTLE,5,
|
|
||||||
TILE_NONE,160
|
|
||||||
};
|
|
||||||
|
|
||||||
static GameOptions gameoptions;
|
|
||||||
|
|
||||||
static const unsigned char playerpositions[MAXNETNODES*3] = { /* color, x, y */
|
|
||||||
2,0,0,
|
|
||||||
3,14,10,
|
|
||||||
4,14,0,
|
|
||||||
5,0,10,
|
|
||||||
1,6,0,
|
|
||||||
6,8,10,
|
|
||||||
7,0,6,
|
|
||||||
8,14,4,
|
|
||||||
};
|
|
||||||
|
|
||||||
static void resetplayer(player *pl, int color, int x, int y) {
|
|
||||||
pl->speed=SPEEDSTART;
|
|
||||||
pl->flags=0;
|
|
||||||
pl->flamelength=gameoptions.flames+1;
|
|
||||||
pl->bombsavailable=gameoptions.bombs+1;
|
|
||||||
|
|
||||||
pl->color=color;
|
|
||||||
|
|
||||||
pl->xpos=arraytoscreenx(x);
|
|
||||||
pl->ypos=arraytoscreeny(y);
|
|
||||||
|
|
||||||
field[y][x]=FIELD_EMPTY;
|
|
||||||
if(x) field[y][x-1]=FIELD_EMPTY;
|
|
||||||
if(y) field[y-1][x]=FIELD_EMPTY;
|
|
||||||
if(x<arraynumx-1) field[y][x+1]=FIELD_EMPTY;
|
|
||||||
if(y<arraynumy-1) field[y+1][x]=FIELD_EMPTY;
|
|
||||||
|
|
||||||
addtail(&activeplayers, pl);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void initplayer(int color,int x,int y,int controller) {
|
|
||||||
player *pl;
|
|
||||||
|
|
||||||
pl = allocentry(player);
|
|
||||||
if(!pl)
|
|
||||||
nomem("Couldn't get player structure (allocentry())");
|
|
||||||
|
|
||||||
list_add_tail(&allplayers, &pl->list_all_players);
|
|
||||||
|
|
||||||
pl->controller=controller;
|
|
||||||
pl->fixx=-4;
|
|
||||||
pl->fixy=-40;
|
|
||||||
pl->kills = pl->deaths = 0;
|
|
||||||
|
|
||||||
resetplayer(pl, color, x, y);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void initplayers(void) {
|
|
||||||
int i;
|
|
||||||
const unsigned char *p;
|
|
||||||
int c,x,y;
|
|
||||||
|
|
||||||
if(NETWORK_NONE == network) {
|
|
||||||
initplayer(2,0,0,-1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
p=playerpositions;
|
|
||||||
for(i=0;i<MAXNETNODES;++i) {
|
|
||||||
if(!netnodes[i].used) continue;
|
|
||||||
c=*p++;
|
|
||||||
x=*p++;
|
|
||||||
y=*p++;
|
|
||||||
initplayer(c,x,y,i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void resetplayers(void) {
|
|
||||||
const unsigned char *p;
|
|
||||||
int c,x,y;
|
|
||||||
player *pl;
|
|
||||||
|
|
||||||
p=playerpositions;
|
|
||||||
list_for_each_entry(pl, &allplayers, list_all_players) {
|
|
||||||
c=*p++;
|
|
||||||
x=*p++;
|
|
||||||
y=*p++;
|
|
||||||
resetplayer(pl, c, x, y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void firstzero(void) {
|
|
||||||
alloc_things();
|
|
||||||
list_init_head(&activebombs);
|
|
||||||
list_init_head(&detonatebombs);
|
|
||||||
list_init_head(&activeflames);
|
|
||||||
list_init_head(&activedecays);
|
|
||||||
list_init_head(&activebonus);
|
|
||||||
list_init_head(&activeplayers);
|
|
||||||
list_init_head(&activegeneric);
|
|
||||||
list_init_head(&allplayers);
|
|
||||||
|
|
||||||
mycount = mydatacount = 0;
|
|
||||||
memset(latestactions,0,sizeof(latestactions));
|
|
||||||
memset(latestcounts,0,sizeof(latestcounts));
|
|
||||||
memset(actionblock,0,sizeof(actionblock));
|
|
||||||
actioncount = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void initgame() {
|
|
||||||
int i,j;
|
|
||||||
int x,y;
|
|
||||||
int bl;
|
|
||||||
const int *p;
|
|
||||||
int comp;
|
|
||||||
|
|
||||||
if (network != NETWORK_SLAVE)
|
|
||||||
set_game_options(&configopts);
|
|
||||||
gameframe=0;
|
|
||||||
|
|
||||||
things_list_clear(&activebombs);
|
|
||||||
things_list_clear(&detonatebombs);
|
|
||||||
things_list_clear(&activeflames);
|
|
||||||
things_list_clear(&activedecays);
|
|
||||||
things_list_clear(&activebonus);
|
|
||||||
list_init_head(&activeplayers);
|
|
||||||
things_list_clear(&activegeneric);
|
|
||||||
|
|
||||||
p=bonuschances;
|
|
||||||
bonustotal=0;
|
|
||||||
for(;;) {
|
|
||||||
i=*p++;
|
|
||||||
if(i==TILE_NONE) break;
|
|
||||||
bonustotal+=*p++;
|
|
||||||
}
|
|
||||||
bonustotal += 64*(3-gameoptions.generosity);
|
|
||||||
memset(field,0,sizeof(field));
|
|
||||||
comp=gameoptions.density;
|
|
||||||
for(j=0;j<arraynumy;++j)
|
|
||||||
for(i=0;i<arraynumx;++i) {
|
|
||||||
/* if((i&j)&1) {
|
|
||||||
field[j][i]=FIELD_BORDER;
|
|
||||||
} else*/
|
|
||||||
field[j][i]=
|
|
||||||
(myrand()&3)>=comp ? FIELD_BRICK : FIELD_EMPTY;
|
|
||||||
}
|
|
||||||
|
|
||||||
solidcopyany(&backgroundoriginal,&background,0,0,IXSIZE,IYSIZE);
|
|
||||||
|
|
||||||
resetplayers();
|
|
||||||
|
|
||||||
for(j=0;j<arraynumy;++j) {
|
|
||||||
y=arraystarty+j*arrayspacey;
|
|
||||||
for(i=0;i<arraynumx;++i) {
|
|
||||||
x=arraystartx+i*arrayspacex;
|
|
||||||
bl=field[j][i];
|
|
||||||
if(bl==FIELD_BORDER) bl=2;
|
|
||||||
else if(bl==FIELD_BRICK) bl=1;
|
|
||||||
else continue;
|
|
||||||
drawfigureany(x,y,blocks+bl,&background);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
solidcopy(&background,0,0,IXSIZE,IYSIZE);
|
|
||||||
copyup();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void addflame(player *owner,int px,int py) {
|
|
||||||
flame *fl,*fl2;
|
|
||||||
|
|
||||||
fl = allocentry(flame);
|
|
||||||
if(!fl) return;
|
|
||||||
addtail(&activeflames,fl);
|
|
||||||
field[py][px]=FIELD_FLAME;
|
|
||||||
info[py][px]=fl;
|
|
||||||
fl->px=px;
|
|
||||||
fl->py=py;
|
|
||||||
fl->xpos=arraytoscreenx(px);
|
|
||||||
fl->ypos=arraytoscreeny(py);
|
|
||||||
fl->owner=owner;
|
|
||||||
if(px && field[py][px-1]==FIELD_FLAME) {
|
|
||||||
fl2=info[py][px-1];
|
|
||||||
fl->lurd|=FL_LEFT;
|
|
||||||
fl2->lurd|=FL_RIGHT;
|
|
||||||
}
|
|
||||||
if(py && field[py-1][px]==FIELD_FLAME) {
|
|
||||||
fl2=info[py-1][px];
|
|
||||||
fl->lurd|=FL_UP;
|
|
||||||
fl2->lurd|=FL_DOWN;
|
|
||||||
}
|
|
||||||
if(px<arraynumx-1 && field[py][px+1]==FIELD_FLAME) {
|
|
||||||
fl2=info[py][px+1];
|
|
||||||
fl->lurd|=FL_RIGHT;
|
|
||||||
fl2->lurd|=FL_LEFT;
|
|
||||||
}
|
|
||||||
if(py<arraynumy-1 && field[py+1][px]==FIELD_FLAME) {
|
|
||||||
fl2=info[py+1][px];
|
|
||||||
fl->lurd|=FL_DOWN;
|
|
||||||
fl2->lurd|=FL_UP;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void dropbomb(player *pl,int px,int py,int type){
|
|
||||||
bomb *bmb;
|
|
||||||
|
|
||||||
if(field[py][px]!=FIELD_EMPTY) return;
|
|
||||||
bmb = allocentry(bomb);
|
|
||||||
if(!bmb) return;
|
|
||||||
playsound(3);
|
|
||||||
addtail(&activebombs,bmb);
|
|
||||||
|
|
||||||
--(pl->bombsavailable);
|
|
||||||
field[py][px]=FIELD_BOMB;
|
|
||||||
info[py][px]=bmb;
|
|
||||||
bmb->type=type;
|
|
||||||
bmb->px=px;
|
|
||||||
bmb->py=py;
|
|
||||||
bmb->xpos=arraytoscreenx(px);
|
|
||||||
bmb->ypos=arraytoscreeny(py);
|
|
||||||
bmb->power=pl->flamelength;
|
|
||||||
bmb->owner=pl;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void adddecay(int px,int py) {
|
|
||||||
brickdecay *bd;
|
|
||||||
int xpos,ypos;
|
|
||||||
|
|
||||||
bd = allocentry(brickdecay);
|
|
||||||
if(!bd) return;
|
|
||||||
field[py][px]=FIELD_EXPLODING;
|
|
||||||
bd->xpos=arraytoscreenx(px);
|
|
||||||
bd->ypos=arraytoscreeny(py);
|
|
||||||
bd->px=px;
|
|
||||||
bd->py=py;
|
|
||||||
addtail(&activedecays,bd);
|
|
||||||
xpos=tovideox(bd->xpos);
|
|
||||||
ypos=tovideoy(bd->ypos);
|
|
||||||
solidcopyany(&backgroundoriginal,&background,xpos,ypos,
|
|
||||||
arrayspacex,arrayspacey);
|
|
||||||
solidcopy(&background,xpos,ypos,arrayspacex,arrayspacey);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void addbonus(int px,int py,int type) {
|
|
||||||
bonustile *bonus;
|
|
||||||
|
|
||||||
bonus = allocentry(bonustile);
|
|
||||||
if(!bonus) return;
|
|
||||||
addtail(&activebonus,bonus);
|
|
||||||
bonus->px=px;
|
|
||||||
bonus->py=py;
|
|
||||||
bonus->xpos=arraytoscreenx(px);
|
|
||||||
bonus->ypos=arraytoscreeny(py);
|
|
||||||
bonus->type=type;
|
|
||||||
field[py][px]=FIELD_BONUS;
|
|
||||||
info[py][px]=bonus;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void trybonus(int px,int py) {
|
|
||||||
int i=0, r;
|
|
||||||
const int *p;
|
|
||||||
|
|
||||||
if(field[py][px]!=FIELD_EMPTY) return;
|
|
||||||
p=bonuschances;
|
|
||||||
r=myrand()%bonustotal;
|
|
||||||
while(r>=0) {
|
|
||||||
i=*p++;
|
|
||||||
r-=*p++;
|
|
||||||
}
|
|
||||||
if(i==TILE_NONE) return;
|
|
||||||
addbonus(px,py,i);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void deletebonus(bonustile *bonus) {
|
|
||||||
int px,py;
|
|
||||||
|
|
||||||
px=bonus->px;
|
|
||||||
py=bonus->py;
|
|
||||||
field[py][px]=0;
|
|
||||||
info[py][px]=0;
|
|
||||||
list_del(&bonus->list);
|
|
||||||
freeentry(bonus);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void adddetonate(bomb *bmb) {
|
|
||||||
if (bmb->type==BOMB_OFF) return;
|
|
||||||
|
|
||||||
bmb->type = BOMB_OFF;
|
|
||||||
field[bmb->py][bmb->px] = FIELD_EXPLODING;
|
|
||||||
info[bmb->py][bmb->px] = 0;
|
|
||||||
|
|
||||||
removeitem(bmb);
|
|
||||||
addtail(&detonatebombs, bmb);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void processbombs() {
|
|
||||||
bomb *bmb, *next;
|
|
||||||
|
|
||||||
list_for_each_entry_safe(bmb, next, &activebombs, list) {
|
|
||||||
++(bmb->figcount);
|
|
||||||
++bmb->timer;
|
|
||||||
switch(bmb->type) {
|
|
||||||
case BOMB_NORMAL:
|
|
||||||
if (bmb->timer == BOMBLIFE)
|
|
||||||
adddetonate(bmb);
|
|
||||||
break;
|
|
||||||
case BOMB_CONTROLLED:
|
|
||||||
if (bmb->timer == BOMB_CONTROLLED_LIFE) {
|
|
||||||
bmb->timer = 0;
|
|
||||||
bmb->type = BOMB_NORMAL;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void flameshaft(player *owner,int px,int py,int dx,int dy,int power) {
|
|
||||||
int there;
|
|
||||||
bomb *bmb;
|
|
||||||
|
|
||||||
while(power--) {
|
|
||||||
px+=dx;
|
|
||||||
py+=dy;
|
|
||||||
if(px<0 || py<0 || px>=arraynumx || py>=arraynumy) break;
|
|
||||||
there=field[py][px];
|
|
||||||
switch(there) {
|
|
||||||
case FIELD_BOMB:
|
|
||||||
bmb=info[py][px];
|
|
||||||
adddetonate(bmb);
|
|
||||||
break;
|
|
||||||
case FIELD_EMPTY:
|
|
||||||
addflame(owner,px,py);
|
|
||||||
break;
|
|
||||||
case FIELD_BRICK:
|
|
||||||
adddecay(px,py);
|
|
||||||
power=0;
|
|
||||||
break;
|
|
||||||
case FIELD_BONUS:
|
|
||||||
deletebonus(info[py][px]);
|
|
||||||
power=0;
|
|
||||||
break;
|
|
||||||
case FIELD_BORDER:
|
|
||||||
case FIELD_EXPLODING:
|
|
||||||
default:
|
|
||||||
power=0;
|
|
||||||
case FIELD_FLAME:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void detonatebomb(bomb *bmb) {
|
|
||||||
int px,py;
|
|
||||||
int power;
|
|
||||||
player *owner;
|
|
||||||
|
|
||||||
++(bmb->owner->bombsavailable);
|
|
||||||
px=bmb->px;
|
|
||||||
py=bmb->py;
|
|
||||||
power=bmb->power;
|
|
||||||
owner=bmb->owner;
|
|
||||||
list_del(&bmb->list);
|
|
||||||
freeentry(bmb);
|
|
||||||
addflame(owner,px,py);
|
|
||||||
flameshaft(owner,px,py,-1,0,power);
|
|
||||||
flameshaft(owner,px,py,0,-1,power);
|
|
||||||
flameshaft(owner,px,py,1,0,power);
|
|
||||||
flameshaft(owner,px,py,0,1,power);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void dodetonations(void) {
|
|
||||||
int i = 0;
|
|
||||||
bomb *bmb;
|
|
||||||
|
|
||||||
while (!list_empty(&detonatebombs)) {
|
|
||||||
bmb = (bomb*) detonatebombs.next;
|
|
||||||
++i;
|
|
||||||
detonatebomb(bmb);
|
|
||||||
}
|
|
||||||
if(i) playsound((myrand()&1) ? 0 : 4);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void processflames(void) {
|
|
||||||
flame *fl, *next;
|
|
||||||
|
|
||||||
list_for_each_entry_safe(fl, next, &activeflames, list) {
|
|
||||||
++(fl->timer);
|
|
||||||
|
|
||||||
if(fl->timer==FLAMELIFE) {
|
|
||||||
field[fl->py][fl->px]=FIELD_EMPTY;
|
|
||||||
info[fl->py][fl->px]=0;
|
|
||||||
list_del(&fl->list);
|
|
||||||
freeentry(fl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void processdecays() {
|
|
||||||
brickdecay *bd, *next;
|
|
||||||
|
|
||||||
list_for_each_entry_safe(bd, next, &activedecays, list) {
|
|
||||||
++(bd->timer);
|
|
||||||
if(bd->timer == DECAYLIFE) {
|
|
||||||
field[bd->py][bd->px] = FIELD_EMPTY;
|
|
||||||
trybonus(bd->px, bd->py);
|
|
||||||
list_del(&bd->list);
|
|
||||||
freeentry(bd);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void drawbombs(void) {
|
|
||||||
int j;
|
|
||||||
bomb *bmb;
|
|
||||||
struct figure *figtab;
|
|
||||||
int color;
|
|
||||||
int xpos,ypos;
|
|
||||||
|
|
||||||
list_for_each_entry(bmb, &activebombs, list) {
|
|
||||||
color=bmb->owner->color;
|
|
||||||
figtab=(bmb->type==BOMB_NORMAL) ? bombs1[color] : bombs2[color];
|
|
||||||
j=bmb->figcount % (NUMBOMBFRAMES<<1);
|
|
||||||
if(j>=NUMBOMBFRAMES) j=(NUMBOMBFRAMES<<1)-j-1;
|
|
||||||
xpos=tovideox(bmb->xpos);
|
|
||||||
ypos=tovideoy(bmb->ypos)-3;
|
|
||||||
|
|
||||||
addsprite(xpos,ypos,figtab+j);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void drawflames(void) {
|
|
||||||
flame *fl;
|
|
||||||
int xpos,ypos;
|
|
||||||
/* no player specific flame sprites yet */
|
|
||||||
/* int color; */
|
|
||||||
int fig;
|
|
||||||
|
|
||||||
list_for_each_entry(fl, &activeflames, list) {
|
|
||||||
/* color=fl->owner->color; */
|
|
||||||
xpos=tovideox(fl->xpos);
|
|
||||||
ypos=tovideoy(fl->ypos);
|
|
||||||
fig=(fl->timer*10)/FLAMELIFE;
|
|
||||||
if(fig>=5) fig=9-fig;
|
|
||||||
fig+=5*fl->lurd;
|
|
||||||
addsprite(xpos,ypos,flamefigs[0/* color */]+fig);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void drawdecays() {
|
|
||||||
brickdecay *bd;
|
|
||||||
|
|
||||||
list_for_each_entry(bd, &activedecays, list) {
|
|
||||||
addsprite(tovideox(bd->xpos),tovideoy(bd->ypos),
|
|
||||||
blocksx+(bd->timer*9)/DECAYLIFE);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void drawbonus() {
|
|
||||||
bonustile *bonus;
|
|
||||||
|
|
||||||
list_for_each_entry(bonus, &activebonus, list) {
|
|
||||||
addsprite(tovideox(bonus->xpos),tovideoy(bonus->ypos),
|
|
||||||
tiles+bonus->type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void drawplayers() {
|
|
||||||
player *pl;
|
|
||||||
int xpos,ypos;
|
|
||||||
|
|
||||||
list_for_each_entry(pl, &activeplayers, list) {
|
|
||||||
if(!(pl->flags & FLG_DEAD)) {
|
|
||||||
if(!pl->figure)
|
|
||||||
pl->figure=walking[pl->color]+30;
|
|
||||||
xpos=tovideox(pl->xpos)+pl->fixx;
|
|
||||||
ypos=tovideoy(pl->ypos)+pl->fixy;
|
|
||||||
addsprite(xpos,ypos,pl->figure);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void detonatecontrolled(player *pl) {
|
|
||||||
bomb *bmb, *next;
|
|
||||||
|
|
||||||
list_for_each_entry_safe(bmb, next, &activebombs, list) {
|
|
||||||
if(bmb->owner==pl && bmb->type==BOMB_CONTROLLED)
|
|
||||||
adddetonate(bmb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void playonce(generic *gen) {
|
|
||||||
if (gen->timer == gen->data1) {
|
|
||||||
list_del(&gen->list);
|
|
||||||
freeentry(gen);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void drawgeneric(generic *gen) {
|
|
||||||
addsprite(gen->xpos,gen->ypos,((figure *)(gen->ptr1))+gen->timer);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void queuesequence(int xpos,int ypos,figure *fig,int count) {
|
|
||||||
generic *gen;
|
|
||||||
|
|
||||||
gen = allocentry(generic);
|
|
||||||
if(!gen) return;
|
|
||||||
gen->xpos=xpos;
|
|
||||||
gen->ypos=ypos;
|
|
||||||
gen->data1=count;
|
|
||||||
gen->process=playonce;
|
|
||||||
gen->draw=drawgeneric;
|
|
||||||
gen->ptr1=fig;
|
|
||||||
addtail(&activegeneric,gen);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void adddeath(player *pl) {
|
|
||||||
int xpos,ypos;
|
|
||||||
|
|
||||||
xpos=tovideox(pl->xpos)+pl->fixx-10;
|
|
||||||
ypos=tovideoy(pl->ypos)+pl->fixy;
|
|
||||||
queuesequence(xpos,ypos,death,NUMDEATHFRAMES);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void killplayer(player *pl) {
|
|
||||||
pl->deaths++;
|
|
||||||
pl->flags|=FLG_DEAD;
|
|
||||||
playsound(2);
|
|
||||||
adddeath(pl);
|
|
||||||
detonatecontrolled(pl);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void processgenerics(void) {
|
|
||||||
generic *gen, *next;
|
|
||||||
|
|
||||||
list_for_each_entry_safe(gen, next, &activegeneric, list) {
|
|
||||||
++(gen->timer);
|
|
||||||
gen->process(gen);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void drawgenerics(void) {
|
|
||||||
generic *gen;
|
|
||||||
|
|
||||||
list_for_each_entry(gen, &activegeneric, list) {
|
|
||||||
gen->draw(gen);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void drawstats(void) {
|
|
||||||
player *pl;
|
|
||||||
int p = 0;
|
|
||||||
const char *n;
|
|
||||||
char buf[16];
|
|
||||||
|
|
||||||
solidcopy(&background, 0, 0, IXSIZE, arraystarty);
|
|
||||||
list_for_each_entry(pl, &allplayers, list_all_players) {
|
|
||||||
if (pl->controller >= 0) {
|
|
||||||
n = netnodes[pl->controller].name;
|
|
||||||
} else {
|
|
||||||
n = playername;
|
|
||||||
}
|
|
||||||
snprintf(buf, sizeof(buf), "%-8.8s %2i/%2i", n, pl->kills % 100, pl->deaths % 100);
|
|
||||||
drawstring(11 + (p/2) * (15 * fontxsize + 7), 11 + (p%2) * (fontysize+2), buf);
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int centerxchange(player *pl) {
|
|
||||||
int speed;
|
|
||||||
int val;
|
|
||||||
int line;
|
|
||||||
int max;
|
|
||||||
|
|
||||||
max=arrayspacex<<FRACTION;
|
|
||||||
speed=pl->speed;
|
|
||||||
val=pl->xpos+(max<<2);
|
|
||||||
val%=max;
|
|
||||||
line=max>>1;
|
|
||||||
if(val<line) {
|
|
||||||
if(val-speed<0)
|
|
||||||
return -val;
|
|
||||||
else
|
|
||||||
return -speed;
|
|
||||||
} else if(val>=line) {
|
|
||||||
if(val+speed>max)
|
|
||||||
return max-val;
|
|
||||||
else
|
|
||||||
return speed;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void centerx(player *pl) {
|
|
||||||
pl->xpos+=centerxchange(pl);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int centerychange(player *pl) {
|
|
||||||
int speed;
|
|
||||||
int val;
|
|
||||||
int line;
|
|
||||||
int max;
|
|
||||||
|
|
||||||
max=arrayspacey<<FRACTION;
|
|
||||||
speed=pl->speed;
|
|
||||||
val=pl->ypos+(max<<2);
|
|
||||||
val%=max;
|
|
||||||
line=max>>1;
|
|
||||||
if(val<line)
|
|
||||||
{
|
|
||||||
if(val-speed<0)
|
|
||||||
return -val;
|
|
||||||
else
|
|
||||||
return -speed;
|
|
||||||
} else if(val>=line)
|
|
||||||
{
|
|
||||||
if(val+speed>max)
|
|
||||||
return max-val;
|
|
||||||
else
|
|
||||||
return speed;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void centery(player *pl) {
|
|
||||||
pl->ypos+=centerychange(pl);
|
|
||||||
}
|
|
||||||
|
|
||||||
#define SGN(x) ((x)==0 ? 0 : ((x)<0 ? -1 : 1))
|
|
||||||
|
|
||||||
static void trymove(player *pl,int dx,int dy) {
|
|
||||||
int wx,wy;
|
|
||||||
int sx,sy;
|
|
||||||
int there;
|
|
||||||
int px,py;
|
|
||||||
static int depth=0;
|
|
||||||
int tx,ty;
|
|
||||||
|
|
||||||
++depth;
|
|
||||||
sx=(dx*(arrayspacex+1)) << (FRACTION-1);
|
|
||||||
sy=(dy*(arrayspacey+1)) << (FRACTION-1);
|
|
||||||
|
|
||||||
wx=screentoarrayx(pl->xpos+sx);
|
|
||||||
wy=screentoarrayy(pl->ypos+sy);
|
|
||||||
px=screentoarrayx(pl->xpos);
|
|
||||||
py=screentoarrayy(pl->ypos);
|
|
||||||
|
|
||||||
if(wx<0 || wx>=arraynumx || wy<0 || wy>=arraynumy) {
|
|
||||||
--depth;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
there=field[wy][wx];
|
|
||||||
if((px!=wx || py!=wy) &&
|
|
||||||
(there==FIELD_BRICK||there==FIELD_BOMB||there==FIELD_BORDER))
|
|
||||||
{
|
|
||||||
if(dx && !dy) {
|
|
||||||
ty=centerychange(pl);
|
|
||||||
if(ty && depth==1)
|
|
||||||
trymove(pl,0,-SGN(ty));
|
|
||||||
|
|
||||||
} else if(dy && !dx) {
|
|
||||||
tx=centerxchange(pl);
|
|
||||||
if(tx && depth==1)
|
|
||||||
trymove(pl,-SGN(tx),0);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
pl->xpos+=dx*pl->speed;
|
|
||||||
pl->ypos+=dy*pl->speed;
|
|
||||||
if(dx && !dy) centery(pl);
|
|
||||||
if(dy && !dx) centerx(pl);
|
|
||||||
}
|
|
||||||
--depth;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void applybonus(player *pl,bonustile *bonus) {
|
|
||||||
int type;
|
|
||||||
int maxflame;
|
|
||||||
|
|
||||||
maxflame=arraynumx>arraynumy ? arraynumx : arraynumy;
|
|
||||||
type=bonus->type;
|
|
||||||
deletebonus(bonus);
|
|
||||||
switch(type) {
|
|
||||||
case TILE_BOMB:
|
|
||||||
if (pl->bombsavailable < 9)
|
|
||||||
++(pl->bombsavailable);
|
|
||||||
break;
|
|
||||||
case TILE_FLAME:
|
|
||||||
if(pl->flamelength<maxflame)
|
|
||||||
++(pl->flamelength);
|
|
||||||
break;
|
|
||||||
case TILE_GOLDFLAME:
|
|
||||||
pl->flamelength=maxflame;
|
|
||||||
break;
|
|
||||||
case TILE_TRIGGER:
|
|
||||||
pl->flags|=FLG_CONTROL;
|
|
||||||
break;
|
|
||||||
case TILE_SKATES:
|
|
||||||
if (pl->speed < SPEEDSTART) {
|
|
||||||
pl->speed = SPEEDSTART;
|
|
||||||
} else {
|
|
||||||
pl->speed+=SPEEDDELTA;
|
|
||||||
}
|
|
||||||
if(pl->speed>SPEEDMAX) pl->speed=SPEEDMAX;
|
|
||||||
break;
|
|
||||||
case TILE_TURTLE:
|
|
||||||
pl->speed=SPEEDTURTLE;
|
|
||||||
pl->speedturtle_timeout=SPEEDTURTLE_TIMEOUT;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void doplayer(player *pl) {
|
|
||||||
/* int last; */
|
|
||||||
int color;
|
|
||||||
/* int speed; */
|
|
||||||
int px,py;
|
|
||||||
int there;
|
|
||||||
int flags;
|
|
||||||
int what;
|
|
||||||
|
|
||||||
if(pl->controller==-1)
|
|
||||||
what=myaction;
|
|
||||||
else
|
|
||||||
what=actions[pl->controller];
|
|
||||||
|
|
||||||
flags=pl->flags;
|
|
||||||
if(flags&FLG_DEAD) return;
|
|
||||||
color=pl->color;
|
|
||||||
/* last=pl->doing; */
|
|
||||||
pl->doing=what;
|
|
||||||
/* speed=pl->speed; */
|
|
||||||
px=screentoarrayx(pl->xpos);
|
|
||||||
py=screentoarrayy(pl->ypos);
|
|
||||||
there=field[py][px];
|
|
||||||
|
|
||||||
if(what==ACT_QUIT) {
|
|
||||||
killplayer(pl);
|
|
||||||
list_del(&pl->list_all_players);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(there==FIELD_BONUS) {
|
|
||||||
playsound((myrand()&1) ? 1 : 5);
|
|
||||||
applybonus(pl,info[py][px]);
|
|
||||||
} else if(there==FIELD_FLAME) {
|
|
||||||
flame *fl = info[py][px];
|
|
||||||
if (fl->owner == pl) {
|
|
||||||
pl->kills--;
|
|
||||||
} else {
|
|
||||||
fl->owner->kills++;
|
|
||||||
}
|
|
||||||
killplayer(pl);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if(what&ACT_TURBO) speed<<=2;
|
|
||||||
if(what&ACT_PRIMARY) {
|
|
||||||
if(there==FIELD_EMPTY && pl->bombsavailable)
|
|
||||||
dropbomb(pl,px,py,
|
|
||||||
(flags&FLG_CONTROL) ? BOMB_CONTROLLED :BOMB_NORMAL);
|
|
||||||
}
|
|
||||||
if(what&ACT_SECONDARY && (flags&FLG_CONTROL))
|
|
||||||
detonatecontrolled(pl);
|
|
||||||
|
|
||||||
switch(what&ACT_MASK) {
|
|
||||||
case ACT_UP:
|
|
||||||
trymove(pl,0,-1);
|
|
||||||
pl->figcount=(pl->figcount+1)%15;
|
|
||||||
pl->figure=walking[color]+pl->figcount+15;
|
|
||||||
break;
|
|
||||||
case ACT_DOWN:
|
|
||||||
trymove(pl,0,1);
|
|
||||||
pl->figcount=(pl->figcount+1)%15;
|
|
||||||
pl->figure=walking[color]+pl->figcount+30;
|
|
||||||
break;
|
|
||||||
case ACT_LEFT:
|
|
||||||
trymove(pl,-1,0);
|
|
||||||
pl->figcount=(pl->figcount+1)%15;
|
|
||||||
pl->figure=walking[color]+pl->figcount+45;
|
|
||||||
break;
|
|
||||||
case ACT_RIGHT:
|
|
||||||
trymove(pl,1,0);
|
|
||||||
pl->figcount=(pl->figcount+1)%15;
|
|
||||||
pl->figure=walking[color]+pl->figcount;
|
|
||||||
break;
|
|
||||||
case ACT_NONE:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pl->speedturtle_timeout > 0) {
|
|
||||||
pl->speedturtle_timeout--;
|
|
||||||
if (0 == pl->speedturtle_timeout) {
|
|
||||||
if (pl->speed < SPEEDSTART) pl->speed = SPEEDSTART;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void processplayers(void) {
|
|
||||||
player *pl, *next;
|
|
||||||
|
|
||||||
list_for_each_entry_safe(pl, next, &activeplayers, list) {
|
|
||||||
doplayer(pl);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void processquits(void) {
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (network != NETWORK_SLAVE) return;
|
|
||||||
for (i = 0; i < MAXNETNODES; ++i) {
|
|
||||||
if (netnodes[i].used && actions[i]==ACT_QUIT)
|
|
||||||
netnodes[i].used=0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int getaction(void) {
|
|
||||||
int what;
|
|
||||||
|
|
||||||
what=ACT_NONE;
|
|
||||||
if(checkpressed(MYLEFT)) what=ACT_LEFT;
|
|
||||||
else if(checkpressed(MYRIGHT)) what=ACT_RIGHT;
|
|
||||||
else if(checkpressed(MYDOWN)) what=ACT_DOWN;
|
|
||||||
else if(checkpressed(MYUP)) what=ACT_UP;
|
|
||||||
else if(checkdown(13)) what=ACT_ENTER;
|
|
||||||
else if(checkdown(0x1b)) what=ACT_QUIT;
|
|
||||||
|
|
||||||
if(checkdown(' '))
|
|
||||||
what|=ACT_PRIMARY;
|
|
||||||
if(checkdown('b'))
|
|
||||||
what|=ACT_SECONDARY;
|
|
||||||
|
|
||||||
return what;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int iterate(void) {
|
|
||||||
int i;
|
|
||||||
int gountil; /* destination tick */
|
|
||||||
static int deathcount = 0;
|
|
||||||
|
|
||||||
mypause();
|
|
||||||
scaninput();
|
|
||||||
|
|
||||||
erasesprites();
|
|
||||||
clearspritelist();
|
|
||||||
gfxunlock();
|
|
||||||
|
|
||||||
myaction = getaction();
|
|
||||||
if (NETWORK_NONE == network && myaction==ACT_QUIT) return CODE_QUIT;
|
|
||||||
if (NETWORK_NONE == network) {
|
|
||||||
gountil = mycount + 1; /* single step in singly player mode */
|
|
||||||
} else {
|
|
||||||
gountil = networktraffic(); /* as master single step, as slave as many as we can do */
|
|
||||||
}
|
|
||||||
|
|
||||||
while (mycount < gountil) { /* simulate ticks up to gountil */
|
|
||||||
++mycount;
|
|
||||||
if (NETWORK_NONE != network) {
|
|
||||||
i = gountil - mycount;
|
|
||||||
if(i >= ACTIONHIST) // too far behind
|
|
||||||
goto leave_game;
|
|
||||||
memcpy(actions, actionblock+i*MAXNETNODES, MAXNETNODES);
|
|
||||||
if (actions[myslot] == ACT_QUIT) return CODE_QUIT;
|
|
||||||
}
|
|
||||||
processbombs();
|
|
||||||
dodetonations();
|
|
||||||
processdecays();
|
|
||||||
processflames();
|
|
||||||
processgenerics();
|
|
||||||
processquits();
|
|
||||||
processplayers();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
if(!(rand()&127))
|
|
||||||
{
|
|
||||||
i=gtime();
|
|
||||||
while(gtime()-i<100);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
drawbombs();
|
|
||||||
drawbonus();
|
|
||||||
drawgenerics();
|
|
||||||
drawdecays();
|
|
||||||
drawflames();
|
|
||||||
drawplayers();
|
|
||||||
drawstats();
|
|
||||||
plotsprites();
|
|
||||||
copyup();
|
|
||||||
if (list_empty(&activegeneric)) {
|
|
||||||
player *pl;
|
|
||||||
|
|
||||||
int deadplayers = 0;
|
|
||||||
i = 0;
|
|
||||||
|
|
||||||
list_for_each_entry(pl, &activeplayers, list) {
|
|
||||||
if(!(pl->flags & FLG_DEAD))
|
|
||||||
++i;
|
|
||||||
else
|
|
||||||
deadplayers++;
|
|
||||||
}
|
|
||||||
if (deadplayers > 0 && (!i || (NETWORK_NONE != network && i==1))) {
|
|
||||||
++deathcount;
|
|
||||||
if(deathcount==25)
|
|
||||||
return CODE_ALLDEAD;
|
|
||||||
} else
|
|
||||||
deathcount=0;
|
|
||||||
}
|
|
||||||
return CODE_CONT;
|
|
||||||
|
|
||||||
leave_game: /* client disconnect/timeout: send ACT_QUIT to master */
|
|
||||||
myaction = ACT_QUIT;
|
|
||||||
networktraffic();
|
|
||||||
return CODE_QUIT;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_game_options(GameOptions *options) {
|
|
||||||
gameoptions = *options;
|
|
||||||
}
|
|
||||||
|
|
||||||
void run_single_player(void) {
|
|
||||||
int code;
|
|
||||||
network = NETWORK_NONE;
|
|
||||||
|
|
||||||
firstzero();
|
|
||||||
initplayers();
|
|
||||||
do {
|
|
||||||
initgame();
|
|
||||||
while(!(code=iterate()) && !exitflag) ++framecount;
|
|
||||||
} while (code != CODE_QUIT && !exitflag);
|
|
||||||
}
|
|
||||||
|
|
||||||
void run_network_game(void) {
|
|
||||||
int code;
|
|
||||||
|
|
||||||
firstzero();
|
|
||||||
initplayers();
|
|
||||||
do {
|
|
||||||
initgame();
|
|
||||||
while (!(code=iterate()) && !exitflag) ++framecount;
|
|
||||||
} while (code != CODE_QUIT && !exitflag);
|
|
||||||
}
|
|
872
gfx.c
872
gfx.c
@ -1,872 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
#include "bomber.h"
|
|
||||||
#include "gfx.h"
|
|
||||||
|
|
||||||
#define MAXCOLORS 256
|
|
||||||
|
|
||||||
int usedcolors=0;
|
|
||||||
SDL_Surface *thescreen;
|
|
||||||
SDL_Color themap[256];
|
|
||||||
uchar *videomem;
|
|
||||||
int stride;
|
|
||||||
|
|
||||||
int mousex,mousey,mouseb;
|
|
||||||
uchar mustlock=0,locked=0;
|
|
||||||
uchar *block64;
|
|
||||||
|
|
||||||
|
|
||||||
int buttonstate=0,buttondown=0;
|
|
||||||
int mxpos,mypos;
|
|
||||||
|
|
||||||
int pressedcodes[KEYMAX],downcodes[KEYMAX],numpressed,numdown;
|
|
||||||
|
|
||||||
|
|
||||||
void dumpgfx()
|
|
||||||
{
|
|
||||||
usedcolors = 0;
|
|
||||||
}
|
|
||||||
static int bestmatch(int red,int green,int blue)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
int bestcolor,bestdelta=0;
|
|
||||||
int rdelta,gdelta,bdelta;
|
|
||||||
int delta;
|
|
||||||
|
|
||||||
|
|
||||||
i=0;
|
|
||||||
bestcolor=-1;
|
|
||||||
while(i<usedcolors)
|
|
||||||
{
|
|
||||||
rdelta=themap[i].r;
|
|
||||||
rdelta-=red;
|
|
||||||
rdelta*=rdelta;
|
|
||||||
gdelta=themap[i].g;
|
|
||||||
gdelta-=green;
|
|
||||||
gdelta*=gdelta;
|
|
||||||
bdelta=themap[i].b;
|
|
||||||
bdelta-=blue;
|
|
||||||
bdelta*=bdelta;
|
|
||||||
delta=rdelta+gdelta+bdelta;
|
|
||||||
if(bestcolor<0 || delta<bestdelta)
|
|
||||||
{
|
|
||||||
bestdelta=delta;
|
|
||||||
bestcolor=i;
|
|
||||||
}
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
return bestcolor;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void updatemap(void)
|
|
||||||
{
|
|
||||||
SDL_SetColors(thescreen, themap, 0, 256);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void createinout(gfxset *gs)
|
|
||||||
{
|
|
||||||
uchar *p;
|
|
||||||
int i,j,counts[256];
|
|
||||||
uchar red,green,blue;
|
|
||||||
int cnt;
|
|
||||||
|
|
||||||
|
|
||||||
p=gs->gs_pic;
|
|
||||||
for(i=0;i<256;i++) counts[i]=0;
|
|
||||||
i=gs->gs_xsize*gs->gs_ysize;
|
|
||||||
while(i--)
|
|
||||||
counts[*p++]++;
|
|
||||||
cnt=0;
|
|
||||||
gs->gs_inout[0]=0;
|
|
||||||
for(i=1;i<256;i++)
|
|
||||||
{
|
|
||||||
if(counts[i])
|
|
||||||
{
|
|
||||||
cnt++;
|
|
||||||
p=gs->gs_colormap+i+i+i;
|
|
||||||
red=*p++;
|
|
||||||
green=*p++;
|
|
||||||
blue=*p++;
|
|
||||||
for(j=0;j<usedcolors;j++)
|
|
||||||
{
|
|
||||||
if(red==themap[j].r &&
|
|
||||||
green==themap[j].g && blue==themap[j].b)
|
|
||||||
{
|
|
||||||
gs->gs_inout[i]=j;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(j==usedcolors)
|
|
||||||
{
|
|
||||||
if(usedcolors<MAXCOLORS)
|
|
||||||
{
|
|
||||||
themap[j].r=red;
|
|
||||||
themap[j].g=green;
|
|
||||||
themap[j].b=blue;
|
|
||||||
gs->gs_inout[i]=usedcolors;
|
|
||||||
++usedcolors;
|
|
||||||
} else
|
|
||||||
gs->gs_inout[i]=bestmatch(red,green,blue);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
updatemap();
|
|
||||||
}
|
|
||||||
|
|
||||||
static uchar *compressfig(uchar *put,gfxset *gs,
|
|
||||||
int sourcex,int sourcey,int sizex,int sizey)
|
|
||||||
{
|
|
||||||
int j,gswidth;
|
|
||||||
uchar *p, *p2,pixel,*map1;
|
|
||||||
int dx,dy;
|
|
||||||
|
|
||||||
gswidth=gs->gs_xsize;
|
|
||||||
map1=gs->gs_inout;
|
|
||||||
p=gs->gs_pic+sourcex+gswidth*sourcey;
|
|
||||||
for(dy=0;dy<sizey;dy++)
|
|
||||||
{
|
|
||||||
p2=p;
|
|
||||||
j=0;
|
|
||||||
for(dx=0;dx<=sizex;dx++)
|
|
||||||
{
|
|
||||||
if(dx<sizex) pixel=*p2;
|
|
||||||
else pixel=0;
|
|
||||||
++p2;
|
|
||||||
if(pixel)
|
|
||||||
++j;
|
|
||||||
else if(j)
|
|
||||||
{
|
|
||||||
*put++=j;
|
|
||||||
*put++=dx-j;
|
|
||||||
*put++=dy;
|
|
||||||
p2-=j+1;
|
|
||||||
while(j)
|
|
||||||
*put++=map1[*p2++],--j;
|
|
||||||
++p2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
p+=gswidth;
|
|
||||||
}
|
|
||||||
*put++=0;
|
|
||||||
return put;
|
|
||||||
}
|
|
||||||
static void gfxfetchsingle(figure *fig,gfxset *gs,int sourcex,int sourcey,int sizex,int sizey)
|
|
||||||
{
|
|
||||||
uchar *p,*p2;
|
|
||||||
int dx,dy;
|
|
||||||
/* uchar *map1; */
|
|
||||||
int gswidth;
|
|
||||||
int minx,miny,maxx,maxy;
|
|
||||||
int tx,ty;
|
|
||||||
|
|
||||||
/* map1=gs->gs_inout; */
|
|
||||||
gswidth=gs->gs_xsize;
|
|
||||||
p=gs->gs_pic+sourcex+gswidth*sourcey;
|
|
||||||
minx=miny=maxx=maxy=-1;
|
|
||||||
for(dy=0;dy<sizey;dy++)
|
|
||||||
{
|
|
||||||
p2=p;
|
|
||||||
ty=sourcey+dy;
|
|
||||||
for(dx=0;dx<sizex;dx++)
|
|
||||||
{
|
|
||||||
if(!*p2++) continue;
|
|
||||||
if(miny==-1 || ty<miny) miny=ty;
|
|
||||||
if(maxy==-1 || ty>maxy) maxy=ty;
|
|
||||||
tx=sourcex+dx;
|
|
||||||
if(minx==-1 || tx<minx) minx=tx;
|
|
||||||
if(maxx==-1 || tx>maxx) maxx=tx;
|
|
||||||
}
|
|
||||||
p+=gswidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(minx==-1)
|
|
||||||
{
|
|
||||||
minx=maxx=sourcex;
|
|
||||||
miny=maxy=sourcey;
|
|
||||||
}
|
|
||||||
|
|
||||||
fig->xdelta=minx-sourcex;
|
|
||||||
fig->ydelta=miny-sourcey;
|
|
||||||
|
|
||||||
sourcex=minx;
|
|
||||||
sourcey=miny;
|
|
||||||
fig->xsize=sizex=maxx-minx+1;
|
|
||||||
fig->ysize=sizey=maxy-miny+1;
|
|
||||||
|
|
||||||
p=compressfig(block64,gs,sourcex,sourcey,sizex,sizey);
|
|
||||||
fig->graphics=malloc(p-block64);
|
|
||||||
if(fig->graphics)
|
|
||||||
memcpy(fig->graphics,block64,p-block64);
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
//(gfxset *gs,figure *fig,int sourcex,int sourcey,int sizex,int sizey)
|
|
||||||
void gfxfetch(gfxset *gs,figure *fig,int num)
|
|
||||||
{
|
|
||||||
int x,y;
|
|
||||||
int xsize,ysize;
|
|
||||||
int fxsize,fysize;
|
|
||||||
unsigned char *p,*p2;
|
|
||||||
|
|
||||||
xsize=gs->gs_xsize;
|
|
||||||
ysize=gs->gs_ysize;
|
|
||||||
p2=p=gs->gs_pic+xsize+1;
|
|
||||||
fxsize=2;
|
|
||||||
while(*p++==0) ++fxsize;
|
|
||||||
fysize=2;
|
|
||||||
while(*p2==0) ++fysize,p2+=xsize;
|
|
||||||
x=fxsize;
|
|
||||||
y=0;
|
|
||||||
while(num--)
|
|
||||||
{
|
|
||||||
gfxfetchsingle(fig,gs,x,y,fxsize,fysize);
|
|
||||||
x+=fxsize;
|
|
||||||
if(x>xsize-fxsize)
|
|
||||||
{
|
|
||||||
x=0;
|
|
||||||
y+=fysize;
|
|
||||||
if(y>ysize-fysize)
|
|
||||||
y=0;
|
|
||||||
}
|
|
||||||
fig++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void solidfetch(gfxset *gs,solid *dest)
|
|
||||||
{
|
|
||||||
int xsize,ysize;
|
|
||||||
int i;
|
|
||||||
unsigned char *p,*map;
|
|
||||||
uchar *gfx;
|
|
||||||
|
|
||||||
memset(dest,0,sizeof(solid));
|
|
||||||
xsize=gs->gs_xsize;
|
|
||||||
ysize=gs->gs_ysize;
|
|
||||||
|
|
||||||
i=xsize*ysize;
|
|
||||||
gfx=dest->graphics=malloc(i);
|
|
||||||
if(!gfx) return;
|
|
||||||
dest->xsize=xsize;
|
|
||||||
dest->ysize=ysize;
|
|
||||||
map=gs->gs_inout;
|
|
||||||
memcpy(gfx,gs->gs_pic,i);
|
|
||||||
p=gfx;
|
|
||||||
while(i--)
|
|
||||||
{
|
|
||||||
if(*p) *p=map[*p];
|
|
||||||
++p;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void solidcopyany(solid *src,solid *dest,int destx,int desty,int sizex,int sizey)
|
|
||||||
{
|
|
||||||
int xmax,ymax;
|
|
||||||
int j;
|
|
||||||
uchar *p1,*p2;
|
|
||||||
int w;
|
|
||||||
|
|
||||||
xmax=src->xsize;
|
|
||||||
ymax=src->ysize;
|
|
||||||
if(destx>=xmax || desty>=ymax || destx+sizex<=0 || desty+sizey<=0)
|
|
||||||
return;
|
|
||||||
if(destx<0)
|
|
||||||
{
|
|
||||||
sizex+=destx;
|
|
||||||
destx=0;
|
|
||||||
}
|
|
||||||
if(desty<0)
|
|
||||||
{
|
|
||||||
sizey+=desty;
|
|
||||||
desty=0;
|
|
||||||
}
|
|
||||||
if(destx+sizex>xmax)
|
|
||||||
sizex=xmax-destx;
|
|
||||||
if(desty+sizey>ymax)
|
|
||||||
sizey=ymax-desty;
|
|
||||||
|
|
||||||
if(dest)
|
|
||||||
{
|
|
||||||
w=dest->xsize;
|
|
||||||
p1=dest->graphics+desty*w+destx;
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
gfxlock();
|
|
||||||
w=stride;
|
|
||||||
p1=videomem+desty*stride+destx;
|
|
||||||
}
|
|
||||||
p2=src->graphics+desty*xmax+destx;
|
|
||||||
for(j=0;j<sizey;++j)
|
|
||||||
{
|
|
||||||
memcpy(p1,p2,sizex);
|
|
||||||
p1+=w;
|
|
||||||
p2+=xmax;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
void solidcopy(solid *solid,int destx,int desty,int sizex,int sizey)
|
|
||||||
{
|
|
||||||
solidcopyany(solid,0,destx,desty,sizex,sizey);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void drawfigureany(int x,int y,figure *fig,solid *dest)
|
|
||||||
{
|
|
||||||
int run;
|
|
||||||
int dx,dy;
|
|
||||||
int xsize,ysize;
|
|
||||||
int clipx,clipy,w;
|
|
||||||
unsigned char *pc,*p,*p2,*take;
|
|
||||||
|
|
||||||
take=fig->graphics;
|
|
||||||
if(dest)
|
|
||||||
{
|
|
||||||
w=clipx=dest->xsize;
|
|
||||||
clipy=dest->ysize;
|
|
||||||
pc=dest->graphics;
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
gfxlock();
|
|
||||||
w=stride;
|
|
||||||
clipx=IXSIZE;
|
|
||||||
clipy=IYSIZE;
|
|
||||||
pc=videomem;
|
|
||||||
}
|
|
||||||
|
|
||||||
dx=fig->xdelta;
|
|
||||||
dy=fig->ydelta;
|
|
||||||
xsize=fig->xsize;
|
|
||||||
ysize=fig->ysize;
|
|
||||||
x+=dx;
|
|
||||||
y+=dy;
|
|
||||||
if(x>=0 && y>=0 && x<=clipx-xsize && y<=clipy-ysize)
|
|
||||||
{
|
|
||||||
while((run=*take++))
|
|
||||||
{
|
|
||||||
dx=*((signed char *)take); ++take;
|
|
||||||
dy=*((signed char *)take); ++take;
|
|
||||||
p=pc+w*(y+dy)+x+dx;
|
|
||||||
while(run--)
|
|
||||||
*p++=*take++;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
while((run=*take++))
|
|
||||||
{
|
|
||||||
dx=*((signed char *)take); ++take;
|
|
||||||
dy=*((signed char *)take); ++take;
|
|
||||||
dx+=x;
|
|
||||||
dy+=y;
|
|
||||||
p2=take;
|
|
||||||
take+=run;
|
|
||||||
if(dy<0 || dy>=clipy) continue;
|
|
||||||
if(dx>=clipx) continue;
|
|
||||||
if(dx<0)
|
|
||||||
{
|
|
||||||
p2-=dx;
|
|
||||||
run+=dx;
|
|
||||||
dx=0;
|
|
||||||
} else if(dx+run>clipx)
|
|
||||||
run=clipx-dx;
|
|
||||||
p=pc+w*dy+dx;
|
|
||||||
if(run)
|
|
||||||
memcpy(p,p2,run);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void drawfigure(int destx,int desty,figure *fig)
|
|
||||||
{
|
|
||||||
drawfigureany(destx,desty,fig,0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void copyup()
|
|
||||||
{
|
|
||||||
gfxunlock();
|
|
||||||
SDL_UpdateRect(thescreen, 0, 0, 0, 0);
|
|
||||||
needwhole=0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void copyupxy(int x,int y)
|
|
||||||
{
|
|
||||||
gfxunlock();
|
|
||||||
SDL_UpdateRect(thescreen,x,y,24,24);
|
|
||||||
}
|
|
||||||
|
|
||||||
void copyupxysize(int x,int y,int xsize,int ysize)
|
|
||||||
{
|
|
||||||
gfxunlock();
|
|
||||||
SDL_UpdateRect(thescreen,x,y,xsize,ysize);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// static void set_color(int color, int red, int green, int blue) {
|
|
||||||
// themap[color].r=red;
|
|
||||||
// themap[color].g=green;
|
|
||||||
// themap[color].b=blue;
|
|
||||||
// }
|
|
||||||
|
|
||||||
void opengfx(int argc, char **argv) {
|
|
||||||
unsigned long videoflags;
|
|
||||||
|
|
||||||
themap[0].r=0;
|
|
||||||
themap[0].g=0;
|
|
||||||
themap[0].b=0;
|
|
||||||
usedcolors=1;
|
|
||||||
|
|
||||||
block64=malloc(65536);
|
|
||||||
if(!block64)
|
|
||||||
{
|
|
||||||
printf("Couldn't allocate block64\n");
|
|
||||||
exit(50);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER|SDL_INIT_AUDIO) < 0 )
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Couldn't initialize SDL: %s\n",SDL_GetError());
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
videoflags = SDL_SWSURFACE|SDL_HWPALETTE; //|SDL_FULLSCREEN;
|
|
||||||
|
|
||||||
thescreen = SDL_SetVideoMode(IXSIZE, IYSIZE, 8, videoflags);
|
|
||||||
if ( thescreen == NULL )
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Couldn't set display mode: %s\n",
|
|
||||||
SDL_GetError());
|
|
||||||
SDL_Quit();
|
|
||||||
exit(5);
|
|
||||||
}
|
|
||||||
stride=thescreen->pitch;
|
|
||||||
videomem=thescreen->pixels;
|
|
||||||
mustlock=SDL_MUSTLOCK(thescreen);
|
|
||||||
locked=0;
|
|
||||||
SDL_ShowCursor(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void closegfx(void)
|
|
||||||
{
|
|
||||||
SDL_Quit();
|
|
||||||
}
|
|
||||||
|
|
||||||
int checkpressed(int code)
|
|
||||||
{
|
|
||||||
int *p,i;
|
|
||||||
i=numpressed;
|
|
||||||
p=pressedcodes;
|
|
||||||
while(i--)
|
|
||||||
if(*p++==code) return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int checkdown(int code)
|
|
||||||
{
|
|
||||||
int *p,i;
|
|
||||||
i=numdown;
|
|
||||||
p=downcodes;
|
|
||||||
while(i--)
|
|
||||||
if(*p++==code) return 1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int checkbutton(int button)
|
|
||||||
{
|
|
||||||
return buttonstate & (1<<button);
|
|
||||||
}
|
|
||||||
|
|
||||||
int checkbuttondown(int button)
|
|
||||||
{
|
|
||||||
return buttondown & (1<<button);
|
|
||||||
}
|
|
||||||
|
|
||||||
int anydown(void)
|
|
||||||
{
|
|
||||||
return numdown;
|
|
||||||
}
|
|
||||||
|
|
||||||
int takedown(void)
|
|
||||||
{
|
|
||||||
int res=0;
|
|
||||||
|
|
||||||
if(numdown)
|
|
||||||
{
|
|
||||||
res=*downcodes;
|
|
||||||
--numdown;
|
|
||||||
if(numdown)
|
|
||||||
memmove(downcodes,downcodes+1,numdown*sizeof(int));
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
int firstdown(void)
|
|
||||||
{
|
|
||||||
return *downcodes;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define ENDMARK 0xaabacada
|
|
||||||
|
|
||||||
int sdlinoutnormal[]={
|
|
||||||
SDLK_0,'0',
|
|
||||||
SDLK_1,'1',
|
|
||||||
SDLK_2,'2',
|
|
||||||
SDLK_3,'3',
|
|
||||||
SDLK_4,'4',
|
|
||||||
SDLK_5,'5',
|
|
||||||
SDLK_6,'6',
|
|
||||||
SDLK_7,'7',
|
|
||||||
SDLK_8,'8',
|
|
||||||
SDLK_9,'9',
|
|
||||||
SDLK_a,'a',
|
|
||||||
SDLK_b,'b',
|
|
||||||
SDLK_c,'c',
|
|
||||||
SDLK_d,'d',
|
|
||||||
SDLK_e,'e',
|
|
||||||
SDLK_f,'f',
|
|
||||||
SDLK_g,'g',
|
|
||||||
SDLK_h,'h',
|
|
||||||
SDLK_i,'i',
|
|
||||||
SDLK_j,'j',
|
|
||||||
SDLK_k,'k',
|
|
||||||
SDLK_l,'l',
|
|
||||||
SDLK_m,'m',
|
|
||||||
SDLK_n,'n',
|
|
||||||
SDLK_o,'o',
|
|
||||||
SDLK_p,'p',
|
|
||||||
SDLK_q,'q',
|
|
||||||
SDLK_r,'r',
|
|
||||||
SDLK_s,'s',
|
|
||||||
SDLK_t,'t',
|
|
||||||
SDLK_u,'u',
|
|
||||||
SDLK_v,'v',
|
|
||||||
SDLK_w,'w',
|
|
||||||
SDLK_x,'x',
|
|
||||||
SDLK_y,'y',
|
|
||||||
SDLK_z,'z',
|
|
||||||
SDLK_MINUS,'-',
|
|
||||||
SDLK_EQUALS,'=',
|
|
||||||
SDLK_LEFTBRACKET,'[',
|
|
||||||
SDLK_RIGHTBRACKET,']',
|
|
||||||
SDLK_SEMICOLON,';',
|
|
||||||
SDLK_QUOTE,'\'',
|
|
||||||
SDLK_SLASH,'/',
|
|
||||||
SDLK_PERIOD,'.',
|
|
||||||
SDLK_COMMA,',',
|
|
||||||
SDLK_BACKQUOTE,'`',
|
|
||||||
SDLK_BACKSPACE,8,
|
|
||||||
SDLK_TAB,9,
|
|
||||||
SDLK_DELETE,MYDELETE,
|
|
||||||
SDLK_RETURN,13,
|
|
||||||
SDLK_F1,MYF1,
|
|
||||||
SDLK_F2,MYF2,
|
|
||||||
SDLK_F3,MYF3,
|
|
||||||
SDLK_F4,MYF4,
|
|
||||||
SDLK_F5,MYF5,
|
|
||||||
SDLK_F6,MYF6,
|
|
||||||
SDLK_F7,MYF7,
|
|
||||||
SDLK_F8,MYF8,
|
|
||||||
SDLK_F9,MYF9,
|
|
||||||
SDLK_F10,MYF10,
|
|
||||||
SDLK_ESCAPE,0x1b,
|
|
||||||
SDLK_LEFT,MYLEFT,
|
|
||||||
SDLK_RIGHT,MYRIGHT,
|
|
||||||
SDLK_UP,MYUP,
|
|
||||||
SDLK_DOWN,MYDOWN,
|
|
||||||
SDLK_PAGEUP,MYPAGEUP,
|
|
||||||
SDLK_PAGEDOWN,MYPAGEDOWN,
|
|
||||||
SDLK_SPACE,' ',
|
|
||||||
SDLK_HOME,MYHOME,
|
|
||||||
SDLK_END,MYEND,
|
|
||||||
SDLK_LALT,MYALTL,
|
|
||||||
SDLK_RALT,MYALTR,
|
|
||||||
ENDMARK
|
|
||||||
};
|
|
||||||
int sdlinoutshifted[]={
|
|
||||||
SDLK_0,')',
|
|
||||||
SDLK_1,'!',
|
|
||||||
SDLK_2,'@',
|
|
||||||
SDLK_3,'#',
|
|
||||||
SDLK_4,'$',
|
|
||||||
SDLK_5,'%',
|
|
||||||
SDLK_6,'^',
|
|
||||||
SDLK_7,'&',
|
|
||||||
SDLK_8,'*',
|
|
||||||
SDLK_9,'(',
|
|
||||||
SDLK_a,'A',
|
|
||||||
SDLK_b,'B',
|
|
||||||
SDLK_c,'C',
|
|
||||||
SDLK_d,'D',
|
|
||||||
SDLK_e,'E',
|
|
||||||
SDLK_f,'F',
|
|
||||||
SDLK_g,'G',
|
|
||||||
SDLK_h,'H',
|
|
||||||
SDLK_i,'I',
|
|
||||||
SDLK_j,'J',
|
|
||||||
SDLK_k,'K',
|
|
||||||
SDLK_l,'L',
|
|
||||||
SDLK_m,'M',
|
|
||||||
SDLK_n,'N',
|
|
||||||
SDLK_o,'O',
|
|
||||||
SDLK_p,'P',
|
|
||||||
SDLK_q,'Q',
|
|
||||||
SDLK_r,'R',
|
|
||||||
SDLK_s,'S',
|
|
||||||
SDLK_t,'T',
|
|
||||||
SDLK_u,'U',
|
|
||||||
SDLK_v,'V',
|
|
||||||
SDLK_w,'W',
|
|
||||||
SDLK_x,'X',
|
|
||||||
SDLK_y,'Y',
|
|
||||||
SDLK_z,'Z',
|
|
||||||
SDLK_MINUS,'_',
|
|
||||||
SDLK_EQUALS,'+',
|
|
||||||
SDLK_LEFTBRACKET,'{',
|
|
||||||
SDLK_RIGHTBRACKET,'}',
|
|
||||||
SDLK_SEMICOLON,':',
|
|
||||||
SDLK_QUOTE,'"',
|
|
||||||
SDLK_SLASH,'?',
|
|
||||||
SDLK_PERIOD,'>',
|
|
||||||
SDLK_COMMA,'<',
|
|
||||||
SDLK_BACKQUOTE,'~',
|
|
||||||
SDLK_BACKSPACE,8,
|
|
||||||
SDLK_TAB,9,
|
|
||||||
SDLK_DELETE,MYDELETE,
|
|
||||||
SDLK_RETURN,13,
|
|
||||||
SDLK_F1,MYF1+MYSHIFTED,
|
|
||||||
SDLK_F2,MYF2+MYSHIFTED,
|
|
||||||
SDLK_F3,MYF3+MYSHIFTED,
|
|
||||||
SDLK_F4,MYF4+MYSHIFTED,
|
|
||||||
SDLK_F5,MYF5+MYSHIFTED,
|
|
||||||
SDLK_F6,MYF6+MYSHIFTED,
|
|
||||||
SDLK_F7,MYF7+MYSHIFTED,
|
|
||||||
SDLK_F8,MYF8+MYSHIFTED,
|
|
||||||
SDLK_F9,MYF9+MYSHIFTED,
|
|
||||||
SDLK_F10,MYF10+MYSHIFTED,
|
|
||||||
SDLK_ESCAPE,0x1b,
|
|
||||||
SDLK_LEFT,MYLEFT+MYSHIFTED,
|
|
||||||
SDLK_RIGHT,MYRIGHT+MYSHIFTED,
|
|
||||||
SDLK_UP,MYUP+MYSHIFTED,
|
|
||||||
SDLK_DOWN,MYDOWN+MYSHIFTED,
|
|
||||||
SDLK_PAGEUP,MYPAGEUP,
|
|
||||||
SDLK_PAGEDOWN,MYPAGEDOWN,
|
|
||||||
SDLK_SPACE,' ',
|
|
||||||
SDLK_HOME,MYHOME,
|
|
||||||
SDLK_END,MYEND,
|
|
||||||
SDLK_LALT,MYALTL,
|
|
||||||
SDLK_RALT,MYALTR,
|
|
||||||
ENDMARK
|
|
||||||
};
|
|
||||||
static int looklist(int code,int *list)
|
|
||||||
{
|
|
||||||
while((unsigned int)*list!=ENDMARK) {
|
|
||||||
if(*list==code)
|
|
||||||
return list[1];
|
|
||||||
list+=2;
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
static int mapkey(int code,int qual)
|
|
||||||
{
|
|
||||||
|
|
||||||
if(qual & KMOD_SHIFT)
|
|
||||||
code=looklist(code,sdlinoutshifted);
|
|
||||||
else
|
|
||||||
code=looklist(code,sdlinoutnormal);
|
|
||||||
if(code<0) return -1;
|
|
||||||
|
|
||||||
if(qual & KMOD_ALT)
|
|
||||||
code|=MYALTED;
|
|
||||||
|
|
||||||
return code;
|
|
||||||
}
|
|
||||||
static void markkey(int code,int status)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
int *ip;
|
|
||||||
|
|
||||||
if(status)
|
|
||||||
{
|
|
||||||
if(numdown<KEYMAX)
|
|
||||||
downcodes[numdown++]=code;
|
|
||||||
ip=pressedcodes;
|
|
||||||
i=numpressed;
|
|
||||||
while(i)
|
|
||||||
if(*ip++==code) break;
|
|
||||||
else i--;
|
|
||||||
if(!i && numpressed<KEYMAX)
|
|
||||||
pressedcodes[numpressed++]=code;
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
i=numpressed;
|
|
||||||
ip=pressedcodes;
|
|
||||||
while(i)
|
|
||||||
if(*ip++==code)
|
|
||||||
{
|
|
||||||
*--ip=pressedcodes[--numpressed];
|
|
||||||
break;
|
|
||||||
} else i--;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void pollinput(void)
|
|
||||||
{
|
|
||||||
SDL_PollEvent(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void scaninput(void)
|
|
||||||
{
|
|
||||||
SDL_Event event;
|
|
||||||
int key,mod;
|
|
||||||
static int bs=0;
|
|
||||||
|
|
||||||
numdown=0;
|
|
||||||
buttondown=0;
|
|
||||||
while(SDL_PollEvent(&event))
|
|
||||||
{
|
|
||||||
switch(event.type)
|
|
||||||
{
|
|
||||||
case SDL_KEYDOWN:
|
|
||||||
key=event.key.keysym.sym;
|
|
||||||
mod=event.key.keysym.mod;
|
|
||||||
markkey(mapkey(key,mod),1);
|
|
||||||
break;
|
|
||||||
case SDL_KEYUP:
|
|
||||||
key=event.key.keysym.sym;
|
|
||||||
mod=event.key.keysym.mod;
|
|
||||||
markkey(mapkey(key,mod),0);
|
|
||||||
break;
|
|
||||||
case SDL_MOUSEBUTTONUP:
|
|
||||||
bs&=~(1<<(event.button.button-1));
|
|
||||||
mousex=event.button.x>>1;
|
|
||||||
mousey=event.button.y>>1;
|
|
||||||
mouseb=bs;
|
|
||||||
break;
|
|
||||||
case SDL_MOUSEBUTTONDOWN:
|
|
||||||
bs|=1<<(event.button.button-1);
|
|
||||||
mousex=event.button.x>>1;
|
|
||||||
mousey=event.button.y>>1;
|
|
||||||
mouseb=bs;
|
|
||||||
break;
|
|
||||||
case SDL_MOUSEMOTION:
|
|
||||||
mousex=event.motion.x>>1;
|
|
||||||
mousey=event.motion.y>>1;
|
|
||||||
break;
|
|
||||||
case SDL_QUIT:
|
|
||||||
exitflag = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
void scaninput()
|
|
||||||
{
|
|
||||||
|
|
||||||
int i,*ip,code;
|
|
||||||
numdown=0;
|
|
||||||
buttondown=0;
|
|
||||||
while(XCheckMaskEvent(dp,~0,&event))
|
|
||||||
switch(event.type)
|
|
||||||
{
|
|
||||||
case KeyPress:
|
|
||||||
code=XLookupKeysym(keyevent,0);
|
|
||||||
if(numdown<KEYMAX)
|
|
||||||
downcodes[numdown++]=code;
|
|
||||||
ip=pressedcodes;
|
|
||||||
i=numpressed;
|
|
||||||
while(i)
|
|
||||||
if(*ip++==code) break;
|
|
||||||
else i--;
|
|
||||||
if(!i && numpressed<KEYMAX)
|
|
||||||
pressedcodes[numpressed++]=code;
|
|
||||||
break;
|
|
||||||
case KeyRelease:
|
|
||||||
code=XLookupKeysym(keyevent,0);
|
|
||||||
i=numpressed;
|
|
||||||
ip=pressedcodes;
|
|
||||||
while(i)
|
|
||||||
if(*ip++==code)
|
|
||||||
{
|
|
||||||
*--ip=pressedcodes[--numpressed];
|
|
||||||
break;
|
|
||||||
} else i--;
|
|
||||||
break;
|
|
||||||
case ButtonPress:
|
|
||||||
i=1<<buttonevent->button;
|
|
||||||
buttonstate|=i;
|
|
||||||
buttondown|=i;
|
|
||||||
break;
|
|
||||||
case ButtonRelease:
|
|
||||||
buttonstate&=~(1<<buttonevent->button);
|
|
||||||
break;
|
|
||||||
case MotionNotify:
|
|
||||||
mxpos=motionevent->x;
|
|
||||||
mypos=motionevent->y;
|
|
||||||
break;
|
|
||||||
case Expose:
|
|
||||||
copyup();
|
|
||||||
needwhole=0;
|
|
||||||
break;
|
|
||||||
case FocusOut:
|
|
||||||
numpressed=0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
static void drawrect(int x,int y,int xs,int ys,int c)
|
|
||||||
{
|
|
||||||
uchar *p;
|
|
||||||
|
|
||||||
gfxlock();
|
|
||||||
p=videomem+y*stride+x;
|
|
||||||
while(ys--)
|
|
||||||
{
|
|
||||||
memset(p,c,xs);
|
|
||||||
p+=stride;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void greyrect(int x,int y,int xsize,int ysize)
|
|
||||||
{
|
|
||||||
static int greycolor=-1;
|
|
||||||
if(greycolor==-1)
|
|
||||||
greycolor=bestmatch(0,0,0x70);
|
|
||||||
drawrect(x,y,xsize,ysize,greycolor);
|
|
||||||
}
|
|
||||||
|
|
||||||
void clear()
|
|
||||||
{
|
|
||||||
int j;
|
|
||||||
uchar *p;
|
|
||||||
|
|
||||||
gfxlock();
|
|
||||||
p=videomem;
|
|
||||||
for(j=0;j<IYSIZE;++j)
|
|
||||||
{
|
|
||||||
memset(p,0,IXSIZE);
|
|
||||||
p+=stride;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void clearrect(int x,int y,int xsize,int ysize)
|
|
||||||
{
|
|
||||||
drawrect(x,y,xsize,ysize,0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void gfxlock(void)
|
|
||||||
{
|
|
||||||
if(locked || !mustlock) return;
|
|
||||||
if ( SDL_LockSurface(thescreen) < 0 )
|
|
||||||
{
|
|
||||||
fprintf(stderr, "Couldn't lock display surface: %s\n",
|
|
||||||
SDL_GetError());
|
|
||||||
}
|
|
||||||
locked=1;
|
|
||||||
}
|
|
||||||
void gfxunlock(void)
|
|
||||||
{
|
|
||||||
if(!locked || !mustlock) return;
|
|
||||||
SDL_UnlockSurface(thescreen);
|
|
||||||
locked=0;
|
|
||||||
}
|
|
69
gfx.h
69
gfx.h
@ -1,69 +0,0 @@
|
|||||||
|
|
||||||
#ifndef GFX_H
|
|
||||||
#define GFX_H
|
|
||||||
|
|
||||||
#define KEYMAX 128
|
|
||||||
|
|
||||||
|
|
||||||
extern int usedcolors;
|
|
||||||
extern uchar mymap[];
|
|
||||||
extern int screen;
|
|
||||||
extern int fontbase,fontysize;
|
|
||||||
extern char *imageloc;
|
|
||||||
|
|
||||||
extern long map2[];
|
|
||||||
extern uchar fmap[128];
|
|
||||||
extern int buttonstate,buttondown;
|
|
||||||
extern int mxpos,mypos;
|
|
||||||
|
|
||||||
extern int pressedcodes[KEYMAX],downcodes[KEYMAX],numpressed,numdown;
|
|
||||||
|
|
||||||
|
|
||||||
void opengfx(int argc, char **argv);
|
|
||||||
void gfxlock(void);
|
|
||||||
void gfxunlock(void);
|
|
||||||
void pollinput(void);
|
|
||||||
int takedown(void);
|
|
||||||
void closegfx(void);
|
|
||||||
void greyrect(int x,int y,int xsize,int ysize);
|
|
||||||
void clearrect(int x,int y,int xsize,int ysize);
|
|
||||||
void solidfetch(gfxset *gs,solid *dest);
|
|
||||||
extern void dumpgfx(void);
|
|
||||||
extern void createinout(struct gfxset *);
|
|
||||||
extern void getcolors(void);
|
|
||||||
extern void gfxfetch(struct gfxset *,struct figure *,int);
|
|
||||||
extern void puttile(int destx,int desty,int source);
|
|
||||||
extern void store(int x,int y,int which);
|
|
||||||
extern void restore(int x,int y,int which);
|
|
||||||
extern void copyup(void);
|
|
||||||
extern void copyupxy(int x,int y);
|
|
||||||
extern void copyupxysize(int x,int y,int xsize,int ysize);
|
|
||||||
extern void getfigures(void);
|
|
||||||
extern unsigned long getcolor(char *name); /* unsigned long */
|
|
||||||
extern int checkpressed(int code);
|
|
||||||
extern int checkdown(int code);
|
|
||||||
extern int checkbutton(int button);
|
|
||||||
extern int checkbuttondown(int button);
|
|
||||||
extern int anydown(void);
|
|
||||||
extern int firstdown(void);
|
|
||||||
extern void scaninput(void);
|
|
||||||
extern void fontinit(void);
|
|
||||||
extern void writechar(int x,int y,uchar ch);
|
|
||||||
extern void clear(void);
|
|
||||||
extern void drawbox(int x,int y,int size,int color);
|
|
||||||
extern void drawbox2(int x,int y,int sizex,int sizey,int color);
|
|
||||||
extern void drawfillrect(int x,int y,int size,int color);
|
|
||||||
extern void bigpixel(int x,int y,int color);
|
|
||||||
extern void invert(int x,int y);
|
|
||||||
extern int getmousex(void);
|
|
||||||
extern int getmousey(void);
|
|
||||||
extern void drawsquare(int x,int y,uchar *source);
|
|
||||||
extern void colormapon(void);
|
|
||||||
extern void colormapoff(void);
|
|
||||||
extern void palette(uchar *pal);
|
|
||||||
extern void drawfigure(int x,int y,figure *fig);
|
|
||||||
extern void drawfigureany(int x,int y,figure *fig,solid *dest);
|
|
||||||
void solidcopy(solid *src,int destx,int desty,int sizex,int sizey);
|
|
||||||
void solidcopyany(solid *src,solid *dest,int destx,int desty,int sizex,int sizey);
|
|
||||||
|
|
||||||
#endif // GFXX_H
|
|
61
list.h
61
list.h
@ -1,61 +0,0 @@
|
|||||||
#ifndef LIST_H
|
|
||||||
#define LIST_H
|
|
||||||
|
|
||||||
/* from linux kernel */
|
|
||||||
|
|
||||||
#define container_of(ptr, type, member) ({ \
|
|
||||||
const typeof( ((type *)0)->member ) *__mptr = (ptr); \
|
|
||||||
(type *)( (char *)__mptr - offsetof(type,member) );})
|
|
||||||
|
|
||||||
/**
|
|
||||||
* list_entry - get the struct for this entry
|
|
||||||
* @ptr: the &struct list_head pointer.
|
|
||||||
* @type: the type of the struct this is embedded in.
|
|
||||||
* @member: the name of the list_struct within the struct.
|
|
||||||
*/
|
|
||||||
#define list_entry(ptr, type, member) container_of(ptr, type, member)
|
|
||||||
|
|
||||||
void alloc_things(void);
|
|
||||||
void *_allocentry(size_t size);
|
|
||||||
#define allocentry(type) (type*) _allocentry(sizeof(type))
|
|
||||||
void freeentry(void *ptr);
|
|
||||||
|
|
||||||
void list_add_tail(listhead *header, listhead *entry);
|
|
||||||
#define addtail(head, entry) list_add_tail(head, &(entry->list));
|
|
||||||
|
|
||||||
/* remove entry from list */
|
|
||||||
void list_del(listhead *entry);
|
|
||||||
#define removeitem(entry) list_del(&(entry->list));
|
|
||||||
|
|
||||||
void list_init_head(listhead *head);
|
|
||||||
|
|
||||||
void things_list_clear(listhead *head); /* listhead member must be the first member */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* list_for_each_entry - iterate over list of given type
|
|
||||||
* @pos: the type * to use as a loop cursor.
|
|
||||||
* @head: the head for your list.
|
|
||||||
* @member: the name of the list_struct within the struct.
|
|
||||||
*/
|
|
||||||
#define list_for_each_entry(pos, head, member) \
|
|
||||||
for (pos = list_entry((head)->next, typeof(*pos), member); \
|
|
||||||
/* prefetch(pos->member.next), */ \
|
|
||||||
&pos->member != (head); \
|
|
||||||
pos = list_entry(pos->member.next, typeof(*pos), member))
|
|
||||||
|
|
||||||
/**
|
|
||||||
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
|
|
||||||
* @pos:<-->the type * to use as a loop cursor.
|
|
||||||
* @n:<><-->another type * to use as temporary storage
|
|
||||||
* @head:<->the head for your list.
|
|
||||||
* @member:>the name of the list_struct within the struct.
|
|
||||||
*/
|
|
||||||
#define list_for_each_entry_safe(pos, n, head, member) \
|
|
||||||
for (pos = list_entry((head)->next, typeof(*pos), member), \
|
|
||||||
n = list_entry(pos->member.next, typeof(*pos), member); \
|
|
||||||
&pos->member != (head); \
|
|
||||||
pos = n, n = list_entry(n->member.next, typeof(*n), member))
|
|
||||||
|
|
||||||
#define list_empty(head) ((head) == (head)->next)
|
|
||||||
|
|
||||||
#endif
|
|
392
matcher.c
392
matcher.c
@ -1,392 +0,0 @@
|
|||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <sys/uio.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#include <netdb.h>
|
|
||||||
#include <sys/timeb.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
|
|
||||||
|
|
||||||
#define MAXMSG 256
|
|
||||||
#define PORT 5521
|
|
||||||
|
|
||||||
#define TIMETOLIVE 600 // seconds
|
|
||||||
|
|
||||||
typedef unsigned char uchar;
|
|
||||||
char logging=0;
|
|
||||||
|
|
||||||
unsigned char mesg[MAXMSG];
|
|
||||||
int lastsize;
|
|
||||||
int network;
|
|
||||||
char masterhostname[256];
|
|
||||||
|
|
||||||
#define PKT_REGISTER 16
|
|
||||||
#define PKT_ACK 24
|
|
||||||
#define PKT_INFO 40
|
|
||||||
#define PKT_QUERY 32
|
|
||||||
|
|
||||||
#define MAXMATCHES 16
|
|
||||||
|
|
||||||
|
|
||||||
struct registration
|
|
||||||
{
|
|
||||||
uchar id;
|
|
||||||
uchar unique[4];
|
|
||||||
uchar password[4];
|
|
||||||
uchar version[4];
|
|
||||||
uchar name[16];
|
|
||||||
uchar status;
|
|
||||||
};
|
|
||||||
struct query
|
|
||||||
{
|
|
||||||
uchar id;
|
|
||||||
uchar password[4];
|
|
||||||
uchar version[4];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct gamehost
|
|
||||||
{
|
|
||||||
struct gamehost *next,*prev;
|
|
||||||
uchar machine[4];
|
|
||||||
uchar port[2];
|
|
||||||
struct registration reg;
|
|
||||||
long timeout;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
struct gamehost *freehosts=0,*activehosts=0;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
int udpsocket,myport;
|
|
||||||
struct sockaddr_in myname={0},mastername={0};
|
|
||||||
socklen_t senderlength;
|
|
||||||
struct sockaddr_in sender={0};
|
|
||||||
|
|
||||||
long longtime(void)
|
|
||||||
{
|
|
||||||
struct timeb tb;
|
|
||||||
ftime(&tb);
|
|
||||||
return tb.time;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *timestr()
|
|
||||||
{
|
|
||||||
static char timestring[80];
|
|
||||||
|
|
||||||
time_t t;
|
|
||||||
int l;
|
|
||||||
time(&t);
|
|
||||||
strcpy(timestring,ctime(&t));
|
|
||||||
l=strlen(timestring);
|
|
||||||
if(l && timestring[l-1]=='\n') timestring[l-1]=0;
|
|
||||||
return timestring;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int putmsg(struct sockaddr_in *toname,unsigned char *msg,int len)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
|
|
||||||
status=sendto(udpsocket,msg,len,0,
|
|
||||||
(struct sockaddr *)toname,sizeof(struct sockaddr_in));
|
|
||||||
return status;
|
|
||||||
}
|
|
||||||
void ack()
|
|
||||||
{
|
|
||||||
uchar copy[256];
|
|
||||||
|
|
||||||
*copy=PKT_ACK;
|
|
||||||
memmove(copy+1,mesg,lastsize);
|
|
||||||
putmsg(&sender,copy,lastsize+1);
|
|
||||||
}
|
|
||||||
|
|
||||||
int getmsg(int seconds)
|
|
||||||
{
|
|
||||||
int size;
|
|
||||||
|
|
||||||
lastsize=-1;
|
|
||||||
memset(&sender,0,sizeof(sender));
|
|
||||||
senderlength=sizeof(sender);
|
|
||||||
if(seconds)
|
|
||||||
{
|
|
||||||
struct timeval timeout;
|
|
||||||
fd_set readfds;
|
|
||||||
int res;
|
|
||||||
|
|
||||||
timeout.tv_sec=seconds;
|
|
||||||
timeout.tv_usec=0;
|
|
||||||
FD_ZERO(&readfds);
|
|
||||||
FD_SET(udpsocket,&readfds);
|
|
||||||
res=select(udpsocket+1,&readfds,0,0,&timeout);
|
|
||||||
if(res<=0) return -1;
|
|
||||||
}
|
|
||||||
lastsize=size=recvfrom(udpsocket,mesg,MAXMSG,0,
|
|
||||||
(struct sockaddr *)&sender,&senderlength);
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
long longind(unsigned char *p)
|
|
||||||
{
|
|
||||||
return (p[0]<<24L) | (p[1]<<16L) | (p[2]<<8) | p[3];
|
|
||||||
}
|
|
||||||
short shortind(unsigned char *p)
|
|
||||||
{
|
|
||||||
return (p[0]<<8L) | p[1];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void openport(int portwant)
|
|
||||||
{
|
|
||||||
int status;
|
|
||||||
|
|
||||||
myport=portwant;
|
|
||||||
udpsocket=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
|
|
||||||
if(udpsocket==-1)
|
|
||||||
{
|
|
||||||
perror("socket()");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
memset(&myname,0,sizeof(myname));
|
|
||||||
myname.sin_family=AF_INET;
|
|
||||||
myname.sin_addr.s_addr=htonl(INADDR_ANY);
|
|
||||||
myname.sin_port=htons(myport);
|
|
||||||
|
|
||||||
status=bind(udpsocket,(struct sockaddr *) &myname,sizeof(myname));
|
|
||||||
if(status==-1)
|
|
||||||
{
|
|
||||||
perror("bind()");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define PERBLOCK 512
|
|
||||||
|
|
||||||
struct gamehost *newhost()
|
|
||||||
{
|
|
||||||
struct gamehost *h,*block;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if(!freehosts)
|
|
||||||
{
|
|
||||||
block=malloc(sizeof(struct gamehost)*PERBLOCK);
|
|
||||||
if(!block) return 0;
|
|
||||||
freehosts=block;
|
|
||||||
i=PERBLOCK-1;
|
|
||||||
while(i--)
|
|
||||||
{
|
|
||||||
block->next=block+1;
|
|
||||||
++block;
|
|
||||||
}
|
|
||||||
block->next=0;
|
|
||||||
}
|
|
||||||
h=freehosts;
|
|
||||||
freehosts=freehosts->next;
|
|
||||||
memset(h,0,sizeof(struct gamehost));
|
|
||||||
return h;
|
|
||||||
}
|
|
||||||
|
|
||||||
void freehost(struct gamehost *h)
|
|
||||||
{
|
|
||||||
h->next=freehosts;
|
|
||||||
freehosts=h;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct gamehost *findmatch(struct registration *key)
|
|
||||||
{
|
|
||||||
struct gamehost *h;
|
|
||||||
h=activehosts;
|
|
||||||
while(h)
|
|
||||||
{
|
|
||||||
if(!memcmp(&h->reg,key,sizeof(struct registration)-1))
|
|
||||||
return h;
|
|
||||||
h=h->next;
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void insert(struct gamehost *h)
|
|
||||||
{
|
|
||||||
if(activehosts)
|
|
||||||
{
|
|
||||||
h->next=activehosts;
|
|
||||||
h->prev=activehosts->prev;
|
|
||||||
activehosts->prev=h;
|
|
||||||
activehosts=h;
|
|
||||||
} else
|
|
||||||
{
|
|
||||||
h->next=h->prev=0;
|
|
||||||
activehosts=h;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
void delete(struct gamehost *h)
|
|
||||||
{
|
|
||||||
if(h->prev)
|
|
||||||
h->prev->next=h->next;
|
|
||||||
else
|
|
||||||
activehosts=h->next;
|
|
||||||
if(h->next)
|
|
||||||
h->next->prev=h->prev;
|
|
||||||
freehost(h);
|
|
||||||
}
|
|
||||||
void doreg()
|
|
||||||
{
|
|
||||||
struct registration *new;
|
|
||||||
struct gamehost *match;
|
|
||||||
long now;
|
|
||||||
|
|
||||||
new=(struct registration *)mesg;
|
|
||||||
match=findmatch(new);
|
|
||||||
if(logging)
|
|
||||||
{
|
|
||||||
unsigned addr=ntohl(sender.sin_addr.s_addr);
|
|
||||||
unsigned short port=ntohs(sender.sin_port);
|
|
||||||
printf("reg :%s:%d.%d.%d.%d:%d %c%lx '%s'\n",timestr(),
|
|
||||||
(addr>>24)&255,(addr>>16)&255,(addr>>8)&255,addr&255,port,
|
|
||||||
new->status ? '+' : '-',(long)match,new->name);
|
|
||||||
fflush(stdout);
|
|
||||||
}
|
|
||||||
if(!match && !new->status) {ack();return;}
|
|
||||||
if(match && new->status) {ack();return;}
|
|
||||||
if(!match && new->status)
|
|
||||||
{
|
|
||||||
match=newhost();
|
|
||||||
if(!match) return; // No memory, what can we do?
|
|
||||||
memmove(match->machine,&sender.sin_addr.s_addr,4);
|
|
||||||
memmove(match->port,&sender.sin_port,2);
|
|
||||||
match->reg=*new;
|
|
||||||
now=longtime();
|
|
||||||
match->timeout=now+TIMETOLIVE;
|
|
||||||
ack();
|
|
||||||
insert(match);
|
|
||||||
return;
|
|
||||||
} else // match && !new->status
|
|
||||||
{
|
|
||||||
delete(match);
|
|
||||||
ack();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void doquery()
|
|
||||||
{
|
|
||||||
uchar *password;
|
|
||||||
uchar *version;
|
|
||||||
struct gamehost *h;
|
|
||||||
uchar response[2048],*rput,*countersave;
|
|
||||||
int counter;
|
|
||||||
|
|
||||||
if(logging)
|
|
||||||
{
|
|
||||||
unsigned addr=ntohl(sender.sin_addr.s_addr);
|
|
||||||
unsigned short port=ntohs(sender.sin_port);
|
|
||||||
printf("query:%s:%d.%d.%d.%d:%d\n",timestr(),
|
|
||||||
(addr>>24)&255,(addr>>16)&255,(addr>>8)&255,addr&255,port);
|
|
||||||
fflush(stdout);
|
|
||||||
}
|
|
||||||
password=mesg+1;
|
|
||||||
version=mesg+5;
|
|
||||||
h=activehosts;
|
|
||||||
rput=response;
|
|
||||||
*rput++=PKT_INFO;
|
|
||||||
memmove(rput,password,4);
|
|
||||||
rput+=4;
|
|
||||||
memmove(rput,version,4);
|
|
||||||
rput+=4;
|
|
||||||
countersave=rput;
|
|
||||||
*rput++=0;
|
|
||||||
*rput++=0;
|
|
||||||
counter=0;
|
|
||||||
|
|
||||||
while(h)
|
|
||||||
{
|
|
||||||
if(!memcmp(password,h->reg.password,4) &&
|
|
||||||
!memcmp(version,h->reg.version,4) && counter<MAXMATCHES)
|
|
||||||
{
|
|
||||||
++counter;
|
|
||||||
memmove(rput,h->reg.unique,4);
|
|
||||||
rput+=4;
|
|
||||||
memmove(rput,h->machine,4);
|
|
||||||
rput+=4;
|
|
||||||
memmove(rput,h->port,2);
|
|
||||||
rput+=2;
|
|
||||||
memmove(rput,h->reg.name,sizeof(h->reg.name));
|
|
||||||
rput+=sizeof(h->reg.name);
|
|
||||||
}
|
|
||||||
h=h->next;
|
|
||||||
}
|
|
||||||
*countersave++=counter>>8;
|
|
||||||
*countersave++=counter;
|
|
||||||
putmsg(&sender,response,rput-response);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void purge(long cutoff)
|
|
||||||
{
|
|
||||||
struct gamehost *h,*h2;
|
|
||||||
h=activehosts;
|
|
||||||
while(h)
|
|
||||||
{
|
|
||||||
h2=h;
|
|
||||||
h=h->next;
|
|
||||||
if(cutoff-h2->timeout>0)
|
|
||||||
{
|
|
||||||
delete(h2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int main(int argc,char **argv)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
int want;
|
|
||||||
int size;
|
|
||||||
long purgetime;
|
|
||||||
long now;
|
|
||||||
|
|
||||||
want=PORT;
|
|
||||||
if(argc>1)
|
|
||||||
{
|
|
||||||
for(i=1;i<argc;++i)
|
|
||||||
if(!strncmp(argv[i],"-p",2))
|
|
||||||
{
|
|
||||||
if(strlen(argv[i])>2) want=atoi(argv[i]+2);
|
|
||||||
else if(i+1<argc) want=atoi(argv[i+1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
freehosts=0;
|
|
||||||
openport(want);
|
|
||||||
purgetime=longtime()+TIMETOLIVE;
|
|
||||||
for(;;)
|
|
||||||
{
|
|
||||||
size=getmsg(10);
|
|
||||||
if(size>=1)
|
|
||||||
switch(*mesg)
|
|
||||||
{
|
|
||||||
case PKT_REGISTER:
|
|
||||||
if(size<sizeof(struct registration)) continue;
|
|
||||||
doreg();
|
|
||||||
break;
|
|
||||||
case PKT_QUERY:
|
|
||||||
if(size<sizeof(struct query)) continue;
|
|
||||||
doquery();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
now=longtime();
|
|
||||||
if(now-purgetime>0) // avoid year 203x bug...
|
|
||||||
{
|
|
||||||
purge(purgetime);
|
|
||||||
purgetime+=TIMETOLIVE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
402
menu.c
402
menu.c
@ -1,402 +0,0 @@
|
|||||||
|
|
||||||
#include "bomber.h"
|
|
||||||
#include "menu.h"
|
|
||||||
#include "draw.h"
|
|
||||||
#include "gfx.h"
|
|
||||||
#include "utils.h"
|
|
||||||
#include "sound.h"
|
|
||||||
#include "network.h"
|
|
||||||
#include "announce.h"
|
|
||||||
#include "game.h"
|
|
||||||
|
|
||||||
GameOptions configopts = { 2, 1, 0, 2 };
|
|
||||||
|
|
||||||
/* Generic menu */
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
MENU_ANY = -1,
|
|
||||||
MENU_MAIN = 0,
|
|
||||||
MENU_CONFIG = 2,
|
|
||||||
MENU_JOIN = 3
|
|
||||||
} menuname;
|
|
||||||
|
|
||||||
#define MENU_SELECT(x) ((menuname) (-x-1))
|
|
||||||
|
|
||||||
static int menuhistory[32]={0};
|
|
||||||
static char menustring[1024];
|
|
||||||
static char *menuput,*menuitems[40],*menutitle;
|
|
||||||
static int menunum, menuexit;
|
|
||||||
static int menudelta;
|
|
||||||
|
|
||||||
static void drawmenu(int selected) {
|
|
||||||
int i,j;
|
|
||||||
int tx,ty;
|
|
||||||
|
|
||||||
clear();
|
|
||||||
j=strlen(menutitle)*bigfontxsize;
|
|
||||||
drawbigstring((IXSIZE-j) >> 1,20,menutitle);
|
|
||||||
ty=((IYSIZE-(bigfontysize*menunum))>>1)-(IYSIZE>>3);
|
|
||||||
for(i=0;i<menunum;++i)
|
|
||||||
{
|
|
||||||
j=strlen(menuitems[i])*bigfontxsize;
|
|
||||||
tx=(IXSIZE-j) >> 1;
|
|
||||||
if(i==selected)
|
|
||||||
{
|
|
||||||
greyrect(0,ty-1,tx-5,bigfontysize);
|
|
||||||
greyrect(tx+j+3,ty-1,IXSIZE-(tx+j+3),bigfontysize);
|
|
||||||
}
|
|
||||||
drawbigstring(tx,ty,menuitems[i]);
|
|
||||||
ty+=bigfontyspace;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int domenu(menuname whichmenu, int (*pause)(void)) {
|
|
||||||
char redraw;
|
|
||||||
int selected;
|
|
||||||
int mcount=0;
|
|
||||||
|
|
||||||
if(whichmenu>=0)
|
|
||||||
selected=menuhistory[whichmenu];
|
|
||||||
else
|
|
||||||
selected=-whichmenu-1;
|
|
||||||
|
|
||||||
if (!pause) pause=mypause;
|
|
||||||
|
|
||||||
redraw=1;
|
|
||||||
clearspritelist();
|
|
||||||
while(!exitflag) {
|
|
||||||
if(redraw) {
|
|
||||||
drawmenu(selected);
|
|
||||||
redraw=0;
|
|
||||||
}
|
|
||||||
if (!pause()) return -1;
|
|
||||||
scaninput();
|
|
||||||
++mcount;
|
|
||||||
|
|
||||||
clearsprites();
|
|
||||||
clearspritelist();
|
|
||||||
addsprite(IXSIZE/2-50-20,IYSIZE-80,walking[2]+(30+mcount%15));
|
|
||||||
addsprite(IXSIZE/2+50-20,IYSIZE-80,walking[3]+(30+(mcount+7)%15));
|
|
||||||
plotsprites();
|
|
||||||
copyup();
|
|
||||||
|
|
||||||
if(anydown()) playsound(3);
|
|
||||||
while(anydown()) {
|
|
||||||
switch(takedown()) {
|
|
||||||
case MYLEFT:
|
|
||||||
menudelta=-1;
|
|
||||||
return selected;
|
|
||||||
case MYRIGHT:
|
|
||||||
case ' ':
|
|
||||||
case 13:
|
|
||||||
menudelta=1;
|
|
||||||
return selected;
|
|
||||||
case 'k':
|
|
||||||
case MYUP:
|
|
||||||
if (selected) --selected;
|
|
||||||
else selected=menunum-1;
|
|
||||||
if (whichmenu>=0)
|
|
||||||
menuhistory[whichmenu]=selected;
|
|
||||||
redraw=1;
|
|
||||||
break;
|
|
||||||
case 'j':
|
|
||||||
case MYDOWN:
|
|
||||||
++selected;
|
|
||||||
if (selected==menunum) selected=0;
|
|
||||||
if (whichmenu>=0)
|
|
||||||
menuhistory[whichmenu]=selected;
|
|
||||||
redraw=1;
|
|
||||||
break;
|
|
||||||
case 0x1b:
|
|
||||||
if (MENU_MAIN == whichmenu && menuexit != selected) {
|
|
||||||
selected = menuexit;
|
|
||||||
redraw = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
menudelta = 1;
|
|
||||||
return menuexit;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
menudelta = 0;
|
|
||||||
return menuexit;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void menustart() {
|
|
||||||
menunum=-1;
|
|
||||||
menuput=menustring;
|
|
||||||
*menuput=0;
|
|
||||||
menuexit = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void additem_s(char *item, int len) {
|
|
||||||
if (len < 0 || (menustring+sizeof(menustring)-menuput <= len)) return;
|
|
||||||
|
|
||||||
if(menunum<0)
|
|
||||||
menutitle=menuput;
|
|
||||||
else
|
|
||||||
menuitems[menunum]=menuput;
|
|
||||||
++menunum;
|
|
||||||
memcpy(menuput,item,len+1);
|
|
||||||
menuput += len+1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void additem(char *item,...) {
|
|
||||||
char output[256];
|
|
||||||
va_list ap;
|
|
||||||
int len;
|
|
||||||
|
|
||||||
va_start(ap, item);
|
|
||||||
|
|
||||||
len = vsnprintf(output,sizeof(output),item,ap);
|
|
||||||
if (len >= 256) len = 255; /* truncated string */
|
|
||||||
|
|
||||||
additem_s(output, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void addexit(char *item,...) {
|
|
||||||
char output[256];
|
|
||||||
va_list ap;
|
|
||||||
int len;
|
|
||||||
|
|
||||||
va_start(ap, item);
|
|
||||||
|
|
||||||
len = vsnprintf(output,sizeof(output),item,ap);
|
|
||||||
if (len >= 256) len = 255; /* truncated string */
|
|
||||||
|
|
||||||
menuexit = menunum;
|
|
||||||
additem_s(output, len);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* end generic menu */
|
|
||||||
|
|
||||||
/* game menues */
|
|
||||||
|
|
||||||
static const char *densities[]={"PACKED","HIGH","MEDIUM","LOW"};
|
|
||||||
static const char *generosities[]={"LOW","MEDIUM","HIGH","RIDICULOUS"};
|
|
||||||
static const char *dis_en_abled[]={"DISABLED","ENABLED"};
|
|
||||||
|
|
||||||
static void config_menu(void) {
|
|
||||||
int sel;
|
|
||||||
|
|
||||||
while (!exitflag) {
|
|
||||||
menustart();
|
|
||||||
additem("GAME OPTIONS");
|
|
||||||
additem("RETURN TO MAIN MENU");
|
|
||||||
additem("DENSITY: %s",densities[configopts.density]);
|
|
||||||
additem("GENEROSITY: %s",generosities[configopts.generosity]);
|
|
||||||
additem("INITIAL FLAME LENGTH: %d",configopts.flames+1);
|
|
||||||
additem("INITIAL NUMBER OF BOMBS: %d",configopts.bombs+1);
|
|
||||||
additem("SOUND: %s", dis_en_abled[sound_enabled]);
|
|
||||||
sel=domenu(MENU_CONFIG, NULL);
|
|
||||||
switch (sel) {
|
|
||||||
case 0:
|
|
||||||
return;
|
|
||||||
case 1:
|
|
||||||
configopts.density+=menudelta;
|
|
||||||
configopts.density&=3;
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
configopts.generosity+=menudelta;
|
|
||||||
configopts.generosity&=3;
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
configopts.flames+=menudelta;
|
|
||||||
configopts.flames&=7;
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
configopts.bombs+=menudelta;
|
|
||||||
configopts.bombs&=7;
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
sound_enabled = 1 - sound_enabled;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void draw_host_game(void) {
|
|
||||||
int i;
|
|
||||||
char *name;
|
|
||||||
char temp[64];
|
|
||||||
|
|
||||||
#define M3X (IXSIZE/3)
|
|
||||||
#define M3Y (IYSIZE/4)
|
|
||||||
|
|
||||||
clear();
|
|
||||||
centerbig(20,"HOST NETWORK GAME");
|
|
||||||
drawbigstring(M3X,M3Y,"SLOT NAME");
|
|
||||||
for(i=0;i<MAXNETNODES;++i) {
|
|
||||||
if(!netnodes[i].used) continue;
|
|
||||||
name=netnodes[i].name;
|
|
||||||
snprintf(temp,sizeof(temp)," %d %s",i+1,name);
|
|
||||||
drawbigstring(M3X,M3Y+(i+2)*bigfontyspace,temp);
|
|
||||||
}
|
|
||||||
|
|
||||||
copyup();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static void host_game(void) {
|
|
||||||
create_seed_unique();
|
|
||||||
if (!start_network_game()) {
|
|
||||||
failure("COULD NOT REGISTER GAME");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
draw_host_game();
|
|
||||||
for(;;) {
|
|
||||||
scaninput();
|
|
||||||
while(anydown()) {
|
|
||||||
switch(takedown()) {
|
|
||||||
case 0x1b:
|
|
||||||
unregistergame();
|
|
||||||
cancel_network_game();
|
|
||||||
return;
|
|
||||||
case ' ':
|
|
||||||
case 13:
|
|
||||||
unregistergame();
|
|
||||||
if (begin_network_game()) {
|
|
||||||
run_network_game();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
send_invites();
|
|
||||||
draw_host_game();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!handle_joins()) continue;
|
|
||||||
|
|
||||||
send_invites();
|
|
||||||
draw_host_game();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void drawjoinscreen(void) {
|
|
||||||
int i;
|
|
||||||
char name[17];
|
|
||||||
char temp[64];
|
|
||||||
|
|
||||||
#define JX (IXSIZE/3)
|
|
||||||
#define JY (IYSIZE/4)
|
|
||||||
|
|
||||||
clear();
|
|
||||||
centerbig(20,"JOIN NETWORK GAME");
|
|
||||||
drawbigstring(JX,JY,"SLOT NAME");
|
|
||||||
for (i = 0; i < MAXNETNODES; ++i) {
|
|
||||||
if(!netnodes[i].used) continue;
|
|
||||||
memmove(name,netnodes[i].name,16);
|
|
||||||
name[16]=0;
|
|
||||||
snprintf(temp,sizeof(temp)," %d %s",i+1,name);
|
|
||||||
drawbigstring(JX,JY+(i+1)*bigfontyspace,temp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int tryjoin(int which) {
|
|
||||||
int res;
|
|
||||||
|
|
||||||
if (0 == (res = send_join(&gamelistentries[which].netname, playername))) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (!exitflag) {
|
|
||||||
switch (res) {
|
|
||||||
case 1:
|
|
||||||
failure("Game closed");
|
|
||||||
return 0;
|
|
||||||
case 2:
|
|
||||||
drawjoinscreen();
|
|
||||||
copyup();
|
|
||||||
break;
|
|
||||||
case 3: return 1;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
scaninput();
|
|
||||||
while(anydown()) {
|
|
||||||
switch(takedown()) {
|
|
||||||
case 0x1b:
|
|
||||||
send_quit();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
res=scaninvite(200);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int join_game_pause(void) {
|
|
||||||
if (find_more_games()) return 0;
|
|
||||||
mypause();
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void join_game(void) {
|
|
||||||
int i;
|
|
||||||
int sel = -1;
|
|
||||||
|
|
||||||
if (!searchgames()) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
menuhistory[MENU_JOIN] = 0;
|
|
||||||
|
|
||||||
while (-1 == sel) {
|
|
||||||
menustart();
|
|
||||||
if (gamelistsize == 0) {
|
|
||||||
additem("JOIN NETWORK GAME - NO GAMES AVAILABLE");
|
|
||||||
addexit("EXIT");
|
|
||||||
} else {
|
|
||||||
additem("JOIN NETWORK GAME");
|
|
||||||
for (i = 0; i < gamelistsize; i++) {
|
|
||||||
additem(gamelistentries[i].name);
|
|
||||||
}
|
|
||||||
addexit("EXIT");
|
|
||||||
}
|
|
||||||
sel = domenu(MENU_JOIN, join_game_pause);
|
|
||||||
if (menudelta < 0) sel = -1;
|
|
||||||
}
|
|
||||||
stop_search();
|
|
||||||
|
|
||||||
if(menuexit == sel || !gamelistsize) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(!tryjoin(sel)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
run_network_game();
|
|
||||||
}
|
|
||||||
|
|
||||||
void mainloop(void) {
|
|
||||||
int sel;
|
|
||||||
|
|
||||||
exitflag = 0;
|
|
||||||
while(!exitflag) {
|
|
||||||
menustart();
|
|
||||||
additem("BOMBER MAIN MENU");
|
|
||||||
additem("EXIT GAME");
|
|
||||||
additem("START SINGLE PLAYER GAME");
|
|
||||||
additem("OPTIONS");
|
|
||||||
// additem("REMAP MOVEMENT KEYS");
|
|
||||||
additem("START NETWORK GAME");
|
|
||||||
additem("JOIN NETWORK GAME");
|
|
||||||
sel=domenu(MENU_MAIN, NULL);
|
|
||||||
if (menudelta < 0) sel = -1;
|
|
||||||
switch (sel) {
|
|
||||||
case 0:
|
|
||||||
return;
|
|
||||||
case 1:
|
|
||||||
run_single_player();
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
config_menu();
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
host_game();
|
|
||||||
break;
|
|
||||||
case 4:
|
|
||||||
join_game();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
75
meson.build
Normal file
75
meson.build
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
project(
|
||||||
|
'sdlbomber',
|
||||||
|
'c',
|
||||||
|
version: '1.0.10',
|
||||||
|
default_options: [
|
||||||
|
'warning_level=3',
|
||||||
|
'buildtype=debugoptimized',
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
avahi_client_dep = dependency(
|
||||||
|
'avahi-client',
|
||||||
|
)
|
||||||
|
sdl_dep = dependency(
|
||||||
|
'sdl',
|
||||||
|
)
|
||||||
|
|
||||||
|
executable(
|
||||||
|
'sdlbomber',
|
||||||
|
'src/announce.c',
|
||||||
|
'src/bomber.c',
|
||||||
|
'src/draw.c',
|
||||||
|
'src/game.c',
|
||||||
|
'src/gfx.c',
|
||||||
|
'src/list.c',
|
||||||
|
# 'src/matcher.c',
|
||||||
|
'src/menu.c',
|
||||||
|
'src/network.c',
|
||||||
|
'src/sound.c',
|
||||||
|
'src/utils.c',
|
||||||
|
override_options: [
|
||||||
|
'c_std=c17',
|
||||||
|
],
|
||||||
|
install: true,
|
||||||
|
dependencies: [
|
||||||
|
avahi_client_dep,
|
||||||
|
sdl_dep,
|
||||||
|
]
|
||||||
|
)
|
||||||
|
|
||||||
|
install_data(
|
||||||
|
'data/bigfont.pcx',
|
||||||
|
'data/blocks1.pcx',
|
||||||
|
'data/blocks1x.pcx',
|
||||||
|
'data/blocks2.pcx',
|
||||||
|
'data/blocks2x.pcx',
|
||||||
|
'data/blocks3.pcx',
|
||||||
|
'data/blocks3x.pcx',
|
||||||
|
'data/bomb1.pcx',
|
||||||
|
'data/bomb1.raw',
|
||||||
|
'data/bomb2.pcx',
|
||||||
|
'data/bomb2.raw',
|
||||||
|
'data/death.raw',
|
||||||
|
'data/death1.pcx',
|
||||||
|
'data/death2.pcx',
|
||||||
|
'data/death3.pcx',
|
||||||
|
'data/drop.raw',
|
||||||
|
'data/field0.pcx',
|
||||||
|
'data/flames.pcx',
|
||||||
|
'data/font.pcx',
|
||||||
|
'data/pal0.pcx',
|
||||||
|
'data/pal1.pcx',
|
||||||
|
'data/pal2.pcx',
|
||||||
|
'data/pal3.pcx',
|
||||||
|
'data/pal4.pcx',
|
||||||
|
'data/pal5.pcx',
|
||||||
|
'data/pal6.pcx',
|
||||||
|
'data/pal7.pcx',
|
||||||
|
'data/pal8.pcx',
|
||||||
|
'data/pal9.pcx',
|
||||||
|
'data/power1.raw',
|
||||||
|
'data/power2.raw',
|
||||||
|
'data/tiles.pcx',
|
||||||
|
'data/walk.pcx',
|
||||||
|
)
|
190
sound.c
190
sound.c
@ -1,190 +0,0 @@
|
|||||||
#include <unistd.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
#include <SDL_audio.h>
|
|
||||||
#include <SDL_error.h>
|
|
||||||
|
|
||||||
#include "sound.h"
|
|
||||||
|
|
||||||
#ifndef DATADIR
|
|
||||||
#define DATADIR "data"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int sound_enabled = 1;
|
|
||||||
|
|
||||||
static char dirlist[]=DATADIR;
|
|
||||||
|
|
||||||
static int readsound(int num);
|
|
||||||
|
|
||||||
#define NUMSOUNDS ((int)(sizeof(soundnames)/sizeof(char*)))
|
|
||||||
#define MIXMAX 16
|
|
||||||
|
|
||||||
#define SOUND_QUIET -1
|
|
||||||
|
|
||||||
static const char *soundnames[] = {
|
|
||||||
"bomb1.raw",
|
|
||||||
"power1.raw",
|
|
||||||
"death.raw",
|
|
||||||
"drop.raw",
|
|
||||||
"bomb2.raw",
|
|
||||||
"power2.raw",
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct sample
|
|
||||||
{
|
|
||||||
char *data;
|
|
||||||
int len;
|
|
||||||
} sample;
|
|
||||||
|
|
||||||
#define SNDFRAGMENT 1024
|
|
||||||
|
|
||||||
static sample samples[NUMSOUNDS];
|
|
||||||
|
|
||||||
static int soundworking=0;
|
|
||||||
static int fragment;
|
|
||||||
// static int soundwrite,soundread;
|
|
||||||
static int *soundbuffer;
|
|
||||||
static int soundbufferlen;
|
|
||||||
static unsigned char sndclip[8192];
|
|
||||||
|
|
||||||
#define MAXSOUNDCOMMANDS 32
|
|
||||||
static char soundcommands[MAXSOUNDCOMMANDS];
|
|
||||||
static int soundtake,soundput;
|
|
||||||
|
|
||||||
static int sndplaying[MIXMAX],sndposition[MIXMAX];
|
|
||||||
static void fillaudio(void *udata,Uint8 *buffer,int len)
|
|
||||||
{
|
|
||||||
char com,*p;
|
|
||||||
int i,j,*ip;
|
|
||||||
int which;
|
|
||||||
|
|
||||||
while(soundtake!=soundput)
|
|
||||||
{
|
|
||||||
com=soundcommands[soundtake];
|
|
||||||
soundtake=(soundtake+1)&(MAXSOUNDCOMMANDS-1);
|
|
||||||
if(com==SOUND_QUIET) {memset(sndposition,0,sizeof(sndposition));continue;}
|
|
||||||
if(com<NUMSOUNDS)
|
|
||||||
{
|
|
||||||
for(i=0;i<MIXMAX;++i)
|
|
||||||
if(!sndposition[i])
|
|
||||||
{
|
|
||||||
sndposition[i]=1;
|
|
||||||
sndplaying[i]=com;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
memset(soundbuffer,0,soundbufferlen);
|
|
||||||
for(i=0;i<MIXMAX;++i)
|
|
||||||
{
|
|
||||||
if(!sndposition[i]) continue;
|
|
||||||
which=sndplaying[i];
|
|
||||||
if(sndposition[i]==samples[which].len)
|
|
||||||
{
|
|
||||||
sndposition[i]=0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
p=samples[which].data;
|
|
||||||
if(!p) continue;
|
|
||||||
p+=len*(sndposition[i]++ -1);
|
|
||||||
ip=soundbuffer;
|
|
||||||
j=len;
|
|
||||||
while(j--) *ip++ += *p++;
|
|
||||||
}
|
|
||||||
j=len;
|
|
||||||
ip=soundbuffer;;
|
|
||||||
while(j--) *buffer++ = sndclip[4096+*ip++];
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int soundopen(void) {
|
|
||||||
SDL_AudioSpec wanted;
|
|
||||||
int i,j;
|
|
||||||
|
|
||||||
soundtake=soundput=0;
|
|
||||||
memset(sndposition,0,sizeof(sndposition));
|
|
||||||
memset(sndplaying,0,sizeof(sndplaying));
|
|
||||||
fragment=SNDFRAGMENT<<1;
|
|
||||||
soundbufferlen=fragment*sizeof(int);
|
|
||||||
soundbuffer=malloc(soundbufferlen);
|
|
||||||
if(!soundbuffer) return -2;
|
|
||||||
|
|
||||||
memset(&wanted,0,sizeof(wanted));
|
|
||||||
wanted.freq=22050;
|
|
||||||
wanted.channels=2;
|
|
||||||
wanted.format=AUDIO_U8;
|
|
||||||
wanted.samples=fragment>>1;
|
|
||||||
wanted.callback=fillaudio;
|
|
||||||
wanted.userdata=0;
|
|
||||||
|
|
||||||
if(SDL_OpenAudio(&wanted,0)<0)
|
|
||||||
{
|
|
||||||
fprintf(stderr,"Couldn't open audio: %s\n",SDL_GetError());
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
soundworking=1;
|
|
||||||
|
|
||||||
for(i=0;i<8192;i++)
|
|
||||||
{
|
|
||||||
j=i-4096;
|
|
||||||
sndclip[i]=j > 127 ? 255 : (j<-128 ? 0 : j+128);
|
|
||||||
}
|
|
||||||
|
|
||||||
for(i=0;i<NUMSOUNDS;++i)
|
|
||||||
readsound(i);
|
|
||||||
|
|
||||||
SDL_PauseAudio(0);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
void soundclose(void) {
|
|
||||||
if(soundworking)
|
|
||||||
{
|
|
||||||
SDL_CloseAudio();
|
|
||||||
soundworking=0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int readsound(int num) {
|
|
||||||
char name[256],*p1,*p2,ch;
|
|
||||||
int file,size,len;
|
|
||||||
p1=dirlist;
|
|
||||||
for(;;)
|
|
||||||
{
|
|
||||||
p2=name;
|
|
||||||
while(*p1 && (ch=*p1++)!=',')
|
|
||||||
*p2++=ch;
|
|
||||||
if(p2>name && p2[-1]!='/') *p2++='/';
|
|
||||||
strcpy(p2,soundnames[num]);
|
|
||||||
file=open(name,O_RDONLY);
|
|
||||||
if(file>=0) break;
|
|
||||||
if(!*p1)
|
|
||||||
{
|
|
||||||
samples[num].len=-1;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
size=lseek(file,0,SEEK_END);
|
|
||||||
lseek(file,0,SEEK_SET);
|
|
||||||
len=samples[num].len=(size+fragment-1)/fragment;
|
|
||||||
len*=fragment;
|
|
||||||
p1=samples[num].data=malloc(len);
|
|
||||||
if(p1)
|
|
||||||
{
|
|
||||||
read(file,p1,size);
|
|
||||||
if(len-size) memset(p1+size,0,len-size);
|
|
||||||
while(size--) *p1++ ^= 0x80;
|
|
||||||
} else
|
|
||||||
samples[num].data=0;
|
|
||||||
close(file);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void playsound(int n) {
|
|
||||||
if (sound_enabled) {
|
|
||||||
soundcommands[soundput]=n;
|
|
||||||
soundput=(soundput+1)&(MAXSOUNDCOMMANDS-1);
|
|
||||||
}
|
|
||||||
}
|
|
@ -2,12 +2,12 @@
|
|||||||
#include "announce.h"
|
#include "announce.h"
|
||||||
#include "network.h"
|
#include "network.h"
|
||||||
|
|
||||||
#include <time.h>
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <assert.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <avahi-client/client.h>
|
#include <avahi-client/client.h>
|
||||||
#include <avahi-client/lookup.h>
|
#include <avahi-client/lookup.h>
|
||||||
@ -20,10 +20,10 @@
|
|||||||
|
|
||||||
#define SERVICE_TYPE "_sdlbomber._udp"
|
#define SERVICE_TYPE "_sdlbomber._udp"
|
||||||
|
|
||||||
static AvahiClient *client = NULL;
|
static AvahiClient* client = NULL;
|
||||||
static AvahiThreadedPoll *threaded_poll = NULL;
|
static AvahiThreadedPoll* threaded_poll = NULL;
|
||||||
static AvahiEntryGroup *group = NULL;
|
static AvahiEntryGroup* group = NULL;
|
||||||
static AvahiServiceBrowser *browser = NULL;
|
static AvahiServiceBrowser* browser = NULL;
|
||||||
|
|
||||||
static char* name = NULL;
|
static char* name = NULL;
|
||||||
|
|
||||||
@ -37,32 +37,31 @@ static char buffer_glchanged[10];
|
|||||||
gamelistentry gamelistentries[10];
|
gamelistentry gamelistentries[10];
|
||||||
int gamelistsize = 0;
|
int gamelistsize = 0;
|
||||||
|
|
||||||
static void myerror(AvahiClient *c, const char *s) {
|
static void myerror(AvahiClient* c, const char* s) {
|
||||||
fprintf(stderr, "Error in: %s\n (%s)", s, avahi_strerror(avahi_client_errno(client)));
|
fprintf(stderr, "Error in: %s\n (%s)", s, avahi_strerror(avahi_client_errno(c)));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void create_services(AvahiClient *c);
|
static void create_services(AvahiClient* c);
|
||||||
|
|
||||||
static void entry_group_callback(AvahiEntryGroup *g, AvahiEntryGroupState state, AVAHI_GCC_UNUSED void *userdata) {
|
static void entry_group_callback(AvahiEntryGroup* g, AvahiEntryGroupState state, AVAHI_GCC_UNUSED void* userdata) {
|
||||||
group = g;
|
group = g;
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case AVAHI_ENTRY_GROUP_ESTABLISHED :
|
case AVAHI_ENTRY_GROUP_ESTABLISHED:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AVAHI_ENTRY_GROUP_COLLISION :
|
case AVAHI_ENTRY_GROUP_COLLISION: {
|
||||||
{
|
char* n = avahi_alternative_service_name(name);
|
||||||
char *n = avahi_alternative_service_name(name);
|
avahi_free(name);
|
||||||
avahi_free(name);
|
name = n;
|
||||||
name = n;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/* And recreate the services */
|
/* And recreate the services */
|
||||||
avahi_entry_group_reset(group);
|
avahi_entry_group_reset(group);
|
||||||
create_services(avahi_entry_group_get_client(g));
|
create_services(avahi_entry_group_get_client(g));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AVAHI_ENTRY_GROUP_FAILURE :
|
case AVAHI_ENTRY_GROUP_FAILURE:
|
||||||
fprintf(stderr, "Entry group failure: %s\n", avahi_strerror(avahi_client_errno(avahi_entry_group_get_client(g))));
|
fprintf(stderr, "Entry group failure: %s\n", avahi_strerror(avahi_client_errno(avahi_entry_group_get_client(g))));
|
||||||
|
|
||||||
avahi_threaded_poll_quit(threaded_poll);
|
avahi_threaded_poll_quit(threaded_poll);
|
||||||
@ -74,7 +73,7 @@ static void entry_group_callback(AvahiEntryGroup *g, AvahiEntryGroupState state,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void create_services(AvahiClient *c) {
|
static void create_services(AvahiClient* c) {
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!group) {
|
if (!group) {
|
||||||
@ -90,10 +89,9 @@ again:
|
|||||||
snprintf(buf_version, sizeof(buf_version), "version=%X", (unsigned int) version);
|
snprintf(buf_version, sizeof(buf_version), "version=%X", (unsigned int) version);
|
||||||
if ((ret = avahi_entry_group_add_service(group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, name, SERVICE_TYPE, NULL, NULL, port, buf_version, NULL)) < 0) {
|
if ((ret = avahi_entry_group_add_service(group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, name, SERVICE_TYPE, NULL, NULL, port, buf_version, NULL)) < 0) {
|
||||||
|
|
||||||
if (ret == AVAHI_ERR_COLLISION)
|
if (ret == AVAHI_ERR_COLLISION) goto collision;
|
||||||
goto collision;
|
|
||||||
|
|
||||||
fprintf(stderr, "Failed to add "SERVICE_TYPE": %s\n", avahi_strerror(ret));
|
fprintf(stderr, "Failed to add " SERVICE_TYPE ": %s\n", avahi_strerror(ret));
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -105,12 +103,11 @@ again:
|
|||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
collision:
|
collision : {
|
||||||
{
|
char* n = avahi_alternative_service_name(name);
|
||||||
char *n = avahi_alternative_service_name(name);
|
avahi_free(name);
|
||||||
avahi_free(name);
|
name = n;
|
||||||
name = n;
|
}
|
||||||
}
|
|
||||||
avahi_entry_group_reset(group);
|
avahi_entry_group_reset(group);
|
||||||
goto again;
|
goto again;
|
||||||
|
|
||||||
@ -118,7 +115,9 @@ fail:
|
|||||||
avahi_threaded_poll_quit(threaded_poll);
|
avahi_threaded_poll_quit(threaded_poll);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void client_callback(AvahiClient *c, AvahiClientState state, void * userdata) {
|
static void client_callback(AvahiClient* c, AvahiClientState state, void* userdata) {
|
||||||
|
(void) userdata;
|
||||||
|
|
||||||
client = c;
|
client = c;
|
||||||
switch (state) {
|
switch (state) {
|
||||||
case AVAHI_CLIENT_S_RUNNING:
|
case AVAHI_CLIENT_S_RUNNING:
|
||||||
@ -130,16 +129,14 @@ static void client_callback(AvahiClient *c, AvahiClientState state, void * userd
|
|||||||
break;
|
break;
|
||||||
case AVAHI_CLIENT_S_COLLISION:
|
case AVAHI_CLIENT_S_COLLISION:
|
||||||
case AVAHI_CLIENT_S_REGISTERING:
|
case AVAHI_CLIENT_S_REGISTERING:
|
||||||
if (group) {
|
if (group) { avahi_entry_group_reset(group); }
|
||||||
avahi_entry_group_reset(group);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case AVAHI_CLIENT_CONNECTING:
|
case AVAHI_CLIENT_CONNECTING:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int registergame(const char *playername, uint16_t p, const unsigned char v[4]) {
|
int registergame(const char* playername, uint16_t p, const unsigned char v[4]) {
|
||||||
if (name) avahi_free(name);
|
if (name) avahi_free(name);
|
||||||
name = avahi_strdup(playername);
|
name = avahi_strdup(playername);
|
||||||
|
|
||||||
@ -163,7 +160,7 @@ void unregistergame(void) {
|
|||||||
avahi_threaded_poll_unlock(threaded_poll);
|
avahi_threaded_poll_unlock(threaded_poll);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void remove_game_with_name(const char *name) {
|
static void remove_game_with_name(const char* name) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < buffer_glsize; i++) {
|
for (i = 0; i < buffer_glsize; i++) {
|
||||||
@ -178,11 +175,26 @@ static void remove_game_with_name(const char *name) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void resolve_callback(AvahiServiceResolver *r, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event,
|
static void resolve_callback(
|
||||||
const char *name, const char *type, const char *domain, const char *host_name, const AvahiAddress *address,
|
AvahiServiceResolver* r,
|
||||||
uint16_t port, AvahiStringList *txt, AvahiLookupResultFlags flags, void* userdata) {
|
AvahiIfIndex interface,
|
||||||
|
AvahiProtocol protocol,
|
||||||
|
AvahiResolverEvent event,
|
||||||
|
const char* name,
|
||||||
|
const char* type,
|
||||||
|
const char* domain,
|
||||||
|
const char* host_name,
|
||||||
|
const AvahiAddress* address,
|
||||||
|
uint16_t port,
|
||||||
|
AvahiStringList* txt,
|
||||||
|
AvahiLookupResultFlags flags,
|
||||||
|
void* userdata) {
|
||||||
int i;
|
int i;
|
||||||
uint32_t want_version;
|
uint32_t want_version;
|
||||||
|
(void) interface;
|
||||||
|
(void) host_name;
|
||||||
|
(void) flags;
|
||||||
|
(void) userdata;
|
||||||
assert(r);
|
assert(r);
|
||||||
|
|
||||||
if (protocol != AVAHI_PROTO_INET) goto done; /* ignore non IPv4 for now */
|
if (protocol != AVAHI_PROTO_INET) goto done; /* ignore non IPv4 for now */
|
||||||
@ -194,74 +206,89 @@ static void resolve_callback(AvahiServiceResolver *r, AvahiIfIndex interface, Av
|
|||||||
/* Called whenever a service has been resolved successfully or timed out */
|
/* Called whenever a service has been resolved successfully or timed out */
|
||||||
|
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case AVAHI_RESOLVER_FAILURE:
|
case AVAHI_RESOLVER_FAILURE:
|
||||||
fprintf(stderr, "(Resolver) Failed to resolve service '%s' of type '%s' in domain '%s': %s\n", name, type, domain, avahi_strerror(avahi_client_errno(avahi_service_resolver_get_client(r))));
|
fprintf(
|
||||||
break;
|
stderr,
|
||||||
|
"(Resolver) Failed to resolve service '%s' of type '%s' in domain '%s': %s\n",
|
||||||
|
name,
|
||||||
|
type,
|
||||||
|
domain,
|
||||||
|
avahi_strerror(avahi_client_errno(avahi_service_resolver_get_client(r))));
|
||||||
|
break;
|
||||||
|
|
||||||
case AVAHI_RESOLVER_FOUND: {
|
case AVAHI_RESOLVER_FOUND: {
|
||||||
gamelistentry *ge;
|
gamelistentry* ge;
|
||||||
unsigned int version;
|
unsigned int version;
|
||||||
int have_version = 0;
|
int have_version = 0;
|
||||||
AvahiStringList *psl;
|
AvahiStringList* psl;
|
||||||
for (psl = txt ; psl ; psl = psl->next) {
|
for (psl = txt; psl; psl = psl->next) {
|
||||||
if (0 == strncmp("version=", (const char*) psl->text, 8)) {
|
if (0 == strncmp("version=", (const char*) psl->text, 8)) {
|
||||||
sscanf((const char*) psl->text, "version=%X", &version);
|
sscanf((const char*) psl->text, "version=%X", &version);
|
||||||
if (version != want_version) goto done; /* version mismatch */
|
if (version != want_version) goto done; /* version mismatch */
|
||||||
have_version = 1;
|
have_version = 1;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (!have_version) goto done;
|
|
||||||
remove_game_with_name(name);
|
|
||||||
i = buffer_glsize++;
|
|
||||||
ge = &buffer_glentries[i];
|
|
||||||
buffer_glchanged[i] = 1;
|
|
||||||
memset(ge, 0, sizeof(*ge));
|
|
||||||
ge->netname.sin_addr.s_addr = address->data.ipv4.address;
|
|
||||||
ge->netname.sin_family = AF_INET;
|
|
||||||
ge->netname.sin_port = port;
|
|
||||||
strncpy(ge->name, name, 15);
|
|
||||||
}
|
}
|
||||||
|
if (!have_version) goto done;
|
||||||
|
remove_game_with_name(name);
|
||||||
|
i = buffer_glsize++;
|
||||||
|
ge = &buffer_glentries[i];
|
||||||
|
buffer_glchanged[i] = 1;
|
||||||
|
memset(ge, 0, sizeof(*ge));
|
||||||
|
ge->netname.sin_addr.s_addr = address->data.ipv4.address;
|
||||||
|
ge->netname.sin_family = AF_INET;
|
||||||
|
ge->netname.sin_port = port;
|
||||||
|
strncpy(ge->name, name, 15);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
avahi_service_resolver_free(r);
|
avahi_service_resolver_free(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void browse_callback(AvahiServiceBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event,
|
static void browse_callback(
|
||||||
const char *name, const char *type, const char *domain, AvahiLookupResultFlags flags, void* userdata) {
|
AvahiServiceBrowser* b,
|
||||||
|
AvahiIfIndex interface,
|
||||||
|
AvahiProtocol protocol,
|
||||||
|
AvahiBrowserEvent event,
|
||||||
|
const char* name,
|
||||||
|
const char* type,
|
||||||
|
const char* domain,
|
||||||
|
AvahiLookupResultFlags flags,
|
||||||
|
void* userdata) {
|
||||||
|
(void) flags;
|
||||||
|
|
||||||
assert(b);
|
assert(b);
|
||||||
|
|
||||||
/* Called whenever a new services becomes available on the LAN or is removed from the LAN */
|
/* Called whenever a new services becomes available on the LAN or is removed from the LAN */
|
||||||
|
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case AVAHI_BROWSER_FAILURE:
|
case AVAHI_BROWSER_FAILURE:
|
||||||
|
|
||||||
fprintf(stderr, "(Browser) %s\n", avahi_strerror(avahi_client_errno(client)));
|
fprintf(stderr, "(Browser) %s\n", avahi_strerror(avahi_client_errno(client)));
|
||||||
avahi_threaded_poll_quit(threaded_poll);
|
avahi_threaded_poll_quit(threaded_poll);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case AVAHI_BROWSER_NEW:
|
case AVAHI_BROWSER_NEW:
|
||||||
/* fprintf(stderr, "(Browser) NEW: service '%s' of type '%s' in domain '%s'\n", name, type, domain); */
|
/* fprintf(stderr, "(Browser) NEW: service '%s' of type '%s' in domain '%s'\n", name, type, domain); */
|
||||||
|
|
||||||
/* We ignore the returned resolver object. In the callback
|
/* We ignore the returned resolver object. In the callback
|
||||||
function we free it. If the server is terminated before
|
function we free it. If the server is terminated before
|
||||||
the callback function is called the server will free
|
the callback function is called the server will free
|
||||||
the resolver for us. */
|
the resolver for us. */
|
||||||
|
|
||||||
if (!(avahi_service_resolver_new(client, interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, 0, resolve_callback, userdata)))
|
if (!(avahi_service_resolver_new(client, interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, 0, resolve_callback, userdata)))
|
||||||
fprintf(stderr, "Failed to resolve service '%s': %s\n", name, avahi_strerror(avahi_client_errno(client)));
|
fprintf(stderr, "Failed to resolve service '%s': %s\n", name, avahi_strerror(avahi_client_errno(client)));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AVAHI_BROWSER_REMOVE:
|
case AVAHI_BROWSER_REMOVE:
|
||||||
remove_game_with_name(name);
|
remove_game_with_name(name);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AVAHI_BROWSER_ALL_FOR_NOW:
|
case AVAHI_BROWSER_ALL_FOR_NOW:
|
||||||
break;
|
break;
|
||||||
case AVAHI_BROWSER_CACHE_EXHAUSTED:
|
case AVAHI_BROWSER_CACHE_EXHAUSTED:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -9,7 +9,7 @@ struct gamelistentry {
|
|||||||
char name[16];
|
char name[16];
|
||||||
};
|
};
|
||||||
|
|
||||||
int registergame(const char *playername, uint16_t port, const unsigned char version[4]);
|
int registergame(const char* playername, uint16_t port, const unsigned char version[4]);
|
||||||
void unregistergame(void);
|
void unregistergame(void);
|
||||||
|
|
||||||
int searchgames(void);
|
int searchgames(void);
|
@ -1,35 +1,35 @@
|
|||||||
|
#include <fcntl.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/types.h>
|
|
||||||
#include <netdb.h>
|
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <signal.h>
|
#include <sys/types.h>
|
||||||
#include <fcntl.h>
|
#include <unistd.h>
|
||||||
#include <stdarg.h>
|
|
||||||
|
|
||||||
#include "bomber.h"
|
|
||||||
#include "gfx.h"
|
|
||||||
#include "announce.h"
|
#include "announce.h"
|
||||||
#include "sound.h"
|
#include "bomber.h"
|
||||||
#include "menu.h"
|
|
||||||
#include "utils.h"
|
|
||||||
#include "network.h"
|
|
||||||
#include "game.h"
|
|
||||||
#include "draw.h"
|
#include "draw.h"
|
||||||
|
#include "game.h"
|
||||||
|
#include "gfx.h"
|
||||||
|
#include "menu.h"
|
||||||
|
#include "network.h"
|
||||||
|
#include "sound.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
int main(int argc,char **argv) {
|
int main(void) {
|
||||||
char *p;
|
char* p;
|
||||||
|
|
||||||
strcpy(playername,"ANONYMOUS");
|
strcpy(playername, "ANONYMOUS");
|
||||||
p=getenv("USER");
|
p = getenv("USER");
|
||||||
if(p) strncpy(playername,p,sizeof(playername));
|
if (p) strncpy(playername, p, sizeof(playername) - 1);
|
||||||
|
|
||||||
create_seed_unique();
|
create_seed_unique();
|
||||||
|
|
||||||
opengfx(argc, argv);
|
opengfx();
|
||||||
getsocket();
|
getsocket();
|
||||||
if (!initannouncer()) exit(1);
|
if (!initannouncer()) exit(1);
|
||||||
|
|
@ -1,7 +1,8 @@
|
|||||||
#ifndef BOMBER_H
|
#ifndef BOMBER_H
|
||||||
#define BOMBER_H
|
#define BOMBER_H
|
||||||
|
|
||||||
#include "SDL.h"
|
#include "list.h"
|
||||||
|
#include <SDL.h>
|
||||||
|
|
||||||
typedef unsigned char uchar;
|
typedef unsigned char uchar;
|
||||||
extern int xcolors[256];
|
extern int xcolors[256];
|
||||||
@ -38,30 +39,25 @@ extern int xcolors[256];
|
|||||||
typedef struct gfxset {
|
typedef struct gfxset {
|
||||||
uchar gs_colormap[768];
|
uchar gs_colormap[768];
|
||||||
uchar gs_inout[256];
|
uchar gs_inout[256];
|
||||||
uchar *gs_pic;
|
uchar* gs_pic;
|
||||||
int gs_xsize;
|
int gs_xsize;
|
||||||
int gs_ysize;
|
int gs_ysize;
|
||||||
} gfxset;
|
} gfxset;
|
||||||
|
|
||||||
typedef struct figure {
|
typedef struct figure {
|
||||||
int xsize,ysize;
|
int xsize, ysize;
|
||||||
int xdelta,ydelta;
|
int xdelta, ydelta;
|
||||||
uchar *graphics;
|
uchar* graphics;
|
||||||
} figure;
|
} figure;
|
||||||
|
|
||||||
typedef struct solid {
|
typedef struct solid {
|
||||||
int xsize,ysize;
|
int xsize, ysize;
|
||||||
uchar *graphics;
|
uchar* graphics;
|
||||||
} solid;
|
} solid;
|
||||||
|
|
||||||
typedef struct listhead listhead;
|
|
||||||
struct listhead {
|
|
||||||
listhead *prev, *next;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct player {
|
typedef struct player {
|
||||||
listhead list, list_all_players;
|
listhead list, list_all_players;
|
||||||
int xpos,ypos;
|
int xpos, ypos;
|
||||||
int flags;
|
int flags;
|
||||||
int abilities;
|
int abilities;
|
||||||
int speed;
|
int speed;
|
||||||
@ -69,15 +65,15 @@ typedef struct player {
|
|||||||
int bombsused;
|
int bombsused;
|
||||||
int bombsavailable;
|
int bombsavailable;
|
||||||
int flamelength;
|
int flamelength;
|
||||||
int *at;
|
int* at;
|
||||||
int figcount;
|
int figcount;
|
||||||
int doing;
|
int doing;
|
||||||
int action;
|
int action;
|
||||||
int color;
|
int color;
|
||||||
int controller;
|
int controller;
|
||||||
int fixx,fixy;
|
int fixx, fixy;
|
||||||
int kills, deaths;
|
int kills, deaths;
|
||||||
figure *figure;
|
figure* figure;
|
||||||
} player;
|
} player;
|
||||||
|
|
||||||
#define FLG_CONTROL 1
|
#define FLG_CONTROL 1
|
||||||
@ -85,25 +81,25 @@ typedef struct player {
|
|||||||
|
|
||||||
|
|
||||||
typedef struct sprite {
|
typedef struct sprite {
|
||||||
int flags;
|
int flags;
|
||||||
int xpos,ypos;
|
int xpos, ypos;
|
||||||
figure *fig;
|
figure* fig;
|
||||||
} sprite;
|
} sprite;
|
||||||
|
|
||||||
typedef struct damage {
|
typedef struct damage {
|
||||||
int xpos,ypos;
|
int xpos, ypos;
|
||||||
int xsize,ysize;
|
int xsize, ysize;
|
||||||
} damage;
|
} damage;
|
||||||
|
|
||||||
typedef struct bomb {
|
typedef struct bomb {
|
||||||
listhead list;
|
listhead list;
|
||||||
int type;
|
int type;
|
||||||
int xpos,ypos;
|
int xpos, ypos;
|
||||||
int px,py;
|
int px, py;
|
||||||
int power;
|
int power;
|
||||||
int timer;
|
int timer;
|
||||||
int figcount;
|
int figcount;
|
||||||
player *owner;
|
player* owner;
|
||||||
} bomb;
|
} bomb;
|
||||||
|
|
||||||
|
|
||||||
@ -117,11 +113,11 @@ typedef struct bomb {
|
|||||||
|
|
||||||
typedef struct flame {
|
typedef struct flame {
|
||||||
listhead list;
|
listhead list;
|
||||||
int xpos,ypos;
|
int xpos, ypos;
|
||||||
int px,py;
|
int px, py;
|
||||||
int timer;
|
int timer;
|
||||||
int lurd;
|
int lurd;
|
||||||
player *owner;
|
player* owner;
|
||||||
} flame;
|
} flame;
|
||||||
|
|
||||||
#define FL_UP 2
|
#define FL_UP 2
|
||||||
@ -131,27 +127,27 @@ typedef struct flame {
|
|||||||
|
|
||||||
typedef struct brickdecay {
|
typedef struct brickdecay {
|
||||||
listhead list;
|
listhead list;
|
||||||
int xpos,ypos;
|
int xpos, ypos;
|
||||||
int px,py;
|
int px, py;
|
||||||
int timer;
|
int timer;
|
||||||
} brickdecay;
|
} brickdecay;
|
||||||
|
|
||||||
typedef struct bonustile {
|
typedef struct bonustile {
|
||||||
listhead list;
|
listhead list;
|
||||||
int xpos,ypos;
|
int xpos, ypos;
|
||||||
int px,py;
|
int px, py;
|
||||||
int type;
|
int type;
|
||||||
} bonustile;
|
} bonustile;
|
||||||
|
|
||||||
typedef struct generic {
|
typedef struct generic {
|
||||||
listhead list;
|
listhead list;
|
||||||
int xpos,ypos;
|
int xpos, ypos;
|
||||||
int px,py;
|
int px, py;
|
||||||
int timer;
|
int timer;
|
||||||
void (*process)();
|
void (*process)();
|
||||||
void (*draw)();
|
void (*draw)();
|
||||||
void *ptr1,*ptr2;
|
void *ptr1, *ptr2;
|
||||||
int data1,data2;
|
int data1, data2;
|
||||||
} generic;
|
} generic;
|
||||||
|
|
||||||
enum tile_types {
|
enum tile_types {
|
||||||
@ -175,10 +171,10 @@ enum tile_types {
|
|||||||
|
|
||||||
|
|
||||||
// #define ACT_INVALID 0x88
|
// #define ACT_INVALID 0x88
|
||||||
#define ACT_NONE 0
|
#define ACT_NONE 0
|
||||||
#define ACT_UP 1
|
#define ACT_UP 1
|
||||||
#define ACT_DOWN 2
|
#define ACT_DOWN 2
|
||||||
#define ACT_LEFT 3
|
#define ACT_LEFT 3
|
||||||
#define ACT_RIGHT 4
|
#define ACT_RIGHT 4
|
||||||
#define ACT_ENTER 5
|
#define ACT_ENTER 5
|
||||||
#define ACT_QUIT 6
|
#define ACT_QUIT 6
|
||||||
@ -200,7 +196,6 @@ enum tile_types {
|
|||||||
#define CODE_ALLDEAD 2
|
#define CODE_ALLDEAD 2
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#define MAXTHINGS 500
|
#define MAXTHINGS 500
|
||||||
#define MAXSETS 8
|
#define MAXSETS 8
|
||||||
#define MAXSPRITES 256
|
#define MAXSPRITES 256
|
482
src/draw.c
Normal file
482
src/draw.c
Normal file
@ -0,0 +1,482 @@
|
|||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "bomber.h"
|
||||||
|
#include "draw.h"
|
||||||
|
#include "game.h"
|
||||||
|
#include "gfx.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
#ifndef DATADIR
|
||||||
|
#define DATADIR "data"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define NUMCHARACTERS 50
|
||||||
|
|
||||||
|
static figure font[NUMCHARACTERS];
|
||||||
|
static figure bigfont[NUMCHARACTERS];
|
||||||
|
|
||||||
|
gfxset gfxsets[NUMGFX];
|
||||||
|
static char walkingname[256];
|
||||||
|
static char colorsetname[256];
|
||||||
|
static char backgroundname[256];
|
||||||
|
static char blocksname[256];
|
||||||
|
static char blocksxname[256];
|
||||||
|
static char bombs1name[256];
|
||||||
|
static char bombs2name[256];
|
||||||
|
static char flamesname[256];
|
||||||
|
static char tilesname[256];
|
||||||
|
static char deathname[256];
|
||||||
|
static char fontname[256];
|
||||||
|
static char bigfontname[256];
|
||||||
|
|
||||||
|
figure blocks[3];
|
||||||
|
figure blocksx[9];
|
||||||
|
figure bombs1[MAXSETS][NUMBOMBFRAMES];
|
||||||
|
figure bombs2[MAXSETS][NUMBOMBFRAMES];
|
||||||
|
figure flamefigs[MAXSETS][NUMFLAMEFRAMES];
|
||||||
|
figure tiles[15];
|
||||||
|
figure death[NUMDEATHFRAMES];
|
||||||
|
|
||||||
|
int fontxsize, fontysize;
|
||||||
|
int bigfontxsize, bigfontysize, bigfontyspace;
|
||||||
|
|
||||||
|
static int textx, texty;
|
||||||
|
|
||||||
|
static const unsigned char* remapstring = (const unsigned char*) "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ.:!?\177/\\*-,>< =";
|
||||||
|
static char asciiremap[256];
|
||||||
|
|
||||||
|
/* On screen array variables */
|
||||||
|
int arraynumx = 15;
|
||||||
|
int arraynumy = 11;
|
||||||
|
int arraystartx = 20;
|
||||||
|
int arraystarty = 70;
|
||||||
|
int arrayspacex = 40;
|
||||||
|
int arrayspacey = 36;
|
||||||
|
|
||||||
|
static sprite sprites[MAXSPRITES];
|
||||||
|
static int spritesused = 0;
|
||||||
|
|
||||||
|
#define IBUFFLEN 1024
|
||||||
|
int ileft = 0, ihand = 0, byteswide;
|
||||||
|
unsigned char ibuff[IBUFFLEN], *itake;
|
||||||
|
|
||||||
|
static void freegfxset(gfxset* gs) {
|
||||||
|
if (gs->gs_pic) free(gs->gs_pic);
|
||||||
|
gs->gs_pic = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int myci() {
|
||||||
|
if (!ileft) {
|
||||||
|
ileft = read(ihand, ibuff, IBUFFLEN);
|
||||||
|
|
||||||
|
if (!ileft) return -1;
|
||||||
|
itake = ibuff;
|
||||||
|
}
|
||||||
|
ileft--;
|
||||||
|
return *itake++;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dopcxreal(char* name, gfxset* gs) {
|
||||||
|
int xs, ys;
|
||||||
|
int i, j, k;
|
||||||
|
int totalsize;
|
||||||
|
int width, height;
|
||||||
|
unsigned char *bm, *lp;
|
||||||
|
char tname[256];
|
||||||
|
|
||||||
|
memset(gs, 0, sizeof(gfxset));
|
||||||
|
ileft = 0;
|
||||||
|
snprintf(tname, sizeof(tname), DATADIR "/%s", name);
|
||||||
|
ihand = open(tname, O_RDONLY);
|
||||||
|
if (ihand < 0) {
|
||||||
|
char tname2[260];
|
||||||
|
snprintf(tname2, sizeof(tname2), "%s.pcx", tname);
|
||||||
|
ihand = open(tname2, O_RDONLY);
|
||||||
|
if (ihand < 0) return 1;
|
||||||
|
}
|
||||||
|
if (myci() != 10) {
|
||||||
|
close(ihand);
|
||||||
|
return 2;
|
||||||
|
} // 10=zsoft .pcx
|
||||||
|
if (myci() != 5) {
|
||||||
|
close(ihand);
|
||||||
|
return 3;
|
||||||
|
} // version 3.0
|
||||||
|
if (myci() != 1) {
|
||||||
|
close(ihand);
|
||||||
|
return 4;
|
||||||
|
} // encoding method
|
||||||
|
if (myci() != 8) {
|
||||||
|
close(ihand);
|
||||||
|
return 5;
|
||||||
|
} // bpp
|
||||||
|
xs = myci();
|
||||||
|
xs |= myci() << 8;
|
||||||
|
ys = myci();
|
||||||
|
ys |= myci() << 8;
|
||||||
|
width = myci();
|
||||||
|
width |= myci() << 8;
|
||||||
|
height = myci();
|
||||||
|
height |= myci() << 8;
|
||||||
|
width = width + 1 - xs;
|
||||||
|
height = height + 1 - ys;
|
||||||
|
for (i = 0; i < 48 + 4; ++i) myci();
|
||||||
|
myci();
|
||||||
|
if (myci() != 1) {
|
||||||
|
close(ihand);
|
||||||
|
return 6;
|
||||||
|
} // # of planes
|
||||||
|
byteswide = myci();
|
||||||
|
byteswide |= myci() << 8;
|
||||||
|
i = myci();
|
||||||
|
i |= myci() << 8;
|
||||||
|
// if(i!=1) {close(ihand);return 7;} // 1=color/bw,2=grey
|
||||||
|
for (i = 0; i < 58; ++i) myci();
|
||||||
|
totalsize = height * byteswide;
|
||||||
|
bm = malloc(totalsize + 1);
|
||||||
|
if (!bm) {
|
||||||
|
close(ihand);
|
||||||
|
return 8;
|
||||||
|
} // no memory
|
||||||
|
gs->gs_pic = bm;
|
||||||
|
gs->gs_xsize = width;
|
||||||
|
gs->gs_ysize = height;
|
||||||
|
while (height--) {
|
||||||
|
lp = bm;
|
||||||
|
i = byteswide;
|
||||||
|
while (i > 0) {
|
||||||
|
j = myci();
|
||||||
|
if (j < 0xc0) {
|
||||||
|
*lp++ = j;
|
||||||
|
--i;
|
||||||
|
} else {
|
||||||
|
j &= 0x3f;
|
||||||
|
k = myci();
|
||||||
|
while (j-- && i) {
|
||||||
|
*lp++ = k;
|
||||||
|
--i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bm += width;
|
||||||
|
}
|
||||||
|
lseek(ihand, -0x300, SEEK_END);
|
||||||
|
read(ihand, gs->gs_colormap, 0x300);
|
||||||
|
close(ihand);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dopcx(char* name, gfxset* gs) {
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = dopcxreal(name, gs);
|
||||||
|
if (err) printf("Error loading \"%s\":code %d\n", name, err);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void getgroup(char* name, gfxset* colorgs, figure* fig, int count) {
|
||||||
|
int err;
|
||||||
|
int i;
|
||||||
|
gfxset gs;
|
||||||
|
|
||||||
|
err = dopcx(name, &gs);
|
||||||
|
if (err) exit(1000 + err);
|
||||||
|
createinout(&gs);
|
||||||
|
for (i = 0; i < MAXSETS; ++i, fig += count, ++colorgs) {
|
||||||
|
if (!colorgs->gs_pic) continue;
|
||||||
|
memmove(gs.gs_colormap, colorgs->gs_colormap, sizeof(gs.gs_colormap));
|
||||||
|
createinout(&gs);
|
||||||
|
gfxfetch(&gs, fig, count);
|
||||||
|
}
|
||||||
|
freegfxset(&gs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void getsingle(char* name, figure* fig, int count) {
|
||||||
|
gfxset gs;
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = dopcx(name, &gs);
|
||||||
|
if (err) exit(1000 + err);
|
||||||
|
createinout(&gs);
|
||||||
|
gfxfetch(&gs, fig, count);
|
||||||
|
freegfxset(&gs);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void texthome(void) {
|
||||||
|
textx = texty = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawstring(int xpos, int ypos, const char* str) {
|
||||||
|
char ch;
|
||||||
|
|
||||||
|
while ((ch = *str++)) {
|
||||||
|
drawfigure(xpos, ypos, font + asciiremap[toupper(ch)]);
|
||||||
|
xpos += fontxsize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void drawbigstring(int xpos, int ypos, const char* str) {
|
||||||
|
char ch;
|
||||||
|
|
||||||
|
while ('\0' != (ch = *str++)) {
|
||||||
|
drawfigure(xpos, ypos, bigfont + asciiremap[toupper(ch)]);
|
||||||
|
xpos += bigfontxsize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void centerbig(int y, const char* str) {
|
||||||
|
int w;
|
||||||
|
|
||||||
|
w = strlen(str) * bigfontxsize;
|
||||||
|
drawbigstring((IXSIZE - w) >> 1, y, str);
|
||||||
|
}
|
||||||
|
|
||||||
|
// static void scrprintf(char *str,...) {
|
||||||
|
// char output[256],*p,*p2;
|
||||||
|
// va_list ap;
|
||||||
|
//
|
||||||
|
// va_start(ap, str);
|
||||||
|
//
|
||||||
|
// vsprintf(output,str,ap);
|
||||||
|
// p=output;
|
||||||
|
// for(;;) {
|
||||||
|
// p2=p;
|
||||||
|
// while(*p2 && *p2!='\n') ++p2;
|
||||||
|
// if(*p2) {
|
||||||
|
// *p2=0;
|
||||||
|
// drawstring(textx,texty,p);
|
||||||
|
// texty+=fontysize;
|
||||||
|
// textx=10;
|
||||||
|
// p=p2+1;
|
||||||
|
// } else {
|
||||||
|
// drawstring(textx,texty,p);
|
||||||
|
// textx+=fontxsize*(p2-p);
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// copyup();
|
||||||
|
// }
|
||||||
|
|
||||||
|
static void bigscrprintf(char* str, ...) {
|
||||||
|
char output[256], *p, *p2;
|
||||||
|
va_list ap;
|
||||||
|
|
||||||
|
va_start(ap, str);
|
||||||
|
vsnprintf(output, sizeof(output), str, ap);
|
||||||
|
p = output;
|
||||||
|
for (;;) {
|
||||||
|
p2 = p;
|
||||||
|
while (*p2 && *p2 != '\n') ++p2;
|
||||||
|
if (*p2) {
|
||||||
|
*p2 = 0;
|
||||||
|
drawbigstring(textx, texty, p);
|
||||||
|
texty += bigfontysize;
|
||||||
|
textx = 10;
|
||||||
|
p = p2 + 1;
|
||||||
|
} else {
|
||||||
|
drawbigstring(textx, texty, p);
|
||||||
|
textx += bigfontxsize * (p2 - p);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
copyup();
|
||||||
|
}
|
||||||
|
|
||||||
|
void addsprite(int x, int y, figure* fig) {
|
||||||
|
sprite* sp;
|
||||||
|
|
||||||
|
if (spritesused == MAXSPRITES) return;
|
||||||
|
sp = sprites + spritesused++;
|
||||||
|
sp->flags = 0;
|
||||||
|
sp->xpos = x;
|
||||||
|
sp->ypos = y;
|
||||||
|
sp->fig = fig;
|
||||||
|
}
|
||||||
|
|
||||||
|
void plotsprites(void) {
|
||||||
|
int i;
|
||||||
|
sprite* sp;
|
||||||
|
|
||||||
|
sp = sprites;
|
||||||
|
for (i = 0; i < spritesused; ++i) {
|
||||||
|
drawfigure(sp->xpos, sp->ypos, sp->fig);
|
||||||
|
++sp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void erasesprites(void) {
|
||||||
|
int i;
|
||||||
|
sprite* sp;
|
||||||
|
figure* fig;
|
||||||
|
|
||||||
|
sp = sprites;
|
||||||
|
for (i = 0; i < spritesused; ++i) {
|
||||||
|
fig = sp->fig;
|
||||||
|
|
||||||
|
solidcopy(&background, sp->xpos + fig->xdelta, sp->ypos + fig->ydelta, fig->xsize, fig->ysize);
|
||||||
|
++sp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void clearsprites(void) {
|
||||||
|
int i;
|
||||||
|
sprite* sp;
|
||||||
|
figure* fig;
|
||||||
|
|
||||||
|
sp = sprites;
|
||||||
|
for (i = 0; i < spritesused; ++i) {
|
||||||
|
fig = sp->fig;
|
||||||
|
|
||||||
|
clearrect(sp->xpos + fig->xdelta, sp->ypos + fig->ydelta, fig->xsize, fig->ysize);
|
||||||
|
++sp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void clearspritelist(void) {
|
||||||
|
spritesused = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tovideox(int x) {
|
||||||
|
return (x >> FRACTION) + arraystartx;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tovideoy(int y) {
|
||||||
|
return (y >> FRACTION) + arraystarty;
|
||||||
|
}
|
||||||
|
|
||||||
|
int screentoarrayx(int x) {
|
||||||
|
x += arrayspacex << (FRACTION + 2);
|
||||||
|
return ((x >> FRACTION) + (arrayspacex >> 1)) / arrayspacex - 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
int screentoarrayy(int y) {
|
||||||
|
y += arrayspacey << (FRACTION + 2);
|
||||||
|
return ((y >> FRACTION) + (arrayspacey >> 1)) / arrayspacey - 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
int arraytoscreenx(int x) {
|
||||||
|
return arrayspacex * x << FRACTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
int arraytoscreeny(int y) {
|
||||||
|
return arrayspacey * y << FRACTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void loadfonts(void) {
|
||||||
|
int i, j;
|
||||||
|
const unsigned char* p;
|
||||||
|
|
||||||
|
getsingle(fontname, font, NUMCHARACTERS);
|
||||||
|
getsingle(bigfontname, bigfont, NUMCHARACTERS);
|
||||||
|
fontxsize = 8;
|
||||||
|
fontysize = 12;
|
||||||
|
bigfontxsize = 16;
|
||||||
|
bigfontysize = 24;
|
||||||
|
bigfontyspace = 32;
|
||||||
|
p = remapstring;
|
||||||
|
j = 0;
|
||||||
|
while (*p && *p != ' ') ++p, ++j;
|
||||||
|
memset(asciiremap, j, sizeof(asciiremap));
|
||||||
|
p = remapstring;
|
||||||
|
i = 0;
|
||||||
|
while (*p && i < NUMCHARACTERS) asciiremap[(int) *p++] = i++;
|
||||||
|
}
|
||||||
|
|
||||||
|
void loadgfx() {
|
||||||
|
gfxset* gs;
|
||||||
|
gfxset* colorgs;
|
||||||
|
int err;
|
||||||
|
int i;
|
||||||
|
char name[267];
|
||||||
|
|
||||||
|
strcpy(walkingname, "walk");
|
||||||
|
strcpy(colorsetname, "pal");
|
||||||
|
strcpy(backgroundname, "field0");
|
||||||
|
strcpy(blocksname, "blocks3");
|
||||||
|
strcpy(blocksxname, "blocks3x");
|
||||||
|
strcpy(bombs1name, "bomb1");
|
||||||
|
strcpy(bombs2name, "bomb2");
|
||||||
|
strcpy(flamesname, "flames");
|
||||||
|
strcpy(tilesname, "tiles");
|
||||||
|
strcpy(deathname, "death1");
|
||||||
|
strcpy(fontname, "font");
|
||||||
|
strcpy(bigfontname, "bigfont");
|
||||||
|
|
||||||
|
gs = malloc((MAXSETS + 1) * sizeof(gfxset));
|
||||||
|
if (!gs) nomem("loadgfx");
|
||||||
|
colorgs = gs + 1;
|
||||||
|
|
||||||
|
for (i = 0; i < MAXSETS; ++i) {
|
||||||
|
snprintf(name, sizeof(name), "%s%d", colorsetname, i);
|
||||||
|
err = dopcx(name, colorgs + i);
|
||||||
|
if (err) continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
loadfonts();
|
||||||
|
texthome();
|
||||||
|
bigscrprintf("Loading graphics...\n");
|
||||||
|
|
||||||
|
err = dopcx(backgroundname, gs);
|
||||||
|
if (err) exit(1000 + err);
|
||||||
|
createinout(gs);
|
||||||
|
solidfetch(gs, &background);
|
||||||
|
solidfetch(gs, &backgroundoriginal);
|
||||||
|
freegfxset(gs);
|
||||||
|
|
||||||
|
bigscrprintf("Loading blocks\n");
|
||||||
|
getsingle(blocksname, blocks, 3);
|
||||||
|
bigscrprintf("Loading block explosions\n");
|
||||||
|
getsingle(blocksxname, blocksx, 9);
|
||||||
|
bigscrprintf("Loading walking figures\n");
|
||||||
|
getgroup(walkingname, colorgs, walking[0], NUMWALKFRAMES);
|
||||||
|
bigscrprintf("Loading normal bombs\n");
|
||||||
|
getgroup(bombs1name, colorgs, bombs1[0], NUMBOMBFRAMES);
|
||||||
|
bigscrprintf("Loading controlled bombs\n");
|
||||||
|
getgroup(bombs2name, colorgs, bombs2[0], NUMBOMBFRAMES);
|
||||||
|
bigscrprintf("Loading flames\n");
|
||||||
|
// getgroup(flamesname,colorgs,flamefigs[0],NUMFLAMEFRAMES);
|
||||||
|
getsingle(flamesname, flamefigs[0], NUMFLAMEFRAMES);
|
||||||
|
bigscrprintf("Loading bonus tiles\n");
|
||||||
|
getsingle(tilesname, tiles, 15);
|
||||||
|
bigscrprintf("Loading death sequence\n");
|
||||||
|
getsingle(deathname, death, NUMDEATHFRAMES);
|
||||||
|
|
||||||
|
for (i = 0; i < MAXSETS; ++i) freegfxset(colorgs + i);
|
||||||
|
free(gs);
|
||||||
|
bigscrprintf("Done loading graphics\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
void failure(char* str, ...) {
|
||||||
|
char output[256];
|
||||||
|
va_list ap;
|
||||||
|
int len;
|
||||||
|
long now;
|
||||||
|
|
||||||
|
va_start(ap, str);
|
||||||
|
|
||||||
|
len = vsnprintf(output, sizeof(output), str, ap);
|
||||||
|
if (len >= 256) len = 255; /* truncated string */
|
||||||
|
clear();
|
||||||
|
drawbigstring((IXSIZE - len * bigfontxsize) / 2, (IYSIZE - bigfontysize) / 2, output);
|
||||||
|
copyup();
|
||||||
|
|
||||||
|
now = longtime();
|
||||||
|
while (!exitflag && longtime() - now < 3) {
|
||||||
|
scaninput();
|
||||||
|
if (anydown()) {
|
||||||
|
takedown();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,12 +3,12 @@
|
|||||||
|
|
||||||
void loadgfx(void);
|
void loadgfx(void);
|
||||||
|
|
||||||
void drawstring(int xpos, int ypos, const char *str);
|
void drawstring(int xpos, int ypos, const char* str);
|
||||||
void drawbigstring(int xpos, int ypos, const char *str);
|
void drawbigstring(int xpos, int ypos, const char* str);
|
||||||
|
|
||||||
void centerbig(int y, const char *str);
|
void centerbig(int y, const char* str);
|
||||||
|
|
||||||
void addsprite(int x,int y,figure *fig);
|
void addsprite(int x, int y, figure* fig);
|
||||||
void plotsprites(void);
|
void plotsprites(void);
|
||||||
void erasesprites(void);
|
void erasesprites(void);
|
||||||
void clearsprites(void);
|
void clearsprites(void);
|
||||||
@ -22,10 +22,10 @@ int screentoarrayy(int y);
|
|||||||
int arraytoscreenx(int x);
|
int arraytoscreenx(int x);
|
||||||
int arraytoscreeny(int y);
|
int arraytoscreeny(int y);
|
||||||
|
|
||||||
void failure(char *str,...);
|
void failure(char* str, ...);
|
||||||
|
|
||||||
extern int fontxsize,fontysize;
|
extern int fontxsize, fontysize;
|
||||||
extern int bigfontxsize,bigfontysize,bigfontyspace;
|
extern int bigfontxsize, bigfontysize, bigfontyspace;
|
||||||
|
|
||||||
/* On screen array variables */
|
/* On screen array variables */
|
||||||
extern int arraynumx, arraynumy, arraystartx, arraystarty, arrayspacex, arrayspacey;
|
extern int arraynumx, arraynumy, arraystartx, arraystarty, arrayspacex, arrayspacey;
|
||||||
@ -37,6 +37,7 @@ extern int arraynumx, arraynumy, arraystartx, arraystarty, arrayspacex, arrayspa
|
|||||||
#define NUMDEATHFRAMES 41
|
#define NUMDEATHFRAMES 41
|
||||||
|
|
||||||
|
|
||||||
extern figure blocks[3], blocksx[9], bombs1[MAXSETS][NUMBOMBFRAMES], bombs2[MAXSETS][NUMBOMBFRAMES], flamefigs[MAXSETS][NUMFLAMEFRAMES], tiles[15], death[NUMDEATHFRAMES];
|
extern figure blocks[3], blocksx[9], bombs1[MAXSETS][NUMBOMBFRAMES], bombs2[MAXSETS][NUMBOMBFRAMES], flamefigs[MAXSETS][NUMFLAMEFRAMES], tiles[15],
|
||||||
|
death[NUMDEATHFRAMES];
|
||||||
|
|
||||||
#endif
|
#endif
|
951
src/game.c
Normal file
951
src/game.c
Normal file
@ -0,0 +1,951 @@
|
|||||||
|
|
||||||
|
#include "game.h"
|
||||||
|
#include "bomber.h"
|
||||||
|
#include "draw.h"
|
||||||
|
#include "gfx.h"
|
||||||
|
#include "list.h"
|
||||||
|
#include "menu.h"
|
||||||
|
#include "network.h"
|
||||||
|
#include "sound.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
static int gameframe;
|
||||||
|
|
||||||
|
static listhead activebombs;
|
||||||
|
static listhead activedecays;
|
||||||
|
static listhead activebonus;
|
||||||
|
static listhead activegeneric;
|
||||||
|
static listhead detonatebombs;
|
||||||
|
static listhead activeflames;
|
||||||
|
static listhead activeplayers;
|
||||||
|
static listhead allplayers;
|
||||||
|
|
||||||
|
figure walking[MAXSETS][NUMWALKFRAMES];
|
||||||
|
solid background, backgroundoriginal;
|
||||||
|
|
||||||
|
/* The playfield array, contains FIELD_* equates */
|
||||||
|
unsigned char field[32][32];
|
||||||
|
void* info[32][32];
|
||||||
|
|
||||||
|
volatile char exitflag = 0;
|
||||||
|
static int framecount = 0;
|
||||||
|
|
||||||
|
char playername[16];
|
||||||
|
|
||||||
|
static int mycount;
|
||||||
|
|
||||||
|
static int bonustotal;
|
||||||
|
static const int bonuschances[] = {TILE_BOMB, 20, TILE_FLAME, 20, TILE_TRIGGER, 2, TILE_GOLDFLAME, 2, TILE_SKATES, 20, TILE_TURTLE, 5, TILE_NONE, 160};
|
||||||
|
|
||||||
|
static GameOptions gameoptions;
|
||||||
|
|
||||||
|
static const unsigned char playerpositions[MAXNETNODES * 3] = {
|
||||||
|
/* color, x, y */
|
||||||
|
2, 0, 0, 3, 14, 10, 4, 14, 0, 5, 0, 10, 1, 6, 0, 6, 8, 10, 7, 0, 6, 8, 14, 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void resetplayer(player* pl, int color, int x, int y) {
|
||||||
|
pl->speed = SPEEDSTART;
|
||||||
|
pl->flags = 0;
|
||||||
|
pl->flamelength = gameoptions.flames + 1;
|
||||||
|
pl->bombsavailable = gameoptions.bombs + 1;
|
||||||
|
|
||||||
|
pl->color = color;
|
||||||
|
|
||||||
|
pl->xpos = arraytoscreenx(x);
|
||||||
|
pl->ypos = arraytoscreeny(y);
|
||||||
|
|
||||||
|
field[y][x] = FIELD_EMPTY;
|
||||||
|
if (x) field[y][x - 1] = FIELD_EMPTY;
|
||||||
|
if (y) field[y - 1][x] = FIELD_EMPTY;
|
||||||
|
if (x < arraynumx - 1) field[y][x + 1] = FIELD_EMPTY;
|
||||||
|
if (y < arraynumy - 1) field[y + 1][x] = FIELD_EMPTY;
|
||||||
|
|
||||||
|
addtail(&activeplayers, pl);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void initplayer(int color, int x, int y, int controller) {
|
||||||
|
player* pl;
|
||||||
|
|
||||||
|
pl = allocentry(player);
|
||||||
|
if (!pl) nomem("Couldn't get player structure (allocentry())");
|
||||||
|
|
||||||
|
list_add_tail(&allplayers, &pl->list_all_players);
|
||||||
|
|
||||||
|
pl->controller = controller;
|
||||||
|
pl->fixx = -4;
|
||||||
|
pl->fixy = -40;
|
||||||
|
pl->kills = pl->deaths = 0;
|
||||||
|
|
||||||
|
resetplayer(pl, color, x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void initplayers(void) {
|
||||||
|
int i;
|
||||||
|
const unsigned char* p;
|
||||||
|
int c, x, y;
|
||||||
|
|
||||||
|
if (NETWORK_NONE == network) {
|
||||||
|
initplayer(2, 0, 0, -1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
p = playerpositions;
|
||||||
|
for (i = 0; i < MAXNETNODES; ++i) {
|
||||||
|
if (!netnodes[i].used) continue;
|
||||||
|
c = *p++;
|
||||||
|
x = *p++;
|
||||||
|
y = *p++;
|
||||||
|
initplayer(c, x, y, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void resetplayers(void) {
|
||||||
|
const unsigned char* p;
|
||||||
|
int c, x, y;
|
||||||
|
player* pl;
|
||||||
|
|
||||||
|
p = playerpositions;
|
||||||
|
list_for_each_entry(pl, &allplayers, list_all_players) {
|
||||||
|
c = *p++;
|
||||||
|
x = *p++;
|
||||||
|
y = *p++;
|
||||||
|
resetplayer(pl, c, x, y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void firstzero(void) {
|
||||||
|
alloc_things();
|
||||||
|
list_init_head(&activebombs);
|
||||||
|
list_init_head(&detonatebombs);
|
||||||
|
list_init_head(&activeflames);
|
||||||
|
list_init_head(&activedecays);
|
||||||
|
list_init_head(&activebonus);
|
||||||
|
list_init_head(&activeplayers);
|
||||||
|
list_init_head(&activegeneric);
|
||||||
|
list_init_head(&allplayers);
|
||||||
|
|
||||||
|
mycount = mydatacount = 0;
|
||||||
|
memset(latestactions, 0, sizeof(latestactions));
|
||||||
|
memset(latestcounts, 0, sizeof(latestcounts));
|
||||||
|
memset(actionblock, 0, sizeof(actionblock));
|
||||||
|
actioncount = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void initgame() {
|
||||||
|
int i, j;
|
||||||
|
int x, y;
|
||||||
|
int bl;
|
||||||
|
const int* p;
|
||||||
|
int comp;
|
||||||
|
|
||||||
|
if (network != NETWORK_SLAVE) set_game_options(&configopts);
|
||||||
|
gameframe = 0;
|
||||||
|
|
||||||
|
things_list_clear(&activebombs);
|
||||||
|
things_list_clear(&detonatebombs);
|
||||||
|
things_list_clear(&activeflames);
|
||||||
|
things_list_clear(&activedecays);
|
||||||
|
things_list_clear(&activebonus);
|
||||||
|
list_init_head(&activeplayers);
|
||||||
|
things_list_clear(&activegeneric);
|
||||||
|
|
||||||
|
p = bonuschances;
|
||||||
|
bonustotal = 0;
|
||||||
|
for (;;) {
|
||||||
|
i = *p++;
|
||||||
|
if (i == TILE_NONE) break;
|
||||||
|
bonustotal += *p++;
|
||||||
|
}
|
||||||
|
bonustotal += 64 * (3 - gameoptions.generosity);
|
||||||
|
memset(field, 0, sizeof(field));
|
||||||
|
comp = gameoptions.density;
|
||||||
|
for (j = 0; j < arraynumy; ++j)
|
||||||
|
for (i = 0; i < arraynumx; ++i) {
|
||||||
|
/* if((i&j)&1) {
|
||||||
|
field[j][i]=FIELD_BORDER;
|
||||||
|
} else*/
|
||||||
|
field[j][i] = (myrand() & 3) >= comp ? FIELD_BRICK : FIELD_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
solidcopyany(&backgroundoriginal, &background, 0, 0, IXSIZE, IYSIZE);
|
||||||
|
|
||||||
|
resetplayers();
|
||||||
|
|
||||||
|
for (j = 0; j < arraynumy; ++j) {
|
||||||
|
y = arraystarty + j * arrayspacey;
|
||||||
|
for (i = 0; i < arraynumx; ++i) {
|
||||||
|
x = arraystartx + i * arrayspacex;
|
||||||
|
bl = field[j][i];
|
||||||
|
if (bl == FIELD_BORDER)
|
||||||
|
bl = 2;
|
||||||
|
else if (bl == FIELD_BRICK)
|
||||||
|
bl = 1;
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
drawfigureany(x, y, blocks + bl, &background);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
solidcopy(&background, 0, 0, IXSIZE, IYSIZE);
|
||||||
|
copyup();
|
||||||
|
}
|
||||||
|
|
||||||
|
static void addflame(player* owner, int px, int py) {
|
||||||
|
flame *fl, *fl2;
|
||||||
|
|
||||||
|
fl = allocentry(flame);
|
||||||
|
if (!fl) return;
|
||||||
|
addtail(&activeflames, fl);
|
||||||
|
field[py][px] = FIELD_FLAME;
|
||||||
|
info[py][px] = fl;
|
||||||
|
fl->px = px;
|
||||||
|
fl->py = py;
|
||||||
|
fl->xpos = arraytoscreenx(px);
|
||||||
|
fl->ypos = arraytoscreeny(py);
|
||||||
|
fl->owner = owner;
|
||||||
|
if (px && field[py][px - 1] == FIELD_FLAME) {
|
||||||
|
fl2 = info[py][px - 1];
|
||||||
|
fl->lurd |= FL_LEFT;
|
||||||
|
fl2->lurd |= FL_RIGHT;
|
||||||
|
}
|
||||||
|
if (py && field[py - 1][px] == FIELD_FLAME) {
|
||||||
|
fl2 = info[py - 1][px];
|
||||||
|
fl->lurd |= FL_UP;
|
||||||
|
fl2->lurd |= FL_DOWN;
|
||||||
|
}
|
||||||
|
if (px < arraynumx - 1 && field[py][px + 1] == FIELD_FLAME) {
|
||||||
|
fl2 = info[py][px + 1];
|
||||||
|
fl->lurd |= FL_RIGHT;
|
||||||
|
fl2->lurd |= FL_LEFT;
|
||||||
|
}
|
||||||
|
if (py < arraynumy - 1 && field[py + 1][px] == FIELD_FLAME) {
|
||||||
|
fl2 = info[py + 1][px];
|
||||||
|
fl->lurd |= FL_DOWN;
|
||||||
|
fl2->lurd |= FL_UP;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dropbomb(player* pl, int px, int py, int type) {
|
||||||
|
bomb* bmb;
|
||||||
|
|
||||||
|
if (field[py][px] != FIELD_EMPTY) return;
|
||||||
|
bmb = allocentry(bomb);
|
||||||
|
if (!bmb) return;
|
||||||
|
playsound(3);
|
||||||
|
addtail(&activebombs, bmb);
|
||||||
|
|
||||||
|
--(pl->bombsavailable);
|
||||||
|
field[py][px] = FIELD_BOMB;
|
||||||
|
info[py][px] = bmb;
|
||||||
|
bmb->type = type;
|
||||||
|
bmb->px = px;
|
||||||
|
bmb->py = py;
|
||||||
|
bmb->xpos = arraytoscreenx(px);
|
||||||
|
bmb->ypos = arraytoscreeny(py);
|
||||||
|
bmb->power = pl->flamelength;
|
||||||
|
bmb->owner = pl;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void adddecay(int px, int py) {
|
||||||
|
brickdecay* bd;
|
||||||
|
int xpos, ypos;
|
||||||
|
|
||||||
|
bd = allocentry(brickdecay);
|
||||||
|
if (!bd) return;
|
||||||
|
field[py][px] = FIELD_EXPLODING;
|
||||||
|
bd->xpos = arraytoscreenx(px);
|
||||||
|
bd->ypos = arraytoscreeny(py);
|
||||||
|
bd->px = px;
|
||||||
|
bd->py = py;
|
||||||
|
addtail(&activedecays, bd);
|
||||||
|
xpos = tovideox(bd->xpos);
|
||||||
|
ypos = tovideoy(bd->ypos);
|
||||||
|
solidcopyany(&backgroundoriginal, &background, xpos, ypos, arrayspacex, arrayspacey);
|
||||||
|
solidcopy(&background, xpos, ypos, arrayspacex, arrayspacey);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void addbonus(int px, int py, int type) {
|
||||||
|
bonustile* bonus;
|
||||||
|
|
||||||
|
bonus = allocentry(bonustile);
|
||||||
|
if (!bonus) return;
|
||||||
|
addtail(&activebonus, bonus);
|
||||||
|
bonus->px = px;
|
||||||
|
bonus->py = py;
|
||||||
|
bonus->xpos = arraytoscreenx(px);
|
||||||
|
bonus->ypos = arraytoscreeny(py);
|
||||||
|
bonus->type = type;
|
||||||
|
field[py][px] = FIELD_BONUS;
|
||||||
|
info[py][px] = bonus;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void trybonus(int px, int py) {
|
||||||
|
int i = 0, r;
|
||||||
|
const int* p;
|
||||||
|
|
||||||
|
if (field[py][px] != FIELD_EMPTY) return;
|
||||||
|
p = bonuschances;
|
||||||
|
r = myrand() % bonustotal;
|
||||||
|
while (r >= 0) {
|
||||||
|
i = *p++;
|
||||||
|
r -= *p++;
|
||||||
|
}
|
||||||
|
if (i == TILE_NONE) return;
|
||||||
|
addbonus(px, py, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void deletebonus(bonustile* bonus) {
|
||||||
|
int px, py;
|
||||||
|
|
||||||
|
px = bonus->px;
|
||||||
|
py = bonus->py;
|
||||||
|
field[py][px] = 0;
|
||||||
|
info[py][px] = 0;
|
||||||
|
list_del(&bonus->list);
|
||||||
|
freeentry(bonus);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void adddetonate(bomb* bmb) {
|
||||||
|
if (bmb->type == BOMB_OFF) return;
|
||||||
|
|
||||||
|
bmb->type = BOMB_OFF;
|
||||||
|
field[bmb->py][bmb->px] = FIELD_EXPLODING;
|
||||||
|
info[bmb->py][bmb->px] = 0;
|
||||||
|
|
||||||
|
removeitem(bmb);
|
||||||
|
addtail(&detonatebombs, bmb);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void processbombs() {
|
||||||
|
bomb *bmb, *next;
|
||||||
|
|
||||||
|
list_for_each_entry_safe(bmb, next, &activebombs, list) {
|
||||||
|
++(bmb->figcount);
|
||||||
|
++bmb->timer;
|
||||||
|
switch (bmb->type) {
|
||||||
|
case BOMB_NORMAL:
|
||||||
|
if (bmb->timer == BOMBLIFE) adddetonate(bmb);
|
||||||
|
break;
|
||||||
|
case BOMB_CONTROLLED:
|
||||||
|
if (bmb->timer == BOMB_CONTROLLED_LIFE) {
|
||||||
|
bmb->timer = 0;
|
||||||
|
bmb->type = BOMB_NORMAL;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void flameshaft(player* owner, int px, int py, int dx, int dy, int power) {
|
||||||
|
int there;
|
||||||
|
bomb* bmb;
|
||||||
|
|
||||||
|
while (power--) {
|
||||||
|
px += dx;
|
||||||
|
py += dy;
|
||||||
|
if (px < 0 || py < 0 || px >= arraynumx || py >= arraynumy) break;
|
||||||
|
there = field[py][px];
|
||||||
|
switch (there) {
|
||||||
|
case FIELD_BOMB:
|
||||||
|
bmb = info[py][px];
|
||||||
|
adddetonate(bmb);
|
||||||
|
break;
|
||||||
|
case FIELD_EMPTY:
|
||||||
|
addflame(owner, px, py);
|
||||||
|
break;
|
||||||
|
case FIELD_BRICK:
|
||||||
|
adddecay(px, py);
|
||||||
|
power = 0;
|
||||||
|
break;
|
||||||
|
case FIELD_BONUS:
|
||||||
|
deletebonus(info[py][px]);
|
||||||
|
power = 0;
|
||||||
|
break;
|
||||||
|
case FIELD_BORDER:
|
||||||
|
case FIELD_EXPLODING:
|
||||||
|
default:
|
||||||
|
power = 0;
|
||||||
|
case FIELD_FLAME:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void detonatebomb(bomb* bmb) {
|
||||||
|
int px, py;
|
||||||
|
int power;
|
||||||
|
player* owner;
|
||||||
|
|
||||||
|
++(bmb->owner->bombsavailable);
|
||||||
|
px = bmb->px;
|
||||||
|
py = bmb->py;
|
||||||
|
power = bmb->power;
|
||||||
|
owner = bmb->owner;
|
||||||
|
list_del(&bmb->list);
|
||||||
|
freeentry(bmb);
|
||||||
|
addflame(owner, px, py);
|
||||||
|
flameshaft(owner, px, py, -1, 0, power);
|
||||||
|
flameshaft(owner, px, py, 0, -1, power);
|
||||||
|
flameshaft(owner, px, py, 1, 0, power);
|
||||||
|
flameshaft(owner, px, py, 0, 1, power);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dodetonations(void) {
|
||||||
|
int i = 0;
|
||||||
|
bomb* bmb;
|
||||||
|
|
||||||
|
while (!list_empty(&detonatebombs)) {
|
||||||
|
bmb = (bomb*) detonatebombs.next;
|
||||||
|
++i;
|
||||||
|
detonatebomb(bmb);
|
||||||
|
}
|
||||||
|
if (i) playsound((myrand() & 1) ? 0 : 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void processflames(void) {
|
||||||
|
flame *fl, *next;
|
||||||
|
|
||||||
|
list_for_each_entry_safe(fl, next, &activeflames, list) {
|
||||||
|
++(fl->timer);
|
||||||
|
|
||||||
|
if (fl->timer == FLAMELIFE) {
|
||||||
|
field[fl->py][fl->px] = FIELD_EMPTY;
|
||||||
|
info[fl->py][fl->px] = 0;
|
||||||
|
list_del(&fl->list);
|
||||||
|
freeentry(fl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void processdecays() {
|
||||||
|
brickdecay *bd, *next;
|
||||||
|
|
||||||
|
list_for_each_entry_safe(bd, next, &activedecays, list) {
|
||||||
|
++(bd->timer);
|
||||||
|
if (bd->timer == DECAYLIFE) {
|
||||||
|
field[bd->py][bd->px] = FIELD_EMPTY;
|
||||||
|
trybonus(bd->px, bd->py);
|
||||||
|
list_del(&bd->list);
|
||||||
|
freeentry(bd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void drawbombs(void) {
|
||||||
|
int j;
|
||||||
|
bomb* bmb;
|
||||||
|
struct figure* figtab;
|
||||||
|
int color;
|
||||||
|
int xpos, ypos;
|
||||||
|
|
||||||
|
list_for_each_entry(bmb, &activebombs, list) {
|
||||||
|
color = bmb->owner->color;
|
||||||
|
figtab = (bmb->type == BOMB_NORMAL) ? bombs1[color] : bombs2[color];
|
||||||
|
j = bmb->figcount % (NUMBOMBFRAMES << 1);
|
||||||
|
if (j >= NUMBOMBFRAMES) j = (NUMBOMBFRAMES << 1) - j - 1;
|
||||||
|
xpos = tovideox(bmb->xpos);
|
||||||
|
ypos = tovideoy(bmb->ypos) - 3;
|
||||||
|
|
||||||
|
addsprite(xpos, ypos, figtab + j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void drawflames(void) {
|
||||||
|
flame* fl;
|
||||||
|
int xpos, ypos;
|
||||||
|
/* no player specific flame sprites yet */
|
||||||
|
/* int color; */
|
||||||
|
int fig;
|
||||||
|
|
||||||
|
list_for_each_entry(fl, &activeflames, list) {
|
||||||
|
/* color=fl->owner->color; */
|
||||||
|
xpos = tovideox(fl->xpos);
|
||||||
|
ypos = tovideoy(fl->ypos);
|
||||||
|
fig = (fl->timer * 10) / FLAMELIFE;
|
||||||
|
if (fig >= 5) fig = 9 - fig;
|
||||||
|
fig += 5 * fl->lurd;
|
||||||
|
addsprite(xpos, ypos, flamefigs[0 /* color */] + fig);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void drawdecays() {
|
||||||
|
brickdecay* bd;
|
||||||
|
|
||||||
|
list_for_each_entry(bd, &activedecays, list) {
|
||||||
|
addsprite(tovideox(bd->xpos), tovideoy(bd->ypos), blocksx + (bd->timer * 9) / DECAYLIFE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void drawbonus() {
|
||||||
|
bonustile* bonus;
|
||||||
|
|
||||||
|
list_for_each_entry(bonus, &activebonus, list) {
|
||||||
|
addsprite(tovideox(bonus->xpos), tovideoy(bonus->ypos), tiles + bonus->type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void drawplayers() {
|
||||||
|
player* pl;
|
||||||
|
int xpos, ypos;
|
||||||
|
|
||||||
|
list_for_each_entry(pl, &activeplayers, list) {
|
||||||
|
if (!(pl->flags & FLG_DEAD)) {
|
||||||
|
if (!pl->figure) pl->figure = walking[pl->color] + 30;
|
||||||
|
xpos = tovideox(pl->xpos) + pl->fixx;
|
||||||
|
ypos = tovideoy(pl->ypos) + pl->fixy;
|
||||||
|
addsprite(xpos, ypos, pl->figure);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void detonatecontrolled(player* pl) {
|
||||||
|
bomb *bmb, *next;
|
||||||
|
|
||||||
|
list_for_each_entry_safe(bmb, next, &activebombs, list) {
|
||||||
|
if (bmb->owner == pl && bmb->type == BOMB_CONTROLLED) adddetonate(bmb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void playonce(generic* gen) {
|
||||||
|
if (gen->timer == gen->data1) {
|
||||||
|
list_del(&gen->list);
|
||||||
|
freeentry(gen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void drawgeneric(generic* gen) {
|
||||||
|
addsprite(gen->xpos, gen->ypos, ((figure*) (gen->ptr1)) + gen->timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void queuesequence(int xpos, int ypos, figure* fig, int count) {
|
||||||
|
generic* gen;
|
||||||
|
|
||||||
|
gen = allocentry(generic);
|
||||||
|
if (!gen) return;
|
||||||
|
gen->xpos = xpos;
|
||||||
|
gen->ypos = ypos;
|
||||||
|
gen->data1 = count;
|
||||||
|
gen->process = playonce;
|
||||||
|
gen->draw = drawgeneric;
|
||||||
|
gen->ptr1 = fig;
|
||||||
|
addtail(&activegeneric, gen);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void adddeath(player* pl) {
|
||||||
|
int xpos, ypos;
|
||||||
|
|
||||||
|
xpos = tovideox(pl->xpos) + pl->fixx - 10;
|
||||||
|
ypos = tovideoy(pl->ypos) + pl->fixy;
|
||||||
|
queuesequence(xpos, ypos, death, NUMDEATHFRAMES);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void killplayer(player* pl) {
|
||||||
|
pl->deaths++;
|
||||||
|
pl->flags |= FLG_DEAD;
|
||||||
|
playsound(2);
|
||||||
|
adddeath(pl);
|
||||||
|
detonatecontrolled(pl);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void processgenerics(void) {
|
||||||
|
generic *gen, *next;
|
||||||
|
|
||||||
|
list_for_each_entry_safe(gen, next, &activegeneric, list) {
|
||||||
|
++(gen->timer);
|
||||||
|
gen->process(gen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void drawgenerics(void) {
|
||||||
|
generic* gen;
|
||||||
|
|
||||||
|
list_for_each_entry(gen, &activegeneric, list) {
|
||||||
|
gen->draw(gen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void drawstats(void) {
|
||||||
|
player* pl;
|
||||||
|
int p = 0;
|
||||||
|
const char* n;
|
||||||
|
char buf[17];
|
||||||
|
|
||||||
|
solidcopy(&background, 0, 0, IXSIZE, arraystarty);
|
||||||
|
list_for_each_entry(pl, &allplayers, list_all_players) {
|
||||||
|
if (pl->controller >= 0) {
|
||||||
|
n = netnodes[pl->controller].name;
|
||||||
|
} else {
|
||||||
|
n = playername;
|
||||||
|
}
|
||||||
|
snprintf(buf, sizeof(buf), "%-8.8s %2i/%2i", n, pl->kills % 100, pl->deaths % 100);
|
||||||
|
drawstring(11 + (p / 2) * (15 * fontxsize + 7), 11 + (p % 2) * (fontysize + 2), buf);
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int centerxchange(player* pl) {
|
||||||
|
int speed;
|
||||||
|
int val;
|
||||||
|
int line;
|
||||||
|
int max;
|
||||||
|
|
||||||
|
max = arrayspacex << FRACTION;
|
||||||
|
speed = pl->speed;
|
||||||
|
val = pl->xpos + (max << 2);
|
||||||
|
val %= max;
|
||||||
|
line = max >> 1;
|
||||||
|
if (val < line) {
|
||||||
|
if (val - speed < 0)
|
||||||
|
return -val;
|
||||||
|
else
|
||||||
|
return -speed;
|
||||||
|
} else if (val >= line) {
|
||||||
|
if (val + speed > max)
|
||||||
|
return max - val;
|
||||||
|
else
|
||||||
|
return speed;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void centerx(player* pl) {
|
||||||
|
pl->xpos += centerxchange(pl);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int centerychange(player* pl) {
|
||||||
|
int speed;
|
||||||
|
int val;
|
||||||
|
int line;
|
||||||
|
int max;
|
||||||
|
|
||||||
|
max = arrayspacey << FRACTION;
|
||||||
|
speed = pl->speed;
|
||||||
|
val = pl->ypos + (max << 2);
|
||||||
|
val %= max;
|
||||||
|
line = max >> 1;
|
||||||
|
if (val < line) {
|
||||||
|
if (val - speed < 0)
|
||||||
|
return -val;
|
||||||
|
else
|
||||||
|
return -speed;
|
||||||
|
} else if (val >= line) {
|
||||||
|
if (val + speed > max)
|
||||||
|
return max - val;
|
||||||
|
else
|
||||||
|
return speed;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void centery(player* pl) {
|
||||||
|
pl->ypos += centerychange(pl);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define SGN(x) ((x) == 0 ? 0 : ((x) < 0 ? -1 : 1))
|
||||||
|
|
||||||
|
static void trymove(player* pl, int dx, int dy) {
|
||||||
|
int wx, wy;
|
||||||
|
int sx, sy;
|
||||||
|
int there;
|
||||||
|
int px, py;
|
||||||
|
static int depth = 0;
|
||||||
|
int tx, ty;
|
||||||
|
|
||||||
|
++depth;
|
||||||
|
sx = (dx * (arrayspacex + 1)) << (FRACTION - 1);
|
||||||
|
sy = (dy * (arrayspacey + 1)) << (FRACTION - 1);
|
||||||
|
|
||||||
|
wx = screentoarrayx(pl->xpos + sx);
|
||||||
|
wy = screentoarrayy(pl->ypos + sy);
|
||||||
|
px = screentoarrayx(pl->xpos);
|
||||||
|
py = screentoarrayy(pl->ypos);
|
||||||
|
|
||||||
|
if (wx < 0 || wx >= arraynumx || wy < 0 || wy >= arraynumy) {
|
||||||
|
--depth;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
there = field[wy][wx];
|
||||||
|
if ((px != wx || py != wy) && (there == FIELD_BRICK || there == FIELD_BOMB || there == FIELD_BORDER)) {
|
||||||
|
if (dx && !dy) {
|
||||||
|
ty = centerychange(pl);
|
||||||
|
if (ty && depth == 1) trymove(pl, 0, -SGN(ty));
|
||||||
|
|
||||||
|
} else if (dy && !dx) {
|
||||||
|
tx = centerxchange(pl);
|
||||||
|
if (tx && depth == 1) trymove(pl, -SGN(tx), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
pl->xpos += dx * pl->speed;
|
||||||
|
pl->ypos += dy * pl->speed;
|
||||||
|
if (dx && !dy) centery(pl);
|
||||||
|
if (dy && !dx) centerx(pl);
|
||||||
|
}
|
||||||
|
--depth;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void applybonus(player* pl, bonustile* bonus) {
|
||||||
|
int type;
|
||||||
|
int maxflame;
|
||||||
|
|
||||||
|
maxflame = arraynumx > arraynumy ? arraynumx : arraynumy;
|
||||||
|
type = bonus->type;
|
||||||
|
deletebonus(bonus);
|
||||||
|
switch (type) {
|
||||||
|
case TILE_BOMB:
|
||||||
|
if (pl->bombsavailable < 9) ++(pl->bombsavailable);
|
||||||
|
break;
|
||||||
|
case TILE_FLAME:
|
||||||
|
if (pl->flamelength < maxflame) ++(pl->flamelength);
|
||||||
|
break;
|
||||||
|
case TILE_GOLDFLAME:
|
||||||
|
pl->flamelength = maxflame;
|
||||||
|
break;
|
||||||
|
case TILE_TRIGGER:
|
||||||
|
pl->flags |= FLG_CONTROL;
|
||||||
|
break;
|
||||||
|
case TILE_SKATES:
|
||||||
|
if (pl->speed < SPEEDSTART) {
|
||||||
|
pl->speed = SPEEDSTART;
|
||||||
|
} else {
|
||||||
|
pl->speed += SPEEDDELTA;
|
||||||
|
}
|
||||||
|
if (pl->speed > SPEEDMAX) pl->speed = SPEEDMAX;
|
||||||
|
break;
|
||||||
|
case TILE_TURTLE:
|
||||||
|
pl->speed = SPEEDTURTLE;
|
||||||
|
pl->speedturtle_timeout = SPEEDTURTLE_TIMEOUT;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void doplayer(player* pl) {
|
||||||
|
/* int last; */
|
||||||
|
int color;
|
||||||
|
/* int speed; */
|
||||||
|
int px, py;
|
||||||
|
int there;
|
||||||
|
int flags;
|
||||||
|
int what;
|
||||||
|
|
||||||
|
if (pl->controller == -1)
|
||||||
|
what = myaction;
|
||||||
|
else
|
||||||
|
what = actions[pl->controller];
|
||||||
|
|
||||||
|
flags = pl->flags;
|
||||||
|
if (flags & FLG_DEAD) return;
|
||||||
|
color = pl->color;
|
||||||
|
/* last=pl->doing; */
|
||||||
|
pl->doing = what;
|
||||||
|
/* speed=pl->speed; */
|
||||||
|
px = screentoarrayx(pl->xpos);
|
||||||
|
py = screentoarrayy(pl->ypos);
|
||||||
|
there = field[py][px];
|
||||||
|
|
||||||
|
if (what == ACT_QUIT) {
|
||||||
|
killplayer(pl);
|
||||||
|
list_del(&pl->list_all_players);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (there == FIELD_BONUS) {
|
||||||
|
playsound((myrand() & 1) ? 1 : 5);
|
||||||
|
applybonus(pl, info[py][px]);
|
||||||
|
} else if (there == FIELD_FLAME) {
|
||||||
|
flame* fl = info[py][px];
|
||||||
|
if (fl->owner == pl) {
|
||||||
|
pl->kills--;
|
||||||
|
} else {
|
||||||
|
fl->owner->kills++;
|
||||||
|
}
|
||||||
|
killplayer(pl);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if(what&ACT_TURBO) speed<<=2;
|
||||||
|
if (what & ACT_PRIMARY) {
|
||||||
|
if (there == FIELD_EMPTY && pl->bombsavailable) dropbomb(pl, px, py, (flags & FLG_CONTROL) ? BOMB_CONTROLLED : BOMB_NORMAL);
|
||||||
|
}
|
||||||
|
if (what & ACT_SECONDARY && (flags & FLG_CONTROL)) detonatecontrolled(pl);
|
||||||
|
|
||||||
|
switch (what & ACT_MASK) {
|
||||||
|
case ACT_UP:
|
||||||
|
trymove(pl, 0, -1);
|
||||||
|
pl->figcount = (pl->figcount + 1) % 15;
|
||||||
|
pl->figure = walking[color] + pl->figcount + 15;
|
||||||
|
break;
|
||||||
|
case ACT_DOWN:
|
||||||
|
trymove(pl, 0, 1);
|
||||||
|
pl->figcount = (pl->figcount + 1) % 15;
|
||||||
|
pl->figure = walking[color] + pl->figcount + 30;
|
||||||
|
break;
|
||||||
|
case ACT_LEFT:
|
||||||
|
trymove(pl, -1, 0);
|
||||||
|
pl->figcount = (pl->figcount + 1) % 15;
|
||||||
|
pl->figure = walking[color] + pl->figcount + 45;
|
||||||
|
break;
|
||||||
|
case ACT_RIGHT:
|
||||||
|
trymove(pl, 1, 0);
|
||||||
|
pl->figcount = (pl->figcount + 1) % 15;
|
||||||
|
pl->figure = walking[color] + pl->figcount;
|
||||||
|
break;
|
||||||
|
case ACT_NONE:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pl->speedturtle_timeout > 0) {
|
||||||
|
pl->speedturtle_timeout--;
|
||||||
|
if (0 == pl->speedturtle_timeout) {
|
||||||
|
if (pl->speed < SPEEDSTART) pl->speed = SPEEDSTART;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void processplayers(void) {
|
||||||
|
player *pl, *next;
|
||||||
|
|
||||||
|
list_for_each_entry_safe(pl, next, &activeplayers, list) {
|
||||||
|
doplayer(pl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void processquits(void) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (network != NETWORK_SLAVE) return;
|
||||||
|
for (i = 0; i < MAXNETNODES; ++i) {
|
||||||
|
if (netnodes[i].used && actions[i] == ACT_QUIT) netnodes[i].used = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int getaction(void) {
|
||||||
|
int what;
|
||||||
|
|
||||||
|
what = ACT_NONE;
|
||||||
|
if (checkpressed(MYLEFT))
|
||||||
|
what = ACT_LEFT;
|
||||||
|
else if (checkpressed(MYRIGHT))
|
||||||
|
what = ACT_RIGHT;
|
||||||
|
else if (checkpressed(MYDOWN))
|
||||||
|
what = ACT_DOWN;
|
||||||
|
else if (checkpressed(MYUP))
|
||||||
|
what = ACT_UP;
|
||||||
|
else if (checkdown(13))
|
||||||
|
what = ACT_ENTER;
|
||||||
|
else if (checkdown(0x1b))
|
||||||
|
what = ACT_QUIT;
|
||||||
|
|
||||||
|
if (checkdown(' ')) what |= ACT_PRIMARY;
|
||||||
|
if (checkdown('b')) what |= ACT_SECONDARY;
|
||||||
|
|
||||||
|
return what;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int iterate(void) {
|
||||||
|
int i;
|
||||||
|
int gountil; /* destination tick */
|
||||||
|
static int deathcount = 0;
|
||||||
|
|
||||||
|
mypause();
|
||||||
|
scaninput();
|
||||||
|
|
||||||
|
erasesprites();
|
||||||
|
clearspritelist();
|
||||||
|
gfxunlock();
|
||||||
|
|
||||||
|
myaction = getaction();
|
||||||
|
if (NETWORK_NONE == network && myaction == ACT_QUIT) return CODE_QUIT;
|
||||||
|
if (NETWORK_NONE == network) {
|
||||||
|
gountil = mycount + 1; /* single step in singly player mode */
|
||||||
|
} else {
|
||||||
|
gountil = networktraffic(); /* as master single step, as slave as many as we can do */
|
||||||
|
}
|
||||||
|
|
||||||
|
while (mycount < gountil) { /* simulate ticks up to gountil */
|
||||||
|
++mycount;
|
||||||
|
if (NETWORK_NONE != network) {
|
||||||
|
i = gountil - mycount;
|
||||||
|
if (i >= ACTIONHIST) // too far behind
|
||||||
|
goto leave_game;
|
||||||
|
memcpy(actions, actionblock + i * MAXNETNODES, MAXNETNODES);
|
||||||
|
if (actions[myslot] == ACT_QUIT) return CODE_QUIT;
|
||||||
|
}
|
||||||
|
processbombs();
|
||||||
|
dodetonations();
|
||||||
|
processdecays();
|
||||||
|
processflames();
|
||||||
|
processgenerics();
|
||||||
|
processquits();
|
||||||
|
processplayers();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
if(!(rand()&127))
|
||||||
|
{
|
||||||
|
i=gtime();
|
||||||
|
while(gtime()-i<100);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
drawbombs();
|
||||||
|
drawbonus();
|
||||||
|
drawgenerics();
|
||||||
|
drawdecays();
|
||||||
|
drawflames();
|
||||||
|
drawplayers();
|
||||||
|
drawstats();
|
||||||
|
plotsprites();
|
||||||
|
copyup();
|
||||||
|
if (list_empty(&activegeneric)) {
|
||||||
|
player* pl;
|
||||||
|
|
||||||
|
int deadplayers = 0;
|
||||||
|
i = 0;
|
||||||
|
|
||||||
|
list_for_each_entry(pl, &activeplayers, list) {
|
||||||
|
if (!(pl->flags & FLG_DEAD))
|
||||||
|
++i;
|
||||||
|
else
|
||||||
|
deadplayers++;
|
||||||
|
}
|
||||||
|
if (deadplayers > 0 && (!i || (NETWORK_NONE != network && i == 1))) {
|
||||||
|
++deathcount;
|
||||||
|
if (deathcount == 25) return CODE_ALLDEAD;
|
||||||
|
} else
|
||||||
|
deathcount = 0;
|
||||||
|
}
|
||||||
|
return CODE_CONT;
|
||||||
|
|
||||||
|
leave_game: /* client disconnect/timeout: send ACT_QUIT to master */
|
||||||
|
myaction = ACT_QUIT;
|
||||||
|
networktraffic();
|
||||||
|
return CODE_QUIT;
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_game_options(GameOptions* options) {
|
||||||
|
gameoptions = *options;
|
||||||
|
}
|
||||||
|
|
||||||
|
void run_single_player(void) {
|
||||||
|
int code;
|
||||||
|
network = NETWORK_NONE;
|
||||||
|
|
||||||
|
firstzero();
|
||||||
|
initplayers();
|
||||||
|
do {
|
||||||
|
initgame();
|
||||||
|
while (!(code = iterate()) && !exitflag) ++framecount;
|
||||||
|
} while (code != CODE_QUIT && !exitflag);
|
||||||
|
}
|
||||||
|
|
||||||
|
void run_network_game(void) {
|
||||||
|
int code;
|
||||||
|
|
||||||
|
firstzero();
|
||||||
|
initplayers();
|
||||||
|
do {
|
||||||
|
initgame();
|
||||||
|
while (!(code = iterate()) && !exitflag) ++framecount;
|
||||||
|
} while (code != CODE_QUIT && !exitflag);
|
||||||
|
}
|
@ -1,11 +1,13 @@
|
|||||||
#ifndef GAME_H
|
#ifndef GAME_H
|
||||||
#define GAME_H
|
#define GAME_H
|
||||||
|
|
||||||
|
#include "bomber.h"
|
||||||
|
|
||||||
#define FRACTION 9
|
#define FRACTION 9
|
||||||
#define SPEEDDELTA (1<<(FRACTION-1))
|
#define SPEEDDELTA (1 << (FRACTION - 1))
|
||||||
#define SPEEDMAX (10<<FRACTION)
|
#define SPEEDMAX (10 << FRACTION)
|
||||||
#define SPEEDSTART (6<<FRACTION)
|
#define SPEEDSTART (6 << FRACTION)
|
||||||
#define SPEEDTURTLE (3<<FRACTION)
|
#define SPEEDTURTLE (3 << FRACTION)
|
||||||
#define SPEEDTURTLE_TIMEOUT 250
|
#define SPEEDTURTLE_TIMEOUT 250
|
||||||
|
|
||||||
#define TEMPNODES 2
|
#define TEMPNODES 2
|
||||||
@ -18,10 +20,10 @@ struct GameOptions {
|
|||||||
void run_single_player(void);
|
void run_single_player(void);
|
||||||
void run_network_game(void);
|
void run_network_game(void);
|
||||||
|
|
||||||
void set_game_options(GameOptions *options);
|
void set_game_options(GameOptions* options);
|
||||||
|
|
||||||
extern char playername[16];
|
extern char playername[16];
|
||||||
|
|
||||||
extern solid background,backgroundoriginal;
|
extern solid background, backgroundoriginal;
|
||||||
|
|
||||||
#endif
|
#endif
|
923
src/gfx.c
Normal file
923
src/gfx.c
Normal file
@ -0,0 +1,923 @@
|
|||||||
|
#include <ctype.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "bomber.h"
|
||||||
|
#include "gfx.h"
|
||||||
|
|
||||||
|
#define MAXCOLORS 256
|
||||||
|
|
||||||
|
int usedcolors = 0;
|
||||||
|
SDL_Surface* thescreen;
|
||||||
|
SDL_Color themap[256];
|
||||||
|
uchar* videomem;
|
||||||
|
int stride;
|
||||||
|
|
||||||
|
int mousex, mousey, mouseb;
|
||||||
|
uchar mustlock = 0, locked = 0;
|
||||||
|
uchar* block64;
|
||||||
|
|
||||||
|
|
||||||
|
int buttonstate = 0, buttondown = 0;
|
||||||
|
int mxpos, mypos;
|
||||||
|
|
||||||
|
int pressedcodes[KEYMAX], downcodes[KEYMAX], numpressed, numdown;
|
||||||
|
|
||||||
|
|
||||||
|
void dumpgfx() {
|
||||||
|
usedcolors = 0;
|
||||||
|
}
|
||||||
|
static int bestmatch(int red, int green, int blue) {
|
||||||
|
int i;
|
||||||
|
int bestcolor, bestdelta = 0;
|
||||||
|
int rdelta, gdelta, bdelta;
|
||||||
|
int delta;
|
||||||
|
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
bestcolor = -1;
|
||||||
|
while (i < usedcolors) {
|
||||||
|
rdelta = themap[i].r;
|
||||||
|
rdelta -= red;
|
||||||
|
rdelta *= rdelta;
|
||||||
|
gdelta = themap[i].g;
|
||||||
|
gdelta -= green;
|
||||||
|
gdelta *= gdelta;
|
||||||
|
bdelta = themap[i].b;
|
||||||
|
bdelta -= blue;
|
||||||
|
bdelta *= bdelta;
|
||||||
|
delta = rdelta + gdelta + bdelta;
|
||||||
|
if (bestcolor < 0 || delta < bestdelta) {
|
||||||
|
bestdelta = delta;
|
||||||
|
bestcolor = i;
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
return bestcolor;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void updatemap(void) {
|
||||||
|
SDL_SetColors(thescreen, themap, 0, 256);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void createinout(gfxset* gs) {
|
||||||
|
uchar* p;
|
||||||
|
int i, j, counts[256];
|
||||||
|
uchar red, green, blue;
|
||||||
|
int cnt;
|
||||||
|
|
||||||
|
|
||||||
|
p = gs->gs_pic;
|
||||||
|
for (i = 0; i < 256; i++) counts[i] = 0;
|
||||||
|
i = gs->gs_xsize * gs->gs_ysize;
|
||||||
|
while (i--) counts[*p++]++;
|
||||||
|
cnt = 0;
|
||||||
|
gs->gs_inout[0] = 0;
|
||||||
|
for (i = 1; i < 256; i++) {
|
||||||
|
if (counts[i]) {
|
||||||
|
cnt++;
|
||||||
|
p = gs->gs_colormap + i + i + i;
|
||||||
|
red = *p++;
|
||||||
|
green = *p++;
|
||||||
|
blue = *p++;
|
||||||
|
for (j = 0; j < usedcolors; j++) {
|
||||||
|
if (red == themap[j].r && green == themap[j].g && blue == themap[j].b) {
|
||||||
|
gs->gs_inout[i] = j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (j == usedcolors) {
|
||||||
|
if (usedcolors < MAXCOLORS) {
|
||||||
|
themap[j].r = red;
|
||||||
|
themap[j].g = green;
|
||||||
|
themap[j].b = blue;
|
||||||
|
gs->gs_inout[i] = usedcolors;
|
||||||
|
++usedcolors;
|
||||||
|
} else
|
||||||
|
gs->gs_inout[i] = bestmatch(red, green, blue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updatemap();
|
||||||
|
}
|
||||||
|
|
||||||
|
static uchar* compressfig(uchar* put, gfxset* gs, int sourcex, int sourcey, int sizex, int sizey) {
|
||||||
|
int j, gswidth;
|
||||||
|
uchar *p, *p2, pixel, *map1;
|
||||||
|
int dx, dy;
|
||||||
|
|
||||||
|
gswidth = gs->gs_xsize;
|
||||||
|
map1 = gs->gs_inout;
|
||||||
|
p = gs->gs_pic + sourcex + gswidth * sourcey;
|
||||||
|
for (dy = 0; dy < sizey; dy++) {
|
||||||
|
p2 = p;
|
||||||
|
j = 0;
|
||||||
|
for (dx = 0; dx <= sizex; dx++) {
|
||||||
|
if (dx < sizex)
|
||||||
|
pixel = *p2;
|
||||||
|
else
|
||||||
|
pixel = 0;
|
||||||
|
++p2;
|
||||||
|
if (pixel)
|
||||||
|
++j;
|
||||||
|
else if (j) {
|
||||||
|
*put++ = j;
|
||||||
|
*put++ = dx - j;
|
||||||
|
*put++ = dy;
|
||||||
|
p2 -= j + 1;
|
||||||
|
while (j) *put++ = map1[*p2++], --j;
|
||||||
|
++p2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p += gswidth;
|
||||||
|
}
|
||||||
|
*put++ = 0;
|
||||||
|
return put;
|
||||||
|
}
|
||||||
|
static void gfxfetchsingle(figure* fig, gfxset* gs, int sourcex, int sourcey, int sizex, int sizey) {
|
||||||
|
uchar *p, *p2;
|
||||||
|
int dx, dy;
|
||||||
|
/* uchar *map1; */
|
||||||
|
int gswidth;
|
||||||
|
int minx, miny, maxx, maxy;
|
||||||
|
int tx, ty;
|
||||||
|
|
||||||
|
/* map1=gs->gs_inout; */
|
||||||
|
gswidth = gs->gs_xsize;
|
||||||
|
p = gs->gs_pic + sourcex + gswidth * sourcey;
|
||||||
|
minx = miny = maxx = maxy = -1;
|
||||||
|
for (dy = 0; dy < sizey; dy++) {
|
||||||
|
p2 = p;
|
||||||
|
ty = sourcey + dy;
|
||||||
|
for (dx = 0; dx < sizex; dx++) {
|
||||||
|
if (!*p2++) continue;
|
||||||
|
if (miny == -1 || ty < miny) miny = ty;
|
||||||
|
if (maxy == -1 || ty > maxy) maxy = ty;
|
||||||
|
tx = sourcex + dx;
|
||||||
|
if (minx == -1 || tx < minx) minx = tx;
|
||||||
|
if (maxx == -1 || tx > maxx) maxx = tx;
|
||||||
|
}
|
||||||
|
p += gswidth;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (minx == -1) {
|
||||||
|
minx = maxx = sourcex;
|
||||||
|
miny = maxy = sourcey;
|
||||||
|
}
|
||||||
|
|
||||||
|
fig->xdelta = minx - sourcex;
|
||||||
|
fig->ydelta = miny - sourcey;
|
||||||
|
|
||||||
|
sourcex = minx;
|
||||||
|
sourcey = miny;
|
||||||
|
fig->xsize = sizex = maxx - minx + 1;
|
||||||
|
fig->ysize = sizey = maxy - miny + 1;
|
||||||
|
|
||||||
|
p = compressfig(block64, gs, sourcex, sourcey, sizex, sizey);
|
||||||
|
fig->graphics = malloc(p - block64);
|
||||||
|
if (fig->graphics) memcpy(fig->graphics, block64, p - block64);
|
||||||
|
}
|
||||||
|
//(gfxset *gs,figure *fig,int sourcex,int sourcey,int sizex,int sizey)
|
||||||
|
void gfxfetch(gfxset* gs, figure* fig, int num) {
|
||||||
|
int x, y;
|
||||||
|
int xsize, ysize;
|
||||||
|
int fxsize, fysize;
|
||||||
|
unsigned char *p, *p2;
|
||||||
|
|
||||||
|
xsize = gs->gs_xsize;
|
||||||
|
ysize = gs->gs_ysize;
|
||||||
|
p2 = p = gs->gs_pic + xsize + 1;
|
||||||
|
fxsize = 2;
|
||||||
|
while (*p++ == 0) ++fxsize;
|
||||||
|
fysize = 2;
|
||||||
|
while (*p2 == 0) ++fysize, p2 += xsize;
|
||||||
|
x = fxsize;
|
||||||
|
y = 0;
|
||||||
|
while (num--) {
|
||||||
|
gfxfetchsingle(fig, gs, x, y, fxsize, fysize);
|
||||||
|
x += fxsize;
|
||||||
|
if (x > xsize - fxsize) {
|
||||||
|
x = 0;
|
||||||
|
y += fysize;
|
||||||
|
if (y > ysize - fysize) y = 0;
|
||||||
|
}
|
||||||
|
fig++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void solidfetch(gfxset* gs, solid* dest) {
|
||||||
|
int xsize, ysize;
|
||||||
|
int i;
|
||||||
|
unsigned char *p, *map;
|
||||||
|
uchar* gfx;
|
||||||
|
|
||||||
|
memset(dest, 0, sizeof(solid));
|
||||||
|
xsize = gs->gs_xsize;
|
||||||
|
ysize = gs->gs_ysize;
|
||||||
|
|
||||||
|
i = xsize * ysize;
|
||||||
|
gfx = dest->graphics = malloc(i);
|
||||||
|
if (!gfx) return;
|
||||||
|
dest->xsize = xsize;
|
||||||
|
dest->ysize = ysize;
|
||||||
|
map = gs->gs_inout;
|
||||||
|
memcpy(gfx, gs->gs_pic, i);
|
||||||
|
p = gfx;
|
||||||
|
while (i--) {
|
||||||
|
if (*p) *p = map[*p];
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void solidcopyany(solid* src, solid* dest, int destx, int desty, int sizex, int sizey) {
|
||||||
|
int xmax, ymax;
|
||||||
|
int j;
|
||||||
|
uchar *p1, *p2;
|
||||||
|
int w;
|
||||||
|
|
||||||
|
xmax = src->xsize;
|
||||||
|
ymax = src->ysize;
|
||||||
|
if (destx >= xmax || desty >= ymax || destx + sizex <= 0 || desty + sizey <= 0) return;
|
||||||
|
if (destx < 0) {
|
||||||
|
sizex += destx;
|
||||||
|
destx = 0;
|
||||||
|
}
|
||||||
|
if (desty < 0) {
|
||||||
|
sizey += desty;
|
||||||
|
desty = 0;
|
||||||
|
}
|
||||||
|
if (destx + sizex > xmax) sizex = xmax - destx;
|
||||||
|
if (desty + sizey > ymax) sizey = ymax - desty;
|
||||||
|
|
||||||
|
if (dest) {
|
||||||
|
w = dest->xsize;
|
||||||
|
p1 = dest->graphics + desty * w + destx;
|
||||||
|
} else {
|
||||||
|
gfxlock();
|
||||||
|
w = stride;
|
||||||
|
p1 = videomem + desty * stride + destx;
|
||||||
|
}
|
||||||
|
p2 = src->graphics + desty * xmax + destx;
|
||||||
|
for (j = 0; j < sizey; ++j) {
|
||||||
|
memcpy(p1, p2, sizex);
|
||||||
|
p1 += w;
|
||||||
|
p2 += xmax;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void solidcopy(solid* solid, int destx, int desty, int sizex, int sizey) {
|
||||||
|
solidcopyany(solid, 0, destx, desty, sizex, sizey);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void drawfigureany(int x, int y, figure* fig, solid* dest) {
|
||||||
|
int run;
|
||||||
|
int dx, dy;
|
||||||
|
int xsize, ysize;
|
||||||
|
int clipx, clipy, w;
|
||||||
|
unsigned char *pc, *p, *p2, *take;
|
||||||
|
|
||||||
|
take = fig->graphics;
|
||||||
|
if (dest) {
|
||||||
|
w = clipx = dest->xsize;
|
||||||
|
clipy = dest->ysize;
|
||||||
|
pc = dest->graphics;
|
||||||
|
} else {
|
||||||
|
gfxlock();
|
||||||
|
w = stride;
|
||||||
|
clipx = IXSIZE;
|
||||||
|
clipy = IYSIZE;
|
||||||
|
pc = videomem;
|
||||||
|
}
|
||||||
|
|
||||||
|
dx = fig->xdelta;
|
||||||
|
dy = fig->ydelta;
|
||||||
|
xsize = fig->xsize;
|
||||||
|
ysize = fig->ysize;
|
||||||
|
x += dx;
|
||||||
|
y += dy;
|
||||||
|
if (x >= 0 && y >= 0 && x <= clipx - xsize && y <= clipy - ysize) {
|
||||||
|
while ((run = *take++)) {
|
||||||
|
dx = *((signed char*) take);
|
||||||
|
++take;
|
||||||
|
dy = *((signed char*) take);
|
||||||
|
++take;
|
||||||
|
p = pc + w * (y + dy) + x + dx;
|
||||||
|
while (run--) *p++ = *take++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
while ((run = *take++)) {
|
||||||
|
dx = *((signed char*) take);
|
||||||
|
++take;
|
||||||
|
dy = *((signed char*) take);
|
||||||
|
++take;
|
||||||
|
dx += x;
|
||||||
|
dy += y;
|
||||||
|
p2 = take;
|
||||||
|
take += run;
|
||||||
|
if (dy < 0 || dy >= clipy) continue;
|
||||||
|
if (dx >= clipx) continue;
|
||||||
|
if (dx < 0) {
|
||||||
|
p2 -= dx;
|
||||||
|
run += dx;
|
||||||
|
dx = 0;
|
||||||
|
} else if (dx + run > clipx)
|
||||||
|
run = clipx - dx;
|
||||||
|
p = pc + w * dy + dx;
|
||||||
|
if (run) memcpy(p, p2, run);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void drawfigure(int destx, int desty, figure* fig) {
|
||||||
|
drawfigureany(destx, desty, fig, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void copyup() {
|
||||||
|
gfxunlock();
|
||||||
|
SDL_UpdateRect(thescreen, 0, 0, 0, 0);
|
||||||
|
needwhole = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void copyupxy(int x, int y) {
|
||||||
|
gfxunlock();
|
||||||
|
SDL_UpdateRect(thescreen, x, y, 24, 24);
|
||||||
|
}
|
||||||
|
|
||||||
|
void copyupxysize(int x, int y, int xsize, int ysize) {
|
||||||
|
gfxunlock();
|
||||||
|
SDL_UpdateRect(thescreen, x, y, xsize, ysize);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// static void set_color(int color, int red, int green, int blue) {
|
||||||
|
// themap[color].r=red;
|
||||||
|
// themap[color].g=green;
|
||||||
|
// themap[color].b=blue;
|
||||||
|
// }
|
||||||
|
|
||||||
|
void opengfx(void) {
|
||||||
|
unsigned long videoflags;
|
||||||
|
|
||||||
|
themap[0].r = 0;
|
||||||
|
themap[0].g = 0;
|
||||||
|
themap[0].b = 0;
|
||||||
|
usedcolors = 1;
|
||||||
|
|
||||||
|
block64 = malloc(65536);
|
||||||
|
if (!block64) {
|
||||||
|
printf("Couldn't allocate block64\n");
|
||||||
|
exit(50);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_AUDIO) < 0) {
|
||||||
|
fprintf(stderr, "Couldn't initialize SDL: %s\n", SDL_GetError());
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
videoflags = SDL_SWSURFACE | SDL_HWPALETTE; //|SDL_FULLSCREEN;
|
||||||
|
|
||||||
|
thescreen = SDL_SetVideoMode(IXSIZE, IYSIZE, 8, videoflags);
|
||||||
|
if (thescreen == NULL) {
|
||||||
|
fprintf(stderr, "Couldn't set display mode: %s\n", SDL_GetError());
|
||||||
|
SDL_Quit();
|
||||||
|
exit(5);
|
||||||
|
}
|
||||||
|
stride = thescreen->pitch;
|
||||||
|
videomem = thescreen->pixels;
|
||||||
|
mustlock = SDL_MUSTLOCK(thescreen);
|
||||||
|
locked = 0;
|
||||||
|
SDL_ShowCursor(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void closegfx(void) {
|
||||||
|
SDL_Quit();
|
||||||
|
}
|
||||||
|
|
||||||
|
int checkpressed(int code) {
|
||||||
|
int *p, i;
|
||||||
|
i = numpressed;
|
||||||
|
p = pressedcodes;
|
||||||
|
while (i--)
|
||||||
|
if (*p++ == code) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int checkdown(int code) {
|
||||||
|
int *p, i;
|
||||||
|
i = numdown;
|
||||||
|
p = downcodes;
|
||||||
|
while (i--)
|
||||||
|
if (*p++ == code) return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int checkbutton(int button) {
|
||||||
|
return buttonstate & (1 << button);
|
||||||
|
}
|
||||||
|
|
||||||
|
int checkbuttondown(int button) {
|
||||||
|
return buttondown & (1 << button);
|
||||||
|
}
|
||||||
|
|
||||||
|
int anydown(void) {
|
||||||
|
return numdown;
|
||||||
|
}
|
||||||
|
|
||||||
|
int takedown(void) {
|
||||||
|
int res = 0;
|
||||||
|
|
||||||
|
if (numdown) {
|
||||||
|
res = *downcodes;
|
||||||
|
--numdown;
|
||||||
|
if (numdown) memmove(downcodes, downcodes + 1, numdown * sizeof(int));
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
int firstdown(void) {
|
||||||
|
return *downcodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ENDMARK 0xaabacada
|
||||||
|
|
||||||
|
int sdlinoutnormal[] = {
|
||||||
|
SDLK_0,
|
||||||
|
'0',
|
||||||
|
SDLK_1,
|
||||||
|
'1',
|
||||||
|
SDLK_2,
|
||||||
|
'2',
|
||||||
|
SDLK_3,
|
||||||
|
'3',
|
||||||
|
SDLK_4,
|
||||||
|
'4',
|
||||||
|
SDLK_5,
|
||||||
|
'5',
|
||||||
|
SDLK_6,
|
||||||
|
'6',
|
||||||
|
SDLK_7,
|
||||||
|
'7',
|
||||||
|
SDLK_8,
|
||||||
|
'8',
|
||||||
|
SDLK_9,
|
||||||
|
'9',
|
||||||
|
SDLK_a,
|
||||||
|
'a',
|
||||||
|
SDLK_b,
|
||||||
|
'b',
|
||||||
|
SDLK_c,
|
||||||
|
'c',
|
||||||
|
SDLK_d,
|
||||||
|
'd',
|
||||||
|
SDLK_e,
|
||||||
|
'e',
|
||||||
|
SDLK_f,
|
||||||
|
'f',
|
||||||
|
SDLK_g,
|
||||||
|
'g',
|
||||||
|
SDLK_h,
|
||||||
|
'h',
|
||||||
|
SDLK_i,
|
||||||
|
'i',
|
||||||
|
SDLK_j,
|
||||||
|
'j',
|
||||||
|
SDLK_k,
|
||||||
|
'k',
|
||||||
|
SDLK_l,
|
||||||
|
'l',
|
||||||
|
SDLK_m,
|
||||||
|
'm',
|
||||||
|
SDLK_n,
|
||||||
|
'n',
|
||||||
|
SDLK_o,
|
||||||
|
'o',
|
||||||
|
SDLK_p,
|
||||||
|
'p',
|
||||||
|
SDLK_q,
|
||||||
|
'q',
|
||||||
|
SDLK_r,
|
||||||
|
'r',
|
||||||
|
SDLK_s,
|
||||||
|
's',
|
||||||
|
SDLK_t,
|
||||||
|
't',
|
||||||
|
SDLK_u,
|
||||||
|
'u',
|
||||||
|
SDLK_v,
|
||||||
|
'v',
|
||||||
|
SDLK_w,
|
||||||
|
'w',
|
||||||
|
SDLK_x,
|
||||||
|
'x',
|
||||||
|
SDLK_y,
|
||||||
|
'y',
|
||||||
|
SDLK_z,
|
||||||
|
'z',
|
||||||
|
SDLK_MINUS,
|
||||||
|
'-',
|
||||||
|
SDLK_EQUALS,
|
||||||
|
'=',
|
||||||
|
SDLK_LEFTBRACKET,
|
||||||
|
'[',
|
||||||
|
SDLK_RIGHTBRACKET,
|
||||||
|
']',
|
||||||
|
SDLK_SEMICOLON,
|
||||||
|
';',
|
||||||
|
SDLK_QUOTE,
|
||||||
|
'\'',
|
||||||
|
SDLK_SLASH,
|
||||||
|
'/',
|
||||||
|
SDLK_PERIOD,
|
||||||
|
'.',
|
||||||
|
SDLK_COMMA,
|
||||||
|
',',
|
||||||
|
SDLK_BACKQUOTE,
|
||||||
|
'`',
|
||||||
|
SDLK_BACKSPACE,
|
||||||
|
8,
|
||||||
|
SDLK_TAB,
|
||||||
|
9,
|
||||||
|
SDLK_DELETE,
|
||||||
|
MYDELETE,
|
||||||
|
SDLK_RETURN,
|
||||||
|
13,
|
||||||
|
SDLK_F1,
|
||||||
|
MYF1,
|
||||||
|
SDLK_F2,
|
||||||
|
MYF2,
|
||||||
|
SDLK_F3,
|
||||||
|
MYF3,
|
||||||
|
SDLK_F4,
|
||||||
|
MYF4,
|
||||||
|
SDLK_F5,
|
||||||
|
MYF5,
|
||||||
|
SDLK_F6,
|
||||||
|
MYF6,
|
||||||
|
SDLK_F7,
|
||||||
|
MYF7,
|
||||||
|
SDLK_F8,
|
||||||
|
MYF8,
|
||||||
|
SDLK_F9,
|
||||||
|
MYF9,
|
||||||
|
SDLK_F10,
|
||||||
|
MYF10,
|
||||||
|
SDLK_ESCAPE,
|
||||||
|
0x1b,
|
||||||
|
SDLK_LEFT,
|
||||||
|
MYLEFT,
|
||||||
|
SDLK_RIGHT,
|
||||||
|
MYRIGHT,
|
||||||
|
SDLK_UP,
|
||||||
|
MYUP,
|
||||||
|
SDLK_DOWN,
|
||||||
|
MYDOWN,
|
||||||
|
SDLK_PAGEUP,
|
||||||
|
MYPAGEUP,
|
||||||
|
SDLK_PAGEDOWN,
|
||||||
|
MYPAGEDOWN,
|
||||||
|
SDLK_SPACE,
|
||||||
|
' ',
|
||||||
|
SDLK_HOME,
|
||||||
|
MYHOME,
|
||||||
|
SDLK_END,
|
||||||
|
MYEND,
|
||||||
|
SDLK_LALT,
|
||||||
|
MYALTL,
|
||||||
|
SDLK_RALT,
|
||||||
|
MYALTR,
|
||||||
|
ENDMARK};
|
||||||
|
int sdlinoutshifted[] = {
|
||||||
|
SDLK_0,
|
||||||
|
')',
|
||||||
|
SDLK_1,
|
||||||
|
'!',
|
||||||
|
SDLK_2,
|
||||||
|
'@',
|
||||||
|
SDLK_3,
|
||||||
|
'#',
|
||||||
|
SDLK_4,
|
||||||
|
'$',
|
||||||
|
SDLK_5,
|
||||||
|
'%',
|
||||||
|
SDLK_6,
|
||||||
|
'^',
|
||||||
|
SDLK_7,
|
||||||
|
'&',
|
||||||
|
SDLK_8,
|
||||||
|
'*',
|
||||||
|
SDLK_9,
|
||||||
|
'(',
|
||||||
|
SDLK_a,
|
||||||
|
'A',
|
||||||
|
SDLK_b,
|
||||||
|
'B',
|
||||||
|
SDLK_c,
|
||||||
|
'C',
|
||||||
|
SDLK_d,
|
||||||
|
'D',
|
||||||
|
SDLK_e,
|
||||||
|
'E',
|
||||||
|
SDLK_f,
|
||||||
|
'F',
|
||||||
|
SDLK_g,
|
||||||
|
'G',
|
||||||
|
SDLK_h,
|
||||||
|
'H',
|
||||||
|
SDLK_i,
|
||||||
|
'I',
|
||||||
|
SDLK_j,
|
||||||
|
'J',
|
||||||
|
SDLK_k,
|
||||||
|
'K',
|
||||||
|
SDLK_l,
|
||||||
|
'L',
|
||||||
|
SDLK_m,
|
||||||
|
'M',
|
||||||
|
SDLK_n,
|
||||||
|
'N',
|
||||||
|
SDLK_o,
|
||||||
|
'O',
|
||||||
|
SDLK_p,
|
||||||
|
'P',
|
||||||
|
SDLK_q,
|
||||||
|
'Q',
|
||||||
|
SDLK_r,
|
||||||
|
'R',
|
||||||
|
SDLK_s,
|
||||||
|
'S',
|
||||||
|
SDLK_t,
|
||||||
|
'T',
|
||||||
|
SDLK_u,
|
||||||
|
'U',
|
||||||
|
SDLK_v,
|
||||||
|
'V',
|
||||||
|
SDLK_w,
|
||||||
|
'W',
|
||||||
|
SDLK_x,
|
||||||
|
'X',
|
||||||
|
SDLK_y,
|
||||||
|
'Y',
|
||||||
|
SDLK_z,
|
||||||
|
'Z',
|
||||||
|
SDLK_MINUS,
|
||||||
|
'_',
|
||||||
|
SDLK_EQUALS,
|
||||||
|
'+',
|
||||||
|
SDLK_LEFTBRACKET,
|
||||||
|
'{',
|
||||||
|
SDLK_RIGHTBRACKET,
|
||||||
|
'}',
|
||||||
|
SDLK_SEMICOLON,
|
||||||
|
':',
|
||||||
|
SDLK_QUOTE,
|
||||||
|
'"',
|
||||||
|
SDLK_SLASH,
|
||||||
|
'?',
|
||||||
|
SDLK_PERIOD,
|
||||||
|
'>',
|
||||||
|
SDLK_COMMA,
|
||||||
|
'<',
|
||||||
|
SDLK_BACKQUOTE,
|
||||||
|
'~',
|
||||||
|
SDLK_BACKSPACE,
|
||||||
|
8,
|
||||||
|
SDLK_TAB,
|
||||||
|
9,
|
||||||
|
SDLK_DELETE,
|
||||||
|
MYDELETE,
|
||||||
|
SDLK_RETURN,
|
||||||
|
13,
|
||||||
|
SDLK_F1,
|
||||||
|
MYF1 + MYSHIFTED,
|
||||||
|
SDLK_F2,
|
||||||
|
MYF2 + MYSHIFTED,
|
||||||
|
SDLK_F3,
|
||||||
|
MYF3 + MYSHIFTED,
|
||||||
|
SDLK_F4,
|
||||||
|
MYF4 + MYSHIFTED,
|
||||||
|
SDLK_F5,
|
||||||
|
MYF5 + MYSHIFTED,
|
||||||
|
SDLK_F6,
|
||||||
|
MYF6 + MYSHIFTED,
|
||||||
|
SDLK_F7,
|
||||||
|
MYF7 + MYSHIFTED,
|
||||||
|
SDLK_F8,
|
||||||
|
MYF8 + MYSHIFTED,
|
||||||
|
SDLK_F9,
|
||||||
|
MYF9 + MYSHIFTED,
|
||||||
|
SDLK_F10,
|
||||||
|
MYF10 + MYSHIFTED,
|
||||||
|
SDLK_ESCAPE,
|
||||||
|
0x1b,
|
||||||
|
SDLK_LEFT,
|
||||||
|
MYLEFT + MYSHIFTED,
|
||||||
|
SDLK_RIGHT,
|
||||||
|
MYRIGHT + MYSHIFTED,
|
||||||
|
SDLK_UP,
|
||||||
|
MYUP + MYSHIFTED,
|
||||||
|
SDLK_DOWN,
|
||||||
|
MYDOWN + MYSHIFTED,
|
||||||
|
SDLK_PAGEUP,
|
||||||
|
MYPAGEUP,
|
||||||
|
SDLK_PAGEDOWN,
|
||||||
|
MYPAGEDOWN,
|
||||||
|
SDLK_SPACE,
|
||||||
|
' ',
|
||||||
|
SDLK_HOME,
|
||||||
|
MYHOME,
|
||||||
|
SDLK_END,
|
||||||
|
MYEND,
|
||||||
|
SDLK_LALT,
|
||||||
|
MYALTL,
|
||||||
|
SDLK_RALT,
|
||||||
|
MYALTR,
|
||||||
|
ENDMARK};
|
||||||
|
static int looklist(int code, int* list) {
|
||||||
|
while ((unsigned int) *list != ENDMARK) {
|
||||||
|
if (*list == code) return list[1];
|
||||||
|
list += 2;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
static int mapkey(int code, int qual) {
|
||||||
|
|
||||||
|
if (qual & KMOD_SHIFT)
|
||||||
|
code = looklist(code, sdlinoutshifted);
|
||||||
|
else
|
||||||
|
code = looklist(code, sdlinoutnormal);
|
||||||
|
if (code < 0) return -1;
|
||||||
|
|
||||||
|
if (qual & KMOD_ALT) code |= MYALTED;
|
||||||
|
|
||||||
|
return code;
|
||||||
|
}
|
||||||
|
static void markkey(int code, int status) {
|
||||||
|
int i;
|
||||||
|
int* ip;
|
||||||
|
|
||||||
|
if (status) {
|
||||||
|
if (numdown < KEYMAX) downcodes[numdown++] = code;
|
||||||
|
ip = pressedcodes;
|
||||||
|
i = numpressed;
|
||||||
|
while (i)
|
||||||
|
if (*ip++ == code)
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
i--;
|
||||||
|
if (!i && numpressed < KEYMAX) pressedcodes[numpressed++] = code;
|
||||||
|
} else {
|
||||||
|
i = numpressed;
|
||||||
|
ip = pressedcodes;
|
||||||
|
while (i)
|
||||||
|
if (*ip++ == code) {
|
||||||
|
*--ip = pressedcodes[--numpressed];
|
||||||
|
break;
|
||||||
|
} else
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void pollinput(void) {
|
||||||
|
SDL_PollEvent(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void scaninput(void) {
|
||||||
|
SDL_Event event;
|
||||||
|
int key, mod;
|
||||||
|
static int bs = 0;
|
||||||
|
|
||||||
|
numdown = 0;
|
||||||
|
buttondown = 0;
|
||||||
|
while (SDL_PollEvent(&event)) {
|
||||||
|
switch (event.type) {
|
||||||
|
case SDL_KEYDOWN:
|
||||||
|
key = event.key.keysym.sym;
|
||||||
|
mod = event.key.keysym.mod;
|
||||||
|
markkey(mapkey(key, mod), 1);
|
||||||
|
break;
|
||||||
|
case SDL_KEYUP:
|
||||||
|
key = event.key.keysym.sym;
|
||||||
|
mod = event.key.keysym.mod;
|
||||||
|
markkey(mapkey(key, mod), 0);
|
||||||
|
break;
|
||||||
|
case SDL_MOUSEBUTTONUP:
|
||||||
|
bs &= ~(1 << (event.button.button - 1));
|
||||||
|
mousex = event.button.x >> 1;
|
||||||
|
mousey = event.button.y >> 1;
|
||||||
|
mouseb = bs;
|
||||||
|
break;
|
||||||
|
case SDL_MOUSEBUTTONDOWN:
|
||||||
|
bs |= 1 << (event.button.button - 1);
|
||||||
|
mousex = event.button.x >> 1;
|
||||||
|
mousey = event.button.y >> 1;
|
||||||
|
mouseb = bs;
|
||||||
|
break;
|
||||||
|
case SDL_MOUSEMOTION:
|
||||||
|
mousex = event.motion.x >> 1;
|
||||||
|
mousey = event.motion.y >> 1;
|
||||||
|
break;
|
||||||
|
case SDL_QUIT:
|
||||||
|
exitflag = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
void scaninput()
|
||||||
|
{
|
||||||
|
|
||||||
|
int i,*ip,code;
|
||||||
|
numdown=0;
|
||||||
|
buttondown=0;
|
||||||
|
while(XCheckMaskEvent(dp,~0,&event))
|
||||||
|
switch(event.type)
|
||||||
|
{
|
||||||
|
case KeyPress:
|
||||||
|
code=XLookupKeysym(keyevent,0);
|
||||||
|
if(numdown<KEYMAX)
|
||||||
|
downcodes[numdown++]=code;
|
||||||
|
ip=pressedcodes;
|
||||||
|
i=numpressed;
|
||||||
|
while(i)
|
||||||
|
if(*ip++==code) break;
|
||||||
|
else i--;
|
||||||
|
if(!i && numpressed<KEYMAX)
|
||||||
|
pressedcodes[numpressed++]=code;
|
||||||
|
break;
|
||||||
|
case KeyRelease:
|
||||||
|
code=XLookupKeysym(keyevent,0);
|
||||||
|
i=numpressed;
|
||||||
|
ip=pressedcodes;
|
||||||
|
while(i)
|
||||||
|
if(*ip++==code)
|
||||||
|
{
|
||||||
|
*--ip=pressedcodes[--numpressed];
|
||||||
|
break;
|
||||||
|
} else i--;
|
||||||
|
break;
|
||||||
|
case ButtonPress:
|
||||||
|
i=1<<buttonevent->button;
|
||||||
|
buttonstate|=i;
|
||||||
|
buttondown|=i;
|
||||||
|
break;
|
||||||
|
case ButtonRelease:
|
||||||
|
buttonstate&=~(1<<buttonevent->button);
|
||||||
|
break;
|
||||||
|
case MotionNotify:
|
||||||
|
mxpos=motionevent->x;
|
||||||
|
mypos=motionevent->y;
|
||||||
|
break;
|
||||||
|
case Expose:
|
||||||
|
copyup();
|
||||||
|
needwhole=0;
|
||||||
|
break;
|
||||||
|
case FocusOut:
|
||||||
|
numpressed=0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
static void drawrect(int x, int y, int xs, int ys, int c) {
|
||||||
|
uchar* p;
|
||||||
|
|
||||||
|
gfxlock();
|
||||||
|
p = videomem + y * stride + x;
|
||||||
|
while (ys--) {
|
||||||
|
memset(p, c, xs);
|
||||||
|
p += stride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void greyrect(int x, int y, int xsize, int ysize) {
|
||||||
|
static int greycolor = -1;
|
||||||
|
if (greycolor == -1) greycolor = bestmatch(0, 0, 0x70);
|
||||||
|
drawrect(x, y, xsize, ysize, greycolor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clear() {
|
||||||
|
int j;
|
||||||
|
uchar* p;
|
||||||
|
|
||||||
|
gfxlock();
|
||||||
|
p = videomem;
|
||||||
|
for (j = 0; j < IYSIZE; ++j) {
|
||||||
|
memset(p, 0, IXSIZE);
|
||||||
|
p += stride;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void clearrect(int x, int y, int xsize, int ysize) {
|
||||||
|
drawrect(x, y, xsize, ysize, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void gfxlock(void) {
|
||||||
|
if (locked || !mustlock) return;
|
||||||
|
if (SDL_LockSurface(thescreen) < 0) { fprintf(stderr, "Couldn't lock display surface: %s\n", SDL_GetError()); }
|
||||||
|
locked = 1;
|
||||||
|
}
|
||||||
|
void gfxunlock(void) {
|
||||||
|
if (!locked || !mustlock) return;
|
||||||
|
SDL_UnlockSurface(thescreen);
|
||||||
|
locked = 0;
|
||||||
|
}
|
69
src/gfx.h
Normal file
69
src/gfx.h
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
|
||||||
|
#ifndef GFX_H
|
||||||
|
#define GFX_H
|
||||||
|
|
||||||
|
#define KEYMAX 128
|
||||||
|
|
||||||
|
|
||||||
|
extern int usedcolors;
|
||||||
|
extern uchar mymap[];
|
||||||
|
extern int screen;
|
||||||
|
extern int fontbase, fontysize;
|
||||||
|
extern char* imageloc;
|
||||||
|
|
||||||
|
extern long map2[];
|
||||||
|
extern uchar fmap[128];
|
||||||
|
extern int buttonstate, buttondown;
|
||||||
|
extern int mxpos, mypos;
|
||||||
|
|
||||||
|
extern int pressedcodes[KEYMAX], downcodes[KEYMAX], numpressed, numdown;
|
||||||
|
|
||||||
|
|
||||||
|
void opengfx(void);
|
||||||
|
void gfxlock(void);
|
||||||
|
void gfxunlock(void);
|
||||||
|
void pollinput(void);
|
||||||
|
int takedown(void);
|
||||||
|
void closegfx(void);
|
||||||
|
void greyrect(int x, int y, int xsize, int ysize);
|
||||||
|
void clearrect(int x, int y, int xsize, int ysize);
|
||||||
|
void solidfetch(gfxset* gs, solid* dest);
|
||||||
|
extern void dumpgfx(void);
|
||||||
|
extern void createinout(struct gfxset*);
|
||||||
|
extern void getcolors(void);
|
||||||
|
extern void gfxfetch(struct gfxset*, struct figure*, int);
|
||||||
|
extern void puttile(int destx, int desty, int source);
|
||||||
|
extern void store(int x, int y, int which);
|
||||||
|
extern void restore(int x, int y, int which);
|
||||||
|
extern void copyup(void);
|
||||||
|
extern void copyupxy(int x, int y);
|
||||||
|
extern void copyupxysize(int x, int y, int xsize, int ysize);
|
||||||
|
extern void getfigures(void);
|
||||||
|
extern unsigned long getcolor(char* name); /* unsigned long */
|
||||||
|
extern int checkpressed(int code);
|
||||||
|
extern int checkdown(int code);
|
||||||
|
extern int checkbutton(int button);
|
||||||
|
extern int checkbuttondown(int button);
|
||||||
|
extern int anydown(void);
|
||||||
|
extern int firstdown(void);
|
||||||
|
extern void scaninput(void);
|
||||||
|
extern void fontinit(void);
|
||||||
|
extern void writechar(int x, int y, uchar ch);
|
||||||
|
extern void clear(void);
|
||||||
|
extern void drawbox(int x, int y, int size, int color);
|
||||||
|
extern void drawbox2(int x, int y, int sizex, int sizey, int color);
|
||||||
|
extern void drawfillrect(int x, int y, int size, int color);
|
||||||
|
extern void bigpixel(int x, int y, int color);
|
||||||
|
extern void invert(int x, int y);
|
||||||
|
extern int getmousex(void);
|
||||||
|
extern int getmousey(void);
|
||||||
|
extern void drawsquare(int x, int y, uchar* source);
|
||||||
|
extern void colormapon(void);
|
||||||
|
extern void colormapoff(void);
|
||||||
|
extern void palette(uchar* pal);
|
||||||
|
extern void drawfigure(int x, int y, figure* fig);
|
||||||
|
extern void drawfigureany(int x, int y, figure* fig, solid* dest);
|
||||||
|
void solidcopy(solid* src, int destx, int desty, int sizex, int sizey);
|
||||||
|
void solidcopyany(solid* src, solid* dest, int destx, int desty, int sizex, int sizey);
|
||||||
|
|
||||||
|
#endif // GFXX_H
|
@ -1,11 +1,11 @@
|
|||||||
|
|
||||||
#include "bomber.h"
|
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
|
#include "bomber.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
typedef union genericlistitem genericlistitem;
|
typedef union genericlistitem genericlistitem;
|
||||||
union genericlistitem {
|
union genericlistitem {
|
||||||
genericlistitem *next;
|
genericlistitem* next;
|
||||||
listhead list;
|
listhead list;
|
||||||
bomb b;
|
bomb b;
|
||||||
flame f;
|
flame f;
|
||||||
@ -16,8 +16,8 @@ union genericlistitem {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* doesn't use prev link */
|
/* doesn't use prev link */
|
||||||
static genericlistitem *things=0;
|
static genericlistitem* things = 0;
|
||||||
static genericlistitem *free_things;
|
static genericlistitem* free_things;
|
||||||
|
|
||||||
static int count_used = 0;
|
static int count_used = 0;
|
||||||
|
|
||||||
@ -27,20 +27,18 @@ void alloc_things(void) {
|
|||||||
if (!things) {
|
if (!things) {
|
||||||
things = calloc(sizeof(genericlistitem), MAXTHINGS);
|
things = calloc(sizeof(genericlistitem), MAXTHINGS);
|
||||||
} else {
|
} else {
|
||||||
memset(things, 0, sizeof(genericlistitem)*MAXTHINGS);
|
memset(things, 0, sizeof(genericlistitem) * MAXTHINGS);
|
||||||
}
|
}
|
||||||
if (!things) nomem("Trying to allocate thing memory");
|
if (!things) nomem("Trying to allocate thing memory");
|
||||||
|
|
||||||
for (i=0; i < MAXTHINGS - 1; ++i) {
|
for (i = 0; i < MAXTHINGS - 1; ++i) { things[i].next = &things[i + 1]; }
|
||||||
things[i].next = &things[i + 1];
|
|
||||||
}
|
|
||||||
things[i].next = 0;
|
things[i].next = 0;
|
||||||
free_things = things;
|
free_things = things;
|
||||||
count_used = 0;
|
count_used = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void *_allocentry(size_t size) {
|
void* _allocentry(size_t size) {
|
||||||
genericlistitem *entry = free_things;
|
genericlistitem* entry = free_things;
|
||||||
|
|
||||||
if (size > sizeof(genericlistitem)) return 0;
|
if (size > sizeof(genericlistitem)) return 0;
|
||||||
|
|
||||||
@ -52,36 +50,36 @@ void *_allocentry(size_t size) {
|
|||||||
return entry;
|
return entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
void freeentry(void *ptr) {
|
void freeentry(void* ptr) {
|
||||||
genericlistitem *entry = ptr;
|
genericlistitem* entry = ptr;
|
||||||
entry->next = free_things;
|
entry->next = free_things;
|
||||||
free_things = entry;
|
free_things = entry;
|
||||||
count_used--;
|
count_used--;
|
||||||
}
|
}
|
||||||
|
|
||||||
void list_add_tail(listhead *head, listhead *entry) {
|
void list_add_tail(listhead* head, listhead* entry) {
|
||||||
entry->next = head;
|
entry->next = head;
|
||||||
entry->prev = head->prev;
|
entry->prev = head->prev;
|
||||||
head->prev->next = entry;
|
head->prev->next = entry;
|
||||||
head->prev = entry;
|
head->prev = entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
void list_del(listhead *entry) {
|
void list_del(listhead* entry) {
|
||||||
entry->next->prev = entry->prev;
|
entry->next->prev = entry->prev;
|
||||||
entry->prev->next = entry->next;
|
entry->prev->next = entry->next;
|
||||||
entry->next = entry->prev = entry;
|
entry->next = entry->prev = entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
void list_init_head(listhead *head) {
|
void list_init_head(listhead* head) {
|
||||||
head->next = head;
|
head->next = head;
|
||||||
head->prev = head;
|
head->prev = head;
|
||||||
}
|
}
|
||||||
|
|
||||||
void things_list_clear(listhead *head) {
|
void things_list_clear(listhead* head) {
|
||||||
genericlistitem *entry;
|
genericlistitem* entry;
|
||||||
|
|
||||||
while (head->next != head) {
|
while (head->next != head) {
|
||||||
entry = container_of(head->next, typeof(*entry), list);
|
entry = container_of(head->next, __typeof__(*entry), list);
|
||||||
list_del(head->next);
|
list_del(head->next);
|
||||||
freeentry(entry);
|
freeentry(entry);
|
||||||
}
|
}
|
63
src/list.h
Normal file
63
src/list.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#ifndef LIST_H
|
||||||
|
#define LIST_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
/* from linux kernel (with some changes for "iso" c) */
|
||||||
|
|
||||||
|
typedef struct listhead listhead;
|
||||||
|
struct listhead {
|
||||||
|
listhead *prev, *next;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define container_of(ptr, type, member) ((type*) ((char*) (__typeof__(((type*) 0)->member)*) (ptr) -offsetof(type, member)))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_entry - get the struct for this entry
|
||||||
|
* @ptr: the &struct list_head pointer.
|
||||||
|
* @type: the type of the struct this is embedded in.
|
||||||
|
* @member: the name of the list_struct within the struct.
|
||||||
|
*/
|
||||||
|
#define list_entry(ptr, type, member) container_of(ptr, type, member)
|
||||||
|
|
||||||
|
void alloc_things(void);
|
||||||
|
void* _allocentry(size_t size);
|
||||||
|
#define allocentry(type) (type*) _allocentry(sizeof(type))
|
||||||
|
void freeentry(void* ptr);
|
||||||
|
|
||||||
|
void list_add_tail(listhead* header, listhead* entry);
|
||||||
|
#define addtail(head, entry) list_add_tail(head, &(entry->list));
|
||||||
|
|
||||||
|
/* remove entry from list */
|
||||||
|
void list_del(listhead* entry);
|
||||||
|
#define removeitem(entry) list_del(&(entry->list));
|
||||||
|
|
||||||
|
void list_init_head(listhead* head);
|
||||||
|
|
||||||
|
void things_list_clear(listhead* head); /* listhead member must be the first member */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_for_each_entry - iterate over list of given type
|
||||||
|
* @pos: the type * to use as a loop cursor.
|
||||||
|
* @head: the head for your list.
|
||||||
|
* @member: the name of the list_struct within the struct.
|
||||||
|
*/
|
||||||
|
#define list_for_each_entry(pos, head, member) \
|
||||||
|
for (pos = list_entry((head)->next, __typeof__(*pos), member); /* prefetch(pos->member.next), */ \
|
||||||
|
&pos->member != (head); \
|
||||||
|
pos = list_entry(pos->member.next, __typeof__(*pos), member))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
|
||||||
|
* @pos:<-->the type * to use as a loop cursor.
|
||||||
|
* @n:<><-->another type * to use as temporary storage
|
||||||
|
* @head:<->the head for your list.
|
||||||
|
* @member:>the name of the list_struct within the struct.
|
||||||
|
*/
|
||||||
|
#define list_for_each_entry_safe(pos, n, head, member) \
|
||||||
|
for (pos = list_entry((head)->next, __typeof__(*pos), member), n = list_entry(pos->member.next, __typeof__(*pos), member); &pos->member != (head); \
|
||||||
|
pos = n, n = list_entry(n->member.next, __typeof__(*n), member))
|
||||||
|
|
||||||
|
#define list_empty(head) ((head) == (head)->next)
|
||||||
|
|
||||||
|
#endif
|
357
src/matcher.c
Normal file
357
src/matcher.c
Normal file
@ -0,0 +1,357 @@
|
|||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/timeb.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/uio.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define MAXMSG 256
|
||||||
|
#define PORT 5521
|
||||||
|
|
||||||
|
#define TIMETOLIVE 600 // seconds
|
||||||
|
|
||||||
|
typedef unsigned char uchar;
|
||||||
|
char logging = 0;
|
||||||
|
|
||||||
|
unsigned char mesg[MAXMSG];
|
||||||
|
int lastsize;
|
||||||
|
int network;
|
||||||
|
char masterhostname[256];
|
||||||
|
|
||||||
|
#define PKT_REGISTER 16
|
||||||
|
#define PKT_ACK 24
|
||||||
|
#define PKT_INFO 40
|
||||||
|
#define PKT_QUERY 32
|
||||||
|
|
||||||
|
#define MAXMATCHES 16
|
||||||
|
|
||||||
|
|
||||||
|
struct registration {
|
||||||
|
uchar id;
|
||||||
|
uchar unique[4];
|
||||||
|
uchar password[4];
|
||||||
|
uchar version[4];
|
||||||
|
uchar name[16];
|
||||||
|
uchar status;
|
||||||
|
};
|
||||||
|
struct query {
|
||||||
|
uchar id;
|
||||||
|
uchar password[4];
|
||||||
|
uchar version[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct gamehost {
|
||||||
|
struct gamehost *next, *prev;
|
||||||
|
uchar machine[4];
|
||||||
|
uchar port[2];
|
||||||
|
struct registration reg;
|
||||||
|
long timeout;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
struct gamehost *freehosts = 0, *activehosts = 0;
|
||||||
|
|
||||||
|
|
||||||
|
int udpsocket, myport;
|
||||||
|
struct sockaddr_in myname = {0}, mastername = {0};
|
||||||
|
socklen_t senderlength;
|
||||||
|
struct sockaddr_in sender = {0};
|
||||||
|
|
||||||
|
long longtime(void) {
|
||||||
|
struct timeb tb;
|
||||||
|
ftime(&tb);
|
||||||
|
return tb.time;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* timestr() {
|
||||||
|
static char timestring[80];
|
||||||
|
|
||||||
|
time_t t;
|
||||||
|
int l;
|
||||||
|
time(&t);
|
||||||
|
strcpy(timestring, ctime(&t));
|
||||||
|
l = strlen(timestring);
|
||||||
|
if (l && timestring[l - 1] == '\n') timestring[l - 1] = 0;
|
||||||
|
return timestring;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int putmsg(struct sockaddr_in* toname, unsigned char* msg, int len) {
|
||||||
|
int status;
|
||||||
|
|
||||||
|
status = sendto(udpsocket, msg, len, 0, (struct sockaddr*) toname, sizeof(struct sockaddr_in));
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
void ack() {
|
||||||
|
uchar copy[256];
|
||||||
|
|
||||||
|
*copy = PKT_ACK;
|
||||||
|
memmove(copy + 1, mesg, lastsize);
|
||||||
|
putmsg(&sender, copy, lastsize + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int getmsg(int seconds) {
|
||||||
|
int size;
|
||||||
|
|
||||||
|
lastsize = -1;
|
||||||
|
memset(&sender, 0, sizeof(sender));
|
||||||
|
senderlength = sizeof(sender);
|
||||||
|
if (seconds) {
|
||||||
|
struct timeval timeout;
|
||||||
|
fd_set readfds;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
timeout.tv_sec = seconds;
|
||||||
|
timeout.tv_usec = 0;
|
||||||
|
FD_ZERO(&readfds);
|
||||||
|
FD_SET(udpsocket, &readfds);
|
||||||
|
res = select(udpsocket + 1, &readfds, 0, 0, &timeout);
|
||||||
|
if (res <= 0) return -1;
|
||||||
|
}
|
||||||
|
lastsize = size = recvfrom(udpsocket, mesg, MAXMSG, 0, (struct sockaddr*) &sender, &senderlength);
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
long longind(unsigned char* p) {
|
||||||
|
return (p[0] << 24L) | (p[1] << 16L) | (p[2] << 8) | p[3];
|
||||||
|
}
|
||||||
|
short shortind(unsigned char* p) {
|
||||||
|
return (p[0] << 8L) | p[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void openport(int portwant) {
|
||||||
|
int status;
|
||||||
|
|
||||||
|
myport = portwant;
|
||||||
|
udpsocket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
|
if (udpsocket == -1) {
|
||||||
|
perror("socket()");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
memset(&myname, 0, sizeof(myname));
|
||||||
|
myname.sin_family = AF_INET;
|
||||||
|
myname.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
|
myname.sin_port = htons(myport);
|
||||||
|
|
||||||
|
status = bind(udpsocket, (struct sockaddr*) &myname, sizeof(myname));
|
||||||
|
if (status == -1) {
|
||||||
|
perror("bind()");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define PERBLOCK 512
|
||||||
|
|
||||||
|
struct gamehost* newhost() {
|
||||||
|
struct gamehost *h, *block;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!freehosts) {
|
||||||
|
block = malloc(sizeof(struct gamehost) * PERBLOCK);
|
||||||
|
if (!block) return 0;
|
||||||
|
freehosts = block;
|
||||||
|
i = PERBLOCK - 1;
|
||||||
|
while (i--) {
|
||||||
|
block->next = block + 1;
|
||||||
|
++block;
|
||||||
|
}
|
||||||
|
block->next = 0;
|
||||||
|
}
|
||||||
|
h = freehosts;
|
||||||
|
freehosts = freehosts->next;
|
||||||
|
memset(h, 0, sizeof(struct gamehost));
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
|
void freehost(struct gamehost* h) {
|
||||||
|
h->next = freehosts;
|
||||||
|
freehosts = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct gamehost* findmatch(struct registration* key) {
|
||||||
|
struct gamehost* h;
|
||||||
|
h = activehosts;
|
||||||
|
while (h) {
|
||||||
|
if (!memcmp(&h->reg, key, sizeof(struct registration) - 1)) return h;
|
||||||
|
h = h->next;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void insert(struct gamehost* h) {
|
||||||
|
if (activehosts) {
|
||||||
|
h->next = activehosts;
|
||||||
|
h->prev = activehosts->prev;
|
||||||
|
activehosts->prev = h;
|
||||||
|
activehosts = h;
|
||||||
|
} else {
|
||||||
|
h->next = h->prev = 0;
|
||||||
|
activehosts = h;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void delete (struct gamehost* h) {
|
||||||
|
if (h->prev)
|
||||||
|
h->prev->next = h->next;
|
||||||
|
else
|
||||||
|
activehosts = h->next;
|
||||||
|
if (h->next) h->next->prev = h->prev;
|
||||||
|
freehost(h);
|
||||||
|
}
|
||||||
|
void doreg() {
|
||||||
|
struct registration* new;
|
||||||
|
struct gamehost* match;
|
||||||
|
long now;
|
||||||
|
|
||||||
|
new = (struct registration*) mesg;
|
||||||
|
match = findmatch(new);
|
||||||
|
if (logging) {
|
||||||
|
unsigned addr = ntohl(sender.sin_addr.s_addr);
|
||||||
|
unsigned short port = ntohs(sender.sin_port);
|
||||||
|
printf(
|
||||||
|
"reg :%s:%d.%d.%d.%d:%d %c%lx '%s'\n",
|
||||||
|
timestr(),
|
||||||
|
(addr >> 24) & 255,
|
||||||
|
(addr >> 16) & 255,
|
||||||
|
(addr >> 8) & 255,
|
||||||
|
addr & 255,
|
||||||
|
port,
|
||||||
|
new->status ? '+' : '-',
|
||||||
|
(long) match,
|
||||||
|
new->name);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
if (!match && !new->status) {
|
||||||
|
ack();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (match && new->status) {
|
||||||
|
ack();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (!match && new->status) {
|
||||||
|
match = newhost();
|
||||||
|
if (!match) return; // No memory, what can we do?
|
||||||
|
memmove(match->machine, &sender.sin_addr.s_addr, 4);
|
||||||
|
memmove(match->port, &sender.sin_port, 2);
|
||||||
|
match->reg = *new;
|
||||||
|
now = longtime();
|
||||||
|
match->timeout = now + TIMETOLIVE;
|
||||||
|
ack();
|
||||||
|
insert(match);
|
||||||
|
return;
|
||||||
|
} else // match && !new->status
|
||||||
|
{
|
||||||
|
delete (match);
|
||||||
|
ack();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void doquery() {
|
||||||
|
uchar* password;
|
||||||
|
uchar* version;
|
||||||
|
struct gamehost* h;
|
||||||
|
uchar response[2048], *rput, *countersave;
|
||||||
|
int counter;
|
||||||
|
|
||||||
|
if (logging) {
|
||||||
|
unsigned addr = ntohl(sender.sin_addr.s_addr);
|
||||||
|
unsigned short port = ntohs(sender.sin_port);
|
||||||
|
printf("query:%s:%d.%d.%d.%d:%d\n", timestr(), (addr >> 24) & 255, (addr >> 16) & 255, (addr >> 8) & 255, addr & 255, port);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
password = mesg + 1;
|
||||||
|
version = mesg + 5;
|
||||||
|
h = activehosts;
|
||||||
|
rput = response;
|
||||||
|
*rput++ = PKT_INFO;
|
||||||
|
memmove(rput, password, 4);
|
||||||
|
rput += 4;
|
||||||
|
memmove(rput, version, 4);
|
||||||
|
rput += 4;
|
||||||
|
countersave = rput;
|
||||||
|
*rput++ = 0;
|
||||||
|
*rput++ = 0;
|
||||||
|
counter = 0;
|
||||||
|
|
||||||
|
while (h) {
|
||||||
|
if (!memcmp(password, h->reg.password, 4) && !memcmp(version, h->reg.version, 4) && counter < MAXMATCHES) {
|
||||||
|
++counter;
|
||||||
|
memmove(rput, h->reg.unique, 4);
|
||||||
|
rput += 4;
|
||||||
|
memmove(rput, h->machine, 4);
|
||||||
|
rput += 4;
|
||||||
|
memmove(rput, h->port, 2);
|
||||||
|
rput += 2;
|
||||||
|
memmove(rput, h->reg.name, sizeof(h->reg.name));
|
||||||
|
rput += sizeof(h->reg.name);
|
||||||
|
}
|
||||||
|
h = h->next;
|
||||||
|
}
|
||||||
|
*countersave++ = counter >> 8;
|
||||||
|
*countersave++ = counter;
|
||||||
|
putmsg(&sender, response, rput - response);
|
||||||
|
}
|
||||||
|
|
||||||
|
void purge(long cutoff) {
|
||||||
|
struct gamehost *h, *h2;
|
||||||
|
h = activehosts;
|
||||||
|
while (h) {
|
||||||
|
h2 = h;
|
||||||
|
h = h->next;
|
||||||
|
if (cutoff - h2->timeout > 0) { delete (h2); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char** argv) {
|
||||||
|
int i;
|
||||||
|
int want;
|
||||||
|
int size;
|
||||||
|
long purgetime;
|
||||||
|
long now;
|
||||||
|
|
||||||
|
want = PORT;
|
||||||
|
if (argc > 1) {
|
||||||
|
for (i = 1; i < argc; ++i)
|
||||||
|
if (!strncmp(argv[i], "-p", 2)) {
|
||||||
|
if (strlen(argv[i]) > 2)
|
||||||
|
want = atoi(argv[i] + 2);
|
||||||
|
else if (i + 1 < argc)
|
||||||
|
want = atoi(argv[i + 1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
freehosts = 0;
|
||||||
|
openport(want);
|
||||||
|
purgetime = longtime() + TIMETOLIVE;
|
||||||
|
for (;;) {
|
||||||
|
size = getmsg(10);
|
||||||
|
if (size >= 1) switch (*mesg) {
|
||||||
|
case PKT_REGISTER:
|
||||||
|
if (size < sizeof(struct registration)) continue;
|
||||||
|
doreg();
|
||||||
|
break;
|
||||||
|
case PKT_QUERY:
|
||||||
|
if (size < sizeof(struct query)) continue;
|
||||||
|
doquery();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
now = longtime();
|
||||||
|
if (now - purgetime > 0) // avoid year 203x bug...
|
||||||
|
{
|
||||||
|
purge(purgetime);
|
||||||
|
purgetime += TIMETOLIVE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
387
src/menu.c
Normal file
387
src/menu.c
Normal file
@ -0,0 +1,387 @@
|
|||||||
|
|
||||||
|
#include "menu.h"
|
||||||
|
#include "announce.h"
|
||||||
|
#include "bomber.h"
|
||||||
|
#include "draw.h"
|
||||||
|
#include "game.h"
|
||||||
|
#include "gfx.h"
|
||||||
|
#include "network.h"
|
||||||
|
#include "sound.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
GameOptions configopts = {2, 1, 0, 2};
|
||||||
|
|
||||||
|
/* Generic menu */
|
||||||
|
|
||||||
|
typedef enum { MENU_ANY = -1, MENU_MAIN = 0, MENU_CONFIG = 2, MENU_JOIN = 3 } menuname;
|
||||||
|
|
||||||
|
#define MENU_SELECT(x) ((menuname)(-x - 1))
|
||||||
|
|
||||||
|
static int menuhistory[32] = {0};
|
||||||
|
static char menustring[1024];
|
||||||
|
static char *menuput, *menuitems[40], *menutitle;
|
||||||
|
static int menunum, menuexit;
|
||||||
|
static int menudelta;
|
||||||
|
|
||||||
|
static void drawmenu(int selected) {
|
||||||
|
int i, j;
|
||||||
|
int tx, ty;
|
||||||
|
|
||||||
|
clear();
|
||||||
|
j = strlen(menutitle) * bigfontxsize;
|
||||||
|
drawbigstring((IXSIZE - j) >> 1, 20, menutitle);
|
||||||
|
ty = ((IYSIZE - (bigfontysize * menunum)) >> 1) - (IYSIZE >> 3);
|
||||||
|
for (i = 0; i < menunum; ++i) {
|
||||||
|
j = strlen(menuitems[i]) * bigfontxsize;
|
||||||
|
tx = (IXSIZE - j) >> 1;
|
||||||
|
if (i == selected) {
|
||||||
|
greyrect(0, ty - 1, tx - 5, bigfontysize);
|
||||||
|
greyrect(tx + j + 3, ty - 1, IXSIZE - (tx + j + 3), bigfontysize);
|
||||||
|
}
|
||||||
|
drawbigstring(tx, ty, menuitems[i]);
|
||||||
|
ty += bigfontyspace;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int domenu(menuname whichmenu, int (*pause)(void)) {
|
||||||
|
char redraw;
|
||||||
|
int selected;
|
||||||
|
int mcount = 0;
|
||||||
|
|
||||||
|
if (whichmenu >= 0)
|
||||||
|
selected = menuhistory[whichmenu];
|
||||||
|
else
|
||||||
|
selected = -whichmenu - 1;
|
||||||
|
|
||||||
|
if (!pause) pause = mypause;
|
||||||
|
|
||||||
|
redraw = 1;
|
||||||
|
clearspritelist();
|
||||||
|
while (!exitflag) {
|
||||||
|
if (redraw) {
|
||||||
|
drawmenu(selected);
|
||||||
|
redraw = 0;
|
||||||
|
}
|
||||||
|
if (!pause()) return -1;
|
||||||
|
scaninput();
|
||||||
|
++mcount;
|
||||||
|
|
||||||
|
clearsprites();
|
||||||
|
clearspritelist();
|
||||||
|
addsprite(IXSIZE / 2 - 50 - 20, IYSIZE - 80, walking[2] + (30 + mcount % 15));
|
||||||
|
addsprite(IXSIZE / 2 + 50 - 20, IYSIZE - 80, walking[3] + (30 + (mcount + 7) % 15));
|
||||||
|
plotsprites();
|
||||||
|
copyup();
|
||||||
|
|
||||||
|
if (anydown()) playsound(3);
|
||||||
|
while (anydown()) {
|
||||||
|
switch (takedown()) {
|
||||||
|
case MYLEFT:
|
||||||
|
menudelta = -1;
|
||||||
|
return selected;
|
||||||
|
case MYRIGHT:
|
||||||
|
case ' ':
|
||||||
|
case 13:
|
||||||
|
menudelta = 1;
|
||||||
|
return selected;
|
||||||
|
case 'k':
|
||||||
|
case MYUP:
|
||||||
|
if (selected)
|
||||||
|
--selected;
|
||||||
|
else
|
||||||
|
selected = menunum - 1;
|
||||||
|
if (whichmenu >= 0) menuhistory[whichmenu] = selected;
|
||||||
|
redraw = 1;
|
||||||
|
break;
|
||||||
|
case 'j':
|
||||||
|
case MYDOWN:
|
||||||
|
++selected;
|
||||||
|
if (selected == menunum) selected = 0;
|
||||||
|
if (whichmenu >= 0) menuhistory[whichmenu] = selected;
|
||||||
|
redraw = 1;
|
||||||
|
break;
|
||||||
|
case 0x1b:
|
||||||
|
if (MENU_MAIN == whichmenu && menuexit != selected) {
|
||||||
|
selected = menuexit;
|
||||||
|
redraw = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
menudelta = 1;
|
||||||
|
return menuexit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
menudelta = 0;
|
||||||
|
return menuexit;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void menustart() {
|
||||||
|
menunum = -1;
|
||||||
|
menuput = menustring;
|
||||||
|
*menuput = 0;
|
||||||
|
menuexit = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void additem_s(char* item, int len) {
|
||||||
|
if (len < 0 || (menustring + sizeof(menustring) - menuput <= len)) return;
|
||||||
|
|
||||||
|
if (menunum < 0)
|
||||||
|
menutitle = menuput;
|
||||||
|
else
|
||||||
|
menuitems[menunum] = menuput;
|
||||||
|
++menunum;
|
||||||
|
memcpy(menuput, item, len + 1);
|
||||||
|
menuput += len + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void additem(char* item, ...) {
|
||||||
|
char output[256];
|
||||||
|
va_list ap;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
va_start(ap, item);
|
||||||
|
|
||||||
|
len = vsnprintf(output, sizeof(output), item, ap);
|
||||||
|
if (len >= 256) len = 255; /* truncated string */
|
||||||
|
|
||||||
|
additem_s(output, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void addexit(char* item, ...) {
|
||||||
|
char output[256];
|
||||||
|
va_list ap;
|
||||||
|
int len;
|
||||||
|
|
||||||
|
va_start(ap, item);
|
||||||
|
|
||||||
|
len = vsnprintf(output, sizeof(output), item, ap);
|
||||||
|
if (len >= 256) len = 255; /* truncated string */
|
||||||
|
|
||||||
|
menuexit = menunum;
|
||||||
|
additem_s(output, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* end generic menu */
|
||||||
|
|
||||||
|
/* game menues */
|
||||||
|
|
||||||
|
static const char* densities[] = {"PACKED", "HIGH", "MEDIUM", "LOW"};
|
||||||
|
static const char* generosities[] = {"LOW", "MEDIUM", "HIGH", "RIDICULOUS"};
|
||||||
|
static const char* dis_en_abled[] = {"DISABLED", "ENABLED"};
|
||||||
|
|
||||||
|
static void config_menu(void) {
|
||||||
|
int sel;
|
||||||
|
|
||||||
|
while (!exitflag) {
|
||||||
|
menustart();
|
||||||
|
additem("GAME OPTIONS");
|
||||||
|
additem("RETURN TO MAIN MENU");
|
||||||
|
additem("DENSITY: %s", densities[configopts.density]);
|
||||||
|
additem("GENEROSITY: %s", generosities[configopts.generosity]);
|
||||||
|
additem("INITIAL FLAME LENGTH: %d", configopts.flames + 1);
|
||||||
|
additem("INITIAL NUMBER OF BOMBS: %d", configopts.bombs + 1);
|
||||||
|
additem("SOUND: %s", dis_en_abled[sound_enabled]);
|
||||||
|
sel = domenu(MENU_CONFIG, NULL);
|
||||||
|
switch (sel) {
|
||||||
|
case 0:
|
||||||
|
return;
|
||||||
|
case 1:
|
||||||
|
configopts.density += menudelta;
|
||||||
|
configopts.density &= 3;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
configopts.generosity += menudelta;
|
||||||
|
configopts.generosity &= 3;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
configopts.flames += menudelta;
|
||||||
|
configopts.flames &= 7;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
configopts.bombs += menudelta;
|
||||||
|
configopts.bombs &= 7;
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
sound_enabled = 1 - sound_enabled;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void draw_host_game(void) {
|
||||||
|
int i;
|
||||||
|
char* name;
|
||||||
|
char temp[64];
|
||||||
|
|
||||||
|
#define M3X (IXSIZE / 3)
|
||||||
|
#define M3Y (IYSIZE / 4)
|
||||||
|
|
||||||
|
clear();
|
||||||
|
centerbig(20, "HOST NETWORK GAME");
|
||||||
|
drawbigstring(M3X, M3Y, "SLOT NAME");
|
||||||
|
for (i = 0; i < MAXNETNODES; ++i) {
|
||||||
|
if (!netnodes[i].used) continue;
|
||||||
|
name = netnodes[i].name;
|
||||||
|
snprintf(temp, sizeof(temp), " %d %s", i + 1, name);
|
||||||
|
drawbigstring(M3X, M3Y + (i + 2) * bigfontyspace, temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
copyup();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void host_game(void) {
|
||||||
|
create_seed_unique();
|
||||||
|
if (!start_network_game()) {
|
||||||
|
failure("COULD NOT REGISTER GAME");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
draw_host_game();
|
||||||
|
for (;;) {
|
||||||
|
scaninput();
|
||||||
|
while (anydown()) {
|
||||||
|
switch (takedown()) {
|
||||||
|
case 0x1b:
|
||||||
|
unregistergame();
|
||||||
|
cancel_network_game();
|
||||||
|
return;
|
||||||
|
case ' ':
|
||||||
|
case 13:
|
||||||
|
unregistergame();
|
||||||
|
if (begin_network_game()) {
|
||||||
|
run_network_game();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
send_invites();
|
||||||
|
draw_host_game();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!handle_joins()) continue;
|
||||||
|
|
||||||
|
send_invites();
|
||||||
|
draw_host_game();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void drawjoinscreen(void) {
|
||||||
|
int i;
|
||||||
|
char name[17];
|
||||||
|
char temp[64];
|
||||||
|
|
||||||
|
#define JX (IXSIZE / 3)
|
||||||
|
#define JY (IYSIZE / 4)
|
||||||
|
|
||||||
|
clear();
|
||||||
|
centerbig(20, "JOIN NETWORK GAME");
|
||||||
|
drawbigstring(JX, JY, "SLOT NAME");
|
||||||
|
for (i = 0; i < MAXNETNODES; ++i) {
|
||||||
|
if (!netnodes[i].used) continue;
|
||||||
|
memmove(name, netnodes[i].name, 16);
|
||||||
|
name[16] = 0;
|
||||||
|
snprintf(temp, sizeof(temp), " %d %s", i + 1, name);
|
||||||
|
drawbigstring(JX, JY + (i + 1) * bigfontyspace, temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tryjoin(int which) {
|
||||||
|
int res;
|
||||||
|
|
||||||
|
if (0 == (res = send_join(&gamelistentries[which].netname, playername))) { return 0; }
|
||||||
|
|
||||||
|
while (!exitflag) {
|
||||||
|
switch (res) {
|
||||||
|
case 1:
|
||||||
|
failure("Game closed");
|
||||||
|
return 0;
|
||||||
|
case 2:
|
||||||
|
drawjoinscreen();
|
||||||
|
copyup();
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
return 1;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
scaninput();
|
||||||
|
while (anydown()) {
|
||||||
|
switch (takedown()) {
|
||||||
|
case 0x1b:
|
||||||
|
send_quit();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res = scaninvite(200);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int join_game_pause(void) {
|
||||||
|
if (find_more_games()) return 0;
|
||||||
|
mypause();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void join_game(void) {
|
||||||
|
int i;
|
||||||
|
int sel = -1;
|
||||||
|
|
||||||
|
if (!searchgames()) { return; }
|
||||||
|
|
||||||
|
menuhistory[MENU_JOIN] = 0;
|
||||||
|
|
||||||
|
while (-1 == sel) {
|
||||||
|
menustart();
|
||||||
|
if (gamelistsize == 0) {
|
||||||
|
additem("JOIN NETWORK GAME - NO GAMES AVAILABLE");
|
||||||
|
addexit("EXIT");
|
||||||
|
} else {
|
||||||
|
additem("JOIN NETWORK GAME");
|
||||||
|
for (i = 0; i < gamelistsize; i++) { additem(gamelistentries[i].name); }
|
||||||
|
addexit("EXIT");
|
||||||
|
}
|
||||||
|
sel = domenu(MENU_JOIN, join_game_pause);
|
||||||
|
if (menudelta < 0) sel = -1;
|
||||||
|
}
|
||||||
|
stop_search();
|
||||||
|
|
||||||
|
if (menuexit == sel || !gamelistsize) { return; }
|
||||||
|
if (!tryjoin(sel)) { return; }
|
||||||
|
run_network_game();
|
||||||
|
}
|
||||||
|
|
||||||
|
void mainloop(void) {
|
||||||
|
int sel;
|
||||||
|
|
||||||
|
exitflag = 0;
|
||||||
|
while (!exitflag) {
|
||||||
|
menustart();
|
||||||
|
additem("BOMBER MAIN MENU");
|
||||||
|
additem("EXIT GAME");
|
||||||
|
additem("START SINGLE PLAYER GAME");
|
||||||
|
additem("OPTIONS");
|
||||||
|
// additem("REMAP MOVEMENT KEYS");
|
||||||
|
additem("START NETWORK GAME");
|
||||||
|
additem("JOIN NETWORK GAME");
|
||||||
|
sel = domenu(MENU_MAIN, NULL);
|
||||||
|
if (menudelta < 0) sel = -1;
|
||||||
|
switch (sel) {
|
||||||
|
case 0:
|
||||||
|
return;
|
||||||
|
case 1:
|
||||||
|
run_single_player();
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
config_menu();
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
host_game();
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
join_game();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,34 +1,34 @@
|
|||||||
|
|
||||||
#include "bomber.h"
|
#include "network.h"
|
||||||
#include "announce.h"
|
#include "announce.h"
|
||||||
|
#include "bomber.h"
|
||||||
|
#include "draw.h"
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
#include "menu.h"
|
#include "menu.h"
|
||||||
#include "network.h"
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "draw.h"
|
|
||||||
|
|
||||||
#define MAXMSG 4096
|
#define MAXMSG 4096
|
||||||
|
|
||||||
int udpsocket;
|
int udpsocket;
|
||||||
const unsigned char gameversion[4]={0xda,0x01,0x00,0x09};
|
const unsigned char gameversion[4] = {0xda, 0x01, 0x00, 0x09};
|
||||||
|
|
||||||
struct netnode netnodes[MAXNETNODES];
|
struct netnode netnodes[MAXNETNODES];
|
||||||
|
|
||||||
static int informsize;
|
static int informsize;
|
||||||
static unsigned char regpacket[64];
|
static unsigned char regpacket[64];
|
||||||
|
|
||||||
static struct sockaddr_in myname={0},mastername={0};
|
static struct sockaddr_in myname = {0}, mastername = {0};
|
||||||
static socklen_t senderlength;
|
static socklen_t senderlength;
|
||||||
static struct sockaddr_in sender={0};
|
static struct sockaddr_in sender = {0};
|
||||||
|
|
||||||
static unsigned char mesg[MAXMSG]="";
|
static unsigned char mesg[MAXMSG] = "";
|
||||||
uchar needwhole=0;
|
uchar needwhole = 0;
|
||||||
int mydatacount;
|
int mydatacount;
|
||||||
int myslot;
|
int myslot;
|
||||||
network_type network = NETWORK_NONE;
|
network_type network = NETWORK_NONE;
|
||||||
|
|
||||||
int actioncount;
|
int actioncount;
|
||||||
unsigned char actionblock[ACTIONHIST*MAXNETNODES];
|
unsigned char actionblock[ACTIONHIST * MAXNETNODES];
|
||||||
|
|
||||||
int myaction;
|
int myaction;
|
||||||
unsigned char actions[MAXNETNODES];
|
unsigned char actions[MAXNETNODES];
|
||||||
@ -37,22 +37,22 @@ unsigned char latestactions[MAXNETNODES];
|
|||||||
long latestcounts[MAXNETNODES];
|
long latestcounts[MAXNETNODES];
|
||||||
|
|
||||||
enum network_packet_types {
|
enum network_packet_types {
|
||||||
PKT_ACK, /* perfect copy of packet received */
|
PKT_ACK, /* perfect copy of packet received */
|
||||||
/* join / host game */
|
/* join / host game */
|
||||||
/* slave -> master packets */
|
/* slave -> master packets */
|
||||||
PKT_JOIN, /* 4 bytes version #, 4 bytes joinunique #, 16 bytes name */
|
PKT_JOIN, /* 4 bytes version #, 4 bytes joinunique #, 16 bytes name */
|
||||||
PKT_QUIT, /* 4 bytes unique # */
|
PKT_QUIT, /* 4 bytes unique # */
|
||||||
/* master -> slave packets */
|
/* master -> slave packets */
|
||||||
PKT_INVITE, /* 4 bytes unique #, 1 byte your slot (0xff for kick, no data following it) #, any # of 1:slot,16:name sets (-1 end) */
|
PKT_INVITE, /* 4 bytes unique #, 1 byte your slot (0xff for kick, no data following it) #, any # of 1:slot,16:name sets (-1 end) */
|
||||||
PKT_BEGIN, /* clone of INVITE */
|
PKT_BEGIN, /* clone of INVITE */
|
||||||
PKT_CONFIG, /* 4 bytes unique #, config */
|
PKT_CONFIG, /* 4 bytes unique #, config */
|
||||||
PKT_ACCEPT, /* 4 bytes join unique #, 132 bytes seed + unique #, config, slot info (see invite) */
|
PKT_ACCEPT, /* 4 bytes join unique #, 132 bytes seed + unique #, config, slot info (see invite) */
|
||||||
PKT_REJECT, /* 4 bytes join unique #, 4 bytes version #, 1: reason */
|
PKT_REJECT, /* 4 bytes join unique #, 4 bytes version #, 1: reason */
|
||||||
/* ingame actions */
|
/* ingame actions */
|
||||||
/* slave -> master packets */
|
/* slave -> master packets */
|
||||||
PKT_MYDATA, /* 4 bytes unique #,4 bytes frame #, 1 byte data */
|
PKT_MYDATA, /* 4 bytes unique #,4 bytes frame #, 1 byte data */
|
||||||
/* master -> slave packets */
|
/* master -> slave packets */
|
||||||
PKT_STEP, /* 4 bytes unique #, 4 bytes frame #, history x MAXNETNODES bytes ACT_* */
|
PKT_STEP, /* 4 bytes unique #, 4 bytes frame #, history x MAXNETNODES bytes ACT_* */
|
||||||
|
|
||||||
PKT_INVALID = 0xff
|
PKT_INVALID = 0xff
|
||||||
};
|
};
|
||||||
@ -65,10 +65,7 @@ enum reject_reason {
|
|||||||
|
|
||||||
#define _REJECT_LAST REJECT_VERSION
|
#define _REJECT_LAST REJECT_VERSION
|
||||||
|
|
||||||
const char *reject_reason_str[] = {
|
const char* reject_reason_str[] = {"Server full", "Version mismatch"};
|
||||||
"Server full",
|
|
||||||
"Version mismatch"
|
|
||||||
};
|
|
||||||
|
|
||||||
/* all bytes stored MSB first */
|
/* all bytes stored MSB first */
|
||||||
|
|
||||||
@ -125,135 +122,126 @@ received will be answered with PKT_QUIT.
|
|||||||
|
|
||||||
/* Network I/O, building/checking packets */
|
/* Network I/O, building/checking packets */
|
||||||
|
|
||||||
#if defined (TEST_LATENCY)
|
#if defined(TEST_LATENCY)
|
||||||
#define NUMQ 512
|
#define NUMQ 512
|
||||||
struct message {
|
struct message {
|
||||||
int time;
|
int time;
|
||||||
struct sockaddr_in *to;
|
struct sockaddr_in* to;
|
||||||
int tosize;
|
int tosize;
|
||||||
unsigned char msg[512];
|
unsigned char msg[512];
|
||||||
int len;
|
int len;
|
||||||
} message[NUMQ]={0};
|
} message[NUMQ] = {0};
|
||||||
|
|
||||||
|
|
||||||
outmsgs() {
|
outmsgs() {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for(i=0;i<NUMQ;++i) {
|
for (i = 0; i < NUMQ; ++i) {
|
||||||
if(message[i].time) {
|
if (message[i].time) {
|
||||||
--message[i].time;
|
--message[i].time;
|
||||||
if(message[i].time) continue;
|
if (message[i].time) continue;
|
||||||
sendto(udpsocket,message[i].msg,message[i].len,0,
|
sendto(udpsocket, message[i].msg, message[i].len, 0, message[i].to, sizeof(struct sockaddr_in));
|
||||||
message[i].to,sizeof(struct sockaddr_in));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int putmsg(struct sockaddr_in *toname,unsigned char *msg,int len) {
|
static int putmsg(struct sockaddr_in* toname, unsigned char* msg, int len) {
|
||||||
int status;
|
int status;
|
||||||
|
|
||||||
#if defined (TEST_LATENCY)
|
#if defined(TEST_LATENCY)
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for(i=0;i<NUMQ;++i) {
|
for (i = 0; i < NUMQ; ++i) {
|
||||||
if(!message[i].time) {
|
if (!message[i].time) {
|
||||||
message[i].time=10;
|
message[i].time = 10;
|
||||||
message[i].to=toname;
|
message[i].to = toname;
|
||||||
memcpy(message[i].msg,msg,len);
|
memcpy(message[i].msg, msg, len);
|
||||||
message[i].len=len;
|
message[i].len = len;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
#else
|
#else
|
||||||
status=sendto(udpsocket,msg,len,0,
|
status = sendto(udpsocket, msg, len, 0, (struct sockaddr*) toname, sizeof(struct sockaddr_in));
|
||||||
(struct sockaddr *)toname,sizeof(struct sockaddr_in));
|
|
||||||
return status;
|
return status;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int getmsg(int msec) {
|
static int getmsg(int msec) {
|
||||||
int size;
|
int size;
|
||||||
|
|
||||||
memset(&sender,0,sizeof(sender));
|
memset(&sender, 0, sizeof(sender));
|
||||||
senderlength=sizeof(sender);
|
senderlength = sizeof(sender);
|
||||||
if(msec) {
|
if (msec) {
|
||||||
struct timeval timeout;
|
struct timeval timeout;
|
||||||
fd_set readfds;
|
fd_set readfds;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
memset(&timeout,0,sizeof(timeout));
|
memset(&timeout, 0, sizeof(timeout));
|
||||||
timeout.tv_sec=msec/1000;
|
timeout.tv_sec = msec / 1000;
|
||||||
timeout.tv_usec=(msec%1000)*1000;
|
timeout.tv_usec = (msec % 1000) * 1000;
|
||||||
FD_ZERO(&readfds);
|
FD_ZERO(&readfds);
|
||||||
FD_SET(udpsocket,&readfds);
|
FD_SET(udpsocket, &readfds);
|
||||||
res=select(udpsocket+1,&readfds,0,0,&timeout);
|
res = select(udpsocket + 1, &readfds, 0, 0, &timeout);
|
||||||
if(res<=0) return -1;
|
if (res <= 0) return -1;
|
||||||
}
|
}
|
||||||
size=recvfrom(udpsocket,mesg,MAXMSG,0,
|
size = recvfrom(udpsocket, mesg, MAXMSG, 0, (struct sockaddr*) &sender, &senderlength);
|
||||||
(struct sockaddr *)&sender,&senderlength);
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int isvalidunique(unsigned char *p) {
|
static int isvalidunique(unsigned char* p) {
|
||||||
return 0 == memcmp(p, &network_unique, 4);
|
return 0 == memcmp(p, &network_unique, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int isvalidversion(unsigned char *p) {
|
static int isvalidversion(unsigned char* p) {
|
||||||
return 0 == memcmp(p, gameversion, 4);
|
return 0 == memcmp(p, gameversion, 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned char* writeuint32(unsigned char *p, Uint32 i) {
|
static unsigned char* writeuint32(unsigned char* p, Uint32 i) {
|
||||||
p[0]=i>>24L;
|
p[0] = i >> 24L;
|
||||||
p[1]=i>>16L;
|
p[1] = i >> 16L;
|
||||||
p[2]=i>>8L;
|
p[2] = i >> 8L;
|
||||||
p[3]=i;
|
p[3] = i;
|
||||||
return p+4;
|
return p + 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Uint32 readuint32(unsigned char *p) {
|
static Uint32 readuint32(unsigned char* p) {
|
||||||
return (p[0]<<24L) | (p[1]<<16L) | (p[2]<<8) | p[3];
|
return (p[0] << 24L) | (p[1] << 16L) | (p[2] << 8) | p[3];
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned char* write_unique(unsigned char *p) {
|
static unsigned char* write_unique(unsigned char* p) {
|
||||||
memcpy(p, &network_unique, 4);
|
memcpy(p, &network_unique, 4);
|
||||||
return p + 4;
|
return p + 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned char* write_version(unsigned char *p) {
|
static unsigned char* write_version(unsigned char* p) {
|
||||||
memcpy(p, &gameversion, 4);
|
memcpy(p, &gameversion, 4);
|
||||||
return p + 4;
|
return p + 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int isvalidmsg_from_slave() {
|
static int isvalidmsg_from_slave() {
|
||||||
int i;
|
int i;
|
||||||
void *host;
|
void* host;
|
||||||
void *port;
|
void* port;
|
||||||
|
|
||||||
if (!isvalidunique(mesg+1)) return -1;
|
if (!isvalidunique(mesg + 1)) return -1;
|
||||||
host=&sender.sin_addr.s_addr;
|
host = &sender.sin_addr.s_addr;
|
||||||
port=&sender.sin_port;
|
port = &sender.sin_port;
|
||||||
for(i=1;i<MAXNETNODES;++i)
|
for (i = 1; i < MAXNETNODES; ++i)
|
||||||
if(netnodes[i].used &&
|
if (netnodes[i].used && !memcmp(&netnodes[i].netname.sin_addr.s_addr, host, 4) && !memcmp(&netnodes[i].netname.sin_port, port, 2)) return i;
|
||||||
!memcmp(&netnodes[i].netname.sin_addr.s_addr,host,4) &&
|
|
||||||
!memcmp(&netnodes[i].netname.sin_port,port,2))
|
|
||||||
return i;
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int isvalidmsg_from_master() {
|
static int isvalidmsg_from_master() {
|
||||||
if (sender.sin_family != mastername.sin_family
|
if (sender.sin_family != mastername.sin_family || sender.sin_addr.s_addr != mastername.sin_addr.s_addr || sender.sin_port != mastername.sin_port) return 0;
|
||||||
|| sender.sin_addr.s_addr != mastername.sin_addr.s_addr
|
|
||||||
|| sender.sin_port != mastername.sin_port) return 0;
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handling game actions */
|
/* Handling game actions */
|
||||||
|
|
||||||
static void addactions(void) {
|
static void addactions(void) {
|
||||||
memmove(actionblock+MAXNETNODES, actionblock, (ACTIONHIST-1)*MAXNETNODES);
|
memmove(actionblock + MAXNETNODES, actionblock, (ACTIONHIST - 1) * MAXNETNODES);
|
||||||
memcpy(actionblock, actions, MAXNETNODES);
|
memcpy(actionblock, actions, MAXNETNODES);
|
||||||
++actioncount;
|
++actioncount;
|
||||||
}
|
}
|
||||||
@ -264,8 +252,8 @@ static void sendactions(int which) {
|
|||||||
msg[0] = PKT_STEP;
|
msg[0] = PKT_STEP;
|
||||||
write_unique(msg + 1);
|
write_unique(msg + 1);
|
||||||
writeuint32(msg + 5, actioncount);
|
writeuint32(msg + 5, actioncount);
|
||||||
memcpy(msg + 9, actionblock, MAXNETNODES*ACTIONHIST);
|
memcpy(msg + 9, actionblock, MAXNETNODES * ACTIONHIST);
|
||||||
putmsg(&netnodes[which].netname, msg, MAXNETNODES*ACTIONHIST + 9);
|
putmsg(&netnodes[which].netname, msg, MAXNETNODES * ACTIONHIST + 9);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sendmine(int frame) {
|
static void sendmine(int frame) {
|
||||||
@ -289,17 +277,15 @@ int networktraffic(void) {
|
|||||||
case NETWORK_NONE:
|
case NETWORK_NONE:
|
||||||
return -1;
|
return -1;
|
||||||
case NETWORK_MASTER:
|
case NETWORK_MASTER:
|
||||||
memcpy(actions,latestactions,MAXNETNODES);
|
memcpy(actions, latestactions, MAXNETNODES);
|
||||||
actions[0]=myaction;
|
actions[0] = myaction;
|
||||||
if (myaction == ACT_QUIT) {
|
if (myaction == ACT_QUIT) {
|
||||||
for (i = 1; i < MAXNETNODES; ++i) {
|
for (i = 1; i < MAXNETNODES; ++i) {
|
||||||
if (netnodes[i].used)
|
if (netnodes[i].used) actions[i] = ACT_QUIT;
|
||||||
actions[i] = ACT_QUIT;
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (i = 1; i < MAXNETNODES; ++i) {
|
for (i = 1; i < MAXNETNODES; ++i) {
|
||||||
if (netnodes[i].used)
|
if (netnodes[i].used) actions[i] &= ACT_MASK; /* only keep direction */
|
||||||
actions[i] &= ACT_MASK; /* only keep direction */
|
|
||||||
}
|
}
|
||||||
now = gtime();
|
now = gtime();
|
||||||
for (;;) {
|
for (;;) {
|
||||||
@ -313,7 +299,7 @@ int networktraffic(void) {
|
|||||||
if (length < 10) continue;
|
if (length < 10) continue;
|
||||||
whosent = isvalidmsg_from_slave();
|
whosent = isvalidmsg_from_slave();
|
||||||
if (whosent <= 0) continue;
|
if (whosent <= 0) continue;
|
||||||
count = readuint32(mesg+5);
|
count = readuint32(mesg + 5);
|
||||||
if (count > latestcounts[whosent]) {
|
if (count > latestcounts[whosent]) {
|
||||||
latestcounts[whosent] = count;
|
latestcounts[whosent] = count;
|
||||||
actions[whosent] = (actions[whosent] & ~ACT_MASK) | mesg[9]; /* don't drop "action" keys */
|
actions[whosent] = (actions[whosent] & ~ACT_MASK) | mesg[9]; /* don't drop "action" keys */
|
||||||
@ -324,10 +310,9 @@ int networktraffic(void) {
|
|||||||
addactions(); /* update action history block */
|
addactions(); /* update action history block */
|
||||||
|
|
||||||
for (i = 1; i < MAXNETNODES; ++i) {
|
for (i = 1; i < MAXNETNODES; ++i) {
|
||||||
if(netnodes[i].used) {
|
if (netnodes[i].used) {
|
||||||
sendactions(i); /* send actions to every active node */
|
sendactions(i); /* send actions to every active node */
|
||||||
if (actions[i] == ACT_QUIT)
|
if (actions[i] == ACT_QUIT) netnodes[i].used = 0; /* remove disconnected clients */
|
||||||
netnodes[i].used = 0; /* remove disconnected clients */
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return actioncount;
|
return actioncount;
|
||||||
@ -339,7 +324,7 @@ int networktraffic(void) {
|
|||||||
sendmine(mydatacount);
|
sendmine(mydatacount);
|
||||||
|
|
||||||
for (;;) {
|
for (;;) {
|
||||||
/* if we got already one packet we only wait 3msec, otherwise 30msec */
|
/* if we got already one packet we only wait 3msec, otherwise 30msec */
|
||||||
long cur = gtime();
|
long cur = gtime();
|
||||||
if (count >= 0 && cur - now > 3) break;
|
if (count >= 0 && cur - now > 3) break;
|
||||||
if (exitflag || cur - now > 30) break;
|
if (exitflag || cur - now > 30) break;
|
||||||
@ -361,37 +346,37 @@ int networktraffic(void) {
|
|||||||
|
|
||||||
/* Handling socket init */
|
/* Handling socket init */
|
||||||
|
|
||||||
int winsock=0;
|
int winsock = 0;
|
||||||
|
|
||||||
void getsocket(void) {
|
void getsocket(void) {
|
||||||
int status;
|
int status;
|
||||||
socklen_t slen = sizeof(myname);
|
socklen_t slen = sizeof(myname);
|
||||||
#if defined(__WIN32__) || defined(WIN32)
|
#if defined(__WIN32__) || defined(WIN32)
|
||||||
char dummydata[128];
|
char dummydata[128];
|
||||||
|
|
||||||
if(WSAStartup(0x0101,(void *)dummydata)) {
|
if (WSAStartup(0x0101, (void*) dummydata)) {
|
||||||
printf("Windows dumped\n");
|
printf("Windows dumped\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
winsock=1;
|
winsock = 1;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
udpsocket=socket(PF_INET,SOCK_DGRAM,IPPROTO_UDP);
|
udpsocket = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||||
if(udpsocket==-1) {
|
if (udpsocket == -1) {
|
||||||
perror("socket()");
|
perror("socket()");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
memset(&myname,0,sizeof(myname));
|
memset(&myname, 0, sizeof(myname));
|
||||||
myname.sin_family=AF_INET;
|
myname.sin_family = AF_INET;
|
||||||
myname.sin_addr.s_addr=htonl(INADDR_ANY);
|
myname.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
myname.sin_port=htons(0);
|
myname.sin_port = htons(0);
|
||||||
status=bind(udpsocket,(struct sockaddr *) &myname,sizeof(myname));
|
status = bind(udpsocket, (struct sockaddr*) &myname, sizeof(myname));
|
||||||
if(-1 == status) {
|
if (-1 == status) {
|
||||||
perror("bind()");
|
perror("bind()");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
status = getsockname(udpsocket, (struct sockaddr *) &myname, &slen);
|
status = getsockname(udpsocket, (struct sockaddr*) &myname, &slen);
|
||||||
if(-1 == status) {
|
if (-1 == status) {
|
||||||
perror("getsockname()");
|
perror("getsockname()");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
@ -399,7 +384,7 @@ char dummydata[128];
|
|||||||
|
|
||||||
void freesocket(void) {
|
void freesocket(void) {
|
||||||
#if defined(__WIN32__) || defined(WIN32)
|
#if defined(__WIN32__) || defined(WIN32)
|
||||||
if(!winsock) return;
|
if (!winsock) return;
|
||||||
WSACleanup();
|
WSACleanup();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -413,7 +398,7 @@ static unsigned char* write_inform(unsigned char* put) {
|
|||||||
|
|
||||||
*put++ = 0xff; /* slot specific for each slave */
|
*put++ = 0xff; /* slot specific for each slave */
|
||||||
for (i = 0; i < MAXNETNODES; ++i) {
|
for (i = 0; i < MAXNETNODES; ++i) {
|
||||||
if(!netnodes[i].used) continue;
|
if (!netnodes[i].used) continue;
|
||||||
*put++ = i;
|
*put++ = i;
|
||||||
memmove(put, netnodes[i].name, 16);
|
memmove(put, netnodes[i].name, 16);
|
||||||
put += 16;
|
put += 16;
|
||||||
@ -424,15 +409,15 @@ static unsigned char* write_inform(unsigned char* put) {
|
|||||||
|
|
||||||
static void send_inform_all(unsigned char type) {
|
static void send_inform_all(unsigned char type) {
|
||||||
int i;
|
int i;
|
||||||
unsigned char *put = mesg;
|
unsigned char* put = mesg;
|
||||||
|
|
||||||
*put++ = type;
|
*put++ = type;
|
||||||
put = write_unique(put);
|
put = write_unique(put);
|
||||||
put = write_inform(put);
|
put = write_inform(put);
|
||||||
informsize = put-mesg;
|
informsize = put - mesg;
|
||||||
|
|
||||||
for(i=1;i<MAXNETNODES;++i) {
|
for (i = 1; i < MAXNETNODES; ++i) {
|
||||||
if(netnodes[i].used) {
|
if (netnodes[i].used) {
|
||||||
mesg[5] = i;
|
mesg[5] = i;
|
||||||
putmsg(&netnodes[i].netname, mesg, informsize);
|
putmsg(&netnodes[i].netname, mesg, informsize);
|
||||||
}
|
}
|
||||||
@ -448,36 +433,35 @@ static unsigned char* write_config(unsigned char* put) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void build_config() {
|
static void build_config() {
|
||||||
unsigned char *put;
|
unsigned char* put;
|
||||||
|
|
||||||
put=mesg;
|
put = mesg;
|
||||||
*put++=PKT_CONFIG;
|
*put++ = PKT_CONFIG;
|
||||||
put = write_config(put);
|
put = write_config(put);
|
||||||
informsize=put-mesg;
|
informsize = put - mesg;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void send_config1(int which) {
|
static void send_config1(int which) {
|
||||||
putmsg(&netnodes[which].netname,mesg,informsize);
|
putmsg(&netnodes[which].netname, mesg, informsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
void send_config() {
|
void send_config() {
|
||||||
int i;
|
int i;
|
||||||
build_config();
|
build_config();
|
||||||
for (i = 1; i < MAXNETNODES; ++i)
|
for (i = 1; i < MAXNETNODES; ++i)
|
||||||
if (netnodes[i].used)
|
if (netnodes[i].used) send_config1(i);
|
||||||
send_config1(i);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void send_reject(struct sockaddr_in *toname, Uint32 network_join_unique, unsigned char reason) {
|
static void send_reject(struct sockaddr_in* toname, Uint32 network_join_unique, unsigned char reason) {
|
||||||
mesg[0] = PKT_REJECT;
|
mesg[0] = PKT_REJECT;
|
||||||
memcpy(mesg+1, &network_join_unique, sizeof(network_join_unique));
|
memcpy(mesg + 1, &network_join_unique, sizeof(network_join_unique));
|
||||||
write_version(mesg+5);
|
write_version(mesg + 5);
|
||||||
mesg[9] = reason;
|
mesg[9] = reason;
|
||||||
putmsg(&sender,mesg,10);
|
putmsg(toname, mesg, 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void send_accept(Uint32 network_join_unique) {
|
static void send_accept(Uint32 network_join_unique) {
|
||||||
unsigned char *put = mesg;
|
unsigned char* put = mesg;
|
||||||
|
|
||||||
*put++ = PKT_ACCEPT;
|
*put++ = PKT_ACCEPT;
|
||||||
memcpy(put, &network_join_unique, sizeof(network_join_unique));
|
memcpy(put, &network_join_unique, sizeof(network_join_unique));
|
||||||
@ -485,15 +469,15 @@ static void send_accept(Uint32 network_join_unique) {
|
|||||||
put = write_seed_unique(put);
|
put = write_seed_unique(put);
|
||||||
put = write_config(put);
|
put = write_config(put);
|
||||||
put = write_inform(put);
|
put = write_inform(put);
|
||||||
putmsg(&sender,mesg,put-mesg);
|
putmsg(&sender, mesg, put - mesg);
|
||||||
}
|
}
|
||||||
|
|
||||||
int start_network_game() {
|
int start_network_game() {
|
||||||
if(!registergame(playername, myname.sin_port, gameversion)) return 0;
|
if (!registergame(playername, myname.sin_port, gameversion)) return 0;
|
||||||
memset(netnodes,0,sizeof(netnodes));
|
memset(netnodes, 0, sizeof(netnodes));
|
||||||
netnodes[0].used=1;
|
netnodes[0].used = 1;
|
||||||
memmove(netnodes[0].name,playername,16);
|
memmove(netnodes[0].name, playername, 16);
|
||||||
myslot=0;
|
myslot = 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -512,13 +496,11 @@ void cancel_network_game() {
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
mesg[0] = PKT_INVITE;
|
mesg[0] = PKT_INVITE;
|
||||||
write_unique(mesg+1);
|
write_unique(mesg + 1);
|
||||||
mesg[5] = 0xff;
|
mesg[5] = 0xff;
|
||||||
|
|
||||||
for(i=1;i<MAXNETNODES;++i) {
|
for (i = 1; i < MAXNETNODES; ++i) {
|
||||||
if(netnodes[i].used) {
|
if (netnodes[i].used) { putmsg(&netnodes[i].netname, mesg, 6); }
|
||||||
putmsg(&netnodes[i].netname,mesg,6);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -526,20 +508,20 @@ int handle_joins() {
|
|||||||
int size;
|
int size;
|
||||||
int i, j;
|
int i, j;
|
||||||
unsigned char temp[64];
|
unsigned char temp[64];
|
||||||
Uint32 network_join_unique;
|
Uint32 network_join_unique = 0;
|
||||||
|
|
||||||
size=getmsg(40);
|
size = getmsg(40);
|
||||||
switch (*mesg) {
|
switch (*mesg) {
|
||||||
case PKT_JOIN:
|
case PKT_JOIN:
|
||||||
if (size < 25) return 0;
|
if (size < 25) return 0;
|
||||||
memcpy(&network_join_unique, mesg+5, sizeof(network_join_unique));
|
memcpy(&network_join_unique, mesg + 5, sizeof(network_join_unique));
|
||||||
if (!isvalidversion(mesg+1)) {
|
if (!isvalidversion(mesg + 1)) {
|
||||||
send_reject(&sender, network_join_unique, REJECT_VERSION);
|
send_reject(&sender, network_join_unique, REJECT_VERSION);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case PKT_QUIT:
|
case PKT_QUIT:
|
||||||
if (size < 5 || !isvalidunique(mesg+1)) return 0;
|
if (size < 5 || !isvalidunique(mesg + 1)) return 0;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
@ -556,37 +538,33 @@ int handle_joins() {
|
|||||||
if (-1 == j) j = i;
|
if (-1 == j) j = i;
|
||||||
continue; /* don't compare with unused host */
|
continue; /* don't compare with unused host */
|
||||||
}
|
}
|
||||||
if(memcmp(&netnodes[i].netname.sin_addr.s_addr,
|
if (memcmp(&netnodes[i].netname.sin_addr.s_addr, &sender.sin_addr.s_addr, 4)) continue;
|
||||||
&sender.sin_addr.s_addr,4)) continue;
|
if (memcmp(&netnodes[i].netname.sin_port, &sender.sin_port, 2)) continue;
|
||||||
if(memcmp(&netnodes[i].netname.sin_port,
|
|
||||||
&sender.sin_port,2)) continue;
|
|
||||||
/* found host */
|
/* found host */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (*mesg) {
|
switch (*mesg) {
|
||||||
case PKT_QUIT:
|
case PKT_QUIT:
|
||||||
if(i < MAXNETNODES) /* if host found, reset entry */
|
if (i < MAXNETNODES) /* if host found, reset entry */
|
||||||
memset(netnodes+i,0,sizeof(struct netnode));
|
memset(netnodes + i, 0, sizeof(struct netnode));
|
||||||
/* send always ACK for QUITs */
|
/* send always ACK for QUITs */
|
||||||
*temp=PKT_ACK;
|
*temp = PKT_ACK;
|
||||||
memmove(temp+1,mesg,5);
|
memmove(temp + 1, mesg, 5);
|
||||||
putmsg(&sender,temp,6);
|
putmsg(&sender, temp, 6);
|
||||||
break;
|
break;
|
||||||
case PKT_JOIN:
|
case PKT_JOIN:
|
||||||
if (i==MAXNETNODES && j==-1) { /* reject */
|
if (i == MAXNETNODES && j == -1) { /* reject */
|
||||||
send_reject(&sender, network_join_unique, REJECT_FULL);
|
send_reject(&sender, network_join_unique, REJECT_FULL);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(i==MAXNETNODES) i=j;
|
if (i == MAXNETNODES) i = j;
|
||||||
memmove(&netnodes[i].netname.sin_addr.s_addr,
|
memmove(&netnodes[i].netname.sin_addr.s_addr, &sender.sin_addr.s_addr, 4);
|
||||||
&sender.sin_addr.s_addr,4);
|
memmove(&netnodes[i].netname.sin_port, &sender.sin_port, 2);
|
||||||
memmove(&netnodes[i].netname.sin_port,
|
netnodes[i].netname.sin_family = AF_INET;
|
||||||
&sender.sin_port,2);
|
netnodes[i].used = 1;
|
||||||
netnodes[i].netname.sin_family=AF_INET;
|
memcpy(netnodes[i].name, mesg + 9, 16);
|
||||||
netnodes[i].used=1;
|
|
||||||
memcpy(netnodes[i].name,mesg+9,16);
|
|
||||||
netnodes[i].name[15] = '\0';
|
netnodes[i].name[15] = '\0';
|
||||||
|
|
||||||
send_accept(network_join_unique);
|
send_accept(network_join_unique);
|
||||||
@ -597,18 +575,20 @@ int handle_joins() {
|
|||||||
|
|
||||||
/* Client side */
|
/* Client side */
|
||||||
|
|
||||||
static int read_inform(unsigned char** pbuf, int *psize) {
|
static int read_inform(unsigned char** pbuf, int* psize) {
|
||||||
unsigned char *buf = *pbuf;
|
unsigned char* buf = *pbuf;
|
||||||
int size = *psize;
|
int size = *psize;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (size < 1) return 0;
|
if (size < 1) return 0;
|
||||||
myslot = *buf++; size--;
|
myslot = *buf++;
|
||||||
|
size--;
|
||||||
if (0xff == myslot) return 1;
|
if (0xff == myslot) return 1;
|
||||||
|
|
||||||
if (size < 1) return 0;
|
if (size < 1) return 0;
|
||||||
while (0xff != *buf) {
|
while (0xff != *buf) {
|
||||||
i = *buf++; size--;
|
i = *buf++;
|
||||||
|
size--;
|
||||||
if (size < 17 || i >= MAXNETNODES) return 0;
|
if (size < 17 || i >= MAXNETNODES) return 0;
|
||||||
netnodes[i].used = 1;
|
netnodes[i].used = 1;
|
||||||
memcpy(netnodes[i].name, buf, 16);
|
memcpy(netnodes[i].name, buf, 16);
|
||||||
@ -634,16 +614,16 @@ static void read_config(unsigned char* buf) {
|
|||||||
/* returns 0=ignore packet,1=we're rejected,2=INVITE/CONFIG,3=BEGIN */
|
/* returns 0=ignore packet,1=we're rejected,2=INVITE/CONFIG,3=BEGIN */
|
||||||
int scaninvite(int msec) {
|
int scaninvite(int msec) {
|
||||||
int size;
|
int size;
|
||||||
unsigned char *take;
|
unsigned char* take;
|
||||||
|
|
||||||
size = getmsg(msec);
|
size = getmsg(msec);
|
||||||
|
|
||||||
if (size < 6) return 0;
|
if (size < 6) return 0;
|
||||||
if (*mesg!=PKT_INVITE && *mesg!=PKT_BEGIN && *mesg!=PKT_CONFIG) return 0;
|
if (*mesg != PKT_INVITE && *mesg != PKT_BEGIN && *mesg != PKT_CONFIG) return 0;
|
||||||
if (!isvalidmsg_from_master()) return 0;
|
if (!isvalidmsg_from_master()) return 0;
|
||||||
if (!isvalidunique(mesg+1)) return 0;
|
if (!isvalidunique(mesg + 1)) return 0;
|
||||||
|
|
||||||
take = mesg+5;
|
take = mesg + 5;
|
||||||
size -= 5;
|
size -= 5;
|
||||||
|
|
||||||
switch (*mesg) {
|
switch (*mesg) {
|
||||||
@ -666,35 +646,35 @@ int scaninvite(int msec) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int send_join(struct sockaddr_in *netname, char playername[16]) {
|
int send_join(struct sockaddr_in* netname, char playername[16]) {
|
||||||
int size;
|
int size;
|
||||||
long now;
|
long now;
|
||||||
Uint32 join_unique = gtime();
|
Uint32 join_unique = gtime();
|
||||||
unsigned char *buf;
|
unsigned char* buf;
|
||||||
|
|
||||||
mastername = *netname;
|
mastername = *netname;
|
||||||
*regpacket=PKT_JOIN;
|
*regpacket = PKT_JOIN;
|
||||||
write_version(regpacket + 1);
|
write_version(regpacket + 1);
|
||||||
writeuint32(regpacket+5, join_unique);
|
writeuint32(regpacket + 5, join_unique);
|
||||||
memcpy(regpacket+9, playername, 16);
|
memcpy(regpacket + 9, playername, 16);
|
||||||
now=longtime();
|
now = longtime();
|
||||||
putmsg(&mastername,regpacket,1+4+4+16);
|
putmsg(&mastername, regpacket, 1 + 4 + 4 + 16);
|
||||||
while(longtime()-now < 3) {
|
while (longtime() - now < 3) {
|
||||||
if (0 == (size = getmsg(1000))) {
|
if (0 == (size = getmsg(1000))) {
|
||||||
/* got no message, send join again */
|
/* got no message, send join again */
|
||||||
putmsg(&mastername,regpacket,1+4+4+16);
|
putmsg(&mastername, regpacket, 1 + 4 + 4 + 16);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (size < 5) continue;
|
if (size < 5) continue;
|
||||||
if (readuint32(mesg+1) != join_unique) continue;
|
if (readuint32(mesg + 1) != join_unique) continue;
|
||||||
switch (*mesg) {
|
switch (*mesg) {
|
||||||
case PKT_ACCEPT:
|
case PKT_ACCEPT:
|
||||||
if (size < 1+4+132+4+2) continue;
|
if (size < 1 + 4 + 132 + 4 + 2) continue;
|
||||||
read_seed_unique(mesg + 5);
|
read_seed_unique(mesg + 5);
|
||||||
read_config(mesg+137);
|
read_config(mesg + 137);
|
||||||
buf = mesg+141;
|
buf = mesg + 141;
|
||||||
size -= 141;
|
size -= 141;
|
||||||
if (!read_inform(&buf,&size)) return 0;
|
if (!read_inform(&buf, &size)) return 0;
|
||||||
return 2;
|
return 2;
|
||||||
case PKT_REJECT:
|
case PKT_REJECT:
|
||||||
if (size < 10 || mesg[9] > _REJECT_LAST) {
|
if (size < 10 || mesg[9] > _REJECT_LAST) {
|
||||||
@ -716,14 +696,13 @@ void send_quit() {
|
|||||||
int size;
|
int size;
|
||||||
|
|
||||||
*regpacket = PKT_QUIT;
|
*regpacket = PKT_QUIT;
|
||||||
write_unique(regpacket+1);
|
write_unique(regpacket + 1);
|
||||||
now=longtime();
|
now = longtime();
|
||||||
while(longtime()-now<10) {
|
while (longtime() - now < 10) {
|
||||||
putmsg(&mastername,regpacket,5);
|
putmsg(&mastername, regpacket, 5);
|
||||||
size=getmsg(1000);
|
size = getmsg(1000);
|
||||||
if(size<6) continue;
|
if (size < 6) continue;
|
||||||
if(mesg[0] != PKT_ACK || mesg[1] != PKT_QUIT) continue;
|
if (mesg[0] != PKT_ACK || mesg[1] != PKT_QUIT) continue;
|
||||||
if (isvalidunique(mesg+2))
|
if (isvalidunique(mesg + 2)) break;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,13 +1,11 @@
|
|||||||
#ifndef NETWORK_H
|
#ifndef NETWORK_H
|
||||||
#define NETWORK_H
|
#define NETWORK_H
|
||||||
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
enum {
|
enum { MAXNETNODES = 8 };
|
||||||
MAXNETNODES = 8
|
|
||||||
};
|
|
||||||
|
|
||||||
struct netnode {
|
struct netnode {
|
||||||
struct sockaddr_in netname;
|
struct sockaddr_in netname;
|
||||||
@ -22,7 +20,7 @@ extern struct netnode netnodes[MAXNETNODES];
|
|||||||
void getsocket(void);
|
void getsocket(void);
|
||||||
void freesocket(void);
|
void freesocket(void);
|
||||||
|
|
||||||
int send_join(struct sockaddr_in *netname, char playername[16]);
|
int send_join(struct sockaddr_in* netname, char playername[16]);
|
||||||
void send_config();
|
void send_config();
|
||||||
void send_quit();
|
void send_quit();
|
||||||
int scaninvite(int msec);
|
int scaninvite(int msec);
|
||||||
@ -45,8 +43,8 @@ int networktraffic(void);
|
|||||||
|
|
||||||
extern int mydatacount;
|
extern int mydatacount;
|
||||||
extern int myslot;
|
extern int myslot;
|
||||||
extern int actionput,actioncount;
|
extern int actionput, actioncount;
|
||||||
extern unsigned char actionblock[ACTIONHIST*MAXNETNODES];
|
extern unsigned char actionblock[ACTIONHIST * MAXNETNODES];
|
||||||
|
|
||||||
extern int myaction;
|
extern int myaction;
|
||||||
extern unsigned char actions[MAXNETNODES];
|
extern unsigned char actions[MAXNETNODES];
|
179
src/sound.c
Normal file
179
src/sound.c
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
#include <SDL_audio.h>
|
||||||
|
#include <SDL_error.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "sound.h"
|
||||||
|
|
||||||
|
#ifndef DATADIR
|
||||||
|
#define DATADIR "data"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int sound_enabled = 1;
|
||||||
|
|
||||||
|
static char dirlist[] = DATADIR;
|
||||||
|
|
||||||
|
static int readsound(int num);
|
||||||
|
|
||||||
|
#define NUMSOUNDS ((int) (sizeof(soundnames) / sizeof(char*)))
|
||||||
|
#define MIXMAX 16
|
||||||
|
|
||||||
|
#define SOUND_QUIET -1
|
||||||
|
|
||||||
|
static const char* soundnames[] = {
|
||||||
|
"bomb1.raw",
|
||||||
|
"power1.raw",
|
||||||
|
"death.raw",
|
||||||
|
"drop.raw",
|
||||||
|
"bomb2.raw",
|
||||||
|
"power2.raw",
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct sample {
|
||||||
|
char* data;
|
||||||
|
int len;
|
||||||
|
} sample;
|
||||||
|
|
||||||
|
#define SNDFRAGMENT 1024
|
||||||
|
|
||||||
|
static sample samples[NUMSOUNDS];
|
||||||
|
|
||||||
|
static int soundworking = 0;
|
||||||
|
static int fragment;
|
||||||
|
// static int soundwrite,soundread;
|
||||||
|
static int* soundbuffer;
|
||||||
|
static int soundbufferlen;
|
||||||
|
static unsigned char sndclip[8192];
|
||||||
|
|
||||||
|
#define MAXSOUNDCOMMANDS 32
|
||||||
|
static char soundcommands[MAXSOUNDCOMMANDS];
|
||||||
|
static int soundtake, soundput;
|
||||||
|
|
||||||
|
static int sndplaying[MIXMAX], sndposition[MIXMAX];
|
||||||
|
static void fillaudio(void* udata, Uint8* buffer, int len) {
|
||||||
|
char com, *p;
|
||||||
|
int i, j, *ip;
|
||||||
|
int which;
|
||||||
|
(void) udata;
|
||||||
|
|
||||||
|
while (soundtake != soundput) {
|
||||||
|
com = soundcommands[soundtake];
|
||||||
|
soundtake = (soundtake + 1) & (MAXSOUNDCOMMANDS - 1);
|
||||||
|
if (com == SOUND_QUIET) {
|
||||||
|
memset(sndposition, 0, sizeof(sndposition));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (com < NUMSOUNDS) {
|
||||||
|
for (i = 0; i < MIXMAX; ++i)
|
||||||
|
if (!sndposition[i]) {
|
||||||
|
sndposition[i] = 1;
|
||||||
|
sndplaying[i] = com;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
memset(soundbuffer, 0, soundbufferlen);
|
||||||
|
for (i = 0; i < MIXMAX; ++i) {
|
||||||
|
if (!sndposition[i]) continue;
|
||||||
|
which = sndplaying[i];
|
||||||
|
if (sndposition[i] == samples[which].len) {
|
||||||
|
sndposition[i] = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
p = samples[which].data;
|
||||||
|
if (!p) continue;
|
||||||
|
p += len * (sndposition[i]++ - 1);
|
||||||
|
ip = soundbuffer;
|
||||||
|
j = len;
|
||||||
|
while (j--) *ip++ += *p++;
|
||||||
|
}
|
||||||
|
j = len;
|
||||||
|
ip = soundbuffer;
|
||||||
|
;
|
||||||
|
while (j--) *buffer++ = sndclip[4096 + *ip++];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int soundopen(void) {
|
||||||
|
SDL_AudioSpec wanted;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
soundtake = soundput = 0;
|
||||||
|
memset(sndposition, 0, sizeof(sndposition));
|
||||||
|
memset(sndplaying, 0, sizeof(sndplaying));
|
||||||
|
fragment = SNDFRAGMENT << 1;
|
||||||
|
soundbufferlen = fragment * sizeof(int);
|
||||||
|
soundbuffer = malloc(soundbufferlen);
|
||||||
|
if (!soundbuffer) return -2;
|
||||||
|
|
||||||
|
memset(&wanted, 0, sizeof(wanted));
|
||||||
|
wanted.freq = 22050;
|
||||||
|
wanted.channels = 2;
|
||||||
|
wanted.format = AUDIO_U8;
|
||||||
|
wanted.samples = fragment >> 1;
|
||||||
|
wanted.callback = fillaudio;
|
||||||
|
wanted.userdata = 0;
|
||||||
|
|
||||||
|
if (SDL_OpenAudio(&wanted, 0) < 0) {
|
||||||
|
fprintf(stderr, "Couldn't open audio: %s\n", SDL_GetError());
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
soundworking = 1;
|
||||||
|
|
||||||
|
for (i = 0; i < 8192; i++) {
|
||||||
|
j = i - 4096;
|
||||||
|
sndclip[i] = j > 127 ? 255 : (j < -128 ? 0 : j + 128);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < NUMSOUNDS; ++i) readsound(i);
|
||||||
|
|
||||||
|
SDL_PauseAudio(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
void soundclose(void) {
|
||||||
|
if (soundworking) {
|
||||||
|
SDL_CloseAudio();
|
||||||
|
soundworking = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int readsound(int num) {
|
||||||
|
char name[256], *p1, *p2, ch;
|
||||||
|
int file, size, len;
|
||||||
|
p1 = dirlist;
|
||||||
|
for (;;) {
|
||||||
|
p2 = name;
|
||||||
|
while (*p1 && (ch = *p1++) != ',') *p2++ = ch;
|
||||||
|
if (p2 > name && p2[-1] != '/') *p2++ = '/';
|
||||||
|
strcpy(p2, soundnames[num]);
|
||||||
|
file = open(name, O_RDONLY);
|
||||||
|
if (file >= 0) break;
|
||||||
|
if (!*p1) {
|
||||||
|
samples[num].len = -1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
size = lseek(file, 0, SEEK_END);
|
||||||
|
lseek(file, 0, SEEK_SET);
|
||||||
|
len = samples[num].len = (size + fragment - 1) / fragment;
|
||||||
|
len *= fragment;
|
||||||
|
p1 = samples[num].data = malloc(len);
|
||||||
|
if (p1) {
|
||||||
|
read(file, p1, size);
|
||||||
|
if (len - size) memset(p1 + size, 0, len - size);
|
||||||
|
while (size--) *p1++ ^= 0x80;
|
||||||
|
} else
|
||||||
|
samples[num].data = 0;
|
||||||
|
close(file);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void playsound(int n) {
|
||||||
|
if (sound_enabled) {
|
||||||
|
soundcommands[soundput] = n;
|
||||||
|
soundput = (soundput + 1) & (MAXSOUNDCOMMANDS - 1);
|
||||||
|
}
|
||||||
|
}
|
@ -1,17 +1,17 @@
|
|||||||
|
|
||||||
#include "bomber.h"
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
#include "bomber.h"
|
||||||
#include "gfx.h"
|
#include "gfx.h"
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/stat.h>
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/types.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
int volatile hc=0;
|
int volatile hc = 0;
|
||||||
char volatile interrupted=0;
|
char volatile interrupted = 0;
|
||||||
static Uint32 cur_unique;
|
static Uint32 cur_unique;
|
||||||
Uint32 network_unique;
|
Uint32 network_unique;
|
||||||
|
|
||||||
@ -20,12 +20,12 @@ Uint32 gtime(void) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Uint32 longtime(void) {
|
Uint32 longtime(void) {
|
||||||
return gtime()/1000;
|
return gtime() / 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* surf random generator: x (Daniel J. Bernstein) */
|
/* surf random generator: x (Daniel J. Bernstein) */
|
||||||
#define ROT(x, b) (((x) << (b)) | ((x) >> (32-(b))))
|
#define ROT(x, b) (((x) << (b)) | ((x) >> (32 - (b))))
|
||||||
#define MUSH(i, b) x = t[i] += (((x ^ seed[i]) + sum) ^ ROT(x,b))
|
#define MUSH(i, b) x = t[i] += (((x ^ seed[i]) + sum) ^ ROT(x, b))
|
||||||
static void surf(Uint32 out[8], const Uint32 in[12], const Uint32 seed[32]) {
|
static void surf(Uint32 out[8], const Uint32 in[12], const Uint32 seed[32]) {
|
||||||
Uint32 t[12], x, sum = 0;
|
Uint32 t[12], x, sum = 0;
|
||||||
int r, i, loop;
|
int r, i, loop;
|
||||||
@ -35,11 +35,20 @@ static void surf(Uint32 out[8], const Uint32 in[12], const Uint32 seed[32]) {
|
|||||||
for (loop = 0; loop < 2; ++loop) {
|
for (loop = 0; loop < 2; ++loop) {
|
||||||
for (r = 0; r < 16; ++r) {
|
for (r = 0; r < 16; ++r) {
|
||||||
sum += 0x9e3779b9;
|
sum += 0x9e3779b9;
|
||||||
MUSH(0, 5); MUSH(1, 7); MUSH(2, 9); MUSH(3, 13);
|
MUSH(0, 5);
|
||||||
MUSH(4, 5); MUSH(5, 7); MUSH(6, 9); MUSH(7, 13);
|
MUSH(1, 7);
|
||||||
MUSH(8, 5); MUSH(9, 7); MUSH(10, 9); MUSH(11, 13);
|
MUSH(2, 9);
|
||||||
|
MUSH(3, 13);
|
||||||
|
MUSH(4, 5);
|
||||||
|
MUSH(5, 7);
|
||||||
|
MUSH(6, 9);
|
||||||
|
MUSH(7, 13);
|
||||||
|
MUSH(8, 5);
|
||||||
|
MUSH(9, 7);
|
||||||
|
MUSH(10, 9);
|
||||||
|
MUSH(11, 13);
|
||||||
}
|
}
|
||||||
for (i = 0; i < 8; ++i) out[i] ^= t[i+4];
|
for (i = 0; i < 8; ++i) out[i] ^= t[i + 4];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#undef ROT
|
#undef ROT
|
||||||
@ -62,10 +71,14 @@ static Uint32 surf_init(void) {
|
|||||||
if (-1 == fd) {
|
if (-1 == fd) {
|
||||||
Uint32 genseed[4][8];
|
Uint32 genseed[4][8];
|
||||||
surf_seed[0] = surf_seed[1] = gtime();
|
surf_seed[0] = surf_seed[1] = gtime();
|
||||||
surf_in[0]++; surf(genseed[0], surf_in, surf_seed);
|
surf_in[0]++;
|
||||||
surf_in[0]++; surf(genseed[1], surf_in, surf_seed);
|
surf(genseed[0], surf_in, surf_seed);
|
||||||
surf_in[0]++; surf(genseed[2], surf_in, surf_seed);
|
surf_in[0]++;
|
||||||
surf_in[0]++; surf(genseed[3], surf_in, surf_seed);
|
surf(genseed[1], surf_in, surf_seed);
|
||||||
|
surf_in[0]++;
|
||||||
|
surf(genseed[2], surf_in, surf_seed);
|
||||||
|
surf_in[0]++;
|
||||||
|
surf(genseed[3], surf_in, surf_seed);
|
||||||
memcpy(surf_seed, genseed[0], 32);
|
memcpy(surf_seed, genseed[0], 32);
|
||||||
memcpy(surf_seed, genseed[1], 32);
|
memcpy(surf_seed, genseed[1], 32);
|
||||||
memcpy(surf_seed, genseed[2], 32);
|
memcpy(surf_seed, genseed[2], 32);
|
||||||
@ -86,14 +99,15 @@ static Uint32 surf_init(void) {
|
|||||||
static Uint32 surf_random(void) {
|
static Uint32 surf_random(void) {
|
||||||
if (surf_left == 0) {
|
if (surf_left == 0) {
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; (i < 12) && !(++surf_in[i]); i++) ;
|
for (i = 0; (i < 12) && !(++surf_in[i]); i++)
|
||||||
|
;
|
||||||
surf_left = 8;
|
surf_left = 8;
|
||||||
surf(surf_out, surf_in, surf_seed);
|
surf(surf_out, surf_in, surf_seed);
|
||||||
}
|
}
|
||||||
return surf_out[--surf_left];
|
return surf_out[--surf_left];
|
||||||
}
|
}
|
||||||
|
|
||||||
void read_seed_unique(unsigned char *buf) {
|
void read_seed_unique(unsigned char* buf) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
memset(surf_in, 0, sizeof(surf_in));
|
memset(surf_in, 0, sizeof(surf_in));
|
||||||
@ -101,12 +115,12 @@ void read_seed_unique(unsigned char *buf) {
|
|||||||
surf_left = 0;
|
surf_left = 0;
|
||||||
|
|
||||||
memcpy(&surf_seed, buf, sizeof(surf_seed));
|
memcpy(&surf_seed, buf, sizeof(surf_seed));
|
||||||
memcpy(&network_unique, buf+sizeof(surf_seed), sizeof(network_unique));
|
memcpy(&network_unique, buf + sizeof(surf_seed), sizeof(network_unique));
|
||||||
cur_unique = ntohl(network_unique);
|
cur_unique = ntohl(network_unique);
|
||||||
for (i = 0; i < 32; i++) surf_seed[i] = ntohl(surf_seed[i]);
|
for (i = 0; i < 32; i++) surf_seed[i] = ntohl(surf_seed[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned char* write_seed_unique(unsigned char *buf) {
|
unsigned char* write_seed_unique(unsigned char* buf) {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < 32; i++) {
|
for (i = 0; i < 32; i++) {
|
||||||
@ -200,34 +214,34 @@ Uint32 get_unique(void) {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void nomem(char *str) {
|
void nomem(char* str) {
|
||||||
printf("No memory!!![%s]\n",str);
|
printf("No memory!!![%s]\n", str);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int mypause(void) {
|
int mypause(void) {
|
||||||
while(!interrupted) {
|
while (!interrupted) {
|
||||||
pollinput();
|
pollinput();
|
||||||
SDL_Delay(1);
|
SDL_Delay(1);
|
||||||
}
|
}
|
||||||
interrupted=0;
|
interrupted = 0;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Uint32 sdlhandler(Uint32 time) {
|
static Uint32 sdlhandler(Uint32 time) {
|
||||||
#if defined (SDL_LATENCY)
|
#if defined(SDL_LATENCY)
|
||||||
outmsgs();
|
outmsgs();
|
||||||
#endif
|
#endif
|
||||||
interrupted=1;
|
interrupted = 1;
|
||||||
hc++;
|
hc++;
|
||||||
return time;
|
return time;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pulseon(void) {
|
void pulseon(void) {
|
||||||
SDL_SetTimer(40,sdlhandler);
|
SDL_SetTimer(40, sdlhandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
void hexdump(unsigned char *p, int len) {
|
void hexdump(unsigned char* p, int len) {
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i < len; i++) {
|
for (i = 0; i < len; i++) {
|
||||||
if (15 == len % 16)
|
if (15 == len % 16)
|
||||||
@ -235,6 +249,5 @@ void hexdump(unsigned char *p, int len) {
|
|||||||
else
|
else
|
||||||
fprintf(stderr, "0x%X ", p[i]);
|
fprintf(stderr, "0x%X ", p[i]);
|
||||||
}
|
}
|
||||||
if (i % 16)
|
if (i % 16) fprintf(stderr, "\n");
|
||||||
fprintf(stderr, "\n");
|
|
||||||
}
|
}
|
@ -1,6 +1,8 @@
|
|||||||
#ifndef UTILS_H
|
#ifndef UTILS_H
|
||||||
#define UTILS_H
|
#define UTILS_H
|
||||||
|
|
||||||
|
#include <SDL.h>
|
||||||
|
|
||||||
Uint32 gtime(void);
|
Uint32 gtime(void);
|
||||||
Uint32 longtime(void);
|
Uint32 longtime(void);
|
||||||
|
|
||||||
@ -10,21 +12,21 @@ void set_unique(Uint32 unique);
|
|||||||
Uint32 get_unique(void);
|
Uint32 get_unique(void);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define SEED_UNIQUE_SIZE (32*4+4)
|
#define SEED_UNIQUE_SIZE (32 * 4 + 4)
|
||||||
void read_seed_unique(unsigned char *buf);
|
void read_seed_unique(unsigned char* buf);
|
||||||
unsigned char* write_seed_unique(unsigned char *buf);
|
unsigned char* write_seed_unique(unsigned char* buf);
|
||||||
void create_seed_unique(void);
|
void create_seed_unique(void);
|
||||||
|
|
||||||
extern Uint32 network_unique;
|
extern Uint32 network_unique;
|
||||||
|
|
||||||
int myrand(void);
|
int myrand(void);
|
||||||
|
|
||||||
void nomem(char *str);
|
void nomem(char* str);
|
||||||
|
|
||||||
int mypause(void);
|
int mypause(void);
|
||||||
void pulseon(void);
|
void pulseon(void);
|
||||||
|
|
||||||
void hexdump(unsigned char *p, int len);
|
void hexdump(unsigned char* p, int len);
|
||||||
|
|
||||||
extern volatile int hc;
|
extern volatile int hc;
|
||||||
extern volatile char interrupted;
|
extern volatile char interrupted;
|
Loading…
Reference in New Issue
Block a user