// C Header File // Created 11/27/2002; 1:01:08 PM static void GraySprite32_OR_64x64(short x,short y,short h,unsigned long* sprite1, unsigned long* sprite2,void* dest1,void* dest2); static void GraySprite32_AND_64x64(short x,short y,short h,unsigned long* sprite1, unsigned long* sprite2,void* dest1,void* dest2); static void SpriteX8_AND_96x96(short x,short y,short h,unsigned char* sprite, short bytewidth,void* dest); static void SpriteX8_OR_96x96(short x,short y,short h,unsigned char* sprite, short bytewidth,void* dest); static void GraySprite16_OR_96x96 (short x, short y, short h,unsigned short *sprite1, unsigned short *sprite2, void *dest1, void *dest2); static void Sprite16_AND_96x96 (short x, short y, short h, unsigned short *sprite, void *dest); static void dissolveGSFromTo (unsigned char *src0,unsigned char *src1, unsigned char *dest0,unsigned char *dest1); static inline void CopyBG(void); static inline void InitGUI(void); static inline void DisplayGUI(void); static inline unsigned char* DecompressIt(unsigned char* src); static inline short LoadGraphicsFiles(void); static inline void UpdateCounters(void); static inline unsigned short DrawStrWidthP(const char *str, short len, short font); static void textEnqueue(const char *new); static inline void textDisplayAndCycle(void); static void ResetMarquee(void); static inline void BlitPage(short offset); static void ProcessTextScrolling(short set); static void portalEffects(void); #define SetupCrosshair() \ {GraySprite16_OR_96x96(40,40,16, \ circle,circle+16, \ gg->HUDlight,gg->HUDdark); \ Sprite16_AND_96x96(40,40,16, \ circle+32,gg->HUDmask);} #define textEnqueueF(f...) {sprintf(gg->textbuf,##f);textEnqueue(gg->textbuf);} #ifndef __GFX_H__ #define __GFX_H__ #include "weapons.h" #include "intro.h" static void GraySprite32_OR_64x64(short x,short y,short h,unsigned long* sprite1, unsigned long* sprite2,void* dest1,void* dest2) { register long offset = (y*8)+((x>>3)&0xfffe); register long addr1 = (long)dest1+offset; register long addr2 = (long)dest2+offset; register unsigned short cnt = x&15; register unsigned short ccnt = 32-cnt; register unsigned long data; for (;h;h--,addr1+=8,addr2+=8) { data=*sprite1++; *(long*)addr1|=(data>>cnt),*(long*)(addr1+4)|=(data<>cnt),*(long*)(addr2+4)|=(data<>3)&0xfffe); register long addr1 = (long)dest1+offset; register long addr2 = (long)dest2+offset; register unsigned short cnt = x&15; register unsigned short ccnt = 32-cnt; register unsigned long data; for (;h;h--,addr1+=8,addr2+=8) { data=~(*sprite1++); *(long*)addr1&=~(data>>cnt),*(long*)(addr1+4)&=~(data<>cnt),*(long*)(addr2+4)&=~(data<>3)); register unsigned short mask1 = x & 7; register unsigned short mask2; register unsigned short lineoffset = 12-bytewidth; register short loop; register unsigned char startmask; register unsigned char endmask; if (mask1) { mask2 = 8 - mask1; startmask = 0xff << mask2; endmask = 0xff >> mask1; for (;h;h--,addr+=lineoffset) { *addr++ &= (*sprite >> mask1) | startmask; for (loop=1;loop> mask1); } *addr &= (*sprite++ << mask2) | endmask; } } else { for (;h;h--,addr+=lineoffset) { for (loop=0;loop>3)); register unsigned short mask1 = x & 7; register unsigned short mask2; register unsigned short lineoffset = 12-bytewidth; register short loop; if (mask1) { mask2 = 8 - mask1; for (;h;h--,addr+=lineoffset) { *addr++ |= *sprite >> mask1; for (loop=1;loop> mask1); } *addr |= (*sprite++ << mask2); } } else { for (;h;h--,addr+=lineoffset) { for (loop=0;loop> 3) & 0xfffe); register long addr1 = (long) dest1 + offset; register long addr2 = (long) dest2 + offset; register unsigned short cnt = 16 - (x & 15); for (;h; h--,addr1 += 12, addr2 += 12) { *(long *) addr1 |= (long) ((*sprite1++) & 0xffff) << cnt; *(long *) addr2 |= (long) ((*sprite2++) & 0xffff) << cnt; } } static void Sprite16_AND_96x96 (short x, short y, short h, unsigned short *sprite, void *dest) { register long addr = (long) dest + (y * 12) + ((x >> 3) & 0xfffe); register unsigned short cnt = 16 - (x & 15); for (;h; h--,addr += 12) *(long *) addr &= ~((long) ~((*sprite++) & 0xffff) << cnt); } static void dissolveGSFromTo (unsigned char *src0,unsigned char *src1, unsigned char *dest0,unsigned char *dest1) { unsigned short seq = 1; unsigned char pixmask; unsigned short byteoffset; do { pixmask = seq & 0x7; byteoffset = seq >> 3; if (byteoffset < LCD_SIZE) { pixmask = 0x80 >> pixmask; if (* (src0 + byteoffset) & pixmask) { * (dest0 + byteoffset) |= pixmask; } else { * (dest0 + byteoffset) &= ~pixmask; } if (* (src1 + byteoffset) & pixmask) { * (dest1 + byteoffset) |= pixmask; } else { * (dest1 + byteoffset) &= ~pixmask; } } if (seq & 1) seq = (seq >> 1) ^ 0x6000; else seq = seq >> 1; } while (seq != 1); } static inline void CopyBG(void) { register GameGlobals *ggg asm("a4") = gg; BlackGrayScreen2B(ggg->BGlight,ggg->BGdark); DrawGrayRect2B(96+display_offsetx,0+display_offsety,159+display_offsetx, 99+display_offsety,COLOR_WHITE,RECT_FILLED,ggg->BGlight,ggg->BGdark); GraySpriteX8_OR(96+display_offsetx,0+display_offsety,100, metalBG,metalBG+800,8,ggg->BGlight,ggg->BGdark); } //============================================================================= // initializes GUI //============================================================================= static inline void InitGUI(void) { register GameGlobals *ggg asm("a4") = gg; short offsetx = display_offsetx; short offsety = display_offsety; CopyBG(); DrawGrayRect2B(99+offsetx,18+offsety, 157+offsetx,37+offsety,COLOR_WHITE, RECT_FILLED,ggg->BGlight,ggg->BGdark); FontSetSys(F_4x6); DrawGrayStr2B(105+offsetx,20+offsety, (char*)titleVersionString,A_NORMAL,ggg->BGlight,ggg->BGdark); DrawGrayStr2B(102+offsetx,30+offsety, (char*)authorString,A_NORMAL,ggg->BGlight,ggg->BGdark); DrawGrayRect2B(109+offsetx,38+offsety, 147+offsetx,45+offsety,COLOR_WHITE, RECT_FILLED,ggg->BGlight,ggg->BGdark); if(ggg->current_level==38) strcpy(ggg->textbuf,stringIdx(gamestrings,eRoof)); else if(ggg->current_level>29 && ggg->current_level<38) sprintf(ggg->textbuf,"%s%i",stringIdx(gamestrings,eFloor),ggg->current_level-29); else sprintf(ggg->textbuf,"%s%02i",stringIdx(gamestrings,eLevel),ggg->current_level); DrawGrayStr2B(110+offsetx,39+offsety,ggg->textbuf,A_NORMAL, ggg->BGlight,ggg->BGdark); DrawGrayRect2B(125+offsetx,51+offsety, 132+offsetx,57+offsety,COLOR_LIGHTGRAY, RECT_FILLED,ggg->BGlight,ggg->BGdark); DrawGrayRect2B(104+offsetx,58+offsety, 152+offsetx,87+offsety,COLOR_LIGHTGRAY, RECT_FILLED,ggg->BGlight,ggg->BGdark); sprintf(ggg->textbuf,"%03i%s",ggg->player.life,stringIdx(gamestrings,eHealthHUD)); DrawGrayStr1B(107+offsetx,60+offsety,ggg->textbuf,A_REPLACE,ggg->BGdark); sprintf(ggg->textbuf,"%03i%s",ggg->player.armor,stringIdx(gamestrings,eArmorHUD)); DrawGrayStr1B(107+offsetx,70+offsety,ggg->textbuf,A_REPLACE,ggg->BGdark); if(weapons[ggg->cur_weapon].ammo == INFINITE_AMMO) sprintf(ggg->textbuf,"---%s",stringIdx(gamestrings,eAmmoHUD)); else sprintf(ggg->textbuf,"%03i%s", weapons[ggg->cur_weapon].ammo,stringIdx(gamestrings,eAmmoHUD)); DrawGrayStr1B(107+offsetx,79+offsety,ggg->textbuf,A_REPLACE,ggg->BGdark); DrawGrayRect2B(97+offsetx,90+offsety, 158+offsetx,97+offsety,COLOR_WHITE,RECT_FILLED,ggg->BGlight,ggg->BGdark); } static inline void DisplayGUI(void) { register GameGlobals *ggg asm("a4") = gg; short toadd = (14*30+6)/2; fc->dest_plane0 = (void*)((BYTE*)ggg->BGlight+30*2); fc->dest_plane1 = (void*)((BYTE*)ggg->BGdark+30*2); if (!TI89) { /* TI92p or V200 */ fc->dest_plane0 += toadd; fc->dest_plane1 += toadd; } fc->nr_sprites = ggg->sprite_count; HandleEvents(); AnimateStaticSprites(); AnimateWalls(); FAT_Render(fc); dissolveGSFromTo(ggg->BGlight,ggg->BGdark,ggg->plane1,ggg->plane2); fc->dest_plane0 = (void*)((BYTE*)ggg->plane1+30*2); fc->dest_plane1 = (void*)((BYTE*)ggg->plane2+30*2); if (!TI89) { /* TI92p or V200 */ fc->dest_plane0 += toadd; fc->dest_plane1 += toadd; } } static inline unsigned char* DecompressIt(unsigned char* src) { unsigned char* dest = NULL; if (!FAT_ValidEXEPACK(src)) return NULL; // is input really exepacked? if ((dest = malloc_special(FAT_UnpackSize(src)))) { // allocate memory for output data if (FAT_UnpackBuffer(src,dest)) // decompress { // unpacking failed free_special(dest); dest = NULL; } } return dest; } static inline short LoadGraphicsFiles(void) { register GameGlobals *ggg asm("a4") = gg; short a; unsigned char* src = 0; //unsigned char *dest = NULL; short offset; if ((ggg->texfile0 = FAT_GetHandleOfFile("oblvgfx0"))) { if ((src = FAT_LockHandleOfFile(ggg->texfile0))) { ggg->gfx0 = /*DecompressIt*/(src+2); } } if(!(ggg->texfile0 && src/* && gfx0*/)) return 0; //------------------------------------------------------------------------- // try to load the used textures from gfx file(s)... //------------------------------------------------------------------------- if ((ggg->texfile = FAT_GetHandleOfFile("oblvgfx1"))) { if ((ggg->texptr = FAT_LockHandleOfFile(ggg->texfile))) { ggg->texptr+=2; // load textures #ifndef COMPRESSED_TEXTURES if (!FAT_LoadTextures(ggg->textures,ggg->texptr,0, TOTAL_TEXCONFIGS_IN_oblvgfx1)) { src = 0; // just to indicate something went wrong } #endif } } if(!(ggg->texfile && ggg->texptr)) return -1; if ((ggg->texfile2 = FAT_GetHandleOfFile("oblvgfx2"))) { if ((src = FAT_LockHandleOfFile(ggg->texfile2))) { // load textures if (!FAT_LoadTextures(ggg->sprites_s,src+2,0, TOTAL_TEXCONFIGS_IN_oblvgfx2)) { src = 0; // just to indicate something went wrong } } } if(!(ggg->texfile2 && src)) return -2; if ((ggg->texfile3 = FAT_GetHandleOfFile("oblvgfx3"))) { if ((src = FAT_LockHandleOfFile(ggg->texfile3))) { //dest3 = DecompressIt(src+2); if (!FAT_LoadTextures(ggg->projectilemodels,/*dest3*/src+2,0, TOTAL_TEXCONFIGS_IN_oblvgfx3)) { src = 0; // just to indicate something went wrong } for(a=0;aweapmodel = (unsigned char*)FAT_GetGenericData (/*dest3*/src+2,a,FAT_DONTCHECKLENGTH))) { src = 0; // just to indicate something went wrong break; } else { weapons[a].cur->hud_x = *(unsigned short*)(ggg->weapmodel); weapons[a].cur->hud_y = *(unsigned short*)(ggg->weapmodel+2); ggg->weapmodel += 4; offset = weapons[a].cur->hud_y * (weapons[a].cur->hud_x>>3); weapons[a].cur->lightdata[0] = ggg->weapmodel; ggg->weapmodel += offset; weapons[a].cur->darkdata[0] = ggg->weapmodel; ggg->weapmodel += offset; weapons[a].cur->maskdata[0] = ggg->weapmodel; ggg->weapmodel += offset; weapons[a].cur->lightdata[1] = ggg->weapmodel; ggg->weapmodel += offset; weapons[a].cur->darkdata[1] = ggg->weapmodel; ggg->weapmodel += offset; weapons[a].cur->maskdata[1] = ggg->weapmodel; } } #if(!(TOTAL_GENERICDATAS_IN_oblvgfx3==WEAPON_COUNT)) #error WEAPON_COUNT does not equal TOTAL_GENERICDATAS_IN_oblvgfx3. #endif } } if(!(ggg->texfile3 && src/* && dest3*/)) return -3; if ((ggg->texfile4 = FAT_GetHandleOfFile("oblvgfx4"))) { if ((src = FAT_LockHandleOfFile(ggg->texfile4))) { //dest4 = DecompressIt(src+2); // load textures if (!FAT_LoadTextures(ggg->enemysprites,/*dest4*/src+2, 0, TOTAL_TEXCONFIGS_IN_oblvgfx4)) { src = 0; // just to indicate something went wrong } } } if(!(ggg->texfile4 && src/* && dest4*/)) return -4; return 1; } static inline void UpdateCounters(void) { register GameGlobals *ggg asm("a4") = gg; register short offsetx = display_offsetx, offsety = display_offsety; if(ggg->oldPlayer.life != ggg->player.life) { Fix3(ggg->textbuf,ggg->player.life); DrawGrayStr1B(107+display_offsetx,60+display_offsety,ggg->textbuf,A_REPLACE,ggg->plane2); } if(ggg->oldPlayer.armor != ggg->player.armor) { Fix3(ggg->textbuf,ggg->player.armor); DrawGrayStr1B(107+display_offsetx,70+display_offsety,ggg->textbuf,A_REPLACE,ggg->plane2); } if(ggg->oldAmmo != weapons[ggg->cur_weapon].ammo) { Fix3(ggg->textbuf,weapons[ggg->cur_weapon].ammo); DrawGrayStr1B(107+display_offsetx,79+display_offsety,ggg->textbuf,A_REPLACE,ggg->plane2); } if(ggg->playerHasKeycard && !ggg->oldPlayerHasKeycard) { DrawGrayStr1B(126+display_offsetx,52+display_offsety,"K",A_REPLACE,ggg->plane2); } short x = 104+offsetx; x+= ((current_weapon->curdelay*48)/current_weapon->cur->repeatdelay); FastDrawGrayHLine2B(104+offsetx,x,87+offsety,COLOR_WHITE,ggg->plane1,ggg->plane2); if(x<152+offsetx) FastDrawGrayHLine2B(x,152+offsetx, 87+offsety,COLOR_BLACK,ggg->plane1,ggg->plane2); //memcpy(&ggg->oldPlayer,&ggg->player,sizeof(Player)); *(long*)&ggg->oldPlayer=*(long*)&ggg->player;//faster ggg->oldAmmo = weapons[ggg->cur_weapon].ammo; ggg->oldPlayerHasKeycard = gg->playerHasKeycard; } static inline unsigned short DrawStrWidthP(const char *str, short len, short font) { char s[len+1]; short i; // Calling memcpy is slower than copying the string by-hand... for (i = len; i--;) s[i] = str[i]; s[len] = 0; return DrawStrWidth (s, font); } static void textEnqueue(const char *new) { register GameGlobals *ggg asm("a4") = gg; short adjust = strlen(ggg->marquee); if(strlen(ggg->marquee)+strlen(new)>MARQUEE_SIZE-1) return; //Unsuccessful strcpy(ggg->marquee+adjust+!!adjust,new); if(adjust) ggg->marquee[adjust] = ' '; } static inline void textDisplayAndCycle(void) { register GameGlobals *ggg asm("a4") = gg; short len = strlen(ggg->marquee)>18?18:strlen(ggg->marquee),t; if(!(ggg->marquee_time%18) || (len&&ggg->oldlen==0)) { if(len&&ggg->oldlen==0) { ggg->marquee_time -= (ggg->marquee_time%18)-1; } ggg->oldlen = len; while(DrawStrWidthP(ggg->marquee,len,F_4x6)>59) len--; t=0; while(ggg->marquee[t]!=' ' && t<18) t++; t= t==18; while(ggg->marquee[len-1]!=' ' && ggg->marquee[len] && !t) len--; if(!len) { DrawGrayRect(97+display_offsetx,90+display_offsety, 158+display_offsetx,97+display_offsety,COLOR_WHITE,RECT_FILLED); return; } strncpy(ggg->marquee_cur,ggg->marquee,len); ggg->marquee_cur[len]=0; DrawGrayRect(97+display_offsetx,90+display_offsety, 158+display_offsetx,97+display_offsety,COLOR_WHITE,RECT_FILLED); DrawGrayStr(98+display_offsetx,91+display_offsety,ggg->marquee_cur,A_NORMAL); memmove(ggg->marquee,ggg->marquee+len,strlen(ggg->marquee)-len); ggg->marquee[strlen(ggg->marquee)-len]=0; } } static void ResetMarquee(void) { register GameGlobals *ggg asm("a4") = gg; memset(ggg->marquee,0,MARQUEE_SIZE); memset(ggg->textbuf,0,MARQUEE_SIZE); memset(ggg->marquee_cur,0,20); ggg->oldlen = 0; } //============================================================================= // Blits background planes to grayplanes (combining them with the textplane) //============================================================================= static inline void BlitPage(short offset) { unsigned long* tmptext = gg->textplane; unsigned long* p0 = (unsigned long*)((unsigned char*)gg->plane1+offset); unsigned long* p1 = (unsigned long*)((unsigned char*)gg->plane2+offset); short i; // NOTE: the lightplane is not taken from the image, but filled // with black (0xffffffff). otherwise the white text wouldn't // be readable anymore. // // (The textplane contains white text on black background) // loop once for each line to copy ... for (i=100;i--;) { *p0++ = 0xffffffff & ((*tmptext)); *p1++ = 0xffffffff & ((*tmptext++)); *p0++ = 0xffffffff & ((*tmptext)); *p1++ = 0xffffffff & ((*tmptext++)); *p0++ = 0xffffffff & ((*tmptext)); *p1++ = 0xffffffff & ((*tmptext++)); *p0++ = 0xffffffff & ((*tmptext)); *p1++ = 0xffffffff & ((*tmptext++)); *p0++ = 0xffffffff & ((*tmptext)); *p1++ = 0xffffffff & ((*tmptext++)); ((unsigned char*)p0)+=10; ((unsigned char*)p1)+=10; } } //============================================================================= // the scrolling routine itself // note that ptr is in a special format: // * number of lines (short) // * nr_lines shorts that are offsets (starting with 0) to where each line's // string begins, in relation to the first string // * string data //============================================================================= static void ProcessTextScrolling(short set) { register GameGlobals *ggg asm("a4") = gg; short nr_lines = getNrLines(ggg->text,set); short actline = 0; short i = 9; unsigned short waitnr = 26; short offset = (TI89) ? 0 : 4+30*12; // for the TI92p we center the image short leave = 0; unsigned long* src; unsigned long* dest; short loop; int1_counter = 0; FontSetSys(F_6x8); // initialize all graphic functions to use our invisible textplane PortSet(ggg->textplane,159,99+ADDITIONALLY_LINES); // fill textplane with black memset(ggg->textplane,0xff,20*(100+ADDITIONALLY_LINES)); // fill grayplane 0 and 1 with black BlackGrayScreen(); // loop until the user gets bored ... do { dest = ggg->textplane; src = &ggg->textplane[LINES_TO_SCROLL*5]; // scrolling up the invisible textplane is performed by // a kind of memmove ... for (loop=(100+ADDITIONALLY_LINES-LINES_TO_SCROLL)*5;loop--;) *dest++ = *src++; // fill part below the last "visible" line with blacks if (i>=7) { memset(&ggg->textplane[100*5],0xff,ADDITIONALLY_LINES*20); } // it's time to print the next line to the part below the last // "visible" line ... if (i==9) { i = 0; memset(&ggg->textplane[100*5],0xff,ADDITIONALLY_LINES*20); // draw the string centered DrawStr((160-DrawStrWidth(stringIdx(set,actline),F_6x8)) >>1,100,stringIdx(set,actline),A_REVERSE); actline++; if (actline==nr_lines) {actline = 0;leave=1;} } else { i+=LINES_TO_SCROLL; } // perform a page blit (combines background planes // with textplane and copy the result to the grayplanes) //BlitPage(offset); // wait a little bit ... while (int1_counter < waitnr); BlitPage(offset); int1_counter=0; // process a key press ... if (_keytest(RR_PLUS)) { if (waitnr) waitnr--; leave = 0; } if (_keytest(RR_MINUS)) { if (waitnr < 199) waitnr++; leave = 0; } if (KeyCheck(KEY_PAUSE)) { FAT_AllKeysReleased(); FAT_WaitKeyPressed(); FAT_AllKeysReleased(); } if(_keytest(RR_ESC)) leave++; } while (!leave); FAT_AllKeysReleased(); } static void portalEffects(void) { register GameGlobals *ggg asm("a4") = gg; OSContrastDn(); if(ggg->HW2) OSContrastDn(); memset(ggg->textplane,0xFF,LCD_SIZE); while(ggg->zoffset) { DrawStars(); FastCopyScreen(ggg->BGlight,ggg->plane1); FastCopyScreen(ggg->BGdark,ggg->plane2); ggg->zoffset-=2; } ggg->zoffset = ZOFFSET; OSContrastUp(); if(ggg->HW2) OSContrastUp(); } #endif