/* asylum.c */ /* Copyright Hugh Robinson 2006-2007. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include #include char keyboard[512]; int keybuf; int mouse; int installed; #define ESC_VALUE 27 #ifndef RESOURCEPATH #define RESOURCEPATH "/usr/share/games/asylum" #endif #ifndef SCOREPATH #define SCOREPATH "/var/games/asylum" #endif #define random rand const double PI=3.1415926535897932384626433832795028841971; #define _firstzone 0; #define STOREAREALEN (16*0x40000) char storearea[STOREAREALEN]; SDL_Surface* ArcScreen; SDL_Surface* DecompScreen; const char _platblim=64; const char _blim=112; const char _bomblowlim=64, _bombhighlim=79; const char _boobylowlim=76, _boobyhighlim=79; const char _gaslowlim=54, _gashighlim=55; const char _animlowlim=54, _animhighlim=63; const char _eleclowlim=56, _elecvertlowlim=60, _elechighlim=63; const char _translowlim=54, _transhighlim=63; const char _atomlowlim=72, _atomhighlim=75; const char _targetlowlim=80, _powertarget=84, _nuttertarget=88, _targethighlim=95; const char _teleplowlim=192, _telephighlim=199; const char _fuelairno=68; const char _neuronlowlim=40, _neuronhighlim=47; const char _bonuslow=16, _bonushigh=31, _megabonuslim=35; const char _starsno=15; const char _markerno=255; const int _xofs=159, _yofs=96; const char _platbase=2, _platno=176, _platlowlim=176, _plathighlim=190, _alplathighlim=177; const char _weaplowlim=96, _weaphighlim=111; const char _triggerlim=193; const char _crumblelowlim=160, _crumblehighlim=167; const char _crumblestandlowlim=168, _crumblestandhighlim=175; const char _spcrumblelowlim=140, _spcrumblehighlim=143; const char _extendno=152; const char _solidlowlim=128, _solidhighlim=131; const char _shutdownno=200; const char _mpmgblamno=8, _rocketblamno=16; const int _windowxsize=160<<8, _windowysize=112<<8; //alentlen=32 #define _speedlim (15<<8) #define _windspeed (1<<8) #define xlowlim 0 #define ylowlim (15<<8) #define _lowx 16 #define _lowy 8 #define _highx 304 #define _highy 200 #define _neuronstoget 8 #define _expwidth (24<<8) #define _expheight (24<<8) #define _alheight (32<<8) #define _alwidth (16<<8) #define backsize 48*60*8 int fsplx, fsply, fsphx, fsphy; #define _boxwidth 20 #define _boxheight 16 #define targetscore 500 #define _sleeprange (512<<8) #define _firerange (128<<8) #define _charwidth 16 #define _alno 0x200 #define _projno 32 #define _bulno 64 //projentlen=24 //bulentlen=24 #define _rockettablen 192 #define _strengthmax (108<<8) #define spstrengthmax (_strengthmax-(1<<8)) #define _strengthinit (108<<8) #define _strengthxofs 108 #define _strengthyofs 239 #define _bonusxplace 34 #define _bonusyplace 232 #define _scorexofs (160-(16*7)/2) #define _scoreyofs 220 #define bombloss (4<<8) #define atomloss (32<<8) #define _explocontloss (1<<7) #define bulletloss (2<<8) #define _fuelairduration 0x18 #define _plheight (32<<8) #define _plwidth (16<<8) // alien object types #define _Explo (1) #define _Ember (2) #define _Platbase (3) #define _Riseplat (_Platbase) #define _Exploplat (_Platbase+1) #define _Updownplat (_Platbase+2) #define _Downplat (_Platbase+3) #define _Fastplat (_Platbase+4) #define _Fastplatstop (_Platbase+5) #define _Fastplatexplo (_Platbase+6) #define _Fastplatfire (_Platbase+7) #define _Fallplat (_Platbase+8) #define _Scoreobj (12) #define _Dyingbonus (13) #define _Flyingbonus (14) #define _Booby (15) #define _Decoration (16) #define _Extender (17) #define _Alien1 (18) typedef struct fastspr_sprite { int x; int y; SDL_Surface* s;} fastspr_sprite; #define _boardhdrlen 32 typedef struct board { int first_int; int width; int height; int fourth; int fifth; int sixth; int seventh; int eighth; char contents[65536]; } board; //alofs=&F00 //colchofs=&5000 // two tables #define _colchlim 0x400 //bulcolchofs=&7000 #define _bulcolchlim 0x400 typedef struct alent { int type; int x; int y; int dx; int dy; int r5; int r6; int foo; } alent; alent alofs[_alno]; typedef struct colchent { alent* r0; int xmin; int ymin; int xmax; int ymax; } colchent; colchent colchofs[2*_colchlim]; typedef struct bulcolchent { alent* r0; int xmin; int ymin; int xmax; int ymax; } bulcolchent; bulcolchent bulcolchofs[_bulcolchlim]; #define _fueltablim 0x3c0 char* fueltabofs[2][_fueltablim]; // &8000 // don't forget there's two of these #define _projlim 0x1000 typedef struct projent { int type; int x; int y; int dx; int dy; int flags; } projent; projent projofs[_projlim]; #define _bullim 0x1000 typedef struct bulent { int type; int x; int y; int dx; int dy; int flags; } bulent; bulent bulofs[_bullim]; //bulofs=&9900 //soundtabofs=&A900:REM length 8*16 #define _savearealen (0x9c0/32) alent saveareaalents[_savearealen+1]; // &C000 int saveareaints[8]; char highscorearea[13*5+1];//=&D000 char wipescrst[128*16*4];//=&D100 /*soundtabvol=0 soundtabsample=1 soundtabpitchmsb=2 soundtabpitchlsb=3 soundtabvolslide=4 soundtabpitchslide=8 soundtabctr=12 soundtabstereo=13 soundentlen=16 soundtabshift=4*/ #define _soundentlen 16 #define _textno 32 #define _textlen (20+60) // was 24 but I deref'd the string typedef struct textinfo { int count; int x; int y; int dx; int dy; char text[60]; } textinfo; textinfo texttabofs[_textno]; //&AA00 #define _SampJump 1 #define _SampBonus 2 #define _SampExplo 3 #define _SampAtomExplo 4 #define _SampCannon 5 #define _SampRocket 6 #define _SampHiss 7 #define _SampStunned 8 #define _Sampsmallzap 9 #define _Sampbigzap 10 #define _Samporgan 16 #define _Samprave 19 #define _projsmallno 54 #define _bulspritebase 16 #define _funnyfacesprbase 66 #define _scoresprbase 16 #define _rocketspriteno 32 #define _rocketspritelim 41 #define _skelspriteno 46 #define _starssprbase 58 #define _deadsprbase 70 #define _rockbase 9 #define _mpmgbase 1 #define _Playerchannel 0 #define _Explochannel 3 #define _Firechannel 1 #define _Sparechannel 2 Mix_Chunk* CHUNK_BULLET_1; Mix_Chunk* CHUNK_BULLET_2; Mix_Chunk* CHUNK_BULLET_3; Mix_Chunk* CHUNK_ELEC_1; Mix_Chunk* CHUNK_ELEC_2; Mix_Chunk* CHUNK_ELEC_3; Mix_Chunk* CHUNK_EXPLO; Mix_Chunk* CHUNK_ATOM; Mix_Chunk* CHUNK_SPINFIRE; Mix_Chunk* CHUNK_SPINPOWERFIRE; Mix_Chunk* CHUNK_SHOOT; Mix_Chunk* CHUNK_SHOOTNUTTER; Mix_Chunk* CHUNK_JUMP; Mix_Chunk* CHUNK_SHUTDOWN_1; Mix_Chunk* CHUNK_SHUTDOWN_2; Mix_Chunk* CHUNK_SHUTDOWN_3; Mix_Chunk* CHUNK_TELEP_1; Mix_Chunk* CHUNK_TELEP_2; Mix_Chunk* CHUNK_TELEP_3; Mix_Chunk* CHUNK_BLAM; Mix_Chunk* CHUNK_FIRE; Mix_Chunk* CHUNK_BLAMFIRE; Mix_Chunk* CHUNK_ROCKET; Mix_Chunk* CHUNK_WEAPON_1; Mix_Chunk* CHUNK_WEAPON_2; Mix_Chunk* CHUNK_WEAPON_3; Mix_Chunk* CHUNK_WEAPON_4; Mix_Chunk* CHUNK_FUELAIR; Mix_Chunk* CHUNK_OBJGOT[12]; Mix_Chunk* CHUNK_BONUS_1; Mix_Chunk* CHUNK_BONUS_2; Mix_Chunk* CHUNK_STUNNED[17]; char bank, plframe, plface, fire; char jumping, falling; char plotal, masterplotal; char uppress, downpress, leftpress, rightpress; // word-aligned char lefthit, righthit, uphit, downhit; // word-aligned char recheck, pluphit, atombombctr, frameinc, firerate; char plfired, plweapontype, plweaponspeed; char rocketflag, electrocuting, alonplat, platuphit; char colchecktype, colchplace, alonobj, rate50, bonusctr; uint16_t bonusreplot; char keypressed, blamctr, rocketblamctr, plotterofs, hiddenplatctr, extending; char charsok, arm3, gameon, savestart; int leftkey, rightkey, upkey, downkey, firekey; char soundtype, soundquality, explospeed, gearchange; char fullscreen, sound_available; char soundvol, musicvol, joyno, mentalzone, saveend, savedornot; char bonusstore, plweaponstore; char hstindex, idpermit, cheatpermit; char initials[3]; // consecutive after o=64 board *boardadr; fastspr_sprite blokeadr[77]; fastspr_sprite blockadr[256]; char* tmp_blockadr; void **fspvars; //void *fspplot; char* backadr; char* backuse; int framectr; int boardwidth; int xtemp; int ytemp; board *brainadr; board *neuronadr; int fspareat; colchent* colchtab; colchent* colchptr; int* platsandstr; fastspr_sprite exploadr[32]; char** fueltabread; char** fueltabwrite; int fueltabctr; int fuelexploctr; //lifeseed1=o+88 //lifeseed2=o+92 Uint32* strengthcoltab; int laststrengthframe; int cliplx; int cliply; int cliphx; int cliphy; int snuffctr; fastspr_sprite charsadr[48]; int* addtabadr; char* screennotuse; //int rnseed; projent* projadr; int projctr; int firelastframe; int fullpitch=0x2155; int rocketctr; int* rockettabadr; alent* aladr; int alctr; int fuelairlastframe; int shutdownctr; char* currentpath; bulent* buladr; int bulctr; int xposmax; int yposmax; fastspr_sprite alspradr[256]; int platypos; colchent* oldcolchtab; colchent* oldcolchptr; colchent* colchadr; colchent* colchtabuse; colchent* colchptruse; alent* dodgypointer; bulcolchent* bulcolchtab; bulcolchent* bulcolchptr; int laststrength; int currentzone; int telepctr; int telepxpos; int telepypos; int bonusxpos; int bonusypos; int bonustimer; int sprlx; int sprly; int sprhx; int sprhy; int lagerctr; char *boardlowlim, *boardhighlim; char* storage; char* storageend; char* gamescreenadr; char* chatscreenadr; int windctr; int xmode; // consecutive words after vdu=&300 char *screenstart; int modesize, hbytes; char *screenuse, *screentop; // consecutive words after pl=&340 int xpos, ypos, initplx, initply, hvec, vvec; char *pladr1, *pladr2, *pladr3, *pladr4, *pladr5, *pladr6, *pladr7, *pladr8; int pllx, plly, plhx, plhy; char plscore[8]; // plscore=pl+72:REM Two words int plscoreadd, plzone, pltophit, plstrength, lives, neuronctr; #include "asylum.h" void init() { storage=storearea; storageend=storearea+STOREAREALEN; xmode=15; gethandlers(); // SWI "FastSpr_GetAddress"; // set up fspplot, fspvars, fspareat=fspvars+24 colchadr=colchofs; bulcolchtab=bulcolchofs; vduread(); swi_removecursors(); bank=1; switchbank() ;//set up bank variables switchfspbank(); switchbank() ;//set up bank variables switchfspbank(); checkifarm3(); if (getfiles()) abort_game(); setdefaults(); loadconfig(); vduread(); // set screen size from options scorezero(); for (prelude()&&abort_game(); ; ) { playloop: osbyte_7c(); if (options(0)) // not in game {abort_game(); return;} if (getlevelfiles()) {notgotlevel: if (1) abort_game(); // or, depending on what getlevelfiles() returned continue;} swi_bodgemusic_stop(); if (game()) continue; if (neuronctr>=_neuronstoget) { zonedone: if (idpermit!=1) permitid(); swi_bodgemusic_start(1,0); // ?? (3,0) in original } else // was "else if overflow clear" { if (soundtype==2) swi_bodgemusic_start(2,0); swi_sound_qtempo(0x980); swi_bodgemusic_volume(musicvol); } showhighscore(); } } int abort_game() { swi_bodgemusic_stop(); losehandlers(); osbyte_7c(); SDL_Quit(); exit(0); } char endmes[] = "Game exited cleanly"; int game() { wipetexttab(); setup(); switchcolch(); //setup colch vars startmessage(); findplayer(); getarms(); if (cheatpermit==1) zonecheatread(); do { zonerestart: restartplayer(); do { mainrestart: showgamescreen(); if (soundtype==2) swi_bodgemusic_start((plzone!=0),0); swi_bodgemusic_volume(musicvol); frameinc=1; rate50=1; swi_blitz_wait(1); while (!swi_readescapestate()) {mainloop: if (plzone != currentzone) {switchzone: loadzone(); goto zonerestart;} //BL saveal //BL restoreal if ((char)rate50 != 1) { plmove(); bonuscheck(); fuelairproc(); switchcolch(); masterplotal=0; moval(); project(); bullets(); alfire(); wakeupal(); } rate50link: plmove(); bonuscheck(); fuelairproc(); mazeplot(); switchcolch(); masterplotal=1; if (snuffctr) playerplot(); moval(); project(); bullets(); alfire(); if (!snuffctr) playerplot(); bonusplot(); scoreadd(); showstrength(); texthandler(); seeifdead(); //makesounds(); wakeupal(); if (cheatpermit==1) cheatread(); scorewipe(); showscore(); if (xmode==49) swi_blitz_screenexpand(screenuse); frameinc=((gearchange==0)?2:1); swi_blitz_wait(frameinc); if ((rate50!=1)&&(frameinc<2)) //rate 25 but one frame passed { swi_blitz_wait(1); frameinc=2; rate50=1; } else if (frameinc>1) rate50=0; rateskip: framectr+=frameinc; switchbankins(); switchfspbank(); swi_blitz_smallretrieve(); if (snuffctr>=300) { playerdead: showgamescreen(); if (lives==0) return 0; lives--; if (lives>9) lives=9; prepstrength(); goto zonerestart; } } swi_bodgemusic_stop(); bonusreplot=4; if (escapehandler()) return 1; } while (1); } while (1); } void switchcolch() { oldcolchtab=colchtab; oldcolchptr=colchptr; colchplace=!colchplace; colchtab=colchptr=colchadr+(colchplace?0:_colchlim+16); //+16 for safety bulcolchptr=bulcolchtab; //reset bullet checking table } void switchbank() { if (xmode==49) swi_blitz_screenexpand(screenuse); switchbankins(); } void switchbankins() { bank^=3; osbyte_71(); // i.e. 0x71 swi_blitz_screenretrieve(); SDL_Flip(ArcScreen); screenuse=screenstart; screennotuse=screenstart; if (bank==1) screenuse=screenstart+modesize; else screennotuse=screenstart+modesize; } void switchfspbank() {swi_fastspr_screenbank(bank);} void bidforsoundforce(int r0,char r1,char r2,int r3,int r4,int r5,char r6,int r7,Mix_Chunk* chunk) { if (sound_available&&soundtype) { r0&=7; soundclaim(r0,r1,r2,r3,r4,r5,r6,r7,chunk); } } void bidforsound(int r0,char r1,char r2,int r3,int r4,int r5,char r6,int r7,Mix_Chunk* chunk) { if (sound_available&&soundtype) { r0&=7; //soundtab=soundtabofs+(r0<volumevolumevolumevolumevolumevolume0;r11++,r9--) { loopa6: if (r11->count==0) continue; textproc:; int r4=(frameinc>4)?4:frameinc; r11->count-=r4; if (r11->count<0) r11->count=0; for (;r4>0;r4--) { loopb1: r11->x += r11->dx; r11->y += r11->dy; } int XxX = r11->x>>8; int YyY = r11->y>>8; for (char* r10=r11->text;*r10!=0;r10++) { char r0; loopa7: r0=*r10; if ((*r10-1) < 48) // only plot known characters (charsadr is [48]) fspplot(charsadr,*r10-1,XxX,YyY); XxX+=14; if (*r10<=10) XxX+=2; if (*r10>43) XxX-=6; } } textdone:; //textdelete: r11->count = 0; } void startmessage() {message(1128,136,0,0,"Let's Go!");} void deathmessage() { message(72,208,0,-1,"§ Snuffed It! §"); if (lives==0) message(72,256,0,-1,"- GAME OVER -"); } void alfire() { int x = xpos + (((random()&15)+(random()&7)-11)<<12); int y = ypos + (((random()&15)-7)<<12); if (x<(1<<12)) return; if (y<(1<<12)) return; if (x>xposmax-(1<<12)) return; if (y>yposmax-(1<<12)) return; x &= ~0xfff; y &= ~0xfff; char* r0=translate(x,y); if ((*r0>=_targetlowlim)&&(*r0<=_targethighlim)) {foundtarget(x,y,*r0); return;} nofoundtarget: if ((r0[1]>=_targetlowlim)&&(r0[1]<=_targethighlim)) {foundtarget(x+(1<<12),y,r0[1]); return;} return; } void foundtarget(int x,int y,char target) { y+=16<<8; int dx=(xpos-x)>>6; int dy=((ypos+(12<<8))-y)>>6; // aim at body char* r0=translate(x+(8<<8)+(dx>>4),y-(8<<8)+(dy>>4)); if (*r0>_targethighlim) return; target&=~3; int r4=random()&7; if (r4==7) r4=6; if (target>=_powertarget) r4-=6; if (target==_powertarget) r4=8+(r4&2); if (target==_nuttertarget) r4=12+(r4&3); makebul(x,y,dx,dy,_bulspritebase+r4,1<<24); } int splittab[14]; void init_splittab() { for (int i=0;i<7;i++) { splittab[i*2] = (int)(0x200*sin((0.5+i)/3.5*PI)); splittab[i*2+1] = (int)(0x200*cos((0.5+i)/3.5*PI)); }} void bullets() // the bullet handler (aliens fire these) { bulent* r11 = buladr; int i; for (i=_bulno;i>0;i--,r11++) { loop71: if (r11->type==0) continue; foundbul: r11->x += r11->dx; r11->y += r11->dy; if ((r11->x<=xlowlim) || (xposmax<=r11->x) || (r11->y<=ylowlim) || (yposmax<=r11->y)) { // goto projoffscr r11->type=0; continue; } if ((r11->dx<=(1<<12)) && (-r11->dx<=(1<<12))) if (r11->flags & (1<<14)) { r11->dx += (r11->dx>>4); r11->dy += (r11->dy>>4); } bulnoacc: if ((r11->flags & (1<<13)) && (r11->flags <= (3<<22))) { int r6 = 1<<6; if (!(r11->flags & (1<<12))) { r6 = 1<<4; r11->dx -= (r11->dx>>5); r11->dy -= (r11->dy>>5); } r11->dx += (r11->xdy += (r11->ydx>_speedlim) r11->dx = _speedlim; if (r11->dx<-_speedlim) r11->dx = -_speedlim; if (r11->dy>_speedlim) r11->dy = _speedlim; if (r11->dy<-_speedlim) r11->dy = -_speedlim; r11->flags -= (1<<16); /* decrement the life counter */ if (r11->flags<0) { // out of time // goto buldestroy if ((r11->flags) & (1<<10)) goto bulsplit; r11->type = 0; continue; } if (!((r11->x<=pllx) || (plhx<=r11->x) || (r11->y<=plly) || (plhy<=r11->y))) { // goto bulletkill; bulletkill: r11->type=0; // goto causeexplobullet; int DX=r11->dx>>4, DY=r11->dy>>4; explogonopyroquiet(r11->x-r11->dx,r11->y-(8<<8)-r11->dy,DX+DY,DY-DX,0,DX+DY,0); explogonopyro(r11->x-r11->dx,r11->y-(8<<8)-r11->dy,DX-DY,DX+DY,0,DX-DY,0); continue; } { char r1=*fntranslate(r11->x,r11->y); if ((r1 >= 16) // hit a block // bulhit: && !((r1>=_translowlim) && (r1<=_transhighlim)) && !((r1>=_targetlowlim) && (r1<=_targethighlim))) ; else { bulhitins: if (masterplotal == 0) continue; int r0=(r11->type); if ((r0==_bulspritebase+8) || (r0==_bulspritebase+10)) r0 ^= (framectr & 4) >> 2; fspplot(exploadr,r0,((r11->x)>>8)-(xpos>>8)+_xofs,((r11->y)>>8)-(ypos>>8)+_yofs); continue; } } nobultarget: r11->type=0; bulnodestroy: if ((r11->flags && (1<<15))!=0) { // causeexplobullet: int DX=r11->dx>>4, DY=r11->dy>>4; explogonopyroquiet(r11->x-r11->dx,r11->y-(8<<8)-r11->dy,DX+DY,DY-DX,DX+DY,0,0); explogonopyro(r11->x-r11->dx,r11->y-(8<<8)-r11->dy,DX-DY,DX+DY,DX-DY,0,0); continue; } buldestroy: if ((r11->flags && (1<<10))==0) { r11->type = 0; continue; } bulsplit:; int newtype=(random()&7); if (newtype==7) newtype=0; int r7=r11->type; if (r7==_bulspritebase+13) newtype=7; if (r7==_bulspritebase+14) newtype=10; if (r7==_bulspritebase+15) newtype=12+(newtype&3); if (newtype==15) newtype=0; newtype+=_bulspritebase; for (int i=0;i<14;i+=2) { loop75: (void)makebul(r11->x,r11->y,(r11->dx>>2)+splittab[i],(r11->dy>>2)+splittab[i+1],newtype,(1<<22)); } r11->type=0; } } int makebul(int x,int y,int dx,int dy,int type,int flags) { int i; bulent* r10 = buladr; r10 += bulctr; for (i=bulctr;i<_bulno;i++,r10++) { loop72: if (r10->type==0) {bulctr=i; break;} } if (i==_bulno) { r10 = buladr; for (i=0;itype==0) {bulctr=i; break;} } if (i==bulctr) return 1; // failed } foundmakebul: if (flags<(1<<16)) flags |= (1<<22); if (type>=_bulspritebase+8) flags |= (9<<12); if (type>=_bulspritebase+12) flags = (1<<21) | (1<<10); if ((type==_bulspritebase+7)||(type==_bulspritebase+8)) flags |= (1<<13); if (type==_bulspritebase+10) flags |= (1<<14); r10->type = type; r10->x = x; r10->y = y; r10->dx = dx; r10->dy = dy; r10->flags = flags; bulctr = (bulctr+1) % _bulno; // loop68: // if (bulctr==0) return; // XXX why??? int r7 = (r10->x - xpos) >> 9; x=abs(r10->x - xpos); y=abs(r10->y - ypos); int vol = (0x7f - ((x+y)>>12)); if (vol>=80) { bidforsound(_Explochannel,(type>=_bulspritebase+8)?_Sampbigzap:_Sampsmallzap, (((vol&0x7f)>0x7c)?0x7c:(vol&0x7f))-((type==_bulspritebase+8)?0x10:0), (type==_bulspritebase+8)?(fullpitch+0x1800):(fullpitch+0x1000), 0,(fullpitch<<16)|(0xfe<<8),2,r7, // lifetime (frames) (type>_bulspritebase+8)?CHUNK_BULLET_3:(type==_bulspritebase+8)?CHUNK_BULLET_2:CHUNK_BULLET_1); } nozapsound:; } void project() // the projectile handler { int i = _projno; // get table length projent* r11 = projadr; for (;i>0;i--,r11++) { loop41: if (r11->type==0) continue; foundproj: r11->x+=r11->dx; r11->y+=r11->dy; if ((r11->x<=xlowlim)||(xposmax<=r11->x)||(r11->y<=ylowlim)||(yposmax<=r11->y)) { // goto projoffscr r11->type=0; continue; } if (r11->flags&(1<<15)) {r11->dx+=r11->dx>>4; r11->dy+=r11->dy>>4;} projnoacc: if (r11->dx>_speedlim) r11->dx=_speedlim; if (r11->dx<-_speedlim) r11->dx=-_speedlim; if (r11->dy>_speedlim) r11->dy=_speedlim; if (r11->dy<-_speedlim) r11->dy=-_speedlim; r11->flags-=1<<16; // decrement the life counter if (r11->flags<0) // out of time { projdestroy: if (r11->flags&(1<<10)) {projsplit(r11); continue;} projoffscr: r11->type=0; continue; } alent* rs=bulcolcheck(r11->x,r11->y); if (rs!=NULL) { projhital: if (r11->flags&(1<<15)) rs->r6 -= (bulletloss<<2); else rs->r6 -= bulletloss; r11->type=0; if (rs->r6>0) continue; int r0=rs->type; int r6=(random()&7)+((r0>=_Alien1)?(r0-_Alien1):0)+_bonuslow; if (r6>_bonushigh) r6=_bonushigh-3; if (r6<_bonuslow) r6=_bonuslow; makeobj(_Flyingbonus,r11->x,r11->y,r11->dx>>2,-(1<<10),(0x200<<16),r6); if (r11->flags & (1<<15)) causeexplo(r11); else causeexplonopyro(r11); continue; } char* r0=fntranslate(r11->x,r11->y); char r1=*r0; if ((r1<16)|| // projhit: // hit a block ((r1>=_translowlim)&&(r1<=_transhighlim)&&!(r11->flags&(1<<9)))) { projhitins: if (masterplotal==0) continue; fspplot(blokeadr,r11->type,_xofs+(r11->x>>8)-(xpos>>8),_yofs+(r11->y>>8)-(ypos>>8)); continue; } projhitcont: if ((r1>=_spcrumblelowlim)&&(r1<=_spcrumblehighlim)&&(plweapontype==5)) { *r0=0; explogo(r11->x,r11->y,0,0,0,0,0); } nospcrumble: r11->type=0; destroy(r0); if (r11->flags&(1<<9)) {atomrocket(r11,r0); continue;} if (r11->flags&(1<<11)) {causeexplonopyro(r11); continue;} if (r11->flags&(1<<15)) {causeexplo(r11); continue;} } } void atomrocket(projent* r11,char* r0) { char r1=*r0; /* switched r1 and r0 from ARM */ if ((r1>=_solidlowlim)&&(r1<=_solidhighlim)) {causeexplo(r11); return;} atomdest: if (((r1>=_eleclowlim)&&(r1<=_elechighlim)) ||((r1>=_targetlowlim)&&(r1<=_targethighlim))) { elecatom: elecdestroy(r0); } noelecatom2: if ((r1>=_neuronlowlim)&&(r1<=_neuronhighlim)) {causeexplo(r11); return;} notreasatom: *r0=0; causeexplo(r11); } void causeexplo(alent* r11) {explogomaybe(r11->x-r11->dx,r11->y-r11->dy-(8<<8),0,0,1,-1,0);} void causeexplo(projent* r11) {explogomaybe(r11->x-r11->dx,r11->y-r11->dy-(8<<8),0,0,1,-1,0);} void causeexplonopyro(alent* r11) {explogonopyro(r11->x-r11->dx,r11->y-r11->dy-(8<<8),0,0,1,-1,0);} void causeexplonopyro(projent* r11) {explogonopyro(r11->x-r11->dx,r11->y-r11->dy-(8<<8),0,0,1,-1,0);} int projsplittab[10]; void init_projsplittab() { for (int i=0;i<5;i++) { projsplittab[i*2] = (int)(0x40*(0.5-sin(i/4.0*PI))); projsplittab[i*2+1] = 0x100*(i-2); }} void projsplit(projent* r11) { int x=r11->x, y=r11->y, dx=(r11->dx)>>1, dy=(r11->dy)>>1; int flags=r11->flags; int* r10; int r9; if (flags&(1<<15)) {rocketsplit(r11); return;} int r7=r11->type, r4, r6; if (flags&(1<<14)) { r10=projsplittab; r9=5; r4=_projsmallno+1;} else { r10=projsplittab+2; r9=3; r4=_projsmallno;} if ((flags&(1<<13))==0) dx>>=1; if (flags&(1<<12)) { r4=_projsmallno+2; dx<<=2;} if (flags&(1<<11)) { r4=_projsmallno+3; r6=1<<15;} else r6=1<<22; for (;r9>0;r9--) { loop76: makeproj(x,y,dx+r10[0],dy+r10[1],r4,r6); r10+=2; } r11->type=0; } int rocketbursttab[10]; void init_rocketbursttab() { for (int i=0;i<5;i++) { rocketbursttab[i*2] = (int)(0x200*sin((0.5+i)/2.5*PI)); rocketbursttab[i*2+1] = (int)(0x200*cos((0.5+i)/2.5*PI)); }} void rocketsplit(projent* r11) { int x=r11->x, y=r11->y, dx=(r11->dx)>>3, dy=(r11->dy)>>3; int flags=r11->flags; if (flags&(1<<14)) {rocketpair(r11); return;} rocketburst:; int r5=(1<<22)|(1<<15)|(1<<11); int* r10=rocketbursttab; for (int r9=5;r9>0;r9--) { loop77: makeproj(x,y,dx+r10[0],dy+r10[1],_projsmallno+3,r5); r10+=2; } r11->type=0; causeexplonopyro(r11); } void rocketpair(projent* r11) { int x=r11->x, y=r11->y, dx=r11->dx, dy=r11->dy; int flags=r11->flags; int type=r11->type; int newflags=1<<22; if (flags&(1<<12)) newflags=(1<<20)|(5<<10); if (flags&(1<<13)) // continue splitting { newflags&=~(1<<22); newflags|=(1<<20)|(17<<10);} newflags|=(1<<15); int newtype=type-2; if (newtype<_rocketspriteno) newtype+=2; if (type&1) makeproj(x,y,dx-(dy>>2),dy+(dx>>2)-(dy>>4),newtype,newflags); else makeproj(x,y,dx+(dy>>2),dy-(dx>>2)+(dy>>4),newtype,newflags); newtype=type+2; if (newtype>_rocketspritelim) newtype-=2; if (type&1) makeproj(x,y,dx+(dy>>2),dy-(dx>>2)+(dy>>4),newtype,newflags); else makeproj(x,y,dx-(dy>>2),dy+(dx>>2)-(dy>>4),newtype,newflags); r11->type=0; } int makeproj(int x,int y,int dx,int dy,int type,int flags) { projent* r10=projadr+projctr; int r9=_projno-projctr; int r8=projctr; for (;r9>0;r9--) { loop42: if (r10->type==0) return foundmakeproj(r10,r8,x,y,dx,dy,type,flags); r10++; r8++; } r10=projadr; for (r9=projctr;r9>0;r9--) { loop43: if (r10->type==0) return foundmakeproj(r10,r8,x,y,dx,dy,type,flags); r10++; r8++; } return 1; } int foundmakeproj(projent* r10,int r8,int x,int y,int dx,int dy,int type,int flags) { if (flags<(1<<16)) flags|=(1<<22); r10->type=type; r10->x=x; r10->y=y; r10->dx=dx; r10->dy=dy; r10->flags=flags; for (r8++;r8>=_projno;r8-=_projno) { loop45:; } projctr=r8; return 0; } int softmakeobj(int r0,int r1,int r2,int r3,int r4,int r5,int r6) { alent* r10=aladr; int r9=_alno; if (alctr>=r9) alctr=0; r9-=alctr; if (r9<10) /* check 10 object spaces */ { alctr=0; r10=aladr; } else r10+=alctr; do { softloop: if (r10->type==0) return foundmakeal(r10,alctr,r0,r1,r2,r3,r4,r5,r6); r10++; alctr++; } while (--r9>0); return 1; } int makeobj(int r0,int r1,int r2,int r3,int r4,int r5,int r6) { int tmpalctr=alctr; alent* r10=aladr; int r9=_alno; if (tmpalctr>=r9) tmpalctr=0; r9-=tmpalctr; r10+=tmpalctr; do { loop52: if (r10->type==0) return foundmakeal(r10,tmpalctr,r0,r1,r2,r3,r4,r5,r6); r10++; tmpalctr++; } while (--r9>0); r10=aladr; r9=alctr; do { loop53: if (r10->type==0) return foundmakeal(r10,tmpalctr,r0,r1,r2,r3,r4,r5,r6); r10++; tmpalctr++; } while (--r9>0); return 1; } int foundmakeal(alent* r10,int newalctr,int r0,int r1,int r2,int r3,int r4,int r5,int r6) { r10->type=r0; r10->x=r1; r10->y=r2; r10->dx=r3; r10->dy=r4; r10->r5=r5; r10->r6=r6; alctr=newalctr+1; if (alctr>=_alno) alctr=0; return 0; } void seestars() { if (plstrength>=laststrength) { laststrength=plstrength; return; } laststrength-=1<<8; int r2, r1=(framectr>>1)&7; int r0=_starssprbase+r1; if ((r1&3)==0) r2=90+plotterofs; else if (r1>4) r2=89+plotterofs; else r2=91+plotterofs; fspplot(blokeadr,r0,160,r2); int r4=laststrength-plstrength; if (r4==0) return; if (electrocuting) { elecsound: bidforsound(_Playerchannel,_Samprave,0x7f,0x2000,(0xff)<<8,0,10,0,CHUNK_ELEC_1); bidforsound(_Firechannel,_Samprave,0x7f,0x2400,(0xff)<<8,0,10,127,CHUNK_ELEC_2); bidforsound(_Sparechannel,_Samprave,0x7f,0x2800,(0xff)<<8,0,10,-127,CHUNK_ELEC_3); } else bidforsound(_Playerchannel,_SampStunned,0x70,0x4000-((r4>0x1000)?0x1000:r4), 0,0,50,0,CHUNK_STUNNED[(r4>=0x1000)?16:((r4<0)?0:(r4>>8))]); } void seeifdead() { if ((plstrength>0)||(snuffctr>0)) return; snuffctr=1; makeobj(_Decoration,1<<8,(2<<8)-(12<<8),0,-(2<<8),_deadsprbase-3+(250<<16),24); makeobj(_Decoration,(1<<8)-(5<<8),2<<8,-(1<<8),-(3<<8),_deadsprbase+1+(250<<16),24); makeobj(_Decoration,(1<<8)+(6<<8),2<<8,1<<8,-(3<<8),_deadsprbase+2+(250<<16),24); deathmessage(); return; } void wipearea(int r0,int r1,int r2,int r3) { int ro=r1*hbytes; int rz=r3*hbytes; SDL_LockSurface(ArcScreen); char* r11=wipescrst; char* r10=screenuse+r0*4+ro-(rz>>1) /* R3 is a multiple of 2 */ -((r2*4)>>1);/* R2 is a multiple of 8 */ for (int r9=16;r9>0;r9--) { wipetest: memcpy(r10,r11,128*4); r11+=128*4; r10+=hbytes; } SDL_UnlockSurface(ArcScreen); } void wipearearead(int r0,int r1,int r2,int r3) { int ro=r1*hbytes; int rz=r3*hbytes; SDL_LockSurface(ArcScreen); char* r11=wipescrst; char* r10=screenuse+r0*4+ro-(rz>>1) /* R3 is a multiple of 2 */ -((r2*4)>>1);/* R2 is a multiple of 8 */ for (int r9=16;r9>0;r9--) { wipetest2: memcpy(r11,r10,128*4); r11+=128*4; r10+=hbytes; } SDL_UnlockSurface(ArcScreen); } void scorewipe() {wipearea(160,_scoreyofs,16*8,16);} void scorewiperead() {wipearearead(160,_scoreyofs,16*8,16);} void showscore() { releaseclip(); int i=0; int x=_scorexofs; int y=_scoreyofs; if (plscore[0]==0) { x+=_charwidth/2; i=1; if (plscore[1]==0) { x+=_charwidth/2; i=2; } } score10mil: /*r7=0*/; for (;i<8;i++) { loop36: if (plscore[i]<=10) { fspplot(charsadr,plscore[i],x,y); /*r8=1*/; } scoreskip: x+=_charwidth; } } void scoreadd() { if (!plscoreadd) return; char* r10=plscore; int* r11=addtabadr; for (int r6=8;r6>0;r6--) { int placeval=*(r11++); loop37: if (plscoreadd>=placeval) { char digit=0; if (plscoreadd>=(placeval<<3)) {digit+=8; plscoreadd-=(placeval<<3);} if (plscoreadd>=(placeval<<2)) {digit+=4; plscoreadd-=(placeval<<2);} if (plscoreadd>=(placeval<<1)) {digit+=2; plscoreadd-=(placeval<<1);} if (plscoreadd>=(placeval<<0)) {digit+=1; plscoreadd-=(placeval<<0);} *r10+=digit; } scoreaddskip: r10++; } char carry=0; for (int r6=8;r6>0;r6--) // now handle carries { loop38: r10--; *r10+=carry; if (*r10>=10) {*r10-=10; carry=1;} else carry=0; } } void showstrength() { SDL_LockSurface(ArcScreen); if (lagerctr!=0) { if ((lagerctr-=frameinc)<0) lagerctr=0; plstrength+=frameinc<<6; if (plstrength>_strengthinit) plstrength=_strengthinit; laststrength+=frameinc<<6; if (laststrength>_strengthinit) laststrength=_strengthinit; } nolager:; Uint32* r10=((Uint32*)screenuse)+_strengthxofs+(hbytes/4)*_strengthyofs; int r3=plstrength; if (r3>_strengthmax) r3=_strengthmax; if (r3<0) r3=0; r3>>=8; int r7=0; loop31: for (;r3>0;r3-=1) { Uint32* r4=r10; loop32: for (int r6=6;r6>0;r6--) { *r4=*(strengthcoltab+(random()&0x1f)); r4+=hbytes/4; } r10++; r7++; } writeblue: r10=((Uint32*)screenuse)+_strengthxofs+(hbytes/4)*_strengthyofs; r10+=(spstrengthmax>>8); if (framectr-laststrengthframe>2) laststrengthframe=framectr; loop35: for (;r7<=spstrengthmax>>8;) { Uint32* r4=r10; loop34: for (int r6=6;r6>0;r6--) { *r4=*(strengthcoltab+0x24+(random()&0x1f)); r4+=hbytes/4; } r10--; r7++; } int mask; writemaskedlife: mask=0; if (r3>=-3) mask+=0xff; if (r3>=-2) mask+=0xff00; if (r3>=-1) mask+=0xff0000; if (r3<0) { Uint32* r4=r10; for (int r6=6;r6>0;r6--) { loop33: *r4=(*(strengthcoltab+0x24+(random()&0x1f))&~mask)|((*r4)&mask); r4+=hbytes/4; } } SDL_UnlockSurface(ArcScreen); return; } void fuelairproc() { if (framectr>1)) return; fuelairlastframe=framectr; char **ftr, **ftw; ftr=fueltabread; fueltabread=ftw=fueltabwrite; fueltabwrite=ftr; if (--fueltabctr<0) {*ftw=0; return;} for (char** r7=ftw+_fueltablim;r7>ftw;) { loop22:; char* r8=*(ftr++); if (r8==NULL) {*ftw=0; return;} char r0=(*r8)&~1; if (r0!=_gaslowlim) skipfuelair: continue; char* r1=r8-1; if (*r1==0) {*r1=_gaslowlim; *(ftw++)=r1;} r1=r8+boardwidth; if (*r1==0) {*r1=_gaslowlim; *(ftw++)=r1;} r1=r8+1; if (*r1==0) {*r1=_gaslowlim; *(ftw++)=r1;} r1=r8-boardwidth; if (*r1==0) {*r1=_gaslowlim; *(ftw++)=r1;} } fuelprocdone: *ftw=0; } void explogonopyro(int r1,int r2,int r3,int r4,int r5,int r6,alent* r10) {explocreate(r1,r2,r3,r4,r5,r6,r10);} void explogonopyroquiet(int r1,int r2,int r3,int r4,int r5,int r6,alent* r10) {explocreatequiet(r1,r2,r3,r4,r5,r6,r10);} void explogoquiet(int r1,int r2,int r3,int r4,int r5,int r6,alent* r10) { explocreatequiet(r1,r2,r3,r4,r5,r6,r10); embercreate(r1,r2,r6); } void explogomaybe(int r1,int r2,int r3,int r4,int r5,int r6,alent* r10) { explocreate(r1,r2,r3,r4,r5,r6,r10); if ((random()&3)==0) embercreate(r1,r2,r6); } void explogo(int r1,int r2,int r3,int r4,int r5,int r6,alent* r10) { explocreate(r1,r2,r3,r4,r5,r6,r10); embercreate(r1,r2,r6); } void explocreate(int r1,int r2,int r3,int r4,int r5,int r6,alent* r10) { if (r10!=NULL) {r1=r10->x; r2=r10->y;} int vol=0x7f-((abs(r1-xpos)+abs(r2-ypos))>>12); if (vol>=80) { bidforsound(_Explochannel,_SampExplo,((vol&0x7f)>0x7c)?0x7c:(vol&0x7f), // channel, , vol, 0x3800,0,0,10,((r1-xpos)>>9),CHUNK_EXPLO); //pitch, , ,lifetime (frames) } noexplosound: explocreatequiet(r1,r2,r3,r4,r5,r6,r10); } void explocreatequiet(int r1,int r2,int r3,int r4,int r5,int r6,alent* r10) { if (r10==NULL) //(r10<8) { noobject: softmakeobj(_Explo,r1,r2+(8<<8),r3,r4,(r5!=0)?(1<<15):0,r6); } else { r10->type=_Explo; r10->dx=r3; r10->dy=r4; r10->r5=0; } noobjectins:; } void embercreate(int r1,int r2,int r6) { r2+=(8<<8); // The original code achieves this by modifying r2 // inside explocreatequiet. Arrgh. softmakeobj(_Ember,r1,r2,1<<8,-(1<<8),0,r6); softmakeobj(_Ember,r1,r2,-(1<<8),-(1<<8),0,r6); } void atomexplogo(int r1,int r2,int r3,int r4,int r5,int r6,alent* r10) { explogoquiet(r1,r2,r3,r4,r5,r6,r10); explogoquiet(r1,r2-(16<<8),r3,-(1<<6),r5,r6,r10); explogoquiet(r1,r2-(32<<8),r3,-(1<<7),r5,r6,r10); explogoquiet(r1+(12<<8),r2-(24<<8),1<<6,-(3<<5),r5,r6,r10); explogoquiet(r1-(12<<8),r2-(24<<8),-(1<<6),-(3<<5),r5,r6,r10); int r7=(r1-xpos)>>9; r1=0x8f-((abs(r1-xpos)+abs(r2-ypos))>>12); if (r1>0x7f) r1=0x7f; if (r1>=60) { /* AND R2,R1,#&7F:MOV R2,#&7F ??? */ bidforsound(_Explochannel,_SampAtomExplo,0x7f,0x2800,0,0,50,r7,CHUNK_ATOM); } noatomsound: return; } void screenwakeup() { char* r7=translate(xpos,ypos)-_boxwidth-(boardwidth<<4); char* r8=boardadr->contents; //set up outer limits: start char* r9=r8+boardadr->width*boardadr->height; // end for (int r5=_boxheight*2;r5>0;r7+=boardwidth,r5--) { loopa4: linecheck(r7,r8,r9); } } void linecheck(char* r7,char* r8,char* r9) { for (int r4=_boxwidth*2;r4>0;r4--) { loopa3: if ((r7>r8)&&(r9>r7)&&(*r7>_triggerlim)) dowakeup(r7); r7++; } } void wakeupal() { char* r7=translate(xpos,ypos)-(_boxwidth/2)-(boardwidth<<3); char* r8=boardadr->contents; //set up outer limits: start char* r9=r8+boardadr->width*boardadr->height; // end boxcheck(_boxwidth,1,&r7,r8,r9); boxcheck(_boxheight,boardwidth,&r7,r8,r9); boxcheck(_boxwidth,-1,&r7,r8,r9); boxcheck(_boxheight,-boardwidth,&r7,r8,r9); } void boxcheck(int r4,int r5,char** r7,char* r8,char* r9) { for (;r4>0;r4--) { loop80: if ((*r7>r8)&&(r9>*r7)&&(**r7>_triggerlim)) dowakeup(*r7); *r7+=r5; // badalmarker: *(*r7-r5)=0; wakeinsert:; } } void dowakeup(char* r7) { char r0=*r7; int r1,r2; if ((r0<240)||(r0>253)) return; // r7-=r5; not for me *r7=0; backtranslate(r7,&r1,&r2); r0=r0-(240-_Alien1); makeobj(r0,r1+(8<<8),r2+(7<<8),0,0,0,(r0<<9)-((_Alien1-1)<<9)); } const int _savevalid = 0x4b4f6349; void saveal() { bonusstore=bonusctr; plweaponstore=plweapontype; int* r10=saveareaints; *(r10++)=_savevalid; *(r10++)=xpos; *(r10++)=ypos; *(r10++)=initplx; *(r10++)=initply; *(r10++)=hvec; *(r10++)=vvec; alent* r10b=saveareaalents; alent* r7=r10b+_savearealen; alent* r11=aladr; for (int r9=_alno; r9>0; r9--) { procsaveal: if (r10b>=r7) break; switch(r11->type) { case _Explo: //don't save these case _Scoreobj: case _Flyingbonus: case _Dyingbonus: case 0: r11++; break; default: *r10b=*r11; r10b++; r11++; } } r10b->type=-1; // end marker } void restoreal() { bonusctr=bonusstore; plweapontype=plweaponstore; wipealtab(); int* r11=saveareaints; if (_savevalid!=*r11) return; *(r11++)=0; xpos=*(r11++); ypos=*(r11++); initplx=*(r11++); initply=*(r11++); hvec=*(r11++); vvec=*(r11++); alent* r10=aladr; alent* r11b=saveareaalents; for (;r11b->type!=-1;) { sl1: *(r10++)=*(r11b++); } restored:; } void moval() { //BL writeclip - active for release version if (extending) extending--; fuelexploctr=extending; /* ?!?! */ sprlx=xpos-_windowxsize; sprhx=xpos+_windowxsize; sprly=ypos-_windowysize; sprhy=ypos+_windowysize; alent* r11=aladr; for (int r9=_alno; r9>0; r9-=8) { l8: if (r11->type) procal(r11); r11++; if (r11->type) procal(r11); r11++; if (r11->type) procal(r11); r11++; if (r11->type) procal(r11); r11++; if (r11->type) procal(r11); r11++; if (r11->type) procal(r11); r11++; if (r11->type) procal(r11); r11++; if (r11->type) procal(r11); r11++; } return; } void procal(alent* r11) { if ((r11->x<=xlowlim)||(xposmax<=r11->x)||(r11->y<=ylowlim)||(yposmax<=r11->y)) { aloffscr: if (r11->type!=_Decoration) /* ??? */ { r11->type=0; return; } } noaloffscr: if ((r11->x>=sprlx)&&(sprhx>=r11->x)&&(r11->y>=sprly)&&(sprhy>=r11->y)) plotal=masterplotal; else plotal=0; switch ((r11->type)&0x1f) { aljumptab: t: case 1: explo(r11); return; case 2: ember(r11); return; case 3: plat1(r11); return; case 4: plat2(r11); return; case 5: case 6: plat3(r11); return; case 7: case 8: case 9: case 10: plat4(r11); return; case 11: plat5(r11); return; case 12: scoreobj(r11); return; case 13: dyingbonus(r11); return; case 14: flyingbonus(r11); return; case 15: booby(r11); return; case 16: decoration(r11); return; case 17: extender(r11); return; case 18: alien1(r11); return; case 19: alien2(r11); return; case 20: alien3(r11); return; case 21: alien4(r11); return; case 22: alien5(r11); return; case 23: alien6(r11); return; case 24: alien7(r11); return; case 25: alien8(r11); return; case 26: alien9(r11); return; case 27: alien10(r11); return; case 28: alien11(r11); return; case 29: alien12(r11); return; case 30: alien13(r11); return; case 31: alien14(r11); return; case 0:; } aljerr: return; } void alienwander(alent* r11,char* r5) { if ((righthit==1)||(lefthit==1)) almightjump(r11); else if (*r5==0) alpossjump(r11); else if (*(r5+1)==0) alpossjump(r11); else if ((random()&0x3f)==0) almightjump(r11); else almightjumpins(r11); } void almightjumpins(alent* r11) { if (((r11->dx)>(1<<5))||((r11->dx)<-(1<<5)) ||((r11->dy)>(1<<7))||((r11->dy)<-(1<<7))) return; alienstopped(r11); } void jumpyalwander(alent* r11) { if ((righthit==1)||(lefthit==1)) almightjump(r11); else if (((r11->dx)>(1<<5))||((r11->dx)<-(1<<5)) ||((r11->dy)>(1<<7))||((r11->dy)<-(1<<7))) return; else alienstopped(r11); } void alienwanderfly(alent* r11) { if ((random()&0xff)==0) alienstoppedfly(r11); if (((r11->dx)>(1<<5))||((r11->dx)<-(1<<5)) ||((r11->dy)>(1<<5))||((r11->dy)<-(1<<5))) return; alienstoppedfly(r11); } void alienwandernojump(alent* r11) { if (((r11->dx)>(1<<5))||((r11->dx)<-(1<<5)) ||((r11->dy)>(1<<8))||((r11->dy)<-(1<<8))) return; alienstopped(r11); } void alienstopped(alent* r11) { if ((downhit==1)||(alonobj==1)) r11->dx=(random()&(1<<9))-(1<<8); } void alienstoppedfly(alent* r11) { int r2=random(); if ((r2&6)==0) { flyup: r11->dx=0; r11->dy=-(1<<7); } else if ((r2&1)==0) { flyupdown: r11->dx=0; r11->dy=(r2&(1<<9))-(1<<8); } else { r11->dx=(r2&(1<<10))-(1<<9); r11->dy=0; } return; } void almightjump(alent* r11) { if (downhit!=1) r11->dx=0; else if ((random()&3)==0) r11->dy=-(8<<8); almightjumpins(r11); } void alpossjump(alent* r11) { if (downhit!=1) r11->dx=0; else if ((random()&0x1f)==0) r11->dy=-(8<<8); almightjumpins(r11); } void almightwelljump(alent* r11) { if (downhit!=1) r11->dx=0; else if ((random()&3)!=0) r11->dy=-(8<<8); almightjumpins(r11); } void alientestplat(alent* r11,char* r5) { if (!alonplat) return; plattoobj(r5); } void decoration(alent* r11) { if (--r11->r6<0) { r11->x+=r11->dx; r11->y+=r11->dy; r11->dy+=(1<<4); } if ((r11->r5-=(1<<16))<0) r11->type=0; if (masterplotal==0) return; fspplot(blokeadr,r11->r5&0xff,_xofs+(r11->x>>8),_yofs+8+(r11->y>>8)); } void extender(alent* r11) { int tmpx=r11->x+r11->dx, tmpy=r11->y+r11->dy; if (!plcolcheck(r11->x+r11->dx,r11->y+r11->dy,(32<<8),(8<<8))); // horiz.size, vert. size r11->x+=r11->dx, r11->y+=r11->dy; char* r0=fntranslate(tmpx,tmpy); char f=r11->r5&0xff; if (r11->r5&(1<<8)) { contracting: if ((*r0==f)||(*r0==0)) f=*r0=0; else if ((*r0!=f+1)&&(*r0!=f+2)&&(*r0!=_gaslowlim)&&(*r0!=_gashighlim)) { r11->type=0; return; } } else { if (*r0==0) *r0=f; if ((*r0!=f)&&(*r0!=f+1)&&(*r0!=f+2)&&(*r0!=_gaslowlim)&&(*r0!=_gashighlim)) { r11->dx=-r11->dx; r11->r5|=(1<<8); } } nostopextend: if (plotal==0) return; r0=fntranslate(r11->x+r11->dx*15,r11->y); f=r11->r5&0xff; if ((*r0!=0)&&(*r0!=f)&&(*r0!=f+1)&&(*r0!=f+2)) return; fspplot(blockadr,r11->r5&0xff, (r11->x>>8)-((xpos-(r11->dx*7))>>8)+_xofs,(r11->y>>8)-(ypos>>8)+_yofs); } int alspintab[40]; void init_alspintab() { for (int i=0;i<20;i++) { alspintab[i*2] = (int)((10<<8)*sin(i*2*PI/16)); alspintab[i*2+1] = (int)((10<<8)*cos(i*2*PI/16)); }} void alien1(alent* r11) { colchecktype=2; platypos=r11->y-(8<<8); colcheck(r11); r11->y=platypos+(8<<8); char* r5=albcheck(r11); r11->x+=r11->dx; r11->y+=r11->dy; r11->dy+=1<<7; // gravity if (r11->dy>(1<<11)) r11->dy=1<<11; alienwandernojump(r11); bulcolchadd(r11); if (plcolcheck(r11->x,r11->y,_alwidth,_alheight/2)) {plstrength-=_explocontloss; r11->r6-=_explocontloss;} // [R11,#20] ; alien strength if (r11->r6<=0) {alkill(r11); return;} if (abs(r11->x-xpos)>_sleeprange) alsleep(1,r11); if (abs(r11->y-ypos)>_sleeprange) alsleep(1,r11); if (plotal==0) return; fspplot(alspradr,8+(r11->dx>0)*2+((framectr&8)>>3), (r11->x>>8)-(xpos>>8)+_xofs,(r11->y>>8)-(ypos>>8)+_yofs+8); } void alien2(alent* r11) { colchecktype=1; platypos=r11->y-(8<<8); colcheck(r11); r11->y=platypos+(8<<8); char* r5=albcheck(r11); r11->x+=r11->dx; r11->y+=r11->dy; r11->dy+=1<<7; // gravity if (r11->dy>(1<<11)) r11->dy=1<<11; alienwander(r11,r5); alientestplat(r11,r5); bulcolchadd(r11); if (plcolcheck(r11->x,r11->y,_alwidth,_alheight)) {plstrength-=_explocontloss; r11->r6-=_explocontloss;} // [R11,#20] ; alien strength if (r11->r6<=0) {alkill(r11); return;} if (abs(r11->x-xpos)>_sleeprange) alsleep(2,r11); if (abs(r11->y-ypos)>_sleeprange) alsleep(2,r11); if (plotal==0) return; fspplot(alspradr,0, (r11->x>>8)-(xpos>>8)+_xofs,(r11->y>>8)-(ypos>>8)+_yofs); } void alien3(alent* r11) { colchecktype=1; platypos=r11->y-(8<<8); colcheck(r11); r11->y=platypos+(8<<8); char* r5=albcheck(r11); r11->x+=r11->dx; r11->y+=r11->dy; r11->dy+=1<<7; // gravity if (r11->dy>(1<<11)) r11->dy=1<<11; alienwander(r11,r5); alientestplat(r11,r5); bulcolchadd(r11); if (plcolcheck(r11->x,r11->y,_alwidth,_alheight)) {plstrength-=_explocontloss; r11->r6-=_explocontloss;} // [R11,#20] ; alien strength if (r11->r6<=0) {alkill(r11); return;} if (abs(r11->x-xpos)>_sleeprange) alsleep(3,r11); if (abs(r11->y-ypos)>_sleeprange) alsleep(3,r11); if ((random()&0x3f)==0) alshoot(r11); if (plotal==0) return; fspplot(alspradr,1, (r11->x>>8)-(xpos>>8)+_xofs,(r11->y>>8)-(ypos>>8)+_yofs); } void alien4(alent* r11) { colchecktype=1; platypos=r11->y-(8<<8); colcheck(r11); r11->y=platypos+(8<<8); char* r5=albcheck(r11); r11->x+=r11->dx; r11->y+=r11->dy; r11->dy+=1<<7; // gravity if (r11->dy>(1<<11)) r11->dy=1<<11; jumpyalwander(r11); alientestplat(r11,r5); bulcolchadd(r11); if (plcolcheck(r11->x,r11->y,_alwidth,_alheight)) {plstrength-=_explocontloss; r11->r6-=_explocontloss;} // [R11,#20] ; alien strength if (r11->r6<=0) {alkill(r11); return;} if (abs(r11->x-xpos)>_sleeprange) alsleep(4,r11); if (abs(r11->y-ypos)>_sleeprange) alsleep(4,r11); r11->r5+=(r11->r5<<16); if (r11->r5&(1<<29)) r11->r5=alspinfire(r11); if (r11->r5&(1<<31)) r11->r5-=8; else r11->r5+=4; if ((r11->r5&0xffff)==0) r11->r5=0; if (plotal==0) return; int x,y; fspplot(alspradr,2, (r11->x>>8)-(xpos>>8)+_xofs,(r11->y>>8)-(ypos>>8)+_yofs); fspplot(alspradr,4+((r11->r5>>24)&3), x=(r11->x>>8)-(xpos>>8)+_xofs,y=(r11->y>>8)-(ypos>>8)+_yofs-7); if (r11->r5&(1<<31)) return; int f=(r11->r5>>26)&3; int r0=(r11->r5>>24)&3; int* r3=alspintab+r0*2; for (int r4=4;r4>0;r4--) { loop81: fspplot(exploadr,_bulspritebase+((r4+f)&3),x+(r3[0]>>8),y+(r3[1]>>8)); r3+=8; // yes, that's 8 ints (32 bytes) } } void alien5(alent* r11) { colchecktype=1; platypos=r11->y-(8<<8); colcheck(r11); r11->y=platypos+(8<<8); char* r5=albcheck(r11); r11->x+=r11->dx; r11->y+=r11->dy; r11->dy+=1<<7; // gravity if (r11->dy>(1<<11)) r11->dy=1<<11; alienwander(r11,r5); alientestplat(r11,r5); bulcolchadd(r11); if (plcolcheck(r11->x,r11->y,_alwidth,_alheight)) {plstrength-=_explocontloss; r11->r6-=_explocontloss;} // [R11,#20] ; alien strength if (r11->r6<=0) {alkill(r11); return;} if (abs(r11->x-xpos)>_sleeprange) alsleep(5,r11); if (abs(r11->y-ypos)>_sleeprange) alsleep(5,r11); r11->r5+=(r11->r5<<16); if (r11->r5&(1<<29)) r11->r5=alspinpowerfire(r11,0); if (r11->r5&(1<<31)) r11->r5-=2; else r11->r5+=2; if ((r11->r5&0xffff)==0) r11->r5=0; if (plotal==0) return; int x,y; fspplot(alspradr,2, (r11->x>>8)-(xpos>>8)+_xofs,(r11->y>>8)-(ypos>>8)+_yofs); fspplot(alspradr,4+((r11->r5>>24)&3), x=(r11->x>>8)-(xpos>>8)+_xofs,y=(r11->y>>8)-(ypos>>8)+_yofs-7); if (r11->r5&(1<<31)) return; int f=(r11->r5>>26)&3; int r0=(r11->r5>>24)&3; int* r3=alspintab+r0*2; for (int r4=4;r4>0;r4--) { loop83: fspplot(exploadr,_bulspritebase+8+((r4+f)&1),x+(r3[0]>>8),y+(r3[1]>>8)); r3+=8; // yes, that's 8 ints (32 bytes) } } void alien6(alent* r11) { colchecktype=1; platypos=r11->y-(8<<8); colcheck(r11); r11->y=platypos+(8<<8); char* r5=albcheck(r11); r11->x+=r11->dx; r11->y+=r11->dy; r11->dy+=1<<7; // gravity if (r11->dy>(1<<11)) r11->dy=1<<11; alienwander(r11,r5); alientestplat(r11,r5); bulcolchadd(r11); if (plcolcheck(r11->x,r11->y,_alwidth,_alheight)) {plstrength-=_explocontloss; r11->r6-=_explocontloss;} // [R11,#20] ; alien strength if (r11->r6<=0) {alkill(r11); return;} if (abs(r11->x-xpos)>_sleeprange) alsleep(6,r11); if (abs(r11->y-ypos)>_sleeprange) alsleep(6,r11); r11->r5+=(r11->r5<<16); if (r11->r5&(1<<29)) r11->r5=alspinpowerfire(r11,1); if (r11->r5&(1<<31)) r11->r5-=2; else r11->r5+=8; if ((r11->r5&0xffff)==0) r11->r5=0; if (plotal==0) return; int x,y; fspplot(alspradr,3, (r11->x>>8)-(xpos>>8)+_xofs,(r11->y>>8)-(ypos>>8)+_yofs); fspplot(alspradr,4+((r11->r5>>24)&3), x=(r11->x>>8)-(xpos>>8)+_xofs,y=(r11->y>>8)-(ypos>>8)+_yofs-7); if (r11->r5&(1<<31)) return; int f=(r11->r5>>26)&3; int r0=(r11->r5>>24)&3; int* r3=alspintab+r0*2; for (int r4=4;r4>0;r4--) { loop85: fspplot(exploadr,_bulspritebase+10+((r4+f)&1),x+(r3[0]>>8),y+(r3[1]>>8)); r3+=8; // yes, that's 8 ints (32 bytes) } } int alspinfire(alent* r11) { int r0=(random()&3); int* r6=alspintab+(r0<<1); for (int r4=4;r4>0;r4--) { loop82: makebul(r6[0]+r11->x,r6[1]+r11->y-(7<<8),r6[8]>>2,r6[9]>>2, _bulspritebase+((r4+r0)&3),1<<24); r6+=8; } r6-=8; int r2=0x7f-abs(r6[0]-xpos)-abs(r6[1]-(7<<8)-ypos); // XXX scaling? if (r2>0x40) bidforsound(_Explochannel,_Sampsmallzap,r2,(fullpitch+0x1000) /*pitch*/, 0,0,2 /* lifetime (frames) */,(r6[1]-(7<<8))>>9,CHUNK_SPINFIRE); nospinzapsound: return 0x80000100; } int alspinpowerfire(alent* r11,int r7) { int r0=(random()&3); int* r6=alspintab+(r0<<1); for (int r4=4;r4>0;r4--) { loop84: makebul(r6[0]+r11->x,r6[1]+r11->y-(7<<8),r6[8]>>2,r6[9]>>2, _bulspritebase+8+(r7<<1),1<<24); r6+=8; } r6-=8; int r2=0x7f-abs(r6[0]-xpos)-abs(r6[1]-(7<<8)-ypos); // XXX scaling? if (r2>0x40) bidforsound(_Explochannel,_Sampbigzap,r2,fullpitch /*pitch*/, 0,0,2 /* lifetime (frames) */,(r6[1]-(7<<8))>>9,CHUNK_SPINPOWERFIRE); nopowerzapsound: return 0x80000040; } void alien7(alent* r11) { colchecktype=1; platypos=r11->y-(8<<8); colcheck(r11); r11->y=platypos+(8<<8); char* r5=albcheck(r11); r11->x+=r11->dx; r11->y+=r11->dy; r11->dy+=1<<7; // gravity if (r11->dy>(1<<11)) r11->dy=1<<11; alienwander(r11,r5); alientestplat(r11,r5); bulcolchadd(r11); if (plcolcheck(r11->x,r11->y,_alwidth,_alheight)) {plstrength-=_explocontloss; r11->r6-=_explocontloss;} // [R11,#20] ; alien strength if (r11->r6<=0) {alkill(r11); return;} if (abs(r11->x-xpos)>_sleeprange) alsleep(7,r11); if (abs(r11->y-ypos)>_sleeprange) alsleep(7,r11); int rng=random(); if ((rng&0x3f)==0) alshootnutter(r11); else if ((rng&0xf)==0) alshootfast(r11); if (plotal==0) return; fspplot(alspradr,16, (r11->x>>8)-(xpos>>8)+_xofs,(r11->y>>8)-(ypos>>8)+_yofs); } void alien8(alent* r11) { colchecktype=1; platypos=r11->y-(8<<8); colcheck(r11); r11->y=platypos+(8<<8); char* r5=albcheck(r11); r11->x+=r11->dx; r11->y+=r11->dy; r11->dy+=1<<7; // gravity if (r11->dy>(1<<11)) r11->dy=1<<11; alienwander(r11,r5); alientestplat(r11,r5); bulcolchadd(r11); if (plcolcheck(r11->x,r11->y,_alwidth,_alheight)) {plstrength-=_explocontloss; r11->r6-=_explocontloss;} // [R11,#20] ; alien strength if (r11->r6<=0) {alkill(r11); return;} if (abs(r11->x-xpos)>_sleeprange) alsleep(8,r11); if (abs(r11->y-ypos)>_sleeprange) alsleep(8,r11); int rng=random(); if ((rng&0x3f)==0) alshootnutter(r11); else if ((rng&0xf)==0) alshootmental(r11); if (plotal==0) return; fspplot(alspradr,16, (r11->x>>8)-(xpos>>8)+_xofs,(r11->y>>8)-(ypos>>8)+_yofs); } void alien9(alent* r11) { colchecktype=1; platypos=r11->y-(8<<8); colcheck(r11); r11->y=platypos+(8<<8); char* r5=albcheck(r11); r11->x+=r11->dx; r11->y+=r11->dy; r11->dy+=1<<7; // gravity if (r11->dy>(1<<11)) r11->dy=1<<11; alienwander(r11,r5); alientestplat(r11,r5); bulcolchadd(r11); if (plcolcheck(r11->x,r11->y,_alwidth,_alheight)) {plstrength-=_explocontloss; r11->r6-=_explocontloss;} // [R11,#20] ; alien strength if (r11->r6<=0) {alkill(r11); return;} if (abs(r11->x-xpos)>_sleeprange) alsleep(9,r11); if (abs(r11->y-ypos)>_sleeprange) alsleep(9,r11); int rng=random(); if ((rng&0x1f)==0) alshootnutterplus(r11); if (plotal==0) return; fspplot(alspradr,17, (r11->x>>8)-(xpos>>8)+_xofs,(r11->y>>8)-(ypos>>8)+_yofs); } void alien10(alent* r11) { colchecktype=1; platypos=r11->y-(8<<8); colcheck(r11); r11->y=platypos+(8<<8); char* r5=albcheck(r11); r11->x+=r11->dx; r11->y+=r11->dy; r11->dy+=1<<7; // gravity if (r11->dy>(1<<11)) r11->dy=1<<11; alienwander(r11,r5); alientestplat(r11,r5); bulcolchadd(r11); if (plcolcheck(r11->x,r11->y,_alwidth,_alheight)) {plstrength-=_explocontloss; r11->r6-=_explocontloss;} // [R11,#20] ; alien strength if (r11->r6<=0) {alkill(r11); return;} if (abs(r11->x-xpos)>_sleeprange) alsleep(10,r11); if (abs(r11->y-ypos)>_sleeprange) alsleep(10,r11); int rng=random(); if ((rng&0x1f)==0) alshootnuttermental(r11); if (plotal==0) return; fspplot(alspradr,17, (r11->x>>8)-(xpos>>8)+_xofs,(r11->y>>8)-(ypos>>8)+_yofs); } void alien11(alent* r11) { colchecktype=1; platypos=r11->y-(8<<8); colcheck(r11); r11->y=platypos+(8<<8); char* r5=albcheck(r11); r11->x+=r11->dx; r11->y+=r11->dy; // no gravity alienwanderfly(r11); bulcolchadd(r11); if (plcolcheck(r11->x,r11->y,_alwidth,_alheight)) {plstrength-=_explocontloss; r11->r6-=_explocontloss;} // [R11,#20] ; alien strength if (r11->r6<=0) {alkill(r11); return;} if (abs(r11->x-xpos)>2*_sleeprange) alsleep(11,r11); if (abs(r11->y-ypos)>2*_sleeprange) alsleep(11,r11); int rng=random(); if ((rng&0x1f)==0) alshootfast(r11); if (plotal==0) return; fspplot(alspradr,12+(random()&3), (r11->x>>8)-(xpos>>8)+_xofs,(r11->y>>8)-(ypos>>8)+_yofs); } void alien12(alent* r11) { colchecktype=1; platypos=r11->y-(8<<8); colcheck(r11); r11->y=platypos+(8<<8); char* r5=albcheck(r11); r11->x+=r11->dx; r11->y+=r11->dy; // no gravity r11->dx+=r11->dx>>6; r11->dy+=r11->dy>>6; if (r11->dx>_speedlim) r11->dx=_speedlim; if (r11->dx<-_speedlim) r11->dx=-_speedlim; if (r11->dy>_speedlim) r11->dy=_speedlim; if (r11->dy<-_speedlim) r11->dy=-_speedlim; alienwanderfly(r11); bulcolchadd(r11); if (plcolcheck(r11->x,r11->y,_alwidth,_alheight)) {plstrength-=_explocontloss; r11->r6-=_explocontloss;} // [R11,#20] ; alien strength if (r11->r6<=0) {alkill(r11); return;} if (abs(r11->x-xpos)>4*_sleeprange) alsleep(12,r11); if (abs(r11->y-ypos)>4*_sleeprange) alsleep(12,r11); int rng=random(); if ((rng&0x1f)==0) alshootnuttermental(r11); if (plotal==0) return; fspplot(alspradr,12+(random()&3), (r11->x>>8)-(xpos>>8)+_xofs,(r11->y>>8)-(ypos>>8)+_yofs); } void alien13(alent* r11) { colchecktype=2; platypos=r11->y-(8<<8); colcheck(r11); r11->y=platypos+(8<<8); char* r5=albcheck(r11); r11->x+=r11->dx; r11->y+=r11->dy; if (r11->dy>(1<<11)) r11->dy=1<<11; alienwanderfly(r11); bulcolchaddshort(r11); if (plcolcheck(r11->x,r11->y,_alwidth,_alheight/2)) {plstrength-=_explocontloss; r11->r6-=_explocontloss;} // [R11,#20] ; alien strength if (r11->r6<=0) {alkill(r11); return;} if (abs(r11->x-xpos)>_sleeprange) alsleep(13,r11); if (abs(r11->y-ypos)>_sleeprange) alsleep(13,r11); if (plotal==0) return; fspplot(alspradr,8+2*(r11->dx>0)+((framectr&8)==8), (r11->x>>8)-(xpos>>8)+_xofs,(r11->y>>8)-(ypos>>8)+_yofs); } void alien14(alent* r11) { colchecktype=1; platypos=r11->y-(8<<8); colcheck(r11); r11->y=platypos+(8<<8); char* r5=albcheck(r11); r11->x+=r11->dx; r11->y+=r11->dy; r11->dy++; if (r11->dy>(1<<9)) r11->dy=1<<8; bulcolchadd(r11); if (downhit==1) hamsterspecial(r11); if (plcolcheck(r11->x,r11->y,_alwidth,_alheight)) {plstrength-=_explocontloss; r11->r6-=_explocontloss;} // [R11,#20] ; alien strength if (r11->r6<=0) {alkill(r11); return;} if (abs(r11->x-xpos)>_sleeprange) alsleep(14,r11); if (abs(r11->y-ypos)>_sleeprange) alsleep(14,r11); if (plotal==0) return; fspplot(alspradr,18, (r11->x>>8)-(xpos>>8)+_xofs,(r11->y>>8)-(ypos>>8)+_yofs); } void hamsterspecial(alent* r11) { r11->type=_Alien1+11; r11->r6=12<<8; r11->dx=r11->dy=0; } void alkill(alent* r11) { plscoreadd+=((r11->type-(_Alien1-1))&0x1f)*100; explogo(r11->x,r11->y,0,0,0,/*r6*/0,r11/*-4*/); exploins(r11); } void alshoot(alent* r11) { int r2=xpos-r11->x; int r3=(ypos+(8<<8))-(r11->y-(6<<8)); // aim at body if ((r2>_firerange)||(r3>_firerange)) return; if ((r2<-_firerange)||(r3<-_firerange)) return; int r4=random()&7; if (r4==7) r4=6; makebul(r11->x,r11->y,(r2>>6),(r3>>6),_bulspritebase+r4,1<<24); bidforsound(_Explochannel,_Sampsmallzap,0x78,fullpitch+0x1000, // pitch 0,(fullpitch<<16)|0xfe00,2 /* lifetime (frames) */,0,CHUNK_SHOOT); noshootsound:; } void alshootfast(alent* r11) { int r2=xpos-r11->x; int r3=(ypos+(8<<8))-(r11->y-(6<<8)); // aim at body if ((r2>_firerange)||(r3>_firerange)) return; if ((r2<-_firerange)||(r3<-_firerange)) return; int r4=random()&7; if (r4==7) r4=6; makebul(r11->x,r11->y,(r2>>5),(r3>>5),_bulspritebase+r4,1<<24); bidforsound(_Explochannel,_Sampsmallzap,0x6f,fullpitch+0x1000, // pitch 0,(fullpitch<<16)|0xfe00,2 /* lifetime (frames) */,0,CHUNK_SHOOT); } void alshootnutter(alent* r11) { int r2=xpos-r11->x; int r3=(ypos+(12<<8))-(r11->y-(8<<8)); //fire from sensible place; aim at body if ((r2>_firerange)||(r3>_firerange)) return; if ((r2<-_firerange)||(r3<-_firerange)) return; makebul(r11->x,r11->y,0,-(1<<10),_bulspritebase+12,1<<22); bidforsound(_Explochannel,_Sampbigzap,0x6f,fullpitch, // pitch 0,(fullpitch<<16)|0xfe00,2 /* lifetime (frames) */,0,CHUNK_SHOOTNUTTER); } void alshootnutterplus(alent* r11) { int r2=xpos-r11->x; int r3=(ypos+(12<<8))-(r11->y-(8<<8)); //fire from sensible place; aim at body if ((r2>_firerange)||(r3>_firerange)) return; if ((r2<-_firerange)||(r3<-_firerange)) return; makebul(r11->x,r11->y,0,-(1<<10),_bulspritebase+13,1<<21); bidforsound(_Explochannel,_Sampbigzap,0x6f,fullpitch, // pitch 0,(fullpitch<<16)|0xfe00,2 /* lifetime (frames) */,0,CHUNK_SHOOTNUTTER); } void alshootnuttermental(alent* r11) { int r2=xpos-r11->x; int r3=(ypos+(12<<8))-(r11->y-(8<<8)); //fire from sensible place; aim at body if ((r2>_firerange)||(r3>_firerange)) return; if ((r2<-_firerange)||(r3<-_firerange)) return; int r=random(); if (r&(1<<11)) {r2=0; r3=-(1<<10);} else {r2=(r&(1<<10))?(1<<10):-(1<<10); r3=0;} makebul(r11->x,r11->y,r2,r3,_bulspritebase+14,1<<21); bidforsound(_Explochannel,_Sampbigzap,0x6f,fullpitch, // pitch 0,(fullpitch<<16)|0xfe00,2 /* lifetime (frames) */,0,CHUNK_SHOOTNUTTER); } void alshootmental(alent* r11) { int r2=xpos-r11->x; int r3=(ypos+(8<<8))-(r11->y-(6<<8)); // aim at body if ((r2>_firerange)||(r3>_firerange)) return; if ((r2<-_firerange)||(r3<-_firerange)) return; int r4=8+(random()&2); makebul(r11->x,r11->y,(r2>>6),(r3>>6),_bulspritebase+r4,1<<24); bidforsound(_Explochannel,_Sampsmallzap,0x6f,fullpitch+0x1000, // pitch 0,(fullpitch<<16)|0xfe00,2 /* lifetime (frames) */,0,CHUNK_SHOOT); } void alsleep(int s,alent* r11) { char* r0=translate(r11->x-(4<<8),r11->y-(8<<8)); if (*r0!=0) return; *r0=240+(s-1); r11->type=0; } void explo(alent* r11) { r11->x+=r11->dx; r11->y+=r11->dy; int r4=r11->r5; int r5=explospeed<<2; if (r4<=r5) if (plcolcheck(r11->x,r11->y,_expwidth,_expheight)) // object size plstrength-=_explocontloss; exploins(r11); } void exploins(alent* r11) { r11->r5=r11->r5+explospeed; if (r11->r5<0) r11->r5=50<<8; //trap negatives char r0=(r11->r5)&0xff; if (r0>=(8<<2)) //explo frame length { r11->type=0; return;} if (plotal==0) return; fspplot(exploadr,(r11->r5>>2)&0x3f, (r11->x>>8)-(xpos>>8)+_xofs, (r11->y>>8)-(ypos>>8)+_yofs); } void booby(alent* r11) { char* r0=fntranslate(r11->x+r11->dx,r11->y); if ((*r0>=_bomblowlim)&&(*r0<_targethighlim)) {emberbooby(r0); return;} noboobybomb: if (*r0>=_blim) r11->dx=-(r11->dx>>1); r0=fntranslate(r11->x+r11->dx,r11->y+r11->dy); if ((*r0>=_boobylowlim)&&(*r0<=_boobyhighlim)) {emberbooby(r0); return;} noboobybooby: if (*r0>=_blim) r11->dy=-(r11->dy>>1); r11->x+=r11->dx; r11->y+=r11->dy; r11->dy+=(1<<4); //gravity r11->r5++; if (r11->r5<0) r11->r5=1<<8; //trap negatives if (r11->r5>=140) // booby lifetime { r11->type=0; return;} if (plotal==0) return; fspplot(exploadr,12+((r11->r5>>2)&3), (r11->x>>8)-(xpos>>8)+_xofs, (r11->y>>8)-(ypos>>8)+_yofs); } void ember(alent* r11) { char* r0=fntranslate(r11->x+r11->dx,r11->y); if ((*r0>=_bomblowlim)&&(*r0<_bombhighlim)) {emberbomb(r0,r11); return;} noemberbomb: if (*r0>=_blim) r11->dx=-(r11->dx>>1); r0=fntranslate(r11->x+r11->dx,r11->y+r11->dy); if ((*r0>=_gaslowlim)&&(*r0<_gashighlim)) {emberbomb(r0,r11); return;} noembergas: if (*r0>=_blim) r11->dy=-(r11->dy>>1); r11->x+=r11->dx; r11->y+=r11->dy; r11->dy+=(1<<4); //gravity r11->r5++; if (r11->r5<0) r11->r5=1<<8; //trap negatives if (r11->r5>=70) // ember lifetime { r11->type=0; return;} if (plotal==0) return; fspplot(exploadr,8+(((r11->r5)>>2)&3), (r11->x>>8)-(xpos>>8)+_xofs, (r11->y>>8)-(ypos>>8)+_yofs); } void flyingbonus(alent* r11) { int r4=0; // hit wall marker char* r0=fntranslate(r11->x+r11->dx-(8<<8),r11->y-(8<<8)); if ((*r0>=_bonuslow)||(r0[boardwidth]>=_bonuslow)) if (r11->dx<=0) {r11->dx=-r11->dx; r4=1;} if ((r0[1]>=_bonuslow)||(r0[boardwidth+1]>=_bonuslow)) if (r11->dx>=0) {r11->dx=-r11->dx; r4=1;} flyingskip: r0=fntranslate(r11->x+r11->dx-(8<<8),r11->y+r11->dy-(8<<8)); if ((*r0>=_bonuslow)||(r0[1]>=_bonuslow)) if (r11->dy<=0) {r11->dy=-r11->dy; r4=1;} if ((r0[boardwidth]>=_bonuslow)||(r0[boardwidth+1]>=_bonuslow)) if (r11->dy>=0) {r11->dy=-r11->dy; r4=1;} flyingvertskip: r0=fntranslate(r11->x+r11->dx-(8<<8),r11->y+r11->dy-(8<<8)); if ((*r0>=_bonuslow)||(r0[boardwidth]>=_bonuslow)) if (r11->dx<=0) {r11->dx=-r11->dx; r4=1;} if ((r0[1]>=_bonuslow)||(r0[boardwidth+1]>=_bonuslow)) if (r11->dx>=0) {r11->dx=-r11->dx; r4=1;} r0=fntranslate(r11->x+r11->dx-(8<<8),r11->y+r11->dy-(8<<8)); if ((*r0>=_bonuslow)||(r0[1]>=_bonuslow)) if (r11->dy<=0) {r11->dy=-r11->dy; r4=1;} if ((r0[boardwidth]>=_bonuslow)||(r0[boardwidth+1]>=_bonuslow)) if (r11->dy>=0) {r11->dy=-r11->dy; r4=1;} r11->x+=r11->dx; r11->y+=r11->dy; r11->dy+=(1<<5); //gravity if (r4!=0) { r11->dx-=(r11->dx>>2); r11->dy-=(r11->dy>>2); } flyingnoslow: r11->r5-=(1<<16); if (r11->r5<0) { bonusdowngrade: r11->type=_Dyingbonus; r11->r5=r11->r6 | (1<<20); } if ((r11->x>(pllx-(8<<8)))&&((plhx+(8<<8))>r11->x) &&(r11->y>plly)&&(plhy>r11->y)) bonusobjgot(r11); if (plotal==0) return; // r8=8-(r8>>17); ??? fspplot(blockadr,r11->r6&0xff, (r11->x>>8)-(xpos>>8)+_xofs, (r11->y>>8)-(ypos>>8)+_yofs); } void dyingbonus(alent* r11) { r11->r5-=(1<<16); if (r11->r5<0) {deleteobj(r11); return;} if (plotal==0) return; int r8=8-(r11->r5>>17); int r0=(r11->r5)&0xffff; int r1= (r11->x>>8)-(xpos>>8)+_xofs; int r2=r8+ (r11->y>>8)-(ypos>>8)+_yofs; fsphy=r2; if (fsphy<=cliphy) if (fsply=cliplx) if (fsphx>cliplx) fspplot(blockadr,r0,fsplx-r8,fsphy+r8); } nodyingtop: fsphy=cliphy; fsplx=cliplx; fsply=r2; if (fsply>=cliply) if (fsply=cliplx) if (fsphx>fsplx) fspplot(blockadr,r0,fsplx-r8,fsply-r8); } nodyingbot: writeclip(); } void scoreobj(alent* r11) { r11->x+=r11->dx; r11->y+=r11->dy; r11->dy+=(1<<5); r11->r5-=1; if ((r11->r5&0xff)==0) {r11->type=0; return;} if (plotal==0) return; fspplot(blokeadr,(r11->r5>>8), (r11->x>>8)-(xpos>>8)+_xofs, (r11->y>>8)-(ypos>>8)+_yofs); } void plat1(alent* r11) // alien routines { r11->dx=0; dvcheck(r11); r11->y+=r11->dy; r11->dy+=1<<4; if (r11->dy>(1<<11)) r11->dy=1<<11; if (downhit!=0) platland(r11,_platno); colchadd(r11); platins(r11,_platno); } void plat2(alent* r11) { r11->dx=0; dvcheck(r11); r11->y+=r11->dy; r11->dy+=1<<4; if (r11->dy>(1<<11)) r11->dy=1<<11; if ((downhit!=0)||(uphit!=0)) plattoexplo(r11/*,_platno+2*/); colchadd(r11); platins(r11,_platno+2); } void plat3(alent* r11) { r11->dx=0; dvcheck(r11); r11->y+=r11->dy; r11->dy+=1<<4; if (r11->dy>(1<<11)) r11->dy=1<<11; if (downhit!=0) platland(r11,_platno+4); colchadd(r11); platins(r11,_platno+4); } void plat4(alent* r11) { r11->dx=0; dvcheck(r11); r11->y+=r11->dy; r11->dy+=1<<4; if (r11->dy>(1<<11)) r11->dy=1<<11; if (downhit!=0) platland(r11,_platno-8+(r11->type<<1)); colchadd(r11); platins(r11,_platno-8+(r11->type<<1)); } void plat5(alent* r11) { r11->dx=0; dvcheck(r11); r11->y+=r11->dy; r11->dy+=1<<2; if (r11->dy>(1<<9)) r11->dy=1<<9; if (downhit!=0) platland(r11,_platno+14); // .platlandins (duplicate label ignored) colchadd(r11); platins(r11,_platno+14); } //.platlandins //colchadd(r11); //goto platins; void platins(alent* r11, char r9) { if (plotal==0) return; int r1=(r11->x>>8)-(xpos>>8)+_xofs; int r2=(r11->y>>8)-(ypos>>8)+_yofs; fspplot(blockadr,r9,r1-8,r2); fspplot(blockadr,r9+1,r1+8,r2); } //aldone: //LDMFD R13!,{R9,R11,PC} void colchadd(alent* r11) { if (colchptr-colchtab>=_colchlim) return; colchptr->r0=r11; int xoff=(r11->r5)>>16; int yoff=(r11->r5)&0xffff; colchptr->xmin=r11->x-(xoff<<7); colchptr->ymin=r11->y-(yoff<<7); colchptr->xmax=r11->x+(xoff<<7); colchptr->ymax=r11->y+(yoff<<7); colchptr++; } void bulcolchadd(alent* r11) { if (bulcolchptr-bulcolchtab>=_bulcolchlim) return; bulcolchptr->r0=r11; bulcolchptr->xmin=r11->x-(32<<7); bulcolchptr->ymin=r11->y-(32<<7); bulcolchptr->xmax=r11->x+(32<<7); bulcolchptr->ymax=r11->y+(32<<7); bulcolchptr++; } void bulcolchaddshort(alent* r11) { if (bulcolchptr-bulcolchtab>=_bulcolchlim) return; bulcolchptr->r0=r11; bulcolchptr->xmin=r11->x-(32<<7); bulcolchptr->ymin=r11->y+(8<<8)-(16<<7); bulcolchptr->xmax=r11->x+(32<<7); bulcolchptr->ymax=r11->y+(8<<8)+(16<<7); bulcolchptr++; } void platland(alent* r11, char r9) { char* r0=translate(r11->x,r11->y); char r1=*r0; if (*r0>=_platblim) r0-=boardwidth; if ((*(r0+boardwidth)!=_extendno) &&(*(r0+boardwidth+1)!=_extendno)) { *r0=r9; r0[1]=r9+1; r11->type=0; } } void plattoexplo(alent* r11) {blowup(r11);} void deleteobj(alent* r11) {r11->type=0;} void blowup(alent* r11) {explogo(r11->x,r11->y,0,1<<6,0,/*r6*/0,r11/*-4*/);} void emberbooby(char* r0) { if ((*r0<_atomlowlim)||(*r0>_atomhighlim)) normbombsurvive(r0); else atombomb(r0); } void emberbomb(char* r0,alent* r11) { if ((*r0<_atomlowlim)||(*r0>_atomhighlim)) normbomb(r0,r11); else atombomb(r0); } void normbomb(char* r0,alent* r11) { r11->type=0; normbombsurvive(r0); } void normbombsurvive(char* r0) { if ((*r0==_fuelairno)||(*r0==_fuelairno+1)) {fuelbomb(r0); return;} normbombins: destroy(r0); } void fuelbomb(char* r0) { if (*r0!=_fuelairno) r0--; *r0=0; r0[1]=0; int x,y; backtranslate(r0,&x,&y); explogo(x+(8<<8),y,0,-(1<<7),0,0,0); } int plcolcheck(int x,int y,int dx,int dy) // returns 0 for EQ { return ((x+(dx>>1)>pllx) && (plhx>x-(dx>>1)) && (y+(dy>>1)>plly) && (plhy>y-(dy>>1))); } void settestal() { makeobj(_Alien1+13,xpos-(65<<8),ypos-(24<<8),0,0,0x100020,1<<10); } void dvcheck(alent* r11) { xtemp=r11->x; ytemp=r11->y; uphit=downhit=0; char* r6=translate(r11->x,r11->y+r11->dy); // up if ((r6[-boardwidth]>=_platblim)||(r6[1-boardwidth]>=_platblim)) noup(r11); //down if ((r6[0]>=_platblim)||(r6[1]>=_platblim)) nodown(r11); } void playerplot() { fsphy=120; swi_fastspr_setclipwindow(20,20,320-20,120); if (snuffctr) { snuffhandler: snuffctr+=frameinc; plotterofs=((snuffctr-96<0)?0:(snuffctr-96))>>1; fspplot(blokeadr,70,160,104+plotterofs); // goto playerplotins; seestars(); writeclip(); return; } if (telepctr) { int telepinc=frameinc; if (telepinc>2) telepinc=2; if (telepctr==31) telepinc=1; telepctr+=telepinc; if (telepctr>64) telepctr=0; if (telepctr==32) { dotelep: xpos=telepxpos; ypos=telepypos; screenwakeup(); } } telepskip: plotterofs=(telepctr>32)?(64-telepctr):telepctr; plframe=(xpos>>10)&3; if (plframe==2) plframe=0; else if (plframe==3) plframe=2; if (plface==1) plframe+=3; if (electrocuting) { plotskel: fspplot(blokeadr,_skelspriteno+(plface==1),160,plotterofs+104); plotskelins: seestars(); writeclip(); return; } fspplot(blokeadr,(plface==1)?1:0,160,plotterofs+104); fspplot(blokeadr,plframe+6,160,plotterofs+115); int r0; if (plstrength>2)&3); else nofunnyface: if (plface==1) r0=15; else r0=12; plotface: fspplot(blokeadr,r0,160,plotterofs+94); //head if (plweapontype==0) plotarms(); else if (plweapontype==_mpmgblamno) plotmpmgblam(); else if (plweapontype==_rocketblamno) plotrocketblam(); else if (plweapontype<_rockbase) plotmpmg(); else plotrocket(); playerplotins: seestars(); writeclip(); } void plotarms() {fspplot(blokeadr,(plframe%3)+2,160+(plframe>2),plotterofs+105);} void plotmpmg() { fspplot(blokeadr,42+(plface==1),160-6+(plface!=1)*12+(plfired?0:2*plface-1),plotterofs+106); fspplot(blokeadr,44+(plface==1),160,plotterofs+104); plfired=0; } void plotmpmgblam() { int r2; if (blamctr&8) r2=(blamctr&15)-15; else r2=blamctr&15; fspplot(blockadr,_weaplowlim+6+(plface==1), 160-6+(plface!=1)*12+(plfired?plface*2-1:0),plotterofs+107+(r2>>1)); fspplot(blokeadr,44+(plface==1),160,plotterofs+104+(r2>>1)); plfired=0; } void plotrocket() { int r0=rockettabadr[rocketctr]; fspplot(blokeadr,50+(r0>170)+(r0>60)-(r0<-60)-(r0<-170), 160+(plfired?(plface*2-1):0),plotterofs+97); fspplot(blokeadr,53,160+plface,plotterofs+102); plfired=0; if (rocketflag==0) rocketctr=0; } void plotrocketblam() { int r2; if (blamctr&8) r2=(blamctr&15)-15; else r2=blamctr&15; fspplot(blockadr,_weaplowlim+15,160+(plfired?0:2*plface-1),plotterofs+(r2>>1)+96); fspplot(blokeadr,53,160,plotterofs+(r2>>2)+102); plfired=0; } void bonusplot() { int r2=(frameinc>2)?2:frameinc; if (bonustimer!=0) bonustimer-=r2; if ((bonustimer==1)||(bonustimer==2)) bonusreset(); if ((bonusctr>=13)&&(bonusreplot==0)) {bonusbonus(); return;} if (bonusreplot==0) return; bonusreplot-=r2; //from above if (bonusreplot<0) bonusreplot=0; fsplx=_bonusxplace-8+0x100; // align to write clip window to FastSpr fsply=_bonusyplace-20; fsphx=_bonusxplace+8+0x100; fsphy=_bonusyplace+20; swi_fastspr_setclipwindow(fsplx,fsply,fsphx,fsphy); swi_fastspr_clearwindow(); int r3=((bonusreplot>7)?bonusreplot-8:0); fspplot(blockadr,(bonusctr+16>_bonuslow+12)?0:(bonusctr+16), _bonusxplace+0x100,_bonusyplace+r3); if (bonusctr!=0) fspplot(blockadr,(bonusctr+15>_bonuslow+12)?0:(bonusctr+15), _bonusxplace+0x100,_bonusyplace-20+r3); nosecond: if (bonusctr!=12) fspplot(blockadr,(bonusctr+17>_bonuslow+12)?0:(bonusctr+17), _bonusxplace+0x100,_bonusyplace+20+r3); nothird: writeclip(); // reset the clip window } void bonusbonus() //not to be called by BL { bonusctr=8; bonusreplot=28; keypressed=0; int bdx=boardadr->width*boardadr->height; char* r11=boardadr->contents; for (;bdx>0;r11++,bdx--) { loop90: if (*r11==_starsno) { foundmarker: *r11=0; backtranslate(r11,&telepxpos,&telepypos); telepypos-=(1<<8); telepctr=1; bonusxpos=xpos; bonusypos=ypos; bonustimer=0x180; return; } } bonus1(); } void bonusreset() { if (keypressed) {normreset(); return;} bonusctr=0; bonusreplot=28; keypressed=1; char* r11=boardadr->contents; int r3; for (r3=boardadr->width*boardadr->height;r3>0;r3--) { loop91: if (*(r11++)==_starsno) break; } if (r3==0) {bonus1(); normreset(); return;} foundresetmarker: *(--r11)=0; backtranslate(r11,&telepxpos,&telepypos); telepypos-=(1<<8); telepctr=1; bonustimer=0x180; } void normreset() { telepctr=1; telepxpos=bonusxpos; telepypos=bonusypos; bonustimer=0; } void zonecheatread() { char r1=osbyte_7a(); // was _81(0) if ((r1<48)||(r1>56)) return; plzone=r1-48; } void cheatread() { if (osbyte_81(-282)==0xff) getmpmg(); if (osbyte_81(-283)==0xff) getrocket(); if (osbyte_81(-285)==0xff) screensave(); if (osbyte_81(-284)==0xff) prepstrength(); } void keyread() { int r4=-1; if (joyno) { int r0, r1; int v=swi_joystick_read(joyno-1,&r0,&r1); if (v) { nostickerr: message(32,32,0,1,"Can't see a joystick!"); r4=-1; joyno=0; } else { r4=-1; /* MOV R1,R0,ASL #24 CMN R1,#32<<24 BICLT R4,R4,#8; down CMP R1,#32<<24 BICGT R4,R4,#4; up BIC R0,R0,#&FF MOV R1,R0,ASL #16 CMN R1,#32<<24 BICLT R4,R4,#1; left CMP R1,#32<<24 BICGT R4,R4,#2; right TST R0,#1<<16 BICNE R4,R4,#16; fire TST R0,#1<<17 BICNE R4,R4,#4; up on fire button 2 */ } } nojoystick: if ((osbyte_81(leftkey)==0xff)||!(r4&1)) {if (++leftpress==0) leftpress=0xff;} else leftpress=0; if ((osbyte_81(rightkey)==0xff)||!(r4&2)) {if (++rightpress==0) rightpress=0xff;} else rightpress=0; if ((osbyte_81(upkey)==0xff)||!(r4&4)) {if (++uppress==0) uppress=0xff;} else uppress=0; if ((osbyte_81(downkey)==0xff)||!(r4&8)) {if (++downpress==0) downpress=0xff;} else downpress=0; if ((osbyte_81(firekey)==0xff)||!(r4&16)) {if (++fire==0) fire=0xff;} else fire=0; // (don't) use word-aligned property if (leftpress||rightpress||uppress||downpress||fire) keypressed=1; } alent fraudalent; void plmove() { if (shutdownctr!=0) shutdownctr++; if (shutdownctr==150) plzone=0; else if (shutdownctr!=0) deletepoint(); keyread(); //if (fire) goto cheatmove; if (snuffctr!=0) uppress=downpress=leftpress=rightpress=fire=0; vvec-=vvec>>5; hvec-=hvec>>5; if (leftpress!=rightpress) plface=(leftpress>rightpress)?1:0; int r2; if ((leftpress<4)&&(rightpress<4)) r2=1<<8; else r2=2<<8; if (leftpress>rightpress) r2=-r2; if (leftpress==rightpress) r2=0; if (falling<=4) hvec=r2; else hvec+=r2>>5; cheatins: if (downpress>=32) windctr=(1<<10); if (windctr) windcheck(); if (hvec>_speedlim) hvec=_speedlim; if (hvec<-_speedlim) hvec=-_speedlim; if (vvec>_speedlim) vvec=_speedlim; if (vvec<-_speedlim) vvec=-_speedlim; platypos=ypos; colchecktype=0; fraudalent.x=xpos; fraudalent.y=ypos; fraudalent.dx=hvec; fraudalent.dy=vvec; colcheck(&fraudalent); xpos=fraudalent.x; ypos=fraudalent.y; hvec=fraudalent.dx; vvec=fraudalent.dy; pluphit=platuphit; //if ((!)fire) bcheck(); pluphit=uphit; int dy=vvec; if (dy>(1<<12)) dy=1<<12; if (dy<-(1<<12)) dy=-(1<<12); xpos+=hvec; ypos+=dy; if ((xpos<=xlowlim)||(xposmax<=xpos)||(ypos<=ylowlim)||(yposmax<=ypos)) restartplayer(); int x=xpos, y=ypos; if (!snuffctr) { y+=(6<<8); vvec=dy; pllx=x-(_plwidth/2); plhx=x+(_plwidth/2); plly=y-(_plheight/2)+(plotterofs<<8); plhy=y+(_plheight/2); y=ypos-(6<<8); // - adjustment } else { fakecolch: plhx=plhy=0; pllx=plly=1; } fakeins: pladr1=translate(x,y); pladr2=pladr1+1; pladr3=pladr1+boardwidth; pladr4=pladr3+1; pladr5=pladr1+2*boardwidth; pladr6=pladr5+1; if (((falling==0)||(falling==0xff))&&(uppress!=0)) { if (downpress>uppress) vvec=-((0x100-(downpress-uppress))<<3); else vvec=-(19<<7); falling=1; bidforsound(_Playerchannel,_SampJump,0x5f,0x4600,0,0,4,0,CHUNK_JUMP); } char* r11; jumpins: r11=translate(xpos,ypos+(1<<8)); pladr7=r11+boardwidth; pladr8=pladr7+1; crumblecheck(pladr7); crumblecheck(pladr8); if ((*pladr7<_blim)&&(*pladr8<_blim)) { if (++falling==0xff) falling=0xfe; if (falling) // [else] standing on a platform { if (falling>1) if (vvec<(12<<8)) vvec+=(8<<4); } } else {nofall: falling=0; } nofallins:; fallins: if ((*pladr8>=_platlowlim+1)&&(*pladr8<=_plathighlim+1)&&(1&*pladr8)) pladr8[-1]=*pladr8-1; noplatrebuild: if ((*pladr7>=_platlowlim)&&(*pladr7<=_plathighlim)) { if (*pladr7!=_plathighlim) { hiddenplatctr=0; nohidplat: if (!(1&*pladr7)) {plplattoobj(pladr7); return;} } else { hiddenplatctr+=frameinc; if ((hiddenplatctr>=50)&&!(1&*pladr7)) {/* I added */hiddenplatctr=0; plplattoobj(pladr7); return;} } } fallinscont: if ((!(1&*pladr7))&&(*pladr7>=_teleplowlim)&&(*pladr7<=_telephighlim)) telep(); notelep: if ((*(pladr1-boardwidth)>=_platlowlim) &&(*(pladr1-boardwidth)<=(_plathighlim-1))) //not hidden platforms plplattoobj(pladr1-boardwidth); else notelepcont1: if ((*(pladr1-boardwidth+1)>=_platlowlim) &&(*(pladr1-boardwidth+1)<=(_plathighlim-1))) //not hidden platforms plplattoobj(pladr1-boardwidth+1); else notelepcont2: if (*pladr7==_extendno+1) { doextendfromleft: if (!extending) if (*(pladr7+1)==0) { int x,y; backtranslate(pladr7,&x,&y); makeobj(_Extender,x-(8<<8),y+(15<<8),1<<8,0,_extendno,0); extending=20; } } else if (*pladr8==_extendno+2) { doextendfromright: if (!extending) if (*(pladr8-1)==0) { int x,y; backtranslate(pladr8,&x,&y); makeobj(_Extender,x+(8<<8),y+(15<<8),-(1<<8),0,_extendno,0); extending=20; } } else if (*pladr7==_shutdownno) { *pladr7=14; shutdownctr=1; neuronctr++; bidforsoundforce(3,_Samprave,0x1f,(3<<8)|0x3000,(soundvol<<25)|0x1000, 0x100ff00,100,(3<<6)-96,CHUNK_SHUTDOWN_1); bidforsoundforce(2,_Samprave,0x1f,(2<<8)|0x3000,(soundvol<<25)|0x1000, 0x100ff00,100,(2<<6)-96,CHUNK_SHUTDOWN_2); bidforsoundforce(1,_Samprave,0x1f,(1<<8)|0x3000,(soundvol<<25)|0x1000, 0x100ff00,100,(1<<6)-96,CHUNK_SHUTDOWN_3); } //plattoins: playerfire(); } void windcheck() { if (*pladr1==0) return; if (!seeifwind(pladr4,seeifwind(pladr3,seeifwind(pladr2,seeifwind(pladr1,0))))) windctr-=64; if (--windctr<0) windctr=0; } int seeifwind(char* r1, int retval) { if (*r1==2) {hvec-=_windspeed*4; retval=1;} if (*r1==3) {hvec+=_windspeed*4; retval=1;} if (*r1==12) {vvec-=_windspeed; retval=1;} if (*r1==13) {vvec+=_windspeed; retval=1;} return retval; } void plattoobj(char* r0) {plattoobjins(r0,0);} void plattoobjins(char* r0,int r4) { char r1=*r0; if (1&r1) r0--; int x,y; backtranslate(r0,&x,&y); char r=(*r0-_platno+2*_Platbase)>>1; if (r==_Exploplat) r4=-1-(1>>5); /* >> ???; stop instant explosion*/ if (r>=_Downplat) r++; int v=makeobj(r,x+(8<<8),y+(15<<8),0,r4,(32<<16)+16,*r0); if (!v) {*r0=0; r0[1]=0;} } void plplattoobj(char* r0) { plattoobjins(r0,vvec>>3); vvec=0; plattoins: playerfire(); } void crumblecheck(char* r1) { if (*r1<_crumblestandlowlim) return; if (*r1>_crumblestandhighlim) return; if (falling<8) return; if (vvec<(2<<8)) return; (*r1)++; if (((*r1)&3)==0) *r1=0; } void telep() { initplx=xpos; initply=ypos; if (downpress<16) return; if (telepctr) return; char* r2=boardadr->contents; char* r3=r2+boardadr->width*boardadr->height; int r4=*pladr7; int r5=(r4&2)?1:-1; if ((leftpress>=64)&&(uppress==0)&&(fire!=0)&&(fire<=downpress)&&(rightpress>=64)) { r5=-r5; bidforsound(_Explochannel,_SampJump,0x7f,0x1000,0,0,50,0,CHUNK_TELEP_1); } normtelep: downpress=0; r4^=2; char* r1; for (r1=pladr7;;r1+=r5) { loop62: if (r1<=r2) {telepoffleft: return;} if (r1>=r3) {telepoffright: return;} if (*r1==r4) break; } telepfound: backtranslate(r1,&telepxpos,&telepypos); telepxpos+=(8<<8); telepypos-=(17<<8); telepctr=1; bidforsound(_Playerchannel,_Samporgan,0x7f,0x1000,0xff00,0x50000a00,25,127,CHUNK_TELEP_2); bidforsound(_Sparechannel,_Samporgan,0x7f,0x4000,0xff00,0x1000f400,25,-127,CHUNK_TELEP_3); } void playerfire() { if (snuffctr) return; if (blamctr) blamctr+=2; if (blamctr>=224) {goblam(); return;} if (plweapontype==0) return; if (fire) dofire(); else // I added this, can't find it in the source if (rocketflag) launchrocket(); } void goblam() { if (plweapontype==_rocketblamno) {rocketblam(); return;} for (int r9=32;r9>0;r9--) { loopa0:; int r3=r9-16; int r4=(r3<0)?-r3:r3; int r2, r0; if (plface==1) {r0=xpos-(20<<8); r2=(r4<<5)-(4<<8);} else {r0=xpos+(20<<8); r2=(4<<8)-(r4<<5);} makeproj(r0,ypos+(12<<8),r2,r3<<6,57,1<<15); } int r1,r3; if (plface==1) {r1=xpos-(24<<8); r3=-(1<<8);} else {r1=xpos+(24<<8); r3=(1<<8);} explogonopyroquiet(r1,ypos+(4<<8),r3,0,0,0/*r6?*/,0); plfired=1; blamctr=0; bidforsound(_Firechannel,_SampAtomExplo,0x7f,fullpitch,0,0,8,0,CHUNK_BLAM); } void rocketblam() { int r0,r1,r2,r3,r4; for (int r9=32;r9>0;r9--) { loopa1: r1=ypos+(2<<8); r3=*(rockettabadr+r9*6); if (plface==1) {r0=xpos-(12<<8); r4=1; r2=-(4<<8); r3=-r3;} else {r0=xpos+(12<<8); r4=0; r2=(4<<8);} r3*=2; if (r3>170) r4+=2; if (r3>60) r4+=2; if (r3<-60) r4-=2; if (r3<-170) r4-=2; // ??? CMP R3,#1 r4+=36; makeproj(r0+r2*2,r1+r3*2,r2,r3,r4,0x12<<8); } if (plface==1) {r1=xpos+(24<<8); r3=(1<<9);} else {r1=xpos-(24<<8); r3=-(1<<9);} explogonopyroquiet(r1,ypos-(8<<8),r3,0,1,/*r6*/0,0); plfired=1; blamctr=0; bidforsound(_Firechannel,_SampAtomExplo,0x7f,fullpitch,0,0,8,0,CHUNK_BLAM); rocketblamctr-=1; if ((rocketblamctr&(1<<7))==0) return; plweapontype=_rockbase; explogoquiet(xpos,ypos+(4<<8),0,-(1<<7),0,/*r6*/0,0); } void dofire() { if (plweapontype>=_rockbase) {firerocket(); return;} // no return firempmg: if (plweapontype==_mpmgblamno) {blamfire(); return;} if (framectr-firelastframe>1)-(plweaponspeed<<8):(hvec>>1)+(plweaponspeed<<8); int r5; switch (plweapontype&7) { case 2: r5=(1<<18)|(1<<10); break; case 3: r5=(1<<18)|(1<<10)|(1<<14); break; case 4: r5=(1<<18)|(1<<10)|(3<<13); break; case 5: r5=(1<<18)|(1<<10)|(1<<20)|(3<<12); r2>>=2; break; case 6: r5=(1<<18)|(1<<10)|(1<<11); break; case 7: r5=(1<<18)|(1<<10)|(9<<11); break; default: r5=1<<22; } makeproj(xpos+((plface==1)?-(14<<8):(14<<8)),ypos+(12<<8), r2,(random()&0xff)-0x7f,(plface==1)?31:30,r5); plfired=1; bidforsound(_Firechannel,_SampCannon,0x7e,fullpitch,0,0,2,0,CHUNK_FIRE); } void blamfire() { if (blamctr!=0) return; if (plweapontype==8) blamctr=128; else blamctr=1; bidforsound(_Firechannel,_Samprave,0x7e,fullpitch,0,(fullpitch<<17)+0x200,40,0,CHUNK_BLAMFIRE); } void firerocket() { if (plweapontype==_rocketblamno) {blamfire(); return;} rocketflag=1; int r2=2; if (plweapontype==_rockbase+6) r2=8; else if (plweapontype>=_rockbase+1) r2=4; if (plface==1) rocketctr+=r2; else rocketctr-=r2; if (rocketctr>=_rockettablen) rocketctr=0; if (rocketctr<0) rocketctr=_rockettablen-1; } void launchrocket() { if (framectr-firelastframe<(int)firerate) return; firelastframe=framectr; int r0,r1,r2,r3,r4; if (plface==1) {r0=xpos-(12<<8); r2=-(plweaponspeed<<8); r3=-*(rockettabadr+rocketctr); r4=1;} else {r0=xpos+(12<<8); r2=plweaponspeed<<8; r3=*(rockettabadr+rocketctr); r4=0;} r1=ypos+(2<<8); if (r3>170) r4+=2; if (r3>60) r4+=2; if (r3<-60) r4-=2; if (r3<-170) r4-=2; // ??? CMP R3,#1 r4+=36; int r6=plweapontype-_rockbase; if (r6>=6) r6=random()&7; int r5; switch (r6) { case 1: r5=(1<<19)|(1<<10)|(1<<14); // split break; case 2: r5=(1<<19)|(1<<10)|(3<<13); //split twice break; case 3: r5= (1<<10)|(9<<12) // burst |(5<<18) ; // a safe distance away break; case 4: r5=(7<<17)|(1<<10)|(0xd<<12); //dual burst break; case 5: r5=(1<<19)|(1<<10)|(0xf<<12); //dual burst /*(1<<18)*/ break; default: r5=1<<22; } r5|=(1<<15); makeproj(r0+r2+r2,r1+r3+r3,r2,r3,r4,r5); plfired=1; bidforsound(_Firechannel,_SampRocket,0x7e,fullpitch,0,0,2,0,CHUNK_ROCKET); rocketflag=0; } void getarms() { blamctr=0; plweapontype=0; } void getrocket() { plweapontype=_rockbase+(random()&7); plweaponspeed=2; firerate=12; blamctr=0; } void getmpmg() { plweapontype=_mpmgbase+(random()&7); plweaponspeed=8; firerate=4; blamctr=0; } alent* bulcolcheck(int x,int y) { bulcolchins: for (bulcolchent* r11=bulcolchtab;r11xmax>=x)&&(r11->ymax>=y)&&(x>=r11->xmin)&&(y>=r11->ymin)) bullethit: return r11->r0; } bulcolched: return NULL; } void colcheck(alent* al) { int x, y; dodgypointer=al; if (colchecktype!=0) {x=al->x; y=al->y;} else {x=xpos; y=ypos;} alonobj=colchecktype; if (colchecktype==0) //player check { platsandstr=NULL; colchtabuse=colchtab; colchptruse=colchptr; } else { colchtabuse=oldcolchtab; colchptruse=oldcolchptr; } //ADD R0,R0,R2 //ADD R1,R1,R3 xtemp=x; ytemp=y; int r4=24<<8, r5=32<<8; int xlo=x-(r4>>1); int ylo=y-(r5>>1); ylo+=8<<8; int xhi=xlo+r4; int yhi=ylo+r5; yhi+=2<<8; //so always in contact with platforms colchent* r11=colchtabuse-1; while (1) { colchcon: colchins: do { l10: r11++; if (r11>=colchptruse) { colched: return; } } while (!((r11->xmax>=xlo)&&(r11->ymax>=ylo)&&(xhi>=r11->xmin)&&(yhi>=r11->ymin))); if ((r11->ymax-ylo>=(1<<8)) //lim for plat on head -> can move horiz. &&(yhi-r11->ymin>=(3<<8))) //same for standing on plat { limr2: if (r11->xmax>xhi) if (al->dx>0) al->dx=0; if (r11->xmindx<0) al->dx=0; } nolimr2: if (((r11->xmax-xlo)>=(6<<8)) //margin for right on edge &&((xhi-r11->xmin)>=(6<<8))) //ditto { if ((yhi-r11->ymin)<=(16<<8)) //safety margin for platform under pl rise(r11->r0,al); if ((r11->ymax-ylo)<=(16<<8)) //ditto for plat on head platonhead(r11->r0,al); } } } void rise(alent* r6,alent* al) { if (colchecktype==2) //no rise {dontrise: al->dy=0; alonobj=1; return;} int r0=r6->type; if (r0==_Fastplatfire) platfire(r6); if ((r0==_Downplat)||(r0==_Fallplat)) //plat type 5 falls { platfall: if (r0==_Fallplat) r0=r6->dy; else r0=(1<<4)+r6->dy; if (r0<-(1<<5)) r0+=(1<<5); //plat is moving up - more speed if (r0>(1<<11)) r0=1<<11; r6->dy=r0; if (al->dy>r0) al->dy=r0; if (colchecktype==0) {falling=0xff; platsandstr=&r6->dy;} al->dy+=r6->y-(32<<8)-platypos; return; } if (r0>_Fastplat) //plat 6+ moves quickly r6->dy-=(1<<7); if (colchecktype==0) r0=pluphit; else r0=alheadcheck(); if (r0==0) r0=r6->dy /*hit*/ -(1<<5); else r0=headonroof(r6); if (r0>(1<<5)) r0-=1<<5; //plat is moving down - more speed if (r0<-(3<<10)) { r0=-(3<<10); platmaxspeed: if (r6->type==_Fastplatstop) { platstop: platsurefire(r6); r0=-(1<<9); } else if ((r6->type==_Fastplatexplo)||(r6->type==_Fastplatfire)) { platexplo: platdestroy(r6); return; } } platmaxspeedins:; r6->dy=r0; if (al->dy>=r0) al->dy=r0; if (colchecktype==0) {falling=0xff; platsandstr=&r6->dy;} al->dy+=(r6->y-(32<<8)-platypos); if (colchecktype!=0) {alonobj=1; al->dx>>=2;} } //B colchcon void platonhead(alent* r6, alent* al) { if (r6->type==_Exploplat) {platdestroy(r6); return;} if (r6->dy>0) r6->dy=-r6->dy; if (r6->dy>al->dy) r6->dy+=(al->dy>>1); platuphit=1; if (al->dy<0) al->dy=0; if (falling==0xff) { platsandwich: if ((colchecktype==0)&&(platsandstr!=NULL)) *platsandstr=(1<<8); } } //B colchcon void platdestroy(alent* r6) {explogo(r6->x,r6->y,0,-(1<<6),0,0,r6);} void platfire(alent* r6) { // R3: best negative (up) int r4=random(); if ((r4&(3<<24))==0) // firing rate { makebul(r6->x,r6->y+(16<<8),(r4&(0xfe<<2))-(0xfe<<1),-((r4&(0xfe<<12))>>11), _bulspritebase+8,1<<24); } platfireskip: return; } void platsurefire(alent* r6) { // R3: best negative (up) int r4=random(); makebul(r6->x,r6->y+(16<<8),(r4&(0xfe<<2))-(0xfe<<1),-((r4&(0xfe<<12))>>11), _bulspritebase+14,1<<24); } //.colchcon //LDMFD R13!,{R0,R1,R4,R5,R6,R11} //B colchins int headonroof(alent* r6) { int r0, r1; if (colchecktype!=0) { if ((random()&7)==0) dodgypointer->y=(random()&(1<<9))-(1<<8); skipalrandload: r0=1; r1=0; } else { r0=1<<8; r1=downpress; } skipalrand: r6->y=platypos+(32<<8); //force plat to player pos if (r1>64) r0=1<<11; if (r6->type==_Updownplat) r6->type=_Downplat; return r0; } int alheadcheck() { //ADD R1,R1,R3 char* r0=translate(xtemp,ytemp); return ((*(r0-boardwidth)>=_blim)||(*(r0-boardwidth+1)>=_blim)); } char* albcheck(alent* r11) { lefthit=righthit=uphit=downhit=0; // wipe all four alonplat=0; xtemp=r11->x-(1<<8); ytemp=r11->y-(8<<8); int r6=ytemp&(15<<8); char* z=translate(xtemp,ytemp+r11->dy); // up if ((*(z-boardwidth)>=_blim)||(*(z-boardwidth+1)>=_blim)) noup(r11); //down if ((*(z+boardwidth)>=_blim)||(*(z+boardwidth+1)>=_blim)) nodown(r11); if (r6!=(15<<8)) { z=translate(xtemp+r11->dx,ytemp); //left if ((*(z-boardwidth)>=_blim)||(*z>=_blim)||(*(z+boardwidth)>=_blim)) noleft(r11); //right if ((*(z-boardwidth+1)>=_blim)||(*(z+1)>=_blim)||(*(z+boardwidth+1)>=_blim)) noright(r11); } else { alshort: z=translate(xtemp+r11->dx,ytemp); if ((*z>=_blim)||(*(z+boardwidth)>=_blim)) noleft(r11); //right if ((*(z+1)>=_blim)||(*(z+boardwidth+1)>=_blim)) noright(r11); } albcheckins: z=translate(xtemp+r11->dx,ytemp+r11->dy); // up if ((*(z-boardwidth)>=_blim)||(*(z-boardwidth+1)>=_blim)) noup(r11); //down if ((*(z+boardwidth)>=_blim)||(*(z+boardwidth+1)>=_blim)) nodown(r11); char* r5=(z+(boardwidth<<1)); //signal position to caller if ((*r5<=_alplathighlim)&&(*r5>=_platlowlim)) alonplat=1; return r5; } void bcheck() { uphit=downhit=0; //AND R6,R1,#15<<8 xtemp=fraudalent.x=xpos; ytemp=fraudalent.y=ypos; fraudalent.dx=hvec; fraudalent.dy=vvec; char* r11=translate(fraudalent.x,fraudalent.y+fraudalent.dy); // up if ((*(r11-boardwidth)>=_blim)||(*(r11-boardwidth+1)>=_blim)) noup(&fraudalent); //down if ((*(r11+boardwidth)>=_blim)||(*(r11+boardwidth+1)>=_blim)) nodown(&fraudalent); if ((*(r11+boardwidth*2)>=_blim)||(*(r11+boardwidth*2+1)>=_blim)) nodownifplat(&fraudalent); //fallinggap(&fraudalent); // CMP R6,#15<<8 // not sure how the original game manages without fallinggap's return value. int fg=fallinggap(&fraudalent); if ((!fg)&&((ytemp&(15<<8))!=(15<<8))) { r11=translate(fraudalent.x+fraudalent.dx,fraudalent.y); char* r10=translate(fraudalent.x+fraudalent.dx,fraudalent.y/*+(4<<8)*/); // 4<<8 was commented out //left if ((*(r10-boardwidth)>=_blim)||(*(r11)>=_blim)||(*(r11+boardwidth)>=_blim)) noleft(&fraudalent); //right if ((*(r10-boardwidth+1)>=_blim)||(*(r11+1)>=_blim)||(*(r11+boardwidth+1)>=_blim)) noright(&fraudalent); } else if (fg==-1) { r11=translate(fraudalent.x+fraudalent.dx,fraudalent.y); if ((*(r11-boardwidth)>=_blim)||(*r11>=_blim)) noleft(&fraudalent); //right if ((*(r11-boardwidth+1)>=_blim)||(*(r11+1)>=_blim)) noright(&fraudalent); } else { shorT: r11=translate(fraudalent.x+fraudalent.dx,fraudalent.y); if ((*(r11)>=_blim)||(*(r11+boardwidth)>=_blim)) noleft(&fraudalent); //right if ((*(r11+1)>=_blim)||(*(r11+1+boardwidth)>=_blim)) noright(&fraudalent); } bcheckins: r11=translate(fraudalent.x+fraudalent.dx,fraudalent.y+fraudalent.dy); // up if ((*(r11-boardwidth)>=_blim)||(*(r11-boardwidth+1)>=_blim)) noup(&fraudalent); //down if ((*(r11+boardwidth)>=_blim)||(*(r11+boardwidth+1)>=_blim)) nodown(&fraudalent); xpos=fraudalent.x; ypos=fraudalent.y; hvec=fraudalent.dx; vvec=fraudalent.dy; } void noleft(alent* r11) { if (r11->dx<0) { r11->dx=0; // -(xtemp&0xfff); // 0; lefthit=1; } } void noright(alent* r11) { if (r11->dx>0) { r11->dx=0; // ((0xfff-xtemp)&0xfff); // 0; righthit=1; } } int fallinggap(alent* re) { char* r11=translate(xtemp+re->dx,ytemp/*+dy*/-((re->dy<0)?(15<<8):0)); int r1=(re->dx<0)?0:1; if ((*(r11+r1)<_blim)&&(*(r11+boardwidth+r1)<_blim)) { stopfall: if (re->dy>0) { stopfalldown: if (*(r11-boardwidth+r1)<_blim) return 0; if (*(r11+boardwidth*2+r1)<_blim) return 0; if (*(r11+boardwidth*2+(1-r1))<_blim) {nodown(re); return 1;} } else if (re->dy<0) { stopfallup: if ((ytemp&(15<<8))>(8<<8)) return 0; if (*(r11-boardwidth+r1)<_blim) return 0; if (*(r11+boardwidth*2+r1)<_blim) return 0; if (*(r11+boardwidth*2+(1-r1))<_blim) {noup(re); return -1;} } } return 0; } void nodown(alent* r11) { if (r11->dy>0) { r11->dy=((15<<8)&((16<<8)-ytemp))-1; if (r11->dy<0) r11->dy=0; } nodownrel: downhit=1; } void nodownifplat(alent* r11) { if (falling!=0xff) return; if (r11->dy>0) { r11->dy=((15<<8)&((16<<8)-ytemp))-1; if (r11->dy<0) r11->dy=0; } //nodownrel: downhit=1; } void noup(alent* r11) { if (r11->dy>=0) return; r11->dy=-((ytemp+(1<<8))&(15<<8)); uphit=1; } char* translate(int r0,int r1) {return (char*)boardadr->contents+(r0>>12)+(r1>>12)*boardadr->width;} char* fntranslate(int r0,int r1) {return (char*)boardadr->contents+((r0+(8<<8))>>12)+((r1-(8<<8))>>12)*boardadr->width;} void backtranslate(char* r, int* x, int* y) { int r0=r-boardadr->contents; int r1=boardwidth; *x=(r0%r1)<<12; *y=(r0/r1)<<12; } /*LDR R1,[R12,#boardadr] ADD R1,R1,#boardhdrlen SUB R0,R0,R1 LDR R1,[R12,#boardwidth] MOV R2,#0 MOV R3,#0 MOV R4,#1<<31 .l9 MOVS R0,R0,ASL #1 ADC R3,R3,R3 CMP R3,R1 SUBGE R3,R3,R1 ORRGE R2,R2,R4 MOVS R4,R4,LSR #1 BNE l9 MOV R0,R3,LSL #12 MOV R1,R2,LSL #12 MOV PC,R14*/ void bonuscheck() { if (snuffctr) { deadbonuscheck: atombombctr=0; electrocuting=0; deadbonuslim(pladr1); deadbonuslim(pladr2); deadbonuslim(pladr3); deadbonuslim(pladr4); return; } atombombctr=0; electrocuting=0; plbombcheck(pladr1); bonuslim(pladr1); weaponcheck(pladr1); plbombcheck(pladr2); bonuslim(pladr2); weaponcheck(pladr2); plbombcheck(pladr3); bonuslim(pladr3); weaponcheck(pladr3); plbombcheck(pladr4); bonuslim(pladr4); weaponcheck(pladr4); } void weaponcheck(char* r5) { if ((*r5<_weaplowlim)||(*r5>_weaphighlim)) return; plweapontype=*r5-_weaplowlim+1; *r5=0; if (plweapontype>=_rockbase) {plweaponspeed=2; firerate=12;} else {plweaponspeed=8; firerate=4;} rocketblamctr=5; int r2=plweapontype-1; int r7, r0; if ((r2&7)==7) {r7=_scoresprbase+12; r0=4000;} else if (r2&4) {r7=_scoresprbase+10; r0=2000;} else {r7=_scoresprbase+9; r0=1000;} plscoreadd+=r0; makeobj(_Scoreobj,xpos,ypos,(random()&(0xfe<<1))-(0xfe)+(hvec>>2), -(random()&(0xfe<<2)),60+(r7<<8),666); bidforsound(_Playerchannel,(r7==_scoresprbase+12)?_Samprave:_Samporgan, 0x7f,0x3000,0xff00,(r7==_scoresprbase+12)?0x60000800:0x60000200,10,127, (r7==_scoresprbase+12)?CHUNK_WEAPON_3:CHUNK_WEAPON_1); bidforsound(_Sparechannel,(r7==_scoresprbase+12)?_Samprave:_Samporgan, 0x7f,0x3800,0xff00,(r7==_scoresprbase+12)?0x60000800:0x60000200,10,-127, (r7==_scoresprbase+12)?CHUNK_WEAPON_4:CHUNK_WEAPON_2); /* XXX Original code also kills message so the same one is never redisplayed */ switch ((plweapontype-1)&15) { case 0: message(320,192,-3,0,"Standard Mini-Gun"); break; case 1: message(320,192,-3,0,"Mini-Gun with spray"); break; case 2: message(320,192,-3,0,"Five Stream Gun"); break; case 3: message(320,192,-3,0,"Fast 5 way - zap those nasties!"); break; case 4: message(320,192,-3,0,"A weird one!"); break; case 5: message(320,192,-3,0,"Three Way Blitzer"); break; case 6: message(320,192,-3,0,"Blitzing Five Way - Lets Party"); break; case 7: message(320,192,-3,0,"MegaBlam 5000 Mini-Gun!!!!"); break; case 8: message(320,192,-3,0,"Standard Rocket Launcher"); break; case 9: message(320,192,-3,0,"Twin Rocket Launcher"); break; case 10: message(320,192,-3,0,"Quad Launcher - Open Fire!"); break; case 11: message(320,192,-3,0,"Launcher with starburst"); break; case 12: message(320,192,-3,0,"Twin rockets with starburst - let's see some fireworks!"); break; case 13: message(320,192,-3,0,"Quad Launcher with starburst! Arrgghhhh!!!!"); break; case 14: message(320,192,-3,0,"A Pot Pourri Rocket Launcher - mix and match!"); break; case 15: message(320,192,-3,0,"MegaBlam Rocket Launcher!!!! Six Shots Only!"); break; } } void plbombcheck(char* r5) { int r1=bombcheck(r5); if ((*r5>=_targetlowlim)&&(*r5<=_targethighlim)) r1=normalbomb(r5); nopltarg: plstrength-=r1; } int bombcheck(char* r5) { char r0=*r5; if ((r0<_bomblowlim)||(r0>_bombhighlim)) return 0; if ((r0==_fuelairno)||(r0==_fuelairno+1)) return fuelairbomb(r5); if (r0>=_boobylowlim) return boobybomb(r5); if ((r0<_atomlowlim)||(r0>_atomhighlim)) return normalbomb(r5); return atombomb(r5); } int atombomb(char* r5) // Caution - recursive routine { if (atombombctr>=0x1f) {atomabandon: return atomloss;} atombombctr++; char r0=(*r5)-_atomlowlim; if (r0&1) r5-=1; if (r0&2) r5-=boardwidth; *r5=0; *(r5+1)=0; *(r5+boardwidth)=0; *(r5+boardwidth+1)=0; // delete this a-bomb procatom(r5-boardwidth); procatom(r5-boardwidth+1); procatom(r5-1); procatom(r5+2); procatom(r5+boardwidth-1); procatom(r5+boardwidth+2); procatom(r5+2*boardwidth); procatom(r5+2*boardwidth+1); int x,y; backtranslate(r5,&x,&y); atomexplogo(x+(8<<8),y+(24<<8),0,0,0,0,0 /*signal no existing object*/); return atomloss; } void procatom(char* r5) { char r0=*r5; if ((r0>=_targetlowlim)&&(r0<=_targethighlim)) shoottarget(r5); noatomtarget: *r5=0; if ((r0<_atomlowlim)||(r0>_atomhighlim)) return; *r5=r0; //replace bomb segment atombomb(r5); } int fuelairbomb(char* r5) { deletetwin(r5); char* r0=r5-boardwidth; *r0=_gaslowlim; *(r0+1)=_gaslowlim; if ((*fueltabread==0)||(*(fueltabread+1)==0)) *(fueltabread+2) = 0; // replace end marker if overwritten *fueltabread=r0; *(fueltabread+1)=r0+1; fueltabctr=_fuelairduration; // fuel-air duration bidforsound(_Explochannel,_SampHiss,0x6f,0x6000,0xff80,0x2000ff00,50,0,CHUNK_FUELAIR); return 0; } int normalbomb(char* r5) { elecdestroy(r5); *r5=0; int x,y; backtranslate(r5,&x,&y); explogo(x,y+(8<<8),0,0,0,0,0 /*signal no existing object*/); return bombloss; } int boobyvectab[] = {-0x400, -0x80, 0x400, -0x80, 0, -0x400, 0, 0x400}; int boobybomb(char* r5) { int* r6=boobyvectab+2*((*r5-_boobylowlim)&3); *r5=0; int x,y; backtranslate(r5,&x,&y); explogonopyro(x,y+(8<<8),-(r6[0]>>2),-(r6[1]>>2), 0,0,0/*;signal no existing object*/); makeobj(_Booby,x,y+(8<<8),r6[0],r6[1],0,0); return bombloss; } void bonusobjgot(alent* r11) { r11->dx=(random()&(0xfe<<1))-0xfe; r11->dy=-(random()&(0xfe<<2))-(1<<9); int r0=r11->r6; sortbonus(r0); r0=(r0-_bonuslow+2)>>1; if (r0>10) r0=10; plscoreadd+=100*r0; r11->r5=0xf60+(r0<<8); r11->type=_Scoreobj; bidforsound(_Playerchannel,_SampBonus,0x6e,0x3000+(_Scoreobj<<6),0,0,3,0,CHUNK_OBJGOT[11]); } void bonuslim(char* r5) { if ((*r5>=_neuronlowlim)&&(*r5<=_neuronhighlim)) { plzone=*r5-(_neuronlowlim-1); *r5=0; initplx=xpos; initply=ypos; return; } noneuron: if ((*r5>=_eleclowlim)&&(*r5<=_elechighlim)) {electrocute(r5); return;} bonuslimcont: if (*r5<_bonuslow) return; if (*r5>_megabonuslim) return; if (*r5>_bonushigh) megabonus(r5); else bonusgot(r5); // was bonusgot } void deadbonuslim(char* r5) { char r0=*r5; if ((r0<_bonushigh-2)||(r0>_bonushigh)) return; bonusgot(r5); } void bonusgot(char* r5) { // MOV R1,R0 ??? char r0=*r5; sortbonus(r0); *r5=0; r0=(((int)r0)-_bonuslow+2)>>1; if (r0>10) r0=10; addbonus(r5,r0); bidforsound(_Playerchannel,_SampBonus,0x6e,(r0<<6)+0x3000,0,0,3,0,CHUNK_OBJGOT[r0-1]); } void addbonus(char* r5, int r0) { plscoreadd+=100*r0; int x,y; backtranslate(r5,&x,&y); makeobj(_Scoreobj,x,y,(random()&(0xfe<<1))-(0xfe)+(hvec>>2), -(random()&(0xfe<<2)),0xf60+(r0<<8),*r5); } void sortbonus(char r0) { r0-=_bonuslow; if ((r0==13)||(r0==14)) { bonusstrength: lagerctr+=(r0==14)?150:50; laststrength=plstrength; } if (r0==bonusctr) { advancebonus: bonusctr++; //sortreplot: bonusreplot=28; return; } if (r0==15) { bonusctr=0; if (snuffctr) if (plstrength>0) { prepstrength(); message(48,24,0,0.5,"A potion and Skull!"); message(48,176,0,-0.5,"Rise from the dead!"); } sortreplot: bonusreplot=28; } return; } void bonusnumb(int r9) { int r6=-1; for (r9&=0xff;r9>0;r9-=(r6+1)) { loopc3: r6=random()&3; makeobj(_Scoreobj,xpos,ypos,(hvec>>2)+((random()&(0xfe<<1))-0xfe), -(random()&(0xfe<<2)),0xf60+(10<<8)+(r6<<8),r6); } } void bonus1() {bonusnumb(10); message(96,224,0,-2,"Bonus 10000"); plscoreadd+=10000;} void megabonus(char* r5) { char r0=*r5; *r5=0; bidforsound(_Playerchannel,_SampBonus,0x7e,0x2200,0,0,5,127,CHUNK_BONUS_1); bidforsound(_Sparechannel,_SampBonus,0x7e,0x2000,0,0,5,-127,CHUNK_BONUS_2); if (r0==_bonushigh+1) { bonus1: bonusnumb(10); message(96,224,0,-2,"Bonus 10000"); plscoreadd+=10000; } else if (r0==_bonushigh+2) { bonus2: bonusnumb(20); message(96,224,0,-2,"Bonus 20000"); plscoreadd+=20000; } else if (r0==_bonushigh+3) { bonus3: bonusnumb(30); message(96,224,0,-2,"Bonus 30000"); plscoreadd+=30000; } else if (r0==_bonushigh+4) { bonus5: bonusnumb(50); message(96,224,0,-2,"Bonus 50000"); plscoreadd+=50000; } else { bonus10: bonusnumb(100); message(96,224,0,-2,"Bonus 100000"); plscoreadd+=100000; } return; } void electrocute(char* r5) { electrocuting=1; int x,y; backtranslate(r5,&x,&y); explogonopyro(x,y+(16<<8),(random()&(0xfe<<2))-(0xfe<<1), (random()&(0xfe<<2))-(0xfe<<1),0,0,0); } void destroy(char* r5) { /*LDR R1,[R12,#boardlowlim] CMP R0,R1 ??? LDR R1,[R12,#boardhighlim] CMP R0,R1*/ bombcheck(r5); char r0=*r5; if ((r0==_gaslowlim)||(r0==_gashighlim)) {normalbomb(r5); return;} if ((r0>=_bonuslow)&&(r0<=_bonushigh)) { int x,y; backtranslate(r5,&x,&y); y+=(8<<8); makeobj(_Dyingbonus,x,y+(7<<8),0,0,(*r5)|(1<<20),666); *r5=0; } noshootbonus: if ((r0>=_targetlowlim)&&(r0<=_targethighlim)) {shoottarget(r5); return;} noshoottarget: if ((r0>=_crumblelowlim)&&(r0<=_crumblehighlim)) if (0==(3&(++(*r5)))) *r5=0; nocrumble: return; } void shoottarget(char* r5) { char r3=*r5; *r5=0; plscoreadd+=targetscore; if (r3>=_powertarget) elecdestroy(r5); int x,y; backtranslate(r5,&x,&y); explogo(x,y+(8<<8),0,0,0,0,0 /* signal no existing object */); makeobj(_Scoreobj,x,y,(hvec>>2)+((random()&(0xfe<<1))-0xfe), -(random()&(0xfe<<2)),0xf60+((targetscore/100)<<8),666); } void elecdestroy(char* r5) { eleccheck(r5-boardwidth); eleccheck(r5-1); eleccheck(r5+1); eleccheck(r5+boardwidth); } void eleccheck(char* r10) { char r0=*r10; if ((r0<_eleclowlim)||(r0>_elechighlim)) return; int r4=(r0>=_elecvertlowlim)?boardwidth:1; elecdelete(r4,r10); elecdelete(-r4,r10); } void elecdelete(int r4,char* r10) { char r2=_eleclowlim; for (;(r2>=_eleclowlim)&&(r2<=_elechighlim);r2=*(r10+=r4)) loop78: *r10=0; } void deletetwin(char* r5) { if ((*r5)&1) *(r5-1)=0; else *(r5+1)=0; *r5=0; } void deletepoint() { for (int r3=16;r3>0;r3--) { delloop:; dodeletepoint:; int x,y; x=xpos+(((random()&15)+(random()&7)-11)<<12); if (x<(1<<12)) return; y=ypos+(((random()&15)-7)<<12); if (y<(1<<12)) return; if (x>xposmax-(1<<12)) return; if (y>yposmax-(1<<12)) return; x&=~0xfff; y&=~0xfff; char* z=translate(x,y); if (*z==0) return; *z=0; makeobj(_Dyingbonus,x,y+(15<<8),0,0,r3|(1<<20),666); } } void mazeplot() { writeclip(); backdrop(); int r0=(xpos-(144<<8))>>8; int r1=(ypos-(96<<8))>>8; int r8=15-(r0&15); int r9=15-(r1&15); int r5=0, rF=0, r7=(r1>>4); if (r7<0) {r5=-r7; r7=0;} // Draw midground elements for (;/*ins2:*/ (r5<14)&&(r7height);r5++,r7++,rF++) { int r4=0,rf=0,r6=((xpos>>8)-144)>>4; if (r6<0) {r4=-r6; r6=0;} for (;/*ins1:*/ (r4<21)&(r6width);/*skip1:*/ r4++,r6++,rf++) { r0=*(boardadr->contents+boardwidth*r7+r6); if ((r0>=8)&&(r0<12)) fspplot(blockadr,r0,(r4<<4)-rf+10+r8,(r5<<4)-rF+7+r9);}} // Now foreground ones r5=0, r7=(r1>>4); if (r7<0) {r5=-r7; r7=0;} for (;/*ins2:*/ (r5<14)&&(r7height);r5++,r7++) { l2:; int r4=0,r6=((xpos>>8)-144)>>4; if (r6<0) {r4=-r6; r6=0;} for (;/*ins1:*/ (r4<21)&(r6width);/*skip1:*/ r4++,r6++) { l1: r0=*(boardadr->contents+boardwidth*r7+r6); if ((r0==0)||((r0>=8)&&(r0<12))) continue; // was if (r0==0) if ((r0&~7)==_neuronlowlim) r0=_neuronlowlim+((framectr&(7<<2))>>2); if (r0<=_crumblestandhighlim) { if (r0>=_crumblelowlim) r0&=~8; //alter for crumbles if ((r0>=_animlowlim)&&(r0<=_animhighlim)) { int r1=random()&7; if ((r0==_gaslowlim)||(r0==_gashighlim)) r0^=r1>>2; else r0^=r1>>1; }} noanimate: if ((r0>=_weaplowlim+1)&&(r0<=_weaplowlim+6)) r0=_weaplowlim+1; fspplot(blockadr,r0,(r4<<4)+r8,(r5<<4)+r9); } } skip2:; } #define FORTYEIGHT (48*4) #define TTOFFSET (hbytes*32) char backdrop_to_blit[FORTYEIGHT]; void backdrop() { // swi_fastspr_clearwindow(); SDL_LockSurface(ArcScreen); screentop=screenuse+hbytes*8+4*16; int r3=((xpos>>8)-(xpos>>10)+3072-768); // parallax backuse=backadr+(r3&3)*1536*sizeof(Uint32); int r2=11-((r3>>2)%12); // self-modifying code went here on ARM: // modpos[0]=backtab[0]; modpos[1]=backtab[1]; int r4=0x1f&((ypos>>8)-(ypos>>10)); // parallax for (int r3=0;r3<32;r3++) { l4: char* r14=screentop+r3*hbytes; char* r12=backuse+r4*FORTYEIGHT; modpos: memcpy(backdrop_to_blit+r2*4*4,r12,(12-r2)*4*4); memcpy(backdrop_to_blit,r12+(12-r2)*4*4,r2*4*4); memcpy(r14 ,backdrop_to_blit,FORTYEIGHT); memcpy(r14+FORTYEIGHT ,backdrop_to_blit,FORTYEIGHT); memcpy(r14+FORTYEIGHT*2,backdrop_to_blit,FORTYEIGHT); memcpy(r14+FORTYEIGHT*3,backdrop_to_blit,FORTYEIGHT); memcpy(r14+FORTYEIGHT*4,backdrop_to_blit,FORTYEIGHT); memcpy(r14+FORTYEIGHT*5,backdrop_to_blit,FORTYEIGHT); r14+=TTOFFSET; memcpy(r14 ,backdrop_to_blit,FORTYEIGHT); memcpy(r14+FORTYEIGHT ,backdrop_to_blit,FORTYEIGHT); memcpy(r14+FORTYEIGHT*2,backdrop_to_blit,FORTYEIGHT); memcpy(r14+FORTYEIGHT*3,backdrop_to_blit,FORTYEIGHT); memcpy(r14+FORTYEIGHT*4,backdrop_to_blit,FORTYEIGHT); memcpy(r14+FORTYEIGHT*5,backdrop_to_blit,FORTYEIGHT); r14+=TTOFFSET; memcpy(r14 ,backdrop_to_blit,FORTYEIGHT); memcpy(r14+FORTYEIGHT ,backdrop_to_blit,FORTYEIGHT); memcpy(r14+FORTYEIGHT*2,backdrop_to_blit,FORTYEIGHT); memcpy(r14+FORTYEIGHT*3,backdrop_to_blit,FORTYEIGHT); memcpy(r14+FORTYEIGHT*4,backdrop_to_blit,FORTYEIGHT); memcpy(r14+FORTYEIGHT*5,backdrop_to_blit,FORTYEIGHT); r14+=TTOFFSET; memcpy(r14 ,backdrop_to_blit,FORTYEIGHT); memcpy(r14+FORTYEIGHT ,backdrop_to_blit,FORTYEIGHT); memcpy(r14+FORTYEIGHT*2,backdrop_to_blit,FORTYEIGHT); memcpy(r14+FORTYEIGHT*3,backdrop_to_blit,FORTYEIGHT); memcpy(r14+FORTYEIGHT*4,backdrop_to_blit,FORTYEIGHT); memcpy(r14+FORTYEIGHT*5,backdrop_to_blit,FORTYEIGHT); r14+=TTOFFSET; memcpy(r14 ,backdrop_to_blit,FORTYEIGHT); memcpy(r14+FORTYEIGHT ,backdrop_to_blit,FORTYEIGHT); memcpy(r14+FORTYEIGHT*2,backdrop_to_blit,FORTYEIGHT); memcpy(r14+FORTYEIGHT*3,backdrop_to_blit,FORTYEIGHT); memcpy(r14+FORTYEIGHT*4,backdrop_to_blit,FORTYEIGHT); memcpy(r14+FORTYEIGHT*5,backdrop_to_blit,FORTYEIGHT); r14+=TTOFFSET; memcpy(r14 ,backdrop_to_blit,FORTYEIGHT); memcpy(r14+FORTYEIGHT ,backdrop_to_blit,FORTYEIGHT); memcpy(r14+FORTYEIGHT*2,backdrop_to_blit,FORTYEIGHT); memcpy(r14+FORTYEIGHT*3,backdrop_to_blit,FORTYEIGHT); memcpy(r14+FORTYEIGHT*4,backdrop_to_blit,FORTYEIGHT); memcpy(r14+FORTYEIGHT*5,backdrop_to_blit,FORTYEIGHT); if (++r4>31) r4=0; } SDL_UnlockSurface(ArcScreen); } int escapehandler() { frameinc=1; showchatscreen(); swi_fastspr_setclipwindow(20,20,319-20,255-20); swi_fastspr_clearwindow(); wipetexttab(); message(36,40-256,0,4,"§ Game Interrupted §"); message(32-256,72,4,0,"Please select action"); message(46+256,104,-4,0,"ESC - Abandon game"); message(40-256,136,4,0,"Q - lose this life"); message(40,168+256,0,-4,"R - Return to Game"); message(40,200+256,0,-4,"O - Alter Options"); showtext(); osbyte_7c(); //clear escape for (int r9=64;swi_readescapestate()==0;) { loopb8: swi_blitz_wait(0); if (r9!=0) { r9--; switchbank(); switchfspbank(); swi_fastspr_clearwindow(); texthandler(); } esctextstop: if (osbyte_81(-113)) {loselife(); return 0;} if (osbyte_81(-111)) {adjustopt(); return 0;} if (osbyte_81(-114)) {rejoin(); return 0;} } osbyte_7c(); return 1; } void loselife() { lagerctr=0; plstrength=0; //no return rejoin(); } void rejoin() { wipetexttab(); showgamescreen(); } void adjustopt() { options(1); // mark as in game rejoin(); } void copyscreen() { // char* r0=screenstart; // char* r2=screenstart+modesize; //for (int r1=0x14000;r1>0;r1-=1) // loop30: *(r2++)=*(r0++); swi_blitz_screenflush(); } void setfullclip() { cliplx=_lowx; cliply=_lowy; cliphx=_highx; cliphy=_highy; writeclip(); return; } void writeclip() { static SDL_Rect clip; clip.x=cliplx; clip.y=cliply; clip.w=cliphx-cliplx; clip.h=cliphy-cliply; SDL_SetClipRect(ArcScreen,&clip); } void releaseclip() { SDL_SetClipRect(ArcScreen, NULL); // 0, 0, 319, 255 ; size of mode } void restartplayer() { xpos=initplx; ypos=initply; screenwakeup(); telepctr=33; //bonusctr=0; (commented out in original) bonusreplot=28; pladr1=0; windctr=0; bonustimer=0; rocketblamctr=0; shutdownctr=0; if (neuronctr>=_neuronstoget) { completedzone: message(114,64,0,0,"WELL DONE!"); message(44,96,0,0,"You have completed"); if (mentalzone==3) message(114,128,0,0,"The game!!!"); else message(114,128,0,0,"This zone!"); lives=0; snuffctr=1; } return; } void findplayer() { bonusctr=0; char* r5=NULL; for (int r3=boardadr->width*boardadr->height;r3>0;r3--) { loop60: if (*(boardadr->contents-1+r3)==_markerno) {*(boardadr->contents-1+r3)=0; r5=boardadr->contents-1+r3; } } int x,y; if (r5) backtranslate(r5,&x,&y); else x=y=64<<8; initplx=x; initply=y-(1<<8); } void showgamescreen() { decomp(gamescreenadr); copyscreen(); scorewiperead(); showlives(); } void showlives() { releaseclip(); fspplot(charsadr,lives&7,44,234); switchbank(); switchfspbank(); fspplot(charsadr,lives&7,44,234); writeclip(); } void showchatscreen() { decomp(chatscreenadr); copyscreen(); } void showchatscores() { decomptonot(chatscreenadr); } int palette[256], alt_palette[256]; void init_palette() { for (int i=0;i<256;i++) palette[i] = 0xff000000 // opaque + ((i&0x80)?0x880000:0) + ((i&0x40)?0x8800:0) + ((i&0x20)?0x4400:0) + ((i&0x10)?0x88:0) + ((i&0x08)?0x440000:0) + ((i&0x04)?0x44:0) + (i&0x03)*0x111111; for (int i=0;i<256;i++) alt_palette[i] = 0xff000000 // opaque + ((i&0x80)?0x88:0) + ((i&0x40)?0x8800:0) + ((i&0x20)?0x4400:0) + ((i&0x10)?0x880000:0) + ((i&0x08)?0x44:0) + ((i&0x04)?0x440000:0) + (i&0x03)*0x111111; } void decomptonot(char* r11) {decompins(screenuse,r11);} void decomp(char* r11) {decompins(screenstart,r11);} void decompins(char* rr10,char* r11) { static SDL_Rect from; static SDL_Rect to; from.x = from.y = to.x = to.y = 0; to.w = ArcScreen->w; to.h = ArcScreen->h; from.w = DecompScreen->w; from.h = DecompScreen->h; SDL_LockSurface(DecompScreen); Uint32* r10=(Uint32*)DecompScreen->pixels; //(Uint32*)rr10; Uint32* r9=0x14000+r10; r11+=68; while (r9>r10) // > or >=? { loopb4:; char r0=*(r11++); if (r0&0x80) { sequence:; Uint32 s=palette[0xff&*(r11++)]; for (int r3=(r0&0x7f)+2;(r9>r10)&&(r3!=0);r3--) loopb6: *(r10++)=s; } else pattern: for (int r3=(r0&0x7f)+1;(r9>r10)&&(r3!=0);r3--) loopb5: *(r10++)=palette[0xff&*(r11++)]; decompdone:; } SDL_UnlockSurface(DecompScreen); releaseclip(); //SDL_SoftStretch(ArcScreen,NULL,DecompScreen,NULL); SDL_BlitSurface(DecompScreen, NULL, ArcScreen, NULL); writeclip(); } void clearkeybuf() { do clearkbloop:; while (osbyte_79(0)!=-1); do clearkbloop2:; while (osbyte_81(1)!=-1); } const int keydefs[] = { -SDLK_z, -SDLK_x, -SDLK_SEMICOLON, -SDLK_PERIOD, -SDLK_RETURN}; void setdefaults() { checkifarm3(); soundtype=2; soundquality=(arm3==0)?0:1; soundvol=0x7f; musicvol=0x7f; leftkey=keydefs[0]; rightkey=keydefs[1]; upkey=keydefs[2]; downkey=keydefs[3]; firekey=keydefs[4]; gearchange=(arm3==0)?0:1; explospeed=(arm3==0)?2:1; fullscreen=0; joyno=0; mentalzone=1; initials[0] = 'P'; initials[1] = 'S'; initials[2] = 'Y'; } void soundupdate() { return;} /* .soundupdate STMFD R13!,{R14} LDRB R5,[R12,#soundtype] LDRB R6,[R12,#soundquality] CMP R5,#0 BEQ soundkill MOV R0,#2 SWI "XSound_Enable" MOV R0,#129 MOV R1,#0 MOV R2,#&FF SWI "OS_Byte" MOV R8,R1 MOV R0,#8; channels CMP R5,#1 MOVEQ R0,#4 MOV R1,#208 MOV R2,#96 TST R6,#1 MOVNE R2,#48 CMP R8,#&A3 MOVLT R2,#0; RISC OS 2 bug MOV R3,#0 MOV R4,#0 SWI "XSound_Configure" ADR R0,sptunenorm TST R6,#1 ADRNE R0,sptunehq CMP R8,#&A3 ADRLT R0,sptunehq SWI "XOS_CLI" LDRB R0,[R12,#soundquality] TST R0,#1 MOV R0,#6 MOVNE R0,#12 SWI "XSound_QBeat" MOV R0,#&1000 SWI "XSound_QTempo" LDRB R0,[R12,#musicvol] SWI "XBodgeMusic_Volume" LDRB R0,[R12,#soundquality] MOV R0,R0,LSR #1 MOV R1,#1 SWI "XStasis_Control" LDMFD R13!,{PC} .sptunenorm EQUS "StasisTune &8000" EQUB 0 .sptunehq EQUS "StasisTune &4000" EQUB 0 ALIGN .soundkill MOV R0,#1 SWI "XSound_Enable" LDMFD R13!,{PC} */ int options(int go) { gameon=go; savedornot=0; return optionins(); } int optionins() { while (1) { clearkeybuf(); wipetexttab(); showchatscreen(); swi_fastspr_setclipwindow(20,20,319-20,255-20); swi_fastspr_clearwindow(); message(128,48,0,0,"Options"); message(32,96,0,0,"1. Define Controls"); message(32,128,0,0,"2. Tune Game Options"); message(88,224,0,0,"Fire - Play"); if (gameon==0) message(32,160,0,0,"3. Choose Mental Zone"); // if (savedornot==1) message(32,192,0,0,"4. Save Settings"); showtext(); swi_blitz_wait(20); // switch (readopt((gameon==0)?3:2)) { case -1: optionexit: return 1; case 1: choosecontrol(); dosaveconf(); break; case 2: tunegame(); dosaveconf(); break; case 3: if (gameon==0) {getzone(); dosaveconf();} break; //case 4: if (savedornot==1) dosaveconf(); break; default: soundupdate(); return 0; } } } void dosaveconf() { saveconfig(); savedornot=0; } void getzone() { int r0; wipetexttab(); showchatscreen(); message(88,48,0,0,"Choose which"); message(96,68,0,0,"mental zone"); message(64,96,0,0,"1. Ego"); message(64,128,0,0,"2. Psyche"); message(64,160,0,0,"3. Id"); if (checkifextend()) { message(64,192,0,0,"4. Extended Level"); r0=4; } else r0=3; showtext(); r0=readopt(r0); if (r0==-1) return; if ((r0==3)&&(/*testid:*/ idpermit!=1)) { wipetexttab(); showchatscreen(); message(80,100,0,0,"To play the id"); message(32,128,0,0,"you need to complete"); message(80,156,0,0,"the ego first."); showtext(); readopt(0); } else mentalzone=r0; } void choosecontrol() { wipetexttab(); showchatscreen(); message(96,48,0,0,"Controls"); message(64,96,0,0,"1. Keyboard"); message(64,128,0,0,"2. Joystick"); if (checkifextend()) message(64,160,0,0,"3. Fnord"); showtext(); switch (readopt(2)) { case -1: return; case 1: choosekeys(); return; case 2: choosestick(); return; } } void choosekeys() { wipetexttab(); showchatscreen(); leftkey=selectkey(48,128,0,0,"Press Key For Left"); rightkey=selectkey(48,128,0,0,"Press Key For Right"); upkey=selectkey(48,128,0,0,"Press Key For Up"); downkey=selectkey(48,128,0,0,"Press Key For Down"); firekey=selectkey(48,128,0,0,"Press Key to Fire"); } void choosestick() { wipetexttab(); showchatscreen(); message(88,48,0,0,"Joystick"); message(64,96,0,0,"Joystick Number"); message(136,128,0,0,"0-3"); showtext(); joyno=1+readopt(3); if (joyno==0) return; wipetexttab(); showchatscreen(); message(96,48,0,0,"Reminder"); message(48,96,0,0,"To jump, you can"); message(32,128,0,0,"1. Use Joystick Up"); message(32,160,0,0,"2. Use Fire Button 2"); message(64,180,0,0,"If you have one."); message(32,212,0,0,"3. Use The Up Key"); showtext(); (void)readopt(9); } void tunegame() { wipetexttab(); showchatscreen(); message(96,48,0,0,"Tune Game"); if (sound_available) { message(64,96,0,0,"1. Sound System"); message(64,128,0,0,"2. Sound Volume"); } else { message(48,96,0,0,"\x11"); message(48,128,0,0,"\x11"); message(64,96,0,0,"1."); message(64,128,0,0,"2."); message(115,101,0,0,"Sound Not"); message(112,123,0,0,"Available"); } message(64,160,0,0,"3. Video System"); showtext(); while (1) switch (readopt(3)) { case -1: return; case 1: if (sound_available) {tunesound(); return;} else break; case 2: if (sound_available) {tunevolume(); return;} else break; case 3: tunespeed(); return; } } char sound1[] = "-1. No Sound"; char sound2[] = "-2. 4 Channels"; char sound3[] = "-3. 4 Channels"; char sound4[] = "-4. 8 Channels"; char sound5[] = "-5. Normal Quality"; char sound6[] = "-6. High Quality"; char sound7[] = "-7. Overdrive"; void tunesound() { showchatscreen(); swi_fastspr_setclipwindow(20,20,320-20-1,255-20); for (;;/*tunesoundloop:*/soundupdate(),swi_stasis_link(1,1),swi_sound_control(1,-15,0x20,0xfe)) { tunesoundins: wipetexttab(); soundfillin(); message(96,32,0,0,"Tune Sound"); message(32,60,0,0,sound1); message(32,80,0,0,sound2); message(32,100,0,0,sound3); message(80,120,0,0,"and music"); message(32,140,0,0,sound4); message(32,160,0,0,sound5); message(32,180,0,0,sound6); message(32,200,0,0,sound7); message(96,220,0,0,"ESC - Exit"); swi_blitz_wait(0); swi_fastspr_clearwindow(); showtext(); switch(readopt(7)) { case 1: soundtype=0; break; case 2: soundtype=1; break; case 3: soundtype=2; break; case 4: soundtype=3; break; case 5: soundquality&=~1; break; case 6: soundquality|=1; break; case 7: soundquality^=2; break; default: return; } } } void soundfillin() { sound1[0]=(soundtype==0)?16:17; sound2[0]=(soundtype==1)?16:17; sound3[0]=(soundtype==2)?16:17; sound4[0]=(soundtype==3)?16:17; sound5[0]=(soundquality&1)?17:16; sound6[0]=(soundquality&1)?16:17; sound7[0]=(soundquality&2)?16:17; } char tunevol1[]="-5. Speaker on"; void tunevolume() { showchatscreen(); wipetexttab(); if (soundtype==2) swi_bodgemusic_start(1,0); swi_bodgemusic_volume(musicvol); swi_fastspr_setclipwindow(20,20,320-20-1,255-20); message(80,32,0,0,"Change volume"); message(48,96,0,0,"1. Louder effects"); message(48,116,0,0,"2. Quieter effects"); message(48,136,0,0,"3. Louder music"); message(48,156,0,0,"4. Quieter music"); message(48-14,176,0,0,tunevol1); message(96,220,0,0,"ESC - Exit"); do { tunevolumeloop: if (swi_sound_speaker(0)) *tunevol1=17; else *tunevol1=16; swi_blitz_wait(0); swi_fastspr_clearwindow(); showtext(); int r0=readopt(5); if (r0==-1) return; if (r0==1) {if (soundvol<0x40) soundvol=soundvol*2+1; maketestsound(soundvol); continue;} if (r0==2) {if (soundvol>0) soundvol=(soundvol-1)/2; maketestsound(soundvol); continue;} if (r0==3) {if (musicvol<0x40) musicvol=musicvol*2+1; maketestsound(musicvol); continue;} if (r0==4) {if (musicvol>0) musicvol=(musicvol-1)/2; maketestsound(musicvol); continue;} if (r0!=5) return; swi_sound_speaker(3-swi_sound_speaker(0)); } while (1); } void maketestsound(int r1) { swi_stasis_link(1,1); swi_sound_control(1,0x100|r1,0x20,0xfe); swi_bodgemusic_volume(musicvol); } char speed1[] = "-1. Auto frame rate"; char speed2[] = "-2. Full Explosions"; char speed3[] = "-3. Full Screen"; void tunespeed() { do { showchatscreen(); swi_fastspr_setclipwindow(20,20,319-20,255-20); do { tunespeedloop: wipetexttab(); if (gearchange==1) speed1[0]=16; else speed1[0]=17; if (explospeed==2) speed2[0]=17; else speed2[0]=16; if (fullscreen==1) speed3[0]=16; else speed3[0]=17; message(96,48,0,0,"Tune Video"); message(32,96,0,0,speed1); message(80,116,0,0,"gearchanging."); message(32,140,0,0,speed2); message(32,164,0,0,speed3); //message(40,172,0,0,"Tick Options if you"); //message(40,192,0,0,"Have a fast machine"); message(96,220,0,0,"ESC - Exit"); swi_blitz_wait(0); swi_fastspr_clearwindow(); showtext(); int r0=readopt(3); if (r0==-1) return; else if (r0==1) gearchange^=1; else if (r0==2) explospeed^=3; else if (r0==3) {fullscreen^=1; vduread(); break;} } while (1); } while (1); } int selectkey(int x,int y,int xv,int yv,char* a) { int r1; wipetexttab(); showchatscreen(); clearkeybuf(); message(x,y,xv,yv,a); showtext(); do { //do choosekeyloop:; // read key //while (osbyte_79(0)!=0xff); //no key pressed //if ((r4=osbyte_81(1))==ESC_VALUE) // read key //{ chooseescape: osbyte_7c(); //return 0;} //early exit } while ((r1=osbyte_79(0))==-1); // scan keyboard if (r1==ESC_VALUE) return 0; return -r1; // and r4 (?) } int readopt(int maxopt) { int r1; do { keyloop: if (joyno!=0) { swi_joystick_read(joyno-1, NULL, NULL); // MOVVS R0,#0 //if (r0&(1<<16)) {/*optfire:*/ return 0;} } nooptstick: r1=osbyte_81(1); // read key in time limit // if (r1!=0xff) printf("%i\n",r1); if (r1==ESC_VALUE) { optescape: osbyte_7c(); // clear escape return -1; } if (r1==0) continue; if (osbyte_81(firekey)==0xff) {optfire: return 0;} r1-=48; // '1' key returns value 49 } while (!((r1>=0)&&(r1<=maxopt))); optexit: return r1; } const int _x=250; const int _v=-1; int prelude() { cheatpermit=0; frameinc=1; setfullclip(); showchatscreen(); swi_fastspr_setclipwindow(20,20,320-20-1,255-20); swi_fastspr_clearwindow(); wipetexttab(); message(2048,_x,0,_v,"Digital Psychosis"); message(2108,_x+24,0,_v,"Presents"); message(2152,_x+(24*5)/2,0,_v,"#"); message(2040,_x+4*24,0,_v,"Young Sigmund has a"); message(2056,_x+5*24,0,_v,"Few problems. Can"); message(2056,_x+6*24,0,_v,"you help him find"); message(2028,_x+7*24,0,_v,"the rogue brain cells"); message(2036,_x+8*24,0,_v,"in his mind and shut"); message(2100,_x+9*24,0,_v,"Them down?"); message(2096,_x+10*24,0,_v,"PRESS SPACE"); message(2088,_x+12*24,0,_v,"Cheat Mode!!!"); message(2028,_x+14*24,0,_v,"F1, F2 Get Weapons"); message(2028,_x+15*24,0,_v,"F3 - Restore Strength"); message(2096,_x+17*24,0,_v,"HAVE FUN !!!"); showtext(); for (int scroll=256+8;swi_readescapestate()==0;) { loope0: swi_blitz_wait(2); if (scroll!=0) { scroll--; switchbank(); switchfspbank(); swi_fastspr_clearwindow(); texthandler(); } preludetextstop:; int r1=osbyte_7a(); if ((r1!=-1)&&(r1!=307)&&(r1!=308)) // escape { endprelude: return 0; } if (mouse&2) { gocheat: if (osbyte_81(-307)!=0xff) return 0; if (osbyte_81(-308)!=0xff) return 0; cheatpermit=1; scroll=1024; } } osbyte_7c(); return 1; } // buf: void checkifarm3() { // The ARM3 is 25-33MHz with a 4Kb cache. If you have // less than that you should probably clear this flag. arm3=1; } int checkifextend() { //swi_XOS_ReadVarVal("PsychoExtend$Path",&buf,1<<31,0); return 0; //return (r2!=0); // z flag } //const char idpermitpath[]="Idpermit"; char idpermitstring[]="You are now permitted to play the ID!!!\n"; char configname[] = "/.asylum"; //"Config"; void permitid() { //swi_osfile(10,idpermitpath,idpermitstring,idpermitstring+40); char fullname[240] = ""; strcat(fullname,getenv("HOME")); strcat(fullname,configname); FILE* r0=swi_osfind(0xc0, fullname); if (r0!=NULL) { fprintf(r0,"%s",idpermitstring); fclose(r0); } idpermit=1; } char config_keywords[13][12] = {"LeftKeysym", "RightKeysym", "UpKeysym", "DownKeysym", "FireKeysym", "SoundType", "SoundQ", "FullScreen", "SoundVolume", "MusicVolume", "MentalZone", "Initials", "You"}; void loadconfig() { char fullname[240] = ""; char keyword[12]; strcat(fullname,getenv("HOME")); strcat(fullname,configname); FILE* r0=swi_osfind(0x40, /* read access with path variable R2 */ fullname); if (r0!=NULL) { //swi_osgbpb(3, /* read bytes from pointer R4 */ //r0,&savestart,&saveend,0); while (fscanf(r0," %12s",&keyword)!=EOF) { int i; for (i=0;i<13;i++) if (!strncmp(keyword,config_keywords[i],12)) break; if (i==11) {fscanf(r0," %3c",initials); continue;} if (i==12) {idpermit=1; break;} // end of file if (i==13) break; // parsing failed int temp; fscanf(r0," %i",&temp); switch(i) { case 0: leftkey=-temp; break; case 1: rightkey=-temp; break; case 2: upkey=-temp; break; case 3: downkey=-temp; break; case 4: firekey=-temp; break; case 5: soundtype=temp; break; //case 6: soundquality=temp; break; case 7: fullscreen=temp; break; case 8: soundvol=temp; break; case 9: soundquality=temp; break; case 10: mentalzone=temp; break; } } fclose(r0); } findoutid:; if (!idpermit) if (mentalzone>2) mentalzone=2; //int idp=swi_osfile(5,idpermitpath,NULL,NULL); //idpermit=(idp==1)?1:0; } void saveconfig() { char fullname[240] = ""; strcat(fullname,getenv("HOME")); strcat(fullname,configname); //printf("%s\n", fullname); FILE* r0=swi_osfind(0x80 /* create file with read/write access with path variable R2 */, fullname); if (r0==NULL) return; //swi_osgbpb(1, /* write bytes to pointer R4 */ //r0,&savestart,&saveend,0); fprintf(r0, "%s %i\n%s %i\n%s %i\n%s %i\n%s %i\n%s %i\n%s %i\n%s %i\n%s %i\n%s %i\n%s %c%c%c\n%s", config_keywords[0], -leftkey, config_keywords[1], -rightkey, config_keywords[2], -upkey, config_keywords[3], -downkey, config_keywords[4], -firekey, config_keywords[5], soundtype, //config_keywords[6], soundquality, config_keywords[7], fullscreen, config_keywords[8], soundvol, config_keywords[9], musicvol, config_keywords[10], mentalzone, config_keywords[11], initials[0], initials[1], initials[2], ((idpermit==1)?idpermitstring:"")); fclose(r0); } char gamescreenpath[] = "GameScreen"; char chatscreenpath[] = "ChatScreen"; char blokepath[] = "FSPBloke"; char boardpath[] = "Brain"; char blockpath[] = "FSPBlocks"; char backpath[] = "Backfile"; char neuronbackpath[] = "Neurons/Backfile"; char neuronpath[] = "Neurons/Cell1"; char* neuronnumber = neuronpath+12; char explopath[] = "FSPExplo"; char charpath[] = "FSPChars"; char alienpath[] = "FSPAliens"; char resourcepath[] = "./Resources/"; char extendpath[] = "./Extend/"; char idpath[] = "./Id/"; char psychepath[] = "./Psyche/"; char egopath[] = "./Ego/"; char egomusic1path[] = "./Ego/Music1"; char egomusic2path[] = "./Ego/Music2"; char psychemusic1path[] = "./Psyche/Music1"; char psychemusic2path[] = "./Psyche/Music2"; char idmusic1path[] = "./Id/Music1"; char idmusic2path[] = "./Id/Music2"; char mainmusicpath[] = "./Resources/Music1"; char deathmusicpath[] = "./Resources/Music2"; int getfiles() { getvitalfiles(); showloading(); getmusicfiles(); getgamefiles(); return 0; } void getvitalfiles() { charsok=0; chatscreenadr=storage; char* charsadr_load=chatscreenadr; loadvitalfile(chatscreenpath,resourcepath,&charsadr_load); gamescreenadr=charsadr_load; loadvitalfile(charpath,resourcepath,&gamescreenadr); initialize_sprites(charsadr_load,charsadr,48,gamescreenadr); charsok=1; } void getmusicfiles() { swi_bodgemusic_load(1,mainmusicpath); swi_bodgemusic_load(2,deathmusicpath); swi_bodgemusic_start(1,0); } void getgamefiles() { char* r10=gamescreenadr; char* o10=r10; int reload=0; load1: do { reload=loadhammered(gamescreenpath,resourcepath,&r10); if (reload==-1) {badload(); return;} } while (reload==1); o10=r10; //blokeadr=r10; load2: do { reload=loadhammered(blokepath,resourcepath,&r10); if (reload==-1) {badload(); return;} } while (reload==1); initialize_sprites(o10,blokeadr,77,r10); o10=r10; //exploadr=r10; load3: do { reload=loadhammered(explopath,resourcepath,&r10); if (reload==-1) {badload(); return;} } while (reload==1); initialize_sprites(o10,exploadr,32,r10); tmp_blockadr=r10; } int getlevelfiles() { int reload=0; showgamescreen(); currentzone=0; switch(mentalzone) { case 2: currentpath=psychepath; break; case 3: currentpath=idpath; break; case 4: currentpath=extendpath; break; default: currentpath=egopath; } char* r10=tmp_blockadr; char* o10=r10; load4: do { reload=loadhammered(blockpath,currentpath,&r10); if (reload==-1) {reload=badlevelload();} } while (reload==1); initialize_sprites(o10,blockadr,256,r10); //alspradr=r10; o10=r10; load5: do { reload=loadhammered(alienpath,currentpath,&r10); if (reload==-1) {reload=badlevelload();} } while (reload==1); initialize_sprites(o10,alspradr,256,r10); brainadr=(board*)r10; boardadr=(board*)r10; load6: do { reload=loadhammered(boardpath,currentpath,&r10); if (reload==-1) {reload=badlevelload();} } while (reload==1); backadr=r10; load7: do { reload=loadhammered(backpath,currentpath,&r10); if (reload==-1) {reload=badlevelload();} // backfiles don't work??? } while (reload==1); char* r1; switch (mentalzone) { case 2: r1 = psychemusic1path; break; case 3: r1 = idmusic1path; break; default: r1 = egomusic1path; } swi_bodgemusic_load(0,r1); switch (mentalzone) { case 2: r1 = psychemusic2path; break; case 3: r1 = idmusic2path; break; default: r1 = egomusic2path; } swi_bodgemusic_load(1,r1); return 0; } int retrievebackdrop() { char* r9=currentpath; char* r10=backadr; int reload; load10: do { reload=loadhammered(backpath,currentpath,&r10); if (reload==-1) {reload=badlevelload();} } while (reload==1); return 0; } int getneuronfiles() { char* r10=backadr; int reload=0; //STR R10,[R12,#backadr] load8: do { reload=loadhammered(neuronbackpath,currentpath,&r10); if (reload==-1) {reload=badlevelload();} } while (reload==1); r10+=backsize*3; neuronadr=boardadr=(board*)r10; while (1) { neuronloadloop: *neuronnumber='0'+plzone; if (filelength(neuronpath,currentpath)) break; currentzone=--plzone; if (currentzone==0) {noneuronshere: return 1;} } load9: do { reload=loadhammered(neuronpath,currentpath,&r10); if (reload==-1) {reload=badlevelload();} } while (reload==1); return 0; } void loadvitalfile(char* r1,char* path,char** space) { // if VS or if r0==1 char fullname[240]=""; strcat(fullname,path); strcat(fullname,r1); int r4=swi_osfile(15,fullname,0,0); if (r4==-1) fatalfile(); if (*space+r4>=storageend) fatalfile(); if (swi_osfile(14,fullname,*space,0)) fatalfile(); *space+=r4; } int loadhammered(char* r1,char* path,char** spaceptr) { int r3=swi_blitz_hammerop(0,r1,path,NULL); if (r3==-1) {filenotthere(); return -1;} if (r3==0) {return loadfile(r1,path,spaceptr);} if (*spaceptr+r3>=storageend) {nomemory(); return 1;} int k; if ((k=swi_blitz_hammerop(1,r1,path,*spaceptr))<0) {printf("Error %i\n",-k); filesyserror(); return 1;} *spaceptr+=k; return 0; } int loadfile(char* r1,char* path,char** spaceptr) { int r4=filelength(r1,path); char fullname[240]=""; strcat(fullname,path); strcat(fullname,r1); if (r4==-1) {filenotthere(); return 1;} if (*spaceptr+r4>=storageend) {nomemory(); return 1;} if (swi_osfile(14,fullname,*spaceptr,0)) {filesyserror(); return 1;} *spaceptr+=r4; return 0; } char egosave[] = "/EgoHighScores"; char psychesave[] = "/PsycheHighScores"; char idsave[] = "/IdHighScores"; char extendedsave[] = "/ExtendedHighScores"; char testsave[] = "/TestPermissions"; void savescores() { highscorearea[13*5] = swi_oscrc(0,highscorearea,highscorearea+13*5,1); char r1[240]=SCOREPATH; if (!installed) strcpy(r1,"../hiscores"); switch (mentalzone) { case 2: strcat(r1,psychesave); break; case 3: strcat(r1,idsave); break; case 4: strcat(r1,extendedsave); break; default: strcat(r1,egosave); } swi_osfile(10,r1,highscorearea,highscorearea+13*5+1); if (installed) chmod(r1,0060); } void loadscores() { char r1[240]=SCOREPATH; if (!installed) strcpy(r1,"../hiscores"); switch (mentalzone) { case 2: strcat(r1,psychesave); break; case 3: strcat(r1,idsave); break; case 4: strcat(r1,extendedsave); break; default: strcat(r1,egosave); } if (swi_osfile(0xff,r1,highscorearea,highscorearea+13*5+1)) setdefaultscores(); else if (swi_oscrc(0,highscorearea,highscorearea+13*5,1) != highscorearea[13*5]) setdefaultscores(); } const char defscore[] = "00000000 PSY\n"; void setdefaultscores() { char* r10=highscorearea; for (int r3=5;r3>0;r3--) { loopd4:; const char* r11=defscore; for (int r2=13;r2>0;r2--) { loopd5: *(r10++)=*(r11++); } } } void fatalfile() { exit(printf("A file vital to the game cannot be loaded. Please reset your machine and try again")); } void showloading() { wipetexttab(); showchatscreen(); message(88,64,0,0,"Please Wait"); message(48,128,0,0,"Loading Game files"); showtext(); } void filenotthere() { showerror(); message(56,64,0,0,"A file is missing."); message(48,96,0,0,"It cannot be loaded"); showtext(); errorwait(); } void filesyserror() { showerrorok(); message(40,64,0,0,"Unable to Load File"); message(56,96,0,0,"Please Check Disc"); showtext(); errorwait(); } void badload() { showerrorok(); message(32,32,0,0,"A game file could not"); message(48,64,0,0,"be loaded. Program"); message(80,96,0,0,"Must exit now."); showtext(); errorwait(); } int badlevelload() { showerrorok(); message(40,32,0, 0,"The level cannot be"); message(32,64,0 ,0,"Loaded. Please check"); message(48,96,0,0,"the disc, or press"); message(48,128,0,0,"escape to end game."); showtext(); return errorwait(); // 'clear carry if carry clear (???)' } void nomemory() { showerrorok(); message(48,32,0,0,"There is not enough"); message(48,64,0,0,"memory available to"); message(48,96,0,0,"load the game files."); showtext(); errorwait(); // XXX smash one more entry from stack (than just nomemory(); return;) } int filelength(char* name,char* path) { char fullname[240]=""; strcat(fullname,path); strcat(fullname,name); int r4=swi_osfile(15,fullname,NULL,NULL); if (r4==-1) {filesyserror(); return 0;} //if (r0!=1) {fileerror: return -1;} return r4; } void showerror() { frameinc=1; showchatscreen(); swi_fastspr_setclipwindow(20,20,320-20-1,255-20); swi_fastspr_clearwindow(); wipetexttab(); message(72,200,0,0,"RET - Try Again"); message(72,224,0,0,"ESC - Abandon"); } void showerrorok() { frameinc=1; showchatscreen(); swi_fastspr_setclipwindow(20,20,320-20-1,255-20); swi_fastspr_clearwindow(); wipetexttab(); message(72,200,0,0,"RET - OK"); message(72,224,0,0,"ESC - Abandon"); } int errorwait() { if (osbyte_81(-74)!=0xff) loopb9: while (osbyte_81(-61)!=0xff) if (swi_readescapestate()) {wipetexttab(); return 0;} waitover: wipetexttab(); return 1; } char buffer[256]; //.hta void errorhandler(int r0) { losehandlers(); exit(printf("Error from Asylum:\n%s",buffer+4)); } void exithandler(int r0) { losehandlers(); exit(255); } void upcallhandler(int sig) { if (sig==SIGTERM) {losehandlers(); exit(0);} if (sig==SIGINT) {losehandlers(); exit(0);} //noexitupcall: //if (r0==1) {insertdiscagain(r2); return;} //if (r0==2) {insertdisc(r2); return;} } void gethandlers() {signal(SIGTERM,upcallhandler); signal(SIGINT,upcallhandler); return;} void losehandlers() {SDL_Quit(); return;} void loadzone() { int r1=currentzone; if ((currentzone=plzone)==0) exitneuron(r1); else enterneuron(r1); } void enterneuron(int r1) { if (r1==0) saveal(); if (getneuronfiles()) {exitneuron(r1); return;} wipealtab(); getarms(); initweapon(); initprojtab(); initbultab(); backprep(); boardreg(); prepfueltab(); findplayer(); } void exitneuron(int r1) { boardadr=brainadr; restoreal(); initweapon(); initprojtab(); initbultab(); retrievebackdrop(); backprep(); boardreg(); prepfueltab(); wipesoundtab(); } int showhighscore() { loadscores(); updatehst(); showhst(); wipetexttab(); message(96,224,0,0,"press fire"); releaseclip(); showtext(); readopt(0); return swi_readescapestate(); } void updatehst() { hstindex=5; char* r10=highscorearea; r10+=4*13; //4*entry length while (comparescore(r10)) { loopd1: r10-=13; //entry length if (--hstindex==0) break; } lessthan: r10+=13; //entry length if (hstindex!=5) { if (4-hstindex>0) { char* r9; int r3; for (r9=highscorearea+4*13-1,r3=13*(4-hstindex);r3>0;r9--,r3--) { loopd7: r9[13]=*r9; } } noshiftscore:; char* r11=plscore; for (int r3=8;r3>0;r3--) { loopda: *(r10++)=*(r11++)+'0'; } r10++; //int r9=1024; swi_blitz_wait(20); // for (int i=0;i<3;i++) r10[i] = initials[i]; for (int r8=3;r8>0;r8--,r10++) { while (osbyte_81(0)!=-firekey) { scorekeyloop: //if (--r9<0) goto scoreexit; keyread(); if (leftpress==0) {(*r10)++; savedornot=0;} if (rightpress==0) {(*r10)--; savedornot=0;} if (*r10<'0') *r10='0'; if (*r10>'Z'+4) *r10='Z'+4; showhst(); swi_blitz_wait(4); } initials[3-r8] = *r10; swi_stasis_link(1,18); swi_stasis_volslide(1,0,0); swi_sound_control(1,0x17c,140,0); /*if (r8>1)*/ swi_blitz_wait(20); } scoreexit: savescores(); dosaveconf(); } notontable:; } int comparescore(char* r10) { char* r11=plscore; for (int r3=8;r3>0;r3--) { loopd0: if (*r10-'0'<*r11) scoregreater: return 1; else if (*r10-'0'>*r11) scoreless: return 0; r10++; r11++; compnext:; } return 1; } void showhst() { swi_blitz_wait(0); switchbank(); switchfspbank(); showchatscores(); wipetexttab(); message(64,32,0,0,"Zone High Scores"); texthandler(); char* r10=highscorearea; int x=32, y=64; for (int r3=5;r3>0;r3--) { for (;*r10>0xa;r10++) { showhstloop: fspplot(charsadr,*r10-'0',x,y); x+=16; } showhstnewline: x=32; y+=32; r10++; } if (hstindex==5) return; fspplot(charsadr,13,280,(hstindex+2)<<5); } void setup() { framectr=0; plzone=_firstzone; wipesoundtab(); initweapon(); initprojtab(); initbultab(); setfullclip(); initrockettab(); addtabinit(); getvars(); prepstrength(); scorezero(); backprep(); boardreg(); wipealtab(); prepfueltab(); } void wipesoundtab() { //r10=&soundtabofs; temporarily undefined for (int r3=_soundentlen*8; r3>0; r3-=sizeof(int)) { loop51:; //*(r10++)=0; } for (int r0=7;r0>=0;r0--) { soundkillloop: swi_stasis_volslide(r0,0xfc00,0); } } void wipetexttab() { char* r10=(char*)texttabofs; for (int r3=_textno*_textlen;r3-=1;r3>0) { loopa5: *(r10++)=0; } } void initprojtab() { projadr=projofs; projent* r10=projadr; projctr=0; for (int r9=_projno;r9>0;r9--) { loop44: *(int*)r10=0; r10++; } } void initbultab() { buladr=bulofs; bulent* r10=buladr; bulctr=0; for (int r9=_bulno;r9>0;r9--) { loop74: *(int*)r10=0; r10++; } } void initweapon() { firelastframe=0; if (plweapontype>=_rockbase) {plweaponspeed=2; firerate=12;} else {plweaponspeed=8; firerate=4;} rocketblamctr=5; } void prepfueltab() { fueltabread=fueltabofs[0]; fueltabwrite=fueltabofs[1]; *fueltabread=0; *fueltabwrite=0; fueltabctr=0; fuelairlastframe=0; } void scorezero() { plscoreadd=0; *(uint64_t*)plscore=0; lives=2; neuronctr=0; } void wipealtab() { aladr=alofs; alent* r10=aladr; alctr=0; for (int r9=_alno;r9>=0;r9--) { l9: r10->type=0; r10++; } boardreg(); // fallthrough? } void boardreg() { boardwidth=boardadr->width; xposmax=boardwidth<<12; yposmax=boardadr->height<<12; boardlowlim=boardadr->contents; boardhighlim=boardlowlim+boardadr->width*boardadr->height; } void backprep() { // This used to be multiply callable. Now it's not. Uint32* ba = (Uint32*)backadr; for (int i=32*48-1;i>=0;i--) ba[i] = alt_palette[backadr[i]]; backexec(ba+32*48,ba); backexec(ba+64*48,ba+32*48); backexec(ba+96*48,ba+64*48); } void backexec(Uint32* dst,Uint32* src) { for (int r4=32;r4>0;r4--) { l6:; Uint32 r2=*(src++); l5: memcpy(dst,src,47*sizeof(Uint32)); dst+=47; src+=47; *(dst++)=r2; } } void prepstrength() { laststrength=plstrength=_strengthinit; snuffctr=lagerctr=0; } void screensave() { showscore(); //oscli("Mount"); //oscli("Screensave Screenfile"); } void getvars() { getstrengthtab(); xpos=64<<8; ypos=48<<8; initplx=0; initply=0; hvec=0; vvec=0; pladr1=0; pladr2=0; plface=0; } typedef struct { int time; int tempo; char* tune; int pitch[4]; int inst[4]; int start_time[4]; char* section; int pointer; } music_state; music_state music; char voice[32][30000]; char tuneload[4][30000]; Sint16 mulaw[256]; Mix_Chunk* make_sound(char samp, int initpitch, int volslide, int pitchslide, char frames) { int numsamples = frames*22050.0/50.0; // frames are 50Hz? Mix_Chunk* mc = (Mix_Chunk*)malloc(sizeof(Mix_Chunk)); Uint16* s = (Uint16*)malloc(numsamples*2*sizeof(Uint16)); mc->abuf = (Uint8*)s; mc->alen = numsamples*2*sizeof(Uint16); mc->allocated = 0; // don't automatically free buffer mc->volume = 0xff; // XXX volume int time = 0; double ps = ((Sint16)(pitchslide&0xffff))*22/22050.0; double vs = ((Sint16)(volslide&0xffff))/22050.0; Sint16 psmax = pitchslide>>16; double matching = 0; fprintf(stderr,"."); fflush(stderr); for (int i=0; i0)&&(pitch>psmax)) pitch=psmax; //if ((ps<0)&&(pitch=len) {if (rep==0) continue; else jj = (len-rep) + ((jj-len)%rep);} double w; if (jj>=len-gap) w = ((jj-(len-gap))*(double)mulaw[voice[samp][jj+44-rep]] + (len-jj)*(double)mulaw[voice[samp][jj+44]])/gap/4; else w = mulaw[voice[samp][jj+44]]/4; double vscale = 0x7f + vs*time; if (vscale>0xff) vscale=0xff; if (vscale>0) w *= (vscale/0x7f); else w = 0; double x = PI*(j - matching); if (x==0) mono += w; else mono += w * sinf(x) / (1.3*x); } s[1]=*s=mono; // XXX stereo } return(mc); } void soundclaim(int c, char samp, char initvol, int initpitch, int volslide, int pitchslide, char frames, int stereo, Mix_Chunk* static_chunk) { //int* argv = (int*)vargv; //int c = argv[0]; char samp = argv[1]; char initvol = argv[2]; int initpitch = argv[3]; //int volslide = argv[4]; int pitchslide = argv[5]; char frames = argv[6]; int stereo = argv[7]; Mix_Chunk* old_chunk = Mix_GetChunk(c); Mix_Chunk* chunk = static_chunk?static_chunk:make_sound(samp,initpitch,volslide,pitchslide,frames); Mix_HaltChannel(c); Mix_Volume(c, ((initvol>soundvol)?soundvol:initvol)); Mix_SetPanning(c, 254-stereo, stereo); Mix_PlayChannel(c, chunk, 0); //if (old_chunk) Mix_FreeChunk(old_chunk); XXX memory leak } void sdl_music_hook(void* udata, Uint8* stream, int len) { music_state* m = (music_state*)udata; char* tuneload = m->tune; Uint16* s = (Uint16*)stream; for (int i=0; itime++, s+=2) { if (0==(m->time%m->tempo)) { // new beat int inst = 0; int pitch = 8; char first; char second; do { first = tuneload[m->pointer++]; second = tuneload[m->pointer++]; if (first) { // pitch word inst = first&0x1f; pitch = second&0x3f; } else { m->pitch[second&3] = pitch; m->inst[second&3] = inst; m->start_time[second&3] = m->time; inst = 0; pitch = 8; } } while ((second&0xc0)==0); if (second&0x80) { m->section++; if (0x80&*m->section) m->section=tuneload+8; m->pointer=((Uint32*)tuneload)[0x42+*m->section]; } } *s=0; s[1]=0; for (int v=0; v<4; v++) { if (m->inst[v] == 0) continue; int pitch = m->pitch[v]; int off = m->time - m->start_time[v]; double old_sample_rate=4000.0*pow(2,pitch/12.0); double matching = off*old_sample_rate/22050; for (int j = (int)matching-4; j <= (int)matching+4; j++) { if ((j<0)) continue; int jj=j; Uint32 len=((Uint32*)voice[m->inst[v]])[6]; Uint32 gap=((Uint32*)voice[m->inst[v]])[7]; // ??? Uint32 rep=((Uint32*)voice[m->inst[v]])[8]; /*if (m->inst[v]==16) while (jj>=6960+1000) jj-=6960; else if (jj>=8192) continue;*/ if (jj>=len) jj = rep?((len-rep) + ((jj-len)%rep)):0; double w; if (jj>=len-gap) w = ((jj-(len-gap))*(double)mulaw[voice[m->inst[v]][jj+44-rep]] + (len-jj)*(double)mulaw[voice[m->inst[v]][jj+44]])/gap/4; else w = mulaw[voice[m->inst[v]][jj+44]]/4; double x = PI*(j - matching); if (x==0) s[v&1] += w; else s[v&1] += w * (sinf(x) * musicvol) / (1.3 * x * 0x7f); } } } } void load_voice(int v, char* filename) { SDL_RWops* file = SDL_RWFromFile(filename, "r"); if (file==NULL) {sound_available=0; return;} SDL_RWseek(file, 0, SEEK_END); int file_len = SDL_RWtell(file)/*-44*/; SDL_RWseek(file, 0/*44*/, SEEK_SET); SDL_RWread(file,voice[v],1,file_len); } void load_voices() { load_voice(1,"./Voices/Jump"); load_voice(2,"./Voices/Bonus"); load_voice(3,"./Voices/Explo"); load_voice(4,"./Voices/AtomExplo"); load_voice(5,"./Voices/Cannon"); load_voice(6,"./Voices/Rocket"); load_voice(7,"./Voices/Hiss"); load_voice(8,"./Voices/Stunned"); load_voice(9,"./Voices/SmallZap"); load_voice(10,"./Voices/BigZap"); load_voice(16,"./Voices/Organ"); load_voice(17,"./Voices/Plink"); load_voice(18,"./Voices/PlinkHard"); load_voice(19,"./Voices/Raver"); load_voice(20,"./Voices/Dome"); load_voice(21,"./Voices/NasalStr"); load_voice(22,"./Voices/BassHollow"); load_voice(23,"./Voices/NasalBass"); load_voice(24,"./Voices/BassDrum"); load_voice(25,"./Voices/Snare"); load_voice(26,"./Voices/Cymbal"); } void vduread() { osbyte_f1(1); //get non-shadow screen bank ArcScreen = SDL_SetVideoMode( 320, 256, 32 /*bpp*/, SDL_HWSURFACE | (fullscreen?SDL_FULLSCREEN:0)); DecompScreen = SDL_CreateRGBSurface(SDL_SWSURFACE, 320, 256, 32, 0xff,0xff00,0xff0000,0); modesize = 0; // hack: don't double buffer 320*256*4; hbytes = ArcScreen->pitch; SDL_LockSurface(ArcScreen); screenstart = (char*)(ArcScreen->pixels); SDL_UnlockSurface(ArcScreen); /* initialise screenstart(149), modesize(7), hbytes(6) */ screenuse=screenstart; SDL_ShowCursor(SDL_DISABLE); } Uint32 strengthcol[72]; void getstrengthtab() {strengthcoltab = strengthcol;} void init_strengthcol() { for (int i=0;i<36;i++) { strengthcol[i] = 0xff000000+0x110000*(11+(i%5)); // varying shade of red strengthcol[i+36] = 0xff000000+0x111111*(3&i); // varying shade of dark grey }} int addtab[] = {10000000, 1000000, 100000, 10000, 1000, 100, 10, 1}; void addtabinit() {addtabadr=addtab;} int rockettab[_rockettablen]; void initrockettab() {rocketctr=0; rocketflag=0; rockettabadr=rockettab;} void init_rockettab() { for (int i=0;i<184;i++) { rockettab[4+i] = (int)(256*sin(i*2*PI/(192-8))); } for (int i=0;i<4;i++) { rockettab[i] = rockettab[188+i] = 0; }} void init_sounds() { Sint16 exp[8] = {0,132,396,924,1980,4092,8316,16764}; for (int i=0;i<256;i++) mulaw[i] = ((i&1)?-1:1) * (exp[i>>5] + ((i&0x1e)<<(2+(i>>5)))); fprintf(stderr,"Building sound effects "); CHUNK_BULLET_1 = make_sound(_Sampsmallzap,fullpitch+0x1000,0,(fullpitch<<16)|0xfe00,2); CHUNK_BULLET_2 = make_sound(_Sampbigzap,fullpitch+0x1800,0,(fullpitch<<16)|0xfe00,2); CHUNK_BULLET_3 = make_sound(_Sampbigzap,fullpitch+0x1000,0,(fullpitch<<16)|0xfe00,2); CHUNK_ELEC_1 = make_sound(_Samprave,0x2000,0xff00,0,10); CHUNK_ELEC_2 = make_sound(_Samprave,0x2400,0xff00,0,10); CHUNK_ELEC_3 = make_sound(_Samprave,0x2800,0xff00,0,10); CHUNK_EXPLO = make_sound(_SampExplo,0x3800,0,0,10); CHUNK_ATOM = make_sound(_SampAtomExplo,0x2800,0,0,50); CHUNK_SPINFIRE = make_sound(_Sampsmallzap,fullpitch+0x1000,0,0,2); CHUNK_SPINPOWERFIRE = make_sound(_Sampbigzap,fullpitch,0,0,2); CHUNK_SHOOT = make_sound(_Sampsmallzap,fullpitch+0x1000,0,(fullpitch<<16)|0xfe00,2); CHUNK_SHOOTNUTTER = make_sound(_Sampbigzap,fullpitch,0,(fullpitch<<16)|0xfe00,2); CHUNK_JUMP = make_sound(_SampJump,0x4600,0,0,4); CHUNK_SHUTDOWN_1 = make_sound(_Samprave,0x3300,(soundvol<<25)|0x1000,0x100ff00,100); CHUNK_SHUTDOWN_2 = make_sound(_Samprave,0x3200,(soundvol<<25)|0x1000,0x100ff00,100); CHUNK_SHUTDOWN_3 = make_sound(_Samprave,0x3100,(soundvol<<25)|0x1000,0x100ff00,100); CHUNK_TELEP_1 = make_sound(_SampJump,0x1000,0,0,50); CHUNK_TELEP_2 = make_sound(_Samporgan,0x1000,0xff00,0x50000a00,25); CHUNK_TELEP_3 = make_sound(_Samporgan,0x4000,0xff00,0x1000f400,25); CHUNK_BLAM = make_sound(_SampAtomExplo,fullpitch,0,0,8); CHUNK_FIRE = make_sound(_SampCannon,fullpitch,0,0,2); CHUNK_BLAMFIRE = make_sound(_Samprave,fullpitch,0,(fullpitch<<17)+0x200,40); CHUNK_ROCKET = make_sound(_SampRocket,fullpitch,0,0,2); CHUNK_WEAPON_1 = make_sound(_Samporgan,0x3000,0xff00,0x60000200,10); CHUNK_WEAPON_2 = make_sound(_Samporgan,0x3800,0xff00,0x60000200,10); CHUNK_WEAPON_3 = make_sound(_Samprave,0x3000,0xff00,0x60000800,10); CHUNK_WEAPON_4 = make_sound(_Samprave,0x3800,0xff00,0x60000800,10); CHUNK_FUELAIR = make_sound(_SampHiss,0x6000,0xff80,0x2000ff00,50); for (int i=0;i<12;i++) CHUNK_OBJGOT[i] = make_sound(_SampBonus,((i+1)<<6)+0x3000,0,0,3); CHUNK_BONUS_1 = make_sound(_SampBonus,0x2200,0,0,5); CHUNK_BONUS_2 = make_sound(_SampBonus,0x2000,0,0,5); for (int i=0;i<17;i++) CHUNK_STUNNED[i] = make_sound(_SampStunned,0x4000-i*0x100,0,0,50); fprintf(stderr," done.\n"); } void c_array_initializers() { init_projsplittab(); init_rocketbursttab(); init_alspintab(); init_strengthcol(); init_rockettab(); init_palette(); init_splittab(); if (sound_available) { load_voices(); if (sound_available) init_sounds(); else fprintf(stderr,"Sound disabled: loading sound effects failed\n"); } for (int i=0;i<512;i++) keyboard[i]=0; } int main() { char r1[240] = SCOREPATH; strcat(r1,testsave); FILE* permission_test = fopen(r1,"w"); installed = (NULL != permission_test); if (installed) { fclose(permission_test); unlink(r1); if (chdir(RESOURCEPATH)) { fprintf(stderr,"Couldn't find resources directory %s\n",RESOURCEPATH); exit(1); } } else { fprintf(stderr,"Running as uninstalled, looking for files in local directory.\n"); if (chdir("./data")) { fprintf(stderr,"Couldn't find resources directory ./data\n"); exit(1); } } SDL_Init(SDL_INIT_VIDEO|SDL_INIT_AUDIO); sound_available=!Mix_OpenAudio(22050,AUDIO_U16LSB,2,1024); if (!sound_available) fprintf(stderr,"Sound disabled: opening audio device failed: %s\n",Mix_GetError()); c_array_initializers(); /*MODE 15 MODE 13 VOICES 8 STEREO 5,-32 STEREO 6,32 STEREO 7,-32 STEREO 8,32*/ swi_stasis_control(8,8); do {init();} while (0);// (snuffctr>=300); SDL_Quit(); exit(0); } void message(int x,int y,float xv,float yv,char* a) { int time=400; char b[60]; char* q=b; if (x>1000) {x-=1000; time=50;} if (x>1000) {x-=1000; time=0x10000;} //int32_t z[5]={time,x<<8,y<<8,(int)(xv*256),(int)(yv*256)}; // might be non-integers for (char* p=a;*p!=0;p++,q++) { switch (*p) { case '-': *q=';'; break; case '§': *q=':'; break; case '\'':*q='~'; break; case '.': *q='{'; break; case ',': *q='|'; break; case '?': *q='<'; break; case '!': *q='}'; break; case '%': *q='>'; break; case 'Ä':*q='?'; break; case '◊': *q='@'; break; case '#': *q=127; break; default: *q=*p; } if (*q>=96) *q-=32; if (*q==' ') *q=0xff; else if ((*q&~1)!=16) {*q-=47; if (*q>55) exit(printf("Bad message character %c (%i)",*p,*p));} } *q=0; { textinfo* r11=texttabofs; int r9; for (r9=_textno;r9>0;r9--) { loopa8: if (r11->count==0) break; r11++; } if (r9==0) return; messageproc: r11->count=time; r11->x=x<<8; r11->y=y<<8; r11->dx=(int)(xv*256); r11->dy=(int)(yv*256); if (strlen(b)>58) exit(printf("Bad string %s",b)); strncpy(r11->text,b,60); } } void swi_bodgemusic_start(int a,int b) { if (!sound_available) return; swi_bodgemusic_stop(); swi_sound_qtempo(0x1000); music.time=0; music.tune=tuneload[a]; music.section=tuneload[a]+8; music.pointer=((Uint32*)(tuneload[a]))[0x42+*music.section]; for (int v=0;v<4;v++) {music.pitch[v]=0; music.inst[v]=0; music.start_time[v]=0;} Mix_HookMusic(sdl_music_hook, &music); } void swi_bodgemusic_stop() { if (sound_available) {Mix_HaltMusic(); Mix_HookMusic(NULL,NULL);} } void swi_bodgemusic_volume(int v) {;} void swi_bodgemusic_load(int a,char* b) { SDL_RWops* tune = SDL_RWFromFile(b, "r"); //SDL_RWseek(tune, 8+256+64, SEEK_SET); SDL_RWread(tune,tuneload+a,1,30000); } void swi_sound_qtempo(int t) { music.tempo=(2756*0x1000)/t; } void swi_sound_control(int c,int a,int p,int d) {;} int swi_sound_speaker(int s) {;} void swi_stasis_link(int a,int b) {;} void swi_stasis_control(int a,int b) {;} void swi_stasis_volslide(int a,int b,int c) {;} void swi_removecursors() {;} int swi_readescapestate() { return keyboard[ESC_VALUE];} void osbyte_71() {;} int osbyte_79(int c) { update_keyboard(); int key = keybuf; keybuf = -1; return key; //for (int i=0;i<512;i++) if (keyboard[i]) {/*printf("Returning %i\n",i);*/ return i;} return -1; } int osbyte_7a() { update_keyboard(); for (int i=0;i<512;i++) if (keyboard[i]) return i; return -1;} void osbyte_7c() { keyboard[ESC_VALUE] = 0;} int osbyte_81(int c) { if (c>=0) return osbyte_79(c); update_keyboard(); return keyboard[-c];} void osbyte_f1(char c) {;} char swi_oscrc(int w,char* start,char* end,int bytes) { return 0xff;} FILE* swi_osfind(int op, const char* name) { switch (op) { case 0x40: return fopen(name,"r"); case 0x80: return fopen(name,"w"); case 0xc0: return fopen(name,"a"); default: return NULL; } } void swi_osgbpb(int op, FILE* f, char* start, char* end, int b) { switch (op) { case 3: for (char* i=start;(i>8)&0xffffff)|((getc(f)<<24)&0xff000000); while(!feof(f)) { c = getc(f); if (c==0xff) break; // end flag else if (c<0x10) { // type 1 int n = (c==15)?256:c+2; char d = getc(f); for (int i=0;i> 2) + 2; for (int i=0;i>1); int P = p - 1 -((c&1)<<8) - d; if (P<0) {fclose(f); return -4;} int n = ((c&0x38)>>3) + 2; for (int i=0;i>3) + 2; for (int i=0;i>2; for (int i=0;i>2)]; } else for (int i=0;imax_sprites) num_sprites = max_sprites; for (int i=0;i>2); uint32_t* r=s; if (i==num_sprites-1) r = (uint32_t*) end; else for (int j=0;(r==s)&&(i+j>2); if (r==s) r=(uint32_t*)end; uint8_t* pp = (uint8_t*) p; int wid = pp[0], hei = pp[1], xcen = pp[2], ycen = pp[3]; sprites[i].x = xcen; sprites[i].y = ycen; sprites[i].s = SDL_CreateRGBSurface(SDL_HWSURFACE|SDL_SRCALPHA,wid,hei,32, 0xff,0xff00,0xff0000,0xff000000); SDL_LockSurface(sprites[i].s); uint32_t* data = (uint32_t*) sprites[i].s->pixels; for (int z=0; z>8) % 320; int y = ((0x0fffff00&*q)>>8) / 320; if ((y*wid+x<0)||(y*wid+x>=wid*hei)) printf("%i: x=%i y=%i wid=%i hei=%i: bad idea\n",i,x,y,wid,hei); else data[y*wid+x] = palette[0xff&*q]; } SDL_UnlockSurface(sprites[i].s); } return num_sprites; } void update_keyboard() { SDL_Event e; SDL_KeyboardEvent* ke; SDL_MouseButtonEvent* me; while (SDL_PollEvent(&e)) { // why not SDL_PeepEvents(&e, 1, SDL_GETEVENT, SDL_KEYDOWNMASK|SDL_KEYUPMASK)>0)? switch (e.type) { case SDL_KEYDOWN: ke=(SDL_KeyboardEvent*)&e; keyboard[ke->keysym.sym] = 0xff; keybuf = ke->keysym.sym; break; case SDL_KEYUP: ke=(SDL_KeyboardEvent*)&e; keyboard[ke->keysym.sym] = 0; break; case SDL_MOUSEBUTTONDOWN: me=(SDL_MouseButtonEvent*)&e; switch (me->button) { case SDL_BUTTON_LEFT: mouse|=4; break; case SDL_BUTTON_MIDDLE: mouse|=2; break; case SDL_BUTTON_RIGHT: mouse|=1; break; } break; case SDL_MOUSEBUTTONUP: me=(SDL_MouseButtonEvent*)&e; switch (me->button) { case SDL_BUTTON_LEFT: mouse&=~4; break; case SDL_BUTTON_MIDDLE: mouse&=~2; break; case SDL_BUTTON_RIGHT: mouse&=~1; break; } break; } } } void fspplot(fastspr_sprite* sprites, char n, int x, int y) { fastspr_sprite sprite = sprites[(char)n]; static SDL_Rect pos; pos.x = x - sprite.x; pos.y = y - sprite.y; SDL_BlitSurface(sprite.s, NULL, ArcScreen, &pos); }