DOOM64-RE

Doom 64 Reverse Engineering
Log | Files | Refs | README | LICENSE

commit 810e31341a27350a9b63a03934797398875b0180
parent 766ada1ac56f65890b5bcf884bd7e7f73fface0f
Author: Erick Vásquez García <41172072+Erick194@users.noreply.github.com>
Date:   Wed, 18 Nov 2020 00:19:59 -0600

Add files via upload
Diffstat:
ADoom 64/__elfcom.c | 1+
ADoom 64/am_main.c | 587+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/asci.c | 130+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/asm.h | 49+++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/audio.c | 544+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/audio.h | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/audio_heap.c | 6++++++
ADoom 64/c_convert.c | 242+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/cfb.c | 14++++++++++++++
ADoom 64/d_main.c | 226+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/d_screens.c | 287+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/decodes.c | 885+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/doomdata.h | 220+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/doomdef.h | 1291+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/doominfo.c | 4437+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/doominfo.h | 1113+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/doomlib.c | 213+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/f_main.c | 996+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/funqueue.c | 144+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/funqueue.h | 18++++++++++++++++++
ADoom 64/g_game.c | 348+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/graph.c | 462+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/graph.h | 53+++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/i_main.c | 1171+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/i_main.h | 8++++++++
ADoom 64/in_main.c | 343+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/m_bbox.c | 21+++++++++++++++++++++
ADoom 64/m_fixed.c | 99+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/m_fixed_s.s | 98+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/m_main.c | 2639+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/m_password.c | 715+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/mem_heap.c | 6++++++
ADoom 64/n64cmd.c | 1109+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/n64cmd.h | 3+++
ADoom 64/p_base.c | 820+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/p_ceilng.c | 316+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/p_change.c | 170+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/p_doors.c | 305++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/p_enemy.c | 1991+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/p_floor.c | 580+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/p_inter.c | 839+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/p_lights.c | 668+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/p_local.h | 327+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/p_macros.c | 185+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/p_map.c | 448+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/p_maputl.c | 591+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/p_misc.c | 843+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/p_mobj.c | 570+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/p_move.c | 747+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/p_plats.c | 298+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/p_pspr.c | 1394+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/p_setup.c | 821+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/p_shoot.c | 925+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/p_sight.c | 307+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/p_slide.c | 755+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/p_spec.c | 1305+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/p_spec.h | 653+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/p_switch.c | 87+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/p_telept.c | 148+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/p_tick.c | 369+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/p_user.c | 853+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/r_data.c | 92+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/r_local.h | 378+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/r_main.c | 406+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/r_phase1.c | 569+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/r_phase2.c | 549+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/r_phase3.c | 1288+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/regdef.h | 187+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/s_sound.c | 281+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/seqload.c | 490+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/seqload.h | 116+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/seqloadl.c | 97+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/seqloadr.c | 94+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/soundhw.h | 23+++++++++++++++++++++++
ADoom 64/sounds.h | 135+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/sprinfo.c | 660+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/st_main.c | 829+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/st_main.h | 49+++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/stdarg.h | 27+++++++++++++++++++++++++++
ADoom 64/tables.c | 263+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/vsprintf.c | 123+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/w_wad.c | 478+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/wessapi.c | 1324+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/wessapi.h | 552+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/wessapic.c | 96+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/wessapim.c | 244+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/wessapip.c | 535+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/wessapit.c | 649+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/wessarc.c | 530+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/wessarc.h | 465+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/wessedit.c | 219+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/wessedit.h | 12++++++++++++
ADoom 64/wessfade.c | 39+++++++++++++++++++++++++++++++++++++++
ADoom 64/wessfade.h | 8++++++++
ADoom 64/wesshand.h | 32++++++++++++++++++++++++++++++++
ADoom 64/wessint_s.h | 10++++++++++
ADoom 64/wessint_s.s | 82+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ADoom 64/wessseq.h | 32++++++++++++++++++++++++++++++++
ADoom 64/wessshell.h | 10++++++++++
ADoom 64/wesstrak.h | 29+++++++++++++++++++++++++++++
100 files changed, 47860 insertions(+), 0 deletions(-)

diff --git a/Doom 64/__elfcom.c b/Doom 64/__elfcom.c @@ -0,0 +1 @@ +#include <ultra64.h> diff --git a/Doom 64/am_main.c b/Doom 64/am_main.c @@ -0,0 +1,587 @@ +/* am_main.c -- automap */ + +#include "doomdef.h" +#include "p_local.h" + +#define COLOR_RED 0xA40000FF +#define COLOR_GREEN 0x00C000FF +#define COLOR_BROWN 0x8A5C30ff +#define COLOR_YELLOW 0xCCCC00FF +#define COLOR_GREY 0x808080FF +#define COLOR_AQUA 0x3373B3FF + +#define MAXSCALE 1500 +#define MINSCALE 200 + +fixed_t am_box[4]; // 80063110 +int am_plycolor; // 80063120 +int am_plyblink; // 80063124 + +void AM_DrawSubsectors(player_t *player); +void AM_DrawThings(fixed_t x, fixed_t y, angle_t angle, int color); +void AM_DrawLine(player_t *player); + +/*================================================================= */ +/* */ +/* Start up Automap */ +/* */ +/*================================================================= */ + +void AM_Start(void) // 800004D8 +{ + am_plycolor = 95; + am_plyblink = 16; +} + +/* +================== += += AM_Control += += Called by P_PlayerThink before any other player processing += += Button bits can be eaten by clearing them in ticbuttons[playernum] +================== +*/ + +#define MAXSENSIVITY 10 + +void AM_Control (player_t *player) // 800004F4 +{ + int buttons, oldbuttons; + + buttons_t *cbuttons; + fixed_t block[8]; + angle_t angle; + fixed_t fs, fc; + fixed_t x, y, x1, y1, x2, y2; + int scale, sensitivity; + int i; + + if (gamepaused) + return; + + cbuttons = BT_DATA[0]; + buttons = ticbuttons[0]; + oldbuttons = oldticbuttons[0]; + + if (player->playerstate != PST_LIVE) + { + am_plycolor = 79; + return; + } + + if ((buttons & cbuttons->BT_MAP) && !(oldbuttons & cbuttons->BT_MAP)) + { + if(player->automapflags & AF_SUBSEC) + { + player->automapflags &= ~AF_SUBSEC; + player->automapflags |= AF_LINES; + } + else if(player->automapflags & AF_LINES) + { + player->automapflags &= ~AF_LINES; + } + else + { + player->automapflags |= AF_SUBSEC; + } + + player->automapx = player->mo->x; + player->automapy = player->mo->y; + } + + if(!(player->automapflags & (AF_LINES|AF_SUBSEC))) + return; + + /* update player flash */ + am_plycolor = (unsigned int)(am_plycolor + am_plyblink); + if(am_plycolor < 80 || (am_plycolor >= 255)) + { + am_plyblink = -am_plyblink; + } + + if (!(buttons & cbuttons->BT_USE)) + { + player->automapflags &= ~AF_FOLLOW; + return; + } + + if (!(player->automapflags & AF_FOLLOW)) + { + player->automapflags |= AF_FOLLOW; + player->automapx = player->mo->x; + player->automapy = player->mo->y; + + M_ClearBox(am_box); + + block[2] = block[4] = (bmapwidth << 23 ) + bmaporgx; + block[1] = block[3] = (bmapheight << 23) + bmaporgy; + block[0] = block[6] = bmaporgx; + block[5] = block[7] = bmaporgy; + + angle = (ANG90 - player->mo->angle) >> ANGLETOFINESHIFT; + + fs = finesine[angle]; + fc = finecosine[angle]; + + for(i = 0; i < 8; i+=2) + { + x = (block[i] - player->automapx) >> FRACBITS; + y = (block[i+1] - player->automapy) >> FRACBITS; + + x1 = (x * fc); + y1 = (y * fs); + x2 = (x * fs); + y2 = (y * fc); + + x = (x1 - y1) + player->automapx; + y = (x2 + y2) + player->automapy; + + M_AddToBox(am_box, x, y); + } + } + + if (!(player->automapflags & AF_FOLLOW)) + return; + + scale = player->automapscale << 15; + scale = (scale / 1500) << 8; + + /* Analyze analog stick movement (left / right) */ + sensitivity = (int)(((buttons & 0xff00) >> 8) << 24) >> 24; + + if(sensitivity >= MAXSENSIVITY || sensitivity <= -MAXSENSIVITY) + { + player->automapx += (sensitivity * scale) / 80; + } + + /* Analyze analog stick movement (up / down) */ + sensitivity = (int)((buttons) << 24) >> 24; + + if(sensitivity >= MAXSENSIVITY || sensitivity <= -MAXSENSIVITY) + { + player->automapy += (sensitivity * scale) / 80; + } + + /* X movement */ + if (player->automapx > am_box[BOXRIGHT]) + { + player->automapx = am_box[BOXRIGHT]; + } + else if (player->automapx < am_box[BOXLEFT]) + { + player->automapx = am_box[BOXLEFT]; + } + + /* Y movement */ + if (player->automapy > am_box[BOXTOP]) + { + player->automapy = am_box[BOXTOP]; + } + else if (player->automapy < am_box[BOXBOTTOM]) + { + player->automapy = am_box[BOXBOTTOM]; + } + + /* Zoom scale in */ + if (buttons & PAD_L_TRIG) + { + player->automapscale -= 32; + + if (player->automapscale < MINSCALE) + player->automapscale = MINSCALE; + } + + /* Zoom scale out */ + if (buttons & PAD_R_TRIG) + { + player->automapscale += 32; + + if (player->automapscale > MAXSCALE) + player->automapscale = MAXSCALE; + } + + ticbuttons[0] &= ~(cbuttons->BT_LEFT | cbuttons->BT_RIGHT | + cbuttons->BT_FORWARD | cbuttons->BT_BACK | + PAD_L_TRIG | PAD_R_TRIG | 0xffff); +} + +/* +================== += += AM_Drawer += += Draws the current frame to workingscreen +================== +*/ + +void AM_Drawer (void) // 800009AC +{ + int i; + player_t *p; + mobj_t *mo; + mobj_t *next; + fixed_t xpos, ypos; + fixed_t ox, oy; + fixed_t c; + fixed_t s; + angle_t angle; + int color; + int scale; + int artflag; + char map_name[48]; + + gDPPipeSync(GFX1++); + gDPSetCycleType(GFX1++, G_CYC_FILL); + gDPSetRenderMode(GFX1++,G_RM_NOOP,G_RM_NOOP2); + + gDPSetColorImage(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_32b, SCREEN_WD, OS_K0_TO_PHYSICAL(cfb[vid_side])); + + /* Fill borders with black */ + gDPSetFillColor(GFX1++, GPACK_RGBA5551(0,0,0,0) << 16 | GPACK_RGBA5551(0,0,0,0)); + gDPFillRectangle(GFX1++, 0, 0, SCREEN_WD-1, SCREEN_HT-1); + gDPSetRenderMode(GFX1++, G_RM_OPA_CI, G_RM_AA_OPA_SURF2); + + p = &players[0]; + + scale = (p->automapscale << 16); + xpos = p->mo->x; + ypos = p->mo->y; + + if (p->onground) + { + xpos += (quakeviewx >> 7); + ypos += quakeviewy; + } + + if (p->automapflags & AF_FOLLOW) + { + angle = (p->mo->angle + ANG270) >> ANGLETOFINESHIFT; + ox = (p->automapx - xpos) >> 16; + oy = (p->automapy - ypos) >> 16; + xpos += ((ox * finecosine[angle]) - (oy * finesine [angle])); + ypos += ((ox * finesine [angle]) + (oy * finecosine[angle])); + } + + angle = p->mo->angle >> ANGLETOFINESHIFT; + + s = finesine[angle]; + c = finecosine[angle]; + + gSPMatrix(GFX1++, OS_K0_TO_PHYSICAL(MTX1), G_MTX_MODELVIEW| G_MTX_LOAD | G_MTX_NOPUSH); + MTX1->m[0][0] = 0x10000; + MTX1->m[0][1] = 0; + MTX1->m[0][2] = 0; + MTX1->m[0][3] = 0x10000; + MTX1->m[1][0] = 0xffff; + MTX1->m[1][1] = 0; + MTX1->m[1][2] = 0; + MTX1->m[1][3] = 1; + MTX1->m[2][0] = 0; + MTX1->m[2][1] = 0; + MTX1->m[2][2] = 0; + MTX1->m[2][3] = 0; + MTX1->m[3][0] = 0; + MTX1->m[3][1] = 0; + MTX1->m[3][2] = 0; + MTX1->m[3][3] = 0; + MTX1+=1; + + gSPMatrix(GFX1++, OS_K0_TO_PHYSICAL(MTX1), G_MTX_MODELVIEW| G_MTX_MUL | G_MTX_NOPUSH); + MTX1->m[0][0] = (s & 0xffff0000); + MTX1->m[0][1] = ((-c) & 0xffff0000); + MTX1->m[0][2] = 1; + MTX1->m[0][3] = 0; + MTX1->m[1][0] = (c & 0xffff0000); + MTX1->m[1][1] = (s & 0xffff0000); + MTX1->m[1][2] = 0; + MTX1->m[1][3] = 1; + MTX1->m[2][0] = ((s << 16) & 0xffff0000); + MTX1->m[2][1] = (((-c)<<16) & 0xffff0000); + MTX1->m[2][2] = 0; + MTX1->m[2][3] = 0; + MTX1->m[3][0] = ((c << 16) & 0xffff0000); + MTX1->m[3][1] = ((s << 16) & 0xffff0000); + MTX1->m[3][2] = 0; + MTX1->m[3][3] = 0; + MTX1+=1; + + gSPMatrix(GFX1++, OS_K0_TO_PHYSICAL(MTX1), G_MTX_MODELVIEW| G_MTX_MUL | G_MTX_NOPUSH); + MTX1->m[0][0] = 0x10000; + MTX1->m[0][1] = 0; + MTX1->m[0][2] = 1; + MTX1->m[0][3] = 0; + MTX1->m[1][0] = 0; + MTX1->m[1][1] = 0x10000; + MTX1->m[1][2] = ((-xpos) & 0xffff0000) | (((-scale) >> 16) &0xffff); + MTX1->m[1][3] = (ypos & 0xffff0000) | 1; + MTX1->m[2][0] = 0; + MTX1->m[2][1] = 0; + MTX1->m[2][2] = 0; + MTX1->m[2][3] = 0; + MTX1->m[3][0] = 0; + MTX1->m[3][1] = 0; + MTX1->m[3][2] = (((-xpos) << 16) & 0xffff0000) | ((-scale) &0xffff); + MTX1->m[3][3] = ((ypos << 16) & 0xffff0000); + MTX1+=1; + + if (p->automapflags & AF_LINES) + { + AM_DrawLine(p); + } + else + { + AM_DrawSubsectors(p); + gDPPipeSync(GFX1++); + gDPSetCombineMode(GFX1++, G_CC_SHADE, G_CC_SHADE); + } + + /* SHOW ALL MAP THINGS (CHEAT) */ + if (p->cheats & CF_ALLMAP) + { + for (mo = mobjhead.next; mo != &mobjhead; mo = next) + { + I_CheckGFX(); + next = mo->next; + + if (mo == p->mo) + continue; /* Ignore player */ + + if (mo->flags & (MF_NOSECTOR|MF_RENDERLASER)) + continue; + + if (mo->flags & (MF_SHOOTABLE|MF_MISSILE)) + color = COLOR_RED; + else + color = COLOR_AQUA; + + AM_DrawThings(mo->x, mo->y, mo->angle, color); + + if (p->automapflags & AF_LINES) + { + gSPLine3D(GFX1++, 0, 1, 0 /*flag*/); + gSPLine3D(GFX1++, 1, 2, 0 /*flag*/); + gSPLine3D(GFX1++, 2, 0, 0 /*flag*/); + } + else + { + gSP1Triangle(GFX1++, 0, 1, 2, 0 /*flag*/); + } + } + } + + /* SHOW PLAYERS */ + AM_DrawThings(p->mo->x, p->mo->y, p->mo->angle, am_plycolor << 16 | 0xff); + + if (p->automapflags & AF_LINES) + { + gSPLine3D(GFX1++, 0, 1, 0 /*flag*/); + gSPLine3D(GFX1++, 1, 2, 0 /*flag*/); + gSPLine3D(GFX1++, 2, 0, 0 /*flag*/); + + gDPPipeSync(GFX1++); + gDPSetScissor(GFX1++, G_SC_NON_INTERLACE, 0, 0, SCREEN_WD, SCREEN_HT); + } + else + { + gSP1Triangle(GFX1++, 0, 1, 2, 0 /*flag*/); + } + + + if (enable_messages) + { + if (p->messagetic <= 0) + { + sprintf(map_name, "LEVEL %d: %s", gamemap, MapInfo[gamemap].name); + ST_Message(20, 20, map_name, 0xffffffff); + } + else + { + ST_Message(20, 20, p->message, 0xffffffff); + } + } + + xpos = 280; + artflag = 4; + do + { + if ((players->artifacts & artflag) != 0) + { + if (artflag == 4) + { + BufferedDrawSprite(MT_ITEM_ARTIFACT3, &states[S_559], 0, 0xffffff80, xpos, 255); + } + else if (artflag == 2) + { + BufferedDrawSprite(MT_ITEM_ARTIFACT2, &states[S_551], 0, 0xffffff80, xpos, 255); + } + else if (artflag == 1) + { + BufferedDrawSprite(MT_ITEM_ARTIFACT1, &states[S_543], 0, 0xffffff80, xpos, 255); + } + + xpos -= 40; + } + artflag >>= 1; + } while (artflag != 0); +} + + +/* +================== += += AM_DrawSubsectors += +================== +*/ + +void AM_DrawSubsectors(player_t *player) // 800012A0 +{ + subsector_t *sub; + sector_t *sec; + leaf_t *lf; + int i; + + gDPPipeSync(GFX1++); + gDPSetCycleType(GFX1++, G_CYC_1CYCLE); + gDPSetTextureLUT(GFX1++, G_TT_RGBA16); + gDPSetTexturePersp(GFX1++, G_TP_PERSP); + gDPSetRenderMode(GFX1++, G_RM_OPA_SURF,G_RM_OPA_SURF2); + gDPSetCombineMode(GFX1++, G_CC_D64COMB01, G_CC_D64COMB01); + + globallump = -1; + + sub = subsectors; + for (i=0 ; i<numsubsectors ; i++, sub++) + { + if((sub->drawindex) || (player->powers[pw_allmap]) || (player->cheats & CF_ALLMAP)) + { + sec = sub->sector; + + if((sec->flags & MS_HIDESSECTOR) || (sec->floorpic == -1)) + continue; + + I_CheckGFX(); + + lf = &leafs[sub->leaf]; + R_RenderPlane(lf, sub->numverts, 0, + textures[sec->floorpic], + 0, 0, + lights[sec->colors[1]].rgba); + } + } +} + +/* +================== += += AM_DrawLine += +================== +*/ + +void AM_DrawLine(player_t *player) // 800014C8 +{ + line_t *l; + int i, color; + + vid_task->t.ucode = (u64 *) gspL3DEX_fifoTextStart; + vid_task->t.ucode_data = (u64 *) gspL3DEX_fifoDataStart; + + gDPPipeSync(GFX1++); + gDPSetCycleType(GFX1++, G_CYC_1CYCLE); + + gDPSetTextureLUT(GFX1++, G_TT_RGBA16); + gDPSetTexturePersp(GFX1++, G_TP_PERSP); + + // [GEC] New Cheat Codes + if (player->cheats & CF_FILTER) { + gDPSetTextureFilter(GFX1++, G_TF_POINT); // <- Nearest texture + } + else { + gDPSetTextureFilter(GFX1++, G_TF_BILERP); // <- Bilinear texture + } + + gDPSetRenderMode(GFX1++,G_RM_AA_XLU_LINE,G_RM_AA_XLU_LINE2); + gDPSetCombineMode(GFX1++, G_CC_D64COMB02, G_CC_D64COMB02); + + l = lines; + for (i = 0; i < numlines; i++, l++) + { + if(l->flags & ML_DONTDRAW) + continue; + + if(((l->flags & ML_MAPPED) || player->powers[pw_allmap]) || (player->cheats & CF_ALLMAP)) + { + I_CheckGFX(); + + /* */ + /* Figure out color */ + /* */ + color = COLOR_BROWN; + + if((player->powers[pw_allmap] || (player->cheats & CF_ALLMAP)) && !(l->flags & ML_MAPPED)) + color = COLOR_GREY; + else if (l->flags & ML_SECRET) + color = COLOR_RED; + else if(l->special && !(l->flags & ML_HIDEAUTOMAPTRIGGER)) + color = COLOR_YELLOW; + else if (!(l->flags & ML_TWOSIDED)) /* ONE-SIDED LINE */ + color = COLOR_RED; + + gSPVertex(GFX1++, (VTX1), 2, 0); + gSPLine3D(GFX1++, 0, 1, 0); + + /* x, z */ + VTX1[0].v.ob[0] = l->v1->x >> FRACBITS; + VTX1[0].v.ob[2] = -l->v1->y >> FRACBITS; + + /* x, z */ + VTX1[1].v.ob[0] = l->v2->x >> FRACBITS; + VTX1[1].v.ob[2] = -l->v2->y >> FRACBITS; + + /* y */ + VTX1[0].v.ob[1] = VTX1[1].v.ob[1] = 0; + + /* rgba */ + *(int *)VTX1[1].v.cn = color; + *(int *)VTX1[0].v.cn = color; + + VTX1 += 2; + } + } +} + +/* +================== += += AM_DrawThings += +================== +*/ + +void AM_DrawThings(fixed_t x, fixed_t y, angle_t angle, int color) // 80001834 +{ + angle_t ang; + + gSPVertex(GFX1++, (VTX1), 3, 0); + + ang = (angle) >> ANGLETOFINESHIFT; + VTX1[0].v.ob[0] = ((finecosine[ang] << 5) + x) >> FRACBITS; + VTX1[0].v.ob[2] =-((finesine [ang] << 5) + y) >> FRACBITS; + + ang = (angle + 0xA0000000) >> ANGLETOFINESHIFT; + VTX1[1].v.ob[0] = ((finecosine[ang] << 5) + x) >> FRACBITS; + VTX1[1].v.ob[2] =-((finesine [ang] << 5) + y) >> FRACBITS; + + ang = (angle + 0x60000000) >> ANGLETOFINESHIFT; + VTX1[2].v.ob[0] = ((finecosine[ang] << 5) + x) >> FRACBITS; + VTX1[2].v.ob[2] =-((finesine [ang] << 5) + y) >> FRACBITS; + + VTX1[0].v.ob[1] = VTX1[1].v.ob[1] = VTX1[2].v.ob[1] = 0; + + *(int *)VTX1[0].v.cn = *(int *)VTX1[1].v.cn = *(int *)VTX1[2].v.cn = color; + + VTX1 += 3; +} diff --git a/Doom 64/asci.c b/Doom 64/asci.c @@ -0,0 +1,130 @@ + +/*---------------------------------------------------------------------* + Copyright (C) 1997 Nintendo. + + $RCSfile: asci.c,v $ + $Revision: 1.2 $ + $Date: 1998/09/25 21:48:13 $ + *---------------------------------------------------------------------*/ +#include <ultra64.h> +u8 pat[][16] = { +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,}, +{0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00,0x10,0x38,0x10,0x00,}, +{0x00,0x6c,0x6c,0x24,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,}, +{0x00,0x24,0x24,0x24,0x26,0x3c,0x64,0x24,0x24,0x26,0x3c,0x64,0x24,0x24,0x24,0x00,}, +{0x00,0x08,0x1c,0x2a,0x49,0x48,0x28,0x1c,0x0a,0x09,0x09,0x49,0x2a,0x1c,0x08,0x00,}, +{0x00,0x22,0x54,0x54,0x54,0x28,0x08,0x08,0x10,0x10,0x14,0x2a,0x2a,0x2a,0x44,0x00,}, +{0x00,0x38,0x44,0x44,0x44,0x44,0x28,0x30,0x20,0x52,0x52,0x4a,0x4a,0x44,0x3a,0x00,}, +{0x00,0x60,0x60,0x20,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,}, +{0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x20,0x20,0x20,0x20,0x10,0x10,0x08,0x08,0x04,}, +{0x20,0x10,0x10,0x08,0x08,0x04,0x04,0x04,0x04,0x04,0x04,0x08,0x08,0x10,0x10,0x20,}, +{0x00,0x00,0x08,0x08,0x49,0x49,0x2a,0x1c,0x08,0x1c,0x2a,0x49,0x49,0x08,0x08,0x00,}, +{0x00,0x00,0x00,0x08,0x08,0x08,0x08,0x7f,0x08,0x08,0x08,0x08,0x08,0x00,0x00,0x00,}, +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x20,0x40,}, +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,}, +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x60,0x60,0x00,0x00,}, +{0x00,0x02,0x04,0x04,0x04,0x08,0x08,0x08,0x10,0x10,0x10,0x20,0x20,0x20,0x40,0x00,}, +{0x00,0x3c,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x3c,0x00,}, +{0x00,0x08,0x18,0x28,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x1c,0x00,}, +{0x00,0x18,0x24,0x42,0x42,0x42,0x02,0x04,0x08,0x10,0x20,0x20,0x40,0x40,0x7e,0x00,}, +{0x00,0x18,0x24,0x42,0x42,0x02,0x04,0x18,0x04,0x02,0x42,0x42,0x42,0x24,0x18,0x00,}, +{0x00,0x04,0x0c,0x0c,0x14,0x14,0x14,0x24,0x24,0x44,0x44,0x7e,0x04,0x04,0x04,0x00,}, +{0x00,0x7e,0x40,0x40,0x40,0x58,0x64,0x42,0x02,0x02,0x02,0x42,0x42,0x24,0x18,0x00,}, +{0x00,0x18,0x24,0x42,0x42,0x40,0x58,0x64,0x42,0x42,0x42,0x42,0x42,0x24,0x18,0x00,}, +{0x00,0x7e,0x42,0x42,0x42,0x04,0x04,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x00,}, +{0x00,0x18,0x24,0x42,0x42,0x42,0x24,0x18,0x24,0x42,0x42,0x42,0x42,0x24,0x18,0x00,}, +{0x00,0x18,0x24,0x42,0x42,0x42,0x42,0x42,0x26,0x1a,0x02,0x42,0x42,0x24,0x18,0x00,}, +{0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,}, +{0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x08,0x10,}, +{0x00,0x00,0x02,0x04,0x08,0x10,0x20,0x40,0x40,0x20,0x10,0x08,0x04,0x02,0x00,0x00,}, +{0x00,0x00,0x00,0x00,0x00,0x00,0x7e,0x00,0x00,0x7e,0x00,0x00,0x00,0x00,0x00,0x00,}, +{0x00,0x00,0x40,0x20,0x10,0x08,0x04,0x02,0x02,0x04,0x08,0x10,0x20,0x40,0x00,0x00,}, +{0x00,0x18,0x24,0x42,0x42,0x02,0x04,0x08,0x10,0x10,0x00,0x00,0x10,0x38,0x10,0x00,}, +{0x00,0x1c,0x22,0x41,0x49,0x55,0x55,0x55,0x55,0x55,0x55,0x4a,0x40,0x21,0x1e,0x00,}, +{0x00,0x18,0x18,0x24,0x24,0x24,0x24,0x24,0x3c,0x42,0x42,0x42,0x42,0x42,0x00,0x00,}, +{0x00,0x78,0x44,0x42,0x42,0x42,0x44,0x78,0x44,0x42,0x42,0x42,0x44,0x78,0x00,0x00,}, +{0x00,0x18,0x24,0x42,0x42,0x40,0x40,0x40,0x40,0x42,0x42,0x42,0x24,0x18,0x00,0x00,}, +{0x00,0x78,0x44,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x44,0x78,0x00,0x00,}, +{0x00,0x7e,0x40,0x40,0x40,0x40,0x40,0x7c,0x40,0x40,0x40,0x40,0x40,0x7e,0x00,0x00,}, +{0x00,0x7e,0x40,0x40,0x40,0x40,0x40,0x7c,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,}, +{0x00,0x18,0x24,0x42,0x40,0x40,0x40,0x4e,0x42,0x42,0x42,0x42,0x26,0x1a,0x00,0x00,}, +{0x00,0x42,0x42,0x42,0x42,0x42,0x42,0x7e,0x42,0x42,0x42,0x42,0x42,0x42,0x00,0x00,}, +{0x00,0x1c,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x1c,0x00,0x00,}, +{0x00,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x02,0x42,0x42,0x24,0x18,0x00,0x00,}, +{0x00,0x42,0x44,0x44,0x48,0x48,0x50,0x60,0x50,0x48,0x48,0x44,0x44,0x42,0x00,0x00,}, +{0x00,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x40,0x7e,0x00,0x00,}, +{0x00,0x41,0x63,0x63,0x55,0x55,0x49,0x49,0x41,0x41,0x41,0x41,0x41,0x41,0x00,0x00,}, +{0x00,0x62,0x62,0x52,0x52,0x52,0x52,0x4a,0x4a,0x4a,0x4a,0x4a,0x46,0x46,0x00,0x00,}, +{0x00,0x18,0x24,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x24,0x18,0x00,0x00,}, +{0x00,0x78,0x44,0x42,0x42,0x42,0x44,0x78,0x40,0x40,0x40,0x40,0x40,0x40,0x00,0x00,}, +{0x00,0x18,0x24,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x52,0x4a,0x24,0x1a,0x00,0x00,}, +{0x00,0x78,0x44,0x42,0x42,0x42,0x44,0x78,0x48,0x48,0x44,0x44,0x42,0x42,0x00,0x00,}, +{0x00,0x18,0x24,0x42,0x40,0x40,0x20,0x18,0x04,0x02,0x42,0x42,0x24,0x18,0x00,0x00,}, +{0x00,0x7f,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x00,0x00,}, +{0x00,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x24,0x18,0x00,0x00,}, +{0x00,0x41,0x41,0x41,0x41,0x22,0x22,0x22,0x22,0x14,0x14,0x14,0x08,0x08,0x00,0x00,}, +{0x00,0x41,0x41,0x41,0x41,0x49,0x49,0x49,0x55,0x55,0x55,0x55,0x22,0x22,0x00,0x00,}, +{0x00,0x42,0x42,0x42,0x24,0x24,0x18,0x18,0x24,0x24,0x24,0x42,0x42,0x42,0x00,0x00,}, +{0x00,0x41,0x41,0x41,0x22,0x22,0x14,0x14,0x08,0x08,0x08,0x08,0x08,0x08,0x00,0x00,}, +{0x00,0x7e,0x02,0x04,0x04,0x08,0x08,0x10,0x10,0x20,0x20,0x40,0x40,0x7e,0x00,0x00,}, +{0x0e,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x0e,}, +{0x00,0x41,0x41,0x22,0x22,0x14,0x14,0x7f,0x08,0x08,0x7f,0x08,0x08,0x08,0x08,0x00,}, +{0x38,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x08,0x38,}, +{0x18,0x24,0x42,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,}, +{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x7e,0x00,0x00,}, +{0x30,0x18,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,}, +{0x00,0x00,0x00,0x00,0x00,0x3c,0x42,0x02,0x1e,0x22,0x42,0x42,0x46,0x3a,0x00,0x00,}, +{0x00,0x40,0x40,0x40,0x40,0x58,0x64,0x42,0x42,0x42,0x42,0x42,0x64,0x58,0x00,0x00,}, +{0x00,0x00,0x00,0x00,0x00,0x18,0x24,0x42,0x40,0x40,0x40,0x42,0x24,0x18,0x00,0x00,}, +{0x00,0x02,0x02,0x02,0x02,0x1a,0x26,0x42,0x42,0x42,0x42,0x42,0x26,0x1a,0x00,0x00,}, +{0x00,0x00,0x00,0x00,0x00,0x18,0x24,0x42,0x42,0x7e,0x40,0x40,0x22,0x1c,0x00,0x00,}, +{0x00,0x08,0x14,0x10,0x10,0x7c,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00,}, +{0x00,0x00,0x00,0x00,0x00,0x1a,0x26,0x42,0x42,0x42,0x42,0x26,0x1a,0x02,0x44,0x38,}, +{0x00,0x40,0x40,0x40,0x40,0x58,0x64,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x00,0x00,}, +{0x00,0x00,0x10,0x10,0x00,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00,}, +{0x00,0x00,0x04,0x04,0x00,0x00,0x04,0x04,0x04,0x04,0x04,0x04,0x04,0x24,0x24,0x18,}, +{0x00,0x40,0x40,0x40,0x40,0x42,0x44,0x48,0x50,0x60,0x50,0x48,0x44,0x42,0x00,0x00,}, +{0x00,0x30,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00,}, +{0x00,0x00,0x00,0x00,0x00,0x56,0x69,0x49,0x49,0x49,0x49,0x49,0x49,0x49,0x00,0x00,}, +{0x00,0x00,0x00,0x00,0x00,0x58,0x64,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x00,0x00,}, +{0x00,0x00,0x00,0x00,0x00,0x18,0x24,0x42,0x42,0x42,0x42,0x42,0x24,0x18,0x00,0x00,}, +{0x00,0x00,0x00,0x00,0x00,0x58,0x64,0x42,0x42,0x42,0x42,0x64,0x58,0x40,0x40,0x40,}, +{0x00,0x00,0x00,0x00,0x00,0x1a,0x26,0x42,0x42,0x42,0x42,0x26,0x1a,0x02,0x02,0x02,}, +{0x00,0x00,0x00,0x00,0x00,0x2c,0x32,0x22,0x20,0x20,0x20,0x20,0x20,0x20,0x00,0x00,}, +{0x00,0x00,0x00,0x00,0x00,0x3c,0x42,0x42,0x20,0x18,0x04,0x42,0x42,0x3c,0x00,0x00,}, +{0x00,0x00,0x00,0x10,0x10,0x7c,0x10,0x10,0x10,0x10,0x10,0x12,0x12,0x0c,0x00,0x00,}, +{0x00,0x00,0x00,0x00,0x00,0x42,0x42,0x42,0x42,0x42,0x42,0x42,0x26,0x1a,0x00,0x00,}, +{0x00,0x00,0x00,0x00,0x00,0x42,0x42,0x42,0x42,0x24,0x24,0x24,0x18,0x18,0x00,0x00,}, +{0x00,0x00,0x00,0x00,0x00,0x41,0x49,0x49,0x55,0x55,0x55,0x55,0x22,0x22,0x00,0x00,}, +{0x00,0x00,0x00,0x00,0x00,0x42,0x42,0x24,0x18,0x18,0x24,0x42,0x42,0x42,0x00,0x00,}, +{0x00,0x00,0x00,0x00,0x00,0x42,0x42,0x42,0x24,0x24,0x14,0x18,0x08,0x10,0x10,0x20,}, +{0x00,0x00,0x00,0x00,0x00,0x7e,0x02,0x04,0x08,0x08,0x10,0x20,0x40,0x7e,0x00,0x00,}, +{0x06,0x08,0x08,0x08,0x08,0x08,0x10,0x30,0x10,0x08,0x08,0x08,0x08,0x08,0x08,0x06,}, +{0x00,0x00,0x00,0x00,0x00,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x10,0x00,0x00,}, +{0x30,0x08,0x08,0x08,0x08,0x08,0x04,0x06,0x04,0x08,0x08,0x08,0x08,0x08,0x08,0x30,}, +{0x7e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,}, + +/* + * arrow (No.127 -) + */ +{0x00,0x00,0x18,0x3c,0x5a,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x00,0x00,}, +{0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x5a,0x3c,0x18,0x00,0x00,}, +{0x00,0x00,0x00,0x00,0x00,0x08,0x04,0xfe,0xfe,0x04,0x08,0x00,0x00,0x00,0x00,0x00,}, +{0x00,0x00,0x00,0x00,0x00,0x20,0x40,0xfe,0xfe,0x40,0x20,0x00,0x00,0x00,0x00,0x00,}, +{0x00,0x00,0x00,0x00,0xf8,0xe0,0xf0,0xb8,0x9c,0x0e,0x07,0x02,0x00,0x00,0x00,0x00,}, +{0x00,0x00,0x00,0x00,0x1f,0x07,0x0f,0x1d,0x39,0x70,0xe0,0x40,0x00,0x00,0x00,0x00,}, +{0x00,0x00,0x00,0x00,0x40,0xe0,0x70,0x39,0x1d,0x0f,0x07,0x1f,0x00,0x00,0x00,0x00,}, +{0x00,0x00,0x00,0x00,0x02,0x07,0x0e,0x9c,0xb8,0xf0,0xe0,0xf8,0x00,0x00,0x00,0x00,}, +/* + * C button unit (No.135 -) + */ +{0x00,0x00,0x00,0x00,0x10,0x10,0x38,0x38,0x38,0x7c,0x7c,0x7c,0xfe,0x00,0x00,0x00,}, +{0x00,0x00,0x00,0x20,0x30,0x38,0x3c,0x3e,0x3e,0x3c,0x38,0x30,0x20,0x00,0x00,0x00,}, +{0x00,0x00,0x00,0xfe,0x7c,0x7c,0x7c,0x38,0x38,0x38,0x10,0x10,0x00,0x00,0x00,0x00,}, +{0x00,0x00,0x00,0x04,0x0c,0x1c,0x3c,0x7c,0x7c,0x3c,0x1c,0x0c,0x04,0x00,0x00,0x00,}, +/* + * Blocks (No.138 -) + */ +{0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,}, + +}; diff --git a/Doom 64/asm.h b/Doom 64/asm.h @@ -0,0 +1,49 @@ +/************************************************************************ + Copyright (C) 1998,1999 NINTENDO Co,Ltd, + Copyright (C) 1998,1999 MONEGI CORPORATION, + All Rights Reserved +This program is a trade secret of NINTENDO Co,Ltd and MONEGI Corp. +and it is not to be reproduced, published, disclosed to others, copied, +adapted, distributed, or displayed without the prior authorization of +NINTENDO Co,Ltd. and MONEGI Corp. Licensee agrees to attach or embed +this Notice on all copies of the program, including partial copies or +modified versions thereof. +*************************************************************************/ +/************************************************************************ + $Date: 1999/07/06 13:21:13 $ + $Revision: 1.1 $ + $Author: doseki $ +************************************************************************/ + +#ifndef __ASM_H__ +#define __ASM_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define _MIPS_ISA_MIPS1 1 /* R2/3K */ +#define _MIPS_ISA_MIPS2 2 /* R4K/6K */ +#define _MIPS_ISA_MIPS3 3 /* R4K */ +#define _MIPS_ISA_MIPS4 4 /* TFP */ + +#define _MIPS_SIM_ABI32 1 /* MIPS MSIG calling convention */ +#define _MIPS_SIM_NABI32 2 /* MIPS new 32-bit abi */ + /* NABI32 is 64bit calling convention but 32bit type sizes) */ +#define _MIPS_SIM_ABI64 3 /* MIPS 64 calling convention */ + +#define LEAF(x) \ + .globl x; \ + .ent x,0; \ +x:; \ + .frame sp,0,ra + +#define END(proc) \ + .end proc + + +#ifdef __cplusplus +} +#endif + +#endif /* !__ASM_H__ */ diff --git a/Doom 64/audio.c b/Doom 64/audio.c @@ -0,0 +1,544 @@ + +#include "audio.h" + +#include "graph.h" + +//------------ +extern void N64_wdd_location(char *wdd_location); +extern void N64_set_output_rate(u32 rate); + +extern int wess_driver_num_dma_buffers; // 8005D948 +extern int wess_driver_num_dma_messages; // 8005D94C +extern int wess_driver_dma_buffer_length; // 8005D950 +extern int wess_driver_extra_samples; // 8005D954 +extern int wess_driver_frame_lag; // 8005D958 +extern int wess_driver_voices; // 8005D95C +extern int wess_driver_updates; // 8005D960 +extern int wess_driver_sequences; // 8005D964 +extern int wess_driver_tracks; // 8005D968 +extern int wess_driver_gates; // 8005D96C +extern int wess_driver_iters; // 8005D970 +extern int wess_driver_callbacks; // 8005D974 +extern int wess_driver_max_trks_per_seq; // 8005D978 load_sequence_data:80039868(R), +extern int wess_driver_max_subs_per_trk; // 8005D97C + +/* used by wesssys_exit */ +enum RestoreFlag {NoRestore,YesRestore}; + +extern int wesssys_init(void); +extern void wesssys_exit(enum RestoreFlag rflag); + +//------------ + +#ifndef NOUSEWESSCODE +//------------ +AMAudioMgr __am; //800B4060 +ALVoice *voice; //800B40E0 +char *reverb_status; //800B40E4 +//------------ + +//------------ +AMDMAState dmaState; //800B40C0 +AMDMABuffer *dmaBuffs; //800B40CC +u32 audFrameCt = 0; //8005D8B0 +u32 nextDMA = 0; //8005D8B4 +u32 curAcmdList = 0; //8005D8B8 +u32 minFrameSize; //800B40D0 +u32 frameSize; //800B40D4 +u32 maxFrameSize; //800b40d8 +u32 maxRSPCmds; //800B40DC + +/* Queues and storage for use with audio DMA's */ +OSMesgQueue audDMAMessageQ; //800B40E8 +OSIoMesg *audDMAIOMesgBuf; //800B4100 +OSMesg *audDMAMessageBuf; //800B4104 + +u32 buf = 0; //8005D8BC +AudioInfo *lastInfo = 0; //8005D8C0 + +u32 init_completed = 0; //8005D8C4 + +#define NUM_DMA_MESSAGES 8 /* The maximum number of DMAs any one frame can have.*/ +OSMesgQueue wess_dmaMessageQ; //800b4108 +OSMesg wess_dmaMessageBuf[NUM_DMA_MESSAGES];//800b4120 +//------------ + +int wess_memfill(void *dst, unsigned char fill, int count) // 8002E300 +{ + char *d; + + d = (char *)dst; + while (count != 0) + { + *d++ = (unsigned char)fill; + count--; + } + return count; +} + +int wess_rom_copy(char *src, char *dest, int len) // 8002E334 +{ + OSMesg dummyMesg; + OSIoMesg DMAIoMesgBuf; + + if (init_completed != 0 && len != 0) + { + osInvalDCache((void *)dest, (s32)len); + osPiStartDma(&DMAIoMesgBuf, OS_MESG_PRI_HIGH, OS_READ, (u32)src, (void *)dest, (u32)len, &wess_dmaMessageQ); + osRecvMesg(&wess_dmaMessageQ, &dummyMesg, OS_MESG_BLOCK); + + return len; + } + + return 0; +} + +/*LEAF(milli_to_param) +lui $at, 0x447A +mtc1 $a1, $f12 +mtc1 $at, $f8 +mtc1 $a0, $f4 +div.s $f10, $f12, $f8 +cvt.s.w $f6, $f4 +mul.s $f16, $f6, $f10 +cfc1 $t6, FCSR +nop +li $at, $t6, 3 +xori $at, $at, 2 +ctc1 $at, FCSR +li $at, 0xFFFFFFF8 +cvt.w.s $f18, $f16 +mfc1 $v0, $f18 +ctc1 $t6, FCSR +and $t7, $v0, $at +jr $ra +move $v0, $t7 +END(milli_to_param)*/ + +s32 milli_to_param(register s32 paramvalue, register s32 rate) // 8002E3D0 +{ + register u32 fpstat, fpstatset, out; + +#ifdef N64ASM + asm("lui $at, 0x447A\n"); + asm("mtc1 %0, $f12\n" ::"r"(rate));//mtc1 $a1, $f12 + asm("mtc1 $at, $f8\n"); + asm("mtc1 %0, $f4\n" ::"r"(paramvalue));//mtc1 $a0, $f4 + asm("div.s $f10, $f12, $f8\n"); + asm("cvt.s.w $f6, $f4\n"); + asm("mul.s $f16, $f6, $f10\n"); + // fetch the current floating-point control/status register + asm("cfc1 %0, $f31\n" :"=r"(fpstat)); + asm("nop\n"); + // enable round to negative infinity for floating point + //"li $at, $t6, 3\n" + asm("ori $at, %0, 3\n" ::"r"(fpstat));//# fpstat |= FPCSR_RM_RM; + asm("xori $at, $at, 2\n"); + asm("ctc1 $at, $f31\n"); + //asm("li $at, 0xFFFFFFF8\n"); + asm("cvt.w.s $f18, $f16\n"); + asm("mfc1 %0, $f18\n" :"=r"(out)); + // _Disable_ unimplemented operation exception for floating point. + asm("ctc1 %0, $f31\n" ::"r"(fpstat)); + + return (s32)(out &~0x7); +#else + //No asm mode + + /* + // fetch the current floating-point control/status register + fpstat = __osGetFpcCsr(); + // enable round to negative infinity for floating point + fpstatset = (fpstat | FPCSR_RM_RM) ^ 2; + // _Disable_ unimplemented operation exception for floating point. + __osSetFpcCsr(fpstatset); + */ + + return (s32)((f32)paramvalue * ((f32)rate / 1000.0f)) &~0x7; +#endif +} + +void wess_init(WessConfig *wessconfig) // 8002E41C +{ + ALSynConfig config; + f32 samplerate; + s32 *params;//Custom reverb + int sections, section_pos; + + // Create audio DMA thread... + osCreateMesgQueue(&wess_dmaMessageQ, wess_dmaMessageBuf, NUM_DMA_MESSAGES); + + buf = 0; + lastInfo = NULL; + + N64_wdd_location(wessconfig->wdd_location); + + config.dmaproc = __amDmaNew; + config.maxPVoices = config.maxVVoices = wess_driver_voices; + config.maxUpdates = wess_driver_updates; + config.fxType = (ALFxId)wessconfig->reverb_id; + + N64_set_output_rate(wessconfig->outputsamplerate); + config.outputRate = osAiSetFrequency(wessconfig->outputsamplerate); + + config.heap = wessconfig->heap_ptr; + + if (config.fxType == WESS_REVERB_CUSTOM) + { + /* set address reverb table*/ + params = wessconfig->revtbl_ptr; + + samplerate = wessconfig->outputsamplerate; + if ((u32)samplerate < 0) { samplerate += 4.2949673e9; } + + /* total allocated memory */ + params[1] = milli_to_param(params[1], (u32)samplerate); + + /* total allocated memory -> params[0]*/ + section_pos = 0; + for (sections = 0; sections < params[0]; sections++) + { + samplerate = wessconfig->outputsamplerate; + if ((u32)samplerate < 0) { samplerate += 4.2949673e9; } + + /* input */ + params[2 + section_pos] = milli_to_param(params[2 + section_pos], (u32)samplerate); + + samplerate = wessconfig->outputsamplerate; + if ((u32)samplerate < 0) { samplerate += 4.2949673e9; } + + /* output */ + params[3 + section_pos] = milli_to_param(params[3 + section_pos], (u32)samplerate); + + section_pos += 8; + } + + config.params = params; + } + + amCreateAudioMgr(&config, wessconfig); + SSP_SeqpNew(); + wesssys_init(); + init_completed = 1; +} + + +/*-------------------*/ +/* Audio Manager API */ +/*-------------------*/ + +void amCreateAudioMgr(ALSynConfig *config, WessConfig *wessconfig) // 8002E610 +{ + f32 fsize; + f32 fsize2; + int frameSize1; + int i; + + /* + * Calculate the frame sample parameters from the + * video field rate and the output rate + */ + fsize = (f32)(config->outputRate) / wessconfig->audioframerate; + frameSize1 = (s32)fsize; + + if (frameSize1 < 0) { + frameSize1 = -1; + } + + fsize2 = (float)frameSize1; + if (frameSize1 < 0) { + fsize2 += 4294967296.0; + } + + frameSize = frameSize1 + 1; + if (fsize <= fsize2) { + frameSize = frameSize1; + } + + if (frameSize & 15) + frameSize = (frameSize & ~0xf) + 16; + + minFrameSize = frameSize - 16; + maxFrameSize = frameSize + wess_driver_extra_samples + 16; + + voice = (ALVoice *)alHeapAlloc(config->heap, 1, wess_driver_voices * sizeof(ALVoice)); + wess_memfill(voice, 0, wess_driver_voices * sizeof(ALVoice)); + + reverb_status = (char *)alHeapAlloc(config->heap, 1, wess_driver_voices); + wess_memfill(reverb_status, 0, wess_driver_voices); + + dmaBuffs = (AMDMABuffer *)alHeapAlloc(config->heap, 1, wess_driver_num_dma_buffers * sizeof(AMDMABuffer)); + wess_memfill(dmaBuffs, 0, wess_driver_num_dma_buffers * sizeof(AMDMABuffer)); + + /* allocate buffers for voices */ + dmaBuffs[0].node.prev = 0; + dmaBuffs[0].node.next = 0; + + for (i = 0; i < (wess_driver_num_dma_buffers - 1); i++) + { + alLink((ALLink *)&dmaBuffs[i + 1], (ALLink *)&dmaBuffs[i]); + dmaBuffs[i].ptr = (char *)alHeapAlloc(config->heap, 1, wess_driver_dma_buffer_length); + wess_memfill(dmaBuffs[i].ptr, 0, wess_driver_dma_buffer_length); + } + + /* last buffer already linked, but still needs buffer */ + dmaBuffs[i].ptr = alHeapAlloc(config->heap, 1, wess_driver_dma_buffer_length); + wess_memfill(dmaBuffs[i].ptr, 0, wess_driver_dma_buffer_length); + + for (i = 0; i < NUM_ACMD_LISTS; i++) + { + __am.ACMDList[i] = (Acmd*)alHeapAlloc(config->heap, 1, wessconfig->maxACMDSize * sizeof(Acmd)); + wess_memfill(__am.ACMDList[i], 0, wessconfig->maxACMDSize * sizeof(Acmd)); + } + + maxRSPCmds = wessconfig->maxACMDSize; + + /* initialize the done messages */ + for (i = 0; i < NUM_OUTPUT_BUFFERS; i++) + { + __am.audioInfo[i] = (AudioInfo *)alHeapAlloc(config->heap, 1, sizeof(AudioInfo)); + wess_memfill(__am.audioInfo[i], 0, sizeof(AudioInfo)); + + /* allocate output buffer */ + __am.audioInfo[i]->data = alHeapAlloc(config->heap, 1, maxFrameSize << 2); + wess_memfill(__am.audioInfo[i]->data, 0, maxFrameSize << 2); + } + + audDMAIOMesgBuf = alHeapAlloc(config->heap, 1, wess_driver_num_dma_messages * sizeof(OSIoMesg)); + wess_memfill(audDMAIOMesgBuf, 0, wess_driver_num_dma_messages * sizeof(OSIoMesg)); + + audDMAMessageBuf = alHeapAlloc(config->heap, 1, wess_driver_num_dma_messages * sizeof(OSMesg)); + wess_memfill(audDMAMessageBuf, 0, wess_driver_num_dma_messages * sizeof(OSMesg)); + + osCreateMesgQueue(&audDMAMessageQ, audDMAMessageBuf, wess_driver_num_dma_messages); + + alInit(&__am.g, config); +} + +OSTask * wess_work(void) // 8002EB2C +{ + OSTask *validTask; + + if (init_completed == 0) + return (OSTask *)NULL; + + validTask = __amHandleFrameMsg(__am.audioInfo[buf]); + + lastInfo = __am.audioInfo[buf]; + + buf++; + if (buf == NUM_OUTPUT_BUFFERS) + buf = 0; + + if (validTask) + curAcmdList ^= 1; /* swap which acmd list you use each frame */ + + return validTask; +} + +OSTask *__amHandleFrameMsg(AudioInfo *info) // 8002EBD8 +{ + s16 *audioPtr; + Acmd *cmdp; + s32 cmdLen; + int samplesLeft; + int check; + + /* audFrameCnt updated here */ + __clearAudioDMA(); /* call once a frame, before doing alAudioFrame */ + + audioPtr = (s16 *)osVirtualToPhysical(info->data); /* info->data addr of current buffer */ + + /* set up the next DMA transfer from DRAM to the audio interface buffer. */ + /* lastInfo->data is the buffer used in the last audio frame. It should be full. */ + if (lastInfo) + { + osAiSetNextBuffer(lastInfo->data, lastInfo->frameSamples << 2); + } + + /* calculate how many samples needed for this frame to keep the DAC full */ + /* this will vary slightly frame to frame, must recalculate every frame */ + samplesLeft = osAiGetLength() >> 2; /* divide by four, to convert bytes */ + + /* to stereo 16 bit samples */ + info->frameSamples = ((frameSize - samplesLeft) + wess_driver_extra_samples & ~0xf) + 16; + + /* no longer necessary to have extra samples, because the buffers */ + /* will be swapped exactly when the buffer runs out */ + /* info->frameSamples = frameSize; */ + + if (info->frameSamples < minFrameSize) + info->frameSamples = minFrameSize; + + cmdp = alAudioFrame(__am.ACMDList[curAcmdList], &cmdLen, audioPtr, info->frameSamples); + + if (maxRSPCmds < cmdLen) + { + wess_error_callback("MAXRSPCMDS", 0, 0); + } + + /* this is the task for the next audio frame */ + info->task.t.data_ptr = (u64 *)__am.ACMDList[curAcmdList]; + info->task.t.data_size = (u32)((int)(((int)cmdp - (int)__am.ACMDList[curAcmdList]) >> 3) << 3); + info->task.t.type = M_AUDTASK; + info->task.t.ucode_boot = (u64 *)rspbootTextStart; + info->task.t.ucode_boot_size = ((int)rspbootTextEnd - (int)rspbootTextStart); + info->task.t.flags = 0; + info->task.t.ucode = (u64 *)aspMainTextStart; + info->task.t.ucode_data = (u64 *)aspMainDataStart; + info->task.t.ucode_data_size = SP_UCODE_DATA_SIZE; + info->task.t.yield_data_ptr = NULL; + info->task.t.yield_data_size = 0; + + return (OSTask *)&info->task; +} + +s32 __amDMA(s32 addr, s32 len, void *state) // 8002ED74 +{ + char *foundBuffer; + s32 delta, addrEnd, buffEnd; + AMDMABuffer *dmaPtr, *lastDmaPtr; + + lastDmaPtr = 0; + dmaPtr = dmaState.firstUsed; + addrEnd = addr+len; + + /* first check to see if a currently existing buffer contains the + sample that you need. */ + while (dmaPtr) + { + buffEnd = dmaPtr->startAddr + wess_driver_dma_buffer_length; + if (dmaPtr->startAddr > addr) /* since buffers are ordered */ + break; /* abort if past possible */ + + else if (addrEnd <= buffEnd) /* yes, found a buffer with samples */ + { + dmaPtr->lastFrame = audFrameCt; /* mark it used */ + foundBuffer = dmaPtr->ptr + addr - dmaPtr->startAddr; + return (int)osVirtualToPhysical(foundBuffer); + } + lastDmaPtr = dmaPtr; + dmaPtr = (AMDMABuffer*)dmaPtr->node.next; + } + + /* get here, and you didn't find a buffer, so dma a new one */ + + /* get a buffer from the free list */ + dmaPtr = dmaState.firstFree; + + /* be sure you have a buffer, */ + /* if you don't have one, you're fucked */ + if (!(dmaPtr)) + { + lastDmaPtr = 0; + wess_error_callback("DMAPTRNULL", 0, 0); + return (int)osVirtualToPhysical(dmaState.firstUsed); + } + + dmaState.firstFree = (AMDMABuffer*)dmaPtr->node.next; + alUnlink((ALLink*)dmaPtr); + + /* add it to the used list */ + if (lastDmaPtr) /* if you have other dmabuffers used, add this one */ + { /* to the list, after the last one checked above */ + alLink((ALLink*)dmaPtr, (ALLink*)lastDmaPtr); + } + else if (dmaState.firstUsed) /* if this buffer is before any others */ + { /* jam at begining of list */ + lastDmaPtr = dmaState.firstUsed; + dmaState.firstUsed = dmaPtr; + dmaPtr->node.next = (ALLink*)lastDmaPtr; + dmaPtr->node.prev = 0; + lastDmaPtr->node.prev = (ALLink*)dmaPtr; + } + else /* no buffers in list, this is the first one */ + { + dmaState.firstUsed = dmaPtr; + dmaPtr->node.next = 0; + dmaPtr->node.prev = 0; + } + + foundBuffer = dmaPtr->ptr; + delta = addr & 0x1; + addr -= delta; + dmaPtr->startAddr = addr; + dmaPtr->lastFrame = audFrameCt; /* mark it */ + + osPiStartDma(&audDMAIOMesgBuf[nextDMA++], OS_MESG_PRI_HIGH, OS_READ, + (u32)addr, foundBuffer, wess_driver_dma_buffer_length, &audDMAMessageQ); + + return (int)osVirtualToPhysical(foundBuffer) + delta; +} + +ALDMAproc __amDmaNew(AMDMAState **state) // 8002EF48 +{ + + if (!dmaState.initialized) /* only do this once */ + { + dmaState.firstUsed = 0; + dmaState.initialized = 1; + dmaState.firstFree = &dmaBuffs[0]; + } + + return __amDMA; +} + +void __clearAudioDMA(void) // 8002EF7C +{ + u32 i; + OSIoMesg *iomsg; + AMDMABuffer *dmaPtr, *nextPtr; + + /* Don't block here. If dma's aren't complete, you've had an audio */ + /* overrun. (Bad news, but go for it anyway, and try and recover. */ + for (i = 0; i<nextDMA; i++) + { + if (osRecvMesg(&audDMAMessageQ, (OSMesg *)&iomsg, OS_MESG_NOBLOCK) == -1) + { + wess_error_callback("DMANOTDONE", 0, 0); + } + } + + dmaPtr = dmaState.firstUsed; + + while (dmaPtr) + { + + nextPtr = (AMDMABuffer*)dmaPtr->node.next; + + /* remove old dma's from list */ + /* Can change FRAME_LAG value if we want. Should be at least one. */ + /* Larger values mean more buffers needed, but fewer DMA's */ + if (dmaPtr->lastFrame + wess_driver_frame_lag < audFrameCt) + { + if (dmaState.firstUsed == dmaPtr) + dmaState.firstUsed = (AMDMABuffer*)dmaPtr->node.next; + + alUnlink((ALLink*)dmaPtr); + + if (dmaState.firstFree) + { + alLink((ALLink*)dmaPtr, (ALLink*)dmaState.firstFree); + } + else + { + dmaState.firstFree = dmaPtr; + dmaPtr->node.next = 0; + dmaPtr->node.prev = 0; + } + } + + dmaPtr = nextPtr; + } + + nextDMA = 0; /* Reset number of DMAs */ + audFrameCt++; +} + +void wess_exit(void) // 8002F0CC +{ + wesssys_exit(YesRestore); + alClose(&__am.g); +} + +#endif // 0 diff --git a/Doom 64/audio.h b/Doom 64/audio.h @@ -0,0 +1,65 @@ +#ifndef _AUDIO_H +#define _AUDIO_H + +#include <ultra64.h> +#include <PR/os.h> +#include <PR/libaudio.h> +#include <PR/ucode.h> + +#include "wessapi.h" +#include "wessarc.h" +#include "wessshell.h" + +/*--------------------------------------------------*/ +/* type define's for structures unique to audiomgr */ +/*--------------------------------------------------*/ + +typedef struct AudioInfo_s +{ + short *data; /* Output data pointer */ + short frameSamples; /* # of samples synthesized in this frame */ + OSTask task; /* scheduler structure */ +} AudioInfo; + +#define NUM_ACMD_LISTS 2 +#define NUM_OUTPUT_BUFFERS 3 + +typedef struct +{ + Acmd *ACMDList[NUM_ACMD_LISTS]; + AudioInfo *audioInfo[NUM_OUTPUT_BUFFERS]; + ALGlobals g; +} AMAudioMgr; + +typedef struct +{ + ALLink node; //0 + u32 startAddr; //8 + u32 lastFrame; //12 + char *ptr; //16 +} AMDMABuffer; + +typedef struct +{ + u8 initialized; + AMDMABuffer *firstUsed; + AMDMABuffer *firstFree; +} AMDMAState; + +extern AMAudioMgr __am; //800B4060 +extern ALVoice *voice; //800B40E0 +extern char *reverb_status; //800B40E4 + +extern int wess_memfill(void *dst, unsigned char fill, int count); // 8002E300 +extern int wess_rom_copy(char *src, char *dest, int len); // 8002E334 +extern s32 milli_to_param(register s32 paramvalue, register s32 rate); // 8002E3D0 +extern void wess_init(WessConfig *wessconfig); // 8002E41C +extern void amCreateAudioMgr(ALSynConfig *config, WessConfig *wessconfig); // 8002E610 +extern OSTask * wess_work(void); // 8002EB2C +extern OSTask *__amHandleFrameMsg(AudioInfo *info); // 8002EBD8 +extern s32 __amDMA(s32 addr, s32 len, void *state); // 8002ED74 +extern ALDMAproc __amDmaNew(AMDMAState **state); // 8002EF48 +extern void __clearAudioDMA(void); // 8002EF7C +extern void wess_exit(void); // 8002F0CC + +#endif // _AUDIO_H diff --git a/Doom 64/audio_heap.c b/Doom 64/audio_heap.c @@ -0,0 +1,6 @@ + +#include <ultra64.h> +#include "i_main.h" + +#define AUDIO_HEAP_SIZE (0x44800) +u64 audio_heap[AUDIO_HEAP_SIZE / sizeof(u64)];//80325800 diff --git a/Doom 64/c_convert.c b/Doom 64/c_convert.c @@ -0,0 +1,242 @@ +/* c_convert.c */ + +/*-----------------------------------*/ +/* Color Converter RGB2HSV & HSV2RGB */ +/*-----------------------------------*/ + +#include "doomdef.h" + +/* +=================== += += LightGetHSV += Set HSV values based on given RGB += +=================== +*/ + +void LightGetHSV(int r,int g,int b,int *h,int *s,int *v) // 800020BC +{ + register u32 fpstat, fpstatset; + + int min; + int max; + float deltamin; + float deltamax; + float j; + float x; + float xr; + float xg; + float xb; + float sum; + + max = MAXINT; + + if(r < max) { + max = r; + } + if(g < max) { + max = g; + } + if(b < max) { + max = b; + } + + min = MININT; + + if(r > min) { + min = r; + } + if(g > min) { + min = g; + } + if(b > min) { + min = b; + } + + deltamin = (float)((double)min / (double)255.0); + deltamax = deltamin - (float)((double)max / (double)255.0); + + if((double)deltamin == 0.0) { + j = 0.0; + } + else { + j = deltamax / deltamin; + } + + if((double)j != 0.0) + { + xr = (float)((double)r / (double)255.0); + xg = (float)((double)g / (double)255.0); + xb = (float)((double)b / (double)255.0); + + if(xr != deltamin) + { + if(xg != deltamin) + { + if(xb == deltamin) + { + sum = ((deltamin - xg) / deltamax + 4.0) - + ((deltamin - xr) / deltamax); + } + } + else + { + sum = ((deltamin - xr) / deltamax + 2.0) - + ((deltamin - xb) / deltamax); + } + } + else + { + sum = ((deltamin - xb) / deltamax) - + ((deltamin - xg) / deltamax); + } + + x = (sum * 60.0); + + if(x < 0.0) + { + x = (float)((double)x + (double)360.0); + } + } + else + { + j = 0.0; + } + + // fetch the current floating-point control/status register + fpstat = __osGetFpcCsr(); + // enable round to negative infinity for floating point + fpstatset = (fpstat | FPCSR_RM_RM) ^ 2; + // _Disable_ unimplemented operation exception for floating point. + __osSetFpcCsr(fpstatset); + + *h = (int)(((double)x / (double)360.0) * (double)255.0); + + // fetch the current floating-point control/status register + fpstat = __osGetFpcCsr(); + // enable round to negative infinity for floating point + fpstatset = (fpstat | FPCSR_RM_RM) ^ 2; + // _Disable_ unimplemented operation exception for floating point. + __osSetFpcCsr(fpstatset); + *s = (int)((double)j * (double)255.0); + + // fetch the current floating-point control/status register + fpstat = __osGetFpcCsr(); + // enable round to negative infinity for floating point + fpstatset = (fpstat | FPCSR_RM_RM) ^ 2; + // _Disable_ unimplemented operation exception for floating point. + __osSetFpcCsr(fpstatset); + *v = (int)((double)deltamin * (double)255.0); +} + +/* +=================== += += LightGetRGB += Set RGB values based on given HSV += +=================== +*/ + +void LightGetRGB(int h,int s,int v,int *r,int *g,int *b) // 8000248C +{ + register u32 fpstat, fpstatset; + + float x; + float j; + float i; + float t; + int table; + float xr; + float xg; + float xb; + + j = (float)(((double)h / (double)255.0) * (double)360.0); + + if((double)360.0 <= (double)j) { + j = (float)((double)j - (double)360.0); + } + + x = ((double)s / (double)255.0); + i = ((double)v / (double)255.0); + + if(x != 0.0) + { + // fetch the current floating-point control/status register + fpstat = __osGetFpcCsr(); + // enable round to negative infinity for floating point + fpstatset = (fpstat | FPCSR_RM_RM) ^ 2; + // _Disable_ unimplemented operation exception for floating point. + __osSetFpcCsr(fpstatset); + + table = (int)(j / 60.0); + if(table < 6) + { + t = (j / 60.0); + switch(table) { + case 0: + xr = i; + xg = ((1.0 - ((1.0 - (t - (float)table)) * x)) * i); + xb = ((1.0 - x) * i); + break; + case 1: + xr = ((1.0 - (x * (t - (float)table))) * i); + xg = i; + xb = ((1.0 - x) * i); + break; + case 2: + xr = ((1.0 - x) * i); + xg = i; + xb = ((1.0 - ((1.0 - (t - (float)table)) * x)) * i); + break; + case 3: + xr = ((1.0 - x) * i); + xg = ((1.0 - (x * (t - (float)table))) * i); + xb = i; + break; + case 4: + xr = ((1.0 - ((1.0 - (t - (float)table)) * x)) * i); + xg = ((1.0 - x) * i); + xb = i; + break; + case 5: + xr = i; + xg = ((1.0 - x) * i); + xb = ((1.0 - (x * (t - (float)table))) * i); + break; + } + } + } + else + { + xr = xg = xb = i; + } + + // fetch the current floating-point control/status register + fpstat = __osGetFpcCsr(); + // enable round to negative infinity for floating point + fpstatset = (fpstat | FPCSR_RM_RM) ^ 2; + // _Disable_ unimplemented operation exception for floating point. + __osSetFpcCsr(fpstatset); + + *r = (int)((double)xr * (double)255.0); + + // fetch the current floating-point control/status register + fpstat = __osGetFpcCsr(); + // enable round to negative infinity for floating point + fpstatset = (fpstat | FPCSR_RM_RM) ^ 2; + // _Disable_ unimplemented operation exception for floating point. + __osSetFpcCsr(fpstatset); + + *g = (int)((double)xg * (double)255.0); + + // fetch the current floating-point control/status register + fpstat = __osGetFpcCsr(); + // enable round to negative infinity for floating point + fpstatset = (fpstat | FPCSR_RM_RM) ^ 2; + // _Disable_ unimplemented operation exception for floating point. + __osSetFpcCsr(fpstatset); + + *b = (int)((double)xb * (double)255.0); +} diff --git a/Doom 64/cfb.c b/Doom 64/cfb.c @@ -0,0 +1,14 @@ + +/* + * RSP view of the frame buffer. It exists to create an RSP address for + * the frame buffer, which is remapped on each frame to either of two + * regions of physical memory that store that actual bits. + */ + +#include <ultra64.h> +#include "i_main.h" + +u32 cfb[2][SCREEN_WD*SCREEN_HT]; // 8036A000 + + + diff --git a/Doom 64/d_main.c b/Doom 64/d_main.c @@ -0,0 +1,226 @@ +/* D_main.c */ + +#include "i_main.h" +#include "doomdef.h" +#include "p_spec.h" +#include "r_local.h" + +int gamevbls; // 80063130 /* may not really be vbls in multiplayer */ +int gametic; // 80063134 +int ticsinframe; // 80063138 /* how many tics since last drawer */ +int ticon; // 8006313C +int lastticon; // 80063140 +int vblsinframe[MAXPLAYERS]; // 80063144 /* range from 4 to 8 */ +int ticbuttons[MAXPLAYERS]; // 80063148 +int oldticbuttons[MAXPLAYERS]; // 8006314C + +buttons_t *BT_DATA[MAXPLAYERS];// 800A559C + +extern boolean run_hectic_demo; + +void D_DoomMain(void) // 800027C0 +{ + int exit; + + I_Init(); + Z_Init(); + W_Init(); + R_Init(); + ST_Init(); + + gamevbls = 0; + gametic = 0; + ticsinframe = 0; + ticon = 0; + ticbuttons[0] = 0; + oldticbuttons[0] = 0; + + D_SplashScreen(); + + while(true) + { + exit = D_TitleMap(); + + if(exit != ga_exit) + { + exit = D_RunDemo("DEMO1LMP", sk_medium, 3); + if(exit != ga_exit) + { + exit = D_RunDemo("DEMO2LMP", sk_medium, 9); + if(exit != ga_exit) + { + exit = D_RunDemo("DEMO3LMP", sk_medium, 17); + if(exit != ga_exit) + { + if(run_hectic_demo) + { + run_hectic_demo = false; + exit = D_RunDemo("DEMO4LMP", sk_medium, 32); + } + + if(exit != ga_exit) + { + exit = D_Credits(); + + if(exit != ga_exit) + { + continue; + } + } + } + } + } + } + + do { + exit = M_RunTitle(); + } while(exit != ga_timeout); + } +} + +/* +=============== += += M_Random += += Returns a 0-255 number += +=============== +*/ + +unsigned char rndtable[256] = { // 8005A190 + 0, 8, 109, 220, 222, 241, 149, 107, 75, 248, 254, 140, 16, 66 , + 74, 21, 211, 47, 80, 242, 154, 27, 205, 128, 161, 89, 77, 36 , + 95, 110, 85, 48, 212, 140, 211, 249, 22, 79, 200, 50, 28, 188 , + 52, 140, 202, 120, 68, 145, 62, 70, 184, 190, 91, 197, 152, 224 , + 149, 104, 25, 178, 252, 182, 202, 182, 141, 197, 4, 81, 181, 242 , + 145, 42, 39, 227, 156, 198, 225, 193, 219, 93, 122, 175, 249, 0 , + 175, 143, 70, 239, 46, 246, 163, 53, 163, 109, 168, 135, 2, 235 , + 25, 92, 20, 145, 138, 77, 69, 166, 78, 176, 173, 212, 166, 113 , + 94, 161, 41, 50, 239, 49, 111, 164, 70, 60, 2, 37, 171, 75 , + 136, 156, 11, 56, 42, 146, 138, 229, 73, 146, 77, 61, 98, 196 , + 135, 106, 63, 197, 195, 86, 96, 203, 113, 101, 170, 247, 181, 113 , + 80, 250, 108, 7, 255, 237, 129, 226, 79, 107, 112, 166, 103, 241 , + 24, 223, 239, 120, 198, 58, 60, 82, 128, 3, 184, 66, 143, 224 , + 145, 224, 81, 206, 163, 45, 63, 90, 168, 114, 59, 33, 159, 95 , + 28, 139, 123, 98, 125, 196, 15, 70, 194, 253, 54, 14, 109, 226 , + 71, 17, 161, 93, 186, 87, 244, 138, 20, 52, 123, 251, 26, 36 , + 17, 46, 52, 231, 232, 76, 31, 221, 84, 37, 216, 165, 212, 106 , + 197, 242, 98, 43, 39, 175, 254, 145, 190, 84, 118, 222, 187, 136 , + 120, 163, 236, 249 +}; + +int rndindex = 0; // 8005A18C +int prndindex = 0; // 8005A188 + +int P_Random(void) // 80002928 +{ + prndindex = (prndindex + 1) & 0xff; + return rndtable[prndindex]; +} + +int M_Random(void) // 80002954 +{ + rndindex = (rndindex + 1) & 0xff; + return rndtable[rndindex]; +} + +void M_ClearRandom(void) // 80002980 +{ + rndindex = prndindex = 0; +} + +/* +=============== += += MiniLoop += +=============== +*/ + +int MiniLoop(void(*start)(void), void(*stop)(), + int(*ticker)(void), void(*drawer)(void)) // 80002998 +{ + int exit; + int buttons; + + gameaction = ga_nothing; + gamevbls = 0; + gametic = 0; + ticon = 0; + ticsinframe = 0; + + /* */ + /* setup (cache graphics, etc) */ + /* */ + if(start != NULL) + start(); + + drawsync1 = 0; + drawsync2 = vsync; + + while (true) + { + vblsinframe[0] = drawsync1; + + // get buttons for next tic + oldticbuttons[0] = ticbuttons[0]; + + buttons = I_GetControllerData(); + ticbuttons[0] = buttons; + + //Read|Write demos + if (demorecording || demoplayback) + { + if (demoplayback) + { + if (buttons & (ALL_JPAD|ALL_BUTTONS)) + { + exit = ga_exit; + break; + } + + buttons = *demobuffer++; + ticbuttons[0] = buttons; + } + + if (demorecording) + { + *demobuffer++ = buttons; + } + + if ((buttons & PAD_START) || ((((int)demobuffer - (int)demo_p) >> 2) >= 4000)) + { + exit = ga_exitdemo; + break; + } + } + + ticon += vblsinframe[0]; + if (ticsinframe < (ticon >> 1)) + { + gametic += 1; + ticsinframe = (ticon >> 1); + } + + if (disabledrawing == false) + { + exit = ticker(); + if (exit != ga_nothing) + break; + + drawer(); + } + + gamevbls = gametic; + } + + I_GetScreenGrab(); + + if(stop != NULL) + stop(exit); + + oldticbuttons[0] = ticbuttons[0]; + + return exit; +} diff --git a/Doom 64/d_screens.c b/Doom 64/d_screens.c @@ -0,0 +1,287 @@ +/* D_screens.c */ + +#include "i_main.h" +#include "doomdef.h" +#include "r_local.h" + +int D_RunDemo(char *name, skill_t skill, int map) // 8002B2D0 +{ + int lump; + int exit; + + demo_p = Z_Alloc(16000, PU_STATIC, NULL); + + lump = W_GetNumForName(name); + W_ReadLump(lump, demo_p, dec_d64); + exit = G_PlayDemoPtr(skill, map); + Z_Free(demo_p); + + return exit; +} + +extern int DefaultConfiguration[5][13]; +int D_TitleMap(void) // 8002B358 +{ + int exit; + + D_OpenControllerPak(); + + demo_p = Z_Alloc(16000, PU_STATIC, NULL); + D_memset(demo_p, 0, 16000); + D_memcpy(demo_p, DefaultConfiguration[0], 13*sizeof(int)); + exit = G_PlayDemoPtr(sk_medium, 33); + Z_Free(demo_p); + + return exit; +} + +int D_WarningTicker(void) // 8002B3E8 +{ + if ((gamevbls < gametic) && !(gametic & 7)) + MenuAnimationTic = MenuAnimationTic + 1 & 7; + return 0; +} + +void D_DrawWarning(void) // 8002B430 +{ + I_ClearFrame(); + + gDPPipeSync(GFX1++); + gDPSetCycleType(GFX1++, G_CYC_FILL); + gDPSetRenderMode(GFX1++,G_RM_NOOP,G_RM_NOOP2); + gDPSetColorImage(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_32b, SCREEN_WD, OS_K0_TO_PHYSICAL(cfb[vid_side])); + gDPSetFillColor(GFX1++, GPACK_RGBA5551(0,0,0,0) << 16 | GPACK_RGBA5551(0,0,0,0)); + gDPFillRectangle(GFX1++, 0, 0, SCREEN_WD-1, SCREEN_HT-1); + + if (MenuAnimationTic & 1) + ST_DrawString(-1, 30, "WARNING!", 0xc00000ff); + + ST_DrawString(-1, 60, "nintendo 64 controller", 0xffffffff); + ST_DrawString(-1, 80, "is not connected.", 0xffffffff); + ST_DrawString(-1, 120, "please turn off your", 0xffffffff); + ST_DrawString(-1, 140, "nintendo 64 system.", 0xffffffff); + ST_DrawString(-1, 180, "plug in your nintendo 64", 0xffffffff); + ST_DrawString(-1, 200, "controller and turn it on.", 0xffffffff); + + I_DrawFrame(); +} + +int D_LegalTicker(void) // 8002B5F8 +{ + if ((ticon - last_ticon) >= 150) // 5 * TICRATE + { + text_alpha -= 8; + if (text_alpha < 0) + { + text_alpha = 0; + return 8; + } + } + return 0; +} + +void D_DrawLegal(void) // 8002B644 +{ + I_ClearFrame(); + + gDPPipeSync(GFX1++); + gDPSetCycleType(GFX1++, G_CYC_FILL); + gDPSetRenderMode(GFX1++,G_RM_NOOP,G_RM_NOOP2); + gDPSetColorImage(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_32b, SCREEN_WD, OS_K0_TO_PHYSICAL(cfb[vid_side])); + gDPSetFillColor(GFX1++, GPACK_RGBA5551(0,0,0,0) << 16 | GPACK_RGBA5551(0,0,0,0)); + gDPFillRectangle(GFX1++, 0, 0, SCREEN_WD-1, SCREEN_HT-1); + + M_DrawBackground(27, 74, text_alpha, "USLEGAL"); + + if (FilesUsed > -1) { + ST_DrawString(-1, 200, "hold \x8d to manage pak", text_alpha | 0xffffff00); + } + + I_DrawFrame(); +} + +int D_NoPakTicker(void) // 8002B7A0 +{ + if ((ticon - last_ticon) >= 240) // 8 * TICRATE + return 8; + + return 0; +} + +void D_DrawNoPak(void) // 8002B7F4 +{ + I_ClearFrame(); + + gDPPipeSync(GFX1++); + gDPSetCycleType(GFX1++, G_CYC_FILL); + gDPSetRenderMode(GFX1++,G_RM_NOOP,G_RM_NOOP2); + gDPSetColorImage(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_32b, SCREEN_WD, OS_K0_TO_PHYSICAL(cfb[vid_side])); + gDPSetFillColor(GFX1++, GPACK_RGBA5551(0,0,0,0) << 16 | GPACK_RGBA5551(0,0,0,0)); + gDPFillRectangle(GFX1++, 0, 0, SCREEN_WD-1, SCREEN_HT-1); + + ST_DrawString(-1, 40, "no controller pak.", 0xffffffff); + ST_DrawString(-1, 60, "your game cannot", 0xffffffff); + ST_DrawString(-1, 80, "be saved.", 0xffffffff); + ST_DrawString(-1, 120, "please turn off your", 0xffffffff); + ST_DrawString(-1, 140, "nintendo 64 system", 0xffffffff); + ST_DrawString(-1, 160, "before inserting a", 0xffffffff); + ST_DrawString(-1, 180, "controller pak.", 0xffffffff); + + I_DrawFrame(); +} + +void D_SplashScreen(void) // 8002B988 +{ + /* */ + /* Check if the n64 control is connected */ + /* if not connected, it will show the Warning screen */ + /* */ + if ((gamepad_bit_pattern & 1) == 0) { + MiniLoop(NULL, NULL,D_WarningTicker,D_DrawWarning); + } + + /* */ + /* Check if the n64 controller Pak is connected */ + /* */ + I_CheckControllerPak(); + + /* */ + /* if not connected, it will show the NoPak screen */ + /* */ + if (FilesUsed < 0) { + last_ticon = 0; + MiniLoop(NULL, NULL, D_NoPakTicker, D_DrawNoPak); + } + + /* */ + /* show the legals screen */ + /* */ + + text_alpha = 0xff; + last_ticon = 0; + MiniLoop(NULL, NULL, D_LegalTicker, D_DrawLegal); +} + +static int cred_step; // 800B2210 +static int cred1_alpha; // 800B2214 +static int cred2_alpha; // 800B2218 +static int cred_next; // 800B2218 + +int D_Credits(void) // 8002BA34 +{ + int exit; + + cred_next = 0; + cred1_alpha = 0; + cred2_alpha = 0; + cred_step = 0; + exit = MiniLoop(NULL, NULL, D_CreditTicker, D_CreditDrawer); + + return exit; +} + +int D_CreditTicker(void) // 8002BA88 +{ + if (((u32)ticbuttons[0] >> 16) != 0) + return ga_exit; + + if ((cred_next == 0) || (cred_next == 1)) + { + if (cred_step == 0) + { + cred1_alpha += 8; + if (cred1_alpha >= 255) + { + cred1_alpha = 0xff; + cred_step = 1; + } + } + else if (cred_step == 1) + { + cred2_alpha += 8; + if (cred2_alpha >= 255) + { + cred2_alpha = 0xff; + last_ticon = ticon; + cred_step = 2; + } + } + else if (cred_step == 2) + { + if ((ticon - last_ticon) >= 180) // 6 * TICRATE + cred_step = 3; + } + else + { + cred1_alpha -= 8; + cred2_alpha -= 8; + if (cred1_alpha < 0) + { + cred_next += 1; + cred1_alpha = 0; + cred2_alpha = 0; + cred_step = 0; + } + } + } + else if (cred_next == 2) + return ga_exitdemo; + + return ga_nothing; +} + +void D_CreditDrawer(void) // 8002BBE4 +{ + int color; + + I_ClearFrame(); + + gDPPipeSync(GFX1++); + gDPSetCycleType(GFX1++, G_CYC_FILL); + gDPSetRenderMode(GFX1++,G_RM_NOOP,G_RM_NOOP2); + gDPSetColorImage(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_32b, SCREEN_WD, OS_K0_TO_PHYSICAL(cfb[vid_side])); + + if (cred_next == 0) + { + // Set Background Color (Dark Blue) + color = (cred1_alpha * 16) / 255; + gDPSetFillColor(GFX1++, color << 8 | 255); + gDPFillRectangle(GFX1++, 0, 0, SCREEN_WD-1, SCREEN_HT-1); + + M_DrawBackground(68, 21, cred1_alpha, "IDCRED1"); + M_DrawBackground(32, 41, cred2_alpha, "IDCRED2"); + } + else + { + if ((cred_next == 1) || (cred_next == 2)) + { + // Set Background Color (Dark Grey) + color = (cred1_alpha * 30) / 255; + gDPSetFillColor(GFX1++, color << 24 | color << 16 | color << 8 | 255); + gDPFillRectangle(GFX1++, 0, 0, SCREEN_WD-1, SCREEN_HT-1); + + M_DrawBackground(22, 82, cred1_alpha, "WMSCRED1"); + M_DrawBackground(29, 28, cred2_alpha, "WMSCRED2"); + } + } + + I_DrawFrame(); +} + +void D_OpenControllerPak(void) // 8002BE28 +{ + unsigned int oldbuttons; + + oldbuttons = I_GetControllerData(); + + if (((oldbuttons & 0xffff0000) == PAD_START) && (I_CheckControllerPak() == 0)) + { + MenuCall = M_ControllerPakDrawer; + linepos = 0; + cursorpos = 0; + + MiniLoop(M_FadeInStart, M_MenuClearCall, M_ScreenTicker, M_MenuGameDrawer); + I_WIPE_FadeOutScreen(); + } + return; +} diff --git a/Doom 64/decodes.c b/Doom 64/decodes.c @@ -0,0 +1,885 @@ +/* decodes.c */ + +#include "doomdef.h" + +#include "graph.h" + +/*=======*/ +/* TYPES */ +/*=======*/ + +typedef struct { + int var0; + int var1; + int var2; + int var3; + byte *write; + byte *writePos; + byte *read; + byte *readPos; +} decoder_t; + +/*=========*/ +/* GLOBALS */ +/*=========*/ + +static short ShiftTable[6] = {4, 6, 8, 10, 12, 14}; // 8005D8A0 + +static int tableVar01[18]; // 800B2250 + +static short *PtrEvenTbl; // 800B2298 +static short *PtrOddTbl; // 800B229C +static short *PtrNumTbl1; // 800B22A0 +static short *PtrNumTbl2; // 800B22A4 + +//static short EvenTable[0x275]; // DecodeTable[0] +//static short OddTable[0x275]; // DecodeTable[0x278] +//static short NumTable1[0x4EA]; // DecodeTable[0x4F0] +//static short NumTable2[0x4EA]; // array01[0] + +static short DecodeTable[2524]; // 800B22A8 +static short array01[1258]; // 800B3660 + +static decoder_t decoder; // 800B4034 +static byte *allocPtr; // 800B4054 + +static int OVERFLOW_READ; // 800B4058 +static int OVERFLOW_WRITE; // 800B405C + +/* +============================================================================ + +DECODE BASED ROUTINES + +============================================================================ +*/ + +/* +======================== += += GetDecodeByte += +======================== +*/ + +static byte GetDecodeByte(void) // 8002D1D0 +{ + if ((int)(decoder.readPos - decoder.read) >= OVERFLOW_READ) + return -1; + + return *decoder.readPos++; +} + +/* +======================== += += WriteOutput += +======================== +*/ + +static void WriteOutput(byte outByte) // 8002D214 +{ + if ((int)(decoder.writePos - decoder.write) >= OVERFLOW_WRITE) + I_Error("Overflowed output buffer"); + + *decoder.writePos++ = outByte; +} + +/* +======================== += += WriteBinary += routine required for encoding += +======================== +*/ + +static void WriteBinary(int binary) // 8002D288 +{ + decoder.var3 = (decoder.var3 << 1); + + if (binary != 0) + decoder.var3 = (decoder.var3 | 1); + + decoder.var2 = (decoder.var2 + 1); + if (decoder.var2 == 8) + { + WriteOutput((byte)decoder.var3); + decoder.var2 = 0; + } +} + +/* +======================== += += DecodeScan += +======================== +*/ + +static int DecodeScan(void) // 8002D2F4 +{ + int resultbyte; + + resultbyte = decoder.var0; + + decoder.var0 = (resultbyte - 1); + if ((resultbyte < 1)) + { + resultbyte = GetDecodeByte(); + + decoder.var1 = resultbyte; + decoder.var0 = 7; + } + + resultbyte = (0 < (decoder.var1 & 0x80)); + decoder.var1 = (decoder.var1 << 1); + + return resultbyte; +} + +/* +======================== += += MakeExtraBinary += routine required for encoding += +======================== +*/ + +static void MakeExtraBinary(int binary, int shift) // 8002D364 +{ + int i; + + i = 0; + if (shift > 0) + { + do + { + WriteBinary(binary & 1); + binary = (binary >> 1); + } while (++i != shift); + } +} + +/* +======================== += += RescanByte += +======================== +*/ + +static int RescanByte(int byte) // 8002D3B8 +{ + int shift; + int i; + int resultbyte; + + resultbyte = 0; + i = 0; + shift = 1; + + if(byte <= 0) + return resultbyte; + + do + { + if (DecodeScan() != 0) + resultbyte |= shift; + + i++; + shift = (shift << 1); + } while (i != byte); + + return resultbyte; +} + +/* +======================== += += WriteEndCode += routine required for encoding += +======================== +*/ + +static void WriteEndCode(void) // 8002D424 +{ + if (decoder.var2 > 0) { + WriteOutput((byte)(decoder.var3 << (8 - decoder.var2)) & 0xff); + } +} + +/* +======================== += += InitDecodeTable += +======================== +*/ + +static void InitDecodeTable(void) // 8002D468 +{ + int evenVal, oddVal, incrVal; + + short *curArray; + short *incrTbl; + short *evenTbl; + short *oddTbl; + + tableVar01[15] = 3; + tableVar01[16] = 0; + tableVar01[17] = 0; + + decoder.var0 = 0; + decoder.var1 = 0; + decoder.var2 = 0; + decoder.var3 = 0; + + curArray = &array01[2]; + incrTbl = &DecodeTable[0x4F2]; + + incrVal = 2; + + do + { + if(incrVal < 0) { + *incrTbl = (short)((incrVal + 1) >> 1); + } + else { + *incrTbl = (short)(incrVal >> 1); + } + + *curArray++ = 1; + incrTbl++; + } while(++incrVal < 1258); + + oddTbl = &DecodeTable[0x279]; + evenTbl = &DecodeTable[1]; + + evenVal = 2; + oddVal = 3; + + do + { + *oddTbl++ = (short)oddVal; + oddVal += 2; + + *evenTbl++ = (short)evenVal; + evenVal += 2; + + } while(oddVal < 1259); + + tableVar01[0] = 0; + + incrVal = (1 << ShiftTable[0]); + tableVar01[6] = (incrVal - 1); + tableVar01[1] = incrVal; + + incrVal += (1 << ShiftTable[1]); + tableVar01[7] = (incrVal - 1); + tableVar01[2] = incrVal; + + incrVal += (1 << ShiftTable[2]); + tableVar01[8] = (incrVal - 1); + tableVar01[3] = incrVal; + + incrVal += (1 << ShiftTable[3]); + tableVar01[9] = (incrVal - 1); + tableVar01[4] = incrVal; + + incrVal += (1 << ShiftTable[4]); + tableVar01[10] = (incrVal - 1); + tableVar01[5] = incrVal; + + incrVal += (1 << ShiftTable[5]); + tableVar01[11] = (incrVal - 1); + tableVar01[12] = (incrVal - 1); + + tableVar01[13] = tableVar01[12] + 64; +} + +/* +======================== += += CheckTable += +======================== +*/ + +static void CheckTable(int a0,int a1,int a2) // 8002D624 +{ + int i; + int idByte1; + int idByte2; + short *curArray; + short *evenTbl; + short *oddTbl; + short *incrTbl; + + i = 0; + evenTbl = &DecodeTable[0]; + oddTbl = &DecodeTable[0x278]; + incrTbl = &DecodeTable[0x4F0]; + + idByte1 = a0; + + do { + idByte2 = incrTbl[idByte1]; + + array01[idByte2] = (array01[a1] + array01[a0]); + + a0 = idByte2; + + if(idByte2 != 1) { + idByte1 = incrTbl[idByte2]; + idByte2 = evenTbl[idByte1]; + + a1 = idByte2; + + if(a0 == idByte2) { + a1 = oddTbl[idByte1]; + } + } + + idByte1 = a0; + }while(a0 != 1); + + if(array01[1] != 0x7D0) { + return; + } + + array01[1] >>= 1; + + curArray = &array01[2]; + do + { + curArray[3] >>= 1; + curArray[2] >>= 1; + curArray[1] >>= 1; + curArray[0] >>= 1; + curArray += 4; + i += 4; + } while(i != 1256); +} + +/* +======================== += += DecodeByte += +======================== +*/ + +static void DecodeByte(int tblpos) // 8002D72C +{ + int incrIdx; + int evenVal; + int idByte1; + int idByte2; + int idByte3; + int idByte4; + + short *evenTbl; + short *oddTbl; + short *incrTbl; + short *tmpIncrTbl; + + evenTbl = &DecodeTable[0]; + oddTbl = &DecodeTable[0x278]; + incrTbl = &DecodeTable[0x4F0]; + + idByte1 = (tblpos + 0x275); + array01[idByte1] += 1; + + if (incrTbl[idByte1] != 1) + { + tmpIncrTbl = &incrTbl[idByte1]; + idByte2 = *tmpIncrTbl; + + if (idByte1 == evenTbl[idByte2]) { + CheckTable(idByte1, oddTbl[idByte2], idByte1); + } + else { + CheckTable(idByte1, evenTbl[idByte2], idByte1); + } + + do + { + incrIdx = incrTbl[idByte2]; + evenVal = evenTbl[incrIdx]; + + if (idByte2 == evenVal) { + idByte3 = oddTbl[incrIdx]; + } + else { + idByte3 = evenVal; + } + + if (array01[idByte3] < array01[idByte1]) + { + if (idByte2 == evenVal) { + oddTbl[incrIdx] = (short)idByte1; + } + else { + evenTbl[incrIdx] = (short)idByte1; + } + + evenVal = evenTbl[idByte2]; + + if (idByte1 == evenVal) { + idByte4 = oddTbl[idByte2]; + evenTbl[idByte2] = (short)idByte3; + } + else { + idByte4 = evenVal; + oddTbl[idByte2] = (short)idByte3; + } + + incrTbl[idByte3] = (short)idByte2; + + *tmpIncrTbl = (short)incrIdx; + CheckTable(idByte3, idByte4, idByte4); + + tmpIncrTbl = &incrTbl[idByte3]; + } + + idByte1 = *tmpIncrTbl; + tmpIncrTbl = &incrTbl[idByte1]; + + idByte2 = *tmpIncrTbl; + } while (idByte2 != 1); + } +} + +/* +======================== += += StartDecodeByte += +======================== +*/ + +static int StartDecodeByte(void) // 8002D904 +{ + int lookup; + short *evenTbl; + short *oddTbl; + + lookup = 1; + + evenTbl = &DecodeTable[0]; + oddTbl = &DecodeTable[0x278]; + + while(lookup < 0x275) + { + if(DecodeScan() == 0) { + lookup = evenTbl[lookup]; + } + else { + lookup = oddTbl[lookup]; + } + } + + lookup = (lookup + -0x275); + DecodeByte(lookup); + + return lookup; +} + +/* +======================== += += L8002d990 += unknown Function += +======================== +*/ + +void L8002d990(int arg0) // 8002D990 +{ + int val; + + val = ((allocPtr[(arg0 + 2) % tableVar01[13]] << 8) ^ (allocPtr[arg0] ^ (allocPtr[(arg0+1) % tableVar01[13]] << 4))) & 0x3fff; + + if (PtrEvenTbl[val] == -1) + { + PtrOddTbl[val] = arg0; + PtrNumTbl1[arg0] = -1; + } + else + { + PtrNumTbl1[arg0] = PtrEvenTbl[val]; + PtrNumTbl2[PtrEvenTbl[val]] = arg0; + } + + PtrEvenTbl[val] = arg0; + PtrNumTbl2[arg0] = -1; +} + +/* +======================== += += FUN_8002dad0 += unknown Function += +======================== +*/ + +void FUN_8002dad0(int arg0) // 8002DAD0 +{ + int val; + + val = ((allocPtr[(arg0 + 2) % tableVar01[13]] << 8) ^ (allocPtr[arg0] ^ (allocPtr[(arg0+1) % tableVar01[13]] << 4))) & 0x3fff; + + if (PtrEvenTbl[val] == PtrOddTbl[val]) + { + PtrEvenTbl[val] = -1; + } + else + { + PtrNumTbl1[PtrNumTbl2[PtrOddTbl[val]]] = -1; + PtrOddTbl[val] = PtrNumTbl2[PtrOddTbl[val]]; + } +} + +/* +======================== += += FUN_8002dc0c += unknown Function += +======================== +*/ + +int FUN_8002dc0c(int start, int count) // 8002DC0C +{ + short sVar1; + int iVar2; + int iVar4; + int iVar5; + int iVar6; + + int cnt; + int curr, next; + + iVar4 = 0; + if (start == tableVar01[13]) { + start = 0; + } + + sVar1 = PtrEvenTbl[(allocPtr[(start + 2) % tableVar01[13]] << 8 ^ allocPtr[start] ^ allocPtr[(start + 1) % tableVar01[13]] << 4) & 0x3fff]; + + iVar5 = 1; + do + { + iVar2 = (int)sVar1; + if ((iVar2 == -1) || (count < iVar5)) { + return iVar4; + } + + if ((allocPtr[(start + iVar4) % tableVar01[13]]) == + (allocPtr[(iVar2 + iVar4) % tableVar01[13]])) + { + cnt = 0; + if (allocPtr[start] == allocPtr[iVar2]) + { + curr = start; + next = iVar2; + + if(next != start) + { + while (curr != tableVar01[15]) + { + curr++; + if (curr == tableVar01[13]) { + curr = 0; + } + + next++; + if (next == tableVar01[13]) { + next = 0; + } + + cnt++; + + if (allocPtr[curr] != allocPtr[next]) + break; + + if (cnt >= 64) + break; + + if (next == start) + break; + } + } + } + + iVar6 = start - iVar2; + if (iVar6 < 0) { + iVar6 += tableVar01[13]; + } + + iVar6 -= cnt; + if (tableVar01[16] && (tableVar01[6]/*15*/ < iVar6)) { + return iVar4; + } + + //if (((iVar4 < cnt) && (iVar6 <= tableVar01[12])) && + //((3 < cnt || (iVar6 <= tableVar01[tableVar01[17] + 9])))) + if(iVar4 < cnt) + { + if(iVar6 <= tableVar01[12]) + { + if((cnt > 3) || (iVar6 <= tableVar01[tableVar01[17] + 9])) + { + iVar4 = cnt; + tableVar01[14] = iVar6; + } + } + } + } + + sVar1 = PtrNumTbl1[iVar2]; + iVar5++; + } while( true ); +} + +/* +======================== += += FUN_8002df14 += unknown Function += +======================== +*/ + +void FUN_8002df14(void) // 8002DF14 +{ + byte byte_val; + + int i, j, k; + byte *curPtr; + byte *nextPtr; + byte *next2Ptr; + + curPtr = &allocPtr[0]; + + k = 0; + j = 0; + i = 1; + do + { + nextPtr = &allocPtr[j]; + if (curPtr[0] == 10) + { + j = i; + if(nextPtr[0] == curPtr[1]) + { + next2Ptr = &allocPtr[i+1]; + do + { + nextPtr++; + byte_val = *next2Ptr++; + k++; + } while (*nextPtr == byte_val); + } + } + curPtr++; + i++; + } while (i != 67); + + if (k >= 16) + tableVar01[16] = 1; +} + +/* +======================== += += DecodeD64 += += Exclusive Doom 64 += +======================== +*/ + +void DecodeD64(unsigned char *input, unsigned char *output) // 8002DFA0 +{ + int copyPos, storePos; + int dec_byte, resc_byte; + int incrBit, copyCnt, shiftPos, j; + + //PRINTF_D2(WHITE, 0, 15, "DecodeD64"); + + InitDecodeTable(); + + OVERFLOW_READ = MAXINT; + OVERFLOW_WRITE = MAXINT; + + incrBit = 0; + + decoder.read = input; + decoder.readPos = input; + decoder.write = output; + decoder.writePos = output; + + allocPtr = (byte *)Z_Alloc(tableVar01[13], PU_STATIC, NULL); + + dec_byte = StartDecodeByte(); + + while(dec_byte != 256) + { + if(dec_byte < 256) + { + /* Decode the data directly using binary data code */ + + WriteOutput((byte)(dec_byte & 0xff)); + allocPtr[incrBit] = (byte)dec_byte; + + /* Resets the count once the memory limit is exceeded in allocPtr, + so to speak resets it at startup for reuse */ + incrBit += 1; + if(incrBit == tableVar01[13]) { + incrBit = 0; + } + } + else + { + /* Decode the data using binary data code, + a count is obtained for the repeated data, + positioning itself in the root that is being stored in allocPtr previously. */ + + /* A number is obtained from a range from 0 to 5, + necessary to obtain a shift value in the ShiftTable*/ + shiftPos = (dec_byte + -257) / 62; + + /* get a count number for data to copy */ + copyCnt = (dec_byte - (shiftPos * 62)) + -254; + + /* To start copying data, you receive a position number + that you must sum with the position of table tableVar01 */ + resc_byte = RescanByte(ShiftTable[shiftPos]); + + /* with this formula the exact position is obtained + to start copying previously stored data */ + copyPos = incrBit - ((tableVar01[shiftPos] + resc_byte) + copyCnt); + + if(copyPos < 0) { + copyPos += tableVar01[13]; + } + + storePos = incrBit; + + for(j = 0; j < copyCnt; j++) + { + /* write the copied data */ + WriteOutput(allocPtr[copyPos]); + + /* save copied data at current position in memory allocPtr */ + allocPtr[storePos] = allocPtr[copyPos]; + + storePos++; /* advance to next allocPtr memory block to store */ + copyPos++; /* advance to next allocPtr memory block to copy */ + + /* reset the position of storePos once the memory limit is exceeded */ + if(storePos == tableVar01[13]) { + storePos = 0; + } + + /* reset the position of copyPos once the memory limit is exceeded */ + if(copyPos == tableVar01[13]) { + copyPos = 0; + } + } + + /* Resets the count once the memory limit is exceeded in allocPtr, + so to speak resets it at startup for reuse */ + incrBit += copyCnt; + if (incrBit >= tableVar01[13]) { + incrBit -= tableVar01[13]; + } + } + + dec_byte = StartDecodeByte(); + } + + Z_Free(allocPtr); + + //PRINTF_D2(WHITE, 0, 21, "DecodeD64:End"); +} + +/* +== == == == == == == == == == += += DecodeJaguar (decode original name) += += Exclusive Psx Doom / Doom 64 from Jaguar Doom += +== == == == == == == == == == +*/ + +#define WINDOW_SIZE 4096 +#define LOOKAHEAD_SIZE 16 + +#define LENSHIFT 4 /* this must be log2(LOOKAHEAD_SIZE) */ + +void DecodeJaguar(unsigned char *input, unsigned char *output) // 8002E1f4 +{ + int getidbyte = 0; + int len; + int pos; + int i; + unsigned char *source; + int idbyte = 0; + + while (1) + { + /* get a new idbyte if necessary */ + if (!getidbyte) idbyte = *input++; + getidbyte = (getidbyte + 1) & 7; + + if (idbyte & 1) + { + /* decompress */ + pos = *input++ << LENSHIFT; + pos = pos | (*input >> LENSHIFT); + source = output - pos - 1; + len = (*input++ & 0xf) + 1; + if (len == 1) break; + + //for (i = 0; i<len; i++) + //*output++ = *source++; + + i = 0; + if (len > 0) + { + if ((len & 3)) + { + while(i != (len & 3)) + { + *output++ = *source++; + i++; + } + } + while(i != len) + { + output[0] = source[0]; + output[1] = source[1]; + output[2] = source[2]; + output[3] = source[3]; + output += 4; + source += 4; + i += 4; + } + } + } + else + { + *output++ = *input++; + } + + idbyte = idbyte >> 1; + } +} diff --git a/Doom 64/doomdata.h b/Doom 64/doomdata.h @@ -0,0 +1,220 @@ +/* DoomData.h */ + +/* all external data is defined here */ +/* most of the data is loaded into different structures at run time */ + +#ifndef __DOOMDATA__ +#define __DOOMDATA__ + +#ifndef __BYTEBOOL__ +#define __BYTEBOOL__ +typedef enum {false, true} boolean; +typedef unsigned char byte; +#endif + +/* +=============================================================================== + + map level types + +=============================================================================== +*/ + +/* lump order in a map wad */ +enum {ML_LABEL, ML_THINGS, ML_LINEDEFS, ML_SIDEDEFS, ML_VERTEXES, ML_SEGS, +ML_SSECTORS, ML_NODES, ML_SECTORS , ML_REJECT, ML_BLOCKMAP, ML_LEAFS, ML_LIGHTS, ML_MACROS, ENDOFWAD +}; + +typedef struct +{ + int x, y; // (Psx Doom / Doom 64) +} mapvertex_t; + +typedef struct +{ + short textureoffset; + short rowoffset; + short toptexture, bottomtexture, midtexture; + short sector; /* on viewer's side */ +} mapsidedef_t; + +typedef struct +{ + short v1, v2; + int flags; + short special, tag; + short sidenum[2]; /* sidenum[1] will be -1 if one sided */ +} maplinedef_t; + +#define ML_BLOCKING 1 +#define ML_BLOCKMONSTERS 2 +#define ML_TWOSIDED 4 /* backside will not be present at all */ + /* if not two sided ???:obsolete */ + +/* if a texture is pegged, the texture will have the end exposed to air held */ +/* constant at the top or bottom of the texture (stairs or pulled down things) */ +/* and will move with a height change of one of the neighbor sectors */ +/* Unpegged textures allways have the first row of the texture at the top */ +/* pixel of the line for both top and bottom textures (windows) */ +#define ML_DONTPEGTOP 8 +#define ML_DONTPEGBOTTOM 16 + +#define ML_SECRET 32 /* don't map as two sided: IT'S A SECRET! */ +#define ML_SOUNDBLOCK 64 /* don't let sound cross two of these */ +#define ML_DONTDRAW 128 /* don't draw on the automap */ +#define ML_MAPPED 256 /* set if allready drawn in automap */ + +// New Doom 64 Line Flags + +#define ML_DRAWMASKED 0x200 /* Draw middle texture on sidedef */ +#define ML_DONTOCCLUDE 0x400 /* Don't add to occlusion buffer */ +#define ML_BLOCKPROJECTILES 0x800 /* blocks projectiles */ +#define ML_THINGTRIGGER 0x1000 /* Line is triggered by dead thing (flagged as ondeathtrigger) */ +#define ML_SWITCHX02 0x2000 /* Switch flag 1 */ +#define ML_SWITCHX04 0x4000 /* Switch flag 2 */ +#define ML_SWITCHX08 0x8000 /* Switch flag 3 */ +#define ML_CHECKFLOORHEIGHT 0x10000 /* if true then check the switch's floor height, else use the ceiling height */ +#define ML_SCROLLRIGHT 0x20000 /* scroll texture to the right */ +#define ML_SCROLLLEFT 0x40000 /* scroll texture to the left */ +#define ML_SCROLLUP 0x80000 /* scroll texture up */ +#define ML_SCROLLDOWN 0x100000 /* scroll texture down */ +#define ML_BLENDFULLTOP 0x200000 /* do not extend blending for top texture */ +#define ML_BLENDFULLBOTTOM 0x400000 /* do not extend blending for bottom texture */ +#define ML_BLENDING 0x800000 /* use sector color blending (top/lower, ceiling, floor colors). */ +#define ML_TRIGGERFRONT 0x1000000 /* can only trigger from the front of the line */ +#define ML_HIDEAUTOMAPTRIGGER 0x2000000 /* don't display as yellow line special in automap */ +#define ML_INVERSEBLEND 0x4000000 /* reverse the blending of the sector colors */ +#define ML_UNKNOWN8000000 0x8000000 /* reserved */ +#define ML_UNKNOWN10000000 0x10000000 /* reserved */ +#define ML_UNKNOWN20000000 0x20000000 /* reserved */ +#define ML_HMIRROR 0x40000000 /* horizontal mirror the texture */ +#define ML_VMIRROR 0x80000000 /* vertical mirror the texture */ + +/* +// Psx Doom New Flags +#define ML_MIDMASKED 0x200 +#define ML_MIDTRANSLUCENT 0x400 +#define ML_BLOCKPRJECTILE 0x800 +// Psx Final Doom New Flag +#define ML_MIDCLIPTEXTURE 0x1000 +*/ + +/*---------------------*/ +/* Special attributes. */ +/*---------------------*/ + +#define MLU_MACRO 0x100 /* line is set to be used as a macro */ +#define MLU_RED 0x200 /* requires red key */ +#define MLU_BLUE 0x400 /* requires blue key */ +#define MLU_YELLOW 0x800 /* requires yellow key */ +#define MLU_CROSS 0x1000 /* must cross to trigger */ +#define MLU_SHOOT 0x2000 /* must shoot the line to trigger */ +#define MLU_USE 0x4000 /* must press use on the line to trigger */ +#define MLU_REPEAT 0x8000 /* line can be reactivated again */ + +/*------------*/ +/* Line masks */ +/*------------*/ + +#define SWITCHMASK(x) (x & 0x6000) +#define SPECIALMASK(x) (x & 0x1FF) +#define MACROMASK(x) (SPECIALMASK(x) - (x & MLU_MACRO)) + +typedef struct +{ + short floorheight, ceilingheight; + short floorpic, ceilingpic; + short colors[5]; + short special, tag; + short flags; +} mapsector_t; + +/*--------------*/ +/* Sector Flags */ +/*--------------*/ + +#define MS_REVERB 1 /* sounds are echoed in this sector */ +#define MS_REVERBHEAVY 2 /* heavier echo effect */ +#define MS_LIQUIDFLOOR 4 /* water effect (blitting two flats together) */ +#define MS_SYNCSPECIALS 8 /* sync light special with multiple sectors */ +#define MS_SCROLLFAST 16 /* faster ceiling/floor scrolling */ +#define MS_SECRET 32 /* count secret when entering and display message */ +#define MS_DAMAGEX5 64 /* damage player x5 */ +#define MS_DAMAGEX10 128 /* damage player x10 */ +#define MS_DAMAGEX20 256 /* damage player x20 */ +#define MS_HIDESSECTOR 512 /* hide subsectors in automap (textured mode) */ +#define MS_SCROLLCEILING 1024 /* enable ceiling scrolling */ +#define MS_SCROLLFLOOR 2048 /* enable floor scrolling */ +#define MS_SCROLLLEFT 4096 /* scroll flat to the left */ +#define MS_SCROLLRIGHT 8192 /* scroll flat to the right */ +#define MS_SCROLLUP 16384 /* scroll flat to the north */ +#define MS_SCROLLDOWN 32768 /* scroll flat to the south */ + + +typedef struct +{ + short numsegs; + short firstseg; /* segs are stored sequentially */ +} mapsubsector_t; + +typedef struct +{ + short v1, v2; + short angle; /* ???: make this a sidedef? */ + short linedef, side; + short offset; +} mapseg_t; + +enum {BOXTOP,BOXBOTTOM,BOXLEFT,BOXRIGHT}; /* bbox coordinates */ + +#define NF_SUBSECTOR 0x8000 +typedef struct +{ + short x,y,dx,dy; /* partition line */ + short bbox[2][4]; /* bounding box for each child */ + unsigned short children[2]; /* if NF_SUBSECTOR its a subsector */ +} mapnode_t; + +typedef struct +{ + short x,y,z; + short angle; + short type; + short options; + short tid; +} mapthing_t; + +#define MTF_EASY 1 +#define MTF_NORMAL 2 +#define MTF_HARD 4 +#define MTF_AMBUSH 8 + +#define MTF_MULTI 16 /* Multiplayer specific */ +#define MTF_SPAWN 32 /* Don't spawn until triggered in level */ +#define MTF_ONTOUCH 64 /* Trigger something when picked up */ +#define MTF_ONDEATH 128 /* Trigger something when killed */ +#define MTF_SECRET 256 /* Count as secret for intermission when picked up */ +#define MTF_NOINFIGHTING 512 /* Ignore other attackers */ +#define MTF_NODEATHMATCH 1024 /* Don't spawn in deathmatch games */ +#define MTF_NONETGAME 2048 /* Don't spawn in standard netgame mode */ +#define MTF_NIGHTMARE 4096 /* [kex] Nightmare thing */ + +/* +//Psx Doom +#define MTF_BLENDMASK1 0x20 +#define MTF_BLENDMASK2 0x40 +#define MTF_BLENDMASK3 0x80 +*/ + +// New Doom 64 +typedef struct +{ + byte r; + byte g; + byte b; + byte a; + short tag; +} maplights_t; + +#endif /* __DOOMDATA__ */ + diff --git a/Doom 64/doomdef.h b/Doom 64/doomdef.h @@ -0,0 +1,1291 @@ +/* DoomDef.h */ + +#define VINT int + +/* ULTRA64 LIBRARIES */ +#include <ultra64.h> +#include "ultratypes.h" +#include <PR/ramrom.h> /* needed for argument passing into the app */ +#include <assert.h> +#include <libaudio.h> + +/* TEST DEBUG */ +#include "graph.h" + +/* WESS SYSTEM */ +#include "soundhw.h" +#include "seqload.h" +#include "wessapi.h" +#include "wessint_s.h" + +/*-----------*/ +/* SYSTEM IO */ +/*-----------*/ +#define SCREEN_HT 240 +#define SCREEN_WD 320 + +extern u32 cfb[2][SCREEN_WD*SCREEN_HT]; // 8036A000 + +/*============================================================================= */ + +/* Fixes and Version Update Here*/ +//FIXES +#define FIX_LINEDEFS_DELETION 1 // Fixes for the 'linedef deletion' bug. From PsyDoom + +/*============================================================================= */ + +/* all external data is defined here */ +#include "doomdata.h" + +/* header generated by multigen utility */ +#include "doominfo.h"//"info.h" + +#define MAXCHAR ((char)0x7f) +#define MAXSHORT ((short)0x7fff) +#define MAXINT ((int)0x7fffffff) /* max pos 32-bit int */ +#define MAXLONG ((long)0x7fffffff) + +#define MINCHAR ((char)0x80) +#define MINSHORT ((short)0x8000) +#define MININT ((int)0x80000000) /* max negative 32-bit integer */ +#define MINLONG ((long)0x80000000) + +#ifndef NULL +#define NULL 0 +#endif + +int D_vsprintf(char *string, const char *format, int *argptr); + +/* c_convert.c */ +void LightGetHSV(int r,int g,int b,int *h,int *s,int *v); // 800020BC +void LightGetRGB(int h,int s,int v,int *r,int *g,int *b); // 8000248C + +/* +=============================================================================== + + GLOBAL TYPES + +=============================================================================== +*/ + +#define MAXPLAYERS 1 /* D64 has one player */ +#define TICRATE 30 /* number of tics / second */ + +#define FRACBITS 16 +#define FRACUNIT (1<<FRACBITS) + +typedef int fixed_t; + +#define ANG45 0x20000000 +#define ANG90 0x40000000 +#define ANG180 0x80000000 +#define ANG270 0xc0000000 +#define ANG5 0x38e0000 // (ANG90/18) +#define ANG1 0xb60000 // (ANG45/45) +typedef unsigned angle_t; + +#define FINEANGLES 8192 +#define FINEMASK (FINEANGLES-1) +#define ANGLETOFINESHIFT 19 /* 0x100000000 to 0x2000 */ + +extern fixed_t finesine[5*FINEANGLES/4]; +extern fixed_t *finecosine; + +typedef enum +{ + sk_baby, + sk_easy, + sk_medium, + sk_hard, + sk_nightmare +} skill_t; + +typedef enum +{ + ga_nothing, + ga_died, + ga_completed, + ga_secretexit,// no used + ga_warped, + ga_exitdemo, + //News + //ga_recorddemo,// no used + ga_timeout, + ga_restart, + ga_exit +} gameaction_t; + +#define LASTLEVEL 34 +#define TOTALMAPS 33 + + +/* */ +/* library replacements */ +/* */ + +void D_memmove(void *dest, void *src); +void D_memset (void *dest, int val, int count); +void D_memcpy (void *dest, void *src, int count); +void D_strncpy (char *dest, char *src, int maxcount); +int D_strncasecmp (char *s1, char *s2, int len); +void D_strupr(char *s); +int D_strlen(char *s); + +/* +=============================================================================== + + MAPOBJ DATA + +=============================================================================== +*/ + +struct mobj_s; + +/* think_t is a function pointer to a routine to handle an actor */ +typedef void (*think_t) (); + +/* a latecall is a function that needs to be called after p_base is done */ +typedef void (*latecall_t) (struct mobj_s *mo); + +typedef struct thinker_s +{ + struct thinker_s *prev, *next; + think_t function; +} thinker_t; + +struct player_s; + +typedef struct mobj_s +{ +/* info for drawing */ + fixed_t x,y,z; + + struct subsector_s *subsector; + + int flags; + struct player_s *player; /* only valid if type == MT_PLAYER */ + + struct mobj_s *prev, *next; + struct mobj_s *snext, *sprev; /* links in sector (if needed) */ + struct mobj_s *bnext, *bprev; /* links in blocks (if needed) */ + + struct mobj_s *target; /* thing being chased/attacked (or NULL) */ + struct mobj_s *tracer; /* Thing being chased/attacked for tracers. */ + + angle_t angle; + VINT sprite; /* used to find patch_t and flip value */ + VINT frame; /* might be ord with FF_FULLBRIGHT */ + fixed_t floorz, ceilingz; /* closest together of contacted secs */ + fixed_t radius, height; /* for movement checking */ + fixed_t momx, momy, momz; /* momentums */ + + mobjtype_t type; + mobjinfo_t *info; /* &mobjinfo[mobj->type] */ + VINT tics; /* state tic counter */ + state_t *state; + + VINT health; + VINT movedir; /* 0-7 */ + VINT movecount; /* when 0, select a new dir */ + + /* also the originator for missiles */ + VINT reactiontime; /* if non 0, don't attack yet */ + /* used by player to freeze a bit after */ + /* teleporting */ + VINT threshold; /* if >0, the target will be chased */ + /* no matter what (even if shot) */ + + int alpha; /* [D64] alpha value */ + + void *extradata; /* for latecall functions */ + + latecall_t latecall; /* set in p_base if more work needed */ + + int tid; /* [D64] tid value */ +} mobj_t; + +/* each sector has a degenmobj_t in it's center for sound origin purposes */ +struct subsector_s; +typedef struct +{ + fixed_t x,y,z; + struct subsector_s *subsec; // Psx Doom / Doom 64 New +} degenmobj_t; + +typedef struct laserdata_s +{ + fixed_t x1, y1, z1; + fixed_t x2, y2, z2; + fixed_t slopex, slopey, slopez; + fixed_t distmax, dist; + mobj_t *marker; + struct laserdata_s *next; +} laserdata_t; + +typedef struct laser_s +{ + thinker_t thinker; + laserdata_t *laserdata; + mobj_t *marker; +} laser_t; + +/* */ +/* frame flags */ +/* */ +#define FF_FULLBRIGHT 0x8000 /* flag in thing->frame */ +#define FF_FRAMEMASK 0x7fff + +/* */ +/* mobj flags */ +/* */ +#define MF_SPECIAL 1 /* call P_SpecialThing when touched */ +#define MF_SOLID 2 +#define MF_SHOOTABLE 4 +#define MF_NOSECTOR 8 /* don't use the sector links */ + /* (invisible but touchable) */ +#define MF_NOBLOCKMAP 16 /* don't use the blocklinks */ + /* (inert but displayable) */ +#define MF_AMBUSH 32 +#define MF_JUSTHIT 64 /* try to attack right back */ +#define MF_JUSTATTACKED 128 /* take at least one step before attacking */ +#define MF_SPAWNCEILING 256 /* hang from ceiling instead of floor */ +//#define MF_NOGRAVITY 512 /* don't apply gravity every tic */ +#define MF_GRAVITY 512 /* apply gravity every tic */ + +/* movement flags */ +#define MF_DROPOFF 0x400 /* allow jumps from high places */ +#define MF_PICKUP 0x800 /* for players to pick up items */ +#define MF_NOCLIP 0x1000 /* player cheat */ +#define MF_TRIGDEATH 0x2000 /* [d64] trigger line special on death */ +#define MF_FLOAT 0x4000 /* allow moves to any height, no gravity */ +#define MF_TELEPORT 0x8000 /* don't cross lines or look at heights */ +#define MF_MISSILE 0x10000 /* don't hit same species, explode on block */ + +#define MF_DROPPED 0x20000 /* dropped by a demon, not level spawned */ +#define MF_TRIGTOUCH 0x40000 /* [d64] trigger line special on touch/pickup */ +#define MF_NOBLOOD 0x80000 /* don't bleed when shot (use puff) */ +#define MF_CORPSE 0x100000 /* don't stop moving halfway off a step */ +#define MF_INFLOAT 0x200000 /* floating to a height for a move, don't */ + /* auto float to target's height */ +#define MF_COUNTKILL 0x400000 /* count towards intermission kill total */ +#define MF_COUNTITEM 0x800000 /* count towards intermission item total */ + +#define MF_SKULLFLY 0x1000000 /* skull in flight */ +#define MF_NOTDMATCH 0x2000000 /* don't spawn in death match (key cards) */ + +#define MF_SEETARGET 0x4000000 /* is target visible? */ + +/* Doom 64 New Flags */ +#define MF_COUNTSECRET 0x8000000 /* [d64] Count as secret when picked up (for intermissions) */ +#define MF_RENDERLASER 0x10000000 /* [d64] Exclusive to MT_LASERMARKER only */ +#define MF_NIGHTMARE 0x20000000 /* [kex] Enables nightmare mode */ +#define MF_SHADOW 0x40000000 /* temporary player invisibility powerup. */ +#define MF_NOINFIGHTING 0x80000000 /* [d64] Do not switch targets */ + +//(val << 0 < 0) 0x80000000 +//(val << 1 < 0) 0x40000000 +//(val << 2 < 0) 0x20000000 +//(val << 3 < 0) 0x10000000 +//(val << 4 < 0) 0x8000000 +//(val << 5 < 0) 0x4000000 +//(val << 6 < 0) 0x2000000 +//(val << 7 < 0) 0x1000000 +//(val << 8 < 0) 0x800000 +//(val << 9 < 0) 0x400000 +//(val << a < 0) 0x200000 +//(val << b < 0) 0x100000 +//(val << c < 0) 0x80000 +//(val << d < 0) 0x40000 +//(val << e < 0) 0x20000 +//(val << f < 0) 0x10000 + +/* Exclusive Psx Doom Flags */ +//#define MF_BLENDMASK1 0x10000000 +//#define MF_BLENDMASK2 0x20000000 +//#define MF_BLENDMASK3 0x40000000 +//#define MF_ALL_BLEND_MASKS (MF_BLENDMASK1 | MF_BLENDMASK2 | MF_BLENDMASK3) + +/*============================================================================= */ +typedef enum +{ + PST_LIVE, /* playing */ + PST_DEAD, /* dead on the ground */ + PST_REBORN /* ready to restart */ +} playerstate_t; + + +/* psprites are scaled shapes directly on the view screen */ +/* coordinates are given for a 320*200 view screen */ +typedef enum +{ + ps_weapon, + ps_flash, + ps_flashalpha, // New Doom64 + NUMPSPRITES +} psprnum_t; + +typedef struct +{ + state_t *state; /* a NULL state means not active */ + int tics; + int alpha; + fixed_t sx, sy; +} pspdef_t; + +typedef enum +{ + it_bluecard, + it_yellowcard, + it_redcard, + it_blueskull, + it_yellowskull, + it_redskull, + NUMCARDS +} card_t; + +typedef enum +{ + wp_chainsaw, + wp_fist, + wp_pistol, + wp_shotgun, + wp_supershotgun,// [psx] + wp_chaingun, + wp_missile, + wp_plasma, + wp_bfg, + wp_laser, // [d64] + NUMWEAPONS, + wp_nochange +} weapontype_t; + +typedef enum +{ + am_clip, /* pistol / chaingun */ + am_shell, /* shotgun */ + am_cell, /* BFG */ + am_misl, /* missile launcher */ + NUMAMMO, + am_noammo /* chainsaw / fist */ +} ammotype_t; + +typedef enum +{ + ART_FAST = 1, + ART_DOUBLE = 2, + ART_TRIPLE = 3, +} artifacts_t; + +typedef struct +{ + ammotype_t ammo; + int upstate; + int downstate; + int readystate; + int atkstate; + int flashstate; +} weaponinfo_t; + +extern weaponinfo_t weaponinfo[NUMWEAPONS]; // 8005AD80 + +typedef enum +{ + pw_invulnerability, + pw_strength, + pw_invisibility, + pw_ironfeet, + pw_allmap, + pw_infrared, + NUMPOWERS +} powertype_t; + +#define INVULNTICS (30*30) +#define INVISTICS (60*30) +#define INFRATICS (120*30) +#define IRONTICS (60*30) +#define STRTICS (3*30) + +#define MSGTICS (5*30) + +/* +================ += += player_t += +================ +*/ + +typedef struct player_s +{ + mobj_t *mo; + playerstate_t playerstate; + + fixed_t forwardmove, sidemove; /* built from ticbuttons */ + angle_t angleturn; /* built from ticbuttons */ + + fixed_t viewz; /* focal origin above r.z */ + fixed_t viewheight; /* base height above floor for viewz */ + fixed_t deltaviewheight; /* squat speed */ + fixed_t bob; /* bounded/scaled total momentum */ + fixed_t recoilpitch; /* [D64] new*/ + + int health; /* only used between levels, mo->health */ + /* is used during levels */ + int armorpoints, armortype; /* armor type is 0-2 */ + + int powers[NUMPOWERS]; /* invinc and invis are tic counters */ + boolean cards[NUMCARDS]; + int artifacts; /* [d64]*/ + boolean backpack; + int frags; /* kills of other player */ + weapontype_t readyweapon; + weapontype_t pendingweapon; /* wp_nochange if not changing */ + boolean weaponowned[NUMWEAPONS]; + int ammo[NUMAMMO]; + int maxammo[NUMAMMO]; + int attackdown, usedown; /* true if button down last tic */ + int cheats; /* bit flags */ + + int refire; /* refired shots are less accurate */ + + int killcount, itemcount, secretcount; /* for intermission */ + char *message; /* hint messages */ + int messagetic; /* messages tic countdown*/ + int damagecount, bonuscount;/* for screen flashing */ + int bfgcount; /* for bfg screen flashing */ + mobj_t *attacker; /* who did damage (NULL for floors) */ + int extralight; /* so gun flashes light up areas */ + pspdef_t psprites[NUMPSPRITES]; /* view sprites (gun, etc) */ + + void *lastsoundsector; /* don't flood noise every time */ + + int automapx, automapy, automapscale, automapflags; + + int turnheld; /* for accelerative turning */ + int onground; /* [d64] */ +} player_t; + +#define CF_NOCLIP 1 // no use +#define CF_GODMODE 2 +#define CF_ALLMAP 4 +#define CF_DEBUG 64 +#define CF_TEX_TEST 0x200 +#define CF_SCREENSHOT 0x400 // Original 0x1000 +#define CF_LOCKMOSTERS 0x800 +#define CF_WALLBLOCKING 0x1000 +#define CF_WEAPONS 0x2000 +#define CF_HEALTH 0x4000 +#define CF_ALLKEYS 0x8000 +#define CF_MACROPEEK 0x10000 + +#define CF_NOCOLORS 0x20000 // [GEC] NEW CHEAT CODE +#define CF_FULLBRIGHT 0x40000 // [GEC] NEW CHEAT CODE +#define CF_FILTER 0x80000 // [GEC] NEW CHEAT CODE + +#define AF_LINES 1 /* automap active on lines mode */ +#define AF_SUBSEC 2 /* automap active on subsector mode */ +#define AF_FOLLOW 4 + +/* +=============================================================================== + + GLOBAL VARIABLES + +=============================================================================== +*/ + +/*================================== */ + +extern int gamevbls; // 80063130 /* may not really be vbls in multiplayer */ +extern int gametic; // 80063134 +extern int ticsinframe; // 80063138 /* how many tics since last drawer */ +extern int ticon; // 8006313C +extern int lastticon; // 80063140 +extern int vblsinframe[MAXPLAYERS]; // 80063144 /* range from 4 to 8 */ +extern int ticbuttons[MAXPLAYERS]; // 80063148 +extern int oldticbuttons[MAXPLAYERS]; // 8006314C + +extern boolean gamepaused; + +extern int DrawerStatus; + +//extern int maxlevel; /* highest level selectable in menu (1-25) */ + +int MiniLoop ( void (*start)(void), void (*stop)() + , int (*ticker)(void), void (*drawer)(void) ); + +int G_Ticker (void); +void G_Drawer (void); +void G_RunGame (void); + +/*================================== */ + + +extern gameaction_t gameaction; + +#define SBARHEIGHT 32 /* status bar height at bottom of screen */ + +typedef enum +{ + gt_single, + gt_coop, + gt_deathmatch +} gametype_t; + +//extern gametype_t netgame; + +//extern boolean playeringame[MAXPLAYERS]; +//extern int consoleplayer; /* player taking events and displaying */ +//extern int displayplayer; +extern player_t players[MAXPLAYERS]; + +extern skill_t gameskill; +extern int gamemap; +extern int nextmap; +extern int totalkills, totalitems, totalsecret; /* for intermission *///80077d4c,80077d58,80077E18 + +extern int gametic; + +//extern mapthing_t deathmatchstarts[10], *deathmatch_p; //80097e4c,80077e8c +extern mapthing_t playerstarts[MAXPLAYERS];//800a8c60 + +/* +=============================================================================== + + GLOBAL FUNCTIONS + +=============================================================================== +*/ + +short BigShort(short dat); +short LittleShort(short dat); +long LongSwap(long dat); + +fixed_t FixedMul (fixed_t a, fixed_t b); +fixed_t FixedDiv (fixed_t a, fixed_t b); +fixed_t FixedDiv2(fixed_t a, fixed_t b); + +//extern fixed_t FixedMul2 (fixed_t a, fixed_t b);// ASM MIPS CODE +//extern fixed_t FixedDiv3 (fixed_t a, fixed_t b);// ASM MIPS CODE + +#ifdef __BIG_ENDIAN__ +#define __BIG_ENDIAN__ +#endif + +#ifdef __BIG_ENDIAN__ + +#define LONGSWAP(x) (x) +#define LITTLESHORT(x) (x) +#define BIGSHORT(x) (x) + +#else + +#define LONGSWAP(x) LongSwap(x) +#define LITTLESHORT(x) LittleShort(x) +#define BIGSHORT(x) BigShort(x) + +#endif // __BIG_ENDIAN__ + +/*----------- */ +/*MEMORY ZONE */ +/*----------- */ +/* tags < 8 are not overwritten until freed */ +#define PU_STATIC 1 /* static entire execution time */ +#define PU_LEVEL 2 /* static until level exited */ +#define PU_LEVSPEC 4 /* a special thinker in a level */ +/* tags >= 8 are purgable whenever needed */ +#define PU_PURGELEVEL 8 +#define PU_CACHE 16 + +#define ZONEID 0x1d4a + +typedef struct memblock_s +{ + int size; /* including the header and possibly tiny fragments */ + void **user; /* NULL if a free block */ + int tag; /* purgelevel */ + int id; /* should be ZONEID */ + int lockframe; /* don't purge on the same frame */ + struct memblock_s *next; + struct memblock_s *prev; + void *gfxcache; /* New on Doom64 */ +} memblock_t; + +typedef struct +{ + int size; /* total bytes malloced, including header */ + memblock_t *rover; + memblock_t *rover2; /* New on Doom64 */ + memblock_t *rover3; /* New on Doom64 */ + memblock_t blocklist; /* start / end cap for linked list */ +} memzone_t; + +extern memzone_t *mainzone; + +void Z_Init (void); +memzone_t *Z_InitZone (byte *base, int size); + +void Z_SetAllocBase(memzone_t *mainzone); +void *Z_Malloc2 (memzone_t *mainzone, int size, int tag, void *ptr); +void *Z_Alloc2(memzone_t *mainzone, int size, int tag, void *user); // PsxDoom / Doom64 +void Z_Free2 (memzone_t *mainzone,void *ptr); + +#define Z_Malloc(x,y,z) Z_Malloc2(mainzone,x,y,z) +#define Z_Alloc(x,y,z) Z_Alloc2(mainzone,x,y,z) +#define Z_Free(x) Z_Free2(mainzone,x) + +void Z_FreeTags(memzone_t *mainzone, int tag); +void Z_Touch(void *ptr); +void Z_CheckZone (memzone_t *mainzone); +void Z_ChangeTag (void *ptr, int tag); +int Z_FreeMemory (memzone_t *mainzone); +void Z_DumpHeap(memzone_t *mainzone); + +/*------- */ +/*WADFILE */ +/*------- */ + +// New Doom64 +typedef enum +{ + dec_none, + dec_jag, + dec_d64 +} decodetype; + +typedef struct +{ + int filepos; /* also texture_t * for comp lumps */ + int size; + char name[8]; +} lumpinfo_t; + +typedef struct { + void *cache; +} lumpcache_t; + +//extern lumpinfo_t *lumpinfo; /* points directly to rom image */ +//extern int numlumps; +//extern lumpcache_t *lumpcache; +//extern byte *mapfileptr; // psxdoom/d64 +//extern int mapnumlumps; // psxdoom/d64 +//extern lumpinfo_t *maplump; // psxdoom/d64 + +void W_Init (void); + +int W_CheckNumForName (char *name, int hibit1, int hibit2); +int W_GetNumForName (char *name); + +int W_LumpLength (int lump); +void W_ReadLump (int lump, void *dest, decodetype dectype); + +void *W_CacheLumpNum (int lump, int tag, decodetype dectype); +void *W_CacheLumpName (char *name, int tag, decodetype dectype); + +void W_OpenMapWad(int mapnum); +void W_FreeMapLump(void); +int W_MapLumpLength(int lump); +int W_MapGetNumForName(char *name); +void *W_GetMapLump(int lump); + +/*---------*/ +/* DECODES */ +/*---------*/ +void DecodeD64(unsigned char *input, unsigned char *output); +void DecodeJaguar(unsigned char *input, unsigned char *output); + +/*------------*/ +/* BASE LEVEL */ +/*------------*/ + +/*--------*/ +/* D_MAIN */ +/*--------*/ + +void D_DoomMain (void); + +/*------*/ +/* GAME */ +/*------*/ + +extern boolean demoplayback, demorecording; +extern int *demo_p, *demobuffer; + +void G_InitNew (skill_t skill, int map, gametype_t gametype); +void G_CompleteLevel (void); +void G_RecordDemo (void); +int G_PlayDemoPtr (int skill, int map); + +/*------*/ +/* PLAY */ +/*------*/ + +mobj_t *P_SpawnMapThing (mapthing_t *mthing); +void P_SetupLevel (int map, skill_t skill); +void P_Init (void); + +void P_Start (void); +void P_Stop (int exit); +int P_Ticker (void); +void P_Drawer (void); + +/*---------*/ +/* IN_MAIN */ +/*---------*/ + +void IN_Start (void); +void IN_Stop (void); +int IN_Ticker (void); +void IN_Drawer (void); + +/*--------*/ +/* M_MAIN */ +/*--------*/ + +typedef void(*menufunc_t)(void); + +typedef struct +{ + int casepos; + int x; + int y; +} menuitem_t; + +typedef struct +{ + menuitem_t *menu_item; + int item_lines; + menufunc_t menu_call; + int cursor_pos; +} menudata_t; + +extern menudata_t MenuData[8]; // 800A54F0 +extern menuitem_t Menu_Game[4]; // 8005AAA4 +extern int MenuAnimationTic; // 800a5570 +extern int cursorpos; // 800A5574 +extern int m_vframe1; // 800A5578 +extern menuitem_t *MenuItem; // 800A5578 +extern int itemlines; // 800A5580 +extern menufunc_t MenuCall; // 800A5584 + +extern int linepos; // 800A5588 +extern int text_alpha_change_value; // 800A558C +extern int MusicID; // 800A5590 +extern int m_actualmap; // 800A5594 +extern int last_ticon; // 800a5598 + +extern skill_t startskill; // 800A55A0 +extern int startmap; // 800A55A4 +extern int EnableExpPak; // 800A55A8 + +//----------------------------------------- + +extern int MenuIdx; // 8005A7A4 +extern int text_alpha; // 8005A7A8 +extern int ConfgNumb; // 8005A7AC +extern int Display_X; // 8005A7B0 +extern int Display_Y; // 8005A7B4 +extern boolean enable_messages; // 8005A7B8 +extern boolean enable_statusbar; // 8005A7BC +extern int SfxVolume; // 8005A7C0 +extern int MusVolume; // 8005A7C4 +extern int brightness; // 8005A7C8 +extern int M_SENSITIVITY; // 8005A7CC +extern boolean FeaturesUnlocked; // 8005A7D0 + +int M_RunTitle(void); // 80007630 + +int M_ControllerPak(void); // 80007724 +int M_ButtonResponder(int buttons); // 80007960 + +void M_AlphaInStart(void); // 800079E0 +void M_AlphaOutStart(void); // 800079F8 +int M_AlphaInOutTicker(void); // 80007A14 +void M_FadeInStart(void); // 80007AB4 +void M_FadeOutStart(int exitmode); // 80007AEC + +void M_SaveMenuData(void); // 80007B2C +void M_RestoreMenuData(boolean alpha_in); // 80007BB8 +void M_MenuGameDrawer(void); // 80007C48 +int M_MenuTicker(void); // 80007E0C +void M_MenuClearCall(void); // 80008E6C + +void M_MenuTitleDrawer(void); // 80008E7C +void M_FeaturesDrawer(void); // 800091C0 +void M_VolumeDrawer(void); // 800095B4 +void M_ControlStickDrawer(void); // 80009738 +void M_DisplayDrawer(void); // 80009884 + +void M_DrawBackground(int x, int y, int color, char *name); // 80009A68 +void M_DrawOverlay(int x, int y, int w, int h, int color); // 80009F58 + +int M_ScreenTicker(void); // 8000A0F8 + +void M_ControllerPakDrawer(void); // 8000A3E4 + +void M_SavePakStart(void); // 8000A6E8 +void M_SavePakStop(void); // 8000A7B4 +int M_SavePakTicker(void); // 8000A804 +void M_SavePakDrawer(void); // 8000AB44 + +void M_LoadPakStart(void); // 8000AEEC +void M_LoadPakStop(void); // 8000AF8C +int M_LoadPakTicker(void); // 8000AFE4 +void M_LoadPakDrawer(void); // 8000B270 + +int M_CenterDisplayTicker(void); // 8000B4C4 +void M_CenterDisplayDrawer(void); // 8000B604 + +int M_ControlPadTicker(void); // 8000B694 +void M_ControlPadDrawer(void); // 8000B988 + +/*----------*/ +/* PASSWORD */ +/*----------*/ + +extern char *passwordChar; // 8005AC60 +extern byte Passwordbuff[16]; // 800A55B0 +extern boolean doPassword; // 8005ACB8 +extern int CurPasswordSlot; // 8005ACBC + +void M_EncodePassword(byte *buff);//8000BC10 +int M_DecodePassword(byte *inbuff, int *levelnum, int *skill, player_t *player); // 8000C194 +void M_PasswordStart(void); // 8000C710 +void M_PasswordStop(void); // 8000C744 +int M_PasswordTicker(void); // 8000C774 +void M_PasswordDrawer(void); // 8000CAF0 + +/*--------*/ +/* F_MAIN */ +/*--------*/ + +void F_StartIntermission (void); +void F_StopIntermission (void); +int F_TickerIntermission (void); +void F_DrawerIntermission (void); + +void F_Start (void); +void F_Stop (void); +int F_Ticker (void); +void F_Drawer (void); + +void BufferedDrawSprite(int type, state_t *state, int rotframe, int color, int xpos, int ypos); + +/*---------*/ +/* AM_MAIN */ +/*---------*/ + +void AM_Start (void); +void AM_Control (player_t *player); +void AM_Drawer (void); + +/*-----------*/ +/* D_SCREENS */ +/*-----------*/ + +int D_RunDemo(char *name, skill_t skill, int map); // 8002B2D0 +int D_TitleMap(void); // 8002B358 +int D_WarningTicker(void); // 8002B3E8 +void D_DrawWarning(void); // 8002B430 +int D_LegalTicker(void); // 8002B5F8 +void D_DrawLegal(void); // 8002B644 +int D_NoPakTicker(void); // 8002B7A0 +void D_DrawNoPak(void); // 8002B7F4 +void D_SplashScreen(void); // 8002B988 +int D_Credits(void); // 8002BA34 +int D_CreditTicker(void); // 8002BA88 +void D_CreditDrawer(void); // 8002BBE4 +void D_OpenControllerPak(void); // 8002BE28 + +/*--------*/ +/* REFRESH */ +/*--------*/ + +void R_RenderPlayerView (void); +void R_Init (void); +angle_t R_PointToAngle2 (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2); +struct subsector_s *R_PointInSubsector (fixed_t x, fixed_t y); + +/*------*/ +/* MISC */ +/*------*/ +typedef struct +{ + char * name; + int MusicSeq; +} mapinfo_t; + +extern mapinfo_t MapInfo[]; + +extern unsigned char rndtable[256]; +int M_Random (void); +int P_Random (void); +void M_ClearRandom (void); +void M_ClearBox (fixed_t *box); +void M_AddToBox (fixed_t *box, fixed_t x, fixed_t y); + +/*---------*/ +/* S_SOUND */ +/*---------*/ + +/* header generated by Dave's sound utility */ +#include "sounds.h" + +void S_Init(void); +void S_SetSoundVolume(int volume); +void S_SetMusicVolume(int volume); +void S_StartMusic(int mus_seq); +void S_StopMusic(void); +void S_PauseSound(void); +void S_ResumeSound(void); +void S_StopSound(mobj_t *origin,int seqnum); +void S_StopAll(void); +int S_SoundStatus(int seqnum); +void S_StartSound(mobj_t *origin, int sound_id); +int S_AdjustSoundParams(mobj_t *listener, mobj_t *origin, int* vol, int* pan); + +void S_StartSoundTest(int origin, int sound_id); + +/*--------*/ +/* I_MAIN */ +/*--------*/ + +/* vbi_wait_thread messages */ +enum VID_MSG { + VID_MSG_RSP = 666, + VID_MSG_RDP = 667, + VID_MSG_PRENMI = 668, + VID_MSG_VBI = 669, + VID_MSG_KICKSTART = 670, +}; + +extern OSTask *vid_task; // 800A5244 +extern u32 vid_side; // 800A5248 + +extern u8 gamepad_bit_pattern; // 800A5260 // one bit for each controller + +// Controller Pak +extern OSPfsState FileState[16]; // 800A52D8 +extern s32 File_Num; // 800A54D8 +extern s32 Pak_Size; // 800A54DC +extern u8 *Pak_Data; // 800A54E0 +extern s32 Pak_Memory; // 800A54E4 + +extern char Pak_Table[256]; // 8005A620 +extern char Game_Name[16]; // 8005A790 + +extern boolean disabledrawing; // 8005A720 +extern s32 vsync; // 8005A724 +extern s32 drawsync2; // 8005A728 +extern s32 drawsync1; // 8005A72C +extern u32 NextFrameIdx; // 8005A730 +extern s32 FilesUsed; // 8005A740 + +#define MAX_GFX 5120 +#define MAX_VTX 3072 +#define MAX_MTX 4 + +extern Gfx *GFX1; // 800A4A00 +extern Gfx *GFX2; // 800A4A04 + +extern Vtx *VTX1; // 800A4A08 +extern Vtx *VTX2; // 800A4A0C + +extern Mtx *MTX1; // 800A4A10 +extern Mtx *MTX2; // 800A4A14 + +void I_Start(void); // 80005620 +void I_IdleGameThread(void *arg); // 8000567C +void I_Main(void *arg); // 80005710 +void I_SystemTicker(void *arg); // 80005730 +void I_Init(void); // 80005C50 + +void I_Error(char *error, ...); // 80005F30 +int I_GetControllerData(void); // 800060D0 + +void I_CheckGFX(void); // 800060E8 +void I_ClearFrame(void); // 8000637C +void I_DrawFrame(void); // 80006570 +void I_GetScreenGrab(void); // 800066C0 + +void I_MoveDisplay(int x,int y); // 80006790 + +int I_CheckControllerPak(void); // 800070B0 +int I_DeletePakFile(int filenumb); // 80007224 +int I_SavePakFile(int filenumb, int flag, byte *data, int size); // 80007308 +int I_ReadPakFile(void); // 800073B8 +int I_CreatePakFile(void); // 800074D4 + +void I_WIPE_MeltScreen(void); // 80006964 +void I_WIPE_FadeOutScreen(void); // 80006D34 + +/*---------*/ +/* Doom 64 */ +/*---------*/ + +/* DOOM 64 CUSTOM COMBINES */ +#define G_CC_D64COMB01 TEXEL0, 0, SHADE, 0, 0, 0, 0, 1 +#define G_CC_D64COMB02 0, 0, 0, SHADE, 0, 0, 0, 1 +#define G_CC_D64COMB03 0, 0, 0, TEXEL0, TEXEL0, 0, PRIMITIVE, 0 +#define G_CC_D64COMB04 TEXEL0, 0, PRIMITIVE, 0, TEXEL0, 0, PRIMITIVE, 0 +#define G_CC_D64COMB05 1, 0, PRIMITIVE, 0, 1, 0, PRIMITIVE, 0 +#define G_CC_D64COMB06 TEXEL0, 0, PRIMITIVE, 0, 0, 0, 0, 0 +#define G_CC_D64COMB07 1, 0, PRIM_LOD_FRAC, TEXEL0, TEXEL0, 0, PRIMITIVE, 0 +#define G_CC_D64COMB08 COMBINED, 0, SHADE, ENVIRONMENT, 0, 0, 0, COMBINED +#define G_CC_D64COMB09 TEXEL0, 0, PRIM_LOD_FRAC, ENVIRONMENT, 0, 0, 0, 1 +#define G_CC_D64COMB10 TEXEL0, 0, PRIM_LOD_FRAC, ENVIRONMENT, 0, 0, 0, TEXEL0 + +#define G_CC_D64COMB11 PRIMITIVE, 0, TEXEL0, SHADE, 0, 0, 0, 0 +#define G_CC_D64COMB12 COMBINED, 0, PRIM_LOD_FRAC, ENVIRONMENT, 0, 0, 0, 0 + +#define G_CC_D64COMB13 TEXEL0, 0, SHADE, 0, 0, 0, 0, 0 +#define G_CC_D64COMB14 COMBINED, 0, PRIM_LOD_FRAC, ENVIRONMENT, 0, 0, 0, 0 + +#define G_CC_D64COMB15 1, 0, SHADE, 0, 0, 0, 0, 1 +#define G_CC_D64COMB16 0, 0, 0, COMBINED, 0, 0, 0, COMBINED + +#define G_CC_D64COMB17 1, 0, PRIM_LOD_FRAC, TEXEL0, TEXEL0, 0, PRIMITIVE, 0 +#define G_CC_D64COMB18 COMBINED, 0, PRIMITIVE, ENVIRONMENT, 0, 0, 0, COMBINED + +#define G_CC_D64COMB19 1, 0, TEXEL0, PRIMITIVE, 0, 0, 0, PRIMITIVE + +/* DOOM 64 CUSTOM RENDER MODES */ +#define RM_XLU_SURF_CLAMP(clk) \ + IM_RD | CVG_DST_CLAMP | FORCE_BL | ZMODE_OPA | \ + GBL_c##clk(G_BL_CLR_IN, G_BL_A_IN, G_BL_CLR_MEM, G_BL_1MA) + +#define G_RM_XLU_SURF_CLAMP RM_XLU_SURF_CLAMP(1) +#define G_RM_XLU_SURF2_CLAMP RM_XLU_SURF_CLAMP(2) + + +#define gDPSetPrimColorD64(pkt, m, l, rgba) \ +{ \ + Gfx *_g = (Gfx *)(pkt); \ + \ + _g->words.w0 = (_SHIFTL(G_SETPRIMCOLOR, 24, 8) | \ + _SHIFTL(m, 8, 8) | _SHIFTL(l, 0, 8)); \ + _g->words.w1 = (unsigned int)(rgba); \ +} + +#define gDPSetEnvColorD64(pkt, rgba) \ + gDPSetColor(pkt, G_SETENVCOLOR, rgba) + +#define gDPSetFogColorD64(pkt, rgba) \ + gDPSetColor(pkt, G_SETFOGCOLOR, rgba) + +#define PACKRGBA(r,g,b,a) (((r)<<24)|((g)<<16)|((b)<<8)|(a)) + +/* +U_JPAD 0x08000000 +L_JPAD 0x02000000 +R_JPAD 0x01000000 +D_JPAD 0x04000000 + +C_UP 0x00080000 +C_LEFT 0x00020000 +C_RIGHT 0x00040000 +C_DOWN 0x00010000 + +START_BUTTON 0x10000000 +A_BUTTON 0x80000000 +B_BUTTON 0x40000000 + +L_TRIG 0x00200000 +R_TRIG 0x00100000 +Z_TRIG 0x20000000 + +A_UP 0x53 MAX +A_LEFT 0xAD00 MAX +A_RIGHT 0x5300 MAX +A_DOWN 0xAD MAX + +#define CONT_A 0x8000 // 1 +#define CONT_B 0x4000 // 2 +#define CONT_G 0x2000 // 4 +#define CONT_START 0x1000 // 8 +#define CONT_UP 0x0800 // 16 +#define CONT_DOWN 0x0400 // 32 +#define CONT_LEFT 0x0200 // 64 +#define CONT_RIGHT 0x0100 // 128 +//0x0080 256 -> NO_USED +//0x0040 512 -> NO_USED +#define CONT_L 0x0020 // 1024 +#define CONT_R 0x0010 // 2048 +#define CONT_E 0x0008 // 4096 +#define CONT_D 0x0004 // 8192 +#define CONT_C 0x0002 // 16384 +#define CONT_F 0x0001 // 32768 + +#define A_BUTTON CONT_A +#define B_BUTTON CONT_B +#define L_TRIG CONT_L +#define R_TRIG CONT_R +#define Z_TRIG CONT_G +#define START_BUTTON CONT_START +#define U_JPAD CONT_UP +#define L_JPAD CONT_LEFT +#define R_JPAD CONT_RIGHT +#define D_JPAD CONT_DOWN +#define U_CBUTTONS CONT_E +#define L_CBUTTONS CONT_C +#define R_CBUTTONS CONT_F +#define D_CBUTTONS CONT_D + +Swap Values +{ + R_JPAD 1 + L_JPAD 2 + D_JPAD 4 + U_JPAD 8 + + START_BUTTON 16 + Z_TRIG 32 + B_BUTTON 64 + A_BUTTON 128 + + R_CBUTTONS 256 + L_CBUTTONS 512 + D_CBUTTONS 1024 + U_CBUTTONS 2048 + + R_TRIG 4096 + L_TRIG 8192 + + Normal|Swap|Result + + 0x2f000000 (47) (Z_TRIG|U_JPAD|D_JPAD|L_JPAD|R_JPAD) + 0xe03f0000 (16352) (L_TRIG|R_TRIG|U_CBUTTONS|D_CBUTTONS|L_CBUTTONS|R_CBUTTONS|A_BUTTON|B_BUTTON|Z_TRIG) + 0xf0000 (3840) (U_CBUTTONS|D_CBUTTONS|L_CBUTTONS|R_CBUTTONS) + + 0xa000000 (10) (U_JPAD|L_JPAD) + 0x5000000 (5) (D_JPAD|R_JPAD) + + 0xef3f0000 (16367) (L_TRIG|R_TRIG|U_CBUTTONS|D_CBUTTONS|L_CBUTTONS|R_CBUTTONS|A_BUTTON|B_BUTTON|Z_TRIG|U_JPAD|D_JPAD|L_JPAD|R_JPAD) + + 0x30000 (768) (L_CBUTTONS|R_CBUTTONS) + + 0xef300000 (12527) (L_TRIG|R_TRIG|A_BUTTON|B_BUTTON|Z_TRIG|U_JPAD|D_JPAD|L_JPAD|R_JPAD) + + 0xe03d0000 (15840) (L_TRIG|R_TRIG|U_CBUTTONS|D_CBUTTONS|R_CBUTTONS|A_BUTTON|B_BUTTON|Z_TRIG) +} + +#define A_BUTTON CONT_A +#define B_BUTTON CONT_B +#define Z_TRIG CONT_G +#define START_BUTTON CONT_START +#define U_JPAD CONT_UP +#define D_JPAD CONT_DOWN +#define L_JPAD CONT_LEFT +#define R_JPAD CONT_RIGHT +#define L_TRIG CONT_L +#define R_TRIG CONT_R +#define U_CBUTTONS CONT_E +#define D_CBUTTONS CONT_D +#define L_CBUTTONS CONT_C +#define R_CBUTTONS CONT_F + +//((int)(buttons << 0) < 0) A_BUTTON || CONT_A +//((int)(buttons << 1) < 0) B_BUTTON || CONT_B +//((int)(buttons << 2) < 0) Z_TRIG || CONT_G +//((int)(buttons << 3) < 0) START_BUTTON || CONT_START +//((int)(buttons << 4) < 0) U_JPAD || CONT_UP +//((int)(buttons << 5) < 0) D_JPAD || CONT_DOWN +//((int)(buttons << 6) < 0) L_JPAD || CONT_LEFT +//((int)(buttons << 7) < 0) R_JPAD || CONT_RIGHT +//((int)(buttons << 8) < 0) NO_USED +//((int)(buttons << 9) < 0) NO_USED +//((int)(buttons << a) < 0) L_TRIG || CONT_L +//((int)(buttons << b) < 0) R_TRIG || CONT_R +//((int)(buttons << c) < 0) U_CBUTTONS || CONT_E +//((int)(buttons << d) < 0) D_CBUTTONS || CONT_D +//((int)(buttons << e) < 0) L_CBUTTONS || CONT_C +//((int)(buttons << f) < 0) R_CBUTTONS || CONT_F +*/ + +/* +(val << 0 < 0) 0x80000000 PAD_A +(val << 1 < 0) 0x40000000 PAD_B +(val << 2 < 0) 0x20000000 PAD_Z_TRIG +(val << 3 < 0) 0x10000000 PAD_START +(val << 4 < 0) 0x08000000 PAD_UP +(val << 5 < 0) 0x04000000 PAD_DOWN +(val << 6 < 0) 0x02000000 PAD_LEFT +(val << 7 < 0) 0x01000000 PAD_RIGHT +(val << 8 < 0) 0x00800000 NO_USED +(val << 9 < 0) 0x00400000 NO_USED +(val << a < 0) 0x00200000 PAD_L_TRIG +(val << b < 0) 0x00100000 PAD_R_TRIG +(val << c < 0) 0x00080000 PAD_UP_C +(val << d < 0) 0x00040000 PAD_DOWN_C +(val << e < 0) 0x00020000 PAD_LEFT_C +(val << f < 0) 0x00010000 PAD_RIGHT_C +*/ + +/* CONTROL PAD */ +#define PAD_RIGHT 0x01000000 +#define PAD_LEFT 0x02000000 +#define PAD_DOWN 0x04000000 +#define PAD_UP 0x08000000 +#define PAD_START 0x10000000 +#define PAD_Z_TRIG 0x20000000 +#define PAD_B 0x40000000 +#define PAD_A 0x80000000 +#define PAD_RIGHT_C 0x00010000 +#define PAD_LEFT_C 0x00020000 +#define PAD_DOWN_C 0x00040000 +#define PAD_UP_C 0x00080000 +#define PAD_R_TRIG 0x00100000 + +#define PAD_L_TRIG 0x00200000 + +#define ALL_JPAD (PAD_UP|PAD_DOWN|PAD_LEFT|PAD_RIGHT) +#define ALL_CBUTTONS (PAD_UP_C|PAD_DOWN_C|PAD_LEFT_C|PAD_RIGHT_C) +#define ALL_BUTTONS (PAD_L_TRIG|PAD_R_TRIG|PAD_UP_C|PAD_DOWN_C|PAD_LEFT_C|PAD_RIGHT_C|PAD_A|PAD_B|PAD_Z_TRIG) +#define ALL_TRIG (PAD_L_TRIG|PAD_R_TRIG|PAD_Z_TRIG) + +typedef struct +{ + unsigned int BT_RIGHT; + unsigned int BT_LEFT; + unsigned int BT_FORWARD; + unsigned int BT_BACK; + unsigned int BT_ATTACK; + unsigned int BT_USE; + unsigned int BT_MAP; + unsigned int BT_SPEED; + unsigned int BT_STRAFE; + unsigned int BT_STRAFELEFT; + unsigned int BT_STRAFERIGHT; + unsigned int BT_WEAPONBACKWARD; + unsigned int BT_WEAPONFORWARD; +} buttons_t; + +extern buttons_t *BT_DATA[MAXPLAYERS]; // 800A559C + +typedef struct +{ + short compressed; + short numpal; + short width; + short height; +} gfxN64_t; + +typedef struct +{ + short id; + short numpal; + short wshift; + short hshift; +} textureN64_t; + +typedef struct +{ + unsigned short tiles; // 0 + short compressed; // 2 + unsigned short cmpsize; // 4 + short xoffs; // 6 + short yoffs; // 8 + unsigned short width; // 10 + unsigned short height; // 12 + unsigned short tileheight; // 14 +} spriteN64_t; diff --git a/Doom 64/doominfo.c b/Doom 64/doominfo.c @@ -0,0 +1,4437 @@ +#include "doomdef.h" +/* generated by multigen */ + +char *sprnames[NUMSPRITES] = { // 8005EE30 +"SPOT", "PLAY", "SARG", "FATT", "POSS", "TROO", "HEAD", "BOSS", +"SKUL", "BSPI", "CYBR", "PAIN", "RECT", "MISL", "PLSS", "BFS1", +"LASS", "BAL1", "BAL3", "BAL2", "BAL7", "BAL8", "APLS", "MANF", +"TRCR", "DART", "FIRE", "RBAL", "PUF2", "PUF3", "PUFF", "BLUD", +"A027", "TFOG", "BFE2", "ARM1", "ARM2", "BON1", "BON2", "BKEY", +"RKEY", "YKEY", "YSKU", "RSKU", "BSKU", "ART1", "ART2", "ART3", +"STIM", "MEDI", "SOUL", "PINV", "PSTR", "PINS", "SUIT", "PMAP", +"PVIS", "MEGA", "CLIP", "AMMO", "RCKT", "BROK", "CELL", "CELP", +"SHEL", "SBOX", "BPAK", "BFUG", "CSAW", "MGUN", "LAUN", "PLSM", +"SHOT", "SGN2", "LSRG", "CAND", "BAR1", "LMP1", "LMP2", "A031", +"A030", "A032", "A033", "A034", "BFLM", "RFLM", "YFLM", "A006", +"A021", "A003", "A020", "A014", "A016", "A008", "A007", "A015", +"A001", "A012", "A010", "A018", "A017", "A026", "A022", "A028", +"A029", "A035", "A036", "TRE3", "TRE2", "TRE1", "A013", "A019", +"A004", "A005", "A023", "SAWG", "PUNG", "PISG", "SHT1", "SHT2", +"CHGG", "ROCK", "PLAS", "BFGG", "LASR" +}; + +void A_WeaponReady(); +void A_ChainSawReady(); +void A_Lower(); +void A_Raise(); +void A_Punch(); +void A_ReFire(); +void A_FirePistol(); +void A_FireShotgun(); +void A_FireShotgun2(); +void A_CheckReload(); +void A_LoadShotgun2(); +void A_CloseShotgun2(); +void A_FireCGun(); +void A_GunFlash(); +void A_FireMissile(); +void A_Saw(); +void A_FirePlasma(); +void A_PlasmaAnimate(); +void A_BFGsound(); +void A_FireBFG(); +void A_BFGSpray(); +void A_BFGFlash(); +void A_FireLaser(); + +void A_Explode(); +void A_Pain(); +void A_PlayerScream(); +void A_Fall(); +void A_XScream(); +void A_Look(); +void A_Chase(); +void A_FaceTarget(); +void A_PosAttack(); +void A_Scream(); +void A_SPosAttack(); +void A_Tracer(); +void A_FatRaise(); +void A_FatAttack1(); +void A_FatAttack2(); +void A_FatAttack3(); +void A_TroopAttack(); +void A_TroopMelee(); +void A_SargAttack(); +void A_HeadAttack(); +void A_BruisAttack(); +void A_SkullAttack(); +void A_Metal(); +void A_SpidRefire(); +void A_BabyMetal(); +void A_BspiAttack(); +void A_Hoof(); +void A_CyberAttack(); +void A_PainAttack(); +void A_PainDie(); +void A_SpawnSmoke(); +void A_FadeAlpha(); +void A_OnDeathTrigger(); +void A_BarrelExplode(); +void A_TargetCamera(); +void A_BspiFaceTarget(); +void A_PlayAttack(); +void A_RectChase(); +void A_RectMissile(); +void A_RectGroundFire(); +void A_MoveGroundFire(); +void A_RectTracer(); +void A_PainDeathEvent(); +void A_CyberDeathEvent(); +void A_RectDeathEvent(); +void A_FadeOut(); +void A_FadeIn(); +void A_SkullSetAlpha(); +void A_MissileSetAlpha(); + +state_t states[NUMSTATES] = // 8004D3F4 +{ +{ SPR_SPOT,0,-1,NULL,S_000 }, /*S_000*/ + { SPR_PLAY,0,-1,NULL,S_000 }, /*S_001*/ + { SPR_PLAY,0,4,NULL,S_003 }, /*S_002*/ + { SPR_PLAY,1,4,NULL,S_004 }, /*S_003*/ + { SPR_PLAY,2,4,NULL,S_005 }, /*S_004*/ + { SPR_PLAY,3,4,NULL,S_002 }, /*S_005*/ + { SPR_PLAY,4,12,NULL,S_007 }, /*S_006*/ + { SPR_PLAY,32773,6,NULL,S_001 }, /*S_007*/ + { SPR_PLAY,6,4,NULL,S_009 }, /*S_008*/ + { SPR_PLAY,6,4,A_Pain,S_001 }, /*S_009*/ + { SPR_PLAY,7,10,NULL,S_011 }, /*S_010*/ + { SPR_PLAY,8,10,A_Scream,S_012 }, /*S_011*/ + { SPR_PLAY,9,10,A_Fall,S_013 }, /*S_012*/ + { SPR_PLAY,10,10,NULL,S_014 }, /*S_013*/ + { SPR_PLAY,11,10,NULL,S_015 }, /*S_014*/ + { SPR_PLAY,12,-1,NULL,S_000 }, /*S_015*/ + { SPR_PLAY,13,5,NULL,S_017 }, /*S_016*/ + { SPR_PLAY,14,5,A_XScream,S_018 }, /*S_017*/ + { SPR_PLAY,15,5,A_Fall,S_019 }, /*S_018*/ + { SPR_PLAY,16,5,NULL,S_020 }, /*S_019*/ + { SPR_PLAY,17,5,NULL,S_021 }, /*S_020*/ + { SPR_PLAY,18,5,NULL,S_022 }, /*S_021*/ + { SPR_PLAY,19,5,NULL,S_023 }, /*S_022*/ + { SPR_PLAY,20,5,NULL,S_024 }, /*S_023*/ + { SPR_PLAY,21,-1,NULL,S_000 }, /*S_024*/ + { SPR_PLAY,4,10,A_Look,S_025 }, /*S_025*/ + { SPR_PLAY,0,4,A_Chase,S_027 }, /*S_026*/ + { SPR_PLAY,1,4,A_Chase,S_028 }, /*S_027*/ + { SPR_PLAY,2,4,A_Chase,S_029 }, /*S_028*/ + { SPR_PLAY,3,4,A_Chase,S_026 }, /*S_029*/ + { SPR_PLAY,4,4,A_PosAttack,S_031 }, /*S_030*/ + { SPR_PLAY,32773,4,A_PosAttack,S_032 }, /*S_031*/ + { SPR_PLAY,4,4,A_PosAttack,S_033 }, /*S_032*/ + { SPR_PLAY,32773,4,A_PosAttack,S_034 }, /*S_033*/ + { SPR_PLAY,4,4,A_PosAttack,S_035 }, /*S_034*/ + { SPR_PLAY,32773,4,A_PosAttack,S_026 }, /*S_035*/ + { SPR_PLAY,6,4,NULL,S_037 }, /*S_036*/ + { SPR_PLAY,6,4,A_Pain,S_026 }, /*S_037*/ + { SPR_PLAY,4,4,A_PlayAttack,S_039 }, /*S_038*/ + { SPR_PLAY,32773,4,A_PlayAttack,S_040 }, /*S_039*/ + { SPR_PLAY,4,4,A_PlayAttack,S_041 }, /*S_040*/ + { SPR_PLAY,32773,4,A_PlayAttack,S_042 }, /*S_041*/ + { SPR_PLAY,4,4,A_PlayAttack,S_043 }, /*S_042*/ + { SPR_PLAY,32773,4,A_PlayAttack,S_026 }, /*S_043*/ + { SPR_SARG,1,8,A_Look,S_045 }, /*S_044*/ + { SPR_SARG,3,8,A_Look,S_044 }, /*S_045*/ + { SPR_SARG,0,2,A_Chase,S_047 }, /*S_046*/ + { SPR_SARG,0,2,A_Chase,S_048 }, /*S_047*/ + { SPR_SARG,1,2,A_Chase,S_049 }, /*S_048*/ + { SPR_SARG,1,2,A_Chase,S_050 }, /*S_049*/ + { SPR_SARG,2,2,A_Chase,S_051 }, /*S_050*/ + { SPR_SARG,2,2,A_Chase,S_052 }, /*S_051*/ + { SPR_SARG,3,2,A_Chase,S_053 }, /*S_052*/ + { SPR_SARG,3,2,A_Chase,S_046 }, /*S_053*/ + { SPR_SARG,4,8,A_FaceTarget,S_055 }, /*S_054*/ + { SPR_SARG,5,8,A_FaceTarget,S_056 }, /*S_055*/ + { SPR_SARG,6,8,A_SargAttack,S_046 }, /*S_056*/ + { SPR_SARG,7,2,NULL,S_058 }, /*S_057*/ + { SPR_SARG,7,2,A_Pain,S_046 }, /*S_058*/ + { SPR_SARG,8,8,NULL,S_060 }, /*S_059*/ + { SPR_SARG,9,8,A_Scream,S_061 }, /*S_060*/ + { SPR_SARG,10,4,NULL,S_062 }, /*S_061*/ + { SPR_SARG,11,4,A_Fall,S_063 }, /*S_062*/ + { SPR_SARG,12,4,A_OnDeathTrigger,S_064 }, /*S_063*/ + { SPR_SARG,13,-1,NULL,S_000 }, /*S_064*/ + { SPR_SARG,0,1,A_FadeOut,S_046 }, /*S_065*/ + { SPR_SARG,4,1,A_FadeOut,S_054 }, /*S_066*/ + { SPR_SARG,7,1,A_FadeOut,S_057 }, /*S_067*/ + { SPR_SARG,8,1,A_FadeIn,S_059 }, /*S_068*/ + { SPR_FATT,0,15,A_Look,S_070 }, /*S_069*/ + { SPR_FATT,1,15,A_Look,S_069 }, /*S_070*/ + { SPR_FATT,0,4,A_Chase,S_072 }, /*S_071*/ + { SPR_FATT,0,4,A_Chase,S_073 }, /*S_072*/ + { SPR_FATT,1,4,A_Chase,S_074 }, /*S_073*/ + { SPR_FATT,1,4,A_Chase,S_075 }, /*S_074*/ + { SPR_FATT,2,4,A_Chase,S_076 }, /*S_075*/ + { SPR_FATT,2,4,A_Chase,S_077 }, /*S_076*/ + { SPR_FATT,3,4,A_Chase,S_078 }, /*S_077*/ + { SPR_FATT,3,4,A_Chase,S_079 }, /*S_078*/ + { SPR_FATT,4,4,A_Chase,S_080 }, /*S_079*/ + { SPR_FATT,4,4,A_Chase,S_081 }, /*S_080*/ + { SPR_FATT,5,4,A_Chase,S_082 }, /*S_081*/ + { SPR_FATT,5,4,A_Chase,S_071 }, /*S_082*/ + { SPR_FATT,7,20,A_FatRaise,S_084 }, /*S_083*/ + { SPR_FATT,32774,10,A_FatAttack1,S_085 }, /*S_084*/ + { SPR_FATT,7,10,A_FaceTarget,S_086 }, /*S_085*/ + { SPR_FATT,32774,10,A_FatAttack2,S_087 }, /*S_086*/ + { SPR_FATT,7,10,A_FaceTarget,S_088 }, /*S_087*/ + { SPR_FATT,32774,10,A_FatAttack3,S_089 }, /*S_088*/ + { SPR_FATT,7,10,A_FaceTarget,S_071 }, /*S_089*/ + { SPR_FATT,8,3,NULL,S_091 }, /*S_090*/ + { SPR_FATT,8,3,A_Pain,S_071 }, /*S_091*/ + { SPR_FATT,9,6,NULL,S_093 }, /*S_092*/ + { SPR_FATT,10,6,A_Scream,S_094 }, /*S_093*/ + { SPR_FATT,11,6,A_Fall,S_095 }, /*S_094*/ + { SPR_FATT,12,6,NULL,S_096 }, /*S_095*/ + { SPR_FATT,13,6,A_OnDeathTrigger,S_097 }, /*S_096*/ + { SPR_FATT,14,-1,NULL,S_000 }, /*S_097*/ + { SPR_POSS,0,10,A_Look,S_099 }, /*S_098*/ + { SPR_POSS,1,10,A_Look,S_098 }, /*S_099*/ + { SPR_POSS,0,4,A_Chase,S_101 }, /*S_100*/ + { SPR_POSS,0,4,A_Chase,S_102 }, /*S_101*/ + { SPR_POSS,1,4,A_Chase,S_103 }, /*S_102*/ + { SPR_POSS,1,4,A_Chase,S_104 }, /*S_103*/ + { SPR_POSS,2,4,A_Chase,S_105 }, /*S_104*/ + { SPR_POSS,2,4,A_Chase,S_106 }, /*S_105*/ + { SPR_POSS,3,4,A_Chase,S_107 }, /*S_106*/ + { SPR_POSS,3,4,A_Chase,S_100 }, /*S_107*/ + { SPR_POSS,4,10,A_FaceTarget,S_109 }, /*S_108*/ + { SPR_POSS,5,8,A_PosAttack,S_110 }, /*S_109*/ + { SPR_POSS,4,8,NULL,S_100 }, /*S_110*/ + { SPR_POSS,6,3,NULL,S_112 }, /*S_111*/ + { SPR_POSS,6,3,A_Pain,S_100 }, /*S_112*/ + { SPR_POSS,7,5,NULL,S_114 }, /*S_113*/ + { SPR_POSS,8,5,A_Scream,S_115 }, /*S_114*/ + { SPR_POSS,9,5,A_Fall,S_116 }, /*S_115*/ + { SPR_POSS,10,5,A_OnDeathTrigger,S_117 }, /*S_116*/ + { SPR_POSS,11,-1,NULL,S_000 }, /*S_117*/ + { SPR_POSS,12,5,NULL,S_119 }, /*S_118*/ + { SPR_POSS,13,5,A_XScream,S_120 }, /*S_119*/ + { SPR_POSS,14,5,A_Fall,S_121 }, /*S_120*/ + { SPR_POSS,15,5,NULL,S_122 }, /*S_121*/ + { SPR_POSS,16,5,NULL,S_123 }, /*S_122*/ + { SPR_POSS,17,5,NULL,S_124 }, /*S_123*/ + { SPR_POSS,18,5,NULL,S_125 }, /*S_124*/ + { SPR_POSS,19,5,A_OnDeathTrigger,S_126 }, /*S_125*/ + { SPR_POSS,20,-1,NULL,S_000 }, /*S_126*/ + { SPR_POSS,0,10,A_Look,S_128 }, /*S_127*/ + { SPR_POSS,1,10,A_Look,S_127 }, /*S_128*/ + { SPR_POSS,0,3,A_Chase,S_130 }, /*S_129*/ + { SPR_POSS,0,3,A_Chase,S_131 }, /*S_130*/ + { SPR_POSS,1,3,A_Chase,S_132 }, /*S_131*/ + { SPR_POSS,1,3,A_Chase,S_133 }, /*S_132*/ + { SPR_POSS,2,3,A_Chase,S_134 }, /*S_133*/ + { SPR_POSS,2,3,A_Chase,S_135 }, /*S_134*/ + { SPR_POSS,3,3,A_Chase,S_136 }, /*S_135*/ + { SPR_POSS,3,3,A_Chase,S_129 }, /*S_136*/ + { SPR_POSS,4,10,A_FaceTarget,S_138 }, /*S_137*/ + { SPR_POSS,5,10,A_SPosAttack,S_139 }, /*S_138*/ + { SPR_POSS,4,10,NULL,S_129 }, /*S_139*/ + { SPR_POSS,6,3,NULL,S_141 }, /*S_140*/ + { SPR_POSS,6,3,A_Pain,S_129 }, /*S_141*/ + { SPR_POSS,7,5,NULL,S_143 }, /*S_142*/ + { SPR_POSS,8,5,A_Scream,S_144 }, /*S_143*/ + { SPR_POSS,9,5,A_Fall,S_145 }, /*S_144*/ + { SPR_POSS,10,5,A_OnDeathTrigger,S_146 }, /*S_145*/ + { SPR_POSS,11,-1,NULL,S_000 }, /*S_146*/ + { SPR_POSS,12,5,NULL,S_148 }, /*S_147*/ + { SPR_POSS,13,5,A_XScream,S_149 }, /*S_148*/ + { SPR_POSS,14,5,A_Fall,S_150 }, /*S_149*/ + { SPR_POSS,15,5,NULL,S_151 }, /*S_150*/ + { SPR_POSS,16,5,NULL,S_152 }, /*S_151*/ + { SPR_POSS,17,5,NULL,S_153 }, /*S_152*/ + { SPR_POSS,18,5,NULL,S_154 }, /*S_153*/ + { SPR_POSS,19,5,A_OnDeathTrigger,S_155 }, /*S_154*/ + { SPR_POSS,20,-1,NULL,S_000 }, /*S_155*/ + { SPR_TROO,0,10,A_Look,S_157 }, /*S_156*/ + { SPR_TROO,1,10,A_Look,S_156 }, /*S_157*/ + { SPR_TROO,0,3,A_Chase,S_159 }, /*S_158*/ + { SPR_TROO,0,3,A_Chase,S_160 }, /*S_159*/ + { SPR_TROO,1,3,A_Chase,S_161 }, /*S_160*/ + { SPR_TROO,1,3,A_Chase,S_162 }, /*S_161*/ + { SPR_TROO,2,3,A_Chase,S_163 }, /*S_162*/ + { SPR_TROO,2,3,A_Chase,S_164 }, /*S_163*/ + { SPR_TROO,3,3,A_Chase,S_165 }, /*S_164*/ + { SPR_TROO,3,3,A_Chase,S_158 }, /*S_165*/ + { SPR_TROO,4,8,A_FaceTarget,S_167 }, /*S_166*/ + { SPR_TROO,5,8,A_FaceTarget,S_168 }, /*S_167*/ + { SPR_TROO,6,6,A_TroopMelee,S_158 }, /*S_168*/ + { SPR_TROO,8,8,A_FaceTarget,S_170 }, /*S_169*/ + { SPR_TROO,9,8,A_FaceTarget,S_171 }, /*S_170*/ + { SPR_TROO,10,6,A_TroopAttack,S_158 }, /*S_171*/ + { SPR_TROO,7,2,NULL,S_173 }, /*S_172*/ + { SPR_TROO,7,2,A_Pain,S_158 }, /*S_173*/ + { SPR_TROO,11,8,NULL,S_175 }, /*S_174*/ + { SPR_TROO,12,8,A_Scream,S_176 }, /*S_175*/ + { SPR_TROO,13,6,A_Fall,S_177 }, /*S_176*/ + { SPR_TROO,14,6,A_OnDeathTrigger,S_178 }, /*S_177*/ + { SPR_TROO,15,-1,NULL,S_000 }, /*S_178*/ + { SPR_TROO,16,5,NULL,S_180 }, /*S_179*/ + { SPR_TROO,17,5,A_XScream,S_181 }, /*S_180*/ + { SPR_TROO,18,5,NULL,S_182 }, /*S_181*/ + { SPR_TROO,19,5,A_Fall,S_183 }, /*S_182*/ + { SPR_TROO,20,5,NULL,S_184 }, /*S_183*/ + { SPR_TROO,21,5,NULL,S_185 }, /*S_184*/ + { SPR_TROO,22,5,A_OnDeathTrigger,S_186 }, /*S_185*/ + { SPR_TROO,23,-1,NULL,S_000 }, /*S_186*/ + { SPR_HEAD,0,15,A_Look,S_188 }, /*S_187*/ + { SPR_HEAD,1,15,A_Look,S_189 }, /*S_188*/ + { SPR_HEAD,2,15,A_Look,S_190 }, /*S_189*/ + { SPR_HEAD,3,15,A_Look,S_187 }, /*S_190*/ + { SPR_HEAD,0,3,A_Chase,S_192 }, /*S_191*/ + { SPR_HEAD,0,3,A_Chase,S_193 }, /*S_192*/ + { SPR_HEAD,1,3,A_Chase,S_194 }, /*S_193*/ + { SPR_HEAD,1,3,A_Chase,S_195 }, /*S_194*/ + { SPR_HEAD,2,3,A_Chase,S_196 }, /*S_195*/ + { SPR_HEAD,2,3,A_Chase,S_197 }, /*S_196*/ + { SPR_HEAD,3,3,A_Chase,S_198 }, /*S_197*/ + { SPR_HEAD,3,3,A_Chase,S_191 }, /*S_198*/ + { SPR_HEAD,4,5,A_FaceTarget,S_200 }, /*S_199*/ + { SPR_HEAD,5,5,A_FaceTarget,S_201 }, /*S_200*/ + { SPR_HEAD,6,5,A_FaceTarget,S_202 }, /*S_201*/ + { SPR_HEAD,6,0,A_HeadAttack,S_191 }, /*S_202*/ + { SPR_HEAD,1,3,NULL,S_204 }, /*S_203*/ + { SPR_HEAD,1,3,A_Pain,S_205 }, /*S_204*/ + { SPR_HEAD,1,6,NULL,S_191 }, /*S_205*/ + { SPR_HEAD,7,8,NULL,S_207 }, /*S_206*/ + { SPR_HEAD,8,8,A_Scream,S_208 }, /*S_207*/ + { SPR_HEAD,9,8,NULL,S_209 }, /*S_208*/ + { SPR_HEAD,10,8,A_Fall,S_210 }, /*S_209*/ + { SPR_HEAD,11,8,A_OnDeathTrigger,S_211 }, /*S_210*/ + { SPR_HEAD,12,-1,NULL,S_000 }, /*S_211*/ + { SPR_BOSS,0,10,A_Look,S_213 }, /*S_212*/ + { SPR_BOSS,1,10,A_Look,S_212 }, /*S_213*/ + { SPR_BOSS,0,3,A_Chase,S_215 }, /*S_214*/ + { SPR_BOSS,0,3,A_Chase,S_216 }, /*S_215*/ + { SPR_BOSS,1,3,A_Chase,S_217 }, /*S_216*/ + { SPR_BOSS,1,3,A_Chase,S_218 }, /*S_217*/ + { SPR_BOSS,2,3,A_Chase,S_219 }, /*S_218*/ + { SPR_BOSS,2,3,A_Chase,S_220 }, /*S_219*/ + { SPR_BOSS,3,3,A_Chase,S_221 }, /*S_220*/ + { SPR_BOSS,3,3,A_Chase,S_214 }, /*S_221*/ + { SPR_BOSS,4,8,A_FaceTarget,S_223 }, /*S_222*/ + { SPR_BOSS,5,8,A_FaceTarget,S_224 }, /*S_223*/ + { SPR_BOSS,6,8,A_BruisAttack,S_214 }, /*S_224*/ + { SPR_BOSS,7,2,NULL,S_226 }, /*S_225*/ + { SPR_BOSS,7,2,A_Pain,S_214 }, /*S_226*/ + { SPR_BOSS,8,8,NULL,S_228 }, /*S_227*/ + { SPR_BOSS,9,8,A_Scream,S_229 }, /*S_228*/ + { SPR_BOSS,10,8,NULL,S_230 }, /*S_229*/ + { SPR_BOSS,11,8,A_Fall,S_231 }, /*S_230*/ + { SPR_BOSS,12,8,A_OnDeathTrigger,S_232 }, /*S_231*/ + { SPR_BOSS,13,-1,NULL,S_000 }, /*S_232*/ + { SPR_BOSS,0,10,A_Look,S_234 }, /*S_233*/ + { SPR_BOSS,1,10,A_Look,S_233 }, /*S_234*/ + { SPR_BOSS,0,3,A_Chase,S_236 }, /*S_235*/ + { SPR_BOSS,0,3,A_Chase,S_237 }, /*S_236*/ + { SPR_BOSS,1,3,A_Chase,S_238 }, /*S_237*/ + { SPR_BOSS,1,3,A_Chase,S_239 }, /*S_238*/ + { SPR_BOSS,2,3,A_Chase,S_240 }, /*S_239*/ + { SPR_BOSS,2,3,A_Chase,S_241 }, /*S_240*/ + { SPR_BOSS,3,3,A_Chase,S_242 }, /*S_241*/ + { SPR_BOSS,3,3,A_Chase,S_235 }, /*S_242*/ + { SPR_BOSS,4,8,A_FaceTarget,S_244 }, /*S_243*/ + { SPR_BOSS,5,8,A_FaceTarget,S_245 }, /*S_244*/ + { SPR_BOSS,6,8,A_BruisAttack,S_235 }, /*S_245*/ + { SPR_BOSS,7,2,NULL,S_247 }, /*S_246*/ + { SPR_BOSS,7,2,A_Pain,S_235 }, /*S_247*/ + { SPR_BOSS,8,8,NULL,S_249 }, /*S_248*/ + { SPR_BOSS,9,8,A_Scream,S_250 }, /*S_249*/ + { SPR_BOSS,10,8,NULL,S_251 }, /*S_250*/ + { SPR_BOSS,11,8,A_Fall,S_252 }, /*S_251*/ + { SPR_BOSS,12,8,A_OnDeathTrigger,S_253 }, /*S_252*/ + { SPR_BOSS,13,-1,NULL,S_000 }, /*S_253*/ + { SPR_SKUL,0,5,A_Look,S_255 }, /*S_254*/ + { SPR_SKUL,1,5,A_Look,S_256 }, /*S_255*/ + { SPR_SKUL,2,5,A_Look,S_254 }, /*S_256*/ + { SPR_SKUL,0,3,A_Chase,S_258 }, /*S_257*/ + { SPR_SKUL,1,3,A_Chase,S_259 }, /*S_258*/ + { SPR_SKUL,2,3,A_Chase,S_257 }, /*S_259*/ + { SPR_SKUL,3,6,A_FaceTarget,S_261 }, /*S_260*/ + { SPR_SKUL,4,4,A_SkullAttack,S_262 }, /*S_261*/ + { SPR_SKUL,3,4,NULL,S_263 }, /*S_262*/ + { SPR_SKUL,4,4,NULL,S_262 }, /*S_263*/ + { SPR_SKUL,5,3,NULL,S_265 }, /*S_264*/ + { SPR_SKUL,5,3,A_Pain,S_257 }, /*S_265*/ + { SPR_SKUL,32774,5,NULL,S_267 }, /*S_266*/ + { SPR_SKUL,32775,5,A_Scream,S_268 }, /*S_267*/ + { SPR_SKUL,32776,5,A_Fall,S_269 }, /*S_268*/ + { SPR_SKUL,32777,5,A_OnDeathTrigger,S_270 }, /*S_269*/ + { SPR_SKUL,32778,4,A_SkullSetAlpha,S_271 }, /*S_270*/ + { SPR_SKUL,32779,3,NULL,S_272 }, /*S_271*/ + { SPR_SKUL,32780,2,NULL,S_273 }, /*S_272*/ + { SPR_SKUL,32781,2,NULL,S_274 }, /*S_273*/ + { SPR_SKUL,32782,1,NULL,S_275 }, /*S_274*/ + { SPR_SKUL,32783,1,NULL,S_000 }, /*S_275*/ + { SPR_BSPI,0,10,A_Look,S_277 }, /*S_276*/ + { SPR_BSPI,1,10,A_Look,S_276 }, /*S_277*/ + { SPR_BSPI,0,20,NULL,S_279 }, /*S_278*/ + { SPR_BSPI,0,3,A_BabyMetal,S_280 }, /*S_279*/ + { SPR_BSPI,0,3,A_Chase,S_281 }, /*S_280*/ + { SPR_BSPI,1,3,A_Chase,S_282 }, /*S_281*/ + { SPR_BSPI,1,3,A_Chase,S_283 }, /*S_282*/ + { SPR_BSPI,2,3,A_Chase,S_284 }, /*S_283*/ + { SPR_BSPI,2,3,A_Chase,S_285 }, /*S_284*/ + { SPR_BSPI,3,3,A_Chase,S_286 }, /*S_285*/ + { SPR_BSPI,3,3,A_Chase,S_279 }, /*S_286*/ + { SPR_BSPI,0,15,A_BspiFaceTarget,S_288 }, /*S_287*/ + { SPR_BSPI,32772,6,A_BspiAttack,S_289 }, /*S_288*/ + { SPR_BSPI,32772,1,A_SpidRefire,S_288 }, /*S_289*/ + { SPR_BSPI,5,3,NULL,S_291 }, /*S_290*/ + { SPR_BSPI,5,3,A_Pain,S_279 }, /*S_291*/ + { SPR_BSPI,6,20,A_Scream,S_293 }, /*S_292*/ + { SPR_BSPI,7,7,A_Fall,S_294 }, /*S_293*/ + { SPR_BSPI,8,7,NULL,S_295 }, /*S_294*/ + { SPR_BSPI,9,7,NULL,S_296 }, /*S_295*/ + { SPR_BSPI,10,7,A_OnDeathTrigger,S_297 }, /*S_296*/ + { SPR_BSPI,11,-1,NULL,S_000 }, /*S_297*/ + { SPR_CYBR,5,10,A_Look,S_298 }, /*S_298*/ + { SPR_CYBR,0,4,A_Hoof,S_300 }, /*S_299*/ + { SPR_CYBR,0,4,A_Chase,S_301 }, /*S_300*/ + { SPR_CYBR,1,4,A_Chase,S_302 }, /*S_301*/ + { SPR_CYBR,1,4,A_Chase,S_303 }, /*S_302*/ + { SPR_CYBR,2,4,A_Chase,S_304 }, /*S_303*/ + { SPR_CYBR,2,4,A_Chase,S_305 }, /*S_304*/ + { SPR_CYBR,3,4,A_Metal,S_306 }, /*S_305*/ + { SPR_CYBR,3,4,A_Chase,S_299 }, /*S_306*/ + { SPR_CYBR,32772,6,A_FaceTarget,S_308 }, /*S_307*/ + { SPR_CYBR,5,12,A_CyberAttack,S_309 }, /*S_308*/ + { SPR_CYBR,32772,12,A_FaceTarget,S_310 }, /*S_309*/ + { SPR_CYBR,5,12,A_CyberAttack,S_311 }, /*S_310*/ + { SPR_CYBR,32772,12,A_FaceTarget,S_312 }, /*S_311*/ + { SPR_CYBR,5,12,A_CyberAttack,S_299 }, /*S_312*/ + { SPR_CYBR,5,10,A_Pain,S_299 }, /*S_313*/ + { SPR_CYBR,6,30,A_CyberDeathEvent,S_315 }, /*S_314*/ + { SPR_CYBR,7,8,NULL,S_316 }, /*S_315*/ + { SPR_CYBR,8,7,NULL,S_317 }, /*S_316*/ + { SPR_CYBR,9,6,NULL,S_318 }, /*S_317*/ + { SPR_CYBR,10,5,NULL,S_319 }, /*S_318*/ + { SPR_CYBR,11,4,A_Fall,S_320 }, /*S_319*/ + { SPR_CYBR,12,4,NULL,S_321 }, /*S_320*/ + { SPR_CYBR,13,4,A_OnDeathTrigger,S_322 }, /*S_321*/ + { SPR_CYBR,14,-1,NULL,S_000 }, /*S_322*/ + { SPR_CYBR,5,1,A_TargetCamera,S_323 }, /*S_323*/ + { SPR_CYBR,32772,18,A_CyberAttack,S_325 }, /*S_324*/ + { SPR_CYBR,5,18,A_FaceTarget,S_324 }, /*S_325*/ + { SPR_PAIN,0,5,A_Look,S_326 }, /*S_326*/ + { SPR_PAIN,0,3,A_Chase,S_327 }, /*S_327*/ + { SPR_PAIN,32769,5,A_FaceTarget,S_329 }, /*S_328*/ + { SPR_PAIN,32769,5,A_FaceTarget,S_330 }, /*S_329*/ + { SPR_PAIN,32770,5,A_FaceTarget,S_331 }, /*S_330*/ + { SPR_PAIN,32770,0,A_PainAttack,S_327 }, /*S_331*/ + { SPR_PAIN,3,6,NULL,S_333 }, /*S_332*/ + { SPR_PAIN,3,6,A_Pain,S_327 }, /*S_333*/ + { SPR_PAIN,32772,8,NULL,S_335 }, /*S_334*/ + { SPR_PAIN,32773,8,A_Scream,S_336 }, /*S_335*/ + { SPR_PAIN,32774,8,A_PainDie,S_337 }, /*S_336*/ + { SPR_PAIN,32775,8,A_PainDeathEvent,S_338 }, /*S_337*/ + { SPR_PAIN,32776,5,A_PainDeathEvent,S_339 }, /*S_338*/ + { SPR_PAIN,32777,5,A_PainDeathEvent,S_340 }, /*S_339*/ + { SPR_PAIN,32778,5,NULL,S_341 }, /*S_340*/ + { SPR_PAIN,32779,5,NULL,S_000 }, /*S_341*/ + { SPR_RECT,0,8,A_Look,S_343 }, /*S_342*/ + { SPR_RECT,1,8,A_Look,S_344 }, /*S_343*/ + { SPR_RECT,2,8,A_Look,S_345 }, /*S_344*/ + { SPR_RECT,3,8,A_Look,S_342 }, /*S_345*/ + { SPR_RECT,0,3,A_RectChase,S_347 }, /*S_346*/ + { SPR_RECT,0,3,A_RectChase,S_348 }, /*S_347*/ + { SPR_RECT,0,3,A_RectChase,S_349 }, /*S_348*/ + { SPR_RECT,1,3,A_RectChase,S_350 }, /*S_349*/ + { SPR_RECT,1,3,A_RectChase,S_351 }, /*S_350*/ + { SPR_RECT,1,3,A_RectChase,S_352 }, /*S_351*/ + { SPR_RECT,2,3,A_RectChase,S_353 }, /*S_352*/ + { SPR_RECT,2,3,A_RectChase,S_354 }, /*S_353*/ + { SPR_RECT,2,3,A_RectChase,S_355 }, /*S_354*/ + { SPR_RECT,3,3,A_RectChase,S_356 }, /*S_355*/ + { SPR_RECT,3,3,A_RectChase,S_357 }, /*S_356*/ + { SPR_RECT,3,3,A_RectChase,S_346 }, /*S_357*/ + { SPR_RECT,32774,12,A_RectGroundFire,S_359 }, /*S_358*/ + { SPR_RECT,4,12,NULL,S_360 }, /*S_359*/ + { SPR_RECT,32773,12,A_RectMissile,S_361 }, /*S_360*/ + { SPR_RECT,4,8,NULL,S_346 }, /*S_361*/ + { SPR_RECT,7,18,A_Pain,S_358 }, /*S_362*/ + { SPR_RECT,8,60,A_RectDeathEvent,S_364 }, /*S_363*/ + { SPR_RECT,9,8,NULL,S_365 }, /*S_364*/ + { SPR_RECT,10,8,NULL,S_366 }, /*S_365*/ + { SPR_RECT,11,5,NULL,S_367 }, /*S_366*/ + { SPR_RECT,12,4,NULL,S_368 }, /*S_367*/ + { SPR_RECT,13,3,A_OnDeathTrigger,S_369 }, /*S_368*/ + { SPR_RECT,14,2,NULL,S_000 }, /*S_369*/ + { SPR_SPOT,32768,-1,NULL,S_000 }, /*S_370*/ + { SPR_MISL,32768,2,A_SpawnSmoke,S_371 }, /*S_371*/ + { SPR_MISL,32769,3,A_Explode,S_373 }, /*S_372*/ + { SPR_MISL,32769,3,A_FadeAlpha,S_374 }, /*S_373*/ + { SPR_MISL,32770,3,A_FadeAlpha,S_375 }, /*S_374*/ + { SPR_MISL,32770,3,A_FadeAlpha,S_376 }, /*S_375*/ + { SPR_MISL,32771,2,A_FadeAlpha,S_377 }, /*S_376*/ + { SPR_MISL,32772,2,NULL,S_378 }, /*S_377*/ + { SPR_MISL,32773,2,NULL,S_000 }, /*S_378*/ + { SPR_PLSS,32768,3,NULL,S_380 }, /*S_379*/ + { SPR_PLSS,32769,3,NULL,S_379 }, /*S_380*/ + { SPR_PLSS,32770,2,A_FadeAlpha,S_382 }, /*S_381*/ + { SPR_PLSS,32771,2,NULL,S_383 }, /*S_382*/ + { SPR_PLSS,32772,2,NULL,S_384 }, /*S_383*/ + { SPR_PLSS,32773,2,NULL,S_385 }, /*S_384*/ + { SPR_PLSS,32774,2,NULL,S_386 }, /*S_385*/ + { SPR_PLSS,32775,2,NULL,S_000 }, /*S_386*/ + { SPR_BFS1,32768,2,NULL,S_388 }, /*S_387*/ + { SPR_BFS1,32769,2,NULL,S_387 }, /*S_388*/ + { SPR_BFS1,32770,8,A_BFGFlash,S_390 }, /*S_389*/ + { SPR_BFS1,32771,6,A_FadeAlpha,S_391 }, /*S_390*/ + { SPR_BFS1,32772,3,A_BFGSpray,S_392 }, /*S_391*/ + { SPR_BFS1,32773,3,A_FadeAlpha,S_393 }, /*S_392*/ + { SPR_BFS1,32774,2,NULL,S_394 }, /*S_393*/ + { SPR_BFS1,32775,2,NULL,S_000 }, /*S_394*/ + { SPR_LASS,32768,3,NULL,S_396 }, /*S_395*/ + { SPR_LASS,32769,3,NULL,S_395 }, /*S_396*/ + { SPR_BAL1,32768,4,NULL,S_398 }, /*S_397*/ + { SPR_BAL1,32769,4,NULL,S_399 }, /*S_398*/ + { SPR_BAL1,32770,4,NULL,S_397 }, /*S_399*/ + { SPR_BAL1,32771,1,NULL,S_401 }, /*S_400*/ + { SPR_BAL1,32772,1,NULL,S_402 }, /*S_401*/ + { SPR_BAL1,32773,1,NULL,S_403 }, /*S_402*/ + { SPR_BAL1,32774,1,NULL,S_404 }, /*S_403*/ + { SPR_BAL1,32775,1,NULL,S_405 }, /*S_404*/ + { SPR_BAL1,32776,1,NULL,S_000 }, /*S_405*/ + { SPR_BAL3,32768,4,NULL,S_407 }, /*S_406*/ + { SPR_BAL3,32769,4,NULL,S_408 }, /*S_407*/ + { SPR_BAL3,32770,4,NULL,S_406 }, /*S_408*/ + { SPR_BAL3,32771,2,NULL,S_410 }, /*S_409*/ + { SPR_BAL3,32772,2,NULL,S_411 }, /*S_410*/ + { SPR_BAL3,32773,2,NULL,S_412 }, /*S_411*/ + { SPR_BAL3,32774,2,NULL,S_413 }, /*S_412*/ + { SPR_BAL3,32775,2,NULL,S_414 }, /*S_413*/ + { SPR_BAL3,32776,2,NULL,S_000 }, /*S_414*/ + { SPR_BAL2,32768,4,NULL,S_416 }, /*S_415*/ + { SPR_BAL2,32769,4,NULL,S_417 }, /*S_416*/ + { SPR_BAL2,32770,4,NULL,S_415 }, /*S_417*/ + { SPR_BAL2,32771,6,A_MissileSetAlpha,S_419 }, /*S_418*/ + { SPR_BAL2,32772,5,NULL,S_420 }, /*S_419*/ + { SPR_BAL2,32773,2,NULL,S_421 }, /*S_420*/ + { SPR_BAL2,32774,2,NULL,S_422 }, /*S_421*/ + { SPR_BAL2,32775,2,NULL,S_000 }, /*S_422*/ + { SPR_BAL7,32768,4,NULL,S_424 }, /*S_423*/ + { SPR_BAL7,32769,4,NULL,S_423 }, /*S_424*/ + { SPR_BAL7,32770,3,NULL,S_426 }, /*S_425*/ + { SPR_BAL7,32771,3,A_FadeAlpha,S_427 }, /*S_426*/ + { SPR_BAL7,32772,3,A_FadeAlpha,S_428 }, /*S_427*/ + { SPR_BAL7,32773,2,NULL,S_429 }, /*S_428*/ + { SPR_BAL7,32774,2,NULL,S_430 }, /*S_429*/ + { SPR_BAL7,32775,2,NULL,S_000 }, /*S_430*/ + { SPR_BAL8,32768,4,NULL,S_432 }, /*S_431*/ + { SPR_BAL8,32769,4,NULL,S_431 }, /*S_432*/ + { SPR_BAL8,32770,3,NULL,S_434 }, /*S_433*/ + { SPR_BAL8,32771,3,A_FadeAlpha,S_435 }, /*S_434*/ + { SPR_BAL8,32772,3,A_FadeAlpha,S_436 }, /*S_435*/ + { SPR_BAL8,32773,2,NULL,S_437 }, /*S_436*/ + { SPR_BAL8,32774,2,NULL,S_438 }, /*S_437*/ + { SPR_BAL8,32775,2,NULL,S_000 }, /*S_438*/ + { SPR_APLS,32768,2,NULL,S_440 }, /*S_439*/ + { SPR_APLS,32769,2,NULL,S_439 }, /*S_440*/ + { SPR_APLS,32770,3,NULL,S_442 }, /*S_441*/ + { SPR_APLS,32771,3,NULL,S_443 }, /*S_442*/ + { SPR_APLS,32772,3,NULL,S_444 }, /*S_443*/ + { SPR_APLS,32773,3,NULL,S_445 }, /*S_444*/ + { SPR_APLS,32774,3,NULL,S_446 }, /*S_445*/ + { SPR_APLS,32775,3,NULL,S_000 }, /*S_446*/ + { SPR_MANF,32768,2,NULL,S_448 }, /*S_447*/ + { SPR_MANF,32769,2,NULL,S_449 }, /*S_448*/ + { SPR_MANF,32770,2,NULL,S_447 }, /*S_449*/ + { SPR_MANF,32771,6,NULL,S_451 }, /*S_450*/ + { SPR_MANF,32772,4,A_FadeAlpha,S_452 }, /*S_451*/ + { SPR_MANF,32773,3,A_FadeAlpha,S_453 }, /*S_452*/ + { SPR_MANF,32774,2,A_FadeAlpha,S_454 }, /*S_453*/ + { SPR_MANF,32775,2,NULL,S_455 }, /*S_454*/ + { SPR_MANF,32776,2,NULL,S_000 }, /*S_455*/ + { SPR_TRCR,32768,3,A_Tracer,S_457 }, /*S_456*/ + { SPR_TRCR,32769,3,A_Tracer,S_456 }, /*S_457*/ + { SPR_TRCR,32770,4,A_FadeAlpha,S_459 }, /*S_458*/ + { SPR_TRCR,32771,3,A_FadeAlpha,S_460 }, /*S_459*/ + { SPR_TRCR,32772,2,A_FadeAlpha,S_461 }, /*S_460*/ + { SPR_TRCR,32773,2,A_FadeAlpha,S_462 }, /*S_461*/ + { SPR_TRCR,32774,2,NULL,S_463 }, /*S_462*/ + { SPR_TRCR,32775,2,NULL,S_464 }, /*S_463*/ + { SPR_TRCR,32776,2,NULL,S_000 }, /*S_464*/ + { SPR_DART,32768,-1,NULL,S_000 }, /*S_465*/ + { SPR_FIRE,32768,3,A_MoveGroundFire,S_467 }, /*S_466*/ + { SPR_FIRE,32769,3,A_MoveGroundFire,S_468 }, /*S_467*/ + { SPR_FIRE,32770,3,A_MoveGroundFire,S_469 }, /*S_468*/ + { SPR_FIRE,32771,3,A_MoveGroundFire,S_466 }, /*S_469*/ + { SPR_RBAL,0,2,A_RectTracer,S_471 }, /*S_470*/ + { SPR_RBAL,1,2,A_RectTracer,S_470 }, /*S_471*/ + { SPR_RBAL,32770,4,NULL,S_473 }, /*S_472*/ + { SPR_RBAL,32771,3,A_MissileSetAlpha,S_474 }, /*S_473*/ + { SPR_RBAL,32772,2,NULL,S_475 }, /*S_474*/ + { SPR_RBAL,32773,2,NULL,S_476 }, /*S_475*/ + { SPR_RBAL,32774,2,NULL,S_477 }, /*S_476*/ + { SPR_RBAL,32775,2,NULL,S_000 }, /*S_477*/ + { SPR_PUF2,32768,2,NULL,S_479 }, /*S_478*/ + { SPR_PUF2,32769,2,NULL,S_480 }, /*S_479*/ + { SPR_PUF2,32770,2,NULL,S_481 }, /*S_480*/ + { SPR_PUF2,32771,2,NULL,S_482 }, /*S_481*/ + { SPR_PUF2,32772,2,NULL,S_000 }, /*S_482*/ + { SPR_PUF3,32768,2,NULL,S_484 }, /*S_483*/ + { SPR_PUF3,32769,2,NULL,S_485 }, /*S_484*/ + { SPR_PUF3,32770,2,NULL,S_486 }, /*S_485*/ + { SPR_PUF3,32771,2,NULL,S_487 }, /*S_486*/ + { SPR_PUF3,32772,2,NULL,S_000 }, /*S_487*/ + { SPR_PUFF,32768,4,NULL,S_489 }, /*S_488*/ + { SPR_PUFF,32769,3,NULL,S_490 }, /*S_489*/ + { SPR_PUFF,2,3,NULL,S_491 }, /*S_490*/ + { SPR_PUFF,3,3,NULL,S_492 }, /*S_491*/ + { SPR_PUFF,4,3,NULL,S_493 }, /*S_492*/ + { SPR_PUFF,5,3,NULL,S_000 }, /*S_493*/ + { SPR_BLUD,0,6,NULL,S_495 }, /*S_494*/ + { SPR_BLUD,1,6,NULL,S_496 }, /*S_495*/ + { SPR_BLUD,2,6,NULL,S_497 }, /*S_496*/ + { SPR_BLUD,3,6,NULL,S_000 }, /*S_497*/ + { SPR_A027,0,-1,NULL,S_000 }, /*S_498*/ + { SPR_TFOG,32772,3,NULL,S_500 }, /*S_499*/ + { SPR_TFOG,32771,3,NULL,S_501 }, /*S_500*/ + { SPR_TFOG,32770,3,NULL,S_502 }, /*S_501*/ + { SPR_TFOG,32769,3,NULL,S_503 }, /*S_502*/ + { SPR_TFOG,32768,3,NULL,S_504 }, /*S_503*/ + { SPR_TFOG,32769,3,NULL,S_505 }, /*S_504*/ + { SPR_TFOG,32770,3,NULL,S_506 }, /*S_505*/ + { SPR_TFOG,32771,3,NULL,S_507 }, /*S_506*/ + { SPR_TFOG,32772,3,NULL,S_508 }, /*S_507*/ + { SPR_TFOG,32773,3,NULL,S_509 }, /*S_508*/ + { SPR_TFOG,32774,3,NULL,S_510 }, /*S_509*/ + { SPR_TFOG,32775,3,NULL,S_000 }, /*S_510*/ + { SPR_BFE2,32768,4,NULL,S_512 }, /*S_511*/ + { SPR_BFE2,32769,3,A_FadeAlpha,S_513 }, /*S_512*/ + { SPR_BFE2,32770,2,NULL,S_514 }, /*S_513*/ + { SPR_BFE2,32771,2,NULL,S_515 }, /*S_514*/ + { SPR_BFE2,32772,2,NULL,S_516 }, /*S_515*/ + { SPR_BFE2,32773,2,NULL,S_000 }, /*S_516*/ + { SPR_ARM1,32768,6,NULL,S_518 }, /*S_517*/ + { SPR_ARM1,32769,6,NULL,S_517 }, /*S_518*/ + { SPR_ARM2,32768,6,NULL,S_520 }, /*S_519*/ + { SPR_ARM2,32769,6,NULL,S_519 }, /*S_520*/ + { SPR_BON1,0,3,NULL,S_522 }, /*S_521*/ + { SPR_BON1,1,3,NULL,S_523 }, /*S_522*/ + { SPR_BON1,2,3,NULL,S_524 }, /*S_523*/ + { SPR_BON1,3,3,NULL,S_521 }, /*S_524*/ + { SPR_BON2,0,3,NULL,S_526 }, /*S_525*/ + { SPR_BON2,1,3,NULL,S_527 }, /*S_526*/ + { SPR_BON2,2,3,NULL,S_528 }, /*S_527*/ + { SPR_BON2,3,3,NULL,S_529 }, /*S_528*/ + { SPR_BON2,2,3,NULL,S_530 }, /*S_529*/ + { SPR_BON2,1,3,NULL,S_525 }, /*S_530*/ + { SPR_BKEY,0,5,NULL,S_532 }, /*S_531*/ + { SPR_BKEY,32768,5,NULL,S_531 }, /*S_532*/ + { SPR_RKEY,0,5,NULL,S_534 }, /*S_533*/ + { SPR_RKEY,32768,5,NULL,S_533 }, /*S_534*/ + { SPR_YKEY,0,5,NULL,S_536 }, /*S_535*/ + { SPR_YKEY,32768,5,NULL,S_535 }, /*S_536*/ + { SPR_YSKU,0,5,NULL,S_538 }, /*S_537*/ + { SPR_YSKU,32768,5,NULL,S_537 }, /*S_538*/ + { SPR_RSKU,0,5,NULL,S_540 }, /*S_539*/ + { SPR_RSKU,32768,5,NULL,S_539 }, /*S_540*/ + { SPR_BSKU,0,5,NULL,S_542 }, /*S_541*/ + { SPR_BSKU,32768,5,NULL,S_541 }, /*S_542*/ + { SPR_ART1,32768,4,NULL,S_544 }, /*S_543*/ + { SPR_ART1,32769,4,NULL,S_545 }, /*S_544*/ + { SPR_ART1,32770,4,NULL,S_546 }, /*S_545*/ + { SPR_ART1,32771,4,NULL,S_547 }, /*S_546*/ + { SPR_ART1,32772,4,NULL,S_548 }, /*S_547*/ + { SPR_ART1,32771,4,NULL,S_549 }, /*S_548*/ + { SPR_ART1,32770,4,NULL,S_550 }, /*S_549*/ + { SPR_ART1,32769,4,NULL,S_543 }, /*S_550*/ + { SPR_ART2,32768,4,NULL,S_552 }, /*S_551*/ + { SPR_ART2,32769,4,NULL,S_553 }, /*S_552*/ + { SPR_ART2,32770,4,NULL,S_554 }, /*S_553*/ + { SPR_ART2,32771,4,NULL,S_555 }, /*S_554*/ + { SPR_ART2,32772,4,NULL,S_556 }, /*S_555*/ + { SPR_ART2,32771,4,NULL,S_557 }, /*S_556*/ + { SPR_ART2,32770,4,NULL,S_558 }, /*S_557*/ + { SPR_ART2,32769,4,NULL,S_551 }, /*S_558*/ + { SPR_ART3,32768,4,NULL,S_560 }, /*S_559*/ + { SPR_ART3,32769,4,NULL,S_561 }, /*S_560*/ + { SPR_ART3,32770,4,NULL,S_562 }, /*S_561*/ + { SPR_ART3,32771,4,NULL,S_563 }, /*S_562*/ + { SPR_ART3,32772,4,NULL,S_564 }, /*S_563*/ + { SPR_ART3,32771,4,NULL,S_565 }, /*S_564*/ + { SPR_ART3,32770,4,NULL,S_566 }, /*S_565*/ + { SPR_ART3,32769,4,NULL,S_559 }, /*S_566*/ + { SPR_STIM,0,-1,NULL,S_000 }, /*S_567*/ + { SPR_MEDI,0,-1,NULL,S_000 }, /*S_568*/ + { SPR_SOUL,32768,6,NULL,S_570 }, /*S_569*/ + { SPR_SOUL,32769,6,NULL,S_571 }, /*S_570*/ + { SPR_SOUL,32770,6,NULL,S_572 }, /*S_571*/ + { SPR_SOUL,32771,6,NULL,S_573 }, /*S_572*/ + { SPR_SOUL,32770,6,NULL,S_574 }, /*S_573*/ + { SPR_SOUL,32769,6,NULL,S_569 }, /*S_574*/ + { SPR_PINV,32768,6,NULL,S_576 }, /*S_575*/ + { SPR_PINV,32769,6,NULL,S_577 }, /*S_576*/ + { SPR_PINV,32770,6,NULL,S_578 }, /*S_577*/ + { SPR_PINV,32771,6,NULL,S_579 }, /*S_578*/ + { SPR_PINV,32770,6,NULL,S_580 }, /*S_579*/ + { SPR_PINV,32769,6,NULL,S_575 }, /*S_580*/ + { SPR_PSTR,32768,-1,NULL,S_000 }, /*S_581*/ + { SPR_PINS,32768,2,NULL,S_583 }, /*S_582*/ + { SPR_PINS,32769,3,NULL,S_584 }, /*S_583*/ + { SPR_PINS,32770,2,NULL,S_585 }, /*S_584*/ + { SPR_PINS,32771,1,NULL,S_586 }, /*S_585*/ + { SPR_PINS,32769,2,NULL,S_587 }, /*S_586*/ + { SPR_PINS,32770,1,NULL,S_582 }, /*S_587*/ + { SPR_SUIT,32768,4,NULL,S_589 }, /*S_588*/ + { SPR_SUIT,32769,4,NULL,S_588 }, /*S_589*/ + { SPR_PMAP,32768,5,NULL,S_591 }, /*S_590*/ + { SPR_PMAP,32769,5,NULL,S_592 }, /*S_591*/ + { SPR_PMAP,32770,5,NULL,S_593 }, /*S_592*/ + { SPR_PMAP,32771,5,NULL,S_590 }, /*S_593*/ + { SPR_PVIS,32768,3,NULL,S_595 }, /*S_594*/ + { SPR_PVIS,1,3,NULL,S_594 }, /*S_595*/ + { SPR_MEGA,32768,4,NULL,S_597 }, /*S_596*/ + { SPR_MEGA,32769,4,NULL,S_598 }, /*S_597*/ + { SPR_MEGA,32770,4,NULL,S_599 }, /*S_598*/ + { SPR_MEGA,32771,4,NULL,S_600 }, /*S_599*/ + { SPR_MEGA,32770,4,NULL,S_601 }, /*S_600*/ + { SPR_MEGA,32769,4,NULL,S_596 }, /*S_601*/ + { SPR_CLIP,0,-1,NULL,S_000 }, /*S_602*/ + { SPR_AMMO,0,-1,NULL,S_000 }, /*S_603*/ + { SPR_RCKT,0,-1,NULL,S_000 }, /*S_604*/ + { SPR_BROK,0,-1,NULL,S_000 }, /*S_605*/ + { SPR_CELL,0,-1,NULL,S_000 }, /*S_606*/ + { SPR_CELP,0,-1,NULL,S_000 }, /*S_607*/ + { SPR_SHEL,0,-1,NULL,S_000 }, /*S_608*/ + { SPR_SBOX,0,-1,NULL,S_000 }, /*S_609*/ + { SPR_BPAK,0,-1,NULL,S_000 }, /*S_610*/ + { SPR_BFUG,0,-1,NULL,S_000 }, /*S_611*/ + { SPR_CSAW,0,-1,NULL,S_000 }, /*S_612*/ + { SPR_MGUN,0,-1,NULL,S_000 }, /*S_613*/ + { SPR_LAUN,0,-1,NULL,S_000 }, /*S_614*/ + { SPR_PLSM,0,-1,NULL,S_000 }, /*S_615*/ + { SPR_SHOT,0,-1,NULL,S_000 }, /*S_616*/ + { SPR_SGN2,0,-1,NULL,S_000 }, /*S_617*/ + { SPR_LSRG,0,-1,NULL,S_000 }, /*S_618*/ + { SPR_FIRE,0,3,NULL,S_620 }, /*S_619*/ + { SPR_FIRE,1,3,NULL,S_621 }, /*S_620*/ + { SPR_FIRE,2,3,NULL,S_622 }, /*S_621*/ + { SPR_FIRE,3,3,NULL,S_623 }, /*S_622*/ + { SPR_FIRE,4,3,NULL,S_619 }, /*S_623*/ + { SPR_CAND,0,2,NULL,S_625 }, /*S_624*/ + { SPR_CAND,1,2,NULL,S_624 }, /*S_625*/ + { SPR_BAR1,0,-1,NULL,S_000 }, /*S_626*/ + { SPR_BAR1,1,5,NULL,S_628 }, /*S_627*/ + { SPR_BAR1,2,5,NULL,S_629 }, /*S_628*/ + { SPR_BAR1,3,5,NULL,S_630 }, /*S_629*/ + { SPR_BAR1,32772,5,A_BarrelExplode,S_000 }, /*S_630*/ + { SPR_MISL,32769,6,NULL,S_632 }, /*S_631*/ + { SPR_MISL,32770,5,NULL,S_633 }, /*S_632*/ + { SPR_MISL,32771,2,NULL,S_634 }, /*S_633*/ + { SPR_MISL,32772,2,NULL,S_635 }, /*S_634*/ + { SPR_MISL,32773,2,NULL,S_000 }, /*S_635*/ + { SPR_MISL,32769,2,NULL,S_637 }, /*S_636*/ + { SPR_MISL,32770,2,NULL,S_638 }, /*S_637*/ + { SPR_MISL,32771,2,NULL,S_639 }, /*S_638*/ + { SPR_MISL,32772,2,NULL,S_640 }, /*S_639*/ + { SPR_MISL,32773,2,NULL,S_000 }, /*S_640*/ + { SPR_LMP1,0,-1,NULL,S_000 }, /*S_641*/ + { SPR_LMP2,0,-1,NULL,S_000 }, /*S_642*/ + { SPR_A031,0,4,NULL,S_644 }, /*S_643*/ + { SPR_A031,1,4,NULL,S_645 }, /*S_644*/ + { SPR_A031,2,4,NULL,S_646 }, /*S_645*/ + { SPR_A031,3,4,NULL,S_647 }, /*S_646*/ + { SPR_A031,4,4,NULL,S_643 }, /*S_647*/ + { SPR_A030,0,4,NULL,S_649 }, /*S_648*/ + { SPR_A030,1,4,NULL,S_650 }, /*S_649*/ + { SPR_A030,2,4,NULL,S_651 }, /*S_650*/ + { SPR_A030,3,4,NULL,S_652 }, /*S_651*/ + { SPR_A030,4,4,NULL,S_648 }, /*S_652*/ + { SPR_A032,0,4,NULL,S_654 }, /*S_653*/ + { SPR_A032,1,4,NULL,S_655 }, /*S_654*/ + { SPR_A032,2,4,NULL,S_656 }, /*S_655*/ + { SPR_A032,3,4,NULL,S_657 }, /*S_656*/ + { SPR_A032,4,4,NULL,S_653 }, /*S_657*/ + { SPR_A033,0,-1,NULL,S_000 }, /*S_658*/ + { SPR_A034,0,-1,NULL,S_000 }, /*S_659*/ + { SPR_BFLM,32768,4,NULL,S_661 }, /*S_660*/ + { SPR_BFLM,32769,4,NULL,S_662 }, /*S_661*/ + { SPR_BFLM,32770,4,NULL,S_663 }, /*S_662*/ + { SPR_BFLM,32771,4,NULL,S_664 }, /*S_663*/ + { SPR_BFLM,32772,4,NULL,S_660 }, /*S_664*/ + { SPR_RFLM,32768,4,NULL,S_666 }, /*S_665*/ + { SPR_RFLM,32769,4,NULL,S_667 }, /*S_666*/ + { SPR_RFLM,32770,4,NULL,S_668 }, /*S_667*/ + { SPR_RFLM,32771,4,NULL,S_669 }, /*S_668*/ + { SPR_RFLM,32772,4,NULL,S_665 }, /*S_669*/ + { SPR_YFLM,32768,4,NULL,S_671 }, /*S_670*/ + { SPR_YFLM,32769,4,NULL,S_672 }, /*S_671*/ + { SPR_YFLM,32770,4,NULL,S_673 }, /*S_672*/ + { SPR_YFLM,32771,4,NULL,S_674 }, /*S_673*/ + { SPR_YFLM,32772,4,NULL,S_670 }, /*S_674*/ + { SPR_A006,0,-1,NULL,S_000 }, /*S_675*/ + { SPR_A021,0,-1,NULL,S_000 }, /*S_676*/ + { SPR_A003,0,-1,NULL,S_000 }, /*S_677*/ + { SPR_A020,0,-1,NULL,S_000 }, /*S_678*/ + { SPR_A014,0,6,NULL,S_680 }, /*S_679*/ + { SPR_A014,1,6,NULL,S_679 }, /*S_680*/ + { SPR_A016,0,-1,NULL,S_000 }, /*S_681*/ + { SPR_A027,0,-1,NULL,S_000 }, /*S_682*/ + { SPR_A008,0,-1,NULL,S_000 }, /*S_683*/ + { SPR_A007,0,-1,NULL,S_000 }, /*S_684*/ + { SPR_A015,0,-1,NULL,S_000 }, /*S_685*/ + { SPR_A001,0,-1,NULL,S_000 }, /*S_686*/ + { SPR_A012,0,-1,NULL,S_000 }, /*S_687*/ + { SPR_A010,0,-1,NULL,S_000 }, /*S_688*/ + { SPR_A018,0,-1,NULL,S_000 }, /*S_689*/ + { SPR_A017,0,-1,NULL,S_000 }, /*S_690*/ + { SPR_A026,0,-1,NULL,S_000 }, /*S_691*/ + { SPR_A022,0,-1,NULL,S_000 }, /*S_692*/ + { SPR_A028,0,-1,NULL,S_000 }, /*S_693*/ + { SPR_A029,0,-1,NULL,S_000 }, /*S_694*/ + { SPR_A035,0,-1,NULL,S_000 }, /*S_695*/ + { SPR_A036,0,-1,NULL,S_000 }, /*S_696*/ + { SPR_TRE3,0,-1,NULL,S_000 }, /*S_697*/ + { SPR_TRE2,0,-1,NULL,S_000 }, /*S_698*/ + { SPR_TRE1,0,-1,NULL,S_000 }, /*S_699*/ + { SPR_A013,0,-1,NULL,S_000 }, /*S_700*/ + { SPR_A019,0,-1,NULL,S_000 }, /*S_701*/ + { SPR_A004,0,-1,NULL,S_000 }, /*S_702*/ + { SPR_A005,0,-1,NULL,S_000 }, /*S_703*/ + { SPR_A023,0,-1,NULL,S_000 }, /*S_704*/ + { SPR_SAWG,0,4,A_ChainSawReady,S_706 }, /*S_705*/ + { SPR_SAWG,1,4,A_WeaponReady,S_705 }, /*S_706*/ + { SPR_SAWG,1,1,A_Lower,S_707 }, /*S_707*/ + { SPR_SAWG,1,1,A_Raise,S_708 }, /*S_708*/ + { SPR_SAWG,2,2,A_Saw,S_710 }, /*S_709*/ + { SPR_SAWG,3,2,A_Saw,S_711 }, /*S_710*/ + { SPR_SAWG,3,0,A_ReFire,S_705 }, /*S_711*/ + { SPR_PUNG,0,1,A_WeaponReady,S_712 }, /*S_712*/ + { SPR_PUNG,0,1,A_Lower,S_713 }, /*S_713*/ + { SPR_PUNG,0,1,A_Raise,S_714 }, /*S_714*/ + { SPR_PUNG,1,4,NULL,S_716 }, /*S_715*/ + { SPR_PUNG,2,4,A_Punch,S_717 }, /*S_716*/ + { SPR_PUNG,3,5,NULL,S_718 }, /*S_717*/ + { SPR_PUNG,2,4,NULL,S_719 }, /*S_718*/ + { SPR_PUNG,1,5,A_ReFire,S_712 }, /*S_719*/ + { SPR_PISG,0,1,A_WeaponReady,S_720 }, /*S_720*/ + { SPR_PISG,0,1,A_Lower,S_721 }, /*S_721*/ + { SPR_PISG,0,1,A_Raise,S_722 }, /*S_722*/ + { SPR_PISG,0,2,NULL,S_724 }, /*S_723*/ + { SPR_PISG,1,1,A_FirePistol,S_725 }, /*S_724*/ + { SPR_PISG,2,5,NULL,S_726 }, /*S_725*/ + { SPR_PISG,1,5,NULL,S_727 }, /*S_726*/ + { SPR_PISG,0,1,A_ReFire,S_720 }, /*S_727*/ + { SPR_PISG,32771,3,NULL,S_000 }, /*S_728*/ + { SPR_SHT1,0,1,A_WeaponReady,S_729 }, /*S_729*/ + { SPR_SHT1,0,1,A_Lower,S_730 }, /*S_730*/ + { SPR_SHT1,0,1,A_Raise,S_731 }, /*S_731*/ + { SPR_SHT1,0,2,NULL,S_733 }, /*S_732*/ + { SPR_SHT1,0,4,A_FireShotgun,S_734 }, /*S_733*/ + { SPR_SHT1,1,18,NULL,S_735 }, /*S_734*/ + { SPR_SHT1,2,5,NULL,S_736 }, /*S_735*/ + { SPR_SHT1,0,3,NULL,S_737 }, /*S_736*/ + { SPR_SHT1,0,7,A_ReFire,S_729 }, /*S_737*/ + { SPR_SHT1,32771,4,NULL,S_000 }, /*S_738*/ + { SPR_SHT2,0,1,A_WeaponReady,S_739 }, /*S_739*/ + { SPR_SHT2,0,1,A_Lower,S_740 }, /*S_740*/ + { SPR_SHT2,0,1,A_Raise,S_741 }, /*S_741*/ + { SPR_SHT2,0,1,NULL,S_743 }, /*S_742*/ + { SPR_SHT2,0,4,A_FireShotgun2,S_744 }, /*S_743*/ + { SPR_SHT2,1,7,NULL,S_745 }, /*S_744*/ + { SPR_SHT2,1,5,A_CheckReload,S_746 }, /*S_745*/ + { SPR_SHT2,1,5,NULL,S_747 }, /*S_746*/ + { SPR_SHT2,1,5,NULL,S_748 }, /*S_747*/ + { SPR_SHT2,1,5,NULL,S_749 }, /*S_748*/ + { SPR_SHT2,1,5,A_LoadShotgun2,S_750 }, /*S_749*/ + { SPR_SHT2,2,4,A_CloseShotgun2,S_751 }, /*S_750*/ + { SPR_SHT2,0,5,A_ReFire,S_739 }, /*S_751*/ + { SPR_SHT2,32771,4,NULL,S_000 }, /*S_752*/ + { SPR_CHGG,0,1,A_WeaponReady,S_753 }, /*S_753*/ + { SPR_CHGG,0,1,A_Lower,S_754 }, /*S_754*/ + { SPR_CHGG,0,1,A_Raise,S_755 }, /*S_755*/ + { SPR_CHGG,0,3,A_FireCGun,S_757 }, /*S_756*/ + { SPR_CHGG,1,3,A_FireCGun,S_758 }, /*S_757*/ + { SPR_CHGG,1,0,A_ReFire,S_753 }, /*S_758*/ + { SPR_CHGG,32771,3,NULL,S_000 }, /*S_759*/ + { SPR_CHGG,32770,3,NULL,S_000 }, /*S_760*/ + { SPR_ROCK,0,1,A_WeaponReady,S_761 }, /*S_761*/ + { SPR_ROCK,0,1,A_Lower,S_762 }, /*S_762*/ + { SPR_ROCK,0,1,A_Raise,S_763 }, /*S_763*/ + { SPR_ROCK,1,8,A_GunFlash,S_765 }, /*S_764*/ + { SPR_ROCK,1,10,A_FireMissile,S_766 }, /*S_765*/ + { SPR_ROCK,1,0,A_ReFire,S_761 }, /*S_766*/ + { SPR_ROCK,32770,3,NULL,S_768 }, /*S_767*/ + { SPR_ROCK,32771,4,NULL,S_769 }, /*S_768*/ + { SPR_ROCK,32772,4,NULL,S_770 }, /*S_769*/ + { SPR_ROCK,32773,4,NULL,S_000 }, /*S_770*/ + { SPR_PLAS,0,1,A_WeaponReady,S_771 }, /*S_771*/ + { SPR_PLAS,0,1,A_Lower,S_772 }, /*S_772*/ + { SPR_PLAS,0,0,A_PlasmaAnimate,S_774 }, /*S_773*/ + { SPR_PLAS,0,1,A_Raise,S_774 }, /*S_774*/ + { SPR_PLAS,32772,2,A_FirePlasma,S_776 }, /*S_775*/ + { SPR_PLAS,0,2,A_PlasmaAnimate,S_777 }, /*S_776*/ + { SPR_PLAS,0,1,A_ReFire,S_771 }, /*S_777*/ + { SPR_PLAS,1,2,NULL,S_779 }, /*S_778*/ + { SPR_PLAS,2,2,NULL,S_780 }, /*S_779*/ + { SPR_PLAS,3,2,NULL,S_778 }, /*S_780*/ + { SPR_BFGG,0,1,A_WeaponReady,S_781 }, /*S_781*/ + { SPR_BFGG,0,1,A_Lower,S_782 }, /*S_782*/ + { SPR_BFGG,0,1,A_Raise,S_783 }, /*S_783*/ + { SPR_BFGG,0,20,A_BFGsound,S_785 }, /*S_784*/ + { SPR_BFGG,1,10,A_GunFlash,S_786 }, /*S_785*/ + { SPR_BFGG,1,10,A_FireBFG,S_787 }, /*S_786*/ + { SPR_BFGG,1,20,A_ReFire,S_781 }, /*S_787*/ + { SPR_BFGG,32770,8,NULL,S_789 }, /*S_788*/ + { SPR_BFGG,32771,5,NULL,S_790 }, /*S_789*/ + { SPR_BFGG,32772,3,NULL,S_000 }, /*S_790*/ + { SPR_LASR,0,2,A_WeaponReady,S_791 }, /*S_791*/ + { SPR_LASR,0,1,A_Lower,S_792 }, /*S_792*/ + { SPR_LASR,0,1,A_Raise,S_793 }, /*S_793*/ + { SPR_LASR,0,8,A_FireLaser,S_795 }, /*S_794*/ + { SPR_LASR,0,3,A_ReFire,S_791 }, /*S_795*/ + { SPR_LASR,32769,3,NULL,S_000 } /*S_796*/ +}; + +mobjinfo_t mobjinfo[NUMMOBJTYPES] = // 80051238 +{ + { /* MT_PLAYER */ + -1, /* doomednum */ + S_001, /* spawnstate */ + 100, /* spawnhealth */ + S_002, /* seestate */ + sfx_None, /* seesound */ + 0, /* reactiontime */ + sfx_None, /* attacksound */ + S_008, /* painstate */ + 255, /* painchance */ + sfx_plrpain, /* painsound */ + S_000, /* meleestate */ + S_006, /* missilestate */ + S_010, /* deathstate */ + S_016, /* xdeathstate */ + sfx_plrdie, /* deathsound */ + 0, /* speed */ + 19*FRACUNIT, /* radius */ + 64*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SOLID|MF_SHOOTABLE|MF_GRAVITY|MF_DROPOFF|MF_PICKUP|MF_NOTDMATCH, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_PLAYERBOT1 */ + 3008, /* doomednum */ + S_025, /* spawnstate */ + 100, /* spawnhealth */ + S_026, /* seestate */ + sfx_None, /* seesound */ + 0, /* reactiontime */ + sfx_None, /* attacksound */ + S_036, /* painstate */ + 255, /* painchance */ + sfx_plrpain, /* painsound */ + S_000, /* meleestate */ + S_030, /* missilestate */ + S_016, /* deathstate */ + S_016, /* xdeathstate */ + sfx_plrdie, /* deathsound */ + 16, /* speed */ + 32*FRACUNIT, /* radius */ + 87*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SOLID|MF_SHOOTABLE|MF_GRAVITY|MF_DROPOFF|MF_COUNTKILL|MF_NOTDMATCH, /* flags */ + 1, /* palette */ + 255, /* alpha */ + }, + + { /* MT_PLAYERBOT2 */ + 3009, /* doomednum */ + S_025, /* spawnstate */ + 100, /* spawnhealth */ + S_026, /* seestate */ + sfx_None, /* seesound */ + 0, /* reactiontime */ + sfx_None, /* attacksound */ + S_036, /* painstate */ + 255, /* painchance */ + sfx_plrpain, /* painsound */ + S_000, /* meleestate */ + S_038, /* missilestate */ + S_010, /* deathstate */ + S_016, /* xdeathstate */ + sfx_plrdie, /* deathsound */ + 16, /* speed */ + 32*FRACUNIT, /* radius */ + 87*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SOLID|MF_SHOOTABLE|MF_GRAVITY|MF_DROPOFF|MF_COUNTKILL|MF_NOTDMATCH, /* flags */ + 2, /* palette */ + 255, /* alpha */ + }, + + { /* MT_PLAYERBOT3 */ + 3010, /* doomednum */ + S_025, /* spawnstate */ + 100, /* spawnhealth */ + S_026, /* seestate */ + sfx_None, /* seesound */ + 0, /* reactiontime */ + sfx_None, /* attacksound */ + S_036, /* painstate */ + 255, /* painchance */ + sfx_plrpain, /* painsound */ + S_000, /* meleestate */ + S_030, /* missilestate */ + S_016, /* deathstate */ + S_016, /* xdeathstate */ + sfx_plrdie, /* deathsound */ + 0, /* speed */ + 32*FRACUNIT, /* radius */ + 87*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SOLID|MF_SHOOTABLE|MF_GRAVITY|MF_DROPOFF|MF_COUNTKILL|MF_NOTDMATCH, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_DEMON1 */ + 3002, /* doomednum */ + S_044, /* spawnstate */ + 150, /* spawnhealth */ + S_046, /* seestate */ + sfx_sargsit, /* seesound */ + 8, /* reactiontime */ + sfx_sargatk, /* attacksound */ + S_057, /* painstate */ + 180, /* painchance */ + sfx_dbpain2, /* painsound */ + S_054, /* meleestate */ + S_000, /* missilestate */ + S_059, /* deathstate */ + S_000, /* xdeathstate */ + sfx_sargdie, /* deathsound */ + 12, /* speed */ + 44*FRACUNIT, /* radius */ + 100*FRACUNIT, /* height */ + 400, /* mass */ + 0, /* damage */ + sfx_dbact, /* activesound */ + MF_SOLID|MF_SHOOTABLE|MF_GRAVITY|MF_COUNTKILL, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_DEMON2 */ + 58, /* doomednum */ + S_044, /* spawnstate */ + 150, /* spawnhealth */ + S_065, /* seestate */ + sfx_sargsit, /* seesound */ + 8, /* reactiontime */ + sfx_sargatk, /* attacksound */ + S_067, /* painstate */ + 180, /* painchance */ + sfx_dbpain2, /* painsound */ + S_066, /* meleestate */ + S_000, /* missilestate */ + S_068, /* deathstate */ + S_000, /* xdeathstate */ + sfx_sargdie, /* deathsound */ + 12, /* speed */ + 50*FRACUNIT, /* radius */ + 100*FRACUNIT, /* height */ + 400, /* mass */ + 0, /* damage */ + sfx_dbact, /* activesound */ + MF_SOLID|MF_SHOOTABLE|MF_GRAVITY|MF_COUNTKILL, /* flags */ + 1, /* palette */ + 255, /* alpha */ + }, + + { /* MT_MANCUBUS */ + 67, /* doomednum */ + S_069, /* spawnstate */ + 600, /* spawnhealth */ + S_071, /* seestate */ + sfx_fattsit, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_090, /* painstate */ + 80, /* painchance */ + sfx_fatthit, /* painsound */ + S_000, /* meleestate */ + S_083, /* missilestate */ + S_092, /* deathstate */ + S_000, /* xdeathstate */ + sfx_fattdie, /* deathsound */ + 8, /* speed */ + 60*FRACUNIT, /* radius */ + 108*FRACUNIT, /* height */ + 1000, /* mass */ + 0, /* damage */ + sfx_posact, /* activesound */ + MF_SOLID|MF_SHOOTABLE|MF_GRAVITY|MF_COUNTKILL, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_POSSESSED1 */ + 3004, /* doomednum */ + S_098, /* spawnstate */ + 20, /* spawnhealth */ + S_100, /* seestate */ + sfx_possit1, /* seesound */ + 8, /* reactiontime */ + sfx_pistol, /* attacksound */ + S_111, /* painstate */ + 200, /* painchance */ + sfx_dbpain1, /* painsound */ + S_000, /* meleestate */ + S_108, /* missilestate */ + S_113, /* deathstate */ + S_118, /* xdeathstate */ + sfx_posdie1, /* deathsound */ + 8, /* speed */ + 32*FRACUNIT, /* radius */ + 87*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_posact, /* activesound */ + MF_SOLID|MF_SHOOTABLE|MF_GRAVITY|MF_COUNTKILL, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_POSSESSED2 */ + 9, /* doomednum */ + S_127, /* spawnstate */ + 30, /* spawnhealth */ + S_129, /* seestate */ + sfx_possit2, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_140, /* painstate */ + 170, /* painchance */ + sfx_dbpain1, /* painsound */ + S_000, /* meleestate */ + S_137, /* missilestate */ + S_142, /* deathstate */ + S_147, /* xdeathstate */ + sfx_posdie2, /* deathsound */ + 8, /* speed */ + 32*FRACUNIT, /* radius */ + 87*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_posact, /* activesound */ + MF_SOLID|MF_SHOOTABLE|MF_GRAVITY|MF_COUNTKILL, /* flags */ + 1, /* palette */ + 255, /* alpha */ + }, + + { /* MT_IMP1 */ + 3001, /* doomednum */ + S_156, /* spawnstate */ + 60, /* spawnhealth */ + S_158, /* seestate */ + sfx_impsit1, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_172, /* painstate */ + 200, /* painchance */ + sfx_dbpain1, /* painsound */ + S_166, /* meleestate */ + S_169, /* missilestate */ + S_174, /* deathstate */ + S_179, /* xdeathstate */ + sfx_impdth1, /* deathsound */ + 8, /* speed */ + 42*FRACUNIT, /* radius */ + 94*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_impact, /* activesound */ + MF_SOLID|MF_SHOOTABLE|MF_GRAVITY|MF_COUNTKILL, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_IMP2 */ + 3007, /* doomednum */ + S_156, /* spawnstate */ + 60, /* spawnhealth */ + S_158, /* seestate */ + sfx_impsit1, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_172, /* painstate */ + 128, /* painchance */ + sfx_dbpain1, /* painsound */ + S_166, /* meleestate */ + S_169, /* missilestate */ + S_174, /* deathstate */ + S_179, /* xdeathstate */ + sfx_impdth1, /* deathsound */ + 16, /* speed */ + 42*FRACUNIT, /* radius */ + 94*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_impact, /* activesound */ + MF_SOLID|MF_SHOOTABLE|MF_GRAVITY|MF_COUNTKILL|MF_SHADOW, /* flags */ + 1, /* palette */ + 180, /* alpha */ + }, + + { /* MT_CACODEMON */ + 3005, /* doomednum */ + S_187, /* spawnstate */ + 400, /* spawnhealth */ + S_191, /* seestate */ + sfx_headsit, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_203, /* painstate */ + 128, /* painchance */ + sfx_dbpain2, /* painsound */ + S_000, /* meleestate */ + S_199, /* missilestate */ + S_206, /* deathstate */ + S_000, /* xdeathstate */ + sfx_headdie, /* deathsound */ + 8, /* speed */ + 55*FRACUNIT, /* radius */ + 90*FRACUNIT, /* height */ + 400, /* mass */ + 0, /* damage */ + sfx_dbact, /* activesound */ + MF_SOLID|MF_SHOOTABLE|MF_FLOAT|MF_COUNTKILL, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_BRUISER1 */ + 3003, /* doomednum */ + S_212, /* spawnstate */ + 1000, /* spawnhealth */ + S_214, /* seestate */ + sfx_bos1sit, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_225, /* painstate */ + 50, /* painchance */ + sfx_dbpain2, /* painsound */ + S_222, /* meleestate */ + S_222, /* missilestate */ + S_227, /* deathstate */ + S_000, /* xdeathstate */ + sfx_bos1die, /* deathsound */ + 8, /* speed */ + 24*FRACUNIT, /* radius */ + 100*FRACUNIT, /* height */ + 1000, /* mass */ + 0, /* damage */ + sfx_dbact, /* activesound */ + MF_SOLID|MF_SHOOTABLE|MF_GRAVITY|MF_COUNTKILL, /* flags */ + 1, /* palette */ + 255, /* alpha */ + }, + + { /* MT_BRUISER2 */ + 69, /* doomednum */ + S_233, /* spawnstate */ + 500, /* spawnhealth */ + S_235, /* seestate */ + sfx_bos2sit, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_246, /* painstate */ + 50, /* painchance */ + sfx_dbpain2, /* painsound */ + S_243, /* meleestate */ + S_243, /* missilestate */ + S_248, /* deathstate */ + S_000, /* xdeathstate */ + sfx_bos2die, /* deathsound */ + 8, /* speed */ + 24*FRACUNIT, /* radius */ + 100*FRACUNIT, /* height */ + 1000, /* mass */ + 0, /* damage */ + sfx_dbact, /* activesound */ + MF_SOLID|MF_SHOOTABLE|MF_GRAVITY|MF_COUNTKILL, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_SKULL */ + 3006, /* doomednum */ + S_254, /* spawnstate */ + 60, /* spawnhealth */ + S_257, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_skullatk, /* attacksound */ + S_264, /* painstate */ + 256, /* painchance */ + sfx_dbpain2, /* painsound */ + S_000, /* meleestate */ + S_260, /* missilestate */ + S_266, /* deathstate */ + S_000, /* xdeathstate */ + sfx_implod, /* deathsound */ + 8, /* speed */ + 28*FRACUNIT, /* radius */ + 64*FRACUNIT, /* height */ + 50, /* mass */ + 3, /* damage */ + sfx_dbact, /* activesound */ + MF_SOLID|MF_SHOOTABLE|MF_FLOAT|MF_COUNTKILL, /* flags */ + 0, /* palette */ + 192, /* alpha */ + }, + + { /* MT_BABY */ + 68, /* doomednum */ + S_276, /* spawnstate */ + 500, /* spawnhealth */ + S_278, /* seestate */ + sfx_bspisit, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_290, /* painstate */ + 128, /* painchance */ + sfx_dbpain2, /* painsound */ + S_000, /* meleestate */ + S_287, /* missilestate */ + S_292, /* deathstate */ + S_000, /* xdeathstate */ + sfx_bspidie, /* deathsound */ + 12, /* speed */ + 64*FRACUNIT, /* radius */ + 80*FRACUNIT, /* height */ + 600, /* mass */ + 0, /* damage */ + sfx_bspilift, /* activesound */ + MF_SOLID|MF_SHOOTABLE|MF_GRAVITY|MF_COUNTKILL, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_CYBORG */ + 16, /* doomednum */ + S_298, /* spawnstate */ + 4000, /* spawnhealth */ + S_299, /* seestate */ + sfx_cybsit, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_313, /* painstate */ + 20, /* painchance */ + sfx_dbpain2, /* painsound */ + S_000, /* meleestate */ + S_307, /* missilestate */ + S_314, /* deathstate */ + S_000, /* xdeathstate */ + sfx_cybdth, /* deathsound */ + 16, /* speed */ + 70*FRACUNIT, /* radius */ + 170*FRACUNIT, /* height */ + 1000, /* mass */ + 0, /* damage */ + sfx_dbact, /* activesound */ + MF_SOLID|MF_SHOOTABLE|MF_GRAVITY|MF_COUNTKILL, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_CYBORG_TITLE */ + 3014, /* doomednum */ + S_323, /* spawnstate */ + 4000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_324, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 40*FRACUNIT, /* radius */ + 110*FRACUNIT, /* height */ + 1000, /* mass */ + 0, /* damage */ + sfx_dbact, /* activesound */ + MF_SOLID|MF_SHOOTABLE|MF_GRAVITY|MF_COUNTKILL, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_PAIN */ + 71, /* doomednum */ + S_326, /* spawnstate */ + 400, /* spawnhealth */ + S_327, /* seestate */ + sfx_pesit, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_332, /* painstate */ + 128, /* painchance */ + sfx_pepain, /* painsound */ + S_000, /* meleestate */ + S_328, /* missilestate */ + S_334, /* deathstate */ + S_000, /* xdeathstate */ + sfx_pedie, /* deathsound */ + 8, /* speed */ + 60*FRACUNIT, /* radius */ + 112*FRACUNIT, /* height */ + 400, /* mass */ + 0, /* damage */ + sfx_dbact, /* activesound */ + MF_SOLID|MF_SHOOTABLE|MF_FLOAT|MF_COUNTKILL, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_RESURRECTOR */ + 3013, /* doomednum */ + S_342, /* spawnstate */ + 5000, /* spawnhealth */ + S_346, /* seestate */ + sfx_rectsit, /* seesound */ + 8, /* reactiontime */ + sfx_rectatk, /* attacksound */ + S_362, /* painstate */ + 50, /* painchance */ + sfx_rectpain, /* painsound */ + S_358, /* meleestate */ + S_000, /* missilestate */ + S_363, /* deathstate */ + S_000, /* xdeathstate */ + sfx_rectdie, /* deathsound */ + 30, /* speed */ + 80*FRACUNIT, /* radius */ + 150*FRACUNIT, /* height */ + 1000, /* mass */ + 0, /* damage */ + sfx_rectact, /* activesound */ + MF_SOLID|MF_SHOOTABLE|MF_GRAVITY|MF_DROPOFF|MF_COUNTKILL, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_CAMERA */ + 0, /* doomednum */ + S_000, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_NOSECTOR|MF_NOBLOCKMAP, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_DEST_TELEPORT */ + 14, /* doomednum */ + S_000, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_NOSECTOR|MF_NOBLOCKMAP, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_DEST_PROJECTILE */ + 2050, /* doomednum */ + S_000, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_NOSECTOR|MF_NOBLOCKMAP, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_FAKEITEM */ + 89, /* doomednum */ + S_370, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 32*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SPECIAL|MF_NOSECTOR, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_LASERMARKER */ + 90, /* doomednum */ + S_000, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_NOBLOCKMAP|MF_RENDERLASER, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_PROJ_ROCKET */ + -1, /* doomednum */ + S_371, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_missile, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_372, /* deathstate */ + S_000, /* xdeathstate */ + sfx_explode, /* deathsound */ + 30, /* speed */ + 11*FRACUNIT, /* radius */ + 8*FRACUNIT, /* height */ + 100, /* mass */ + 20, /* damage */ + sfx_None, /* activesound */ + MF_NOBLOCKMAP|MF_DROPOFF|MF_MISSILE, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_PROJ_PLASMA */ + -1, /* doomednum */ + S_379, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_plasma, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_381, /* deathstate */ + S_000, /* xdeathstate */ + sfx_implod, /* deathsound */ + 40, /* speed */ + 13*FRACUNIT, /* radius */ + 8*FRACUNIT, /* height */ + 100, /* mass */ + 5, /* damage */ + sfx_None, /* activesound */ + MF_NOBLOCKMAP|MF_DROPOFF|MF_MISSILE, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_PROJ_BFG */ + -1, /* doomednum */ + S_387, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_389, /* deathstate */ + S_000, /* xdeathstate */ + sfx_bfgexp, /* deathsound */ + 40, /* speed */ + 13*FRACUNIT, /* radius */ + 8*FRACUNIT, /* height */ + 100, /* mass */ + 100, /* damage */ + sfx_None, /* activesound */ + MF_NOBLOCKMAP|MF_DROPOFF|MF_MISSILE, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_PROJ_LASER */ + -1, /* doomednum */ + S_395, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 8*FRACUNIT, /* radius */ + 8*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_NOBLOCKMAP, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_PROJ_IMP1 */ + -1, /* doomednum */ + S_397, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_bdmissile, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_400, /* deathstate */ + S_000, /* xdeathstate */ + sfx_implod, /* deathsound */ + 10, /* speed */ + 6*FRACUNIT, /* radius */ + 8*FRACUNIT, /* height */ + 100, /* mass */ + 3, /* damage */ + sfx_None, /* activesound */ + MF_NOBLOCKMAP|MF_DROPOFF|MF_MISSILE, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_PROJ_IMP2 */ + -1, /* doomednum */ + S_406, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_bdmissile, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_409, /* deathstate */ + S_000, /* xdeathstate */ + sfx_implod, /* deathsound */ + 20, /* speed */ + 6*FRACUNIT, /* radius */ + 8*FRACUNIT, /* height */ + 100, /* mass */ + 3, /* damage */ + sfx_None, /* activesound */ + MF_NOBLOCKMAP|MF_DROPOFF|MF_MISSILE, /* flags */ + 0, /* palette */ + 100, /* alpha */ + }, + + { /* MT_PROJ_HEAD */ + -1, /* doomednum */ + S_415, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_bdmissile, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_418, /* deathstate */ + S_000, /* xdeathstate */ + sfx_implod, /* deathsound */ + 20, /* speed */ + 6*FRACUNIT, /* radius */ + 8*FRACUNIT, /* height */ + 100, /* mass */ + 5, /* damage */ + sfx_None, /* activesound */ + MF_NOBLOCKMAP|MF_DROPOFF|MF_MISSILE, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_PROJ_BRUISER1 */ + -1, /* doomednum */ + S_423, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_bdmissile, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_425, /* deathstate */ + S_000, /* xdeathstate */ + sfx_implod, /* deathsound */ + 15, /* speed */ + 6*FRACUNIT, /* radius */ + 8*FRACUNIT, /* height */ + 100, /* mass */ + 8, /* damage */ + sfx_None, /* activesound */ + MF_NOBLOCKMAP|MF_DROPOFF|MF_MISSILE, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_PROJ_BRUISER2 */ + -1, /* doomednum */ + S_431, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_bdmissile, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_433, /* deathstate */ + S_000, /* xdeathstate */ + sfx_implod, /* deathsound */ + 15, /* speed */ + 6*FRACUNIT, /* radius */ + 8*FRACUNIT, /* height */ + 100, /* mass */ + 8, /* damage */ + sfx_None, /* activesound */ + MF_NOBLOCKMAP|MF_DROPOFF|MF_MISSILE, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_PROJ_BABY */ + -1, /* doomednum */ + S_439, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_plasma, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_441, /* deathstate */ + S_000, /* xdeathstate */ + sfx_implod, /* deathsound */ + 25, /* speed */ + 13*FRACUNIT, /* radius */ + 8*FRACUNIT, /* height */ + 100, /* mass */ + 3, /* damage */ + sfx_None, /* activesound */ + MF_NOBLOCKMAP|MF_DROPOFF|MF_MISSILE, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_PROJ_FATSO */ + -1, /* doomednum */ + S_447, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_bdmissile, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_450, /* deathstate */ + S_000, /* xdeathstate */ + sfx_implod, /* deathsound */ + 20, /* speed */ + 6*FRACUNIT, /* radius */ + 8*FRACUNIT, /* height */ + 100, /* mass */ + 8, /* damage */ + sfx_None, /* activesound */ + MF_NOBLOCKMAP|MF_DROPOFF|MF_MISSILE, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_PROJ_TRACER */ + -1, /* doomednum */ + S_456, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_tracer, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_458, /* deathstate */ + S_000, /* xdeathstate */ + sfx_explode, /* deathsound */ + 10, /* speed */ + 11*FRACUNIT, /* radius */ + 8*FRACUNIT, /* height */ + 100, /* mass */ + 10, /* damage */ + sfx_None, /* activesound */ + MF_NOBLOCKMAP|MF_DROPOFF|MF_MISSILE, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_PROJ_DART */ + -1, /* doomednum */ + S_465, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_dart, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 16, /* speed */ + 13*FRACUNIT, /* radius */ + 8*FRACUNIT, /* height */ + 100, /* mass */ + 4, /* damage */ + sfx_None, /* activesound */ + MF_NOBLOCKMAP|MF_DROPOFF|MF_MISSILE, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_PROJ_RECTFIRE */ + -1, /* doomednum */ + S_466, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_tracer, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 20, /* speed */ + 16*FRACUNIT, /* radius */ + 64*FRACUNIT, /* height */ + 100, /* mass */ + 5, /* damage */ + sfx_None, /* activesound */ + MF_NOBLOCKMAP|MF_GRAVITY|MF_DROPOFF|MF_MISSILE|MF_SHADOW, /* flags */ + 0, /* palette */ + 180, /* alpha */ + }, + + { /* MT_PROJ_RECT */ + -1, /* doomednum */ + S_470, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_tracer, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_472, /* deathstate */ + S_000, /* xdeathstate */ + sfx_explode, /* deathsound */ + 18, /* speed */ + 11*FRACUNIT, /* radius */ + 8*FRACUNIT, /* height */ + 100, /* mass */ + 10, /* damage */ + sfx_None, /* activesound */ + MF_NOBLOCKMAP|MF_DROPOFF|MF_MISSILE, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_SMOKE_GRAY */ + -1, /* doomednum */ + S_478, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_NOBLOCKMAP, /* flags */ + 0, /* palette */ + 120, /* alpha */ + }, + + { /* MT_SMOKE_RED */ + -1, /* doomednum */ + S_483, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_NOBLOCKMAP, /* flags */ + 0, /* palette */ + 120, /* alpha */ + }, + + { /* MT_SMOKE_SMALL */ + -1, /* doomednum */ + S_488, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_NOBLOCKMAP|MF_SHADOW, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_BLOOD */ + -1, /* doomednum */ + S_494, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_NOBLOCKMAP|MF_GRAVITY, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_GIB_CRUSHED */ + 24, /* doomednum */ + S_498, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + 0, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_TELEPORTFOG */ + -1, /* doomednum */ + S_499, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_NOBLOCKMAP|MF_SHADOW, /* flags */ + 0, /* palette */ + 140, /* alpha */ + }, + + { /* MT_BFGSPREAD */ + -1, /* doomednum */ + S_511, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_NOBLOCKMAP, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_ITEM_ARMOR1 */ + 2018, /* doomednum */ + S_517, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SPECIAL, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_ITEM_ARMOR2 */ + 2019, /* doomednum */ + S_519, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SPECIAL, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_ITEM_BONUSHEALTH */ + 2014, /* doomednum */ + S_521, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SPECIAL|MF_COUNTITEM, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_ITEM_BONUSARMOR */ + 2015, /* doomednum */ + S_525, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SPECIAL|MF_COUNTITEM, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_ITEM_BLUECARDKEY */ + 5, /* doomednum */ + S_531, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SPECIAL|MF_NOTDMATCH, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_ITEM_REDCARDKEY */ + 13, /* doomednum */ + S_533, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SPECIAL|MF_NOTDMATCH, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_ITEM_YELLOWCARDKEY */ + 6, /* doomednum */ + S_535, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SPECIAL|MF_NOTDMATCH, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_ITEM_YELLOWSKULLKEY */ + 39, /* doomednum */ + S_537, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SPECIAL|MF_NOTDMATCH, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_ITEM_REDSKULLKEY */ + 38, /* doomednum */ + S_539, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SPECIAL|MF_NOTDMATCH, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_ITEM_BLUESKULLKEY */ + 40, /* doomednum */ + S_541, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SPECIAL|MF_NOTDMATCH, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_ITEM_ARTIFACT1 */ + 1042, /* doomednum */ + S_543, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SPECIAL, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_ITEM_ARTIFACT2 */ + 1043, /* doomednum */ + S_551, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SPECIAL, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_ITEM_ARTIFACT3 */ + 1044, /* doomednum */ + S_559, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SPECIAL, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_ITEM_STIMPACK */ + 2011, /* doomednum */ + S_567, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SPECIAL, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_ITEM_MEDKIT */ + 2012, /* doomednum */ + S_568, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SPECIAL, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_ITEM_SOULSPHERE */ + 2013, /* doomednum */ + S_569, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SPECIAL|MF_COUNTITEM, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_ITEM_INVULSPHERE */ + 2022, /* doomednum */ + S_575, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SPECIAL|MF_COUNTITEM, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_ITEM_BERSERK */ + 2023, /* doomednum */ + S_581, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SPECIAL|MF_COUNTITEM, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_ITEM_INVISSPHERE */ + 2024, /* doomednum */ + S_582, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SPECIAL|MF_COUNTITEM|MF_SHADOW, /* flags */ + 0, /* palette */ + 176, /* alpha */ + }, + + { /* MT_ITEM_RADSPHERE */ + 2025, /* doomednum */ + S_588, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SPECIAL, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_ITEM_AUTOMAP */ + 2026, /* doomednum */ + S_590, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SPECIAL|MF_COUNTITEM, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_ITEM_PVIS */ + 2045, /* doomednum */ + S_594, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SPECIAL|MF_COUNTITEM, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_ITEM_MEGASPHERE */ + 83, /* doomednum */ + S_596, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SPECIAL|MF_COUNTITEM, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_AMMO_CLIP */ + 2007, /* doomednum */ + S_602, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SPECIAL, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_AMMO_CLIPBOX */ + 2048, /* doomednum */ + S_603, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SPECIAL, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_AMMO_ROCKET */ + 2010, /* doomednum */ + S_604, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SPECIAL, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_AMMO_ROCKETBOX */ + 2046, /* doomednum */ + S_605, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SPECIAL, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_AMMO_CELL */ + 2047, /* doomednum */ + S_606, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SPECIAL, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_AMMO_CELLPACK */ + 17, /* doomednum */ + S_607, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SPECIAL, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_AMMO_SHELL */ + 2008, /* doomednum */ + S_608, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SPECIAL, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_AMMO_SHELLBOX */ + 2049, /* doomednum */ + S_609, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SPECIAL, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_AMMO_BACKPACK */ + 8, /* doomednum */ + S_610, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SPECIAL, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_WEAP_BFG */ + 2006, /* doomednum */ + S_611, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SPECIAL, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_WEAP_CHAINSAW */ + 2005, /* doomednum */ + S_612, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SPECIAL, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_WEAP_CHAINGUN */ + 2002, /* doomednum */ + S_613, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SPECIAL, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_WEAP_LAUNCHER */ + 2003, /* doomednum */ + S_614, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SPECIAL, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_WEAP_PLASMA */ + 2004, /* doomednum */ + S_615, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SPECIAL, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_WEAP_SHOTGUN */ + 2001, /* doomednum */ + S_616, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SPECIAL, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_WEAP_SSHOTGUN */ + 82, /* doomednum */ + S_617, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SPECIAL, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_WEAP_LCARBINE */ + 84, /* doomednum */ + S_618, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SPECIAL, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_PROP_FIRE */ + 2051, /* doomednum */ + S_619, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 16*FRACUNIT, /* radius */ + 64*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SHADOW, /* flags */ + 0, /* palette */ + 140, /* alpha */ + }, + + { /* MT_PROP_CANDLE */ + 34, /* doomednum */ + S_624, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + 0, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_PROP_BARREL */ + 1001, /* doomednum */ + S_626, /* spawnstate */ + 20, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_627, /* deathstate */ + S_000, /* xdeathstate */ + sfx_explode, /* deathsound */ + 0, /* speed */ + 16*FRACUNIT, /* radius */ + 50*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SOLID|MF_SHOOTABLE|MF_NOBLOOD, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_EXPLOSION1 */ + -1, /* doomednum */ + S_631, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_NOBLOCKMAP, /* flags */ + 0, /* palette */ + 80, /* alpha */ + }, + + { /* MT_EXPLOSION2 */ + -1, /* doomednum */ + S_636, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_NOBLOCKMAP, /* flags */ + 0, /* palette */ + 80, /* alpha */ + }, + + { /* MT_PROP_TECHLAMP1 */ + 1015, /* doomednum */ + S_641, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 54*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_NOBLOCKMAP|MF_SPAWNCEILING, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_PROP_TECHLAMP2 */ + 1016, /* doomednum */ + S_642, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 12*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_NOBLOCKMAP|MF_SPAWNCEILING, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_PROP_TORCHBLUE */ + 1003, /* doomednum */ + S_643, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + 0, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_PROP_TORCHYELLOW */ + 1039, /* doomednum */ + S_648, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + 0, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_PROP_TORCHRED */ + 1025, /* doomednum */ + S_653, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + 0, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_PROP_POLEBASELONG */ + 1050, /* doomednum */ + S_658, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 12*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SOLID, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_PROP_POLEBASESHORT */ + 1051, /* doomednum */ + S_659, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 8*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SOLID, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_PROP_FIREBLUE */ + 1033, /* doomednum */ + S_660, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + 0, /* flags */ + 0, /* palette */ + 192, /* alpha */ + }, + + { /* MT_PROP_FIRERED */ + 1034, /* doomednum */ + S_665, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + 0, /* flags */ + 0, /* palette */ + 192, /* alpha */ + }, + + { /* MT_PROP_FIREYELLOW */ + 1035, /* doomednum */ + S_670, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + 0, /* flags */ + 0, /* palette */ + 192, /* alpha */ + }, + + { /* MT_GIB_MEATSTICK */ + 1005, /* doomednum */ + S_675, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SOLID, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_GIB_MEATHANG */ + 1006, /* doomednum */ + S_676, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 95*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_NOBLOCKMAP|MF_SPAWNCEILING, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_GIB_TORSOHANG */ + 1007, /* doomednum */ + S_677, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 83*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_NOBLOCKMAP|MF_SPAWNCEILING, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_GIB_RIBFLOOR */ + 1008, /* doomednum */ + S_678, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + 0, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_GIB_TWITCHFLOOR */ + 1009, /* doomednum */ + S_679, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + 0, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_GIB_BLOODPOOL */ + 1010, /* doomednum */ + S_681, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + 0, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_GIB_BONEFLOOR */ + 1011, /* doomednum */ + S_682, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + 0, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_GIB_MEATRIBFLOOR */ + 1012, /* doomednum */ + S_683, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + 0, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_GIB_MEATRIBCAGE */ + 1013, /* doomednum */ + S_684, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + 0, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_GIB_CHAINHOOK */ + 1014, /* doomednum */ + S_685, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 95*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_NOBLOCKMAP|MF_SPAWNCEILING, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_GIB_HANGCAGE */ + 1017, /* doomednum */ + S_686, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 91*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_NOBLOCKMAP|MF_SPAWNCEILING, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_GIB_CHAINPINSER */ + 1018, /* doomednum */ + S_687, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 101*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_NOBLOCKMAP|MF_SPAWNCEILING, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_GIB_CHAINARM */ + 1019, /* doomednum */ + S_688, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 58*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_NOBLOCKMAP|MF_SPAWNCEILING, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_GIB_HANGMACE1 */ + 1020, /* doomednum */ + S_689, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 80*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_NOBLOCKMAP|MF_SPAWNCEILING, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_GIB_HEADSTICK1 */ + 1022, /* doomednum */ + S_690, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 8*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SOLID, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_GIB_HEADSTICK2 */ + 1023, /* doomednum */ + S_691, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 8*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SOLID, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_GIB_DOUBLEMEATSTICK */ + 1024, /* doomednum */ + S_692, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 8*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SOLID, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_PROP_STATUE1 */ + 1028, /* doomednum */ + S_693, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SOLID, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_PROP_STATUE2 */ + 1029, /* doomednum */ + S_694, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SOLID, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_PROP_TECHPOLELONG */ + 1031, /* doomednum */ + S_695, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 8*FRACUNIT, /* radius */ + 80*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SOLID, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_PROP_TECHPOLESHORT */ + 1032, /* doomednum */ + S_696, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 8*FRACUNIT, /* radius */ + 62*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SOLID, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_PROP_TREESTUMPSMALL */ + 1036, /* doomednum */ + S_697, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 16*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SOLID, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_PROP_TREESTUMPLARGE */ + 1037, /* doomednum */ + S_698, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 16*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SOLID, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_PROP_TREE */ + 1038, /* doomednum */ + S_699, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 16*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SOLID, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_PROP_BLOODYPOLE */ + 1045, /* doomednum */ + S_700, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 8*FRACUNIT, /* radius */ + 16*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_SOLID, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_GIB_HANGMACE2 */ + 1046, /* doomednum */ + S_701, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 56*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_NOBLOCKMAP|MF_SPAWNCEILING, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_GIB_HANGWHITEMEAT */ + 1047, /* doomednum */ + S_702, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 64*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_NOBLOCKMAP|MF_SPAWNCEILING, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_GIB_HANGHEAD */ + 1048, /* doomednum */ + S_703, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 60*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_NOBLOCKMAP|MF_SPAWNCEILING, /* flags */ + 0, /* palette */ + 255, /* alpha */ + }, + + { /* MT_GIB_HANGRIB */ + 1049, /* doomednum */ + S_704, /* spawnstate */ + 1000, /* spawnhealth */ + S_000, /* seestate */ + sfx_None, /* seesound */ + 8, /* reactiontime */ + sfx_None, /* attacksound */ + S_000, /* painstate */ + 0, /* painchance */ + sfx_None, /* painsound */ + S_000, /* meleestate */ + S_000, /* missilestate */ + S_000, /* deathstate */ + S_000, /* xdeathstate */ + sfx_None, /* deathsound */ + 0, /* speed */ + 20*FRACUNIT, /* radius */ + 98*FRACUNIT, /* height */ + 100, /* mass */ + 0, /* damage */ + sfx_None, /* activesound */ + MF_NOBLOCKMAP|MF_SPAWNCEILING, /* flags */ + 0, /* palette */ + 255, /* alpha */ + } +}; + diff --git a/Doom 64/doominfo.h b/Doom 64/doominfo.h @@ -0,0 +1,1113 @@ +/* generated by multigen */ + +#define FF_FULLBRIGHT 0x8000 // flag in thing->frame +#define FF_FRAMEMASK 0x7fff + +typedef enum { + SPR_SPOT, + SPR_PLAY, + SPR_SARG, + SPR_FATT, + SPR_POSS, + SPR_TROO, + SPR_HEAD, + SPR_BOSS, + SPR_SKUL, + SPR_BSPI, + SPR_CYBR, + SPR_PAIN, + SPR_RECT, + SPR_MISL, + SPR_PLSS, + SPR_BFS1, + SPR_LASS, + SPR_BAL1, + SPR_BAL3, + SPR_BAL2, + SPR_BAL7, + SPR_BAL8, + SPR_APLS, + SPR_MANF, + SPR_TRCR, + SPR_DART, + SPR_FIRE, + SPR_RBAL, + SPR_PUF2, + SPR_PUF3, + SPR_PUFF, + SPR_BLUD, + SPR_A027, + SPR_TFOG, + SPR_BFE2, + SPR_ARM1, + SPR_ARM2, + SPR_BON1, + SPR_BON2, + SPR_BKEY, + SPR_RKEY, + SPR_YKEY, + SPR_YSKU, + SPR_RSKU, + SPR_BSKU, + SPR_ART1, + SPR_ART2, + SPR_ART3, + SPR_STIM, + SPR_MEDI, + SPR_SOUL, + SPR_PINV, + SPR_PSTR, + SPR_PINS, + SPR_SUIT, + SPR_PMAP, + SPR_PVIS, + SPR_MEGA, + SPR_CLIP, + SPR_AMMO, + SPR_RCKT, + SPR_BROK, + SPR_CELL, + SPR_CELP, + SPR_SHEL, + SPR_SBOX, + SPR_BPAK, + SPR_BFUG, + SPR_CSAW, + SPR_MGUN, + SPR_LAUN, + SPR_PLSM, + SPR_SHOT, + SPR_SGN2, + SPR_LSRG, + SPR_CAND, + SPR_BAR1, + SPR_LMP1, + SPR_LMP2, + SPR_A031, + SPR_A030, + SPR_A032, + SPR_A033, + SPR_A034, + SPR_BFLM, + SPR_RFLM, + SPR_YFLM, + SPR_A006, + SPR_A021, + SPR_A003, + SPR_A020, + SPR_A014, + SPR_A016, + SPR_A008, + SPR_A007, + SPR_A015, + SPR_A001, + SPR_A012, + SPR_A010, + SPR_A018, + SPR_A017, + SPR_A026, + SPR_A022, + SPR_A028, + SPR_A029, + SPR_A035, + SPR_A036, + SPR_TRE3, + SPR_TRE2, + SPR_TRE1, + SPR_A013, + SPR_A019, + SPR_A004, + SPR_A005, + SPR_A023, + SPR_SAWG, + SPR_PUNG, + SPR_PISG, + SPR_SHT1, + SPR_SHT2, + SPR_CHGG, + SPR_ROCK, + SPR_PLAS, + SPR_BFGG, + SPR_LASR, + NUMSPRITES +} spritenum_t; + +typedef enum +{ + S_000, + S_001, + S_002, + S_003, + S_004, + S_005, + S_006, + S_007, + S_008, + S_009, + S_010, + S_011, + S_012, + S_013, + S_014, + S_015, + S_016, + S_017, + S_018, + S_019, + S_020, + S_021, + S_022, + S_023, + S_024, + S_025, + S_026, + S_027, + S_028, + S_029, + S_030, + S_031, + S_032, + S_033, + S_034, + S_035, + S_036, + S_037, + S_038, + S_039, + S_040, + S_041, + S_042, + S_043, + S_044, + S_045, + S_046, + S_047, + S_048, + S_049, + S_050, + S_051, + S_052, + S_053, + S_054, + S_055, + S_056, + S_057, + S_058, + S_059, + S_060, + S_061, + S_062, + S_063, + S_064, + S_065, + S_066, + S_067, + S_068, + S_069, + S_070, + S_071, + S_072, + S_073, + S_074, + S_075, + S_076, + S_077, + S_078, + S_079, + S_080, + S_081, + S_082, + S_083, + S_084, + S_085, + S_086, + S_087, + S_088, + S_089, + S_090, + S_091, + S_092, + S_093, + S_094, + S_095, + S_096, + S_097, + S_098, + S_099, + S_100, + S_101, + S_102, + S_103, + S_104, + S_105, + S_106, + S_107, + S_108, + S_109, + S_110, + S_111, + S_112, + S_113, + S_114, + S_115, + S_116, + S_117, + S_118, + S_119, + S_120, + S_121, + S_122, + S_123, + S_124, + S_125, + S_126, + S_127, + S_128, + S_129, + S_130, + S_131, + S_132, + S_133, + S_134, + S_135, + S_136, + S_137, + S_138, + S_139, + S_140, + S_141, + S_142, + S_143, + S_144, + S_145, + S_146, + S_147, + S_148, + S_149, + S_150, + S_151, + S_152, + S_153, + S_154, + S_155, + S_156, + S_157, + S_158, + S_159, + S_160, + S_161, + S_162, + S_163, + S_164, + S_165, + S_166, + S_167, + S_168, + S_169, + S_170, + S_171, + S_172, + S_173, + S_174, + S_175, + S_176, + S_177, + S_178, + S_179, + S_180, + S_181, + S_182, + S_183, + S_184, + S_185, + S_186, + S_187, + S_188, + S_189, + S_190, + S_191, + S_192, + S_193, + S_194, + S_195, + S_196, + S_197, + S_198, + S_199, + S_200, + S_201, + S_202, + S_203, + S_204, + S_205, + S_206, + S_207, + S_208, + S_209, + S_210, + S_211, + S_212, + S_213, + S_214, + S_215, + S_216, + S_217, + S_218, + S_219, + S_220, + S_221, + S_222, + S_223, + S_224, + S_225, + S_226, + S_227, + S_228, + S_229, + S_230, + S_231, + S_232, + S_233, + S_234, + S_235, + S_236, + S_237, + S_238, + S_239, + S_240, + S_241, + S_242, + S_243, + S_244, + S_245, + S_246, + S_247, + S_248, + S_249, + S_250, + S_251, + S_252, + S_253, + S_254, + S_255, + S_256, + S_257, + S_258, + S_259, + S_260, + S_261, + S_262, + S_263, + S_264, + S_265, + S_266, + S_267, + S_268, + S_269, + S_270, + S_271, + S_272, + S_273, + S_274, + S_275, + S_276, + S_277, + S_278, + S_279, + S_280, + S_281, + S_282, + S_283, + S_284, + S_285, + S_286, + S_287, + S_288, + S_289, + S_290, + S_291, + S_292, + S_293, + S_294, + S_295, + S_296, + S_297, + S_298, + S_299, + S_300, + S_301, + S_302, + S_303, + S_304, + S_305, + S_306, + S_307, + S_308, + S_309, + S_310, + S_311, + S_312, + S_313, + S_314, + S_315, + S_316, + S_317, + S_318, + S_319, + S_320, + S_321, + S_322, + S_323, + S_324, + S_325, + S_326, + S_327, + S_328, + S_329, + S_330, + S_331, + S_332, + S_333, + S_334, + S_335, + S_336, + S_337, + S_338, + S_339, + S_340, + S_341, + S_342, + S_343, + S_344, + S_345, + S_346, + S_347, + S_348, + S_349, + S_350, + S_351, + S_352, + S_353, + S_354, + S_355, + S_356, + S_357, + S_358, + S_359, + S_360, + S_361, + S_362, + S_363, + S_364, + S_365, + S_366, + S_367, + S_368, + S_369, + S_370, + S_371, + S_372, + S_373, + S_374, + S_375, + S_376, + S_377, + S_378, + S_379, + S_380, + S_381, + S_382, + S_383, + S_384, + S_385, + S_386, + S_387, + S_388, + S_389, + S_390, + S_391, + S_392, + S_393, + S_394, + S_395, + S_396, + S_397, + S_398, + S_399, + S_400, + S_401, + S_402, + S_403, + S_404, + S_405, + S_406, + S_407, + S_408, + S_409, + S_410, + S_411, + S_412, + S_413, + S_414, + S_415, + S_416, + S_417, + S_418, + S_419, + S_420, + S_421, + S_422, + S_423, + S_424, + S_425, + S_426, + S_427, + S_428, + S_429, + S_430, + S_431, + S_432, + S_433, + S_434, + S_435, + S_436, + S_437, + S_438, + S_439, + S_440, + S_441, + S_442, + S_443, + S_444, + S_445, + S_446, + S_447, + S_448, + S_449, + S_450, + S_451, + S_452, + S_453, + S_454, + S_455, + S_456, + S_457, + S_458, + S_459, + S_460, + S_461, + S_462, + S_463, + S_464, + S_465, + S_466, + S_467, + S_468, + S_469, + S_470, + S_471, + S_472, + S_473, + S_474, + S_475, + S_476, + S_477, + S_478, + S_479, + S_480, + S_481, + S_482, + S_483, + S_484, + S_485, + S_486, + S_487, + S_488, + S_489, + S_490, + S_491, + S_492, + S_493, + S_494, + S_495, + S_496, + S_497, + S_498, + S_499, + S_500, + S_501, + S_502, + S_503, + S_504, + S_505, + S_506, + S_507, + S_508, + S_509, + S_510, + S_511, + S_512, + S_513, + S_514, + S_515, + S_516, + S_517, + S_518, + S_519, + S_520, + S_521, + S_522, + S_523, + S_524, + S_525, + S_526, + S_527, + S_528, + S_529, + S_530, + S_531, + S_532, + S_533, + S_534, + S_535, + S_536, + S_537, + S_538, + S_539, + S_540, + S_541, + S_542, + S_543, + S_544, + S_545, + S_546, + S_547, + S_548, + S_549, + S_550, + S_551, + S_552, + S_553, + S_554, + S_555, + S_556, + S_557, + S_558, + S_559, + S_560, + S_561, + S_562, + S_563, + S_564, + S_565, + S_566, + S_567, + S_568, + S_569, + S_570, + S_571, + S_572, + S_573, + S_574, + S_575, + S_576, + S_577, + S_578, + S_579, + S_580, + S_581, + S_582, + S_583, + S_584, + S_585, + S_586, + S_587, + S_588, + S_589, + S_590, + S_591, + S_592, + S_593, + S_594, + S_595, + S_596, + S_597, + S_598, + S_599, + S_600, + S_601, + S_602, + S_603, + S_604, + S_605, + S_606, + S_607, + S_608, + S_609, + S_610, + S_611, + S_612, + S_613, + S_614, + S_615, + S_616, + S_617, + S_618, + S_619, + S_620, + S_621, + S_622, + S_623, + S_624, + S_625, + S_626, + S_627, + S_628, + S_629, + S_630, + S_631, + S_632, + S_633, + S_634, + S_635, + S_636, + S_637, + S_638, + S_639, + S_640, + S_641, + S_642, + S_643, + S_644, + S_645, + S_646, + S_647, + S_648, + S_649, + S_650, + S_651, + S_652, + S_653, + S_654, + S_655, + S_656, + S_657, + S_658, + S_659, + S_660, + S_661, + S_662, + S_663, + S_664, + S_665, + S_666, + S_667, + S_668, + S_669, + S_670, + S_671, + S_672, + S_673, + S_674, + S_675, + S_676, + S_677, + S_678, + S_679, + S_680, + S_681, + S_682, + S_683, + S_684, + S_685, + S_686, + S_687, + S_688, + S_689, + S_690, + S_691, + S_692, + S_693, + S_694, + S_695, + S_696, + S_697, + S_698, + S_699, + S_700, + S_701, + S_702, + S_703, + S_704, + S_705, + S_706, + S_707, + S_708, + S_709, + S_710, + S_711, + S_712, + S_713, + S_714, + S_715, + S_716, + S_717, + S_718, + S_719, + S_720, + S_721, + S_722, + S_723, + S_724, + S_725, + S_726, + S_727, + S_728, + S_729, + S_730, + S_731, + S_732, + S_733, + S_734, + S_735, + S_736, + S_737, + S_738, + S_739, + S_740, + S_741, + S_742, + S_743, + S_744, + S_745, + S_746, + S_747, + S_748, + S_749, + S_750, + S_751, + S_752, + S_753, + S_754, + S_755, + S_756, + S_757, + S_758, + S_759, + S_760, + S_761, + S_762, + S_763, + S_764, + S_765, + S_766, + S_767, + S_768, + S_769, + S_770, + S_771, + S_772, + S_773, + S_774, + S_775, + S_776, + S_777, + S_778, + S_779, + S_780, + S_781, + S_782, + S_783, + S_784, + S_785, + S_786, + S_787, + S_788, + S_789, + S_790, + S_791, + S_792, + S_793, + S_794, + S_795, + S_796, + NUMSTATES +} statenum_t; + +typedef struct +{ + spritenum_t sprite; + long frame; + long tics; + void (*action) (); + statenum_t nextstate; +} state_t; + +extern state_t states[NUMSTATES]; +extern char *sprnames[NUMSPRITES]; + +typedef enum +{ + MT_PLAYER, // 0 + MT_PLAYERBOT1, // 1 + MT_PLAYERBOT2, // 2 + MT_PLAYERBOT3, // 3 + MT_DEMON1, // 4 + MT_DEMON2, // 5 + MT_MANCUBUS, // 6 + MT_POSSESSED1, // 7 + MT_POSSESSED2, // 8 + MT_IMP1, // 9 + MT_IMP2, // 10 + MT_CACODEMON, // 11 + MT_BRUISER1, // 12 + MT_BRUISER2, // 13 + MT_SKULL, // 14 + MT_BABY, // 15 + MT_CYBORG, // 16 + MT_CYBORG_TITLE, // 17 + MT_PAIN, // 18 + MT_RESURRECTOR, // 19 + MT_CAMERA, // 20 + MT_DEST_TELEPORT, // 21 + MT_DEST_PROJECTILE, // 22 + MT_FAKEITEM, // 23 + MT_LASERMARKER, // 24 + MT_PROJ_ROCKET, // 25 + MT_PROJ_PLASMA, // 26 + MT_PROJ_BFG, // 27 + MT_PROJ_LASER, // 28 + MT_PROJ_IMP1, // 29 + MT_PROJ_IMP2, // 30 + MT_PROJ_HEAD, // 31 + MT_PROJ_BRUISER1, // 32 + MT_PROJ_BRUISER2, // 33 + MT_PROJ_BABY, // 34 + MT_PROJ_FATSO, // 35 + MT_PROJ_TRACER, // 36 + MT_PROJ_DART, // 37 + MT_PROJ_RECTFIRE, // 38 + MT_PROJ_RECT, // 39 + MT_SMOKE_GRAY, // 40 + MT_SMOKE_RED, // 41 + MT_SMOKE_SMALL, // 42 + MT_BLOOD, // 43 + MT_GIB_CRUSHED, // 44 + MT_TELEPORTFOG, // 45 + MT_BFGSPREAD, // 46 + MT_ITEM_ARMOR1, // 47 + MT_ITEM_ARMOR2, // 48 + MT_ITEM_BONUSHEALTH, // 49 + MT_ITEM_BONUSARMOR, // 50 + MT_ITEM_BLUECARDKEY, // 51 + MT_ITEM_REDCARDKEY, // 52 + MT_ITEM_YELLOWCARDKEY, // 53 + MT_ITEM_YELLOWSKULLKEY, // 54 + MT_ITEM_REDSKULLKEY, // 55 + MT_ITEM_BLUESKULLKEY, // 56 + MT_ITEM_ARTIFACT1, // 57 + MT_ITEM_ARTIFACT2, // 58 + MT_ITEM_ARTIFACT3, // 59 + MT_ITEM_STIMPACK, // 60 + MT_ITEM_MEDKIT, // 61 + MT_ITEM_SOULSPHERE, // 62 + MT_ITEM_INVULSPHERE, // 63 + MT_ITEM_BERSERK, // 64 + MT_ITEM_INVISSPHERE, // 65 + MT_ITEM_RADSPHERE, // 66 + MT_ITEM_AUTOMAP, // 67 + MT_ITEM_PVIS, // 68 + MT_ITEM_MEGASPHERE, // 69 + MT_AMMO_CLIP, // 70 + MT_AMMO_CLIPBOX, // 71 + MT_AMMO_ROCKET, // 72 + MT_AMMO_ROCKETBOX, // 73 + MT_AMMO_CELL, // 74 + MT_AMMO_CELLPACK, // 75 + MT_AMMO_SHELL, // 76 + MT_AMMO_SHELLBOX, // 77 + MT_AMMO_BACKPACK, // 78 + MT_WEAP_BFG, // 79 + MT_WEAP_CHAINSAW, // 80 + MT_WEAP_CHAINGUN, // 81 + MT_WEAP_LAUNCHER, // 82 + MT_WEAP_PLASMA, // 83 + MT_WEAP_SHOTGUN, // 84 + MT_WEAP_SSHOTGUN, // 85 + MT_WEAP_LCARBINE, // 86 + MT_PROP_FIRE, // 87 + MT_PROP_CANDLE, // 88 + MT_PROP_BARREL, // 89 + MT_EXPLOSION1, // 90 + MT_EXPLOSION2, // 91 + MT_PROP_TECHLAMP1, // 92 + MT_PROP_TECHLAMP2, // 93 + MT_PROP_TORCHBLUE, // 94 + MT_PROP_TORCHYELLOW, // 95 + MT_PROP_TORCHRED, // 96 + MT_PROP_POLEBASELONG, // 97 + MT_PROP_POLEBASESHORT, // 98 + MT_PROP_FIREBLUE, // 99 + MT_PROP_FIRERED, // 100 + MT_PROP_FIREYELLOW, // 101 + MT_GIB_MEATSTICK, // 102 + MT_GIB_MEATHANG, // 103 + MT_GIB_TORSOHANG, // 104 + MT_GIB_RIBFLOOR, // 105 + MT_GIB_TWITCHFLOOR, // 106 + MT_GIB_BLOODPOOL, // 107 + MT_GIB_BONEFLOOR, // 108 + MT_GIB_MEATRIBFLOOR, // 109 + MT_GIB_MEATRIBCAGE, // 110 + MT_GIB_CHAINHOOK, // 111 + MT_GIB_HANGCAGE, // 112 + MT_GIB_CHAINPINSER, // 113 + MT_GIB_CHAINARM, // 114 + MT_GIB_HANGMACE1, // 115 + MT_GIB_HEADSTICK1, // 116 + MT_GIB_HEADSTICK2, // 117 + MT_GIB_DOUBLEMEATSTICK, // 118 + MT_PROP_STATUE1, // 119 + MT_PROP_STATUE2, // 120 + MT_PROP_TECHPOLELONG, // 121 + MT_PROP_TECHPOLESHORT, // 122 + MT_PROP_TREESTUMPSMALL, // 123 + MT_PROP_TREESTUMPLARGE, // 124 + MT_PROP_TREE, // 125 + MT_PROP_BLOODYPOLE, // 126 + MT_GIB_HANGMACE2, // 127 + MT_GIB_HANGWHITEMEAT, // 128 + MT_GIB_HANGHEAD, // 129 + MT_GIB_HANGRIB, // 130 + NUMMOBJTYPES +} mobjtype_t; + +typedef struct { + int doomednum; + int spawnstate; + int spawnhealth; + int seestate; + int seesound; + int reactiontime; + int attacksound; + int painstate; + int painchance; + int painsound; + int meleestate; + int missilestate; + int deathstate; + int xdeathstate; + int deathsound; + int speed; + int radius; + int height; + int mass; + int damage; + int activesound; + int flags; + int palette; + int alpha; +} mobjinfo_t; + +extern mobjinfo_t mobjinfo[NUMMOBJTYPES]; + diff --git a/Doom 64/doomlib.c b/Doom 64/doomlib.c @@ -0,0 +1,213 @@ +/* doomlib.c */ + +#include "doomdef.h" + +#define WORDMASK 7 + +/* +==================== += += D_memmove += +==================== +*/ + +void D_memmove(void *dest, void *src) // 800019F0 +{ + byte p; + byte *p1; + byte *p2; + + p = *(byte *)src; + p1 = (byte *)src; + p2 = (byte *)dest; + + *p2++ = *p1++; + + while (p != '\0') + { + p = *p1; + *p2++ = *p1++; + } +} + +/* +==================== += += D_memset += +==================== +*/ + +void D_memset(void *dest, int val, int count) // 80001A20 +{ + byte *p; + int *lp; + int v; + + /* round up to nearest word */ + p = dest; + while ((int)p & WORDMASK) + { + if (--count < 0) + return; + *p++ = (char)val; + } + + /* write 8 bytes at a time */ + lp = (int *)p; + v = (int)(val << 24) | (val << 16) | (val << 8) | val; + while (count >= 8) + { + lp[0] = lp[1] = v; + lp += 2; + count -= 8; + } + + /* finish up */ + p = (byte *)lp; + while (count--) + *p++ = (char)val; +} + +/* +==================== += += D_memcpy += +==================== +*/ + +void D_memcpy(void *dest, void *src, int count) // 80001ACC +{ + byte *d, *s; + int *ld, *ls; + int stopcnt; + + ld = (int *)dest; + ls = (int *)src; + + if ((((int)ld | (int)ls | count) & 7)) + { + d = (byte *)dest; + s = (byte *)src; + while (count--) + *d++ = *s++; + } + else + { + if (count == 0) + return; + + if(-(count & 31)) + { + stopcnt = -(count & 31) + count; + while (stopcnt != count) + { + ld[0] = ls[0]; + ld[1] = ls[1]; + ld += 2; + ls += 2; + count -= 8; + } + + if (count == 0) + return; + } + + while (count) + { + ld[0] = ls[0]; + ld[1] = ls[1]; + ld[2] = ls[2]; + ld[3] = ls[3]; + ld[4] = ls[4]; + ld[5] = ls[5]; + ld[6] = ls[6]; + ld[7] = ls[7]; + ld += 8; + ls += 8; + count -= 32; + } + } +} + +/* +==================== += += D_strncpy += +==================== +*/ + +void D_strncpy(char *dest, char *src, int maxcount) // 8000lBB0 +{ + byte *p1, *p2; + p1 = (byte *)dest; + p2 = (byte *)src; + while (maxcount--) + if (!(*p1++ = *p2++)) + return; +} + +/* +==================== += += D_strncasecmp += +==================== +*/ + +int D_strncasecmp(char *s1, char *s2, int len) // 80001BEC +{ + while (*s1 && *s2) + { + if (*s1 != *s2) + return 1; + s1++; + s2++; + if (!--len) + return 0; + } + if (*s1 != *s2) + return 1; + return 0; +} + +/* +==================== += += D_strupr += +==================== +*/ + +void D_strupr(char *s) // 80001C74 +{ + char c; + + while ((c = *s) != 0) + { + if (c >= 'a' && c <= 'z') + c -= 'a' - 'A'; + *s++ = c; + } +} + +/* +==================== += += D_strlen += +==================== +*/ + +int D_strlen(char *s) // 80001CC0 +{ + int len = 0; + + while(*(s++)) + len++; + + return len; +} diff --git a/Doom 64/f_main.c b/Doom 64/f_main.c @@ -0,0 +1,996 @@ +/* f_main.c -- finale */ + +#include "doomdef.h" +#include "p_local.h" +#include "st_main.h" +#include "r_local.h" + +#define T_NULL "" + +#define C_END1_TXT01 "you cackle as the" +#define C_END1_TXT02 "familiarity of the" +#define C_END1_TXT03 "situation occurs to you." +#define C_END1_TXT04 "The gateway to the Demons" +#define C_END1_TXT05 "domain was too accessible." +#define C_END1_TXT06 "You realize the demons mock" +#define C_END1_TXT07 "you with their invitation." +#define C_END1_TXT08 "It does not matter..." +#define C_END1_TXT09 "The demons spawn like rats" +#define C_END1_TXT10 "and you have the grade AAA" +#define C_END1_TXT11 "U.A.C. poison they crave." +#define C_END1_TXT12 "Your bloodthirsty scream" +#define C_END1_TXT13 "shatters the teleport haze." +#define C_END1_TXT14 "Once again you find yourself" +#define C_END1_TXT15 "amidst..." + +#define C_END2_TXT01 "The vast silence reminds" +#define C_END2_TXT02 "you of the military morgue." +#define C_END2_TXT03 " " +#define C_END2_TXT04 "You knew the installation" +#define C_END2_TXT05 "had a classified level." +#define C_END2_TXT06 " " +#define C_END2_TXT07 "The U.A.C. had some good" +#define C_END2_TXT08 "reason to hide this place." +#define C_END2_TXT09 " " +#define C_END2_TXT10 "You wonder what it" +#define C_END2_TXT11 "could be..." + +#define C_END3_TXT01 "You smile." +#define C_END3_TXT02 " " +#define C_END3_TXT03 "What strange place have" +#define C_END3_TXT04 "you stumbled upon?" +#define C_END3_TXT05 " " +#define C_END3_TXT06 "The Demons did not expect" +#define C_END3_TXT07 "you to survive this far." +#define C_END3_TXT08 "You feel their demonic" +#define C_END3_TXT09 "presence waiting for you..." +#define C_END3_TXT10 " " +#define C_END3_TXT11 "Let them taste their guts!" + +#define C_END4_TXT01 "You wretch as a strange" +#define C_END4_TXT02 "acrid odor assaults you." +#define C_END4_TXT03 " " +#define C_END4_TXT04 "Death and Demon carcass!" +#define C_END4_TXT05 " " +#define C_END4_TXT06 "No nightmare could have" +#define C_END4_TXT07 "prepared you for this." +#define C_END4_TXT08 " " +#define C_END4_TXT09 "You realize that this" +#define C_END4_TXT10 "place was not meant for" +#define C_END4_TXT11 "living humans." + +#define C_END5_TXT01 "Congratulations!" +#define C_END5_TXT02 "You found..." +#define C_END5_TXT03 " " +#define C_END5_TXT04 "HECTIC" +#define C_END5_TXT05 " " +#define C_END5_TXT06 "Only the best will reap" +#define C_END5_TXT07 "its rewards." + +#define C_END6_TXT01 "Finally..." +#define C_END6_TXT02 "The mother of all demons" +#define C_END6_TXT03 "is dead!" +#define C_END6_TXT04 " " +#define C_END6_TXT05 "The blood pours from" +#define C_END6_TXT06 "your eyes as you stand" +#define C_END6_TXT07 "in defiance." +#define C_END6_TXT08 " " +#define C_END6_TXT09 "As the only marine to" +#define C_END6_TXT10 "endure the slaughter-" +#define C_END6_TXT11 "you decide to remain" +#define C_END6_TXT12 "in Hell and ensure no" +#define C_END6_TXT13 "demon ever rises again." +#define C_END6_TXT14 " " +#define C_END6_TXT15 "The End." + +char *endcluster1[] = // 8005A2C0 +{ + C_END1_TXT01, + C_END1_TXT02, + C_END1_TXT03, + C_END1_TXT04, + C_END1_TXT05, + C_END1_TXT06, + C_END1_TXT07, + C_END1_TXT08, + C_END1_TXT09, + C_END1_TXT10, + C_END1_TXT11, + C_END1_TXT12, + C_END1_TXT13, + C_END1_TXT14, + C_END1_TXT15, + T_NULL +}; + +char *endcluster2[] = // 8005A300 +{ + C_END2_TXT01, + C_END2_TXT02, + C_END2_TXT03, + C_END2_TXT04, + C_END2_TXT05, + C_END2_TXT06, + C_END2_TXT07, + C_END2_TXT08, + C_END2_TXT09, + C_END2_TXT10, + C_END2_TXT11, + T_NULL +}; + +char *endcluster3[] = // 8005A330 +{ + C_END3_TXT01, + C_END3_TXT02, + C_END3_TXT03, + C_END3_TXT04, + C_END3_TXT05, + C_END3_TXT06, + C_END3_TXT07, + C_END3_TXT08, + C_END3_TXT09, + C_END3_TXT10, + C_END3_TXT11, + T_NULL +}; + +char *endcluster4[] = // 8005A360 +{ + C_END4_TXT01, + C_END4_TXT02, + C_END4_TXT03, + C_END4_TXT04, + C_END4_TXT05, + C_END4_TXT06, + C_END4_TXT07, + C_END4_TXT08, + C_END4_TXT09, + C_END4_TXT10, + C_END4_TXT11, + T_NULL +}; + +char *endcluster5[] = // 8005A390 +{ + C_END5_TXT01, + C_END5_TXT02, + C_END5_TXT03, + C_END5_TXT04, + C_END5_TXT05, + C_END5_TXT06, + C_END5_TXT07, + T_NULL +}; + +char *endcluster6[] = // 8005A3B0 +{ + C_END6_TXT01, + C_END6_TXT02, + C_END6_TXT03, + C_END6_TXT04, + C_END6_TXT05, + C_END6_TXT06, + C_END6_TXT07, + C_END6_TXT08, + C_END6_TXT09, + C_END6_TXT10, + C_END6_TXT11, + C_END6_TXT12, + C_END6_TXT13, + C_END6_TXT14, + C_END6_TXT15, + T_NULL +}; + +// +// Character cast strings F_FINALE.C +// +#define CC_ZOMBIE "Zombieman" +#define CC_SHOTGUN "Shotgun Guy" +//#define CC_HEAVY "Heavy Weapon Dude" // Enemy Removed +#define CC_IMP "Imp" +#define CC_NIMP "Nightmare Imp" // New Enemy on Doom64 +#define CC_DEMON "Demon" +#define CC_SPECT "Spectre" // New Enemy on Doom64 +#define CC_LOST "Lost Soul" +#define CC_CACO "Cacodemon" +#define CC_HELL "Hell Knight" +#define CC_BARON "Baron Of Hell" +#define CC_ARACH "Arachnotron" +#define CC_PAIN "Pain Elemental" +//#define CC_REVEN "Revenant" // Enemy Removed +#define CC_MANCU "Mancubus" +//#define CC_ARCH "Arch-Vile" // Enemy Removed +//#define CC_SPIDER "The Spider Mastermind" // Enemy Removed +#define CC_CYBER "The Cyberdemon" +#define CC_HERO "Our Hero" + +// +// Final DOOM 2 animation +// Casting by id Software. +// in order of appearance +// +typedef struct +{ + char *name; + mobjtype_t type; +} castinfo_t; + +static castinfo_t castorder[] = // 8005A3F0 +{ + { CC_ZOMBIE, MT_POSSESSED1 },// MT_POSSESSED + { CC_SHOTGUN, MT_POSSESSED2 },// MT_SHOTGUY + //{ CC_HEAVY, MT_CHAINGUY }, + { CC_IMP, MT_IMP1 },// MT_TROOP + { CC_NIMP, MT_IMP2 },// MT_TROOP2 + { CC_DEMON, MT_DEMON1 },// MT_SERGEANT + { CC_SPECT, MT_DEMON2 },// MT_SERGEANT2 + { CC_LOST, MT_SKULL },// MT_SKULL + { CC_CACO, MT_CACODEMON },// MT_HEAD + { CC_HELL, MT_BRUISER2 },// MT_KNIGHT + { CC_BARON, MT_BRUISER1 },// MT_BRUISER + { CC_ARACH, MT_BABY },// MT_BABY + { CC_PAIN, MT_PAIN },// MT_PAIN + //{ CC_REVEN, MT_UNDEAD }, + { CC_MANCU, MT_MANCUBUS },// MT_FATSO + //{ CC_ARCH, MT_VILE }, + //{ CC_SPIDER, MT_SPIDER }, + { CC_CYBER, MT_CYBORG },// MT_CYBORG + { CC_HERO, MT_PLAYER },// MT_PLAYER + { NULL, 0 } +}; + +typedef enum +{ + F_STAGE_FADEIN_BACKGROUD, + F_STAGE_DRAWTEXT, + F_STAGE_SCROLLTEXT, + F_STAGE_FADEOUT_BACKGROUD, + F_STAGE_CAST +} finalestage_t; + +static int textypos; // 800631F0 +static int textline; // 800631F4 +static char **text; // 800631F8 +static int textalpha; // 800631FC + +/* +================= += += F_StartIntermission += +================= +*/ + +void F_StartIntermission(void) // 80002CD0 +{ + if ((gamemap == 8) && (nextmap == 9)) + { + text = endcluster1; + textypos = 15; + } + else if ((gamemap == 4) && (nextmap == 29)) + { + text = endcluster2; + textypos = 43; + } + else if ((gamemap == 12) && (nextmap == 30)) + { + text = endcluster3; + textypos = 43; + } + else if ((gamemap == 18) && (nextmap == 31)) + { + text = endcluster4; + textypos = 43; + } + else if ((gamemap == 1) && (nextmap == 32)) + { + text = endcluster5; + textypos = 71; + } + + DrawerStatus = 2; + textline = 0; + textalpha = 0; +} + +/* +================= += += F_StopIntermission += +================= +*/ + +void F_StopIntermission(void) // 80002E14 +{ + gamepaused = false; + DrawerStatus = 0; + I_WIPE_FadeOutScreen(); +} + +/* +================= += += F_TickerIntermission += +================= +*/ + +int F_TickerIntermission(void) // 80002E44 +{ + unsigned int buttons, oldbuttons, exit; + + gameaction = ga_nothing; + P_CheckCheats(); + + exit = gameaction; + if (!gamepaused) + { + buttons = ticbuttons[0] & 0xffff0000; + oldbuttons = oldticbuttons[0] & 0xffff0000; + + exit = ga_nothing; + + if(*text[textline]) + { + textalpha += 8; + if (textalpha > 255) + { + textalpha = 0; + textline++; + } + } + else if ((buttons != oldbuttons) && (buttons & (ALL_CBUTTONS|ALL_TRIG|PAD_A|PAD_B))) + { + exit = ga_exit; + } + } + + return exit; +} + +/* +================= += += F_DrawerIntermission += +================= +*/ + +void F_DrawerIntermission(void) // 80002F14 +{ + int i, ypos; + I_ClearFrame(); + + gDPPipeSync(GFX1++); + gDPSetCycleType(GFX1++, G_CYC_FILL); + gDPSetRenderMode(GFX1++,G_RM_NOOP,G_RM_NOOP2); + gDPSetColorImage(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_32b, SCREEN_WD, OS_K0_TO_PHYSICAL(cfb[vid_side])); + // Fill borders with black + gDPSetFillColor(GFX1++, GPACK_RGBA5551(0,0,0,0) << 16 | GPACK_RGBA5551(0,0,0,0)) ; + gDPFillRectangle(GFX1++, 0, 0, SCREEN_WD-1, SCREEN_HT-1); + + M_DrawBackground(63, 25, 128, "EVIL"); + + ypos = textypos; + for(i = 0; i < textline; i++) + { + ST_DrawString(-1, ypos, text[i], 0xc0c0c0ff); + ypos += 14; + } + + ST_DrawString(-1, ypos, text[i], textalpha | 0xc0c0c000); + + if (MenuCall) + { + M_DrawOverlay(0, 0, 320, 240, 96); + MenuCall(); + } + + I_DrawFrame(); +} + +static finalestage_t finalestage; // 80063200 +static int castnum; // 80063204 +static int casttics; // 80063208 +static state_t *caststate; // 8006320C +static boolean castdeath; // 80063210 +static int castframes; // 80063214 +static int castonmelee; // 80063218 +static int castrotation; // 8006321C +static int castfadein; // 80063220 +static int fadeinout; // 80063224 + +/* +================= += += F_Start/Cast_Start += +================= +*/ + +void F_Start(void) // 8000313C +{ + DrawerStatus = 3; + finalestage = F_STAGE_FADEIN_BACKGROUD; + fadeinout = 0; + textypos = 15; + textline = 0; + textalpha = 0; + castnum = 0; + caststate = &states[mobjinfo[castorder[castnum].type].seestate]; + casttics = states[mobjinfo[castorder[castnum].type].seestate].tics; + castdeath = false; + castframes = 0; + castonmelee = 0; + castrotation = 0; + castfadein = 0; + + S_StartMusic(113); +} + +/* +================= += += F_Stop/Cast_Stop += +================= +*/ + +void F_Stop(void) // 80003220 +{ + gamepaused = false; + DrawerStatus = 0; + S_StopMusic(); + I_WIPE_FadeOutScreen(); +} + +/* +================= += += F_Ticker/Cast_Ticker += +================= +*/ + +int F_Ticker(void) // 80003258 +{ + unsigned int buttons, oldbuttons; + int st, sfx; + + buttons = ticbuttons[0] = M_ButtonResponder(ticbuttons[0]); + oldbuttons = oldticbuttons[0] & 0xffff0000; + + gameaction = ga_nothing; + P_CheckCheats(); + + if (gamepaused != 0) + { + return gameaction; + } + + switch(finalestage) + { + case F_STAGE_FADEIN_BACKGROUD: + fadeinout += 6; + if (fadeinout > 160) + { + fadeinout = 160; + finalestage = F_STAGE_DRAWTEXT; + } + break; + + case F_STAGE_DRAWTEXT: + if (*endcluster6[textline]) + { + textalpha += 8; + if (textalpha > 255) + { + textalpha = 0; + textline++; + } + } + else + { + finalestage = F_STAGE_SCROLLTEXT; + } + break; + + case F_STAGE_SCROLLTEXT: + textypos -= 1; + if (textypos < -200) + { + finalestage = F_STAGE_FADEOUT_BACKGROUD; + } + break; + + case F_STAGE_FADEOUT_BACKGROUD: + fadeinout -= 6; + if (fadeinout < 0) + { + fadeinout = 0; + finalestage = F_STAGE_CAST; + } + break; + + case F_STAGE_CAST: + fadeinout += 6; + if (fadeinout > 128) + { + fadeinout = 128; + } + + if (castdeath == false) + { + if (buttons != oldbuttons) + { + if (buttons & PAD_LEFT) + { + castrotation += 1; + if (castrotation > 7) { + castrotation = 0; + } + } + else if (buttons & PAD_RIGHT) + { + castrotation -= 1; + if (castrotation < 0) { + castrotation = 7; + } + } + else if (buttons & (ALL_CBUTTONS|ALL_TRIG|PAD_A|PAD_B)) + { + S_StartSound(NULL, sfx_shotgun); // sfx_shotgn + + /* go into death frame */ + if (mobjinfo[castorder[castnum].type].deathsound) + S_StartSound(NULL, mobjinfo[castorder[castnum].type].deathsound); + + caststate = &states[mobjinfo[castorder[castnum].type].deathstate]; + castframes = 0; + castdeath = true; + + if(castorder[castnum].type == MT_CYBORG) { + casttics = 10; + } + else { + casttics = caststate->tics; + } + + } + } + } + + if (gametic > gamevbls) + { + if (castfadein < 192) { + castfadein += 2; + } + + /* advance state*/ + if (--casttics > 0) + return ga_nothing; /* not time to change state yet */ + + if (castdeath && caststate->nextstate == S_000) // S_NULL + { + /* switch from deathstate to next monster */ + castrotation = 0; + castnum++; + castfadein = 0; + castdeath = false; + + if (castorder[castnum].name == NULL) + castnum = 0; + + if (mobjinfo[castorder[castnum].type].seesound) + S_StartSound(NULL, mobjinfo[castorder[castnum].type].seesound); + + caststate = &states[mobjinfo[castorder[castnum].type].seestate]; + castframes = 0; + } + + st = caststate->nextstate; + caststate = &states[st]; + + if (castdeath == false) + { + castframes++; + + if (castframes == 12) + { /* go into attack frame */ + if (castonmelee) + caststate = &states[mobjinfo[castorder[castnum].type].meleestate]; + else + caststate = &states[mobjinfo[castorder[castnum].type].missilestate]; + + castonmelee ^= 1; + + if (caststate == &states[S_000]) // S_NULL + { + if (castonmelee) + caststate = &states[mobjinfo[castorder[castnum].type].meleestate]; + else + caststate = &states[mobjinfo[castorder[castnum].type].missilestate]; + } + } + + if (((castframes == 20) && (castorder[castnum].type == MT_MANCUBUS)) || + castframes == 24 || caststate == &states[S_001])//S_PLAY + { + caststate = &states[mobjinfo[castorder[castnum].type].seestate]; + castframes = 0; + } + } + + casttics = caststate->tics; + if (casttics == -1) + casttics = TICRATE; + + /* sound hacks.... */ + st = ((int)caststate - (int)states) / sizeof(state_t); + switch (st) + { + case S_007: // S_PLAY_ATK2 + sfx = sfx_sht2fire; // sfx_dshtgn + break; + + case S_055: // S_SARG_ATK2 + sfx = sfx_sargatk; // sfx_sgtatk + break; + + case S_084: // S_FATT_ATK8 + case S_086: // S_FATT_ATK5 + case S_088: // S_FATT_ATK2 + sfx = sfx_bdmissile; // sfx_firsht + break; + + case S_109: // S_POSS_ATK2 + sfx = sfx_pistol; + break; + + case S_138: // S_SPOS_ATK2 + sfx = sfx_shotgun; // sfx_shotgn + break; + + case S_166: // S_TROO_ATK3 + sfx = sfx_scratch; // sfx_claw + break; + + case S_169: // S_TROO_ATK + case S_199: // S_HEAD_ATK2 + case S_222: // S_BOSS_ATK2 + case S_243: // S_BOS2_ATK2 + sfx = sfx_bdmissile; // sfx_firsht + break; + + case S_261: // S_SKULL_ATK2 + sfx = sfx_skullatk; // sfx_sklatk + break; + + case S_288: // S_BSPI_ATK2 + sfx = sfx_plasma; // sfx_plasma + break; + + case S_307: // S_CYBER_ATK2 + case S_309: // S_CYBER_ATK4 + case S_311: // S_CYBER_ATK6 + sfx = sfx_missile; // sfx_rlaunc + break; + + case S_328: // S_PAIN_ATK3 + sfx = sfx_skullatk; // sfx_sklatk + break; + + //case S_VILE_ATK2: + //sfx = sfx_vilatk; + //break; + + //case S_SKEL_FIST2: + //sfx = sfx_skeswg; + //break; + + //case S_SKEL_FIST4: + //sfx = sfx_skepch; + //break; + + //case S_SKEL_MISS2: + //sfx = sfx_skeatk; + //break; + + //case S_CPOS_ATK2: + //case S_CPOS_ATK3: + //case S_CPOS_ATK4: + //sfx = sfx_pistol; + //break; + + //case S_SPID_ATK2: + //case S_SPID_ATK3: + //sfx = sfx_pistol; + //break; + + default: + sfx = 0; + break; + } + + if (sfx) + S_StartSound(NULL, sfx); + } + + break; + + default: + break; + } + + return ga_nothing; +} + +/* +================= += += F_Drawer/Cast_Drawer += +================= +*/ +void F_Drawer(void) // 800039DC +{ + int i, type, alpha, ypos; + char buff[64]; + + I_ClearFrame(); + + gDPPipeSync(GFX1++); + gDPSetCycleType(GFX1++, G_CYC_FILL); + gDPSetRenderMode(GFX1++,G_RM_NOOP,G_RM_NOOP2); + gDPSetColorImage(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_32b, SCREEN_WD, OS_K0_TO_PHYSICAL(cfb[vid_side])); + // Fill borders with black + gDPSetFillColor(GFX1++, GPACK_RGBA5551(0,0,0,0) << 16 | GPACK_RGBA5551(0,0,0,0)) ; + gDPFillRectangle(GFX1++, 0, 0, SCREEN_WD-1, SCREEN_HT-1); + + switch(finalestage) + { + case F_STAGE_FADEIN_BACKGROUD: + case F_STAGE_FADEOUT_BACKGROUD: + M_DrawBackground(0, 0, fadeinout, "FINAL"); + break; + + case F_STAGE_DRAWTEXT: + case F_STAGE_SCROLLTEXT: + M_DrawBackground(0, 0, fadeinout, "FINAL"); + + ypos = textypos; + for(i = 0; i < textline; i++) + { + ST_DrawString(-1, ypos, endcluster6[i], 0xc0c0c0ff); + ypos += 14; + } + + ST_DrawString(-1, ypos, endcluster6[i], textalpha | 0xc0c0c000); + break; + + case F_STAGE_CAST: + M_DrawBackground(63, 25, fadeinout, "EVIL"); + + type = castorder[castnum].type; + + if (type == MT_DEMON2){ + alpha = 48; + } + else { + alpha = mobjinfo[type].alpha; + } + + BufferedDrawSprite(type, caststate, castrotation, + PACKRGBA(castfadein, castfadein, castfadein, alpha), 160, 190); + + ST_DrawString(-1, 208, castorder[castnum].name, 0xC00000ff); + break; + + default: + break; + } + + if (MenuCall) + { + M_DrawOverlay(0, 0, 320, 240, 96); + MenuCall(); + } + + I_DrawFrame(); +} + +void BufferedDrawSprite(int type, state_t *state, int rotframe, int color, int xpos, int ypos) // 80003D1C +{ + spritedef_t *sprdef; + spriteframe_t *sprframe; + int lump; + boolean flip; + + byte *data; + byte *paldata; + byte *src; + + int compressed; + int tileh; + int tilew; + int height; + int width; + int width2; + int tiles; + int xoffs; + int yoffs; + + int tilecnt; + int dsdx; + int spos; + int tpos; + int x1; + int y1; + int xh; + int yh; + + // draw the current frame in the middle of the screen + sprdef = &sprites[state->sprite]; + sprframe = &sprdef->spriteframes[state->frame & FF_FRAMEMASK]; + lump = sprframe->lump[rotframe]; + flip = (boolean)sprframe->flip[rotframe]; + + gDPPipeSync(GFX1++); + gDPSetCycleType(GFX1++, G_CYC_1CYCLE); + gDPSetTexturePersp(GFX1++, G_TP_NONE); + gDPSetTextureLUT(GFX1++, G_TT_RGBA16); + gDPSetAlphaCompare(GFX1++, G_AC_THRESHOLD); + gDPSetBlendColor(GFX1++, 0, 0, 0, 0); + gDPSetCombineMode(GFX1++, G_CC_D64COMB04, G_CC_D64COMB04); + + gDPSetPrimColorD64(GFX1++, 0, 0, color); + + if ((color & 255) < 255) { + gDPSetRenderMode(GFX1++, G_RM_XLU_SURF_CLAMP, G_RM_XLU_SURF2_CLAMP); + } + else { + gDPSetRenderMode(GFX1++, G_RM_TEX_EDGE, G_RM_TEX_EDGE2); + } + + + data = W_CacheLumpNum(lump, PU_CACHE, dec_jag); + + compressed = ((spriteN64_t*)data)->compressed; + tileh = ((spriteN64_t*)data)->tileheight; + width = ((spriteN64_t*)data)->width; + height = ((spriteN64_t*)data)->height; + tiles = ((spriteN64_t*)data)->tiles; + xoffs = ((spriteN64_t*)data)->xoffs; + yoffs = ((spriteN64_t*)data)->yoffs; + + src = data + sizeof(spriteN64_t); + + if (compressed < 0) + { + width2 = width + 7 & ~7; + tilew = tileh * width2; + + if (((spriteN64_t*)data)->cmpsize & 1) + { + paldata = W_CacheLumpNum(((mobjinfo[type].palette + lump) - + (((spriteN64_t*)data)->cmpsize >> 1)), PU_CACHE, dec_jag) + 8; + } + else + { + paldata = (src + ((spriteN64_t*)data)->cmpsize); + } + + /* Load Palette Data (256 colors) */ + gDPSetTextureImage(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_16b , 1, paldata); + + gDPTileSync(GFX1++); + gDPSetTile(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_4b, 0, 256, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0); + + gDPLoadSync(GFX1++); + gDPLoadTLUTCmd(GFX1++, G_TX_LOADTILE, 255); + + gDPPipeSync(GFX1++); + } + else + { + width2 = width + 15 & ~15; + tilew = tileh * width2; + + if (tilew < 0) { + tilew = tilew + 1; + } + + tilew >>= 1; + + /* Load Palette Data (16 colors) */ + gDPSetTextureImage(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_16b , 1, (src + ((spriteN64_t*)data)->cmpsize)); + + gDPTileSync(GFX1++); + gDPSetTile(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_4b, 0, 256, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0); + + gDPLoadSync(GFX1++); + gDPLoadTLUTCmd(GFX1++, G_TX_LOADTILE, 15); + + gDPPipeSync(GFX1++); + } + + if (!flip) + { + x1 = (xpos - xoffs) << 2; + xh = (x1 + (width << 2)); + spos = 0; + dsdx = 1; + } + else + { + xh = (xpos + xoffs) << 2; + x1 = (xh - (width << 2)); + spos = (width - 1); + dsdx = 63; + } + + y1 = (ypos - yoffs) << 2; + + if (tiles > 0) + { + do + { + if (tileh < height) + tpos = tileh; + else + tpos = height; + + if (compressed < 0) + { + /* Load Image Data (8bit) */ + gDPSetTextureImage(GFX1++, G_IM_FMT_CI, G_IM_SIZ_16b , 1, src); + gDPSetTile(GFX1++, G_IM_FMT_CI, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0); + + gDPLoadSync(GFX1++); + gDPLoadBlock(GFX1++, G_TX_LOADTILE, 0, 0, ((width2 * tpos + 1) >> 1) - 1, 0); + + gDPPipeSync(GFX1++); + gDPSetTile(GFX1++, G_IM_FMT_CI, G_IM_SIZ_8b, ((width2 + 7) >> 3), 0, + G_TX_RENDERTILE , 0, 0, 0, 0, 0, 0, 0); + + gDPSetTileSize(GFX1++, G_TX_RENDERTILE, 0, 0, ((width2 - 1) << 2), (tpos - 1) << 2); + } + else + { + /* Load Image Data (4bit) */ + gDPSetTextureImage(GFX1++, G_IM_FMT_CI, G_IM_SIZ_16b , 1, src); + gDPSetTile(GFX1++, G_IM_FMT_CI, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0); + + gDPLoadSync(GFX1++); + gDPLoadBlock(GFX1++, G_TX_LOADTILE, 0, 0, ((width2 * tpos + 3) >> 2) - 1, 0); + + gDPPipeSync(GFX1++); + gDPSetTile(GFX1++, G_IM_FMT_CI, G_IM_SIZ_4b, (((width2>>1) + 7) >> 3), 0, + G_TX_RENDERTILE , 0, 0, 0, 0, 0, 0, 0); + + gDPSetTileSize(GFX1++, G_TX_RENDERTILE, 0, 0, ((width2 - 1) << 2), (tpos - 1) << 2); + } + + yh = (y1 + (tpos << 2)); + + gSPTextureRectangle(GFX1++, + x1, y1, + xh, yh, + G_TX_RENDERTILE, + (spos << 5), (0 << 5), + (dsdx << 10), (1 << 10)); + + height -= tpos; + + src += tilew; + y1 = yh; + tilecnt += 1; + } while (tilecnt != tiles); + } + + globallump = -1; +} diff --git a/Doom 64/funqueue.c b/Doom 64/funqueue.c @@ -0,0 +1,144 @@ +/* WESS API INCLUDES */ +#include "wessapi.h" // audio stuff... +#include "seqload.h" +#include "soundhw.h" +#include "wessarc.h" +#include "wessseq.h" + +#include "funqueue.h" + +#include "graph.h" + +#ifndef NOUSEWESSCODE + +extern void run_queue_wess_seq_stopall(void); +extern void run_queue_wess_seq_stop(void); + +extern void run_queue_wess_master_sfx_vol_set(void); +extern void run_queue_wess_master_mus_vol_set(void); +extern void run_queue_wess_handle_parm_mod(void); +extern void run_queue_wess_handle_noteon(void); + +extern void run_queue_wess_seq_pause(void); +extern void run_queue_wess_seq_restart(void); +extern void run_queue_wess_seq_pauseall(void); +extern void run_queue_wess_seq_restartall(void); + +extern void run_queue_wess_seq_stoptype(void); +extern void run_queue_wess_seq_update_type_special(void); +extern void run_queue_wess_seq_stopall_and_voiceramp(void); +extern void run_queue_wess_seq_stop_and_voiceramp(void); +extern void run_queue_wess_seq_stoptype_and_voiceramp(void); + +static void(*FuncQueueArr[15])(void) = //8005D9A0 +{ + run_queue_wess_seq_stopall, //QUEUE_SEQ_STOPALL + run_queue_wess_seq_stop, //QUEUE_SEQ_STOP + run_queue_wess_master_sfx_vol_set, //QUEUE_MASTER_SFX_VOL_SET + run_queue_wess_master_mus_vol_set, //QUEUE_MASTER_MUS_VOL_SET + run_queue_wess_handle_parm_mod, //QUEUE_HANDLE_PARM_MOD + run_queue_wess_handle_noteon, //QUEUE_HANDLE_NOTEON + run_queue_wess_seq_pause, //QUEUE_SEQ_PAUSE + run_queue_wess_seq_restart, //QUEUE_SEQ_RESTART + run_queue_wess_seq_pauseall, //QUEUE_SEQ_PAUSEALL + run_queue_wess_seq_restartall, //QUEUE_SEQ_RESTARTALL + run_queue_wess_seq_stoptype, //QUEUE_SEQ_STOPTYPE + run_queue_wess_seq_update_type_special, //QUEUE_SEQ_UPDATE_TYPE_SPECIAL + run_queue_wess_seq_stopall_and_voiceramp, //QUEUE_SEQ_STOPALL_AND_VOICERAMP + run_queue_wess_seq_stop_and_voiceramp, //QUEUE_SEQ_STOP_AND_VOICERAMP + run_queue_wess_seq_stoptype_and_voiceramp //QUEUE_SEQ_STOPTYPE_AND_VOICERAMP +}; + +static int func_num = 0; //8005D9DC +static int func_num_arr = 0; //8005D9E0 +static QUEUE_DATA_MEMORY queue_data_mem; //800B4420 +static char *queue_write_ptr = queue_data_mem.data; //8005D9E4 +static char *queue_read_ptr; //800B6620 + +void queue_memcpy(void *dest, void *src, int size) // 80035CC0 +{ + char *d, *s; + + d = (char *)dest; + s = (char *)src; + while (size--) + { + *d++ = *s++; + } +} + +void queue_the_function(char mode) // 80035CF0 +{ + if (func_num_arr == 0) + { + if (func_num < MAX_QUEUE_FUNCTION_SIZE) + { + queue_data_mem.function[func_num] = mode; + func_num += 1; + return; + } + func_num_arr = 1; + } + return; +} + +void queue_the_data(void *src, int size) // 80035D48 +{ + int memsize; + + if (func_num_arr == 0) + { + memsize = queue_data_mem.data - queue_write_ptr + MAX_QUEUE_DATA_SIZE; + + if (memsize < size) + { + if (func_num > 0) + func_num -= 1; + + func_num_arr = 1; + } + else + { + queue_memcpy(queue_write_ptr, src, size); + queue_write_ptr += size; + } + } + return; +} + +void unqueue_the_data(void *dest, int size) // 80035DF4 +{ + queue_memcpy(dest, queue_read_ptr, size); + queue_read_ptr += size; +} + +void process_function_queue(void) // 80035E38 +{ + char *func; + int i; + + //PRINTF_D2(WHITE,0,10,"process_function_queue"); + //PRINTF_D2(WHITE,0,11,"func_num %d",func_num); + + func_num_arr = 0; + + //init queue_read_ptr + queue_read_ptr = (char *)&queue_data_mem.data; + + func = queue_data_mem.function; + for (i = 0; i < func_num; i++) + { + //PRINTF_D(WHITE,"*func %d",*func); + FuncQueueArr[*func](); + func++; + } + + //restore queue_write_ptr + wess_disable(); + func_num = 0; + queue_write_ptr = (char *)&queue_data_mem.data; + wess_enable(); + return; +} + +#endif diff --git a/Doom 64/funqueue.h b/Doom 64/funqueue.h @@ -0,0 +1,18 @@ +#ifndef _FUNQUEUE_H +#define _FUNQUEUE_H + +#define MAX_QUEUE_DATA_SIZE 8192 +#define MAX_QUEUE_FUNCTION_SIZE 512 + +typedef struct +{ + char data[MAX_QUEUE_DATA_SIZE]; //800B4420 + char function[MAX_QUEUE_FUNCTION_SIZE]; //800B6420 +} QUEUE_DATA_MEMORY; + +extern void queue_memcpy(void *dest, void *src, int size); +extern void queue_the_function(char mode); +extern void queue_the_data(void *src, int size); +extern void unqueue_the_data(void *dest, int size); +extern void process_function_queue(void); +#endif diff --git a/Doom 64/g_game.c b/Doom 64/g_game.c @@ -0,0 +1,348 @@ +/* G_game.c */ + +#include "doomdef.h" +#include "p_local.h" + +void G_PlayerReborn (int player); + +void G_DoReborn (int playernum); + +void G_DoLoadLevel (void); + + +gameaction_t gameaction; // 80063230 +skill_t gameskill; // 80063234 +int gamemap; // 80063238 +int nextmap; // 8006323C /* the map to go to after the stats */ + +//boolean playeringame[MAXPLAYERS]; // +player_t players[MAXPLAYERS]; // 80063240 + +int consoleplayer; /* player taking events and displaying */ +int displayplayer; /* view being displayed */ +int gametic; +int totalkills, totalitems, totalsecret; /* for intermission */ + +//char demoname[32]; +boolean demorecording; // 800633A4 +boolean demoplayback; // 800633A8 +int *demo_p = NULL, *demobuffer = NULL; // 8005A180, 8005a184 + +//mapthing_t deathmatchstarts[10], *deathmatch_p; // 80097e4c, 80077E8C +mapthing_t playerstarts[MAXPLAYERS]; // 800a8c60 + +/* +============== += += G_DoLoadLevel += +============== +*/ + +void G_DoLoadLevel (void) // 80004530 +{ + if (((gameaction == 7) || (gameaction == 4)) || (players[0].playerstate == PST_DEAD)) + players[0].playerstate = PST_REBORN; + + P_SetupLevel(gamemap, gameskill); + gameaction = ga_nothing; +} + + +/* +============================================================================== + + PLAYER STRUCTURE FUNCTIONS + +also see P_SpawnPlayer in P_Mobj +============================================================================== +*/ + +/* +==================== += += G_PlayerFinishLevel += += Can when a player completes a level +==================== +*/ + +void G_PlayerFinishLevel (int player) // 80004598 +{ + player_t *p; + + p = &players[player]; + + D_memset (p->powers, 0, sizeof (p->powers)); + D_memset (p->cards, 0, sizeof (p->cards)); + p->mo->flags &= ~MF_SHADOW; /* cancel invisibility */ + p->extralight = 0; /* cancel gun flashes */ + p->damagecount = 0; /* no palette changes */ + p->bonuscount = 0; + p->bfgcount = 0; + p->automapflags = 0; + p->messagetic = 0; +} + +/* +==================== += += G_PlayerReborn += += Called after a player dies += almost everything is cleared and initialized +==================== +*/ + +int gobalcheats = 0; // [GEC] + +void G_PlayerReborn (int player) // 80004630 +{ + player_t *p; + + p = &players[player]; + D_memset(p, 0, sizeof(*p)); + + p->usedown = p->attackdown = true; // don't do anything immediately + p->playerstate = PST_LIVE; + p->health = MAXHEALTH; + p->readyweapon = p->pendingweapon = wp_pistol; + p->weaponowned[wp_fist] = true; + p->weaponowned[wp_pistol] = true; + p->ammo[am_clip] = 50; + p->maxammo[am_clip] = maxammo[am_clip]; + p->maxammo[am_shell] = maxammo[am_shell]; + p->maxammo[am_cell] = maxammo[am_cell]; + p->maxammo[am_misl] = maxammo[am_misl]; + + p->cheats |= gobalcheats; // [GEC] Apply global cheat codes +} + +/*============================================================================ */ + +/* +==================== += += G_CompleteLevel += +==================== +*/ + +void G_CompleteLevel (void) // 800046E4 +{ + gameaction = ga_completed; +} + +/* +==================== += += G_InitNew += +==================== +*/ + +extern int ActualConfiguration[13]; +mobj_t emptymobj; // 80063158 + +void G_InitNew (skill_t skill, int map, gametype_t gametype) // 800046F4 +{ + //printf ("G_InitNew, skill %d, map %d\n", skill, map); + + /* free all tags except the PU_STATIC tag */ + Z_FreeTags(mainzone, ~PU_STATIC); // (PU_LEVEL | PU_LEVSPEC | PU_CACHE) + + M_ClearRandom (); + +/* force players to be initialized upon first level load */ + players[0].playerstate = PST_REBORN; + +/* these may be reset by I_NetSetup */ + gameskill = skill; + gamemap = map; + + D_memset(&emptymobj, 0, sizeof(emptymobj)); + players[0].mo = &emptymobj; /* for net consistancy checks */ + + demorecording = false; + demoplayback = false; + + BT_DATA[0] = (buttons_t *)ActualConfiguration; + + /*if (skill == sk_nightmare) + { + states[S_SARG_ATK1].tics = 2; + states[S_SARG_ATK2].tics = 2; + states[S_SARG_ATK3].tics = 2; + mobjinfo[MT_SERGEANT].speed = 15; + + mobjinfo[MT_BRUISERSHOT].speed = 40*FRACUNIT; + mobjinfo[MT_HEADSHOT].speed = 40*FRACUNIT; + mobjinfo[MT_TROOPSHOT].speed = 40*FRACUNIT; + } + else + { + states[S_SARG_ATK1].tics = 4; + states[S_SARG_ATK2].tics = 4; + states[S_SARG_ATK3].tics = 4; + mobjinfo[MT_SERGEANT].speed = 10; + + mobjinfo[MT_BRUISERSHOT].speed = 30*FRACUNIT; + mobjinfo[MT_HEADSHOT].speed = 20*FRACUNIT; + mobjinfo[MT_TROOPSHOT].speed = 20*FRACUNIT; + }*/ +} + +/*============================================================================ */ + +/* +================= += += G_RunGame += += The game should allready have been initialized or laoded +================= +*/ + +void G_RunGame (void) // 80004794 +{ + + while (1) + { + /* load a level */ + G_DoLoadLevel (); + + //printf("RUN P_Start\n"); + //PRINTF_D2(WHITE, 0, 28, "RUN P_Start\n"); + /* run a level until death or completion */ + MiniLoop (P_Start, P_Stop, P_Ticker, P_Drawer); + + //if (gameaction == ga_recorddemo) + //G_RecordDemo(); + + if(gameaction == ga_warped) + continue; /* skip intermission */ + + if ((gameaction == ga_died) || (gameaction == ga_restart)) + continue; /* died, so restart the level */ + + if (gameaction == ga_exitdemo) + return; + + /* run a stats intermission */ + if (nextmap != 32) { + MiniLoop(IN_Start, IN_Stop, IN_Ticker, IN_Drawer); + } + + if(((gamemap == 8) && (nextmap == 9)) || + ((gamemap == 4) && (nextmap == 29)) || + ((gamemap == 12) && (nextmap == 30)) || + ((gamemap == 18) && (nextmap == 31)) || + ((gamemap == 1) && (nextmap == 32))) + { + /* run the intermission if needed */ + MiniLoop(F_StartIntermission, F_StopIntermission, F_TickerIntermission, F_DrawerIntermission); + + if(gameaction == ga_warped) + continue; /* skip intermission */ + + if(gameaction == ga_restart) + continue; + + if (gameaction == ga_exitdemo) + return; + } + else + { + if (nextmap >= LASTLEVEL) + { + /* run the finale if needed */ + MiniLoop(F_Start, F_Stop, F_Ticker, F_Drawer); + + if(gameaction == ga_warped) + continue; /* skip intermission */ + + if(gameaction == ga_restart) + continue; + else + return; + } + } + + /* Set Next Level */ + gamemap = nextmap; + } +} + +int G_PlayDemoPtr (int skill, int map) // 800049D0 +{ + int exit; + int config[13]; + int sensitivity; + + demobuffer = demo_p; + + /* copy key configuration */ + D_memcpy(config, ActualConfiguration, sizeof(config)); + + /* set new key configuration */ + D_memcpy(ActualConfiguration, demobuffer, sizeof(config)); + + /* copy analog m_sensitivity */ + sensitivity = M_SENSITIVITY; + + /* set new analog m_sensitivity */ + M_SENSITIVITY = demobuffer[13]; + + /* skip analog and key configuration */ + demobuffer += 14; + + /* play demo game */ + G_InitNew (skill, map, gt_single); + G_DoLoadLevel (); + demoplayback = true; + exit = MiniLoop (P_Start, P_Stop, P_Ticker, P_Drawer); + demoplayback = false; + + /* restore key configuration */ + D_memcpy(ActualConfiguration, config, sizeof(config)); + + /* restore analog m_sensitivity */ + M_SENSITIVITY = sensitivity; + + /* free all tags except the PU_STATIC tag */ + Z_FreeTags(mainzone, ~PU_STATIC); // (PU_LEVEL | PU_LEVSPEC | PU_CACHE) + + return exit; +} + +/* +================= += += G_RecordDemo += +================= +*/ + +void G_RecordDemo (void)//80013D0C +{ + #if 0 + demo_p = demobuffer = Z_Malloc (0x8000, PU_STATIC, NULL); + + *demo_p++ = startskill; + *demo_p++ = startmap; + + G_InitNew (startskill, startmap, gt_single); + G_DoLoadLevel (); + demorecording = true; + MiniLoop (P_Start, P_Stop, P_Ticker, P_Drawer); + demorecording = false; + + D_printf ("w %x,%x",demobuffer,demo_p); + + while (1) + { + G_PlayDemoPtr (demobuffer); + D_printf ("w %x,%x",demobuffer,demo_p); + } + #endif +} diff --git a/Doom 64/graph.c b/Doom 64/graph.c @@ -0,0 +1,462 @@ +/*==================================================================== + File : graph.c + + Created by Koji Mitsunari. Sep,11 1996. + Copyright by Nintendo, Co., Ltd. 1997. + ====================================================================*/ +#include <ultra64.h> +#include "i_main.h" +#include "graph.h" + +#if 0 + +extern u8 pat[][CHAR_HT]; + +#if BMP_DATA +#include "bmpdata.c" +#endif + +u32 __color; + +/*--------------------------------------------------------------------- + Display Big character on the screen + ---------------------------------------------------------------------*/ +void +bigputc(u32 color, int curs_x, int curs_y, char c, int xsize, int ysize) +{ + int i, j, k, l, x, y; + u16 *p; + + x = curs_x*CHAR_WD; + p = (u16 *)osViGetNextFramebuffer(); + + if ( ysize ) { + y = curs_y*CHAR_HT; + + for (j = 0; j < CHAR_HT; j ++) { + for (i = 0; i < 8; i ++) { + if (pat[c-0x20][j] & (1 << (8-i))) { + for (k = 0; k < xsize; k ++){ + for (l = 0; l < ysize; l ++){ + p[x + SCREEN_WD*(y-8+l) + k] = color; + } + } + } else { +#if 0 + for (k = 0; k < xsize; k ++){ + for (l = 0; l < ysize; l ++){ + p[x + SCREEN_WD*(y-8+l) + k] = BGCOLOR; + } + } +#endif + } + x += xsize; + } + x = curs_x*CHAR_WD; + y += ysize; + } + } else { + y = curs_y*CHAR_HT/2; + + for (j = 0; j < CHAR_HT; j += 2) { + for (i = CHAR_WD - 1; i >= 0; i --) { + if (pat[c-0x20][j] & (1 << i)) { + p[x + SCREEN_WD*(y-8)] = color; +#if 0 + } else { + p[x + SCREEN_WD*(y-8)] = BGCOLOR; +#endif + } + x++; + } + x = curs_x*CHAR_WD; + y ++; + } + } +} + +/*--------------------------------------------------------------------- + Display big character string on the screen + ---------------------------------------------------------------------*/ +void +printbig(u32 color, int curs_x, int curs_y, char *s, int xsize, int ysize) +{ + int i; + + for (i = 0 ; *s != NULL ; i ++){ + bigputc(color, curs_x + i*xsize, curs_y, *s++, xsize, ysize); + } +} + +/*--------------------------------------------------------------------- + Display character on the screen + ---------------------------------------------------------------------*/ +void +putchar(u32 color, int curs_x, int curs_y, char c) +{ + int i, j; + int x = curs_x*CHAR_WD; + int y = curs_y*CHAR_HT; + u8 *pc = pat[c-0x20]; + u16 *p = (u16 *)osViGetNextFramebuffer() + x + SCREEN_WD*(y-8); + + for (j = 0; j < CHAR_HT; j ++, pc++) { + for (i = CHAR_WD - 1; i >= 0; i --) { + if (*pc & (1 << i)) { + *p = color; + } else { + *p = BGCOLOR; + } + p ++; + } + p += SCREEN_WD - CHAR_WD; + } +} + +/*--------------------------------------------------------------------- + Display reverse character on the screen + ---------------------------------------------------------------------*/ +void revchar(u32 color, int curs_x, int curs_y, char c) +{ + int i, j; + int x = curs_x*CHAR_WD; + int y = curs_y*CHAR_HT; + u8 *pc = pat[c-0x20]; + u16 *p = (u16 *)osViGetNextFramebuffer() + x + SCREEN_WD*(y-8); + + for (j = 0; j < CHAR_HT; j ++, pc++) { + for (i = CHAR_WD - 1; i >= 0; i --) { + if (*pc & (1 << i)) { + *p = BGCOLOR; + } else { + *p = color; + } + p ++; + } + p += SCREEN_WD - CHAR_WD; + } +} + +/*--------------------------------------------------------------------- + Display hex-data on the screen + ---------------------------------------------------------------------*/ +void +putint_h(u32 color, int curs_x, int curs_y, int num, char c) { + int i, k; + + for (i = 0 ; i < c ; i ++) { + k = num % 16; + if (k > 9) { + putchar(color, curs_x - i, curs_y, k + 'A' - 10); + } else { + putchar(color, curs_x - i, curs_y, k + '0'); + } + num = num >> 4; + } +} + +/*--------------------------------------------------------------------- + Display dec-data on the screen + ---------------------------------------------------------------------*/ +void +putint_d(u32 color, int curs_x, int curs_y, int i) +{ + char c; + int j; + + if (i >= 0) { + c = ' '; + j = i; + } else { + c = '-'; + j = -i; + } + + do { + putchar(color, curs_x--, curs_y, (j % 10) + '0'); + j /= 10; + } while (j > 0); + + putchar(color, curs_x-1, curs_y, ' '); + putchar(color, curs_x, curs_y, c); + + if (i > -10 && i < 10){ + putchar(color, curs_x-2, curs_y, ' '); + } +} + +/*--------------------------------------------------------------------- + Display string on the screen + ---------------------------------------------------------------------*/ +void +printstr(u32 color, int curs_x, int curs_y, char *s) +{ + int i; + + for (i = 0 ; *s != NULL; i ++) { + putchar(color, curs_x + i, curs_y, *s++); + } +} + + + +/*--------------------------------------------------------------------- + Put a dot on the screen + ---------------------------------------------------------------------*/ +void +pset(int x, int y, u32 color) +{ + ((u16 *)osViGetNextFramebuffer())[x + SCREEN_WD*y]=color; +} + +/*--------------------------------------------------------------------- + Make a circle on the screen + ---------------------------------------------------------------------*/ +void +circle(int x0, int y0, int r, u32 color) +{ + int x, y, f; + + x = r; + y = 0; + f = -2 * r + 3; + + while (x >= y) { + pset(x0 + x, y0 + y, color); + pset(x0 - x, y0 + y, color); + pset(x0 + x, y0 - y, color); + pset(x0 - x, y0 - y, color); + pset(x0 + y, y0 + x, color); + pset(x0 - y, y0 + x, color); + pset(x0 + y, y0 - x, color); + pset(x0 - y, y0 - x, color); + if (f >= 0) { + x --; + f -= x*4; + } + y++; + f += 4*y + 2; + } +} + +/*--------------------------------------------------------------------- + Make a line on the screen + ---------------------------------------------------------------------*/ +void +line(int x0, int y0, int x1, int y1, u32 color) +{ + int dx, dy, sx, sy, i, e; + int x = x0; + int y = y0; + + if (x1-x0 > 0){ + sx = 1; + dx = x1-x0; + } else if (x1-x0 < 0) { + sx = -1; + dx = x0-x1; + } else { + sx = 0; + dx = 0; + } + + if (y1-y0 > 0){ + sy = 1; + dy = y1-y0; + } else if (y1-y0 < 0) { + sy = -1; + dy = y0-y1; + } else { + sy = 0; + dy = 0; + } + + if (dx >= dy) { + e = -dx; + for (i=0; i<= dx; i++){ + pset(x, y, color); + x += sx; + e += 2*dy; + if (e>=0) { + y += sy; + e -= 2*dx; + } + } + } else { + e = -dy; + for (i = 0; i <= dy; i ++){ + pset(x, y, color); + y += sy; + e += 2*dx; + if (e >= 0) { + x += sx; + e -= 2*dy; + } + } + } +} + +/*--------------------------------------------------------------------- + Make a box on the screen + ---------------------------------------------------------------------*/ +void +box(int x0, int y0, int x1, int y1, u32 color) +{ + line(x0, y0, x1, y0, color); + line(x0, y0, x0, y1, color); + line(x0, y1, x1, y1, color); + line(x1, y0, x1, y1, color); +} + +/*--------------------------------------------------------------------- + Clear the screen + ---------------------------------------------------------------------*/ +void +gcls(void) +{ + int i; + u16 *p; + + p = (u16 *)osViGetNextFramebuffer(); + for (i = 0; i < SCREEN_WD*SCREEN_HT; i ++) { +#if BMP_DATA + *p++ = bmpdata[i]; +#else + *p++ = BGCOLOR; +#endif + } +} + +/*--------------------------------------------------------------------- + Set Graphic data to tmp buffer + ---------------------------------------------------------------------*/ +void +SetBG(u8 *gr, u16 *gbuf) +{ + int i, j; + + for (i = 0, j = 0 ; i < SCREEN_WD*SCREEN_HT ; i ++ , j += 3) { + *gbuf++ = GPACK_RGBA5551(gr[j], gr[j + 1], gr[j + 2], 1); + } +} + +/*--------------------------------------------------------------------- + Write Graphic data to buffer from tmp buffer + ---------------------------------------------------------------------*/ +void +WriteBG(u8 *gr, u16 *gbuf) +{ + int i; + u16 *p; + + p = (u16 *)osViGetNextFramebuffer(); + for (i = 0 ; i < SCREEN_WD*SCREEN_HT ; i ++ ) { + *p++ = *gbuf++; + } +} + +/*--------------------------------------------------------------------- + Display character on the tmp buffer + ---------------------------------------------------------------------*/ +void +gputchar(u32 color, int curs_x, int curs_y, char c, u16 *buf) +{ + int i, j; + int x = curs_x*CHAR_WD; + int y = curs_y*CHAR_HT; + u8 *pc = pat[c-0x20]; + u16 *p = buf + x + SCREEN_WD*(y-8); + + for (j = 0; j < CHAR_HT; j ++, pc++) { + for (i = CHAR_WD - 1; i >= 0; i --) { + if (*pc & (1 << i)) { + *p = color; + } else { + *p = BGCOLOR; + } + p ++; + } + p += SCREEN_WD - CHAR_WD; + } +} + +/*--------------------------------------------------------------------- + Display string on the tmp buffer + ---------------------------------------------------------------------*/ +void +gprintstr(u32 color, int curs_x, int curs_y, char *s, u16 *buf) +{ + int i; + + for (i = 0; *s != NULL; i ++) { + gputchar(color, curs_x+i, curs_y, *s++, buf); + } +} + +/*--------------------------------------------------------------------- + Put pattern on the screen + ---------------------------------------------------------------------*/ +void +putpattern(u32 color, int pos_x, int pos_y, char c) +{ + int i, j; + int x = pos_x; + int y = pos_y; + u8 *pc = pat[c-0x20]; + u16 *p = (u16 *)osViGetNextFramebuffer() + x + SCREEN_WD*(y-8); + + for (j = 0; j < CHAR_HT; j ++, pc++) { + for (i = CHAR_WD - 1; i >= 0; i --) { + if (*pc & (1 << i)) { + *p ^= color; + } else { +#if 0 + *p = BGCOLOR; +#endif + } + p ++; + } + p += SCREEN_WD - CHAR_WD; + } +} + + +#include "STDARG.H" + +static int pos_x_ = 0; +static int pos_y_ = 1; +void PRINTF_D(u32 color_, char *c_, ...) +{ + char buffer[256]; + va_list args; + va_start (args, c_); + D_vsprintf (buffer, c_, args); + va_end (args); + + if(pos_y_ >= 30) + pos_y_ = 1; + + printstr(color_, pos_x_, pos_y_, buffer); + pos_y_++; +} + +void PRINTF_D2(u32 color_, int x, int y, char *c_, ...) +{ + char buffer[256]; + va_list args; + va_start (args, c_); + D_vsprintf (buffer, c_, args); + va_end (args); + + printstr(color_, x, y, buffer); +} + +void WAIT(void) +{ + int cnt; + + for(cnt = 0; cnt < 1000; cnt++) + PRINTF_D2(WHITE, 0, 0, "cnt %d", cnt); +} + +#endif // 0 diff --git a/Doom 64/graph.h b/Doom 64/graph.h @@ -0,0 +1,53 @@ +/*==================================================================== + File : graph.h + + Created by Koji Mitsunari. Mar,14 1996. + Copyright by Nintendo, Co., Ltd. 1997. + =====================================================================*/ +#ifndef _graph_h_ +#define _graph_h_ + +#define BMP_DATA 0 + +#define WHITE 0xffffffff +#define BLACK 0x0000 +#define GRAY GPACK_RGBA5551(127,127,127,1) +#define BLUE GPACK_RGBA5551(0,0,255,1) +#define GREEN GPACK_RGBA5551(0,255,0,1) +#define RED GPACK_RGBA5551(255,0,0,1) +#define YELLOW GPACK_RGBA5551(255,255,0,1) +#define DARK GPACK_RGBA5551(50,50,128,1) +#define MARKCOLOR GPACK_RGBA5551(50,250,50,1) +#define BGCOLOR 0x0000 + +#define CHAR_WD 8 +#define CHAR_HT 16 + +#define TEXT_WD SCREEN_WD/CHAR_WD +#define TEXT_HT SCREEN_HT/CHAR_HT + +extern void putchar(u32, int, int, char); +extern void revchar(u32, int, int, char); +extern void putint_h(u32, int, int, int, char); +extern void putint_d(u32, int, int, int); +extern void printstr(u32, int, int, char*); +extern void circle(int, int, int, u32); +extern void pset(int, int, u32); +extern void line(int, int, int, int, u32); +extern void box(int, int, int, int, u32); +extern void gcls(void); +extern void bigputc(u32, int, int, char, int, int); +extern void printbig(u32, int, int, char*, int, int); +extern void WriteBG(u8 *, u16 *); +extern void SetBG(u8 *, u16 *); +extern void gputchar(u32, int, int, char, u16 *); +extern void gprintstr(u32, int, int, char*, u16 *); +extern void putpattern(u32, int, int, char); + +extern u16 *__cursor; +extern u32 __color; + +extern void PRINTF_D(u32 color_, char *c_, ...); +extern void PRINTF_D2(u32 color_, int x, int y, char *c_, ...); +extern void WAIT(void); +#endif diff --git a/Doom 64/i_main.c b/Doom 64/i_main.c @@ -0,0 +1,1171 @@ + +#include <ultra64.h> +#include <PR/ramrom.h> /* needed for argument passing into the app */ +#include <assert.h> + +#include "i_main.h" +#include "doomdef.h" +#include "st_main.h" + +// text for debug +#include "graph.h" + +/* + * Symbol genererated by "makerom" to indicate the end of the code segment + * in virtual (and physical) memory + */ +extern char _codeSegmentEnd[]; + +/* + * Symbols generated by "makerom" to tell us where the static segment is + * in ROM. + */ + +/* + * Stacks for the threads as well as message queues for synchronization + * This stack is ridiculously large, and could also be reclaimed once + * the main thread is started. + */ +u64 bootStack[STACKSIZE/sizeof(u64)]; + +extern u32 cfb[2][SCREEN_WD*SCREEN_HT]; // 8036A000 + +extern int globallump; // 800A68f8 r_local.h +extern int globalcm; // 800A68fC r_local.h + +//"\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91" +//static char sysmbols[] = {0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, 0x90, 0x91}; + +//---------- + +#define SYS_THREAD_ID_IDLE 1 +#define SYS_THREAD_ID_MAIN 2 +#define SYS_THREAD_ID_TICKER 3 + +#define SYS_IDLE_STACKSIZE 0x2020 +OSThread idle_thread; // 800A4A18 +u64 idle_stack[SYS_IDLE_STACKSIZE/sizeof(u64)]; // 800979E0 + +#define SYS_MAIN_STACKSIZE 0xA000 +OSThread main_thread; // 800A4BC8 +u64 main_stack[SYS_MAIN_STACKSIZE/sizeof(u64)]; // 80099A00 + +#define SYS_TICKER_STACKSIZE 0x1000 +OSThread sys_ticker_thread; // 800A4D78 +u64 sys_ticker_stack[SYS_TICKER_STACKSIZE/sizeof(u64)]; // 800A3A00 + +#define SYS_MSGBUF_SIZE_PI 128 +OSMesgQueue msgque_Pi; // 800A4FA0 +OSMesg msgbuf_Pi[SYS_MSGBUF_SIZE_PI]; // 800A4FD0 + +#define SYS_FIFO_SIZE 512 + +#if __GNUC__ /* for GNU compiler */ +u64 fifo_buff[2][SYS_FIFO_SIZE] __attribute__((aligned (16))); /* buffer for RDP DL */ // 800633E0 +u64 sys_rcp_stack[SP_DRAM_STACK_SIZE64] __attribute__((aligned (16))); /* used for matrix stack */ // 800915E0 +#else /* for SGI compiler */ +u64 fifo_buff[2][SYS_FIFO_SIZE]; /* buffer for RDP DL */ // 800633E0 +u64 sys_rcp_stack[SP_DRAM_STACK_SIZE64]; /* used for matrix stack */ // 800915E0 +#endif + +#define SYS_YIELD_SIZE OS_YIELD_DATA_SIZE +u64 gfx_yield_buff[SYS_YIELD_SIZE]; // 800919E0 + +OSTask vid_rsptask[2] = // 8005A590 +{ + { + M_GFXTASK, /* task type */ + NULL, /* task flags */ + (u64*) rspbootTextStart, /* boot ucode pointer (fill in later) */ + 0, /* boot ucode size (fill in later) */ + (u64*) gspF3DEX_NoN_fifoTextStart, /* task ucode pointer (fill in later) */ + SP_UCODE_SIZE, /* task ucode size */ + (u64*) gspF3DEX_NoN_fifoDataStart, /* task ucode data pointer (fill in later) */ + SP_UCODE_DATA_SIZE, /* task ucode data size */ + &sys_rcp_stack[0], /* task dram stack pointer */ + SP_DRAM_STACK_SIZE8, /* task dram stack size */ + &fifo_buff[0][0], /* task fifo buffer start ptr */ + &fifo_buff[0][0]+SYS_FIFO_SIZE, /* task fifo buffer end ptr */ + NULL, /* task data pointer (fill in later) */ + 0, /* task data size (fill in later) */ + &gfx_yield_buff[0], /* task yield buffer ptr (not used here) */ + SYS_YIELD_SIZE /* task yield buffer size (not used here) */ + }, + { + M_GFXTASK, /* task type */ + NULL, /* task flags */ + (u64*) rspbootTextStart, /* boot ucode pointer (fill in later) */ + 0, /* boot ucode size (fill in later) */ + (u64*) gspF3DEX_NoN_fifoTextStart, /* task ucode pointer (fill in later) */ + SP_UCODE_SIZE, /* task ucode size */ + (u64*) gspF3DEX_NoN_fifoDataStart, /* task ucode data pointer (fill in later) */ + SP_UCODE_DATA_SIZE, /* task ucode data size */ + &sys_rcp_stack[0], /* task dram stack pointer */ + SP_DRAM_STACK_SIZE8, /* task dram stack size */ + &fifo_buff[1][0], /* task fifo buffer start ptr */ + &fifo_buff[1][0]+SYS_FIFO_SIZE, /* task fifo buffer end ptr */ + NULL, /* task data pointer (fill in later) */ + 0, /* task data size (fill in later) */ + &gfx_yield_buff[0], /* task yield buffer ptr (not used here) */ + SYS_YIELD_SIZE /* task yield buffer size (not used here) */ + } +}; + +Vp vid_viewport = // 8005A610 +{ + SCREEN_WD*2, SCREEN_HT*2, G_MAXZ, 0, /* scale */ + SCREEN_WD*2, SCREEN_HT*2, 0, 0, /* translate */ +}; + +OSMesgQueue romcopy_msgque; // 800A4F70 +OSMesg romcopy_msgbuf; // 800A51D0 + +OSMesgQueue sys_msgque_joy; // 800A4F88 +OSMesg sys_msg_joy; // 800A51D4 + +#define SYS_MSGBUF_SIZE_VID 16 +OSMesgQueue sys_msgque_vbi; // 800A4FB8 +OSMesg sys_msgbuf_vbi[SYS_MSGBUF_SIZE_VID]; // 800A51E0 + +#define SYS_MSGBUF_SIZE_VID2 2 +OSMesgQueue sys_msgque_vbi2; // 800A4F28 +OSMesg sys_msgbuf_vbi2[SYS_MSGBUF_SIZE_VID2]; // 800A51D8 + +OSMesgQueue sys_msgque_vbi3; // 800A4F40 +OSMesg sys_msgbuf_vbi3[SYS_MSGBUF_SIZE_VID2]; // 800A5220 + +OSMesgQueue sys_msgque_vbi4; // 800A4F58 +OSMesg sys_msgbuf_vbi4[SYS_MSGBUF_SIZE_VID2]; // 800A5228 + +OSContStatus gamepad_status[MAXCONTROLLERS]; // 800a5230 +OSContPad *gamepad_data; // 800A5240 + +OSTask *vid_task; // 800A5244 +u32 vid_side; // 800A5248 + +u32 video_hStart; // 800A524c +u32 video_vStart1; // 800A5250 +u32 video_vStart2; // 800A5254 + +u32 GfxIndex; // 800A5258 +u32 VtxIndex; // 800A525C + +u8 gamepad_bit_pattern; // 800A5260 // one bit for each controller + +// Controller Pak +OSPfs ControllerPak; // 800A5270 +OSPfsState FileState[16]; // 800A52D8 +s32 File_Num; // 800A54D8 +s32 Pak_Size; // 800A54DC +u8 *Pak_Data; // 800A54E0 +s32 Pak_Memory; // 800A54E4 + +char Pak_Table[256] = // 8005A620 +{ + '\0',// 0 + ' ', ' ', ' ', ' ', ' ',// 1 + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',// 6 + '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',// 16 + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',// 26 + 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't',// 36 + 'u', 'v', 'w', 'x', 'y', 'z', '!', '"', '#','\'',// 46 + '*', '+', ',', '-', '.', '/', ':', '=', '?', '@',// 56 + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',// 66 + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',// 76 + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',// 86 + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',// 96 + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',// 106 + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',// 116 + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',// 126 + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',// 136 + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',// 146 + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',// 156 + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',// 166 + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',// 176 + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',// 186 + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',// 196 + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',// 206 + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',// 216 + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',// 226 + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ',// 236 + ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ' // 246 +}; + +char Game_Name[16] = // 8005A790 +{ + 0x1D, 0x28, 0x28, 0x26, 0x0F, 0x16, 0x14, 0x00, // (doom 64) byte index from Pak_Table + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +boolean disabledrawing = false; // 8005A720 + +s32 vsync = 0; // 8005A724 +s32 drawsync2 = 0; // 8005A728 +s32 drawsync1 = 0; // 8005A72C +u32 NextFrameIdx = 0; // 8005A730 + +s32 ControllerPakStatus = 1; // 8005A738 +s32 gamepad_system_busy = 0; // 8005A73C +s32 FilesUsed = -1; // 8005A740 +u32 SystemTickerStatus = 0; // 8005a744 + +Gfx Gfx_base[2][MAX_GFX]; // 800653E0 +Mtx Mtx_base[2][MAX_MTX]; // 800793E0 +Vtx Vtx_base[2][MAX_VTX]; // 800795E0 + +Gfx *GFX1; // 800A4A00 +Gfx *GFX2; // 800A4A04 + +Vtx *VTX1; // 800A4A08 +Vtx *VTX2; // 800A4A0C + +Mtx *MTX1; // 800A4A10 +Mtx *MTX2; // 800A4A14 + +Gfx *GfxBlocks[8] = {0,0,0,0,0,0,0,0}; // 8005A748 +Vtx *VtxBlocks[8] = {0,0,0,0,0,0,0,0}; // 8005A768 + +extern OSTask * wess_work(void); + +void I_Start(void) // 80005620 +{ + /* Re-initialize U64 operating system... */ + osInitialize(); + + /* Create and start idle thread... */ + osCreateThread(&idle_thread, SYS_THREAD_ID_IDLE, I_IdleGameThread, (void *)0, + idle_stack + SYS_IDLE_STACKSIZE/sizeof(u64), 10); + osStartThread(&idle_thread); +} + +void I_IdleGameThread(void *arg) // 8000567C +{ + /* Create and start the Pi manager... */ + osCreatePiManager( (OSPri)OS_PRIORITY_PIMGR, &msgque_Pi, msgbuf_Pi, + SYS_MSGBUF_SIZE_PI ); + + /* Create main thread... */ + osCreateThread(&main_thread, SYS_THREAD_ID_MAIN, I_Main, (void *)0, + main_stack + SYS_MAIN_STACKSIZE/sizeof(u64), 10); + osStartThread(&main_thread); + + osSetThreadPri(&idle_thread, (OSPri)OS_PRIORITY_IDLE); + + /* Idle loop... */ + do { + osYieldThread(); + } while(TRUE); +} + +void I_Main(void *arg) // 80005710 +{ + D_DoomMain(); +} + +void I_SystemTicker(void *arg) // 80005730 +{ + int vbi_msg; + int vidside; + int side, stat, ret; + int current_fbuf, next_fbuf; + OSTask *wess; + OSTask *rspTask; + OSTask *rspTaskPrev; + + //char str[64]; + + rspTask = NULL; + rspTaskPrev = NULL; + side = 1; + + while(true) + { + osRecvMesg(&sys_msgque_vbi, (OSMesg *)&vbi_msg, OS_MESG_BLOCK); + + //sprintf(str, "SystemTickerStatus %d",SystemTickerStatus); + //printstr(WHITE, 0, 13, str); + //sprintf(str, "vbi_msg %d",vbi_msg); + //printstr(WHITE, 0, 14, str); + //sprintf(str, "vidside %d",vidside); + //printstr(WHITE, 0, 15, str); + + switch (vbi_msg) + { + case VID_MSG_RSP: // end of signal processing + { + //sprintf(str, "VID_MSG_RSP"); + //printstr(WHITE, 0, 28, str); + + if(rspTask->t.type == M_AUDTASK) + { + SystemTickerStatus &= ~32; + + if (SystemTickerStatus & 4)//OS_SC_YIELDED + { + SystemTickerStatus &= ~4; + SystemTickerStatus |= 1; + + rspTask = rspTaskPrev; + osWritebackDCacheAll(); + osSpTaskLoad(rspTask); + osSpTaskStartGo(rspTask); + } + else + { + if ((SystemTickerStatus & 24) == 0) + { + ret = osRecvMesg(&sys_msgque_vbi3, (OSMesg *)&vbi_msg, OS_MESG_NOBLOCK); + rspTask = (OSTask*)vbi_msg; + + if(ret != -1) + { + if(rspTask == vid_rsptask) + vidside = 0; + else + vidside = 1; + + SystemTickerStatus |= 1; + + osWritebackDCacheAll(); + osSpTaskLoad(rspTask); + osSpTaskStartGo(rspTask); + } + } + } + } + else + { + SystemTickerStatus &= ~1; + + if(SystemTickerStatus & 2)//OS_SC_YIELD + { + SystemTickerStatus &= ~2; + + if (osSpTaskYielded(rspTask)) + { + rspTaskPrev = rspTask; + + SystemTickerStatus |= 4;//OS_SC_YIELDED + + osRecvMesg(&sys_msgque_vbi4, (OSMesg *)&vbi_msg, OS_MESG_NOBLOCK); + rspTask = (OSTask*)vbi_msg; + + SystemTickerStatus |= 32; + + osWritebackDCacheAll(); + osSpTaskLoad(rspTask); + osSpTaskStartGo(rspTask); + } + } + else + { + if ((SystemTickerStatus & 16) == 0) + SystemTickerStatus |= 8; + + ret = osRecvMesg(&sys_msgque_vbi4, (OSMesg *)&vbi_msg, OS_MESG_NOBLOCK); + rspTask = (OSTask*)vbi_msg; + + if(ret!= -1) + { + SystemTickerStatus |= 32; + + osWritebackDCacheAll(); + osSpTaskLoad(rspTask); + osSpTaskStartGo(rspTask); + } + } + } + } + break; + + case VID_MSG_RDP: // end of display processing + { + //sprintf(str, "VID_MSG_RDP"); + //printstr(WHITE, 0, 28, str); + + SystemTickerStatus &= ~8; + SystemTickerStatus |= 16; + + osViSwapBuffer(cfb[vidside]); + } + break; + + case VID_MSG_PRENMI: + { + //sprintf(str, "VID_MSG_PRENMI"); + //printstr(WHITE, 0, 28, str); + disabledrawing = true; + S_StopAll(); + osViBlack(TRUE); + I_MoveDisplay(0,0); + } + break; + + case VID_MSG_VBI: + { + //sprintf(str, "VID_MSG_VBI || vsync(%d) || side(%d)", vsync, side); + //printstr(WHITE, 0, 28, str); + + vsync += 1; + + if (sys_msgque_vbi4.validCount) + { + if (SystemTickerStatus & 1) + { + SystemTickerStatus |= 2; // GFX_YIELDED + osSpTaskYield(); + } + else + { + if ((SystemTickerStatus & 32) == 0) + { + osRecvMesg(&sys_msgque_vbi4, (OSMesg *)&vbi_msg, OS_MESG_NOBLOCK); + rspTask = (OSTask*)vbi_msg; + + SystemTickerStatus |= 32; + + osWritebackDCacheAll(); + osSpTaskLoad(rspTask); + osSpTaskStartGo(rspTask); + } + } + } + + if (side & 1) + { + if (gamepad_system_busy) + { + osContGetReadData(gamepad_data); + gamepad_system_busy = 0; + } + + // next audio function task + wess = wess_work(); + if (wess) + osSendMesg(&sys_msgque_vbi4,(OSMesg) wess, OS_MESG_NOBLOCK); + } + side++; + + if (SystemTickerStatus & 16) + { + if ((u32)(vsync - drawsync2) < 2) continue; + + current_fbuf = (int)osViGetCurrentFramebuffer(); + next_fbuf = (int)osViGetNextFramebuffer(); + + if (next_fbuf != current_fbuf) continue; + + SystemTickerStatus &= ~16; + + if (demoplayback || demorecording) + { + vsync = drawsync2 + 2; + } + + //sprintf(str, "vsync %d | side %d",vsync, side); + //printstr(WHITE, 0, 29, str); + + drawsync1 = vsync - drawsync2; + drawsync2 = vsync; + + if ((ControllerPakStatus != 0) && (gamepad_system_busy == 0)) + { + osContStartReadData(&sys_msgque_joy); + gamepad_system_busy = 1; + } + + osSendMesg(&sys_msgque_vbi2, (OSMesg)VID_MSG_KICKSTART, OS_MESG_NOBLOCK); + } + + if(SystemTickerStatus == 0) + { + ret = osRecvMesg(&sys_msgque_vbi3, (OSMesg *)&vbi_msg, OS_MESG_NOBLOCK); + rspTask = (OSTask*)vbi_msg; + + //sprintf(str, "ret %d", ret); + //printstr(WHITE, 0, 17, str); + + if(ret != -1) + { + //sprintf(str, "rspTask->t.type %d",rspTask->t.type); + //printstr(WHITE, 0, 14, str); + //sprintf(str, "rspTask->t.type %x",(u64*)rspTask->t.ucode); + //printstr(WHITE, 0, 15, str); + + if(rspTask == vid_rsptask) + vidside = 0; + else + vidside = 1; + + SystemTickerStatus |= 1; + + osWritebackDCacheAll(); + osSpTaskLoad(rspTask); + osSpTaskStartGo(rspTask); + } + } + } + break; + } + } +} + +extern void S_Init(void); + +void I_Init(void) // 80005C50 +{ + OSViMode *ViMode; + + vid_rsptask[0].t.ucode_boot_size = (int)rspbootTextEnd - (int)rspbootTextStart; // set ucode size (waste but who cares) + vid_rsptask[1].t.ucode_boot_size = (int)rspbootTextEnd - (int)rspbootTextStart; // set ucode size (waste but who cares) + + osCreateMesgQueue( &romcopy_msgque, &romcopy_msgbuf, 1 ); + + osCreateMesgQueue( &sys_msgque_vbi, sys_msgbuf_vbi, SYS_MSGBUF_SIZE_VID ); + + osCreateMesgQueue(&sys_msgque_vbi2, sys_msgbuf_vbi2, SYS_MSGBUF_SIZE_VID2);//&sys_msgque_jam, sys_msgbuf_jam + osCreateMesgQueue(&sys_msgque_vbi3, sys_msgbuf_vbi3, SYS_MSGBUF_SIZE_VID2);//&sys_msgque_ser, sys_msgbuf_ser + osCreateMesgQueue(&sys_msgque_vbi4, sys_msgbuf_vbi4, SYS_MSGBUF_SIZE_VID2);//&sys_msgque_tmr, sys_msgbuf_tmr + + if(osTvType == OS_TV_PAL) + { + ViMode = &osViModeTable[OS_VI_PAL_LPN2]; + } + else if(osTvType == OS_TV_NTSC) + { + ViMode = &osViModeTable[OS_VI_NTSC_LPN2]; + } + else if(osTvType == OS_TV_MPAL) + { + ViMode = &osViModeTable[OS_VI_MPAL_LPN2]; + } + + video_hStart = ViMode->comRegs.hStart; + video_vStart1 = ViMode->fldRegs[0].vStart; + video_vStart2 = ViMode->fldRegs[1].vStart; + + // Create and start the Vi manager and init the video mode... + + osCreateViManager( OS_PRIORITY_VIMGR ); + osViSetMode(ViMode); + osViBlack(TRUE); + + osViSetSpecialFeatures(OS_VI_GAMMA_OFF|OS_VI_GAMMA_DITHER_OFF|OS_VI_DIVOT_OFF|OS_VI_DITHER_FILTER_OFF); + + osViSetXScale(1.0); + osViSetYScale(1.0); + + D_memset(cfb, 0, ((SCREEN_WD*SCREEN_HT)*sizeof(u32))*2); + osViSwapBuffer(cfb); + + if (osViGetCurrentFramebuffer() != cfb) { + do { + } while (osViGetCurrentFramebuffer() != cfb); + } + + osViBlack(FALSE); + + osSetEventMesg( OS_EVENT_SP, &sys_msgque_vbi, (OSMesg)VID_MSG_RSP ); + osSetEventMesg( OS_EVENT_DP, &sys_msgque_vbi, (OSMesg)VID_MSG_RDP ); + osSetEventMesg( OS_EVENT_PRENMI, &sys_msgque_vbi, (OSMesg)VID_MSG_PRENMI ); + + osViSetEvent( &sys_msgque_vbi, (OSMesg)VID_MSG_VBI, 1 ); // last parm: 2 indicates 30 FPS (1=60) + + vid_side = 1; + + /* Serial/Joy queue */ + + osCreateMesgQueue(&sys_msgque_joy, &sys_msg_joy, 1); + osSetEventMesg(OS_EVENT_SI, &sys_msgque_joy, &sys_msg_joy); + + osContInit(&sys_msgque_joy, &gamepad_bit_pattern, gamepad_status); + + gamepad_data = (OSContPad *)idle_stack; + + if ((gamepad_bit_pattern & 1) != 0) + { + osContStartReadData(&sys_msgque_joy); + osRecvMesg(&sys_msgque_joy, NULL, OS_MESG_BLOCK); + osContGetReadData(gamepad_data); + } + + S_Init(); + + /* Create and start ticker thread... */ + osCreateThread(&sys_ticker_thread, SYS_THREAD_ID_TICKER, I_SystemTicker, (void *)0, + sys_ticker_stack + SYS_TICKER_STACKSIZE/sizeof(u64), 11); + osStartThread(&sys_ticker_thread); + + osJamMesg(&sys_msgque_vbi2, (OSMesg)VID_MSG_KICKSTART, OS_MESG_NOBLOCK); +} + +#include "STDARG.H" + +void I_Error(char *error, ...) // 80005F30 +{ + char buffer[256]; + va_list args; + va_start (args, error); + D_vsprintf (buffer, error, args); + va_end (args); + + while (true) + { + I_ClearFrame(); + + gDPPipeSync(GFX1++); + gDPSetCycleType(GFX1++, G_CYC_FILL); + gDPSetRenderMode(GFX1++,G_RM_NOOP,G_RM_NOOP2); + gDPSetColorImage(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_32b, SCREEN_WD, OS_K0_TO_PHYSICAL(cfb[vid_side])); + gDPSetFillColor(GFX1++, GPACK_RGBA5551(0,0,0,0) << 16 | GPACK_RGBA5551(0,0,0,0)) ; + gDPFillRectangle(GFX1++, 0, 0, SCREEN_WD-1, SCREEN_HT-1); + + ST_Message(err_text_x, err_text_y, buffer, 0xffffffff); + I_DrawFrame(); + } +} + +typedef struct +{ + int pad_data; +} pad_t; + +int I_GetControllerData(void) // 800060D0 +{ + return ((pad_t*)gamepad_data)->pad_data; +} + +void I_CheckGFX(void) // 800060E8 +{ + memblock_t *block; + + Gfx **Gfx_Blocks; + Vtx **Vtx_Blocks; + + int i, index; + int block_idx; + + index = (int)((int)GFX1 - (int)GFX2) / sizeof(Gfx); + + if (index > MAX_GFX) + I_Error("I_CheckGFX: GFX Overflow by %d\n",index); + + if ((index < (MAX_GFX-1024)) == 0) + { + Gfx_Blocks = GfxBlocks; + block_idx = -1; + + for(i = 0; i < 8; i++) + { + block = (memblock_t *)((byte *)*Gfx_Blocks - sizeof(memblock_t)); + + if (*Gfx_Blocks) + { + if(((u32)block->lockframe < NextFrameIdx - 1) == 0) + { + Gfx_Blocks++; + continue; + } + + block->lockframe = NextFrameIdx; + GFX2 = (Gfx *)*Gfx_Blocks; + goto move_gfx; + } + + block_idx = i; + } + + if (block_idx < 0) + I_Error("I_CheckGFX: GFX Cache overflow"); + + GFX2 = (Gfx *)Z_Malloc(MAX_GFX * sizeof(Gfx), PU_CACHE, &GfxBlocks[block_idx]); + + move_gfx: + gSPBranchList(GFX1,GFX2); + GFX1 = GFX2; + GfxIndex += index; + } + + index = (int)((int)VTX1 - (int)VTX2) / sizeof(Vtx); + + if (index > MAX_VTX) + I_Error("I_CheckVTX: VTX Overflow by %d\n",index); + + if ((index < (MAX_VTX-615)) == 0) + { + Vtx_Blocks = VtxBlocks; + block_idx = -1; + + for(i = 0; i < 8; i++) + { + block = (memblock_t *)((byte *)*Vtx_Blocks - sizeof(memblock_t)); + + if (*Vtx_Blocks) + { + if(((u32)block->lockframe < NextFrameIdx - 1) == 0) + { + Vtx_Blocks++; + continue; + } + + block->lockframe = NextFrameIdx; + VTX2 = (Vtx *)*Vtx_Blocks; + goto move_vtx; + } + + block_idx = i; + } + + if (block_idx < 0) + I_Error("I_CheckGFX: VTX Cache overflow"); + + VTX2 = (Vtx *)Z_Malloc(MAX_VTX * sizeof(Vtx), PU_CACHE, &VtxBlocks[block_idx]); + + move_vtx: + VTX1 = VTX2; + VtxIndex += index; + } +} + +void I_ClearFrame(void) // 8000637C +{ + NextFrameIdx += 1; + + GFX1 = Gfx_base[vid_side]; + GFX2 = GFX1; + GfxIndex = 0; + + VTX1 = Vtx_base[vid_side]; + VTX2 = VTX1; + VtxIndex = 0; + + MTX1 = Mtx_base[vid_side]; + + vid_task = &vid_rsptask[vid_side]; + + vid_task->t.ucode = (u64 *) gspF3DEX_NoN_fifoTextStart; + vid_task->t.ucode_data = (u64 *) gspF3DEX_NoN_fifoDataStart; + + gMoveWd(GFX1++, G_MW_SEGMENT, G_MWO_SEGMENT_0, 0); + + gDPSetColorImage(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_32b, SCREEN_WD, OS_K0_TO_PHYSICAL(cfb[vid_side])); + gDPSetScissor(GFX1++, G_SC_NON_INTERLACE, 0, 0, SCREEN_WD, SCREEN_HT); + + // [GEC] New Cheat Codes + if (players[0].cheats & CF_FILTER) { + gDPSetTextureFilter(GFX1++, G_TF_POINT); // <- Nearest texture + } + else { + gDPSetTextureFilter(GFX1++, G_TF_BILERP); // <- Bilinear texture + } + + gSPViewport(GFX1++, &vid_viewport); + + gSPClearGeometryMode(GFX1++, -1); + gSPSetGeometryMode(GFX1++, G_SHADE|G_SHADING_SMOOTH|G_FOG ); + + globallump = -1; + globalcm = 0; +} + +void I_DrawFrame(void) // 80006570 +{ + int index; + + gDPFullSync(GFX1++); + gSPEndDisplayList(GFX1++); + + index = (int)((int)GFX1 - (int)GFX2) / sizeof(Gfx); + if (index > MAX_GFX) + I_Error("I_DrawFrame: GFX Overflow by %d\n\n",index); + + index = (int)((int)VTX1 - (int)VTX2) / sizeof(Vtx); + if (index > MAX_VTX) + I_Error("I_DrawFrame: VTX Overflow by %d\n",index); + + vid_task->t.data_ptr = (u64 *) Gfx_base[vid_side]; + vid_task->t.data_size = (u32)((((int)((int)GFX1 - (int)GFX2) / sizeof(Gfx)) + GfxIndex) * sizeof(Gfx)); + + osSendMesg(&sys_msgque_vbi3,(OSMesg) vid_task, OS_MESG_NOBLOCK); + osRecvMesg(&sys_msgque_vbi2, NULL, OS_MESG_BLOCK);//retraceMessageQ + vid_side ^= 1; +} + +void I_GetScreenGrab(void) // 800066C0 +{ + if ((SystemTickerStatus & ~32) || (sys_msgque_vbi3.validCount != 0)) { + osRecvMesg(&sys_msgque_vbi2, (OSMesg *)0, OS_MESG_BLOCK); + osJamMesg(&sys_msgque_vbi2, (OSMesg)VID_MSG_KICKSTART, OS_MESG_NOBLOCK); + } +} + +long LongSwap(long dat) // 80006724 +{ + return (u32)dat >> 0x18 | dat >> 8 & 0xff00U | (dat & 0xff00U) << 8 | dat << 0x18; +} + +short LittleShort(short dat) // 80006750 +{ + return ((((dat << 8) | (dat >> 8 & 0xff)) << 16) >> 16); +} + +short BigShort(short dat) // 80006770 +{ + return ((dat << 8) | (dat >> 8 & 0xff)) & 0xffff; +} + +void I_MoveDisplay(int x,int y) // 80006790 +{ + int ViMode; + + ViMode = osViGetCurrentMode(); + + osViModeTable[ViMode].comRegs.hStart = + (int)(((int)video_hStart >> 0x10 & 65535) + x) % 65535 << 0x10 | + (int)((video_hStart & 65535) + x) % 65535; + + osViModeTable[ViMode].fldRegs[0].vStart = + (int)(((int)video_vStart1 >> 0x10 & 65535) + y) % 65535 << 0x10 | + (int)((video_vStart1 & 65535) + y) % 65535; + + osViModeTable[ViMode].fldRegs[1].vStart = + (int)(((int)video_vStart2 >> 0x10 & 65535) + y) % 65535 << 0x10 | + (int)((video_vStart2 & 65535) + y) % 65535; +} + +void I_WIPE_MeltScreen(void) // 80006964 +{ + u32 *fb; + int y1; + int tpos; + int yscroll; + int height; + + fb = Z_Malloc((SCREEN_WD*SCREEN_HT)*sizeof(u32), PU_STATIC, NULL); + + I_GetScreenGrab(); + D_memcpy(&cfb[vid_side][0], &cfb[vid_side ^ 1][0], (SCREEN_WD*SCREEN_HT)*sizeof(u32)); + + yscroll = 1; + while( true ) + { + y1 = 0; + D_memcpy(fb, &cfb[vid_side ^ 1][0], (SCREEN_WD*SCREEN_HT)*sizeof(u32)); + + I_ClearFrame(); + + gDPSetCycleType(GFX1++, G_CYC_1CYCLE); + gDPSetTextureLUT(GFX1++, G_TT_NONE); + gDPSetTexturePersp(GFX1++, G_TP_NONE); + gDPSetAlphaCompare(GFX1++, G_AC_THRESHOLD); + gDPSetBlendColor(GFX1++, 0, 0, 0, 0); + gDPSetCombineMode(GFX1++, G_CC_D64COMB19, G_CC_D64COMB19); + gDPSetRenderMode(GFX1++, G_RM_XLU_SURF, G_RM_XLU_SURF2); + gDPSetPrimColor(GFX1++, 0, 0, 15, 0, 0, 22); // 0x0f000016 + + height = SCREEN_HT - (yscroll >> 2); + tpos = 0; + if (height > 0) + { + do + { + gDPSetTextureImage(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_32b , SCREEN_WD, fb); + gDPSetTile(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_32b, + (SCREEN_WD >> 2), 0, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0); + + gDPLoadSync(GFX1++); + gDPLoadTile(GFX1++, G_TX_LOADTILE, + (0 << 2), (tpos << 2), + ((SCREEN_WD-1) << 2), (((tpos+3)-1) << 2)); + + gDPPipeSync(GFX1++); + gDPSetTile(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_32b, + (SCREEN_WD >> 2), 0, G_TX_RENDERTILE, 0, 0, 0, 0, 0, 0, 0); + + gDPSetTileSize(GFX1++, G_TX_RENDERTILE, + (0 << 2), (tpos << 2), + ((SCREEN_WD-1) << 2), (((tpos+3)-1) << 2)); + + gSPTextureRectangle(GFX1++, + (0 << 2), (y1 << 2) + yscroll, + (SCREEN_WD << 2), ((y1 + 3) << 2) + yscroll, + G_TX_RENDERTILE, + (0 << 5), (tpos << 5), + (1 << 10), (1 << 10)); + + y1 += 2; + tpos += 2; + } while (y1 < height); + } + + yscroll += 2; + if (yscroll >= 160) break; + I_DrawFrame(); + } + + Z_Free(fb); + I_WIPE_FadeOutScreen(); +} + +void I_WIPE_FadeOutScreen(void) // 80006D34 +{ + u32 *fb; + int y1, tpos, outcnt; + + fb = Z_Malloc((SCREEN_WD*SCREEN_HT)*sizeof(u32), PU_STATIC, NULL); + + I_GetScreenGrab(); + D_memcpy(fb, &cfb[vid_side ^ 1][0], (SCREEN_WD*SCREEN_HT)*sizeof(u32)); + + outcnt = 248; + do + { + I_ClearFrame(); + + gDPSetCycleType(GFX1++, G_CYC_1CYCLE); + gDPSetTextureLUT(GFX1++, G_TT_NONE); + gDPSetTexturePersp(GFX1++, G_TP_NONE); + gDPSetAlphaCompare(GFX1++, G_AC_NONE); + gDPSetCombineMode(GFX1++, G_CC_D64COMB06, G_CC_D64COMB06); + gDPSetRenderMode(GFX1++,G_RM_OPA_SURF,G_RM_OPA_SURF2); + gDPSetPrimColor(GFX1++, 0, 0, outcnt, outcnt, outcnt, 0); + + tpos = 0; + y1 = 0; + do + { + gDPSetTextureImage(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_32b , SCREEN_WD, fb); + gDPSetTile(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_32b, + (SCREEN_WD >> 2), 0, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0); + + gDPLoadSync(GFX1++); + gDPLoadTile(GFX1++, G_TX_LOADTILE, + (0 << 2), (tpos << 2), + ((SCREEN_WD-1) << 2), (((tpos+3)-1) << 2)); + + gDPPipeSync(GFX1++); + gDPSetTile(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_32b, + (SCREEN_WD >> 2), 0, G_TX_RENDERTILE, 0, 0, 0, 0, 0, 0, 0); + + gDPSetTileSize(GFX1++, G_TX_RENDERTILE, + (0 << 2), (tpos << 2), + ((SCREEN_WD-1) << 2), (((tpos+3)-1) << 2)); + + gSPTextureRectangle(GFX1++, + (0 << 2), (y1 << 2), + (SCREEN_WD << 2), ((y1+3) << 2), + G_TX_RENDERTILE, + (0 << 5), (tpos << 5), + (1 << 10), (1 << 10)); + + tpos += 3; + y1 += 3; + } while (y1 != SCREEN_HT); + + I_DrawFrame(); + outcnt -= 8; + } while (outcnt >= 0); + + I_GetScreenGrab(); + Z_Free(fb); +} + + +int I_CheckControllerPak(void) // 800070B0 +{ + int ret, file; + OSPfsState *fState; + s32 MaxFiles [2]; + u8 validpaks; + + ControllerPakStatus = 0; + + if (gamepad_system_busy != 0) + { + do { + osYieldThread(); + } while (gamepad_system_busy != 0); + } + + FilesUsed = -1; + ret = PFS_ERR_NOPACK; + + osPfsIsPlug(&sys_msgque_joy, &validpaks); + + /* does the current controller have a memory pak? */ + if (validpaks & 1) + { + ret = osPfsInit(&sys_msgque_joy, &ControllerPak, NULL); + + if ((ret != PFS_ERR_NOPACK) && + (ret != PFS_ERR_ID_FATAL) && + (ret != PFS_ERR_DEVICE) && + (ret != PFS_ERR_CONTRFAIL)) + { + ret = osPfsNumFiles(&ControllerPak, MaxFiles, &FilesUsed); + + if (ret == PFS_ERR_INCONSISTENT) + ret = osPfsChecker(&ControllerPak); + + if (ret == 0) + { + Pak_Memory = 123; + fState = FileState; + file = 0; + do + { + ret = osPfsFileState(&ControllerPak, file, fState); + file += 1; + + if (ret != 0) + fState->file_size = 0; + + Pak_Memory -= (fState->file_size >> 8); + fState += 1; + } while (file != 16); + ret = 0; + } + } + } + + ControllerPakStatus = 1; + + return ret; +} + +int I_DeletePakFile(int filenumb) // 80007224 +{ + int ret; + OSPfsState *fState; + + ControllerPakStatus = 0; + + if (gamepad_system_busy != 0) + { + do { + osYieldThread(); + } while (gamepad_system_busy != 0); + } + + fState = &FileState[filenumb]; + + if (fState->file_size == 0) { + ret = 0; + } + else + { + ret = osPfsDeleteFile(&ControllerPak, + FileState[filenumb].company_code, + FileState[filenumb].game_code, + FileState[filenumb].game_name, + FileState[filenumb].ext_name); + + if (ret == PFS_ERR_INCONSISTENT) + ret = osPfsChecker(&ControllerPak); + + if (ret == 0) + { + Pak_Memory += (fState->file_size >> 8); + fState->file_size = 0; + } + } + + ControllerPakStatus = 1; + + return ret; +} + +int I_SavePakFile(int filenumb, int flag, byte *data, int size) // 80007308 +{ + int ret; + + ControllerPakStatus = 0; + + if (gamepad_system_busy != 0) + { + do { + osYieldThread(); + } while (gamepad_system_busy != 0); + } + + ret = osPfsReadWriteFile(&ControllerPak, filenumb, (u8)flag, 0, size, (u8*)data); + + if (ret == PFS_ERR_INCONSISTENT) + ret = osPfsChecker(&ControllerPak); + + ControllerPakStatus = 1; + + return ret; +} + +#define COMPANY_CODE 0x3544 // 5D +#define GAME_CODE 0x4e444d45 // NDME + +int I_ReadPakFile(void) // 800073B8 +{ + int ret; + u8 *ext_name; + + ControllerPakStatus = 0; + + if (gamepad_system_busy != 0) + { + do { + osYieldThread(); + } while (gamepad_system_busy != 0); + } + + Pak_Data = NULL; + Pak_Size = 0; + ext_name = NULL; + + ret = osPfsFindFile(&ControllerPak, COMPANY_CODE, GAME_CODE, Game_Name, ext_name, &File_Num); + + if (ret == 0) + { + Pak_Size = FileState[File_Num].file_size; + Pak_Data = (byte *)Z_Malloc(Pak_Size, PU_STATIC, NULL); + ret = osPfsReadWriteFile(&ControllerPak, File_Num, PFS_READ, 0, Pak_Size, Pak_Data); + } + + ControllerPakStatus = 1; + + return ret; +} + +int I_CreatePakFile(void) // 800074D4 +{ + int ret; + u8 ExtName [8]; + + ControllerPakStatus = 0; + + if (gamepad_system_busy != 0) + { + do { + osYieldThread(); + } while (gamepad_system_busy != 0); + } + + if (Pak_Memory < 2) + Pak_Size = 256; + else + Pak_Size = 512; + + Pak_Data = (byte *)Z_Malloc(Pak_Size, PU_STATIC, NULL); + D_memset(Pak_Data, 0, Pak_Size); + + *(int*)ExtName = 0; + + ret = osPfsAllocateFile(&ControllerPak, COMPANY_CODE, GAME_CODE, Game_Name, ExtName, Pak_Size, &File_Num); + + if (ret == PFS_ERR_INCONSISTENT) + ret = osPfsChecker(&ControllerPak); + + if (ret == 0) + ret = osPfsReadWriteFile(&ControllerPak, File_Num, PFS_WRITE, 0, Pak_Size, Pak_Data); + + ControllerPakStatus = 1; + + return ret; +} diff --git a/Doom 64/i_main.h b/Doom 64/i_main.h @@ -0,0 +1,8 @@ + +#define SCREEN_HT 240 +#define SCREEN_WD 320 + +/* this stack size is in bytes, and is a lot larger + * than this program needs. + */ +#define STACKSIZE 0x2000 diff --git a/Doom 64/in_main.c b/Doom 64/in_main.c @@ -0,0 +1,343 @@ + +/* in_main.c -- intermission */ + +#include "doomdef.h" +#include "st_main.h" +#include "r_local.h" + +extern int nextmap; + +#define T_NULL "" + +#define MI_TXT01 "Staging Area" +#define MI_TXT02 "The Terraformer" +#define MI_TXT03 "Main Engineering" +#define MI_TXT04 "Holding Area" +#define MI_TXT05 "Tech Center" +#define MI_TXT06 "Alpha Quadrant" +#define MI_TXT07 "Research Lab" +#define MI_TXT08 "Final Outpost" +#define MI_TXT09 "Even Simpler" +#define MI_TXT10 "The Bleeding" +#define MI_TXT11 "Terror Core" +#define MI_TXT12 "Altar of Pain" +#define MI_TXT13 "Dark Citadel" +#define MI_TXT14 "Eye of the Storm" +#define MI_TXT15 "Dark Entries" +#define MI_TXT16 "Blood Keep" +#define MI_TXT17 "Watch Your Step" +#define MI_TXT18 "Spawned Fear" +#define MI_TXT19 "The Spiral" +#define MI_TXT20 "Breakdown" +#define MI_TXT21 "Pitfalls" +#define MI_TXT22 "Burnt Offerings" +#define MI_TXT23 "Unholy Temple" +#define MI_TXT24 "No Escape" +#define MI_TXT25 "Cat And Mouse" +#define MI_TXT26 "HardCore" +#define MI_TXT27 "Playground" +#define MI_TXT28 "The Absolution" +#define MI_TXT29 "Outpost Omega" +#define MI_TXT30 "The Lair" +#define MI_TXT31 "In The Void" +#define MI_TXT32 "Hectic" +#define MI_TXT33 "TITLE" + +mapinfo_t MapInfo[] = //8005A478 +{ + {T_NULL , 0}, + {MI_TXT01 , 96}, + {MI_TXT02 , 97}, + {MI_TXT03 , 105}, + {MI_TXT04 , 104}, + {MI_TXT05 , 101}, + {MI_TXT06 , 107}, + {MI_TXT07 , 108}, + {MI_TXT08 , 110}, + {MI_TXT09 , 95}, + {MI_TXT10 , 98}, + {MI_TXT11 , 99}, + {MI_TXT12 , 102}, + {MI_TXT13 , 93}, + {MI_TXT14 , 106}, + {MI_TXT15 , 111}, + {MI_TXT16 , 97}, + {MI_TXT17 , 103}, + {MI_TXT18 , 94}, + {MI_TXT19 , 100}, + {MI_TXT20 , 112}, + {MI_TXT21 , 109}, + {MI_TXT22 , 101}, + {MI_TXT23 , 108}, + {MI_TXT24 , 98}, + {MI_TXT25 , 97}, + {MI_TXT26 , 98}, + {MI_TXT27 , 94}, + {MI_TXT28 , 99}, + {MI_TXT29 , 101}, + {MI_TXT30 , 102}, + {MI_TXT31 , 103}, + {MI_TXT32 , 104}, + {MI_TXT33 , 115}, + {T_NULL , 0} +}; + +typedef struct pstats_s +{ + int killpercent; + int itempercent; + int secretpercent; +} pstats_t; + +int killvalue, itemvalue, secretvalue; // 800633B8, 800633BC, 800633C0 +pstats_t pstats; // 800633C4 + +// used to accelerate or skip a stage +int acceleratestage; // 800633B0 +int nextstage; // 800633B4 + +char timetext[16]; // 800633D0 +int start_time; // 80063390 +int end_time; // 80063394 + +void IN_Start(void) // 80004AF0 +{ + int time; + + killvalue = itemvalue = secretvalue = -1; + + if (totalkills) + pstats.killpercent = (players[0].killcount * 100) / totalkills; + else + pstats.killpercent = 100; + + if (totalitems) + pstats.itempercent = (players[0].itemcount * 100) / totalitems; + else + pstats.itempercent = 100; + + if (totalsecret) + pstats.secretpercent = (players[0].secretcount * 100) / totalsecret; + else + pstats.secretpercent = 100; + + time = (unsigned int)(end_time - start_time) / 60; + + if ((time / 60) < 60) { + sprintf(timetext, "%2.2d:%2.2d", (time / 60), (time % 60)); + } + else { + D_memmove(timetext, "--:--"); + } + + nextstage = 0; + acceleratestage = 0; + last_ticon = 0; + text_alpha = 255; + + if ((nextmap >= 2) && (nextmap < LASTLEVEL)) + { + M_EncodePassword(Passwordbuff); + CurPasswordSlot = 16; + } + + S_StartMusic(114); +} + +void IN_Stop(void) // 80004DB0 +{ + S_StopMusic(); + + if ((nextmap >= 2) && (nextmap < LASTLEVEL)) + { + if (EnableExpPak) { + MiniLoop(M_SavePakStart,M_SavePakStop,M_SavePakTicker,M_SavePakDrawer); + } + } + + I_WIPE_FadeOutScreen(); +} + +int IN_Ticker(void) // 80004E24 +{ + boolean state; + int buttons, oldbuttons; + + buttons = ticbuttons[0] & 0xffff0000; + oldbuttons = oldticbuttons[0] & 0xffff0000; + + if ((buttons != oldbuttons) && (buttons & (PAD_A|PAD_B|PAD_START|ALL_TRIG|ALL_CBUTTONS))) + { + acceleratestage++; + if (acceleratestage == 1) + { + killvalue = pstats.killpercent; + itemvalue = pstats.itempercent; + secretvalue = pstats.secretpercent; + nextstage = 5; + last_ticon = 0; + S_StartSound(NULL, sfx_explode); + } + else if (acceleratestage >= 2) + { + S_StartSound(NULL, sfx_explode); + return ga_exit; + } + } + + if (last_ticon) + { + if ((ticon - last_ticon) <= 90) // 3 * TICRATE + return ga_nothing; + } + + state = false; + + switch(nextstage) + { + case 0: + S_StartSound(NULL, sfx_explode); + nextstage = 1; + break; + + case 1: // kills + killvalue += 4; + if (killvalue > pstats.killpercent) + { + S_StartSound(NULL, sfx_explode); + killvalue = pstats.killpercent; + last_ticon = ticon; + nextstage = 2; + } + else { + state = true; + } + break; + + case 2: // item + itemvalue += 4; + if (itemvalue > pstats.itempercent) + { + S_StartSound(NULL, sfx_explode); + itemvalue = pstats.itempercent; + last_ticon = ticon; + nextstage = 3; + } + else { + state = true; + } + break; + + case 3: // secret + secretvalue += 4; + if (secretvalue > pstats.secretpercent) + { + S_StartSound(NULL, sfx_explode); + secretvalue = pstats.secretpercent; + last_ticon = ticon; + nextstage = 4; + } + else { + state = true; + } + break; + + case 4: + S_StartSound(NULL, sfx_explode); + last_ticon = ticon; + nextstage = 5; + break; + } + + if (!state && (acceleratestage == 0)) + { + if (nextstage == 5) { + acceleratestage = 1; + } + } + + // Play Sound sfx_pistol + if (!(gametic & 3) && state) + { + S_StartSound(NULL, sfx_pistol); + } + + return ga_nothing; +} + +void IN_Drawer(void) // 80005164 +{ + int i, c; + char password[32]; + char *pbuff; + + I_ClearFrame(); + + gDPPipeSync(GFX1++); + gDPSetCycleType(GFX1++, G_CYC_FILL); + gDPSetRenderMode(GFX1++, G_RM_NOOP, G_RM_NOOP2); + gDPSetColorImage(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_32b, SCREEN_WD, OS_K0_TO_PHYSICAL(cfb[vid_side])); + // Fill borders with black + gDPSetFillColor(GFX1++, GPACK_RGBA5551(0,0,0,0) << 16 | GPACK_RGBA5551(0,0,0,0)) ; + gDPFillRectangle(GFX1++, 0, 0, SCREEN_WD-1, SCREEN_HT-1); + + M_DrawBackground(63, 25, 128, "EVIL"); + + ST_DrawString(-1, 20, MapInfo[gamemap].name, PACKRGBA(255, 255, 255, text_alpha)); + + ST_DrawString(-1, 36, "Finished", PACKRGBA(255, 255, 255, text_alpha)); + + if ((nextstage > 0) && (killvalue > -1)) + { + ST_DrawString(57, 60, "Kills", PACKRGBA(192, 0, 0, text_alpha)); + ST_DrawString(248, 60, "%", PACKRGBA(192, 0, 0, text_alpha)); + ST_DrawNumber(210, 60, killvalue, 1, PACKRGBA(192, 0, 0, text_alpha)); + } + + if ((nextstage > 1) && (itemvalue > -1)) + { + ST_DrawString(57, 78, "Items", PACKRGBA(192, 0, 0, text_alpha)); + ST_DrawString(248, 78, "%", PACKRGBA(192, 0, 0, text_alpha)); + ST_DrawNumber(210, 78, itemvalue, 1, PACKRGBA(192, 0, 0, text_alpha)); + } + + if ((nextstage > 2) && (secretvalue > -1)) + { + ST_DrawString(57, 99, "Secrets", PACKRGBA(192, 0, 0, text_alpha)); + ST_DrawString(248, 99, "%", PACKRGBA(192, 0, 0, text_alpha)); + ST_DrawNumber(210, 99, secretvalue, 1, PACKRGBA(192, 0, 0, text_alpha)); + } + + if ((nextstage > 3)) + { + ST_DrawString(57, 120, "Time", PACKRGBA(192, 0, 0, text_alpha)); + ST_DrawString(210, 120, timetext, PACKRGBA(192, 0, 0, text_alpha)); + } + + if ((nextstage > 4) && (nextmap < LASTLEVEL)) + { + ST_DrawString(-1, 145, "Entering", PACKRGBA(255, 255, 255, text_alpha)); + ST_DrawString(-1, 161, MapInfo[nextmap].name, PACKRGBA(255, 255, 255, text_alpha)); + + ST_DrawString(-1, 187, "Password", PACKRGBA(255, 255, 255, text_alpha)); + + pbuff = password; + for (i = 0; i < 16; i++) + { + c = i & 3; + if ((i < 0) && (c != 0)) { + c -= 4; + } + if (c == 0) { + *pbuff++ = ' '; + } + + *pbuff++ = passwordChar[Passwordbuff[i]]; + } + *pbuff = 0; + + ST_DrawString(-1, 203, password, PACKRGBA(255, 255, 255, text_alpha)); + } + + I_DrawFrame(); +} diff --git a/Doom 64/m_bbox.c b/Doom 64/m_bbox.c @@ -0,0 +1,21 @@ +/* m_bbox.c */ + +#include "doomdef.h" + +void M_ClearBox(fixed_t *box) // 80000450 +{ + box[BOXTOP] = box[BOXRIGHT] = MININT; + box[BOXBOTTOM] = box[BOXLEFT] = MAXINT; +} + +void M_AddToBox(fixed_t *box, fixed_t x, fixed_t y) // 80000470 +{ + if (x<box[BOXLEFT]) + box[BOXLEFT] = x; + if (x>box[BOXRIGHT]) + box[BOXRIGHT] = x; + if (y<box[BOXBOTTOM]) + box[BOXBOTTOM] = y; + if (y>box[BOXTOP]) + box[BOXTOP] = y; +} diff --git a/Doom 64/m_fixed.c b/Doom 64/m_fixed.c @@ -0,0 +1,99 @@ + +/* m_fixed.c -- fixed point implementation */ + +#include "i_main.h" +#include "doomdef.h" +#include "p_spec.h" +#include "r_local.h" + +/* +=============== += += FixedDiv += +=============== +*/ + +fixed_t FixedDiv(fixed_t a, fixed_t b) // 80002BF8 +{ + fixed_t aa, bb; + unsigned c; + int sign; + + sign = a^b; + + if (a < 0) + aa = -a; + else + aa = a; + + if (b < 0) + bb = -b; + else + bb = b; + + if ((unsigned)(aa >> 14) >= bb) + { + if (sign < 0) + c = MININT; + else + c = MAXINT; + } + else + c = (fixed_t) FixedDiv2(a, b); + + return c; +} + +/* +=============== += += FixedMul += +=============== +*/ + +fixed_t FixedMul(fixed_t a, fixed_t b) // 800044D0 +{ + s64 result = ((s64) a * (s64) b) >> 16; + + return (fixed_t) result; +} + +#if 0 +s64 FixedMul2(s64 a, s64 b) // 800044D0 +{ + register s64 flo; + + //asm(".set noreorder"); + asm("dmult $4, $5"); + asm("mflo $3"); + asm("dsra $3, 16"); + asm("move %0, $3":"=r" (flo):); + + return (fixed_t) flo; + + /* + dmult $4, $5 + mflo $2 + dsra $2, $2, 16 + jr $31 + nop + */ +} +#endif // 0 + +/* +=============== += += FixedDiv2 += +=============== +*/ + +fixed_t FixedDiv2(fixed_t a, fixed_t b) // 800044E4 +{ + s64 result = ((s64) a << 16) / (s64)b; + + return (fixed_t) result; +} diff --git a/Doom 64/m_fixed_s.s b/Doom 64/m_fixed_s.s @@ -0,0 +1,98 @@ +#include <asm.h> +#include <PR/R4300.h> +#include <PR/ultratypes.h> + +#define zero $0 +#define at $1 +#define v0 $2 +#define v1 $3 +#define a0 $4 +#define a1 $5 +#define a2 $6 +#define a3 $7 +#define t0 $8 +#define t1 $9 +#define t2 $10 +#define t3 $11 +#define t4 $12 +#define t5 $13 +#define t6 $14 +#define t7 $15 +#define s0 $16 +#define s1 $17 +#define s2 $18 +#define s3 $19 +#define s4 $20 +#define s5 $21 +#define s6 $22 +#define s7 $23 +#define t8 $24 +#define t9 $25 +#define k0 $26 +#define k1 $27 +#define gp $28 +#define sp $29 +#define fp $30 +#define ra $31 +#define return s7 + + .text + .set noreorder + +/*------------------------------------------*/ +/* fixed_t FixedMul (fixed_t a, fixed_t b) */ +/*------------------------------------------*/ + +.globl FixedMul +.ent FixedMul + +FixedMul: /* 800044D0 */ + + dmult $4, $5 + mflo $2 + dsra $2, $2, 16 + jr $31 + nop + +.end FixedMul + +/*-------------------------------------------*/ +/* fixed_t FixedDiv2 (fixed_t a, fixed_t b) */ +/*-------------------------------------------*/ + +.globl FixedDiv2 +.ent FixedDiv2 + +FixedDiv2: /* 800044E4 */ + + dsll $4, $4, 16 + ddiv $4, $5 + +/*---------------------------------------------------*/ +/* automatically generated with opcode (ddiv $4, $5) */ +/* and -mips3 on command line */ +/*---------------------------------------------------*/ +/* + bne $5, $0, loc_800044F8 + nop + break 0x1C00 + +loc_800044F8: + daddiu $1, $0, 0xffff + bne $5, $1, loc_80004514 + daddiu $1, $0, 0x0001 + dsll32 $1, $1, 0x1f + bne $4, $1, loc_80004514 + nop + break 0x1800 + +loc_80004514: + mflo $4 +*/ +/*--------------------------------------------------*/ + + mflo $2 + jr $31 + nop + +.end FixedDiv2 diff --git a/Doom 64/m_main.c b/Doom 64/m_main.c @@ -0,0 +1,2639 @@ +/* m_main.c -- menu routines */ + +#include "doomdef.h" +#include "r_local.h" +#include "st_main.h" + +//intermission +int DrawerStatus; + +#define CT_TXT00 "default: %d" +#define CT_TXT01 "right" +#define CT_TXT02 "left" +#define CT_TXT03 "forward" +#define CT_TXT04 "backward" +#define CT_TXT05 "attack" +#define CT_TXT06 "use" +#define CT_TXT07 "map" +#define CT_TXT08 "speed" +#define CT_TXT09 "strafe on" +#define CT_TXT10 "strafe left" +#define CT_TXT11 "strafe right" +#define CT_TXT12 "weapon backward" +#define CT_TXT13 "weapon forward" + +char *ControlText[] = //8007517C +{ + CT_TXT00, CT_TXT01, CT_TXT02, CT_TXT03, CT_TXT04, + CT_TXT05, CT_TXT06, CT_TXT07, CT_TXT08, CT_TXT09, + CT_TXT10, CT_TXT11, CT_TXT12, CT_TXT13 +}; + +#define M_TXT00 "Control Pad" +#define M_TXT01 "Volume" +#define M_TXT02 "Display" +#define M_TXT03 "Password" +#define M_TXT04 "Main Menu" +#define M_TXT05 "Restart Level" +#define M_TXT06 "\x90 Return" +#define M_TXT07 "Music Volume" +#define M_TXT08 "Sound Volume" +#define M_TXT09 "Brightness" +#define M_TXT10 "Resume" +#define M_TXT11 "Options" +#define M_TXT12 "Default" +#define M_TXT13 "Default" +#define M_TXT14 "New Game" +#define M_TXT15 "Be Gentle!" +#define M_TXT16 "Bring it on!" +#define M_TXT17 "I own Doom!" +#define M_TXT18 "Watch me die!" +#define M_TXT19 "Nightmare" +#define M_TXT20 "Yes" +#define M_TXT21 "No" +#define M_TXT22 "Features" +#define M_TXT23 "WARP TO LEVEL" +#define M_TXT24 "INVULNERABLE" +#define M_TXT25 "HEALTH BOOST" +#define M_TXT26 "SECURITY KEYS" +#define M_TXT27 "WEAPONS" +#define M_TXT28 "Exit" +#define M_TXT29 "DEBUG" +#define M_TXT30 "TEXTURE TEST" +#define M_TXT31 "WALL BLOCKING" +#define M_TXT32 "Center Display" +#define M_TXT33 "Messages:" +#define M_TXT34 "Status Bar:" +#define M_TXT35 "LOCK MONSTERS" +#define M_TXT36 "SCREENSHOT" +#define M_TXT37 "MAP EVERYTHING" +#define M_TXT38 "MACRO PEEK" +#define M_TXT39 "MUSIC TEST" +#define M_TXT40 "WARP TO FUN" +#define M_TXT41 "Control Stick" +#define M_TXT42 "Default" +#define M_TXT43 "Sensitivity" +#define M_TXT44 "Manage Pak" +#define M_TXT45 "Do not use Pak" +#define M_TXT46 "Try again" +#define M_TXT47 "Create game note" + +#define M_TXT48 "COLORS" // [GEC] NEW CHEAT CODE +#define M_TXT49 "FULL BRIGHT" // [GEC] NEW CHEAT CODE +#define M_TXT50 "FILTER" // [GEC] NEW CHEAT CODE + +char *MenuText[] = // 8005ABA0 +{ + M_TXT00, M_TXT01, M_TXT02, M_TXT03, M_TXT04, + M_TXT05, M_TXT06, M_TXT07, M_TXT08, M_TXT09, + M_TXT10, M_TXT11, M_TXT12, M_TXT13, M_TXT14, + M_TXT15, M_TXT16, M_TXT17, M_TXT18, M_TXT19, + M_TXT20, M_TXT21, M_TXT22, M_TXT23, M_TXT24, + M_TXT25, M_TXT26, M_TXT27, M_TXT28, M_TXT29, + M_TXT30, M_TXT31, M_TXT32, M_TXT33, M_TXT34, + M_TXT35, M_TXT36, M_TXT37, M_TXT38, M_TXT39, + M_TXT40, M_TXT41, M_TXT42, M_TXT43, M_TXT44, + M_TXT45, M_TXT46, M_TXT47, + M_TXT48, M_TXT49, M_TXT50 // [GEC] NEW +}; + +menuitem_t Menu_Title[2] = // 8005A978 +{ + { 14, 115, 190 }, // New Game + { 11, 115, 210 }, // Options +}; + +menuitem_t Menu_Skill[4] = // 8005A990 +{ + { 15, 102, 80 }, // Be Gentle! + { 16, 102, 100}, // Bring it on! + { 17, 102, 120}, // I own Doom! + { 18, 102, 140}, // Watch me die! + /* Disable on Doom 64 Original */ + //{ 19, 102, 160}, // Nightmare +}; + +menuitem_t Menu_Options[6] = // 8005A9C0 +{ + { 0, 102, 60 }, // Control Pad + { 41, 102, 80 }, // Control Stick + { 1, 102, 100}, // Volume + { 2, 102, 120}, // Display + { 3, 102, 140}, // Password + { 6, 102, 160}, // Return +}; + +menuitem_t Menu_Volume[4] = // 8005AA08 +{ + { 7, 102, 60 }, // Music Volume + { 8, 102, 100}, // Sound Volume + { 12, 102, 140}, // Default Volume + { 6, 102, 160}, // Return +}; + +menuitem_t Menu_ControlStick[3] = // 8005AA38 +{ + { 43, 102, 90 }, // Sensitivity + { 42, 102, 130}, // Default Sensitivity + { 6, 102, 150}, // Return +}; + +menuitem_t Menu_Display[6] = // 8005AA5C +{ + { 9, 102, 60 }, // Brightness + { 32, 102, 100}, // Center Display + { 33, 102, 120}, // Messages + { 34, 102, 140}, // Status Bar + { 13, 102, 160}, // Default Display + { 6, 102, 180}, // Return +}; + +menuitem_t Menu_Game[4] = // 8005AAA4 +{ + { 11, 122, 80 }, // Options + { 4, 122, 100}, // Main Menu + { 5, 122, 120}, // Restart Level + { 22, 122, 140}, // Features +}; + +menuitem_t Menu_Quit[2] = // 8005AAD4 +{ + { 20, 142, 100}, // Yes + { 21, 142, 120}, // No +}; + +menuitem_t Menu_DeleteNote[2] = // 8005AAEC +{ + { 20, 142, 100}, // Yes + { 21, 142, 120}, // No +}; + +menuitem_t Menu_ControllerPakBad[2] = // 8005AB04 +{ + { 46, 120, 100}, // Try again + { 45, 120, 120}, // Do not use Pak +}; + +menuitem_t Menu_ControllerPakFull[3] = // 8005AB1C +{ + { 44, 110, 90 }, // Manage Pak + { 47, 110, 110}, // Create game note + { 45, 110, 130}, // Do not use Pak +}; + +menuitem_t Menu_CreateNote[3] = // 8005AB40 +{ + { 20, 110, 90 }, // Yes + { 45, 110, 110}, // Do not use Pak + { 44, 110, 130}, // Manage Pak +}; + +//#define MAXFEATURES 5 +//#define MAXFEATURES 9 +#define MAXFEATURES 12 +menuitem_t Menu_Features[MAXFEATURES] = // 8005AB64 +{ + { 23, 40, 50}, // WARP TO LEVEL + { 24, 40, 60}, // INVULNERABLE + { 25, 40, 70}, // HEALTH BOOST + { 27, 40, 80}, // WEAPONS + { 37, 40, 90}, // MAP EVERYTHING + // + { 26, 40, 100}, // SECURITY KEYS + { 31, 40, 110}, // WALL BLOCKING + { 35, 40, 120}, // LOCK MONSTERS + { 39, 40, 130}, // MUSIC TEST + // + { 48, 40, 140}, // COLORS [GEC] NEW CHEAT CODE + { 49, 40, 150}, // FULL BRIGHT [GEC] NEW CHEAT CODE + { 50, 40, 160}, // FILTER [GEC] NEW CHEAT CODE + + // no usados +//#define M_TXT26 "SECURITY KEYS" +//#define M_TXT28 "Exit" +//#define M_TXT29 "DEBUG" +//#define M_TXT30 "TEXTURE TEST" +//#define M_TXT31 "WALL BLOCKING" +//#define M_TXT35 "LOCK MONSTERS" +//#define M_TXT36 "SCREENSHOT" +//#define M_TXT38 "MACRO PEEK" +//#define M_TXT39 "MUSIC TEST" +//#define M_TXT40 "WARP TO FUN" + +}; + +menudata_t MenuData[8]; // 800A54F0 +int MenuAnimationTic; // 800a5570 +int cursorpos; // 800A5574 +int m_vframe1; // 800A5578 +menuitem_t *MenuItem; // 800A5578 +int itemlines; // 800A5580 +menufunc_t MenuCall; // 800A5584 + +int linepos; // 800A5588 +int text_alpha_change_value; // 800A558C +int MusicID; // 800A5590 +int m_actualmap; // 800A5594 +int last_ticon; // 800A5598 + +skill_t startskill; // 800A55A0 +int startmap; // 800A55A4 +int EnableExpPak; // 800A55A8 + +//----------------------------------------- + +int MenuIdx = 0; // 8005A7A4 +int text_alpha = 255; // 8005A7A8 +int ConfgNumb = 0; // 8005A7AC +int Display_X = 0; // 8005A7B0 +int Display_Y = 0; // 8005A7B4 +boolean enable_messages = true; // 8005A7B8 +boolean enable_statusbar = true;// 8005A7BC +int SfxVolume = 80; // 8005A7C0 +int MusVolume = 80; // 8005A7C4 +int brightness = 0; // 8005A7C8 +int M_SENSITIVITY = 0; // 8005A7CC +boolean FeaturesUnlocked = false; // 8005A7D0 + +int TempConfiguration[13] = // 8005A80C +{ + PAD_LEFT, PAD_RIGHT, PAD_UP, PAD_DOWN, + PAD_LEFT_C, PAD_RIGHT_C, PAD_UP_C, PAD_DOWN_C, + PAD_L_TRIG, PAD_R_TRIG, PAD_A, PAD_B, PAD_Z_TRIG +}; + +int ActualConfiguration[13] = // 8005A840 +{ + PAD_RIGHT, PAD_LEFT, PAD_UP, PAD_DOWN, + PAD_Z_TRIG, + PAD_RIGHT_C, PAD_UP_C, PAD_LEFT_C, PAD_DOWN_C, + PAD_L_TRIG, PAD_R_TRIG, PAD_A, PAD_B +}; + +int DefaultConfiguration[5][13] = // 8005A840 +{ + // Default 1 + { + PAD_RIGHT, PAD_LEFT, PAD_UP, PAD_DOWN, + PAD_Z_TRIG, + PAD_RIGHT_C, PAD_UP_C, PAD_LEFT_C, PAD_DOWN_C, + PAD_L_TRIG, PAD_R_TRIG, PAD_A, PAD_B + }, + + // Default 2 + { + PAD_RIGHT, PAD_LEFT, PAD_UP, PAD_DOWN, + PAD_Z_TRIG, + PAD_RIGHT_C, PAD_UP_C, + PAD_R_TRIG, PAD_L_TRIG, + PAD_A, PAD_DOWN_C, + PAD_B, PAD_LEFT_C + }, + + // Default 3 + { + PAD_RIGHT, PAD_LEFT, PAD_UP, PAD_DOWN, + PAD_Z_TRIG, + PAD_UP_C, PAD_UP, + PAD_R_TRIG, + PAD_DOWN, PAD_LEFT_C, PAD_RIGHT_C, + PAD_A, PAD_B + }, + + // Default 4 + { + PAD_RIGHT_C, PAD_LEFT_C, + PAD_UP, PAD_DOWN, + PAD_Z_TRIG, + PAD_UP, PAD_UP_C, + PAD_L_TRIG, + PAD_DOWN_C, PAD_LEFT, PAD_RIGHT, + PAD_A, PAD_B + }, + + // Default 5 + { + PAD_RIGHT, PAD_LEFT, PAD_UP, PAD_DOWN, + PAD_A, PAD_RIGHT_C, PAD_UP_C, PAD_DOWN_C, + PAD_Z_TRIG, PAD_L_TRIG, PAD_R_TRIG, + PAD_B, PAD_LEFT_C + } +}; + +//----------------------------------------- + +int M_RunTitle(void) // 80007630 +{ + int exit; + + DrawerStatus = 0; + startskill = sk_easy; + startmap = 1; + MenuIdx = 0; + MenuItem = Menu_Title; + MenuCall = M_MenuTitleDrawer; + text_alpha = 0; + itemlines = 2; + cursorpos = 0; + last_ticon = 0; + + S_StartMusic(116); + + exit = MiniLoop(M_FadeInStart, M_MenuClearCall, M_MenuTicker, M_MenuGameDrawer); + I_WIPE_FadeOutScreen(); + S_StopMusic(); + + if (exit == ga_timeout) + return ga_timeout; + + G_InitNew(startskill, startmap, ga_nothing); + G_RunGame(); + + return 0; +} + +int M_ControllerPak(void) // 80007724 +{ + int exit; + int ret; + boolean PakBad; + + PakBad = false; + + while(1) + { + ret = I_CheckControllerPak(); + + if ((ret != PFS_ERR_NOPACK) && (ret != PFS_ERR_ID_FATAL)) + PakBad = true; + + if(ret == 0) + { + ret = I_ReadPakFile(); + + // Free Pak_Data + if (Pak_Data) + { + Z_Free(Pak_Data); + Pak_Data = NULL; + } + + if(ret == 0) + { + exit = ga_nothing; + break; + } + + // Create Controller Pak Note + MenuItem = Menu_CreateNote; + itemlines = 3; + MenuCall = M_MenuTitleDrawer; + cursorpos = 0; + + MiniLoop(M_FadeInStart, NULL, M_MenuTicker, M_MenuGameDrawer); + M_FadeOutStart(8); + + if (cursorpos != 0) + { + exit = ga_exit; + break; + } + + // Check Memory and Files Used on Controller Pak + if ((Pak_Memory > 0) && (FilesUsed != 16)) + { + if (I_CreatePakFile() != 0) + goto ControllerPakBad; + + exit = ga_nothing; + break; + } + + // Show Controller Pak Full + MenuItem = Menu_ControllerPakFull; + itemlines = 3; + MenuCall = M_MenuTitleDrawer; + cursorpos = 0; + + MiniLoop(M_FadeInStart, NULL, M_MenuTicker, M_MenuGameDrawer); + M_FadeOutStart(8); + + if (cursorpos != 1) + { + exit = ga_exit; + break; + } + } + else + { + if (PakBad == false) + { + exit = ga_exit; + break; + } + + // Show Controller Pak Bad + ControllerPakBad: + MenuItem = Menu_ControllerPakBad; + itemlines = 2; + MenuCall = M_MenuTitleDrawer; + cursorpos = 0; + + MiniLoop(M_FadeInStart, NULL, M_MenuTicker, M_MenuGameDrawer); + M_FadeOutStart(8); + + if (cursorpos != 0) + { + exit = ga_exit; + break; + } + } + } + + return exit; +} + +#define MAXSENSIVITY 20 + +int M_ButtonResponder(int buttons) // 80007960 +{ + int sensitivity; + int NewButtons; + + /* Copy Default Buttons */ + NewButtons = (buttons); + + /* Analyze Analog Stick (up / down) */ + sensitivity = (int)((buttons) << 24) >> 24; + + if (sensitivity <= -MAXSENSIVITY) + NewButtons |= PAD_DOWN; + else if (sensitivity >= MAXSENSIVITY) + NewButtons |= PAD_UP; + + /* Analyze Analog Stick (left / right) */ + sensitivity = (int)(((buttons & 0xff00) >> 8) << 24) >> 24; + + if (sensitivity <= -MAXSENSIVITY) + NewButtons |= PAD_LEFT; + else if (sensitivity >= MAXSENSIVITY) + NewButtons |= PAD_RIGHT; + + return NewButtons & 0xffff0000; +} + +void M_AlphaInStart(void) // 800079E0 +{ + text_alpha = 0; + text_alpha_change_value = 20; +} + +void M_AlphaOutStart(void) // 800079F8 +{ + text_alpha = 255; + text_alpha_change_value = -20; +} + +int M_AlphaInOutTicker(void) // 80007A14 +{ + if ((gamevbls < gametic) && ((gametic & 3) == 0)) { + MenuAnimationTic = MenuAnimationTic + 1 & 7; + } + + text_alpha += text_alpha_change_value; + if (text_alpha_change_value < 0) + { + if (text_alpha < 0) + { + text_alpha = 0; + return 8; + } + } + else + { + if ((text_alpha_change_value > 0) && (text_alpha >= 256)) + { + text_alpha = 255; + return 8; + } + } + + return 0; +} + +void M_FadeInStart(void) // 80007AB4 +{ + MiniLoop(M_AlphaInStart, NULL, M_AlphaInOutTicker, M_MenuGameDrawer); +} + +void M_FadeOutStart(int exitmode) // 80007AEC +{ + if (exitmode == 8) + MiniLoop(M_AlphaOutStart, NULL, M_AlphaInOutTicker, M_MenuGameDrawer); +} + +void M_SaveMenuData(void) // 80007B2C +{ + menudata_t *mdat; + + // Save Actual Menu Page + mdat = &MenuData[MenuIdx]; + MenuIdx += 1; + + mdat->menu_item = MenuItem; + mdat->item_lines = itemlines; + mdat->menu_call = MenuCall; + mdat->cursor_pos = cursorpos; + + // Start Menu Fade Out + MiniLoop(M_AlphaOutStart, NULL, M_AlphaInOutTicker, M_MenuGameDrawer); +} + +void M_RestoreMenuData(boolean alpha_in) // 80007BB8 +{ + menudata_t *mdat; + + // Restore Previous Save Menu Page + MenuIdx -= 1; + mdat = &MenuData[MenuIdx]; + + MenuItem = mdat->menu_item; + itemlines = mdat->item_lines; + MenuCall = mdat->menu_call; + cursorpos = mdat->cursor_pos; + + // Start Menu Fade In + if (alpha_in) + MiniLoop(M_AlphaInStart, NULL, M_AlphaInOutTicker, M_MenuGameDrawer); +} + +void M_MenuGameDrawer(void) // 80007C48 +{ + if (DrawerStatus == 1) { + P_Drawer(); + } + else if (DrawerStatus == 2) { + F_DrawerIntermission(); + } + else if (DrawerStatus == 3) { + F_Drawer(); + } + else + { + I_ClearFrame(); + + gDPPipeSync(GFX1++); + gDPSetCycleType(GFX1++, G_CYC_FILL); + gDPSetRenderMode(GFX1++,G_RM_NOOP,G_RM_NOOP2); + gDPSetColorImage(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_32b, SCREEN_WD, OS_K0_TO_PHYSICAL(cfb[vid_side])); + gDPSetFillColor(GFX1++, GPACK_RGBA5551(0,0,0,0) << 16 | GPACK_RGBA5551(0,0,0,0)); + gDPFillRectangle(GFX1++, 0, 0, SCREEN_WD-1, SCREEN_HT-1); + + M_DrawBackground(56, 57, 80, "TITLE"); + + if (MenuItem != Menu_Title) { + M_DrawOverlay(0, 0, 320, 240, 96); + } + + MenuCall(); + I_DrawFrame(); + } +} + +extern mobj_t mobjhead; +extern mapthing_t *spawnlist; // 800A5D74 +extern int spawncount; // 800A5D78 +extern int gobalcheats; // [GEC] + +int M_MenuTicker(void) // 80007E0C +{ + unsigned int buttons, oldbuttons; + int exit; + int truebuttons; + int ret; + int i; + mobj_t *m; + + /* animate skull */ + if ((gamevbls < gametic) && ((gametic & 3) == 0)) + MenuAnimationTic = MenuAnimationTic + 1 & 7; + + buttons = M_ButtonResponder(ticbuttons[0]); + oldbuttons = oldticbuttons[0] & 0xffff0000; + + /* exit menu if button press */ + if (buttons != 0) + last_ticon = ticon; + + /* exit menu if time out */ + if ((MenuItem == Menu_Title) && ((ticon - last_ticon) >= 900)) // 30 * TICRATE + { + exit = ga_timeout; + } + else + { + /* check for movement */ + if (!(buttons & (PAD_Z_TRIG|ALL_JPAD))) + m_vframe1 = 0; + else + { + m_vframe1 = m_vframe1 - vblsinframe[0]; + if (m_vframe1 <= 0) + { + m_vframe1 = 0xf; // TICRATE / 2 + + if (buttons & PAD_DOWN) + { + cursorpos += 1; + + if (cursorpos >= itemlines) + cursorpos = 0; + + S_StartSound(NULL, sfx_switch1); + } + else if (buttons & PAD_UP) + { + cursorpos -= 1; + + if (cursorpos < 0) + cursorpos = itemlines-1; + + S_StartSound(NULL, sfx_switch1); + } + } + } + + if ((buttons & PAD_START) && !(oldticbuttons[0] & PAD_START)) + { + if ((MenuItem == Menu_Title) || + (MenuItem == Menu_ControllerPakBad) || + (MenuItem == Menu_CreateNote) || + (MenuItem == Menu_ControllerPakFull)) + { + return ga_nothing; + } + else + { + if (MenuIdx != 0) + S_StartSound(NULL, sfx_pistol); + + return ga_exit; + } + } + else + { + truebuttons = (0 < (buttons ^ oldbuttons)); + + if (truebuttons) + truebuttons = (0 < (buttons & ALL_BUTTONS)); + + switch(MenuItem[cursorpos].casepos) + { + + case 0: // Control Pad + if (truebuttons) + { + S_StartSound(NULL, sfx_pistol); + M_SaveMenuData(); + + MenuCall = M_ControlPadDrawer; + cursorpos = 0; + linepos = 0; + + MiniLoop(M_FadeInStart,M_FadeOutStart,M_ControlPadTicker,M_MenuGameDrawer); + M_RestoreMenuData(true); + return ga_nothing; + } + break; + + case 1: // Volume + if (truebuttons) + { + S_StartSound(NULL, sfx_pistol); + M_SaveMenuData(); + + MenuItem = Menu_Volume; + itemlines = 4; + MenuCall = M_VolumeDrawer; + cursorpos = 0; + + MiniLoop(M_FadeInStart,M_FadeOutStart,M_MenuTicker,M_MenuGameDrawer); + M_RestoreMenuData(true); + return ga_nothing; + } + break; + + case 2: // Display + if (truebuttons) + { + S_StartSound(NULL, sfx_pistol); + M_SaveMenuData(); + + MenuItem = Menu_Display; + itemlines = 6; + MenuCall = M_DisplayDrawer; + cursorpos = 0; + + MiniLoop(M_FadeInStart,M_FadeOutStart,M_MenuTicker,M_MenuGameDrawer); + M_RestoreMenuData(true); + return ga_nothing; + } + break; + + case 3: // Password + if (truebuttons) + { + S_StartSound(NULL, sfx_pistol); + M_SaveMenuData(); + + ret = I_CheckControllerPak(); + exit = ga_exit; + + if (ret == 0) + { + if (I_ReadPakFile() == 0) + { + EnableExpPak = 1; + MenuCall = M_LoadPakDrawer; + exit = MiniLoop(M_LoadPakStart,M_LoadPakStop,M_LoadPakTicker,M_MenuGameDrawer); + } + else + exit = ga_exit; + } + + if (exit == ga_exit) + { + MenuCall = M_PasswordDrawer; + exit = MiniLoop(M_PasswordStart,M_PasswordStop,M_PasswordTicker,M_MenuGameDrawer); + } + + if (exit == ga_exit) + { + M_RestoreMenuData(true); + return ga_nothing; + } + + if (EnableExpPak != 0) + { + return exit; + } + + EnableExpPak = (M_ControllerPak() == 0); + return exit; + } + break; + + case 4: // Main Menu + if (truebuttons) + { + S_StartSound(NULL, sfx_pistol); + M_SaveMenuData(); + + MenuItem = Menu_Quit; + itemlines = 2; + MenuCall = M_MenuTitleDrawer; + cursorpos = 1; + + exit = MiniLoop(M_FadeInStart,M_FadeOutStart,M_MenuTicker,M_MenuGameDrawer); + M_RestoreMenuData((exit == ga_exit)); + if (exit == ga_exit) { + return ga_nothing; + } + + return 5;//ga_exitdemo; + } + break; + + case 5: // Restart Level + if (truebuttons) + { + S_StartSound(NULL, sfx_pistol); + M_SaveMenuData(); + + MenuItem = Menu_Quit; + itemlines = 2; + MenuCall = M_MenuTitleDrawer; + cursorpos = 1; + + exit = MiniLoop(M_FadeInStart, M_FadeOutStart, M_MenuTicker, M_MenuGameDrawer); + M_RestoreMenuData((exit == ga_exit)); + + if (exit == ga_exit) + return ga_nothing; + + return ga_restart; + } + break; + + case 6: // Return + if (truebuttons) + { + S_StartSound(NULL, sfx_pistol); + return ga_exit; + } + break; + + case 7: // Music Volume + if (buttons & PAD_RIGHT) + { + MusVolume += 1; + if (MusVolume <= 100) + { + S_SetMusicVolume(MusVolume); + if (MusVolume & 1) + { + S_StartSound(NULL, sfx_secmove); + return ga_nothing; + } + } + else + { + MusVolume = 100; + } + } + else if (buttons & PAD_LEFT) + { + MusVolume -= 1; + if (MusVolume < 0) + { + MusVolume = 0; + } + else + { + S_SetMusicVolume(MusVolume); + if (MusVolume & 1) + { + S_StartSound(NULL, sfx_secmove); + return ga_nothing; + } + } + } + break; + + case 8: // Sound Volume + if (buttons & PAD_RIGHT) + { + SfxVolume += 1; + if (SfxVolume <= 100) + { + S_SetSoundVolume(SfxVolume); + if (SfxVolume & 1) + { + S_StartSound(NULL, sfx_secmove); + return ga_nothing; + } + } + else + { + SfxVolume = 100; + } + } + else if (buttons & PAD_LEFT) + { + SfxVolume -= 1; + if (SfxVolume < 0) + { + SfxVolume = 0; + } + else + { + S_SetSoundVolume(SfxVolume); + if (SfxVolume & 1) + { + S_StartSound(NULL, sfx_secmove); + return ga_nothing; + } + } + } + break; + + case 9: // Brightness + if (buttons & PAD_RIGHT) + { + brightness += 1; + if (brightness <= 100) + { + P_RefreshBrightness(); + if (brightness & 1) + { + S_StartSound(NULL, sfx_secmove); + return ga_nothing; + } + } + else + { + brightness = 100; + } + } + else if (buttons & PAD_LEFT) + { + brightness -= 1; + if (brightness < 0) + { + brightness = 0; + } + else + { + P_RefreshBrightness(); + if (brightness & 1) + { + S_StartSound(NULL, sfx_secmove); + return ga_nothing; + } + } + } + break; + + case 11: // Options + if (truebuttons) + { + S_StartSound(NULL, sfx_pistol); + M_SaveMenuData(); + + MenuItem = Menu_Options; + itemlines = 6; + MenuCall = M_MenuTitleDrawer; + cursorpos = 0; + + exit = MiniLoop(M_FadeInStart, M_FadeOutStart, M_MenuTicker, M_MenuGameDrawer); + M_RestoreMenuData((exit == ga_exit)); + + if (exit == ga_exit) + return ga_nothing; + + return exit; + } + break; + + case 12: // Default Volume + if (truebuttons) + { + S_StartSound(NULL, sfx_switch2); + + SfxVolume = 0x50; + MusVolume = 0x50; + + S_SetMusicVolume(MusVolume); + S_SetSoundVolume(SfxVolume); + + return ga_nothing; + } + break; + + case 13: // Default Display + if (truebuttons) + { + S_StartSound(NULL, sfx_switch2); + + Display_X = 0; + Display_Y = 0; + + enable_messages = true; + enable_statusbar = true; + + brightness = 0; + I_MoveDisplay(0,0); + P_RefreshBrightness(); + return ga_nothing; + } + break; + + case 14: // New Game + if (truebuttons) + { + S_StartSound(NULL, sfx_pistol); + M_FadeOutStart(8); + + // Check ControllerPak + EnableExpPak = (M_ControllerPak() == 0); + + MenuItem = Menu_Skill; + itemlines = 4; + MenuCall = M_MenuTitleDrawer; + cursorpos = 1; // Set Default Bring it on! + + MiniLoop(M_FadeInStart, M_MenuClearCall, M_MenuTicker, M_MenuGameDrawer); + startskill = MenuItem[cursorpos].casepos - 15; + + return ga_exit; + } + break; + + case 15: // Be Gentle! + case 16: // Bring it on! + case 17: // I own Doom! + case 18: // Watch me die! + //case 19: // Nightmare + if (truebuttons) + { + S_StartSound(NULL, sfx_pistol); + return ga_exit; + } + break; + + case 20: // Yes + case 46: // Try again + case 47: // Create game note + if (truebuttons) + { + S_StartSound(NULL, sfx_pistol); + return 5; //ga_exitdemo; + } + break; + + case 21: // No + case 45: // Do not use Pak + if (truebuttons) + { + S_StartSound(NULL, sfx_pistol); + return ga_exit; + } + break; + + case 22: // Features + if (truebuttons) + { + S_StartSound(NULL, sfx_pistol); + M_SaveMenuData(); + + players[0].cheats &= 0xffff1fff; + + MenuItem = Menu_Features; + itemlines = MAXFEATURES; + MenuCall = M_FeaturesDrawer; + cursorpos = 0; + m_actualmap = gamemap; + + exit = MiniLoop(M_FadeInStart,M_FadeOutStart,M_MenuTicker,M_MenuGameDrawer); + M_RestoreMenuData((exit == 8)); + + if (exit == 8) + return ga_nothing; + + return exit; + } + break; + + case 23: // WARP TO LEVEL + if (buttons ^ oldbuttons) + { + if (buttons & PAD_LEFT) + { + m_actualmap -= 1; + if (m_actualmap > 27) + m_actualmap = 27; + + if (m_actualmap > 0) + { + S_StartSound(NULL, sfx_switch2); + return ga_nothing; + } + m_actualmap = 1; + } + else if (buttons & PAD_RIGHT) + { + m_actualmap += 1; + if (m_actualmap < 28) + { + S_StartSound(NULL, sfx_switch2); + return ga_nothing; + } + m_actualmap = 27; + } + else if (buttons & ALL_CBUTTONS) + { + gamemap = m_actualmap; + startmap = m_actualmap; + return ga_warped; + } + } + break; + + case 24: // INVULNERABLE + if (((gamemap != 32) & truebuttons)) + { + players[0].cheats ^= CF_GODMODE; + S_StartSound(NULL, sfx_switch2); + return ga_nothing; + } + break; + + case 25: // HEALTH BOOST + if (truebuttons) + { + players[0].cheats |= CF_HEALTH; + players[0].health = 100; + players[0].mo->health = 100; + S_StartSound(NULL, sfx_switch2); + return ga_nothing; + } + break; + + case 26: // SECURITY KEYS + /* Not available in the release code */ + /* + Reconstructed code based on Psx Doom + */ + if (truebuttons) + { + players[0].cheats |= CF_ALLKEYS; + + for (m = mobjhead.next; m != &mobjhead; m = m->next) + { + switch (m->type) + { + case MT_ITEM_BLUECARDKEY: + players[0].cards[it_bluecard] = true; + break; + case MT_ITEM_REDCARDKEY: + players[0].cards[it_redcard] = true; + break; + case MT_ITEM_YELLOWCARDKEY: + players[0].cards[it_yellowcard] = true; + break; + case MT_ITEM_YELLOWSKULLKEY: + players[0].cards[it_yellowskull] = true; + break; + case MT_ITEM_REDSKULLKEY: + players[0].cards[it_redskull] = true; + break; + case MT_ITEM_BLUESKULLKEY: + players[0].cards[it_blueskull] = true; + break; + default: + break; + } + } + + for (i = 0; i < spawncount; i++) + { + switch (spawnlist[i].type) + { + case 5: + players[0].cards[it_bluecard] = true; + break; + case 13: + players[0].cards[it_redcard] = true; + break; + case 6: + players[0].cards[it_yellowcard] = true; + break; + case 39: + players[0].cards[it_yellowskull] = true; + break; + case 38: + players[0].cards[it_redskull] = true; + break; + case 40: + players[0].cards[it_blueskull] = true; + break; + default: + break; + } + } + + S_StartSound(NULL, sfx_switch2); + return ga_nothing; + } + break; + + case 27: // WEAPONS + if (truebuttons) + { + players[0].cheats |= CF_WEAPONS; + + for(i = 0; i < NUMWEAPONS; i++) { + players[0].weaponowned[i] = true; + } + + for(i = 0; i < NUMAMMO; i++) { + players[0].ammo[i] = players[0].maxammo[i]; + } + + S_StartSound(NULL, sfx_switch2); + return ga_nothing; + } + break; + + case 28: // Exit + /* nothing special */ + break; + + case 29: // DEBUG + /* Not available in the release code */ + if (truebuttons) + { + players[0].cheats ^= CF_DEBUG; + S_StartSound(NULL, sfx_switch2); + return ga_nothing; + } + break; + + case 30: // TEXTURE TEST + /* Not available in the release code */ + if (truebuttons) + { + players[0].cheats ^= CF_TEX_TEST; + S_StartSound(NULL, sfx_switch2); + return ga_nothing; + } + break; + + case 31: // WALL BLOCKING + /* Not available in the release code */ + /* + In my opinion it must have been the NOCLIP cheat code + */ + if (truebuttons) + { + players[0].cheats ^= CF_WALLBLOCKING; + players[0].mo->flags ^= MF_NOCLIP; + S_StartSound(NULL, sfx_switch2); + return ga_nothing; + } + break; + + case 32: // Center Display + if (truebuttons) + { + S_StartSound(NULL, sfx_pistol); + M_SaveMenuData(); + + MenuCall = M_CenterDisplayDrawer; + + MiniLoop(M_FadeInStart,M_FadeOutStart,M_CenterDisplayTicker,M_MenuGameDrawer); + M_RestoreMenuData(true); + + return ga_nothing; + } + break; + + case 33: // Messages + if (truebuttons) + { + S_StartSound(NULL, sfx_switch2); + enable_messages ^= true; + } + break; + + case 34: // Status Bar + if (truebuttons) + { + S_StartSound(NULL, sfx_switch2); + enable_statusbar ^= true; + } + break; + + case 35: // LOCK MONSTERS + /* Not available in the release code */ + /* + Reconstructed code based on Doom 64 Ex + */ + if (truebuttons) + { + players[0].cheats ^= CF_LOCKMOSTERS; + S_StartSound(NULL, sfx_switch2); + return ga_nothing; + } + break; + + case 36: // SCREENSHOT + /* Not available in the release code */ + if (truebuttons) + { + players[0].cheats ^= CF_SCREENSHOT; + S_StartSound(NULL, sfx_switch2); + return ga_nothing; + } + break; + + case 37: // MAP EVERYTHING + if (truebuttons) + { + players[0].cheats ^= CF_ALLMAP; + S_StartSound(NULL, sfx_switch2); + return ga_nothing; + } + break; + + case 38: // MACRO PEEK + /* Not available in the release code */ + if (truebuttons) + { + players[0].cheats ^= CF_MACROPEEK; + S_StartSound(NULL, sfx_switch2); + return ga_nothing; + } + break; + + case 39: // MUSIC TEST + /* Not available in the release code */ + /* + Reconstructed code in my interpretation + */ + if (buttons ^ oldbuttons) + { + if (buttons & PAD_LEFT) + { + MusicID -= 1; + if (MusicID > 0) + { + S_StartSound(NULL, sfx_switch2); + return ga_nothing; + } + MusicID = 1; + } + else if (buttons & PAD_RIGHT) + { + MusicID += 1; + if (MusicID < 25) + { + S_StartSound(NULL, sfx_switch2); + return ga_nothing; + } + MusicID = 24; + } + else if (buttons & ALL_CBUTTONS) + { + S_StopMusic(); + S_StartMusic(MusicID+92); + return ga_nothing; + } + } + break; + + case 41: // Control Stick + if (truebuttons) + { + S_StartSound(NULL, sfx_pistol); + M_SaveMenuData(); + + MenuItem = Menu_ControlStick; + itemlines = 3; + MenuCall = M_ControlStickDrawer; + cursorpos = 0; + + MiniLoop(M_FadeInStart, M_FadeOutStart, M_MenuTicker, M_MenuGameDrawer); + M_RestoreMenuData(true); + + return ga_nothing; + } + break; + + case 42: // Default Sensitivity + if (truebuttons) + { + S_StartSound(NULL, sfx_switch2); + M_SENSITIVITY = 0; + } + break; + + case 43: // Sensitivity + if (buttons & PAD_RIGHT) + { + M_SENSITIVITY += 1; + if (M_SENSITIVITY <= 100) + { + if (M_SENSITIVITY & 1) + { + S_StartSound(NULL, sfx_secmove); + return ga_nothing; + } + } + else + { + M_SENSITIVITY = 100; + } + } + else if (buttons & PAD_LEFT) + { + M_SENSITIVITY -= 1; + if (M_SENSITIVITY < 0) + { + M_SENSITIVITY = 0; + } + else + { + if (M_SENSITIVITY & 1) + { + S_StartSound(NULL, sfx_secmove); + return ga_nothing; + } + } + } + break; + + case 44: // Manage Pak + if (truebuttons) + { + S_StartSound(NULL, sfx_pistol); + M_SaveMenuData(); + + MenuCall = M_ControllerPakDrawer; + linepos = 0; + cursorpos = 0; + + exit = MiniLoop(M_FadeInStart, M_FadeOutStart, M_ScreenTicker, M_MenuGameDrawer); + M_RestoreMenuData((exit == 8)); + + if (exit == 8) + return ga_nothing; + + return exit; + } + break; + + case 48: // COLORS [GEC] NEW CHEAT CODE + if (truebuttons) + { + players[0].cheats ^= CF_NOCOLORS; + gobalcheats ^= CF_NOCOLORS; + P_RefreshBrightness(); + S_StartSound(NULL, sfx_switch2); + return ga_nothing; + } + break; + + case 49: // FULL BRIGHT [GEC] NEW CHEAT CODE + if (truebuttons) + { + players[0].cheats ^= CF_FULLBRIGHT; + gobalcheats ^= CF_FULLBRIGHT; + P_RefreshBrightness(); + S_StartSound(NULL, sfx_switch2); + return ga_nothing; + } + break; + + case 50: // FILTER [GEC] NEW CHEAT CODE + if (truebuttons) + { + players[0].cheats ^= CF_FILTER; + gobalcheats ^= CF_FILTER; + S_StartSound(NULL, sfx_switch2); + return ga_nothing; + } + break; + } + + exit = ga_nothing; + } + } + + return exit; +} + +void M_MenuClearCall(void) // 80008E6C +{ + MenuCall = NULL; +} + +void M_MenuTitleDrawer(void) // 80008E7C +{ + menuitem_t *item; + int i; + + if (MenuItem == Menu_Game) + { + ST_DrawString(-1, 20, "Pause", text_alpha | 0xc0000000); + ST_DrawString(-1, 200, "press \x8d to resume", text_alpha | 0xffffff00); + } + else if (MenuItem == Menu_Skill) + { + ST_DrawString(-1, 20, "Choose Your Skill...", text_alpha | 0xc0000000); + } + else if (MenuItem == Menu_Options) + { + ST_DrawString(-1, 20, "Options", text_alpha | 0xc0000000); + } + else if (MenuItem == Menu_Quit) + { + ST_DrawString(-1, 20, "Quit Game?", text_alpha | 0xc0000000); + } + else if (MenuItem == Menu_DeleteNote) + { + ST_DrawString(-1, 20, "Delete Game Note?", text_alpha | 0xc0000000); + } + else if (MenuItem == Menu_ControllerPakBad) + { + ST_DrawString(-1, 20, "Controller Pak Bad", text_alpha | 0xc0000000); + } + else if (MenuItem == Menu_ControllerPakFull) + { + ST_DrawString(-1, 20, "Controller Pak Full", text_alpha | 0xc0000000); + } + else if (MenuItem == Menu_CreateNote) + { + ST_DrawString(-1, 20, "Create Game Note?", text_alpha | 0xc0000000); + } + + item = MenuItem; + for(i = 0; i < itemlines; i++) + { + ST_DrawString(item->x, item->y, MenuText[item->casepos], text_alpha | 0xc0000000); + item++; + } + + ST_DrawSymbol(MenuItem[0].x -37, MenuItem[cursorpos].y -9, MenuAnimationTic + 70, text_alpha | 0xffffff00); +} + +void M_FeaturesDrawer(void) // 800091C0 +{ + char *text, textbuff[16]; + menuitem_t *item; + int i; + + ST_DrawString(-1, 20, "Features", text_alpha | 0xc0000000); + item = MenuItem; + + for(i = 0; i < itemlines; i++) + { + if ((item->casepos == 23) && ((m_actualmap >= 25) && (m_actualmap <= 27))) + { + /* Show "WARP TO FUN" text */ + ST_Message(item->x, item->y, MenuText[40], text_alpha | 0xffffff00); + } + else + { + /* Show "WARP TO LEVEL" text */ + ST_Message(item->x, item->y, MenuText[item->casepos], text_alpha | 0xffffff00); + } + + text = textbuff; + switch(item->casepos) + { + case 23: /* WARP TO LEVEL */ + sprintf(textbuff, "%s", MapInfo[m_actualmap].name); + break; + case 24: /* INVULNERABLE */ + text = (!(players[0].cheats & CF_GODMODE)) ? "OFF": "ON"; + break; + case 25: /* HEALTH BOOST */ + text = (!(players[0].cheats & CF_HEALTH)) ? "-" : "100%"; + break; + case 26: /* SECURITY KEYS */ + text = (!(players[0].cheats & CF_ALLKEYS)) ? "-" : "100%"; + break; + case 27: /* WEAPONS */ + text = (!(players[0].cheats & CF_WEAPONS)) ? "-" : "100%"; + break; + case 28: /* Exit */ + break; + case 29: /* DEBUG */ + text = (!(players[0].cheats & CF_DEBUG)) ? "OFF": "ON"; + break; + case 30: /* TEXTURE TEST */ + text = (!(players[0].cheats & CF_TEX_TEST)) ? "OFF": "ON"; + break; + case 31: /* WALL BLOCKING */ + text = (!(players[0].cheats & CF_WALLBLOCKING)) ? "ON": "OFF"; + break; + case 35: /* LOCK MONSTERS */ + text = (!(players[0].cheats & CF_LOCKMOSTERS)) ? "OFF": "ON"; + break; + case 36: /* SCREENSHOT */ + text = (!(players[0].cheats & CF_SCREENSHOT)) ? "OFF": "ON"; + break; + case 37: /* MAP EVERYTHING */ + text = (!(players[0].cheats & CF_ALLMAP)) ? "OFF": "ON"; + break; + case 38: /* MACRO PEEK */ + text = ((players[0].cheats & CF_MACROPEEK)) ? "ON": "OFF"; + break; + case 39: /* MUSIC TEST */ + sprintf(textbuff, "%d", MusicID); + break; + + // [GEC] NEW CHEAT CODES + case 48: /* COLORS */ + text = (!(players[0].cheats & CF_NOCOLORS)) ? "ON": "OFF"; + break; + + case 49: /* FULL BRIGHT */ + text = (!(players[0].cheats & CF_FULLBRIGHT)) ? "OFF": "ON"; + break; + + case 50: /* FILTER */ + text = (!(players[0].cheats & CF_FILTER)) ? "LINEAR": "NEAREST"; + break; + + default: + text = "NOT IMPLEMENTED"; + break; + } + + ST_Message(item->x + 130, item->y, text, text_alpha | 0xffffff00); + item++; + } + + ST_DrawSymbol(MenuItem->x -10, MenuItem[cursorpos].y -1, 78, text_alpha | 0xffffff00); +} + +void M_VolumeDrawer(void) // 800095B4 +{ + menuitem_t *item; + int i; + + ST_DrawString(-1, 20, "Volume", text_alpha | 0xc0000000); + item = Menu_Volume; + + for(i = 0; i < itemlines; i++) + { + ST_DrawString(item->x, item->y, MenuText[item->casepos], text_alpha | 0xc0000000); + item++; + } + + ST_DrawSymbol(MenuItem->x - 37, MenuItem[cursorpos].y - 9, MenuAnimationTic + 70, text_alpha | 0xffffff00); + + ST_DrawSymbol(102, 80, 68, text_alpha | 0xffffff00); + ST_DrawSymbol(MusVolume + 103, 80, 69, text_alpha | 0xffffff00); + + ST_DrawSymbol(102, 120, 68, text_alpha | 0xffffff00); + ST_DrawSymbol(SfxVolume + 103, 120, 69, text_alpha | 0xffffff00); +} + +void M_ControlStickDrawer(void) // 80009738 +{ + menuitem_t *item; + int i; + + ST_DrawString(-1, 20, "Control Stick", text_alpha | 0xc0000000); + + item = Menu_ControlStick; + + for(i = 0; i < itemlines; i++) + { + ST_DrawString(item->x, item->y, MenuText[item->casepos], text_alpha | 0xc0000000); + item++; + } + + ST_DrawSymbol(MenuItem->x - 37, MenuItem[cursorpos].y - 9, MenuAnimationTic + 70, text_alpha | 0xffffff00); + + ST_DrawSymbol(102,110,68,text_alpha | 0xffffff00); + ST_DrawSymbol(M_SENSITIVITY + 103, 110, 69, text_alpha | 0xffffff00); +} + +void M_DisplayDrawer(void) // 80009884 +{ + char *text; + menuitem_t *item; + int i, casepos; + + ST_DrawString(-1, 20, "Display", text_alpha | 0xc0000000); + + item = Menu_Display; + + for(i = 0; i < 6; i++) + { + casepos = item->casepos; + + if (casepos == 33) // Messages: + { + if (enable_messages) + text = "On"; + else + text = "Off"; + } + else if (casepos == 34) // Status Bar: + { + if (enable_statusbar) + text = "On"; + else + text = "Off"; + } + else + { + text = NULL; + } + + if (text) + ST_DrawString(item->x + 140, item->y, text, text_alpha | 0xc0000000); + + ST_DrawString(item->x, item->y, MenuText[casepos], text_alpha | 0xc0000000); + + item++; + } + + ST_DrawSymbol(102, 80, 68, text_alpha | 0xffffff00); + ST_DrawSymbol(brightness + 103, 80, 69, text_alpha | 0xffffff00); + + ST_DrawSymbol(Menu_Display[0].x - 37, Menu_Display[cursorpos].y - 9, MenuAnimationTic + 70, text_alpha | 0xffffff00); +} + +void M_DrawBackground(int x, int y, int color, char *name) // 80009A68 +{ + int width, height; + int yh, xh, t; + int offset; + byte *data; + + data = (byte *)W_CacheLumpName(name, PU_CACHE, dec_jag); + + gDPPipeSync(GFX1++); + gDPSetCycleType(GFX1++, G_CYC_1CYCLE); + + gDPSetTextureLUT(GFX1++, G_TT_RGBA16); + gDPSetTexturePersp(GFX1++, G_TP_NONE); + + gDPSetAlphaCompare(GFX1++, G_AC_THRESHOLD); + + gDPSetBlendColor(GFX1++, 0, 0, 0, 0); + gDPSetCombineMode(GFX1++, G_CC_D64COMB03, G_CC_D64COMB03); + + if (color == 0xff) + { + gDPSetRenderMode(GFX1++, G_RM_TEX_EDGE, G_RM_TEX_EDGE2); + } + else + { + gDPSetRenderMode(GFX1++, G_RM_XLU_SURF, G_RM_XLU_SURF2); + } + + gDPSetPrimColorD64(GFX1++, 0, 0, color); + + width = ((gfxN64_t*)data)->width; + height = ((gfxN64_t*)data)->height; + + // Load Palette Data + offset = (width * height); + offset = (offset + 7) & ~7; + gDPSetTextureImage(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_16b , + 1, data + offset + sizeof(gfxN64_t)); + + gDPTileSync(GFX1++); + gDPSetTile(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_4b, 0, 256, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0); + + gDPLoadSync(GFX1++); + gDPLoadTLUTCmd(GFX1++, G_TX_LOADTILE, 255); + + gDPPipeSync(GFX1++); + + xh = (width + 7) & ~7; + + t = 0; + while (height != 0) + { + if ((2048 / xh) < height) + yh = (2048 / xh); + else + yh = height; + + // Load Image Data + gDPSetTextureImage(GFX1++, G_IM_FMT_CI, G_IM_SIZ_8b , + width, data + sizeof(gfxN64_t)); + + // Clip Rectangle From Image + gDPSetTile(GFX1++, G_IM_FMT_CI, G_IM_SIZ_8b, + (width + 7) / 8, 0, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0); + + gDPLoadSync(GFX1++); + gDPLoadTile(GFX1++, G_TX_LOADTILE, + (0 << 2), (t << 2), + ((width - 1) << 2), (((t + yh) - 1) << 2)); + + gDPPipeSync(GFX1++); + gDPSetTile(GFX1++, G_IM_FMT_CI, G_IM_SIZ_8b, + (width + 7) / 8, 0, G_TX_RENDERTILE, 0, 0, 0, 0, 0, 0, 0); + + gDPSetTileSize(GFX1++, G_TX_RENDERTILE, + (0 << 2), (t << 2), + ((width - 1) << 2), (((t + yh) - 1) << 2)); + + gSPTextureRectangle(GFX1++, + (x << 2), (y << 2), + ((width + x) << 2), ((yh + y) << 2), + G_TX_RENDERTILE, + (0 << 5), (t << 5), + (1 << 10), (1 << 10)); + + height -= yh; + t += yh; + y += yh; + } + + globallump = -1; +} + +void M_DrawOverlay(int x, int y, int w, int h, int color) // 80009F58 +{ + I_CheckGFX(); + + gDPPipeSync(GFX1++); + + gDPSetCycleType(GFX1++, G_CYC_1CYCLE); + + gDPSetTextureLUT(GFX1++, G_TT_RGBA16); + gDPSetTexturePersp(GFX1++, G_TP_NONE); + + gDPSetAlphaCompare(GFX1++, G_AC_THRESHOLD); + + gDPSetBlendColor(GFX1++, 0, 0, 0, 0); + gDPSetCombineMode(GFX1++, G_CC_D64COMB05, G_CC_D64COMB05); + gDPSetRenderMode(GFX1++, G_RM_XLU_SURF, G_RM_XLU_SURF2); + + gDPSetPrimColorD64(GFX1++, 0, 0, color); + + gDPFillRectangle(GFX1++, x, y, w, h); + globallump = -1; +} + +int M_ScreenTicker(void) // 8000A0F8 +{ + int exit; + unsigned int buttons; + unsigned int oldbuttons; + OSPfsState *fState; + + if ((FilesUsed == -1) && (I_CheckControllerPak() == 0)) + { + cursorpos = 0; + linepos = 0; + } + + if ((gamevbls < gametic) && ((gametic & 3) == 0)) + MenuAnimationTic = MenuAnimationTic + 1 & 7; + + buttons = M_ButtonResponder(ticbuttons[0]); + oldbuttons = oldticbuttons[0] & 0xffff0000; + + if (!(buttons & ALL_JPAD)) + { + m_vframe1 = 0; + } + else + { + m_vframe1 -= vblsinframe[0]; + + if (m_vframe1 <= 0) + { + m_vframe1 = 0xf; // TICRATE/2 + + if (buttons & PAD_DOWN) + { + cursorpos += 1; + + if (cursorpos < 16) + S_StartSound(NULL, sfx_switch1); + else + cursorpos = 15; + + if ((linepos + 5) < cursorpos) + linepos += 1; + } + else if (buttons & PAD_UP) + { + cursorpos -= 1; + + if (cursorpos < 0) + cursorpos = 0; + else + S_StartSound(NULL, sfx_switch1); + + if(cursorpos < linepos) + linepos -= 1; + } + } + } + + if (!(buttons ^ oldbuttons) || !(buttons & PAD_START)) + { + if (buttons ^ oldbuttons) + { + if(buttons == (PAD_LEFT_C|PAD_RIGHT_C)) + { + fState = &FileState[cursorpos]; + + if(fState->file_size != 0) + { + S_StartSound(NULL, sfx_pistol); + M_SaveMenuData(); + + MenuItem = Menu_DeleteNote; + itemlines = 2; + MenuCall = M_MenuTitleDrawer; + cursorpos = 1; + MiniLoop(M_FadeInStart, NULL, M_MenuTicker, M_MenuGameDrawer); + + M_FadeOutStart(8); + if (cursorpos == 0) + { + if (I_DeletePakFile(cursorpos) == 0) + { + fState->file_size = 0; + } + else + { + FilesUsed = -1; + } + } + M_RestoreMenuData(true); + } + } + } + exit = 0; + } + else + { + S_StartSound(NULL, sfx_pistol); + exit = 8; + } + return exit; +} + +void M_ControllerPakDrawer(void) // 8000A3E4 +{ + byte idx; + int i,j; + OSPfsState *fState; + char buffer [32]; + char *tmpbuf; + + ST_DrawString(-1, 20, "Controller Pak", text_alpha | 0xc0000000); + + if (FilesUsed == -1) + { + if ((MenuAnimationTic & 2) != 0) + ST_DrawString(-1, 114, "Controller Pak removed!", text_alpha | 0xc0000000); + + ST_DrawString(-1, 210, "press \x8d to exit", text_alpha | 0xffffff00); + } + else + { + fState = &FileState[linepos]; + + for(i = linepos; i < (linepos + 6); i++) + { + if (fState->file_size == 0) + { + D_memmove(buffer, "empty"); + } + else + { + tmpbuf = buffer; + + for(j = 0; j < 16; j++) + { + idx = (byte) fState->game_name[j]; + if(idx == 0) + break; + + tmpbuf[0] = Pak_Table[idx]; + tmpbuf++; + } + + idx = (byte) fState->ext_name[0]; + if (idx != 0) + { + tmpbuf[0] = '.'; + tmpbuf[1] = Pak_Table[idx]; + tmpbuf += 2; + } + + *tmpbuf = '\0'; + } + + ST_DrawString(60, (i - linepos) * 15 + 60, buffer, text_alpha | 0xc0000000); + + fState++; + } + + if (linepos != 0) + { + ST_DrawString(60, 45, "\x8F more...", text_alpha | 0xffffff00); + } + + if ((linepos + 6) < 16) + { + ST_DrawString(60, 150, "\x8E more...", text_alpha | 0xffffff00); + } + + sprintf(buffer, "pages used: %d free: %d", FileState[cursorpos].file_size >> 8, Pak_Memory); + + ST_DrawString(-1, 170, buffer, text_alpha | 0xc0000000); + ST_DrawSymbol(23, (cursorpos - linepos) * 15 + 51, MenuAnimationTic + 70, text_alpha | 0xffffff00); + + ST_DrawString(-1, 200, "press \x8d to exit", text_alpha | 0xffffff00); + ST_DrawString(-1, 215, "press \x84\x85 to delete", text_alpha | 0xffffff00); + } +} + +void M_SavePakStart(void) // 8000A6E8 +{ + int i; + int ret; + int size; + + cursorpos = 0; + linepos = 0; + last_ticon = 0; + + ret = I_CheckControllerPak(); + if (ret == 0) + { + if (I_ReadPakFile() == 0) + { + size = Pak_Size / 32; + + i = 0; + if (size != 0) + { + do + { + if (Pak_Data[i * 32] == 0) + break; + + i++; + } while (i != size); + } + + if (i < size) + { + cursorpos = i; + + if (!(size < (i+6))) + linepos = i; + else + linepos = (size-6); + } + } + } + else + { + FilesUsed = -1; + } +} + +void M_SavePakStop(void) // 8000A7B4 +{ + S_StartSound(NULL, sfx_pistol); + + if (Pak_Data) + { + Z_Free(Pak_Data); + Pak_Data = NULL; + } +} + +int M_SavePakTicker(void) // 8000A804 +{ + unsigned int buttons; + unsigned int oldbuttons; + int size; + + if ((gamevbls < gametic) && ((gametic & 3) == 0)) { + MenuAnimationTic = MenuAnimationTic + 1 & 7; + } + + buttons = M_ButtonResponder(ticbuttons[0]); + oldbuttons = oldticbuttons[0] & 0xffff0000; + + if ((buttons != oldbuttons) && (buttons & PAD_START)) { + return ga_exit; + } + + if (FilesUsed == -1) + { + if (I_CheckControllerPak()) { + return ga_nothing; + } + + if (I_ReadPakFile()) { + FilesUsed = -1; + return ga_nothing; + } + + cursorpos = 0; + linepos = 0; + } + + if (!(buttons & ALL_JPAD)) { + m_vframe1 = 0; + } + else + { + m_vframe1 -= vblsinframe[0]; + + if (m_vframe1 <= 0) + { + m_vframe1 = 0xf; // TICRATE/2 + + if (buttons & PAD_DOWN) + { + cursorpos += 1; + + size = (Pak_Size / 32) - 1; + + if (size < cursorpos) + cursorpos = size; + else + S_StartSound(NULL, sfx_switch1); + + + if ((linepos + 5) < cursorpos) + linepos += 1; + } + else if (buttons & PAD_UP) + { + cursorpos -= 1; + + if (cursorpos < 0) + cursorpos = 0; + else + S_StartSound(NULL, sfx_switch1); + + if(cursorpos < linepos) + linepos -= 1; + } + } + } + + if (last_ticon == 0) + { + if ((buttons != oldbuttons) && (buttons == (PAD_RIGHT_C|PAD_LEFT_C))) + { + // save the next level number and password data in text format + sprintf(&Pak_Data[cursorpos * 32], "level %2.2d", nextmap); + D_memcpy(&Pak_Data[(cursorpos * 32) + 16], &Passwordbuff, 16); + + if (I_SavePakFile(File_Num, PFS_WRITE, Pak_Data, Pak_Size) == 0) { + last_ticon = ticon; + } + else + { + FilesUsed = -1; + if (Pak_Data) + { + Z_Free(Pak_Data); + Pak_Data = NULL; + } + } + } + } + else if ((ticon - last_ticon) >= 60) // 2 * TICRATE + { + return ga_exit; + } + + return ga_nothing; +} + +void M_SavePakDrawer(void) // 8000AB44 +{ + int i; + char buffer[36]; + + I_ClearFrame(); + + gDPPipeSync(GFX1++); + gDPSetCycleType(GFX1++, G_CYC_FILL); + gDPSetRenderMode(GFX1++,G_RM_NOOP,G_RM_NOOP2); + gDPSetColorImage(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_32b, SCREEN_WD, OS_K0_TO_PHYSICAL(cfb[vid_side])); + // Fill borders with black + gDPSetFillColor(GFX1++, GPACK_RGBA5551(0,0,0,0) << 16 | GPACK_RGBA5551(0,0,0,0)) ; + gDPFillRectangle(GFX1++, 0, 0, SCREEN_WD-1, SCREEN_HT-1); + + M_DrawBackground(63, 25, 128, "EVIL"); + + ST_DrawString(-1, 20, "Controller Pak", text_alpha | 0xc0000000); + + if (FilesUsed == -1) + { + if (MenuAnimationTic & 2) + { + ST_DrawString(-1, 100, "Controller Pak removed!", 0xc00000ff); + ST_DrawString(-1, 120, "Game cannot be saved.", 0xc00000ff); + } + + ST_DrawString(-1, 210, "press \x8d to exit", text_alpha | 0xffffff00); + } + else + { + for(i = linepos; i < (linepos + 6); i++) + { + if (Pak_Data[i * 32] == 0) { + D_memmove(buffer, "empty"); + } + else { + D_memmove(buffer, &Pak_Data[i * 32]); + } + + ST_DrawString(60, (i - linepos) * 15 + 65, buffer, text_alpha | 0xc0000000); + } + + if (linepos != 0) { + ST_DrawString(60, 50, "\x8f more...", text_alpha | 0xffffff00); + } + + if ((linepos + 6) <= ((Pak_Size >> 5) - 1)) { + ST_DrawString(60, 155, "\x8e more...", text_alpha | 0xffffff00); + } + + ST_DrawSymbol(23, (cursorpos - linepos) * 15 + 56, MenuAnimationTic + 70, text_alpha | 0xffffff00); + + ST_DrawString(-1, 195, "press \x8d to exit", text_alpha | 0xffffff00); + ST_DrawString(-1, 210, "press \x84\x85 to save", text_alpha | 0xffffff00); + } + + I_DrawFrame(); +} + +void M_LoadPakStart(void) // 8000AEEC +{ + int i; + int size; + + cursorpos = 0; + linepos = 0; + + size = Pak_Size / 32; + + i = 0; + if (size != 0) + { + do + { + if (Pak_Data[i * 32]) + break; + + i++; + } while (i != size); + } + + if (i < size) + { + cursorpos = i; + + if (!(size < (i+6))) + linepos = i; + else + linepos = (size-6); + } + + M_FadeInStart(); +} + +void M_LoadPakStop(void) // 8000AF8C +{ + S_StartSound(NULL, sfx_pistol); + M_FadeOutStart(ga_exit); + + if (Pak_Data) + { + Z_Free(Pak_Data); + Pak_Data = NULL; + } +} + +int M_LoadPakTicker(void) // 8000AFE4 +{ + unsigned int buttons; + unsigned int oldbuttons; + int size; + int skill; + int levelnum; + int exit; + + if ((gamevbls < gametic) && ((gametic & 3U) == 0)) { + MenuAnimationTic = MenuAnimationTic + 1 & 7; + } + + buttons = M_ButtonResponder(ticbuttons[0]); + oldbuttons = oldticbuttons[0] & 0xffff0000; + + if (!(buttons & ALL_JPAD)) + { + m_vframe1 = 0; + } + else + { + m_vframe1 -= vblsinframe[0]; + + if (m_vframe1 <= 0) + { + m_vframe1 = 0xf; // TICRATE/2 + + if (buttons & PAD_DOWN) + { + cursorpos += 1; + + size = (Pak_Size / 32) - 1; + + if (size < cursorpos) + cursorpos = size; + else + S_StartSound(NULL, sfx_switch1); + + if ((linepos + 5) < cursorpos) + linepos += 1; + + } + else if (buttons & PAD_UP) + { + cursorpos -= 1; + + if (cursorpos < 0) + cursorpos = 0; + else + S_StartSound(NULL, sfx_switch1); + + if(cursorpos < linepos) + linepos -= 1; + } + } + } + + if (!(buttons ^ oldbuttons) || !(buttons & PAD_START)) + { + if (!(buttons ^ oldbuttons) || buttons != (PAD_RIGHT_C|PAD_LEFT_C) || + (Pak_Data[cursorpos * 32] == 0)) + { + exit = ga_nothing; + } + else + { + // load the password data in text format + D_memcpy(&Passwordbuff, &Pak_Data[((cursorpos * 32) + 16)], 16); + + if (M_DecodePassword(Passwordbuff, &levelnum, &skill, 0) == 0) + { + CurPasswordSlot = 0; + exit = ga_exit; + } + else + { + doPassword = true; + CurPasswordSlot = 16; + + startmap = gamemap = levelnum; + startskill = gameskill = skill; + + exit = ga_warped; + } + } + } + else + { + exit = ga_exit; + } + + return exit; +} + +void M_LoadPakDrawer(void) // 8000B270 +{ + int i; + char buffer[32]; + + ST_DrawString(-1, 20, "Controller Pak", text_alpha | 0xc0000000); + + for(i = linepos; i < (linepos + 6); i++) + { + if (FilesUsed == -1) { + D_memmove(buffer, "-"); + } + else if (Pak_Data[i * 32] == 0) { + D_memmove(buffer, "no save"); + } + else { + D_memmove(buffer, &Pak_Data[i * 32]); + } + + ST_DrawString(60, (i - linepos) * 15 + 65, buffer, text_alpha | 0xc0000000); + } + + if (linepos != 0) { + ST_DrawString(60, 50, "\x8f more...", text_alpha | 0xffffff00); + } + + if ((linepos + 6) <= ((Pak_Size >> 5) - 1)) { + ST_DrawString(60, 155, "\x8e more...", text_alpha | 0xffffff00); + } + + ST_DrawSymbol(23, (cursorpos - linepos) * 15 + 56, MenuAnimationTic + 70, text_alpha | 0xffffff00); + + ST_DrawString(-1, 195, "press \x8D to exit", text_alpha | 0xffffff00); + ST_DrawString(-1, 210, "press \x84\x85 to load", text_alpha | 0xffffff00); +} + +int M_CenterDisplayTicker(void) // 8000B4C4 +{ + unsigned int buttons, oldbuttons; + int exit; + + buttons = M_ButtonResponder(ticbuttons[0]); + oldbuttons = oldticbuttons[0] & 0xffff0000; + + if ((buttons == oldbuttons) || !(buttons & PAD_START)) + { + if (buttons & PAD_LEFT) + { + Display_X -= 1; + if (Display_X < -16) + Display_X = -16; + } + else if (buttons & PAD_RIGHT) + { + Display_X += 1; + if (Display_X > 24) + Display_X = 24; + } + + if (buttons & PAD_UP) + { + Display_Y -= 1; + if (Display_Y < -20) + Display_Y = -20; + } + else if (buttons & PAD_DOWN) + { + Display_Y += 1; + if (Display_Y > 12) + Display_Y = 12; + } + + if (buttons & ALL_JPAD) + I_MoveDisplay(Display_X, Display_Y); + + exit = 0; + } + else + { + S_StartSound(NULL, sfx_pistol); + exit = 8; + } + + return exit; +} + +void M_CenterDisplayDrawer(void) // 8000B604 +{ + ST_DrawString(-1, 20, "Center Display", text_alpha | 0xc0000000); + ST_DrawString(-1, 114, "use control pad to adjust", text_alpha | 0xffffff00); + ST_DrawString(-1, 210, "press \x8d to exit", text_alpha | 0xffffff00); +} + +int M_ControlPadTicker(void) // 8000B694 +{ + unsigned int buttons; + unsigned int oldbuttons; + int exit; + int *tmpcfg, code; + + if ((gamevbls < gametic) && ((gametic & 3U) == 0)) { + MenuAnimationTic = MenuAnimationTic + 1 & 7; + } + + buttons = M_ButtonResponder(ticbuttons[0] & 0xffff); + + if (!(buttons & ALL_JPAD)) + { + m_vframe1 = 0; + } + else + { + m_vframe1 = m_vframe1 - vblsinframe[0]; + if (m_vframe1 <= 0) + { + m_vframe1 = 0xf; // TICRATE / 2 + + if (buttons & PAD_DOWN) + { + cursorpos += 1; + if (cursorpos < 14) + S_StartSound(NULL, sfx_switch1); + else + cursorpos = 13; + + if (cursorpos > (linepos + 5)) + linepos += 1; + } + else + { + if (buttons & PAD_UP) + { + cursorpos -= 1; + if (cursorpos < 0) + cursorpos = 0; + else + S_StartSound(NULL, sfx_switch1); + + if (cursorpos < linepos) + linepos -= 1; + } + } + } + } + + buttons = ticbuttons[0] & 0xffff0000; + oldbuttons = oldticbuttons[0] & 0xffff0000; + + if (buttons & PAD_START) + { + S_StartSound(NULL, sfx_pistol); + exit = 8; + } + else + { + if (buttons == oldbuttons) + exit = 0; + else + { + tmpcfg = TempConfiguration; + + if (cursorpos == 0) // Set Default Configuration + { + if (!(buttons & (PAD_UP|PAD_LEFT))) + { + if (buttons & (PAD_DOWN|PAD_RIGHT)) + { + ConfgNumb += 1; + if(ConfgNumb > 4) + ConfgNumb = 0; + } + } + else + { + ConfgNumb -= 1; + if (ConfgNumb < 0) + ConfgNumb = 4; + } + + if ((buttons & (ALL_BUTTONS|ALL_JPAD)) != 0) + { + D_memcpy(ActualConfiguration, DefaultConfiguration[ConfgNumb], (13 * sizeof(int))); + S_StartSound(NULL, sfx_switch2); + return 0; + } + } + else // Set Custom Configuration + { + do + { + code = *tmpcfg++; + if ((code & buttons) != 0) + { + TempConfiguration[cursorpos + 12] = code; + S_StartSound(NULL,sfx_switch2); + return 0; + } + } while (tmpcfg != (int*)(TempConfiguration+13)); + } + exit = 0; + } + } + return exit; +} + +void M_ControlPadDrawer(void) // 8000B988 +{ + int i, lpos; + int *tmpcfg; + char **text; + char buffer [44]; + + ST_DrawString(-1, 20, "Control Pad", text_alpha | 0xc0000000); + + if (linepos < (linepos + 6)) + { + text = &ControlText[linepos]; + lpos = linepos; + do + { + if (lpos != 0) + { + i = 0; + if(lpos != cursorpos || ((ticon & 8U) == 0)) + { + tmpcfg = TempConfiguration; + do + { + if ((*tmpcfg & TempConfiguration[lpos + 12]) != 0) break; + + i += 1; + tmpcfg++; + } while (i != 13); + + ST_DrawSymbol(60, ((lpos - linepos) * 18) + 68, i + 80, text_alpha | 0xffffff00); + } + } + + sprintf(buffer, *text, ConfgNumb + 1); + ST_DrawString(80, ((lpos - linepos) * 18) + 68, buffer, text_alpha | 0xc0000000); + + lpos += 1; + text += 1; + } while (lpos < (linepos + 6)); + } + + if (linepos != 0) { + ST_DrawString(80, 50, "\x8f more...", text_alpha | 0xffffff00); + } + + if ((linepos + 6) < 14) { + ST_DrawString(80, 176, "\x8e more...", text_alpha | 0xffffff00); + } + + ST_DrawSymbol(23,(cursorpos - linepos) * 0x12 + 0x3b, MenuAnimationTic + 0x46, text_alpha | 0xffffff00); + + ST_DrawString(-1, 210, "press \x8d to exit", text_alpha | 0xffffff00); +} diff --git a/Doom 64/m_password.c b/Doom 64/m_password.c @@ -0,0 +1,715 @@ +/* m_password.c -- password (encode/decode) and menu password routines */ + +#include "doomdef.h" +#include "p_local.h" +#include "st_main.h" +#include "r_local.h" + +char *passwordChar = "bcdfghjklmnpqrstvwxyz0123456789?"; // 8005AC60 +int passwordTable[10] = { 1, 8, 9, 5, 6, 2, 7, 0, 4, 3 }; // 8005AC80 + +char *hectic_demo = "rvnh3ct1cd3m0???"; // 8005ACA8 +boolean run_hectic_demo = false; // 8005A7A0 + +byte Passwordbuff[16]; // 800A55B0 +int PassCodePos; // 800A55C0 +int PassInvalidTic; // 800A55C4 + +boolean doPassword = false; // 8005A7A0 +int CurPasswordSlot = 0; // 8005ACBC + +void M_EncodePassword(byte *buff) // 8000BC10 +{ + byte encode[10]; + int i; + int bit; + short decodebit[3]; + int passBit; + int xbit1, xbit2, xbit3; + int maxclip, maxshell, maxcell, maxmisl; + player_t* player; + + player = &players[0]; + D_memset(encode, 0, sizeof(encode)); + + // + // Map and Skill + // + encode[0] = ((((nextmap & 63) << 2) & 0xff) | (gameskill & 3)); + + // + // Weapons + // + bit = 0; + for(i = 0; i < NUMWEAPONS; i++) + { + if(i != wp_fist && i != wp_pistol) + { + if(player->weaponowned[i]) + { + encode[1] |= (1 << bit); + encode[1] = encode[1] & 0xff; + } + + bit++; + } + } + + // + // Get Maximun Ammo + // + maxclip = maxammo[am_clip]; + maxshell = maxammo[am_shell]; + maxcell = maxammo[am_cell]; + maxmisl = maxammo[am_misl]; + + // + // Backpack + // + if(player->backpack) + { + maxclip <<= 1; + maxshell <<= 1; + maxcell <<= 1; + maxmisl <<= 1; + encode[5] |= 0x80; + } + + // + // Clip + // + bit = (player->ammo[am_clip] << 3) / maxclip; + if ((player->ammo[am_clip] << 3) % maxclip) { bit += 1; } + encode[2] = bit << 4; + + // + // Shell + // + bit = (player->ammo[am_shell] << 3) / maxshell; + if ((player->ammo[am_shell] << 3) % maxshell) { bit += 1; } + encode[2] |= bit; + + // + // Cell + // + bit = (player->ammo[am_cell] << 3) / maxcell; + if ((player->ammo[am_cell] << 3) % maxcell) { bit += 1; } + encode[3] = bit << 4; + + // + // Missile + // + bit = (player->ammo[am_misl] << 3) / maxmisl; + if ((player->ammo[am_misl] << 3) % maxmisl) { bit += 1; } + encode[3] |= bit; + + // + // Health + // + bit = (player->health << 3) / 200; + if ((player->health << 3) % 200) { bit += 1; } + encode[4] = bit << 4; + + // + // Armor + // + bit = (player->armorpoints << 3) / 200; + if ((player->armorpoints << 3) % 200) { bit += 1; } + encode[4] |= bit; + + // + // ArmorType + // + encode[5] |= player->armortype; + + // + // Artifacts + // + encode[5] |= (player->artifacts << 2); + + decodebit[0] = (*(short*)&encode[0]); + decodebit[1] = (*(short*)&encode[2]); + decodebit[2] = (*(short*)&encode[4]); + + *(short*)&encode[6] = (~(decodebit[0] + decodebit[1] + decodebit[2])); + *(short*)&encode[8] = (~(decodebit[0] ^ decodebit[1] ^ decodebit[2])); + + for(i = 0; i < 10; i++) + { + bit = encode[passwordTable[i]]; + encode[i] = (encode[i] ^ bit); + } + + bit = 0; + + while(bit < 80) + { + passBit = 0; + + if(bit < 0) { + xbit2 = (bit + 7) >> 3; + } + else { + xbit2 = bit >> 3; + } + + xbit3 = (bit & 7); + + if(bit < 0) + { + if(xbit3 != 0) { + xbit3 -= 8; + } + } + + if((encode[xbit2] & (0x80 >> xbit3))) + { + passBit = 16; + } + + xbit1 = 8; + bit++; + + for(i = 0; i < 4; i++) + { + if(bit < 0) { + xbit2 = (bit + 7) >> 3; + } + else { + xbit2 = bit >> 3; + } + + xbit3 = (bit & 7); + + if(bit < 0) + { + if(xbit3 != 0) { + xbit3 -= 8; + } + } + + if((encode[xbit2] & (0x80 >> xbit3))) + { + passBit |= xbit1; + } + + xbit1 >>= 1; + bit++; + } + + buff[((bit - 1) / 5)] = passBit; + } +} + +int M_DecodePassword(byte *inbuff, int *levelnum, int *skill, player_t *player) // 8000C194 +{ + byte data[16]; + byte decode[10]; + int bit; + int i, j; + short xbit1, xbit2, xbit3; + short x, y; + int passBit; + int decodeBit; + byte checkByte; + + D_memcpy(data, inbuff, 16); + + // + // Decode Password + // + bit = 0; + + while(bit < 80) + { + passBit = 0; + decodeBit = 0x80; + checkByte = 0; + + i = 0; + + while(i != 8) + { + i += 4; + + for(j = 0; j < 4; j++) + { + checkByte = data[bit / 5]; + if((checkByte & (16 >> (bit % 5)))) + { + passBit |= decodeBit; + } + + bit++; + decodeBit >>= 1; + } + } + + if((bit - 1) >= 0) + { + checkByte = ((bit - 1) >> 3); + } + else + { + checkByte = (((bit - 1) + 7) >> 3); + } + + decode[checkByte] = passBit; + } + + for(i = 9; i >= 0; i--) + { + bit = decode[passwordTable[i]]; + decode[i] = (decode[i] ^ bit); + } + + // + // Verify Decoded Password + // + + xbit1 = *(short*)&decode[0]; + xbit2 = *(short*)&decode[2]; + xbit3 = *(short*)&decode[4]; + + x = ((~((xbit1 + xbit2) + xbit3) << 16) >> 16); + y = *(short*)&decode[6]; + + if(x != y) + { + return false; + } + + x = ((~(xbit1 ^ (xbit2 ^ xbit3)) << 16) >> 16); + y = *(short*)&decode[8]; + + if(x != y) + { + return false; + } + + // + // Get Map + // + *levelnum = (decode[0] >> 2); + + // + // Verify Map + // + if ((*levelnum == 0) || (*levelnum >= TOTALMAPS)) + { + return false; + } + + // + // Get Skill + // + *skill = (decode[0] & 3); + + // + // Verify Skill + // + if(*skill > sk_nightmare) + { + return false; + } + + // + // Verify Ammo (Shell / Clip) + // + if((decode[2] & 0xf) >= 9 || (decode[2] >> 4) >= 9) + { + return false; + } + + // + // Verify Ammo (Missile / Cell) + // + if((decode[3] & 0xf) >= 9 || (decode[3] >> 4) >= 9) + { + return false; + } + + // + // Verify (Armor / Health) + // + if((decode[4] & 0xf) >= 9 || (decode[4] >> 4) >= 9) + { + return false; + } + + // + // Verify Armortype + // + if((decode[5] & 3) >= 3) + { + return false; + } + + bit = 0; + if (player != 0) + { + // + // Get Weapons + // + for(i = 0; i < NUMWEAPONS; i++) + { + if(i != wp_fist && i != wp_pistol) + { + if(decode[1] & (1 << bit)) + { + player->weaponowned[i] = true; + } + + bit++; + } + } + + // + // Get Backpack + // + if(decode[5] & 0x80) + { + if (!player->backpack) + { + player->backpack = true; + player->maxammo[am_clip] = (maxammo[am_clip] << 1); + player->maxammo[am_shell] = (maxammo[am_shell] << 1); + player->maxammo[am_cell] = (maxammo[am_cell] << 1); + player->maxammo[am_misl] = (maxammo[am_misl] << 1); + } + } + + // + // Get Clip + // + bit = (decode[2] >> 4) * player->maxammo[am_clip]; + if (bit < 0) { bit += 7; } + player->ammo[am_clip] = bit >> 3; + + // + // Get Shell + // + bit = (decode[2] & 0xf) * player->maxammo[am_shell]; + if (bit < 0) { bit += 7; } + player->ammo[am_shell] = bit >> 3; + + // + // Get Cell + // + bit = (decode[3] >> 4) * player->maxammo[am_cell]; + if (bit < 0) { bit += 7; } + player->ammo[am_cell] = bit >> 3; + + // + // Get Missile + // + bit = (decode[3] & 0xf) * player->maxammo[am_misl]; + if (bit < 0) { bit += 7; } + player->ammo[am_misl] = bit >> 3; + + // + // Get Health + // + bit = (decode[4] >> 4) * 200; + if (bit < 0) { bit += 7; } + player->health = bit >> 3; + + // + // Get Armor + // + bit = (decode[4] & 0xf) * 200; + if (bit < 0) { bit += 7; } + player->armorpoints = bit >> 3; + + // + // Get Armor Type + // + player->armortype = (decode[5] & 3); + + // + // Get Artifacts + // + player->artifacts = ((decode[5] >> 2) & 7); + + // + // Apply Health on mobj_t + // + player->mo->health = player->health; + + // + // Set Cheat Menu If Password Leads To Map 01 + // + if((decode[0] >> 2) == 1) + { + FeaturesUnlocked = true; + } + } + + return true; +} + +void M_PasswordStart(void) // 8000C710 +{ + PassInvalidTic = 0; + PassCodePos = 0; + last_ticon = 0; + M_FadeInStart(); +} + +void M_PasswordStop(void) // 8000C744 +{ + S_StartSound(NULL, sfx_pistol); + M_FadeOutStart(8); +} + +int M_PasswordTicker(void) // 8000C774 +{ + byte *passbuf; + char *hpassbuf; + unsigned int buttons; + unsigned int oldbuttons; + boolean playsound; + int exit; + int skill; + int levelnum; + + if (last_ticon) + { + if ((ticon - last_ticon) < 16) + exit = ga_nothing; + else + exit = ga_warped; + + return exit; + } + + if (PassInvalidTic) + { + if((gametic & 1U) == 0) + { + PassInvalidTic -= 1; + if((PassInvalidTic & 7) == 4) { + S_StartSound(NULL, sfx_itemup); + } + } + } + + buttons = M_ButtonResponder(ticbuttons[0]); + oldbuttons = oldticbuttons[0] & 0xffff0000; + + if (!(buttons & (ALL_TRIG|PAD_A|PAD_B|ALL_JPAD))) + { + m_vframe1 = 0; + } + else + { + m_vframe1 -= vblsinframe[0]; + + if (m_vframe1 <= 0) + { + m_vframe1 = 0xf; // TICRATE / 2 + + playsound = false; + + if (buttons & PAD_UP) + { + if (PassCodePos > 7) + { + playsound = true; + PassCodePos -= 8; + } + } + if ((buttons & PAD_DOWN) && (PassCodePos < 24)) + { + playsound = true; + PassCodePos += 8; + } + + if (buttons & PAD_LEFT) + { + if (PassCodePos > 0) + { + playsound = true; + PassCodePos -= 1; + } + } + else if ((buttons & PAD_RIGHT) && (PassCodePos < 31)) + { + playsound = true; + PassCodePos += 1; + } + + if (playsound) + { + S_StartSound(NULL, sfx_switch1); + } + } + } + + if (buttons == oldbuttons) + { + exit = ga_nothing; + } + else + { + if (buttons & PAD_START) + { + exit = ga_exit; + } + else + { + if (!(buttons & (ALL_TRIG|PAD_A|PAD_B|PAD_UP_C|PAD_DOWN_C|PAD_RIGHT_C))) + { + if (buttons & PAD_LEFT_C) + { + S_StartSound(0, sfx_switch2); + + CurPasswordSlot -= 1; + if (CurPasswordSlot < 0) + CurPasswordSlot = 0; + + Passwordbuff[CurPasswordSlot] = 0; + } + } + else + { + S_StartSound(0, sfx_switch2); + + if (CurPasswordSlot < 16) + { + Passwordbuff[CurPasswordSlot] = (byte)PassCodePos; + CurPasswordSlot += 1; + } + + if (CurPasswordSlot > 15) + { + hpassbuf = hectic_demo; + passbuf = Passwordbuff; + do + { + if (passwordChar[*passbuf++] != *hpassbuf++) + break; + + } while (hpassbuf != (hectic_demo + 16)); + + if ((hectic_demo + 15) < hpassbuf) + { + run_hectic_demo = true; + return ga_exit; + } + + if (M_DecodePassword(Passwordbuff, &levelnum, &skill, NULL) == 0) + { + PassInvalidTic = 16; + } + else + { + doPassword = true; + startmap = gamemap = levelnum; + startskill = gameskill = skill; + last_ticon = ticon; + } + } + } + + exit = ga_nothing; + } + } + + return exit; +} + +void M_PasswordDrawer(void) // 8000CAF0 +{ + byte pass[2]; + byte c; + int texid, cnt; + int xpos, ypos, pos1; + + ST_DrawString(-1, 20, "Password", text_alpha | 0xc0000000); + + for(cnt = 0; cnt < 32; cnt++) + { + pos1 = cnt; + if (cnt < 0) { + pos1 = cnt + 7; + } + pos1 >>= 3; + ypos = (pos1 * 20) + 60; + + if ((cnt == PassCodePos) && (ticon & 8)) + continue; + + c = passwordChar[cnt]; + if ((byte)(c - 'a') < 26) + { + texid = (byte)(c - 55); + ypos = (pos1 * 20) + 63; + } + else if ((byte)(c - '0') < 10) + { + texid = (byte)(c - '0'); + } + else if (c == '?') + { + texid = 14; + } + + pos1 = cnt & 7; + if ((cnt < 0) && (pos1 != 0)) { + pos1 -= 8; + } + xpos = (pos1 * 20) + 84; + + ST_DrawSymbol(xpos, ypos, texid, text_alpha | 0xc0000000); + } + + cnt = PassCodePos; + + pos1 = cnt & 7; + if ((cnt < 0) && (pos1 != 0)) { + pos1 -= 8; + } + xpos = (pos1 * 20) + 80; + + pos1 = cnt; + if (pos1 < 0) { + pos1 = cnt + 7; + } + pos1 >>= 3; + ypos = (pos1 * 20) + 59; + + ST_DrawSymbol(xpos, ypos, 79, text_alpha | 0xffffff00); + + xpos = 47; + cnt = 0; + if ((PassInvalidTic & 4) == 0) + { + pass[1] = '\0'; + do + { + if ((cnt & 3) == 0) { + xpos += 6; + } + + if (cnt < CurPasswordSlot) { + pass[0] = passwordChar[Passwordbuff[cnt]]; + } + else { + pass[0] = '.'; + } + + ST_DrawString(xpos, 160, pass, text_alpha | 0xc0000000); + + xpos += 13; + cnt += 1; + } while (cnt != 16); + } + else + { + ST_DrawString(-1, 160, "Invalid Password", text_alpha | 0xffffff00); + } + + ST_DrawString(-1,195, "press \x8d to exit", text_alpha | 0xffffff00); + ST_DrawString(-1,210, "press \x84 to change", text_alpha | 0xffffff00); +} diff --git a/Doom 64/mem_heap.c b/Doom 64/mem_heap.c @@ -0,0 +1,6 @@ + +#include <ultra64.h> +#include "i_main.h" + +#define MEM_HEAP_SIZE (0x26B510) // 2.41 MB +u64 mem_heap[MEM_HEAP_SIZE / sizeof(u64)]; // 800BA2F0 diff --git a/Doom 64/n64cmd.c b/Doom 64/n64cmd.c @@ -0,0 +1,1109 @@ + +/* ULTRA64 LIBRARIES */ +#include <ultra64.h> +#include "ultratypes.h" +#include <libaudio.h> + +#include "wessseq.h" + +#include "graph.h"//debug + +#define _ALIGN8_ 1 + +#ifndef NOUSEWESSCODE + +extern ALVoice *voice; //800B40E0 + +void wess_set_mute_release(int millisec); +f32 WessCents2Ratio(s32 cents); +void TriggerN64Voice(voice_status *voice_stat/*, unsigned char keynum, unsigned char velnum*/); + +void N64_DriverInit (track_status *ptk_stat);//(master_status_structure *pm_stat); +void N64_DriverExit (track_status *ptk_stat); +void N64_DriverEntry1 (track_status *ptk_stat); +void N64_DriverEntry2(track_status *ptk_stat); +void N64_DriverEntry3(track_status *ptk_stat); +void N64_TrkOff(track_status *ptk_stat); +void N64_TrkMute(track_status *ptk_stat); +void N64_PatchChg(track_status *ptk_stat); +void N64_PatchMod(track_status *ptk_stat); +void N64_PitchMod(track_status *ptk_stat); +void N64_ZeroMod(track_status *ptk_stat); +void N64_ModuMod(track_status *ptk_stat); +void N64_VolumeMod(track_status *ptk_stat); +void N64_PanMod(track_status *ptk_stat); +void N64_PedalMod(track_status *ptk_stat); +void N64_ReverbMod(track_status *ptk_stat); +void N64_ChorusMod(track_status *ptk_stat); +void N64_voiceon(voice_status *voice_stat, track_status *ptk_stat, + patchmaps_header *patchmaps, patchinfo_header *patchinfo, + unsigned char keynum, unsigned char velnum); +void N64_voiceparmoff(voice_status *voice_stat); +void N64_voicemuterelease(voice_status *voice_stat, int muterelease); +void N64_voicerelease(voice_status *voice_stat); +void N64_voicedecay(voice_status *voice_stat); +void N64_voicenote(track_status *ptk_stat, + patchmaps_header *patchmap, patchinfo_header *patchinfo, + unsigned char keynum, unsigned char velnum); +void N64_NoteOn(track_status *ptk_stat); +void N64_NoteOff(track_status *ptk_stat); + +void(*drv_cmds[19])(track_status *) = +{ + N64_DriverInit, //0x0 + N64_DriverExit, //0x1 + N64_DriverEntry1, //0x2 + N64_DriverEntry2, //0x3 + N64_DriverEntry3, //0x4 + N64_TrkOff, //0x5 + N64_TrkMute, //0x6 + N64_PatchChg, //0x7 + N64_PatchMod, //0x8 + N64_PitchMod, //0x9 + N64_ZeroMod, //0xA + N64_ModuMod, //0xB + N64_VolumeMod, //0xC + N64_PanMod, //0xD + N64_PedalMod, //0xE + N64_ReverbMod, //0xF + N64_ChorusMod, //0x10 + N64_NoteOn, //0x11 + N64_NoteOff //0x12 +}; + +extern unsigned char master_sfx_volume; +extern unsigned char master_mus_volume; +extern unsigned char pan_status; +extern int enabledecay; + +typedef struct NoteData +{ + short seq_num; //*8 + short track; //*10 + char keynum; //*12 + char velnum; //*13 + patchmaps_header *patchmap; //*16 mapptr + patchinfo_header *patchinfo; //*20 sampptr +}NoteData; + +typedef struct NoteState +{ + int numnotes; //* + int remember; //*4 + NoteData nd[32]; //*8 +}NoteState;//Final Size 520 +int i = sizeof(NoteState); + +int N64_mute_release = 250; // 8005DB48 +master_status_structure *pmsbase; // 800B66F0 +sequence_status *pssbase; // 800B66F4 +track_status *ptsbase; // 800B66F8 +voice_status *pvsbase; // 800B66FC +unsigned long nvss; // 800B6700 +patch_group_data *ppgd; // 800B6704 +unsigned long *pcurabstime; // 800B6708 +patches_header *patchesbase; // 800B670C +patchmaps_header *patchmapsbase; // 800B6710 +patchinfo_header *samplesbase; // 800B6714 +char *drummapsbase; // 800B6718 +loopinfo_header *samplesinfochunk; // 800B671C +ALRawLoop2 *samplesrawloopbase; // 800B6720 +ALADPCMloop2 *samplescmploopbase; // 800B6724 +ALADPCMBook2 *samplescmphdrbase; // 800B6728 +ALRawLoop2 rawloop; // 800B6730 +ALADPCMloop2 cmploop; // 800B6740 +NoteState *pns = 0; // 8005DB4C +NoteState pnotestate; // 800B6770 +s32 g_wddloc; // 800B6978 +f32 wess_output_ratio = 1.0;// 8005DB50 + +enum Snd_Type {Snd_Music, Snd_Sfx}; + +extern void (**CmdFuncArr[10])(track_status *); +extern void(*DrvFunctions[36])(track_status *); + +//----------------------------------------------------------- +// Sound System +//----------------------------------------------------------- + +f32 sample_rate = 22050.0; // 80061A70 +void N64_set_output_rate(u32 rate) // 80037750 +{ + f32 out_rate; + + out_rate = (f32)rate; + if ((s32)rate < 0) + { + out_rate += 4.2949673e9; + } + wess_output_ratio = (f32)(sample_rate / out_rate); +} + +void N64_wdd_location(char *wdd_location) // 80037788 +{ + g_wddloc = (s32)wdd_location; +} + +void start_record_music_mute(int remember) // 80037794 +{ + if ((int)&pnotestate) + { + pnotestate.numnotes = 0; + pnotestate.remember = remember; + } + pns = (NoteState *)&pnotestate; +} + +void end_record_music_mute(void) // 800377C4 +{ + pns = (NoteState *)0; +} + +#define REMEMBER_MUSIC (0x1L<< 0)//1 +#define REMEMBER_SNDFX (0x1L<< 1)//2 + +void do_record_music_unmute(int seq_num, int track, track_status *ptk_stat) // 800377D0 +{ + int i; + NoteData *notestate; + + for(i = 0; i < pnotestate.numnotes; i++) + { + notestate = &pnotestate.nd[i]; + + if ((notestate->track == track) && (notestate->seq_num == seq_num) && (notestate->patchmap != 0)) + { + N64_voicenote(ptk_stat, notestate->patchmap, notestate->patchinfo, notestate->keynum, notestate->velnum); + notestate->patchmap = (patchmaps_header *)0; + } + } +} + +void add_music_mute_note(track_status *ptk_stat, + unsigned short seq_num, unsigned short track, + unsigned char keynum, unsigned char velnum, + patchmaps_header *patchmap, + patchinfo_header *patchinfo) // 800378A8 +{ + + seq_num = (seq_num << 16) >> 16; + track = (track << 16) >> 16; + + if (pns != 0) + { + if (((ptk_stat->sndclass == MUSIC_CLASS) && (pns->remember & REMEMBER_MUSIC)) || + ((ptk_stat->sndclass == SNDFX_CLASS) && (pns->remember & REMEMBER_SNDFX))) + { + if (pns->numnotes < 32) + { + pns->nd[pns->numnotes].seq_num = seq_num; + pns->nd[pns->numnotes].track = track; + pns->nd[pns->numnotes].keynum = keynum; + pns->nd[pns->numnotes].velnum = velnum; + pns->nd[pns->numnotes].patchmap = patchmap; + pns->nd[pns->numnotes].patchinfo = patchinfo; + pns->numnotes++; + } + } + } +} + +void wess_set_mute_release(int millisec) // 800379E4 +{ + N64_mute_release = millisec; +} + +int wess_get_mute_release(void) // 800379F0 +{ + return N64_mute_release; +} + +f32 WessCents2Ratio(s32 cents) // 80037A00 +{ + f32 x; + f32 ratio = 1.0f; + + if (cents >= 0) { + x = 1.00057779f; /* 2^(1/1200) */ //rate1 + } + else { + x = 0.9994225441f; /* 2^(-1/1200) */ //rate2 + cents = -cents; + } + + while (cents) { + if (cents & 1) + ratio *= x; + x *= x; + cents >>= 1; + } + + return ratio * wess_output_ratio; +} + +/*extern unsigned long drv_pitch1; //L8007EEB8 +extern unsigned long drv_pitch2; //L8007EEBC +extern unsigned long drv_pitch3; //L8007EEC0 +extern unsigned long drv_volume_1; //L8007EEC4 +extern track_status *drv_ptrk_stat; //L8007EEC8 +extern short drv_pan_1; //L8007EECC*/ + +void TriggerN64Voice(voice_status *voice_stat) // 80037A64 +{ + static track_status *pts; //800B697C + static long adjvol; //800B6980 + static short adjpan; //800B6984 + static long adjpitch; //800B6988 + static ALVoiceConfig config; //800b698c + static float pitch; //800B6994 + static long deltatime;//800B6998 + + u32 volume; + s32 priority; + double fpitch; + + pts = (ptsbase + voice_stat->track); + + if (pan_status != 0) + { + adjpan = (s32)(((pts->pan_cntrl + voice_stat->patchmaps->pan) - 0x40) << 16) >> 16; + + if (adjpan < 0) adjpan = 0; + if (adjpan > 0x7F) adjpan = 0x7f; + } + else + { + adjpan = 0x40; + } + + //Volume + if (pts->sndclass == SNDFX_CLASS) + { + volume = voice_stat->velnum * voice_stat->patchmaps->volume * pts->volume_cntrl * master_sfx_volume; + } + else + { + volume = voice_stat->velnum * voice_stat->patchmaps->volume * pts->volume_cntrl * master_mus_volume; + } + + adjvol = voice_stat->patchmaps->attack_level * (volume >> 0xd) >> 7; + + //Pitch + if (pts->pitch_cntrl == 0) + { + adjpitch = 0; + } + else + { + if (pts->pitch_cntrl < 1) + { + adjpitch = (s32)((f64)(voice_stat->patchmaps->pitchstep_min * pts->pitch_cntrl) * (f64)0.0122); + } + else + { + adjpitch = (s32)((f64)(voice_stat->patchmaps->pitchstep_max * pts->pitch_cntrl) * (f64)0.0122); + } + } + + //Voice Priority + priority = voice_stat->priority & 255; + + if((priority >= 0) && (priority < 128)) + { + config.priority = priority; + } + else + { + config.priority = 0x7f; + } + + config.fxBus = (u16)0; + config.unityPitch = (u8)0; + + //PRINTF_D2(WHITE,0,10,"voice_stat->refindx %d ", voice_stat->refindx); + + alSynAllocVoice(&alGlobals->drvr, &voice[voice_stat->refindx], &config); + + pitch = (f32)WessCents2Ratio((voice_stat->patchinfo->pitch + adjpitch + (voice_stat->keynum - voice_stat->patchmaps->root_key) * 100) - voice_stat->patchmaps->fine_adj); + deltatime = voice_stat->patchmaps->attack_time * 1000; + + alSynStartVoiceParams(&alGlobals->drvr, &voice[voice_stat->refindx], (ALWaveTable *)&voice_stat->patchinfo->wave, (f32)pitch, (s16)adjvol, (ALPan)adjpan, (u8)pts->reverb, (ALMicroTime)deltatime); +} +//----------------------------------------------------------- +// Driver System +//----------------------------------------------------------- + +void N64_DriverInit (track_status *ptk_stat) // 80037DA8 +{ + static int vt, mi; //800B699C + + char *pmem; + patchinfo_header *sample; + master_status_structure *pm_stat; + + pm_stat = (master_status_structure*)ptk_stat; + + //PRINTF_D2(WHITE,0,7,"N64_DriverInit"); + pmsbase = pm_stat; + + pcurabstime = pm_stat->pabstime; + pssbase = pm_stat->pseqstattbl; + ptsbase = pm_stat->ptrkstattbl; + pvsbase = pm_stat->pvoicestattbl; + ppgd = pm_stat->ppat_info; + nvss = wess_driver_voices; + + //PRINTF_D(WHITE,"pmsbase %x",pmsbase); + //PRINTF_D(WHITE,"pcurabstime %d",*pcurabstime); + //PRINTF_D(WHITE,"pssbase %x",pssbase); + //PRINTF_D(WHITE,"ptsbase %x",ptsbase); + //PRINTF_D(WHITE,"pvsbase %x",pvsbase); + //PRINTF_D(WHITE,"ppgd %x",ppgd); + //PRINTF_D(WHITE,"nvss %d",nvss); + + pmem = ppgd->ppat_data; /* pointer math temp */ + + patchesbase = (patches_header *)pmem; + pmem += (unsigned int)(ppgd->pat_grp_hdr.patches * sizeof(patches_header)); + //pmem = ((unsigned int)pmem + 7) & ~7; /* phrase align everything */ +#if _ALIGN8_ == 1 + //force align to word boundary because previous size adjust + //may wind up with odd address + pmem += (unsigned int)pmem & 1; + pmem += (unsigned int)pmem & 2; + pmem += (unsigned int)pmem & 4; +#endif + //PRINTF_D(WHITE,"patchesbase %d",(ppgd->pat_grp_hdr.patches));//588 + + patchmapsbase = (patchmaps_header *)pmem; + pmem += (unsigned int)(ppgd->pat_grp_hdr.patchmaps * sizeof(patchmaps_header)); + //pmem = ((unsigned int)pmem + 7) & ~7; /* phrase align everything */ +#if _ALIGN8_ == 1 + //force align to word boundary because previous size adjust + //may wind up with odd address + pmem += (unsigned int)pmem & 1; + pmem += (unsigned int)pmem & 2; + pmem += (unsigned int)pmem & 4; +#endif + //PRINTF_D(WHITE,"patchmapsbase %d",(ppgd->pat_grp_hdr.patchmaps));//10100 + + samplesbase = (patchinfo_header *)pmem; + pmem += (unsigned int)(ppgd->pat_grp_hdr.patchinfo * sizeof(patchinfo_header)); + //pmem = ((unsigned int)pmem + 7) & ~7; /* phrase align everything */ +#if _ALIGN8_ == 1 + //force align to word boundary because previous size adjust + //may wind up with odd address + pmem += (unsigned int)pmem & 1; + pmem += (unsigned int)pmem & 2; + pmem += (unsigned int)pmem & 4; +#endif + //PRINTF_D(WHITE,"samplesbase %d",(ppgd->pat_grp_hdr.patchinfo));//2976 + + drummapsbase = (char *)pmem; + pmem += (unsigned int)(ppgd->pat_grp_hdr.drummaps * sizeof(char *)); + //pmem = ((unsigned int)pmem + 7) & ~7; /* phrase align everything */ +#if _ALIGN8_ == 1 + //force align to word boundary because previous size adjust + //may wind up with odd address + pmem += (unsigned int)pmem & 1; + pmem += (unsigned int)pmem & 2; + pmem += (unsigned int)pmem & 4; +#endif + //PRINTF_D(WHITE,"drummapsbase %d",(ppgd->pat_grp_hdr.drummaps * sizeof(char *))); + + samplesinfochunk = (loopinfo_header *)pmem; + pmem += sizeof(loopinfo_header); + + samplesrawloopbase = (ALRawLoop2 *)pmem; + pmem += (samplesinfochunk->rawcount * sizeof(ALRawLoop2)); + + samplescmploopbase = (ALADPCMloop2 *)pmem; + pmem += (samplesinfochunk->adpcmcount * sizeof(ALADPCMloop2)); + + samplescmphdrbase = (ALADPCMBook2 *)pmem;//264 + + //PRINTF_D(WHITE,"ppgd->pat_grp_hdr.patchinfo %d",ppgd->pat_grp_hdr.patchinfo); + + //PRINTF_D(WHITE,"ALADPCMBook %d",sizeof(ALADPCMBook)); + //PRINTF_D(WHITE,"ALADPCMBook2 %d",sizeof(ALADPCMBook2)); + //PRINTF_D(WHITE,"ALADPCMloop %d",sizeof(ALADPCMloop)); + //PRINTF_D(WHITE,"ALADPCMloop2 %d",sizeof(ALADPCMloop2)); + + //PRINTF_D(WHITE,"ALRawLoop %d",sizeof(ALRawLoop)); + //PRINTF_D(WHITE,"ALRawLoop2 %d",sizeof(ALRawLoop2)); + + for (vt = 0; vt < ppgd->pat_grp_hdr.patchinfo; vt++) + { + sample = (samplesbase + vt); /* pointer math */ + + sample->wave.base += g_wddloc; //Offset of (or pointer to) the start of the raw or ADPCM compressed. + sample->wave.flags = 1; //If the base field contains an offset, [flags = 0]. If ifcontains an pointer, [flags = 1]. + + sample->pitch = (s32)(sample->wave.loop);//move pitch value + + if (sample->wave.type == AL_RAW16_WAVE) + { + if ((s32)(sample->wave.book) != -1) // index id for loop table + { + sample->wave.loop = &samplesrawloopbase[(u32)(sample->wave.book)]; + } + else + { + sample->wave.loop = &rawloop; + } + } + else//AL_ADPCM_WAVE + { + if ((s32)(sample->wave.book) != -1) // index id for loop table + { + sample->wave.loop = &samplescmploopbase[(u32)(sample->wave.book)]; + } + else + { + sample->wave.loop = &cmploop; + } + + sample->wave.book = &samplescmphdrbase[vt]; + } + } +} + +void N64_DriverExit (track_status *ptk_stat) // 8003806C +{ + //PRINTF_D2(WHITE,0,7,"N64_DriverExit"); +} + +void N64_DriverEntry1 (track_status *ptk_stat) // 80038074 +{ + static unsigned long vn; //800B69A0 + static unsigned long vi; //800B69A4 + static voice_status *pvs; //800B69A8 + + //printf("N64_DriverEntry1\n"); + + //PRINTF_D2(WHITE,0,7,"N64_DriverEntry1"); + + vn = pmsbase->voices_active; + //PRINTF_D2(WHITE,0,8,"vn %d",vn); + + if (vn != 0) + { + pvs = pvsbase; + vi = nvss; + + while (vi--) + { + if (pvs->flags & VOICE_ACTIVE) + { + if ((pvs->flags & VOICE_RELEASE) && (pvs->pabstime < *pcurabstime)) + { + N64_voiceparmoff(pvs); + } + else if ((pvs->flags & VOICE_DECAY) && ((pvs->pabstime + pvs->patchmaps->attack_time) < *pcurabstime)) + { + N64_voicedecay(pvs); + } + + if (!--vn) break; + } + + pvs++; + } + } +} + +void N64_DriverEntry2(track_status *ptk_stat) // 800381AC +{ + //PRINTF_D2(WHITE,0,7,"N64_DriverEntry2"); +} + +void N64_DriverEntry3(track_status *ptk_stat) // 800381B4 +{ + //PRINTF_D2(WHITE,0,7,"N64_DriverEntry3"); +} + +void N64_TrkOff(track_status *ptk_stat) // 800381BC +{ + static sequence_status *pss; //800B69AC + + //PRINTF_D2(WHITE,0,7,"N64_TrkOff"); + + pss = pssbase + ptk_stat->seq_owner; + N64_TrkMute(ptk_stat); + + if (ptk_stat->voices_active) + { + ptk_stat->flags |= TRK_STOPPED; + + if (!--pss->tracks_playing) + pss->playmode = SEQ_STATE_STOPPED; + } + else + { + Eng_TrkOff(ptk_stat); + } +} + +void N64_TrkMute(track_status *ptk_stat) // 80038254 +{ + static unsigned long vn; //800B69B0 + static unsigned long vi; //800B69B4 + static voice_status *pvs; //800B69B8 + static sequence_status *pss; //800B69BC + + //PRINTF_D2(WHITE,0,7,"N64_TrkMute"); + vn = ptk_stat->voices_active; + + if (vn != 0) + { + pvs = pvsbase; + vi = nvss; + + while (vi--) + { + if ((pvs->flags & VOICE_ACTIVE) && (pvs->track == ptk_stat->refindx)) + { + if (pns != 0 && (!(pvs->flags & VOICE_RELEASE) && (pvs->sndtype == Snd_Music))) + { + pss = (pssbase + ptk_stat->seq_owner); + + add_music_mute_note(ptk_stat, + pss->seq_num, + pvs->track, + pvs->keynum, + pvs->velnum, + pvs->patchmaps, + pvs->patchinfo); + } + + N64_voicemuterelease(pvs, N64_mute_release); + if (!--vn) break; + } + + pvs++; + } + } +} + +void N64_PatchChg(track_status *ptk_stat) // 800383F8 +{ + static unsigned short thepatch; //800B69C0 + + //PRINTF_D2(WHITE,0,7,"N64_PatchChg"); + thepatch = (*(ptk_stat->ppos + 1) | (*(ptk_stat->ppos + 2) << 8)); + ptk_stat->patchnum = thepatch; +} + +void N64_PatchMod(track_status *ptk_stat) // 8003841C +{ + //PRINTF_D2(WHITE,0,7,"N64_PatchMod"); +} + +void N64_PitchMod(track_status *ptk_stat) // 80038424 +{ + static unsigned long vn; //800B69C4 + static unsigned long vi; //800B69C8 + static voice_status *pvs; //800B69CC + static short thepitchmod; //800B69D0 + static f32 pitch; //800B69D4 + static unsigned long adjpitch; //800B69D8 + + //PRINTF_D2(WHITE,0,7,"N64_PitchMod"); + + thepitchmod = (*(ptk_stat->ppos + 1) | (*(ptk_stat->ppos + 2) << 8)); + if (ptk_stat->pitch_cntrl != thepitchmod) + { + ptk_stat->pitch_cntrl = thepitchmod; + vn = ptk_stat->voices_active; + + if (vn != 0) + { + pvs = pvsbase; + vi = nvss; + + while (vi--) + { + if ((pvs->flags & VOICE_ACTIVE) && (pvs->track == ptk_stat->refindx)) + { + //Pitch + if (ptk_stat->pitch_cntrl != 0) + { + if (ptk_stat->pitch_cntrl < 1) + { + adjpitch = (s32)((f64)(pvs->patchmaps->pitchstep_min * ptk_stat->pitch_cntrl) * (f64)0.0122); + } + else + { + adjpitch = (s32)((f64)(pvs->patchmaps->pitchstep_max * ptk_stat->pitch_cntrl) * (f64)0.0122); + } + } + else + { + adjpitch = 0; + } + + pitch = (f32)WessCents2Ratio((pvs->patchinfo->pitch + adjpitch + (pvs->keynum - pvs->patchmaps->root_key) * 100) - pvs->patchmaps->fine_adj); + alSynSetPitch(&alGlobals->drvr, &voice[pvs->refindx], (f32)pitch); + + if (!--vn) break; + } + + pvs++; + } + } + } +} + +void N64_ZeroMod(track_status *ptk_stat) // 800386C8 +{ + //PRINTF_D2(WHITE,0,7,"N64_ZeroMod"); +} + +void N64_ModuMod(track_status *ptk_stat) // 800386D0 +{ + //PRINTF_D2(WHITE,0,7,"N64_ModuMod"); +} + +void N64_VolumeMod(track_status *ptk_stat) // 800386D8 +{ + static unsigned long vn; //800B69DC + static unsigned long vi; //800B69E0 + static unsigned long adjvol; //800B69E4 + static voice_status *pvs; //800B69E8 + static unsigned char thevolmod; //800B69EC + + u32 volume; + ALMicroTime deltaTime; + + //PRINTF_D2(WHITE,0,7,"N64_VolumeMod"); + + thevolmod = *(ptk_stat->ppos + 1); + if (thevolmod != ptk_stat->volume_cntrl) + { + ptk_stat->volume_cntrl = thevolmod; + vn = ptk_stat->voices_active; + + if (vn != 0) + { + pvs = pvsbase; + vi = nvss; + + while (vi--) + { + if ((pvs->flags & VOICE_ACTIVE) && (pvs->track == ptk_stat->refindx)) + { + if (ptk_stat->sndclass == SNDFX_CLASS) + { + volume = pvs->velnum * pvs->patchmaps->volume * ptk_stat->volume_cntrl * master_sfx_volume; + } + else//MUSIC_CLASS + { + volume = pvs->velnum * pvs->patchmaps->volume * ptk_stat->volume_cntrl * master_mus_volume; + } + + adjvol = volume >> 0xd; + deltaTime = 1000; + + alSynSetVol(&alGlobals->drvr, &voice[pvs->refindx], (s16)adjvol, (ALMicroTime)deltaTime); + + if (!--vn) break; + } + + pvs++; + } + } + } +} + +void N64_PanMod(track_status *ptk_stat) // 800388FC +{ + static unsigned long vn; //800B69F0 + static unsigned long vi; //800B69F4 + static voice_status *pvs; //800B69F8 + static short adjpan; //800B69FC + static unsigned char thepanmod; //800B69FE + + //PRINTF_D2(WHITE,0,7,"N64_PanMod"); + + thepanmod = *(ptk_stat->ppos + 1); + if (thepanmod != ptk_stat->pan_cntrl) + { + ptk_stat->pan_cntrl = thepanmod; + + if (pan_status != 0) + { + vn = ptk_stat->voices_active; + + if (vn != 0) + { + pvs = pvsbase; + vi = nvss; + + while (vi--) + { + if ((pvs->flags & VOICE_ACTIVE) && (pvs->track == ptk_stat->refindx)) + { + adjpan = (s32)(((ptk_stat->pan_cntrl + pvs->patchmaps->pan) - 0x40) << 16) >> 16; + if (adjpan < 0) adjpan = 0; + if (adjpan > 0x7f) adjpan = 0x7f; + + alSynSetPan(&alGlobals->drvr, &voice[pvs->refindx], (ALPan)adjpan); + + if (!--vn) break; + } + + pvs++; + } + } + } + } +} + +//N64_PedalMod +void N64_PedalMod(track_status *ptk_stat) // 80038AA0 +{ + static unsigned char vn; //800B69FF + static unsigned char vi; //800B6A00 + static voice_status *pvs; //800B6A04 + + //PRINTF_D2(WHITE,0,7,"N64_PedalMod"); + + if (*(ptk_stat->ppos + 1) == 0) + { + ptk_stat->flags |= TRK_OFF; + + vn = ptk_stat->voices_active; + + if (vn != 0) + { + pvs = pvsbase; + vi = nvss; + + while (vi--) + { + if ((pvs->flags & VOICE_ACTIVE) && !(pvs->flags & VOICE_RELEASE) && (pvs->track == ptk_stat->refindx)) + { + if (pvs->sndtype != Snd_Music) + { + pvs->sndtype = Snd_Music; + N64_voicerelease(pvs); + if (!--vn) break; + } + } + + pvs++; + } + } + } + else + { + ptk_stat->flags &= ~TRK_OFF; + } +} + +//N64_ReverbMod +void N64_ReverbMod(track_status *ptk_stat) // 80038BD8 +{ + static unsigned char vn; //800B6A08 + static unsigned char vi; //800B6A0C + static voice_status *pvs; //800B6A10 + static unsigned char thereverbmod; //800B6A14 + + //PRINTF_D2(WHITE,0,7,"N64_ReverbMod"); + + thereverbmod = *(ptk_stat->ppos + 1); + if (thereverbmod != ptk_stat->reverb) + { + ptk_stat->reverb = thereverbmod; + vn = ptk_stat->voices_active; + + if (vn != 0) + { + pvs = pvsbase; + vi = nvss; + + while (vi--) + { + if ((pvs->flags & VOICE_ACTIVE) && (pvs->track == ptk_stat->refindx)) + { + alSynSetPan(&alGlobals->drvr, &voice[pvs->refindx], (ALPan)thereverbmod); + + if (!--vn) break; + } + + pvs++; + } + } + } +} + +//N64_ChorusMod +void N64_ChorusMod(track_status *ptk_stat) // 80038D2C +{ + //PRINTF_D2(WHITE,0,7,"N64_ChorusMod"); +} + +void N64_voiceon(voice_status *voice_stat, track_status *ptk_stat, + patchmaps_header *patchmaps, patchinfo_header *patchinfo, + unsigned char keynum, unsigned char velnum) // 80038D34 +{ + //PRINTF_D2(WHITE,0,17,"N64_voiceon"); + voice_stat->flags = (voice_stat->flags | VOICE_ACTIVE | VOICE_DECAY) & ~VOICE_RELEASE; + voice_stat->track = ptk_stat->refindx; + voice_stat->priority = patchmaps->priority; + voice_stat->keynum = keynum; + voice_stat->sndtype = Snd_Music; + voice_stat->patchmaps = patchmaps; + voice_stat->patchinfo = patchinfo; + voice_stat->velnum = velnum; + voice_stat->pabstime = *pcurabstime; + + ptk_stat->voices_active++; + pmsbase->voices_active++; + + TriggerN64Voice(voice_stat); +} + +void N64_voiceparmoff(voice_status *voice_stat) // 80038DE4 +{ + static track_status *ptrack; //800B6A18 + //PRINTF_D2(WHITE,0,7,"N64_voiceparmoff"); + + alSynStopVoice(&alGlobals->drvr, &voice[voice_stat->refindx]); + alSynFreeVoice(&alGlobals->drvr, &voice[voice_stat->refindx]); + + ptrack = (ptsbase + voice_stat->track); + pmsbase->voices_active--; + + if (!--ptrack->voices_active) + { + if ((ptrack->flags & TRK_STOPPED) && !(ptrack->flags & TRK_MUTE)) + { + Eng_TrkOff(ptrack); + } + } + + voice_stat->flags &= ~(VOICE_ACTIVE | VOICE_RELEASE | VOICE_DECAY); +} + +void N64_voicemuterelease(voice_status *voice_stat, int muterelease) // 80038EF8 +{ + ALMicroTime deltaTime; + + //PRINTF_D2(WHITE,0,7,"N64_voicemuterelease"); + + deltaTime = muterelease * 1000; + alSynSetPriority(&alGlobals->drvr, &voice[voice_stat->refindx], 0); /* make candidate for stealing */ + alSynSetVol(&alGlobals->drvr, &voice[voice_stat->refindx], 0, deltaTime); + + voice_stat->flags = (voice_stat->flags | VOICE_RELEASE) & ~VOICE_DECAY; + voice_stat->pabstime = *pcurabstime + muterelease; +} + +void N64_voicerelease(voice_status *voice_stat) // 80038FBC +{ + ALMicroTime deltaTime; + + //PRINTF_D2(WHITE,0,7,"N64_voicerelease"); + + deltaTime = voice_stat->patchmaps->release_time * 1000; + alSynSetPriority(&alGlobals->drvr, &voice[voice_stat->refindx], 0); /* make candidate for stealing */ + alSynSetVol(&alGlobals->drvr, &voice[voice_stat->refindx], 0, deltaTime); + + voice_stat->flags = (voice_stat->flags | VOICE_RELEASE) & ~VOICE_DECAY; + voice_stat->pabstime = *pcurabstime + (unsigned long)voice_stat->patchmaps->release_time; +} + +void N64_voicedecay(voice_status *voice_stat) // 80039084 +{ + static unsigned long adjvol; //800B6A1C + static track_status *pts; //800B6A20 + + u32 volume; + ALMicroTime deltaTime; + + //PRINTF_D2(WHITE,0,7,"N64_voicedecay"); + + pts = (ptsbase + voice_stat->track); + + //sndclass + if (pts->sndclass == SNDFX_CLASS) + { + volume = voice_stat->velnum * voice_stat->patchmaps->volume * pts->volume_cntrl * master_sfx_volume; + } + else + { + volume = voice_stat->velnum * voice_stat->patchmaps->volume * pts->volume_cntrl * master_mus_volume; + } + + adjvol = voice_stat->patchmaps->decay_level * (volume >> 0xd) >> 7; + + if (enabledecay) + { + deltaTime = voice_stat->patchmaps->decay_time * 1000; + alSynSetVol(&alGlobals->drvr, &voice[voice_stat->refindx], (s16)adjvol, deltaTime); + } + + voice_stat->flags &= ~VOICE_DECAY; +} + +void N64_voicenote(track_status *ptk_stat, + patchmaps_header *patchmap, patchinfo_header *patchinfo, + unsigned char keynum, unsigned char velnum) // 800391F8 +{ + static unsigned long vi; //800B6A24 + static unsigned long found_one; //800B6A28 + static voice_status *pvs; //800B6A2C + static voice_status *pvsact; //800B6A30 + static unsigned long lowprio; //800B6A34 + static unsigned long lowtime; //800B6A38 + + + unsigned int pabstime_tmp; + unsigned int priority_tmp; + voice_status *voice_tmp; + + //PRINTF_D2(WHITE,0,15,"N64_voicenote"); + + found_one = 0; + + pvsact = voice_tmp = (voice_status *)0x0; + lowprio = priority_tmp = 0x100; + lowtime = pabstime_tmp = 0xFFFFFFFF; + + pvs = pvsbase; + vi = nvss; + + while (vi--) + { + if (!(pvs->flags & VOICE_ACTIVE)) + { + pvsact = voice_tmp; + lowprio = priority_tmp; + lowtime = pabstime_tmp; + N64_voiceon(pvs, ptk_stat, patchmap, patchinfo, keynum, velnum); + found_one = 0; + break; + } + + if (pvs->priority <= patchmap->priority) + { + if (pvs->priority < lowprio) + { + found_one = 1; + pabstime_tmp = pvs->pabstime; + priority_tmp = pvs->priority; + voice_tmp = pvs; + } + else + { + if(pvs->flags & VOICE_RELEASE) + { + if(pvsact->flags & VOICE_RELEASE) + { + if (pvs->pabstime < lowtime) + { + found_one = 1; + pabstime_tmp = pvs->pabstime; + priority_tmp = pvs->priority; + voice_tmp = pvs; + } + } + else + { + found_one = 1; + pabstime_tmp = pvs->pabstime; + priority_tmp = pvs->priority; + voice_tmp = pvs; + } + } + else if(!(pvsact->flags & VOICE_RELEASE)) + { + if (pvs->pabstime < lowtime) + { + found_one = 1; + pabstime_tmp = pvs->pabstime; + priority_tmp = pvs->priority; + voice_tmp = pvs; + } + } + } + } + + pvs++; + pvsact = voice_tmp; + lowprio = priority_tmp; + lowtime = pabstime_tmp; + } + + if (found_one != 0) + { + N64_voiceparmoff(pvsact); + N64_voiceon(pvsact, ptk_stat, patchmap, patchinfo, keynum, velnum); + } +} + +void N64_NoteOn(track_status *ptk_stat) // 80039434 +{ + static unsigned long i; //800B6A3C + static unsigned char note; //800B6A40 + static unsigned char vel; //800B6A41 + static unsigned char mapcount; //800B6A42 + static patches_header *samp_pat; //800B6A44 + static patchmaps_header *mapdat; //800B6A48 + static patchinfo_header *sampdat; //800B6A4C + + //PRINTF_D2(WHITE,0,16,"N64_NoteOn"); + + note = *(ptk_stat->ppos + 1); + vel = *(ptk_stat->ppos + 2); + + samp_pat = patchesbase + ptk_stat->patchnum; + mapcount = samp_pat->patchmap_cnt; + + //PRINTF_D2(WHITE,15,14,"note %d",note); + //PRINTF_D2(WHITE,15,15,"vel %d",vel); + //PRINTF_D2(WHITE,15,16,"mapcount %d",mapcount); + + i = 0; + while (mapcount--) + { + mapdat = patchmapsbase + (samp_pat->patchmap_idx + i); + sampdat = samplesbase + mapdat->sample_id; + + if ((mapdat->note_min <= note) && (note <= mapdat->note_max)) + { + N64_voicenote(ptk_stat, mapdat, sampdat, note, vel); + } + i += 1; + } +} + +void N64_NoteOff(track_status *ptk_stat) // 800395B4 +{ + static unsigned long vi; //800B6A50 + static voice_status *pvs; //800B6A54 + + //PRINTF_D2(WHITE,0,7,"N64_NoteOff"); + pvs = pvsbase; + vi = nvss; + + while (vi--) + { + if (((pvs->flags & (VOICE_ACTIVE | VOICE_RELEASE)) == VOICE_ACTIVE) && + (pvs->keynum == *(ptk_stat->ppos + 1)) && + (pvs->track == ptk_stat->refindx)) + { + if ((ptk_stat->flags & TRK_OFF) == 0) { + pvs->sndtype = Snd_Sfx; + } + else { + N64_voicerelease(pvs); + } + } + + pvs++; + } +} + +#endif diff --git a/Doom 64/n64cmd.h b/Doom 64/n64cmd.h @@ -0,0 +1,3 @@ + + +extern void N64_wdd_location(char *wdd_location); diff --git a/Doom 64/p_base.c b/Doom 64/p_base.c @@ -0,0 +1,820 @@ +/* p_base.c */ + +#include "doomdef.h" +#include "p_local.h" + +//completo y revisado + +mobj_t *checkthing; /* Used for PB_CheckThing */ // 800A55D0 +fixed_t testx, testy; // 800A55D8, 800A55DC +static fixed_t testfloorz, testceilingz, testdropoffz; // 800A5604, 800A5608, 800A560C +static subsector_t *testsubsec; // 800A55F8 +static line_t *ceilingline; // 800A5600 +static mobj_t *hitthing; // 800A55fC +static fixed_t testbbox[4]; /* Bounding box for tests */ // 800A55E8 +int testflags; // 800A55D4 +fixed_t testradius; // 800A55E0 + +void P_XYMovement(mobj_t *mo); +void P_FloatChange(mobj_t *mo); +void P_ZMovement(mobj_t *mo); +void P_MobjThinker(mobj_t *mobj); +boolean PB_TryMove(int tryx, int tryy); +void PB_UnsetThingPosition(mobj_t *thing); +void PB_SetThingPosition(mobj_t *thing); +boolean PB_CheckPosition(void); +boolean PB_BoxCrossLine(line_t *ld); +boolean PB_CheckLine(line_t *ld); +boolean PB_CheckThing(mobj_t *thing); +boolean PB_BlockLinesIterator(int x, int y); +boolean PB_BlockThingsIterator(int x, int y); + +/* +================= += += P_RunMobjBase += += Execute base think logic for the critters every tic += +================= +*/ + +void P_RunMobjBase(void) // 8000CDE0 +{ + mobj_t *mo; + mobj_t *next; + + for (mo = mobjhead.next; mo != &mobjhead; mo = mo->next) + { + /* Based on Doom 64 Ex */ + /*-----------------------------------------------------------------------------------*/ + if((players[0].cheats & CF_LOCKMOSTERS) && !mo->player && mo->flags & MF_COUNTKILL) { + continue; + } + /*-----------------------------------------------------------------------------------*/ + + if (!mo->player) + { + mo->latecall = NULL; + P_MobjThinker(mo); + } + } + + //P_RunMobjLate(); + for (mo = mobjhead.next; mo != &mobjhead; mo = next) + { + next = mo->next; /* in case mo is removed this time */ + + /* Based on Doom 64 Ex */ + /*-----------------------------------------------------------------------------------*/ + if((players[0].cheats & CF_LOCKMOSTERS) && !mo->player && mo->flags & MF_COUNTKILL) { + continue; + } + /*-----------------------------------------------------------------------------------*/ + + if(mo->latecall) + { + mo->latecall(mo); + } + } +} + +/* +=================== += += P_MobjThinker += += Process all the critter logic += +=================== +*/ + +void P_MobjThinker(mobj_t *mobj) // 8000CE74 +{ + state_t *st; + statenum_t state; + + checkthing = mobj; + + // momentum movement + if (mobj->momx || mobj->momy) + { + P_XYMovement(mobj); + + // removed or has a special action to perform? + if (mobj->latecall) + return; + } + + if (mobj->z != mobj->floorz || mobj->momz) + { + P_ZMovement(mobj); + + // removed or has a special action to perform? + if (mobj->latecall) + return; + } + + // cycle through states + if (mobj->tics != -1) + { + mobj->tics--; + + // you can cycle through multiple states in a tic + if (mobj->tics <= 0) + { + state = mobj->state->nextstate; + if (state == S_000) + { + mobj->latecall = P_RemoveMobj; + } + else + { + st = &states[state]; + mobj->state = st; + mobj->tics = st->tics; + mobj->sprite = st->sprite; + mobj->frame = st->frame; + mobj->latecall = st->action; + } + } + } +} + + +/* +=================== += += P_XYMovement += +=================== +*/ + +#define STOPSPEED 0x1000 +#define FRICTION 0xd200 //Jag 0xd240 + +void P_XYMovement(mobj_t *mo) // 8000CF98 +{ + fixed_t xleft, yleft; + fixed_t xuse, yuse; + + // + // cut the move into chunks if too large + // + + xleft = xuse = mo->momx & ~7; + yleft = yuse = mo->momy & ~7; + + while (xuse > MAXMOVE || xuse < -MAXMOVE + || yuse > MAXMOVE || yuse < -MAXMOVE) + { + xuse >>= 1; + yuse >>= 1; + } + + while (xleft || yleft) + { + xleft -= xuse; + yleft -= yuse; + if (!PB_TryMove(mo->x + xuse, mo->y + yuse)) + { + // blocked move + if (mo->flags & MF_SKULLFLY) + { + mo->latecall = L_SkullBash; + mo->extradata = (mobj_t*)hitthing; + } + + // explode a missile + if (mo->flags & MF_MISSILE) + { + if(hitthing == NULL && ceilingline) + { + if ((ceilingline->backsector && (ceilingline->backsector->ceilingpic == -1)) || + ((ceilingline->backsector == NULL) && (sides[ceilingline->sidenum[0]].midtexture == 1))) // hack to prevent missiles exploding against the sky + { + mo->latecall = P_RemoveMobj; + return; + } + } + + mo->latecall = L_MissileHit; + mo->extradata = (mobj_t*)hitthing; + return; + } + + mo->momx = mo->momy = 0; + return; + } + } + + // + // slow down + // + if (mo->flags & (MF_MISSILE | MF_SKULLFLY)) + return; // no friction for missiles ever + + if (mo->z > mo->floorz) + return; // no friction when airborne + + if ((mo->flags & MF_CORPSE) && (mo->floorz != mo->subsector->sector->floorheight)) + return; // don't stop halfway off a step + + if (mo->momx > -STOPSPEED && mo->momx < STOPSPEED && + mo->momy > -STOPSPEED && mo->momy < STOPSPEED) + { + mo->momx = 0; + mo->momy = 0; + } + else + { + mo->momx = (mo->momx >> 8) * (FRICTION >> 8); + mo->momy = (mo->momy >> 8) * (FRICTION >> 8); + } +} + +/* +=================== += += P_FloatChange += += Float up or down at a set speed, used by flying monsters += +=================== +*/ + +void P_FloatChange(mobj_t *mo) // inline function +{ + mobj_t *target; + fixed_t dist, delta; + + target = mo->target; /* Get the target object */ + + dist = P_AproxDistance(target->x - mo->x, target->y - mo->y); /* Distance to target */ + + delta = (target->z + (mo->height >> 1)) - mo->z; /* Get the height differance */ + delta *= 3; /* Mul by 3 for a fudge factor */ + + if (delta<0) /* Delta is signed... */ + { + if (dist < (-delta)) /* Negate */ + { + mo->z -= FLOATSPEED; /* Adjust the height */ + } + } + else if (delta>0) /* Delta is signed... */ + { + if (dist < delta) /* Normal compare */ + { + mo->z += FLOATSPEED; /* Adjust the height */ + } + } +} + +/* +=================== += += P_ZMovement += += Move a critter in the Z axis += +=================== +*/ + +void P_ZMovement(mobj_t *mo) // 8000D228 +{ + + mo->z += mo->momz; /* Basic z motion */ + + if ((mo->flags & MF_FLOAT) && mo->target) /* float down towards target if too close */ + { + P_FloatChange(mo); + } + + // + // clip movement + // + if (mo->z <= mo->floorz) // hit the floor + { + if (mo->momz < 0) + mo->momz = 0; + + mo->z = mo->floorz; + if ((mo->flags & MF_MISSILE) && (mo->type != MT_PROJ_RECTFIRE)) + { + mo->latecall = P_ExplodeMissile; + return; + } + } + else if (mo->flags & MF_GRAVITY) + { + // apply gravity + if (mo->momz == 0) + mo->momz = -(GRAVITY/2); + else + mo->momz -= ((GRAVITY/FRACBITS)*3); // [d64]: non-players fall slightly slower + } + + if (mo->z + mo->height > mo->ceilingz) // hit the ceiling + { + if (mo->momz > 0) + mo->momz = 0; + + mo->z = mo->ceilingz - mo->height; + if (mo->flags & MF_MISSILE) + mo->latecall = P_ExplodeMissile; + } +} + +/* +=================== += += PB_TryMove += += Attempt to move to a new position += +=================== +*/ + +boolean PB_TryMove(int tryx, int tryy) // 8000D3F4 +{ + testradius = checkthing->radius; + testflags = checkthing->flags; + testx = tryx; + testy = tryy; + + if (!PB_CheckPosition()) + return false; // solid wall or thing + + if (testceilingz - testfloorz < checkthing->height) + return false; // doesn't fit + if (testceilingz - checkthing->z < checkthing->height) + return false; // mobj must lower itself to fit + if (testfloorz - checkthing->z > 24 * FRACUNIT) + return false; // too big a step up + if (!(testflags&(MF_DROPOFF | MF_FLOAT)) && testfloorz - testdropoffz > 24 * FRACUNIT) + return false; // don't stand over a dropoff + + // + // the move is ok, so link the thing into its new position + // + + PB_UnsetThingPosition(checkthing); + checkthing->floorz = testfloorz; + checkthing->ceilingz = testceilingz; + checkthing->x = tryx; + checkthing->y = tryy; + PB_SetThingPosition(checkthing); + return true; +} + +/* +=================== += += PB_UnsetThingPosition += +=================== +*/ + +void PB_UnsetThingPosition(mobj_t *thing) // 8000D55C +{ + int blockx, blocky; + + // inert things don't need to be in blockmap + // unlink from subsector + if (thing->snext) + thing->snext->sprev = thing->sprev; + if (thing->sprev) + thing->sprev->snext = thing->snext; + else + thing->subsector->sector->thinglist = thing->snext; + + if (!(testflags & MF_NOBLOCKMAP)) + { + // inert things don't need to be in blockmap + // unlink from block map + if (thing->bnext) + thing->bnext->bprev = thing->bprev; + if (thing->bprev) + thing->bprev->bnext = thing->bnext; + else + { + blockx = (thing->x - bmaporgx) >> MAPBLOCKSHIFT; + blocky = (thing->y - bmaporgy) >> MAPBLOCKSHIFT; + + // Prevent buffer overflow if the map object is out of bounds. + // This is part of the fix for the famous 'linedef deletion' bug. + // From PsyDoom (StationDoom) by BodbDearg + #if FIX_LINEDEFS_DELETION == 1 + if (blockx>=0 && blockx <bmapwidth + && blocky>=0 && blocky <bmapheight) + { + blocklinks[blocky*bmapwidth+blockx] = thing->bnext; + } + #else + blocklinks[blocky*bmapwidth+blockx] = thing->bnext; + #endif + } + } +} + +/* +=================== += += PB_SetThingPosition += +=================== +*/ + +void PB_SetThingPosition(mobj_t *thing) // 8000D650 +{ + sector_t *sec; + int blockx, blocky; + mobj_t **link; + + // + // link into subsector + // + + thing->subsector = testsubsec; + sec = thing->subsector->sector; + + thing->sprev = NULL; + thing->snext = sec->thinglist; + + if (sec->thinglist) + sec->thinglist->sprev = thing; + + sec->thinglist = thing; + + // + // link into blockmap + // + if (!(testflags & MF_NOBLOCKMAP)) + { + // inert things don't need to be in blockmap + blockx = (thing->x - bmaporgx) >> MAPBLOCKSHIFT; + blocky = (thing->y - bmaporgy) >> MAPBLOCKSHIFT; + if (blockx >= 0 && blockx < bmapwidth && blocky >= 0 && blocky < bmapheight) + { + link = &blocklinks[blocky*bmapwidth + blockx]; + thing->bprev = NULL; + thing->bnext = *link; + if (*link) + (*link)->bprev = thing; + *link = thing; + } + else + { + // thing is off the map + thing->bnext = thing->bprev = NULL; + } + } +} + +/* +================== += += PB_CheckPosition += += This is purely informative, nothing is modified (except things picked up) + +in: +basething a mobj_t +testx,testy a position to be checked (doesn't need relate to the mobj_t->x,y) + +out: + +testsubsec +floorz +ceilingz +testdropoffz the lowest point contacted (monsters won't move to a dropoff) +hitthing + +================== +*/ + +boolean PB_CheckPosition(void) // 8000D750 +{ + int xl, xh, yl, yh, bx, by; + + testbbox[BOXTOP ] = testy + testradius; + testbbox[BOXBOTTOM] = testy - testradius; + testbbox[BOXRIGHT ] = testx + testradius; + testbbox[BOXLEFT ] = testx - testradius; + + // + // the base floor / ceiling is from the subsector that contains the + // point. Any contacted lines the step closer together will adjust them + // + testsubsec = R_PointInSubsector(testx, testy); + testfloorz = testdropoffz = testsubsec->sector->floorheight; + testceilingz = testsubsec->sector->ceilingheight; + + ++validcount; + + ceilingline = NULL; + hitthing = NULL; + + // + // the bounding box is extended by MAXRADIUS because mobj_ts are grouped + // into mapblocks based on their origin point, and can overlap into adjacent + // blocks by up to MAXRADIUS units + // + + // [d64]: intentionally removed MAXRADIUS? + xl = (testbbox[BOXLEFT ] - bmaporgx) >> MAPBLOCKSHIFT; + xh = (testbbox[BOXRIGHT ] - bmaporgx) >> MAPBLOCKSHIFT; + yl = (testbbox[BOXBOTTOM] - bmaporgy) >> MAPBLOCKSHIFT; + yh = (testbbox[BOXTOP ] - bmaporgy) >> MAPBLOCKSHIFT; + + if (xl<0) + { + xl = 0; + } + if (yl<0) + { + yl = 0; + } + if (xh >= bmapwidth) + { + xh = bmapwidth - 1; + } + if (yh >= bmapheight) + { + yh = bmapheight - 1; + } + + for (bx = xl; bx <= xh; bx++) + { + for (by = yl; by <= yh; by++) + { + if (!PB_BlockLinesIterator(bx, by)) + return false; + if (!PB_BlockThingsIterator(bx, by)) + return false; + } + } + + return true; +} + +/* +================= += += PB_BoxCrossLine += +================= +*/ + +boolean PB_BoxCrossLine(line_t *ld) // 8000920 +{ + fixed_t x1, x2; + fixed_t lx, ly; + fixed_t ldx, ldy; + fixed_t dx1, dy1; + fixed_t dx2, dy2; + boolean side1, side2; + + // entirely outside bounding box of line? + if(testbbox[BOXRIGHT ] <= ld->bbox[BOXLEFT ] || + testbbox[BOXLEFT ] >= ld->bbox[BOXRIGHT ] || + testbbox[BOXTOP ] <= ld->bbox[BOXBOTTOM] || + testbbox[BOXBOTTOM] >= ld->bbox[BOXTOP ]) + { + return false; + } + + if (ld->slopetype == ST_POSITIVE) + { + x1 = testbbox[BOXLEFT]; + x2 = testbbox[BOXRIGHT]; + } + else + { + x1 = testbbox[BOXRIGHT]; + x2 = testbbox[BOXLEFT]; + } + + lx = ld->v1->x; + ly = ld->v1->y; + ldx = ld->dx >> FRACBITS; + ldy = ld->dy >> FRACBITS; + + dx1 = (x1 - lx) >> 16; + dy1 = (testbbox[BOXTOP] - ly) >> FRACBITS; + dx2 = (x2 - lx) >> 16; + dy2 = (testbbox[BOXBOTTOM] - ly) >> FRACBITS; + + side1 = ldy*dx1 < dy1*ldx; + side2 = ldy*dx2 < dy2*ldx; + + return (side1 != side2); +} + +/* +================== += += PB_CheckLine += += Adjusts testfloorz and testceilingz as lines are contacted +================== +*/ + +boolean PB_CheckLine(line_t *ld) // 8000DA44 +{ + fixed_t opentop, openbottom; + fixed_t lowfloor; + sector_t *front, *back; + + /* + = + = The moving thing's destination position will cross the given line. + = If this should not be allowed, return FALSE. + */ + if (!ld->backsector) + { + ceilingline = ld; + return false; // one sided line + } + + if (!(testflags & MF_MISSILE) && (ld->flags & (ML_BLOCKING | ML_BLOCKMONSTERS))) + { + ceilingline = ld; + return false; // explicitly blocking + } + + // [d64] don't cross projectile blockers + if ((ld->flags & ML_BLOCKPROJECTILES)) //psx doom / doom 64 new + { + ceilingline = ld; + return false; + } + + front = ld->frontsector; + back = ld->backsector; + + if (front->ceilingheight < back->ceilingheight) + opentop = front->ceilingheight; + else + opentop = back->ceilingheight; + + if (front->floorheight > back->floorheight) + { + openbottom = front->floorheight; + lowfloor = back->floorheight; + } + else + { + openbottom = back->floorheight; + lowfloor = front->floorheight; + } + + // adjust floor / ceiling heights + if (opentop < testceilingz) + { + testceilingz = opentop; + ceilingline = ld; + } + if (openbottom > testfloorz) + testfloorz = openbottom; + if (lowfloor < testdropoffz) + testdropoffz = lowfloor; + + return true; +} + +/* +================== += += PB_BlockLinesIterator += +================== +*/ + +boolean PB_BlockLinesIterator(int x, int y) // 8000DB70 +{ + int offset; + short *list; + line_t *ld; + + offset = y*bmapwidth+x; + + offset = *(blockmap + offset); + + for (list = blockmaplump + offset; *list != -1; list++) + { + ld = &lines[*list]; + if (ld->validcount == validcount) + continue; // line has already been checked + ld->validcount = validcount; + + if (PB_BoxCrossLine(ld)) + { + if (!PB_CheckLine(ld)) + return false; + } + } + + return true; // everything was checked +} + +/* +================== += += PB_CheckThing += +================== +*/ + +boolean PB_CheckThing(mobj_t *thing) // 8000DC70 +{ + fixed_t blockdist; + int delta; + mobj_t *mo; + + if (!(thing->flags & MF_SOLID)) + return true; // not blocking + + mo = checkthing; + + if(thing == mo) + return true; // don't clip against self + + blockdist = thing->radius + testradius; + + delta = thing->x - testx; + if (delta < 0) + delta = -delta; + + if (delta >= blockdist) + return true; // didn't hit it + + delta = thing->y - testy; + if (delta < 0) + delta = -delta; + + if (delta >= blockdist) + return true; // didn't hit it + + // + // check for skulls slamming into things + // + if (testflags & MF_SKULLFLY) + { + hitthing = thing; + return false; // stop moving + } + + // + // missiles can hit other things + // + if (testflags & MF_MISSILE) + { + // see if it went over / under + if (mo->z > thing->z + thing->height) + return true; // overhead + + if (mo->z + mo->height < thing->z) + return true; // underneath + + if (mo->target->type == thing->type) // don't hit same species as originator + { + if (thing == mo->target) + return true; // don't explode on shooter + + if (thing->type != MT_PLAYER) + return false; // explode, but do no damage + // let players missile other players + } + if (!(thing->flags & MF_SHOOTABLE)) + return !(thing->flags & MF_SOLID); // didn't do any damage + // damage / explode + hitthing = thing; + return false; // don't traverse any more + } + + return !(thing->flags & MF_SOLID); +} + + +/* +================== += += PB_BlockThingsIterator += +================== +*/ + +boolean PB_BlockThingsIterator(int x, int y) // 8000DDD4 +{ + mobj_t *mobj; + + for (mobj = blocklinks[y*bmapwidth+x]; mobj; mobj = mobj->bnext) + { + if (!PB_CheckThing(mobj)) + return false; + } + + return true; +} diff --git a/Doom 64/p_ceilng.c b/Doom 64/p_ceilng.c @@ -0,0 +1,316 @@ +#include "doomdef.h" +#include "p_local.h" + +/*================================================================== */ +/*================================================================== */ +/* */ +/* CEILINGS */ +/* */ +/*================================================================== */ +/*================================================================== */ + +ceiling_t *activeceilings[MAXCEILINGS]; //800A5610 + +/*================================================================== */ +/* */ +/* T_MoveCeiling */ +/* */ +/*================================================================== */ +void T_MoveCeiling (ceiling_t *ceiling) // 8000F880 +{ + result_e res; + + switch(ceiling->direction) + { + case 0: /* IN STASIS */ + break; + case 1: /* UP */ + res = T_MovePlane(ceiling->sector,ceiling->speed, + ceiling->topheight,false,1,ceiling->direction); + + if (!ceiling->instant) + { + if (!(gametic & 7)) + { + S_StartSound((mobj_t *)&ceiling->sector->soundorg, sfx_secmove); + } + } + + if (res == pastdest) + { + switch(ceiling->type) + { + //case lowerToFloor://--- + case raiseToHighest: + case customCeiling: + case crushAndRaiseOnce: + case customCeilingToHeight: + P_RemoveActiveCeiling(ceiling); + break; + //case lowerAndCrush://--- + case crushAndRaise: + case silentCrushAndRaise: + case fastCrushAndRaise: + ceiling->direction = -1; + break; + default: + break; + } + } + break; + case -1: /* DOWN */ + res = T_MovePlane(ceiling->sector,ceiling->speed, + ceiling->bottomheight,ceiling->crush,1,ceiling->direction); + + if (!ceiling->instant) + { + if (!(gametic & 7)) + { + S_StartSound((mobj_t *)&ceiling->sector->soundorg, sfx_secmove); + } + } + + if (res == pastdest) + { + switch(ceiling->type) + { + case silentCrushAndRaise: + case crushAndRaise: + ceiling->speed = CEILSPEED; + case fastCrushAndRaise: + case crushAndRaiseOnce: + ceiling->direction = 1; + break; + case lowerAndCrush: + case lowerToFloor: + case customCeiling: + case customCeilingToHeight: + P_RemoveActiveCeiling(ceiling); + break; + default: + break; + } + } + else + { + if (res == crushed) + { + switch(ceiling->type) + { + case crushAndRaise: + case lowerAndCrush: + ceiling->speed = CEILSPEED / 8; + break; + default: + break; + } + } + } + break; + } +} + +/*================================================================== */ +/* */ +/* EV_DoCeiling */ +/* Move a ceiling up/down and all around! */ +/* */ +/*================================================================== */ +int EV_DoCeiling (line_t *line, ceiling_e type, fixed_t speed) // 8000FA4C +{ + int secnum,rtn; + sector_t *sec; + ceiling_t *ceiling; + + secnum = -1; + rtn = 0; + + /* */ + /* Reactivate in-stasis ceilings...for certain types. */ + /* */ + switch(type) + { + case fastCrushAndRaise: + case silentCrushAndRaise: + case crushAndRaise: + P_ActivateInStasisCeiling(line); + default: + break; + } + + while ((secnum = P_FindSectorFromLineTag(line->tag,secnum)) >= 0) + { + sec = &sectors[secnum]; + if (sec->specialdata) + continue; + + /* */ + /* new door thinker */ + /* */ + rtn = 1; + ceiling = Z_Malloc (sizeof(*ceiling), PU_LEVSPEC, 0); + P_AddThinker (&ceiling->thinker); + sec->specialdata = ceiling; + ceiling->thinker.function = T_MoveCeiling; + ceiling->sector = sec; + ceiling->crush = false; + + if (speed == (4096 * FRACUNIT)) + ceiling->instant = true; + else + ceiling->instant = false; + + switch(type) + { + case silentCrushAndRaise: + ceiling->instant = true; + case fastCrushAndRaise: + case crushAndRaiseOnce: + ceiling->crush = true; + ceiling->topheight = sec->ceilingheight; + ceiling->bottomheight = sec->floorheight + (8*FRACUNIT); + ceiling->direction = -1; + ceiling->speed = speed; + break; + case crushAndRaise: + ceiling->crush = true; + ceiling->topheight = sec->ceilingheight; + case lowerAndCrush: + case lowerToFloor: + ceiling->bottomheight = sec->floorheight; + if (type != lowerToFloor) + ceiling->bottomheight += 8*FRACUNIT; + ceiling->direction = -1; + ceiling->speed = speed; + break; + case raiseToHighest: + ceiling->topheight = P_FindHighestCeilingSurrounding(sec); + ceiling->direction = 1; + ceiling->speed = speed; + break; + case customCeiling: + ceiling->speed = speed; + if(macrointeger >= 0) + { + ceiling->direction = 1; + ceiling->topheight = ceiling->sector->ceilingheight + (macrointeger * FRACUNIT); + } + else + { + ceiling->direction = -1; + ceiling->bottomheight = ceiling->sector->ceilingheight + (macrointeger * FRACUNIT); + } + break; + case customCeilingToHeight: + ceiling->speed = speed; + if((macrointeger * FRACUNIT) < ceiling->sector->ceilingheight) + { + ceiling->bottomheight = (macrointeger * FRACUNIT); + ceiling->direction = -1; + } + else + { + ceiling->topheight = (macrointeger * FRACUNIT); + ceiling->direction = 1; + } + break; + } + + ceiling->tag = sec->tag; + ceiling->type = type; + P_AddActiveCeiling(ceiling); + } + return rtn; +} + +/*================================================================== */ +/* */ +/* Add an active ceiling */ +/* */ +/*================================================================== */ +void P_AddActiveCeiling(ceiling_t *c) // 8000FCC0 +{ + int i; + for (i = 0; i < MAXCEILINGS;i++) + { + if (activeceilings[i] == NULL) + { + activeceilings[i] = c; + return; + } + } + + // [d64] added error message + I_Error("P_AddActiveCeiling: no more ceiling slots"); +} + +/*================================================================== */ +/* */ +/* Remove a ceiling's thinker */ +/* */ +/*================================================================== */ +void P_RemoveActiveCeiling(ceiling_t *c) // 8000FD18 +{ + int i; + + for (i = 0;i < MAXCEILINGS;i++) + { + if (activeceilings[i] == c) + { + activeceilings[i]->sector->specialdata = NULL; + P_RemoveThinker (&activeceilings[i]->thinker); + activeceilings[i] = NULL; + return; + } + } + + // [d64] added error message + I_Error("P_RemoveActiveCeiling: ceiling not found"); +} + +/*================================================================== */ +/* */ +/* Restart a ceiling that's in-stasis */ +/* */ +/*================================================================== */ +void P_ActivateInStasisCeiling(line_t *line) // 8000FD88 +{ + int i; + + for (i = 0;i < MAXCEILINGS;i++) + { + if (activeceilings[i] && (activeceilings[i]->tag == line->tag) && + (activeceilings[i]->direction == 0)) + { + activeceilings[i]->direction = activeceilings[i]->olddirection; + activeceilings[i]->thinker.function = T_MoveCeiling; + } + } +} + +/*================================================================== */ +/* */ +/* EV_CeilingCrushStop */ +/* Stop a ceiling from crushing! */ +/* */ +/*================================================================== */ +int EV_CeilingCrushStop(line_t *line) // 8000FF74 +{ + int i; + int rtn; + + rtn = 0; + for (i = 0;i < MAXCEILINGS;i++) + { + if (activeceilings[i] && (activeceilings[i]->tag == line->tag) && + (activeceilings[i]->direction != 0)) + { + activeceilings[i]->olddirection = activeceilings[i]->direction; + activeceilings[i]->thinker.function = NULL; + activeceilings[i]->direction = 0; /* in-stasis */ + rtn = 1; + } + } + + return rtn; +} diff --git a/Doom 64/p_change.c b/Doom 64/p_change.c @@ -0,0 +1,170 @@ +/* p_change.c */ + +#include "doomdef.h" +#include "p_local.h" +#include "st_main.h" + +//completo y revisado + +/* +============================================================================== + + SECTOR HEIGHT CHANGING + += After modifying a sectors floor or ceiling height, call this += routine to adjust the positions of all things that touch the += sector. += += If anything doesn't fit anymore, true will be returned. += If crunch is true, they will take damage as they are being crushed += If Crunch is false, you should set the sector height back the way it += was and call P_ChangeSector again to undo the changes +============================================================================== +*/ + +static boolean crushchange;// 800A5690 +static boolean nofit; // 800A5694 + +/* +================== += += P_ThingHeightClip += += Takes a valid thing and adjusts the thing->floorz, thing->ceilingz, += anf possibly thing->z += += This is called for all nearby monsters whenever a sector changes height += += If the thing doesn't fit, the z will be set to the lowest value and += false will be returned +================== +*/ + +boolean P_ThingHeightClip (mobj_t *thing) // 80010180 +{ + boolean onfloor; + + onfloor = (thing->z == thing->floorz); + + P_CheckPosition (thing, thing->x, thing->y); + /* what about stranding a monster partially off an edge? */ + + thing->floorz = tmfloorz; + thing->ceilingz = tmceilingz; + + if (onfloor) + /* walking monsters rise and fall with the floor */ + thing->z = thing->floorz; + else + { /* don't adjust a floating monster unless forced to */ + if (thing->z+thing->height > thing->ceilingz) + thing->z = thing->ceilingz - thing->height; + } + + if (thing->ceilingz - thing->floorz < thing->height) + return false; + + return true; +} + + +/* +=============== += += PIT_ChangeSector += +=============== +*/ + +boolean PIT_ChangeSector (mobj_t *thing) // 80010234 +{ + mobj_t *mo; + + if (P_ThingHeightClip (thing)) + return true; /* keep checking */ + + /* crunch bodies to giblets */ + if (thing->health <= 0 && thing->tics == -1) + { + if(thing->state != &states[S_498]) + { + P_SetMobjState(thing, S_498);//S_GIBS + S_StartSound(thing, sfx_slop); + thing->height = 0; + thing->radius = 0; + } + + return true; /* keep checking */ + } + + /* crunch dropped items */ + if (thing->flags & MF_DROPPED) + { + P_RemoveMobj (thing); + return true; /* keep checking */ + } + + if (!(thing->flags & MF_SHOOTABLE) ) + return true; /* assume it is bloody gibs or something */ + + nofit = true; + + // + // [d64] insta-kill thing if sector type is 666 + // + if(crushchange == 2) + { + P_DamageMobj(thing, NULL, NULL, MAXINT); + return true; + } + else + { + if (crushchange && !(gametic&3) ) + { + P_DamageMobj(thing,NULL,NULL,10); + /* spray blood in a random direction */ + mo = P_SpawnMobj (thing->x, thing->y, thing->z + thing->height/2, MT_BLOOD); + mo->momx = (P_Random() - P_Random())<<12; + mo->momy = (P_Random() - P_Random())<<12; + } + } + + return true; /* keep checking (crush other things) */ +} + +/* +=============== += += P_ChangeSector += +=============== +*/ + +boolean P_ChangeSector (sector_t *sector, boolean crunch) // 800103BC +{ + int x,y; + int i; + + /* force next sound to reflood */ + players[0].lastsoundsector = NULL; + + nofit = false; + crushchange = crunch; + + // [d64] handle special case if sector's special is 666 + if(sector->special == 666) + crushchange = 2; + + /* recheck heights for all things near the moving sector */ + for (x = sector->blockbox[BOXLEFT]; x <= sector->blockbox[BOXRIGHT]; x++) + { + for (y = sector->blockbox[BOXBOTTOM]; y <= sector->blockbox[BOXTOP]; y++) + { + P_BlockThingsIterator(x, y, PIT_ChangeSector); + } + } + + return nofit; +} + + diff --git a/Doom 64/p_doors.c b/Doom 64/p_doors.c @@ -0,0 +1,305 @@ +#include "doomdef.h" +#include "p_local.h" +#include "st_main.h" + +/*================================================================== */ +/*================================================================== */ +/* */ +/* VERTICAL DOORS */ +/* */ +/*================================================================== */ +/*================================================================== */ + +/*================================================================== */ +/* */ +/* T_VerticalDoor */ +/* */ +/*================================================================== */ +void T_VerticalDoor (vldoor_t *door) // 800104A0 +{ + result_e res1; + result_e res2; + + switch(door->direction) + { + case 0: /* WAITING */ + if (!--door->topcountdown) + { + switch(door->type) + { + case BlazeRaise: + door->direction = -1; /* time to go back down */ + S_StartSound((mobj_t *)&door->sector->soundorg,80/*sfx_bdcls*/); + break; + case Normal: + door->direction = -1; /* time to go back down */ + S_StartSound((mobj_t *)&door->sector->soundorg,18/*sfx_dorcls*/); + break; + case Close30ThenOpen: + door->direction = 1; + S_StartSound((mobj_t *)&door->sector->soundorg,17/*sfx_doropn*/); + break; + //case RaiseIn5Mins: // [D64] moved here? + //door->direction = 1; + //door->type = Normal; + //S_StartSound((mobj_t *)&door->sector->soundorg,17/*sfx_doropn*/); + //break; + default: + break; + } + } + break; + #if 1 // [D64] no used + case 2: /* INITIAL WAIT */ + if (!--door->topcountdown) + { + switch(door->type) + { + case RaiseIn5Mins: + door->direction = 1; + door->type = Normal; + S_StartSound((mobj_t *)&door->sector->soundorg,17/*sfx_doropn*/); + break; + default: + break; + } + } + break; + #endif // 0 + case -1: /* DOWN */ + res1 = T_MovePlane(door->sector,door->speed, door->initceiling,false,1,-1); + res2 = T_MovePlane(door->sector,door->speed, door->initceiling,false,0,1); + if ((res1 == pastdest) && (res2 == pastdest)) + { + switch(door->type) + { + case BlazeRaise: + case BlazeClose: + door->sector->specialdata = NULL; + P_RemoveThinker(&door->thinker); /* unlink and free */ + S_StartSound((mobj_t *)&door->sector->soundorg, 80/*sfx_bdcls*/); + break; + case Normal: + case DoorClose: + door->sector->specialdata = NULL; + P_RemoveThinker (&door->thinker); /* unlink and free */ + break; + case Close30ThenOpen: + door->direction = 0; + door->topcountdown = TICRATE*30; + break; + default: + break; + } + } + else if ((res1 == crushed) || (res2 == crushed)) + { + switch (door->type) + { + case BlazeClose: + case DoorClose: /* DO NOT GO BACK UP! */ + break; + + default: + door->direction = 1; + S_StartSound((mobj_t *)&door->sector->soundorg, 17/*sfx_doropn*/); + break; + } + } + break; + case 1: /* UP */ + res1 = T_MovePlane(door->sector,door->speed,door->topheight,false,1,1); + res2 = T_MovePlane(door->sector,door->speed,door->bottomheight,false,0,-1); + if ((res1 == pastdest) && (res2 == pastdest)) + { + switch(door->type) + { + case BlazeRaise: + case Normal: + door->direction = 0; /* wait at top */ + door->topcountdown = door->topwait; + break; + case Close30ThenOpen: + case BlazeOpen: + case DoorOpen: + door->sector->specialdata = NULL; + P_RemoveThinker (&door->thinker); /* unlink and free */ + break; + default: + break; + } + } + break; + } +} + +/*================================================================== */ +/* */ +/* EV_DoDoor */ +/* Move a door up/down and all around! */ +/* */ +/*================================================================== */ +int EV_DoDoor (line_t *line, vldoor_e type) // 80010750 +{ + int secnum,rtn; + sector_t *sec; + vldoor_t *door; + + secnum = -1; + rtn = 0; + while ((secnum = P_FindSectorFromLineTag(line->tag,secnum)) >= 0) + { + sec = &sectors[secnum]; + if (sec->specialdata) + continue; + + /* */ + /* new door thinker */ + /* */ + rtn = 1; + door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0); + P_AddThinker (&door->thinker); + sec->specialdata = door; + door->thinker.function = T_VerticalDoor; + door->topwait = VDOORWAIT; + door->speed = VDOORSPEED; + door->sector = sec; + door->type = type; + door->bottomheight = sec->floorheight; + door->initceiling = sec->floorheight; + + switch(type) + { + case BlazeClose: + door->topheight = P_FindLowestCeilingSurrounding(sec); + door->topheight -= 4 * FRACUNIT; + door->direction = -1; + door->speed = VDOORSPEED * 4; + S_StartSound((mobj_t *)&door->sector->soundorg, 80/*sfx_bdcls*/); + break; + case DoorClose: + door->topheight = P_FindLowestCeilingSurrounding(sec); + door->topheight -= 4*FRACUNIT; + door->direction = -1; + S_StartSound((mobj_t *)&door->sector->soundorg,18/*sfx_dorcls*/); + break; + case Close30ThenOpen: + door->topheight = sec->ceilingheight; + door->direction = -1; + S_StartSound((mobj_t *)&door->sector->soundorg,18/*sfx_dorcls*/); + break; + case BlazeRaise: + case BlazeOpen: + door->direction = 1; + door->topheight = P_FindLowestCeilingSurrounding(sec); + door->topheight -= 4 * FRACUNIT; + door->speed = VDOORSPEED * 4; + if (door->topheight != sec->ceilingheight) + S_StartSound((mobj_t *)&door->sector->soundorg, 79/*sfx_bdopn*/); + break; + case Normal: + case DoorOpen: + door->direction = 1; + door->topheight = P_FindLowestCeilingSurrounding(sec); + door->topheight -= 4*FRACUNIT; + if (door->topheight != sec->ceilingheight) + S_StartSound((mobj_t *)&door->sector->soundorg,17/*sfx_doropn*/); + break; + default: + break; + } + } + return rtn; +} + + +/*================================================================== */ +/* */ +/* EV_VerticalDoor : open a door manually, no tag value */ +/* */ +/*================================================================== */ +void EV_VerticalDoor (line_t *line, mobj_t *thing) // 80010998 +{ + player_t *player; + sector_t *sec; + vldoor_t *door; + int side; + + side = 0; /* only front sides can be used */ + + /* if the sector has an active thinker, use it */ + sec = sides[ line->sidenum[side^1]] .sector; + if (sec->specialdata) + { + door = sec->specialdata; + switch(SPECIALMASK(line->special)) + { + case 1: /* ONLY FOR "RAISE" DOORS, NOT "OPEN"s */ + case 117: + if (door->direction == -1) + door->direction = 1; /* go back up */ + else + { + if (!thing->player) + return; /* JDC: bad guys never close doors */ + door->direction = -1; /* start going down immediately */ + } + return; + } + } + + /* for proper sound */ + switch(SPECIALMASK(line->special)) + { + case 117: /* BLAZING DOOR RAISE */ + case 118: /* BLAZING DOOR OPEN */ + S_StartSound((mobj_t *)&sec->soundorg,79/*sfx_bdopn*/); + break; + default: /* LOCKED DOOR SOUND */ + S_StartSound((mobj_t *)&sec->soundorg,17/*sfx_doropn*/); + break; + } + + /* */ + /* new door thinker */ + /* */ + door = Z_Malloc (sizeof(*door), PU_LEVSPEC, 0); + P_AddThinker (&door->thinker); + sec->specialdata = door; + door->thinker.function = T_VerticalDoor; + door->speed = VDOORSPEED; + door->sector = sec; + door->direction = 1; + door->topwait = VDOORWAIT; + + switch(SPECIALMASK(line->special)) + { + case 1: + door->type = Normal; + break; + case 31: + door->type = DoorOpen; + line->special = 0; + break; + case 117: /* blazing door raise */ + door->type = BlazeRaise; + door->speed = VDOORSPEED * 4; + break; + case 118: /* blazing door open */ + door->type = BlazeOpen; + door->speed = VDOORSPEED * 4; + line->special = 0; + break; + } + + /* */ + /* find the top and bottom of the movement range */ + /* */ + door->topheight = P_FindLowestCeilingSurrounding(sec); + door->topheight -= 4*FRACUNIT; + door->bottomheight = P_FindLowestFloorSurrounding(sec); + door->initceiling = sec->floorheight; + + if(door->bottomheight != sec->floorheight) + door->bottomheight += 4*FRACUNIT; +} diff --git a/Doom 64/p_enemy.c b/Doom 64/p_enemy.c @@ -0,0 +1,1991 @@ +/* P_enemy.c */ + +#include "doomdef.h" +#include "p_local.h" + +void A_Fall (mobj_t *actor); + +typedef enum +{ + DP_STRAIGHT, + DP_LEFT, + DP_RIGHT +} dirproj_e; + +mobj_t* P_MissileAttack(mobj_t *actor, dirproj_e direction); + +/* +=============================================================================== + + ENEMY THINKING + +enemies are allways spawned with targetplayer = -1, threshold = 0 +Most monsters are spawned unaware of all players, but some can be made preaware + +=============================================================================== +*/ + +/* +================ += += P_CheckMeleeRange += +================ +*/ + +boolean P_CheckMeleeRange (mobj_t *actor) // 80010B90 +{ + mobj_t *pl; + fixed_t dist; + + if (!(actor->flags&MF_SEETARGET)) + return false; + + if (!actor->target) + return false; + + pl = actor->target; + dist = P_AproxDistance (pl->x-actor->x, pl->y-actor->y); + if (dist >= MELEERANGE) + return false; + + return true; +} + +/* +================ += += P_CheckMissileRange += +================ +*/ + +boolean P_CheckMissileRange (mobj_t *actor) // 80010C10 +{ + fixed_t dist; + + if (!(actor->flags & MF_SEETARGET)) + return false; + + if (actor->flags & MF_JUSTHIT) + { /* the target just hit the enemy, so fight back! */ + actor->flags &= ~MF_JUSTHIT; + return true; + } + + if (actor->reactiontime) + return false; /* don't attack yet */ + + dist = P_AproxDistance ( actor->x-actor->target->x, actor->y-actor->target->y) - 64*FRACUNIT; + if (!actor->info->meleestate) + dist -= 128*FRACUNIT; /* no melee attack, so fire more */ + + dist >>= 16; + + if (actor->type == MT_SKULL) + dist >>= 1; + + if (dist > 200) + dist = 200; + + if (P_Random() < dist) + return false; + + return true; +} + + +/* +================ += += P_Move += += Move in the current direction += returns false if the move is blocked +================ +*/ + +fixed_t xspeed[8] = {FRACUNIT,47000,0,-47000,-FRACUNIT,-47000,0,47000};// 8005ACC0 +fixed_t yspeed[8] = {0,47000,FRACUNIT,47000,0,-47000,-FRACUNIT,-47000};// 8005ACE0 + +extern line_t *blockline; // 800A5D9C + +boolean P_Move (mobj_t *actor) // 80010D08 +{ + fixed_t tryx, tryy; + boolean good; + line_t *blkline; + + if (actor->movedir == DI_NODIR) + return false; + + if((actor->flags & MF_GRAVITY) != 0) + { + if(actor->floorz != actor->z) + { + return false; + } + } + + tryx = actor->x + actor->info->speed * xspeed[actor->movedir]; + tryy = actor->y + actor->info->speed * yspeed[actor->movedir]; + + if (!P_TryMove (actor, tryx, tryy) ) + { /* open any specials */ + if (actor->flags & MF_FLOAT && floatok) + { /* must adjust height */ + if (actor->z < tmfloorz) + actor->z += FLOATSPEED; + else + actor->z -= FLOATSPEED; + + //actor->flags |= MF_INFLOAT; + return true; + } + + blkline = blockline;//(line_t *)DSPRead (&blockline); + if (!blkline || !blkline->special) + return false; + + actor->movedir = DI_NODIR; + good = false; + + if(blockline->special & MLU_USE) + good = P_UseSpecialLine (blkline, actor); + + return good; + } + //else + // actor->flags &= ~MF_INFLOAT; + + //if (!(actor->flags & MF_FLOAT)) + // actor->z = actor->floorz; + + return true; +} + + +/* +================================== += += TryWalk += += Attempts to move actoron in its current (ob->moveangle) direction. += += If blocked by either a wall or an actor returns FALSE += If move is either clear or blocked only by a door, returns TRUE and sets += If a door is in the way, an OpenDoor call is made to start it opening. += +================================== +*/ + +boolean P_TryWalk (mobj_t *actor) // 80010E88 +{ + if (!P_Move (actor)) + return false; + + actor->movecount = P_Random()&7; + return true; +} + + +/* +================ += += P_NewChaseDir += +================ +*/ + +dirtype_t opposite[] = // 8005AD00 +{DI_WEST, DI_SOUTHWEST, DI_SOUTH, DI_SOUTHEAST, DI_EAST, DI_NORTHEAST, +DI_NORTH, DI_NORTHWEST, DI_NODIR}; + +dirtype_t diags[] = {DI_NORTHWEST,DI_NORTHEAST,DI_SOUTHWEST,DI_SOUTHEAST}; // 8005AD24 + +void P_NewChaseDir (mobj_t *actor) // 80010ED0 +{ + fixed_t deltax,deltay; + dirtype_t d[3]; + dirtype_t tdir, olddir, turnaround; + + if (!actor->target) + I_Error ("P_NewChaseDir: called with no target"); + + olddir = actor->movedir; + turnaround=opposite[olddir]; + + deltax = actor->target->x - actor->x; + deltay = actor->target->y - actor->y; + + if (deltax>10*FRACUNIT) + d[1]= DI_EAST; + else if (deltax<-10*FRACUNIT) + d[1]= DI_WEST; + else + d[1]=DI_NODIR; + + if (deltay<-10*FRACUNIT) + d[2]= DI_SOUTH; + else if (deltay>10*FRACUNIT) + d[2]= DI_NORTH; + else + d[2]=DI_NODIR; + +/* try direct route */ + if (d[1] != DI_NODIR && d[2] != DI_NODIR) + { + actor->movedir = diags[((deltay<0)<<1)+(deltax>0)]; + if (actor->movedir != turnaround && P_TryWalk(actor)) + return; + } + +/* try other directions */ + if (P_Random() > 200 || abs(deltay)>abs(deltax)) + { + tdir=d[1]; + d[1]=d[2]; + d[2]=tdir; + } + + if (d[1]==turnaround) + d[1]=DI_NODIR; + + if (d[2]==turnaround) + d[2]=DI_NODIR; + + if (d[1]!=DI_NODIR) + { + actor->movedir = d[1]; + if (P_TryWalk(actor)) + return; /*either moved forward or attacked*/ + } + + if (d[2]!=DI_NODIR) + { + actor->movedir =d[2]; + if (P_TryWalk(actor)) + return; + } + +/* there is no direct path to the player, so pick another direction */ + + if (olddir!=DI_NODIR) + { + actor->movedir =olddir; + if (P_TryWalk(actor)) + return; + } + + if (P_Random()&1) /*randomly determine direction of search*/ + { + for (tdir=DI_EAST ; tdir<=DI_SOUTHEAST ; tdir++) + { + if (tdir!=turnaround) + { + actor->movedir =tdir; + if ( P_TryWalk(actor) ) + return; + } + } + } + else + { + for (tdir=DI_SOUTHEAST ; (int)tdir >= (int)DI_EAST;tdir--) + { + if (tdir!=turnaround) + { + actor->movedir =tdir; + if ( P_TryWalk(actor) ) + return; + } + } + } + + if (turnaround != DI_NODIR) + { + actor->movedir =turnaround; + if ( P_TryWalk(actor) ) + return; + } + + actor->movedir = DI_NODIR; /* can't move */ +} + + +/* +================ += += P_LookForPlayers += += If allaround is false, only look 180 degrees in front += returns true if a player is targeted +================ +*/ + +boolean P_LookForPlayers (mobj_t *actor, boolean allaround) // 8001115C +{ + angle_t an; + fixed_t dist, dist2; + mobj_t *mo; + mobj_t *mobj; + + mo = actor->target; + if (!mo || mo->health <= 0 || !(actor->flags & MF_SEETARGET)) + { + if(actor->type > MT_PLAYERBOT3) /* for monsters */ + { + actor->target = players[0].mo; + } + else /* special case for player bots */ + { + dist2 = MAXINT; + + for(mobj = mobjhead.next; mobj != &mobjhead; mobj = mobj->next) + { + + if((mobj->flags & MF_COUNTKILL) == 0 || + mobj->type <= MT_PLAYERBOT3 || + mobj->health <= 0 || + mobj == actor) + { + continue; + } + + /* find a killable target as close as possible */ + dist = P_AproxDistance(mobj->x - actor->x, mobj->y - actor->y); + if(!(dist < dist2)) + continue; + + actor->target = mobj; + dist2 = dist; + } + } + + return false; + } + + if (!actor->subsector->sector->soundtarget) + { + if (!allaround) + { + an = R_PointToAngle2 (actor->x, actor->y, mo->x, mo->y) - actor->angle; + if (an > ANG90 && an < ANG270) + { + dist = P_AproxDistance (mo->x - actor->x, mo->y - actor->y); + /* if real close, react anyway */ + if (dist > MELEERANGE) + return false; /* behind back */ + } + } + } + + return true; +} + + +/* +=============================================================================== + + ACTION ROUTINES + +=============================================================================== +*/ + +/* +============== += += A_Look += += Stay in state until a player is sighted += +============== +*/ + +void A_Look (mobj_t *actor) // 80011340 +{ + mobj_t *targ; + int sound; + + /* if current target is visible, start attacking */ + if (!P_LookForPlayers(actor, false)) + { + /* if the sector has a living soundtarget, make that the new target */ + actor->threshold = 0; /* any shot will wake up */ + targ = actor->subsector->sector->soundtarget; + if (targ == NULL || !(targ->flags & MF_SHOOTABLE) || (actor->flags & MF_AMBUSH)) + return; + actor->target = targ; + } + + /* go into chase state */ + if (actor->info->seesound) + { + switch (actor->info->seesound) + { + case sfx_possit1://sfx_posit1: + case sfx_possit2://sfx_posit2: + case sfx_possit3://sfx_posit3: + sound = sfx_possit1+(P_Random()&1); + break; + case sfx_impsit1://sfx_bgsit1: + case sfx_impsit2://sfx_bgsit2: + sound = sfx_impsit1+(P_Random()&1); + break; + default: + sound = actor->info->seesound; + break; + } + + if (actor->type == MT_RESURRECTOR || actor->type == MT_CYBORG) + S_StartSound(NULL, sound); // full volume + else + S_StartSound(actor, sound); + } + + P_SetMobjState (actor, actor->info->seestate); +} + + +/* +============== += += A_Chase += += Actor has a melee attack, so it tries to close as fast as possible += +============== +*/ + +void A_Chase (mobj_t *actor) // 8001146C +{ + int delta; + + if (actor->reactiontime) + actor->reactiontime--; + + /* */ + /* modify target threshold */ + /* */ + if (actor->threshold) + actor->threshold--; + + /* */ + /* turn towards movement direction if not there yet */ + /* */ + if (actor->movedir < 8) + { + actor->angle &= (7<<29); + delta = actor->angle - (actor->movedir << 29); + if (delta > 0) + actor->angle -= ANG90/2; + else if (delta < 0) + actor->angle += ANG90/2; + } + + if (!actor->target || !(actor->target->flags&MF_SHOOTABLE)) + { /* look for a new target */ + if (P_LookForPlayers(actor,true)) + return; /* got a new target */ + P_SetMobjState (actor, actor->info->spawnstate); + return; + } + + /* */ + /* don't attack twice in a row */ + /* */ + if (actor->flags & MF_JUSTATTACKED) + { + actor->flags &= ~MF_JUSTATTACKED; + P_NewChaseDir (actor); + return; + } + + /* */ + /* check for melee attack */ + /* */ + if (actor->info->meleestate && P_CheckMeleeRange (actor)) + { + if (actor->info->attacksound) + S_StartSound (actor, actor->info->attacksound); + P_SetMobjState (actor, actor->info->meleestate); + return; + } + + /* */ + /* check for missile attack */ + /* */ + if ( (/*gameskill == sk_nightmare || */!actor->movecount) && actor->info->missilestate + && P_CheckMissileRange (actor)) + { + P_SetMobjState (actor, actor->info->missilestate); + //if (gameskill != sk_nightmare) + actor->flags |= MF_JUSTATTACKED; + return; + } + + /* */ + /* chase towards player */ + /* */ + if (--actor->movecount<0 || !P_Move (actor)) + P_NewChaseDir (actor); + + /* */ + /* make active sound */ + /* */ + if (actor->info->activesound && P_Random () < 3) + S_StartSound (actor, actor->info->activesound); +} + +/*============================================================================= */ + +/* +============== += += A_FaceTarget += +============== +*/ + +void A_FaceTarget (mobj_t *actor) // 800116A8 +{ + int rnd1, rnd2; + if (!actor->target) + return; + + actor->flags &= ~MF_AMBUSH; + actor->angle = R_PointToAngle2 (actor->x, actor->y , actor->target->x, actor->target->y); + + if (actor->target->flags & MF_SHADOW) + { + rnd1 = P_Random(); + rnd2 = P_Random(); + actor->angle += (rnd2 - rnd1) << 21; + } +} + +/* +============== += += A_Scream += +============== +*/ + +void A_Scream (mobj_t *actor) // 80011740 +{ + int sound; + + switch (actor->info->deathsound) + { + case 0: + return; + + case sfx_posdie1://sfx_podth1: + case sfx_posdie2://sfx_podth2: + case sfx_posdie3://sfx_podth3: + sound = sfx_posdie1 + (P_Random ()&1); + break; + + case sfx_impdth1://sfx_bgdth1: + case sfx_impdth2://sfx_bgdth2: + sound = sfx_impdth1 + (P_Random ()&1); + break; + + default: + sound = actor->info->deathsound; + break; + } + + S_StartSound(actor, sound); +} + +/* +============== += += A_XScream += +============== +*/ + +void A_XScream (mobj_t *actor) // 800117E4 +{ + S_StartSound (actor, sfx_slop); +} + +/* +============== += += A_Pain += +============== +*/ + +void A_Pain (mobj_t *actor) // 80011804 +{ + if(actor->info->painsound) + { + if(actor->type == MT_RESURRECTOR) + S_StartSound(NULL, actor->info->painsound); + else + S_StartSound(actor, actor->info->painsound); + } +} + +/* +============== += += A_Fall += +============== +*/ + +void A_Fall (mobj_t *actor) // 8001185C +{ +/* actor is on ground, it can be walked over */ + actor->flags &= ~MF_SOLID; +} + + +/* +================ += += A_Explode += +================ +*/ + +void A_Explode (mobj_t *thingy) // 80011870 +{ + P_RadiusAttack(thingy, thingy->target, 128); +} + + +/* +================ += += A_OnDeathTrigger(A_BossDeath) += += Possibly trigger special effects +================ +*/ + +void A_OnDeathTrigger (mobj_t *mo) // 80011894 +{ + mobj_t *mo2; + + if(!(mo->flags & MF_TRIGDEATH)) + return; + + for(mo2 = mobjhead.next; mo2 != &mobjhead; mo2 = mo2->next) + { + if((mo2->tid == mo->tid) && (mo2->health > 0)) + return; + } + + if(!P_ActivateLineByTag(mo->tid, mo)) + { + macroqueue[macroidx1].activator = mo; + macroqueue[macroidx1].tag = mo->tid; + macroidx1 = (macroidx1 + 1) & 3; + } +} + +/* +============== += += A_PosAttack += +============== +*/ + +void A_PosAttack (mobj_t *actor) // 80011954 +{ + int angle, damage, rnd1, rnd2; + + if (!actor->target) + return; + + A_FaceTarget (actor); + angle = actor->angle; + + S_StartSound (actor, sfx_pistol); + + rnd1 = P_Random(); + rnd2 = P_Random(); + angle += (rnd2-rnd1)<<20; + + damage = ((P_Random() & 7) * 3) + 3; + P_LineAttack (actor, angle, 0, MISSILERANGE, MAXINT, damage); +} + +/* +============== += += A_SPosAttack += +============== +*/ + +void A_SPosAttack (mobj_t *actor) // 800119FC +{ + int i; + int angle, bangle, damage; + + if (!actor->target) + return; + + S_StartSound (actor, sfx_shotgun); + A_FaceTarget (actor); + bangle = actor->angle; + + for (i=0 ; i<3 ; i++) + { + angle = bangle + ((P_Random()-P_Random())<<20); + damage = ((P_Random() % 5) * 3) + 3; + P_LineAttack (actor, angle, 0, MISSILERANGE, MAXINT, damage); + } +} + +/* +============== += += A_PlayAttack(A_CPosAttack) += +============== +*/ + +void A_PlayAttack(mobj_t* actor) // 80011b1C +{ + int angle; + int bangle; + int damage; + int slope; + + if (!actor->target) + return; + + S_StartSound(actor, sfx_pistol); + A_FaceTarget(actor); + bangle = actor->angle; + + slope = P_AimLineAttack(actor, bangle, 0, MISSILERANGE); + + angle = bangle + ((P_Random() - P_Random()) << 20); + damage = ((P_Random() % 5) * 3) + 3; + P_LineAttack(actor, angle, 0, MISSILERANGE, slope, damage); +} + +/* +============== += += A_CPosRefire += +============== +*/ + +void A_CPosRefire(mobj_t* actor) // 80011BD4 +{ + A_FaceTarget(actor); + + if (P_Random() < 40) + return; + + if (!actor->target || actor->target->health <= 0 + || !P_CheckSight(actor, actor->target)) + { + P_SetMobjState(actor, actor->info->seestate); + } +} + +/* +============== += += A_BspiFaceTarget += +============== +*/ + +void A_BspiFaceTarget(mobj_t *actor) // 80011C50 +{ + A_FaceTarget(actor); + actor->extradata = (int *)5; +} + +/* +============== += += A_BspiAttack += +============== +*/ + +void A_BspiAttack(mobj_t *actor) // 80011C74 +{ + if (!actor->target) + return; + + A_FaceTarget(actor); + +/* */ +/* launch a missile */ +/* */ + P_MissileAttack(actor, DP_LEFT); + P_MissileAttack(actor, DP_RIGHT); +} + +/* +============== += += A_SpidRefire += +============== +*/ + +void A_SpidRefire (mobj_t *actor) // 80011CBC +{ + A_FaceTarget (actor); + + if (P_Random () < 10) + return; + + if (!actor->target || actor->target->health <= 0 || !(actor->flags&MF_SEETARGET) ) + { + P_SetMobjState (actor, actor->info->seestate); + actor->extradata = (int *)5; + return; + } + + if(--actor->extradata <= 0) + { + P_SetMobjState(actor, actor->info->missilestate); + actor->extradata = (int *)5; + } +} + +/* +============== += += A_TroopMelee += +============== +*/ + +void A_TroopMelee(mobj_t* actor) // 80011D78 +{ + int damage; + + if(!actor->target) + return; + + A_FaceTarget (actor); + if(P_CheckMeleeRange(actor)) + { + S_StartSound(actor, sfx_scratch); + damage = ((P_Random() & 7) * 3) + 3; + P_DamageMobj(actor->target, actor, actor, damage); + } +} + +/* +============== += += A_TroopAttack += +============== +*/ + +void A_TroopAttack (mobj_t *actor) // 80011DEC +{ + int damage; + + if (!actor->target) + return; + + A_FaceTarget (actor); + +/* */ +/* launch a missile */ +/* */ + P_MissileAttack(actor, DP_STRAIGHT); +} + +/* +============== += += A_SargAttack += +============== +*/ + +void A_SargAttack (mobj_t *actor) // 80011E28 +{ + int damage; + + if (!actor->target) + return; + + A_FaceTarget (actor); + if(P_CheckMeleeRange(actor)) + { + damage = ((P_Random() & 7) * 4) + 4; + P_DamageMobj(actor->target, actor, actor, damage); + } +} + +/* +============== += += A_HeadAttack += +============== +*/ + +void A_HeadAttack (mobj_t *actor) // 80011E90 +{ + int damage; + + if (!actor->target) + return; + + A_FaceTarget (actor); + if (P_CheckMeleeRange (actor)) + { + damage = ((P_Random() & 7) * 8) + 8; + P_DamageMobj (actor->target, actor, actor, damage); + return; + } +/* */ +/* launch a missile */ +/* */ + P_MissileAttack(actor, DP_STRAIGHT); +} + +/* +============== += += A_CyberAttack += +============== +*/ + +void A_CyberAttack (mobj_t *actor) // 80011F08 +{ + if (!actor->target) + return; + + A_FaceTarget (actor); + P_MissileAttack(actor, DP_LEFT); +} + +/* +============== += += A_CyberDeathEvent += +============== +*/ + +void A_CyberDeathEvent(mobj_t* actor) // 80011F44 +{ + mobjexp_t *exp; + + //P_BossExplode(actor, 4, 12); + exp = Z_Malloc (sizeof(*exp), PU_LEVSPEC, 0); + P_AddThinker (&exp->thinker); + exp->thinker.function = T_MobjExplode; + exp->mobj = actor; + exp->delay = 0; + exp->delaydefault = 4; + exp->lifetime = 12; + S_StartSound(NULL, actor->info->deathsound); +} + +/* +============== += += A_BruisAttack += +============== +*/ + +void A_BruisAttack (mobj_t *actor) // 80011FC4 +{ + int damage; + + if (!actor->target) + return; + + if (P_CheckMeleeRange (actor)) + { + S_StartSound (actor, sfx_scratch); + damage = ((P_Random() & 7) * 11) + 11; + P_DamageMobj (actor->target, actor, actor, damage); + return; + } +/* */ +/* launch a missile */ +/* */ + P_MissileAttack(actor, DP_STRAIGHT); +} + +/* +============== += += A_SpawnSmoke += +============== +*/ + +void A_SpawnSmoke(mobj_t *actor) // 8001204C +{ + mobj_t *smoke; + + smoke = P_SpawnMobj(actor->x, actor->y, actor->z, MT_SMOKE_GRAY); + smoke->momz = FRACUNIT/2; +} + +/* +============== += += A_Tracer += +============== +*/ + +#define TRACEANGLE 0x10000000 + +void A_Tracer(mobj_t *actor) // 80012088 +{ + angle_t exact; + fixed_t dist; + fixed_t slope; + mobj_t *dest; + mobj_t *th; + + th = P_SpawnMobj(actor->x - actor->momx, actor->y - actor->momy, actor->z, MT_SMOKE_RED); + + th->momz = FRACUNIT; + th->tics -= P_Random() & 3; + + if (th->tics < 1) + th->tics = 1; + + if(actor->threshold-- < -100) + return; + + // adjust direction + dest = actor->tracer; + + if (!dest || dest->health <= 0) + return; + + // change angle + exact = R_PointToAngle2(actor->x, actor->y, dest->x, dest->y); + + if (exact != actor->angle) + { + if (exact - actor->angle > 0x80000000) + { + actor->angle -= TRACEANGLE; + if (exact - actor->angle < 0x80000000) + actor->angle = exact; + } + else + { + actor->angle += TRACEANGLE; + if (exact - actor->angle > 0x80000000) + actor->angle = exact; + } + } + + exact = actor->angle >> ANGLETOFINESHIFT; + actor->momx = (actor->info->speed * finecosine[exact]); + actor->momy = (actor->info->speed * finesine[exact]); + + // change slope + dist = P_AproxDistance(dest->x - actor->x, dest->y - actor->y); + dist = dist / (actor->info->speed << FRACBITS); + + if (dist < 1) + dist = 1; + + slope = (dest->height * 3); + if(slope < 0) { + slope = slope + 3; + } + + slope = (dest->z + (slope >> 2) - actor->z) / dist; + + if (slope < actor->momz) + actor->momz -= FRACUNIT / 8; + else + actor->momz += FRACUNIT / 4; +} + +/* +============== += += A_FatRaise += +============== +*/ + +#define FATSPREAD (ANG90/4) + +void A_FatRaise(mobj_t *actor) // 800122F4 +{ + A_FaceTarget(actor); + S_StartSound(actor, sfx_fattatk); +} + +/* +============== += += A_FatAttack1 += +============== +*/ + +void A_FatAttack1(mobj_t *actor) // 80012320 +{ + mobj_t *mo; + int an; + + A_FaceTarget(actor); + + // Change direction to ... + P_MissileAttack(actor, DP_RIGHT); + mo = P_MissileAttack(actor, DP_LEFT); + + mo->angle += FATSPREAD; + an = mo->angle >> ANGLETOFINESHIFT; + mo->momx = (mo->info->speed * finecosine[an]); + mo->momy = (mo->info->speed * finesine[an]); +} + +/* +============== += += A_FatAttack2 += +============== +*/ + +void A_FatAttack2(mobj_t *actor) // 800123B0 +{ + mobj_t *mo; + mobj_t *target; + int an; + + A_FaceTarget(actor); + + // Now here choose opposite deviation. + P_MissileAttack(actor, DP_LEFT); + mo = P_MissileAttack(actor, DP_RIGHT); + + mo->angle -= FATSPREAD; + an = mo->angle >> ANGLETOFINESHIFT; + mo->momx = (mo->info->speed * finecosine[an]); + mo->momy = (mo->info->speed * finesine[an]); +} + +/* +============== += += A_FatAttack3 += +============== +*/ + +void A_FatAttack3(mobj_t *actor) // 80012440 +{ + mobj_t *mo; + mobj_t *target; + int an; + + A_FaceTarget(actor); + + mo = P_MissileAttack(actor, DP_RIGHT); + mo->angle -= FATSPREAD / 4; + an = mo->angle >> ANGLETOFINESHIFT; + mo->momx = (mo->info->speed * finecosine[an]); + mo->momy = (mo->info->speed * finesine[an]); + + mo = P_MissileAttack(actor, DP_LEFT); + mo->angle += FATSPREAD / 4; + an = mo->angle >> ANGLETOFINESHIFT; + mo->momx = (mo->info->speed * finecosine[an]); + mo->momy = (mo->info->speed * finesine[an]); +} + + +/* +================== += += SkullAttack += += Fly at the player like a missile += +================== +*/ + +#define SKULLSPEED (40*FRACUNIT) + +void A_SkullAttack (mobj_t *actor) // 80012528 +{ + mobj_t *dest; + angle_t an; + int dist; + + if (!actor->target) + return; + + dest = actor->target; + actor->flags |= MF_SKULLFLY; + + S_StartSound (actor, actor->info->attacksound); + A_FaceTarget (actor); + an = actor->angle >> ANGLETOFINESHIFT; + actor->momx = (finecosine[an] * (SKULLSPEED/FRACUNIT)); + actor->momy = (finesine[an] * (SKULLSPEED/FRACUNIT)); + dist = P_AproxDistance (dest->x - actor->x, dest->y - actor->y); + dist = dist / SKULLSPEED; + if (dist < 1) + dist = 1; + actor->momz = (dest->z+(dest->height>>1) - actor->z) / dist; +} + + +/* +============== += += PIT_PainCheckLine += +============== +*/ +boolean PIT_PainCheckLine(intercept_t *in) // 80012654 +{ + if (!(in->d.line->backsector)) + return false; + + return true; +} + +/* +============== += += A_PainShootSkull += +============== +*/ + +void A_PainShootSkull(mobj_t *actor, angle_t angle) // 8001267C +{ + fixed_t x; + fixed_t y; + fixed_t z; + + mobj_t* newmobj; + angle_t an; + int prestep; + int count; + + mobj_t *mo; + + // count total number of skull currently on the level + count = 0; + for (mo=mobjhead.next ; mo != &mobjhead ; mo=mo->next) + { + if ((mo->type == MT_SKULL)) + { + count++; + + // if there are allready 17 skulls on the level, + // don't spit another one + if (count >= 17) + return; + } + } + + // okay, there's playe for another one + an = angle >> ANGLETOFINESHIFT; + + prestep = (mobjinfo[MT_SKULL].radius + (4 * FRACUNIT) + actor->info->radius) >> FRACBITS; + + x = actor->x + (finecosine[an] * prestep); + y = actor->y + (finesine[an] * prestep); + z = actor->z + 16 * FRACUNIT; + + newmobj = P_SpawnMobj(x, y, z, MT_SKULL); + + // Check for movements. + if (!P_PathTraverse(actor->x, actor->y, newmobj->x, newmobj->y, PT_ADDLINES, PIT_PainCheckLine) || + !P_TryMove(newmobj, newmobj->x, newmobj->y)) + { + // kill it immediately + P_DamageMobj(newmobj, actor, actor, 10000); + P_RadiusAttack(newmobj, newmobj, 128); + return; + } + + newmobj->target = actor->target; + P_SetMobjState(newmobj,newmobj->info->missilestate); + A_SkullAttack(newmobj); +} + +/* +============== += += A_PainAttack += +============== +*/ + +void A_PainAttack(mobj_t *actor) // 80012804 +{ + if (!actor->target) + return; + + A_FaceTarget(actor); + A_PainShootSkull(actor, actor->angle-0x15550000); + A_PainShootSkull(actor, actor->angle+0x15550000); +} + +/* +============== += += A_PainDie += +============== +*/ + +void A_PainDie(mobj_t *actor) // 8001285C +{ + A_Fall(actor); + A_PainShootSkull(actor, actor->angle + ANG90); + A_PainShootSkull(actor, actor->angle + ANG180); + A_PainShootSkull(actor, actor->angle + ANG270); + + A_OnDeathTrigger(actor); +} + + +/* +============== += += A_RectChase += +============== +*/ + +void A_RectChase(mobj_t* actor) // 800128C4 +{ + if(!(actor->target) || (actor->target->health <= 0) || + !(P_AproxDistance(actor->target->x-actor->x, actor->target->y-actor->y) < (600*FRACUNIT))) + { + A_Chase(actor); + return; + } + + A_FaceTarget(actor); + S_StartSound(NULL, actor->info->attacksound); + P_SetMobjState(actor, actor->info->meleestate); + +} + +/* +============== += += A_RectGroundFire += +============== +*/ + +void A_RectGroundFire(mobj_t* actor) // 8001296C +{ + mobj_t* mo; + angle_t an; + + A_FaceTarget(actor); + + mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_PROJ_RECTFIRE); + mo->target = actor; + an = R_PointToAngle2(actor->x, actor->y, actor->target->x, actor->target->y); + + mo->angle = an; + mo->momx = finecosine[mo->angle >> ANGLETOFINESHIFT] * mo->info->speed; + mo->momy = finesine[mo->angle >> ANGLETOFINESHIFT] * mo->info->speed; + + mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_PROJ_RECTFIRE); + mo->target = actor; + mo->angle = an - ANG45; + mo->momx = finecosine[mo->angle >> ANGLETOFINESHIFT] * mo->info->speed; + mo->momy = finesine[mo->angle >> ANGLETOFINESHIFT] * mo->info->speed; + + mo = P_SpawnMobj(actor->x, actor->y, actor->z, MT_PROJ_RECTFIRE); + mo->target = actor; + mo->angle = an + ANG45; + mo->momx = finecosine[mo->angle >> ANGLETOFINESHIFT] * mo->info->speed; + mo->momy = finesine[mo->angle >> ANGLETOFINESHIFT] * mo->info->speed; + + S_StartSound(mo, mo->info->seesound); +} + +/* +============== += += A_RectMissile += +============== +*/ + +void A_RectMissile(mobj_t* actor) // 80012B1C +{ + mobj_t* mo; + int count; + angle_t an; + fixed_t x; + fixed_t y; + fixed_t speed; + + if(!actor->target) + return; + + A_FaceTarget(actor); + for(mo = mobjhead.next; mo != &mobjhead; mo = mo->next) + { + // not a rect projectile + if(mo->type == MT_PROJ_RECT) + { + if((++count >= 9)) + return; + } + } + + // Arm 1 + + an = (actor->angle/*-ANG90*/) >> ANGLETOFINESHIFT; + x = (finesine[an] * 68); + y = (finecosine[an] * 68); + mo = P_SpawnMobj(actor->x + x, actor->y - y, actor->z + (68*FRACUNIT), MT_PROJ_RECT); + mo->target = actor; + mo->tracer = actor->target; + mo->threshold = 5; + an = (actor->angle + ANG270); + mo->angle = an; + an >>= ANGLETOFINESHIFT; + speed = mo->info->speed >> 1; + if(!(speed >= 0)) + { + speed = (mo->info->speed + 1) >> 1; + } + mo->momx = (finecosine[an] * speed); + mo->momy = (finesine[an] * speed); + + // Arm2 + + an = (actor->angle/*-ANG90*/) >> ANGLETOFINESHIFT; + x = (finesine[an] * 50); + y = (finecosine[an] * 50); + mo = P_SpawnMobj(actor->x + x, actor->y - y, actor->z + (139*FRACUNIT), MT_PROJ_RECT); + mo->target = actor; + mo->tracer = actor->target; + mo->threshold = 1; + an = (actor->angle + ANG270); + mo->angle = an; + an >>= ANGLETOFINESHIFT; + speed = mo->info->speed >> 1; + if(!(speed >= 0)) + { + speed = (mo->info->speed + 1) >> 1; + } + mo->momx = (finecosine[an] * speed); + mo->momy = (finesine[an] * speed); + + // Arm3 + + an = (actor->angle/*+ANG90*/) >> ANGLETOFINESHIFT; + x = (finesine[an] * 68); + y = (finecosine[an] * 68); + mo = P_SpawnMobj(actor->x - x, actor->y + y, actor->z + (68*FRACUNIT), MT_PROJ_RECT); + mo->target = actor; + mo->tracer = actor->target; + mo->threshold = 5; + an = (actor->angle - ANG270); + mo->angle = an; + an >>= ANGLETOFINESHIFT; + speed = mo->info->speed >> 1; + if(!(speed >= 0)) + { + speed = (mo->info->speed + 1) >> 1; + } + mo->momx = (finecosine[an] * speed); + mo->momy = (finesine[an] * speed); + + // Arm4 + + an = (actor->angle/*+ANG90*/) >> ANGLETOFINESHIFT; + x = (finesine[an] * 50); + y = (finecosine[an] * 50); + mo = P_SpawnMobj(actor->x - x, actor->y + y, actor->z + (139*FRACUNIT), MT_PROJ_RECT); + mo->target = actor; + mo->tracer = actor->target; + mo->threshold = 1; + an = (actor->angle - ANG270); + mo->angle = an; + an >>= ANGLETOFINESHIFT; + speed = mo->info->speed >> 1; + if(!(speed >= 0)) + { + speed = (mo->info->speed + 1) >> 1; + } + mo->momx = (finecosine[an] * speed); + mo->momy = (finesine[an] * speed); +} + +/* +============== += += A_MoveGroundFire += +============== +*/ + +void A_MoveGroundFire(mobj_t* fire) // 80012EA4 +{ + mobj_t* mo; + fade_t *fade; + + mo = P_SpawnMobj(fire->x, fire->y, fire->floorz, MT_PROP_FIRE); + + //P_FadeMobj(mo, -8, 0, mobjflag_t::MF_NONE); + fade = Z_Malloc (sizeof(*fade), PU_LEVSPEC, 0); + P_AddThinker (&fade->thinker); + fade->thinker.function = T_FadeThinker; + fade->amount = -8; + fade->destAlpha = 0; + fade->flagReserve = 0; + fade->mobj = mo; +} + +/* +============== += += A_RectTracer += +============== +*/ + +void A_RectTracer(mobj_t* actor) // 80012F34 +{ + if(actor->threshold < 0) + A_Tracer(actor); + else + actor->threshold--; +} + + +/* +============== += += A_RectDeathEvent += +============== +*/ + +void A_RectDeathEvent(mobj_t* actor) // 80012F6C +{ + mobjexp_t *exp; + + //P_BossExplode(actor, 3, 32); + exp = Z_Malloc (sizeof(*exp), PU_LEVSPEC, 0); + P_AddThinker (&exp->thinker); + exp->thinker.function = T_MobjExplode; + exp->mobj = actor; + exp->delay = 0; + exp->delaydefault = 3; + exp->lifetime = 32; + S_StartSound(NULL, actor->info->deathsound); +} + + +/* +================== += += A_TargetCamera += +================== +*/ + +void A_TargetCamera(mobj_t* actor) // 80012FEC +{ + mobj_t* mo; + + actor->threshold = MAXINT; + + for(mo = mobjhead.next; mo != &mobjhead; mo = mo->next) + { + if(actor->tid+1 == mo->tid) + { + actor->target = mo; + P_SetMobjState(actor, actor->info->missilestate); + return; + } + } +} + +/* +================== += += A_BarrelExplode += +================== +*/ + +void A_BarrelExplode(mobj_t* actor) // 80013070 +{ + + S_StartSound(actor, actor->info->deathsound); + P_SpawnMobj(actor->x, actor->y, actor->z + (actor->info->height >> 1), MT_EXPLOSION1); + P_RadiusAttack(actor, actor->target, 128);//A_Explode(actor); + + A_OnDeathTrigger(actor); +} + + +/* +================ += += A_Hoof += +================ +*/ + +void A_Hoof (mobj_t *mo) // 800130E0 +{ + S_StartSound(mo, sfx_cybhoof); + A_Chase(mo); +} + +/* +================ += += A_Metal += +================ +*/ + +void A_Metal (mobj_t *mo) // 80013110 +{ + S_StartSound(mo, sfx_metal); + A_Chase(mo); +} + +/* +================ += += A_BabyMetal += +================ +*/ + +void A_BabyMetal(mobj_t* mo) // 80013140 +{ + S_StartSound(mo, sfx_bspistomp); + A_Chase(mo); +} + +/*============================================================================= */ + +/* a move in p_base.c crossed a special line */ +#if 0 +void L_CrossSpecial (mobj_t *mo) +{ + line_t *line; + + line = (line_t *)(mo->extradata & ~1); + + P_CrossSpecialLine (line, mo); +} +#endif + +/* +================ += += L_MissileHit += +================ +*/ + +/* a move in p_base.c caused a missile to hit another thing or wall */ +void L_MissileHit (mobj_t *mo) // 80013170 +{ + int damage; + mobj_t *missilething; + + missilething = (mobj_t *)mo->extradata; + damage = 0; + + if (missilething) + { + damage = ((P_Random()&7)+1)*mo->info->damage; + P_DamageMobj (missilething, mo, mo->target, damage); + + if ((mo->type == MT_PROJ_RECTFIRE) && (missilething->player)) + { + missilething->momz = (1500*FRACUNIT) / missilething->info->mass; + } + } + + if (mo->type == MT_PROJ_DART) + { + if (missilething && !(missilething->flags & MF_NOBLOOD)) + { + P_SpawnBlood(mo->x, mo->y, mo->z, damage); + } + else + { + S_StartSound(mo, sfx_darthit); + P_SpawnPuff(mo->x, mo->y, mo->z); + } + } + P_ExplodeMissile (mo); +} + +/* +================ += += L_SkullBash += +================ +*/ + +/* a move in p_base.c caused a flying skull to hit another thing or a wall */ +void L_SkullBash (mobj_t *mo) // 800132AC +{ + int damage; + mobj_t *skullthing; + + skullthing = (mobj_t *)mo->extradata; + + if (skullthing) + { + damage = ((P_Random()&7)+1)*mo->info->damage; + P_DamageMobj (skullthing, mo, mo, damage); + } + + mo->flags &= ~MF_SKULLFLY; + mo->momx = mo->momy = mo->momz = 0; + P_SetMobjState (mo, mo->info->spawnstate); +} + +/* +================== += += A_FadeAlpha += +================== +*/ + +void A_FadeAlpha(mobj_t *mobj) // 8001333C +{ + int fade; + + fade = mobj->alpha * 3; + if(!(fade >= 0)) + { + fade = fade + 3; + } + + mobj->alpha = (fade >> 2); +} + +/* +================== += += A_PainDeathEvent += +================== +*/ + +void A_PainDeathEvent(mobj_t* actor) // 80013364 +{ + actor->alpha -= 0x40; +} + +/* +================== += += A_SkullSetAlpha += +================== +*/ + +void A_SkullSetAlpha(mobj_t* actor) // 80013378 +{ + actor->alpha >>= 2; +} + +/* +================== += += A_MissileSetAlpha += +================== +*/ + +void A_MissileSetAlpha(mobj_t* actor) // 8001338C +{ + actor->alpha >>= 1; +} + + +/* +================== += += A_FadeOut += +================== +*/ + +void A_FadeOut(mobj_t* actor) // 800133A0 +{ + fade_t *fade; + + if (actor->alpha >= 0xff) + { + actor->flags |= MF_SHADOW; + //P_FadeMobj(actor, -8, 0x30, mobjflag_t::MF_NONE); + fade = Z_Malloc (sizeof(*fade), PU_LEVSPEC, 0); + P_AddThinker (&fade->thinker); + fade->thinker.function = T_FadeThinker; + fade->amount = -8; + fade->destAlpha = 0x30; + fade->flagReserve = 0; + fade->mobj = actor; + } +} + + +/* +================== += += A_FadeIn += +================== +*/ + +void A_FadeIn(mobj_t* actor) // 80013428 +{ + fade_t *fade; + + if (actor->alpha < 0xff) + { + actor->alpha = 0x30; + actor->flags &= ~MF_SHADOW; + + //P_FadeMobj(actor, 8, 0xff, mobjflag_t::MF_NONE); + fade = Z_Malloc (sizeof(*fade), PU_LEVSPEC, 0); + P_AddThinker (&fade->thinker); + fade->thinker.function = T_FadeThinker; + fade->mobj = actor; + fade->amount = 8; + fade->destAlpha = 0xff; + fade->flagReserve = 0; + } +} + + +/* +================ += +P_MissileAttack += +================ +*/ + +mobj_t* P_MissileAttack(mobj_t *actor, dirproj_e direction) // 800134BC +{ + angle_t angle; + fixed_t deltax, deltay, deltaz; + fixed_t x, y; + mobjtype_t type; + mobj_t *mo; + + if(direction == DP_LEFT) + { + angle = actor->angle + ANG45; + } + else if(direction == DP_RIGHT) + { + angle = actor->angle - ANG45; + } + else + { + angle = actor->angle; + } + + angle >>= ANGLETOFINESHIFT; + x = finecosine[angle]; + y = finesine[angle]; + + switch(actor->type) + { + case MT_MANCUBUS: + deltay = (y * 50); + deltax = (x * 50); + deltaz = (69*FRACUNIT); + type = MT_PROJ_FATSO; + break; + case MT_IMP1: + deltay = 0; + deltax = 0; + deltaz = (64*FRACUNIT); + type = MT_PROJ_IMP1; + break; + case MT_IMP2: + deltay = 0; + deltax = 0; + deltaz = (64*FRACUNIT); + type = MT_PROJ_IMP2; + break; + case MT_CACODEMON: + deltay = 0; + deltax = 0; + deltaz = (46*FRACUNIT); + type = MT_PROJ_HEAD; + break; + case MT_BRUISER1: + deltay = 0; + deltax = 0; + deltaz = (48*FRACUNIT); + type = MT_PROJ_BRUISER2; + break; + case MT_BRUISER2: + deltay = 0; + deltax = 0; + deltaz = (48*FRACUNIT); + type = MT_PROJ_BRUISER1; + break; + case MT_BABY: + deltay = (y * 20); + deltax = (x * 20); + deltaz = (28*FRACUNIT); + type = MT_PROJ_BABY; + break; + case MT_CYBORG: + case MT_CYBORG_TITLE: + deltay = (y * 45); + deltax = (x * 45); + deltaz = (88*FRACUNIT); + type = MT_PROJ_ROCKET; + break; + + default: + break; + } + + mo = P_SpawnMissile(actor, actor->target, deltax, deltay, deltaz, type); + return mo; +} diff --git a/Doom 64/p_floor.c b/Doom 64/p_floor.c @@ -0,0 +1,580 @@ +#include "doomdef.h" +#include "p_local.h" + +/*================================================================== */ +/*================================================================== */ +/* */ +/* FLOORS */ +/* */ +/*================================================================== */ +/*================================================================== */ + + + +/*================================================================== */ +/* */ +/* Move a plane (floor or ceiling) and check for crushing */ +/* */ +/*================================================================== */ +result_e T_MovePlane(sector_t *sector,fixed_t speed, + fixed_t dest,boolean crush,int floorOrCeiling,int direction) // 800136C0 +{ + boolean flag; + fixed_t lastpos; + result_e result; + + result = ok; + + switch(floorOrCeiling) + { + case 0: /* FLOOR */ + switch(direction) + { + case -1: /* DOWN */ + lastpos = sector->floorheight; + sector->floorheight -= speed; + if (sector->floorheight <= dest) + { + sector->floorheight = dest; + result = pastdest; + } + + flag = P_ChangeSector(sector,crush); + if (flag != 0) + { + sector->floorheight = lastpos; + P_ChangeSector(sector,crush); + if (!crush) + result = stop; + else + result = crushed; + } + break; + + case 1: /* UP */ + lastpos = sector->floorheight; + sector->floorheight += speed; + if (dest <= sector->floorheight) + { + sector->floorheight = dest; + result = pastdest; + } + + flag = P_ChangeSector(sector,crush); + if (flag != 0) + { + sector->floorheight = lastpos; + P_ChangeSector(sector,crush); + if(!crush) + result = stop; + else + result = crushed; + } + break; + } + break; + + case 1: /* CEILING */ + switch(direction) + { + case -1: /* DOWN */ + + lastpos = sector->ceilingheight; + sector->ceilingheight -= speed; + if (sector->ceilingheight <= dest) + { + sector->ceilingheight = dest; + result = pastdest; + } + + flag = P_ChangeSector(sector,crush); + if (flag != 0) + { + if(crush == true && result == ok) + { + result = crushed; + } + else + { + sector->ceilingheight = lastpos; + P_ChangeSector(sector,crush); + if (result == ok) + result = crushed; + } + } + break; + + case 1: /* UP */ + + lastpos = sector->ceilingheight; + sector->ceilingheight += speed; + if (dest <= sector->ceilingheight) + { + sector->ceilingheight = dest; + result = pastdest; + } + + flag = P_ChangeSector(sector,false); + if ((flag != 0) && (result != 0)) + { + sector->ceilingheight = lastpos; + P_ChangeSector(sector,false); + } + break; + } + break; + + } + + return result; +} + +/*================================================================== */ +/* */ +/* MOVE A FLOOR TO IT'S DESTINATION (UP OR DOWN) */ +/* */ +/*================================================================== */ +void T_MoveFloor(floormove_t *floor) // 80013920 +{ + result_e res; + + res = T_MovePlane(floor->sector,floor->speed, + floor->floordestheight,floor->crush,0,floor->direction); + + if (!floor->instant) + { + if (!(gametic&3)) + { + S_StartSound((mobj_t *)&floor->sector->soundorg,sfx_secmove);//sfx_stnmov + } + } + + if (res == pastdest) + { + floor->sector->specialdata = NULL; + if (floor->direction == -1) + { + switch(floor->type) + { + case lowerAndChange: + floor->sector->special = floor->newspecial; + floor->sector->floorpic = floor->texture; + default: + break; + } + } + P_RemoveThinker(&floor->thinker); + } + +} + +/*================================================================== */ +/* */ +/* HANDLE FLOOR TYPES */ +/* */ +/*================================================================== */ +int EV_DoFloor(line_t *line,floor_e floortype,fixed_t speed) // 800139FC +{ + int secnum; + int rtn; + int i; + sector_t *sec; + floormove_t *floor; + + secnum = -1; + rtn = 0; + while ((secnum = P_FindSectorFromLineTag(line->tag,secnum)) >= 0) + { + sec = &sectors[secnum]; + + /* ALREADY MOVING? IF SO, KEEP GOING... */ + if (sec->specialdata) + continue; + + /* */ + /* new floor thinker */ + /* */ + rtn = 1; + floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); + P_AddThinker (&floor->thinker); + sec->specialdata = floor; + floor->thinker.function = T_MoveFloor; + floor->type = floortype; + floor->crush = false; + floor->sector = sec; + + if (speed == (4096 * FRACUNIT)) + floor->instant = true; + else + floor->instant = false; + + switch(floortype) + { + case lowerFloor: + floor->direction = -1; + floor->speed = speed; + floor->floordestheight = P_FindHighestFloorSurrounding(sec); + break; + case lowerFloorToLowest: + floor->direction = -1; + floor->speed = speed; + floor->floordestheight = P_FindLowestFloorSurrounding(sec); + break; + case turboLower: + floor->direction = -1; + floor->speed = speed; + floor->floordestheight = P_FindHighestFloorSurrounding(sec); + if (floor->floordestheight != sec->floorheight) + floor->floordestheight += 8 * FRACUNIT; + break; + case raiseFloorCrush: + floor->crush = true; + case raiseFloor: + floor->direction = 1; + floor->speed = speed; + floor->floordestheight = P_FindLowestCeilingSurrounding(sec); + if (floor->floordestheight > sec->ceilingheight) + floor->floordestheight = sec->ceilingheight; + + if (floortype == raiseFloorCrush) + floor->floordestheight -= (8 * FRACUNIT); + break; + case raiseFloorToNearest: + floor->direction = 1; + floor->speed = speed; + floor->floordestheight = P_FindNextHighestFloor(sec,sec->floorheight); + break; + case raiseFloor24: + floor->direction = 1; + floor->speed = speed; + floor->floordestheight = floor->sector->floorheight + 24 * FRACUNIT; + break; + case raiseFloor24AndChange: + floor->direction = 1; + floor->speed = speed; + floor->floordestheight = floor->sector->floorheight + 24 * FRACUNIT; + sec->floorpic = line->frontsector->floorpic; + sec->special = line->frontsector->special; + break; + case customFloor: + floor->direction = (macrointeger > 0) ? 1 : -1; + floor->speed = speed; + floor->floordestheight = floor->sector->floorheight + (macrointeger * FRACUNIT); + break; + case customFloorToHeight: + floor->direction = ((macrointeger*FRACUNIT) > (floor->sector->floorheight)) ? 1 : -1; + floor->speed = speed; + floor->floordestheight = (macrointeger * FRACUNIT); + break; +#if 0 //Missing on D64 + case raiseToTexture: + { + int minsize = MAXINT; + side_t *side; + + floor->direction = 1; + floor->speed = speed; + for (i = 0; i < sec->linecount; i++) + { + if (twoSided (secnum, i) ) + { + side = getSide(secnum,i,0); + if (side->bottomtexture >= 0) + { + if ((textures[side->bottomtexture].h << FRACBITS) < minsize) + minsize = (textures[side->bottomtexture].h << FRACBITS); + } + side = getSide(secnum,i,1); + if (side->bottomtexture >= 0) + { + if ((textures[side->bottomtexture].h << FRACBITS) < minsize) + minsize = (textures[side->bottomtexture].h << FRACBITS); + } + } + } + floor->floordestheight = floor->sector->floorheight + minsize; + } + break; +#endif // 0 + case lowerAndChange: + floor->direction = -1; + floor->speed = speed; + floor->floordestheight = P_FindLowestFloorSurrounding(sec); + floor->texture = sec->floorpic; + for (i = 0; i < sec->linecount; i++) + { + if ( twoSided(secnum, i) ) + { + if (getSide(secnum,i,0)->sector-sectors == secnum) + { + sec = getSector(secnum,i,1); + floor->texture = sec->floorpic; + floor->newspecial = sec->special; + break; + } + else + { + sec = getSector(secnum,i,0); + floor->texture = sec->floorpic; + floor->newspecial = sec->special; + break; + } + } + } + default: + break; + } + } + return rtn; +} + +/*================================================================== */ +/* */ +/* BUILD A STAIRCASE! */ +/* */ +/*================================================================== */ +int EV_BuildStairs(line_t *line, stair_e type) // 80013DB0 +{ + int secnum; + int height; + int i; + int newsecnum; + int texture; + int ok; + int rtn; + fixed_t stairsize; + fixed_t speed; + sector_t *sec, *tsec; + floormove_t *floor; + + + secnum = -1; + rtn = 0; + while ((secnum = P_FindSectorFromLineTag(line->tag,secnum)) >= 0) + { + sec = &sectors[secnum]; + + /* ALREADY MOVING? IF SO, KEEP GOING... */ + if (sec->specialdata) + continue; + + /* */ + /* new floor thinker */ + /* */ + rtn = 1; + floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); + P_AddThinker (&floor->thinker); + sec->specialdata = floor; + floor->thinker.function = T_MoveFloor; + floor->direction = 1; + floor->sector = sec; + floor->instant = false; + + switch (type) + { + case build8: + speed = FLOORSPEED / 2; + stairsize = 8 * FRACUNIT; + break; + case turbo16: + speed = FLOORSPEED * 2; + stairsize = 16 * FRACUNIT; + break; + } + + floor->speed = speed; + height = sec->floorheight + stairsize; + floor->floordestheight = height; + + texture = sec->floorpic; + + /* */ + /* Find next sector to raise */ + /* 1. Find 2-sided line with same sector side[0] */ + /* 2. Other side is the next sector to raise */ + /* */ + do + { + ok = 0; + for (i = 0;i < sec->linecount;i++) + { + if ( !((sec->lines[i])->flags & ML_TWOSIDED) ) + continue; + + tsec = (sec->lines[i])->frontsector; + newsecnum = tsec-sectors; + if (secnum != newsecnum) + continue; + + tsec = (sec->lines[i])->backsector; + newsecnum = tsec - sectors; + if (tsec->floorpic != texture) + continue; + + height += stairsize; + if (tsec->specialdata) + continue; + + sec = tsec; + secnum = newsecnum; + floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); + P_AddThinker (&floor->thinker); + sec->specialdata = floor; + floor->thinker.function = T_MoveFloor; + floor->direction = 1; + floor->sector = sec; + floor->speed = speed; + floor->floordestheight = height; + floor->instant = false; + ok = 1; + break; + } + } while(ok); + } + return rtn; +} + +/*================================================================== */ +/* */ +/* T_MoveSplitPlane */ +/* */ +/*================================================================== */ + +void T_MoveSplitPlane(splitmove_t *split) // 80014098 +{ + sector_t *sector; + fixed_t lastceilpos; + fixed_t lastflrpos; + boolean cdone; + boolean fdone; + + sector = split->sector; + lastceilpos = sector->ceilingheight; + lastflrpos = sector->floorheight; + cdone = false; + fdone = false; + + if (split->ceildir == -1) + { + sector->ceilingheight -= (2*FRACUNIT); + if (sector->ceilingheight <= split->ceildest) + { + sector->ceilingheight = split->ceildest; + cdone = true; + } + } + else if (split->ceildir == 1) + { + sector->ceilingheight += (2*FRACUNIT); + if(sector->ceilingheight >= split->ceildest) + { + sector->ceilingheight = split->ceildest; + cdone = true; + } + } + + if (split->flrdir == -1) + { + sector->floorheight -= (2*FRACUNIT); + if(sector->floorheight <= split->flrdest) + { + sector->floorheight = split->flrdest; + fdone = true; + } + } + else if (split->flrdir == 1) + { + sector->floorheight += (2*FRACUNIT); + if(sector->floorheight >= split->flrdest) + { + sector->floorheight = split->flrdest; + fdone = true; + } + } + + if(!P_ChangeSector(sector, false)) + { + if(!cdone || !fdone) + return; + + P_RemoveThinker(&split->thinker); + split->sector->specialdata = NULL; + } + else + { + sector->floorheight = lastflrpos; + sector->ceilingheight = lastceilpos; + P_ChangeSector(sector,false); + } +} + +/*================================================================== */ +/* */ +/* EV_SplitSector */ +/* */ +/*================================================================== */ + +int EV_SplitSector(line_t *line, boolean sync) // 80014234 +{ + int secnum; + int rtn; + sector_t *sec; + splitmove_t *split; + + secnum = -1; + rtn = 0; + + while((secnum = P_FindSectorFromLineTag(line->tag, secnum)) >= 0) + { + sec = &sectors[secnum]; + + /* ALREADY MOVING? IF SO, KEEP GOING... */ + if (sec->specialdata) + continue; + + /* */ + /* new split thinker */ + /* */ + rtn = 1; + split = Z_Malloc (sizeof(*split), PU_LEVSPEC, 0); + P_AddThinker (&split->thinker); + sec->specialdata = split; + split->thinker.function = T_MoveSplitPlane; + split->sector = sec; + + split->ceildest = sec->ceilingheight + (macrointeger * FRACUNIT); + + if(sync) + { + split->flrdest = sec->floorheight + (macrointeger * FRACUNIT); + + if (macrointeger >= 0) + { + split->ceildir = 1; + split->flrdir = 1; + } + else + { + split->ceildir = -1; + split->flrdir = -1; + } + } + else + { + split->flrdest = sec->floorheight - (macrointeger * FRACUNIT); + + if (macrointeger >= 0) + { + split->ceildir = 1; + split->flrdir = -1; + } + else + { + split->ceildir = -1; + split->flrdir = 1; + } + } + } + + return rtn; +} diff --git a/Doom 64/p_inter.c b/Doom 64/p_inter.c @@ -0,0 +1,839 @@ +/* P_inter.c */ + + +#include "doomdef.h" +#include "p_local.h" +#include "st_main.h" + +#define BONUSADD 4 + +/* a weapon is found with two clip loads, a big item has five clip loads */ +int maxammo[NUMAMMO] = {200, 50, 300, 50}; // 8005AD40 +int clipammo[NUMAMMO] = {10, 4, 20, 1}; // 8005AD50 + +/* +=============================================================================== + + GET STUFF + +=============================================================================== +*/ + +/* +=================== += += P_GiveAmmo += += Num is the number of clip loads, not the individual count (0= 1/2 clip) += Returns false if the ammo can't be picked up at all +=================== +*/ + +boolean P_GiveAmmo (player_t *player, ammotype_t ammo, int num) // 800143E0 +{ + int oldammo; + + if (ammo == am_noammo) + return false; + + if (ammo > NUMAMMO) + I_Error ("P_GiveAmmo: bad type %i", ammo); + + if ( player->ammo[ammo] == player->maxammo[ammo] ) + return false; + + if (num) + num *= clipammo[ammo]; + else + { + //num = clipammo[ammo]/2; + num = clipammo[ammo]; + if(!(num >= 0)) + { + num = num + 1; + } + + num = num/2; + } + + if (gameskill == sk_baby) + num <<= 1; /* give double ammo in trainer mode */ + + oldammo = player->ammo[ammo]; + player->ammo[ammo] += num; + if (player->ammo[ammo] > player->maxammo[ammo]) + player->ammo[ammo] = player->maxammo[ammo]; + + if (oldammo) + return true; /* don't change up weapons, player was lower on */ + /* purpose */ + + switch (ammo) + { + case am_clip: + if (player->readyweapon == wp_fist) + { + if (player->weaponowned[wp_chaingun]) + player->pendingweapon = wp_chaingun; + else + player->pendingweapon = wp_pistol; + } + break; + case am_shell: + if (player->readyweapon == wp_fist || player->readyweapon == wp_pistol) + { + if (player->weaponowned[wp_shotgun]) + player->pendingweapon = wp_shotgun; + } + break; + case am_cell: + if (player->readyweapon == wp_fist || player->readyweapon == wp_pistol) + { + if (player->weaponowned[wp_plasma]) + player->pendingweapon = wp_plasma; + } + break; + case am_misl: + if (player->readyweapon == wp_fist) + { + if (player->weaponowned[wp_missile]) + player->pendingweapon = wp_missile; + } + default: + break; + } + + return true; +} + + +/* +=================== += += P_GiveWeapon += += The weapon name may have a MF_DROPPED flag ored in +=================== +*/ + +boolean P_GiveWeapon (player_t *player, weapontype_t weapon, boolean dropped) // 800145C0 +{ + boolean gaveammo, gaveweapon; + + if (weaponinfo[weapon].ammo != am_noammo) + { /* give one clip with a dropped weapon, two clips with a found weapon */ + if (dropped) + gaveammo = P_GiveAmmo (player, weaponinfo[weapon].ammo, 1); + else + gaveammo = P_GiveAmmo (player, weaponinfo[weapon].ammo, 2); + } + else + gaveammo = false; + + if (player->weaponowned[weapon]) + gaveweapon = false; + else + { + gaveweapon = true; + player->weaponowned[weapon] = true; + player->pendingweapon = weapon; + } + + return gaveweapon || gaveammo; +} + + + +/* +=================== += += P_GiveBody += += Returns false if the body isn't needed at all +=================== +*/ + +boolean P_GiveBody (player_t *player, int num) // 80014680 +{ + if (player->health >= MAXHEALTH) + return false; + + player->health += num; + if (player->health > MAXHEALTH) + player->health = MAXHEALTH; + player->mo->health = player->health; + + return true; +} + + +/* +=================== += += P_GiveArmor += += Returns false if the armor is worse than the current armor +=================== +*/ + +boolean P_GiveArmor (player_t *player, int armortype) // 800146C8 +{ + int hits; + + hits = armortype*100; + if (player->armorpoints >= hits) + return false; /* don't pick up */ + + player->armortype = armortype; + player->armorpoints = hits; + + return true; +} + + +/* +=================== += += P_GiveCard += +=================== +*/ + +void P_GiveCard (player_t *player, card_t card) // 80014704 +{ + if (player->cards[card]) + return; + player->bonuscount = BONUSADD; + player->cards[card] = true; +} + + +/* +=================== += += P_GivePower += +=================== +*/ + +boolean P_GivePower (player_t *player, powertype_t power) // 8001472C +{ + switch (power) + { + case pw_invulnerability: + player->powers[power] = INVULNTICS; + return true; + case pw_invisibility: + player->powers[power] = INVISTICS; + player->mo->flags |= MF_SHADOW; + return true; + case pw_infrared: + player->powers[power] = INFRATICS; + infraredFactor = 300; + P_RefreshBrightness(); + return true; + case pw_ironfeet: + player->powers[power] = IRONTICS; + return true; + case pw_strength: + P_GiveBody(player, 100); + player->powers[power] = STRTICS; + return true; + default: + break; + } + //pw_allmap + if (player->powers[power]) + return false; /* already got it */ + + player->powers[power] = 1; + return true; +} + +/* +================== += += P_TouchSpecialThing += +================== +*/ + +int ArtifactLookupTable[8] = {0, 1, 1, 2, 1, 2, 2, 3}; // 8005AD60 + +void P_TouchSpecialThing (mobj_t *special, mobj_t *toucher) // 80014810 +{ + player_t *player; + int i; + fixed_t delta; + int sound; + char *message; + int artflag; + + delta = special->z - toucher->z; + if (delta > toucher->height || delta < -8*FRACUNIT) + return; /* out of reach */ + + sound = sfx_itemup; + player = toucher->player; + if (toucher->health <= 0) + return; /* can happen with a sliding player corpse */ + + message = NULL; + + switch (special->type) + { + + /* */ + /* bonus items */ + /* */ + case MT_ITEM_BONUSHEALTH: + player->health+=2; /* can go over 100% */ + if (player->health > 200) + player->health = 200; + player->mo->health = player->health; + message = "You pick up a health bonus."; + break; + case MT_ITEM_BONUSARMOR: + player->armorpoints+=2; /* can go over 100% */ + if (player->armorpoints > 200) + player->armorpoints = 200; + if (!player->armortype) + player->armortype = 1; + message = "You pick up an armor bonus."; + break; + case MT_ITEM_SOULSPHERE: + player->health += 100; + if (player->health > 200) + player->health = 200; + player->mo->health = player->health; + message = "Supercharge!"; + sound = sfx_powerup; + break; + case MT_ITEM_MEGASPHERE: + player->health = 200; + player->mo->health = 200; + P_GiveArmor(player, 2); + message = "Mega Sphere!"; + sound = sfx_powerup; + break; + + /* */ + /* ammo */ + /* */ + case MT_AMMO_CLIP: + if (special->flags & MF_DROPPED) + { + if (!P_GiveAmmo (player,am_clip,0)) + return; + } + else + { + if (!P_GiveAmmo (player,am_clip,1)) + return; + } + message = "Picked up a clip."; + break; + case MT_AMMO_CLIPBOX: + if (!P_GiveAmmo (player, am_clip,5)) + return; + message = "Picked up a box of bullets."; + break; + case MT_AMMO_ROCKET: + if (!P_GiveAmmo (player, am_misl,1)) + return; + message = "Picked up a rocket."; + break; + case MT_AMMO_ROCKETBOX: + if (!P_GiveAmmo (player, am_misl,5)) + return; + message = "Picked up a box of rockets."; + break; + case MT_AMMO_CELL: + if (!P_GiveAmmo (player, am_cell,1)) + return; + message = "Picked up an energy cell."; + break; + case MT_AMMO_CELLPACK: + if (!P_GiveAmmo (player, am_cell,5)) + return; + message = "Picked up an energy cell pack."; + break; + case MT_AMMO_SHELL: + if (!P_GiveAmmo (player, am_shell,1)) + return; + if (gameskill == sk_baby) + message = "Picked up 8 shotgun shells."; + else + message = "Picked up 4 shotgun shells."; + break; + case MT_AMMO_SHELLBOX: + if (!P_GiveAmmo (player, am_shell,5)) + return; + message = "Picked up a box of shotgun shells."; + break; + case MT_AMMO_BACKPACK: + if (!player->backpack) + { + for (i=0 ; i<NUMAMMO ; i++) + player->maxammo[i] *= 2; + player->backpack = true; + } + for (i=0 ; i<NUMAMMO ; i++) + P_GiveAmmo (player, i, 1); + message = "You got the backpack!"; + break; + + + /* */ + /* weapons */ + /* */ + case MT_WEAP_BFG: + if (!P_GiveWeapon (player, wp_bfg, false) ) + return; + message = "You got the BFG9000! Oh, yes."; + sound = sfx_sgcock; + break; + case MT_WEAP_CHAINGUN: + if (!P_GiveWeapon (player, wp_chaingun, special->flags&MF_DROPPED) ) + return; + message = "You got the chaingun!"; + sound = sfx_sgcock; + break; + case MT_WEAP_CHAINSAW: + if (!P_GiveWeapon (player, wp_chainsaw, false) ) + return; + message = "A chainsaw! Find some meat!"; + sound = sfx_sgcock; + break; + case MT_WEAP_LAUNCHER: + if (!P_GiveWeapon (player, wp_missile, false) ) + return; + message = "You got the rocket launcher!"; + sound = sfx_sgcock; + break; + case MT_WEAP_PLASMA: + if (!P_GiveWeapon (player, wp_plasma, false) ) + return; + message = "You got the plasma gun!"; + sound = sfx_sgcock; + break; + case MT_WEAP_SHOTGUN: + if (!P_GiveWeapon (player, wp_shotgun, special->flags&MF_DROPPED ) ) + return; + message = "You got the shotgun!"; + sound = sfx_sgcock; + break; + case MT_WEAP_SSHOTGUN: + if (!P_GiveWeapon(player, wp_supershotgun, special->flags&MF_DROPPED)) + return; + message = "You got the super shotgun!"; + sound = sfx_sgcock; + break; + case MT_WEAP_LCARBINE: + if (!P_GiveWeapon(player, wp_laser, false)) + return; + message = "What the !@#%* is this!"; + sound = sfx_sgcock; + break; + + /* */ + /* armor */ + /* */ + case MT_ITEM_ARMOR1: + if (!P_GiveArmor(player, 1)) + return; + message = "You pick up the armor."; + break; + + case MT_ITEM_ARMOR2: + if (!P_GiveArmor(player, 2)) + return; + message = "You got the MegaArmor!"; + break; + + /* */ + /* cards */ + /* leave cards for everyone */ + /* */ + case MT_ITEM_BLUECARDKEY: + if (!player->cards[it_bluecard]) + message = "You pick up a blue keycard."; + P_GiveCard(player, it_bluecard); + break; + case MT_ITEM_REDCARDKEY: + if (!player->cards[it_redcard]) + message = "You pick up a red keycard."; + P_GiveCard(player, it_redcard); + break; + case MT_ITEM_YELLOWCARDKEY: + if (!player->cards[it_yellowcard]) + message = "You pick up a yellow keycard."; + P_GiveCard(player, it_yellowcard); + break; + case MT_ITEM_BLUESKULLKEY: + if (!player->cards[it_blueskull]) + message = "You pick up a blue skull key."; + P_GiveCard(player, it_blueskull); + break; + case MT_ITEM_REDSKULLKEY: + if (!player->cards[it_redskull]) + message = "You pick up a red skull key."; + P_GiveCard(player, it_redskull); + break; + case MT_ITEM_YELLOWSKULLKEY: + if (!player->cards[it_yellowskull]) + message = "You pick up a yellow skull key."; + P_GiveCard(player, it_yellowskull); + break; + + /* */ + /* heals */ + /* */ + case MT_ITEM_STIMPACK: + if (!P_GiveBody(player, 10)) + return; + message = "You pick up a stimpack."; + break; + case MT_ITEM_MEDKIT: + if (!P_GiveBody(player, 25)) + return; + if (player->health < 25) + message = "You pick up a medikit that you REALLY need!"; + else + message = "You pick up a medikit."; + break; + + /* */ + /* power ups */ + /* */ + case MT_ITEM_INVULSPHERE: + P_GivePower(player, pw_invulnerability); + message = "Invulnerability!"; + sound = sfx_powerup; + break; + case MT_ITEM_BERSERK: + P_GivePower(player, pw_strength); + message = "Berserk!"; + if (player->readyweapon != wp_fist) + player->pendingweapon = wp_fist; + sound = sfx_powerup; + break; + case MT_ITEM_INVISSPHERE: + P_GivePower(player, pw_invisibility); + message = "Partial Invisibility!"; + sound = sfx_powerup; + break; + case MT_ITEM_RADSPHERE: + P_GivePower(player, pw_ironfeet); + message = "Radiation Shielding Suit"; + sound = sfx_powerup; + break; + case MT_ITEM_AUTOMAP: + if (!P_GivePower(player, pw_allmap)) + return; + message = "Computer Area Map"; + sound = sfx_powerup; + break; + case MT_ITEM_PVIS: + P_GivePower(player, pw_infrared); + message = "Light Amplification Goggles"; + sound = sfx_powerup; + break; + + /* */ + /* artifacts */ + /* */ + case MT_ITEM_ARTIFACT1: + case MT_ITEM_ARTIFACT2: + case MT_ITEM_ARTIFACT3: + + artflag = 1 << ((special->type + 7) & 0x1f); + + if ((player->artifacts & artflag)) + return; + + player->artifacts |= artflag; + + if (ArtifactLookupTable[player->artifacts] == 1) /* ART_FAST */ + message = "You have a feeling that\nit wasn't to be touched..."; + else if (ArtifactLookupTable[player->artifacts] == 2) /* ART_TRIPLE */ + message = "Whatever it is, it doesn't\nbelong in this world..."; + else /* ART_DOUBLE */ + message = "It must do something..."; + + sound = sfx_powerup; + break; + + /* */ + /* fake item */ + /* */ + case MT_FAKEITEM: + goto runtrigger; + break; + + default: + I_Error("P_SpecialThing: Unknown gettable thing"); // Restored + break; + } + + if (message) + { + player->message = message; + player->messagetic = MSGTICS; + } + + if (special->flags & MF_COUNTITEM) + player->itemcount++; + + if (special->flags & MF_COUNTSECRET) + player->secretcount++; + + P_RemoveMobj (special); + player->bonuscount += BONUSADD; + + if (player == &players[0]) + S_StartSound(NULL, sound); + + if(special->flags & MF_TRIGTOUCH) + { + runtrigger: + if(!P_ActivateLineByTag(special->tid, toucher)) + { + macroqueue[macroidx1].activator = toucher; + macroqueue[macroidx1].tag = special->tid; + macroidx1 = (macroidx1 + 1) & 3; + } + } +} + +/* +============== += += KillMobj += +============== +*/ +extern int deathmocktics; // 800A56A0 + +void P_KillMobj (mobj_t *source, mobj_t *target) // 80015080 +{ + mobjtype_t item; + mobj_t *mo; + boolean forceXdeath; + + target->flags &= ~(MF_SHOOTABLE|MF_FLOAT|MF_SKULLFLY); + + if (target->type != MT_SKULL) + target->flags |= MF_GRAVITY; + + target->flags |= MF_CORPSE|MF_DROPOFF; + target->height >>= 2; + + forceXdeath = false; //New PsxDoom / Doom64 + + if (target->player) + { /* a frag of one sort or another */ + if (!source || !source->player || source->player == target->player) + { /* killed self somehow */ + target->player->frags--; + //if (target->player->frags < 0) + //target->player->frags = 0; + } + else + { /* killed by other player */ + source->player->frags++; + } + + /* else just killed by a monster */ + } + else if (source && source->player && (target->flags & MF_COUNTKILL) ) + { /* a deliberate kill by a player */ + source->player->killcount++; /* count for intermission */ + } + else if ((target->flags & MF_COUNTKILL) ) + players[0].killcount++; /* count all monster deaths, even */ + /* those caused by other monsters */ + + if (target->player) + { + target->flags &= ~MF_SOLID; + target->player->playerstate = PST_DEAD; + P_DropWeapon (target->player); + if (target->health < -50) + { + forceXdeath = true; //Force the player to the state of Xdeath + + S_StartSound (target, sfx_slop); + } + else + S_StartSound (target, sfx_plrdie); + + deathmocktics = ticon; + } + + if (forceXdeath || (target->health < -target->info->spawnhealth) && target->info->xdeathstate) + P_SetMobjState (target, target->info->xdeathstate); + else + P_SetMobjState (target, target->info->deathstate); + + target->tics -= P_Random()&1; + if (target->tics < 1) + target->tics = 1; + + /* */ + /* drop stuff */ + /* */ + switch (target->type) + { + case MT_POSSESSED1: //MT_POSSESSED: + item = MT_AMMO_CLIP; //MT_CLIP; + break; + case MT_POSSESSED2: //MT_SHOTGUY: + item = MT_WEAP_SHOTGUN; //MT_SHOTGUN; + break; + /*case MT_CHAINGUY: + item = MT_WEAP_CHAINGUN; //MT_CHAINGUN; + break;*/ + default: + return; + } + + mo = P_SpawnMobj (target->x,target->y,ONFLOORZ, item); + mo->flags |= MF_DROPPED; /* special versions of items */ +} + + + +/* +================= += += P_DamageMobj += += Damages both enemies and players += inflictor is the thing that caused the damage += creature or missile, can be NULL (slime, etc) += source is the thing to target after taking damage += creature or NULL += Source and inflictor are the same for melee attacks += source can be null for barrel explosions and other environmental stuff +================== +*/ + +void P_DamageMobj (mobj_t *target, mobj_t *inflictor, mobj_t *source, int damage) // 800152DC +{ + unsigned ang, an; + int saved; + player_t *player; + fixed_t thrust; + + if (!(target->flags & MF_SHOOTABLE)) + return; /* shouldn't happen... */ + + if (target->health <= 0) + return; + + if (target->flags & MF_SKULLFLY) + { + target->momx = target->momy = target->momz = 0; + } + + player = target->player; + if (player && gameskill == sk_baby) + damage >>= 1; /* take half damage in trainer mode */ + + /* */ + /* kick away unless using the chainsaw */ + /* */ + if (inflictor && (!source || !source->player || source->player->readyweapon != wp_chainsaw)) + { + ang = R_PointToAngle2 (inflictor->x, inflictor->y, target->x, target->y); + + thrust = (damage * ((FRACUNIT >> 2) * 100)) / target->info->mass; + + /* make fall forwards sometimes */ + if ( (damage < 40) && (damage > target->health) && (target->z - inflictor->z > (64*FRACUNIT)) && (P_Random ()&1)) + { + ang += ANG180; + thrust *= 4; + } + + an = ang >> ANGLETOFINESHIFT; + thrust >>= 16; + target->momx += thrust * finecosine[an]; + target->momy += thrust * finesine[an]; + + // [psx/d64]: clamp thrust for players only + if (target->player) + { + if (target->momx > MAXMOVE) + target->momx = MAXMOVE; + else if (target->momx < -MAXMOVE) + target->momx = -MAXMOVE; + + if (target->momy > MAXMOVE) + target->momy = MAXMOVE; + else if (target->momy < -MAXMOVE) + target->momy = -MAXMOVE; + } + } + + /* */ + /* player specific */ + /* */ + if (player) + { + if ((player->cheats&CF_GODMODE) || player->powers[pw_invulnerability]) + return; + + if (player->armortype) + { + if (player->armortype == 1) + saved = damage/3; + else + saved = damage/2; + if (player->armorpoints <= saved) + { /* armor is used up */ + saved = player->armorpoints; + player->armortype = 0; + } + player->armorpoints -= saved; + damage -= saved; + } + S_StartSound (target,sfx_plrpain); + player->health -= damage; /* mirror mobj health here for Dave */ + if (player->health < 0) + player->health = 0; + player->attacker = source; + + player->damagecount += (damage/*>>1*/); /* add damage after armor / invuln */ + } + + /* */ + /* do the damage */ + /* */ + target->health -= damage; + if (target->health <= 0) + { + P_KillMobj (source, target); + return; + } + + if ( (P_Random () < target->info->painchance) && !(target->flags&MF_SKULLFLY) ) + { + target->flags |= MF_JUSTHIT; /* fight back! */ + if(target->info->painstate) + P_SetMobjState (target, target->info->painstate); + } + + target->reactiontime = 0; /* we're awake now... */ + if (!target->threshold && source && (source->flags & MF_SHOOTABLE) && !(target->flags & MF_NOINFIGHTING)) + { /* if not intent on another player, chase after this one */ + target->target = source; + target->threshold = BASETHRESHOLD; + if (target->state == &states[target->info->spawnstate] && target->info->seestate != S_000) + { + P_SetMobjState (target, target->info->seestate); + } + } +} + diff --git a/Doom 64/p_lights.c b/Doom 64/p_lights.c @@ -0,0 +1,668 @@ +#include "doomdef.h" +#include "p_local.h" + +/*================================================================== */ +/*================================================================== */ +/* */ +/* BROKEN LIGHT FLASHING */ +/* */ +/*================================================================== */ +/*================================================================== */ + +/*================================================================== */ +/* */ +/* T_FireFlicker */ +/* */ +/* Exclusive Psx Doom From PC Doom */ +/* */ +/*================================================================== */ + +void T_FireFlicker(fireflicker_t *flick) // 80015740 +{ + int amount; + + if (--flick->count) + return; + + if(flick->sector->special != flick->special) + { + P_RemoveThinker(&flick->thinker); + return; + } + + amount = (P_Random() & 31); + flick->sector->lightlevel = amount; + flick->count = 3; +} + +/*================================================================== */ +/* */ +/* P_SpawnFireFlicker */ +/* */ +/*================================================================== */ + +void P_SpawnFireFlicker(sector_t *sector) // 800157B4 +{ + fireflicker_t *flick; + + flick = Z_Malloc(sizeof(*flick), PU_LEVSPEC, 0); + P_AddThinker(&flick->thinker); + flick->thinker.function = T_FireFlicker; + flick->sector = sector; + flick->special = sector->special; + flick->count = 3; +} + +/*================================================================== */ +/* */ +/* Spawn glowing light */ +/* */ +/*================================================================== */ + +void T_Glow(glow_t *g) // 80015820 +{ + if(--g->count) + return; + + if(g->sector->special != g->special) + { + P_RemoveThinker(&g->thinker); + return; + } + + g->count = 2; + + switch(g->direction) + { + case -1: /* DOWN */ + g->sector->lightlevel -= GLOWSPEED; + if (g->sector->lightlevel < g->minlight) + { + g->sector->lightlevel = g->minlight; + + if(g->type == PULSERANDOM) + g->maxlight = (P_Random() & 31) + 17; + + g->direction = 1; + } + break; + case 1: /* UP */ + g->sector->lightlevel += GLOWSPEED; + if (g->maxlight < g->sector->lightlevel) + { + g->sector->lightlevel = g->maxlight; + + if(g->type == PULSERANDOM) + g->minlight = (P_Random() & 15); + + g->direction = -1; + } + break; + } +} + +/*================================================================== */ +/* */ +/* P_SpawnGlowingLight */ +/* */ +/*================================================================== */ + +void P_SpawnGlowingLight(sector_t *sector, glowtype_e type) // 80015968 +{ + glow_t *g; + + g = Z_Malloc(sizeof(*g), PU_LEVSPEC, 0); + P_AddThinker(&g->thinker); + g->thinker.function = T_Glow; + g->sector = sector; + g->count = 2; + g->direction = 1; + g->minlight = 0; + g->type = type; + g->special = sector->special; + + switch (type) + { + case PULSENORMAL: + g->maxlight = 32; + break; + case PULSESLOW: + case PULSERANDOM: + g->maxlight = 48; + break; + } +} + +/*================================================================== */ +/* */ +/* T_LightFlash */ +/* */ +/* After the map has been loaded, scan each sector for specials */ +/* that spawn thinkers */ +/* */ +/*================================================================== */ +void T_LightFlash (lightflash_t *flash) // 80015A14 +{ + if (--flash->count) + return; + + if(flash->sector->special != flash->special) + { + P_RemoveThinker(&flash->thinker); + return; + } + + if (flash->sector->lightlevel == 32) + { + flash->sector->lightlevel = 0; + flash->count = (P_Random()&7)+1; + } + else + { + flash->sector->lightlevel = 32; + flash->count = (P_Random()&32)+1; + } +} + +/*================================================================== */ +/* */ +/* P_SpawnLightFlash */ +/* */ +/* After the map has been loaded, scan each sector for specials that spawn thinkers */ +/* */ +/*================================================================== */ +void P_SpawnLightFlash (sector_t *sector) // 80015AB4 +{ + lightflash_t *flash; + + sector->special = 0; /* nothing special about it during gameplay */ + + flash = Z_Malloc ( sizeof(*flash), PU_LEVSPEC, 0); + P_AddThinker (&flash->thinker); + flash->thinker.function = T_LightFlash; + flash->sector = sector; + flash->special = sector->special; + flash->count = (P_Random()&63)+1; +} + +/*================================================================== */ +/* */ +/* STROBE LIGHT FLASHING */ +/* */ +/*================================================================== */ + +/*================================================================== */ +/* */ +/* T_StrobeFlash */ +/* */ +/* After the map has been loaded, scan each sector for specials that spawn thinkers */ +/* */ +/*================================================================== */ +void T_StrobeFlash (strobe_t *flash) // 80015B28 +{ + if (--flash->count) + return; + + if(flash->sector->special != flash->special) + { + P_RemoveThinker(&flash->thinker); + return; + } + + if (flash->sector->lightlevel == 0) + { + flash->sector->lightlevel = flash->maxlight; + flash->count = flash->brighttime; + } + else + { + flash->sector->lightlevel = 0; + flash->count = flash->darktime; + } +} + +/*================================================================== */ +/* */ +/* P_SpawnLightFlash */ +/* */ +/* After the map has been loaded, scan each sector for specials that spawn thinkers */ +/* */ +/*================================================================== */ + +void P_SpawnStrobeFlash (sector_t *sector,int fastOrSlow) // 80015BB4 +{ + strobe_t *flash; + + flash = Z_Malloc ( sizeof(*flash), PU_LEVSPEC, 0); + P_AddThinker (&flash->thinker); + flash->thinker.function = T_StrobeFlash; + flash->sector = sector; + flash->special = sector->special; + flash->brighttime = STROBEBRIGHT; + flash->maxlight = 16; + flash->darktime = fastOrSlow; + flash->count = (P_Random()&7)+1; +} + +/*================================================================== */ +/* */ +/* P_SpawnStrobeAltFlash */ +/* Alternate variation of P_SpawnStrobeFlash */ +/* */ +/*================================================================== */ +void P_SpawnStrobeAltFlash (sector_t *sector,int fastOrSlow) // 80015C44 +{ + strobe_t *flash; + + flash = Z_Malloc ( sizeof(*flash), PU_LEVSPEC, 0); + P_AddThinker (&flash->thinker); + flash->thinker.function = T_StrobeFlash; + flash->sector = sector; + flash->special = sector->special; + flash->brighttime = STROBEBRIGHT2; + flash->maxlight = 127; + flash->darktime = fastOrSlow; + flash->count = 1; +} + +/*================================================================== */ +/* */ +/* Start strobing lights (usually from a trigger) */ +/* */ +/*================================================================== */ +int EV_StartLightStrobing(line_t *line) // 80015CC4 +{ + int secnum; + sector_t *sec; + int ok; + + ok = 0; + secnum = -1; + while ((secnum = P_FindSectorFromLineTag(line->tag,secnum)) >= 0) + { + sec = &sectors[secnum]; + if (sec->specialdata) + continue; + + ok = 1; + P_SpawnStrobeFlash (sec,SLOWDARK); + } + + return ok; +} + +/*================================================================== */ +/* */ +/* SPECIALS FUNCTIONS */ +/* */ +/*================================================================== */ + +/*================================================================== */ +/* */ +/* Changes a sector light index */ +/* This doesn't appear to be used at all */ +/* */ +/*================================================================== */ +int P_ModifySectorColor(line_t* line, int index, int type) // 80015D6C +{ + int secnum; + int rtn; + sector_t* sec; + + secnum = -1; + rtn = 0; + + while((secnum = P_FindSectorFromLineTag(line->tag, secnum)) >= 0) + { + sec = &sectors[secnum]; + rtn = 1; + + switch(type) + { + case 0: + sec->colors[1] = index; + break; + case 1: + sec->colors[0] = index; + break; + case 2: + sec->colors[2] = index; + break; + case 3: + sec->colors[3] = index; + break; + case 4: + sec->colors[4] = index; + break; + } + } + + return rtn; +} + +/*================================================================== */ +/* */ +/* T_SequenceGlow */ +/* */ +/*================================================================== */ +void T_SequenceGlow(sequenceglow_t *seq) // 80015E5C +{ + sector_t *next; + int i; + + if(--seq->count) + return; + + if(seq->sector->special != seq->special) + { + P_RemoveThinker(&seq->thinker); + return; + } + + seq->count = 1; + + switch(seq->start) + { + case -1: /* DOWN */ + seq->sector->lightlevel -= GLOWSPEED; + + if(seq->sector->lightlevel > 0) + return; + + seq->sector->lightlevel = 0; + + if (seq->headsector == NULL) + { + seq->sector->special = 0; + P_RemoveThinker(&seq->thinker); + return; + } + + seq->start = 0; + break; + case 0: /* CHECK */ + if(!seq->headsector->lightlevel) + return; + + seq->start = 1; + break; + case 1: /* UP */ + seq->sector->lightlevel += GLOWSPEED; + if (seq->sector->lightlevel < (SEQUENCELIGHTMAX + 1)) + { + if(seq->sector->lightlevel != 8) + return; + + if(seq->sector->linecount <= 0) + return; + + for(i = 0; i < seq->sector->linecount; i++) + { + next = seq->sector->lines[i]->backsector; + + if(next && (next->special == 0)) + { + if(next->tag == (seq->sector->tag + 1)) + { + next->special = seq->sector->special; + P_SpawnSequenceLight(next, false); + } + } + } + } + else + { + seq->sector->lightlevel = SEQUENCELIGHTMAX; + seq->start = -1; + } + break; + } +} + +/*================================================================== */ +/* */ +/* P_SpawnSequenceLight */ +/* */ +/*================================================================== */ +void P_SpawnSequenceLight(sector_t* sector, boolean first) // 80016038 +{ + sequenceglow_t *seq; + sector_t *headsector; + int i; + + headsector = NULL; + + if(first) + { + for(i = 0; i < sector->linecount; i++) + { + headsector = sector->lines[i]->frontsector; + + if ((headsector != sector) && (sector->tag == headsector->tag)) + break; + } + + if(headsector == NULL) + return; + } + + seq = Z_Malloc ( sizeof(*seq), PU_LEVSPEC, 0); + P_AddThinker (&seq->thinker); + seq->thinker.function = T_SequenceGlow; + seq->sector = sector; + seq->special = sector->special; + seq->count = 1; + seq->index = sector->tag; + seq->start = (headsector == NULL ? 1 : 0); + seq->headsector = headsector; +} + +/*================================================================== */ +/* */ +/* P_UpdateLightThinker */ +/* */ +/*================================================================== */ + +extern maplights_t *maplights; // 800A5EA4 + +void P_UpdateLightThinker(int destlight, int srclight) // 80016118 +{ + lightmorph_t *lt; + byte r, g, b; + int rgb; + + r = g = b = (byte)destlight; + + if (destlight > 255) + { + r = maplights[destlight-256].r; + g = maplights[destlight-256].b; + b = maplights[destlight-256].g; + } + + maplights[srclight-256].r = r; + maplights[srclight-256].b = g; + maplights[srclight-256].g = b; + + rgb = lights[srclight].rgba; + + lt = Z_Malloc ( sizeof(*lt), PU_LEVSPEC, 0); + P_AddThinker(&lt->thinker); + lt->thinker.function = T_LightMorph; + lt->inc = 0; + lt->dest = destlight; + lt->src = srclight; + lt->r = (rgb >> 24) & 0xff; + lt->g = (rgb >> 16) & 0xff; + lt->b = (rgb >> 8) & 0xff; +} + +/*================================================================== */ +/* */ +/* T_LightMorph */ +/* */ +/*================================================================== */ +void T_LightMorph(lightmorph_t *lt) // 80016244 +{ + int rgb; + + lt->inc += 4; + + if(lt->inc > 256) + { + P_RemoveThinker(&lt->thinker); + return; + } + + rgb = lights[lt->dest].rgba; + lights[lt->src].rgba = + (lt->r + ((lt->inc * (((rgb >> 24) & 0xff) - lt->r)) >> 8)) << 24 | + (lt->g + ((lt->inc * (((rgb >> 16) & 0xff) - lt->g)) >> 8)) << 16 | + (lt->b + ((lt->inc * (((rgb >> 8) & 0xff) - lt->b)) >> 8)) << 8 | 0xff; +} + +/*================================================================== */ +/* */ +/* P_ChangeLightByTag */ +/* This has to be early stuff because this is only */ +/* used once in the entire game and the only place where */ +/* internal light tags are used.. */ +/* */ +/*================================================================== */ +int P_ChangeLightByTag(int tag1, int tag2) // 80016320 +{ + int destlight; + int srclight; + int rtn; + + destlight = P_FindLightFromLightTag(tag1,-1); + if (destlight < 0) + return 0; + + srclight = -1; + rtn = 0; + + while((srclight = P_FindLightFromLightTag(tag2, srclight)) >= 256) + { + rtn = 1; + P_UpdateLightThinker(destlight, srclight); + } + + return rtn; +} + +/*================================================================== */ +/* */ +/* P_DoSectorLightChange */ +/* */ +/*================================================================== */ +int P_DoSectorLightChange(int tag1,int tag2) // 800163B8 +{ + sector_t *sec1; + sector_t *sec2; + int secnum; + int rtn; + + secnum = P_FindSectorFromLineTag(tag1, -1); + if (secnum < 0) + return 0; + + sec2 = &sectors[secnum]; + + secnum = -1; + rtn = 0; + + while((secnum = P_FindSectorFromLineTag(tag2, secnum)) >= 0) + { + sec1 = &sectors[secnum]; + rtn = 1; + + if (sec1->colors[0] >= 256) + P_UpdateLightThinker(sec2->colors[0], sec1->colors[0]); + + if (sec1->colors[1] >= 256) + P_UpdateLightThinker(sec2->colors[1], sec1->colors[1]); + + if (sec1->colors[2] >= 256) + P_UpdateLightThinker(sec2->colors[2], sec1->colors[2]); + + if (sec1->colors[3] >= 256) + P_UpdateLightThinker(sec2->colors[3], sec1->colors[3]); + + if (sec1->colors[4] >= 256) + P_UpdateLightThinker(sec2->colors[4], sec1->colors[4]); + } + + return rtn; +} + +/*================================================================== */ +/* */ +/* T_Combine */ +/* */ +/*================================================================== */ +void T_Combine(combine_t *combine) // 80016524 +{ + sector_t *sector; + + sector = combine->sector; + if (sector->special != combine->special) + { + P_RemoveThinker(&combine->thinker); + return; + } + + sector->lightlevel = combine->combiner->lightlevel; +} + +/*================================================================== */ +/* */ +/* P_CombineLightSpecials */ +/* */ +/*================================================================== */ +void P_CombineLightSpecials(sector_t *sector) // 80016578 +{ + think_t func; + thinker_t *thinker; + combine_t *combine; + + switch(sector->special) + { + case 1: + func = T_LightFlash; + break; + case 2: + case 3: + case 202: + case 204: + //case 205: + case 206: + case 208: + func = T_StrobeFlash; + break; + case 8: + case 9: + case 11: + func = T_Glow; + break; + case 17: + func = T_FireFlicker; + break; + default: + return; + } + + for(thinker = thinkercap.next; thinker != &thinkercap; thinker = thinker->next) + { + if(func != thinker->function) + continue; + + combine = Z_Malloc ( sizeof(*combine), PU_LEVSPEC, 0); + P_AddThinker(&combine->thinker); + combine->thinker.function = T_Combine; + combine->sector = sector; + combine->combiner = ((combine_t *)thinker)->sector; + combine->special = sector->special; + return; + } +} diff --git a/Doom 64/p_local.h b/Doom 64/p_local.h @@ -0,0 +1,327 @@ +/* P_local.h */ + +#ifndef __P_LOCAL__ +#define __P_LOCAL__ + +#ifndef __R_LOCAL__ +#include "r_local.h" +#endif + +#define FLOATSPEED (FRACUNIT*4) + +#define GRAVITY (FRACUNIT*4) //like JagDoom +#define MAXMOVE (16*FRACUNIT) + + +#define MAXHEALTH 100 +#define VIEWHEIGHT (56*FRACUNIT) // D64 change to 41 + +/* mapblocks are used to check movement against lines and things */ +#define MAPBLOCKUNITS 128 +#define MAPBLOCKSIZE (MAPBLOCKUNITS*FRACUNIT) +#define MAPBLOCKSHIFT (FRACBITS+7) +#define MAPBMASK (MAPBLOCKSIZE-1) +#define MAPBTOFRAC (MAPBLOCKSHIFT-FRACBITS) + + +/* player radius for movement checking */ +#define PLAYERRADIUS 16*FRACUNIT + +/* MAXRADIUS is for precalculated sector block boxes */ +/* the spider demon is larger, but we don't have any moving sectors */ +/* nearby */ +#define MAXRADIUS 32*FRACUNIT + + +#define USERANGE (70*FRACUNIT) +#define MELEERANGE (80*FRACUNIT) +#define MISSILERANGE (32*64*FRACUNIT) + + +typedef enum +{ + DI_EAST, + DI_NORTHEAST, + DI_NORTH, + DI_NORTHWEST, + DI_WEST, + DI_SOUTHWEST, + DI_SOUTH, + DI_SOUTHEAST, + DI_NODIR, + NUMDIRS +} dirtype_t; + +#define BASETHRESHOLD 90 /* follow a player exlusively for 3 seconds */ + + + +/* +=============================================================================== + + P_TICK + +=============================================================================== +*/ + +extern thinker_t thinkercap; /* both the head and tail of the thinker list */ + + +void P_InitThinkers (void); +void P_AddThinker (thinker_t *thinker); +void P_RemoveThinker (thinker_t *thinker); + +/* +=============================================================================== + + P_PSPR + +=============================================================================== +*/ + +void P_SetupPsprites (int curplayer); //(player_t *curplayer); +void P_MovePsprites (player_t *curplayer); + +void P_SetPsprite (player_t *player, int position, statenum_t stnum); +void P_BringUpWeapon (player_t *player); +void P_DropWeapon (player_t *player); + +/* +=============================================================================== + + P_USER + +=============================================================================== +*/ + +void P_PlayerThink (player_t *player); + + +/* +=============================================================================== + + P_MOBJ + +=============================================================================== +*/ + +extern mobj_t mobjhead; + +extern int activethinkers; /* debug count */ +extern int activemobjs; /* debug count */ + +#define ONFLOORZ MININT +#define ONCEILINGZ MAXINT + +mobj_t *P_SpawnMobj (fixed_t x, fixed_t y, fixed_t z, mobjtype_t type); + +void P_RemoveMobj (mobj_t *th); +boolean P_SetMobjState (mobj_t *mobj, statenum_t state); +void P_MobjThinker (mobj_t *mobj); + +void P_SpawnPuff (fixed_t x, fixed_t y, fixed_t z); +void P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, int damage); +//mobj_t *P_SpawnMissile (mobj_t *source, mobj_t *dest, mobjtype_t type); +mobj_t *P_SpawnMissile (mobj_t *source, mobj_t *dest, fixed_t xoffs, fixed_t yoffs, fixed_t heightoffs, mobjtype_t type); + +void P_SpawnPlayerMissile (mobj_t *source, mobjtype_t type); + +void P_RunMobjBase (void);//P_RunMobjBase2 (void); +void P_RunMobjExtra (void); + +void L_SkullBash (mobj_t *mo); +void L_MissileHit (mobj_t *mo); +void L_CrossSpecial (mobj_t *mo); + +void P_ExplodeMissile (mobj_t *mo); + +/* +=============================================================================== + + P_ENEMY + +=============================================================================== +*/ + +void A_MissileExplode (mobj_t *mo); +void A_SkullBash (mobj_t *mo); + +/* +=============================================================================== + + P_MAPUTL + +=============================================================================== +*/ + +/*typedef struct +{ + fixed_t x,y, dx, dy; +} divline_t;*/ + +typedef struct +{ + fixed_t frac; + boolean isaline; + union { + line_t *line; + mobj_t *thing; + } d;//8 +} intercept_t; + +typedef boolean(*traverser_t)(intercept_t *in); + + +fixed_t P_AproxDistance (fixed_t dx, fixed_t dy); +int P_PointOnLineSide (fixed_t x, fixed_t y, line_t *line); +int P_PointOnDivlineSide (fixed_t x, fixed_t y, divline_t *line); +void P_MakeDivline (line_t *li, divline_t *dl); +fixed_t P_InterceptVector (divline_t *v2, divline_t *v1); +int P_BoxOnLineSide (fixed_t *tmbox, line_t *ld); +boolean P_CheckUseHeight(line_t *line); + +extern fixed_t opentop, openbottom, openrange;//,,800A5748 +extern fixed_t lowfloor; +void P_LineOpening (line_t *linedef); + +boolean P_BlockLinesIterator (int x, int y, boolean(*func)(line_t*) ); +boolean P_BlockThingsIterator (int x, int y, boolean(*func)(mobj_t*) ); + +extern divline_t trace; // 800A5D58 + +#define PT_ADDLINES 1 +#define PT_ADDTHINGS 2 +#define PT_EARLYOUT 4 + +#define MAXINTERCEPTS 128 + +boolean P_PathTraverse(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, int flags, boolean(*trav)(intercept_t *)); +boolean PIT_AddLineIntercepts(line_t* ld); // 80018574 +boolean PIT_AddThingIntercepts(mobj_t* thing); // 8001860C +fixed_t P_InterceptLine(line_t *line, divline_t *trace); // 8001872C +boolean P_TraverseIntercepts(traverser_t func, fixed_t maxfrac); + +/* +=============================================================================== + + P_MAP + +=============================================================================== +*/ + +extern boolean floatok; /* if true, move would be ok if */ //80077ea8 +extern fixed_t tmfloorz, tmceilingz; /* within tmfloorz - tmceilingz */ //80078010, 80077d30 + +extern line_t *specialline;//80077dc8 +extern mobj_t *movething; + + +boolean P_CheckPosition (mobj_t *thing, fixed_t x, fixed_t y); +boolean P_TryMove (mobj_t *thing, fixed_t x, fixed_t y); +boolean P_CheckSight (mobj_t *t1, mobj_t *t2); +void P_UseLines (player_t *player); + +boolean P_ChangeSector (sector_t *sector, boolean crunch); + +extern mobj_t *linetarget; /* who got hit (or NULL) */ +fixed_t P_AimLineAttack (mobj_t *t1, angle_t angle, fixed_t zheight, fixed_t distance); + +void P_LineAttack (mobj_t *t1, angle_t angle, fixed_t zheight, fixed_t distance, fixed_t slope, int damage); + +void P_RadiusAttack (mobj_t *spot, mobj_t *source, int damage); + +/* +=============================================================================== + + P_SETUP + +=============================================================================== +*/ + +extern byte *rejectmatrix; /* for fast sight rejection */ +extern short *blockmaplump; /* offsets in blockmap are from here */ +extern short *blockmap; +extern int bmapwidth, bmapheight; /* in mapblocks */ +extern fixed_t bmaporgx, bmaporgy; /* origin of block map */ +extern mobj_t **blocklinks; /* for thing chains */ + +/* +=============================================================================== + + P_INTER + +=============================================================================== +*/ + +extern int maxammo[NUMAMMO]; +extern int clipammo[NUMAMMO]; + +void P_TouchSpecialThing (mobj_t *special, mobj_t *toucher); + +void P_DamageMobj (mobj_t *target, mobj_t *inflictor, mobj_t *source, int damage); + +#include "p_spec.h" + +/* +=============================================================================== + + P_MOVE + +=============================================================================== +*/ + +//PSX NEW +#define MAXTHINGSPEC 8 +extern line_t *thingspec[8]; +extern int numthingspec;//80077ee8 + +extern mobj_t *tmthing; +extern fixed_t tmx, tmy; +extern boolean checkposonly; + +void P_TryMove2(void); +int PM_PointOnLineSide(fixed_t x, fixed_t y, line_t *line); +void P_UnsetThingPosition (mobj_t *thing); +void P_SetThingPosition (mobj_t *thing); +void PM_CheckPosition(void); +boolean PM_BoxCrossLine(line_t *ld); +boolean PIT_CheckLine(line_t *ld); +boolean PIT_CheckThing(mobj_t *thing); +boolean PM_BlockLinesIterator(int x, int y); +boolean PM_BlockThingsIterator(int x, int y); + + +/* +=============================================================================== + + P_SHOOT + +=============================================================================== +*/ + +void P_Shoot2(void); +boolean PA_DoIntercept(void *value, boolean isline, int frac); +boolean PA_ShootLine(line_t *li, fixed_t interceptfrac); +boolean PA_ShootThing(mobj_t *th, fixed_t interceptfrac); +fixed_t PA_SightCrossLine(line_t *line); +boolean PA_CrossSubsector(subsector_t *sub); +int PA_DivlineSide(fixed_t x, fixed_t y, divline_t *line); +boolean PA_CrossBSPNode(int bspnum); + +/* +=============================================================================== + + P_SIGHT + +=============================================================================== +*/ + +void P_CheckSights(void); +boolean P_CheckSight(mobj_t *t1, mobj_t *t2); +boolean PS_CrossBSPNode(int bspnum); +boolean PS_CrossSubsector(subsector_t *sub); +fixed_t PS_SightCrossLine (line_t *line); + +#endif /* __P_LOCAL__ */ + + diff --git a/Doom 64/p_macros.c b/Doom 64/p_macros.c @@ -0,0 +1,185 @@ +/* P_Macros.c */ +#include "doomdef.h" +#include "r_local.h" +#include "p_local.h" +#include "st_main.h" + +/* MACRO Variables */ +macro_t *activemacro; // 800A6094 +mobj_t *macroactivator; // 800A6098 +line_t macrotempline; // 800A60A0 +line_t *macroline; // 800A60EC +thinker_t *macrothinker; // 800A60F0 +int macrointeger; // 800A60F4 +macro_t *restartmacro; // 800A60F8 +int macrocounter; // 800A60FC +macroactivator_t macroqueue[4]; // 800A6100 +int macroidx1; // 800A6120 +int macroidx2; // 800A6124 + +int P_StartMacro(int macroindex, line_t *line, mobj_t *thing) // 80021088 +{ + macro_t *macro; + + if (activemacro) + return 0; + + macro = macros[macroindex-256]; + if (macro->id <= 0) + { + if (macro->id == 0) + line->special = 0; + + return 0; + } + + activemacro = macro; + macroactivator = thing; + macrothinker = NULL; + macroline = line; + + D_memcpy(&macrotempline, line, sizeof(line_t)); + P_ChangeSwitchTexture(line, line->special & MLU_REPEAT); + + return 1; +} + +int P_SuspendMacro(void) // 80021148 +{ + macroactivator_t *activatorInfo; + + if(!activemacro) + return 0; + + macrothinker = NULL; + macrocounter = 0; + activemacro = NULL; + + if (!(macroline->special & MLU_REPEAT)) + { + macros[SPECIALMASK(macroline->special)-256]->id = 0; + macroline->special = 0; + } + + if (macroidx2 != macroidx1) + { + activatorInfo = &macroqueue[macroidx2]; + macroidx2 = (macroidx2 + 1) & 3; + + P_ActivateLineByTag(activatorInfo->tag, activatorInfo->activator); + } + + return 1; +} + +void P_ToggleMacros(int tag, boolean toggleon) // 80021214 +{ + macro_t *macro = macros[tag-256]; + + if(toggleon) + { + if(macro->id >= 0) + return; + } + else + { + if(macro->id <= 0) + return; + } + + macro->id = -macro->id; +} + +void P_RunMacros(void) // 8002126C +{ + thinker_t *thinker; + int id; + + if(!activemacro) + return; + + if(macrothinker) + { + //ST_DebugPrint("macrothinker %x wait", macrothinker); + return; /* must wait for this thinker to finish */ + } + + //ST_DebugPrint("activemacro->id %d",activemacro->id); + + + /* keep track of the current thinker */ + thinker = thinkercap.prev; + + while(activemacro->id != 0) + { + id = activemacro->id; + + macrotempline.special = activemacro->special; + macrotempline.tag = activemacro->tag; + + activemacro++; + + /* invoke a line special from this macro */ + P_UseSpecialLine(&macrotempline, macroactivator); + + /* keep executing macros until reaching a new batch ID */ + if (id != activemacro->id) + { + if (activemacro->id == 0) + { + //ST_DebugPrint("P_SuspendMacro act->id %d",activemacro->id); + P_SuspendMacro(); + return; + } + + /* if the last macro produced a new thinker then keep track of it */ + if (thinker != thinkercap.prev) + { + /* don't execute any more macros until this thinker is done */ + macrothinker = thinkercap.prev; + return; + } + } + + thinker = thinkercap.prev; + } +} + +void P_RestartMacro(line_t *line, int id) // 80021384 +{ + macro_t *macro; + + if(!activemacro) + return; + + if (macrocounter == 0) + { + macro = macros[SPECIALMASK(macroline->special)-256]; + + /* find the first macro in the batch to restart on */ + while((macro->id != 0) && (macro->id != id)) + { + macro++; + } + + if ((macro->id != 0) && (line->tag != 0)) + { + /* its now set */ + activemacro = macro; + restartmacro = macro; + macrocounter = line->tag; + + } + } + else + { + if(macrocounter > 0) + { + if(--macrocounter == 0) + return; + } + + // restart the macro + activemacro = restartmacro; + } +} diff --git a/Doom 64/p_map.c b/Doom 64/p_map.c @@ -0,0 +1,448 @@ +/* P_map.c */ + +#include "doomdef.h" +#include "p_local.h" + +//int DSPRead (void volatile *adr); + +/*============================================================================= */ + +/*================== */ +/* */ +/* in */ +/* */ +/*================== */ + +mobj_t *tmthing; // 800A56B0 +fixed_t tmx, tmy; // 800A56B4, 800A56B8 +boolean checkposonly; // 800A56C8 + +/*================== */ +/* */ +/* out */ +/* */ +/*================== */ +extern boolean trymove2; // 800A5D80 + +extern boolean floatok; /* if true, move would be ok if */ + /* within tmfloorz - tmceilingz */ + +extern fixed_t tmfloorz, tmceilingz, tmdropoffz; + +extern mobj_t *movething; // 800A5D98 + +/*============================================================================= */ + +/* +=================== += += P_TryMove += +in: +tmthing a mobj_t (can be valid or invalid) +tmx,tmy a position to be checked (doesn't need relate to the mobj_t->x,y) + +out: + +newsubsec +floatok if true, move would be ok if within tmfloorz - tmceilingz +floorz +ceilingz +tmdropoffz the lowest point contacted (monsters won't move to a dropoff) + +movething + +================== +*/ + +void P_TryMove2 (void); + +//int checkpostics; + +boolean P_CheckPosition (mobj_t *thing, fixed_t x, fixed_t y) // 800166e0 +{ + checkposonly = true; + + tmthing = thing; + tmx = x; + tmy = y; + + P_TryMove2 (); + + return trymove2; +} + +boolean P_TryMove (mobj_t *thing, fixed_t x, fixed_t y) // 80016724 +{ + int damage; + mobj_t *latchedmovething; + + tmthing = thing; + tmx = x; + tmy = y; + + P_TryMove2 (); + + /* */ + /* pick up the specials */ + /* */ + latchedmovething = movething; + + if (latchedmovething) + { + if (thing->flags & MF_MISSILE) + { /* missile bash into a monster */ + damage = ((P_Random()&7)+1)*thing->info->damage; + P_DamageMobj (latchedmovething, thing, thing->target, damage); + } + else if (thing->flags & MF_SKULLFLY) + { /* skull bash into a monster */ + damage = ((P_Random()&7)+1)*thing->info->damage; + P_DamageMobj (latchedmovething, thing, thing, damage); + thing->flags &= ~MF_SKULLFLY; + thing->momx = thing->momy = thing->momz = 0; + P_SetMobjState (thing, thing->info->spawnstate); + } + else /* pick up */ + { + P_TouchSpecialThing (latchedmovething, thing); + } + + // [d64]: clear movething + movething = NULL; + } + + return trymove2; +} + + +/* +============================================================================== + + USE LINES + +============================================================================== +*/ + +int usebbox[4]; // 800A56D0 +divline_t useline; // 800A56E0 + +line_t *closeline; // 800A56F0 +fixed_t closedist; // 800A56F4 + +/* +================ += += P_CheckUseHeight += +================ +*/ + +boolean P_CheckUseHeight(line_t *line) // 80016858 +{ + int flags; + fixed_t rowoffset; + fixed_t check; + + rowoffset = sides[line->sidenum[0]].rowoffset; + flags = line->flags & (ML_CHECKFLOORHEIGHT|ML_SWITCHX08); + + if (flags == ML_SWITCHX08) + { + check = (line->backsector->ceilingheight + rowoffset) + (32*FRACUNIT); + } + else if (flags == ML_CHECKFLOORHEIGHT) + { + check = (line->backsector->floorheight + rowoffset) -(32*FRACUNIT); + } + else if (flags == (ML_CHECKFLOORHEIGHT|ML_SWITCHX08)) + { + check = (line->frontsector->floorheight + rowoffset) + (32*FRACUNIT); + } + else + return true; + + if((check < players[0].mo->z)) + return false; + + if((players[0].mo->z + (64*FRACUNIT)) < check) + return false; + + return true; +} + +/* +=============== += += P_InterceptVector += += Returns the fractional intercept point along the first divline += +=============== +*/ + +fixed_t P_InterceptVector (divline_t *v2, divline_t *v1) // 80016954 +{ + fixed_t frac, num, den; + + den = (v1->dy>>16)*(v2->dx>>16) - (v1->dx>>16)*(v2->dy>>16); + + if (den == 0) + return -1; + + num = ((v1->x-v2->x)>>16) *(v1->dy>>16) + ((v2->y-v1->y)>>16) * (v1->dx>>16); + + frac = (num<<16) / den; + + return frac; +} + + +/* +================ += += PIT_UseLines += +================ +*/ + +boolean PIT_UseLines (line_t *li) // 80016A28 +{ + divline_t dl; + fixed_t frac; + + /* */ + /* check bounding box first */ + /* */ + if (usebbox[BOXRIGHT] <= li->bbox[BOXLEFT] + || usebbox[BOXLEFT] >= li->bbox[BOXRIGHT] + || usebbox[BOXTOP] <= li->bbox[BOXBOTTOM] + || usebbox[BOXBOTTOM] >= li->bbox[BOXTOP] ) + return true; + + if(!li->special) + { + // [d64]: new logic + if(closeline != NULL) + { + if(closeline->special) + return true; // keep going + } + } + else + { + // [d64]: new logic + if(P_PointOnLineSide(useline.x, useline.y, li) != 0) + return true; // must be in front of the line + } + + /* */ + /* find distance along usetrace */ + /* */ + //P_MakeDivline (li, &dl); + dl.x = li->v1->x; + dl.y = li->v1->y; + dl.dx = li->dx; + dl.dy = li->dy; + + frac = P_InterceptVector (&useline, &dl); + if (frac < 0) + return true; /* behind source */ + + /* */ + /* the line is actually hit, find the distance */ + /* */ + if (!li->special) + { + if (frac > closedist) + return true; /* too far away */ + + P_LineOpening (li); + if (openrange > 0) + return true; /* keep going */ + } + else if(closeline && closeline->special != 0) + { + if(frac > closedist) + return true; /* too far away */ + } + + closeline = li; + closedist = frac; + + return true; /* can't use for than one special line in a row */ +} + + +/* +================ += += P_UseLines += += Looks for special lines in front of the player to activate +================ +*/ + +void P_UseLines (player_t *player) // 80016C10 +{ + int angle; + fixed_t x1, y1, x2, y2; + int x,y, xl, xh, yl, yh; + + angle = player->mo->angle >> ANGLETOFINESHIFT; + x1 = player->mo->x; + y1 = player->mo->y; + x2 = x1 + (USERANGE>>FRACBITS)*finecosine[angle]; + y2 = y1 + (USERANGE>>FRACBITS)*finesine[angle]; + + useline.x = x1; + useline.y = y1; + useline.dx = x2-x1; + useline.dy = y2-y1; + + if (useline.dx > 0) + { + usebbox[BOXRIGHT ] = x2; + usebbox[BOXLEFT ] = x1; + } + else + { + usebbox[BOXRIGHT ] = x1; + usebbox[BOXLEFT ] = x2; + } + + if (useline.dy > 0) + { + usebbox[BOXTOP ] = y2; + usebbox[BOXBOTTOM] = y1; + } + else + { + usebbox[BOXTOP ] = y1; + usebbox[BOXBOTTOM] = y2; + } + + yh = (usebbox[BOXTOP ] - bmaporgy) >> MAPBLOCKSHIFT; + yl = (usebbox[BOXBOTTOM] - bmaporgy) >> MAPBLOCKSHIFT; + xh = (usebbox[BOXRIGHT ] - bmaporgx) >> MAPBLOCKSHIFT; + xl = (usebbox[BOXLEFT ] - bmaporgx) >> MAPBLOCKSHIFT; + + closeline = NULL; + closedist = FRACUNIT; + validcount++; + + for (y = yl; y <= yh; y++) + { + for (x = xl; x <= xh; x++) + { + P_BlockLinesIterator(x, y, PIT_UseLines); + } + } + + /* */ + /* check closest line */ + /* */ + if (!closeline) + return; + + if (!(closeline->special & MLU_USE) || + !P_CheckUseHeight(closeline)) + S_StartSound (player->mo, sfx_noway); + else + P_UseSpecialLine (closeline, player->mo); +} + + + +/* +============================================================================== + + RADIUS ATTACK + +============================================================================== +*/ + +mobj_t *bombsource; //pmGp0000090c +mobj_t *bombspot; //pmGp00000bb8 +int bombdamage; //iGp000008b4 + +/* +================= += += PIT_RadiusAttack += += Source is the creature that casued the explosion at spot +================= +*/ + +boolean PIT_RadiusAttack (mobj_t *thing) // 80016E3C +{ + fixed_t dx, dy, dist; + + if (!(thing->flags & MF_SHOOTABLE)) + return true; + + // Boss cyborg take no damage from concussion. + if(thing->type == MT_CYBORG) + return true; + + if(thing->type == MT_SKULL || thing->type == MT_PAIN) + { + if(bombsource && bombsource->type == MT_SKULL) + return true; + } + + dx = abs(thing->x - bombspot->x); + dy = abs(thing->y - bombspot->y); + + dist = dx>dy ? dx : dy; + dist = dist - thing->radius >> FRACBITS; + + if (dist < 0) + dist = 0; + + if (dist >= bombdamage) + return true; /* out of range */ + + if (P_CheckSight(thing, bombspot) != 0) // must be in direct path */ + { + P_DamageMobj(thing, bombspot, bombsource, bombdamage - dist); + } + + return true; +} + + +/* +================= += += P_RadiusAttack += += Source is the creature that casued the explosion at spot +================= +*/ + +void P_RadiusAttack (mobj_t *spot, mobj_t *source, int damage)// 80016F9C +{ + int x,y, xl, xh, yl, yh; + fixed_t dist; + + dist = (damage+MAXRADIUS)<<FRACBITS; + + yh = (spot->y + dist - bmaporgy)>>MAPBLOCKSHIFT; + yl = (spot->y - dist - bmaporgy)>>MAPBLOCKSHIFT; + xh = (spot->x + dist - bmaporgx)>>MAPBLOCKSHIFT; + xl = (spot->x - dist - bmaporgx)>>MAPBLOCKSHIFT; + + bombspot = spot; + bombsource = source; + bombdamage = damage; + + for (y = yl; y <= yh; y++) + { + for (x = xl; x <= xh; x++) + { + P_BlockThingsIterator(x, y, PIT_RadiusAttack); + } + } +} diff --git a/Doom 64/p_maputl.c b/Doom 64/p_maputl.c @@ -0,0 +1,591 @@ + +/* P_maputl.c */ + +#include "doomdef.h" +#include "p_local.h" + + +/* +=================== += += P_AproxDistance += += Gives an estimation of distance (not exact) += +=================== +*/ + +fixed_t P_AproxDistance (fixed_t dx, fixed_t dy) // 80017F00 +{ + dx = abs(dx); + dy = abs(dy); + if (dx < dy) + return dx+dy-(dx>>1); + return dx+dy-(dy>>1); +} + +/* +================== += += P_PointOnDivlineSide += += Returns 0 or 1 +================== +*/ +#if 0 +int P_PointOnDivlineSide (fixed_t x, fixed_t y, divline_t *line)//L8001C598() +{ + fixed_t dx,dy; + fixed_t left, right; + + if (!line->dx) + { + if (x <= line->x) + return line->dy > 0; + return line->dy < 0; + } + if (!line->dy) + { + if (y <= line->y) + return line->dx < 0; + return line->dx > 0; + } + + dx = (x - line->x); + dy = (y - line->y); + +/* try to quickly decide by looking at sign bits */ + if ( (line->dy ^ line->dx ^ dx ^ dy)&0x80000000 ) + { + if ( (line->dy ^ dx) & 0x80000000 ) + return 1; /* (left is negative) */ + return 0; + } + + left = FixedMul ( line->dy>>8, dx>>8 ); + right = FixedMul ( dy>>8 , line->dx>>8 ); + + if (right < left) + return 0; /* front side */ + return 1; /* back side */ +} + + + +/* +============== += += P_MakeDivline += +============== +*/ + +void P_MakeDivline (line_t *li, divline_t *dl)//L8001C68C() +{ + dl->x = li->v1->x; + dl->y = li->v1->y; + dl->dx = li->dx; + dl->dy = li->dy; +} +#endif // 0 + + +/* +================== += += P_LineOpening += += Sets opentop and openbottom to the window through a two sided line += OPTIMIZE: keep this precalculated +================== +*/ + +fixed_t opentop, openbottom, openrange; // 800A5740, 800A5744, 800A5748 +fixed_t lowfloor; // 800A574C + +void P_LineOpening (line_t *linedef) // 80017F40 +{ + sector_t *front, *back; + + //if (linedef->sidenum[1] == -1) + if (linedef->backsector == 0) // D64 change this line + { /* single sided line */ + openrange = 0; + return; + } + + front = linedef->frontsector; + back = linedef->backsector; + + if (front->ceilingheight < back->ceilingheight) + opentop = front->ceilingheight; + else + opentop = back->ceilingheight; + if (front->floorheight > back->floorheight) + { + openbottom = front->floorheight; + lowfloor = back->floorheight; + } + else + { + openbottom = back->floorheight; + lowfloor = front->floorheight; + } + + openrange = opentop - openbottom; +} + +/* +=============================================================================== + + BLOCK MAP ITERATORS + +For each line/thing in the given mapblock, call the passed function. +If the function returns false, exit with false without checking anything else. + +=============================================================================== +*/ + +/* +================== += += P_BlockLinesIterator += += The validcount flags are used to avoid checking lines += that are marked in multiple mapblocks, so increment validcount before += the first call to P_BlockLinesIterator, then make one or more calls to it +=================== +*/ + +boolean P_BlockLinesIterator (int x, int y, boolean(*func)(line_t*) ) // 80017FE8 +{ + int offset; + short *list; + line_t *ld; + + if (x<0 || y<0 || x>=bmapwidth || y>=bmapheight) + return true; + offset = y*bmapwidth+x; + + offset = *(blockmap+offset); + + for ( list = blockmaplump+offset ; *list != -1 ; list++) + { + ld = &lines[*list]; + if (ld->validcount == validcount) + continue; /* line has already been checked */ + ld->validcount = validcount; + + if ( !func(ld) ) + return false; + } + + return true; /* everything was checked */ +} + + +/* +================== += += P_BlockThingsIterator += +================== +*/ + +boolean P_BlockThingsIterator (int x, int y, boolean(*func)(mobj_t*) ) // 8001811C +{ + mobj_t *mobj; + + if (x<0 || y<0 || x>=bmapwidth || y>=bmapheight) + return true; + + for (mobj = blocklinks[y*bmapwidth+x] ; mobj ; mobj = mobj->bnext) + { + if (!func( mobj ) ) + return false; + } + + return true; +} + +/* +=============================================================================== + +INTERCEPT ROUTINES + +=============================================================================== +*/ + +intercept_t intercepts[MAXINTERCEPTS]; // 800A5750 +intercept_t* intercept_p; // 800a5d50 + +divline_t trace; // 800A5D58 + +// +// P_PathTraverse +// Traces a line from x1,y1 to x2,y2, +// calling the traverser function for each. +// Returns true if the traverser function returns true +// for all lines. +// +boolean P_PathTraverse(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, int flags, boolean(*trav)(intercept_t *)) +{ + fixed_t xt1, yt1, xt2, yt2; + fixed_t xstep, ystep; + fixed_t partial; + fixed_t xintercept, yintercept; + int mapx, mapy; + int mapxstep, mapystep; + int count; + + validcount++; + intercept_p = intercepts; + + if(((x1-bmaporgx)&(MAPBLOCKSIZE-1)) == 0) + { + x1 += FRACUNIT; // don't side exactly on a line + } + + if(((y1-bmaporgy)&(MAPBLOCKSIZE-1)) == 0) + { + y1 += FRACUNIT; // don't side exactly on a line + } + + trace.x = x1; + trace.y = y1; + trace.dx = x2 - x1; + trace.dy = y2 - y1; + + x1 -= bmaporgx; + y1 -= bmaporgy; + xt1 = x1>>MAPBLOCKSHIFT; + yt1 = y1>>MAPBLOCKSHIFT; + + x2 -= bmaporgx; + y2 -= bmaporgy; + xt2 = x2>>MAPBLOCKSHIFT; + yt2 = y2>>MAPBLOCKSHIFT; + + if(xt2 > xt1) + { + mapxstep = 1; + partial = FRACUNIT - ((x1>>MAPBTOFRAC)&(FRACUNIT-1)); + ystep = FixedDiv(y2-y1,abs(x2-x1)); + } + else if(xt2 < xt1) + { + mapxstep = -1; + partial = (x1>>MAPBTOFRAC)&(FRACUNIT-1); + ystep = FixedDiv(y2-y1,abs(x2-x1)); + } + else + { + mapxstep = 0; + partial = FRACUNIT; + ystep = 256*FRACUNIT; + } + + yintercept = (y1>>MAPBTOFRAC) + FixedMul(partial, ystep); + + + if(yt2 > yt1) + { + mapystep = 1; + partial = FRACUNIT - ((y1>>MAPBTOFRAC)&(FRACUNIT-1)); + xstep = FixedDiv(x2-x1,abs(y2-y1)); + } + else if(yt2 < yt1) + { + mapystep = -1; + partial = (y1>>MAPBTOFRAC)&(FRACUNIT-1); + xstep = FixedDiv(x2-x1,abs(y2-y1)); + } + else + { + mapystep = 0; + partial = FRACUNIT; + xstep = 256*FRACUNIT; + } + + xintercept = (x1>>MAPBTOFRAC) + FixedMul(partial, xstep); + + // Step through map blocks. + // Count is present to prevent a round off error + // from skipping the break. + mapx = xt1; + mapy = yt1; + + for(count = 0; count < 64; count++) + { + // [d64]: switched order of function calls + if(flags & PT_ADDTHINGS) + { + if(!P_BlockThingsIterator(mapx, mapy, PIT_AddThingIntercepts)) + { + return false; // early out + } + } + + if(flags & PT_ADDLINES) + { + if(!P_BlockLinesIterator(mapx, mapy, PIT_AddLineIntercepts)) + { + return false; // early out + } + } + + if(mapx == xt2 && mapy == yt2) + { + break; + } + + if((yintercept >> FRACBITS) == mapy) + { + yintercept += ystep; + mapx += mapxstep; + } + else if((xintercept >> FRACBITS) == mapx) + { + xintercept += xstep; + mapy += mapystep; + } + } + // go through the sorted list + return P_TraverseIntercepts(trav, FRACUNIT); +} + +// +// PIT_AddLineIntercepts. +// Looks for lines in the given block +// that intercept the given trace +// to add to the intercepts list. +// +// A line is crossed if its endpoints +// are on opposite sides of the trace. +// +boolean PIT_AddLineIntercepts(line_t* ld) // 80018574 +{ + fixed_t frac; + + // hit the line + frac = P_InterceptLine(ld, &trace); + + if(frac < 0) + { + return true; // behind source + } + + // [d64] exit out if max intercepts has been hit + if((intercept_p - intercepts) >= MAXINTERCEPTS) + { + return true; + } + + intercept_p->frac = frac; + intercept_p->isaline = true; + intercept_p->d.line = ld; + intercept_p++; + + return true; // continue +} + +// +// PIT_AddThingIntercepts +// +boolean PIT_AddThingIntercepts(mobj_t* thing) // 8001860C +{ + fixed_t x1, y1, x2, y2; + boolean tracepositive; + fixed_t frac; + line_t templine; + vertex_t tempvertex1, tempvertex2; + + // [d64]: added an early out check + if((thing->flags & MF_SHOOTABLE) == 0) + { + return true; // keep going + } + + tracepositive = (trace.dx ^ trace.dy)>0; + + // check a corner to corner crossection for hit + if(tracepositive) + { + x1 = thing->x - thing->radius; + y1 = thing->y + thing->radius; + + x2 = thing->x + thing->radius; + y2 = thing->y - thing->radius; + } + else + { + x1 = thing->x - thing->radius; + y1 = thing->y - thing->radius; + + x2 = thing->x + thing->radius; + y2 = thing->y + thing->radius; + } + + tempvertex1.x = x1; + tempvertex1.y = y1; + tempvertex2.x = x2; + tempvertex2.y = y2; + + templine.v1 = &tempvertex1; + templine.v2 = &tempvertex2; + + templine.dx = x2 - x1; + templine.dy = y2 - y1; + + frac = P_InterceptLine(&templine, &trace); + + if(frac < 0) + { + return true; // behind source + } + + // [d64] exit out if max intercepts has been hit + if((intercept_p - intercepts) >= MAXINTERCEPTS) + { + return true; + } + + intercept_p->frac = frac; + intercept_p->isaline = false; + intercept_p->d.thing = thing; + intercept_p++; + + return true; // keep going +} + +// +// P_InterceptLine +// [d64]: new function + +fixed_t P_InterceptLine(line_t *line, divline_t *trace) // 8001872C +{ + fixed_t normal_x, normal_y; + fixed_t v1x, v1y, v2x, v2y; + fixed_t tx, ty, tdx, tdy; + fixed_t dir_x, dir_y; + fixed_t leftSide, rightSide; + fixed_t ldx, ldy; + fixed_t end_x, end_y; + fixed_t num, den, frac; + + v1x = line->v1->x; + v1y = line->v1->y; + v2y = line->v2->y; + v2x = line->v2->x; + + tx = trace->x; + ty = trace->y; + + tdx = trace->dx; + tdy = trace->dy; + + normal_y = (-tdx) >> 8; + normal_x = tdy >> 8; + + dir_x = (v1x - tx) >> 8; + dir_y = (v1y - ty) >> 8; + + leftSide = FixedMul(dir_x, normal_x) + FixedMul(dir_y, normal_y); + rightSide = FixedMul((v2x - tx) >> 8, normal_x) + FixedMul((v2y - ty) >> 8, normal_y); + + if ((leftSide < 0) == (rightSide < 0)) + { + // didn't cross + return -1; + } + + ldy = (v1y - v2y) >> 8; + ldx = (v2x - v1x) >> 8; + + end_x = (tx + tdx); + end_y = (ty + tdy); + + num = FixedMul(dir_x, ldy) + FixedMul(dir_y, ldx); + den = FixedMul((end_x - v1x) >> 8, ldy) + FixedMul((end_y - v1y) >> 8, ldx); + + frac = FixedDiv(num, num + den); + + return frac; + + /*normal_x = trace.dy >> 8; + normal_y = (-trace.dx) >> 8; + v1x = line->v1->x >> 8; + v1y = line->v1->y >> 8; + v2x = line->v2->x >> 8; + v2y = line->v2->y >> 8; + tx = trace.x >> 8; + ty = trace.y >> 8; + end_x = tx + (trace.dx >> 8); + end_y = ty + (trace.dy >> 8); + dir_x = v1x - tx; + dir_y = v1y - ty; + ldx = v2x - v1x; + ldy = v1y - v2y; + + leftSide = FixedMul(dir_x, normal_x) + FixedMul(dir_y, normal_y); + rightSide = FixedMul(v2x - tx, normal_x) + FixedMul(v2y - ty, normal_y); + + s1 = (leftSide < 0) ? 1 : 0; + s2 = (rightSide < 0) ? 1 : 0; + + if(s1 == s2) + { + // didn't cross + return -1; + } + + num = FixedMul(dir_x, ldy) + FixedMul(dir_y, ldx); + den = FixedMul(end_x - v1x, ldy) + FixedMul(end_y - v1y, ldx); + + frac = FixedDiv(num, num + den); + return frac;*/ +} + +// +// P_TraverseIntercepts +// Returns true if the traverser function returns true +// for all lines. +// +boolean P_TraverseIntercepts(traverser_t func, fixed_t maxfrac) // 800188F0 +{ + int count; + fixed_t dist; + intercept_t* scan; + intercept_t* in; + + count = (int)(intercept_p - intercepts); + + in = 0; // shut up compiler warning + + while(count--) + { + dist = MAXINT; + for(scan = intercepts ; scan<intercept_p ; scan++) + { + if(scan->frac < dist) + { + dist = scan->frac; + in = scan; + } + } + + if(dist > maxfrac) + { + return true; // checked everything in range + } + + if(!func(in)) + { + return false; // don't bother going farther + } + + in->frac = MAXINT; + } + + return true; // everything was traversed +} diff --git a/Doom 64/p_misc.c b/Doom 64/p_misc.c @@ -0,0 +1,843 @@ +/* p_misc.c */ + +#include "doomdef.h" +#include "p_local.h" +#include "r_local.h" + +/* +============================================================================== + + AIM CAMERA + +============================================================================== +*/ + +#define CAMAIMANGLE ANG5 + +void T_AimCamera(aimcamera_t *camera) // 8000DE60 +{ + angle_t delta; + angle_t newangle; + angle_t angle; + + if((cameratarget != camera->viewmobj) || (cameratarget == players[0].mo)) + { + P_RemoveThinker(&camera->thinker); + return; + } + + /* adjust angle */ + newangle = R_PointToAngle2(cameratarget->x, cameratarget->y, players[0].mo->x, players[0].mo->y); + angle = cameratarget->angle; + delta = (newangle - angle); + + if ((delta < CAMAIMANGLE) || (delta > -CAMAIMANGLE)) { + cameratarget->angle = newangle; + } + else if (delta < ANG180) { + cameratarget->angle = angle + CAMAIMANGLE; + } + else { + cameratarget->angle = angle - CAMAIMANGLE; + } +} + +int P_SetAimCamera(line_t *line, boolean aim) // 8000DF20 +{ + aimcamera_t *camera; + mobj_t *mo; + + if (demorecording == false) + { + for (mo = mobjhead.next; mo != &mobjhead; mo = mo->next) + { + if((line->tag != mo->tid)) + continue; /* not matching the tid */ + + if(line->tag == cameratarget->tid) + continue; /* skip if cameratarget matches tag */ + + cameratarget = mo; + if ((cameratarget != players[0].mo) && (aim)) + { + mo->angle = R_PointToAngle2(mo->x, mo->y, players[0].mo->x, players[0].mo->y); + + camera = Z_Malloc(sizeof(*camera), PU_LEVSPEC, NULL); + P_AddThinker(&camera->thinker); + camera->thinker.function = T_AimCamera; + camera->viewmobj = mo; + } + + return 1; + } + } + + return 0; +} + +/* +============================================================================== + + EV_SpawnTrapMissile + +============================================================================== +*/ + +int EV_SpawnTrapMissile(line_t *line, mobj_t *target, mobjtype_t type) // 8000E02C +{ + mobj_t* mo; + mobj_t* th; + int ok; + + ok = 0; + for(mo = mobjhead.next; mo != &mobjhead; mo = mo->next) + { + if(mo->type != MT_DEST_PROJECTILE) + continue; /* not a dart projector */ + + if((line->tag != mo->tid)) + continue; /* not matching the tid */ + + ok = 1; + + if(type == MT_PROJ_TRACER) + { + th = P_SpawnMissile(mo, target, 0, 0, (32*FRACUNIT), MT_PROJ_TRACER); + th->x = (th->x + th->momx); + th->y = (th->y + th->momy); + th->tracer = target; + } + else if(type == MT_PROJ_DART) + { + th = P_SpawnMissile(mo, NULL, 0, 0, 0, MT_PROJ_DART); + } + } + + return ok; +} + +/* +============================================================================== + + EXIT DELAY + +============================================================================== +*/ + +/* +================================================================================ += += P_SpawnDelayTimer += += Exclusive Psx Doom / Doom 64 += +=============================================================================== +*/ + +void P_SpawnDelayTimer(int tics, void(*action)()) // 8000E160 +{ + delay_t *timer; + + timer = Z_Malloc(sizeof(*timer), PU_LEVSPEC, NULL); + P_AddThinker(&timer->thinker); + timer->thinker.function = T_CountdownTimer; + timer->tics = tics; + timer->finishfunc = action; +} + +/* +================================================================================ += += T_CountdownTimer += += Exclusive Psx Doom / Doom 64 += +=============================================================================== +*/ + +void T_CountdownTimer(delay_t *timer) // 8000E1CC +{ + if((--timer->tics) <= 0) + { + if (timer->finishfunc) + timer->finishfunc(); + + P_RemoveThinker(&timer->thinker); + } +} + +/* +================================================================================ += += P_ExitLevel += += Exclusive Psx Doom / Doom 64 += +=============================================================================== +*/ + +void P_ExitLevel(void) // 8000E220 +{ + nextmap = gamemap + 1; + P_SpawnDelayTimer(15, G_CompleteLevel); +} + +/* +================================================================================ += += P_SecretExitLevel += += Exclusive Psx Doom / Doom 64 += +=============================================================================== +*/ + +void P_SecretExitLevel(int map) // 8000E25C +{ + int delaytics; + + if (map < LASTLEVEL) + delaytics = 15; + else + delaytics = 120; + + nextmap = map; + P_SpawnDelayTimer(delaytics, G_CompleteLevel); +} + +/* +==================================================================== + + TELEPORTATION + The teleportation functions for some reason, were in the middle of + the other functions in this file, I move them in the corresponding + file p_telept.c + +==================================================================== +*/ + +//void P_Telefrag (mobj_t *thing, fixed_t x, fixed_t y) // 8000E29C +//int EV_Teleport( line_t *line, mobj_t *thing ) // 8000E3A0 +//int EV_SilentTeleport( line_t *line, mobj_t *thing ) // 8000E5C0 + +/* --------------------------------------------------------------------------------- */ + +int P_ModifyLineFlags(line_t *line, int tag) // 8000E6BC +{ + line_t *line1, *line2; + int i; + + line2 = lines; + for (i = 0; i < numlines; i++, line2++) + { + if (line2->tag == tag) break; + } + + if (i < numlines) + { + line1 = lines; + for (i = 0; i < numlines; i++, line1++) + { + if (line->tag == line1->tag) + { + if (line1->flags & ML_TWOSIDED) + { + line1->flags = (line2->flags | ML_TWOSIDED); + } + else + { + line1->flags = line2->flags; + line1->flags &= ~ML_TWOSIDED; + } + } + } + + return 1; + } + + return 0; +} + +int P_ModifyLineData(line_t *line, int tag) // 8000E780 +{ + line_t *line1, *line2; + int i; + + line2 = lines; + for (i = 0; i < numlines; i++, line2++) + { + if (line2->tag == tag) break; + } + + if (i < numlines) + { + line1 = lines; + for (i = 0; i < numlines; i++, line1++) + { + if (line->tag == line1->tag) + { + line1->special = line2->special; + } + } + + return 1; + } + + return 0; +} + +int P_ModifyLineTexture(line_t *line, int tag) // 8000E82C +{ + line_t *line1, *line2; + int i; + + line2 = lines; + for (i = 0; i < numlines; i++, line2++) + { + if (line2->tag == tag) break; + } + + if (i < numlines) + { + line1 = lines; + for (i = 0; i < numlines; i++, line1++) + { + if (line->tag == line1->tag) + { + sides[line1->sidenum[0]].toptexture = sides[line2->sidenum[0]].toptexture; + sides[line1->sidenum[0]].bottomtexture = sides[line2->sidenum[0]].bottomtexture; + sides[line1->sidenum[0]].midtexture = sides[line2->sidenum[0]].midtexture; + } + } + + return 1; + } + + return 0; +} + +int P_ModifySector(line_t *line, int tag, int type) // 8000E928 +{ + sector_t *sec1, *sec2; + int secnum; + int rtn; + + secnum = P_FindSectorFromLineTag(tag, 0); + + if(secnum == -1) + return 0; + + sec2 = &sectors[secnum]; + + secnum = -1; + rtn = 0; + + while((secnum = P_FindSectorFromLineTag(line->tag, secnum)) >= 0) + { + sec1 = &sectors[secnum]; + rtn = 1; + + switch(type) + { + case mods_flags: + sec1->flags = sec2->flags; + break; + case mods_special: + if (sec1->special != sec2->special) + { + sec1->special = sec2->special; + P_AddSectorSpecial(sec1); + } + break; + case mods_flats: + sec1->ceilingpic = sec2->ceilingpic; + sec1->floorpic = sec2->floorpic; + break; + case mods_lights: + sec1->colors[0] = sec2->colors[0]; + sec1->colors[1] = sec2->colors[1]; + sec1->colors[2] = sec2->colors[2]; + sec1->colors[3] = sec2->colors[3]; + sec1->colors[4] = sec2->colors[4]; + break; + default: + break; + } + } + + return rtn; +} + +void T_FadeThinker(fade_t *fade) // 8000EACC +{ + mobj_t *mo; + + mo = fade->mobj; + mo->alpha += fade->amount; + + if (fade->amount > 0) + { + if (mo->alpha < fade->destAlpha) + return; + + mo->alpha = fade->destAlpha; + mo->flags |= fade->flagReserve; + P_RemoveThinker(&fade->thinker); + } + else if ((fade->destAlpha < mo->alpha) == 0) + { + mo->alpha = fade->destAlpha; + P_RemoveThinker(&fade->thinker); + + if (fade->destAlpha == 0) + P_RemoveMobj(mo); + } + + /*if (fade->amount <= 0) + { + if (mo->alpha <= fade->destAlpha) + { + mo->alpha = fade->destAlpha; + P_RemoveThinker(&fade->thinker); + + if (fade->destAlpha == 0) + P_RemoveMobj(mo); + } + } + else if (mo->alpha >= fade->destAlpha) + { + mo->alpha = fade->destAlpha; + mo->flags |= fade->flagReserve; + P_RemoveThinker(&fade->thinker); + }*/ +} + +extern mobj_t *P_SpawnMapThing (mapthing_t *mthing); +extern mapthing_t *spawnlist; // 800A5D74 +extern int spawncount; // 800A5D78 + +int EV_SpawnMobjTemplate(int tag) // 8000EB8C +{ + mobj_t *mobj; + fade_t *fade; + mapthing_t *mthing; + int i; + int rtn; + + rtn = 0; + mthing = spawnlist; + for (i = 0; i < spawncount; i++, mthing++) + { + if(mthing->tid != tag) + continue; /* find matching tid */ + + if(!(mobj = P_SpawnMapThing(mthing))) + continue; /* setup spawning */ + + rtn = 1; + if (mobj->type == MT_DEMON2) + { + mobj->alpha = 48; + mobj->flags |= MF_SHADOW; + } + else + { + fade = Z_Malloc (sizeof(*fade), PU_LEVSPEC, NULL); + P_AddThinker (&fade->thinker); + fade->thinker.function = T_FadeThinker; + fade->mobj = mobj; + fade->amount = 8; + fade->destAlpha = mobj->alpha; + fade->flagReserve = mobj->flags & (MF_SPECIAL|MF_SOLID|MF_SHOOTABLE); + + if (mobj->flags & MF_SHOOTABLE) + { + mobj->flags &= ~MF_SHOOTABLE; + } + else + { + mobj->flags &= ~(MF_SPECIAL|MF_SOLID|MF_SHOOTABLE); + } + mobj->alpha = 0; + } + + S_StartSound(mobj, sfx_spawn); + } + + return rtn; +} + +int EV_FadeOutMobj(int tag) // 8000ED08 +{ + fade_t *fade; + mobj_t *mo; + mobj_t *pmVar1; + int rtn; + + rtn = 0; + + for (mo=mobjhead.next ; mo != &mobjhead ; mo=mo->next) + { + if(tag != mo->tid) + continue; /* not matching the tid */ + + rtn = 1; + mo->flags &= ~(MF_SPECIAL|MF_SOLID|MF_SHOOTABLE); + + fade = Z_Malloc (sizeof(*fade), PU_LEVSPEC, 0); + P_AddThinker (&fade->thinker); + fade->thinker.function = T_FadeThinker; + fade->mobj = mo; + fade->amount = -8; + fade->destAlpha = 0; + } + + return rtn; +} + +void T_Quake(quake_t *quake) // 8000EDE8 +{ + if((--quake->tics) == 0) + { + S_StopSound(NULL, sfx_quake); + quakeviewy = 0; + quakeviewx = 0; + P_RemoveThinker(&quake->thinker); + return; + } + + quakeviewy = (((P_Random() & 1) << 18) - (2*FRACUNIT)); + quakeviewx = (((P_Random() & 1) << 24) - (128*FRACUNIT)); +} + +void P_SpawnQuake(int tics) // 8000EE7C +{ + quake_t *quake; + + quake = Z_Malloc (sizeof(*quake), PU_LEVSPEC, 0); + P_AddThinker (&quake->thinker); + quake->thinker.function = T_Quake; + quake->tics = tics; + + S_StopSound(NULL, sfx_quake); +} + +int P_RandomLineTrigger(line_t *line,mobj_t *thing) // 8000EEE0 +{ + line_t *li; + int line_idx[16]; + int i, count; + + if (activemacro) + return 0; + + count = 0; + + li = lines; + for(i = 0; ((i < numlines)&&(count < 16)); i++, li++) + { + /* special 240 -> Execute random line trigger */ + if(((line->tag == li->tag) && (li != line)) && (SPECIALMASK(li->special) != 240)) + { + line_idx[count] = i; + count++; + } + } + + if(!count) + return 0; + + return P_UseSpecialLine(&lines[line_idx[P_Random()%count]], thing); +} + +#define CAMMOVESPEED 164 +#define CAMTRACEANGLE ANG1 + +void T_MoveCamera(movecamera_t *camera) // 8000F014 +{ + angle_t delta; + angle_t newangle; + angle_t angle; + int dist; + mobj_t *mo; + + int iVar1; + + /* adjust angle */ + newangle = R_PointToAngle2(cameratarget->x, cameratarget->y, camera->x, camera->y); + angle = cameratarget->angle; + delta = newangle - angle; + if ((delta < CAMTRACEANGLE) || (delta > -CAMTRACEANGLE)) { + cameratarget->angle = newangle; + } + else if (delta < ANG180) { + cameratarget->angle = angle + CAMTRACEANGLE; + } + else { + cameratarget->angle = angle - CAMTRACEANGLE; + } + + /* adjust pitch */ + dist = P_AproxDistance(cameratarget->x - camera->x, cameratarget->y - camera->y); + if(dist >= (48*FRACUNIT)) + { + newangle = R_PointToAngle2(0, cameratarget->z, dist, camera->z); + angle = camviewpitch; + delta = newangle - angle; + if ((delta < CAMTRACEANGLE) || (delta > -CAMTRACEANGLE)) { + camviewpitch = newangle; + } + else if (delta < ANG180) { + camviewpitch = angle + CAMTRACEANGLE; + } + else { + camviewpitch = angle - CAMTRACEANGLE; + } + } + + /* adjust camera position */ + + camera->tic++; + if (camera->tic < CAMMOVESPEED) + { + cameratarget->x = cameratarget->x + camera->slopex; + cameratarget->y = cameratarget->y + camera->slopey; + cameratarget->z = cameratarget->z + camera->slopez; + return; + } + + /* jump to next camera spot */ + for(mo = mobjhead.next; mo != &mobjhead; mo = mo->next) + { + if(camera->current != mo->tid) + continue; /* must match tid */ + + if(mo->type != MT_CAMERA) + continue; /* not a camera */ + + camera->slopex = (mo->x - cameratarget->x) / CAMMOVESPEED; + camera->slopey = (mo->y - cameratarget->y) / CAMMOVESPEED; + camera->slopez = (mo->z - cameratarget->z) / CAMMOVESPEED; + + camera->tic = 0; + camera->current++; + return; + } +} + +void P_SetMovingCamera(line_t *line) // 8000F2F8 +{ + movecamera_t *camera; + mobj_t *mo; + + camera = Z_Malloc (sizeof(*camera), PU_LEVSPEC, 0); + P_AddThinker (&camera->thinker); + camera->thinker.function = T_MoveCamera; + + for(mo = mobjhead.next; mo != &mobjhead; mo = mo->next) + { + if(mo->tid != line->tag) + continue; /* not matching the tid */ + + if(mo->type != MT_CAMERA) + continue; /* not a camera */ + + /* setup moving camera */ + camera->x = mo->x; + camera->y = mo->y; + camera->z = mo->z; + camera->tic = CAMMOVESPEED; + camera->current = mo->tid + 1; + + /* set camera target */ + mo->angle = cameratarget->angle; + mo->x = cameratarget->x; + mo->y = cameratarget->y; + cameratarget = mo; + return; + } +} + +void P_RefreshBrightness(void) // 8000f410 +{ + int factor; + + factor = brightness + 100; + if (factor < infraredFactor) { + factor = infraredFactor; + } + + P_SetLightFactor(factor); +} + +extern maplights_t *maplights; // 800A5EA4 + +void P_SetLightFactor(int lightfactor) // 8000F458 +{ + register u32 fpstat, fpstatset; + + float l_flt; + light_t *light; + maplights_t *maplight; + int base_r, base_g, base_b; + int r, g, b; + int h, s, v; + int factor; + int i; + + maplight = maplights; + light = lights; + for(i = 0; i < numlights; i++) + { + if (i > 255) + { + LightGetHSV(maplight->r, maplight->g, maplight->b, &h, &s, &v); + maplight++; + factor = v; + } + else + { + factor = i; + } + + // fetch the current floating-point control/status register + fpstat = __osGetFpcCsr(); + // enable round to negative infinity for floating point + fpstatset = (fpstat | FPCSR_RM_RM) ^ 2; + // _Disable_ unimplemented operation exception for floating point. + __osSetFpcCsr(fpstatset); + + l_flt = (float)factor * ((float)lightfactor / 100.0); + + v = (int)l_flt; + if (v > 255) { + v = 255; + } + + if (i > 255) + { + LightGetRGB(h, s, v, &r, &g, &b); + base_r = r; + base_g = g; + base_b = b; + /*base_r = maplight->r; + base_g = maplight->g; + base_b = maplight->b; + maplight++;*/ + } + else + { + base_r = v; + base_g = v; + base_b = v; + + /* base_r = i; + base_g = i; + base_b = i;*/ + } + + // [GEC] New Cheat Codes + if (players[0].cheats & CF_FULLBRIGHT) + { + base_r = 255; + base_g = 255; + base_b = 255; + } + else if (players[0].cheats & CF_NOCOLORS) + { + base_r = v & 255; + base_g = v & 255; + base_b = v & 255; + } + + light->rgba = PACKRGBA(base_r, base_g, base_b, 255); + light++; + } +} + +void T_FadeInBrightness(fadebright_t *fb) // 8000f610 +{ + fb->factor += 2; + if (fb->factor >= (brightness + 100)) + { + fb->factor = (brightness + 100); + P_RemoveThinker(&fb->thinker); + } + + P_SetLightFactor(fb->factor); +} + +int P_ModifyMobjFlags(int tid, int flags) // 8000F674 +{ + mobj_t *mo; + int ok; + + ok = 0; + for(mo = mobjhead.next; mo != &mobjhead; mo = mo->next) + { + if(mo->tid != tid) + continue; /* not matching the tid */ + + ok = 1; + mo->flags &= ~flags; + } + + return ok; +} + +int P_AlertTaggedMobj(int tid, mobj_t *activator) // 8000F6C4 +{ + mobj_t *mo; + state_t *st; + int ok; + + ok = 0; + for(mo = mobjhead.next; mo != &mobjhead; mo = mo->next) + { + if(mo->tid != tid) + continue; /* not matching the tid */ + + if(mo->info->seestate == S_000) + continue; + + mo->threshold = 0; + mo->target = activator; + ok = 1; + + st = &states[mo->info->seestate]; + + mo->state = st; + mo->tics = st->tics; + mo->sprite = st->sprite; + mo->frame = st->frame; + } + + return ok; +} + +void T_MobjExplode(mobjexp_t *exp) // 8000F76C +{ + fixed_t x; + fixed_t y; + fixed_t z; + mobj_t *mo; + + if((--exp->delay) <= 0) + { + exp->delay = exp->delaydefault; + + x = (((P_Random() - P_Random()) << 14) + exp->mobj->x); + y = (((P_Random() - P_Random()) << 14) + exp->mobj->y); + z = (((P_Random() - P_Random()) << 14) + exp->mobj->z); + + mo = P_SpawnMobj(x, y, z + (exp->mobj->info->height >> 1), MT_EXPLOSION2); + + if((exp->lifetime & 1)) + S_StartSound(mo, sfx_explode); + + if((--exp->lifetime) == 0) + { + P_RemoveThinker(&exp->thinker); + } + } +} diff --git a/Doom 64/p_mobj.c b/Doom 64/p_mobj.c @@ -0,0 +1,570 @@ +/* P_mobj.c */ + +#include "doomdef.h" +#include "p_local.h" +#include "sounds.h" + +void G_PlayerReborn (int player); + +extern mobj_t *cameratarget; // 800A5D70 +extern mapthing_t *spawnlist; // 800A5D74 +extern int spawncount; // 800A5D78 + +/* +=============== += += P_SpawnMobj += +=============== +*/ + +mobj_t *P_SpawnMobj (fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) // 80018a20 +{ + mobj_t *mobj; + state_t *st; + mobjinfo_t *info; + + mobj = Z_Malloc (sizeof(*mobj), PU_LEVEL, NULL); + + D_memset (mobj, 0, sizeof (*mobj)); + info = &mobjinfo[type]; + + mobj->type = type; + mobj->info = info; + mobj->x = x; + mobj->y = y; + mobj->radius = info->radius; + mobj->height = info->height; + mobj->flags = info->flags; + mobj->health = info->spawnhealth; + mobj->reactiontime = info->reactiontime; + mobj->alpha = info->alpha; + + /* do not set the state with P_SetMobjState, because action routines can't */ + /* be called yet */ + st = &states[info->spawnstate]; + + mobj->state = st; + mobj->tics = st->tics; + mobj->sprite = st->sprite; + mobj->frame = st->frame; + + /* set subsector and/or block links */ + P_SetThingPosition (mobj); + + mobj->floorz = mobj->subsector->sector->floorheight; + mobj->ceilingz = mobj->subsector->sector->ceilingheight; + if (z == ONFLOORZ) + mobj->z = mobj->floorz; + else if (z == ONCEILINGZ) + mobj->z = mobj->ceilingz - mobj->info->height; + else + mobj->z = z; + + /* */ + /* link into the mobj list */ + /* */ + mobjhead.prev->next = mobj; + mobj->next = &mobjhead; + mobj->prev = mobjhead.prev; + mobjhead.prev = mobj; + + if((mobj->flags & MF_COUNTKILL) != 0) + totalkills++; + + if((mobj->flags & MF_COUNTITEM) != 0) + totalitems++; + + return mobj; +} + +/* +================= += += P_SpawnMapThing += += The fields of the mapthing should already be in host byte order +================== +*/ + +extern mobj_t* checkthing; +extern int testflags; +extern fixed_t testradius; +extern fixed_t testx; +extern fixed_t testy; + +extern boolean PB_CheckPosition(void); + +mobj_t *P_SpawnMapThing (mapthing_t *mthing) // 80018C24 +{ + int i, bit; + mobj_t *mobj; + fixed_t x,y,z; + mobj_t tmp_mobj; + + if (mthing->type == MAXPLAYERS) + { + playerstarts[0] = *mthing; + return NULL; + } + + /*if (gameskill == sk_baby) + bit = 1; + else if (gameskill == sk_nightmare) + bit = 4; + else + bit = 1<<(gameskill-1);*/ + + if (gameskill == sk_baby || gameskill == sk_easy) + bit = 1; + else if (gameskill == sk_medium) + bit = 2; + else if (gameskill == sk_hard) + bit = 4; + + if (!(mthing->options & bit) ) + return NULL; + + /* find which type to spawn */ + for (i = 0; i < NUMMOBJTYPES; i++) + { + if (mthing->type == mobjinfo[i].doomednum) + break; + } + + if (i==NUMMOBJTYPES) + { + I_Error ("P_SpawnMapThing: Unknown type %d at (%d, %d)",mthing->type , mthing->x, mthing->y); + } + + // + // [d64] check if spawn is valid + // + if((mobjinfo[i].flags & MF_SOLID) != 0) + { + checkthing = &tmp_mobj; + testflags = mobjinfo[i].flags; + testradius = mobjinfo[i].radius; + testx = mthing->x << FRACBITS; + testy = mthing->y << FRACBITS; + + if(!PB_CheckPosition()) + return NULL; + } + + // [d64]: queue mobj for spawning later + if(mthing->options & MTF_SPAWN) + { + mthing->options &= ~MTF_SPAWN; + D_memcpy(&spawnlist[spawncount], mthing, sizeof(mapthing_t)); + spawncount += 1; + + return NULL; + } + + /* spawn it */ + x = mthing->x << FRACBITS; + y = mthing->y << FRACBITS; + if (mobjinfo[i].flags & MF_SPAWNCEILING) + z = ONCEILINGZ; + else + z = ONFLOORZ; + + mobj = P_SpawnMobj (x,y,z, i); + mobj->z += (mthing->z << FRACBITS); + mobj->angle = ANG45 * (mthing->angle/45); + mobj->tid = mthing->tid; + + if (mobj->tics > 0) + mobj->tics = 1 + (P_Random () % mobj->tics); + + if (mthing->options & MTF_AMBUSH) + mobj->flags |= MF_AMBUSH; + + if (mthing->options & MTF_ONTOUCH) + mobj->flags |= MF_TRIGTOUCH; + + if (mthing->options & MTF_ONDEATH) + mobj->flags |= MF_TRIGDEATH; + + if (mthing->options & MTF_SECRET) + { + mobj->flags |= MF_COUNTSECRET; + totalsecret++; + } + + if (mthing->options & MTF_NOINFIGHTING) + mobj->flags |= MF_NOINFIGHTING; + + return mobj; +} + +/* +============ += += P_SpawnPlayer += += Called when a player is spawned on the level += Most of the player structure stays unchanged between levels +============ +*/ + +void P_SpawnPlayer(/*mapthing_t *mthing*/) // 80018F94 +{ + player_t *p; + fixed_t x,y,z; + mobj_t *mobj; + int i; + int levelnum; + int skill; + + //if (!playeringame[mthing->type-1]) + //return; /* not playing */ + + p = &players[0]; + + if (p->playerstate == PST_REBORN) + G_PlayerReborn(0); + else + { + p->killcount = 0; + p->secretcount = 0; + p->itemcount = 0; + } + + x = playerstarts[0].x << FRACBITS; + y = playerstarts[0].y << FRACBITS; + + z = ONFLOORZ; + mobj = P_SpawnMobj (x,y,z, MT_PLAYER); + + mobj->angle = ANG45 * (playerstarts[0].angle/45); + mobj->player = p; + mobj->health = p->health; + mobj->tid = playerstarts[0].tid; + mobj->z = mobj->z + (playerstarts[0].z << FRACBITS); + p->mo = mobj; + p->playerstate = PST_LIVE; + p->refire = 0; + p->message = NULL; + p->messagetic = 0; + p->damagecount = 0; + p->bonuscount = 0; + p->extralight = 0; + p->bfgcount = 0; + p->viewheight = VIEWHEIGHT; + p->automapscale = 850; + p->viewz = mobj->z + VIEWHEIGHT; + cameratarget = p->mo; + + P_SetupPsprites (0); /* setup gun psprite */ + + if (doPassword != 0) + { + M_DecodePassword(Passwordbuff, &levelnum, &skill, p); + doPassword = false; + } + + ST_InitEveryLevel(); + ST_UpdateFlash(); // ST_doPaletteStuff(); +} + +/* +=============== += += P_RemoveMobj += +=============== +*/ + +void P_RemoveMobj (mobj_t *mobj) // 80019130 +{ + /* unlink from sector and block lists */ + P_UnsetThingPosition (mobj); + + /* unlink from mobj list */ + mobj->next->prev = mobj->prev; + mobj->prev->next = mobj->next; + Z_Free (mobj); +} + +/* +================ += += P_SetMobjState += += Returns true if the mobj is still present +================ +*/ + +boolean P_SetMobjState (mobj_t *mobj, statenum_t state) // 80019184 +{ + state_t *st; + + if (state == S_000) + { + mobj->state = NULL; + P_RemoveMobj (mobj); + return false; + } + + st = &states[state]; + + mobj->state = st; + mobj->tics = st->tics; + mobj->sprite = st->sprite; + mobj->frame = st->frame; + + if (st->action) /* call action functions when the state is set */ + st->action (mobj); + + mobj->latecall = NULL; /* make sure it doesn't come back to life... */ + + return true; +} + +/*============================================================================= */ + +/* +=============================================================================== + + GAME SPAWN FUNCTIONS + +=============================================================================== +*/ + +/* +================ += += P_SpawnPuff += +================ +*/ + +extern fixed_t attackrange; // 800A5704 + +void P_SpawnPuff (fixed_t x, fixed_t y, fixed_t z) // 80019218 +{ + mobj_t *th; + int rnd1, rnd2; + + rnd1 = P_Random(); + rnd2 = P_Random(); + + z += ((rnd2-rnd1)<<10); + th = P_SpawnMobj (x,y,z, MT_SMOKE_SMALL); + th->momz = FRACUNIT; + th->tics -= P_Random()&1; + if (th->tics < 1) + th->tics = 1; + +/* don't make punches spark on the wall */ + if (attackrange == MELEERANGE) + P_SetMobjState (th, S_490); +} + + +/* +================ += += P_SpawnBlood += +================ +*/ + +void P_SpawnBlood (fixed_t x, fixed_t y, fixed_t z, int damage) // 800192B8 +{ + mobj_t *th; + int i; + + for(i = 0; i < 3; i++) + { + x += ((P_Random()-P_Random())<<12); + y += ((P_Random()-P_Random())<<12); + z += ((P_Random()-P_Random())<<11); + th = P_SpawnMobj (x,y,z, MT_BLOOD); + th->momz = FRACUNIT*2; + th->tics -= P_Random()&1; + if (th->tics<1) + th->tics = 1; + if (damage <= 12 && damage >= 9) + P_SetMobjState (th, S_495); + else if (damage < 9) + P_SetMobjState (th, S_496); + } +} + +/* +================ += += P_SpawnMissile += +================ +*/ + +mobj_t *P_SpawnMissile (mobj_t *source, mobj_t *dest, fixed_t xoffs, fixed_t yoffs, fixed_t heightoffs, mobjtype_t type) // 80019410 +{ + mobj_t *th; + angle_t an; + int dist; + int speed; + fixed_t x, y, z; + int rnd1, rnd2; + + x = source->x + xoffs; + y = source->y + yoffs; + z = source->z + heightoffs; + + th = P_SpawnMobj (x, y, z, type); + if (th->info->seesound) + S_StartSound (source, th->info->seesound); + th->target = source; /* where it came from */ + + if ((type == MT_PROJ_BABY) || (type == MT_PROJ_DART)) /* no aim projectile */ + an = source->angle; + else if (dest) + an = R_PointToAngle2(x, y, dest->x, dest->y); + + if (dest && (dest->flags & MF_SHADOW)) + { + rnd1 = P_Random(); + rnd2 = P_Random(); + an += ((rnd2 - rnd1) << 20); + } + + th->angle = an; + an >>= ANGLETOFINESHIFT; + speed = th->info->speed; + th->momx = speed * finecosine[an]; + th->momy = speed * finesine[an]; + + if (dest) + { + dist = P_AproxDistance (dest->x - x, dest->y - y); + dist = dist / (th->info->speed << FRACBITS); + if (dist < 1) + dist = 1; + th->momz = ((dest->z + (dest->height >> 1)) - z) / dist; + } + + if (!P_CheckPosition (th, th->x, th->y)) + P_ExplodeMissile (th); + + return th; +} + + +/* +================ += += P_SpawnPlayerMissile += += Tries to aim at a nearby monster +================ +*/ +extern line_t* shotline; // 800A56FC +extern fixed_t aimfrac; // 800A5720 + +void P_SpawnPlayerMissile (mobj_t *source, mobjtype_t type) // 80019668 +{ + mobj_t *th; + angle_t an; + fixed_t x,y,z, slope; + int speed; + fixed_t missileheight; + int offset; + + // [d64] adjust offset and height based on missile + if(type == MT_PROJ_ROCKET) + { + missileheight = (42*FRACUNIT); + offset = 30; + } + else if(type == MT_PROJ_PLASMA) + { + missileheight = (32*FRACUNIT); + offset = 40; + } + else if(type == MT_PROJ_BFG) + { + missileheight = (32*FRACUNIT); + offset = 30; + } + else + { + missileheight = (32*FRACUNIT); + offset = 0; + } + + /* */ + /* see which target is to be aimed at */ + /* */ + an = source->angle; + slope = P_AimLineAttack (source, an, missileheight, 16*64*FRACUNIT); + if (!linetarget) + { + an += 1<<26; + slope = P_AimLineAttack (source, an, missileheight, 16*64*FRACUNIT); + if (!linetarget) + { + an -= 2<<26; + slope = P_AimLineAttack (source, an, missileheight, 16*64*FRACUNIT); + } + if (!linetarget) + { + an = source->angle; + slope = 0; + } + } + + x = source->x; + y = source->y; + z = source->z; + + th = P_SpawnMobj (x,y,z+missileheight, type); + if (th->info->seesound) + S_StartSound (source, th->info->seesound); + th->target = source; + th->angle = an; + + speed = th->info->speed; + + th->momx = speed * finecosine[an>>ANGLETOFINESHIFT]; + th->momy = speed * finesine[an>>ANGLETOFINESHIFT]; + th->momz = speed * slope; + + x = source->x + (offset * finecosine[an>>ANGLETOFINESHIFT]); + y = source->y + (offset * finesine[an>>ANGLETOFINESHIFT]); + + // [d64]: checking against very close lines? + if((shotline && aimfrac <= 0xC80) || !P_TryMove(th, x, y)) + P_ExplodeMissile(th); +} + + +/* +=================== += += P_ExplodeMissile += +=================== +*/ + +void P_ExplodeMissile (mobj_t *mo) // 800198B8 +{ + if(!P_SetMobjState(mo, mobjinfo[mo->type].deathstate)) + return; + + mo->momx = mo->momy = mo->momz = 0; + + mo->tics -= P_Random()&1; + if (mo->tics < 1) + mo->tics = 1; + + mo->flags &= ~MF_MISSILE; + if (mo->info->deathsound) + { + S_StopSound(mo, 0); + S_StartSound(mo, mo->info->deathsound); + } +} diff --git a/Doom 64/p_move.c b/Doom 64/p_move.c @@ -0,0 +1,747 @@ +#include "doomdef.h" +#include "p_local.h" + +/*================== */ +/* */ +/* out */ +/* */ +/*================== */ + +extern mobj_t *tmthing; // 800A56B0 +extern fixed_t tmx, tmy; // 800A56B4, 800A56B8 +extern boolean checkposonly; // 800A56C8 + +/*================== */ +/* */ +/* in */ +/* */ +/*================== */ + +boolean trymove2; // 800A5D80 /* Result from P_TryMove2 */ +boolean floatok; // 800A5D84 /* if true, move would be ok if within tmfloorz - tmceilingz */ +fixed_t tmfloorz; // 800A5D88 /* Current floor z for P_TryMove2 */ +fixed_t tmceilingz; // 800A5D8C /* Current ceiling z for P_TryMove2 */ +mobj_t *movething; // 800A5D98 /* Either a skull/missile target or a special pickup */ +line_t *blockline; // 800A5D9C /* Might be a door that can be opened */ + +fixed_t oldx, oldy; // 800A5DA0, 800A5DA4 +fixed_t tmbbox[4]; // +int tmflags; // 800A5DB8 +fixed_t tmdropoffz; // 800A5D90 /* Lowest point contacted */ +subsector_t *newsubsec; // 800A5D94 /* Dest subsector */ + +//PSX NEW +line_t *thingspec[8]; // 800A5DE0 +int numthingspec; // 800A5DE0 + +/* +=================== += += P_TryMove2 += += Attempt to move to a new position, crossing special lines unless MF_TELEPORT += is set += +=================== +*/ + +void P_TryMove2(void) // 80019980 +{ + int side; + int oldside; + line_t *line; + + trymove2 = false; // until proven otherwise + floatok = false; + + oldx = tmthing->x; + oldy = tmthing->y; + + PM_CheckPosition(); + + if (checkposonly) + { + checkposonly = false; + return; + } + + if (!trymove2) + return; + + if (!(tmthing->flags & MF_NOCLIP)) + { + trymove2 = false; + + if (tmceilingz - tmfloorz < tmthing->height) + return; // doesn't fit + floatok = true; + if ( !(tmthing->flags&MF_TELEPORT) && tmceilingz - tmthing->z < tmthing->height) + return; // mobj must lower itself to fit + if ( !(tmthing->flags&MF_TELEPORT) && tmfloorz - tmthing->z > 24*FRACUNIT ) + return; // too big a step up + if ( !(tmthing->flags&(MF_DROPOFF|MF_FLOAT)) && tmfloorz - tmdropoffz > 24*FRACUNIT ) + return; // don't stand over a dropoff + } + + // + // the move is ok, so link the thing into its new position + // + P_UnsetThingPosition(tmthing); + + tmthing->floorz = tmfloorz; + tmthing->ceilingz = tmceilingz; + tmthing->x = tmx; + tmthing->y = tmy; + + P_SetThingPosition(tmthing); + + if (!(tmthing->flags & (MF_NOCLIP | MF_TELEPORT))) + { + while (numthingspec > 0) + { + numthingspec--; + line = thingspec[numthingspec]; + + side = P_PointOnLineSide(tmthing->x, tmthing->y, line); + oldside = P_PointOnLineSide(oldx, oldy, line); + + if (side != oldside) + { + if (!(line->flags & ML_TRIGGERFRONT) || (side)) + { + P_UseSpecialLine(line, tmthing); + } + } + } + } + + trymove2 = true; + + return; +} + +/* +================== += += P_PointOnLineSide += += Returns 0 or 1 +================== +*/ + +int P_PointOnLineSide (fixed_t x, fixed_t y, line_t *line) // 80019C24 +{ + fixed_t dx,dy; + fixed_t left, right; + + if (!line->dx) + { + if (x <= line->v1->x) + return line->dy > 0; + return line->dy < 0; + } + if (!line->dy) + { + if (y <= line->v1->y) + return line->dx < 0; + return line->dx > 0; + } + + dx = (x - line->v1->x); + dy = (y - line->v1->y); + + left = (line->dy>>16) * (dx>>16); + right = (dy>>16) * (line->dx>>16); + + if (right < left) + return 0; /* front side */ + return 1; /* back side */ +} + +#if 0 +static boolean PM_CrossCheck(line_t *ld) +{ + if (PM_BoxCrossLine (ld)) { + if (!PIT_CheckLine(ld)) { + return true; + } + } + return false; +} + +/* +================== += += PM_PointOnLineSide += Exclusive Psx Doom += += Returns 0 or 1 += +================== +*/ + +int PM_PointOnLineSide(fixed_t x, fixed_t y, line_t *line)//L8001EB8C() +{ + fixed_t dx, dy; + fixed_t left, right; + + dx = (x - line->v1->x); + dy = (y - line->v1->y); + + left = (line->dy >> 16) * (dx >> 16); + right = (dy >> 16) *(line->dx >> 16); + + if (right < left) + return 0; /* front side */ + return 1; /* back side */ +} +#endif + +/* +=============================================================================== + + THING POSITION SETTING + +=============================================================================== +*/ + +/* +=================== += += P_UnsetThingPosition += += Unlinks a thing from block map and sectors += +=================== +*/ + +void P_UnsetThingPosition (mobj_t *thing)//L8001C768() +{ + int blockx, blocky; + + if (!(thing->flags & MF_NOSECTOR)) + { /* inert things don't need to be in blockmap */ + /* unlink from subsector */ + if (thing->snext) + thing->snext->sprev = thing->sprev; + if (thing->sprev) + thing->sprev->snext = thing->snext; + else + thing->subsector->sector->thinglist = thing->snext; + } + + if (!(thing->flags & MF_NOBLOCKMAP)) + { /* inert things don't need to be in blockmap */ + /* unlink from block map */ + if (thing->bnext) + thing->bnext->bprev = thing->bprev; + if (thing->bprev) + thing->bprev->bnext = thing->bnext; + else + { + blockx = (thing->x - bmaporgx)>>MAPBLOCKSHIFT; + blocky = (thing->y - bmaporgy)>>MAPBLOCKSHIFT; + + // Prevent buffer overflow if the map object is out of bounds. + // This is part of the fix for the famous 'linedef deletion' bug. + // From PsyDoom (StationDoom) by BodbDearg + #if FIX_LINEDEFS_DELETION == 1 + if (blockx>=0 && blockx <bmapwidth + && blocky>=0 && blocky <bmapheight) + { + blocklinks[blocky*bmapwidth+blockx] = thing->bnext; + } + #else + blocklinks[blocky*bmapwidth+blockx] = thing->bnext; + #endif + } + } +} + + +/* +=================== += += P_SetThingPosition += += Links a thing into both a block and a subsector based on it's x y += Sets thing->subsector properly += +=================== +*/ + +void P_SetThingPosition (mobj_t *thing) // 80019E20 +{ + subsector_t *ss; + sector_t *sec; + int blockx, blocky; + mobj_t **link; + + /* */ + /* link into subsector */ + /* */ + ss = R_PointInSubsector (thing->x,thing->y); + thing->subsector = ss; + if(!(thing->flags & MF_NOSECTOR)) + { + /* invisible things don't go into the sector links */ + sec = ss->sector; + + thing->sprev = NULL; + thing->snext = sec->thinglist; + if(sec->thinglist) + sec->thinglist->sprev = thing; + sec->thinglist = thing; + } + + /* */ + /* link into blockmap */ + /* */ + if(!(thing->flags & MF_NOBLOCKMAP)) + { + /* inert things don't need to be in blockmap */ + blockx = (thing->x - bmaporgx)>>MAPBLOCKSHIFT; + blocky = (thing->y - bmaporgy)>>MAPBLOCKSHIFT; + if(blockx >= 0 && blockx < bmapwidth && blocky >= 0 && blocky < bmapheight) + { + link = &blocklinks[blocky*bmapwidth+blockx]; + thing->bprev = NULL; + thing->bnext = *link; + if (*link) + (*link)->bprev = thing; + *link = thing; + } + else + { + /* thing is off the map */ + thing->bnext = thing->bprev = NULL; + } + } +} + +/* +================== += += PM_CheckPosition += += This is purely informative, nothing is modified (except things picked up) + +in: +tmthing a mobj_t (can be valid or invalid) +tmx,tmy a position to be checked (doesn't need relate to the mobj_t->x,y) + +out: + +newsubsec +floorz +ceilingz +tmdropoffz the lowest point contacted (monsters won't move to a dropoff) +movething + +================== +*/ + +void PM_CheckPosition (void) // 80019F50 +{ + int xl,xh,yl,yh,bx,by; + + tmflags = tmthing->flags; + + tmbbox[BOXTOP] = tmy + tmthing->radius; + tmbbox[BOXBOTTOM] = tmy - tmthing->radius; + tmbbox[BOXRIGHT] = tmx + tmthing->radius; + tmbbox[BOXLEFT] = tmx - tmthing->radius; + + newsubsec = R_PointInSubsector(tmx,tmy); + + // + // the base floor / ceiling is from the subsector that contains the + // point. Any contacted lines the step closer together will adjust them + // + tmfloorz = tmdropoffz = newsubsec->sector->floorheight; + tmceilingz = newsubsec->sector->ceilingheight; + + ++validcount; + + numthingspec = 0;//PSX + movething = NULL; + blockline = NULL; + + if (tmflags & MF_NOCLIP) + { + trymove2 = true; + return; + } + + // + // check things first, possibly picking things up + // the bounding box is extended by MAXRADIUS because mobj_ts are grouped + // into mapblocks based on their origin point, and can overlap into adjacent + // blocks by up to MAXRADIUS units + // + // [D64] no use MAXRADIUS + // + xl = (tmbbox[BOXLEFT] - bmaporgx/* - MAXRADIUS*/)>>MAPBLOCKSHIFT; + xh = (tmbbox[BOXRIGHT] - bmaporgx/* + MAXRADIUS*/)>>MAPBLOCKSHIFT; + yl = (tmbbox[BOXBOTTOM] - bmaporgy/* - MAXRADIUS*/)>>MAPBLOCKSHIFT; + yh = (tmbbox[BOXTOP] - bmaporgy/* + MAXRADIUS*/)>>MAPBLOCKSHIFT; + + if (xl<0) + xl = 0; + if (yl<0) + yl = 0; + if (xh>= bmapwidth) + xh = bmapwidth -1; + if (yh>= bmapheight) + yh = bmapheight -1; + + for (bx = xl; bx <= xh; bx++) + { + for (by = yl; by <= yh; by++) + { + if (!PM_BlockThingsIterator(bx, by)) + { + trymove2 = false; + return; + } + } + } + + // + // check lines + // + xl = (tmbbox[BOXLEFT] - bmaporgx)>>MAPBLOCKSHIFT; + xh = (tmbbox[BOXRIGHT] - bmaporgx)>>MAPBLOCKSHIFT; + yl = (tmbbox[BOXBOTTOM] - bmaporgy)>>MAPBLOCKSHIFT; + yh = (tmbbox[BOXTOP] - bmaporgy)>>MAPBLOCKSHIFT; + + if (xl<0) + xl = 0; + if (yl<0) + yl = 0; + if (xh>= bmapwidth) + xh = bmapwidth -1; + if (yh>= bmapheight) + yh = bmapheight -1; + + for (bx = xl; bx <= xh; bx++) + { + for (by = yl; by <= yh; by++) + { + if (!PM_BlockLinesIterator(bx, by)) + { + trymove2 = false; + return; + } + } + } + + trymove2 = true; + return; +} + +//============================================================================= + + +/* +================= += += PM_BoxCrossLine += +================= +*/ +boolean PM_BoxCrossLine (line_t *ld) // 8001A280 +{ + boolean side1, side2; + + if (tmbbox[BOXRIGHT] <= ld->bbox[BOXLEFT] + || tmbbox[BOXLEFT] >= ld->bbox[BOXRIGHT] + || tmbbox[BOXTOP] <= ld->bbox[BOXBOTTOM] + || tmbbox[BOXBOTTOM] >= ld->bbox[BOXTOP] ) + return false; + + switch(ld->slopetype) + { + case ST_HORIZONTAL: + side1 = (ld->bbox[BOXTOP] < tmbbox[BOXTOP]); + side2 = (ld->bbox[BOXTOP] < tmbbox[BOXBOTTOM]); + break; + + case ST_VERTICAL: + side1 = (ld->bbox[BOXLEFT] < tmbbox[BOXRIGHT]); + side2 = (ld->bbox[BOXLEFT] < tmbbox[BOXLEFT]); + break; + + case ST_POSITIVE: + side1 = P_PointOnLineSide(tmbbox[BOXLEFT], tmbbox[BOXTOP], ld); + side2 = P_PointOnLineSide(tmbbox[BOXRIGHT], tmbbox[BOXBOTTOM], ld); + break; + + case ST_NEGATIVE: + side1 = P_PointOnLineSide(tmbbox[BOXRIGHT], tmbbox[BOXTOP], ld); + side2 = P_PointOnLineSide(tmbbox[BOXLEFT], tmbbox[BOXBOTTOM], ld); + break; + + default: + break; + } + + return (0 < (side1 ^ side2)); +} + +//============================================================================= + + +/* +================== += += PIT_CheckLine += += Adjusts tmfloorz and tmceilingz as lines are contacted +================== +*/ + +boolean PIT_CheckLine (line_t *ld) // 8001A3DC +{ + fixed_t pm_opentop, pm_openbottom; + fixed_t pm_lowfloor; + sector_t *front, *back; + + // a line has been hit + + /* + = + = The moving thing's destination position will cross the given line. + = If this should not be allowed, return false. + */ + if (!ld->backsector) + return false; // one sided line + + if (!(tmthing->flags & MF_MISSILE) ) + { + if ( ld->flags & ML_BLOCKING ) + return false; // explicitly blocking everything + if ( !tmthing->player && ld->flags & ML_BLOCKMONSTERS ) + return false; // block monsters only + } + + front = ld->frontsector; + back = ld->backsector; + + if (front->ceilingheight == front->floorheight + || back->ceilingheight == back->floorheight) + { + blockline = ld; + return false; // probably a closed door + } + + if (front->ceilingheight < back->ceilingheight) + pm_opentop = front->ceilingheight; + else + pm_opentop = back->ceilingheight; + + if (front->floorheight > back->floorheight) + { + pm_openbottom = front->floorheight; + pm_lowfloor = back->floorheight; + } + else + { + pm_openbottom = back->floorheight; + pm_lowfloor = front->floorheight; + } + + // adjust floor / ceiling heights + if (pm_opentop < tmceilingz) + tmceilingz = pm_opentop; + if (pm_openbottom > tmfloorz) + tmfloorz = pm_openbottom; + if (pm_lowfloor < tmdropoffz) + tmdropoffz = pm_lowfloor; + + // if contacted a special line, add it to the list + if(ld->special & MLU_CROSS) + { + //New Psx Doom + if (numthingspec < MAXTHINGSPEC) + { + thingspec[numthingspec] = ld; + numthingspec++; + } + } + + return true; +} + +/* +================== += += PIT_CheckThing += +================== +*/ + +boolean PIT_CheckThing(mobj_t *thing) // 8001A560 +{ + fixed_t blockdist; + fixed_t x, y; + fixed_t rx, ry; + + if (thing == tmthing) + return true; // don't clip against self + + if (!(thing->flags & (MF_SOLID|MF_SPECIAL|MF_SHOOTABLE) )) + return true; + + blockdist = thing->radius + tmthing->radius; + + /*delta = thing->x - tmx; + if (delta < 0) + delta = -delta; + if (delta >= blockdist) + return true; // didn't hit it + + delta = thing->y - tmy; + if (delta < 0) + delta = -delta; + if (delta >= blockdist) + return true; // didn't hit it + + if (thing == tmthing) + return true; // don't clip against self*/ + + // [d64]: different logic versus Jaguar Doom + x = abs(thing->x - tmx); + y = abs(thing->y - tmy); + + rx = blockdist - x; + ry = blockdist - x; + + if(!(x < y)) + { + if(((rx - y) + (y >> 1)) <= 0) + return true; // didn't hit it + } + else + { + if(((ry - y) + (x >> 1)) <= 0) + return true; // didn't hit it + } + + // + // check for skulls slamming into things + // + if (tmthing->flags & MF_SKULLFLY) + { + movething = thing; + return false; // stop moving + } + + // + // missiles can hit other things + // + if (tmthing->flags & MF_MISSILE) + { + // see if it went over / under + if (tmthing->z > thing->z + thing->height) + return true; // overhead + if (tmthing->z+tmthing->height < thing->z) + return true; // underneath + if (tmthing->target->type == thing->type) // don't hit same species as originator + { + if (thing == tmthing->target) + return true; + if (thing->type != MT_PLAYER) // let players missile other players + return false; // explode, but do no damage + } + if (! (thing->flags & MF_SHOOTABLE) ) + return !(thing->flags & MF_SOLID); // didn't do any damage + + // damage / explode + movething = thing; + return false; // don't traverse any more + } + + // + // check for special pickup + // + if ((thing->flags&MF_SPECIAL) && (tmflags&MF_PICKUP) ) + { + movething = thing; + return true; + } + + return !(thing->flags & MF_SOLID); +} + +/* +=============================================================================== + +BLOCK MAP ITERATORS + +For each line/thing in the given mapblock, call the passed function. +If the function returns false, exit with false without checking anything else. + +=============================================================================== +*/ + +/* +================== += += PM_BlockLinesIterator += Exclusive Psx Doom / Doom 64 += += The validcount flags are used to avoid checking lines += that are marked in multiple mapblocks, so increment validcount before += the first call to PM_BlockLinesIterator, then make one or more calls to it += +================== +*/ + +boolean PM_BlockLinesIterator(int x, int y) // 8001A710 +{ + int offset; + short *list; + line_t *ld; + + offset = (y*bmapwidth)+x; + offset = *(blockmap + offset); + + for (list = blockmaplump + offset; *list != -1; list++) + { + ld = &lines[*list]; + if (ld->validcount == validcount) + continue; /* line has already been checked */ + ld->validcount = validcount; + + if (PM_BoxCrossLine(ld)) + { + if (!PIT_CheckLine(ld)) + return false; + } + } + + return true; /* everything was checked */ +} + +/* +================== += += PM_BlockThingsIterator += Exclusive Psx Doom / Doom 64 += +================== +*/ + +boolean PM_BlockThingsIterator(int x, int y) // 8001A810 +{ + mobj_t *mobj; + + for (mobj = blocklinks[y * bmapwidth + x]; mobj; mobj = mobj->bnext) + { + if (!PIT_CheckThing(mobj)) + return false; + } + + return true; +} diff --git a/Doom 64/p_plats.c b/Doom 64/p_plats.c @@ -0,0 +1,298 @@ +/*================================================================== */ +/*================================================================== */ +/* */ +/* PLATFORM RAISING */ +/* */ +/*================================================================== */ +/*================================================================== */ +#include "doomdef.h" +#include "p_local.h" + +plat_t *activeplats[MAXPLATS];//80097a24 + +/*================================================================== */ +/* */ +/* Move a plat up and down */ +/* */ +/*================================================================== */ +void T_PlatRaise(plat_t *plat) // 8001A890 +{ + result_e res; + + switch(plat->status) + { + case up: + res = T_MovePlane(plat->sector,plat->speed, plat->high,plat->crush,0,1); + + if (plat->type == raiseAndChange || plat->type == raiseToNearestAndChange) + { + if (!(gametic&7)) + S_StartSound((mobj_t *)&plat->sector->soundorg,sfx_secmove); + } + + //if (res == crushed && (!plat->crush)) + // + // [d64] crushed and crush is no longer used. + // more likely to avoid confusion with ceilings + // + if(res == stop) + { + plat->count = plat->wait; + plat->status = down; + S_StartSound((mobj_t *)&plat->sector->soundorg,sfx_pstart); + } + else + { + if (res == pastdest) + { + plat->count = plat->wait; + plat->status = waiting; + S_StartSound((mobj_t *)&plat->sector->soundorg,sfx_pstop); + switch(plat->type) + { + case raiseAndChange: + case raiseToNearestAndChange: + case downWaitUpStay: + case blazeDWUS: + case customDownUp: + case customDownUpFast: + P_RemoveActivePlat(plat); + break; + default: + break; + } + } + } + break; + case down: + res = T_MovePlane(plat->sector,plat->speed,plat->low,false,0,-1); + if (res == pastdest) + { + plat->count = plat->wait; + plat->status = waiting; + S_StartSound((mobj_t *)&plat->sector->soundorg,sfx_pstop); + switch(plat->type) + { + case upWaitDownStay: + case blazeUWDS: + case customUpDown: + case customUpDownFast: + P_RemoveActivePlat(plat); + break; + default: + break; + } + } + break; + case waiting: + if (!--plat->count) + { + if (plat->sector->floorheight == plat->low) + plat->status = up; + else + plat->status = down; + S_StartSound((mobj_t *)&plat->sector->soundorg,sfx_pstart); + } + case in_stasis: + break; + } +} + +/*================================================================== */ +/* */ +/* Do Platforms */ +/* "amount" is only used for SOME platforms. */ +/* */ +/*================================================================== */ +int EV_DoPlat(line_t *line,plattype_e type,int amount) // 8001AA94 +{ + plat_t *plat; + int secnum; + int rtn; + sector_t *sec; + + secnum = -1; + rtn = 0; + + /* */ + /* Activate all <type> plats that are in_stasis */ + /* */ + switch(type) + { + case perpetualRaise: + P_ActivateInStasis(line->tag); + break; + default: + break; + } + + while ((secnum = P_FindSectorFromLineTag(line->tag,secnum)) >= 0) + { + sec = &sectors[secnum]; + if (sec->specialdata) + continue; + + /* */ + /* Find lowest & highest floors around sector */ + /* */ + rtn = 1; + plat = Z_Malloc( sizeof(*plat), PU_LEVSPEC, 0); + P_AddThinker(&plat->thinker); + + plat->type = type; + plat->sector = sec; + plat->sector->specialdata = plat; + plat->thinker.function = T_PlatRaise; + plat->crush = false; + plat->tag = line->tag; + switch(type) + { + case raiseToNearestAndChange: + plat->speed = PLATSPEED/2; + sec->floorpic = sides[line->sidenum[0]].sector->floorpic; + plat->high = P_FindNextHighestFloor(sec,sec->floorheight); + plat->wait = 0; + plat->status = up; + sec->special = 0; /* NO MORE DAMAGE, IF APPLICABLE */ + S_StartSound((mobj_t *)&sec->soundorg,sfx_secmove); + break; + case raiseAndChange: + plat->speed = PLATSPEED/2; + sec->floorpic = sides[line->sidenum[0]].sector->floorpic; + plat->high = sec->floorheight + amount*FRACUNIT; + plat->wait = 0; + plat->status = up; + S_StartSound((mobj_t *)&sec->soundorg,sfx_secmove); + break; + case downWaitUpStay: + case blazeDWUS: + if (type == blazeDWUS) + plat->speed = PLATSPEED*8; + else + plat->speed = PLATSPEED*4; + plat->low = P_FindLowestFloorSurrounding(sec); + if (plat->low > sec->floorheight) + plat->low = sec->floorheight; + plat->high = sec->floorheight; + plat->wait = 30*PLATWAIT; + plat->status = down; + S_StartSound((mobj_t *)&sec->soundorg,sfx_pstart); + break; + case upWaitDownStay: + case blazeUWDS: + if (type == blazeUWDS) + plat->speed = PLATSPEED*8; + else + plat->speed = PLATSPEED*4; + plat->low = sec->floorheight; + plat->high = P_FindHighestFloorSurrounding(sec); + plat->wait = 30*PLATWAIT; + plat->status = up; + S_StartSound((mobj_t *)&sec->soundorg,sfx_pstart); + break; + case customDownUp: + case customDownUpFast: + if (type == customDownUpFast) + plat->speed = PLATSPEED*8; + else + plat->speed = PLATSPEED*4; + plat->low = sec->floorheight - (macrointeger * FRACUNIT); + plat->high = sec->floorheight; + plat->wait = 30*PLATWAIT; + plat->status = down; + S_StartSound((mobj_t *)&sec->soundorg,sfx_pstart); + break; + case customUpDown: + case customUpDownFast: + if (type == customUpDownFast) + plat->speed = PLATSPEED*8; + else + plat->speed = PLATSPEED*4; + plat->low = sec->floorheight; + plat->high = sec->floorheight + (macrointeger * FRACUNIT); + plat->wait = 30*PLATWAIT; + plat->status = up; + S_StartSound((mobj_t *)&sec->soundorg,sfx_pstart); + break; + case perpetualRaise: + plat->speed = PLATSPEED; + plat->low = P_FindLowestFloorSurrounding(sec); + if (plat->low > sec->floorheight) + plat->low = sec->floorheight; + plat->high = P_FindHighestFloorSurrounding(sec); + if (plat->high < sec->floorheight) + plat->high = sec->floorheight; + plat->wait = 30*PLATWAIT; + plat->status = ((P_Random()&1) << 1) + down; + S_StartSound((mobj_t *)&sec->soundorg,sfx_pstart); + break; + } + P_AddActivePlat(plat); + } + return rtn; +} + +void P_ActivateInStasis(int tag) // 8001AE6C +{ + int i; + + for (i = 0;i < MAXPLATS;i++) + if (activeplats[i] && + (activeplats[i])->tag == tag && + (activeplats[i])->status == in_stasis) + { + (activeplats[i])->status = (activeplats[i])->oldstatus; + (activeplats[i])->thinker.function = T_PlatRaise; + } +} + +int EV_StopPlat(line_t *line) // 8001AF2C +{ + int j; + int ok; + + ok = 0; + for (j = 0; j < MAXPLATS; j++) + { + if (activeplats[j] && ((activeplats[j])->status != in_stasis) && + ((activeplats[j])->tag == line->tag)) + { + ok = 1; + (activeplats[j])->oldstatus = (activeplats[j])->status; + (activeplats[j])->status = in_stasis; + (activeplats[j])->thinker.function = NULL; + } + } + + return ok; +} + +void P_AddActivePlat(plat_t *plat) // 8001AFF8 +{ + int i; + for (i = 0;i < MAXPLATS;i++) + { + if (activeplats[i] == NULL) + { + activeplats[i] = plat; + return; + } + } + I_Error ("P_AddActivePlat: no more plats!"); +} + +void P_RemoveActivePlat(plat_t *plat) // 8001B050 +{ + int i; + for (i = 0;i < MAXPLATS;i++) + { + if (plat == activeplats[i]) + { + (activeplats[i])->sector->specialdata = NULL; + P_RemoveThinker(&(activeplats[i])->thinker); + activeplats[i] = NULL; + return; + } + } + I_Error ("P_RemoveActivePlat: can't find plat!"); +} diff --git a/Doom 64/p_pspr.c b/Doom 64/p_pspr.c @@ -0,0 +1,1394 @@ +/* P_pspr.c */ + +#include "doomdef.h" +#include "p_local.h" + +#define LOWERSPEED FRACUNIT*7 +#define RAISESPEED FRACUNIT*7 + +#define WEAPONX (0)*FRACUNIT +#define WEAPONBOTTOM (96)*FRACUNIT //old 128 +#define WEAPONTOP (0)*FRACUNIT //old 32 + +#define RECOILPITCH 0x2AA8000 + +#define BFGCELLS 40 /* plasma cells for a bfg attack */ + +#define LASERRANGE (4096*FRACUNIT) +#define LASERAIMHEIGHT (40*FRACUNIT) +#define LASERDISTANCE (30) + +extern int ArtifactLookupTable[8]; + +/*============================================================================= */ + +int ticremainder[MAXPLAYERS]; // 800A5E70 + +/* +================== += += P_SetupPsprites += += Called at start of level for each player +================== +*/ + +void P_SetupPsprites (int curplayer) // 8001B0D0 +{ + int i; + player_t *player; + + ticremainder[curplayer] = 0; + player = &players[curplayer]; + + /* remove all psprites */ + + for (i=0 ; i<NUMPSPRITES ; i++) + { + player->psprites[i].state = NULL; + player->psprites[i].alpha = 255; + } + + /* spawn the gun */ + player->pendingweapon = player->readyweapon; + P_BringUpWeapon (player); +} + +/* +================== += += P_MovePsprites += += Called every tic by player thinking routine +================== +*/ + +void P_MovePsprites (player_t *player) // 8001B14C +{ + int i; + pspdef_t *psp; + state_t *state; + + ticremainder[0] += vblsinframe[0]; + + while (ticremainder[0] >= 2) + { + ticremainder[0] -= 2; + + psp = &player->psprites[0]; + for (i=0 ; i<NUMPSPRITES ; i++, psp++) + { + if ( (state = psp->state) != 0) /* a null state means not active */ + { + /* drop tic count and possibly change state */ + if (psp->tics != -1) /* a -1 tic count never changes */ + { + psp->tics--; + if (!psp->tics) + P_SetPsprite (player, i, psp->state->nextstate); + } + } + } + } + + player->psprites[ps_flash].sx = player->psprites[ps_flashalpha].sx = player->psprites[ps_weapon].sx; + player->psprites[ps_flash].sy = player->psprites[ps_flashalpha].sy = player->psprites[ps_weapon].sy; +} + +/*============================================================================= */ + +/* +================= += += P_NoiseAlert += += If a monster yells at a player, it will alert other monsters to the player += +================= +*/ + +mobj_t *soundtarget; // 800A5E74 + +void P_RecursiveSound (sector_t *sec, int soundblocks) // 8001B254 +{ + int i; + line_t *check; + sector_t *other; + sector_t *front, *back; + + /* wake up all monsters in this sector */ + if (sec->validcount == validcount && sec->soundtraversed <= soundblocks+1) + return; /* already flooded */ + + sec->validcount = validcount; + sec->soundtraversed = soundblocks+1; + sec->soundtarget = soundtarget; + + for (i=0 ;i<sec->linecount ; i++) + { + check = sec->lines[i]; + back = check->backsector; + if (!back) + continue; /* single sided */ + + front = check->frontsector; + if (front->floorheight >= back->ceilingheight || + front->ceilingheight <= back->floorheight || + back->floorheight == back->ceilingheight) // [d64] added this check + continue; /* closed door */ + + if ( front == sec) + other = back; + else + other = front; + + if (check->flags & ML_SOUNDBLOCK) + { + if (!soundblocks) + P_RecursiveSound (other, 1); + } + else + P_RecursiveSound (other, soundblocks); + } +} + + +/* +================= += += P_NoiseAlert += +================= +*/ + +void P_NoiseAlert (player_t *player) // 8001B3A4 +{ + sector_t *sec; + + sec = player->mo->subsector->sector; + + if (player->lastsoundsector == (void *)sec) + return; /* don't bother doing it again here */ + + soundtarget = player->mo; + player->lastsoundsector = (void *)sec; + + validcount++; + P_RecursiveSound (sec, 0); +} + + +/* +================== += += P_SetPsprite += +================== +*/ + +void P_SetPsprite (player_t *player, int position, statenum_t stnum) // 8001B3FC +{ + pspdef_t *psp; + state_t *state; + + psp = &player->psprites[position]; + + do + { + if (!stnum) + { + psp->state = NULL; + break; /* object removed itself */ + } + state = &states[stnum]; + psp->state = state; + psp->tics = state->tics; /* could be 0 */ + + /* call action routine */ + if (state->action) + { + state->action (player, psp); + if (!psp->state) + break; + } + stnum = psp->state->nextstate; + } while (!psp->tics); /* an initial state of 0 could cycle through */ +} + + +/* +=============================================================================== + + PSPRITE ACTIONS + +=============================================================================== +*/ + +/* +=============================================================================== + +PSPRITE ACTIONS + +=============================================================================== +*/ + +weaponinfo_t weaponinfo[NUMWEAPONS] = // 8005AD80 +{ + { /* saw */ +/* ammo */ am_noammo, +/* upstate */ S_708,//S_SAWUP, +/* downstate */ S_707,//S_SAWDOWN, +/* readystate */ S_705,//S_SAW, +/* atkstate */ S_709,//S_SAW1, +/* flashstate */ S_000 //S_NULL + }, + + { /* fist */ +/* ammo */ am_noammo, +/* upstate */ S_714,//S_PUNCHUP, +/* downstate */ S_713,//S_PUNCHDOWN, +/* readystate */ S_712,//S_PUNCH, +/* atkstate */ S_715,//S_PUNCH1, +/* flashstate */ S_000 //S_NULL + }, + + { /* pistol */ +/* ammo */ am_clip, +/* upstate */ S_722,//S_PISTOLUP, +/* downstate */ S_721,//S_PISTOLDOWN, +/* readystate */ S_720,//S_PISTOL, +/* atkstate */ S_724,//S_PISTOL2, +/* flashstate */ S_728 //S_PISTOLFLASH + }, + + { /* shotgun */ +/* ammo */ am_shell, +/* upstate */ S_731,//S_SGUNUP, +/* downstate */ S_730,//S_SGUNDOWN, +/* readystate */ S_729,//S_SGUN, +/* atkstate */ S_733,//S_SGUN2, +/* flashstate */ S_738 //S_SGUNFLASH1 + }, + + { /* super shotgun */ +/* ammo */ am_shell, +/* upstate */ S_741,//S_DSGUNUP, +/* downstate */ S_740,//S_DSGUNDOWN, +/* readystate */ S_739,//S_DSGUN, +/* atkstate */ S_742,//S_DSGUN1, +/* flashstate */ S_752 //S_DSGUNFLASH1 + }, + + { /* chaingun */ +/* ammo */ am_clip, +/* upstate */ S_755,//S_CHAINUP, +/* downstate */ S_754,//S_CHAINDOWN, +/* readystate */ S_753,//S_CHAIN, +/* atkstate */ S_756,//S_CHAIN1, +/* flashstate */ S_759 //S_CHAINFLASH1 + }, + + { /* missile */ +/* ammo */ am_misl, +/* upstate */ S_763,//S_MISSILEUP, +/* downstate */ S_762,//S_MISSILEDOWN, +/* readystate */ S_761,//S_MISSILE, +/* atkstate */ S_764,//S_MISSILE1, +/* flashstate */ S_767 //S_MISSILEFLASH1 + }, + + { /* plasma */ +/* ammo */ am_cell, +/* upstate */ S_773,//S_PLASMAUP, +/* downstate */ S_772,//S_PLASMADOWN, +/* readystate */ S_771,//S_PLASMA, +/* atkstate */ S_775,//S_PLASMA1, +/* flashstate */ S_000 //S_NULL + }, + + { /* bfg */ +/* ammo */ am_cell, +/* upstate */ S_783,//S_BFGUP, +/* downstate */ S_782,//S_BFGDOWN, +/* readystate */ S_781,//S_BFG, +/* atkstate */ S_784,//S_BFG1, +/* flashstate */ S_788 //S_BFGFLASH1 + }, + + { /* laser rifle */ +/* ammo */ am_cell, +/* upstate */ S_793,//S_LASERUP, +/* downstate */ S_792,//S_LASERDOWN, +/* readystate */ S_791,//S_LASER, +/* atkstate */ S_794,//S_LASER1, +/* flashstate */ S_796 //S_LASERFLASH + } +}; + + +/* +================ += += P_BringUpWeapon += += Starts bringing the pending weapon up from the bottom of the screen += Uses player +================ +*/ + +void P_BringUpWeapon (player_t *player) // 8001B4BC +{ + statenum_t new; + + if (player->pendingweapon == wp_nochange) + player->pendingweapon = player->readyweapon; + + if (player->pendingweapon == wp_chainsaw) + S_StartSound(player->mo, sfx_sawup); + else if (player->pendingweapon == wp_plasma) + S_StartSound(player->mo, sfx_electric); + + new = weaponinfo[player->pendingweapon].upstate; + + player->pendingweapon = wp_nochange; + player->psprites[ps_weapon].sx = WEAPONX; + player->psprites[ps_weapon].sy = WEAPONBOTTOM; + player->psprites[ps_flashalpha].alpha = 255; + P_SetPsprite (player, ps_weapon, new); +} + +/* +================ += += P_DropWeapon += += Player died, so put the weapon away +================ +*/ + +void P_DropWeapon (player_t *player) // 8001B580 +{ + P_SetPsprite (player, ps_weapon, weaponinfo[player->readyweapon].downstate); +} + +/* +================ += += P_CheckAmmo += += returns true if there is enough ammo to shoot += if not, selects the next weapon to use +================ +*/ + +boolean P_CheckAmmo (player_t *player) // 8001B5BC +{ + ammotype_t ammo; + int count; + + ammo = weaponinfo[player->readyweapon].ammo; + + if (player->readyweapon == wp_bfg) + count = BFGCELLS; + else if (player->readyweapon == wp_laser) + { + count = ArtifactLookupTable[player->artifacts]; + if (count == 0) + count = 1; + } + else if (player->readyweapon == wp_supershotgun) + count = 2; // Double barrel. + else + count = 1; + + if (ammo == am_noammo || player->ammo[ammo] >= count) + return true; + + /* out of ammo, pick a weapon to change to */ + do + { + if (player->weaponowned[wp_plasma] && player->ammo[am_cell]) + player->pendingweapon = wp_plasma; + else if (player->weaponowned[wp_supershotgun] && player->ammo[am_shell] > 2) + player->pendingweapon = wp_supershotgun; + else if (player->weaponowned[wp_chaingun] && player->ammo[am_clip]) + player->pendingweapon = wp_chaingun; + else if (player->weaponowned[wp_shotgun] && player->ammo[am_shell]) + player->pendingweapon = wp_shotgun; + else if (player->ammo[am_clip]) + player->pendingweapon = wp_pistol; + else if (player->weaponowned[wp_chainsaw]) + player->pendingweapon = wp_chainsaw; + else if (player->weaponowned[wp_missile] && player->ammo[am_misl]) + player->pendingweapon = wp_missile; + else if (player->weaponowned[wp_bfg] && player->ammo[am_cell]>40) + player->pendingweapon = wp_bfg; + else + player->pendingweapon = wp_fist; + } while (player->pendingweapon == wp_nochange); + + P_SetPsprite (player, ps_weapon, weaponinfo[player->readyweapon].downstate); + + return false; +} + + +/* +================ += += P_FireWeapon += +================ +*/ + +void P_FireWeapon (player_t *player) // 8001B7CC +{ + statenum_t new; + + if (!P_CheckAmmo (player)) + return; + + P_SetMobjState (player->mo, S_006/*S_PLAY_ATK1*/); + + player->psprites[ps_weapon].sx = WEAPONX; + player->psprites[ps_weapon].sy = WEAPONTOP; + new = weaponinfo[player->readyweapon].atkstate; + P_SetPsprite (player, ps_weapon, new); + P_NoiseAlert (player); +} + +/* +================= += += A_WeaponReady += += The player can fire the weapon or change to another weapon at this time += +================= +*/ + +void A_WeaponReady (player_t *player, pspdef_t *psp) // 8001B83C +{ + statenum_t new; + int angle; + + /* */ + /* check for change */ + /* if player is dead, put the weapon away */ + /* */ + if (player->pendingweapon != wp_nochange || !player->health) + { + /* change weapon (pending weapon should allready be validated) */ + P_DropWeapon(player); + return; + } + + /* */ + /* check for fire */ + /* */ + /* the missile launcher and bfg do not auto fire */ + if (ticbuttons[0] & BT_DATA[0]->BT_ATTACK) + { + P_FireWeapon (player); + return; + } + + /* */ + /* bob the weapon based on movement speed */ + /* */ + //angle = (64*gamevbls)&(FINEANGLES-1); + angle = (64*ticon)&(FINEANGLES-1); // PsxDoom/D64 use ticon no gamevbls + psp->sx = WEAPONX + FixedMul(player->bob, finecosine[angle]); + angle &= FINEANGLES/2-1; + psp->sy = WEAPONTOP + FixedMul(player->bob, finesine[angle]); +} + + +/* +================= += += A_ReFire += += The player can re fire the weapon without lowering it entirely += +================= +*/ + +void A_ReFire (player_t *player, pspdef_t *psp) // 8001B91C +{ + /* */ + /* check for fire (if a weaponchange is pending, let it go through instead) */ + /* */ + if ((ticbuttons[0] & BT_DATA[0]->BT_ATTACK) + && player->pendingweapon == wp_nochange && player->health) + { + player->refire++; + P_FireWeapon (player); + } + else + { + player->refire = 0; + P_CheckAmmo (player); + } +} + +/* +================= += += A_CheckReload += +================= +*/ + +void A_CheckReload(player_t *player, pspdef_t *psp) // 8001B9A0 +{ + P_CheckAmmo(player); +} + +/* +================= += += A_Lower += +================= +*/ + +void A_Lower (player_t *player, pspdef_t *psp) // 8001B9C0 +{ + psp->sy += LOWERSPEED; + if (psp->sy < WEAPONBOTTOM ) + return; + + /* */ + /* [d64] stop plasma buzz */ + /* */ + if (player->readyweapon == wp_plasma) + S_StopSound(NULL, sfx_electric); + + /* */ + /* [d64] clear flash graphic drawer */ + /* */ + P_SetPsprite(player, ps_flash, S_000); + + if (player->playerstate == PST_DEAD) + { + psp->sy = WEAPONBOTTOM; + return; /* don't bring weapon back up */ + } + + /* */ + /* The old weapon has been lowered off the screen, so change the weapon */ + /* and start raising it */ + /* */ + if (!player->health) + { /* player is dead, so keep the weapon off screen */ + P_SetPsprite (player, ps_weapon, S_000); + return; + } + + player->readyweapon = player->pendingweapon; + + P_BringUpWeapon (player); +} + + +/* +================= += += A_Raise += +================= +*/ + +void A_Raise (player_t *player, pspdef_t *psp) // 8001BA84 +{ + statenum_t new; + + psp->sy -= RAISESPEED; + + if (psp->sy > WEAPONTOP ) + return; + + psp->sy = WEAPONTOP; + + /* */ + /* the weapon has been raised all the way, so change to the ready state */ + /* */ + new = weaponinfo[player->readyweapon].readystate; + + P_SetPsprite (player, ps_weapon, new); +} + + +/* +================ += += A_GunFlash += +================= +*/ + +void A_GunFlash (player_t *player, pspdef_t *psp) // 8001BAD8 +{ + /* [d64] set alpha on flash frame */ + if(player->readyweapon == wp_missile) + player->psprites[ps_flashalpha].alpha = 100; + + P_SetPsprite (player,ps_flashalpha,weaponinfo[player->readyweapon].flashstate); +} + + +/* +=============================================================================== + + WEAPON ATTACKS + +=============================================================================== +*/ + + +/* +================== += += A_Punch += +================== +*/ + +void A_Punch (player_t *player, pspdef_t *psp) // 8001BB2C +{ + angle_t angle; + int damage; + + //damage = ((P_Random ()&7)*3)+3; + damage = ((P_Random()&7)+1)*3; + if (player->powers[pw_strength]) + damage *= 10; + angle = player->mo->angle; + angle += (angle_t)(P_Random()-P_Random())<<18; + P_LineAttack (player->mo, angle, 0, MELEERANGE, MAXINT, damage); + /* turn to face target */ + if (linetarget) + { + S_StartSound(player->mo, sfx_punch); + player->mo->angle = R_PointToAngle2 (player->mo->x, player->mo->y, linetarget->x, linetarget->y); + } +} + +/* +================== += += A_Saw += +================== +*/ + +void A_Saw (player_t *player, pspdef_t *psp) // 8001BC1C +{ + angle_t angle; + int damage; + int rnd1, rnd2; + + //damage = ((P_Random ()&7)*3)+3; + damage = ((P_Random()&7)+1)*3; + angle = player->mo->angle; + rnd1 = P_Random(); + rnd2 = P_Random(); + angle += (angle_t)(rnd2-rnd1)<<18; + /* use meleerange + 1 se the puff doesn't skip the flash */ + P_LineAttack (player->mo, angle, 0, MELEERANGE+1, MAXINT, damage); + if (!linetarget) + { + S_StartSound (player->mo, sfx_saw1); + return; + } + S_StartSound (player->mo, sfx_saw2); + + /* turn to face target */ + angle = R_PointToAngle2 (player->mo->x, player->mo->y, linetarget->x, linetarget->y); + if (angle - player->mo->angle > ANG180) + { + if (angle - player->mo->angle < -ANG90/20) + player->mo->angle = angle + ANG90/21; + else + player->mo->angle -= ANG90/20; + } + else + { + if (angle - player->mo->angle > ANG90/20) + player->mo->angle = angle - ANG90/21; + else + player->mo->angle += ANG90/20; + } + player->mo->flags |= MF_JUSTATTACKED; +} + +/* +================== += += A_FireMissile += +================== +*/ + +void A_ChainSawReady(player_t *player, pspdef_t *psp) // 8001BDA8 +{ + S_StartSound(player->mo, sfx_sawidle); + A_WeaponReady(player, psp); +} + +/* +================== += += A_FireMissile += +================== +*/ + +void A_FireMissile (player_t *player, pspdef_t *psp) // 8001BDE4 +{ + player->ammo[weaponinfo[player->readyweapon].ammo]--; + + player->recoilpitch = RECOILPITCH; + + if(player->onground) + P_Thrust(player, player->mo->angle + ANG180, FRACUNIT); + + P_SpawnPlayerMissile (player->mo, MT_PROJ_ROCKET); +} + + +/* +================== += += A_FireBFG += +================== +*/ + +void A_FireBFG (player_t *player, pspdef_t *psp) // 8001BE78 +{ + player->ammo[weaponinfo[player->readyweapon].ammo] -= BFGCELLS; + P_SpawnPlayerMissile (player->mo, MT_PROJ_BFG); +} + + +/* +================== += += A_FirePlasma += +================== +*/ +int pls_animpic = 0; // 8005AE70 + +void A_PlasmaAnimate(player_t *player, pspdef_t *psp) // 8001BED8 +{ + P_SetPsprite(player, ps_flash, pls_animpic + S_778); + + if (++pls_animpic >= 3) + pls_animpic = 0; +} + +/* +================== += += A_FirePlasma += +================== +*/ + +void A_FirePlasma (player_t *player, pspdef_t *psp) // 8001BF2C +{ + player->ammo[weaponinfo[player->readyweapon].ammo]--; + P_SetPsprite (player,ps_flash,S_000); + P_SpawnPlayerMissile (player->mo, MT_PROJ_PLASMA); +} + +/* +=============== += += P_BulletSlope += +=============== +*/ + +fixed_t bulletslope; // 800A5E78 + +void P_BulletSlope(mobj_t* mo) // 8001BF88 +{ + angle_t an; + + // see which target is to be aimed at + an = mo->angle; + bulletslope = P_AimLineAttack(mo, an, 0, 16 * 64 * FRACUNIT); + + if (!linetarget) + { + an += 1 << 26; + bulletslope = P_AimLineAttack(mo, an, 0, 16 * 64 * FRACUNIT); + if (!linetarget) + { + an -= 2 << 26; + bulletslope = P_AimLineAttack(mo, an, 0, 16 * 64 * FRACUNIT); + } + } +} + +/* +=============== += += P_GunShot += +=============== +*/ + +void P_GunShot (mobj_t *mo, boolean accurate) // 8001C024 +{ + angle_t angle; + int damage; + int rnd1, rnd2; + + damage = ((P_Random ()&3)*4)+4; + angle = mo->angle; + if (!accurate) + { + rnd1 = P_Random(); + rnd2 = P_Random(); + angle += (rnd2-rnd1)<<18; + } + P_LineAttack (mo, angle, 0, MISSILERANGE, bulletslope, damage); +} + +/* +================== += += A_FirePistol += +================== +*/ + +void A_FirePistol (player_t *player, pspdef_t *psp) // 8001C0B4 +{ + S_StartSound (player->mo, sfx_pistol); + + player->ammo[weaponinfo[player->readyweapon].ammo]--; + P_SetPsprite (player,ps_flashalpha,weaponinfo[player->readyweapon].flashstate); + P_BulletSlope(player->mo); + + P_GunShot (player->mo, !player->refire); +} + +/* +================== += += A_FireShotgun += +================== +*/ + +void A_FireShotgun (player_t *player, pspdef_t *psp) // 8001C138 +{ + angle_t angle; + int damage; + int i; + + S_StartSound (player->mo, sfx_shotgun); + + player->ammo[weaponinfo[player->readyweapon].ammo]--; + player->recoilpitch = RECOILPITCH; + + P_SetPsprite (player,ps_flashalpha,weaponinfo[player->readyweapon].flashstate); + P_BulletSlope(player->mo); + + for (i=0 ; i<7 ; i++) + { + P_GunShot(player->mo, false); + } +} + +/* +================== += += A_FireShotgun2 += +================== +*/ + +void A_FireShotgun2(player_t *player, pspdef_t *psp) // 8001C210 +{ + angle_t angle; + int damage; + int i; + + S_StartSound(player->mo, sfx_sht2fire); + P_SetMobjState(player->mo, S_007); + + player->ammo[weaponinfo[player->readyweapon].ammo] -= 2; + player->recoilpitch = RECOILPITCH; + + if(player->onground) + P_Thrust(player, player->mo->angle + ANG180, FRACUNIT); + + P_SetPsprite(player, ps_flashalpha, weaponinfo[player->readyweapon].flashstate); + P_BulletSlope(player->mo); + + for (i = 0; i<20; i++) + { + //damage = ((P_Random() % 3) * 5) + 5; + damage = 5 * (P_Random() % 3 + 1); + angle = player->mo->angle; + angle += (P_Random() - P_Random()) << 19; + P_LineAttack(player->mo, angle, 0, MISSILERANGE, bulletslope + ((P_Random() - P_Random()) << 5), damage); + } +} + +/* +================== += += A_CockSgun += +================== +*/ +#if 0 //No Used In PSX Doom/ Doom64 +void A_CockSgun (player_t *player, pspdef_t *psp) +{ + S_StartSound (player->mo, sfx_sgcock); +} +#endif // 0 + +/* +================== += += A_FireCGun += +================== +*/ + +void A_FireCGun (player_t *player, pspdef_t *psp) // 8001C3F8 +{ + int ammo; + int rand; + + ammo = player->ammo[weaponinfo[player->readyweapon].ammo]; + + if (!ammo) + return; + + S_StartSound (player->mo, sfx_pistol); + + player->ammo[weaponinfo[player->readyweapon].ammo]--; + + /* randomize sx */ + rand = (((P_Random() & 1) << 1) - 1); + psp->sx = (rand * FRACUNIT); + + /* randomize sy */ + rand = ((((ammo - 1) & 1) << 1) - 1); + psp->sy = WEAPONTOP - (rand * (2*FRACUNIT)); + + player->recoilpitch = RECOILPITCH; + + P_SetPsprite (player,ps_flashalpha,weaponinfo[player->readyweapon].flashstate + psp->state - &states[S_756/*S_CHAIN1*/]); + P_BulletSlope(player->mo); + + player->psprites[ps_flashalpha].alpha = 160; + + P_GunShot (player->mo, !player->refire); +} + +/* +================ += += A_BFGFlash += +================= +*/ + +void A_BFGFlash(mobj_t* actor) // 8001C548 +{ + players[0].bfgcount = 100; + actor->alpha = 170; +} + +/* +================ += += A_BFGSpray += += Spawn a BFG explosion on every monster in view += +================= +*/ + +void A_BFGSpray (mobj_t *mo) // 8001C560 +{ + int i, j, damage; + angle_t an; + int alpha; + + alpha = 0; + + /* offset angles from its attack angle */ + for (i=0 ; i<40 ; i++) + { + an = mo->angle - ANG90/2 + ANG90/40*i; + /* mo->target is the originator (player) of the missile */ + P_AimLineAttack (mo->target, an, 0, 16*64*FRACUNIT); + if (!linetarget) + continue; + P_SpawnMobj (linetarget->x, linetarget->y, linetarget->z + (linetarget->height>>1), MT_BFGSPREAD); + damage = 0; + for (j=0;j<15;j++) + { + damage += (P_Random()&7) + 1; + } + P_DamageMobj (linetarget, mo->target,mo->target, damage); + } + + alpha = mo->alpha * 3; + if (alpha < 0) + alpha += 3; + + mo->alpha = alpha >> 2; +} + +/* +================ += += A_BFGsound += +================= +*/ + +void A_BFGsound (player_t *player, pspdef_t *psp) // 8001C698 +{ + S_StartSound (player->mo, sfx_bfg); +} + +#if 0 +/* +================ += += A_OpenShotgun2 += +================= +*/ + +void A_OpenShotgun2(player_t *player, pspdef_t *psp)//L80021AFC() +{ + S_StartSound(player->mo, sfx_dbopn); +} +#endif // 0 + +/* +================ += += A_LoadShotgun2 += +================= +*/ + +void A_LoadShotgun2(player_t *player, pspdef_t *psp) // 8001C6C0 +{ + S_StartSound(player->mo, sfx_sht2load1); +} + +/* +================ += += A_CloseShotgun2 += +================= +*/ + +void A_CloseShotgun2(player_t *player, pspdef_t *psp) // 8001C6E8 +{ + S_StartSound(player->mo, sfx_sht2load2); + //A_ReFire(player, psp); +} + +/* +================ += += P_LaserCrossBSP += +================= +*/ + +void P_LaserCrossBSP(int bspnum, laserdata_t *laser) // 8001C710 +{ + node_t* node; + int ds1, ds2; + int s1, s2; + int dist; + int frac; + mobj_t *marker; + laserdata_t *childlaser; + laser_t *next_cl, *next_l; + fixed_t x, y, z; + fixed_t x1, y1, z1; + fixed_t x2, y2, z2; + fixed_t nx, ny, ndx, ndy; + + while(!(bspnum & NF_SUBSECTOR)) + { + node = &nodes[bspnum]; + + x1 = laser->x1; + y1 = laser->y1; + z1 = laser->z1; + x2 = laser->x2; + y2 = laser->y2; + z2 = laser->z2; + + nx = node->line.x; + ny = node->line.y; + ndx = (node->line.dx >> FRACBITS); + ndy = (node->line.dy >> FRACBITS); + + /* traverse nodes */ + ds1 = (((x1 - nx) >> FRACBITS) * ndy) - (((y1 - ny) >> FRACBITS) * ndx); + ds2 = (((x2 - nx) >> FRACBITS) * ndy) - (((y2 - ny) >> FRACBITS) * ndx); + + s1 = (ds1 < 0); + s2 = (ds2 < 0); + + /* did the two laser points cross the node? */ + if(s1 == s2) + { + bspnum = node->children[s1]; + continue; + } + + /* new child laser */ + childlaser = (laserdata_t *)Z_Malloc( sizeof(*childlaser), PU_LEVSPEC, 0); + + /* copy laser pointer */ + *childlaser = *laser; + + /* get the intercepting point of the laser and node */ + frac = FixedDiv(ds1, ds1 - ds2); + + x = (((x2 - x1) >> FRACBITS) * frac) + x1; + y = (((y2 - y1) >> FRACBITS) * frac) + y1; + z = (((z2 - z1) >> FRACBITS) * frac) + z1; + + /* update endpoint of current laser to intercept point */ + laser->x2 = x; + laser->y2 = y; + laser->z2 = z; + + /* childlaser begins at intercept point */ + childlaser->x1 = x; + childlaser->y1 = y; + childlaser->z1 = z; + + /* update distmax */ + dist = (laser->distmax * frac) >> FRACBITS; + + childlaser->distmax = laser->distmax - dist; + laser->distmax = dist; + + /* point to child laser */ + laser->next = childlaser; + + /* traverse child nodes */ + P_LaserCrossBSP(node->children[s1], laser); + + laser = childlaser; + bspnum = node->children[s2]; + } + + /* subsector was hit, spawn a marker between the two laser points */ + x = (laser->x1 + laser->x2) >> 1; + y = (laser->y1 + laser->y2) >> 1; + z = (laser->z1 + laser->z2) >> 1; + + marker = P_SpawnMobj(x, y, z, MT_LASERMARKER); + + /* have marker point to which laser it belongs to */ + marker->extradata = (laser_t*)laser; + laser->marker = marker; +} + +/* +================ += += T_LaserThinker += +================= +*/ + +void T_LaserThinker(laser_t *laser) // 8001C9B8 +{ + fade_t *fade; + laserdata_t *pThisLaser; + + pThisLaser = laser->laserdata; + pThisLaser ->dist += 64; + + /* laser reached its destination? */ + if(pThisLaser->dist >= pThisLaser->distmax) + { + /* reached the end? */ + if (!pThisLaser->next) + { + P_RemoveThinker(&laser->thinker); + + /* fade out the laser puff */ + fade = Z_Malloc (sizeof(*fade), PU_LEVSPEC, 0); + P_AddThinker (&fade->thinker); + fade->thinker.function = T_FadeThinker; + fade->amount = -24; + fade->destAlpha = 0; + fade->flagReserve = 0; + fade->mobj = laser->marker; + } + else + { + laser->laserdata = pThisLaser->next; + } + + P_RemoveMobj(pThisLaser->marker); + Z_Free(pThisLaser); + } + else + { + /* update laser's location */ + pThisLaser->x1 += (pThisLaser->slopex * 32); + pThisLaser->y1 += (pThisLaser->slopey * 32); + pThisLaser->z1 += (pThisLaser->slopez * 32); + } +} + +/* +================ += += A_FireLaser += +================= +*/ +extern fixed_t aimfrac; // 800A5720 + +void A_FireLaser(player_t *player, pspdef_t *psp) // 8001CAC0 +{ + angle_t angleoffs; + angle_t spread; + mobj_t *mobj; + int lasercount; + int i; + fixed_t slopex, slopey, slopez; + fixed_t x, y, z; + fixed_t x1, y1, z1; + fixed_t x2, y2, z2; + byte type; + laserdata_t *laser_data; + laser_t *laser; + fixed_t laserfrac; + int damage; + + mobj = player->mo; + + type = ArtifactLookupTable[player->artifacts]; + + /* setup laser type */ + switch(type) + { + case 1: /* Rapid fire / single shot */ + psp->tics = 5; + lasercount = 1; + angleoffs = mobj->angle; + break; + case 2: /* Rapid fire / double shot */ + psp->tics = 4; + lasercount = 2; + spread = 0x16C0000; + angleoffs = mobj->angle + 0xFF4A0000; + break; + case 3: /* Spread shot */ + psp->tics = 4; + lasercount = 3; + spread = 0x2220000 + (0x2220000 * (player->refire & 3)); + angleoffs = mobj->angle - spread; + break; + default: /* Normal shot */ + lasercount = 1; + angleoffs = mobj->angle; + break; + } + + x1 = mobj->x + (finecosine[mobj->angle >> ANGLETOFINESHIFT] * LASERDISTANCE); + y1 = mobj->y + (finesine[mobj->angle >> ANGLETOFINESHIFT] * LASERDISTANCE); + z1 = mobj->z + LASERAIMHEIGHT; + + /* setup laser beams */ + for(i = 0; i < lasercount; i++) + { + slopez = P_AimLineAttack(mobj, angleoffs, LASERAIMHEIGHT, LASERRANGE); + + if(aimfrac) + laserfrac = (aimfrac << (FRACBITS - 4)) - (4 << FRACBITS); + else + laserfrac = (2048*FRACUNIT); + + slopex = finecosine[angleoffs >> ANGLETOFINESHIFT]; + slopey = finesine[angleoffs >> ANGLETOFINESHIFT]; + + x2 = mobj->x + FixedMul(slopex, laserfrac); + y2 = mobj->y + FixedMul(slopey, laserfrac); + z2 = z1 + FixedMul(slopez, laserfrac); + + z = (z2 - z1) >> FRACBITS; + x = (x2 - x1) >> FRACBITS; + y = (y2 - y1) >> FRACBITS; + + /* setup laser */ + laser_data = (laserdata_t *)Z_Malloc( sizeof(*laser_data), PU_LEVSPEC, 0); + + /* setup laser head point */ + laser_data->x1 = x1; + laser_data->y1 = y1; + laser_data->z1 = z1; + + /* setup laser tail point */ + laser_data->x2 = x2; + laser_data->y2 = y2; + laser_data->z2 = z2; + + /* setup movement slope */ + laser_data->slopex = slopex; + laser_data->slopey = slopey; + laser_data->slopez = slopez; + + /* setup distance info */ + laser_data->dist = 0; + laser_data->distmax = (fixed_t) sqrtf((float)((x * x) + (y * y) + (z * z))); + + laser_data->next = NULL; + + P_LaserCrossBSP(numnodes-1, laser_data); + + /* setup laser puff */ + laser = (laser_t *)Z_Malloc( sizeof(*laser), PU_LEVSPEC, 0); + P_AddThinker (&laser->thinker); + laser->thinker.function = T_LaserThinker; + laser->laserdata = laser_data; + laser->marker = P_SpawnMobj(x2, y2, z2, MT_PROJ_LASER); + + player->ammo[weaponinfo[player->readyweapon].ammo]--; + + if(!linetarget) + { + angleoffs += spread; + } + else + { + damage = ((P_Random() & 7) * 10) + 10; + P_DamageMobj(linetarget, mobj, mobj, damage); + } + } + + P_SetPsprite(player, ps_flashalpha, weaponinfo[player->readyweapon].flashstate); + S_StartSound(player->mo, sfx_laser); +} diff --git a/Doom 64/p_setup.c b/Doom 64/p_setup.c @@ -0,0 +1,821 @@ +/* P_main.c */ + +#include "doomdef.h" +#include "p_local.h" + +// text for debug +#include "graph.h" + +int numvertexes; //80077E44|uGp00000a34 +vertex_t *vertexes; //8007800C|puGp00000bfc + +int numsegs; //80077ECC +seg_t *segs; //8007805C + +int numsectors; //80077D80 +sector_t *sectors; //80077ED0 + +int numsubsectors; //80078048 +subsector_t *subsectors; //80077D6C + +int numnodes; //80077FE0 +node_t *nodes; //80077CD0 + +int numlines; //80077FF0 +line_t *lines; //80077CDC + +int numsides; //80077FDC +side_t *sides; //80077CCC + +int numleafs; //80077D90 +leaf_t *leafs; //80077F34 + +int numlights; // 800A5EFC +light_t *lights; // 800A5E9C +maplights_t *maplights; // 800A5EA4 + +int nummacros; // 800A5F00 +macro_t **macros; // 800A5EA0 + +short *blockmaplump; //80077EEC /* offsets in blockmap are from here */ +short *blockmap; +int bmapwidth, bmapheight; /* in mapblocks */ //800780A8, 80077CE4 +fixed_t bmaporgx, bmaporgy; /* origin of block map */ //80077FB4,80077FBC +mobj_t **blocklinks; /* for thing chains */ //80077D08 + +byte *rejectmatrix; /* for fast sight rejection */ + +mapthing_t *spawnlist; // 800A5D74 +int spawncount; // 800A5D78 + +//mapthing_t deathmatchstarts[10], *deathmatch_p;//80097e4c, 80077E8C +//mapthing_t playerstarts[MAXPLAYERS];//800a8c60 + +/* +================= += += P_LoadVertexes += +================= +*/ + +void P_LoadVertexes (void) // 8001CF20 +{ + int i, lumpSize; + mapvertex_t *ml; + vertex_t *li; + + numvertexes = W_MapLumpLength(ML_VERTEXES) / sizeof(mapvertex_t); + vertexes = Z_Malloc (numvertexes*sizeof(vertex_t),PU_LEVEL,0); + D_memset (vertexes, 0, numvertexes*sizeof(vertex_t)); + + ml = (mapvertex_t *)W_GetMapLump(ML_VERTEXES); + li = vertexes; + for (i=0 ; i<numvertexes ; i++, li++, ml++) + { + li->x = LONGSWAP(ml->x); + li->y = LONGSWAP(ml->y); + //li->validcount = 0; + + //PRINTF_D2(WHITE, 0, 25, "vertexes(%i,%i,%i) \n", li->x>>16, li->y>>16,li->validcount); + //WAIT(); + } +} + +/* +================= += += P_LoadSegs += +================= +*/ + +void P_LoadSegs (void) // 8001D020 +{ + int i; + mapseg_t *ml; + seg_t *li; + line_t *ldef; + int linedef, side; + float x, y; + + numsegs = W_MapLumpLength(ML_SEGS) / sizeof(mapseg_t); + segs = Z_Malloc (numsegs*sizeof(seg_t),PU_LEVEL,0); + D_memset (segs, 0, numsegs*sizeof(seg_t)); + + ml = (mapseg_t *)W_GetMapLump(ML_SEGS); + li = segs; + for (i=0 ; i<numsegs ; i++, li++, ml++) + { + li->v1 = &vertexes[LITTLESHORT(ml->v1)]; + li->v2 = &vertexes[LITTLESHORT(ml->v2)]; + + li->angle = (BIGSHORT(ml->angle)) << FRACBITS; + li->offset = (LITTLESHORT(ml->offset)) << FRACBITS; + + linedef = LITTLESHORT(ml->linedef); + ldef = &lines[linedef]; + li->linedef = ldef; + + side = LITTLESHORT(ml->side); + li->sidedef = &sides[ldef->sidenum[side]]; + + li->frontsector = sides[ldef->sidenum[side]].sector; + + if (ldef-> flags & ML_TWOSIDED) + li->backsector = sides[ldef->sidenum[side^1]].sector; + else + li->backsector = 0; + + if (ldef->v1 == li->v1) + ldef->fineangle = li->angle >> ANGLETOFINESHIFT; + + x = (float) ((double) (li->v2->x - li->v1->x) / 65536.0); + y = (float) ((double) (li->v2->y - li->v1->y) / 65536.0); + + li->length = (short)((int)((double)sqrtf((x * x) + (y * y)) * 16.0)); + + //PRINTF_D2(WHITE, 0, 25, "segs(length %i) ", li->length); + //WAIT(); + } +} + +/* +================= += += P_LoadSubSectors += +================= +*/ + +void P_LoadSubSectors (void) // 8001D34C +{ + int i; + mapsubsector_t *ms; + subsector_t *ss; + + numsubsectors = W_MapLumpLength (ML_SSECTORS) / sizeof(mapsubsector_t); + subsectors = Z_Malloc (numsubsectors*sizeof(subsector_t),PU_LEVEL,0); + D_memset (subsectors, 0, numsubsectors*sizeof(subsector_t)); + + ms = (mapsubsector_t *)W_GetMapLump(ML_SSECTORS); + ss = subsectors; + for (i=0 ; i<numsubsectors ; i++, ss++, ms++) + { + ss->numlines = LITTLESHORT(ms->numsegs); + ss->firstline = LITTLESHORT(ms->firstseg); + + //ss->numverts = 0; + //ss->leaf = 0; + //ss->drawindex = 0; + } +} + + +/* +================= += += P_LoadSectors += +================= +*/ + +void P_LoadSectors (void) // 8001D43C +{ + int i; + mapsector_t *ms; + sector_t *ss; + int skyname; + + skytexture = 0; + skyname = W_GetNumForName("F_SKYA") - firsttex; + + numsectors = W_MapLumpLength(ML_SECTORS) / sizeof(mapsector_t); + sectors = Z_Malloc (numsectors*sizeof(sector_t),PU_LEVEL,0); + D_memset (sectors, 0, numsectors*sizeof(sector_t)); + + ms = (mapsector_t *)W_GetMapLump(ML_SECTORS); + ss = sectors; + for (i=0 ; i<numsectors ; i++, ss++, ms++) + { + ss->floorheight = LITTLESHORT(ms->floorheight)<<FRACBITS; + ss->ceilingheight = LITTLESHORT(ms->ceilingheight)<<FRACBITS; + ss->floorpic = LITTLESHORT(ms->floorpic); + ss->ceilingpic = LITTLESHORT(ms->ceilingpic); + + ss->colors[0] = LITTLESHORT(ms->colors[1]); + ss->colors[1] = LITTLESHORT(ms->colors[0]); + ss->colors[2] = LITTLESHORT(ms->colors[2]); + ss->colors[3] = LITTLESHORT(ms->colors[3]); + ss->colors[4] = LITTLESHORT(ms->colors[4]); + + ss->special = LITTLESHORT(ms->special); + ss->thinglist = NULL; + ss->tag = LITTLESHORT(ms->tag); + ss->flags = LITTLESHORT(ms->flags); + + if (skyname <= ss->ceilingpic) + { + skytexture = (ss->ceilingpic - skyname) + 1; + ss->ceilingpic = -1; + } + if (skyname <= ss->floorpic) + ss->floorpic = -1; + + } +} + +/* +================= += += P_LoadNodes += +================= +*/ + +void P_LoadNodes (void) // 8001D64C +{ + int i,j,k; + mapnode_t *mn; + node_t *no; + + numnodes = W_MapLumpLength(ML_NODES) / sizeof(mapnode_t); + nodes = Z_Malloc (numnodes*sizeof(node_t),PU_LEVEL,0); + D_memset (nodes, 0, numnodes*sizeof(node_t)); + + mn = (mapnode_t *)W_GetMapLump(ML_NODES); + no = nodes; + for (i=0 ; i<numnodes ; i++, no++, mn++) + { + no->line.x = LITTLESHORT(mn->x) << FRACBITS; + no->line.y = LITTLESHORT(mn->y) << FRACBITS; + no->line.dx = LITTLESHORT(mn->dx) << FRACBITS; + no->line.dy = LITTLESHORT(mn->dy) << FRACBITS; + for (j=0 ; j<2 ; j++) + { + no->children[j] = (unsigned short)LITTLESHORT(mn->children[j]); + for (k=0 ; k<4 ; k++) + no->bbox[j][k] = LITTLESHORT(mn->bbox[j][k]) << FRACBITS; + } + } +} + +/* +================= += += P_LoadThings += +================= +*/ + +void P_LoadThings (void) // 8001D864 +{ + int i; + mapthing_t *mt, *mts; + int numthings; + int spawncnt; + + numthings = W_MapLumpLength(ML_THINGS) / sizeof(mapthing_t); + + mts = (mapthing_t *)W_GetMapLump(ML_THINGS); + for (i=0, spawncnt=0; i<numthings ; i++, mts++) + { + if(LITTLESHORT(mts->options) & MTF_SPAWN) + { + spawncnt++; + } + } + + if (spawncnt != 0) + spawnlist = (mapthing_t *)Z_Malloc(spawncnt * sizeof(mapthing_t),PU_LEVEL,0); + + mt = (mapthing_t *)W_GetMapLump(ML_THINGS); + for (i=0 ; i<numthings ; i++, mt++) + { + mt->x = LITTLESHORT(mt->x); + mt->y = LITTLESHORT(mt->y); + mt->z = LITTLESHORT(mt->z); + mt->angle = LITTLESHORT(mt->angle); + mt->type = LITTLESHORT(mt->type); + mt->options = LITTLESHORT(mt->options); + mt->tid = LITTLESHORT(mt->tid); + P_SpawnMapThing (mt); + + if (mt->type >= 4096) + I_Error("P_LoadThings: doomednum:%d >= 4096", mt->type); + } +} + +/* +================= += += P_LoadLineDefs += += Also counts secret lines for intermissions +================= +*/ + +void P_LoadLineDefs (void) // 8001D9B8 +{ + int i; + maplinedef_t *mld; + line_t *ld; + vertex_t *v1, *v2; + unsigned int special; + + numlines = W_MapLumpLength(ML_LINEDEFS) / sizeof(maplinedef_t); + lines = Z_Malloc (numlines*sizeof(line_t),PU_LEVEL,0); + D_memset (lines, 0, numlines*sizeof(line_t)); + + mld = (maplinedef_t *)W_GetMapLump(ML_LINEDEFS); + ld = lines; + for (i=0 ; i<numlines ; i++, mld++, ld++) + { + ld->flags = LONGSWAP(mld->flags); + ld->special = BIGSHORT(mld->special); + ld->tag = LITTLESHORT(mld->tag); + + v1 = ld->v1 = &vertexes[LITTLESHORT(mld->v1)]; + v2 = ld->v2 = &vertexes[LITTLESHORT(mld->v2)]; + + ld->dx = (v2->x - v1->x); + ld->dy = (v2->y - v1->y); + + if (!ld->dx) + ld->slopetype = ST_VERTICAL; + else if (!ld->dy) + ld->slopetype = ST_HORIZONTAL; + else + { + if (FixedDiv (ld->dy , ld->dx) > 0) + ld->slopetype = ST_POSITIVE; + else + ld->slopetype = ST_NEGATIVE; + } + + if (v1->x < v2->x) + { + ld->bbox[BOXLEFT] = v1->x; + ld->bbox[BOXRIGHT] = v2->x; + } + else + { + ld->bbox[BOXLEFT] = v2->x; + ld->bbox[BOXRIGHT] = v1->x; + } + + if (v1->y < v2->y) + { + ld->bbox[BOXBOTTOM] = v1->y; + ld->bbox[BOXTOP] = v2->y; + } + else + { + ld->bbox[BOXBOTTOM] = v2->y; + ld->bbox[BOXTOP] = v1->y; + } + + ld->sidenum[0] = LITTLESHORT(mld->sidenum[0]); + ld->sidenum[1] = LITTLESHORT(mld->sidenum[1]); + + if (ld->sidenum[0] != -1) + ld->frontsector = sides[ld->sidenum[0]].sector; + else + ld->frontsector = 0; + + if (ld->sidenum[1] != -1) + ld->backsector = sides[ld->sidenum[1]].sector; + else + ld->backsector = 0; + + special = SPECIALMASK(ld->special); + + if(special >= 256) + { + if(special >= (nummacros + 256)) + { + I_Error("P_LoadLineDefs: linedef %d has unknown macro", i); + } + } + } +} + +/* +================= += += P_LoadSideDefs += +================= +*/ + +void P_LoadSideDefs (void) // 8001DCC8 +{ + int i; + mapsidedef_t *msd; + side_t *sd; + + numsides = W_MapLumpLength(ML_SIDEDEFS) / sizeof(mapsidedef_t); + sides = Z_Malloc (numsides*sizeof(side_t),PU_LEVEL,0); + D_memset (sides, 0, numsides*sizeof(side_t)); + + msd = (mapsidedef_t *)W_GetMapLump(ML_SIDEDEFS); + sd = sides; + for (i=0 ; i<numsides ; i++, msd++, sd++) + { + sd->textureoffset = LITTLESHORT(msd->textureoffset)<<FRACBITS; + sd->rowoffset = LITTLESHORT(msd->rowoffset)<<FRACBITS; + sd->sector = &sectors[LITTLESHORT(msd->sector)]; + + sd->toptexture = LITTLESHORT(msd->toptexture); + sd->midtexture = LITTLESHORT(msd->midtexture); + sd->bottomtexture = LITTLESHORT(msd->bottomtexture); + } +} + +/* +================= += += P_LoadBlockMap += +================= +*/ + +void P_LoadBlockMap (void) // 8001DE38 +{ + int count; + int i; + int length; + byte *src; + + length = W_MapLumpLength(ML_BLOCKMAP); + blockmaplump = Z_Malloc(length, PU_LEVEL, 0); + src = (byte *)W_GetMapLump(ML_BLOCKMAP); + D_memcpy(blockmaplump,src,length); + + blockmap = blockmaplump+4;//skip blockmap header + count = length/2; + for (i=0 ; i<count ; i++) + blockmaplump[i] = LITTLESHORT(blockmaplump[i]); + + bmapwidth = blockmaplump[2]; + bmapheight = blockmaplump[3]; + bmaporgx = blockmaplump[0]<<FRACBITS; + bmaporgy = blockmaplump[1]<<FRACBITS; + + /* clear out mobj chains */ + count = sizeof(*blocklinks)* bmapwidth*bmapheight; + blocklinks = Z_Malloc (count,PU_LEVEL, 0); + D_memset (blocklinks, 0, count); +} + +/* +================= += += P_LoadReject += Include On Psx Doom / Doom64 += +================= +*/ + +void P_LoadReject(void) // 8001DF98 +{ + int length; + byte *src; + + length = W_MapLumpLength(ML_REJECT); + rejectmatrix = (byte*)Z_Malloc(length, PU_LEVEL, NULL); + + src = (byte *)W_GetMapLump(ML_REJECT); + D_memcpy(rejectmatrix,src,length); +} + +/* +================= += += P_LoadLeafs += Exclusive Psx Doom / Doom64 += +================= +*/ + +void P_LoadLeafs(void) // 8001DFF8 +{ + int i, j; + int length, size, count; + int vertex, seg; + subsector_t *ss; + leaf_t *lf; + byte *data; + short *mlf; + + data = W_GetMapLump(ML_LEAFS); + + size = 0; + count = 0; + mlf = (short *)data; + length = W_MapLumpLength(ML_LEAFS); + while (mlf < (short *)(data + length)) + { + count += 1; + size += (int)LITTLESHORT(*mlf); + mlf += (int)(LITTLESHORT(*mlf) << 1) + 1; + } + + if (count != numsubsectors) + I_Error("P_LoadLeafs: leaf/subsector inconsistancy\n"); + + leafs = Z_Malloc(size * sizeof(leaf_t), PU_LEVEL, 0); + + lf = leafs; + ss = subsectors; + + numleafs = 0; + mlf = (short *)data; + for (i = 0; i < count; i++, ss++) + { + ss->numverts = LITTLESHORT(*mlf++); + ss->leaf = (short)numleafs; + + for (j = 0; j < (int)ss->numverts; j++, lf++) + { + vertex = LITTLESHORT(*mlf++); + + if (vertex >= numvertexes) + I_Error("P_LoadLeafs: vertex out of range\n"); + + lf->vertex = &vertexes[vertex]; + + seg = LITTLESHORT(*mlf++); + if (seg != -1) + { + if (seg >= numsegs) + I_Error("P_LoadLeafs: seg out of range\n"); + + lf->seg = &segs[seg]; + } + else + { + lf->seg = NULL; + } + } + numleafs += (int)j; + } +} + +/* +================= += += P_LoadLights += Exclusive Doom64 += +================= +*/ + +void P_LoadLights(void) // 8001E29C +{ + int i; + int length; + byte *data; + maplights_t *ml; + light_t *l; + + length = W_MapLumpLength(ML_LIGHTS); + maplights = (maplights_t *)Z_Malloc(length, PU_LEVEL, 0); + + data = (byte *)W_GetMapLump(ML_LIGHTS); + D_memcpy(maplights,data,length); + + numlights = (length / sizeof(maplights_t)) + 256; + + lights = (light_t *)Z_Malloc(numlights*sizeof(light_t), PU_LEVEL, 0); + D_memset(lights,0,numlights*sizeof(light_t)); + + ml = maplights; + l = lights; + + /* Default light color (0 to 255) */ + for (i = 0; i < 256; i++, l++) + { + l->rgba = ((i << 24) | (i << 16) | (i << 8) | 255); + } + + /* Copy custom light colors */ + for (i = i; i < numlights; i++, l++, ml++) + { + l->rgba = ((ml->r << 24) | (ml->g << 16) | (ml->b << 8) | ml->a); + l->tag = LITTLESHORT(ml->tag); + } + + P_SetLightFactor(0); +} + +/* +================= += += P_LoadMacros += Exclusive Doom64 += +================= +*/ + +void P_LoadMacros(void) // 8001E478 +{ + short *data; + int specialCount; + byte *macroData; + macro_t *pMacro; + int headerSize; + int i, j; + + data = (short *)W_GetMapLump(ML_MACROS); + + nummacros = LITTLESHORT(*data++); + specialCount = LITTLESHORT(*data++); + headerSize = sizeof(void*) * nummacros; + + macroData = (byte *)Z_Malloc(((nummacros + specialCount) * sizeof(macro_t)) + headerSize, PU_LEVEL, 0); + macros = (macro_t**)macroData; + pMacro = (macro_t*)(macroData + headerSize); + + for(i = 0; i < nummacros; i++) + { + macros[i] = pMacro; + specialCount = LITTLESHORT(*data++); + + for(j = 0; j < specialCount+1; j++) + { + pMacro->id = LITTLESHORT(*data++); + pMacro->tag = LITTLESHORT(*data++); + pMacro->special = LITTLESHORT(*data++); + + if(j == specialCount) + pMacro->id = 0; + + pMacro++; + } + } +} + +/* +================= += += P_GroupLines += += Builds sector line lists and subsector sector numbers += Finds block bounding boxes for sectors +================= +*/ + +void P_GroupLines (void) // 8001E614 +{ + line_t **linebuffer; + int i, j, total; + sector_t *sector; + subsector_t *ss; + seg_t *seg; + int block; + line_t *li; + fixed_t bbox[4]; + +/* look up sector number for each subsector */ + ss = subsectors; + for (i=0 ; i<numsubsectors ; i++, ss++) + { + seg = &segs[ss->firstline]; + ss->sector = seg->sidedef->sector; + } + +/* count number of lines in each sector */ + li = lines; + total = 0; + for (i=0 ; i<numlines ; i++, li++) + { + total++; + li->frontsector->linecount++; + if (li->backsector && li->backsector != li->frontsector) + { + li->backsector->linecount++; + total++; + } + } + +/* build line tables for each sector */ + linebuffer = Z_Malloc (total*4, PU_LEVEL, 0); + sector = sectors; + for (i=0 ; i<numsectors ; i++, sector++) + { + M_ClearBox (bbox); + sector->lines = linebuffer; + li = lines; + for (j=0 ; j<numlines ; j++, li++) + { + if (li->frontsector == sector || li->backsector == sector) + { + *linebuffer++ = li; + M_AddToBox (bbox, li->v1->x, li->v1->y); + M_AddToBox (bbox, li->v2->x, li->v2->y); + } + } + if (linebuffer - sector->lines != sector->linecount) + I_Error ("P_GroupLines: miscounted"); + + /* set the degenmobj_t to the middle of the bounding box */ + sector->soundorg.x = (bbox[BOXRIGHT]+bbox[BOXLEFT])/2; + sector->soundorg.y = (bbox[BOXTOP]+bbox[BOXBOTTOM])/2; + //sector->soundorg.z = (sector->floorheight + sector->ceilingheight) / 2; + + /* link into subsector */ + sector->soundorg.subsec = R_PointInSubsector(sector->soundorg.x, sector->soundorg.y); + + /* adjust bounding box to map blocks */ + block = (bbox[BOXTOP]-bmaporgy+MAXRADIUS)>>MAPBLOCKSHIFT; + block = (block >= bmapheight) ? bmapheight-1 : block; + sector->blockbox[BOXTOP]=block; + + block = (bbox[BOXBOTTOM]-bmaporgy-MAXRADIUS)>>MAPBLOCKSHIFT; + block = (block < 0) ? 0 : block; + sector->blockbox[BOXBOTTOM]=block; + + block = (bbox[BOXRIGHT]-bmaporgx+MAXRADIUS)>>MAPBLOCKSHIFT; + block = (block >= bmapwidth) ? bmapwidth-1 : block; + sector->blockbox[BOXRIGHT]=block; + + block = (bbox[BOXLEFT]-bmaporgx-MAXRADIUS)>>MAPBLOCKSHIFT; + block = (block < 0) ? 0 : block; + sector->blockbox[BOXLEFT]=block; + } +} + +/*============================================================================= */ + +/* +================= += += P_SetupLevel += +================= +*/ + +void P_SetupLevel(int map, skill_t skill) // 8001E974 +{ + int i, memory; + int lumpnum; + mobj_t *mobj; + char lumpname[16]; + + /* free all tags except the PU_STATIC tag */ + Z_FreeTags(mainzone, ~PU_STATIC); // (PU_LEVEL | PU_LEVSPEC | PU_CACHE) + + Z_CheckZone(mainzone);//Z_CheckHeap + M_ClearRandom(); + + //printf("P_SetupLevel(%i,%i)\n", map, skill); + //PRINTF_D2(WHITE, 0, 24, "P_SetupLevel(%i,%i)\n", map, skill); + + totalkills = totalitems = totalsecret = 0; + + //P_InitThinkers(); + thinkercap.prev = thinkercap.next = &thinkercap; + mobjhead.next = mobjhead.prev = &mobjhead; + + spawncount = 0; + + W_OpenMapWad(map); + + /* note: most of this ordering is important */ + P_LoadMacros(); + P_LoadBlockMap(); + P_LoadVertexes(); + P_LoadSectors(); + P_LoadSideDefs(); + P_LoadLineDefs(); + P_LoadSubSectors(); + P_LoadNodes(); + P_LoadSegs(); + P_LoadLeafs(); + P_LoadReject(); + P_LoadLights(); + P_GroupLines(); + P_LoadThings(); + W_FreeMapLump(); + + P_Init(); + + /* set up world state */ + P_SpawnSpecials(); + R_SetupSky(); + + Z_SetAllocBase(mainzone); + Z_CheckZone(mainzone); + + memory = Z_FreeMemory(mainzone); + if (memory < 0x10000) + { + Z_DumpHeap(mainzone); + I_Error("P_SetupLevel: not enough free memory %d", memory); + } + + P_SpawnPlayer(); + + //PRINTF_D2(WHITE, 0, 27, "P_SetupLevel DONE\n"); +} diff --git a/Doom 64/p_shoot.c b/Doom 64/p_shoot.c @@ -0,0 +1,925 @@ +#include "doomdef.h" +#include "p_local.h" + +// +// P_LineAttack +// +mobj_t* linetarget; // 800A56F8 // who got hit (or NULL) +mobj_t* shootthing; // 800A5700 +line_t* shotline; // 800A56FC +fixed_t aimfrac; // 800A5720 + +fixed_t shootdirx; +fixed_t shootdiry; +fixed_t shootdirz; + +// Height if not aiming up or down +// ???: use slope for monsters? +fixed_t shootz; // 800A571C + +int la_damage; // 800A5724 +fixed_t attackrange; // 800A5704 + +fixed_t aimslope; // 800A5710 +fixed_t aimpitch; + +// For P_PathTraverse +fixed_t tx2; // 800A5714 +fixed_t ty2; // 800A5718 + +// slopes to top and bottom of target +extern fixed_t topslope; // 800A5708 +extern fixed_t bottomslope; // 800A570C + +/* +============== += += PTR_AimTraverse += Sets linetaget and aimslope when a target is aimed at. += +============== +*/ + +boolean PTR_AimTraverse(intercept_t* in) // 80017508 +{ + line_t* li; + mobj_t* th; + fixed_t linebottomslope; + fixed_t linetopslope; + fixed_t thingtopslope; + fixed_t thingbottomslope; + fixed_t dist; + + if(in->isaline) + { + li = in->d.line; + + if(!(li->flags & ML_TWOSIDED)) + { + aimfrac = in->frac; + shotline = li; + return false; // stop + } + + // Crosses a two sided line. + // A two sided line will restrict + // the possible target ranges. + P_LineOpening(li); + + if(openbottom >= opentop) + { + aimfrac = in->frac; + shotline = li; + return false; // stop + } + + dist = FixedMul(attackrange, in->frac); + + if(li->frontsector->floorheight != li->backsector->floorheight) + { + linebottomslope = FixedDiv(openbottom - shootz , dist); + if(linebottomslope > bottomslope) + { + bottomslope = linebottomslope; + } + } + + if(li->frontsector->ceilingheight != li->backsector->ceilingheight) + { + linetopslope = FixedDiv(opentop - shootz , dist); + if(linetopslope < topslope) + { + topslope = linetopslope; + } + } + + if(topslope <= bottomslope) + { + shotline = li; + aimfrac = in->frac; + return false; // stop + } + + return true; // shot continues + } + + // shoot a thing + th = in->d.thing; + if(th == shootthing) + { + return true; // can't shoot self + } + + if((th->flags & MF_SHOOTABLE) == 0) + { + return true; // corpse or something + } + + // check angles to see if the thing can be aimed at + dist = FixedMul(attackrange, in->frac); + thingtopslope = FixedDiv(th->z + th->height - shootz , dist); + + if(thingtopslope < bottomslope) + { + return true; // shot over the thing + } + + thingbottomslope = FixedDiv(th->z - shootz, dist); + + if(thingbottomslope > topslope) + { + return true; // shot under the thing + } + + // this thing can be hit! + if(thingtopslope > topslope) + { + thingtopslope = topslope; + } + + if(thingbottomslope < bottomslope) + { + thingbottomslope = bottomslope; + } + + aimslope = (thingtopslope+thingbottomslope) >> 1; + linetarget = th; + aimfrac = in->frac; + + return false; // don't go any farther +} + +/* +============== += += PTR_ShootTraverse += [d64]: Some logic from PTR_AimTraverse has been merged += +============== +*/ + +boolean PTR_ShootTraverse(intercept_t* in) // 800177A8 +{ + fixed_t x, y, z; + fixed_t frac; + line_t* li; + mobj_t* th; + fixed_t slope, dist; + fixed_t thingtopslope, thingbottomslope; + sector_t *front, *back; + + if(in->isaline) + { + li = in->d.line; + + if(li->special && (li->special & MLU_SHOOT)) + { + P_UseSpecialLine(li, shootthing); + } + + front = li->frontsector; + back = li->backsector; + + if(back) + { + // crosses a two sided line + P_LineOpening(li); + + dist = FixedMul(attackrange, in->frac); + + if(front->floorheight != back->floorheight) + { + slope = FixedDiv(openbottom - shootz, dist); + if(slope > bottomslope) + { + bottomslope = slope; + } + } + if(front->ceilingheight != back->ceilingheight) + { + slope = FixedDiv(opentop - shootz, dist); + if(slope < topslope) + { + topslope = slope; + } + } + + if(bottomslope < topslope) + { + return true; // shot continues + } + } + + // hit line + // position a bit closer + frac = in->frac - FixedDiv(4*FRACUNIT, attackrange); + + x = trace.x + FixedMul(trace.dx, frac); + y = trace.y + FixedMul(trace.dy, frac); + z = shootz + FixedMul(aimslope, FixedMul(frac, attackrange)); + + if (front->ceilingpic == -1) + { + // don't shoot the sky! + if(z > front->ceilingheight) + return false; + + // it's a sky hack wall + if(back && (back->ceilingpic == -1)) + return false; + + // don't shoot blank mid texture + if((back == NULL) && (sides[li->sidenum[0]].midtexture == 1)) + return false; + } + + // Spawn bullet puffs. + //ST_DebugPrint("P_SpawnPuff line"); + P_SpawnPuff(x, y, z); + + shotline = li; + + // don't go any farther + return false; + } + + // shoot a thing + th = in->d.thing; + if(th == shootthing) + { + return true; // can't shoot self + } + + if((th->flags & MF_SHOOTABLE) == 0) + { + return true; // corpse or something + } + + // check angles to see if the thing can be aimed at + dist = FixedMul(attackrange, in->frac); + thingtopslope = FixedDiv((th->z + th->height) - shootz, dist); + + if(thingtopslope < bottomslope) + { + return true; // shot over the thing + } + + thingbottomslope = FixedDiv(th->z - shootz, dist); + + if(thingbottomslope > topslope) + { + return true; // shot under the thing + } + + // this thing can be hit! + if(thingtopslope > topslope) + { + thingtopslope = topslope; + } + + if(thingbottomslope < bottomslope) + { + thingbottomslope = bottomslope; + } + + // hit thing + // position a bit closer + frac = in->frac - FixedDiv(10*FRACUNIT, attackrange); + + x = trace.x + FixedMul(trace.dx, frac); + y = trace.y + FixedMul(trace.dy, frac); + z = shootz + FixedMul((thingtopslope+thingbottomslope)>>1, FixedMul(frac, attackrange)); + + // Spawn bullet puffs or blod spots, + // depending on target type. + if((in->d.thing->flags & MF_NOBLOOD) != 0) + { + //ST_DebugPrint("P_SpawnPuff thing"); + P_SpawnPuff(x, y, z); + } + else + { + P_SpawnBlood(x, y, z, la_damage); + } + + if(la_damage) + { + P_DamageMobj(th, shootthing, shootthing, la_damage); + } + + linetarget = th; + // don't go any farther + return false; +} + +/* +================= += += P_AimLineAttack += +================= +*/ + +fixed_t P_AimLineAttack (mobj_t *t1, angle_t angle, fixed_t zheight, fixed_t distance) // 80017C30 +{ + int flags; + fixed_t dist; + + angle >>= ANGLETOFINESHIFT; + dist = distance>>FRACBITS; + + shootthing = t1; + + tx2 = t1->x + dist*finecosine[angle]; + ty2 = t1->y + dist*finesine[angle]; + + // can't shoot outside view angles + // [d64] use 120 instead of 100 + topslope = 120*FRACUNIT/160; + bottomslope = -120*FRACUNIT/160; + + attackrange = distance; + linetarget = NULL; + shotline = NULL; + aimfrac = 0; + flags = PT_ADDLINES|PT_ADDTHINGS|PT_EARLYOUT; + + // [d64] new argument for shoot height + if(!zheight) + { + shootz = t1->z + (t1->height>>1) + 12*FRACUNIT; + } + else + { + shootz = t1->z + zheight; + } + + P_PathTraverse(t1->x, t1->y, tx2, ty2, flags, PTR_AimTraverse); + + if(linetarget) + { + return aimslope; + } + + return 0; +} + +/* +================= += += P_LineAttack += += [d64]: A lot of code from P_AimLineAttack and PTR_AimTraverse has been merged += +================= +*/ + +void P_LineAttack (mobj_t *t1, angle_t angle, fixed_t zheight, fixed_t distance, fixed_t slope, int damage) // 80017D74 +{ + int flags; + fixed_t dist; + + angle >>= ANGLETOFINESHIFT; + dist = distance>>FRACBITS; + + shootthing = t1; + la_damage = damage; + + tx2 = t1->x + dist*finecosine[angle]; + ty2 = t1->y + dist*finesine[angle]; + linetarget = NULL; + shotline = NULL; + + if(!zheight) + { + shootz = t1->z + (t1->height>>1) + 12*FRACUNIT; + } + else + { + shootz = t1->z + zheight; + } + + if(slope == MAXINT) + { + topslope = 120*FRACUNIT/160; + bottomslope = -120*FRACUNIT/160; + } + else + { + topslope = slope+1; + bottomslope = slope-1; + } + + aimslope = topslope+bottomslope; // addu $t3, $t8, $t9 + if(aimslope < 0) + { // addiu $at, $t3, 1 + aimslope = (aimslope+1)>>1; // sra $t5, $at, 1 + // ^^ that's really weird.... + } + else // bgez $t3, loc_80017EC0 + { + aimslope >>= 1; // sra $t5, $t3, 1 + } + + attackrange = distance; + flags = PT_ADDLINES|PT_ADDTHINGS|PT_EARLYOUT; + + P_PathTraverse(t1->x, t1->y, tx2, ty2, flags, PTR_ShootTraverse); +} + + +#if 0 +//=================== +// +// IN +// +// A line will be shootdivd from the middle of shooter in the direction of +// attackangle until either a shootable mobj is within the visible +// aimtopslope / aimbottomslope range, or a solid wall blocks further +// tracing. If no thing is targeted along the entire range, the first line +// that blocks the midpoint of the shootdiv will be hit. +//=================== + +line_t *shootline; //iGp00000ce4 +mobj_t *shootmobj; //iGp00000ce8 +fixed_t shootslope; // between aimtop and aimbottom //iGp00000968 +fixed_t shootx, shooty, shootz; // location for puff/blood //iGp000009e0, iGp000009ec, iGp000009f0 + +//=================== +// +// TEMPS +// +//=================== + +fixed_t aimmidslope; // for detecting first wall hit iGp000009c8 +divline_t shootdiv; //800a8e58 +fixed_t shootx2, shooty2; //iGp00000a54,iGp00000a60 +fixed_t firstlinefrac; //iGp00000be8 + +int shootdivpositive; //uGp00000a88 + +fixed_t old_frac; //uGp00000b44 +void *old_value; //pvGp00000c74 +boolean old_isline; //bGp000008e4 +int ssx1,ssy1,ssx2,ssy2; //iGp00000c08, iGp00000c18, iGp00000c14, iGp00000c24 + +typedef struct +{ + vertex_t v1, v2; +} thingline_t; + +static thingline_t thingline;//800A8824*/ +static vertex_t *thing_line[2] = {&thingline.v1, &thingline.v2};//iGp00000534, iGp00000538 + +extern mobj_t *shooter;//*(r28 + 2764) +extern angle_t attackangle;//*(r28 + 2484) +extern fixed_t attackrange;//*(r28 + 2460) +extern fixed_t aimtopslope;//*(r28 + 2580) +extern fixed_t aimbottomslope;//*(r28 + 3340) + +/* +===================== += += P_Shoot2 += +===================== +*/ + +void P_Shoot2(void)//L80024144() +{ + mobj_t *t1; + unsigned angle; + + t1 = shooter; + + shootline = 0; + shootmobj = 0; + + angle = attackangle >> ANGLETOFINESHIFT; + + shootdiv.x = t1->x; + shootdiv.y = t1->y; + shootx2 = t1->x + (attackrange>>FRACBITS)*finecosine[angle]; + shooty2 = t1->y + (attackrange>>FRACBITS)*finesine[angle]; + shootdiv.dx = shootx2 - shootdiv.x; + shootdiv.dy = shooty2 - shootdiv.y; + shootz = t1->z + (t1->height>>1) + 8*FRACUNIT; + + shootdivpositive = (shootdiv.dx ^ shootdiv.dy)>0; + + ssx1 = shootdiv.x >> 16; + ssy1 = shootdiv.y >> 16; + ssx2 = shootx2 >> 16; + ssy2 = shooty2 >> 16; + + aimmidslope = (aimtopslope + aimbottomslope)>>1; + + // + // cross everything + // + old_frac = 0; + + PA_CrossBSPNode(numnodes-1); + + // check the last intercept if needed + if (!shootmobj) + PA_DoIntercept(0, false, FRACUNIT); + + // + // post process + // + if (shootmobj) + return; + + if (!shootline) + return; + + // + // calculate the intercept point for the first line hit + // + // position a bit closer + firstlinefrac -= FixedDiv(4*FRACUNIT,attackrange); + + shootx = shootdiv.x + FixedMul(shootdiv.dx, firstlinefrac); + shooty = shootdiv.y + FixedMul(shootdiv.dy, firstlinefrac); + shootz += FixedMul(aimmidslope, FixedMul(firstlinefrac,attackrange)); +} + + +/* +================== += += PA_DoIntercept += +================== +*/ + +boolean PA_DoIntercept(void *value, boolean isline, int frac)//L8002434C() +{ + void *value_; + int frac_; + boolean isline_; + + isline_ = isline; + value_ = value; + frac_ = frac; + + if (old_frac < frac) + { + isline_ = old_isline; + value_ = old_value; + frac_ = old_frac; + + old_isline = isline; + old_frac = frac; + old_value = value; + } + + if (frac_ == 0 || (0xffff < frac_))//frac >= FRACUNIT) + return true; + + if (isline_) + return PA_ShootLine ((line_t *)value_, frac_); + else + return PA_ShootThing ((mobj_t *)value_, frac_); +} + + +/* +============================================================================== += += PA_ShootLine += +============================================================================== +*/ + +boolean PA_ShootLine(line_t *li, fixed_t interceptfrac)//L800243D4() +{ + fixed_t slope; + fixed_t dist; + sector_t *front, *back; + static fixed_t opentop,openbottom;//80077ee4, 80077d5c + + if ( !(li->flags & ML_TWOSIDED) ) + { + if (!shootline) + { + shootline = li; + firstlinefrac = interceptfrac; + } + old_frac = 0; // don't shoot anything past this + return false; + } + + // + // crosses a two sided line + // + front = li->frontsector; + back = li->backsector; + + if (front->ceilingheight < back->ceilingheight) + opentop = front->ceilingheight; + else + opentop = back->ceilingheight; + if (front->floorheight > back->floorheight) + openbottom = front->floorheight; + else + openbottom = back->floorheight; + + dist = FixedMul(attackrange,interceptfrac); + + if (li->frontsector->floorheight != li->backsector->floorheight) + { + slope = FixedDiv(openbottom - shootz , dist); + if (slope >= aimmidslope && !shootline) + { + shootline = li; + firstlinefrac = interceptfrac; + } + if (slope > aimbottomslope) + aimbottomslope = slope; + } + + if (li->frontsector->ceilingheight != li->backsector->ceilingheight) + { + slope = FixedDiv(opentop - shootz , dist); + if (slope <= aimmidslope && !shootline) + { + shootline = li; + firstlinefrac = interceptfrac; + } + if (slope < aimtopslope) + aimtopslope = slope; + } + + if (aimtopslope <= aimbottomslope) + return false; // stop + + return true; // shot continues +} + +/* +============================================================================== += += PA_ShootThing += +============================================================================== +*/ + +boolean PA_ShootThing(mobj_t *th, fixed_t interceptfrac)//L800245CC() +{ + fixed_t frac; + fixed_t dist; + fixed_t thingaimtopslope, thingaimbottomslope; + + if (th == shooter) + return true; // can't shoot self + if (!(th->flags&MF_SHOOTABLE)) + return true; // corpse or something + + // check angles to see if the thing can be aimed at + dist = FixedMul(attackrange, interceptfrac); + + thingaimtopslope = FixedDiv(th->z+th->height - shootz , dist); + if (thingaimtopslope < aimbottomslope) + return true; // shot over the thing + + thingaimbottomslope = FixedDiv(th->z - shootz, dist); + if (thingaimbottomslope > aimtopslope) + return true; // shot under the thing + + // + // this thing can be hit! + // + if (thingaimtopslope > aimtopslope) + thingaimtopslope = aimtopslope; + if (thingaimbottomslope < aimbottomslope) + thingaimbottomslope = aimbottomslope; + + // shoot midway in the visible part of the thing + shootslope = (thingaimtopslope+thingaimbottomslope)/2; + + shootmobj = th; + + // position a bit closer + frac = interceptfrac - FixedDiv(10*FRACUNIT,attackrange); + shootx = shootdiv.x + FixedMul(shootdiv.dx, frac); + shooty = shootdiv.y + FixedMul(shootdiv.dy, frac); + shootz = shootz + FixedMul(shootslope, FixedMul(frac,attackrange)); + + return false; // don't go any farther +} + +/* +================= += += PA_SightCrossLine += += First checks the endpoints of the line to make sure that they cross the += sight trace treated as an infinite line. += += If so, it calculates the fractional distance along the sight trace that += the intersection occurs at. If 0 < intercept < 1.0, the line will block += the sight. +================= +*/ + + +fixed_t PA_SightCrossLine(line_t *line)//L8002476C() +{ + int s1, s2; + int p1x,p1y,p2x,p2y,p3x,p3y,p4x,p4y,dx,dy,ndx,ndy; + + // p1, p2 are line endpoints + p1x = line->v1->x >> FRACBITS; + p1y = line->v1->y >> FRACBITS; + p2x = line->v2->x >> FRACBITS; + p2y = line->v2->y >> FRACBITS; + + // p3, p4 are sight endpoints + p3x = ssx1; + p3y = ssy1; + p4x = ssx2; + p4y = ssy2; + + dx = p2x - p3x; + dy = p2y - p3y; + + ndx = p4x - p3x; // this can be precomputed if worthwhile + ndy = p4y - p3y; + + s1 = (ndy * dx) < (dy * ndx); + + dx = p1x - p3x; + dy = p1y - p3y; + + s2 = (ndy * dx) < (dy * ndx); + + if (s1 == s2) + return -1; // line isn't crossed + + ndx = p1y - p2y; // vector normal to world line + ndy = p2x - p1x; + + s1 = ndx*dx + ndy*dy; // distance projected onto normal + + dx = p4x - p1x; + dy = p4y - p1y; + + s2 = ndx*dx + ndy*dy; // distance projected onto normal + + s2 = FixedDiv(s1,(s1+s2)); + + return s2; +} + + + +/* +================= += += PA_CrossSubsectorPass += += Returns true if strace crosses the given subsector successfuly +================= +*/ + +boolean PA_CrossSubsector(subsector_t *sub)//L80024844 +{ + seg_t *seg; + line_t *line; + int count; + fixed_t frac; + mobj_t *thing; + + // + // check things + // + for (thing = sub->sector->thinglist ; thing ; thing = thing->snext ) + { + if (thing->subsector != sub) + continue; + + // check a corner to corner crossection for hit + + if (shootdivpositive) + { + thingline.v1.x = thing->x - thing->radius; + thingline.v1.y = thing->y + thing->radius; + thingline.v2.x = thing->x + thing->radius; + thingline.v2.y = thing->y - thing->radius; + } + else + { + thingline.v1.x = thing->x - thing->radius; + thingline.v1.y = thing->y - thing->radius; + thingline.v2.x = thing->x + thing->radius; + thingline.v2.y = thing->y + thing->radius; + } + + // inline function + frac = PA_SightCrossLine ((line_t *)&thing_line); + + if (frac < 0 || frac > FRACUNIT) { + continue; + } + // inline function + if (!PA_DoIntercept (thing, false, frac)) + { + return false; + } + } + + // + // check lines + // + count = sub->numlines; + seg = &segs[sub->firstline]; + + for ( ; count ; seg++, count--) + { + line = seg->linedef; + + if (line->validcount == validcount) + continue; // already checked other side + line->validcount = validcount; + + // inline function + frac = PA_SightCrossLine (line); + + if (frac < 0 || frac > FRACUNIT) + continue; + + // inline function + if (!PA_DoIntercept (line, true, frac)) + { + return false; + } + } + + return true; // passed the subsector ok +} + +/* +===================== += += PA_DivlineSide += +===================== +*/ +//inline +int PA_DivlineSide(fixed_t x, fixed_t y, divline_t *line)//L80024C68() +{ + fixed_t dx, dy; + + x = (x - line->x) >> FRACBITS; + y = (y - line->y) >> FRACBITS; + + dx = x * (line->dy >> FRACBITS); + dy = y * (line->dx >> FRACBITS); + + return dy < dx ^ 1; +} + +/********************************** + +Returns true if strace crosses the given node successfuly + +**********************************/ + +boolean PA_CrossBSPNode(int bspnum)//L80024CAC() +{ + node_t *bsp; + int bsp_num, side; + + if (bspnum & NF_SUBSECTOR) + { + bsp_num = (bspnum & ~NF_SUBSECTOR); + if (bsp_num >= numsubsectors) + { + I_Error("PA_CrossSubsector: ss %i with numss = %i", bsp_num, numsubsectors); + } + + return PA_CrossSubsector(&subsectors[bsp_num]); + } + + bsp = &nodes[bspnum]; + + // + // decide which side the start point is on + // + side = PA_DivlineSide(shootdiv.x, shootdiv.y, &bsp->line); + + // cross the starting side + + if (!PA_CrossBSPNode(bsp->children[side])) + return false; + + // the partition plane is crossed here + if (side == PA_DivlineSide(shootx2, shooty2, &bsp->line)) + return true; // the line doesn't touch the other side + + // cross the ending side + return PA_CrossBSPNode(bsp->children[side ^ 1]); +} +#endif // 0 diff --git a/Doom 64/p_sight.c b/Doom 64/p_sight.c @@ -0,0 +1,307 @@ +#include "doomdef.h" +#include "p_local.h" + +fixed_t sightzstart; //800A5F20 // eye z of looker +fixed_t topslope, bottomslope; //800A5F24 ,800A5F28 // slopes to top and bottom of target + +divline_t strace; //800A5F30 // from t1 to t2 +fixed_t t2x, t2y; //800A5F40, 800A5F44 + +int t1xs,t1ys,t2xs,t2ys; //800A5F48,800A5F4C,800A5F50,800A5F54 + + +/* +=============== += += P_CheckSights += += Check sights of all mobj thinkers that are going to change state this += tic and have MF_COUNTKILL set +=============== +*/ + +void P_CheckSights(void) // 8001EB00 +{ + mobj_t *mobj; + + for (mobj = mobjhead.next; mobj != &mobjhead; mobj = mobj->next) + { + // must be killable + if (!(mobj->flags & MF_COUNTKILL)) + continue; + + // must be about to change states + if (mobj->tics != 1) + continue; + + mobj->flags &= ~MF_SEETARGET; + + // must have a target + if (!mobj->target) + continue; + + if (P_CheckSight(mobj, mobj->target)) + mobj->flags |= MF_SEETARGET; + } +} + + +/********************************** + +Returns true if a straight line between t1 and t2 is unobstructed + +**********************************/ + +boolean P_CheckSight(mobj_t *t1, mobj_t *t2) // 8001EBCC +{ + int s1, s2; + int pnum, bytenum, bitnum; + + // + // check for trivial rejection + // + s1 = (t1->subsector->sector - sectors); + s2 = (t2->subsector->sector - sectors); + pnum = s1*numsectors + s2; + bytenum = pnum >> 3; + bitnum = 1 << (pnum & 7); + + if (rejectmatrix[bytenum] & bitnum) { + return false; // can't possibly be connected + } + + // look from eyes of t1 to any part of t2 + + ++validcount; + + // make sure it never lies exactly on a vertex coordinate + + strace.x = (t1->x & ~0x1ffff) | 0x10000; + strace.y = (t1->y & ~0x1ffff) | 0x10000; + t2x = (t2->x & ~0x1ffff) | 0x10000; + t2y = (t2->y & ~0x1ffff) | 0x10000; + strace.dx = t2x - strace.x; + strace.dy = t2y - strace.y; + + t1xs = strace.x >> FRACBITS; + t1ys = strace.y >> FRACBITS; + t2xs = t2x >> FRACBITS; + t2ys = t2y >> FRACBITS; + + sightzstart = (t1->z + t1->height) - (t1->height >> 2); + topslope = (t2->z + t2->height) - sightzstart; + bottomslope = (t2->z) - sightzstart; + + return PS_CrossBSPNode(numnodes - 1); +} + +/* +================= += += PS_SightCrossLine += += First checks the endpoints of the line to make sure that they cross the += sight trace treated as an infinite line. += += If so, it calculates the fractional distance along the sight trace that += the intersection occurs at. If 0 < intercept < 1.0, the line will block += the sight. +================= +*/ + +fixed_t PS_SightCrossLine (line_t *line) // 8001EDD8 +{ + int s1, s2; + int p1x,p1y,p2x,p2y,p3x,p3y,p4x,p4y,dx,dy,ndx,ndy; + + // p1, p2 are line endpoints + p1x = line->v1->x >> FRACBITS; + p1y = line->v1->y >> FRACBITS; + p2x = line->v2->x >> FRACBITS; + p2y = line->v2->y >> FRACBITS; + + // p3, p4 are sight endpoints + p3x = t1xs; + p3y = t1ys; + p4x = t2xs; + p4y = t2ys; + + dx = p2x - p3x; + dy = p2y - p3y; + + ndx = p4x - p3x; // this can be precomputed if worthwhile + ndy = p4y - p3y; + + s1 = (ndy * dx) < (dy * ndx); + + dx = p1x - p3x; + dy = p1y - p3y; + + s2 = (ndy * dx) < (dy * ndx); + + if (s1 == s2) + return -1; // line isn't crossed + + ndx = p1y - p2y; // vector normal to world line + ndy = p2x - p1x; + + s1 = ndx*dx + ndy*dy; // distance projected onto normal + + dx = p4x - p1x; + dy = p4y - p1y; + + s2 = ndx*dx + ndy*dy; // distance projected onto normal + + s2 = FixedDiv(s1,(s1+s2)); + + return s2; +} + +/* +================= += += PS_CrossSubsector += += Returns true if strace crosses the given subsector successfuly +================= +*/ + +boolean PS_CrossSubsector(subsector_t *sub) // 8001EF10 +{ + seg_t *seg; + line_t *line; + int count; + sector_t *front, *back; + fixed_t opentop, openbottom; + fixed_t frac, slope; + + // + // check lines + // + count = sub->numlines; + seg = &segs[sub->firstline]; + + for ( ; count ; seg++, count--) + { + line = seg->linedef; + + if (line->validcount == validcount) + continue; // allready checked other side + line->validcount = validcount; + + frac = PS_SightCrossLine (line); + + if (frac < 4 || frac >= (FRACUNIT+1)) + continue; + + // + // crosses line + // + back = line->backsector; + if (!back) + return false; // one sided line + front = line->frontsector; + + if (front->floorheight == back->floorheight + && front->ceilingheight == back->ceilingheight) + continue; // no wall to block sight with + + if (front->ceilingheight < back->ceilingheight) + opentop = front->ceilingheight; + else + opentop = back->ceilingheight; + if (front->floorheight > back->floorheight) + openbottom = front->floorheight; + else + openbottom = back->floorheight; + + if (openbottom >= opentop) // quick test for totally closed doors + return false; // stop + + frac >>= 2; + + if (front->floorheight != back->floorheight) + { + slope = (((openbottom - sightzstart)<<6) / frac) << 8; + if (slope > bottomslope) + bottomslope = slope; + } + + if (front->ceilingheight != back->ceilingheight) + { + slope = (((opentop - sightzstart)<<6) / frac) << 8; + if (slope < topslope) + topslope = slope; + } + + if (topslope <= bottomslope) + return false; // stop + } + + return true; // passed the subsector ok +} + +/* +================= += += PS_CrossBSPNode += += Returns true if strace crosses the given node successfuly +================= +*/ + +boolean PS_CrossBSPNode(int bspnum) // 8001F15C +{ + node_t *bsp; + int side1, side2; + int bsp_num; + fixed_t dx, dy; + fixed_t left, right; + + if (bspnum & NF_SUBSECTOR) + { + bsp_num = (bspnum & ~NF_SUBSECTOR); + if (bsp_num >= numsubsectors) + { + I_Error("PS_CrossSubsector: ss %i with numss = %i", bsp_num, numsubsectors); + } + + return PS_CrossSubsector(&subsectors[bsp_num]); + } + + bsp = &nodes[bspnum]; + + // decide which side the start point is on + side1 = 1; + + dx = (strace.x - bsp->line.x); + dy = (strace.y - bsp->line.y); + + left = (bsp->line.dy>>FRACBITS) * (dx>>FRACBITS); + right = (dy>>FRACBITS) * (bsp->line.dx>>FRACBITS); + + if(right < left) + side1 = 0; // front side + + // cross the starting side + if (!PS_CrossBSPNode(bsp->children[side1])) + return false; + + // the partition plane is crossed here + side2 = 1; + + dx = (t2x - bsp->line.x); + dy = (t2y - bsp->line.y); + + left = (bsp->line.dy>>FRACBITS) * (dx>>FRACBITS); + right = (dy>>FRACBITS) * (bsp->line.dx>>FRACBITS); + + if(right < left) + side2 = 0; // front side + + if (side1 == side2) + return true; // the line doesn't touch the other side + + // cross the ending side + return PS_CrossBSPNode(bsp->children[side1 ^ 1]); +} diff --git a/Doom 64/p_slide.c b/Doom 64/p_slide.c @@ -0,0 +1,755 @@ +#include "doomdef.h" +#include "p_local.h" + +#define CLIPRADIUS 23 +#define SIDE_ON 0 +#define SIDE_FRONT 1 +#define SIDE_BACK -1 + +fixed_t bestslidefrac; // 800A5728 +line_t *bestslideline; // 800A572C +mobj_t *slidemo; // 800A5730 + +/* +==================== += += PTR_SlideTraverse += +==================== +*/ + +boolean PTR_SlideTraverse(intercept_t* in) // 800170AC +{ + line_t* li; + + li = in->d.line; + + if(!(li->flags & ML_TWOSIDED)) + { + if(P_PointOnLineSide(slidemo->x, slidemo->y, li)) + return true; /* don't hit the back side */ + + goto isblocking; + } + + /* set openrange, opentop, openbottom */ + P_LineOpening(li); + + if(openrange < slidemo->height) + { + goto isblocking; /* doesn't fit */ + } + + if(opentop - slidemo->z < slidemo->height) + { + goto isblocking; /* mobj is too high */ + } + + if(openbottom - slidemo->z > 24*FRACUNIT) + { + goto isblocking; /* too big a step up */ + } + + /* this line doesn't block movement */ + return true; + + /* the line does block movement, */ + /* see if it is closer than best so far */ + +isblocking: + + if(in->frac < bestslidefrac) + { + bestslidefrac = in->frac; + bestslideline = li; + } + + return false; /* stop */ +} + +/* +=============================================== += P_SlideMove += The momx / momy move is bad, so try to slide += along a wall. += Find the first line hit, move flush to it, += and slide along it += += This is a kludgy mess. +=============================================== +*/ + +void P_SlideMove(mobj_t* mo) // 800171B0 +{ + fixed_t tmxmove; + fixed_t tmymove; + fixed_t leadx; + fixed_t leady; + fixed_t trailx; + fixed_t traily; + fixed_t newx; + fixed_t newy; + int hitcount; + line_t* ld; + int an1; + int an2; + + slidemo = mo; + hitcount = 0; + +retry: + hitcount++; + + if(hitcount == 3) + { + goto stairstep; // don't loop forever + } + + // trace along the three leading corners + if(mo->momx > 0) + { + leadx = mo->x + mo->radius; + trailx = mo->x - mo->radius; + } + else + { + leadx = mo->x - mo->radius; + trailx = mo->x + mo->radius; + } + + if(mo->momy > 0) + { + leady = mo->y + mo->radius; + traily = mo->y - mo->radius; + } + else + { + leady = mo->y - mo->radius; + traily = mo->y + mo->radius; + } + + bestslidefrac = FRACUNIT+1; + + P_PathTraverse(leadx, leady, leadx + mo->momx, leady + mo->momy, + PT_ADDLINES, PTR_SlideTraverse); + P_PathTraverse(trailx, leady, trailx + mo->momx, leady + mo->momy, + PT_ADDLINES, PTR_SlideTraverse); + P_PathTraverse(leadx, traily, leadx + mo->momx, traily + mo->momy, + PT_ADDLINES, PTR_SlideTraverse); + + // move up to the wall + if(bestslidefrac == FRACUNIT+1) + { + // the move most have hit the middle, so stairstep +stairstep: + if(!P_TryMove(mo, mo->x, mo->y + mo->momy)) + { + if(!P_TryMove(mo, mo->x + mo->momx, mo->y)) + { + // [d64] set momx and momy to 0 + mo->momx = 0; + mo->momy = 0; + } + } + return; + } + + // fudge a bit to make sure it doesn't hit + bestslidefrac -= 0x800; + if(bestslidefrac > 0) + { + newx = FixedMul(mo->momx, bestslidefrac); + newy = FixedMul(mo->momy, bestslidefrac); + + if(!P_TryMove(mo, mo->x + newx, mo->y + newy)) + { + bestslidefrac = FRACUNIT; + + // [d64] jump to hitslideline instead of stairstep + goto hitslideline; + } + } + + // Now continue along the wall. + // First calculate remainder. + bestslidefrac = 0xf800 - bestslidefrac; + //bestslidefrac = FRACUNIT - (bestslidefrac + 0x800); + + if(bestslidefrac > FRACUNIT) + { + bestslidefrac = FRACUNIT; + } + + if(bestslidefrac <= 0) + { + return; + } + + // + // [d64] code below is loosely based on P_HitSlideLine + // +hitslideline: + + ld = bestslideline; + + if(ld->slopetype == ST_HORIZONTAL) + { + tmymove = 0; + } + else + { + tmymove = FixedMul(mo->momy, bestslidefrac); + } + + if(ld->slopetype == ST_VERTICAL) + { + tmxmove = 0; + } + else + { + tmxmove = FixedMul(mo->momx, bestslidefrac); + } + + // + // [d64] this new algorithm seems to reduce the chances + // of boosting the player's speed when wall running + // + + an1 = finecosine[ld->fineangle]; + an2 = finesine[ld->fineangle]; + + if(P_PointOnLineSide(mo->x, mo->y, bestslideline)) + { + // + // [d64] same as deltaangle += ANG180 ? + // + an1 = -an1; + an2 = -an2; + } + + newx = FixedMul(tmxmove, an1); + newy = FixedMul(tmymove, an2); + + mo->momx = FixedMul(newx + newy, an1); + mo->momy = FixedMul(newx + newy, an2); + + if(!P_TryMove(mo, mo->x + mo->momx, mo->y + mo->momy)) + { + goto retry; + } +} + +//---------------------- + +#if 0 + +fixed_t slidex, slidey; // the final position //80077DBC|fGp000009ac, 80077DC0|fGp000009b0 +line_t *specialline; //80077DC8, uGp000009b8 + +fixed_t slidedx, slidedy; // current move for completablefrac //80077E9C|fGp00000a8c, 80077EA0|fGp00000a90 + +fixed_t endbox[4]; // final proposed position //800979d0 + +fixed_t blockfrac; // the fraction of move that gets completed //8007804C|iGp00000c3c +fixed_t blocknvx, blocknvy; // the vector of the line that blocks move //80077FD0|fGp00000bc0, 80077FD8|fGp00000bc8 + +// p1, p2 are line endpoints +// p3, p4 are move endpoints +/*iGp00000ae4, iGp00000aec*///p1x, p1y +/*iGp00000ae8, iGp00000af8*///p2x, p2y +/*iGp00000af4, iGp00000b0c*///p3x, p3y +/*iGp00000b08, iGp00000b14*///p4x, p4y + +int p1x, p1y, p2x, p2y, p3x, p3y, p4x, p4y; +fixed_t nvx, nvy; // normalized line vector //fGp00000b70, fGp00000b74 + +extern mobj_t *slidething;//80077D04 + + +fixed_t P_CompletableFrac(fixed_t dx, fixed_t dy); +int SL_PointOnSide(fixed_t x, fixed_t y); +fixed_t SL_CrossFrac (void); +boolean CheckLineEnds (void); +void SL_ClipToLine( void ); +boolean SL_CheckLine(line_t *ld); +int SL_PointOnSide2(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, fixed_t x3, fixed_t y3); +void SL_CheckSpecialLines (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2); + +/* +=================== += += P_SlideMove += +=================== +*/ + +void P_SlideMove(void)//L8002553C() +{ + fixed_t dx, dy, rx, ry; + fixed_t frac, slide; + int i; + + dx = slidething->momx; + dy = slidething->momy; + slidex = slidething->x; + slidey = slidething->y; + + if (slidething->flags & MF_NOCLIP)//Psx Doom + { + frac = FRACUNIT; + goto Skip_P_CompletableFrac; + } + + // perform a maximum of three bumps + for (i = 0; i < 3; i++) + { + frac = P_CompletableFrac(dx, dy); + + if (frac != FRACUNIT) + frac -= 0x1000; + + if (frac < 0) + frac = 0; + + Skip_P_CompletableFrac: + rx = FixedMul(frac, dx); + ry = FixedMul(frac, dy); + + slidex += rx; + slidey += ry; + + // made it the entire way + if (frac == FRACUNIT) + { + slidething->momx = dx; + slidething->momy = dy; + SL_CheckSpecialLines(slidething->x, slidething->y, slidex, slidey); + return; + } + + // project the remaining move along the line that blocked movement + dx -= rx; + dy -= ry; + slide = FixedMul(dx, blocknvx) + FixedMul(dy, blocknvy); + + dx = FixedMul(slide, blocknvx); + dy = FixedMul(slide, blocknvy); + } + + // some hideous situation has happened that won't let the player slide + slidex = slidething->x; + slidey = slidething->y; + slidething->momx = slidething->momy = 0; +} + + +/* +=================== += += P_CompletableFrac += += Returns the fraction of the move that is completable +=================== +*/ + +fixed_t P_CompletableFrac(fixed_t dx, fixed_t dy)//L800256CC() +{ + int xl,xh,yl,yh,bx,by; + int offset; + short *list; + line_t *ld; + + blockfrac = FRACUNIT; // the entire dist until shown otherwise + slidedx = dx; + slidedy = dy; + + endbox[BOXTOP ] = slidey + CLIPRADIUS*FRACUNIT; + endbox[BOXBOTTOM] = slidey - CLIPRADIUS*FRACUNIT; + endbox[BOXRIGHT ] = slidex + CLIPRADIUS*FRACUNIT; + endbox[BOXLEFT ] = slidex - CLIPRADIUS*FRACUNIT; + + if (dx > 0) + endbox[BOXRIGHT ] += dx; + else + endbox[BOXLEFT ] += dx; + + if (dy > 0) + endbox[BOXTOP ] += dy; + else + endbox[BOXBOTTOM] += dy; + + ++validcount; + + // + // check lines + // + xl = (endbox[BOXLEFT ] - bmaporgx) >> MAPBLOCKSHIFT; + xh = (endbox[BOXRIGHT ] - bmaporgx) >> MAPBLOCKSHIFT; + yl = (endbox[BOXBOTTOM] - bmaporgy) >> MAPBLOCKSHIFT; + yh = (endbox[BOXTOP ] - bmaporgy) >> MAPBLOCKSHIFT; + + if (xl<0) + xl = 0; + if (yl<0) + yl = 0; + + if (xh>= bmapwidth) + xh = bmapwidth -1; + + if (yh>= bmapheight) + yh = bmapheight -1; + + for (bx = xl; bx <= xh; bx++) + { + for (by = yl; by <= yh; by++) + { + /*inline ??*/ + //P_BlockLinesIterator(bx, by, SL_CheckLine); + + offset = by*bmapwidth+bx; + + offset = *(blockmap+offset); + + for ( list = blockmaplump+offset ; *list != -1 ; list++) + { + ld = &lines[*list]; + + if (ld->validcount != validcount) + { + ld->validcount = validcount; + SL_CheckLine(ld); + } + } + } + } + + // + // examine results + // + if (blockfrac < 0x1000) + { + blockfrac = 0; + specialline = 0; // can't cross anything on a bad move + return 0; // solid wall or thing + } + + return blockfrac; +} + +//inline +int SL_PointOnSide(fixed_t x, fixed_t y)//L80025970() +{ + //checked + fixed_t dx, dy, dist; + + dx = x - p1x; + dy = y - p1y; + dist = FixedMul(dx,nvx) + FixedMul(dy,nvy); + + if(dist > FRACUNIT) + return SIDE_FRONT; + else if(dist < -FRACUNIT) + return SIDE_BACK; + else + return SIDE_ON; +} + +//inline +fixed_t SL_CrossFrac (void)//L800259E0() +{ + //checked + fixed_t dx, dy, dist1, dist2, frac; + + // project move start and end points onto line normal + dx = p3x - p1x; + dy = p3y - p1y; + + dist1 = FixedMul(dx,nvx) + FixedMul(dy,nvy); + + dx = p4x - p1x; + dy = p4y - p1y; + dist2 = FixedMul(dx,nvx) + FixedMul(dy,nvy); + + if ((dist1 < 0) == (dist2 < 0)) + return FRACUNIT; // doesn't cross + + frac = FixedDiv(dist1, dist1 - dist2 ); + + return frac; +} + + +boolean CheckLineEnds (void)//L80025A98() +{ + //checked + fixed_t snx, sny; // sight normals + fixed_t dist1, dist2; + fixed_t dx, dy; + + snx = p4y - p3y; + sny = p3x - p4x; + + dx = p1x - p3x; + dy = p1y - p3y; + + dist1 = FixedMul(dx,snx) + FixedMul(dy,sny); + + dx = p2x - p3x; + dy = p2y - p3y; + + dist2 = FixedMul(dx,snx) + FixedMul(dy,sny); + + return ((dist1 < 0)^(dist2 < 0)); + + /* + if ( (dist1<0) == (dist2<0) ) + return false; + + return true; + */ +} + + +/* +==================== += += SL_ClipToLine += += Call with p1 and p2 set to the endpoints += and nvx, nvy set to normalized vector += Assumes the start point is definately on the front side of the line += returns the fraction of the current move that crosses the line segment +==================== +*/ + +void SL_ClipToLine( void )//L80025B58() +{ + fixed_t frac; + int side2, side3; + + // adjust start so it will be the first point contacted on the player circle + // p3, p4 are move endpoints + + p3x = slidex - CLIPRADIUS * nvx; + p3y = slidey - CLIPRADIUS * nvy; + p4x = p3x + slidedx; + p4y = p3y + slidedy; + + // if the adjusted point is on the other side of the line, the endpoint must + // be checked. + side2 = SL_PointOnSide(p3x, p3y); + if(side2 == SIDE_BACK) + return; // ClipToPoint and slide along normal to line + + side3 = SL_PointOnSide(p4x, p4y); + if(side3 == SIDE_ON) + return; // the move goes flush with the wall + else if(side3 == SIDE_FRONT) + return; // move doesn't cross line + + if(side2 == SIDE_ON) + { + frac = 0; // moves toward the line + goto blockmove; + } + + // the line endpoints must be on opposite sides of the move trace + + // find the fractional intercept + frac = SL_CrossFrac(); + + if(frac < blockfrac) + { + blockmove: + blockfrac = frac; + blocknvx = -nvy; + blocknvy = nvx; + } +} + +/* +================== += += SL_CheckLine += +================== +*/ + + +boolean SL_CheckLine(line_t *ld)//L80025D50() +{ + fixed_t opentop, openbottom; + sector_t *front, *back; + int side1, temp; + + // check bbox first + if (endbox[BOXRIGHT ] < ld->bbox[BOXLEFT ] + || endbox[BOXLEFT ] > ld->bbox[BOXRIGHT ] + || endbox[BOXTOP ] < ld->bbox[BOXBOTTOM] + || endbox[BOXBOTTOM] > ld->bbox[BOXTOP ] ) + return true; + + // see if it can possibly block movement + if (!ld->backsector || ld->flags & ML_BLOCKING) + goto findfrac; // explicitly blocking + + front = ld->frontsector; + back = ld->backsector; + + if (front->floorheight > back->floorheight) + openbottom = front->floorheight; + else + openbottom = back->floorheight; + + if (openbottom - slidething->z > 24*FRACUNIT) + goto findfrac; // too big of a step up + + if (front->ceilingheight < back->ceilingheight) + opentop = front->ceilingheight; + else + opentop = back->ceilingheight; + + if (opentop - openbottom >= 56*FRACUNIT) + return true; // the line doesn't block movement + + // the line definately blocks movement +findfrac: + // p1, p2 are line endpoints + p1x = ld->v1->x; + p1y = ld->v1->y; + p2x = ld->v2->x; + p2y = ld->v2->y; + + nvx = finesine[ld->fineangle]; + nvy = -finecosine[ld->fineangle]; + + side1 = SL_PointOnSide (slidex, slidey); + if (side1 == SIDE_ON) + return true; + if (side1 == SIDE_BACK) + { + if (!ld->backsector) + return true; // don't clip to backs of one sided lines + temp = p1x; + p1x = p2x; + p2x = temp; + temp = p1y; + p1y = p2y; + p2y = temp; + nvx = -nvx; + nvy = -nvy; + } + + SL_ClipToLine(); + return true; +} + +int SL_PointOnSide2(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2, fixed_t x3, fixed_t y3)//L80025f9C() +{ + //checked + fixed_t nx, ny; + fixed_t dist; + + x1 = (x1 - x2); + y1 = (y1 - y2); + + nx = (y3 - y2); + ny = (x2 - x3); + + dist = FixedMul(x1, nx) + FixedMul(y1, ny); + + if (dist < 0) + return SIDE_BACK; + return SIDE_FRONT; +} + +static short *list_; //80078074|psGp00000c64 +static line_t *ld_; //80077E48|plGp00000a38 +static int offset_; //80077DB0|iGp000009a0 + +void SL_CheckSpecialLines (fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2)//L8002600C() +{ + fixed_t bx, by, xl, xh, yl, yh, bxl, bxh, byl, byh; + fixed_t x3,y3,x4,y4; + int side1, side2; + + if (x1<x2) { + xl = x1; + xh = x2; + } else { + xl = x2; + xh = x1; + } + if (y1<y2) { + yl = y1; + yh = y2; + } else { + yl = y2; + yh = y1; + } + + bxl = (xl - bmaporgx)>>MAPBLOCKSHIFT; + bxh = (xh - bmaporgx)>>MAPBLOCKSHIFT; + byl = (yl - bmaporgy)>>MAPBLOCKSHIFT; + byh = (yh - bmaporgy)>>MAPBLOCKSHIFT; + + if (bxl<0) + bxl = 0; + if (byl<0) + byl = 0; + if (bxh>= bmapwidth) + bxh = bmapwidth -1; + if (byh>= bmapheight) + byh = bmapheight -1; + + specialline = 0; + ++validcount; + + for (bx = bxl; bx <= bxh; bx++) + { + for (by = byl; by <= byh; by++) + { + offset_ = (by*bmapwidth) + bx; + offset_ = *(blockmap + offset_); + + for (list_ = blockmaplump + offset_; *list_ != -1; list_++) + { + ld_ = &lines[*list_]; + + if (!ld_->special) + continue; + if (ld_->validcount == validcount) + continue; // line has already been checked + + ld_->validcount = validcount; + + if (xh < ld_->bbox[BOXLEFT] + || xl > ld_->bbox[BOXRIGHT] + || yh < ld_->bbox[BOXBOTTOM] + || yl > ld_->bbox[BOXTOP]) + continue; + + x3 = ld_->v1->x; + y3 = ld_->v1->y; + x4 = ld_->v2->x; + y4 = ld_->v2->y; + + side1 = SL_PointOnSide2(x1, y1, x3, y3, x4, y4); + side2 = SL_PointOnSide2(x2, y2, x3, y3, x4, y4); + + if (side1 == side2) + continue; // move doesn't cross line + + side1 = SL_PointOnSide2(x3, y3, x1, y1, x2, y2); + side2 = SL_PointOnSide2(x4, y4, x1, y1, x2, y2); + + if (side1 == side2) + continue; // line doesn't cross move + + specialline = ld_; + return; + } + } + } +} +#endif // 0 diff --git a/Doom 64/p_spec.c b/Doom 64/p_spec.c @@ -0,0 +1,1305 @@ +/* P_Spec.c */ +#include "doomdef.h" +#include "r_local.h" +#include "p_local.h" +#include "st_main.h" + +extern mapthing_t *spawnlist; // 800A5D74 +extern int spawncount; // 800A5D78 + +line_t **linespeciallist; // 800A5F60 +int numlinespecials; // 800A5F64 + +sector_t **sectorspeciallist;// 800A5F68 +int numsectorspecials; // 800A5F6C + +animdef_t animdefs[MAXANIMS] = // 8005AE80 +{ + { 15, "SMONAA", 4, 7, false, false }, + { 0, "SMONBA", 4, 1, false, false }, + { 0, "SMONCA", 4, 7, false, false }, + { 90, "CFACEA", 3, 3, true, false }, + { 0, "SMONDA", 4, 3, false, false }, + { 10, "SMONEA", 4, 7, false, false }, + { 0, "SPORTA", 9, 3, false, true }, + { 10, "SMONF", 5, 1, true, true }, + { 10, "STRAKR", 5, 1, true, true }, + { 10, "STRAKB", 5, 1, true, true }, + { 10, "STRAKY", 5, 1, true, true }, + { 50, "C307B", 5, 1, true, true }, + { 0, "CTEL", 8, 3, false, true }, + { 0,"CASFL98", 5, 7, true, true }, + { 0, "HTELA", 4, 1, true, false } +}; + +/*---------- +/ anims[8] -> anims[MAXANIMS = 15] +/ For some reason Doom 64 is 8, +/ I will leave it at 15 to avoid problems loading data into this pointer. +/---------*/ +anim_t anims[MAXANIMS], *lastanim; // 800A5F70, 800A6090 + +card_t MapBlueKeyType; //0x80077E9C +card_t MapRedKeyType; //0x8007821C +card_t MapYellowKeyType; //0x800780A0 + +void P_AddSectorSpecial(sector_t *sec); + +/* +================= += += P_Init += +================= +*/ + +void P_Init (void) // 8001F340 +{ + int i; + sector_t *sector; + side_t *side; + + side = sides; + for (i = 0; i < numsides; i++, side++) + { + W_CacheLumpNum(side->toptexture + firsttex , PU_LEVEL, dec_d64); + W_CacheLumpNum(side->bottomtexture + firsttex , PU_LEVEL, dec_d64); + W_CacheLumpNum(side->midtexture + firsttex , PU_LEVEL, dec_d64); + } + + sector = sectors; + for (i = 0; i < numsectors; i++, sector++) + { + if (sector->ceilingpic >= 0) + W_CacheLumpNum(sector->ceilingpic + firsttex, PU_LEVEL, dec_d64); + + if (sector->floorpic >= 0) + W_CacheLumpNum(sector->floorpic + firsttex, PU_LEVEL, dec_d64); + + if (sector->flags & MS_LIQUIDFLOOR) + W_CacheLumpNum(sector->floorpic + firsttex + 1, PU_LEVEL,dec_d64); + } +} + +/* +============================================================================== + + SPECIAL SPAWNING + +============================================================================== +*/ +/* +================================================================================ += P_SpawnSpecials += += After the map has been loaded, scan for specials that += spawn thinkers += +=============================================================================== +*/ + +void P_SpawnSpecials (void) // 8001F490 +{ + mobj_t *mo; + sector_t *sector; + line_t *line; + int i, j; + int lump; + + /* */ + /* Init animation aka (P_InitPicAnims) */ + /* */ + lastanim = anims; + for (i=0 ; i < MAXANIMS ; i++) + { + lump = W_GetNumForName(animdefs[i].startname); + + lastanim->basepic = (lump - firsttex); + lastanim->tics = animdefs[i].speed; + lastanim->delay = animdefs[i].delay; + lastanim->delaycnt = lastanim->delay; + lastanim->isreverse = animdefs[i].isreverse; + + if (animdefs[i].ispalcycle == false) + { + lastanim->current = (lump << 4); + lastanim->picstart = (lump << 4); + lastanim->picend = (animdefs[i].frames + lump - 1) << 4; + lastanim->frame = 16; + + /* Load the following graphics for animation */ + for (j=0 ; j < animdefs[i].frames ; j++) + { + W_CacheLumpNum(lump, PU_LEVEL, dec_d64); + lump++; + } + } + else + { + lastanim->current = (lump << 4); + lastanim->picstart = (lump << 4); + lastanim->picend = (lump << 4) | (animdefs[i].frames - 1); + lastanim->frame = 1; + } + + lastanim++; + } + + /* */ + /* Init Macro Variables */ + /* */ + activemacro = NULL; + macrocounter = 0; + macroidx1 = 0; + macroidx2 = 0; + + /* */ + /* Init special SECTORs */ + /* */ + scrollfrac = 0; + numsectorspecials = 0; // Restart count + sector = sectors; + for(i = 0; i < numsectors; i++, sector++) + { + P_AddSectorSpecial(sector); + if(sector->flags & MS_SECRET) + { + totalsecret++; + } + + if(sector->flags & (MS_SCROLLCEILING | MS_SCROLLFLOOR| + MS_SCROLLLEFT | MS_SCROLLRIGHT| MS_SCROLLUP| MS_SCROLLDOWN)) + { + numsectorspecials++; + } + } + + sectorspeciallist = (sector_t**)Z_Malloc(numsectorspecials*sizeof(void*), PU_LEVEL, NULL); + sector = sectors; + for(i = 0, j = 0; i < numsectors; i++, sector++) + { + if(sector->flags & (MS_SCROLLCEILING | MS_SCROLLFLOOR| + MS_SCROLLLEFT | MS_SCROLLRIGHT| MS_SCROLLUP| MS_SCROLLDOWN)) + { + sectorspeciallist[j] = sector; + j++; + } + } + + /* */ + /* Init line EFFECTs */ + /* */ + numlinespecials = 0; + line = lines; + for (i = 0;i < numlines; i++, line++) + { + if(line->flags & (ML_SCROLLRIGHT|ML_SCROLLLEFT|ML_SCROLLUP|ML_SCROLLDOWN)) + { + numlinespecials++; + } + } + + linespeciallist = (line_t**)Z_Malloc(numlinespecials*sizeof(void*), PU_LEVEL, NULL); + line = lines; + for (i = 0, j = 0; i < numlines; i++, line++) + { + if(line->flags & (ML_SCROLLRIGHT|ML_SCROLLLEFT|ML_SCROLLUP|ML_SCROLLDOWN)) + { + linespeciallist[j] = line; + j++; + } + } + + /* */ + /* Init Keys */ + /* */ + + MapBlueKeyType = it_bluecard; + MapYellowKeyType = it_yellowcard; + MapRedKeyType = it_redcard; + for (mo = mobjhead.next ; mo != &mobjhead ; mo = mo->next) + { + if((mo->type == MT_ITEM_BLUESKULLKEY) || + (mo->type == MT_ITEM_YELLOWSKULLKEY) || + (mo->type == MT_ITEM_REDSKULLKEY)) + { + MapBlueKeyType = it_blueskull; + MapYellowKeyType = it_yellowskull; + MapRedKeyType = it_redskull; + break; + } + + /*switch (mo->type) + { + case MT_ITEM_BLUESKULLKEY: MapBlueKeyType = it_blueskull; break; + case MT_ITEM_YELLOWSKULLKEY: MapYellowKeyType = it_yellowskull; break; + case MT_ITEM_REDSKULLKEY: MapRedKeyType = it_redskull; break; + }*/ + } + + for (i = 0; i < spawncount; i++) + { + if((spawnlist[i].type == 40) || + (spawnlist[i].type == 39) || + (spawnlist[i].type == 38)) + { + MapBlueKeyType = it_blueskull; + MapYellowKeyType = it_yellowskull; + MapRedKeyType = it_redskull; + break; + } + + /*if(spawnlist[i].type == 40)//mobjinfo[MT_ITEM_BLUESKULLKEY].doomednum + MapBlueKeyType = it_blueskull; + if(spawnlist[i].type == 39)//mobjinfo[MT_ITEM_YELLOWSKULLKEY].doomednum + MapYellowKeyType = it_yellowskull; + if(spawnlist[i].type == 38)//mobjinfo[MT_ITEM_REDSKULLKEY].doomednum + MapRedKeyType = it_redskull;*/ + } + + /* */ + /* Init other misc stuff */ + /* */ + D_memset(activeceilings, 0, MAXCEILINGS * sizeof(ceiling_t*)); + D_memset(activeplats, 0, MAXPLATS * sizeof(plat_t*)); + D_memset(buttonlist, 0, MAXBUTTONS * sizeof(button_t)); +} + +/* +============================================================================== + + UTILITIES + +============================================================================== +*/ + +/*================================================================== */ +/* */ +/* Return sector_t * of sector next to current. NULL if not two-sided line */ +/* */ +/*================================================================== */ +sector_t *getNextSector(line_t *line,sector_t *sec) // 8001F96C +{ + if (!(line->flags & ML_TWOSIDED)) + return NULL; + + if (line->frontsector == sec) + return line->backsector; + + return line->frontsector; +} + +/*================================================================== */ +/* */ +/* FIND LOWEST FLOOR HEIGHT IN SURROUNDING SECTORS */ +/* */ +/*================================================================== */ +fixed_t P_FindLowestFloorSurrounding(sector_t *sec) // 8001F9AC +{ + int i; + line_t *check; + sector_t *other; + fixed_t floor = sec->floorheight; + + for (i=0 ;i < sec->linecount ; i++) + { + check = sec->lines[i]; + other = getNextSector(check,sec); + if (!other) + continue; + if (other->floorheight < floor) + floor = other->floorheight; + } + return floor; +} + +/*================================================================== */ +/* */ +/* FIND HIGHEST FLOOR HEIGHT IN SURROUNDING SECTORS */ +/* */ +/*================================================================== */ +fixed_t P_FindHighestFloorSurrounding(sector_t *sec) // 8001FA48 +{ + int i; + line_t *check; + sector_t *other; + fixed_t floor = -500*FRACUNIT; + + for (i=0 ;i < sec->linecount ; i++) + { + check = sec->lines[i]; + other = getNextSector(check,sec); + if (!other) + continue; + if (other->floorheight > floor) + floor = other->floorheight; + } + return floor; +} + +/*================================================================== */ +/* */ +/* FIND NEXT HIGHEST FLOOR IN SURROUNDING SECTORS */ +/* */ +/*================================================================== */ +fixed_t P_FindNextHighestFloor(sector_t *sec,int currentheight) // 8001FAE4 +{ + int i; + int h; + int min; + line_t *check; + sector_t *other; + fixed_t height = currentheight; + fixed_t heightlist[20]; /* 20 adjoining sectors max! */ + + for (i =0,h = 0 ;i < sec->linecount ; i++) + { + check = sec->lines[i]; + other = getNextSector(check,sec); + if (!other) + continue; + if (other->floorheight > height) + heightlist[h++] = other->floorheight; + } + + /* */ + /* Find lowest height in list */ + /* */ + min = heightlist[0]; + for (i = 1;i < h;i++) + if (heightlist[i] < min) + min = heightlist[i]; + + return min; +} + +/*================================================================== */ +/* */ +/* FIND LOWEST CEILING IN THE SURROUNDING SECTORS */ +/* */ +/*================================================================== */ +fixed_t P_FindLowestCeilingSurrounding(sector_t *sec) // 8001FC68 +{ + int i; + line_t *check; + sector_t *other; + fixed_t height = MAXINT; + + for (i=0 ;i < sec->linecount ; i++) + { + check = sec->lines[i]; + other = getNextSector(check,sec); + if (!other) + continue; + if (other->ceilingheight < height) + height = other->ceilingheight; + } + return height; +} + +/*================================================================== */ +/* */ +/* FIND HIGHEST CEILING IN THE SURROUNDING SECTORS */ +/* */ +/*================================================================== */ +fixed_t P_FindHighestCeilingSurrounding(sector_t *sec) // 8001FD08 +{ + int i; + line_t *check; + sector_t *other; + fixed_t height = 0; + + for (i=0 ;i < sec->linecount ; i++) + { + check = sec->lines[i]; + other = getNextSector(check,sec); + if (!other) + continue; + if (other->ceilingheight > height) + height = other->ceilingheight; + } + return height; +} + +/*================================================================== */ +/* */ +/* RETURN NEXT SECTOR # THAT LINE TAG REFERS TO */ +/* */ +/*================================================================== */ +int P_FindSectorFromLineTag(int tag,int start) // 8001FDA4 +{ + int i; + + for (i=start+1;i<numsectors;i++) + if (sectors[i].tag == tag) + return i; + return -1; +} + +/*================================================================== */ +/* */ +/* RETURN NEXT LIGHT # THAT LINE TAG REFERS TO */ +/* Exclusive Doom 64 */ +/* */ +/*================================================================== */ +int P_FindLightFromLightTag(int tag,int start) // 8001FE08 +{ + int i; + + for (i=(start+256+1);i<numlights;i++) + if (lights[i].tag == tag) + return i; + return -1; +} + +/*================================================================== */ +/* */ +/* RETURN TRUE OR FALSE */ +/* Exclusive Doom 64 */ +/* */ +/*================================================================== */ +boolean P_ActivateLineByTag(int tag,mobj_t *thing) // 8001FE64 +{ + int i; + line_t *li; + + li = lines; + for (i=0;i<numlines;i++,li++) + { + if (li->tag == tag) + return P_UseSpecialLine(li, thing); + } + return false; +} + +#if 0 +/*================================================================== */ +/* */ +/* Find minimum light from an adjacent sector */ +/* */ +/*================================================================== */ +int P_FindMinSurroundingLight(sector_t *sector,int max)//L80026C10() +{ + int i; + int min; + line_t *line; + sector_t *check; + + min = max; + for (i=0 ; i < sector->linecount ; i++) + { + line = sector->lines[i]; + check = getNextSector(line,sector); + if (!check) + continue; + if (check->lightlevel < min) + min = check->lightlevel; + } + return min; +} +#endif // 0 + +/* +============================================================================== + + EVENTS + +Events are operations triggered by using, crossing, or shooting special lines, or by timed thinkers + +============================================================================== +*/ + +/* +=============================================================================== += += P_UpdateSpecials += += Animate planes, scroll walls, etc +=============================================================================== +*/ + +#define SCROLLLIMIT (FRACUNIT*127) + +void P_UpdateSpecials (void) // 8001FEC0 +{ + anim_t *anim; + line_t *line; + sector_t *sector; + fixed_t speed; + int i; + int neg; + + /* */ + /* ANIMATE FLATS AND TEXTURES GLOBALY */ + /* */ + for (anim = anims ; anim < lastanim ; anim++) + { + anim->delaycnt--; + if ((anim->delaycnt <= 0) && !(gametic & anim->tics)) + { + anim->current += anim->frame; + + if ((anim->current < anim->picstart) || (anim->picend < anim->current)) + { + neg = -anim->frame; + + if (anim->isreverse) + { + anim->frame = neg; + anim->current += neg; + + if (anim->delay == 0) + anim->current += neg + neg; + } + else + { + anim->current = anim->picstart; + } + + anim->delaycnt = anim->delay; + } + + textures[anim->basepic] = anim->current; + } + } + + /* */ + /* ANIMATE LINE SPECIALS */ + /* */ + for (i = 0; i < numlinespecials; i++) + { + line = linespeciallist[i]; + + if(line->flags & ML_SCROLLRIGHT) + { + sides[line->sidenum[0]].textureoffset += FRACUNIT; + sides[line->sidenum[0]].textureoffset &= SCROLLLIMIT; + } + else if(line->flags & ML_SCROLLLEFT) + { + sides[line->sidenum[0]].textureoffset -= FRACUNIT; + sides[line->sidenum[0]].textureoffset &= SCROLLLIMIT; + } + + if(line->flags & ML_SCROLLUP) + { + sides[line->sidenum[0]].rowoffset += FRACUNIT; + sides[line->sidenum[0]].rowoffset &= SCROLLLIMIT; + } + else if(line->flags & ML_SCROLLDOWN) + { + sides[line->sidenum[0]].rowoffset -= FRACUNIT; + sides[line->sidenum[0]].rowoffset &= SCROLLLIMIT; + } + } + + /* */ + /* ANIMATE SECTOR SPECIALS */ + /* */ + + scrollfrac = (scrollfrac + (FRACUNIT / 2)); + + for (i = 0; i < numsectorspecials; i++) + { + sector = sectorspeciallist[i]; + + if(sector->flags & MS_SCROLLFAST) + speed = 3*FRACUNIT; + else + speed = FRACUNIT; + + if(sector->flags & MS_SCROLLLEFT) + { + sector->xoffset += speed; + } + else if(sector->flags & MS_SCROLLRIGHT) + { + sector->xoffset -= speed; + } + + if(sector->flags & MS_SCROLLUP) + { + sector->yoffset -= speed; + } + else if(sector->flags & MS_SCROLLDOWN) + { + sector->yoffset += speed; + } + } + + /* */ + /* DO BUTTONS */ + /* */ + for (i = 0; i < MAXBUTTONS; i++) + { + if (buttonlist[i].btimer > 0) + { + buttonlist[i].btimer -= vblsinframe[0]; + + if (buttonlist[i].btimer <= 0) + { + switch (buttonlist[i].where) + { + case top: + buttonlist[i].side->toptexture = buttonlist[i].btexture; + break; + case middle: + buttonlist[i].side->midtexture = buttonlist[i].btexture; + break; + case bottom: + buttonlist[i].side->bottomtexture = buttonlist[i].btexture; + break; + } + S_StartSound((mobj_t *)buttonlist[i].soundorg, sfx_switch1); + D_memset(&buttonlist[i], 0, sizeof(button_t)); // ? Doom 64 elimina esta linea + } + } + } +} + +/* +============================================================================== + + UTILITIES + +============================================================================== +*/ + +/* */ +/* Will return a side_t* given the number of the current sector, */ +/* the line number, and the side (0/1) that you want. */ +/* */ +side_t *getSide(int currentSector,int line, int side) // 8002026C +{ + return &sides[ (sectors[currentSector].lines[line])->sidenum[side] ]; +} + +/* */ +/* Will return a sector_t* given the number of the current sector, */ +/* the line number and the side (0/1) that you want. */ +/* */ +sector_t *getSector(int currentSector,int line,int side) // 800202BC +{ + return sides[ (sectors[currentSector].lines[line])->sidenum[side] ].sector; +} + +/* */ +/* Given the sector number and the line number, will tell you whether */ +/* the line is two-sided or not. */ +/* */ +int twoSided(int sector,int line) // 80020314 +{ + return (sectors[sector].lines[line])->flags & ML_TWOSIDED; +} + +/* +============================================================================== + + EVENTS + +Events are operations triggered by using, crossing, or shooting special lines, or by timed thinkers + +============================================================================== +*/ + +void P_AddSectorSpecial(sector_t* sector) // 80020354 +{ + + if((sector->flags & MS_SYNCSPECIALS) && (sector->special)) + { + P_CombineLightSpecials(sector); + return; + } + + switch(sector->special) + { + case 0: + sector->lightlevel = 0; + break; + + case 1: + /* FLICKERING LIGHTS */ + P_SpawnLightFlash(sector); + break; + + case 2: + /* STROBE FAST */ + P_SpawnStrobeFlash(sector, FASTDARK); + break; + + case 3: + /* STROBE SLOW */ + P_SpawnStrobeFlash(sector, SLOWDARK); + break; + + case 8: + /* GLOWING LIGHT */ + P_SpawnGlowingLight(sector, PULSENORMAL); + break; + + case 9: + P_SpawnGlowingLight(sector, PULSESLOW); + break; + + case 11: + P_SpawnGlowingLight(sector, PULSERANDOM); + break; + + case 17: + P_SpawnFireFlicker(sector); + break; + + case 202: + P_SpawnStrobeAltFlash(sector, 3); + break; + + case 204: + P_SpawnStrobeFlash(sector, 7); + break; + + case 205: + P_SpawnSequenceLight(sector, true); + break; + + case 206: + P_SpawnStrobeFlash(sector, 90); + break; + + case 208: + P_SpawnStrobeAltFlash(sector, 6); + break; + + case 666: + break; + } +} + +/* +============================================================================== += += P_UseSpecialLine += += Called when a thing uses a special line += Only the front sides of lines are usable +=============================================================================== +*/ + +boolean P_UseSpecialLine (line_t *line, mobj_t *thing) // 800204BC +{ + player_t *player; + boolean ok; + int actionType; + + actionType = SPECIALMASK(line->special); + + if(actionType == 0) + return false; + + + player = thing->player; + + /* */ + /* Switches that other things can activate */ + /* */ + if (!player) + { + /* Missiles should NOT trigger specials... */ + if(thing->flags & MF_MISSILE) + return false; + + if(!(line->flags & ML_THINGTRIGGER)) + { + /* never open secret doors */ + if (line->flags & ML_SECRET) + return false; + + /* never allow a non-player mobj to use lines with these useflags */ + if (line->special & (MLU_BLUE|MLU_YELLOW|MLU_RED)) + return false; + + /* + actionType == 1 // MANUAL DOOR RAISE + actionType == 2 // OPEN DOOR IMPACT + actionType == 4 // RAISE DOOR + actionType == 10 // PLAT DOWN-WAIT-UP-STAY TRIGGER + actionType == 39 // TELEPORT TRIGGER + actionType == 125 // TELEPORT MONSTERONLY TRIGGER + */ + + if (!((line->special & MLU_USE && actionType == 1) || + (line->special & MLU_CROSS &&(actionType == 4 || actionType == 10 || actionType == 39 || actionType == 125)) || + (line->special & MLU_SHOOT && actionType == 2))) + return false; + } + } + else + { + if(line->special & MLU_BLUE) /* Blue Card Lock */ + { + if(!player->cards[it_bluecard] && !player->cards[it_blueskull]) + { + player->message = "You need a blue key."; + player->messagetic = MSGTICS; + S_StartSound(thing, sfx_oof); + + if (player == &players[0]) + tryopen[MapBlueKeyType] = true; + + return true; + } + } + + if(line->special & MLU_YELLOW) /* Yellow Card Lock */ + { + if(!player->cards[it_yellowcard] && !player->cards[it_yellowskull]) + { + player->message = "You need a yellow key."; + player->messagetic = MSGTICS; + S_StartSound(thing, sfx_oof); + + if (player == &players[0]) + tryopen[MapYellowKeyType] = true; + + return true; + } + } + + if(line->special & MLU_RED) /* Red Card Lock */ + { + if(!player->cards[it_redcard] && !player->cards[it_redskull]) + { + player->message = "You need a red key."; + player->messagetic = MSGTICS; + S_StartSound(thing, sfx_oof); // ?? line missing on Doom64 + + if (player == &players[0]) + tryopen[MapRedKeyType] = true; + + return true; + } + } + + /* + actionType == 90 // ARTIFACT SWITCH 1 + actionType == 91 // ARTIFACT SWITCH 2 + actionType == 92 // ARTIFACT SWITCH 3 + */ + + if ((actionType == 90 || actionType == 91 || actionType == 92) && + !((player->artifacts & 1) << ((actionType + 6) & 0x1f))) + { + player->message = "You lack the ability to activate it."; + player->messagetic = MSGTICS; + S_StartSound(thing, sfx_oof); + + return false; + } + } + + if(actionType >= 256) + return P_StartMacro(actionType, line, thing); + + ok = false; + + /* */ + /* do something */ + /* */ + switch(SPECIALMASK(line->special)) + { + case 1: /* Vertical Door */ + case 31: /* Manual Door Open */ + case 117: /* Blazing Door Raise */ + case 118: /* Blazing Door Open */ + EV_VerticalDoor(line, thing); + ok = true; + break; + case 2: /* Open Door */ + ok = EV_DoDoor(line, DoorOpen); + break; + case 3: /* Close Door */ + ok = EV_DoDoor(line, DoorClose); + break; + case 4: /* Raise Door */ + ok = EV_DoDoor(line, Normal); + break; + case 5: /* Raise Floor */ + ok = EV_DoFloor(line, raiseFloor, FLOORSPEED); + break; + case 6: /* Fast Ceiling Crush & Raise */ + ok = EV_DoCeiling(line, fastCrushAndRaise, CEILSPEED*2); + break; + case 8: /* Build Stairs */ + ok = EV_BuildStairs(line, build8); + break; + case 10: /* PlatDownWaitUp */ + ok = EV_DoPlat(line, downWaitUpStay, 0); + break; + case 16: /* Close Door 30 */ + ok = EV_DoDoor(line, Close30ThenOpen); + break; + case 17: /* Start Light Strobing */ + ok = EV_StartLightStrobing(line); + break; + case 19: /* Lower Floor */ + ok = EV_DoFloor(line, lowerFloor, FLOORSPEED); + break; + case 22: /* Raise floor to nearest height and change texture */ + ok = EV_DoPlat(line, raiseToNearestAndChange, 0); + break; + case 25: /* Ceiling Crush and Raise */ + ok = EV_DoCeiling(line, crushAndRaise, CEILSPEED); + break; + case 30: /* Raise floor to shortest texture height on either side of lines */ + ok = EV_DoFloor(line, raiseToTexture, FLOORSPEED); + break; + case 36: /* Lower Floor (TURBO) */ + ok = EV_DoFloor(line, turboLower, FLOORSPEED * 4); + break; + case 37: /* LowerAndChange */ + ok = EV_DoFloor(line, lowerAndChange, FLOORSPEED); + break; + case 38: /* Lower Floor To Lowest */ + ok = EV_DoFloor(line, lowerFloorToLowest, FLOORSPEED); + break; + case 39: /* TELEPORT! */ + EV_Teleport(line, thing); + ok = false; + break; + case 43: /* Lower Ceiling to Floor */ + ok = EV_DoCeiling(line, lowerToFloor, CEILSPEED); + break; + case 44: /* Ceiling Crush */ + ok = EV_DoCeiling(line, lowerAndCrush, CEILSPEED); + break; + case 52: /* EXIT! */ + P_ExitLevel();//G_ExitLevel + ok = true; + break; + case 53: /* Perpetual Platform Raise */ + ok = EV_DoPlat(line, perpetualRaise, 0); + break; + case 54: /* Platform Stop */ + ok = EV_StopPlat(line); + break; + case 56: /* Raise Floor Crush */ + ok = EV_DoFloor(line, raiseFloorCrush, FLOORSPEED); + break; + case 57: /* Ceiling Crush Stop */ + ok = EV_CeilingCrushStop(line); + break; + case 58: /* Raise Floor 24 */ + ok = EV_DoFloor(line, raiseFloor24, FLOORSPEED); + break; + case 59: /* Raise Floor 24 And Change */ + ok = EV_DoFloor(line, raiseFloor24AndChange, FLOORSPEED); + break; + case 66: /* Raise Floor 24 and change texture */ + ok = EV_DoPlat(line, raiseAndChange, 24); + break; + case 67: /* Raise Floor 32 and change texture */ + ok = EV_DoPlat(line, raiseAndChange, 32); + break; + case 90: /* Artifact Switch 1 */ + case 91: /* Artifact Switch 2 */ + case 92: /* Artifact Switch 3 */ + ok = P_ActivateLineByTag(line->tag + 1, thing); + break; + case 93: /* Modify mobj flags */ + ok = P_ModifyMobjFlags(line->tag, MF_NOINFIGHTING); + break; + case 94: /* Noise Alert */ + ok = P_AlertTaggedMobj(line->tag, thing); + break; + case 100: /* Build Stairs Turbo 16 */ + ok = EV_BuildStairs(line, turbo16); + break; + case 108: /* Blazing Door Raise (faster than TURBO!) */ + ok = EV_DoDoor(line, BlazeRaise); + break; + case 109: /* Blazing Door Open (faster than TURBO!) */ + ok = EV_DoDoor(line, BlazeOpen); + break; + case 110: /* Blazing Door Close (faster than TURBO!) */ + ok = EV_DoDoor(line, BlazeClose); + break; + case 119: /* Raise floor to nearest surr. floor */ + ok = EV_DoFloor(line, raiseFloorToNearest, FLOORSPEED); + break; + case 121: /* Blazing PlatDownWaitUpStay */ + ok = EV_DoPlat(line, blazeDWUS, 0); + break; + case 122: /* PlatDownWaitUpStay */ + ok = EV_DoPlat(line, upWaitDownStay, 0); + break; + case 123: /* Blazing PlatDownWaitUpStay */ + ok = EV_DoPlat(line, blazeDWUS, 0); + break; + case 124: /* Secret EXIT */ + P_SecretExitLevel(line->tag);//(G_SecretExitLevel) + ok = true; + break; + case 125: /* TELEPORT MonsterONLY */ + if (!thing->player) + { + EV_Teleport(line, thing); + ok = false; + } + break; + case 141: /* Silent Ceiling Crush & Raise (Demon Disposer)*/ + ok = EV_DoCeiling(line, silentCrushAndRaise, CEILSPEED*2); + break; + case 200: /* Set Lookat Camera */ + ok = P_SetAimCamera(line, true); + break; + case 201: /* Set Camera */ + ok = P_SetAimCamera(line, false); + break; + case 202: /* Invoke Dart */ + ok = EV_SpawnTrapMissile(line, thing, MT_PROJ_DART); + break; + case 203: /* Delay Thinker */ + P_SpawnDelayTimer(line->tag, NULL); + ok = true; + break; + case 204: /* Set global integer */ + macrointeger = line->tag; + ok = true; + break; + case 205: /* Modify sector color */ + P_ModifySectorColor(line, LIGHT_FLOOR, macrointeger); + ok = true; + break; + case 206: /* Modify sector color */ + ok = P_ModifySectorColor(line, LIGHT_CEILING, macrointeger); + break; + case 207: /* Modify sector color */ + ok = P_ModifySectorColor(line, LIGHT_THING, macrointeger); + break; + case 208: /* Modify sector color */ + ok = P_ModifySectorColor(line, LIGHT_UPRWALL, macrointeger); + break; + case 209: /* Modify sector color */ + ok = P_ModifySectorColor(line, LIGHT_LWRWALL, macrointeger); + break; + case 210: /* Modify sector ceiling height */ + ok = EV_DoCeiling(line, customCeiling, CEILSPEED); + break; + case 212: /* Modify sector floor height */ + ok = EV_DoFloor(line, customFloor, FLOORSPEED); + break; + case 214: /* Elevator Sector */ + ok = EV_SplitSector(line, true); + break; + case 218: /* Modify Line Flags */ + ok = P_ModifyLineFlags(line, macrointeger); + break; + case 219: /* Modify Line Texture */ + ok = P_ModifyLineTexture(line, macrointeger); + break; + case 220: /* Modify Sector Flags */ + ok = P_ModifySector(line, macrointeger, mods_flags); + break; + case 221: /* Modify Sector Specials */ + ok = P_ModifySector(line, macrointeger, mods_special); + break; + case 222: /* Modify Sector Lights */ + ok = P_ModifySector(line, macrointeger, mods_lights); + break; + case 223: /* Modify Sector Flats */ + ok = P_ModifySector(line, macrointeger, mods_flats); + break; + case 224: /* Spawn Thing */ + ok = EV_SpawnMobjTemplate(line->tag); + break; + case 225: /* Quake Effect */ + P_SpawnQuake(line->tag); + ok = true; + break; + case 226: /* Modify sector ceiling height */ + ok = EV_DoCeiling(line, customCeiling, CEILSPEED * 4); + break; + case 227: /* Modify sector ceiling height */ + ok = EV_DoCeiling(line, customCeiling, 4096 * FRACUNIT); + break; + case 228: /* Modify sector floor height */ + ok = EV_DoFloor(line, customFloor, FLOORSPEED * 4); + break; + case 229: /* Modify sector floor height */ + ok = EV_DoFloor(line, customFloor, 4096 * FRACUNIT); + break; + case 230: /* Modify Line Special */ + ok = P_ModifyLineData(line, macrointeger); + break; + case 231: /* Invoke Revenant Missile */ + ok = EV_SpawnTrapMissile(line, thing, MT_PROJ_TRACER); + break; + case 232: /* Fast Ceiling Crush & Raise */ + ok = EV_DoCeiling(line, crushAndRaiseOnce, CEILSPEED * 4); + break; + case 233: /* Freeze Player */ + thing->reactiontime = line->tag; + ok = true; + break; + case 234: /* Change light by light tag */ + ok = P_ChangeLightByTag(macrointeger, line->tag); + break; + case 235: /* Modify Light Data */ + ok = P_DoSectorLightChange(macrointeger, line->tag); + break; + case 236: /* Modify platform */ + ok = EV_DoPlat(line, customDownUp, 0); + break; + case 237: /* Modify platform */ + ok = EV_DoPlat(line, customDownUpFast,0); + break; + case 238: /* Modify platform */ + ok = EV_DoPlat(line,customUpDown,0); + break; + case 239: /* Modify platform */ + ok = EV_DoPlat(line,customUpDownFast,0); + break; + case 240: /* Execute random line trigger */ + ok = P_RandomLineTrigger(line, thing); + break; + case 241: /* Split Open Sector */ + ok = EV_SplitSector(line, false); + break; + case 242: /* Fade Out Thing */ + ok = EV_FadeOutMobj(line->tag); + break; + case 243: /* Move and Aim Camera */ + P_SetMovingCamera(line); + ok = false; + break; + case 244: /* Modify Sector Floor */ + ok = EV_DoFloor(line, customFloorToHeight, 4096 * FRACUNIT); + break; + case 245: /* Modify Sector Ceiling */ + ok = EV_DoCeiling(line, customCeilingToHeight, 4096 * FRACUNIT); + break; + case 246: /* Restart Macro at ID */ + P_RestartMacro(line, macrointeger); + ok = false; + break; + case 247: /* Modify Sector Floor */ + ok = EV_DoFloor(line, customFloorToHeight, FLOORSPEED); + break; + case 248: /* Suspend a macro script */ + ok = P_SuspendMacro(); + break; + case 249: /* Silent Teleport */ + ok = EV_SilentTeleport(line, thing); + break; + case 250: /* Toggle macros on */ + P_ToggleMacros(line->tag, true); + ok = true; + break; + case 251: /* Toggle macros off */ + P_ToggleMacros(line->tag, false); + ok = true; + break; + case 252: /* Modify Sector Ceiling */ + ok = EV_DoCeiling(line, customCeilingToHeight, CEILSPEED); + break; + case 253: /* Unlock Cheat Menu */ + if(!demoplayback) { + FeaturesUnlocked = true; + } + ok = true; + break; + case 254: /* D64 Map33 Logo */ + Skyfadeback = true; + break; + + default: + return false; + } + + if (ok) + { + if (line == &macrotempline) + return true; + + P_ChangeSwitchTexture(line, line->special & MLU_REPEAT); + + if (line->special & MLU_REPEAT) + return true; + + line->special = 0; + } + + return true; +} + +#if 0 + +/*============================================================ */ +/* */ +/* Special Stuff that can't be categorized */ +/* */ +/*============================================================ */ +int EV_DoDonut(line_t *line)//L8002796C() +{ + sector_t *s1; + sector_t *s2; + sector_t *s3; + int secnum; + int rtn; + int i; + floormove_t *floor; + + secnum = -1; + rtn = 0; + while ((secnum = P_FindSectorFromLineTag(line->tag,secnum)) >= 0) + { + s1 = &sectors[secnum]; + + /* ALREADY MOVING? IF SO, KEEP GOING... */ + if (s1->specialdata) + continue; + + rtn = 1; + s2 = getNextSector(s1->lines[0],s1); + for (i = 0;i < s2->linecount;i++) + { + if (//(!s2->lines[i]->flags & ML_TWOSIDED) || + (s2->lines[i]->backsector == s1)) + continue; + s3 = s2->lines[i]->backsector; + + /* */ + /* Spawn rising slime */ + /* */ + floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); + P_AddThinker (&floor->thinker); + s2->specialdata = floor; + floor->thinker.function = T_MoveFloor; + floor->type = donutRaise; + floor->crush = false; + floor->direction = 1; + floor->sector = s2; + floor->speed = FLOORSPEED / 2; + floor->texture = s3->floorpic; + floor->newspecial = 0; + floor->floordestheight = s3->floorheight; + + /* */ + /* Spawn lowering donut-hole */ + /* */ + floor = Z_Malloc (sizeof(*floor), PU_LEVSPEC, 0); + P_AddThinker (&floor->thinker); + s1->specialdata = floor; + floor->thinker.function = T_MoveFloor; + floor->type = lowerFloor; + floor->crush = false; + floor->direction = -1; + floor->sector = s1; + floor->speed = FLOORSPEED / 2; + floor->floordestheight = s3->floorheight; + break; + } + } + return rtn; +} + +#endif // 0 diff --git a/Doom 64/p_spec.h b/Doom 64/p_spec.h @@ -0,0 +1,653 @@ +/* P_spec.h */ + +#include "r_local.h" + +/* +=============================================================================== + + P_SPEC + +=============================================================================== +*/ + +/* */ +/* Aim Camera */ +/* */ +typedef struct +{ + thinker_t thinker; + mobj_t *viewmobj; +} aimcamera_t; + +/* */ +/* move Camera */ +/* */ +typedef struct +{ + thinker_t thinker; + fixed_t x; + fixed_t y; + fixed_t z; + fixed_t slopex; + fixed_t slopey; + fixed_t slopez; + int tic; + int current; +} movecamera_t; + +/* */ +/* Fade Mobj in/out */ +/* */ +typedef struct +{ + thinker_t thinker; + mobj_t *mobj; + int amount; + int destAlpha; + int flagReserve; +} fade_t; + +/* */ +/* Fade Bright */ +/* */ +typedef struct +{ + thinker_t thinker; + int factor; +} fadebright_t; + +/* */ +/* Mobj Exp */ +/* */ +typedef struct +{ + thinker_t thinker; + int delay; + int lifetime; + int delaydefault; + mobj_t *mobj; +} mobjexp_t; + + +/* */ +/* Quake */ +/* */ +typedef struct +{ + thinker_t thinker; + int tics; +} quake_t; + + +/* */ +/* Animating textures and planes */ +/* */ +typedef struct +{ + int basepic; + int picstart; + int picend; + int current; + int frame; + int tics; + int delay; + int delaycnt; + boolean isreverse; +} anim_t; + +/* */ +/* psx doom / doom64 exit delay */ +/* */ +typedef struct +{ + thinker_t thinker; + int tics; + void(*finishfunc)(void); +}delay_t; + +/* */ +/* source animation definition */ +/* */ +typedef struct +{ + int delay; + char startname[9]; + int frames; + int speed; + boolean isreverse; + boolean ispalcycle; +} animdef_t; + +#define MAXANIMS 15 //[d64] is 15 +extern anim_t anims[MAXANIMS], *lastanim; + +extern card_t MapBlueKeyType; +extern card_t MapRedKeyType; +extern card_t MapYellowKeyType; + +/* */ +/* Animating line specials */ +/* */ +extern line_t **linespeciallist; +extern int numlinespecials; + +/* */ +/* Animating sector specials */ +/* */ +extern sector_t **sectorspeciallist; +extern int numsectorspecials; + +/* Define values for map objects */ +#define MO_TELEPORTMAN 14 + + +/* at game start */ +//void P_InitPicAnims (void); + +/* at map load */ +void P_SpawnSpecials (void); + +/* every tic */ +void P_UpdateSpecials (void); + +/* when needed */ +boolean P_UseSpecialLine (line_t *line, mobj_t *thing); +//void P_ShootSpecialLine ( mobj_t *thing, line_t *line); +//void P_CrossSpecialLine (line_t *line,mobj_t *thing); + +void P_PlayerInSpecialSector (player_t *player, sector_t *sec); + +int twoSided(int sector,int line); +sector_t *getSector(int currentSector,int line,int side); +side_t *getSide(int currentSector,int line, int side); +fixed_t P_FindLowestFloorSurrounding(sector_t *sec); +fixed_t P_FindHighestFloorSurrounding(sector_t *sec); +fixed_t P_FindNextHighestFloor(sector_t *sec,int currentheight); +fixed_t P_FindLowestCeilingSurrounding(sector_t *sec); +fixed_t P_FindHighestCeilingSurrounding(sector_t *sec); +int P_FindSectorFromLineTag(int tag,int start); +int P_FindMinSurroundingLight(sector_t *sector,int max); +sector_t *getNextSector(line_t *line,sector_t *sec); + +int P_FindLightFromLightTag(int tag,int start); +boolean P_ActivateLineByTag(int tag,mobj_t *thing); + +/* */ +/* SPECIAL */ +/* */ +int EV_DoDonut(line_t *line); + +/* +=============================================================================== + + P_LIGHTS + +=============================================================================== +*/ + +typedef struct +{ + thinker_t thinker; + sector_t *sector; + int count; + int special; +} fireflicker_t; + +typedef struct +{ + thinker_t thinker; + sector_t *sector; + int count; + int special; +} lightflash_t; + +typedef struct +{ + thinker_t thinker; + sector_t *sector; + int count; + int maxlight; + int darktime; + int brighttime; + int special; +} strobe_t; + +typedef enum +{ + PULSENORMAL, + PULSESLOW, + PULSERANDOM +} glowtype_e; + +/*#define GLOWSPEED 2 +#define STROBEBRIGHT 1 +#define SUPERFAST 10 +#define FASTDARK 15 +#define SLOWDARK 30*/ + +typedef struct +{ + thinker_t thinker; + sector_t *sector; + glowtype_e type; + int count; + int direction; + int minlight; + int maxlight; + int special; +} glow_t; + +typedef struct +{ + thinker_t thinker; + sector_t *sector; + sector_t *headsector; + int count; + int start; + int index; + int special; +} sequenceglow_t; + +#define GLOWSPEED 2 +#define STROBEBRIGHT 3 +#define STROBEBRIGHT2 1 +#define TURBODARK 4 +#define FASTDARK 15 +#define SLOWDARK 30 + +void T_FireFlicker(fireflicker_t *flick); +void P_SpawnFireFlicker(sector_t *sector); +void T_LightFlash (lightflash_t *flash); +void P_SpawnLightFlash (sector_t *sector); +void T_StrobeFlash (strobe_t *flash); +void P_SpawnStrobeFlash (sector_t *sector, int fastOrSlow); +void P_SpawnStrobeAltFlash(sector_t *sector, int fastOrSlow); +int EV_StartLightStrobing(line_t *line); +void T_Glow(glow_t *g); +void P_SpawnGlowingLight(sector_t *sector, glowtype_e type); + + +typedef enum +{ + mods_flags, + mods_special, + mods_flats, + mods_lights, +} modifysector_t; + +#define LIGHT_FLOOR 0 +#define LIGHT_CEILING 1 +#define LIGHT_THING 2 +#define LIGHT_UPRWALL 3 +#define LIGHT_LWRWALL 4 + +int P_ModifySectorColor(line_t* line, int index, int type); + +#define SEQUENCELIGHTMAX 48 + +void T_SequenceGlow(sequenceglow_t *seq_g); +void P_SpawnSequenceLight(sector_t* sector, boolean first); + +typedef struct +{ + thinker_t thinker; + sector_t *sector; + int dest; + int src; + int r; + int g; + int b; + int inc; +} lightmorph_t; + +void P_UpdateLightThinker(int destlight, int srclight); +void T_LightMorph(lightmorph_t *lt); +int P_ChangeLightByTag(int tag1, int tag2); +int P_DoSectorLightChange(int tag1,int tag2); + +typedef struct +{ + thinker_t thinker; + sector_t *sector; + sector_t *combiner; + int special; +} combine_t; +void P_CombineLightSpecials(sector_t *sector); + +/* +=============================================================================== + + P_SWITCH + +=============================================================================== +*/ +typedef struct +{ + char name1[9]; + char name2[9]; +} switchlist_t; + +typedef enum +{ + top, + middle, + bottom +} bwhere_e; + +typedef struct +{ + side_t *side; //old line_t *line; + bwhere_e where; + int btexture; + int btimer; + mobj_t *soundorg; +} button_t; + +#define MAXSWITCHES 50 /* max # of wall switches in a level */ +#define MAXBUTTONS 16 /* 4 players, 4 buttons each at once, max. */ +#define BUTTONTIME 30 /* 1 second */ + +extern button_t buttonlist[MAXBUTTONS]; + +void P_ChangeSwitchTexture(line_t *line,int useAgain); +void P_InitSwitchList(void); + +/* +=============================================================================== + + P_PLATS + +=============================================================================== +*/ +typedef enum +{ + down = -1, + waiting = 0, + up = 1, + in_stasis = 2 +} plat_e; + +typedef enum +{ + perpetualRaise, + raiseAndChange, + raiseToNearestAndChange, + downWaitUpStay, + blazeDWUS, + upWaitDownStay, + blazeUWDS, + customDownUp, + customDownUpFast, + customUpDown, + customUpDownFast +} plattype_e; + +typedef struct +{ + thinker_t thinker; + sector_t *sector; + fixed_t speed; + fixed_t low; + fixed_t high; + int wait; + int count; + plat_e status; + plat_e oldstatus; + boolean crush; + int tag; + plattype_e type; +} plat_t; + +#define PLATWAIT 3 /* seconds */ +#define PLATSPEED (FRACUNIT*2) +#define MAXPLATS 30 + +extern plat_t *activeplats[MAXPLATS]; + +void T_PlatRaise(plat_t *plat); +int EV_DoPlat(line_t *line,plattype_e type,int amount); +void P_AddActivePlat(plat_t *plat); +void P_RemoveActivePlat(plat_t *plat); +int EV_StopPlat(line_t *line); +void P_ActivateInStasis(int tag); + +/* +=============================================================================== + + P_DOORS + +=============================================================================== +*/ +typedef enum +{ + Normal, + Close30ThenOpen, + DoorClose, + DoorOpen, + RaiseIn5Mins, + BlazeRaise, + BlazeOpen, + BlazeClose +} vldoor_e; + +typedef struct +{ + thinker_t thinker; + vldoor_e type; + sector_t *sector; + fixed_t topheight; + fixed_t bottomheight; // D64 new + boolean initceiling; // D64 new + fixed_t speed; + int direction; /* 1 = up, 0 = waiting at top, -1 = down */ + int topwait; /* tics to wait at the top */ + /* (keep in case a door going down is reset) */ + int topcountdown; /* when it reaches 0, start going down */ +} vldoor_t; + +#define VDOORSPEED FRACUNIT*2 +#define VDOORWAIT 120 + +void EV_VerticalDoor (line_t *line, mobj_t *thing); +boolean P_CheckKeyLock(line_t *line, mobj_t *thing); // Psx Doom New +int EV_DoDoor (line_t *line, vldoor_e type); +void T_VerticalDoor (vldoor_t *door); +void P_SpawnDoorCloseIn30 (sector_t *sec); +void P_SpawnDoorRaiseIn5Mins (sector_t *sec, int secnum); + +/* +=============================================================================== + + P_CEILNG + +=============================================================================== +*/ +typedef enum +{ + lowerToFloor, + raiseToHighest, + lowerAndCrush, + crushAndRaise, + fastCrushAndRaise, + silentCrushAndRaise, + customCeiling, + crushAndRaiseOnce, + customCeilingToHeight, +} ceiling_e; + +typedef struct +{ + thinker_t thinker; + ceiling_e type; + sector_t *sector; + fixed_t bottomheight, topheight; + fixed_t speed; + boolean crush; + int direction; /* 1 = up, 0 = waiting, -1 = down */ + int tag; /* ID */ + int olddirection; + boolean instant; +} ceiling_t; + +#define CEILSPEED FRACUNIT*2 +#define MAXCEILINGS 30 + +extern ceiling_t *activeceilings[MAXCEILINGS]; + +int EV_DoCeiling (line_t *line, ceiling_e type, fixed_t speed); +void T_MoveCeiling (ceiling_t *ceiling); +void P_AddActiveCeiling(ceiling_t *c); +void P_RemoveActiveCeiling(ceiling_t *c); +int EV_CeilingCrushStop(line_t *line); +void P_ActivateInStasisCeiling(line_t *line); + +/* +=============================================================================== + + P_FLOOR + +=============================================================================== +*/ +typedef enum +{ + lowerFloor, /* lower floor to highest surrounding floor */ + lowerFloorToLowest, /* lower floor to lowest surrounding floor */ + turboLower, /* lower floor to highest surrounding floor VERY FAST */ + raiseFloor, /* raise floor to lowest surrounding CEILING */ + raiseFloorToNearest, /* raise floor to next highest surrounding floor */ + raiseToTexture, /* raise floor to shortest height texture around it */ + lowerAndChange, /* lower floor to lowest surrounding floor and change */ + /* floorpic */ + raiseFloor24, + raiseFloor24AndChange, + raiseFloorCrush, + raiseFloorTurbo, // [d64]: unused + customFloor, + customFloorToHeight +} floor_e; + +typedef enum +{ + build8, // slowly build by 8 + turbo16 // quickly build by 16 +} stair_e; + +typedef struct +{ + thinker_t thinker; + floor_e type; + boolean crush; + sector_t *sector; + int direction; + int newspecial; + short texture; + fixed_t floordestheight; + fixed_t speed; + boolean instant; +} floormove_t; + +typedef struct +{ + thinker_t thinker; + sector_t *sector; + fixed_t ceildest; + fixed_t flrdest; + int ceildir; + int flrdir; +} splitmove_t; + +#define FLOORSPEED FRACUNIT*3 + +typedef enum +{ + ok, + crushed, + pastdest, + stop +} result_e; + +result_e T_MovePlane(sector_t *sector,fixed_t speed, + fixed_t dest,boolean crush,int floorOrCeiling,int direction); + +int EV_BuildStairs(line_t *line, stair_e type); +int EV_DoFloor(line_t *line,floor_e floortype,fixed_t speed); +int EV_SplitSector(line_t *line, boolean sync);// New D64 +void T_MoveFloor(floormove_t *floor); +void T_MoveSplitPlane(splitmove_t *split);// New D64 + +/* +=============================================================================== + + P_TELEPT + +=============================================================================== +*/ +int EV_Teleport( line_t *line,mobj_t *thing ); +int EV_SilentTeleport( line_t *line,mobj_t *thing ); + +/* +=============================================================================== + + P_MISC + +=============================================================================== +*/ + +void T_AimCamera(aimcamera_t *camera); // 8000DE60 +int P_SetAimCamera(line_t *line, boolean aim); // 8000DF20 +int EV_SpawnTrapMissile(line_t *line, mobj_t *target, mobjtype_t type); // 8000E02C +void P_SpawnDelayTimer(int tics, void(*action)()); // 8000E1CC +void T_CountdownTimer(delay_t *timer); // 8000E1CC +void P_ExitLevel(void); // 8000E220 +void P_SecretExitLevel(int map); // 8000E25C +int P_ModifyLineFlags(line_t *line, int tag); // 8000E6BC +int P_ModifyLineData(line_t *line, int tag); // 8000E780 +int P_ModifyLineTexture(line_t *line, int tag); // 8000E82C +int P_ModifySector(line_t *line, int tag, int type); // 8000E928 +void T_FadeThinker(fade_t *fade); // 8000EACC +int EV_SpawnMobjTemplate(int tag); // 8000EB8C +int EV_FadeOutMobj(int tag); // 8000ED08 +void T_Quake(quake_t *quake); // 8000EDE8 +void P_SpawnQuake(int tics); // 8000EE7C +int P_RandomLineTrigger(line_t *line,mobj_t *thing); // 8000EEE0 +void T_MoveCamera(movecamera_t *camera); // 8000F014 +void P_SetMovingCamera(line_t *line); // 8000f2f8 +void P_RefreshBrightness(void); // 8000f410 +void P_SetLightFactor(int lightfactor); // 8000F458 +void T_FadeInBrightness(fadebright_t *fb); // 8000f610 +int P_ModifyMobjFlags(int tid, int flags); // 8000F674 +int P_AlertTaggedMobj(int tid, mobj_t *activator); // 8000F6C4 +void T_MobjExplode(mobjexp_t *exp); // 8000F76C + +/* +=============================================================================== + + P_MACROS + +=============================================================================== +*/ + +typedef struct +{ + int tag; + mobj_t *activator; +} macroactivator_t; + +/* MACRO Variables */ +extern macro_t *activemacro; // 800A6094 +extern mobj_t *macroactivator; // 800A6098 +extern line_t macrotempline; // 800A60A0 +extern line_t *macroline; // 800A60EC +extern thinker_t *macrothinker; // 800A60F0 +extern int macrointeger; // 800A60F4 +extern macro_t *restartmacro; // 800A60F8 +extern int macrocounter; // 800A60FC +extern macroactivator_t macroqueue[4]; // 800A6100 +extern int macroidx1; // 800A6120 +extern int macroidx2; // 800A6124 + +int P_StartMacro(int macroindex, line_t *line, mobj_t *thing); // 80021088 +int P_SuspendMacro(void); // 80021148 +void P_ToggleMacros(int tag, boolean toggleon); // 80021214 +void P_RunMacros(void); // 8002126C +void P_RestartMacro(line_t *line, int id); // 80021384 diff --git a/Doom 64/p_switch.c b/Doom 64/p_switch.c @@ -0,0 +1,87 @@ +#include "doomdef.h" +#include "p_local.h" + +/*================================================================== */ +/* */ +/* CHANGE THE TEXTURE OF A WALL SWITCH TO ITS OPPOSITE */ +/* */ +/*================================================================== */ + +button_t buttonlist[MAXBUTTONS];//800975B0 + +void P_StartButton(line_t *line,bwhere_e w,int texture,int time); + +/*================================================================== */ +/* */ +/* Function that changes wall texture. */ +/* Tell it if switch is ok to use again (1=yes, it's a button). */ +/* */ +/*================================================================== */ +void P_ChangeSwitchTexture(line_t *line,int useAgain) // 80021460 +{ + int sound; + int swx; + + /* 52 EXIT! */ + /* 124 Secret EXIT */ + if(SPECIALMASK(line->special) == 52 || SPECIALMASK(line->special) == 124) + sound = sfx_switch2;//sfx_swtchx + else + sound = sfx_switch1;//sfx_swtchn + + if(SWITCHMASK(line->flags) == (ML_SWITCHX02 | ML_SWITCHX04)) /* Mid */ + { + S_StartSound((mobj_t *)&line->frontsector->soundorg, sound); + + swx = sides[line->sidenum[0]].midtexture; + sides[line->sidenum[0]].midtexture = ((swx - firstswx) ^ 1) + firstswx; + + if (useAgain) + P_StartButton(line, middle, swx, BUTTONTIME); + } + else if(SWITCHMASK(line->flags) == (ML_SWITCHX02)) /* Top */ + { + S_StartSound((mobj_t *)&line->frontsector->soundorg, sound); + + swx = sides[line->sidenum[0]].toptexture; + sides[line->sidenum[0]].toptexture = ((swx - firstswx) ^ 1) + firstswx; + + if (useAgain) + P_StartButton(line, top ,swx, BUTTONTIME); + } + else if(SWITCHMASK(line->flags) == (ML_SWITCHX04)) /* Bot */ + { + S_StartSound((mobj_t *)&line->frontsector->soundorg, sound); + + swx = sides[line->sidenum[0]].bottomtexture; + sides[line->sidenum[0]].bottomtexture = ((swx - firstswx) ^ 1) + firstswx; + + if (useAgain) + P_StartButton(line, bottom, swx, BUTTONTIME); + } +} + +/*================================================================== */ +/* */ +/* Start a button counting down till it turns off. */ +/* */ +/*================================================================== */ +void P_StartButton(line_t *line,bwhere_e w,int texture,int time) // 80021608 +{ + int i; + + for (i = 0;i < MAXBUTTONS;i++) + { + if (buttonlist[i].btimer <= 0) + { + buttonlist[i].side = &sides[line->sidenum[0]]; + buttonlist[i].where = w; + buttonlist[i].btexture = texture; + buttonlist[i].btimer = time; + buttonlist[i].soundorg = (mobj_t *)&line->frontsector->soundorg; + return; + } + } + + //I_Error("P_StartButton: no button slots left!"); +} diff --git a/Doom 64/p_telept.c b/Doom 64/p_telept.c @@ -0,0 +1,148 @@ +#include "doomdef.h" +#include "p_local.h" + +/* +============== += += P_Telefrag += += Kill all monsters around the given spot += +============== +*/ + +void P_Telefrag (mobj_t *thing, fixed_t x, fixed_t y) // 8000E29C +{ + int delta; + int size; + mobj_t *m; + + for (m=mobjhead.next ; m != &mobjhead ; m=m->next) + { + if (!(m->flags & MF_SHOOTABLE) ) + continue; /* not shootable */ + size = m->radius + thing->radius + 4*FRACUNIT; + delta = m->x - x; + if (delta < - size || delta > size) + continue; + delta = m->y - y; + if (delta < -size || delta > size) + continue; + P_DamageMobj (m, thing, thing, 10000); + m->flags &= ~(MF_SOLID|MF_SHOOTABLE); + } +} + +/*================================================================== */ +/* */ +/* TELEPORTATION */ +/* */ +/*================================================================== */ + +/* +============== += += EV_Teleport += +============== +*/ + +int EV_Teleport( line_t *line, mobj_t *thing ) // 8000E3A0 +{ + int tag; + boolean flag; + mobj_t *m,*fog; + unsigned an; + fixed_t oldx, oldy, oldz; + int side; + + side = !P_PointOnLineSide (thing->x, thing->y, line); + + if (thing->flags & MF_MISSILE) + return 0; /* don't teleport missiles */ + + if (side == 1) /* don't teleport if hit back of line, */ + return 0; /* so you can get out of teleporter */ + + tag = line->tag; + for (m=mobjhead.next ; m != &mobjhead ; m=m->next) + { + if (m->type != MT_DEST_TELEPORT ) + continue; /* not a teleportman */ + + if((tag != m->tid)) + continue; /* not matching the tid */ + + oldx = thing->x; + oldy = thing->y; + oldz = thing->z; + thing->flags |= MF_TELEPORT; + numthingspec = 0; + + if (thing->player) + P_Telefrag (thing, m->x, m->y); + + flag = P_TryMove (thing, m->x, m->y); + thing->flags &= ~MF_TELEPORT; + if (!flag) + return 0; /* move is blocked */ + thing->z = thing->floorz; + + /* spawn teleport fog at source and destination */ + fog = P_SpawnMobj (oldx, oldy, oldz + (thing->info->height>>1), MT_TELEPORTFOG); + S_StartSound (fog, sfx_telept); + an = m->angle >> ANGLETOFINESHIFT; + fog = P_SpawnMobj (m->x+20*finecosine[an], m->y+20*finesine[an] + , thing->z + (thing->info->height>>1), MT_TELEPORTFOG); + S_StartSound (fog, sfx_telept); + if (thing->player) + thing->reactiontime = 9; /* don't move for a bit */ //[psx] changed to 9 + thing->angle = m->angle; + thing->momx = thing->momy = thing->momz = 0; + return 1; + } + + return 0; +} + +/* +============== += += EV_SilentTeleport += += Doom 64 += +============== +*/ + +int EV_SilentTeleport( line_t *line, mobj_t *thing ) // 8000E5C0 +{ + int tag; + mobj_t *m; + unsigned an; + + tag = line->tag; + for (m=mobjhead.next ; m != &mobjhead ; m=m->next) + { + if (m->type != MT_DEST_TELEPORT ) + continue; /* not a teleportman */ + + if((tag != m->tid)) + continue; /* not matching the tid */ + + thing->flags |= MF_TELEPORT; + numthingspec = 0; + + if (thing->player) + P_Telefrag (thing, m->x, m->y); + + P_TryMove (thing, m->x, m->y); + thing->flags &= ~MF_TELEPORT; + thing->z = m->z; + thing->angle = m->angle; + thing->momx = thing->momy = thing->momz = 0; + return 1; + } + + return 0; +} diff --git a/Doom 64/p_tick.c b/Doom 64/p_tick.c @@ -0,0 +1,369 @@ +#include "doomdef.h" +#include "p_local.h" +#include "st_main.h" + +boolean gamepaused = true; // 800A6270 + +/* +=============================================================================== + + THINKERS + +All thinkers should be allocated by Z_Malloc so they can be operated on uniformly. The actual +structures will vary in size, but the first element must be thinker_t. + +Mobjs are similar to thinkers, but kept seperate for more optimal list +processing +=============================================================================== +*/ + +thinker_t thinkercap; /* both the head and tail of the thinker list */ //80096378 +mobj_t mobjhead; /* head and tail of mobj list */ //800A8C74, +//int activethinkers; /* debug count */ +//int activemobjs; /* debug count */ + +/* +=============== += += P_InitThinkers += +=============== +*/ +#if 0 +void P_InitThinkers (void) +{ + thinkercap.prev = thinkercap.next = &thinkercap; + mobjhead.next = mobjhead.prev = &mobjhead; +} +#endif // 0 + +/* +=============== += += P_AddThinker += += Adds a new thinker at the end of the list += +=============== +*/ + +void P_AddThinker (thinker_t *thinker) // 80021770 +{ + thinkercap.prev->next = thinker; + thinker->next = &thinkercap; + thinker->prev = thinkercap.prev; + thinkercap.prev = thinker; +} + +/* +=============== += += P_RemoveThinker += += Deallocation is lazy -- it will not actually be freed until its += thinking turn comes up += +=============== +*/ + +void P_RemoveThinker (thinker_t *thinker) // 8002179C +{ + thinker->function = (think_t)-1; + + if (thinker == macrothinker) { // [D64] New lines + macrothinker = NULL; + } +} + +/* +=============== += += P_RunThinkers += +=============== +*/ + +void P_RunThinkers (void) // 800217C8 +{ + thinker_t *currentthinker; + + //activethinkers = 0; + + currentthinker = thinkercap.next; + if (thinkercap.next != &thinkercap) + { + while (currentthinker != &thinkercap) + { + if (currentthinker->function == (think_t)-1) + { // time to remove it + currentthinker->next->prev = currentthinker->prev; + currentthinker->prev->next = currentthinker->next; + Z_Free (currentthinker); + } + else + { + if (currentthinker->function) + { + currentthinker->function (currentthinker); + } + //activethinkers++; + } + currentthinker = currentthinker->next; + } + } +} + +/* +=================== += += P_RunMobjLate += += Run stuff that doesn't happen every tick +=================== +*/ +#if 0 +void P_RunMobjLate (void) +{ + mobj_t *mo; + mobj_t *next; + + for (mo=mobjhead.next ; mo != &mobjhead ; mo=next) + { + next = mo->next; /* in case mo is removed this time */ + if (mo->latecall) + { + mo->latecall(mo); + } + } +} +#endif // 0 + +/* +============== += += P_CheckCheats += +============== +*/ + +void P_CheckCheats (void) // 8002187C +{ + unsigned int buttons; + int exit; + + buttons = ticbuttons[0] & 0xffff0000; + + if (!gamepaused) + { + if ((buttons & PAD_START) && !(oldticbuttons[0] & PAD_START)) + { + gamepaused = true; + + S_PauseSound(); + + lastticon = ticon; + + MenuCall = M_MenuTitleDrawer; + MenuItem = Menu_Game; + cursorpos = 0; + + if (FeaturesUnlocked == false) + itemlines = 3; + else + itemlines = 4; // Enable cheat menu + + MenuIdx = 0; + text_alpha = 255; + MenuAnimationTic = 0; + } + + return; + } + + exit = M_MenuTicker(); + + if (exit) + M_MenuClearCall(); + + if (exit == ga_warped) { + gameaction = ga_warped; + } + else if (exit == ga_exitdemo) { + gameaction = ga_exitdemo; + } + else if (exit == ga_restart) { + gameaction = ga_restart; + } + else if (exit == ga_exit) + { + gamepaused = false; + S_ResumeSound(); + ticon = lastticon; + ticsinframe = lastticon >> 2; + } +} + +void G_DoReborn (int playernum);//extern + +/* +================= += += P_Ticker += +================= +*/ + +//extern functions +void P_CheckSights (void); +void P_RunMobjBase (void); + +int P_Ticker (void)//80021A00 +{ + player_t *pl; + + gameaction = ga_nothing; + + // + // check for pause and cheats + // + P_CheckCheats(); + + if ((!gamepaused) && (gamevbls < gametic)) + { + P_RunThinkers(); + P_CheckSights(); + P_RunMobjBase(); + + P_UpdateSpecials(); + P_RunMacros(); + + ST_Ticker(); // update status bar + } + + //ST_DebugPrint("%d",Z_FreeMemory (mainzone)); + + // + // run player actions + // + pl = players; + + if (pl->playerstate == PST_REBORN) + gameaction = ga_died; + + AM_Control(pl); + P_PlayerThink(pl); + + return gameaction; // may have been set to ga_died, ga_completed, or ga_secretexit +} + +/* +============= += += P_Drawer += += draw current display +============= +*/ + +extern Mtx R_ProjectionMatrix; // 800A68B8 +extern Mtx R_ModelMatrix; // 8005b0C8 + +void P_Drawer (void) // 80021AC8 +{ + I_ClearFrame(); + + gMoveWd(GFX1++, G_MW_CLIP, G_MWO_CLIP_RNX, 1); + gMoveWd(GFX1++, G_MW_CLIP, G_MWO_CLIP_RNY, 1); + gMoveWd(GFX1++, G_MW_CLIP, G_MWO_CLIP_RPX, 65535); + gMoveWd(GFX1++, G_MW_CLIP, G_MWO_CLIP_RPY, 65535); + gMoveWd(GFX1++, G_MW_PERSPNORM, G_MWO_MATRIX_XX_XY_I, 68); + + // create a projection matrix + gSPMatrix(GFX1++, OS_K0_TO_PHYSICAL(&R_ProjectionMatrix), G_MTX_PROJECTION | G_MTX_LOAD | G_MTX_NOPUSH); + + // create a model matrix + gSPMatrix(GFX1++, OS_K0_TO_PHYSICAL(&R_ModelMatrix), G_MTX_MODELVIEW | G_MTX_LOAD | G_MTX_NOPUSH); + + if (players[0].automapflags & (AF_LINES|AF_SUBSEC)) + { + AM_Drawer(); + } + else + { + R_RenderPlayerView(); + //ST_DebugPrint("x %d || y %d", players[0].mo->x >> 16, players[0].mo->y >> 16); + + if (demoplayback == false) + ST_Drawer(); + } + + if (MenuCall) + { + M_DrawOverlay(0, 0, 320, 240, 96); + MenuCall(); + } + + I_DrawFrame(); +} + +extern void T_FadeInBrightness(fadebright_t *fb); +extern int start_time; // 80063390 +extern int end_time; // 80063394 + +void P_Start (void) // 80021C50 +{ + fadebright_t *fb; + + DrawerStatus = 1; + + if (gamemap == 33) /* Add by default God Mode in player */ + players[0].cheats |= CF_GODMODE; + else if (gamemap == 32) /* Remove by default God Mode in player */ + players[0].cheats &= ~CF_GODMODE; + + gamepaused = false; + validcount = 1; + + AM_Start(); + M_ClearRandom(); + + /* do a nice little fade in effect */ + fb = Z_Malloc(sizeof(*fb), PU_LEVSPEC, 0); + P_AddThinker(&fb->thinker); + fb->thinker.function = T_FadeInBrightness; + fb->factor = 0; + + /* autoactivate line specials */ + P_ActivateLineByTag(999, players[0].mo); + + start_time = ticon; + + MusicID = MapInfo[gamemap].MusicSeq-92; + S_StartMusic(MapInfo[gamemap].MusicSeq); +} + +void P_Stop (int exit) // 80021D58 +{ + /* [d64] stop plasma buzz */ + S_StopSound(0, sfx_electric); + + end_time = ticon; + gamepaused = false; + DrawerStatus = 0; + + G_PlayerFinishLevel(0); + + /* free all tags except the PU_STATIC tag */ + Z_FreeTags(mainzone, ~PU_STATIC); // (PU_LEVEL | PU_LEVSPEC | PU_CACHE) + + if ((gamemap != 33) || (exit == 8)) + S_StopMusic(); + + if ((demoplayback) && (exit == 8)) + I_WIPE_FadeOutScreen(); + else + I_WIPE_MeltScreen(); + + S_StopAll(); +} + diff --git a/Doom 64/p_user.c b/Doom 64/p_user.c @@ -0,0 +1,853 @@ +/* P_user.c */ + +#include "doomdef.h" +#include "p_local.h" +#include "st_main.h" + +#define MAXMOCKTIME 1800 +int deathmocktics; // 800A56A0 + +#define MK_TXT01 "HAHAHAHA!" +#define MK_TXT02 "YOU SHOULDN'T HAVE DONE THAT." +#define MK_TXT03 "TRY AN EASIER LEVEL..." +#define MK_TXT04 "WOW! LOOK AT THOSE DEMON FEET." +#define MK_TXT05 "I PLAY DOOM AND I CAN'T GET UP." +#define MK_TXT06 "OUCH! THAT HAD TO HURT." +#define MK_TXT07 "LOOK AT ME! I'M FLAT!" +#define MK_TXT08 "THANKS FOR PLAYING!" +#define MK_TXT09 "YOU LAZY @&$#!" +#define MK_TXT10 "HAVE YOU HAD ENOUGH?" +#define MK_TXT11 "THE DEMONS GAVE YOU THE BOOT!" +#define MK_TXT12 "THE LEAD DEMON VANQUISHED YOU!" + +char *mockstrings[] = // 8005A290 +{ + MK_TXT01, MK_TXT02, MK_TXT03, MK_TXT04, + MK_TXT05, MK_TXT06, MK_TXT07, MK_TXT08, + MK_TXT09, MK_TXT10, MK_TXT11, MK_TXT12, +}; + +fixed_t forwardmove[2] = {0xE000, 0x16000}; // 8005B060 +fixed_t sidemove[2] = {0xE000, 0x16000}; // 8005B068 + +#define SLOWTURNTICS 10 +fixed_t angleturn[] = // 8005B070 + {50,50,83,83,100,116,133,150,150,166, + 133,133,150,166,166,200,200,216,216,233}; // fastangleturn + +/*============================================================================= */ + +mobj_t *slidething; //80077D04, pmGp000008f4 +extern fixed_t slidex, slidey; //80077dbc || 80077dc0 +extern line_t *specialline; //80077dc8 + +void P_SlideMove (mobj_t *mo); + +#if 0 +void P_PlayerMove (mobj_t *mo)//L80029CB8() +{ + fixed_t momx, momy; + line_t *latchedline; + fixed_t latchedx, latchedy; + + //momx = vblsinframe[playernum] * (mo->momx>>2); + //momy = vblsinframe[playernum] * (mo->momy>>2); + + // Change on Final Doom + momx = mo->momx; + momy = mo->momy; + + slidething = mo; + + P_SlideMove (); + + latchedline = (line_t *)specialline; + latchedx = slidex; + latchedy = slidey; + + if ((latchedx == mo->x) && (latchedy == mo->y)) + goto stairstep; + + if (P_TryMove (mo, latchedx, latchedy)) + goto dospecial; + +stairstep: + + if (momx > MAXMOVE) + momx = MAXMOVE; + else if (momx < -MAXMOVE) + momx = -MAXMOVE; + + if (momy > MAXMOVE) + momy = MAXMOVE; + else if (momy < -MAXMOVE) + momy = -MAXMOVE; + + /* something fucked up in slidemove, so stairstep */ + + if (P_TryMove (mo, mo->x, mo->y + momy)) + { + mo->momx = 0; + mo->momy = momy; + goto dospecial; + } + + if (P_TryMove (mo, mo->x + momx, mo->y)) + { + mo->momx = momx; + mo->momy = 0; + goto dospecial; + } + + mo->momx = mo->momy = 0; + +dospecial: + if (latchedline) + P_CrossSpecialLine (latchedline, mo); +} +#endif // 0 + +/* +=================== += += P_PlayerXYMovement += +=================== +*/ + +#define STOPSPEED 0x1000 +#define FRICTION 0xd200 //Jag 0xd240 + +void P_PlayerXYMovement (mobj_t *mo) // 80021E20 +{ + /* */ + /* try to slide along a blocked move */ + /* */ + if (!P_TryMove(mo, mo->x + mo->momx, mo->y + mo->momy)) + P_SlideMove(mo); + + /* */ + /* slow down */ + /* */ + if (mo->z > mo->floorz) + return; /* no friction when airborne */ + + if (mo->flags & MF_CORPSE) + if (mo->floorz != mo->subsector->sector->floorheight) + return; /* don't stop halfway off a step */ + + if (mo->momx > -STOPSPEED && mo->momx < STOPSPEED && + mo->momy > -STOPSPEED && mo->momy < STOPSPEED) + { + mo->momx = 0; + mo->momy = 0; + } + else + { + mo->momx = (mo->momx>>8)*(FRICTION>>8); + mo->momy = (mo->momy>>8)*(FRICTION>>8); + } +} + + +/* +=============== += += P_PlayerZMovement += +=============== +*/ + +void P_PlayerZMovement (mobj_t *mo) // 80021f38 +{ + /* */ + /* check for smooth step up */ + /* */ + if (mo->z < mo->floorz) + { + mo->player->viewheight -= (mo->floorz - mo->z); + mo->player->deltaviewheight = (VIEWHEIGHT - mo->player->viewheight) >> 2; + } + + /* */ + /* adjust height */ + /* */ + mo->z += mo->momz; + + /* */ + /* clip movement */ + /* */ + if (mo->z <= mo->floorz) + { /* hit the floor */ + if (mo->momz < 0) + { + if (mo->momz < -(GRAVITY*2)) /* squat down */ + { + mo->player->deltaviewheight = mo->momz>>3; + S_StartSound (mo, sfx_oof); + } + mo->momz = 0; + } + mo->z = mo->floorz; + } + else + { + if (mo->momz == 0) + mo->momz = -(GRAVITY/2); + else + mo->momz -= (GRAVITY/4); + } + + if (mo->z + mo->height > mo->ceilingz) + { /* hit the ceiling */ + if (mo->momz > 0) + mo->momz = 0; + mo->z = mo->ceilingz - mo->height; + } +} + + +/* +================ += += P_PlayerMobjThink += +================ +*/ + +void P_PlayerMobjThink (mobj_t *mobj) // 80022060 +{ + state_t *st; + int state; + + /* */ + /* momentum movement */ + /* */ + if (mobj->momx || mobj->momy) + P_PlayerXYMovement (mobj); + + mobj->player->onground = (mobj->z <= mobj->floorz); + + if ( (mobj->z != mobj->floorz) || mobj->momz) + P_PlayerZMovement (mobj); + + /* */ + /* cycle through states, calling action functions at transitions */ + /* */ + if (mobj->tics == -1) + return; /* never cycle */ + + mobj->tics--; + + if (mobj->tics > 0) + return; /* not time to cycle yet */ + + state = mobj->state->nextstate; + st = &states[state]; + + mobj->state = st; + mobj->tics = st->tics; + mobj->sprite = st->sprite; + mobj->frame = st->frame; +} + +/*============================================================================= */ + + +/* +==================== += += P_BuildMove += +==================== +*/ + +#define MAXSENSIVITY 10 + +void P_BuildMove (player_t *player) // 80022154 +{ + int speed, sensitivity; + int buttons, oldbuttons; + mobj_t *mo; + buttons_t *cbutton; + + cbutton = BT_DATA[0]; + buttons = ticbuttons[0]; + oldbuttons = oldticbuttons[0]; + + player->forwardmove = player->sidemove = player->angleturn = 0; + + speed = (buttons & cbutton->BT_SPEED) > 0; + sensitivity = 0; + + /* */ + /* forward and backward movement */ + /* */ + if (cbutton->BT_FORWARD & buttons) + { + player->forwardmove = forwardmove[speed]; + } + else if (cbutton->BT_BACK & buttons) + { + player->forwardmove = -forwardmove[speed]; + } + else + { + /* Analyze analog stick movement (up / down) */ + sensitivity = (int)((buttons) << 24) >> 24; + + if(sensitivity >= MAXSENSIVITY || sensitivity <= -MAXSENSIVITY) + { + player->forwardmove += (forwardmove[1] * sensitivity) / 80; + } + } + + /* */ + /* use two stage accelerative turning on the joypad */ + /* */ + if (((buttons & cbutton->BT_LEFT) && (oldbuttons & cbutton->BT_LEFT))) + player->turnheld++; + else if (((buttons & cbutton->BT_RIGHT) && (oldbuttons & cbutton->BT_RIGHT))) + player->turnheld++; + else + player->turnheld = 0; + + if (player->turnheld >= SLOWTURNTICS) + player->turnheld = SLOWTURNTICS-1; + + /* */ + /* strafe movement */ + /* */ + if (buttons & cbutton->BT_STRAFELEFT) + { + player->sidemove -= sidemove[speed]; + } + if (buttons & cbutton->BT_STRAFERIGHT) + { + player->sidemove += sidemove[speed]; + } + + if (buttons & cbutton->BT_STRAFE) + { + if (buttons & cbutton->BT_LEFT) + { + player->sidemove = -sidemove[speed]; + } + else if (buttons & cbutton->BT_RIGHT) + { + player->sidemove = sidemove[speed]; + } + else + { + /* Analyze analog stick movement (left / right) */ + sensitivity = (int)(((buttons & 0xff00) >> 8) << 24) >> 24; + + if(sensitivity >= MAXSENSIVITY || sensitivity <= -MAXSENSIVITY) + { + player->sidemove += (sidemove[1] * sensitivity) / 80; + } + } + } + else + { + if (sensitivity == 0) + speed = 0; + + if (cbutton->BT_LEFT & buttons) + { + player->angleturn = angleturn[player->turnheld + (speed * SLOWTURNTICS)] << 17; + } + else if (cbutton->BT_RIGHT & buttons) + { + player->angleturn = -angleturn[player->turnheld + (speed * SLOWTURNTICS)] << 17; + } + else + { + /* Analyze analog stick movement (left / right) */ + sensitivity = (int)(((buttons & 0xff00) >> 8) << 24) >> 24; + sensitivity = -sensitivity; + + if(sensitivity >= MAXSENSIVITY || sensitivity <= -MAXSENSIVITY) + { + sensitivity = (((M_SENSITIVITY * 800) / 100) + 233) * sensitivity; + player->angleturn += (sensitivity / 80) << 17; + } + } + } + + /* */ + /* if slowed down to a stop, change to a standing frame */ + /* */ + mo = player->mo; + + if (!mo->momx && !mo->momy && player->forwardmove == 0 && player->sidemove == 0 ) + { /* if in a walking frame, stop moving */ + if (mo->state == &states[S_002] //S_PLAY_RUN1 + || mo->state == &states[S_003] //S_PLAY_RUN2 + || mo->state == &states[S_004] //S_PLAY_RUN3 + || mo->state == &states[S_005]) //S_PLAY_RUN4 + P_SetMobjState (mo, S_001); //S_PLAY + } +} + +/* +=============================================================================== + + movement + +=============================================================================== +*/ + +#define MAXBOB 0x100000 /* 16 pixels of bob */ + +/* +================== += += P_Thrust += += moves the given origin along a given angle += +================== +*/ + +void P_Thrust (player_t *player, angle_t angle, fixed_t move) // 800225BC +{ + angle >>= ANGLETOFINESHIFT; + player->mo->momx += FixedMul(vblsinframe[0] * move, finecosine[angle]); + player->mo->momy += FixedMul(vblsinframe[0] * move, finesine[angle]); +} + + + +/* +================== += += P_CalcHeight += += Calculate the walking / running height adjustment += +================== +*/ + +void P_CalcHeight (player_t *player) // 80022670 +{ + int angle; + fixed_t bob; + fixed_t val; + + /* */ + /* regular movement bobbing (needs to be calculated for gun swing even */ + /* if not on ground) */ + /* OPTIMIZE: tablify angle */ + /* */ + val = player->mo->momx; + player->bob = FixedMul(val, val); + val = player->mo->momy; + player->bob += FixedMul(val, val); + + player->bob >>= 2; + if (player->bob > MAXBOB) + { + player->bob = MAXBOB; + } + + if (!player->onground) + { + player->viewz = player->mo->z + VIEWHEIGHT; + if (player->viewz > player->mo->ceilingz-4*FRACUNIT) + player->viewz = player->mo->ceilingz-4*FRACUNIT; + return; + } + + angle = (FINEANGLES/40*ticon)&(FINEANGLES-1); + bob = FixedMul((player->bob / 2), finesine[angle]); + + //ST_DebugPrint("bob %x",FixedMul((player->bob / 2), finesine[angle])); + //ST_DebugPrint("bob2 %x",FixedMul2((player->bob / 2), finesine[angle])); + + //ST_DebugPrint("bobdiv %x",FixedDiv2(0x49003, 0x2)); + //ST_DebugPrint("bobdiv2 %x",FixedMul3(0x49003, 0x2)); + + /* */ + /* move viewheight */ + /* */ + if (player->playerstate == PST_LIVE) + { + player->viewheight += player->deltaviewheight; + if (player->viewheight > VIEWHEIGHT) + { + player->viewheight = VIEWHEIGHT; + player->deltaviewheight = 0; + } + if (player->viewheight < VIEWHEIGHT/2) + { + player->viewheight = VIEWHEIGHT/2; + if (player->deltaviewheight <= 0) + player->deltaviewheight = 1; + } + + if (player->deltaviewheight) + { + player->deltaviewheight += FRACUNIT/2; + if (!player->deltaviewheight) + player->deltaviewheight = 1; + } + } + player->viewz = player->mo->z + player->viewheight + bob; + if (player->viewz > player->mo->ceilingz-4*FRACUNIT) + player->viewz = player->mo->ceilingz-4*FRACUNIT; +} + +/* +================= += += P_MovePlayer += +================= +*/ + +void P_MovePlayer (player_t *player) // 8002282C +{ + player->mo->angle += vblsinframe[0] * player->angleturn; + + if(player->onground) + { + if (player->forwardmove) + P_Thrust (player, player->mo->angle, player->forwardmove); + if (player->sidemove) + P_Thrust (player, player->mo->angle-ANG90, player->sidemove); + } + + if ((player->forwardmove || player->sidemove) && player->mo->state == &states[S_001])//S_PLAY + P_SetMobjState (player->mo, S_002);//S_PLAY_RUN1 +} + + +/* +================= += += P_DeathThink += +================= +*/ + +void P_DeathThink (player_t *player) // 80022914 +{ + angle_t angle, delta; + + P_MovePsprites (player); + + /* fall to the ground */ + if (player->viewheight > 8*FRACUNIT) + player->viewheight -= FRACUNIT; + + player->onground = (player->mo->z <= player->mo->floorz); + + P_CalcHeight (player); + + if (player->attacker && player->attacker != player->mo) + { + angle = R_PointToAngle2 (player->mo->x, player->mo->y, player->attacker->x, player->attacker->y); + delta = angle - player->mo->angle; + if (delta < ANG5 || delta > (unsigned)-ANG5) + { /* looking at killer, so fade damage flash down */ + player->mo->angle = angle; + if (player->damagecount) + player->damagecount--; + } + else if (delta < ANG180) + player->mo->angle += ANG5; + else + player->mo->angle -= ANG5; + } + else if (player->damagecount) + player->damagecount--; + + /* mocking text */ + if ((ticon - deathmocktics) > MAXMOCKTIME) + { + player->messagetic = MSGTICS; + player->message = mockstrings[P_Random() % 12]; + deathmocktics = ticon; + } + + if (((ticbuttons[0] & (PAD_A|PAD_B|ALL_TRIG|ALL_CBUTTONS)) != 0) && + (player->viewheight <= 8*FRACUNIT)) + { + player->playerstate = PST_REBORN; + } + + if (player->bonuscount) + player->bonuscount -= 1; + + // [d64] - recoil pitch from weapons + if (player->recoilpitch) + player->recoilpitch = (((player->recoilpitch << 2) - player->recoilpitch) >> 2); + + if(player->bfgcount) + { + player->bfgcount -= 6; + + if(player->bfgcount < 0) + player->bfgcount = 0; + } +} + +/* +=============================================================================== += += P_PlayerInSpecialSector += += Called every tic frame that the player origin is in a special sector += +=============================================================================== +*/ + +void P_PlayerInSpecialSector (player_t *player, sector_t *sec) // 80022B1C +{ + fixed_t speed; + + if (player->mo->z != sec->floorheight) + return; /* not all the way down yet */ + + if(sec->flags & MS_SECRET) + { + player->secretcount++; + player->message = "You found a secret area!"; + player->messagetic = MSGTICS; + sec->flags &= ~MS_SECRET; + } + + if(sec->flags & MS_DAMAGEX5) /* NUKAGE DAMAGE */ + { + if(!player->powers[pw_ironfeet]) + { + if ((gamevbls < (int)gametic) && !(gametic & 31)) + P_DamageMobj(player->mo, NULL, NULL, 5); + } + } + + if(sec->flags & MS_DAMAGEX10) /* HELLSLIME DAMAGE */ + { + if(!player->powers[pw_ironfeet]) + { + if ((gamevbls < (int)gametic) && !(gametic & 31)) + P_DamageMobj(player->mo, NULL, NULL, 10); + } + } + + if(sec->flags & MS_DAMAGEX20) /* SUPER HELLSLIME DAMAGE */ + { + if(!player->powers[pw_ironfeet] || (P_Random() < 5)) + { + if ((gamevbls < (int)gametic) && !(gametic & 31)) + P_DamageMobj(player->mo, NULL, NULL, 20); + } + } + + if(sec->flags & MS_SCROLLFLOOR) + { + if(sec->flags & MS_SCROLLFAST) + speed = 0x3000; + else + speed = 0x1000; + + if(sec->flags & MS_SCROLLLEFT) + { + P_Thrust(player, ANG180, speed); + } + else if(sec->flags & MS_SCROLLRIGHT) + { + P_Thrust(player, 0, speed); + } + + if(sec->flags & MS_SCROLLUP) + { + P_Thrust(player, ANG90, speed); + } + else if(sec->flags & MS_SCROLLDOWN) + { + P_Thrust(player, ANG270, speed); + } + } +} + +/* +================= += += P_PlayerThink += +================= +*/ + +void P_PlayerThink (player_t *player) // 80022D60 +{ + int buttons, oldbuttons; + buttons_t *cbutton; + weapontype_t weapon; + sector_t *sec; + + buttons = ticbuttons[0]; + oldbuttons = oldticbuttons[0]; + cbutton = BT_DATA[0]; + + /* */ + /* check for weapon change */ + /* */ + if (player->playerstate == PST_LIVE) + { + weapon = player->pendingweapon; + if (weapon == wp_nochange) + weapon = player->readyweapon; + + if ((buttons & cbutton->BT_WEAPONBACKWARD) && !(oldbuttons & cbutton->BT_WEAPONBACKWARD)) + { + if (weapon == wp_chainsaw) + { + player->pendingweapon = wp_fist; + } + else + { + if((int)(weapon-1) >= wp_chainsaw) + { + while(--weapon >= wp_chainsaw && !player->weaponowned[weapon]); + } + + if((int)weapon >= wp_chainsaw) + player->pendingweapon = weapon; + } + } + else if ((buttons & cbutton->BT_WEAPONFORWARD) && !(oldbuttons & cbutton->BT_WEAPONFORWARD)) + { + if((int)(weapon+1) < NUMWEAPONS) + { + while(++weapon < NUMWEAPONS && !player->weaponowned[weapon]); + } + + if((int)weapon < NUMWEAPONS) + player->pendingweapon = weapon; + } + } + + if (!gamepaused) + { + P_PlayerMobjThink(player->mo); + P_BuildMove(player); + + sec = player->mo->subsector->sector; + if (sec->flags & (MS_SECRET | MS_DAMAGEX5 | MS_DAMAGEX10 | MS_DAMAGEX20 | MS_SCROLLFLOOR)) + P_PlayerInSpecialSector(player, sec); + + if (player->playerstate == PST_DEAD) + { + P_DeathThink(player); + return; + } + + /* */ + /* chain saw run forward */ + /* */ + if (player->mo->flags & MF_JUSTATTACKED) + { + player->angleturn = 0; + player->forwardmove = 0xc800; + player->sidemove = 0; + player->mo->flags &= ~MF_JUSTATTACKED; + } + + /* */ + /* move around */ + /* reactiontime is used to prevent movement for a bit after a teleport */ + /* */ + + if (player->mo->reactiontime) + player->mo->reactiontime--; + else + P_MovePlayer(player); + + P_CalcHeight(player); + + /* */ + /* check for use */ + /* */ + + if ((buttons & cbutton->BT_USE)) + { + if (player->usedown == false) + { + P_UseLines(player); + player->usedown = true; + } + } + else + { + player->usedown = false; + } + + if (buttons & cbutton->BT_ATTACK) + { + P_SetMobjState(player->mo, S_006);//S_PLAY_ATK1 + player->attackdown++; + } + else + { + player->attackdown = 0; + } + + /* */ + /* cycle psprites */ + /* */ + + P_MovePsprites(player); + + /* */ + /* counters */ + /* */ + + if (gamevbls < gametic) + { + if (player->powers[pw_strength] > 1) + player->powers[pw_strength]--; /* strength counts down to diminish fade */ + + if (player->powers[pw_invulnerability]) + player->powers[pw_invulnerability]--; + + if (player->powers[pw_invisibility]) + { + player->powers[pw_invisibility]--; + if (!player->powers[pw_invisibility]) + { + player->mo->flags &= ~MF_SHADOW; + } + else if ((player->powers[pw_invisibility] < 61) && !(player->powers[pw_invisibility] & 7)) + { + player->mo->flags ^= MF_SHADOW; + } + } + + if (player->powers[pw_infrared]) + player->powers[pw_infrared]--; + + if (player->powers[pw_ironfeet]) + player->powers[pw_ironfeet]--; + + if (player->damagecount) + player->damagecount--; + + if (player->bonuscount) + player->bonuscount--; + + // [d64] - recoil pitch from weapons + if (player->recoilpitch) + player->recoilpitch = (((player->recoilpitch << 2) - player->recoilpitch) >> 2); + + if(player->bfgcount) + { + player->bfgcount -= 6; + + if(player->bfgcount < 0) + player->bfgcount = 0; + } + } + } +} diff --git a/Doom 64/r_data.c b/Doom 64/r_data.c @@ -0,0 +1,92 @@ +/* R_data.c */ + +#include "doomdef.h" +#include "r_local.h" +#include "p_local.h" + +int firsttex; // 800A632C +int lasttex; // 800A6330 +int numtextures; // 800A6334 +int firstswx; // 800A6338 +int *textures; // 800A633C + +int firstsprite; // 800A6320 +int lastsprite; // 800A6324 +int numsprites; // 800A6328 + +int skytexture; // 800A5f14 + +void R_InitTextures(void); +void R_InitSprites(void); +/*============================================================================ */ + +#define PI_VAL 3.141592653589793 + +/* +================ += += R_InitData += += Locates all the lumps that will be used by all views += Must be called after W_Init +================= +*/ + +void R_InitData (void) // 80023180 +{ + int i; + int val; + + for(i = 0; i < (5*FINEANGLES/4); i++) + { + finesine[i] = (fixed_t) (sinf((((f64) val * (f64) PI_VAL) / 8192.0)) * 65536.0); + val += 2; + } + + R_InitTextures(); + R_InitSprites(); +} + +/* +================== += += R_InitTextures += += Initializes the texture list with the textures from the world map += +================== +*/ + +void R_InitTextures(void) // 8002327C +{ + int lump, swx, i; + + firsttex = W_GetNumForName("T_START") + 1; + lasttex = W_GetNumForName("T_END") - 1; + numtextures = (lasttex - firsttex) + 1; + + textures = Z_Malloc(numtextures * sizeof(int), PU_STATIC, NULL); + + for (i = 0; i < numtextures; i++) + { + textures[i] = (i + firsttex) << 4; + } + + swx = W_CheckNumForName("SWX", 0x7fffff00, 0); + firstswx = (swx - firsttex); +} + +/* +================ += += R_InitSprites += +================= +*/ + +void R_InitSprites(void) // 80023378 +{ + firstsprite = W_GetNumForName("S_START") + 1; + lastsprite = W_GetNumForName("S_END") - 1; + numsprites = (lastsprite - firstsprite) + 1; +} diff --git a/Doom 64/r_local.h b/Doom 64/r_local.h @@ -0,0 +1,378 @@ +/* R_local.h */ + +#ifndef __R_LOCAL__ +#define __R_LOCAL__ + +/* proper screen size would be 160*100, stretched to 224 is 2.2 scale */ +#define STRETCH (22*FRACUNIT/10) + +#define CENTERX (SCREENWIDTH/2) +#define CENTERY (SCREENHEIGHT/2) +#define CENTERXFRAC (SCREENWIDTH/2*FRACUNIT) +#define CENTERYFRAC (SCREENHEIGHT/2*FRACUNIT) +#define PROJECTION CENTERXFRAC + +#define ANGLETOSKYSHIFT 22 /* sky map is 256*128*4 maps */ + +#define BASEYCENTER 100 + +#define CENTERY (SCREENHEIGHT/2) +#define WINDOWHEIGHT (SCREENHEIGHT-SBARHEIGHT) + +#define MINZ 8 +#define MAXZ 256 + +#define FIELDOFVIEW 2048 /* fineangles in the SCREENWIDTH wide window */ + +/* */ +/* Seg flags */ +/* */ +#define SGF_VISIBLE_COLS 1 /* The seg has at least 1 visible (non fully occluded column) */ + + +/* */ +/* lighting constants */ +/* */ +#define LIGHTLEVELS 256 /* number of diminishing */ +#define INVERSECOLORMAP 255 + +/* +============================================================================== + + INTERNAL MAP TYPES + +============================================================================== +*/ + +/*================ used by play and refresh */ + +typedef struct +{ + fixed_t x, y, dx, dy; +} divline_t; + +typedef struct +{ + fixed_t x, y; + fixed_t vx, vy; + int validcount; +} vertex_t; + +struct line_s; +struct subsector_s; + +typedef struct +{ + fixed_t floorheight, ceilingheight; + VINT floorpic, ceilingpic; /* if ceilingpic == -1,draw sky */ + int colors[5]; // Doom 64 New + int lightlevel; + VINT special, tag; + + VINT xoffset, yoffset; // Doom 64 New + + VINT soundtraversed; /* 0 = untraversed, 1,2 = sndlines -1 */ + mobj_t *soundtarget; /* thing that made a sound (or null) */ + + VINT flags; // Psx Doom / Doom 64 New + VINT blockbox[4]; /* mapblock bounding box for height changes */ + degenmobj_t soundorg; /* for any sounds played by the sector */ + + int validcount; /* if == validcount, already checked */ + mobj_t *thinglist; /* list of mobjs in sector */ + void *specialdata; /* thinker_t for reversable actions */ + VINT linecount; + struct line_s **lines; /* [linecount] size */ +} sector_t; + +typedef struct +{ + fixed_t textureoffset; /* add this to the calculated texture col */ + fixed_t rowoffset; /* add this to the calculated texture top */ + VINT toptexture, bottomtexture, midtexture; + sector_t *sector; +} side_t; + +typedef enum {ST_HORIZONTAL, ST_VERTICAL, ST_POSITIVE, ST_NEGATIVE} slopetype_t; + +typedef struct line_s +{ + vertex_t *v1, *v2; + fixed_t dx,dy; /* v2 - v1 for side checking */ + VINT flags; + VINT special, tag; + VINT sidenum[2]; /* sidenum[1] will be -1 if one sided */ + fixed_t bbox[4]; + slopetype_t slopetype; /* to aid move clipping */ + sector_t *frontsector, *backsector; + int validcount; /* if == validcount, already checked */ + void *specialdata; /* thinker_t for reversable actions */ + int fineangle; /* to get sine / cosine for sliding */ +} line_t; + +typedef struct vissprite_s +{ + int zdistance; //* + mobj_t *thing; //*4 + int lump; //*8 + boolean flip; //*12 + sector_t *sector; //*16 + struct vissprite_s *next;//*20 +} vissprite_t; + +typedef struct subsector_s +{ + sector_t *sector; //* + vissprite_t *vissprite; //*4 + short numlines; //*8 + short firstline; //*10 + short numverts; //*12 + short leaf; //*14 + short drawindex; //*16 + short padding; //*18 +} subsector_t; + +typedef struct seg_s +{ + vertex_t *v1, *v2; + fixed_t offset; + angle_t angle; /* this is not used (keep for padding) */ + side_t *sidedef; + line_t *linedef; + sector_t *frontsector; + sector_t *backsector; /* NULL for one sided lines */ + short flags; + short length; +} seg_t; + +typedef struct +{ + //fixed_t x,y,dx,dy; //old + divline_t line; /* partition line */ + fixed_t bbox[2][4]; /* bounding box for each child */ + int children[2]; /* if NF_SUBSECTOR its a subsector */ +} node_t; + +typedef struct { + vertex_t *vertex; + seg_t *seg;//*(A24 + 4) +} leaf_t; + +// +// Light Data Doom64 +// +typedef struct { + int rgba; + int tag; +} light_t; + +// +// Macros Doom64 +// +typedef struct +{ + int id, tag, special; +} macro_t; + +/* +============================================================================== + + OTHER TYPES + +============================================================================== +*/ + +/* Sprites are patches with a special naming convention so they can be */ +/* recognized by R_InitSprites. The sprite and frame specified by a */ +/* thing_t is range checked at run time. */ +/* a sprite is a patch_t that is assumed to represent a three dimensional */ +/* object and may have multiple rotations pre drawn. Horizontal flipping */ +/* is used to save space. Some sprites will only have one picture used */ +/* for all views. */ + +#ifdef MARS + +int spritelump[NUMSPRITES]; /* no rotations, so just add frame num... */ + +#else + +typedef struct +{ + boolean rotate; /* if false use 0 for any position */ + int lump[8]; /* lump to use for view angles 0-7 */ + byte flip[8]; /* flip (1 = flip) to use for view angles 0-7 */ +} spriteframe_t; + +typedef struct +{ + spriteframe_t *spriteframes; + int numframes; +} spritedef_t; + +extern spritedef_t sprites[NUMSPRITES]; + +#endif + +/* +=============================================================================== + + MAP DATA + +=============================================================================== +*/ + +extern int numvertexes; +extern vertex_t *vertexes; + +extern int numsegs; +extern seg_t *segs; + +extern int numsectors; +extern sector_t *sectors; + +extern int numsubsectors; +extern subsector_t *subsectors; + +extern int numnodes; +extern node_t *nodes; + +extern int numlines; +extern line_t *lines; + +extern int numsides; +extern side_t *sides; + +extern int numleafs; +extern leaf_t *leafs; + +extern light_t *lights; +extern int numlights; + +extern macro_t **macros; +extern int nummacros; + +//extern int skyflatnum; + +/*============================================================================= */ + +/*------*/ +/*R_main*/ +/*------*/ +extern mobj_t *cameratarget; // 800A5D70 +extern angle_t camviewpitch; // 800A811C +extern fixed_t scrollfrac; // 800A812C +extern sector_t *frontsector; // 800A6340 +extern int globallump; // 800A68f8 +extern int globalcm; // 800A68fC +extern int infraredFactor; // 800A810C +extern int FlashEnvColor; // 800A8110 +extern fixed_t quakeviewx; // 800A8118 +extern fixed_t quakeviewy; // 800A8114 + +/*------*/ +/*R_data*/ +/*------*/ +void R_InitData (void); + +/*--------*/ +/*r_phase1*/ +/*--------*/ +void R_BSP (void); +void R_RenderBSPNode (int bspnum); + +/*--------*/ +/*r_phase2*/ +/*--------*/ +typedef void(*skyfunc_t)(); +extern fixed_t FogNear; // 800A8120 +extern int FogColor; // 800A8124 +skyfunc_t R_RenderSKY; // 800A8130 +extern int Skyfadeback; // 800A814C + +void R_SetupSky(void); + +/*--------*/ +/*r_phase3*/ +/*--------*/ +void R_RenderAll(void); +void R_RenderPSprites(void); + + +/* to get a global angle from cartesian coordinates, the coordinates are */ +/* flipped until they are in the first octant of the coordinate system, then */ +/* the y (<=x) is scaled and divided by x to get a tangent (slope) value */ +/* which is looked up in the tantoangle[] table. The +1 size is to handle */ +/* the case when x==y without additional checking. */ +#define SLOPERANGE 2048 +#define SLOPEBITS 11 +#define DBITS (FRACBITS-SLOPEBITS) + +extern angle_t tantoangle[SLOPERANGE+1]; + + +#define VIEW_3D_H 200 +//extern fixed_t yslope[VIEW_3D_H]; + +#define HEIGHTBITS 6 +#define SCALEBITS 9 + +#define FIXEDTOSCALE (FRACBITS-SCALEBITS) +#define FIXEDTOHEIGHT (FRACBITS-HEIGHTBITS) + + +#define HALF_SCREEN_W (SCREENWIDTH/2) + +extern fixed_t viewx, viewy, viewz; //80077D0C, 80077D10, 80077D18 +extern angle_t viewangle; //800780B8 +extern fixed_t viewcos, viewsin; //80077EC8, 80077EE0 + +extern player_t *viewplayer; //80077D60 + +extern fixed_t finetangent[FINEANGLES/2]; + +extern int validcount; //800779F4 +//extern int framecount; + + + + +/* */ +/* R_data.c */ +/* */ +extern boolean rendersky; // 800A68A8 +extern byte solidcols[320]; // 800A6348 + +#define MAXSUBSECTORS 256 /* Maximum number of subsectors to scan */ +extern subsector_t *solidsubsectors[MAXSUBSECTORS]; // 800A6488 /* List of valid ranges to scan through */ +extern subsector_t **endsubsector; // 800A6888 /* Pointer to the first free entry */ +extern int numdrawsubsectors; // 800A68AC + +#define MAXVISSPRITES 256 +extern vissprite_t vissprites[MAXVISSPRITES]; // 800A6908 +extern vissprite_t *visspritehead; // 800A8108 +extern int numdrawvissprites; // 800A68B0 + + +//extern short skypalette; +//extern psxobj_t *skytexturep; + +extern int firsttex, lasttex, numtextures,firstswx; +extern int *textures; +extern int skytexture; + +//extern int *flattranslation; /* for global animation */ +//extern int *texturetranslation; /* for global animation */ + +//extern int firstflat, lastflat, numflats; +//extern psxobj_t *texflats; + +extern int firstsprite, lastsprite, numsprites; +//extern int *texsprites; + +//#define MAX_PALETTES 26 //Final Doom 20 to 26 +//extern short palette[MAX_PALETTES]; +//extern short palettebase; +//extern light_t *lights; + +#endif /* __R_LOCAL__ */ + diff --git a/Doom 64/r_main.c b/Doom 64/r_main.c @@ -0,0 +1,406 @@ +/* r_main.c */ + +#include "doomdef.h" +#include "r_local.h" + +/*===================================== */ + +/* */ +/* subsectors */ +/* */ +//subsector_t *vissubsectors[MAXVISSSEC], **lastvissubsector; + +/* */ +/* walls */ +/* */ +//viswall_t viswalls[MAXWALLCMDS], *lastwallcmd; + +/* */ +/* planes */ +/* */ +//visplane_t visplanes[MAXVISPLANES], *lastvisplane; + +/* */ +/* sprites */ +/* */ +//vissprite_t vissprites[MAXVISSPRITES], *lastsprite_p, *vissprite_p; + +/* */ +/* openings / misc refresh memory */ +/* */ +//unsigned short openings[MAXOPENINGS], *lastopening; + + +/*===================================== */ + +fixed_t viewx, viewy, viewz; // 800A6890, 800A6894, 800A6898 +angle_t viewangle; // 800A689C +fixed_t viewcos, viewsin; // 800A68A0, +player_t *viewplayer; // 800A688C, 800a68a4 + +int validcount; /* increment every time a check is made */ // 800A6900 +//int framecount; /* incremented every frame */ + +/* */ +/* sky mapping */ +/* */ +boolean rendersky; // 800A68A8 + +byte solidcols[320]; // 800A6348 +subsector_t *solidsubsectors[MAXSUBSECTORS]; // 800A6488 /* List of valid ranges to scan through */ +subsector_t **endsubsector; // 800A6888 /* Pointer to the first free entry */ +int numdrawsubsectors; // 800A68AC + +vissprite_t vissprites[MAXVISSPRITES]; // 800A6908 +vissprite_t *visspritehead; // 800A8108 +int numdrawvissprites; // 800A68B0 + +int globallump; // 800A68f8 +int globalcm; // 800A68FC + +Mtx R_ProjectionMatrix; // 800A68B8 +/*Mtx R_ProjectionMatrix = // 800A68B8 +{ + 0x00010000, 0x00000000, + 0x00000001, 0x00000000, + 0x00000000, 0xfffeffff, + 0x00000000, 0xffef0000, + 0x00000000, 0x00000000, + 0x00005555, 0x00000000, + 0x00000000, 0xfeed0000, + 0x00000000, 0xf7610000 +};*/ + +Mtx R_ModelMatrix = // 8005b0C8 +{ + 0x00010000, 0x00000000, + 0x00000001, 0x00000000, + 0x00000000, 0x00010000, + 0x00000000, 0x00000001, + 0x00000000, 0x00000000, + 0x00000000, 0x00000000, + 0x00000000, 0x00000000, + 0x00000000, 0x00000000 +}; + +/* */ +/* precalculated math */ +/* */ +fixed_t* finecosine = &finesine[FINEANGLES / 4]; // 8005B890 + +int infraredFactor; // 800A810C +int FlashEnvColor; // 800A8110 +fixed_t quakeviewx; // 800A8118 +fixed_t quakeviewy; // 800A8114 +mobj_t *cameratarget; // 800A5D70 +angle_t camviewpitch; // 800A811C + +fixed_t scrollfrac; // 800A812C +sector_t *frontsector; // 800A6340 + +/*============================================================================= */ + +/* +============== += += R_Init += +============== +*/ + +void R_Init(void) // 800233E0 +{ + R_InitData(); + guFrustum(&R_ProjectionMatrix, -8.0f, 8.0f, -6.0f, 6.0f, 8.0f, 3808.0f, 1.0f); + + /*PRINTF_D2(WHITE, 0, 10, "R_ProjectionMatrix[0][0] %x", R_ProjectionMatrix.m[0][0]); + PRINTF_D2(WHITE, 0, 11, "R_ProjectionMatrix[0][1] %x", R_ProjectionMatrix.m[0][1]); + PRINTF_D2(WHITE, 0, 12, "R_ProjectionMatrix[0][2] %x", R_ProjectionMatrix.m[0][2]); + PRINTF_D2(WHITE, 0, 13, "R_ProjectionMatrix[0][3] %x", R_ProjectionMatrix.m[0][3]); + PRINTF_D2(WHITE, 0, 14, "R_ProjectionMatrix[1][0] %x", R_ProjectionMatrix.m[1][0]); + PRINTF_D2(WHITE, 0, 15, "R_ProjectionMatrix[1][1] %x", R_ProjectionMatrix.m[1][1]); + PRINTF_D2(WHITE, 0, 16, "R_ProjectionMatrix[1][2] %x", R_ProjectionMatrix.m[1][2]); + PRINTF_D2(WHITE, 0, 17, "R_ProjectionMatrix[1][3] %x", R_ProjectionMatrix.m[1][3]); + PRINTF_D2(WHITE, 0, 18, "R_ProjectionMatrix[2][0] %x", R_ProjectionMatrix.m[2][0]); + PRINTF_D2(WHITE, 0, 19, "R_ProjectionMatrix[2][1] %x", R_ProjectionMatrix.m[2][1]); + PRINTF_D2(WHITE, 0, 20, "R_ProjectionMatrix[2][2] %x", R_ProjectionMatrix.m[2][2]); + PRINTF_D2(WHITE, 0, 21, "R_ProjectionMatrix[2][3] %x", R_ProjectionMatrix.m[2][3]); + PRINTF_D2(WHITE, 0, 22, "R_ProjectionMatrix[3][0] %x", R_ProjectionMatrix.m[3][0]); + PRINTF_D2(WHITE, 0, 23, "R_ProjectionMatrix[3][1] %x", R_ProjectionMatrix.m[3][1]); + PRINTF_D2(WHITE, 0, 24, "R_ProjectionMatrix[3][2] %x", R_ProjectionMatrix.m[3][2]); + PRINTF_D2(WHITE, 0, 25, "R_ProjectionMatrix[3][3] %x", R_ProjectionMatrix.m[3][3]); + while(1){}*/ +} + + +/* +============== += += R_RenderView += +============== +*/ + +void R_RenderPlayerView(void) // 80023448 +{ + fixed_t pitch; + fixed_t Fnear, FnearA, FnearB; + fixed_t sin, cos; + + viewplayer = &players[0]; + + if (cameratarget == players[0].mo) + { + viewz = players[0].viewz; + pitch = players[0].recoilpitch >> ANGLETOFINESHIFT; + } + else + { + viewz = cameratarget->z; + pitch = camviewpitch >> ANGLETOFINESHIFT; + } + + viewx = cameratarget->x; + viewy = cameratarget->y; + viewz += quakeviewy; + + viewangle = cameratarget->angle + quakeviewx; + viewcos = finecosine[viewangle >> ANGLETOFINESHIFT]; + viewsin = finesine[viewangle >> ANGLETOFINESHIFT]; + + // Phase 1 + R_BSP(); + + gDPSetEnvColorD64(GFX1++, FlashEnvColor); + + // Phase 2 + if (rendersky) + { + R_RenderSKY(); + gDPPipeSync(GFX1++); + } + + gDPSetCycleType(GFX1++, G_CYC_2CYCLE); + gDPSetTextureLOD(GFX1++, G_TL_TILE); + gDPSetTextureLUT(GFX1++, G_TT_RGBA16); + gDPSetTexturePersp(GFX1++, G_TP_PERSP); + gDPSetAlphaCompare(GFX1++, G_AC_THRESHOLD); + gDPSetBlendColor(GFX1++, 0, 0, 0, 0); + + gDPSetCombineMode(GFX1++, G_CC_D64COMB07, G_CC_D64COMB08); + + gDPSetRenderMode(GFX1++, G_RM_FOG_SHADE_A, G_RM_TEX_EDGE2); + + FnearA = (1000 - FogNear); + FnearB = ((0-FogNear) << 8) + 128000; + Fnear = (((128000 / FnearA) << 16) | ((FnearB / FnearA) & 0xffff)); + gMoveWd(GFX1++, G_MW_FOG, G_MWO_FOG, Fnear); + + // Apply Fog Color + gDPSetFogColorD64(GFX1++, FogColor); + + sin = finesine[pitch]; + cos = finecosine[pitch]; + + gSPMatrix(GFX1++, OS_K0_TO_PHYSICAL(MTX1), G_MTX_MODELVIEW| G_MTX_LOAD | G_MTX_NOPUSH); + MTX1->m[0][0] = 0x10000; + MTX1->m[0][1] = 0; + MTX1->m[0][2] = ((cos & 0xffff0000) >> 16); + MTX1->m[0][3] = ((-sin) & 0xffff0000); + MTX1->m[1][0] = ((sin & 0xffff0000) >> 16); + MTX1->m[1][1] = (cos & 0xffff0000); + MTX1->m[1][2] = 0; + MTX1->m[1][3] = 1; + MTX1->m[2][0] = 0; + MTX1->m[2][1] = 0; + MTX1->m[2][2] = (cos & 0xffff); + MTX1->m[2][3] = (((-sin) << 16) & 0xffff0000); + MTX1->m[3][0] = (sin & 0xffff); + MTX1->m[3][1] = ((cos << 16) & 0xffff0000); + MTX1->m[3][2] = 0; + MTX1->m[3][3] = 0; + MTX1++; + + sin = viewsin; + cos = viewcos; + + gSPMatrix(GFX1++, OS_K0_TO_PHYSICAL(MTX1), G_MTX_MODELVIEW| G_MTX_MUL | G_MTX_NOPUSH); + MTX1->m[0][0] = (sin & 0xffff0000); + MTX1->m[0][1] = ((-cos) & 0xffff0000); + MTX1->m[0][2] = 1; + MTX1->m[0][3] = 0; + MTX1->m[1][0] = (cos & 0xffff0000); + MTX1->m[1][1] = (sin & 0xffff0000); + MTX1->m[1][2] = 0; + MTX1->m[1][3] = 1; + MTX1->m[2][0] = ((sin << 16) & 0xffff0000); + MTX1->m[2][1] = (((-cos) << 16) & 0xffff0000); + MTX1->m[2][2] = 0; + MTX1->m[2][3] = 0; + MTX1->m[3][0] = ((cos << 16) & 0xffff0000); + MTX1->m[3][1] = ((sin << 16) & 0xffff0000); + MTX1->m[3][2] = 0; + MTX1->m[3][3] = 0; + MTX1++; + + gSPMatrix(GFX1++, OS_K0_TO_PHYSICAL(MTX1), G_MTX_MODELVIEW| G_MTX_MUL | G_MTX_NOPUSH); + MTX1->m[0][0] = 0x10000; + MTX1->m[0][1] = 0; + MTX1->m[0][2] = 1; + MTX1->m[0][3] = 0; + MTX1->m[1][0] = 0; + MTX1->m[1][1] = 0x10000; + MTX1->m[1][2] = ((-viewx) & 0xffff0000) | (((-viewz) >> 16) & 0xffff); + MTX1->m[1][3] = (viewy & 0xffff0000) | 1; + MTX1->m[2][0] = 0; + MTX1->m[2][1] = 0; + MTX1->m[2][2] = 0; + MTX1->m[2][3] = 0; + MTX1->m[3][0] = 0; + MTX1->m[3][1] = 0; + MTX1->m[3][2] = (((-viewx) << 16) & 0xffff0000) | ((-viewz) & 0xffff); + MTX1->m[3][3] = ((viewy << 16) & 0xffff0000); + MTX1++; + + // Phase 3 + R_RenderAll(); + + if (cameratarget == viewplayer->mo) + R_RenderPSprites(); +} + +/*============================================================================= */ + +/* +=============================================================================== += += R_PointOnSide += += Returns side 0 (front) or 1 (back) +=============================================================================== +*/ +int R_PointOnSide(int x, int y, node_t *node) // 80023B6C +{ + fixed_t dx, dy; + fixed_t left, right; + + if (!node->line.dx) + { + if (x <= node->line.x) + return (node->line.dy > 0); + return (node->line.dy < 0); + } + if (!node->line.dy) + { + if (y <= node->line.y) + return (node->line.dx < 0); + return (node->line.dx > 0); + } + + dx = (x - node->line.x); + dy = (y - node->line.y); + + left = (node->line.dy >> 16) * (dx >> 16); + right = (dy >> 16) * (node->line.dx >> 16); + + if (right < left) + return 0; /* front side */ + return 1; /* back side */ +} + +/* +============== += += R_PointInSubsector += +============== +*/ + +struct subsector_s *R_PointInSubsector(fixed_t x, fixed_t y) // 80023C44 +{ + node_t *node; + int side, nodenum; + + if (!numnodes) /* single subsector is a special case */ + return subsectors; + + nodenum = numnodes - 1; + + while (!(nodenum & NF_SUBSECTOR)) + { + node = &nodes[nodenum]; + side = R_PointOnSide(x, y, node); + nodenum = node->children[side]; + } + + return &subsectors[nodenum & ~NF_SUBSECTOR]; +} + +/* +=============================================================================== += += R_PointToAngle += +=============================================================================== +*/ + +extern angle_t tantoangle[SLOPERANGE + 1]; + +int SlopeDiv(unsigned num, unsigned den) // 80023D10 +{ + unsigned ans; + if (den < 512) + return SLOPERANGE; + ans = (num << 3) / (den >> 8); + return ans <= SLOPERANGE ? ans : SLOPERANGE; +} + +angle_t R_PointToAngle2(fixed_t x1, fixed_t y1, fixed_t x2, fixed_t y2) // 80023D60 +{ + int x; + int y; + + x = x2 - x1; + y = y2 - y1; + + if ((!x) && (!y)) + return 0; + + if (x >= 0) + { /* x >=0 */ + if (y >= 0) + { /* y>= 0 */ + if (x>y) + return tantoangle[SlopeDiv(y, x)]; /* octant 0 */ + else + return ANG90 - 1 - tantoangle[SlopeDiv(x, y)]; /* octant 1 */ + } + else + { /* y<0 */ + y = -y; + if (x>y) + return -tantoangle[SlopeDiv(y, x)]; /* octant 8 */ + else + return ANG270 + tantoangle[SlopeDiv(x, y)]; /* octant 7 */ + } + } + else + { /* x<0 */ + x = -x; + if (y >= 0) + { /* y>= 0 */ + if (x>y) + return ANG180 - 1 - tantoangle[SlopeDiv(y, x)]; /* octant 3 */ + else + return ANG90 + tantoangle[SlopeDiv(x, y)]; /* octant 2 */ + } + else + { /* y<0 */ + y = -y; + if (x>y) + return ANG180 + tantoangle[SlopeDiv(y, x)]; /* octant 4 */ + else + return ANG270 - 1 - tantoangle[SlopeDiv(x, y)]; /* octant 5 */ + } + } +} diff --git a/Doom 64/r_phase1.c b/Doom 64/r_phase1.c @@ -0,0 +1,569 @@ + +//Renderer phase 1 - BSP traversal + +#include "doomdef.h" +#include "r_local.h" + +int checkcoord[12][4] = // 8005B110 +{ + { 3, 0, 2, 1 },/* Above,Left */ + { 3, 0, 2, 0 },/* Above,Center */ + { 3, 1, 2, 0 },/* Above,Right */ + { 0, 0, 0, 0 }, + { 2, 0, 2, 1 },/* Center,Left */ + { 0, 0, 0, 0 },/* Center,Center */ + { 3, 1, 3, 0 },/* Center,Right */ + { 0, 0, 0, 0 }, + { 2, 0, 3, 1 },/* Below,Left */ + { 2, 1, 3, 1 },/* Below,Center */ + { 2, 1, 3, 0 },/* Below,Right */ + { 0, 0, 0, 0 } +}; + +void R_RenderBSPNode(int bspnum); +boolean R_CheckBBox(fixed_t bspcoord[4]); +void R_Subsector(int num); +void R_AddLine(seg_t *line); +void R_AddSprite(subsector_t *sub); +void R_RenderBSPNodeNoClip(int bspnum); + +// +// Kick off the rendering process by initializing the solidsubsectors array and then +// starting the BSP traversal. +// + +void R_BSP(void) // 80023F30 +{ + int count; + subsector_t **sub; + + validcount++; + rendersky = false; + + numdrawsubsectors = 0; + numdrawvissprites = 0; + + visspritehead = vissprites; + + endsubsector = solidsubsectors; /* Init the free memory pointer */ + D_memset(solidcols, 0, 320); + + if (camviewpitch == 0) + { + R_RenderBSPNode(numnodes - 1); /* Begin traversing the BSP tree for all walls in render range */ + } + else + { + R_RenderBSPNodeNoClip(numnodes - 1); /* Begin traversing the BSP tree for all walls in render range */ + rendersky = true; + } + + sub = solidsubsectors; + count = numdrawsubsectors; + while(count) + { + R_AddSprite(*sub); /* Render each sprite */ + sub++; /* Inc the sprite pointer */ + count--; + } +} + +// +// Recursively descend through the BSP, classifying nodes according to the +// player's point of view, and render subsectors in view. +// + +void R_RenderBSPNode(int bspnum) // 80024020 +{ + node_t *bsp; + int side; + fixed_t dx, dy; + fixed_t left, right; + + //printf("R_RenderBSPNode\n"); + + while(!(bspnum & NF_SUBSECTOR)) + { + bsp = &nodes[bspnum]; + + // Decide which side the view point is on. + //side = R_PointOnSide(viewx, viewy, bsp); + dx = (viewx - bsp->line.x); + dy = (viewy - bsp->line.y); + + left = (bsp->line.dy >> 16) * (dx >> 16); + right = (dy >> 16) * (bsp->line.dx >> 16); + + if (right < left) + side = 0; /* front side */ + else + side = 1; /* back side */ + + // check the front space + if(R_CheckBBox(bsp->bbox[side])) + { + R_RenderBSPNode(bsp->children[side]); + } + + // continue down the back space + if(!R_CheckBBox(bsp->bbox[side^1])) + { + return; + } + + bspnum = bsp->children[side^1]; + } + + // subsector with contents + // add all the drawable elements in the subsector + if(bspnum == -1) + bspnum = 0; + + R_Subsector(bspnum & ~NF_SUBSECTOR); +} + +// +// Checks BSP node/subtree bounding box. Returns true if some part of the bbox +// might be visible. +// + +boolean R_CheckBBox(fixed_t bspcoord[4]) // 80024170 +{ + int boxx; + int boxy; + int boxpos; + + fixed_t x1, y1, x2, y2; + byte *solid_cols; + int vx1, vy1, vx2, vy2, delta; + int Xstart, Xend; + + // find the corners of the box that define the edges from current viewpoint + if (viewx < bspcoord[BOXLEFT]) + boxx = 0; + else if (viewx <= bspcoord[BOXRIGHT]) + boxx = 1; + else + boxx = 2; + + if (viewy > bspcoord[BOXTOP]) + boxy = 0; + else if (viewy >= bspcoord[BOXBOTTOM]) + boxy = 1; + else + boxy = 2; + + boxpos = (boxy << 2) + boxx; + if (boxpos == 5) + return true; + + x1 = bspcoord[checkcoord[boxpos][0]]; + y1 = bspcoord[checkcoord[boxpos][1]]; + x2 = bspcoord[checkcoord[boxpos][2]]; + y2 = bspcoord[checkcoord[boxpos][3]]; + + vx1 = FixedMul(viewsin, x1 - viewx) - FixedMul(viewcos, y1 - viewy); + vy1 = FixedMul(viewcos, x1 - viewx) + FixedMul(viewsin, y1 - viewy); + vx2 = FixedMul(viewsin, x2 - viewx) - FixedMul(viewcos, y2 - viewy); + vy2 = FixedMul(viewcos, x2 - viewx) + FixedMul(viewsin, y2 - viewy); + + if ((vx1 < -vy1) && (vx2 < -vy2)) + return false; + + if ((vy1 < vx1) && (vy2 < vx2)) + return false; + + if ((((vx2 >> 16) * (vy1 >> 16)) - ((vx1 >> 16) * (vy2 >> 16))) < 2) + return true; + + if ((vy1 <= 0) && (vy2 <= 0)) + return false; + + if (vx1 < -vy1) + { + delta = (vx1 + vy1); + delta = FixedDiv2(delta, ((delta - vx2) - vy2)); + delta = FixedMul(delta, (vy2 - vy1)); + + vy1 += delta; + vx1 = -vy1; + } + + if (vy2 < vx2) + { + delta = (vx1 - vy1); + delta = FixedDiv2(delta, ((delta - vx2) + vy2)); + delta = FixedMul(delta, (vy2 - vy1)); + vx2 = delta + vy1; + vy2 = vx2; + } + + Xstart = ((FixedDiv2(vx1, vy1) * 160) >> 16) + 160; + Xend = ((FixedDiv2(vx2, vy2) * 160) >> 16) + 160; + + if (Xstart < 0) + Xstart = 0; + + if (Xend >= 320) + Xend = 320; + + solid_cols = &solidcols[Xstart]; + while (Xstart < Xend) + { + if (*solid_cols == 0) + return true; + solid_cols++; + Xstart++; + } + + return false; +} + +// +// Determine floor/ceiling planes, add sprites of things in sector, +// draw one or more segments. +// + +void R_Subsector(int num) // 8002451C +{ + subsector_t *sub; + seg_t *line; + int count; + + if (num >= numsubsectors) + { + I_Error("R_Subsector: ss %i with numss = %i", num, numsubsectors); + } + + if (numdrawsubsectors < MAXSUBSECTORS) + { + numdrawsubsectors++; + + sub = &subsectors[num]; + sub->drawindex = numdrawsubsectors; + + *endsubsector = sub;//copy subsector + endsubsector++; + + frontsector = sub->sector; + + line = &segs[sub->firstline]; + count = sub->numlines; + do + { + R_AddLine(line); /* Render each line */ + ++line; /* Inc the line pointer */ + } while (--count); /* All done? */ + } +} + +// +// Clips the given segment and adds any visible pieces to the line list. +// + +void R_AddLine(seg_t *line) // 80024604 +{ + sector_t *backsector; + vertex_t *vrt, *vrt2; + int x1, y1, x2, y2, count; + int Xstart, Xend, delta; + byte *solid_cols; + + line->flags &= ~1; + + vrt = line->v1; + if (vrt->validcount != validcount) + { + x1 = FixedMul(viewsin, (vrt->x - viewx)) - FixedMul(viewcos,(vrt->y - viewy)); + y1 = FixedMul(viewcos, (vrt->x - viewx)) + FixedMul(viewsin,(vrt->y - viewy)); + + vrt->vx = x1; + vrt->vy = y1; + + vrt->validcount = validcount; + } + else + { + x1 = vrt->vx; + y1 = vrt->vy; + } + + vrt2 = line->v2; + if (vrt2->validcount != validcount) + { + x2 = FixedMul(viewsin, (vrt2->x - viewx)) - FixedMul(viewcos,(vrt2->y - viewy)); + y2 = FixedMul(viewcos, (vrt2->x - viewx)) + FixedMul(viewsin,(vrt2->y - viewy)); + + vrt2->vx = x2; + vrt2->vy = y2; + + vrt2->validcount = validcount; + } + else + { + x2 = vrt2->vx; + y2 = vrt2->vy; + } + + if ((x1 < -y1) && (x2 < -y2)) + return; + + if ((y1 < x1) && (y2 < x2)) + return; + + if ((y1 < ((8*FRACUNIT)+1)) && (y2 < ((8*FRACUNIT)+1))) + return; + + if ((((x2 >> 16) * (y1 >> 16)) - ((x1 >> 16) * (y2 >> 16))) <= 0) + return; + + if (y1 < (8*FRACUNIT)) + { + delta = FixedDiv2(((8*FRACUNIT) - y1), (y2 - y1)); + delta = FixedMul(delta, (x2 - x1)); + x1 += delta; + y1 = (8*FRACUNIT); + } + else if (y2 < (8*FRACUNIT)) + { + delta = FixedDiv2(((8*FRACUNIT) - y2), (y1 - y2)); + delta = FixedMul(delta, (x1 - x2)); + x2 += delta; + y2 = (8*FRACUNIT); + } + + Xstart = ((FixedDiv2(x1, y1) * 160) >> 16) + 160; + Xend = ((FixedDiv2(x2, y2) * 160) >> 16) + 160; + + if (Xstart < 0) + Xstart = 0; + + if (Xend >= 320) + Xend = 320; + + if (Xstart != Xend) + { + solid_cols = &solidcols[Xstart]; + count = Xstart; + while (count < Xend) + { + if (*solid_cols == 0) + { + line->flags |= 1; + line->linedef->flags |= ML_MAPPED; + break; + } + solid_cols++; + count++; + } + + if (frontsector->ceilingpic == -1) { + rendersky = true; + } + + if (!(line->linedef->flags & (ML_DONTOCCLUDE|ML_DRAWMASKED))) + { + backsector = line->backsector; + + if(!backsector || + backsector->ceilingheight <= frontsector->floorheight || + backsector->floorheight >= frontsector->ceilingheight || + backsector->floorheight == backsector->ceilingheight) // New line on Doom 64 + { + solid_cols = &solidcols[Xstart]; + while (Xstart < Xend) + { + *solid_cols = 1; + solid_cols++; + Xstart += 1; + } + } + } + } +} + +void R_AddSprite(subsector_t *sub) // 80024A98 +{ + byte *data; + mobj_t *thing; + spritedef_t *sprdef; + spriteframe_t *sprframe; + + subsector_t *pSub; + subsector_t *CurSub; + vissprite_t *VisSrpCur, *VisSrpCurTmp; + vissprite_t *VisSrpNew; + + angle_t ang; + unsigned int rot; + boolean flip; + int lump; + fixed_t tx, tz; + fixed_t x, y; + int numdraw; + + sub->vissprite = NULL; + + for (thing = sub->sector->thinglist; thing; thing = thing->snext) + { + if (thing->subsector != sub) + continue; + + if (numdrawvissprites >= MAXVISSPRITES) + break; + + if (thing->flags & MF_RENDERLASER) + { + visspritehead->zdistance = MAXINT; + visspritehead->thing = thing; + visspritehead->next = sub->vissprite; + sub->vissprite = visspritehead; + + visspritehead++; + numdrawvissprites++; + } + else + { + // transform origin relative to viewpoint + x = (thing->x - viewx) >> 16; + y = (thing->y - viewy) >> 16; + tx = ((viewsin * x) - (viewcos * y)) >> 16; + tz = ((viewcos * x) + (viewsin * y)) >> 16; + + // thing is behind view plane? + if (tz < MINZ) + continue; + + // too far off the side? + if (tx > (tz << 1) || tx < -(tz << 1)) + continue; + + sprdef = &sprites[thing->sprite]; + sprframe = &sprdef->spriteframes[thing->frame & FF_FRAMEMASK]; + + if (sprframe->rotate != 0) + { + ang = R_PointToAngle2(viewx, viewy, thing->x, thing->y); + rot = ((ang - thing->angle) + ((unsigned int)(ANG45 / 2) * 9)) >> 29; + lump = sprframe->lump[rot]; + flip = (boolean)(sprframe->flip[rot]); + } + else + { + lump = sprframe->lump[0]; + flip = (boolean)(sprframe->flip[0]); + } + + visspritehead->zdistance = tz; + visspritehead->thing = thing; + visspritehead->lump = lump; + visspritehead->flip = flip; + visspritehead->next = NULL; + visspritehead->sector = sub->sector; + + data = (byte *)W_CacheLumpNum(lump, PU_CACHE, dec_jag); + + CurSub = sub; + if (tz < MAXZ) + { + if (thing->flags & (MF_CORPSE|MF_SHOOTABLE)) + { + x = ((((spriteN64_t*)data)->width >> 1) * viewsin); + y = ((((spriteN64_t*)data)->width >> 1) * viewcos); + + pSub = R_PointInSubsector((thing->x - x), (thing->y + y)); + if ((pSub->drawindex) && (pSub->drawindex < sub->drawindex)) { + CurSub = pSub; + } + + pSub = R_PointInSubsector((thing->x + x), (thing->y - y)); + if ((pSub->drawindex) && (pSub->drawindex < CurSub->drawindex)) { + CurSub = pSub; + } + } + } + + VisSrpCur = CurSub->vissprite; + VisSrpNew = NULL; + + if (VisSrpCur) + { + VisSrpCurTmp = VisSrpCur; + while ((VisSrpCur = VisSrpCurTmp, tz < VisSrpCur->zdistance)) + { + VisSrpCur = VisSrpCurTmp->next; + VisSrpNew = VisSrpCurTmp; + + if (VisSrpCur == NULL) + break; + + VisSrpCurTmp = VisSrpCur; + } + } + + if (VisSrpNew) + VisSrpNew->next = visspritehead; + else + CurSub->vissprite = visspritehead; + + visspritehead->next = VisSrpCur; + + numdrawvissprites++; + visspritehead++; + } + } +} + +void R_RenderBSPNodeNoClip(int bspnum) // 80024E64 +{ + subsector_t *sub; + seg_t *line; + int count; + node_t *bsp; + int side; + fixed_t dx, dy; + fixed_t left, right; + + while(!(bspnum & NF_SUBSECTOR)) + { + bsp = &nodes[bspnum]; + + // Decide which side the view point is on. + //side = R_PointOnSide(viewx, viewy, bsp); + dx = (viewx - bsp->line.x); + dy = (viewy - bsp->line.y); + + left = (bsp->line.dy >> 16) * (dx >> 16); + right = (dy >> 16) * (bsp->line.dx >> 16); + + if (right < left) + side = 1; /* back side */ + else + side = 0; /* front side */ + + R_RenderBSPNodeNoClip(bsp->children[side ^ 1]); + + bspnum = bsp->children[side]; + } + + // subsector with contents + // add all the drawable elements in the subsector + + numdrawsubsectors++; + + sub = &subsectors[bspnum & ~NF_SUBSECTOR]; + sub->drawindex = numdrawsubsectors; + + *endsubsector = sub;//copy subsector + endsubsector++; + + frontsector = sub->sector; + + line = &segs[sub->firstline]; + count = sub->numlines; + do + { + line->flags |= 1; /* Render each line */ + ++line; /* Inc the line pointer */ + } while (--count); /* All done? */ +} diff --git a/Doom 64/r_phase2.c b/Doom 64/r_phase2.c @@ -0,0 +1,549 @@ + +//Renderer phase 2 - Sky Rendering Routines + +#include "doomdef.h" +#include "r_local.h" + +#define FIRESKY_WIDTH 64 +#define FIRESKY_HEIGHT 64 + +typedef enum +{ + SKF_CLOUD = 1, + SKF_THUNDER = 2, + SKF_MOUNTAIN = 4, +} skyflags_e; + +Vtx SkyCloudVertex[4] = // 8005B1D0 +{ + { -300, 120, -160, 0, (0 << 6), (0 << 6), 0, 0, 0, 0xff }, + { 300, 120, -160, 0, (0 << 6), (0 << 6), 0, 0, 0, 0xff }, + { 300, 0, -300, 0, (0 << 6), (0 << 6), 0, 0, 0, 0xff }, + { -300, 0, -300, 0, (0 << 6), (0 << 6), 0, 0, 0, 0xff }, +}; + +Vtx SkyFireVertex[4] = // 8005B210 +{ + { -160, 120, -160, 0, (0 << 6), (0 << 6), 0, 0, 0, 0xff }, + { 160, 120, -160, 0, (0 << 6), (0 << 6), 0, 0, 0, 0xff }, + { 160, 0, -160, 0, (0 << 6), (64 << 6), 0, 0, 0, 0xff }, + { -160, 0, -160, 0, (0 << 6), (64 << 6), 0, 0, 0, 0xff }, +}; + +fixed_t FogNear; // 800A8120 +int FogColor; // 800A8124 +skyfunc_t R_RenderSKY; // 800A8130 +byte *SkyFireData[2]; // 800A8140 // Fire data double buffer +byte *SkyCloudData; // 800A8148 +int Skyfadeback; // 800A814C +int FireSide; // 800A8150 +int SkyCloudOffsetX; // 800A8154 +int SkyCloudOffsetY; // 800A8158 +int ThunderCounter; // 800A815C +int LightningCounter; // 800A8160 +int SkyPicSpace; // 800A8164 +int SkyPicMount; // 800A8168 +int SkyCloudColor; // 800A816C +int SkyVoidColor; // 800A8170 +int SkyFlags; // 800A8174 + +void R_RenderSpaceSky(void); +void R_RederCloudSky(void); +void R_RenderVoidSky(void); +void R_RenderEvilSky(void); +void R_RenderClouds(void); +void R_RenderSkyPic(int lump, int yoffset); +void R_RenderFireSky(void); +void R_CloudThunder(void); + +void R_SetupSky(void) // 80025060 +{ + byte *data; + + FogNear = 985; + FogColor = PACKRGBA(0,0,0,0); + R_RenderSKY = NULL; + SkyFlags = 0; + SkyCloudOffsetX = 0; + SkyCloudOffsetY = 0; + ThunderCounter = 180; + LightningCounter = 0; + FireSide = 0; + Skyfadeback = 0; + SkyPicSpace = W_GetNumForName("SPACE"); + + switch(skytexture) + { + case 1: + case 10: + SkyFlags = (SKF_CLOUD|SKF_THUNDER); + R_RenderSKY = R_RederCloudSky; + + SkyCloudData = (byte *)W_CacheLumpName("CLOUD", PU_STATIC, dec_jag); + SkyCloudColor = PACKRGBA(176,128,255,255); // 0xb080ffff + + if (skytexture == 10) + { + SkyPicMount = W_GetNumForName("MOUNTC"); + SkyFlags |= SKF_MOUNTAIN; + } + + *(int*)SkyCloudVertex[0].v.cn = PACKRGBA(0,0,0,255); // 0xff; + *(int*)SkyCloudVertex[1].v.cn = PACKRGBA(0,0,0,255); // 0xff; + *(int*)SkyCloudVertex[2].v.cn = PACKRGBA(0,0,21,255); // 0x15ff; + *(int*)SkyCloudVertex[3].v.cn = PACKRGBA(0,0,21,255); // 0x15ff; + break; + + case 2: + SkyFlags = SKF_CLOUD; + R_RenderSKY = R_RederCloudSky; + + SkyCloudData = (byte *)W_CacheLumpName("CLOUD", PU_STATIC, dec_jag); + SkyCloudColor = PACKRGBA(255,48,48,255); // 0xff3030ff; + + *(int*)SkyCloudVertex[0].v.cn = PACKRGBA(16,0,0,255); // 0x100000ff; + *(int*)SkyCloudVertex[1].v.cn = PACKRGBA(16,0,0,255); // 0x100000ff; + *(int*)SkyCloudVertex[2].v.cn = PACKRGBA(16,0,0,255); // 0x100000ff; + *(int*)SkyCloudVertex[3].v.cn = PACKRGBA(16,0,0,255); // 0x100000ff; + break; + + case 3: + case 5: + SkyFlags = SKF_CLOUD; + R_RenderSKY = R_RederCloudSky; + + SkyCloudData = (byte *)W_CacheLumpName("CLOUD", PU_STATIC, dec_jag); + SkyCloudColor = PACKRGBA(208,112,64,255); // 0xd07040ff; + + if (skytexture == 3) + { + SkyPicMount = W_GetNumForName("MOUNTB"); + SkyFlags |= SKF_MOUNTAIN; + } + else + { + FogNear = 975; + FogColor = PACKRGBA(48,16,8,0); // 0x30100800; + } + + *(int*)SkyCloudVertex[0].v.cn = PACKRGBA(0,0,0,255); // 0xff; + *(int*)SkyCloudVertex[1].v.cn = PACKRGBA(0,0,0,255); // 0xff; + *(int*)SkyCloudVertex[2].v.cn = PACKRGBA(64,16,0,255); // 0x401000ff; + *(int*)SkyCloudVertex[3].v.cn = PACKRGBA(64,16,0,255); // 0x401000ff; + break; + + case 4: + case 9: + R_RenderSKY = R_RenderFireSky; + + data = W_CacheLumpName("FIRE", PU_LEVEL, dec_jag); + SkyFireData[0] = (data + 8); + SkyFireData[1] = Z_Malloc((FIRESKY_WIDTH*FIRESKY_HEIGHT), PU_LEVEL, NULL); + + D_memcpy(SkyFireData[1], SkyFireData[0],(FIRESKY_WIDTH*FIRESKY_HEIGHT)); + + if (skytexture == 4) + { + *(int*)SkyFireVertex[0].v.cn = PACKRGBA(255,0,0,255); // 0xff0000ff; + *(int*)SkyFireVertex[1].v.cn = PACKRGBA(255,0,0,255); // 0xff0000ff; + *(int*)SkyFireVertex[2].v.cn = PACKRGBA(255,96,0,255); // 0xff6000ff; + *(int*)SkyFireVertex[3].v.cn = PACKRGBA(255,96,0,255); // 0xff6000ff; + } + else + { + *(int*)SkyFireVertex[0].v.cn = PACKRGBA(0,255,0,255); // 0xff00ff; + *(int*)SkyFireVertex[1].v.cn = PACKRGBA(0,255,0,255); // 0xff00ff; + *(int*)SkyFireVertex[2].v.cn = PACKRGBA(112,112,0,255); // 0x707000ff; + *(int*)SkyFireVertex[3].v.cn = PACKRGBA(112,112,0,255); // 0x707000ff; + } + break; + + case 6: + R_RenderSKY = R_RenderSpaceSky; + break; + + case 7: + FogNear = 995; + R_RenderSKY = R_RenderEvilSky; + break; + + case 8: + R_RenderSKY = R_RenderVoidSky; + FogNear = 975; + FogColor = PACKRGBA(0,64,64,0); // 0x404000; + SkyVoidColor = PACKRGBA(0,56,56,0); // 0x383800; + break; + + case 11: + R_RenderSKY = R_RenderSpaceSky; + SkyPicMount = W_GetNumForName("MOUNTA"); + SkyFlags |= SKF_MOUNTAIN; + break; + } +} + +void R_RenderSpaceSky(void) // 80025440 +{ + + gDPSetAlphaCompare(GFX1++, G_AC_NONE); + gDPSetCombineMode(GFX1++, G_CC_D64COMB09, G_CC_D64COMB09); + gDPSetRenderMode(GFX1++, G_RM_OPA_SURF, G_RM_OPA_SURF2); + gDPSetPrimColor(GFX1++, 0, (lights[255].rgba >> 8), 0, 0, 0, 255); + + R_RenderSkyPic(SkyPicSpace, 128); + + if (SkyFlags & SKF_MOUNTAIN) + { + gDPPipeSync(GFX1++); + gDPSetAlphaCompare(GFX1++, G_AC_THRESHOLD); + gDPSetCombineMode(GFX1++, G_CC_D64COMB10, G_CC_D64COMB10); + gDPSetRenderMode(GFX1++, G_RM_TEX_EDGE, G_RM_TEX_EDGE2); + + R_RenderSkyPic(SkyPicMount, 170); + } +} + +void R_RederCloudSky(void) // 800255B8 +{ + if (SkyFlags & SKF_CLOUD) + R_RenderClouds(); + + if (SkyFlags & SKF_THUNDER) + R_CloudThunder(); + + if (SkyFlags & SKF_MOUNTAIN) + { + gDPPipeSync(GFX1++); + gDPSetAlphaCompare(GFX1++, G_AC_THRESHOLD); + gDPSetCombineMode(GFX1++, G_CC_D64COMB10, G_CC_D64COMB10); + gDPSetRenderMode(GFX1++, G_RM_TEX_EDGE, G_RM_TEX_EDGE2); + + R_RenderSkyPic(SkyPicMount, 170); + } +} + +void R_RenderVoidSky(void) // 800256B4 +{ + + gDPSetCycleType(GFX1++, G_CYC_FILL); + gDPSetRenderMode(GFX1++,G_RM_NOOP,G_RM_NOOP2); + + // Fill borders with SkyVoidColor + gDPSetFillColor(GFX1++, SkyVoidColor); + gDPFillRectangle(GFX1++, 0, 0, SCREEN_WD-1, SCREEN_HT-1); +} + +void R_RenderEvilSky(void) // 80025738 +{ + int color; + + gDPSetPrimColor(GFX1++, 0, ((lights[255].rgba >> 8) - Skyfadeback), 0, 0, 0, 255); + gDPSetAlphaCompare(GFX1++, G_AC_NONE); + gDPSetCombineMode(GFX1++, G_CC_D64COMB09, G_CC_D64COMB09); + gDPSetRenderMode(GFX1++,G_RM_OPA_SURF,G_RM_OPA_SURF2); + + R_RenderSkyPic(SkyPicSpace, 128); + R_RenderSkyPic(SkyPicSpace, 240); + + if (Skyfadeback) + { + Skyfadeback += 4; + + if (Skyfadeback > 255) + Skyfadeback = 255; + + if (Skyfadeback > 128) + color = 128; + else + color = Skyfadeback; + + M_DrawBackground(63, 25, color, "EVIL"); + } +} + +void R_RenderClouds(void) // 80025878 +{ + int x, y; + + gDPSetCycleType(GFX1++, G_CYC_2CYCLE); + gDPSetTexturePersp(GFX1++, G_TP_PERSP); + gDPSetTextureLUT(GFX1++, G_TT_NONE); + gDPSetCombineMode(GFX1++, G_CC_D64COMB11, G_CC_D64COMB12); + gDPSetRenderMode(GFX1++,G_RM_OPA_SURF,G_RM_OPA_SURF2); + + gDPSetPrimColorD64(GFX1++, 0, (lights[255].rgba >> 8), SkyCloudColor); + + if (!gamepaused) + { + SkyCloudOffsetX = (SkyCloudOffsetX - (viewcos >> 14)) & 16383; + SkyCloudOffsetY = (SkyCloudOffsetY + (viewsin >> 13)) & 16383; + } + + x = SkyCloudOffsetX - (viewangle >> ANGLETOFINESHIFT); + y = SkyCloudOffsetY; + + D_memcpy(VTX1, SkyCloudVertex, sizeof(Vtx)*4); + + VTX1[0].v.tc[0] = x; + VTX1[1].v.tc[0] = x + (64 << 6); + VTX1[2].v.tc[0] = x + (64 << 6); + VTX1[3].v.tc[0] = x; + + VTX1[0].v.tc[1] = y; + VTX1[1].v.tc[1] = y; + VTX1[2].v.tc[1] = y + (128 << 6); + VTX1[3].v.tc[1] = y + (128 << 6); + + gDPSetTextureImage(GFX1++, G_IM_FMT_I, G_IM_SIZ_16b , 1, (SkyCloudData+8)); + gDPSetTile(GFX1++, G_IM_FMT_I, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, 0, 0, 6, 0, 0, 6, 0); + + gDPLoadSync(GFX1++); + gDPLoadBlock(GFX1++, G_TX_LOADTILE, 0, 0, (((64 * 64) -1) >> 1), 0); + + gDPPipeSync(GFX1++); + gDPSetTile(GFX1++, G_IM_FMT_I, G_IM_SIZ_8b, 8, 0, G_TX_RENDERTILE, 0, 0, 6, 0, 0, 6, 0); + gDPSetTileSize(GFX1++, G_TX_RENDERTILE, 0, 0, (63 << 2), (63 << 2)); + gSPTexture(GFX1++, (768 << 6), (512 << 6), 0, G_TX_RENDERTILE, G_ON); + + gSPVertex(GFX1++, VTX1, 4, 0); + gSP1Triangle(GFX1++, 0, 2, 1, 0); + gSP1Triangle(GFX1++, 0, 3, 2, 0); + + VTX1 += 4; +} + +void R_RenderSkyPic(int lump, int yoffset) // 80025BDC +{ + byte *data; + byte *src; + byte *paldata; + int i; + + int tileh; + int yl, yh; + int ang; + int lrs; + + data = W_CacheLumpNum(lump, PU_CACHE, dec_jag); + + ang = (0 - ( viewangle >> 22) & 255); + tileh = ((spriteN64_t*)data)->tileheight; + + src = data + sizeof(spriteN64_t); + paldata = (src + ((spriteN64_t*)data)->cmpsize); + + gDPSetCycleType(GFX1++, G_CYC_1CYCLE); + + gDPSetTexturePersp(GFX1++, G_TP_NONE); + gDPSetTextureLUT(GFX1++, G_TT_RGBA16); + gDPSetBlendColor(GFX1++, 0, 0, 0, 0); + + // Load Palette Data (256 colors) + gDPSetTextureImage(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_16b , 1, paldata); + + gDPTileSync(GFX1++); + gDPSetTile(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_4b, 0, 256, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0); + + gDPLoadSync(GFX1++); + gDPLoadTLUTCmd(GFX1++, G_TX_LOADTILE, 255); + + gDPPipeSync(GFX1++); + + lrs = (((tileh << 8) + 1) >> 1) - 1; + yl = (yoffset - ((spriteN64_t*)data)->height); + + for(i = 0; i < ((spriteN64_t*)data)->tiles; i++) + { + yh = (tileh + yl); + + gDPSetTextureImage(GFX1++, G_IM_FMT_CI, G_IM_SIZ_16b , 1, src); + gDPSetTile(GFX1++, G_IM_FMT_CI, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, 0, 0, 0, 0, 0, 8, 0); + + gDPLoadSync(GFX1++); + gDPLoadBlock(GFX1++, G_TX_LOADTILE, 0, 0, lrs, 0); + + gDPPipeSync(GFX1++); + gDPSetTile(GFX1++, G_IM_FMT_CI, G_IM_SIZ_8b, 32, 0, G_TX_RENDERTILE, 0, 0, 0, 0, 0, 8, 0); + gDPSetTileSize(GFX1++, 0, 0, 0, ((256-1) << 2), ((tileh - 1) << 2)); + + gSPTextureRectangle(GFX1++, (0 << 2), (yl << 2), + (320 << 2), (yh << 2), + G_TX_RENDERTILE, + (ang << 5), (0 << 5), + (1 << 10), (1 << 10)); + src += (tileh << 8); + yl = yh; + } +} + +void R_RenderFireSky(void) // 80025F68 +{ + byte *buff; + byte *src, *srcoffset, *tmpSrc; + int width, height, rand; + int pixel, randIdx; + int ang, t; + + gDPSetCycleType(GFX1++, G_CYC_2CYCLE); + gDPSetTexturePersp(GFX1++, G_TP_PERSP); + gDPSetTextureLUT(GFX1++, G_TT_NONE); + gDPSetCombineMode(GFX1++, G_CC_D64COMB13, G_CC_D64COMB14); + gDPSetRenderMode(GFX1++,G_RM_OPA_SURF,G_RM_OPA_SURF2); + gDPSetPrimColor(GFX1++, 0, (lights[255].rgba >> 8), 0, 0, 0, 255); + + if (((gamevbls < gametic) && (gametic & 1)) && (!gamepaused)) + { + buff = SkyFireData[FireSide]; + D_memcpy(buff, SkyFireData[FireSide ^ 1], (FIRESKY_WIDTH*FIRESKY_HEIGHT)); + + rand = (M_Random() & 0xff); + width = 0; + src = (buff + FIRESKY_WIDTH); + + do // width + { + height = 2; + srcoffset = (src + width); + + // R_SpreadFire + pixel = *(byte*)srcoffset; + if (pixel != 0) + { + randIdx = rndtable[rand]; + rand = ((rand + 2) & 0xff); + + tmpSrc = (src + (((width - (randIdx & 3)) + 1) & (FIRESKY_WIDTH-1))); + *(byte*)(tmpSrc - FIRESKY_WIDTH) = pixel - ((randIdx & 1) << 4); + } + else + { + *(byte*)(srcoffset - FIRESKY_WIDTH) = 0; + } + + src += FIRESKY_WIDTH; + srcoffset += FIRESKY_WIDTH; + + do // height + { + height += 2; + + // R_SpreadFire + pixel = *(byte*)srcoffset; + if (pixel != 0) + { + randIdx = rndtable[rand]; + rand = ((rand + 2) & 0xff); + + tmpSrc = (src + (((width - (randIdx & 3)) + 1) & (FIRESKY_WIDTH-1))); + *(byte*)(tmpSrc - FIRESKY_WIDTH) = pixel - ((randIdx & 1) << 4); + } + else + { + *(byte*)(srcoffset - FIRESKY_WIDTH) = 0; + } + + src += FIRESKY_WIDTH; + srcoffset += FIRESKY_WIDTH; + + // R_SpreadFire + pixel = *(byte*)srcoffset; + if (pixel != 0) + { + randIdx = rndtable[rand]; + rand = ((rand + 2) & 0xff); + + tmpSrc = (src + (((width - (randIdx & 3)) + 1) & (FIRESKY_WIDTH-1))); + *(byte*)(tmpSrc - FIRESKY_WIDTH) = pixel - ((randIdx & 1) << 4); + } + else + { + *(byte*)(srcoffset - FIRESKY_WIDTH) = 0; + } + + src += FIRESKY_WIDTH; + srcoffset += FIRESKY_WIDTH; + + } while (height != FIRESKY_HEIGHT); + + src -= ((FIRESKY_WIDTH*FIRESKY_HEIGHT) - FIRESKY_WIDTH); + width++; + + } while (width != FIRESKY_WIDTH); + + FireSide ^= 1; + } + else + { + buff = SkyFireData[FireSide ^ 1]; + } + + D_memcpy(VTX1, SkyFireVertex, sizeof(Vtx)*4); + + ang = (viewangle >> 22); + t = ((-ang & 255) << 5); + + VTX1[0].v.tc[0] = t; + VTX1[1].v.tc[0] = t + 0x2800; + VTX1[2].v.tc[0] = t + 0x2800; + VTX1[3].v.tc[0] = t; + + gDPSetTextureImage(GFX1++, G_IM_FMT_I, G_IM_SIZ_16b , 1, buff); + gDPSetTile(GFX1++, G_IM_FMT_I, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, 0, 0, 0, 0, 0, 6, 0); + + gDPLoadSync(GFX1++); + gDPLoadBlock(GFX1++, G_TX_LOADTILE, 0, 0, (((64 * 64) -1) >> 1), 256); + + gDPPipeSync(GFX1++); + gDPSetTile(GFX1++, G_IM_FMT_I, G_IM_SIZ_8b, 8, 0, G_TX_RENDERTILE, 0, 0, 0, 0, 0, 6, 0); + gDPSetTileSize(GFX1++, G_TX_RENDERTILE, 0, 0, (63 << 2), (63 << 2)); + gSPTexture(GFX1++, (1024 << 6)-1, (512 << 6), 0, G_TX_RENDERTILE, G_ON); + + gSPVertex(GFX1++, VTX1, 4, 0); + gSP1Triangle(GFX1++, 0, 2, 1, 0); + gSP1Triangle(GFX1++, 0, 3, 2, 0); + + VTX1 += 4; +} + +void R_CloudThunder(void) // 80026418 +{ + int rand; + if (!(gamepaused)) + { + ThunderCounter -= vblsinframe[0]; + + if(ThunderCounter <= 0) + { + if (LightningCounter == 0) + { + S_StartSound(NULL, sfx_thndrlow + (M_Random() & 1)); + } + else if(!(LightningCounter < 6)) // Reset loop after 6 lightning flickers + { + rand = (M_Random() & 7); + ThunderCounter = ((rand << 4) - rand << 2) + 60; + LightningCounter = 0; + return; + } + + if ((LightningCounter & 1) == 0) + { + *(int*)SkyCloudVertex[0].v.cn += PACKRGBA(17,17,17,0); // 0x11111100; + *(int*)SkyCloudVertex[1].v.cn += PACKRGBA(17,17,17,0); // 0x11111100; + *(int*)SkyCloudVertex[2].v.cn += PACKRGBA(17,17,17,0); // 0x11111100; + *(int*)SkyCloudVertex[3].v.cn += PACKRGBA(17,17,17,0); // 0x11111100; + } + else + { + *(int*)SkyCloudVertex[0].v.cn -= PACKRGBA(17,17,17,0); // 0x11111100; + *(int*)SkyCloudVertex[1].v.cn -= PACKRGBA(17,17,17,0); // 0x11111100; + *(int*)SkyCloudVertex[2].v.cn -= PACKRGBA(17,17,17,0); // 0x11111100; + *(int*)SkyCloudVertex[3].v.cn -= PACKRGBA(17,17,17,0); // 0x11111100; + } + + ThunderCounter = (M_Random() & 7) + 1; // Do short delay loops for lightning flickers + LightningCounter += 1; + } + } +} + diff --git a/Doom 64/r_phase3.c b/Doom 64/r_phase3.c @@ -0,0 +1,1288 @@ + +//Renderer phase 3 - World Rendering Routines + +#include "doomdef.h" +#include "r_local.h" + +//-----------------------------------// +void R_RenderWorld(subsector_t *sub); + +void R_WallPrep(seg_t *seg); +void R_RenderWall(seg_t *seg, int flags, int texture, int topHeight, int bottomHeight, int topOffset, int bottomOffset, int topColor, int bottomColor); +void R_RenderSwitch(seg_t *seg, int texture, int topOffset, int color); + +void R_RenderPlane(leaf_t *leaf, int numverts, int zpos, int texture, int xpos, int ypos, int color); + +void R_RenderThings(subsector_t *sub); +void R_RenderLaser(mobj_t *thing); +void R_RenderPSprites(void); +//-----------------------------------// + +void R_RenderAll(void) // 80026590 +{ + subsector_t *sub; + + while (endsubsector--, (endsubsector >= solidsubsectors)) + { + sub = *endsubsector; + frontsector = sub->sector; + R_RenderWorld(sub); + + sub->drawindex = 0x7fff; + } +} + +void R_RenderWorld(subsector_t *sub) // 80026638 +{ + leaf_t *lf; + seg_t *seg; + + fixed_t xoffset; + fixed_t yoffset; + int numverts; + int i; + + I_CheckGFX(); + + gDPSetPrimColor(GFX1++, 0, frontsector->lightlevel, 0, 0, 0, 255); + + numverts = sub->numverts; + + /* */ + /* Render Walls */ + /* */ + lf = &leafs[sub->leaf]; + for (i = 0; i < numverts; i++) + { + seg = lf->seg; + + if (seg && (seg->flags & 1)) + { + R_WallPrep(seg); + } + + lf++; + } + + /* */ + /* Render Ceilings */ + /* */ + if ((frontsector->ceilingpic != -1) && (viewz < frontsector->ceilingheight)) + { + if (frontsector->flags & MS_SCROLLCEILING) + { + xoffset = frontsector->xoffset; + yoffset = frontsector->yoffset; + } + else + { + xoffset = 0; + yoffset = 0; + } + + lf = &leafs[sub->leaf]; + R_RenderPlane(lf, numverts, frontsector->ceilingheight >> FRACBITS, + textures[frontsector->ceilingpic], + xoffset, yoffset, + lights[frontsector->colors[0]].rgba); + } + + /* */ + /* Render Floors */ + /* */ + if ((frontsector->floorpic != -1) && (frontsector->floorheight < viewz)) + { + if (!(frontsector->flags & MS_LIQUIDFLOOR)) + { + if (frontsector->flags & MS_SCROLLFLOOR) + { + xoffset = frontsector->xoffset; + yoffset = frontsector->yoffset; + } + else + { + xoffset = 0; + yoffset = 0; + } + + lf = &leafs[sub->leaf]; + R_RenderPlane(lf, numverts, frontsector->floorheight >> FRACBITS, + textures[frontsector->floorpic], + xoffset, yoffset, + lights[frontsector->colors[1]].rgba); + } + else + { + gDPPipeSync(GFX1++); + gDPSetRenderMode(GFX1++, G_RM_FOG_SHADE_A, G_RM_XLU_SURF2); + + if (frontsector->flags & MS_SCROLLFLOOR) + { + xoffset = frontsector->xoffset; + yoffset = frontsector->yoffset; + } + else + { + xoffset = scrollfrac; + yoffset = 0; + } + + //-------------------------------------------------------------- + lf = &leafs[sub->leaf]; + R_RenderPlane(lf, numverts, frontsector->floorheight >> FRACBITS, + textures[frontsector->floorpic + 1], + xoffset, yoffset, + lights[frontsector->colors[1]].rgba); + + //-------------------------------------------------------------- + gDPSetPrimColor(GFX1++, 0, frontsector->lightlevel, 0, 0, 0, 160); + + lf = &leafs[sub->leaf]; + R_RenderPlane(lf, numverts, frontsector->floorheight >> FRACBITS, + textures[frontsector->floorpic], + -yoffset, xoffset, + lights[frontsector->colors[1]].rgba); + + gDPPipeSync(GFX1++); + gDPSetRenderMode(GFX1++, G_RM_FOG_SHADE_A, G_RM_TEX_EDGE2); + } + } + + /* */ + /* Render Things */ + /* */ + R_RenderThings(sub); +} + +void R_WallPrep(seg_t *seg) // 80026A44 +{ + sector_t *backsector; + line_t *li; + side_t *side; + fixed_t f_ceilingheight; + fixed_t f_floorheight; + fixed_t b_ceilingheight; + fixed_t b_floorheight; + fixed_t m_top; + fixed_t m_bottom; + fixed_t height; + fixed_t rowoffs; + int pic; + + unsigned int height2; + unsigned int r1, g1, b1; + unsigned int r2, g2, b2; + unsigned int thingcolor; + unsigned int upcolor; + unsigned int lowcolor; + unsigned int topcolor; + unsigned int bottomcolor; + unsigned int tmp_upcolor; + unsigned int tmp_lowcolor; + + li = seg->linedef; + side = seg->sidedef; + + f_ceilingheight = frontsector->ceilingheight >> 16; + f_floorheight = frontsector->floorheight >> 16; + + thingcolor = lights[frontsector->colors[2]].rgba; + upcolor = lights[frontsector->colors[3]].rgba; + lowcolor = lights[frontsector->colors[4]].rgba; + + if (li->flags & ML_BLENDING) + { + r1 = upcolor >> 24; + g1 = upcolor >> 16 & 0xff; + b1 = upcolor >> 8 & 0xff; + r2 = lowcolor >> 24; + g2 = lowcolor >> 16 & 0xff; + b2 = lowcolor >> 8 & 0xff; + + tmp_upcolor = upcolor; + tmp_lowcolor = lowcolor; + } + else + { + topcolor = thingcolor; + bottomcolor = thingcolor; + } + + m_bottom = f_floorheight; // set middle bottom + m_top = f_ceilingheight; // set middle top + + backsector = seg->backsector; + if (backsector) + { + b_floorheight = backsector->floorheight >> 16; + b_ceilingheight = backsector->ceilingheight >> 16; + + if ((backsector->ceilingheight < frontsector->ceilingheight) && (backsector->ceilingpic != -1)) + { + if (li->flags & ML_DONTPEGTOP) + { + height = (f_ceilingheight - b_ceilingheight); + rowoffs = (side->rowoffset >> 16) + height; + } + else + { + height = (f_ceilingheight - b_ceilingheight); + rowoffs = (height + 127 & -128) + (side->rowoffset >> 16); + } + + if (li->flags & ML_BLENDING) + { + if (!(li->flags & ML_BLENDFULLTOP)) + { + if (f_floorheight < f_ceilingheight) + { + height2 = ((height << 16) / (f_ceilingheight - f_floorheight)); + } + else + { + height2 = 0; + } + + tmp_lowcolor = (((((r2 - r1) * height2) >> 16) + r1) << 24) | + (((((g2 - g1) * height2) >> 16) + g1) << 16) | + (((((b2 - b1) * height2) >> 16) + b1) << 8) | 0xff; + } + + if (li->flags & ML_INVERSEBLEND) + { + bottomcolor = tmp_upcolor; + topcolor = tmp_lowcolor; + } + else + { + topcolor = tmp_upcolor; + bottomcolor = tmp_lowcolor; + } + + // clip middle color upper + upcolor = tmp_lowcolor; + } + + R_RenderWall(seg, li->flags, textures[side->toptexture], + f_ceilingheight, b_ceilingheight, + rowoffs - height, rowoffs, + topcolor, bottomcolor); + + m_top = b_ceilingheight; // clip middle top height + if ((li->flags & (ML_CHECKFLOORHEIGHT|ML_SWITCHX08)) == ML_SWITCHX08) + { + if (SWITCHMASK(li->flags) == ML_SWITCHX04) + { + pic = side->bottomtexture; + rowoffs = side->rowoffset >> 16; + } + else + { + pic = side->midtexture; + rowoffs = side->rowoffset >> 16; + } + + R_RenderSwitch(seg, pic, b_ceilingheight + rowoffs + 48, thingcolor); + } + } + + if (frontsector->floorheight < backsector->floorheight) + { + height = (f_ceilingheight - b_floorheight); + + if ((li->flags & ML_DONTPEGBOTTOM) == 0) + { + rowoffs = side->rowoffset >> 16; + } + else + { + rowoffs = height + (side->rowoffset >> 16); + } + + if (li->flags & ML_BLENDING) + { + if (!(li->flags & ML_BLENDFULLBOTTOM)) + { + if (f_floorheight < f_ceilingheight) + { + height2 = ((height << 16) / (f_ceilingheight - f_floorheight)); + } + else + { + height2 = 0; + } + + tmp_upcolor = (((((r2 - r1) * height2) >> 16) + r1) << 24) | + (((((g2 - g1) * height2) >> 16) + g1) << 16) | + (((((b2 - b1) * height2) >> 16) + b1) << 8) | 0xff; + } + + topcolor = tmp_upcolor; + bottomcolor = lowcolor; + + // clip middle color lower + lowcolor = tmp_upcolor; + } + + R_RenderWall(seg, li->flags, textures[side->bottomtexture], + b_floorheight, f_floorheight, + rowoffs, rowoffs + (b_floorheight - f_floorheight), + topcolor, bottomcolor); + + m_bottom = b_floorheight; // clip middle bottom height + if ((li->flags & (ML_CHECKFLOORHEIGHT|ML_SWITCHX08)) == ML_CHECKFLOORHEIGHT) + { + if (SWITCHMASK(li->flags) == ML_SWITCHX02) + { + pic = side->toptexture; + rowoffs = side->rowoffset >> 16; + } + else + { + pic = side->midtexture; + rowoffs = side->rowoffset >> 16; + } + + R_RenderSwitch(seg, pic, b_floorheight + rowoffs - 16, thingcolor); + } + } + + if (!(li->flags & ML_DRAWMASKED)) + { + return; + } + } + + if (li->flags & ML_DONTPEGBOTTOM) + { + height = m_top - m_bottom; + rowoffs = (height + 127 & -128) + (side->rowoffset >> 16); + } + else if (li->flags & ML_DONTPEGTOP) + { + rowoffs = (side->rowoffset >> 16) - m_bottom; + height = m_top - m_bottom; + } + else + { + height = m_top - m_bottom; + rowoffs = (side->rowoffset >> 16) + height; + } + + if (li->flags & ML_BLENDING) + { + topcolor = upcolor; + bottomcolor = lowcolor; + } + + R_RenderWall(seg, li->flags, textures[side->midtexture], + m_top, m_bottom, + rowoffs - height, rowoffs, + topcolor, bottomcolor); + + if ((li->flags & (ML_CHECKFLOORHEIGHT|ML_SWITCHX08)) == (ML_CHECKFLOORHEIGHT|ML_SWITCHX08)) + { + if (SWITCHMASK(li->flags) == ML_SWITCHX02) + { + pic = side->toptexture; + rowoffs = side->rowoffset >> 16; + } + else + { + pic = side->bottomtexture; + rowoffs = side->rowoffset >> 16; + } + + R_RenderSwitch(seg, pic, m_bottom + rowoffs + 48, thingcolor); + } +} + +void R_RenderWall(seg_t *seg, int flags, int texture, int topHeight, int bottomHeight, + int topOffset, int bottomOffset, int topColor, int bottomColor) // 80027138 +{ + byte *data; + byte *src; + vertex_t *v1; + vertex_t *v2; + int cms, cmt; + int wshift, hshift; + + if (texture != 16) + { + if (flags & ML_HMIRROR) { + cms = G_TX_MIRROR; + } + else { + cms = G_TX_NOMIRROR; + } + + if (flags & ML_VMIRROR) { + cmt = G_TX_MIRROR; + } + else { + cmt = G_TX_NOMIRROR; + } + + if ((texture != globallump) || (globalcm != (cms | cmt))) + { + /* + In Doom 64 all textures are compressed with the second method (dec_d64), + in the original line it was declared that if a texture was not stored, + it would be stored from the DOOM64.WAD and decompressed with the Jaguar Doom + method (dec_jag) which is wrong since all the textures are previously + loaded from the P_Init function with the second decompression method (dec_d64) + */ + //data = W_CacheLumpNum(texture >> 4, PU_CACHE, dec_jag); // error decomp mode + data = W_CacheLumpNum(texture >> 4, PU_CACHE, dec_d64); /* [GEC] FIXED */ + + wshift = ((textureN64_t*)data)->wshift; + hshift = ((textureN64_t*)data)->hshift; + + src = data + sizeof(textureN64_t); + + // Load Image Data + gDPSetTextureImage(GFX1++, G_IM_FMT_CI, G_IM_SIZ_16b , 1, src); + gDPSetTile(GFX1++, G_IM_FMT_CI, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0); + + gDPLoadSync(GFX1++); + gDPLoadBlock(GFX1++, G_TX_LOADTILE, 0, 0, + (((1 << wshift) * (1 << hshift)) >> 2) - 1, 0); + + gDPPipeSync(GFX1++); + gDPSetTile(GFX1++, G_IM_FMT_CI, G_IM_SIZ_4b, + (((1 << wshift) >> 1) + 7) >> 3, 0, G_TX_RENDERTILE, 0, + cmt, hshift, 0, + cms, wshift, 0); + + gDPSetTileSize(GFX1++, G_TX_RENDERTILE, 0, 0, + ((1 << wshift) - 1) << 2, + ((1 << hshift) - 1) << 2); + + // Load Palette Data + gDPSetTextureImage(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_16b , 1, + src + (1 << ((wshift + hshift + 31) & 31)) + ((texture & 15) << 5)); + + gDPTileSync(GFX1++); + gDPSetTile(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_4b, 0, 256, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0); + + gDPLoadSync(GFX1++); + gDPLoadTLUTCmd(GFX1++, G_TX_LOADTILE, 15); + + gDPPipeSync(GFX1++); + + globallump = texture; + globalcm = (cms | cmt); + } + + gSPTexture(GFX1++, (1024 << 6)-1, (1024 << 6)-1, 0, G_TX_RENDERTILE, G_ON); + + gSPVertex(GFX1++, VTX1, 4, 0); + gSP1Quadrangle(GFX1++, 0, 1, 2, 3, 1); + + v1 = seg->v1; + v2 = seg->v2; + + // x coordinates + VTX1[0].v.ob[0] = VTX1[3].v.ob[0] = (signed short)(v1->x >> 16); + VTX1[1].v.ob[0] = VTX1[2].v.ob[0] = (signed short)(v2->x >> 16); + + // y coordinates + VTX1[0].v.ob[1] = VTX1[1].v.ob[1] = topHeight; + VTX1[3].v.ob[1] = VTX1[2].v.ob[1] = bottomHeight; + + // z coordinates + VTX1[0].v.ob[2] = VTX1[3].v.ob[2] = (signed short)-(v1->y >> 16); + VTX1[1].v.ob[2] = VTX1[2].v.ob[2] = (signed short)-(v2->y >> 16); + + // texture s coordinates + VTX1[0].v.tc[0] = VTX1[3].v.tc[0] = ((seg->sidedef->textureoffset + seg->offset) >> 11); + VTX1[1].v.tc[0] = VTX1[2].v.tc[0] = VTX1[0].v.tc[0] + (seg->length << 1); + + // texture t coordinates + VTX1[0].v.tc[1] = VTX1[1].v.tc[1] = (topOffset << 5); + VTX1[2].v.tc[1] = VTX1[3].v.tc[1] = (bottomOffset << 5); + + // vertex color + *(int*)VTX1[0].v.cn = *(int*)VTX1[1].v.cn = topColor; + *(int*)VTX1[2].v.cn = *(int*)VTX1[3].v.cn = bottomColor; + + VTX1 += 4; + } +} + +void R_RenderSwitch(seg_t *seg, int texture, int topOffset, int color) // 80027654 +{ + byte *data; + byte *src; + vertex_t *v1; + vertex_t *v2; + fixed_t x, y; + fixed_t sin, cos; + int wshift, hshift; + + if (texture != globallump) + { + /* + In Doom 64 all textures are compressed with the second method (dec_d64), + in the original line it was declared that if a texture was not stored, + it would be stored from the DOOM64.WAD and decompressed with the Jaguar Doom + method (dec_jag) which is wrong since all the textures are previously + loaded from the P_Init function with the second decompression method (dec_d64) + */ + //data = W_CacheLumpNum(firsttex + texture, PU_CACHE, dec_jag); // error decomp mode + data = W_CacheLumpNum(firsttex + texture, PU_CACHE, dec_d64); /* [GEC] FIXED */ + + wshift = ((textureN64_t*)data)->wshift; + hshift = ((textureN64_t*)data)->hshift; + + src = data + sizeof(textureN64_t); + + // Load Image Data + gDPSetTextureImage(GFX1++, G_IM_FMT_CI, G_IM_SIZ_16b , 1, src); + gDPSetTile(GFX1++, G_IM_FMT_CI, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0); + + gDPLoadSync(GFX1++); + gDPLoadBlock(GFX1++, G_TX_LOADTILE, 0, 0, + (((1 << wshift) * (1 << hshift)) >> 2) - 1, 0); + + gDPPipeSync(GFX1++); + gDPSetTile(GFX1++, G_IM_FMT_CI, G_IM_SIZ_4b, + (((1 << wshift) >> 1) + 7) >> 3, 0, G_TX_RENDERTILE, 0, + 0, 0, 0, + 0, 0, 0); + + gDPSetTileSize(GFX1++, G_TX_RENDERTILE, 0, 0, + ((1 << wshift) - 1) << 2, + ((1 << hshift) - 1) << 2); + + // Load Palette Data + gDPSetTextureImage(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_16b , 1, + src + (1 << ((wshift + hshift + 31) & 31))); + + gDPTileSync(GFX1++); + gDPSetTile(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_4b, 0, 256, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0); + + gDPLoadSync(GFX1++); + gDPLoadTLUTCmd(GFX1++, G_TX_LOADTILE, 15); + + gDPPipeSync(GFX1++); + + globallump = texture; + } + + gSPTexture(GFX1++, (512 << 6), (512 << 6), 0, 0, 1); + + gSPVertex(GFX1++, VTX1, 4, 0); + gSP1Quadrangle(GFX1++, 0, 1, 2, 3, 1); + + v1 = seg->linedef->v1; + v2 = seg->linedef->v2; + + x = (v1->x + v2->x); + if (x < 0) {x = x + 1;} + + y = (v1->y + v2->y); + if (y < 0) {y = y + 1;} + + x >>= 1; + y >>= 1; + + cos = finecosine[seg->angle >> ANGLETOFINESHIFT] << 1; + sin = finesine [seg->angle >> ANGLETOFINESHIFT] << 1; + + // x coordinates + VTX1[0].v.ob[0] = VTX1[3].v.ob[0] = ((x) - (cos << 3) + sin) >> 16; + VTX1[1].v.ob[0] = VTX1[2].v.ob[0] = ((x) + (cos << 3) + sin) >> 16; + + // y coordinates + VTX1[0].v.ob[1] = VTX1[1].v.ob[1] = topOffset; + VTX1[3].v.ob[1] = VTX1[2].v.ob[1] = topOffset - 32; + + // z coordinates + VTX1[0].v.ob[2] = VTX1[3].v.ob[2] = ((-y) + (sin << 3) + cos) >> 16; + VTX1[1].v.ob[2] = VTX1[2].v.ob[2] = ((-y) - (sin << 3) + cos) >> 16; + + // texture s coordinates + VTX1[0].v.tc[0] = VTX1[3].v.tc[0] = (0 << 6); + VTX1[1].v.tc[0] = VTX1[2].v.tc[0] = (32 << 6); + + // texture t coordinates + VTX1[0].v.tc[1] = VTX1[1].v.tc[1] = (0 << 6); + VTX1[2].v.tc[1] = VTX1[3].v.tc[1] = (32 << 6); + + // vertex color + *(int*)VTX1[0].v.cn = *(int*)VTX1[1].v.cn = *(int*)VTX1[2].v.cn = *(int*)VTX1[3].v.cn = color; + + VTX1 += 4; +} + +void R_RenderPlane(leaf_t *leaf, int numverts, int zpos, int texture, int xpos, int ypos, int color) // 80027B68 +{ + byte *data; + byte *src; + vertex_t *vrt; + fixed_t x; + fixed_t y; + int idx, i; + int v00, v01, v02; + + if (texture != globallump) + { + /* + In Doom 64 all textures are compressed with the second method (dec_d64), + in the original line it was declared that if a texture was not stored, + it would be stored from the DOOM64.WAD and decompressed with the Jaguar Doom + method (dec_jag) which is wrong since all the textures are previously + loaded from the P_Init function with the second decompression method (dec_d64) + */ + //data = W_CacheLumpNum(texture >> 4, PU_CACHE, dec_jag); // error decomp mode + data = W_CacheLumpNum(texture >> 4, PU_CACHE, dec_d64); /* [GEC] FIXED */ + + src = data + sizeof(textureN64_t); + + // Load Image Data + gDPSetTextureImage(GFX1++, G_IM_FMT_CI, G_IM_SIZ_16b , 1, src); + gDPSetTile(GFX1++, G_IM_FMT_CI, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0); + + gDPLoadSync(GFX1++); + gDPLoadBlock(GFX1++, G_TX_LOADTILE, 0, 0, + (((1 << 6) * (1 << 6)) >> 2) - 1, 0); + + gDPPipeSync(GFX1++); + gDPSetTile(GFX1++, G_IM_FMT_CI, G_IM_SIZ_4b, + (((1 << 6) >> 1) + 7) >> 3, 0, G_TX_RENDERTILE, 0, + 0, 6, 0, + 0, 6, 0); + + gDPSetTileSize(GFX1++, G_TX_RENDERTILE, 0, 0, + ((1 << 6) - 1) << 2, + ((1 << 6) - 1) << 2); + + // Load Palette Data + gDPSetTextureImage(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_16b , 1, + src + (1 << (6 + 6 - 1)) + ((texture & 15) << 5)); + + gDPTileSync(GFX1++); + gDPSetTile(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_4b, 0, 256, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0); + + gDPLoadSync(GFX1++); + gDPLoadTLUTCmd(GFX1++, G_TX_LOADTILE, 15); + + gDPPipeSync(GFX1++); + + globallump = texture; + } + + vrt = leaf->vertex; + VTX1[0].v.ob[0] = (vrt->x >> 16); + VTX1[0].v.ob[1] = zpos; + VTX1[0].v.ob[2] =-(vrt->y >> 16); + VTX1[0].v.tc[0] = (((vrt->x + xpos & 0x3f0000U) >> 16) << 5); + VTX1[0].v.tc[1] =-(((vrt->y + ypos & 0x3f0000U) >> 16) << 5); + *(int *)VTX1[0].v.cn = color; + + x = ((vrt->x + xpos) >> 16) & -64; + y = ((vrt->y + ypos) >> 16) & -64; + + gSPTexture(GFX1++, (1024 << 6)-1, (1024 << 6)-1, 0, G_TX_RENDERTILE, G_ON); + + if (numverts >= 32) + numverts = 32; + + gSPVertex(GFX1++, VTX1, numverts, 0); + VTX1++; + + if (numverts & 1) + { + idx = 2; + gSP1Triangle(GFX1++, 0, 1, 2, 0); + } + else + { + idx = 1; + } + + leaf++; + numverts--; + + if (idx < numverts) + { + v00 = idx + 0; + v01 = idx + 1; + v02 = idx + 2; + do + { + gSP2Triangles(GFX1++, + v00, v01, v02, 0, // 0, 1, 2 + v00, v02, 0, 0); // 0, 2, 0 + + v00 += 2; + v01 += 2; + v02 += 2; + } while (v02 < (numverts + 2)); + } + + /*i = 0; + if (numverts > 0) + { + if ((numverts & 3)) + { + while(i != (numverts & 3)) + { + vrt = leaf->vertex; + VTX1[0].v.ob[0] = (vrt->x >> 16); + VTX1[0].v.ob[1] = zpos; + VTX1[0].v.ob[2] =-(vrt->y >> 16); + VTX1[0].v.tc[0] = ((((vrt->x + xpos) >> 16) - x) << 5); + VTX1[0].v.tc[1] =-((((vrt->y + ypos) >> 16) - y) << 5); + *(int *)VTX1[0].v.cn = color; + VTX1++; + leaf++; + i++; + } + } + + while(i != numverts) + { + vrt = leaf->vertex; + VTX1[0].v.ob[0] = (vrt->x >> 16); + VTX1[0].v.ob[1] = zpos; + VTX1[0].v.ob[2] =-(vrt->y >> 16); + VTX1[0].v.tc[0] = ((((vrt->x + xpos) >> 16) - x) << 5); + VTX1[0].v.tc[1] =-((((vrt->y + ypos) >> 16) - y) << 5); + *(int *)VTX1[0].v.cn = color; + VTX1++; + leaf++; + + vrt = leaf->vertex; + VTX1[0].v.ob[0] = (vrt->x >> 16); + VTX1[0].v.ob[1] = zpos; + VTX1[0].v.ob[2] =-(vrt->y >> 16); + VTX1[0].v.tc[0] = ((((vrt->x + xpos) >> 16) - x) << 5); + VTX1[0].v.tc[1] =-((((vrt->y + ypos) >> 16) - y) << 5); + *(int *)VTX1[0].v.cn = color; + VTX1++; + leaf++; + + vrt = leaf->vertex; + VTX1[0].v.ob[0] = (vrt->x >> 16); + VTX1[0].v.ob[1] = zpos; + VTX1[0].v.ob[2] =-(vrt->y >> 16); + VTX1[0].v.tc[0] = ((((vrt->x + xpos) >> 16) - x) << 5); + VTX1[0].v.tc[1] =-((((vrt->y + ypos) >> 16) - y) << 5); + *(int *)VTX1[0].v.cn = color; + VTX1++; + leaf++; + + vrt = leaf->vertex; + VTX1[0].v.ob[0] = (vrt->x >> 16); + VTX1[0].v.ob[1] = zpos; + VTX1[0].v.ob[2] =-(vrt->y >> 16); + VTX1[0].v.tc[0] = ((((vrt->x + xpos) >> 16) - x) << 5); + VTX1[0].v.tc[1] =-((((vrt->y + ypos) >> 16) - y) << 5); + *(int *)VTX1[0].v.cn = color; + VTX1++; + leaf++; + + i += 4; + } + }*/ + + for(i = 0; i < numverts; i++) + { + vrt = leaf->vertex; + VTX1[0].v.ob[0] = (vrt->x >> 16); + VTX1[0].v.ob[1] = zpos; + VTX1[0].v.ob[2] =-(vrt->y >> 16); + VTX1[0].v.tc[0] = ((((vrt->x + xpos) >> 16) - x) << 5); + VTX1[0].v.tc[1] =-((((vrt->y + ypos) >> 16) - y) << 5); + *(int *)VTX1[0].v.cn = color; + VTX1++; + leaf++; + } +} + +void R_RenderThings(subsector_t *sub) // 80028248 +{ + byte *data; + byte *src; + byte *paldata; + vissprite_t *vissprite_p; + + mobj_t *thing; + boolean flip; + int lump; + + int compressed; + int tileh; + int tilew; + int height; + int width; + int tiles; + int color; + + fixed_t xx, yy; + int xpos1, xpos2; + int ypos; + int zpos1, zpos2; + int spos, tpos; + int v00, v01, v02, v03; + + vissprite_p = sub->vissprite; + if (vissprite_p) + { + gDPPipeSync(GFX1++); + + if (vissprite_p->thing->flags & MF_RENDERLASER) + { + gDPSetRenderMode(GFX1++, G_RM_FOG_SHADE_A, G_RM_RA_OPA_SURF2); + gDPSetCombineMode(GFX1++, G_CC_D64COMB15, G_CC_D64COMB16); + + do + { + I_CheckGFX(); + R_RenderLaser(vissprite_p->thing); + + vissprite_p = vissprite_p->next; + if(vissprite_p == NULL) { + break; + } + + } while(vissprite_p->thing->flags & MF_RENDERLASER); + + gDPPipeSync(GFX1++); + gDPSetCombineMode(GFX1++, G_CC_D64COMB07, G_CC_D64COMB08); + + if (vissprite_p == NULL) + { + gDPSetRenderMode(GFX1++, G_RM_FOG_SHADE_A, G_RM_TEX_EDGE2); + return; + } + } + + gDPSetRenderMode(GFX1++, G_RM_FOG_SHADE_A, G_RM_XLU_SURF2_CLAMP); + + while (vissprite_p) + { + I_CheckGFX(); + + thing = vissprite_p->thing; + lump = vissprite_p->lump; + flip = vissprite_p->flip; + + if (thing->frame & FF_FULLBRIGHT) + { + color = PACKRGBA(255, 255, 255, 255);//0xffffffff; + } + else + { + color = lights[vissprite_p->sector->colors[2]].rgba; + } + + gDPSetPrimColorD64(GFX1++, 0, vissprite_p->sector->lightlevel, thing->alpha); + + data = W_CacheLumpNum(lump, PU_CACHE, dec_jag); + + compressed = ((spriteN64_t*)data)->compressed; + tileh = ((spriteN64_t*)data)->tileheight; + width = ((spriteN64_t*)data)->width; + height = ((spriteN64_t*)data)->height; + tiles = ((spriteN64_t*)data)->tiles << 1; + + spos = width; + tpos = 0; + + src = data + sizeof(spriteN64_t); + + if (flip) + { + xx = thing->x + (((spriteN64_t*)data)->xoffs * viewsin); + xpos1 = (xx - (width * viewsin)) >> 16; + xpos2 = (xx) >> 16; + + yy = thing->y - (((spriteN64_t*)data)->xoffs * viewcos); + zpos1 = -(yy + (width * viewcos)) >> 16; + zpos2 = -(yy) >> 16; + } + else + { + xx = thing->x - (((spriteN64_t*)data)->xoffs * viewsin); + xpos2 = (xx + (width * viewsin)) >> 16; + xpos1 = (xx) >> 16; + + yy = thing->y + (((spriteN64_t*)data)->xoffs * viewcos); + zpos2 = -(yy - (width * viewcos)) >> 16; + zpos1 = -(yy) >> 16; + } + + gSPTexture(GFX1++, (512 << 6), (512 << 6), 0, 0, 1); + + gSPVertex(GFX1++, VTX1, (tiles+2), 0); + + if (compressed < 0) + { + width = ((spriteN64_t*)data)->width + 7 & ~7; + tilew = tileh * width; + + if (((spriteN64_t*)data)->cmpsize & 1) + { + paldata = W_CacheLumpNum((lump - (((spriteN64_t*)data)->cmpsize >> 1)) + + thing->info->palette, PU_CACHE, dec_jag) + 8; + } + else + { + paldata = (src + ((spriteN64_t*)data)->cmpsize); + } + + // Load Palette Data (256 colors) + gDPSetTextureImage(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_16b , 1, paldata); + + gDPTileSync(GFX1++); + gDPSetTile(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_4b, 0, 256, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0); + + gDPLoadSync(GFX1++); + gDPLoadTLUTCmd(GFX1++, G_TX_LOADTILE, 255); + + gDPPipeSync(GFX1++); + } + else + { + width = ((spriteN64_t*)data)->width + 15 & ~15; + tilew = tileh * width; + + if (tilew < 0) { + tilew = tilew + 1; + } + + tilew >>= 1; + + // Load Palette Data (16 colors) + gDPSetTextureImage(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_16b , 1, (src + ((spriteN64_t*)data)->cmpsize)); + + gDPTileSync(GFX1++); + gDPSetTile(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_4b, 0, 256, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0); + + gDPLoadSync(GFX1++); + gDPLoadTLUTCmd(GFX1++, G_TX_LOADTILE, 15); + + gDPPipeSync(GFX1++); + } + + ypos = (thing->z >> 16) + ((spriteN64_t*)data)->yoffs; + + VTX1[0].v.ob[0] = xpos1; + VTX1[0].v.ob[1] = ypos; + VTX1[0].v.ob[2] = zpos1; + + VTX1[1].v.ob[0] = xpos2; + VTX1[1].v.ob[1] = ypos; + VTX1[1].v.ob[2] = zpos2; + + VTX1[flip].v.tc[0] = 0; + VTX1[flip^1].v.tc[0] = (spos << 6); + + VTX1[0].v.tc[1] = VTX1[1].v.tc[1] = (tpos << 6); + + *(int *)VTX1[0].v.cn = *(int *)VTX1[1].v.cn = color; + VTX1 += 2; + + v03 = 0; + v00 = 1; + v01 = 3; + v02 = 2; + + if (tiles > 0) + { + do + { + if (compressed < 0) + { + // Load Image Data (8bit) + gDPSetTextureImage(GFX1++, G_IM_FMT_CI, G_IM_SIZ_16b , 1, src); + gDPSetTile(GFX1++, G_IM_FMT_CI, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0); + + gDPLoadSync(GFX1++); + gDPLoadBlock(GFX1++, G_TX_LOADTILE, 0, 0, (tilew >> 1) - 1, 0); + + gDPPipeSync(GFX1++); + gDPSetTile(GFX1++, G_IM_FMT_CI, G_IM_SIZ_8b, (width >> 3), 0, + G_TX_RENDERTILE , 0, 0, 0, 0, 0, 0, 0); + + gDPSetTileSize(GFX1++, G_TX_RENDERTILE, 0, tpos << 2, ((width - 1) << 2), (tpos + tileh - 1) << 2); + } + else + { + // Load Image Data (4bit) + gDPSetTextureImage(GFX1++, G_IM_FMT_CI, G_IM_SIZ_16b , 1, src); + gDPSetTile(GFX1++, G_IM_FMT_CI, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0); + + gDPLoadSync(GFX1++); + gDPLoadBlock(GFX1++, G_TX_LOADTILE, 0, 0, (tilew >> 1) - 1, 0); + + gDPPipeSync(GFX1++); + gDPSetTile(GFX1++, G_IM_FMT_CI, G_IM_SIZ_4b, (width >> 4), 0, + G_TX_RENDERTILE , 0, 0, 0, 0, 0, 0, 0); + + gDPSetTileSize(GFX1++, G_TX_RENDERTILE, 0, tpos << 2, ((width - 1) << 2), (tpos + tileh - 1) << 2); + } + + tpos += tileh; + ypos -= tileh; + + gSP2Triangles(GFX1++, v00, v01, v02, 0, // 1, 3, 2 + v00, v02, v03, 0); // 1, 2, 0 + + VTX1[0].v.ob[0] = xpos1; + VTX1[0].v.ob[1] = ypos; + VTX1[0].v.ob[2] = zpos1; + + VTX1[1].v.ob[0] = xpos2; + VTX1[1].v.ob[1] = ypos; + VTX1[1].v.ob[2] = zpos2; + + VTX1[flip].v.tc[0] = 0; + VTX1[flip^1].v.tc[0] = (spos << 6); + + VTX1[0].v.tc[1] = VTX1[1].v.tc[1] = (tpos << 6); + + *(int *)VTX1[0].v.cn = *(int *)VTX1[1].v.cn = color; + VTX1 += 2; + + src += tilew; + + height -= tileh; + if (height < tileh) { + tileh = height; + } + + v00 += 2; + v01 += 2; + v02 += 2; + v03 += 2; + } while (v02 < (tiles+2)); + } + + vissprite_p = vissprite_p->next; + } + + globallump = -1; + + gDPPipeSync(GFX1++); + gDPSetRenderMode(GFX1++, G_RM_FOG_SHADE_A, G_RM_TEX_EDGE2); + } +} + +void R_RenderLaser(mobj_t *thing) // 80028CCC +{ + laserdata_t *laserdata; + + laserdata = (laserdata_t *)thing->extradata; + + gSPVertex(GFX1++, (VTX1), 6, 0); + + gSP2Triangles(GFX1++, 0, 2, 3, 1/*flag1*/, + 0, 1, 2, 2/*flag2*/); + + gSP2Triangles(GFX1++, 0, 3, 5, 2/*flag1*/, + 3, 4, 5, 2/*flag2*/); + + VTX1[0].v.ob[0] = (laserdata->x1 >> 16); + VTX1[0].v.ob[1] = (laserdata->z1 >> 16); + VTX1[0].v.ob[2] = -(laserdata->y1 >> 16); + + VTX1[1].v.ob[0] = ((laserdata->x1 - laserdata->slopey) >> 16); + VTX1[1].v.ob[1] = (laserdata->z1 >> 16); + VTX1[1].v.ob[2] = (-(laserdata->y1 + laserdata->slopex) >> 16); + + VTX1[2].v.ob[0] = ((laserdata->x2 - laserdata->slopey) >> 16); + VTX1[2].v.ob[1] = (laserdata->z2 >> 16); + VTX1[2].v.ob[2] = (-(laserdata->y2 + laserdata->slopex) >> 16); + + VTX1[3].v.ob[0] = (laserdata->x2 >> 16); + VTX1[3].v.ob[1] = (laserdata->z2 >> 16); + VTX1[3].v.ob[2] = -(laserdata->y2 >> 16); + + VTX1[4].v.ob[0] = ((laserdata->x2 + laserdata->slopey) >> 16); + VTX1[4].v.ob[1] = (laserdata->z2 >> 16); + VTX1[4].v.ob[2] = (-(laserdata->y2 - laserdata->slopex) >> 16); + + VTX1[5].v.ob[0] = ((laserdata->x1 + laserdata->slopey) >> 16); + VTX1[5].v.ob[1] = (laserdata->z1 >> 16); + VTX1[5].v.ob[2] = (-(laserdata->y1 - laserdata->slopex) >> 16); + + *(int *)VTX1[0].v.cn = PACKRGBA(255,0,0,255); // 0xff0000ff; + *(int *)VTX1[1].v.cn = PACKRGBA(0,0,0,255); // 0xff; + *(int *)VTX1[2].v.cn = PACKRGBA(0,0,0,255); // 0xff; + *(int *)VTX1[3].v.cn = PACKRGBA(255,0,0,255); // 0xff0000ff; + *(int *)VTX1[4].v.cn = PACKRGBA(0,0,0,255); // 0xff; + *(int *)VTX1[5].v.cn = PACKRGBA(0,0,0,255); // 0xff; + + VTX1 += 6; +} + +void R_RenderPSprites(void) // 80028f20 +{ + int i; + pspdef_t *psp, *psptmp; + state_t *state; + spritedef_t *sprdef; + spriteframe_t *sprframe; + int lump; + int flagtranslucent; + + boolean palloaded; + byte *data; + byte *paldata; + byte *src; + + int tilecnt; + int tiles; + int tileh; + int tilew; + int width; + int height; + int width2; + int yh; + int x, y; + + I_CheckGFX(); + + gDPPipeSync(GFX1++); + gDPSetTexturePersp(GFX1++, G_TP_NONE); + gDPSetCombineMode(GFX1++, G_CC_D64COMB17, G_CC_D64COMB18); + + psp = &viewplayer->psprites[0]; + + flagtranslucent = (viewplayer->mo->flags & MF_SHADOW) != 0; + + psptmp = psp; + for (i = 0; i < NUMPSPRITES; i++, psptmp++) + { + if(flagtranslucent || ((psptmp->state != 0) && (psptmp->alpha < 255))) + { + gDPSetRenderMode(GFX1++, G_RM_FOG_SHADE_A, G_RM_XLU_SURF2_CLAMP); + break; + } + } + + palloaded = false; + + for (i = 0; i < NUMPSPRITES; i++, psp++) + { + if ((state = psp->state) != 0) /* a null state means not active */ + { + sprdef = &sprites[state->sprite]; + sprframe = &sprdef->spriteframes[state->frame & FF_FRAMEMASK]; + lump = sprframe->lump[0]; + + data = W_CacheLumpNum(lump, PU_CACHE, dec_jag); + + tilecnt = 0; + tiles = ((spriteN64_t*)data)->tiles; + width = ((spriteN64_t*)data)->width; + tileh = ((spriteN64_t*)data)->tileheight; + width2 = width + 7 & ~7; + tilew = tileh * width2; + height = ((spriteN64_t*)data)->height; + src = data + sizeof(spriteN64_t); + + x = (((psp->sx >> 16) - ((spriteN64_t*)data)->xoffs) + 160) << 2; + y = (((psp->sy >> 16) - ((spriteN64_t*)data)->yoffs) + 239) << 2; + if (viewplayer->onground) + { + x += (quakeviewx >> 20); + y += (quakeviewy >> 14); + } + + if (psp->state->frame & FF_FULLBRIGHT) + { + gDPSetPrimColorD64(GFX1, 0, 0, PACKRGBA(255,255,255,0));//0xffffff00 + } + else + { + gDPSetPrimColorD64(GFX1, 0, frontsector->lightlevel, + lights[frontsector->colors[2]].rgba & ~255); // remove alpha value + } + + // apply alpha value + if (flagtranslucent) + { + GFX1->words.w1 |= 144; + } + else + { + GFX1->words.w1 |= psp->alpha; + } + GFX1++; // continue to next GFX1 + + if (!palloaded) + { + palloaded = true; + + if (((spriteN64_t*)data)->cmpsize & 1) + { + /* Loads the palette from the first frame of the animation, */ + /* which uses an odd number to get to the lump */ + paldata = W_CacheLumpNum((lump - (((spriteN64_t*)data)->cmpsize >> 1)), + PU_CACHE, dec_jag); + + paldata += (((spriteN64_t*)paldata)->cmpsize + sizeof(spriteN64_t)); + } + else + { + /* Loads the palette if it is included in the image data */ + paldata = (src + ((spriteN64_t*)data)->cmpsize); + } + + /* Load Palette Data (256 colors) */ + gDPSetTextureImage(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_16b , 1, paldata); + + gDPTileSync(GFX1++); + gDPSetTile(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_4b, 0, 256, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0); + + gDPLoadSync(GFX1++); + gDPLoadTLUTCmd(GFX1++, G_TX_LOADTILE, 255); + + gDPPipeSync(GFX1++); + } + + if (tiles > 0) + { + do + { + /* Load Image Data (8bit) */ + gDPSetTextureImage(GFX1++, G_IM_FMT_CI, G_IM_SIZ_16b , 1, src); + gDPSetTile(GFX1++, G_IM_FMT_CI, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0); + + gDPLoadSync(GFX1++); + gDPLoadBlock(GFX1++, G_TX_LOADTILE, 0, 0, ((width2 * tileh + 1) >> 1) - 1, 0); + + gDPPipeSync(GFX1++); + gDPSetTile(GFX1++, G_IM_FMT_CI, G_IM_SIZ_8b, ((width2 + 7) >> 3), 0, + G_TX_RENDERTILE , 0, 0, 0, 0, 0, 0, 0); + + gDPSetTileSize(GFX1++, G_TX_RENDERTILE, 0, 0, ((width2 - 1) << 2), (tileh - 1) << 2); + + yh = (tileh << 2) + y; + + gSPTextureRectangle(GFX1++, + x, y, + (width << 2) + x, yh, + 0, + 0, 0, + (1 << 10), (1 << 10)); + + height -= tileh; + if (height < tileh) { + tileh = height; + } + + y = yh; + + src += tilew; + tilecnt += 1; + } while (tilecnt != (int)tiles); + } + } + } +} diff --git a/Doom 64/regdef.h b/Doom 64/regdef.h @@ -0,0 +1,187 @@ +/************************************************************************ + Copyright (C) 1998,1999 NINTENDO Co,Ltd, + Copyright (C) 1998,1999 MONEGI CORPORATION, + All Rights Reserved +This program is a trade secret of NINTENDO Co,Ltd and MONEGI Corp. +and it is not to be reproduced, published, disclosed to others, copied, +adapted, distributed, or displayed without the prior authorization of +NINTENDO Co,Ltd. and MONEGI Corp. Licensee agrees to attach or embed +this Notice on all copies of the program, including partial copies or +modified versions thereof. +*************************************************************************/ +/************************************************************************ + $Date: 1999/07/06 13:21:13 $ + $Revision: 1.1 $ + $Author: doseki $ +************************************************************************/ + +#ifndef __REGDEF_H__ +#define __REGDEF_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef mips + +#if (_MIPS_SIM == _MIPS_SIM_ABI32) +#define zero $0 +#define AT $at +#define v0 $2 +#define v1 $3 +#define a0 $4 +#define a1 $5 +#define a2 $6 +#define a3 $7 +#define t0 $8 +#define t1 $9 +#define t2 $10 +#define t3 $11 +#define t4 $12 +#define ta0 $12 +#define t5 $13 +#define ta1 $13 +#define t6 $14 +#define ta2 $14 +#define t7 $15 +#define ta3 $15 +#define s0 $16 +#define s1 $17 +#define s2 $18 +#define s3 $19 +#define s4 $20 +#define s5 $21 +#define s6 $22 +#define s7 $23 +#define t8 $24 +#define t9 $25 +#define jp $25 +#define k0 $26 +#define k1 $27 +#define gp $28 +#define sp $29 +#define fp $30 +#define s8 $30 +#define ra $31 +#endif + +#if (_MIPS_SIM == _MIPS_SIM_ABI64) +#define zero $0 +#define AT $at +#define v0 $2 +#define v1 $3 +#define a0 $4 +#define a1 $5 +#define a2 $6 +#define a3 $7 +#define a4 $8 +#define ta0 $8 +#define a5 $9 +#define ta1 $9 +#define a6 $10 +#define ta2 $10 +#define a7 $11 +#define ta3 $11 +#define t0 $12 +#define t1 $13 +#define t2 $14 +#define t3 $15 +#define s0 $16 +#define s1 $17 +#define s2 $18 +#define s3 $19 +#define s4 $20 +#define s5 $21 +#define s6 $22 +#define s7 $23 +#define t8 $24 +#define t9 $25 +#define jp $25 +#define k0 $26 +#define k1 $27 +#define gp $28 +#define sp $29 +#define fp $30 +#define s8 $30 +#define ra $31 +#endif + +#if (_MIPS_SIM == _MIPS_SIM_ABI32) +#define fv0 $f0 +#define fv0f $f1 +#define fv1 $f2 +#define fv1f $f3 +#define fa0 $f12 +#define fa0f $f13 +#define fa1 $f14 +#define fa1f $f15 +#define ft0 $f4 +#define ft0f $f5 +#define ft1 $f6 +#define ft1f $f7 +#define ft2 $f8 +#define ft2f $f9 +#define ft3 $f10 +#define ft3f $f11 +#define ft4 $f16 +#define ft4f $f17 +#define ft5 $f18 +#define ft5f $f19 +#define fs0 $f20 +#define fs0f $f21 +#define fs1 $f22 +#define fs1f $f23 +#define fs2 $f24 +#define fs2f $f25 +#define fs3 $f26 +#define fs3f $f27 +#define fs4 $f28 +#define fs4f $f29 +#define fs5 $f30 +#define fs5f $f31 +#endif + +#if (_MIPS_SIM == _MIPS_SIM_ABI64) +#define fv0 $f0 +#define fv1 $f2 +#define fa0 $f12 +#define fa1 $f13 +#define fa2 $f14 +#define fa3 $f15 +#define fa4 $f16 +#define fa5 $f17 +#define fa6 $f18 +#define fa7 $f19 +#define ft0 $f4 +#define ft1 $f5 +#define ft2 $f6 +#define ft3 $f7 +#define ft4 $f8 +#define ft5 $f9 +#define ft6 $f10 +#define ft7 $f11 +#define ft8 $f20 +#define ft9 $f21 +#define ft10 $f22 +#define ft11 $f23 +#define ft12 $f1 +#define ft13 $f3 +#define fs0 $f24 +#define fs1 $f25 +#define fs2 $f26 +#define fs3 $f27 +#define fs4 $f28 +#define fs5 $f29 +#define fs6 $f30 +#define fs7 $f31 +#endif + +#define fcr31 $31 + +#endif /* mips */ + +#ifdef __cplusplus +} +#endif + +#endif /* !__REGDEF_H__ */ diff --git a/Doom 64/s_sound.c b/Doom 64/s_sound.c @@ -0,0 +1,281 @@ +/* s_sound.c */ +#include "doomdef.h" +#include "p_local.h" +#include "r_local.h" + +#define AUDIO_HEAP_SIZE (0x44800) +extern u64 audio_heap[AUDIO_HEAP_SIZE / sizeof(u64)];//80325800 + +extern char _doom64_wmdSegmentRomStart[], _doom64_wmdSegmentRomEnd[]; +extern char _doom64_wsdSegmentRomStart[], _doom64_wsdSegmentRomEnd[]; +extern char _doom64_wddSegmentRomStart[], _doom64_wddSegmentRomEnd[]; + +#define SYS_FRAMES_PER_SEC 30 + +void S_Error_Callback_Routine(char *errstring, int errnum1, int errnum2) // 80029580 +{ + I_Error(errstring, errnum1, errnum2); +} + +extern int SfxVolume; +extern int MusVolume; + +extern void wess_set_tweaks2(WessTweakAttr *attr); +extern void wess_get_tweaks2(WessTweakAttr *attr); + +void S_Init(void) // 80029590 +{ + int audioHeapEnd; + int wmdlength; + int loaded; + int modulesize; + int seqsize, seqtblsize; + char *moduleptr; + char *seqptr, *seqtblptr; + u32 old_ovmemptr; + void *tempram; + + WessTweakAttr tweak; + WessConfig wess_config; + ALHeap sys_aheap; + + //PRINTF_D(WHITE, "S_Init: Start"); + + alHeapInit(&sys_aheap, (u8 *)audio_heap, AUDIO_HEAP_SIZE); + + //PRINTF_D(WHITE, "base %x", (int)&sys_aheap.base); + //PRINTF_D(WHITE, "cur %x", (int)&sys_aheap.cur); + //PRINTF_D(WHITE, "len %d", sys_aheap.len); + //PRINTF_D(WHITE, "count %d", sys_aheap.count); + + wess_set_error_callback(S_Error_Callback_Routine); + + /* tweak audio */ + wess_get_tweaks(&tweak); + + tweak.mask = TWEAK_DMA_BUFFERS | TWEAK_DMA_MESSAGES | TWEAK_DMA_BUFFER_LENGTH; + tweak.dma_buffers = 40; + tweak.dma_messages = 56; + tweak.dma_buffer_length = 0x600; + wess_set_tweaks(&tweak); + + /* init audio */ + wess_config.heap_ptr = &sys_aheap; + wess_config.outputsamplerate = 22050; + wess_config.maxACMDSize = 1024 * 3; + wess_config.wdd_location = _doom64_wddSegmentRomStart; + wess_config.reverb_id = WESS_REVERB_BIGROOM; + wess_config.revtbl_ptr = 0; + wess_config.audioframerate = (f32)SYS_FRAMES_PER_SEC; + + wess_init(&wess_config); + + //PRINTF_D(WHITE, "heap_ptr %x", (int)&wess_config.heap_ptr); + //PRINTF_D(WHITE, "outputsamplerate %d", wess_config.outputsamplerate); + //PRINTF_D(WHITE, "maxACMDSize %d", wess_config.maxACMDSize); + //PRINTF_D(WHITE, "wdd_location %x", (int)&wess_config.wdd_location); + //PRINTF_D(WHITE, "reverb_id %d", wess_config.reverb_id); + //PRINTF_D(WHITE, "revtbl_ptr %d", wess_config.revtbl_ptr); + //PRINTF_D(WHITE, "audioframerate %f", (f32)wess_config.audioframerate); + + // now we load the .wmd image into a temporary ram space + modulesize = wess_size_module(_doom64_wmdSegmentRomStart); + modulesize = (modulesize + 15 & ~15); + moduleptr = alHeapAlloc(&sys_aheap, 1, modulesize); + //PRINTF_D(WHITE, "modulesize %d", modulesize); + //PRINTF_D(WHITE, "moduleptr %x", (int)&moduleptr); + + loaded = wess_load_module(_doom64_wmdSegmentRomStart, moduleptr, modulesize); + //PRINTF_D(WHITE, "loaded %d", loaded); + + + seqtblsize = wess_seq_loader_sizeof(wess_get_master_status(), _doom64_wsdSegmentRomStart); + seqtblsize = (seqtblsize + 15 & ~15); + seqtblptr = alHeapAlloc(&sys_aheap, 1, seqtblsize); + //PRINTF_D(WHITE, "seqtblsize %d", seqtblsize); + //PRINTF_D(WHITE, "seqtblptr %x", (int)&seqtblptr); + + //this call may result in decompression callbacks + wess_seq_loader_init(wess_get_master_status(), _doom64_wsdSegmentRomStart, NoOpenSeqHandle, seqtblptr, seqtblsize); + + seqsize = wess_seq_range_sizeof(0, wess_seq_loader_count()); + seqtblsize = (seqsize + 15 & ~15); + seqptr = alHeapAlloc(&sys_aheap, 1, seqsize); + + //PRINTF_D(WHITE, "seqsize %d", seqsize); + //PRINTF_D(WHITE, "seqptr %x", (int)&seqptr); + + //this call may result in decompression callbacks + wess_seq_range_load(0, wess_seq_loader_count(), seqptr); + + audioHeapEnd = (int)alHeapAlloc(&sys_aheap, 1, 4) - (int)&audio_heap; + audioHeapEnd += 16; + + //PRINTF_D(WHITE, "audioHeapEnd %x", audioHeapEnd); + + if (audioHeapEnd > AUDIO_HEAP_SIZE) + I_Error("S_Init: Audio heap overflow"); + + S_SetSoundVolume(SfxVolume); + S_SetMusicVolume(MusVolume); + + //PRINTF_D(WHITE, "S_Init: End"); + + //while(1){} +} + +void S_SetSoundVolume(int volume) // 800297A8 +{ + wess_master_sfx_vol_set((char)((volume * 85) / 100)); +} + +void S_SetMusicVolume(int volume) // 800297F4 +{ + wess_master_mus_vol_set((char)((volume * 110) / 100)); +} + +int music_sequence; // 8005b250 + +void S_StartMusic(int mus_seq) // 8002983C +{ + if (disabledrawing == false) + { + wess_seq_trigger(mus_seq); + music_sequence = mus_seq; + } +} + +void S_StopMusic(void) // 80029878 +{ + wess_seq_stop(music_sequence); + music_sequence = 0; +} + +void S_PauseSound(void) // 800298A4 +{ + wess_seq_pauseall(YesMute, (REMEMBER_MUSIC|REMEMBER_SNDFX)); +} + +void S_ResumeSound(void) // 800298C8 +{ + wess_seq_restartall(YesVoiceRestart); +} + +void S_StopSound(mobj_t *origin,int seqnum) // 800298E8 +{ + if (!origin) + wess_seq_stop(seqnum); + else + wess_seq_stoptype((int)origin); +} + +void S_StopAll(void) // 8002991C +{ + wess_seq_stopall(); +} + +#define SND_INACTIVE 0 +#define SND_PLAYING 1 + +int S_SoundStatus(int seqnum) // 8002993C +{ + if (wess_seq_status(seqnum) == SEQUENCE_PLAYING) + return SND_PLAYING; + else + return SND_INACTIVE; +} + +void S_StartSound(mobj_t *origin, int sound_id) // 80029970 +{ + int flags; + int vol; + int pan; + TriggerPlayAttr attr; + + if (disabledrawing == false) + { + if (origin && (origin != cameratarget)) + { + if (!S_AdjustSoundParams(cameratarget, origin, &vol, &pan)) + { + return; + } + } + else + { + vol = 127; + pan = 64; + } + + attr.mask = (TRIGGER_VOLUME | TRIGGER_PAN | TRIGGER_REVERB); + attr.volume = (char)vol; + attr.pan = (char)pan; + + attr.reverb = 0; + + if (origin) + { + flags = origin->subsector->sector->flags; + + if (flags & MS_REVERB) { + attr.reverb = 16; + } + else if (flags & MS_REVERBHEAVY) { + attr.reverb = 32; + } + } + + wess_seq_trigger_type_special(sound_id, (unsigned long)origin, &attr); + } +} + +#define S_CLIPPING_DIST (1700) +#define S_MAX_DIST (127 * S_CLIPPING_DIST) +#define S_CLOSE_DIST (200) +#define S_ATTENUATOR (S_CLIPPING_DIST - S_CLOSE_DIST) +#define S_STEREO_SWING (96) + +int S_AdjustSoundParams(mobj_t *listener, mobj_t *origin, int* vol, int* pan) // 80029A48 +{ + fixed_t approx_dist; + angle_t angle; + + approx_dist = P_AproxDistance(listener->x - origin->x, listener->y - origin->y); + approx_dist >>= FRACBITS; + + if (approx_dist > S_CLIPPING_DIST) { + return 0; + } + + if (listener->x != origin->x || listener->y != origin->y) + { + /* angle of source to listener */ + angle = R_PointToAngle2(listener->x, listener->y, origin->x, origin->y); + + if (angle <= listener->angle) { + angle += 0xffffffff; + } + angle -= listener->angle; + + /* stereo separation */ + *pan = (128 - ((finesine[angle >> ANGLETOFINESHIFT] * S_STEREO_SWING) >> FRACBITS)) >> 1; + } + else + { + *pan = 64; + } + + /* volume calculation */ + if (approx_dist < S_CLOSE_DIST) + { + *vol = 127; + } + else + { + /* distance effect */ + approx_dist = -approx_dist; /* set neg */ + *vol = (((approx_dist << 7) - approx_dist) + S_MAX_DIST) / S_ATTENUATOR; + } + + return (*vol > 0); +} diff --git a/Doom 64/seqload.c b/Doom 64/seqload.c @@ -0,0 +1,490 @@ + +#define _ALIGN4_ 1 +#define _ALIGN8_ 1 + +/* WESS API INCLUDES */ +#include "wessapi.h" // audio stuff... +#include "seqload.h" +#include "soundhw.h" +#include "wessarc.h" +#include "wessseq.h" + +#include "funqueue.h" + +#include "graph.h"//debug + +#ifndef NOUSEWESSCODE + +module_header sfile_hdr; //800b6a60 +master_status_structure *ref_pm_stat; //800B6A80 +char *loaderfile; //800B6A84 +int ref_max_seq_num; //800B6A88 +int opencount; //800B6A8C +int(*Error_func)(int, int); //800B6A90 +int Error_module; //800B6A94 +Wess_File_IO_Struct *fp_seq_file; //800B6A98 +int seq_loader_offset; //800B6A9C +int seq_loader_enable; //800B6AA0 + + +static void err(int code) // 800396C0 +{ + if (Error_func) { + Error_func(Error_module, code); + } +} + +void wess_seq_loader_install_error_handler(int(*error_func)(int, int), int module) // 800396F8 +{ + Error_func = error_func; + Error_module = module; +} + +int wess_seq_loader_count(void) // 8003970C +{ + return ref_max_seq_num; +} + +int Is_Seq_Seq_Num_Valid(int seqnum) // 8003971C() +{ + if (seqnum >= 0) + { + if(ref_max_seq_num <= seqnum) + return 0; + + return 1; + } + return 0; +} + +int open_sequence_data(void) // 80039748 +{ + if (opencount == 0) + { + fp_seq_file = module_open(loaderfile); + if (!fp_seq_file) + { + err(SEQLOAD_FOPEN); + return 0; + } + } + opencount += 1; + return 1; +} + +void close_sequence_data(void) // 800397B8 +{ + if (opencount == 1) + { + module_close(fp_seq_file); + } + if (opencount > 0) + { + opencount -= 1; + } + return; +} + +int load_sequence_data(int seqnum, void *memptr) // 8003980C +{ + sequence_data *psq_info; + track_data *ptrk_info; + int seqload; + int seqread; + int seqseek; + int seekpos; + int numtracks, tracknum, readbytes, decomp_type; + char *pmem; + char *dmem;//data memory + + //char *dat; + //int j; + + pmem = (char *)memptr; + + if (seq_loader_enable) + { + if (!Is_Seq_Seq_Num_Valid(seqnum)) + return 0; + + //printf("\nseqnum %d\n", seqnum); + + psq_info = (ref_pm_stat->pmod_info->pseq_info + seqnum); /* pointer math */ + + numtracks = psq_info->seq_hdr.tracks; + //PRINTF_D(WHITE,"numtracks %d\n", numtracks); + + if (wess_driver_max_trks_per_seq < numtracks) + return 0; + + psq_info->ptrk_info = (track_data *)pmem; + pmem += (numtracks * sizeof(track_data)); + +#if _ALIGN8_ == 1 + //force align to word boundary because previous size adjust + //may wind up with odd address + pmem += (unsigned int)pmem & 1; + pmem += (unsigned int)pmem & 2; + pmem += (unsigned int)pmem & 4; +#endif + dmem = pmem; + pmem += (unsigned int)psq_info->seq_hdr.trkinfolength; + + //printf("trkinfolength %d\n", psq_info->seq_hdr.trkinfolength); + //getch(); + + // Read data + seekpos = psq_info->seq_hdr.fileposition + seq_loader_offset; + decomp_type = psq_info->seq_hdr.decomp_type; + readbytes = psq_info->seq_hdr.trkinfolength; + + //PRINTF_D(WHITE,"seekpos %d",seekpos); + //PRINTF_D(WHITE,"readbytes %d",readbytes); + + if (decomp_type == 0) + { + seqload = open_sequence_data(); + if (!seqload) + { + err(SEQLOAD_FOPEN); + return (0); + } + + seqseek = module_seek(fp_seq_file, seekpos, 0); + if (seqseek) + { + err(SEQLOAD_FSEEK); + return (0); + } + + seqread = module_read(dmem, readbytes, fp_seq_file); + + if (seqread != readbytes) + { + err(SEQLOAD_FREAD); + return (0); + } + + close_sequence_data(); + } + else + { + if (wess_decomp(decomp_type, loaderfile, seekpos, dmem, readbytes) < 0) + return(0); + } + + tracknum = 0; + if (numtracks > 0) + { + if (numtracks & 3) + { + //printf("numtracks & 3 %d\n", (numtracks & 3)); + do + { + ptrk_info = (psq_info->ptrk_info + tracknum); + + ptrk_info->trk_hdr = (track_header *)dmem; + dmem += sizeof(track_header); + + //PRINTF_D2(WHITE,0,20,"labellist_count %d", ptrk_info->trk_hdr->labellist_count); + //PRINTF_D2(WHITE,0,21,"data_size %d", ptrk_info->trk_hdr->data_size); + //WAIT(); + + ptrk_info->plabellist = (unsigned long *)dmem; + dmem += (ptrk_info->trk_hdr->labellist_count * sizeof(long)); + + ptrk_info->ptrk_data = (char *)dmem; + dmem += (ptrk_info->trk_hdr->data_size); + + tracknum++; + } while ((numtracks & 3) != tracknum); + } + + if (tracknum != numtracks) + { + do + { + ptrk_info = (psq_info->ptrk_info + tracknum); + + //------------ + ptrk_info->trk_hdr = (track_header *)dmem; + dmem += sizeof(track_header); + + //printf("[0] labellist_count %d\n", ptrk_info->trk_hdr->labellist_count); + //printf("[0] data_size %d\n", ptrk_info->trk_hdr->data_size); + + ptrk_info->plabellist = (unsigned long *)dmem; + dmem += (ptrk_info->trk_hdr->labellist_count * sizeof(long)); + + ptrk_info->ptrk_data = (char *)dmem; + dmem += (ptrk_info->trk_hdr->data_size); + + //------------ + (ptrk_info + 1)->trk_hdr = (track_header *)dmem; + dmem += sizeof(track_header); + + //printf("[1] labellist_count %d\n", (ptrk_info + 1)->trk_hdr->labellist_count); + //printf("[1] data_size %d\n", (ptrk_info + 1)->trk_hdr->data_size); + + (ptrk_info + 1)->plabellist = (unsigned long *)dmem; + dmem += ((ptrk_info + 1)->trk_hdr->labellist_count * sizeof(long)); + + (ptrk_info + 1)->ptrk_data = (char *)dmem; + dmem += ((ptrk_info + 1)->trk_hdr->data_size); + + //------------ + (ptrk_info + 2)->trk_hdr = (track_header *)dmem; + dmem += sizeof(track_header); + + + //printf("[2] labellist_count %d\n", (ptrk_info + 2)->trk_hdr->labellist_count); + //printf("[2] data_size %d\n", (ptrk_info + 2)->trk_hdr->data_size); + + (ptrk_info + 2)->plabellist = (unsigned long *)dmem; + dmem += ((ptrk_info + 2)->trk_hdr->labellist_count * sizeof(long)); + + (ptrk_info + 2)->ptrk_data = (char *)dmem; + dmem += ((ptrk_info + 2)->trk_hdr->data_size); + + //------------ + (ptrk_info + 3)->trk_hdr = (track_header *)dmem; + dmem += sizeof(track_header); + + //printf("[3] labellist_count %d\n", (ptrk_info + 3)->trk_hdr->labellist_count); + //printf("[3] data_size %d\n", (ptrk_info + 3)->trk_hdr->data_size); + + (ptrk_info + 3)->plabellist = (unsigned long *)dmem; + dmem += ((ptrk_info + 3)->trk_hdr->labellist_count * sizeof(long)); + + (ptrk_info + 3)->ptrk_data = (char *)dmem; + dmem += ((ptrk_info + 3)->trk_hdr->data_size); + + tracknum += 4; + } while (tracknum != numtracks); + } + } + } + + return (int)((char *)pmem - (char *)memptr);//(int)(void *)((int)pmem - (int)memptr); +} + +int wess_seq_loader_sizeof(void *input_pm_stat, char *seqfile) // 80039C20 +{ + int size, seqload, seqseek, seqread, readbytes; + + loaderfile = seqfile; + ref_pm_stat = (master_status_structure *)input_pm_stat; + + size = 0; + if (ref_pm_stat != NULL) + { + seqload = open_sequence_data(); + if (!seqload) + { + err(SEQLOAD_FOPEN); + return (0); + } + + //printf("seqload %d\n",seqload); + //printf("opencount %d\n",opencount); + + seqseek = module_seek(fp_seq_file, 0, 0); + if (seqseek) + { + err(SEQLOAD_FSEEK); + return (0); + } + + readbytes = sizeof(module_header); + seqread = module_read(&sfile_hdr, sizeof(module_header), fp_seq_file); + if (seqread != readbytes) + { + err(SEQLOAD_FREAD); + return (0); + } + + close_sequence_data(); + + //printf("module_id_text %x\n",sfile_hdr.module_id_text); + //printf("module_version %d\n",sfile_hdr.module_version); + //printf("sequences %d\n",sfile_hdr.sequences); + //printf("compress_size %d\n",sfile_hdr.compress_size); + //printf("data_size %d\n",sfile_hdr.data_size); + + size = sfile_hdr.data_size; + } + + return size; +} + +int wess_seq_loader_init(void *input_pm_stat, char *seqfile, enum OpenSeqHandleFlag flag, char *memory_pointer, int memory_allowance) // 80039CE4 +{ + int seqload; + int seqread; + int seqseek; + int readbytes; + int size; + int decomp_type; + + seq_loader_enable = 0; + + loaderfile = seqfile; + ref_pm_stat = (master_status_structure *)input_pm_stat; + + size = 0; + if (ref_pm_stat != NULL) + { + seqload = open_sequence_data(); + if (!seqload) + { + err(SEQLOAD_FOPEN); + return (0); + } + + seqseek = module_seek(fp_seq_file, 0, 0); + if (seqseek) + { + err(SEQLOAD_FSEEK); + return (0); + } + + readbytes = sizeof(module_header); + seqread = module_read(&sfile_hdr, sizeof(module_header), fp_seq_file); + if (seqread != readbytes) + { + err(SEQLOAD_FREAD); + return (0); + } + + //PRINTF_D(WHITE,"WSD::module_id_text %x",sfile_hdr.module_id_text); + //PRINTF_D(WHITE,"WSD::module_version %d",sfile_hdr.module_version); + //PRINTF_D(WHITE,"WSD::decomp_type %d",sfile_hdr.decomp_type); + //PRINTF_D(WHITE,"WSD::sequences %d",sfile_hdr.sequences); + //PRINTF_D(WHITE,"WSD::compress_size %d",sfile_hdr.compress_size); + //PRINTF_D(WHITE,"WSD::data_size %d",sfile_hdr.data_size); + + ref_max_seq_num = sfile_hdr.sequences; + ref_pm_stat->pmod_info->pseq_info = (sequence_data *)memory_pointer; + + readbytes = sfile_hdr.data_size; + decomp_type = sfile_hdr.decomp_type; + + if (!decomp_type) + { + //PRINTF_D(WHITE,"WSD::readbytes %d",readbytes); + + seqread = module_read(ref_pm_stat->pmod_info->pseq_info, readbytes, fp_seq_file); + + if (seqread != readbytes) + { + err(SEQLOAD_FREAD); + return (0); + } + seq_loader_offset = sfile_hdr.data_size + sizeof(module_header); + } + else + { + if (wess_decomp(decomp_type, loaderfile, sizeof(module_header), (char*)ref_pm_stat->pmod_info->pseq_info, readbytes) < 0) + return(0); + + seq_loader_offset = sfile_hdr.compress_size + sizeof(module_header); + } + + if (flag != YesOpenSeqHandle) + { + //PRINTF_D(WHITE,"WSD::close_sequence_data"); + close_sequence_data(); + } + + seq_loader_enable = 1; + + size = readbytes; + } + + //PRINTF_D(WHITE,"WSD::seq_loader_offset %d",seq_loader_offset); + //PRINTF_D(WHITE,"WSD::size %d",size); + + return size; +} + +void wess_seq_loader_exit(void) // 80039EA4 +{ + seq_loader_enable = 0; + close_sequence_data(); +} + +int wess_seq_sizeof(int seqnum) // 80039EC8 +{ + sequence_data *psq_info; + int seq_sizeof, numtracks; + + if (seq_loader_enable) + { + if (!Is_Seq_Seq_Num_Valid(seqnum)) + return 0; + + psq_info = ref_pm_stat->pmod_info->pseq_info+seqnum; /* pointer math */ + + //printf("\nseq_hdr.tracks %d\n",psq_info->seq_hdr.tracks); + //printf("seq_hdr.decomp_type %d\n",psq_info->seq_hdr.decomp_type); + //printf("seq_hdr.trkinfolength %d\n",psq_info->seq_hdr.trkinfolength); + //printf("seq_hdr.fileposition %d\n",psq_info->seq_hdr.fileposition); + + numtracks = psq_info->seq_hdr.tracks; + if (wess_driver_max_trks_per_seq < numtracks) + return 0; + + if (psq_info->ptrk_info) + return 0; + + numtracks *= sizeof(sequence_data); + +#if _ALIGN8_ == 1 + numtracks += (unsigned int)numtracks & 1; + numtracks += (unsigned int)numtracks & 2; + numtracks += (unsigned int)numtracks & 4; +#endif + + return (int)(psq_info->seq_hdr.trkinfolength + numtracks); + } + return 0; +} + +int wess_seq_load(int seqnum, void *memptr) // 80039F84 +{ + if (seq_loader_enable) + { + if (!Is_Seq_Seq_Num_Valid(seqnum)) + return 0; + + if (!(ref_pm_stat->pmod_info->pseq_info + seqnum)->ptrk_info) + { + //PRINTF_D(WHITE,"wess_seq_load %d", seqnum); + return load_sequence_data(seqnum, memptr); + } + } + + return 0; +} + +int wess_seq_free(int seqnum) // 8003A010 +{ + sequence_data *psq_info; + + if (seq_loader_enable) + { + if (!Is_Seq_Seq_Num_Valid(seqnum)) + return 0; + + psq_info = ref_pm_stat->pmod_info->pseq_info + seqnum; /* pointer math */ + + if (psq_info->ptrk_info) + { + psq_info->ptrk_info = 0; + return 1; + } + } + return 0; +} + +#endif diff --git a/Doom 64/seqload.h b/Doom 64/seqload.h @@ -0,0 +1,116 @@ + /*------------------------------------------------------------------*/ + /* + The Williams Entertainment Sound System + by Scott Patterson + */ + /*------------------------------------------------------------------*/ + +#ifndef _SEQLOAD_H +#define _SEQLOAD_H + +enum Seq_Load_Error { + + SEQLOAD_NO_ERROR, + SEQLOAD_FOPEN, + SEQLOAD_FREAD, + SEQLOAD_FSEEK +}; + +enum OpenSeqHandleFlag {NoOpenSeqHandle,YesOpenSeqHandle}; + + /* + routine: wess_seq_loader_init() + + - this routine must be called before and seq_loader_routines + - input_pm_stat is returned by wess_get_master_status() + - seqfile is the .wmd filename + - flag specifies if the file handle will be opened during init or + each time file is accessed + */ + +extern int wess_seq_loader_sizeof( void *input_pm_stat, + char *seqfile ); + +extern int wess_seq_loader_init( void *input_pm_stat, + char *seqfile, + enum OpenSeqHandleFlag flag, + char *memory_pointer, + int memory_allowance); + +extern int wess_seq_loader_count( void ); + + /* + routine: wess_seq_loader_exit() + + - closes file handle if not already closed + - disables sequence loading calls + */ + +extern void wess_seq_loader_exit(void); + + /* + routine: wess_seq_loader_install_error_handler() + + - for installing an error callback to notify file access errors + - module is your own ID returned as err_module parameter + - err_enum is the returned Seq_Load_Error enum parameter + */ + +extern void wess_seq_loader_install_error_handler(int (*error_func)(int, int), + int module); + + /* + general loading guidelines: + + - sizeof functions return the amount of bytes needed for data + not already loaded, therefore, when sizeof returns 0, this + means the data referred to is already loaded + + - load functions only load data that is not already loaded + and return the amount of bytes loaded, memory is not allocated + internally, you must use the sizeof functions and allocate + memory yourself + + - free functions mark data as not loaded, memory is not freed + internally, you must free memory yourself + */ + + /* + individual sequence loading + */ + +extern int wess_seq_sizeof(int seqnum); + +extern int wess_seq_load(int seqnum,void *memptr); + +extern int wess_seq_free(int seqnum); + + /* + sequence list loading + + - pass in a list of sequnce numbers to be loaded + - end this list with the END_SEQ_LIST define + */ + +#define END_SEQ_LIST -1 + +extern int wess_seq_list_sizeof(short *seqlist); + +extern int wess_seq_list_load(short *seqlist,void *memptr); + +extern int wess_seq_list_free(short *seqlist); + + /* + sequence range loading + + - specify a number of consecutive sequences to be loaded + */ + +extern int wess_seq_range_sizeof(int seqfirst,int numseqs); + +extern int wess_seq_range_load(int seqfirst,int numseqs,void *memptr); + +extern int wess_seq_range_free(int seqfirst,int numseqs); + +#endif + diff --git a/Doom 64/seqloadl.c b/Doom 64/seqloadl.c @@ -0,0 +1,97 @@ +/* ULTRA64 LIBRARIES */ +#include <ultra64.h> +#include "ultratypes.h" +#include <libaudio.h> + +/* WESS API INCLUDES */ +#include "wessapi.h" // audio stuff... +#include "seqload.h" +#include "soundhw.h" +#include "wessarc.h" +#include "wessseq.h" + +#include "funqueue.h" + +#ifndef NOUSEWESSCODE + +extern module_header sfile_hdr; //800b6a60 +extern master_status_structure *ref_pm_stat; //800B6A80 +extern char *loaderfile; //800B6A84 +extern int ref_max_seq_num; //800B6A88 +extern int opencount; //800B6A8C +extern int(*Error_func)(int, int); //800B6A90 +extern int Error_module; //800B6A94 +extern Wess_File_IO_Struct *fp_seq_file; //800B6A98 +extern int seq_loader_offset; //800B6A9C +extern int seq_loader_enable; //800B6AA0 + +#define END_SEQ_LIST -1 + +int wess_seq_list_sizeof(short *seqlist) // 8003A090 +{ + int seqnum; + int count; + + count = 0; + if (seq_loader_enable) + { + if (*seqlist == END_SEQ_LIST) + return 0; + + do + { + seqnum = *seqlist++; + count += wess_seq_sizeof(seqnum); + } while (seqnum != END_SEQ_LIST); + } + return (count); +} + +int wess_seq_list_load(short *seqlist, void *memptr) // 8003A108 +{ + int seqnum; + int count; + char *pmem; + + pmem = (char *)memptr; + + count = 0; + if (seq_loader_enable) + { + if (!open_sequence_data()) + return 0; + + if (*seqlist != END_SEQ_LIST) + { + do + { + seqnum = *seqlist++; + count += wess_seq_load(seqnum, pmem + count); + } while (seqnum != END_SEQ_LIST); + } + + close_sequence_data(); + } + + return count; +} + +int wess_seq_list_free(short *seqlist) // 8003A1B4 +{ + int seqnum; + if (seq_loader_enable) + { + if (*seqlist != END_SEQ_LIST) + { + do + { + seqnum = *seqlist++; + wess_seq_free(seqnum); + } while (seqnum != END_SEQ_LIST); + } + return 1; + } + return 0; +} + +#endif diff --git a/Doom 64/seqloadr.c b/Doom 64/seqloadr.c @@ -0,0 +1,94 @@ +/* ULTRA64 LIBRARIES */ +#include <ultra64.h> +#include "ultratypes.h" +#include <libaudio.h> + +/* WESS API INCLUDES */ +#include "wessapi.h" // audio stuff... +#include "seqload.h" +#include "soundhw.h" +#include "wessarc.h" +#include "wessseq.h" + +#include "funqueue.h" + +#ifndef NOUSEWESSCODE + +extern module_header sfile_hdr; //800b6a60 +extern master_status_structure *ref_pm_stat; //800B6A80 +extern char *loaderfile; //800B6A84 +extern int ref_max_seq_num; //800B6A88 +extern int opencount; //800B6A8C +extern int(*Error_func)(int, int); //800B6A90 +extern int Error_module; //800B6A94 +extern Wess_File_IO_Struct *fp_seq_file; //800B6A98 +extern int seq_loader_offset; //800B6A9C +extern int seq_loader_enable; //800B6AA0 + +int wess_seq_range_sizeof(int seqfirst, int numseqs) // 8003A230 +{ + int count; + + count = 0; + if (seq_loader_enable) + { + if (numseqs == 0) + return 0; + + while (numseqs--) + { + count += wess_seq_sizeof(seqfirst); + seqfirst++; + //printf("numseqs %d || seqfirst %d || count %d\n",numseqs, seqfirst, count); + } + } + return (count); +} + +int wess_seq_range_load(int seqfirst, int numseqs, void *memptr) // 8003A2AC +{ + int count; + char *pmem; + + pmem = (char *)memptr; + + count = 0; + if (seq_loader_enable) + { + if (!open_sequence_data()) + return 0; + + if (!numseqs) + return 0; + + while (numseqs--) + { + count += wess_seq_load(seqfirst, pmem + count); + seqfirst += 1; + } + + close_sequence_data(); + } + + return count; +} + +int wess_seq_range_free(int seqfirst, int numseqs) // 8003A35C +{ + if (seq_loader_enable) + { + if (numseqs == 0) + return 0; + + while (numseqs--) + { + wess_seq_free(seqfirst); + seqfirst++; + } + + return 1; + } + return 0; +} + +#endif diff --git a/Doom 64/soundhw.h b/Doom 64/soundhw.h @@ -0,0 +1,22 @@ + /*------------------------------------------------------------------*/ + /* + The Williams Entertainment Sound System + by Scott Patterson + */ + /*------------------------------------------------------------------*/ + +#ifndef _SOUNDHW_H +#define _SOUNDHW_H + +enum DriverIds {NoSound_ID,N64_ID,GENERIC_ID=50}; + +enum SoundHardwareTags { + SNDHW_TAG_END, + SNDHW_TAG_DRIVER_ID, + SNDHW_TAG_SOUND_EFFECTS, + SNDHW_TAG_MUSIC, + SNDHW_TAG_DRUMS, + SNDHW_TAG_MAX +}; + +#endif +\ No newline at end of file diff --git a/Doom 64/sounds.h b/Doom 64/sounds.h @@ -0,0 +1,135 @@ +#ifndef __SOUNDSH__ +#define __SOUNDSH__ + +/* + * Identifiers for all sfx in game. + */ + +typedef enum +{ + sfx_None, + sfx_punch, //punch + sfx_spawn, //spawn + sfx_explode, //explode + sfx_implod, //impact + sfx_pistol, //pistol + sfx_shotgun, //shotgun + sfx_plasma, //plasma + sfx_bfg, //bfg + sfx_sawup, //sawup + sfx_sawidle, //sawidle + sfx_saw1, //saw1 + sfx_saw2, //saw2 + sfx_missile, //missile + sfx_bfgexp, //bfgexplode + sfx_pstart, //platup + sfx_pstop, //platdown + sfx_doorup, //doorup + sfx_doordown, //doordown + sfx_secmove, //secmove + sfx_switch1, //switch1 + sfx_switch2, //switch2 + sfx_itemup, //itemup + sfx_sgcock, //sgcock + sfx_oof, //oof + sfx_telept, //teleport + sfx_noway, //oof2?? + sfx_sht2fire, //shot2fire + sfx_sht2load1, //shot2load1 + sfx_sht2load2, //shot2load2 + sfx_plrpain, //playerpain + sfx_plrdie, //playerdie + sfx_slop, //slop + sfx_possit1, //posssit1 + sfx_possit2, //posssit2 + sfx_possit3, //posssit3 + sfx_posdie1, //possdie1 + sfx_posdie2, //possdie2 + sfx_posdie3, //possdie3 + sfx_posact, //possact + sfx_dbpain1, //pain1 + sfx_dbpain2, //pain2 + sfx_dbact, //monsteract + sfx_scratch, //scratch + sfx_impsit1, //impsit1 + sfx_impsit2, //impsit2 + sfx_impdth1, //impdeath1 + sfx_impdth2, //impdeath2 + sfx_impact, //impact + sfx_sargsit, //sargsit + sfx_sargatk, //sargatk + sfx_sargdie, //sargdie + sfx_bos1sit, //boss1sit + sfx_bos1die, //boss1die + sfx_headsit, //headsit + sfx_headdie, //headdie + sfx_skullatk, //skullatk + sfx_bos2sit, //boss2sit + sfx_bos2die, //boss2die + sfx_pesit, //painsit + sfx_pepain, //painhit + sfx_pedie, //paindie + sfx_bspisit, //bspisit + sfx_bspidie, //bspidie + sfx_bspilift, //bspilift + sfx_bspistomp, //bspistomp + sfx_fattatk, //fattatk + sfx_fattsit, //fattsit + sfx_fatthit, //fatthit + sfx_fattdie, //fattdie + sfx_bdmissile, //projectile + sfx_skelact, //revenantact?? + sfx_tracer, //tracer + sfx_dart, //dart + sfx_dartshoot, //revenantpunch?? + sfx_cybsit, //cybsit + sfx_cybdth, //cybdeath + sfx_cybhoof, //hoof + sfx_metal, //metal + sfx_door2up, //door2up + sfx_door2dwn, //door2down + sfx_powerup, //powerup + sfx_laser, //laser + sfx_electric, //electric (loop) + sfx_thndrlow, //thunderlow + sfx_thndrhigh, //thunderhigh + sfx_quake, //quake (loop) + sfx_darthit, //darthit + sfx_rectact, //rectact + sfx_rectatk, //rectatk + sfx_rectdie, //rectdie + sfx_rectpain, //rectpain + sfx_rectsit, //rectsit + NUMSFX +} sfxenum_t; + +typedef enum +{ + mus_amb01 = 93, //NUMSFX + mus_amb02, + mus_amb03, + mus_amb04, + mus_amb05, + mus_amb06, + mus_amb07, + mus_amb08, + mus_amb09, + mus_amb10, + mus_amb11, + mus_amb12, + mus_amb13, + mus_amb14, + mus_amb15, + mus_amb16, + mus_amb17, + mus_amb18, + mus_amb19, + mus_amb20, + mus_final, + mus_complete, + mus_intro, + mus_title, + NUMMUS +} musenum_t; +#endif + diff --git a/Doom 64/sprinfo.c b/Doom 64/sprinfo.c @@ -0,0 +1,660 @@ +/* sprinfo.c -- generated by sprgen */ + +#include "doomdef.h" +#include "r_local.h" + +spriteframe_t spriteframes[] = { // 80054358 +{1, {398,405,412,419,426,419,412,405}, {0,0,0,0,0,1,1,1}}, +{1, {399,406,413,420,427,420,413,406}, {0,0,0,0,0,1,1,1}}, +{1, {400,407,414,421,428,421,414,407}, {0,0,0,0,0,1,1,1}}, +{1, {401,408,415,422,429,422,415,408}, {0,0,0,0,0,1,1,1}}, +{1, {402,409,416,423,430,423,416,409}, {0,0,0,0,0,1,1,1}}, +{1, {403,410,417,424,431,424,417,410}, {0,0,0,0,0,1,1,1}}, +{1, {404,411,418,425,432,425,418,411}, {0,0,0,0,0,1,1,1}}, +{0, {433,433,433,433,433,433,433,433}, {0,0,0,0,0,0,0,0}}, +{0, {434,434,434,434,434,434,434,434}, {0,0,0,0,0,0,0,0}}, +{0, {435,435,435,435,435,435,435,435}, {0,0,0,0,0,0,0,0}}, +{0, {436,436,436,436,436,436,436,436}, {0,0,0,0,0,0,0,0}}, +{0, {437,437,437,437,437,437,437,437}, {0,0,0,0,0,0,0,0}}, +{0, {438,438,438,438,438,438,438,438}, {0,0,0,0,0,0,0,0}}, +{0, {439,439,439,439,439,439,439,439}, {0,0,0,0,0,0,0,0}}, +{0, {440,440,440,440,440,440,440,440}, {0,0,0,0,0,0,0,0}}, +{0, {441,441,441,441,441,441,441,441}, {0,0,0,0,0,0,0,0}}, +{0, {442,442,442,442,442,442,442,442}, {0,0,0,0,0,0,0,0}}, +{0, {443,443,443,443,443,443,443,443}, {0,0,0,0,0,0,0,0}}, +{0, {444,444,444,444,444,444,444,444}, {0,0,0,0,0,0,0,0}}, +{0, {445,445,445,445,445,445,445,445}, {0,0,0,0,0,0,0,0}}, +{0, {446,446,446,446,446,446,446,446}, {0,0,0,0,0,0,0,0}}, +{0, {447,447,447,447,447,447,447,447}, {0,0,0,0,0,0,0,0}}, +{1, {349,357,365,373,381,373,365,357}, {0,0,0,0,0,1,1,1}}, +{1, {350,358,366,374,382,374,366,358}, {0,0,0,0,0,1,1,1}}, +{1, {351,359,367,375,383,375,367,359}, {0,0,0,0,0,1,1,1}}, +{1, {352,360,368,376,384,376,368,360}, {0,0,0,0,0,1,1,1}}, +{1, {353,361,369,377,385,377,369,361}, {0,0,0,0,0,1,1,1}}, +{1, {354,362,370,378,386,378,370,362}, {0,0,0,0,0,1,1,1}}, +{1, {355,363,371,379,387,379,371,363}, {0,0,0,0,0,1,1,1}}, +{1, {356,364,372,380,388,380,372,364}, {0,0,0,0,0,1,1,1}}, +{0, {389,389,389,389,389,389,389,389}, {0,0,0,0,0,0,0,0}}, +{0, {390,390,390,390,390,390,390,390}, {0,0,0,0,0,0,0,0}}, +{0, {391,391,391,391,391,391,391,391}, {0,0,0,0,0,0,0,0}}, +{0, {392,392,392,392,392,392,392,392}, {0,0,0,0,0,0,0,0}}, +{0, {393,393,393,393,393,393,393,393}, {0,0,0,0,0,0,0,0}}, +{0, {394,394,394,394,394,394,394,394}, {0,0,0,0,0,0,0,0}}, +{1, {567,576,585,594,603,594,585,576}, {0,0,0,0,0,1,1,1}}, +{1, {568,577,586,595,604,595,586,577}, {0,0,0,0,0,1,1,1}}, +{1, {569,578,587,596,605,596,587,578}, {0,0,0,0,0,1,1,1}}, +{1, {570,579,588,597,606,597,588,579}, {0,0,0,0,0,1,1,1}}, +{1, {571,580,589,598,607,598,589,580}, {0,0,0,0,0,1,1,1}}, +{1, {572,581,590,599,608,599,590,581}, {0,0,0,0,0,1,1,1}}, +{1, {573,582,591,600,609,600,591,582}, {0,0,0,0,0,1,1,1}}, +{1, {574,583,592,601,610,601,592,583}, {0,0,0,0,0,1,1,1}}, +{1, {575,584,593,602,611,602,593,584}, {0,0,0,0,0,1,1,1}}, +{0, {612,612,612,612,612,612,612,612}, {0,0,0,0,0,0,0,0}}, +{0, {613,613,613,613,613,613,613,613}, {0,0,0,0,0,0,0,0}}, +{0, {614,614,614,614,614,614,614,614}, {0,0,0,0,0,0,0,0}}, +{0, {615,615,615,615,615,615,615,615}, {0,0,0,0,0,0,0,0}}, +{0, {616,616,616,616,616,616,616,616}, {0,0,0,0,0,0,0,0}}, +{0, {617,617,617,617,617,617,617,617}, {0,0,0,0,0,0,0,0}}, +{1, {727,734,741,748,755,748,741,734}, {0,0,0,0,0,1,1,1}}, +{1, {728,735,742,749,756,749,742,735}, {0,0,0,0,0,1,1,1}}, +{1, {729,736,743,750,757,750,743,736}, {0,0,0,0,0,1,1,1}}, +{1, {730,737,744,751,758,751,744,737}, {0,0,0,0,0,1,1,1}}, +{1, {731,738,745,752,759,752,745,738}, {0,0,0,0,0,1,1,1}}, +{1, {732,739,746,753,760,753,746,739}, {0,0,0,0,0,1,1,1}}, +{1, {733,740,747,754,761,754,747,740}, {0,0,0,0,0,1,1,1}}, +{0, {762,762,762,762,762,762,762,762}, {0,0,0,0,0,0,0,0}}, +{0, {763,763,763,763,763,763,763,763}, {0,0,0,0,0,0,0,0}}, +{0, {764,764,764,764,764,764,764,764}, {0,0,0,0,0,0,0,0}}, +{0, {765,765,765,765,765,765,765,765}, {0,0,0,0,0,0,0,0}}, +{0, {766,766,766,766,766,766,766,766}, {0,0,0,0,0,0,0,0}}, +{0, {767,767,767,767,767,767,767,767}, {0,0,0,0,0,0,0,0}}, +{0, {768,768,768,768,768,768,768,768}, {0,0,0,0,0,0,0,0}}, +{0, {769,769,769,769,769,769,769,769}, {0,0,0,0,0,0,0,0}}, +{0, {770,770,770,770,770,770,770,770}, {0,0,0,0,0,0,0,0}}, +{0, {771,771,771,771,771,771,771,771}, {0,0,0,0,0,0,0,0}}, +{0, {772,772,772,772,772,772,772,772}, {0,0,0,0,0,0,0,0}}, +{0, {773,773,773,773,773,773,773,773}, {0,0,0,0,0,0,0,0}}, +{0, {774,774,774,774,774,774,774,774}, {0,0,0,0,0,0,0,0}}, +{0, {775,775,775,775,775,775,775,775}, {0,0,0,0,0,0,0,0}}, +{1, {450,461,472,483,494,483,472,461}, {0,0,0,0,0,1,1,1}}, +{1, {451,462,473,484,495,484,473,462}, {0,0,0,0,0,1,1,1}}, +{1, {452,463,474,485,496,485,474,463}, {0,0,0,0,0,1,1,1}}, +{1, {453,464,475,486,497,486,475,464}, {0,0,0,0,0,1,1,1}}, +{1, {454,465,476,487,498,487,476,465}, {0,0,0,0,0,1,1,1}}, +{1, {455,466,477,488,499,488,477,466}, {0,0,0,0,0,1,1,1}}, +{1, {456,467,478,489,500,489,478,467}, {0,0,0,0,0,1,1,1}}, +{1, {457,468,479,490,501,490,479,468}, {0,0,0,0,0,1,1,1}}, +{1, {458,469,480,491,502,491,480,469}, {0,0,0,0,0,1,1,1}}, +{1, {459,470,481,492,503,492,481,470}, {0,0,0,0,0,1,1,1}}, +{1, {460,471,482,493,504,493,482,471}, {0,0,0,0,0,1,1,1}}, +{0, {505,505,505,505,505,505,505,505}, {0,0,0,0,0,0,0,0}}, +{0, {506,506,506,506,506,506,506,506}, {0,0,0,0,0,0,0,0}}, +{0, {507,507,507,507,507,507,507,507}, {0,0,0,0,0,0,0,0}}, +{0, {508,508,508,508,508,508,508,508}, {0,0,0,0,0,0,0,0}}, +{0, {509,509,509,509,509,509,509,509}, {0,0,0,0,0,0,0,0}}, +{0, {510,510,510,510,510,510,510,510}, {0,0,0,0,0,0,0,0}}, +{0, {511,511,511,511,511,511,511,511}, {0,0,0,0,0,0,0,0}}, +{0, {512,512,512,512,512,512,512,512}, {0,0,0,0,0,0,0,0}}, +{0, {513,513,513,513,513,513,513,513}, {0,0,0,0,0,0,0,0}}, +{0, {514,514,514,514,514,514,514,514}, {0,0,0,0,0,0,0,0}}, +{0, {515,515,515,515,515,515,515,515}, {0,0,0,0,0,0,0,0}}, +{0, {516,516,516,516,516,516,516,516}, {0,0,0,0,0,0,0,0}}, +{0, {517,517,517,517,517,517,517,517}, {0,0,0,0,0,0,0,0}}, +{1, {777,784,791,798,805,798,791,784}, {0,0,0,0,0,1,1,1}}, +{1, {778,785,792,799,806,799,792,785}, {0,0,0,0,0,1,1,1}}, +{1, {779,786,793,800,807,800,793,786}, {0,0,0,0,0,1,1,1}}, +{1, {780,787,794,801,808,801,794,787}, {0,0,0,0,0,1,1,1}}, +{1, {781,788,795,802,809,802,795,788}, {0,0,0,0,0,1,1,1}}, +{1, {782,789,796,803,810,803,796,789}, {0,0,0,0,0,1,1,1}}, +{1, {783,790,797,804,811,804,797,790}, {0,0,0,0,0,1,1,1}}, +{0, {812,812,812,812,812,812,812,812}, {0,0,0,0,0,0,0,0}}, +{0, {813,813,813,813,813,813,813,813}, {0,0,0,0,0,0,0,0}}, +{0, {814,814,814,814,814,814,814,814}, {0,0,0,0,0,0,0,0}}, +{0, {815,815,815,815,815,815,815,815}, {0,0,0,0,0,0,0,0}}, +{0, {816,816,816,816,816,816,816,816}, {0,0,0,0,0,0,0,0}}, +{0, {817,817,817,817,817,817,817,817}, {0,0,0,0,0,0,0,0}}, +{1, {520,524,523,522,521,522,523,524}, {0,0,0,0,0,1,1,1}}, +{1, {525,529,528,527,526,527,528,529}, {0,0,0,0,0,1,1,1}}, +{1, {530,534,533,532,531,532,533,534}, {0,0,0,0,0,1,1,1}}, +{1, {535,539,538,537,536,537,538,539}, {0,0,0,0,0,1,1,1}}, +{1, {540,544,543,542,541,542,543,544}, {0,0,0,0,0,1,1,1}}, +{1, {545,549,548,547,546,547,548,549}, {0,0,0,0,0,1,1,1}}, +{1, {550,554,553,552,551,552,553,554}, {0,0,0,0,0,1,1,1}}, +{1, {555,559,558,557,556,557,558,559}, {0,0,0,0,0,1,1,1}}, +{0, {560,560,560,560,560,560,560,560}, {0,0,0,0,0,0,0,0}}, +{0, {561,561,561,561,561,561,561,561}, {0,0,0,0,0,0,0,0}}, +{0, {562,562,562,562,562,562,562,562}, {0,0,0,0,0,0,0,0}}, +{0, {563,563,563,563,563,563,563,563}, {0,0,0,0,0,0,0,0}}, +{0, {564,564,564,564,564,564,564,564}, {0,0,0,0,0,0,0,0}}, +{0, {565,565,565,565,565,565,565,565}, {0,0,0,0,0,0,0,0}}, +{1, {619,625,631,637,643,637,631,625}, {0,0,0,0,0,1,1,1}}, +{1, {620,626,632,638,644,638,632,626}, {0,0,0,0,0,1,1,1}}, +{1, {621,627,633,639,645,639,633,627}, {0,0,0,0,0,1,1,1}}, +{1, {622,628,634,640,646,640,634,628}, {0,0,0,0,0,1,1,1}}, +{1, {623,629,635,641,647,641,635,629}, {0,0,0,0,0,1,1,1}}, +{1, {624,630,636,642,648,642,636,630}, {0,0,0,0,0,1,1,1}}, +{0, {649,649,649,649,649,649,649,649}, {0,0,0,0,0,0,0,0}}, +{0, {650,650,650,650,650,650,650,650}, {0,0,0,0,0,0,0,0}}, +{0, {651,651,651,651,651,651,651,651}, {0,0,0,0,0,0,0,0}}, +{0, {652,652,652,652,652,652,652,652}, {0,0,0,0,0,0,0,0}}, +{0, {653,653,653,653,653,653,653,653}, {0,0,0,0,0,0,0,0}}, +{0, {654,654,654,654,654,654,654,654}, {0,0,0,0,0,0,0,0}}, +{0, {655,655,655,655,655,655,655,655}, {0,0,0,0,0,0,0,0}}, +{0, {656,656,656,656,656,656,656,656}, {0,0,0,0,0,0,0,0}}, +{0, {657,657,657,657,657,657,657,657}, {0,0,0,0,0,0,0,0}}, +{0, {658,658,658,658,658,658,658,658}, {0,0,0,0,0,0,0,0}}, +{1, {689,695,701,707,713,707,701,695}, {0,0,0,0,0,1,1,1}}, +{1, {690,696,702,708,714,708,702,696}, {0,0,0,0,0,1,1,1}}, +{1, {691,697,703,709,715,709,703,697}, {0,0,0,0,0,1,1,1}}, +{1, {692,698,704,710,716,710,704,698}, {0,0,0,0,0,1,1,1}}, +{1, {693,699,705,711,717,711,705,699}, {0,0,0,0,0,1,1,1}}, +{1, {694,700,706,712,718,712,706,700}, {0,0,0,0,0,1,1,1}}, +{0, {719,719,719,719,719,719,719,719}, {0,0,0,0,0,0,0,0}}, +{0, {720,720,720,720,720,720,720,720}, {0,0,0,0,0,0,0,0}}, +{0, {721,721,721,721,721,721,721,721}, {0,0,0,0,0,0,0,0}}, +{0, {722,722,722,722,722,722,722,722}, {0,0,0,0,0,0,0,0}}, +{0, {723,723,723,723,723,723,723,723}, {0,0,0,0,0,0,0,0}}, +{0, {724,724,724,724,724,724,724,724}, {0,0,0,0,0,0,0,0}}, +{1, {819,861,855,849,843,837,831,825}, {0,0,0,0,0,0,0,0}}, +{1, {820,862,856,850,844,838,832,826}, {0,0,0,0,0,0,0,0}}, +{1, {821,863,857,851,845,839,833,827}, {0,0,0,0,0,0,0,0}}, +{1, {822,864,858,852,846,840,834,828}, {0,0,0,0,0,0,0,0}}, +{1, {823,865,859,853,847,841,835,829}, {0,0,0,0,0,0,0,0}}, +{1, {824,866,860,854,848,842,836,830}, {0,0,0,0,0,0,0,0}}, +{0, {867,867,867,867,867,867,867,867}, {0,0,0,0,0,0,0,0}}, +{0, {868,868,868,868,868,868,868,868}, {0,0,0,0,0,0,0,0}}, +{0, {869,869,869,869,869,869,869,869}, {0,0,0,0,0,0,0,0}}, +{0, {870,870,870,870,870,870,870,870}, {0,0,0,0,0,0,0,0}}, +{0, {871,871,871,871,871,871,871,871}, {0,0,0,0,0,0,0,0}}, +{0, {872,872,872,872,872,872,872,872}, {0,0,0,0,0,0,0,0}}, +{0, {873,873,873,873,873,873,873,873}, {0,0,0,0,0,0,0,0}}, +{0, {874,874,874,874,874,874,874,874}, {0,0,0,0,0,0,0,0}}, +{0, {875,875,875,875,875,875,875,875}, {0,0,0,0,0,0,0,0}}, +{1, {660,664,668,672,676,672,668,664}, {0,0,0,0,0,1,1,1}}, +{1, {661,665,669,673,677,673,669,665}, {0,0,0,0,0,1,1,1}}, +{1, {662,666,670,674,678,674,670,666}, {0,0,0,0,0,1,1,1}}, +{1, {663,667,671,675,679,675,671,667}, {0,0,0,0,0,1,1,1}}, +{0, {680,680,680,680,680,680,680,680}, {0,0,0,0,0,0,0,0}}, +{0, {681,681,681,681,681,681,681,681}, {0,0,0,0,0,0,0,0}}, +{0, {682,682,682,682,682,682,682,682}, {0,0,0,0,0,0,0,0}}, +{0, {683,683,683,683,683,683,683,683}, {0,0,0,0,0,0,0,0}}, +{0, {684,684,684,684,684,684,684,684}, {0,0,0,0,0,0,0,0}}, +{0, {685,685,685,685,685,685,685,685}, {0,0,0,0,0,0,0,0}}, +{0, {686,686,686,686,686,686,686,686}, {0,0,0,0,0,0,0,0}}, +{0, {687,687,687,687,687,687,687,687}, {0,0,0,0,0,0,0,0}}, +{1, {877,885,893,901,909,901,893,885}, {0,0,0,0,0,1,1,1}}, +{1, {878,886,894,902,910,902,894,886}, {0,0,0,0,0,1,1,1}}, +{1, {879,887,895,903,911,903,895,887}, {0,0,0,0,0,1,1,1}}, +{1, {880,888,896,904,912,904,896,888}, {0,0,0,0,0,1,1,1}}, +{1, {881,889,897,905,913,905,897,889}, {0,0,0,0,0,1,1,1}}, +{1, {882,890,898,906,914,906,898,890}, {0,0,0,0,0,1,1,1}}, +{1, {883,891,899,907,915,907,899,891}, {0,0,0,0,0,1,1,1}}, +{1, {884,892,900,908,916,908,900,892}, {0,0,0,0,0,1,1,1}}, +{0, {917,917,917,917,917,917,917,917}, {0,0,0,0,0,0,0,0}}, +{0, {918,918,918,918,918,918,918,918}, {0,0,0,0,0,0,0,0}}, +{0, {919,919,919,919,919,919,919,919}, {0,0,0,0,0,0,0,0}}, +{0, {920,920,920,920,920,920,920,920}, {0,0,0,0,0,0,0,0}}, +{0, {921,921,921,921,921,921,921,921}, {0,0,0,0,0,0,0,0}}, +{0, {922,922,922,922,922,922,922,922}, {0,0,0,0,0,0,0,0}}, +{0, {923,923,923,923,923,923,923,923}, {0,0,0,0,0,0,0,0}}, +{1, {211,212,213,214,215,214,213,212}, {0,0,0,0,0,1,1,1}}, +{0, {216,216,216,216,216,216,216,216}, {0,0,0,0,0,0,0,0}}, +{0, {217,217,217,217,217,217,217,217}, {0,0,0,0,0,0,0,0}}, +{0, {218,218,218,218,218,218,218,218}, {0,0,0,0,0,0,0,0}}, +{0, {219,219,219,219,219,219,219,219}, {0,0,0,0,0,0,0,0}}, +{0, {220,220,220,220,220,220,220,220}, {0,0,0,0,0,0,0,0}}, +{0, {323,323,323,323,323,323,323,323}, {0,0,0,0,0,0,0,0}}, +{0, {324,324,324,324,324,324,324,324}, {0,0,0,0,0,0,0,0}}, +{0, {325,325,325,325,325,325,325,325}, {0,0,0,0,0,0,0,0}}, +{0, {326,326,326,326,326,326,326,326}, {0,0,0,0,0,0,0,0}}, +{0, {327,327,327,327,327,327,327,327}, {0,0,0,0,0,0,0,0}}, +{0, {328,328,328,328,328,328,328,328}, {0,0,0,0,0,0,0,0}}, +{0, {329,329,329,329,329,329,329,329}, {0,0,0,0,0,0,0,0}}, +{0, {330,330,330,330,330,330,330,330}, {0,0,0,0,0,0,0,0}}, +{0, {315,315,315,315,315,315,315,315}, {0,0,0,0,0,0,0,0}}, +{0, {316,316,316,316,316,316,316,316}, {0,0,0,0,0,0,0,0}}, +{0, {317,317,317,317,317,317,317,317}, {0,0,0,0,0,0,0,0}}, +{0, {318,318,318,318,318,318,318,318}, {0,0,0,0,0,0,0,0}}, +{0, {319,319,319,319,319,319,319,319}, {0,0,0,0,0,0,0,0}}, +{0, {320,320,320,320,320,320,320,320}, {0,0,0,0,0,0,0,0}}, +{0, {321,321,321,321,321,321,321,321}, {0,0,0,0,0,0,0,0}}, +{0, {322,322,322,322,322,322,322,322}, {0,0,0,0,0,0,0,0}}, +{0, {345,345,345,345,345,345,345,345}, {0,0,0,0,0,0,0,0}}, +{0, {346,346,346,346,346,346,346,346}, {0,0,0,0,0,0,0,0}}, +{0, {238,238,238,238,238,238,238,238}, {0,0,0,0,0,0,0,0}}, +{0, {239,239,239,239,239,239,239,239}, {0,0,0,0,0,0,0,0}}, +{0, {240,240,240,240,240,240,240,240}, {0,0,0,0,0,0,0,0}}, +{0, {241,241,241,241,241,241,241,241}, {0,0,0,0,0,0,0,0}}, +{0, {242,242,242,242,242,242,242,242}, {0,0,0,0,0,0,0,0}}, +{0, {243,243,243,243,243,243,243,243}, {0,0,0,0,0,0,0,0}}, +{0, {244,244,244,244,244,244,244,244}, {0,0,0,0,0,0,0,0}}, +{0, {245,245,245,245,245,245,245,245}, {0,0,0,0,0,0,0,0}}, +{0, {246,246,246,246,246,246,246,246}, {0,0,0,0,0,0,0,0}}, +{0, {247,247,247,247,247,247,247,247}, {0,0,0,0,0,0,0,0}}, +{0, {248,248,248,248,248,248,248,248}, {0,0,0,0,0,0,0,0}}, +{0, {249,249,249,249,249,249,249,249}, {0,0,0,0,0,0,0,0}}, +{0, {250,250,250,250,250,250,250,250}, {0,0,0,0,0,0,0,0}}, +{0, {251,251,251,251,251,251,251,251}, {0,0,0,0,0,0,0,0}}, +{0, {252,252,252,252,252,252,252,252}, {0,0,0,0,0,0,0,0}}, +{0, {253,253,253,253,253,253,253,253}, {0,0,0,0,0,0,0,0}}, +{0, {254,254,254,254,254,254,254,254}, {0,0,0,0,0,0,0,0}}, +{0, {255,255,255,255,255,255,255,255}, {0,0,0,0,0,0,0,0}}, +{0, {305,305,305,305,305,305,305,305}, {0,0,0,0,0,0,0,0}}, +{0, {306,306,306,306,306,306,306,306}, {0,0,0,0,0,0,0,0}}, +{0, {307,307,307,307,307,307,307,307}, {0,0,0,0,0,0,0,0}}, +{0, {308,308,308,308,308,308,308,308}, {0,0,0,0,0,0,0,0}}, +{0, {309,309,309,309,309,309,309,309}, {0,0,0,0,0,0,0,0}}, +{0, {310,310,310,310,310,310,310,310}, {0,0,0,0,0,0,0,0}}, +{0, {311,311,311,311,311,311,311,311}, {0,0,0,0,0,0,0,0}}, +{0, {312,312,312,312,312,312,312,312}, {0,0,0,0,0,0,0,0}}, +{0, {313,313,313,313,313,313,313,313}, {0,0,0,0,0,0,0,0}}, +{0, {314,314,314,314,314,314,314,314}, {0,0,0,0,0,0,0,0}}, +{1, {256,257,258,259,256,259,258,257}, {0,0,0,0,1,1,1,1}}, +{1, {260,261,262,263,260,263,262,261}, {0,0,0,0,1,1,1,1}}, +{0, {264,264,264,264,264,264,264,264}, {0,0,0,0,0,0,0,0}}, +{0, {265,265,265,265,265,265,265,265}, {0,0,0,0,0,0,0,0}}, +{0, {266,266,266,266,266,266,266,266}, {0,0,0,0,0,0,0,0}}, +{0, {267,267,267,267,267,267,267,267}, {0,0,0,0,0,0,0,0}}, +{0, {268,268,268,268,268,268,268,268}, {0,0,0,0,0,0,0,0}}, +{0, {269,269,269,269,269,269,269,269}, {0,0,0,0,0,0,0,0}}, +{1, {270,271,272,273,270,273,272,271}, {0,0,0,0,1,1,1,1}}, +{1, {274,275,276,277,274,277,276,275}, {0,0,0,0,1,1,1,1}}, +{0, {278,278,278,278,278,278,278,278}, {0,0,0,0,0,0,0,0}}, +{0, {279,279,279,279,279,279,279,279}, {0,0,0,0,0,0,0,0}}, +{0, {280,280,280,280,280,280,280,280}, {0,0,0,0,0,0,0,0}}, +{0, {281,281,281,281,281,281,281,281}, {0,0,0,0,0,0,0,0}}, +{0, {282,282,282,282,282,282,282,282}, {0,0,0,0,0,0,0,0}}, +{0, {283,283,283,283,283,283,283,283}, {0,0,0,0,0,0,0,0}}, +{0, {331,331,331,331,331,331,331,331}, {0,0,0,0,0,0,0,0}}, +{0, {332,332,332,332,332,332,332,332}, {0,0,0,0,0,0,0,0}}, +{0, {333,333,333,333,333,333,333,333}, {0,0,0,0,0,0,0,0}}, +{0, {334,334,334,334,334,334,334,334}, {0,0,0,0,0,0,0,0}}, +{0, {335,335,335,335,335,335,335,335}, {0,0,0,0,0,0,0,0}}, +{0, {336,336,336,336,336,336,336,336}, {0,0,0,0,0,0,0,0}}, +{0, {337,337,337,337,337,337,337,337}, {0,0,0,0,0,0,0,0}}, +{0, {338,338,338,338,338,338,338,338}, {0,0,0,0,0,0,0,0}}, +{1, {284,285,286,287,288,287,286,285}, {0,0,0,0,0,1,1,1}}, +{1, {289,290,291,292,293,292,291,290}, {0,0,0,0,0,1,1,1}}, +{1, {294,295,296,297,298,297,296,295}, {0,0,0,0,0,1,1,1}}, +{0, {299,299,299,299,299,299,299,299}, {0,0,0,0,0,0,0,0}}, +{0, {300,300,300,300,300,300,300,300}, {0,0,0,0,0,0,0,0}}, +{0, {301,301,301,301,301,301,301,301}, {0,0,0,0,0,0,0,0}}, +{0, {302,302,302,302,302,302,302,302}, {0,0,0,0,0,0,0,0}}, +{0, {303,303,303,303,303,303,303,303}, {0,0,0,0,0,0,0,0}}, +{0, {304,304,304,304,304,304,304,304}, {0,0,0,0,0,0,0,0}}, +{1, {221,222,223,224,225,224,223,222}, {0,0,0,0,0,1,1,1}}, +{1, {226,227,228,229,230,229,228,227}, {0,0,0,0,0,1,1,1}}, +{0, {231,231,231,231,231,231,231,231}, {0,0,0,0,0,0,0,0}}, +{0, {232,232,232,232,232,232,232,232}, {0,0,0,0,0,0,0,0}}, +{0, {233,233,233,233,233,233,233,233}, {0,0,0,0,0,0,0,0}}, +{0, {234,234,234,234,234,234,234,234}, {0,0,0,0,0,0,0,0}}, +{0, {235,235,235,235,235,235,235,235}, {0,0,0,0,0,0,0,0}}, +{0, {236,236,236,236,236,236,236,236}, {0,0,0,0,0,0,0,0}}, +{0, {237,237,237,237,237,237,237,237}, {0,0,0,0,0,0,0,0}}, +{1, {340,341,342,343,344,343,342,341}, {0,0,0,0,0,1,1,1}}, +{0, {105,105,105,105,105,105,105,105}, {0,0,0,0,0,0,0,0}}, +{0, {106,106,106,106,106,106,106,106}, {0,0,0,0,0,0,0,0}}, +{0, {107,107,107,107,107,107,107,107}, {0,0,0,0,0,0,0,0}}, +{0, {108,108,108,108,108,108,108,108}, {0,0,0,0,0,0,0,0}}, +{0, {109,109,109,109,109,109,109,109}, {0,0,0,0,0,0,0,0}}, +{1, {53,54,55,56,57,56,55,54}, {0,0,0,0,0,1,1,1}}, +{1, {58,59,60,61,62,61,60,59}, {0,0,0,0,0,1,1,1}}, +{0, {63,63,63,63,63,63,63,63}, {0,0,0,0,0,0,0,0}}, +{0, {64,64,64,64,64,64,64,64}, {0,0,0,0,0,0,0,0}}, +{0, {65,65,65,65,65,65,65,65}, {0,0,0,0,0,0,0,0}}, +{0, {66,66,66,66,66,66,66,66}, {0,0,0,0,0,0,0,0}}, +{0, {67,67,67,67,67,67,67,67}, {0,0,0,0,0,0,0,0}}, +{0, {68,68,68,68,68,68,68,68}, {0,0,0,0,0,0,0,0}}, +{0, {92,92,92,92,92,92,92,92}, {0,0,0,0,0,0,0,0}}, +{0, {93,93,93,93,93,93,93,93}, {0,0,0,0,0,0,0,0}}, +{0, {94,94,94,94,94,94,94,94}, {0,0,0,0,0,0,0,0}}, +{0, {95,95,95,95,95,95,95,95}, {0,0,0,0,0,0,0,0}}, +{0, {96,96,96,96,96,96,96,96}, {0,0,0,0,0,0,0,0}}, +{0, {97,97,97,97,97,97,97,97}, {0,0,0,0,0,0,0,0}}, +{0, {98,98,98,98,98,98,98,98}, {0,0,0,0,0,0,0,0}}, +{0, {99,99,99,99,99,99,99,99}, {0,0,0,0,0,0,0,0}}, +{0, {100,100,100,100,100,100,100,100}, {0,0,0,0,0,0,0,0}}, +{0, {101,101,101,101,101,101,101,101}, {0,0,0,0,0,0,0,0}}, +{0, {86,86,86,86,86,86,86,86}, {0,0,0,0,0,0,0,0}}, +{0, {87,87,87,87,87,87,87,87}, {0,0,0,0,0,0,0,0}}, +{0, {88,88,88,88,88,88,88,88}, {0,0,0,0,0,0,0,0}}, +{0, {89,89,89,89,89,89,89,89}, {0,0,0,0,0,0,0,0}}, +{0, {90,90,90,90,90,90,90,90}, {0,0,0,0,0,0,0,0}}, +{0, {91,91,91,91,91,91,91,91}, {0,0,0,0,0,0,0,0}}, +{0, {69,69,69,69,69,69,69,69}, {0,0,0,0,0,0,0,0}}, +{0, {70,70,70,70,70,70,70,70}, {0,0,0,0,0,0,0,0}}, +{0, {71,71,71,71,71,71,71,71}, {0,0,0,0,0,0,0,0}}, +{0, {72,72,72,72,72,72,72,72}, {0,0,0,0,0,0,0,0}}, +{0, {23,23,23,23,23,23,23,23}, {0,0,0,0,0,0,0,0}}, +{0, {45,45,45,45,45,45,45,45}, {0,0,0,0,0,0,0,0}}, +{0, {46,46,46,46,46,46,46,46}, {0,0,0,0,0,0,0,0}}, +{0, {47,47,47,47,47,47,47,47}, {0,0,0,0,0,0,0,0}}, +{0, {48,48,48,48,48,48,48,48}, {0,0,0,0,0,0,0,0}}, +{0, {49,49,49,49,49,49,49,49}, {0,0,0,0,0,0,0,0}}, +{0, {50,50,50,50,50,50,50,50}, {0,0,0,0,0,0,0,0}}, +{0, {51,51,51,51,51,51,51,51}, {0,0,0,0,0,0,0,0}}, +{0, {52,52,52,52,52,52,52,52}, {0,0,0,0,0,0,0,0}}, +{0, {138,138,138,138,138,138,138,138}, {0,0,0,0,0,0,0,0}}, +{0, {139,139,139,139,139,139,139,139}, {0,0,0,0,0,0,0,0}}, +{0, {140,140,140,140,140,140,140,140}, {0,0,0,0,0,0,0,0}}, +{0, {141,141,141,141,141,141,141,141}, {0,0,0,0,0,0,0,0}}, +{0, {142,142,142,142,142,142,142,142}, {0,0,0,0,0,0,0,0}}, +{0, {143,143,143,143,143,143,143,143}, {0,0,0,0,0,0,0,0}}, +{0, {179,179,179,179,179,179,179,179}, {0,0,0,0,0,0,0,0}}, +{0, {180,180,180,180,180,180,180,180}, {0,0,0,0,0,0,0,0}}, +{0, {181,181,181,181,181,181,181,181}, {0,0,0,0,0,0,0,0}}, +{0, {182,182,182,182,182,182,182,182}, {0,0,0,0,0,0,0,0}}, +{0, {78,78,78,78,78,78,78,78}, {0,0,0,0,0,0,0,0}}, +{0, {79,79,79,79,79,79,79,79}, {0,0,0,0,0,0,0,0}}, +{0, {80,80,80,80,80,80,80,80}, {0,0,0,0,0,0,0,0}}, +{0, {81,81,81,81,81,81,81,81}, {0,0,0,0,0,0,0,0}}, +{0, {165,165,165,165,165,165,165,165}, {0,0,0,0,0,0,0,0}}, +{0, {166,166,166,166,166,166,166,166}, {0,0,0,0,0,0,0,0}}, +{0, {167,167,167,167,167,167,167,167}, {0,0,0,0,0,0,0,0}}, +{0, {168,168,168,168,168,168,168,168}, {0,0,0,0,0,0,0,0}}, +{0, {190,190,190,190,190,190,190,190}, {0,0,0,0,0,0,0,0}}, +{0, {188,188,188,188,188,188,188,188}, {0,0,0,0,0,0,0,0}}, +{0, {189,189,189,189,189,189,189,189}, {0,0,0,0,0,0,0,0}}, +{0, {210,210,210,210,210,210,210,210}, {0,0,0,0,0,0,0,0}}, +{0, {208,208,208,208,208,208,208,208}, {0,0,0,0,0,0,0,0}}, +{0, {209,209,209,209,209,209,209,209}, {0,0,0,0,0,0,0,0}}, +{0, {193,193,193,193,193,193,193,193}, {0,0,0,0,0,0,0,0}}, +{0, {194,194,194,194,194,194,194,194}, {0,0,0,0,0,0,0,0}}, +{0, {195,195,195,195,195,195,195,195}, {0,0,0,0,0,0,0,0}}, +{0, {196,196,196,196,196,196,196,196}, {0,0,0,0,0,0,0,0}}, +{0, {197,197,197,197,197,197,197,197}, {0,0,0,0,0,0,0,0}}, +{0, {198,198,198,198,198,198,198,198}, {0,0,0,0,0,0,0,0}}, +{0, {199,199,199,199,199,199,199,199}, {0,0,0,0,0,0,0,0}}, +{0, {200,200,200,200,200,200,200,200}, {0,0,0,0,0,0,0,0}}, +{0, {201,201,201,201,201,201,201,201}, {0,0,0,0,0,0,0,0}}, +{0, {202,202,202,202,202,202,202,202}, {0,0,0,0,0,0,0,0}}, +{0, {203,203,203,203,203,203,203,203}, {0,0,0,0,0,0,0,0}}, +{0, {204,204,204,204,204,204,204,204}, {0,0,0,0,0,0,0,0}}, +{0, {205,205,205,205,205,205,205,205}, {0,0,0,0,0,0,0,0}}, +{0, {206,206,206,206,206,206,206,206}, {0,0,0,0,0,0,0,0}}, +{0, {207,207,207,207,207,207,207,207}, {0,0,0,0,0,0,0,0}}, +{0, {169,169,169,169,169,169,169,169}, {0,0,0,0,0,0,0,0}}, +{0, {175,175,175,175,175,175,175,175}, {0,0,0,0,0,0,0,0}}, +{0, {110,110,110,110,110,110,110,110}, {0,0,0,0,0,0,0,0}}, +{0, {111,111,111,111,111,111,111,111}, {0,0,0,0,0,0,0,0}}, +{0, {112,112,112,112,112,112,112,112}, {0,0,0,0,0,0,0,0}}, +{0, {113,113,113,113,113,113,113,113}, {0,0,0,0,0,0,0,0}}, +{0, {130,130,130,130,130,130,130,130}, {0,0,0,0,0,0,0,0}}, +{0, {131,131,131,131,131,131,131,131}, {0,0,0,0,0,0,0,0}}, +{0, {132,132,132,132,132,132,132,132}, {0,0,0,0,0,0,0,0}}, +{0, {133,133,133,133,133,133,133,133}, {0,0,0,0,0,0,0,0}}, +{0, {173,173,173,173,173,173,173,173}, {0,0,0,0,0,0,0,0}}, +{0, {134,134,134,134,134,134,134,134}, {0,0,0,0,0,0,0,0}}, +{0, {135,135,135,135,135,135,135,135}, {0,0,0,0,0,0,0,0}}, +{0, {136,136,136,136,136,136,136,136}, {0,0,0,0,0,0,0,0}}, +{0, {137,137,137,137,137,137,137,137}, {0,0,0,0,0,0,0,0}}, +{0, {73,73,73,73,73,73,73,73}, {0,0,0,0,0,0,0,0}}, +{0, {74,74,74,74,74,74,74,74}, {0,0,0,0,0,0,0,0}}, +{0, {82,82,82,82,82,82,82,82}, {0,0,0,0,0,0,0,0}}, +{0, {83,83,83,83,83,83,83,83}, {0,0,0,0,0,0,0,0}}, +{0, {84,84,84,84,84,84,84,84}, {0,0,0,0,0,0,0,0}}, +{0, {85,85,85,85,85,85,85,85}, {0,0,0,0,0,0,0,0}}, +{0, {171,171,171,171,171,171,171,171}, {0,0,0,0,0,0,0,0}}, +{0, {172,172,172,172,172,172,172,172}, {0,0,0,0,0,0,0,0}}, +{0, {126,126,126,126,126,126,126,126}, {0,0,0,0,0,0,0,0}}, +{0, {127,127,127,127,127,127,127,127}, {0,0,0,0,0,0,0,0}}, +{0, {128,128,128,128,128,128,128,128}, {0,0,0,0,0,0,0,0}}, +{0, {129,129,129,129,129,129,129,129}, {0,0,0,0,0,0,0,0}}, +{0, {177,177,177,177,177,177,177,177}, {0,0,0,0,0,0,0,0}}, +{0, {192,192,192,192,192,192,192,192}, {0,0,0,0,0,0,0,0}}, +{0, {170,170,170,170,170,170,170,170}, {0,0,0,0,0,0,0,0}}, +{0, {186,186,186,186,186,186,186,186}, {0,0,0,0,0,0,0,0}}, +{0, {183,183,183,183,183,183,183,183}, {0,0,0,0,0,0,0,0}}, +{0, {178,178,178,178,178,178,178,178}, {0,0,0,0,0,0,0,0}}, +{0, {162,162,162,162,162,162,162,162}, {0,0,0,0,0,0,0,0}}, +{0, {164,164,164,164,164,164,164,164}, {0,0,0,0,0,0,0,0}}, +{0, {187,187,187,187,187,187,187,187}, {0,0,0,0,0,0,0,0}}, +{0, {191,191,191,191,191,191,191,191}, {0,0,0,0,0,0,0,0}}, +{0, {102,102,102,102,102,102,102,102}, {0,0,0,0,0,0,0,0}}, +{0, {174,174,174,174,174,174,174,174}, {0,0,0,0,0,0,0,0}}, +{0, {176,176,176,176,176,176,176,176}, {0,0,0,0,0,0,0,0}}, +{0, {104,104,104,104,104,104,104,104}, {0,0,0,0,0,0,0,0}}, +{0, {161,161,161,161,161,161,161,161}, {0,0,0,0,0,0,0,0}}, +{0, {163,163,163,163,163,163,163,163}, {0,0,0,0,0,0,0,0}}, +{0, {103,103,103,103,103,103,103,103}, {0,0,0,0,0,0,0,0}}, +{0, {184,184,184,184,184,184,184,184}, {0,0,0,0,0,0,0,0}}, +{0, {185,185,185,185,185,185,185,185}, {0,0,0,0,0,0,0,0}}, +{0, {114,114,114,114,114,114,114,114}, {0,0,0,0,0,0,0,0}}, +{0, {115,115,115,115,115,115,115,115}, {0,0,0,0,0,0,0,0}}, +{0, {116,116,116,116,116,116,116,116}, {0,0,0,0,0,0,0,0}}, +{0, {117,117,117,117,117,117,117,117}, {0,0,0,0,0,0,0,0}}, +{0, {118,118,118,118,118,118,118,118}, {0,0,0,0,0,0,0,0}}, +{0, {159,159,159,159,159,159,159,159}, {0,0,0,0,0,0,0,0}}, +{0, {160,160,160,160,160,160,160,160}, {0,0,0,0,0,0,0,0}}, +{0, {31,31,31,31,31,31,31,31}, {0,0,0,0,0,0,0,0}}, +{0, {32,32,32,32,32,32,32,32}, {0,0,0,0,0,0,0,0}}, +{0, {33,33,33,33,33,33,33,33}, {0,0,0,0,0,0,0,0}}, +{0, {34,34,34,34,34,34,34,34}, {0,0,0,0,0,0,0,0}}, +{0, {35,35,35,35,35,35,35,35}, {0,0,0,0,0,0,0,0}}, +{0, {26,26,26,26,26,26,26,26}, {0,0,0,0,0,0,0,0}}, +{0, {27,27,27,27,27,27,27,27}, {0,0,0,0,0,0,0,0}}, +{0, {28,28,28,28,28,28,28,28}, {0,0,0,0,0,0,0,0}}, +{0, {29,29,29,29,29,29,29,29}, {0,0,0,0,0,0,0,0}}, +{0, {30,30,30,30,30,30,30,30}, {0,0,0,0,0,0,0,0}}, +{0, {36,36,36,36,36,36,36,36}, {0,0,0,0,0,0,0,0}}, +{0, {37,37,37,37,37,37,37,37}, {0,0,0,0,0,0,0,0}}, +{0, {38,38,38,38,38,38,38,38}, {0,0,0,0,0,0,0,0}}, +{0, {39,39,39,39,39,39,39,39}, {0,0,0,0,0,0,0,0}}, +{0, {40,40,40,40,40,40,40,40}, {0,0,0,0,0,0,0,0}}, +{0, {41,41,41,41,41,41,41,41}, {0,0,0,0,0,0,0,0}}, +{0, {42,42,42,42,42,42,42,42}, {0,0,0,0,0,0,0,0}}, +{0, {144,144,144,144,144,144,144,144}, {0,0,0,0,0,0,0,0}}, +{0, {145,145,145,145,145,145,145,145}, {0,0,0,0,0,0,0,0}}, +{0, {146,146,146,146,146,146,146,146}, {0,0,0,0,0,0,0,0}}, +{0, {147,147,147,147,147,147,147,147}, {0,0,0,0,0,0,0,0}}, +{0, {148,148,148,148,148,148,148,148}, {0,0,0,0,0,0,0,0}}, +{0, {149,149,149,149,149,149,149,149}, {0,0,0,0,0,0,0,0}}, +{0, {150,150,150,150,150,150,150,150}, {0,0,0,0,0,0,0,0}}, +{0, {151,151,151,151,151,151,151,151}, {0,0,0,0,0,0,0,0}}, +{0, {152,152,152,152,152,152,152,152}, {0,0,0,0,0,0,0,0}}, +{0, {153,153,153,153,153,153,153,153}, {0,0,0,0,0,0,0,0}}, +{0, {154,154,154,154,154,154,154,154}, {0,0,0,0,0,0,0,0}}, +{0, {155,155,155,155,155,155,155,155}, {0,0,0,0,0,0,0,0}}, +{0, {156,156,156,156,156,156,156,156}, {0,0,0,0,0,0,0,0}}, +{0, {157,157,157,157,157,157,157,157}, {0,0,0,0,0,0,0,0}}, +{0, {158,158,158,158,158,158,158,158}, {0,0,0,0,0,0,0,0}}, +{0, {5,5,5,5,5,5,5,5}, {0,0,0,0,0,0,0,0}}, +{0, {19,19,19,19,19,19,19,19}, {0,0,0,0,0,0,0,0}}, +{0, {2,2,2,2,2,2,2,2}, {0,0,0,0,0,0,0,0}}, +{0, {18,18,18,18,18,18,18,18}, {0,0,0,0,0,0,0,0}}, +{0, {11,11,11,11,11,11,11,11}, {0,0,0,0,0,0,0,0}}, +{0, {12,12,12,12,12,12,12,12}, {0,0,0,0,0,0,0,0}}, +{0, {14,14,14,14,14,14,14,14}, {0,0,0,0,0,0,0,0}}, +{0, {7,7,7,7,7,7,7,7}, {0,0,0,0,0,0,0,0}}, +{0, {6,6,6,6,6,6,6,6}, {0,0,0,0,0,0,0,0}}, +{0, {13,13,13,13,13,13,13,13}, {0,0,0,0,0,0,0,0}}, +{0, {1,1,1,1,1,1,1,1}, {0,0,0,0,0,0,0,0}}, +{0, {9,9,9,9,9,9,9,9}, {0,0,0,0,0,0,0,0}}, +{0, {8,8,8,8,8,8,8,8}, {0,0,0,0,0,0,0,0}}, +{0, {16,16,16,16,16,16,16,16}, {0,0,0,0,0,0,0,0}}, +{0, {15,15,15,15,15,15,15,15}, {0,0,0,0,0,0,0,0}}, +{0, {22,22,22,22,22,22,22,22}, {0,0,0,0,0,0,0,0}}, +{0, {20,20,20,20,20,20,20,20}, {0,0,0,0,0,0,0,0}}, +{0, {24,24,24,24,24,24,24,24}, {0,0,0,0,0,0,0,0}}, +{0, {25,25,25,25,25,25,25,25}, {0,0,0,0,0,0,0,0}}, +{0, {43,43,43,43,43,43,43,43}, {0,0,0,0,0,0,0,0}}, +{0, {44,44,44,44,44,44,44,44}, {0,0,0,0,0,0,0,0}}, +{0, {77,77,77,77,77,77,77,77}, {0,0,0,0,0,0,0,0}}, +{0, {76,76,76,76,76,76,76,76}, {0,0,0,0,0,0,0,0}}, +{0, {75,75,75,75,75,75,75,75}, {0,0,0,0,0,0,0,0}}, +{0, {10,10,10,10,10,10,10,10}, {0,0,0,0,0,0,0,0}}, +{0, {17,17,17,17,17,17,17,17}, {0,0,0,0,0,0,0,0}}, +{0, {3,3,3,3,3,3,3,3}, {0,0,0,0,0,0,0,0}}, +{0, {4,4,4,4,4,4,4,4}, {0,0,0,0,0,0,0,0}}, +{0, {21,21,21,21,21,21,21,21}, {0,0,0,0,0,0,0,0}}, +{0, {924,924,924,924,924,924,924,924}, {0,0,0,0,0,0,0,0}}, +{0, {925,925,925,925,925,925,925,925}, {0,0,0,0,0,0,0,0}}, +{0, {926,926,926,926,926,926,926,926}, {0,0,0,0,0,0,0,0}}, +{0, {927,927,927,927,927,927,927,927}, {0,0,0,0,0,0,0,0}}, +{0, {928,928,928,928,928,928,928,928}, {0,0,0,0,0,0,0,0}}, +{0, {929,929,929,929,929,929,929,929}, {0,0,0,0,0,0,0,0}}, +{0, {930,930,930,930,930,930,930,930}, {0,0,0,0,0,0,0,0}}, +{0, {931,931,931,931,931,931,931,931}, {0,0,0,0,0,0,0,0}}, +{0, {932,932,932,932,932,932,932,932}, {0,0,0,0,0,0,0,0}}, +{0, {933,933,933,933,933,933,933,933}, {0,0,0,0,0,0,0,0}}, +{0, {934,934,934,934,934,934,934,934}, {0,0,0,0,0,0,0,0}}, +{0, {935,935,935,935,935,935,935,935}, {0,0,0,0,0,0,0,0}}, +{0, {936,936,936,936,936,936,936,936}, {0,0,0,0,0,0,0,0}}, +{0, {937,937,937,937,937,937,937,937}, {0,0,0,0,0,0,0,0}}, +{0, {938,938,938,938,938,938,938,938}, {0,0,0,0,0,0,0,0}}, +{0, {939,939,939,939,939,939,939,939}, {0,0,0,0,0,0,0,0}}, +{0, {940,940,940,940,940,940,940,940}, {0,0,0,0,0,0,0,0}}, +{0, {941,941,941,941,941,941,941,941}, {0,0,0,0,0,0,0,0}}, +{0, {942,942,942,942,942,942,942,942}, {0,0,0,0,0,0,0,0}}, +{0, {943,943,943,943,943,943,943,943}, {0,0,0,0,0,0,0,0}}, +{0, {944,944,944,944,944,944,944,944}, {0,0,0,0,0,0,0,0}}, +{0, {945,945,945,945,945,945,945,945}, {0,0,0,0,0,0,0,0}}, +{0, {946,946,946,946,946,946,946,946}, {0,0,0,0,0,0,0,0}}, +{0, {947,947,947,947,947,947,947,947}, {0,0,0,0,0,0,0,0}}, +{0, {948,948,948,948,948,948,948,948}, {0,0,0,0,0,0,0,0}}, +{0, {949,949,949,949,949,949,949,949}, {0,0,0,0,0,0,0,0}}, +{0, {950,950,950,950,950,950,950,950}, {0,0,0,0,0,0,0,0}}, +{0, {951,951,951,951,951,951,951,951}, {0,0,0,0,0,0,0,0}}, +{0, {952,952,952,952,952,952,952,952}, {0,0,0,0,0,0,0,0}}, +{0, {953,953,953,953,953,953,953,953}, {0,0,0,0,0,0,0,0}}, +{0, {954,954,954,954,954,954,954,954}, {0,0,0,0,0,0,0,0}}, +{0, {955,955,955,955,955,955,955,955}, {0,0,0,0,0,0,0,0}}, +{0, {956,956,956,956,956,956,956,956}, {0,0,0,0,0,0,0,0}}, +{0, {957,957,957,957,957,957,957,957}, {0,0,0,0,0,0,0,0}}, +{0, {958,958,958,958,958,958,958,958}, {0,0,0,0,0,0,0,0}}, +{0, {959,959,959,959,959,959,959,959}, {0,0,0,0,0,0,0,0}}, +{0, {960,960,960,960,960,960,960,960}, {0,0,0,0,0,0,0,0}}, +{0, {961,961,961,961,961,961,961,961}, {0,0,0,0,0,0,0,0}}, +{0, {962,962,962,962,962,962,962,962}, {0,0,0,0,0,0,0,0}}, +{0, {963,963,963,963,963,963,963,963}, {0,0,0,0,0,0,0,0}}, +{0, {964,964,964,964,964,964,964,964}, {0,0,0,0,0,0,0,0}}, +{0, {965,965,965,965,965,965,965,965}, {0,0,0,0,0,0,0,0}} +}; + +spritedef_t sprites[] = { // 80059D98 +{&spriteframes[0], 22}, +{&spriteframes[0], 14}, +{&spriteframes[22], 15}, +{&spriteframes[36], 21}, +{&spriteframes[51], 24}, +{&spriteframes[72], 13}, +{&spriteframes[96], 14}, +{&spriteframes[109], 16}, +{&spriteframes[123], 12}, +{&spriteframes[139], 15}, +{&spriteframes[151], 12}, +{&spriteframes[166], 15}, +{&spriteframes[178], 6}, +{&spriteframes[193], 8}, +{&spriteframes[199], 8}, +{&spriteframes[207], 2}, +{&spriteframes[215], 9}, +{&spriteframes[217], 9}, +{&spriteframes[226], 10}, +{&spriteframes[235], 8}, +{&spriteframes[245], 8}, +{&spriteframes[253], 8}, +{&spriteframes[261], 9}, +{&spriteframes[269], 9}, +{&spriteframes[278], 1}, +{&spriteframes[287], 5}, +{&spriteframes[288], 8}, +{&spriteframes[293], 5}, +{&spriteframes[301], 5}, +{&spriteframes[306], 6}, +{&spriteframes[311], 4}, +{&spriteframes[317], 1}, +{&spriteframes[321], 8}, +{&spriteframes[322], 6}, +{&spriteframes[330], 2}, +{&spriteframes[336], 2}, +{&spriteframes[338], 4}, +{&spriteframes[340], 4}, +{&spriteframes[344], 1}, +{&spriteframes[348], 1}, +{&spriteframes[349], 1}, +{&spriteframes[350], 1}, +{&spriteframes[351], 1}, +{&spriteframes[352], 1}, +{&spriteframes[353], 5}, +{&spriteframes[354], 5}, +{&spriteframes[359], 5}, +{&spriteframes[364], 1}, +{&spriteframes[369], 1}, +{&spriteframes[370], 4}, +{&spriteframes[371], 4}, +{&spriteframes[375], 1}, +{&spriteframes[379], 4}, +{&spriteframes[380], 2}, +{&spriteframes[384], 4}, +{&spriteframes[386], 2}, +{&spriteframes[390], 4}, +{&spriteframes[392], 1}, +{&spriteframes[396], 1}, +{&spriteframes[397], 1}, +{&spriteframes[398], 1}, +{&spriteframes[399], 1}, +{&spriteframes[400], 1}, +{&spriteframes[401], 1}, +{&spriteframes[402], 1}, +{&spriteframes[403], 1}, +{&spriteframes[404], 1}, +{&spriteframes[405], 1}, +{&spriteframes[406], 1}, +{&spriteframes[407], 1}, +{&spriteframes[408], 1}, +{&spriteframes[409], 1}, +{&spriteframes[410], 1}, +{&spriteframes[411], 1}, +{&spriteframes[412], 2}, +{&spriteframes[413], 5}, +{&spriteframes[415], 1}, +{&spriteframes[420], 1}, +{&spriteframes[421], 5}, +{&spriteframes[422], 5}, +{&spriteframes[427], 5}, +{&spriteframes[432], 1}, +{&spriteframes[437], 1}, +{&spriteframes[438], 5}, +{&spriteframes[439], 5}, +{&spriteframes[444], 5}, +{&spriteframes[449], 1}, +{&spriteframes[454], 1}, +{&spriteframes[455], 1}, +{&spriteframes[456], 1}, +{&spriteframes[457], 2}, +{&spriteframes[458], 1}, +{&spriteframes[460], 1}, +{&spriteframes[461], 1}, +{&spriteframes[462], 1}, +{&spriteframes[463], 1}, +{&spriteframes[464], 1}, +{&spriteframes[465], 1}, +{&spriteframes[466], 1}, +{&spriteframes[467], 1}, +{&spriteframes[468], 1}, +{&spriteframes[469], 1}, +{&spriteframes[470], 1}, +{&spriteframes[471], 1}, +{&spriteframes[472], 1}, +{&spriteframes[473], 1}, +{&spriteframes[474], 1}, +{&spriteframes[475], 1}, +{&spriteframes[476], 1}, +{&spriteframes[477], 1}, +{&spriteframes[478], 1}, +{&spriteframes[479], 1}, +{&spriteframes[480], 1}, +{&spriteframes[481], 1}, +{&spriteframes[482], 4}, +{&spriteframes[483], 4}, +{&spriteframes[487], 4}, +{&spriteframes[491], 4}, +{&spriteframes[495], 4}, +{&spriteframes[499], 4}, +{&spriteframes[503], 6}, +{&spriteframes[507], 5}, +{&spriteframes[513], 5}, +{&spriteframes[518], 2}, +{&spriteframes[523], 0} +}; diff --git a/Doom 64/st_main.c b/Doom 64/st_main.c @@ -0,0 +1,829 @@ +/* st_main.c -- status bar */ + +#include "doomdef.h" +#include "st_main.h" +#include "r_local.h" + +sbflash_t flashCards[6]; // 800A8180 +boolean tryopen[6]; // 800A81E0 + +byte *sfontlump; // 800A81F8 +byte *statuslump; // 800A81FC +int sumbolslump; // 800A8204 + +int err_text_x; // 800A8208 +int err_text_y; // 800A820C + +symboldata_t symboldata[] = // 8005B260 +{ + {120, 14, 13, 13}, // 0 + {134, 14, 9, 13}, // 1 + {144, 14, 14, 13}, // 2 + {159, 14, 14, 13}, // 3 + {174, 14, 16, 13}, // 4 + {191, 14, 13, 13}, // 5 + {205, 14, 13, 13}, // 6 + {219, 14, 14, 13}, // 7 + {234, 14, 14, 13}, // 8 + { 0, 29, 13, 13}, // 9 + { 67, 28, 14, 13}, // - + { 36, 28, 15, 14}, // % + { 28, 28, 7, 14}, // ! + { 14, 29, 6, 13}, // . + { 52, 28, 13, 13}, // ? + { 21, 29, 6, 13}, // : + { 0, 0, 13, 13}, // A + { 14, 0, 13, 13}, // B + { 28, 0, 13, 13}, // C + { 42, 0, 14, 13}, // D + { 57, 0, 14, 13}, // E + { 72, 0, 10, 13}, // F + { 87, 0, 15, 13}, // G + {103, 0, 15, 13}, // H + {119, 0, 6, 13}, // I + {122, 0, 13, 13}, // J + {140, 0, 14, 13}, // K + {155, 0, 11, 13}, // L + {167, 0, 15, 13}, // M + {183, 0, 16, 13}, // N + {200, 0, 15, 13}, // O + {216, 0, 13, 13}, // P + {230, 0, 15, 13}, // Q + {246, 0, 13, 13}, // R + { 0, 14, 14, 13}, // S + { 15, 14, 14, 13}, // T + { 30, 14, 13, 13}, // U + { 44, 14, 15, 13}, // V + { 60, 14, 15, 13}, // W + { 76, 14, 15, 13}, // X + { 92, 14, 13, 13}, // Y + {106, 14, 13, 13}, // Z + { 83, 31, 10, 11}, // a + { 93, 31, 10, 11}, // b + {103, 31, 11, 11}, // c + {114, 31, 11, 11}, // d + {125, 31, 11, 11}, // e + {136, 31, 11, 11}, // f + {147, 31, 12, 11}, // g + {159, 31, 12, 11}, // h + {171, 31, 4, 11}, // i + {175, 31, 10, 11}, // j + {185, 31, 11, 11}, // k + {196, 31, 9, 11}, // l + {205, 31, 12, 11}, // m + {217, 31, 13, 11}, // n + {230, 31, 12, 11}, // o + {242, 31, 11, 11}, // p + { 0, 43, 12, 11}, // q + { 12, 43, 11, 11}, // r + { 23, 43, 11, 11}, // s + { 34, 43, 10, 11}, // t + { 44, 43, 11, 11}, // u + { 55, 43, 12, 11}, // v + { 67, 43, 13, 11}, // w + { 80, 43, 13, 11}, // x + { 93, 43, 10, 11}, // y + {103, 43, 11, 11}, // z + { 0, 95, 108, 11}, // Slider bar + {108, 95, 6, 11}, // Slider gem + { 0, 54, 32, 26}, // Skull 1 + { 32, 54, 32, 26}, // Skull 2 + { 64, 54, 32, 26}, // Skull 3 + { 96, 54, 32, 26}, // Skull 4 + {128, 54, 32, 26}, // Skull 5 + {160, 54, 32, 26}, // Skull 6 + {192, 54, 32, 26}, // Skull 7 + {224, 54, 32, 26}, // Skull 8 + {134, 97, 7, 11}, // Right arrow + {114, 95, 20, 18}, // Select box + {105, 80, 15, 15}, // Dpad left + {120, 80, 15, 15}, // Dpad right + {135, 80, 15, 15}, // Dpad up + {150, 80, 15, 15}, // Dpad down + { 45, 80, 15, 15}, // C left button + { 60, 80, 15, 15}, // C right button + { 75, 80, 15, 15}, // C up button + { 90, 80, 15, 15}, // C down button + {165, 80, 15, 15}, // L button + {180, 80, 15, 15}, // R button + { 0, 80, 15, 15}, // A button + { 15, 80, 15, 15}, // B btton + {195, 80, 15, 15}, // Z button + { 30, 80, 15, 15}, // Start button + {156, 96, 13, 13}, // Down arrow + {143, 96, 13, 13}, // Up arrow + {169, 96, 7, 13}, // Left arrow + //{134, 96, 7, 13}, // Right arrow Missing On Doom 64 +}; + +int card_x[6] = {(78 << 2), (89 << 2), (100 << 2), (78 << 2), (89 << 2), (100 << 2)}; // 8005b870 + +void ST_Init(void) // 80029BA0 +{ + sfontlump = (byte *)W_CacheLumpName("SFONT",PU_STATIC,dec_jag); + statuslump = (byte *)W_CacheLumpName("STATUS",PU_STATIC,dec_jag); + sumbolslump = W_GetNumForName("SYMBOLS"); +} + +void ST_InitEveryLevel(void) // 80029C00 +{ + infraredFactor = 0; + quakeviewy = 0; + quakeviewx = 0; + camviewpitch = 0; + flashCards[0].active = false; + flashCards[1].active = false; + flashCards[2].active = false; + flashCards[3].active = false; + flashCards[4].active = false; + flashCards[5].active = false; + tryopen[0] = false; + tryopen[1] = false; + tryopen[2] = false; + tryopen[3] = false; + tryopen[4] = false; + tryopen[5] = false; + +} + +/* +==================== += += ST_Ticker += +==================== +*/ + +void ST_Ticker (void) // 80029C88 +{ + player_t *player; + int ind, base; + + player = &players[0]; + + /* */ + /* Countdown time for the message */ + /* */ + player->messagetic--; + + /* */ + /* Tried to open a CARD or SKULL door? */ + /* */ + for (ind = 0; ind < NUMCARDS; ind++) + { + /* CHECK FOR INITIALIZATION */ + if (tryopen[ind]) + { + tryopen[ind] = false; + flashCards[ind].active = true; + flashCards[ind].delay = FLASHDELAY-1; + flashCards[ind].times = FLASHTIMES+1; + flashCards[ind].doDraw = false; + } + /* MIGHT AS WELL DO TICKING IN THE SAME LOOP! */ + else if (flashCards[ind].active && !--flashCards[ind].delay) + { + flashCards[ind].delay = FLASHDELAY-1; + flashCards[ind].doDraw ^= 1; + if (!--flashCards[ind].times) + flashCards[ind].active = false; + if (flashCards[ind].doDraw && flashCards[ind].active) + S_StartSound(NULL,sfx_itemup); + } + } + + /* */ + /* Do flashes from damage/items */ + /* */ + if (cameratarget == player->mo) + { + ST_UpdateFlash(); // ST_doPaletteStuff(); + } +} + + +/* +==================== += += ST_Drawer += +==================== +*/ +#if SHOWFPS == 1 +//extern int fps; +#endif // _SHOWFPS + +static char buffer[16][256]; +static int debugX, debugY;//80077E5C|uGp00000a4c, 80077E68|uGp00000a58 +static int debugcnt = 0; +static int debug = 0; + +void ST_Drawer (void) // 80029DC0 +{ + byte *src; + player_t *player; + weapontype_t weapon; + int ammo, ind, ms_alpha; + + player = &players[0]; + + /* */ + /* Draw Text Message */ + /* */ + ms_alpha = players[0].messagetic << 3; + if ((enable_messages) && (ms_alpha > 0)) + { + if (ms_alpha >= 255) + ms_alpha = 255; + + ST_Message(20, 20, players[0].message, ms_alpha | 0xffffff00); + } + + if (enable_statusbar) + { + I_CheckGFX(); + + debug = 1;// + + if (globallump != (int)sfontlump) + { + gDPPipeSync(GFX1++); + gDPSetCycleType(GFX1++, G_CYC_1CYCLE); + gDPSetTextureLUT(GFX1++, G_TT_RGBA16); + gDPSetTexturePersp(GFX1++, G_TP_NONE); + gDPSetAlphaCompare(GFX1++, G_AC_THRESHOLD); + gDPSetBlendColor(GFX1++, 0, 0, 0, 0); + gDPSetCombineMode(GFX1++, G_CC_D64COMB04, G_CC_D64COMB04); + gDPSetRenderMode(GFX1++, G_RM_XLU_SURF_CLAMP, G_RM_XLU_SURF2_CLAMP); + } + + src = statuslump+sizeof(spriteN64_t); + + gDPSetTextureImage(GFX1++, G_IM_FMT_CI, G_IM_SIZ_16b , 1, src); + gDPSetTile(GFX1++, G_IM_FMT_CI, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0); + + gDPLoadSync(GFX1++); + gDPLoadBlock(GFX1++, G_TX_LOADTILE, 0, 0, 639, 0); + + gDPPipeSync(GFX1++); + gDPSetTile(GFX1++, G_IM_FMT_CI, G_IM_SIZ_8b, 10, 0, G_TX_RENDERTILE, 0, 0, 0, 0, 0, 0, 0); + gDPSetTileSize(GFX1++, G_TX_RENDERTILE, 0, 0, (79 << 2), (15 << 2)); + + gDPSetTextureImage(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_16b , 1, src + ((spriteN64_t*)statuslump)->cmpsize); + + gDPTileSync(GFX1++); + gDPSetTile(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_4b, 0, 256, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0); + + gDPLoadSync(GFX1++); + gDPLoadTLUTCmd(GFX1++, G_TX_LOADTILE, 255); + + gDPPipeSync(GFX1++); + + /* */ + /* Gray color with alpha 144 */ + /* */ + gDPSetPrimColor(GFX1++, 0, 0, 104, 104, 104, 144); + + /* */ + /* Health */ + /* */ + gSPTextureRectangle(GFX1++, (29 << 2), (203 << 2), + (69 << 2), (209 << 2), + G_TX_RENDERTILE, + (0 << 5), (0 << 5), + (1 << 10), (1 << 10)); + + /* */ + /* Armor */ + /* */ + gSPTextureRectangle(GFX1++, (253 << 2), (203 << 2), + (289 << 2), (209 << 2), + G_TX_RENDERTILE, + (40 << 5), (0 << 5), + (1 << 10), (1 << 10)); + + /* */ + /* White color with alpha 128 */ + /* */ + gDPSetPrimColor(GFX1++, 0, 0, 255, 255, 255, 128); + + /* */ + /* Cards & skulls */ + /* */ + for (ind = 0; ind < NUMCARDS; ind++) + { + if (player->cards[ind] || (flashCards[ind].active && flashCards[ind].doDraw)) + { + /* */ + /* Draw Keys Graphics */ + /* */ + gSPTextureRectangle(GFX1++, card_x[ind], (216 << 2), + card_x[ind]+(9 << 2), (226 << 2), + G_TX_RENDERTILE, + ((ind * 9) << 5), (6 << 5), + (1 << 10), (1 << 10)); + } + } + + /* */ + /* Ammo */ + /* */ + weapon = player->pendingweapon; + + if (weapon == wp_nochange) + weapon = player->readyweapon; + + if (weaponinfo[weapon].ammo != am_noammo) + { + ammo = player->ammo[weaponinfo[weapon].ammo]; + if (ammo < 0) + ammo = 0; + + ST_DrawNumber(160, 215, ammo, 0, PACKRGBA(224,0,0,128)); // 0xe0000080 + } + + /* */ + /* Health */ + /* */ + ST_DrawNumber(49, 215, player->health, 0, PACKRGBA(224,0,0,128)); // 0xe0000080 + + /* */ + /* Armor */ + /* */ + ST_DrawNumber(271, 215, player->armorpoints, 0, PACKRGBA(224,0,0,128)); // 0xe0000080 + } + + #if SHOWFPS == 1 + //fps = (60-((fps)/60)); + //fps = fps > 0? fps:0; + //D_DebugSetPrintPos(10, 10); + //D_DebugPrint("fps %d", fps); + #endif // SHOWFPS + + if(debug) + { + for(ammo = 0; ammo < debugcnt; ammo++) + { + ST_Message(8, (ammo*8)+8, buffer[ammo],0x00ff00ff); + } + } +} + +#define ST_FONTWHSIZE 8 + +void ST_Message(int x,int y,char *text,int color) // 8002A36C +{ + byte *src; + byte c; + int s,t; + int xpos, ypos; + int bVar2; + + if (globallump != (int)sfontlump) + { + gDPPipeSync(GFX1++); + + gDPSetCycleType(GFX1++, G_CYC_1CYCLE); + gDPSetTextureLUT(GFX1++, G_TT_RGBA16); + gDPSetTexturePersp(GFX1++, G_TP_NONE); + + gDPSetAlphaCompare(GFX1++, G_AC_THRESHOLD); + gDPSetBlendColor(GFX1++, 0, 0, 0, 0); + + gDPSetCombineMode(GFX1++, G_CC_D64COMB04, G_CC_D64COMB04); + gDPSetRenderMode(GFX1++, G_RM_XLU_SURF_CLAMP, G_RM_XLU_SURF2_CLAMP); + + src = sfontlump+sizeof(spriteN64_t); + + gDPSetTextureImage(GFX1++, G_IM_FMT_CI, G_IM_SIZ_16b , 1, src); + + gDPSetTile(GFX1++, G_IM_FMT_CI, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0); + + gDPLoadSync(GFX1++); + gDPLoadBlock(GFX1++, G_TX_LOADTILE, 0, 0, 1023, 0); + + gDPPipeSync(GFX1++); + gDPSetTile(GFX1++, G_IM_FMT_CI, G_IM_SIZ_4b, 16, 0, G_TX_RENDERTILE, 0, 0, 0, 0, 0, 0, 0); + gDPSetTileSize(GFX1++, G_TX_RENDERTILE, 0, 0, (255 << 2), (15 << 2)); + + gDPSetTextureImage(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_16b , 1, (src+0x800)); + + gDPTileSync(GFX1++); + gDPSetTile(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_4b, 0, 256, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0); + + gDPLoadSync(GFX1++); + gDPLoadTLUTCmd(GFX1++, G_TX_LOADTILE, 15); + + gDPPipeSync(GFX1++); + + globallump = (int)sfontlump; + } + + gDPSetPrimColorD64(GFX1++, 0, 0, color); + + ypos = y; + xpos = x; + while (*text) + { + c = *text; + + if (c == '\n') + { + ypos += (ST_FONTWHSIZE+1); + xpos = x; + } + else + { + if(c >= 'a' && c <= 'z') + c -= (26 + 6); + + if (c >= '!' && c <= '_') + { + if ((c - '!') < 32) + t = 0; + else + t = ST_FONTWHSIZE; + + s = (c - '!' & ~32) * ST_FONTWHSIZE; + + gSPTextureRectangle(GFX1++, + (xpos << 2), (ypos << 2), + ((xpos + ST_FONTWHSIZE) << 2), ((ypos + ST_FONTWHSIZE) << 2), + G_TX_RENDERTILE, + (s << 5), (t << 5), + (1 << 10), (1 << 10)); + } + xpos += ST_FONTWHSIZE; + } + text++; + } +} + +void ST_DrawNumber(int x, int y, int value, int mode, int color) // 8002A79C +{ + int index, width, i; + int number [16]; + + width = 0; + for (index = 0; index < 16; index++) + { + number[index] = value % 10; + width += symboldata[number[index]].w; + + value /= 10; + if (!value) break; + } + + switch(mode) + { + case 0: /* Center */ + x -= (width / 2); + case 1: /* Right */ + while (index >= 0) + { + ST_DrawSymbol(x, y, number[index], color); + x += symboldata[number[index]].w; + index--; + } + break; + case 2: /* Left */ + i = 0; + while (index >= 0) + { + x -= symboldata[number[i]].w; + ST_DrawSymbol(x, y, number[i], color); + i++; + index--; + } + break; + default: + break; + } +} + +void ST_DrawString(int x, int y, char *text, int color) // 8002A930 +{ + byte c; + int xpos, ypos, index; + + I_CheckGFX(); + + xpos = x; + if(xpos <= -1) /* Get Center Text Position */ + xpos = ST_GetCenterTextX(text); + + while (*text) + { + c = *text; + ypos = y; + + if(c >= 'A' && c <= 'Z') + { + index = (c - 'A') + 16; + } + else if(c >= 'a' && c <= 'z') + { + index = (c - 'a') + 42; + ypos = y + 2; + } + else if(c >= '0' && c <= '9') + { + index = (c - '0') + 0; + } + else if (c == '!') + { + index = 12; + ypos = y - 1; + } + else if (c == '-') + { + index = 10; + } + else if (c == '.') + { + index = 13; + } + else if (c == ':') + { + index = 15; + } + else if (c == '?') + { + index = 14; + } + else if (c == '%') + { + index = 11; + } + else if(c >= FIRST_SYMBOL && c <= LAST_SYMBOL) + { + index = (c - '0'); + } + else + { + xpos += 6; /* space */ + text++; + continue; + } + + ST_DrawSymbol(xpos, ypos, index, color); + xpos += symboldata[index].w; + + text++; + } +} + +int ST_GetCenterTextX(byte *text) // 8002AAF4 +{ + byte c; + int xpos, index; + + xpos = 0; + while (*text) + { + c = *text; + + if(c >= 'A' && c <= 'Z') + { + index = (c - 'A') + 16; + } + else if(c >= 'a' && c <= 'z') + { + index = (c - 'a') + 42; + } + else if(c >= '0' && c <= '9') + { + index = (c - '0') + 0; + } + else if (c == '!') + { + index = 12; + } + else if (c == '-') + { + index = 10; + } + else if (c == '.') + { + index = 13; + } + else if (c == ':') + { + index = 15; + } + else if (c == '?') + { + index = 14; + } + else if (c == '%') + { + index = 11; + } + else if(c >= FIRST_SYMBOL && c <= LAST_SYMBOL) + { + index = (c - '0'); + } + else + { + xpos += 6; /* space */ + text++; + continue; + } + + xpos += symboldata[index].w; + + text++; + } + + return (320 - xpos) / 2; +} + +#define ST_MAXDMGCOUNT 144 +#define ST_MAXSTRCOUNT 32 +#define ST_MAXBONCOUNT 100 + +void ST_UpdateFlash(void) // 8002AC30 +{ + player_t *plyr; + int cnt; + int bzc; + int bnc; + + + plyr = &players[0]; + + if ((plyr->powers[pw_infrared] < 120) && infraredFactor) + { + infraredFactor -= 4; + if (infraredFactor < 0) { + infraredFactor = 0; + } + + P_RefreshBrightness(); + } + + /* invulnerability flash (white) */ + if (plyr->powers[pw_invulnerability] >= 61 || plyr->powers[pw_invulnerability] & 8) + { + FlashEnvColor = PACKRGBA(128, 128, 128, 255); + } + /* bfg flash (green)*/ + else if(plyr->bfgcount) + { + FlashEnvColor = PACKRGBA(0, plyr->bfgcount, 0, 255); + } + else + { + /* damage and strength flash (red) */ + cnt = plyr->damagecount; + + if (cnt) + { + if((cnt + 16) > ST_MAXDMGCOUNT) + cnt = ST_MAXDMGCOUNT; + } + + if (plyr->powers[pw_strength] <= ST_MAXSTRCOUNT) + { + /* slowly fade the berzerk out */ + bzc = plyr->powers[pw_strength]; + + if (bzc == 1) + bzc = 0; + } + else + { + bzc = ST_MAXSTRCOUNT; + } + + if ((cnt != 0) || (bzc != 0)) + { + if (bzc < cnt) + { + FlashEnvColor = PACKRGBA(cnt, 0, 0, 255); + } + else + { + FlashEnvColor = PACKRGBA(bzc, 0, 0, 255); + } + } + /* suit flash (green/yellow) */ + else if(plyr->powers[pw_ironfeet] >= 61 || plyr->powers[pw_ironfeet] & 8) + { + FlashEnvColor = PACKRGBA(0, 32, 4, 255); + } + /* bonus flash (yellow) */ + else if (plyr->bonuscount) + { + cnt = (plyr->bonuscount + 7) >> 3; + + if (cnt > ST_MAXBONCOUNT) + cnt = ST_MAXBONCOUNT; + + bnc = (cnt << 2) + cnt << 1; + + FlashEnvColor = PACKRGBA(bnc, bnc, cnt, 255); + } + else + { + FlashEnvColor = PACKRGBA(0, 0, 0, 255); /* Default Flash */ + } + } +} + +void ST_DrawSymbol(int xpos, int ypos, int index, int color) // 8002ADEC +{ + symboldata_t *symbol; + byte *data; + int offset; + + data = W_CacheLumpNum(sumbolslump, PU_CACHE, dec_jag); + + if (sumbolslump != globallump) + { + gDPPipeSync(GFX1++); + gDPSetCycleType(GFX1++, G_CYC_1CYCLE); + + gDPSetTextureLUT(GFX1++, G_TT_RGBA16); + gDPSetTexturePersp(GFX1++, G_TP_NONE); + + gDPSetAlphaCompare(GFX1++, G_AC_THRESHOLD); + gDPSetBlendColor(GFX1++, 0, 0, 0, 0); + + gDPSetCombineMode(GFX1++, G_CC_D64COMB04, G_CC_D64COMB04); + gDPSetRenderMode(GFX1++, G_RM_XLU_SURF_CLAMP, G_RM_XLU_SURF2_CLAMP); + + // Load Palette Data + offset = (((gfxN64_t*)data)->width * ((gfxN64_t*)data)->height); + offset = (offset + 7) & ~7; + gDPSetTextureImage(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_16b , + 1, data + offset + sizeof(gfxN64_t)); + + gDPTileSync(GFX1++); + gDPSetTile(GFX1++, G_IM_FMT_RGBA, G_IM_SIZ_4b, 0, 256, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0); + + gDPLoadSync(GFX1++); + gDPLoadTLUTCmd(GFX1++, G_TX_LOADTILE, 255); + + gDPPipeSync(GFX1++); + + globallump = sumbolslump; + } + + gDPSetPrimColorD64(GFX1++, 0, 0, color) + + // Load Image Data + gDPSetTextureImage(GFX1++, G_IM_FMT_CI, G_IM_SIZ_8b , + ((gfxN64_t*)data)->width, data + sizeof(gfxN64_t)); + + symbol = &symboldata[index]; + + // Clip Rectangle From Image + gDPSetTile(GFX1++, G_IM_FMT_CI, G_IM_SIZ_8b, + (symbol->w + 8) / 8, 0, G_TX_LOADTILE, 0, 0, 0, 0, 0, 0, 0); + + gDPLoadSync(GFX1++); + gDPLoadTile(GFX1++, G_TX_LOADTILE, + (symbol->x << 2), (symbol->y << 2), + ((symbol->x + symbol->w) << 2), ((symbol->y + symbol->h) << 2)); + + gDPPipeSync(GFX1++); + gDPSetTile(GFX1++, G_IM_FMT_CI, G_IM_SIZ_8b, + (symbol->w + 8) / 8, 0, G_TX_RENDERTILE, 0, 0, 0, 0, 0, 0, 0); + + gDPSetTileSize(GFX1++, G_TX_RENDERTILE, + (symbol->x << 2), (symbol->y << 2), + ((symbol->x + symbol->w) << 2), ((symbol->y + symbol->h) << 2)); + + gSPTextureRectangle(GFX1++, + (xpos << 2), (ypos << 2), + ((xpos + symbol->w) << 2), ((ypos + symbol->h) << 2), + G_TX_RENDERTILE, + (symbol->x << 5), (symbol->y << 5), + (1 << 10), (1 << 10)); +} + +#include "STDARG.H" + + +void ST_DebugSetPrintPos(int x, int y) +{ + debugX = x; + debugY = y; +} + +void ST_DebugPrint(const char *text, ...) +{ + if(debug) + { + va_list args; + va_start (args, text); + D_vsprintf (buffer[debugcnt], text, args); + va_end (args); + + debugcnt += 1; + debugcnt &= 15; + } + + //debugY += 8; +} diff --git a/Doom 64/st_main.h b/Doom 64/st_main.h @@ -0,0 +1,49 @@ + +#define FLASHDELAY 8 /* # of tics delay (1/30 sec) */ +#define FLASHTIMES 6 /* # of times to flash new frag amount (EVEN!) */ + +typedef struct +{ + int active; + int doDraw; + int delay; + int times; +} sbflash_t; + +extern sbflash_t flashCards[6]; // 800A8180 +extern boolean tryopen[6]; // 800A81E0 + +extern byte *sfontlump; // 800A81F8 +extern byte *statuslump; // 800A81FC +extern int sumbolslump; // 800A8204 + +extern int err_text_x; // 800A8208 +extern int err_text_y; // 800A820C + +#define FIRST_SYMBOL 0x80 +#define LAST_SYMBOL 0x90 // 0x91 for Right arrow + +typedef struct +{ + int x; + int y; + int w; + int h; +} symboldata_t; + +extern symboldata_t symboldata[];// 8005B260 + +void ST_Init(void); // 80029BA0 +void ST_InitEveryLevel(void); // 80029C00 +void ST_Ticker (void); // 80029C88 +void ST_Drawer (void); // 80029DC0 +void ST_Message(int x,int y,char *text,int color); // 8002A36C +void ST_DrawNumber(int x, int y, int val, int mode, int color); // 8002A79C +void ST_DrawString(int x, int y, char *text, int color); // 8002A930 +int ST_GetCenterTextX(byte *text); // 8002AAF4 +void ST_UpdateFlash(void); // 8002AC30 +void ST_DrawSymbol(int xpos, int ypos, int index, int color); // 8002ADEC + +// Debug +void ST_DebugSetPrintPos(int x, int y); +void ST_DebugPrint(const char *text, ...); diff --git a/Doom 64/stdarg.h b/Doom 64/stdarg.h @@ -0,0 +1,27 @@ +/* + * File:stdarg.h + */ +/* + * $PSLibId: Run-time Library Release 4.6$ + */ + +#ifndef _STDARG_H +#define _STDARG_H + + +#define __va_rounded_size(TYPE) \ + (((sizeof (TYPE) + sizeof (int) - 1) / sizeof (int)) * sizeof (int)) + +#define va_start(AP, LASTARG) \ + (AP = ((char *)&(LASTARG) + __va_rounded_size(LASTARG))) + +#define va_end(AP) AP = (char *)NULL + +#define va_arg(AP, TYPE) \ + (AP = ((char *) (AP)) += __va_rounded_size (TYPE), \ + *((TYPE *) ((char *) (AP) - __va_rounded_size (TYPE)))) + + +typedef void *va_list; + +#endif /* _STDARG_H */ diff --git a/Doom 64/tables.c b/Doom 64/tables.c @@ -0,0 +1,263 @@ +#include "doomdef.h" + +fixed_t finesine[10240]; // 800A8210 + +angle_t tantoangle[2049] = { // 8005b894 +0,333772,667544,1001315,1335086,1668857,2002626,2336395, +2670163,3003929,3337694,3671457,4005219,4338979,4672736,5006492, +5340245,5673995,6007743,6341488,6675230,7008968,7342704,7676435, +8010164,8343888,8677609,9011325,9345037,9678744,10012447,10346145, +10679838,11013526,11347209,11680887,12014558,12348225,12681885,13015539, +13349187,13682829,14016464,14350092,14683714,15017328,15350936,15684536, +16018129,16351714,16685291,17018860,17352422,17685974,18019518,18353054, +18686582,19020100,19353610,19687110,20020600,20354080,20687552,21021014, +21354466,21687906,22021338,22354758,22688168,23021568,23354956,23688332, +24021698,24355052,24688396,25021726,25355046,25688352,26021648,26354930, +26688200,27021456,27354702,27687932,28021150,28354356,28687548,29020724, +29353888,29687038,30020174,30353296,30686404,31019496,31352574,31685636, +32018684,32351718,32684734,33017736,33350722,33683692,34016648,34349584, +34682508,35015412,35348300,35681172,36014028,36346868,36679688,37012492, +37345276,37678044,38010792,38343524,38676240,39008936,39341612,39674272, +40006912,40339532,40672132,41004716,41337276,41669820,42002344,42334848, +42667332,42999796,43332236,43664660,43997060,44329444,44661800,44994140, +45326456,45658752,45991028,46323280,46655512,46987720,47319908,47652072, +47984212,48316332,48648428,48980500,49312548,49644576,49976580,50308556, +50640512,50972444,51304352,51636236,51968096,52299928,52631740,52963524, +53295284,53627020,53958728,54290412,54622068,54953704,55285308,55616888, +55948444,56279972,56611472,56942948,57274396,57605816,57937212,58268576, +58599916,58931228,59262512,59593768,59924992,60256192,60587364,60918508, +61249620,61580704,61911760,62242788,62573788,62904756,63235692,63566604, +63897480,64228332,64559148,64889940,65220696,65551424,65882120,66212788, +66543420,66874024,67204600,67535136,67865648,68196120,68526568,68856984, +69187360,69517712,69848024,70178304,70508560,70838776,71168960,71499112, +71829224,72159312,72489360,72819376,73149360,73479304,73809216,74139096, +74468936,74798744,75128520,75458264,75787968,76117632,76447264,76776864, +77106424,77435952,77765440,78094888,78424304,78753688,79083032,79412336, +79741608,80070840,80400032,80729192,81058312,81387392,81716432,82045440, +82374408,82703336,83032224,83361080,83689896,84018664,84347400,84676096, +85004760,85333376,85661952,85990488,86318984,86647448,86975864,87304240, +87632576,87960872,88289128,88617344,88945520,89273648,89601736,89929792, +90257792,90585760,90913688,91241568,91569408,91897200,92224960,92552672, +92880336,93207968,93535552,93863088,94190584,94518040,94845448,95172816, +95500136,95827416,96154648,96481832,96808976,97136080,97463136,97790144, +98117112,98444032,98770904,99097736,99424520,99751256,100077944,100404592, +100731192,101057744,101384248,101710712,102037128,102363488,102689808,103016080, +103342312,103668488,103994616,104320696,104646736,104972720,105298656,105624552, +105950392,106276184,106601928,106927624,107253272,107578872,107904416,108229920, +108555368,108880768,109206120,109531416,109856664,110181872,110507016,110832120, +111157168,111482168,111807112,112132008,112456856,112781648,113106392,113431080, +113755720,114080312,114404848,114729328,115053760,115378136,115702464,116026744, +116350960,116675128,116999248,117323312,117647320,117971272,118295176,118619024, +118942816,119266560,119590248,119913880,120237456,120560984,120884456,121207864, +121531224,121854528,122177784,122500976,122824112,123147200,123470224,123793200, +124116120,124438976,124761784,125084528,125407224,125729856,126052432,126374960, +126697424,127019832,127342184,127664472,127986712,128308888,128631008,128953072, +129275080,129597024,129918912,130240744,130562520,130884232,131205888,131527480, +131849016,132170496,132491912,132813272,133134576,133455816,133776992,134098120, +134419184,134740176,135061120,135382000,135702816,136023584,136344272,136664912, +136985488,137306016,137626464,137946864,138267184,138587456,138907664,139227808, +139547904,139867920,140187888,140507776,140827616,141147392,141467104,141786752, +142106336,142425856,142745312,143064720,143384048,143703312,144022512,144341664, +144660736,144979744,145298704,145617584,145936400,146255168,146573856,146892480, +147211040,147529536,147847968,148166336,148484640,148802880,149121056,149439152, +149757200,150075168,150393072,150710912,151028688,151346400,151664048,151981616, +152299136,152616576,152933952,153251264,153568496,153885680,154202784,154519824, +154836784,155153696,155470528,155787296,156104000,156420624,156737200,157053696, +157370112,157686480,158002768,158318976,158635136,158951216,159267232,159583168, +159899040,160214848,160530592,160846256,161161840,161477376,161792832,162108208, +162423520,162738768,163053952,163369040,163684080,163999040,164313936,164628752, +164943504,165258176,165572784,165887312,166201776,166516160,166830480,167144736, +167458912,167773008,168087040,168400992,168714880,169028688,169342432,169656096, +169969696,170283216,170596672,170910032,171223344,171536576,171849728,172162800, +172475808,172788736,173101600,173414384,173727104,174039728,174352288,174664784, +174977200,175289536,175601792,175913984,176226096,176538144,176850096,177161984, +177473792,177785536,178097200,178408784,178720288,179031728,179343088,179654368, +179965568,180276704,180587744,180898720,181209616,181520448,181831184,182141856, +182452448,182762960,183073408,183383760,183694048,184004240,184314368,184624416, +184934400,185244288,185554096,185863840,186173504,186483072,186792576,187102000, +187411344,187720608,188029808,188338912,188647936,188956896,189265760,189574560, +189883264,190191904,190500448,190808928,191117312,191425632,191733872,192042016, +192350096,192658096,192966000,193273840,193581584,193889264,194196848,194504352, +194811792,195119136,195426400,195733584,196040688,196347712,196654656,196961520, +197268304,197574992,197881616,198188144,198494592,198800960,199107248,199413456, +199719584,200025616,200331584,200637456,200943248,201248960,201554576,201860128, +202165584,202470960,202776256,203081456,203386592,203691632,203996592,204301472, +204606256,204910976,205215600,205520144,205824592,206128960,206433248,206737456, +207041584,207345616,207649568,207953424,208257216,208560912,208864512,209168048, +209471488,209774832,210078112,210381296,210684384,210987408,211290336,211593184, +211895936,212198608,212501184,212803680,213106096,213408432,213710672,214012816, +214314880,214616864,214918768,215220576,215522288,215823920,216125472,216426928, +216728304,217029584,217330784,217631904,217932928,218233856,218534704,218835472, +219136144,219436720,219737216,220037632,220337952,220638192,220938336,221238384, +221538352,221838240,222138032,222437728,222737344,223036880,223336304,223635664, +223934912,224234096,224533168,224832160,225131072,225429872,225728608,226027232, +226325776,226624240,226922608,227220880,227519056,227817152,228115168,228413088, +228710912,229008640,229306288,229603840,229901312,230198688,230495968,230793152, +231090256,231387280,231684192,231981024,232277760,232574416,232870960,233167440, +233463808,233760096,234056288,234352384,234648384,234944304,235240128,235535872, +235831504,236127056,236422512,236717888,237013152,237308336,237603424,237898416, +238193328,238488144,238782864,239077488,239372016,239666464,239960816,240255072, +240549232,240843312,241137280,241431168,241724960,242018656,242312256,242605776, +242899200,243192512,243485744,243778896,244071936,244364880,244657744,244950496, +245243168,245535744,245828224,246120608,246412912,246705104,246997216,247289216, +247581136,247872960,248164688,248456320,248747856,249039296,249330640,249621904, +249913056,250204128,250495088,250785968,251076736,251367424,251658016,251948512, +252238912,252529200,252819408,253109520,253399536,253689456,253979280,254269008, +254558640,254848176,255137632,255426976,255716224,256005376,256294432,256583392, +256872256,257161024,257449696,257738272,258026752,258315136,258603424,258891600, +259179696,259467696,259755600,260043392,260331104,260618704,260906224,261193632, +261480960,261768176,262055296,262342320,262629248,262916080,263202816,263489456, +263776000,264062432,264348784,264635024,264921168,265207216,265493168,265779024, +266064784,266350448,266636000,266921472,267206832,267492096,267777264,268062336, +268347312,268632192,268916960,269201632,269486208,269770688,270055072,270339360, +270623552,270907616,271191616,271475488,271759296,272042976,272326560,272610048, +272893440,273176736,273459936,273743040,274026048,274308928,274591744,274874432, +275157024,275439520,275721920,276004224,276286432,276568512,276850528,277132416, +277414240,277695936,277977536,278259040,278540448,278821728,279102944,279384032, +279665056,279945952,280226752,280507456,280788064,281068544,281348960,281629248, +281909472,282189568,282469568,282749440,283029248,283308960,283588544,283868032, +284147424,284426720,284705920,284985024,285264000,285542912,285821696,286100384, +286378976,286657440,286935840,287214112,287492320,287770400,288048384,288326240, +288604032,288881696,289159264,289436768,289714112,289991392,290268576,290545632, +290822592,291099456,291376224,291652896,291929440,292205888,292482272,292758528, +293034656,293310720,293586656,293862496,294138240,294413888,294689440,294964864, +295240192,295515424,295790560,296065600,296340512,296615360,296890080,297164704, +297439200,297713632,297987936,298262144,298536256,298810240,299084160,299357952, +299631648,299905248,300178720,300452128,300725408,300998592,301271680,301544640, +301817536,302090304,302362976,302635520,302908000,303180352,303452608,303724768, +303996800,304268768,304540608,304812320,305083968,305355520,305626944,305898272, +306169472,306440608,306711616,306982528,307253344,307524064,307794656,308065152, +308335552,308605856,308876032,309146112,309416096,309685984,309955744,310225408, +310494976,310764448,311033824,311303072,311572224,311841280,312110208,312379040, +312647776,312916416,313184960,313453376,313721696,313989920,314258016,314526016, +314793920,315061728,315329408,315597024,315864512,316131872,316399168,316666336, +316933408,317200384,317467232,317733984,318000640,318267200,318533632,318799968, +319066208,319332352,319598368,319864288,320130112,320395808,320661408,320926912, +321192320,321457632,321722816,321987904,322252864,322517760,322782528,323047200, +323311744,323576192,323840544,324104800,324368928,324632992,324896928,325160736, +325424448,325688096,325951584,326215008,326478304,326741504,327004608,327267584, +327530464,327793248,328055904,328318496,328580960,328843296,329105568,329367712, +329629760,329891680,330153536,330415264,330676864,330938400,331199808,331461120, +331722304,331983392,332244384,332505280,332766048,333026752,333287296,333547776, +333808128,334068384,334328544,334588576,334848512,335108352,335368064,335627712, +335887200,336146624,336405920,336665120,336924224,337183200,337442112,337700864, +337959552,338218112,338476576,338734944,338993184,339251328,339509376,339767296, +340025120,340282848,340540480,340797984,341055392,341312704,341569888,341826976, +342083968,342340832,342597600,342854272,343110848,343367296,343623648,343879904, +344136032,344392064,344648000,344903808,345159520,345415136,345670656,345926048, +346181344,346436512,346691616,346946592,347201440,347456224,347710880,347965440, +348219872,348474208,348728448,348982592,349236608,349490528,349744320,349998048, +350251648,350505152,350758528,351011808,351264992,351518048,351771040,352023872, +352276640,352529280,352781824,353034272,353286592,353538816,353790944,354042944, +354294880,354546656,354798368,355049952,355301440,355552800,355804096,356055264, +356306304,356557280,356808128,357058848,357309504,357560032,357810464,358060768, +358311008,358561088,358811104,359060992,359310784,359560480,359810048,360059520, +360308896,360558144,360807296,361056352,361305312,361554144,361802880,362051488, +362300032,362548448,362796736,363044960,363293056,363541024,363788928,364036704, +364284384,364531936,364779392,365026752,365274016,365521152,365768192,366015136, +366261952,366508672,366755296,367001792,367248192,367494496,367740704,367986784, +368232768,368478656,368724416,368970080,369215648,369461088,369706432,369951680, +370196800,370441824,370686752,370931584,371176288,371420896,371665408,371909792, +372154080,372398272,372642336,372886304,373130176,373373952,373617600,373861152, +374104608,374347936,374591168,374834304,375077312,375320224,375563040,375805760, +376048352,376290848,376533248,376775520,377017696,377259776,377501728,377743584, +377985344,378227008,378468544,378709984,378951328,379192544,379433664,379674688, +379915584,380156416,380397088,380637696,380878176,381118560,381358848,381599040, +381839104,382079072,382318912,382558656,382798304,383037856,383277280,383516640, +383755840,383994976,384233984,384472896,384711712,384950400,385188992,385427488, +385665888,385904160,386142336,386380384,386618368,386856224,387093984,387331616, +387569152,387806592,388043936,388281152,388518272,388755296,388992224,389229024, +389465728,389702336,389938816,390175200,390411488,390647680,390883744,391119712, +391355584,391591328,391826976,392062528,392297984,392533312,392768544,393003680, +393238720,393473632,393708448,393943168,394177760,394412256,394646656,394880960, +395115136,395349216,395583200,395817088,396050848,396284512,396518080,396751520, +396984864,397218112,397451264,397684288,397917248,398150080,398382784,398615424, +398847936,399080320,399312640,399544832,399776928,400008928,400240832,400472608, +400704288,400935872,401167328,401398720,401629984,401861120,402092192,402323136, +402553984,402784736,403015360,403245888,403476320,403706656,403936896,404167008, +404397024,404626944,404856736,405086432,405316032,405545536,405774912,406004224, +406233408,406462464,406691456,406920320,407149088,407377760,407606336,407834784, +408063136,408291392,408519520,408747584,408975520,409203360,409431072,409658720, +409886240,410113664,410340992,410568192,410795296,411022304,411249216,411476032, +411702720,411929312,412155808,412382176,412608480,412834656,413060736,413286720, +413512576,413738336,413964000,414189568,414415040,414640384,414865632,415090784, +415315840,415540800,415765632,415990368,416215008,416439552,416663968,416888288, +417112512,417336640,417560672,417784576,418008384,418232096,418455712,418679200, +418902624,419125920,419349120,419572192,419795200,420018080,420240864,420463552, +420686144,420908608,421130976,421353280,421575424,421797504,422019488,422241344, +422463104,422684768,422906336,423127776,423349120,423570400,423791520,424012576, +424233536,424454368,424675104,424895744,425116288,425336736,425557056,425777280, +425997408,426217440,426437376,426657184,426876928,427096544,427316064,427535488, +427754784,427974016,428193120,428412128,428631040,428849856,429068544,429287168, +429505664,429724064,429942368,430160576,430378656,430596672,430814560,431032352, +431250048,431467616,431685120,431902496,432119808,432336992,432554080,432771040, +432987936,433204736,433421408,433637984,433854464,434070848,434287104,434503296, +434719360,434935360,435151232,435367008,435582656,435798240,436013696,436229088, +436444352,436659520,436874592,437089568,437304416,437519200,437733856,437948416, +438162880,438377248,438591520,438805696,439019744,439233728,439447584,439661344, +439875008,440088576,440302048,440515392,440728672,440941824,441154880,441367872, +441580736,441793472,442006144,442218720,442431168,442643552,442855808,443067968, +443280032,443492000,443703872,443915648,444127296,444338880,444550336,444761696, +444972992,445184160,445395232,445606176,445817056,446027840,446238496,446449088, +446659552,446869920,447080192,447290400,447500448,447710432,447920320,448130112, +448339776,448549376,448758848,448968224,449177536,449386720,449595808,449804800, +450013664,450222464,450431168,450639776,450848256,451056640,451264960,451473152, +451681248,451889248,452097152,452304960,452512672,452720288,452927808,453135232, +453342528,453549760,453756864,453963904,454170816,454377632,454584384,454791008, +454997536,455203968,455410304,455616544,455822688,456028704,456234656,456440512, +456646240,456851904,457057472,457262912,457468256,457673536,457878688,458083744, +458288736,458493600,458698368,458903040,459107616,459312096,459516480,459720768, +459924960,460129056,460333056,460536960,460740736,460944448,461148064,461351584, +461554976,461758304,461961536,462164640,462367680,462570592,462773440,462976160, +463178816,463381344,463583776,463786144,463988384,464190560,464392608,464594560, +464796448,464998208,465199872,465401472,465602944,465804320,466005600,466206816, +466407904,466608896,466809824,467010624,467211328,467411936,467612480,467812896, +468013216,468213440,468413600,468613632,468813568,469013440,469213184,469412832, +469612416,469811872,470011232,470210528,470409696,470608800,470807776,471006688, +471205472,471404192,471602784,471801312,471999712,472198048,472396288,472594400, +472792448,472990400,473188256,473385984,473583648,473781216,473978688,474176064, +474373344,474570528,474767616,474964608,475161504,475358336,475555040,475751648, +475948192,476144608,476340928,476537184,476733312,476929376,477125344,477321184, +477516960,477712640,477908224,478103712,478299104,478494400,478689600,478884704, +479079744,479274656,479469504,479664224,479858880,480053408,480247872,480442240, +480636512,480830656,481024736,481218752,481412640,481606432,481800128,481993760, +482187264,482380704,482574016,482767264,482960416,483153472,483346432,483539296, +483732064,483924768,484117344,484309856,484502240,484694560,484886784,485078912, +485270944,485462880,485654720,485846464,486038144,486229696,486421184,486612576, +486803840,486995040,487186176,487377184,487568096,487758912,487949664,488140320, +488330880,488521312,488711712,488901984,489092160,489282240,489472256,489662176, +489851968,490041696,490231328,490420896,490610336,490799712,490988960,491178144, +491367232,491556224,491745120,491933920,492122656,492311264,492499808,492688256, +492876608,493064864,493253056,493441120,493629120,493817024,494004832,494192544, +494380160,494567712,494755136,494942496,495129760,495316928,495504000,495691008, +495877888,496064704,496251424,496438048,496624608,496811040,496997408,497183680, +497369856,497555936,497741920,497927840,498113632,498299360,498484992,498670560, +498856000,499041376,499226656,499411840,499596928,499781920,499966848,500151680, +500336416,500521056,500705600,500890080,501074464,501258752,501442944,501627040, +501811072,501995008,502178848,502362592,502546240,502729824,502913312,503096704, +503280000,503463232,503646368,503829408,504012352,504195200,504377984,504560672, +504743264,504925760,505108192,505290496,505472736,505654912,505836960,506018944, +506200832,506382624,506564320,506745952,506927488,507108928,507290272,507471552, +507652736,507833824,508014816,508195744,508376576,508557312,508737952,508918528, +509099008,509279392,509459680,509639904,509820032,510000064,510180000,510359872, +510539648,510719328,510898944,511078432,511257856,511437216,511616448,511795616, +511974688,512153664,512332576,512511392,512690112,512868768,513047296,513225792, +513404160,513582432,513760640,513938784,514116800,514294752,514472608,514650368, +514828064,515005664,515183168,515360608,515537952,515715200,515892352,516069440, +516246432,516423328,516600160,516776896,516953536,517130112,517306592,517482976, +517659264,517835488,518011616,518187680,518363648,518539520,518715296,518891008, +519066624,519242144,519417600,519592960,519768256,519943424,520118528,520293568, +520468480,520643328,520818112,520992800,521167392,521341888,521516320,521690656, +521864896,522039072,522213152,522387168,522561056,522734912,522908640,523082304, +523255872,523429376,523602784,523776096,523949312,524122464,524295552,524468512, +524641440,524814240,524986976,525159616,525332192,525504640,525677056,525849344, +526021568,526193728,526365792,526537760,526709632,526881440,527053152,527224800, +527396352,527567840,527739200,527910528,528081728,528252864,528423936,528594880, +528765760,528936576,529107296,529277920,529448480,529618944,529789344,529959648, +530129856,530300000,530470048,530640000,530809888,530979712,531149440,531319072, +531488608,531658080,531827488,531996800,532166016,532335168,532504224,532673184, +532842080,533010912,533179616,533348288,533516832,533685312,533853728,534022048, +534190272,534358432,534526496,534694496,534862400,535030240,535197984,535365632, +535533216,535700704,535868128,536035456,536202720,536369888,536536992,536704000, +536870912 +}; diff --git a/Doom 64/vsprintf.c b/Doom 64/vsprintf.c @@ -0,0 +1,123 @@ + + +int mystrlen(char *string) // 80001CE8 +{ + int rc = 0; + if (string) while (*(string++)) rc++; + else rc = -1; + return rc; +} + +int D_vsprintf(char *string, const char *format, int *argptr) // 80001D24 +{ + int len, i, div, uselong; + int fieldsize; + unsigned long num; + long snum; + char padchar; + char *str; + char *origstring = string; + + while (*format) + { + if (*format != '%') *(string++) = *(format++); + else + { + format++; + + /* set field pad character to 0 if necessary */ + if (*format == '0') + { + padchar = '0'; + format++; + } + else padchar = ' '; + + /* get the fieldwidth if any */ + fieldsize = 0; + while (*format >= '0' && *format <= '9') + fieldsize = fieldsize * 10 + *(format++) - '0'; + + /* get rid of 'l' if present */ + if (*format == 'l') + { + uselong = 1; + format++; + } else uselong = 0; + + div = 10; + if (*format == 'c') + { + *(string++) = *argptr++; + format++; + } + else if (*format == 's') + { + str = (char *)*argptr++; + len = mystrlen(str); + while (fieldsize-- > len) *(string++) = padchar; /* do field pad */ + while (*str) *(string++) = *(str++); /* copy string */ + format++; + } + else + { + if (*format == 'o') /* octal */ + { + div = 8; + if (uselong) + num = *argptr++; + else + num = *argptr++; +/* printf("o=0%o\n", num); */ + } + else if (*format == 'x' || *format == 'X') /* hex */ + { + div = 16; + if (uselong) + num = *argptr++; + else + num = *argptr++; +/* printf("x=%x\n", num); */ + } + else if (*format == 'i' || *format == 'd' || *format == 'u') /* decimal */ + { + div = 10; + if (uselong) + snum = *argptr++; + else + snum = *argptr++; + if (snum < 0 && *format != 'u') /* handle negative %i or %d */ + { + *(string++) = '-'; + num = -snum; + if (fieldsize) fieldsize--; + } else num = snum; + } + else return -1; /* unrecognized format specifier */ + + /* print any decimal or hex integer */ + len = 0; + while (num || fieldsize || !len) + { + for (i=len ; i ; i--) string[i] = string[i-1]; /* shift right */ + if (len && fieldsize && !num) *string = padchar; /* pad out */ + else + { + /* put in a hex or decimal digit */ + *string = num % div; + *string += *string > 9 ? 'A'-10 : '0'; +/* printf("d = %c\n", *string); */ + num /= div; + } + len++; + if (fieldsize) fieldsize--; + } + string += len; + format++; + } + } + } + *string = 0; + + return origstring - string; +} diff --git a/Doom 64/w_wad.c b/Doom 64/w_wad.c @@ -0,0 +1,478 @@ +/* W_wad.c */ + +#include "doomdef.h" +//#include "r_local.h" + +#include "graph.h" +//char str[64]; + +/*=============== */ +/* TYPES */ +/*=============== */ + + +typedef struct +{ + char identification[4]; /* should be IWAD */ + int numlumps; + int infotableofs; +} wadinfo_t; + +/*============= */ +/* GLOBALS */ +/*============= */ + +static lumpcache_t *lumpcache; //800B2220 +static int numlumps; //800B2224 +static lumpinfo_t *lumpinfo; //800B2228 /* points directly to rom image */ + +static int mapnumlumps; //800B2230 psxdoom/doom64 +static lumpinfo_t *maplump; //800B2234 psxdoom/doom64 +static byte *mapfileptr; //800B2238 psxdoom/doom64 + + +/*=========*/ +/* EXTERNS */ +/*=========*/ + +extern OSMesgQueue romcopy_msgque; +extern char _doom64_wadSegmentRomStart[], _doom64_wadSegmentRomEnd[]; + +/* +============================================================================ + + LUMP BASED ROUTINES + +============================================================================ +*/ + +/* +==================== += += W_Init += +==================== +*/ + +void W_Init (void) // 8002BEC0 +{ + OSIoMesg romio_msgbuf; + wadinfo_t *wadfileptr; + int infotableofs, i; + + wadfileptr = (wadinfo_t *)Z_Alloc(sizeof(wadinfo_t), PU_STATIC, NULL); + osInvalDCache((void *)wadfileptr, sizeof(wadinfo_t)); + + osPiStartDma(&romio_msgbuf, OS_MESG_PRI_NORMAL, OS_READ, + (u32)_doom64_wadSegmentRomStart, + (void *)wadfileptr, sizeof(wadinfo_t), &romcopy_msgque); + + osRecvMesg(&romcopy_msgque, NULL, OS_MESG_BLOCK); + + //sprintf(str, "identification %s",wadfileptr->identification); + //printstr(WHITE, 0, 4, str); + + if (D_strncasecmp(wadfileptr->identification, "IWAD", 4)) + I_Error("W_Init: invalid main IWAD id"); + + numlumps = LONGSWAP(wadfileptr->numlumps); + lumpinfo = (lumpinfo_t *) Z_Malloc(numlumps * sizeof(lumpinfo_t), PU_STATIC, 0); + osInvalDCache((void *)lumpinfo, numlumps * sizeof(lumpinfo_t)); + + infotableofs = LONGSWAP(wadfileptr->infotableofs); + + osPiStartDma(&romio_msgbuf, OS_MESG_PRI_NORMAL, OS_READ, + (u32)_doom64_wadSegmentRomStart + infotableofs, + (void *)lumpinfo, numlumps * sizeof(lumpinfo_t), &romcopy_msgque); + + osRecvMesg(&romcopy_msgque, NULL, OS_MESG_BLOCK); + + //sprintf(str, "identification %s",wadfileptr->identification); + //printstr(WHITE, 0, 4, str); + //sprintf(str, "numlumps %d",numlumps); + //printstr(WHITE, 0, 5, str); + //sprintf(str, "infotableofs %d",infotableofs); + //printstr(WHITE, 0, 6, str); + + for(i = 0; i < numlumps; i++) + { + lumpinfo[i].filepos = LONGSWAP(lumpinfo[i].filepos); + lumpinfo[i].size = LONGSWAP(lumpinfo[i].size); + + //sprintf(str, "filepos %d ",lumpinfo[i].filepos); + //printstr(WHITE, 0, 7, str); + //sprintf(str, "size %d ",lumpinfo[i].size); + //printstr(WHITE, 0, 8, str); + } + + lumpcache = (lumpcache_t *) Z_Malloc(numlumps * sizeof(lumpcache_t), PU_STATIC, 0); + D_memset(lumpcache, NULL, numlumps * sizeof(lumpcache_t)); + Z_Free(wadfileptr); +} + + +/* +==================== += += W_CheckNumForName += += Returns -1 if name not found += +==================== +*/ +//int W_CheckNumForName(char *name, int unk1, int hibit1, int hibit2) // original +int W_CheckNumForName(char *name, int hibit1, int hibit2) // 8002C0F4 removed unknown parameter +{ + char name8[12]; + char c, *tmp; + int i; + lumpinfo_t *lump_p; + + /* make the name into two integers for easy compares */ + + *(int *)&name8[4] = 0; + *(int *)&name8[0] = 0; + + tmp = name8; + while ((c = *name) != 0) + { + *tmp++ = c; + + if ((tmp >= name8+8)) + break; + + name++; + } + + /* scan backwards so patch lump files take precedence */ + + lump_p = lumpinfo; + for(i = 0; i < numlumps; i++) + { + if ((*(int *)&name8[0] == (*(int *)&lump_p->name[0] & hibit1)) && + (*(int *)&name8[4] == (*(int *)&lump_p->name[4] & hibit2))) + return i; + + lump_p++; + } + + return -1; +} + +/* +==================== += += W_GetNumForName += += Calls W_CheckNumForName, but bombs out if not found += +==================== +*/ + +int W_GetNumForName (char *name) // 8002C1B8 +{ + int i; + + i = W_CheckNumForName (name, 0x7fffffff, 0xFFFFFFFF); + if (i != -1) + return i; + + I_Error ("W_GetNumForName: %s not found!",name); + return -1; +} + + +/* +==================== += += W_LumpLength += += Returns the buffer size needed to load the given lump += +==================== +*/ + +int W_LumpLength (int lump) // 8002C204 +{ + if ((lump < 0) || (lump >= numlumps)) + I_Error ("W_LumpLength: lump %i out of range",lump); + + return lumpinfo[lump].size; +} + + +/* +==================== += += W_ReadLump += += Loads the lump into the given buffer, which must be >= W_LumpLength() += +==================== +*/ + +void W_ReadLump (int lump, void *dest, decodetype dectype) // 8002C260 +{ + OSIoMesg romio_msgbuf; + byte *input; + lumpinfo_t *l; + int lumpsize; + + if ((lump < 0) || (lump >= numlumps)) + I_Error ("W_ReadLump: lump %i out of range",lump); + + l = &lumpinfo[lump]; + if(dectype != dec_none) + { + if ((l->name[0] & 0x80)) /* compressed */ + { + lumpsize = l[1].filepos - (l->filepos); + input = Z_Alloc(lumpsize, PU_STATIC, NULL); + + osInvalDCache((void *)input, lumpsize); + + osPiStartDma(&romio_msgbuf, OS_MESG_PRI_NORMAL, OS_READ, + (u32)_doom64_wadSegmentRomStart + l->filepos, + (void *)input, lumpsize, &romcopy_msgque); + + osRecvMesg(&romcopy_msgque, NULL, OS_MESG_BLOCK); + + if (dectype == dec_jag) + DecodeJaguar((byte *)input, (byte *)dest); + else // dec_d64 + DecodeD64((byte *)input, (byte *)dest); + + Z_Free(input); + return; + } + } + + if (l->name[0] & 0x80) + lumpsize = l[1].filepos - (l->filepos); + else + lumpsize = (l->size); + + osInvalDCache((void *)dest, lumpsize); + + osPiStartDma(&romio_msgbuf, OS_MESG_PRI_NORMAL, OS_READ, + (u32)_doom64_wadSegmentRomStart + l->filepos, + (void *)dest, lumpsize, &romcopy_msgque); + + osRecvMesg(&romcopy_msgque, NULL, OS_MESG_BLOCK); +} + +/* +==================== += += W_CacheLumpNum += +==================== +*/ + +void *W_CacheLumpNum (int lump, int tag, decodetype dectype) // 8002C430 +{ + int lumpsize; + lumpcache_t *lc; + + if ((lump < 0) || (lump >= numlumps)) + I_Error ("W_CacheLumpNum: lump %i out of range",lump); + + lc = &lumpcache[lump]; + + if (!lc->cache) + { /* read the lump in */ + //if (dectype == dec_d64) + //ST_DebugPrint("W_CacheLumpNum: lump %i", lump); + + if (dectype == dec_none) + lumpsize = lumpinfo[lump + 1].filepos - lumpinfo[lump].filepos; + else + lumpsize = lumpinfo[lump].size; + + Z_Malloc(lumpsize, tag, &lc->cache); + + W_ReadLump(lump, lc->cache, dectype); + } + else + { + if (tag & PU_CACHE) { + Z_Touch(lc->cache); + } + } + + return lc->cache; +} + +/* +==================== += += W_CacheLumpName += +==================== +*/ + +void *W_CacheLumpName (char *name, int tag, decodetype dectype) // 8002C57C +{ + return W_CacheLumpNum (W_GetNumForName(name), tag, dectype); +} + + +/* +============================================================================ + +MAP LUMP BASED ROUTINES + +============================================================================ +*/ + +/* +==================== += += W_OpenMapWad += += Exclusive Psx Doom / Doom64 +==================== +*/ + +void W_OpenMapWad(int mapnum) // 8002C5B0 +{ + int lump, size, infotableofs, i; + char name [8]; + + name[0] = 'M'; + name[1] = 'A'; + name[2] = 'P'; + name[3] = '0' + (char)(mapnum / 10); + name[4] = '0' + (char)(mapnum % 10); + name[5] = NULL; + + lump = W_GetNumForName(name); + size = W_LumpLength(lump); + + //sprintf(str, "name %s ",name); + //printstr(WHITE, 0, 7, str); + //sprintf(str, "lump %d ",lump); + //printstr(WHITE, 0, 8, str); + //sprintf(str, "size %d ",size); + //printstr(WHITE, 0, 9, str); + + mapfileptr = Z_Alloc(size, PU_STATIC, NULL); + + W_ReadLump(lump, mapfileptr, dec_d64); + + mapnumlumps = LONGSWAP(((wadinfo_t*)mapfileptr)->numlumps); + infotableofs = LONGSWAP(((wadinfo_t*)mapfileptr)->infotableofs); + + //sprintf(str, "mapnumlumps %d ",mapnumlumps); + //printstr(WHITE, 0, 10, str); + //sprintf(str, "infotableofs %d ",infotableofs); + //printstr(WHITE, 0, 11, str); + + maplump = (lumpinfo_t*)(mapfileptr + infotableofs); + + for(i = 0; i < mapnumlumps; i++) + { + maplump[i].filepos = LONGSWAP(maplump[i].filepos); + maplump[i].size = LONGSWAP(maplump[i].size); + } +} + +/* +==================== += += W_FreeMapLump += += Exclusive Doom64 +==================== +*/ + +void W_FreeMapLump(void) // 8002C748 +{ + Z_Free(mapfileptr); + mapnumlumps = 0; +} + +/* +==================== += += W_MapLumpLength += += Exclusive Psx Doom / Doom64 +==================== +*/ + +int W_MapLumpLength(int lump) // 8002C77C +{ + if (lump >= mapnumlumps) + I_Error("W_MapLumpLength: %i out of range", lump); + + return maplump[lump].size; +} + + +/* +==================== += += W_MapGetNumForName += += Exclusive Psx Doom / Doom64 +==================== +*/ + +int W_MapGetNumForName(char *name) // 8002C7D0 +{ + char name8[12]; + char c, *tmp; + int i; + lumpinfo_t *lump_p; + + /* make the name into two integers for easy compares */ + + *(int *)&name8[4] = 0; + *(int *)&name8[0] = 0; + + tmp = name8; + while ((c = *name) != 0) + { + *tmp++ = c; + + if ((tmp >= name8+8)) + break; + + name++; + } + + /* scan backwards so patch lump files take precedence */ + + lump_p = maplump; + for(i = 0; i < mapnumlumps; i++) + { + if ((*(int *)&name8[0] == (*(int *)&lump_p->name[0] & 0x7fffffff)) && + (*(int *)&name8[4] == (*(int *)&lump_p->name[4]))) + return i; + + lump_p++; + } + + return -1; +} + +/* +==================== += += W_GetMapLump += += Exclusive Doom64 +==================== +*/ + +void *W_GetMapLump(int lump) // 8002C890 +{ + lumpinfo_t *l; + int lumpsize; + + if (lump >= mapnumlumps) + I_Error("W_GetMapLump: lump %d out of range", lump); + + return (void *) ((byte *)mapfileptr + maplump[lump].filepos); +} diff --git a/Doom 64/wessapi.c b/Doom 64/wessapi.c @@ -0,0 +1,1324 @@ + +/* WESS API INCLUDES */ +#include "wessapi.h" // audio stuff... +#include "seqload.h" +#include "soundhw.h" +#include "wessarc.h" +#include "wessseq.h" + +#include "funqueue.h" + +#include "graph.h" // debug + +#ifndef NOUSEWESSCODE +//./seqload.h +//./wessapi.h +//./wessseq.h +//./funqueue.h + +#define _ALIGN4_ 1 +#define _ALIGN8_ 1 + +extern void (**CmdFuncArr[10])(track_status *); + +module_data tmp_moddata; //0x800B4160 +patch_group_data tmp_patgrpdata; //0x800B4188 +pmasterstat tmp_mss; //0x800B41A8 +pmasterstat *pm_stat; //0x800B41CC + +Wess_File_IO_Struct *fp_wmd_file;//8005D8D0 +int sysinit;//8005D8D4 +int module_loaded;//8005D8D8 +int early_exit;//8005D8DC +int wmd_mem_is_mine;//8005D8E0 +char *wmd_mem;//8005D8E4 +char *wmd_end;//8005D8E8 +int wmd_size;//8005D8EC +static int(*Error_func)(int, int) = 0;//8005D8F0 +static int Error_module = 0;//8005D8F4 + +static void err(int code) // 8002F400 +{ + if (Error_func) { + Error_func(Error_module, code); + } +} + +static void zeroset(char *pdest, unsigned long size) // 8002F438 +{ + while (size--) *pdest++ = 0; +} + +void wess_install_error_handler(int(*error_func)(int, int), int module) // 8002F460 +{ + Error_func = error_func; + Error_module = module; +} + +void * wess_get_master_status(void) // 8002F474 +{ + return pm_stat; +} + +int Is_System_Active(void) // 8002F484 +{ + if (!sysinit) + { + return 0; + } + return 1; +} + +int Is_Module_Loaded(void) // 8002F4A8 +{ + if (!module_loaded) + { + return 0; + } + return 1; +} + +int Is_Seq_Num_Valid(int seq_num) // 8002F4CC +{ + if ((seq_num >= 0) && (seq_num < wess_seq_loader_count())) + { + if ((pm_stat->pmod_info->pseq_info + seq_num)->ptrk_info) + { + return 1; + } + } + + return 0; + + /*if ((seq_num<0) || (seq_num >= wess_seq_loader_count())) + { + return 0; + } + else if ((pm_stat->pmod_info->pseq_info + seq_num)->ptrk_info == NULL) { + return 0; + } + return 1;*/ +} + +void Register_Early_Exit(void) // 8002F540 +{ + if (!early_exit) + { + early_exit = 1; + } +} + +void wess_install_handler(void) // 8002F564 +{ + init_WessTimer(); +} + +void wess_restore_handler(void) // 8002F584 +{ + exit_WessTimer(); +} + +/* used by wesssys_exit */ +enum RestoreFlag {NoRestore,YesRestore}; + +int wesssys_init(void) // 8002F5A4 +{ + int initok; + + initok = 0; + + if (!sysinit) + { + wess_engine_off(); /* make sure the SeqEngine is disabled */ + + if (!WessTimerActive) + { + wess_install_handler(); + } + + wess_low_level_init(); + sysinit = 1; + initok = 1; + } + return (initok); +} + +void wesssys_exit(enum RestoreFlag rflag) // 8002F608 +{ + if (!Is_System_Active()) + { + return; + } + + if (sysinit) + { + if (module_loaded) + { + wess_unload_module(); + } + + wess_low_level_exit(); + sysinit = 0; + if (rflag | WessTimerActive) + { + wess_restore_handler(); + } + } +} + +char *wess_get_wmd_start(void) // 8002F684 +{ + return(wmd_mem); +} + +char *wess_get_wmd_end(void) // 8002F694 +{ + return(wmd_end); +} + +static void free_mem_if_mine(void) // 8002F6A4 +{ + if (wmd_mem_is_mine) + { + if (wmd_mem != NULL) + { + wess_free(wmd_mem); + wmd_mem = NULL; + } + wmd_mem_is_mine = 0; + } +} + +void wess_unload_module(void) // 8002F6F4 +{ + if (module_loaded) + { + wess_seq_stopall(); + wess_engine_off(); + + /* shutdown the loaded drivers and SeqEngine */ + CmdFuncArr[NoSound_ID][DriverExit]((track_status *)pm_stat); + CmdFuncArr[N64_ID][DriverExit]((track_status *)pm_stat); + free_mem_if_mine(); + + module_loaded = 0; + } +} + +int wess_size_module(char *wmd_filename) // 8002F770 +{ + int readrequest, readresult; + callback_status *pcalltable; + int size, i; + + if (!wmd_filename) + return 0; + + if (!(fp_wmd_file = module_open(wmd_filename))) + { + err(wess_FOPEN); + return (module_loaded); + } + + pm_stat = (master_status_structure *)&tmp_mss; + tmp_mss.voices_total = wess_driver_voices; + tmp_mss.pabstime = &millicount; + tmp_mss.pmod_info = (module_data *)&tmp_moddata; + tmp_mss.ppat_info = (patch_group_data *)&tmp_patgrpdata; + + readrequest = sizeof(tmp_moddata.mod_hdr); + readresult = module_read(&tmp_moddata.mod_hdr, readrequest, fp_wmd_file); + if (readrequest != readresult) + { + err(wess_FREAD); + return(0); + } + + if ((pm_stat->pmod_info->mod_hdr.module_id_text != WESS_SSSP_TEXT) || + (pm_stat->pmod_info->mod_hdr.module_version != WESS_CORE_VERSION)) + { + return(0); + } + + readrequest = sizeof(tmp_patgrpdata.pat_grp_hdr); + readresult = module_read(&tmp_patgrpdata.pat_grp_hdr, readrequest, fp_wmd_file); + if (readrequest != readresult) + { + err(wess_FREAD); + return(0); + } + + module_close(fp_wmd_file); + + size = 8;//start Align 8 + pm_stat->ppat_info->ppat_data = (char *)size; + size += pm_stat->pmod_info->mod_hdr.data_size; + + pm_stat->pseqstattbl = (sequence_status *)size; + size += sizeof(*pm_stat->pseqstattbl) * wess_driver_sequences; + + pm_stat->ptrkstattbl = (track_status *)size; + size += sizeof(*pm_stat->ptrkstattbl) * wess_driver_tracks; + + pm_stat->pvoicestattbl = (voice_status *)size; + size += sizeof(*pm_stat->pvoicestattbl) * pm_stat->voices_total; + + pm_stat->pcalltable = (callback_status *)size; + size += sizeof(*pm_stat->pcalltable) * wess_driver_callbacks; + + pm_stat->max_trks_perseq = wess_driver_max_trks_per_seq; + + for (i = 0; i < wess_driver_sequences; i++) + { + size += sizeof(char) * wess_driver_gates; +#if _ALIGN4_ == 1 + //force align to word boundary because previous size adjust + //may wind up with odd address + size += (unsigned int)size & 1; + size += (unsigned int)size & 2; +#endif + + size += sizeof(char) * wess_driver_iters; +#if _ALIGN4_ == 1 + //force align to word boundary because previous size adjust + //may wind up with odd address + size += (unsigned int)size & 1; + size += (unsigned int)size & 2; +#endif + + size += sizeof(char) * pm_stat->max_trks_perseq; +#if _ALIGN4_ == 1 + //force align to word boundary because previous size adjust + //may wind up with odd address + size += (unsigned int)size & 1; + size += (unsigned int)size & 2; +#endif + } + + pm_stat->max_substack_pertrk = wess_driver_max_subs_per_trk; + + for (i = 0; i < wess_driver_tracks; i++) + { + size += sizeof(long) * pm_stat->max_substack_pertrk; + } + +#if _ALIGN4_ == 1 + //force align to word boundary because previous size adjust + //may wind up with odd address + size += (unsigned int)size & 1; + size += (unsigned int)size & 2; +#endif + + return size; +} + +int wess_load_module(char *wmd_filename, + char *memory_pointer, + int memory_allowance/*, + int **settings_tag_lists*/) // 8002FA3C +{ + int i, j, k, n, z, types, num, indx, loadit; + int tracks_toload; + int readrequest, readresult; + char max_tracks_inseq, max_voices_intrk, max_substack_intrk; + char *pdest; + char *pmem; + unsigned long patfpos, trkinfosize; + char *tempwmd; + int setting, flag, flag2; + int decomp_type; + + //PRINTF_D(WHITE, "WMD::module_loaded %d", module_loaded); + + if (module_loaded) + { + wess_unload_module(); + } + + //num_sd = get_num_Wess_Sound_Drivers(settings_tag_lists); + //printf("num_sd %d\n", num_sd); + + //PRINTF_D(WHITE, "WMD::memory_pointer %x", &memory_pointer); + + if (memory_pointer == NULL) + { + wmd_mem_is_mine = 1; + wmd_mem = wess_malloc((char *)memory_allowance); + if (wmd_mem == NULL) + { + return(module_loaded); + } + } + else + { + wmd_mem_is_mine = 0; + wmd_mem = memory_pointer; + } + + wmd_size = memory_allowance; + + //PRINTF_D(WHITE, "WMD::wmd_mem %x", &wmd_mem); + //PRINTF_D(WHITE, "WMD::wmd_size %d", wmd_size); + + zeroset(wmd_mem, wmd_size); + + if (!Is_System_Active()) + { + //PRINTF_D(WHITE, "WMD::Is_System_Active no activo"); + free_mem_if_mine(); + return (module_loaded); + } + + if (wmd_filename == NULL) + { + free_mem_if_mine(); + return (module_loaded); + } + + if (!(fp_wmd_file = module_open(wmd_filename))) + { + //PRINTF_D(WHITE, "WMD::fp_wmd_file %s Error al abrir", fp_wmd_file); + err(wess_FOPEN); + free_mem_if_mine(); + return (module_loaded); + } + + //PRINTF_D(WHITE, "WMD::fp_wmd_file %s", fp_wmd_file); + + + + /* loads a related group of patches and sequences */ + /* a module has the information necessary to set up sequencer work + areas and data areas */ + /* + The module loading sequence works as follows : + */ + + pmem = wmd_mem; + + /* + - allocate space for a master_status_structure + - update the pmasterstat pointer + */ + + pm_stat = (master_status_structure *)&tmp_mss; + tmp_mss.voices_total = wess_driver_voices; + tmp_mss.pabstime = &millicount; + + /* + - allocate for the module_data structure + - update the pmod_info pointer + */ + + tmp_mss.pmod_info = (module_data *)&tmp_moddata; + + /* + - allocate for the patch_group_data structure + - update the ppat_info pointer + */ + tmp_mss.ppat_info = (patch_group_data *)&tmp_patgrpdata; + + /* + - read in sizeof(pm_stat->pmod_info->mod_hdr) + bytes from the .lmd file into the pm_stat->pmod_info->mod_hdr + structure. + */ + + readrequest = sizeof(tmp_moddata.mod_hdr); + readresult = module_read(&tmp_moddata.mod_hdr, readrequest, fp_wmd_file); + if (readrequest != readresult) + { + err(wess_FREAD); + free_mem_if_mine(); + return(0); + } + + //PRINTF_D(WHITE, "WMD::mod_hdr"); + //PRINTF_D(WHITE, "WMD::module_id_text %x",pm_stat->pmod_info->mod_hdr.module_id_text); + //PRINTF_D(WHITE, "WMD::module_version %d",pm_stat->pmod_info->mod_hdr.module_version); + //PRINTF_D(WHITE, "WMD::sequences %d",pm_stat->pmod_info->mod_hdr.sequences); + //PRINTF_D(WHITE, "WMD::decomp_type %d",pm_stat->pmod_info->mod_hdr.decomp_type); + //PRINTF_D(WHITE, "WMD::compress_size %d",pm_stat->pmod_info->mod_hdr.compress_size); + //PRINTF_D(WHITE, "WMD::data_size %d",pm_stat->pmod_info->mod_hdr.data_size); + + if ((pm_stat->pmod_info->mod_hdr.module_id_text != WESS_SSSP_TEXT) || + (pm_stat->pmod_info->mod_hdr.module_version != WESS_CORE_VERSION)) + { + free_mem_if_mine(); + return(0); + } + + readrequest = sizeof(tmp_patgrpdata.pat_grp_hdr); + readresult = module_read(&tmp_patgrpdata.pat_grp_hdr, readrequest, fp_wmd_file); + if (readrequest != readresult) + { + err(wess_FREAD); + free_mem_if_mine(); + return(0); + } + + //PRINTF_D(WHITE, "WMD::pat_grp_hdr"); + //PRINTF_D(WHITE, "WMD::load_flags %d",pm_stat->ppat_info->pat_grp_hdr.load_flags); + //PRINTF_D(WHITE, "WMD::patches %d",pm_stat->ppat_info->pat_grp_hdr.patches); + //PRINTF_D(WHITE, "WMD::patch_size %d",pm_stat->ppat_info->pat_grp_hdr.patch_size); + //PRINTF_D(WHITE, "WMD::patchmaps %d",pm_stat->ppat_info->pat_grp_hdr.patchmaps); + //PRINTF_D(WHITE, "WMD::patchmap_size %d",pm_stat->ppat_info->pat_grp_hdr.patchmap_size); + //PRINTF_D(WHITE, "WMD::patchinfo %d",pm_stat->ppat_info->pat_grp_hdr.patchinfo); + //PRINTF_D(WHITE, "WMD::patchinfo_size %d",pm_stat->ppat_info->pat_grp_hdr.patchinfo_size); + //PRINTF_D(WHITE, "WMD::drummaps %d",pm_stat->ppat_info->pat_grp_hdr.drummaps); + //PRINTF_D(WHITE, "WMD::drummap_size %d",pm_stat->ppat_info->pat_grp_hdr.drummap_size); + //PRINTF_D(WHITE, "WMD::extra_data_size %d",pm_stat->ppat_info->pat_grp_hdr.extra_data_size); + +#if _ALIGN8_ == 1 + //force align to word boundary because previous size adjust + //may wind up with odd address + pmem += (unsigned int)pmem & 1; + pmem += (unsigned int)pmem & 2; + pmem += (unsigned int)pmem & 4; +#endif + + /* + - allocate and initialize space for + pm_stat->patch_types patch_group_data structures + and update the pm_stat->ppat_info pointer. + */ + + pm_stat->ppat_info->ppat_data = (char*)(patch_group_data *)pmem; + pmem += pm_stat->pmod_info->mod_hdr.data_size; + + if (pm_stat->pmod_info->mod_hdr.decomp_type) + { + module_close(fp_wmd_file); + + decomp_type = pm_stat->pmod_info->mod_hdr.decomp_type; + readrequest = pm_stat->pmod_info->mod_hdr.data_size;//uncompressed_size + if (wess_decomp(decomp_type, wmd_filename, 56, pm_stat->ppat_info->ppat_data, readrequest) < 0) + return(0); + } + else + { + readrequest = pm_stat->pmod_info->mod_hdr.data_size; + readresult = module_read(pm_stat->ppat_info->ppat_data, readrequest, fp_wmd_file); + + //printf("WMD::readrequest %d\n",readrequest); + //printf("WMD::readrequest %d\n",readresult); + if (readrequest != readresult) + { + err(wess_FREAD); + free_mem_if_mine(); + return(0); + } + + module_close(fp_wmd_file); + } + + /* + --init work structures -------------------------------------------- + - allocate and initialize space for + pmod_info->mod_hdr.seq_work_areas sequence_status structures + and update the pmseqstattbl pointer and zero seqs_active. + */ + + pm_stat->pseqstattbl = (sequence_status *)pmem; + pmem += sizeof(*pm_stat->pseqstattbl) * wess_driver_sequences; + + //PRINTF_D(WHITE, "WMD::pseqstattbl %d",sizeof(*pm_stat->pseqstattbl) * wess_driver_sequences); + + /* + - allocate and initialize space for + pmod_info->mod_hdr.trk_work_areas track_status structures + and update the pmtrkstattbl pointer and zero trks_active. + */ + + pm_stat->ptrkstattbl = (track_status *)pmem; + pmem += sizeof(*pm_stat->ptrkstattbl) * wess_driver_tracks; + + //PRINTF_D(WHITE, "WMD::ptrkstattbl %d",sizeof(*pm_stat->ptrkstattbl) * wess_driver_tracks); + + /* + - allocate and initialize space for + voice_total voice_status structures + and update the pmvoicestattbl pointer and zero voices_active. + */ + + pm_stat->pvoicestattbl = (voice_status *)pmem; + pmem += sizeof(*pm_stat->pvoicestattbl) * pm_stat->voices_total; + + //PRINTF_D(WHITE, "WMD::pvoicestattbl %d",sizeof(*pm_stat->pvoicestattbl) * pm_stat->voices_total); + + /* + - initialize patch_type parameter for each voice work area. + only the amount of hardware voices possible for each + patch_type loaded will have voice work areas!!! + you will run out of voice work areas for a given patch type + at the same time you have run out of hardware polyphony!!! + eh,eh,this is cool!,eh,eh + */ + + for (i = 0; i < pm_stat->voices_total; i++) + { + (pm_stat->pvoicestattbl + i)->patchtype = 1; + (pm_stat->pvoicestattbl + i)->refindx = i; + } + + /* + - allocate pm_stat->max_tracks_inseq chars for the ptrk_indxs + pointers in each sequence_status structure. + update each pointer to each area. + initialize indexes to 0xFF. + */ + + pm_stat->pcalltable = (callback_status *)pmem; + pmem += sizeof(*pm_stat->pcalltable) * wess_driver_callbacks; + + //PRINTF_D(WHITE, "WMD::pcalltable %d",sizeof(*pm_stat->pcalltable) * wess_driver_callbacks); + + pm_stat->max_trks_perseq = wess_driver_max_trks_per_seq; + + //PRINTF_D(WHITE, "WMD::max_trks_perseq %d",pm_stat->max_trks_perseq); + + for (i = 0; i < wess_driver_sequences; i++) + { + (pm_stat->pseqstattbl + i)->pgates = (char *)pmem; + + pmem += sizeof(char) * wess_driver_gates; +#if _ALIGN4_ == 1 + //force align to word boundary because previous pmem adjust + //may wind up with odd address + pmem += (unsigned int)pmem & 1; + pmem += (unsigned int)pmem & 2; +#endif + + (pm_stat->pseqstattbl + i)->piters = (char *)pmem; + pmem += sizeof(char) * wess_driver_iters; +#if _ALIGN4_ == 1 + //force align to word boundary because previous pmem adjust + //may wind up with odd address + pmem += (unsigned int)pmem & 1; + pmem += (unsigned int)pmem & 2; +#endif + + j = pm_stat->max_trks_perseq; + pdest = (pm_stat->pseqstattbl + i)->ptrk_indxs = (char *)pmem; + pmem += sizeof(char) * j; +#if _ALIGN4_ == 1 + //force align to word boundary because previous pmem adjust + //may wind up with odd address + pmem += (unsigned int)pmem & 1; + pmem += (unsigned int)pmem & 2; +#endif + + while (j--) + { + *pdest++ = 0xFF; + } + } + + /* + - allocate pm_stat->max_voices_intrk chars for the pvoice_indxs + pointers in each track_status structure. + update each pointer to each area. + initialize indexes to 0xFF. + */ + + pm_stat->max_substack_pertrk = wess_driver_max_subs_per_trk; + + //PRINTF_D(WHITE, "WMD::max_substack_pertrk %d",wess_driver_max_subs_per_trk); + + for (i = 0; i < wess_driver_tracks; i++) + { + (pm_stat->ptrkstattbl + i)->refindx = i; + (pm_stat->ptrkstattbl + i)->psubstack = (unsigned long *)pmem; + /* (pm_stat->ptrkstattbl+i)->psp is set when sequence is triggered */ + pmem += sizeof(long) * pm_stat->max_substack_pertrk; + (pm_stat->ptrkstattbl + i)->pstackend = (unsigned long *)pmem; + } + +#if _ALIGN4_ == 1 + //force align to word boundary because previous pmem adjust + //may wind up with odd address + pmem += (unsigned int)pmem & 1; + pmem += (unsigned int)pmem & 2; +#endif + + CmdFuncArr[NoSound_ID][DriverInit]((track_status *)pm_stat); + CmdFuncArr[N64_ID][DriverInit]((track_status *)pm_stat); + + wmd_end = pmem; + module_loaded = 1; + wess_engine_on(); + + return (1); +} + +void filltrackstat(track_status *ptk_stat, track_data *ptk_info, TriggerPlayAttr *attr) // 8003002C +{ + int tempmask; + + ptk_stat->flags = (ptk_stat->flags | TRK_ACTIVE | TRK_OFF) & ~TRK_TIMED & ~TRK_LOOPED & ~TRK_SKIP; + + ptk_stat->patchtype = 1; + ptk_stat->voices_active = 0; + ptk_stat->sndclass = ptk_info->trk_hdr->voices_type;//ptk_info->trk_hdr.voices_class; + + ptk_stat->starppi = 0; + ptk_stat->accppi = 0; + ptk_stat->totppi = 0; + ptk_stat->psp = (unsigned char*)ptk_stat->psubstack; + ptk_stat->ppq = ptk_info->trk_hdr->initppq; + ptk_stat->labellist_count = ptk_info->trk_hdr->labellist_count; + ptk_stat->data_size = ptk_info->trk_hdr->data_size; + + ptk_stat->mutemask = ptk_info->trk_hdr->mutebits; + + if ((attr == NULL) || (!attr->mask)) + { + tempmask = 0; + } + else { + tempmask = attr->mask; + } + + if (tempmask & TRIGGER_VOLUME) //0x01 + { + ptk_stat->volume_cntrl = attr->volume; + } + else { + ptk_stat->volume_cntrl = ptk_info->trk_hdr->initvolume_cntrl; + } + + if (tempmask & TRIGGER_PAN) //0x02 + { + ptk_stat->pan_cntrl = attr->pan; + } + else { + ptk_stat->pan_cntrl = ptk_info->trk_hdr->initpan_cntrl; + } + + if (tempmask & TRIGGER_PATCH) //0x04 + { + ptk_stat->patchnum = attr->patch; + } + else { + ptk_stat->patchnum = ptk_info->trk_hdr->initpatchnum; + } + + if (tempmask & TRIGGER_PITCH) //0x08 + { + ptk_stat->pitch_cntrl = attr->pitch; + } + else { + ptk_stat->pitch_cntrl = ptk_info->trk_hdr->initpitch_cntrl; + } + + if (tempmask & TRIGGER_MUTEMODE) //0x10 + { + if (ptk_stat->mutemask & (1 << attr->mutemode)) + { + ptk_stat->flags |= TRK_MUTE; + } + else { + ptk_stat->flags &= ~TRK_MUTE; + } + } + else { + ptk_stat->flags &= ~TRK_MUTE; + } + + if (tempmask & TRIGGER_TEMPO) //0x20 + { + ptk_stat->qpm = attr->tempo; + } + else { + ptk_stat->qpm = ptk_info->trk_hdr->initqpm; + } + + ptk_stat->ppi = CalcPartsPerInt(GetIntsPerSec(), ptk_stat->ppq, ptk_stat->qpm); + + if (tempmask & TRIGGER_TIMED) //0x40 + { + ptk_stat->endppi = ptk_stat->totppi + attr->timeppq; + ptk_stat->flags |= TRK_TIMED; + } + else { + ptk_stat->flags &= ~TRK_TIMED; + } + + if (tempmask&TRIGGER_LOOPED) //0x80 + { + ptk_stat->flags |= TRK_LOOPED; + } + else { + ptk_stat->flags &= ~TRK_LOOPED; + } + + if (tempmask & TRIGGER_REVERB) //0x100 + { + ptk_stat->reverb = attr->reverb; + } + else { + ptk_stat->reverb = ptk_info->trk_hdr->reverb; + } + + /*printf("ptk_stat->ppq %d\n",ptk_stat->ppq); + printf("ptk_stat->ppq %d\n",ptk_stat->ppq); + printf("ptk_stat->labellist_count %d\n",ptk_stat->labellist_count); + printf("ptk_stat->data_size %d\n",ptk_stat->data_size); + printf("ptk_stat->mutemask %d\n",ptk_stat->mutemask); + printf("ptk_stat->volume_cntrl %d\n",ptk_stat->volume_cntrl); + printf("ptk_stat->pan_cntrl %d\n",ptk_stat->pan_cntrl); + printf("ptk_stat->patchnum %d\n",ptk_stat->patchnum); + printf("ptk_stat->pitch_cntrl %d\n",ptk_stat->pitch_cntrl); + printf("ptk_stat->qpm %d\n",ptk_stat->qpm); + printf("ptk_stat->ppi %d\n",ptk_stat->ppi); + printf("ptk_stat->flags %d\n",ptk_stat->flags); + printf("ptk_stat->reverb %d\n",ptk_stat->reverb);*/ +} + +void assigntrackstat(track_status *ptk_stat, track_data *ptk_info) // 800302F8 +{ + ptk_stat->data_space = ptk_info->trk_hdr->data_size; + ptk_stat->labellist_max = ptk_info->trk_hdr->labellist_count; + ptk_stat->pstart = ptk_info->ptrk_data; + ptk_stat->ppos = Read_Vlq(ptk_stat->pstart, &ptk_stat->deltatime); + ptk_stat->plabellist = ptk_info->plabellist; +} + +/* used by wess trigger functions */ +enum LoopedFlag { NoLooped, YesLooped }; + +/* used by wess trigger functions */ +enum HandleFlag { NoHandle, YesHandle }; + +int wess_seq_structrig(sequence_data *psq_info, + int seq_num, + int seq_type, + enum HandleFlag gethandle, + TriggerPlayAttr *attr) // 8003036C +{ + char i, j, limit; + short n; + char tracksfilled; + char *pdest; + sequence_status *psq_stat; + track_data *ptk_info; + track_status *ptk_stat; + + //------- + sequence_data *_psq_info; + int _seq_num; + int _seq_type; + enum HandleFlag _gethandle; + TriggerPlayAttr *_attr; + + _psq_info = psq_info; + _seq_num = seq_num; + _seq_type = seq_type; + _gethandle = gethandle; + _attr = attr; + + if (!Is_Seq_Num_Valid(_seq_num)) + { + return (0); + } + + //printf("wess_seq_structrig %d\n",_seq_num); + + /* runs trigger function and update status structures for api */ + + /* + - save the sequencer information block pointer, + if a sequence status structure is free: + mark sequence as active, + flag to start what tracks can be started, + for each track started update psq_info->ptrk_indxs + */ + + wess_disable(); + + /* find an open sequence structure */ + + limit = wess_driver_sequences;//pm_stat->pmod_info->mod_hdr.seq_work_areas; + + for (i = 0; i<limit; i++) + { + if (!((pm_stat->pseqstattbl + i)->flags & SEQ_ACTIVE)) + { + break; + } + } + if (i == limit) + { + wess_enable(); + return (0); /* no sequence work area available */ + } + else + { + tracksfilled = 0; /* used to check if any tracks are started */ + /* + we found a sequence structure so fill it. + */ + + psq_stat = pm_stat->pseqstattbl + i; /* pointer math */ + + /* + for n tracks in the sequence find and open track structure + and initialize it. + */ + n = _psq_info->seq_hdr.tracks; + limit = wess_driver_tracks;//pm_stat->pmod_info->mod_hdr.trk_work_areas; + pdest = psq_stat->ptrk_indxs; + + //printf("tracks %d\n",n); + //printf("limit %d\n",limit); + + for (j = 0; j<limit; j++) + { + if (!((pm_stat->ptrkstattbl + j)->flags & TRK_ACTIVE)) + { + + ptk_stat = pm_stat->ptrkstattbl + j; /* pointer math */ + ptk_info = _psq_info->ptrk_info + tracksfilled; + + /* refindx was filled at init time */ + ptk_stat->seq_owner = i; + + filltrackstat(ptk_stat, ptk_info, _attr); + assigntrackstat(ptk_stat, ptk_info); + + if (_gethandle) + { + ptk_stat->flags |= (TRK_STOPPED | TRK_HANDLED); + + } + else { + ptk_stat->flags &= ~(TRK_STOPPED | TRK_HANDLED); + psq_stat->tracks_playing++; + } + + psq_stat->tracks_active++; + pm_stat->trks_active++; + *pdest++ = j; /* update ptrk_indxs for the sequence */ + tracksfilled++; + + if (!(((--n)<<16)>>16)) break; + } + } + + /* if tracks were started, activate the sequence */ + if (tracksfilled) + { + psq_stat->seq_num = _seq_num; + psq_stat->seq_type = _seq_type; + if (_gethandle) + { + psq_stat->flags |= SEQ_HANDLE; + psq_stat->playmode = SEQ_STATE_STOPPED; + } + else { + psq_stat->flags &= ~SEQ_HANDLE; + psq_stat->playmode = SEQ_STATE_PLAYING; + } + psq_stat->volume = 128; + psq_stat->pan = 64; + psq_stat->flags |= SEQ_ACTIVE; + pm_stat->seqs_active++; + } + wess_enable(); + + if (tracksfilled) + { + return (i + 1); + } + else { + return (0); + } + } +} + +void wess_seq_trigger(int seq_num) // 80030650 +{ + wess_seq_trigger_type(seq_num, 0); +} + +void wess_seq_trigger_special(int seq_num, TriggerPlayAttr *attr) // 80030670 +{ + sequence_data *psq_info; + + psq_info = pm_stat->pmod_info->pseq_info + seq_num; /* pointer math */ + + wess_seq_structrig(psq_info, seq_num, 0, NoHandle, attr); +} + +int wess_seq_status(int sequence_number) // 800306C0 +{ + /* immediate stop of sequence */ + char nt, na; + sequence_status *psq_stat; + int status; + + int _sequence_number; + + _sequence_number = sequence_number; + + if (!Is_Seq_Num_Valid(_sequence_number)) + { + return(SEQUENCE_INVALID); + } + + status = SEQUENCE_INACTIVE; + + wess_disable(); + + /* search for all sequences with this number and turn them off */ + nt = wess_driver_sequences;//pm_stat->pmod_info->mod_hdr.seq_work_areas; + na = pm_stat->seqs_active; + psq_stat = pm_stat->pseqstattbl; + + if (na) + { + while (nt--) + { + if (psq_stat->flags & SEQ_ACTIVE) + { + if (psq_stat->seq_num == _sequence_number) + { + if (psq_stat->playmode == SEQ_STATE_STOPPED) + { + status = SEQUENCE_STOPPED; + } + else if (psq_stat->playmode == SEQ_STATE_PLAYING) { + status = SEQUENCE_PLAYING; + } + } + + if (!--na) break; + } + psq_stat++; + } + } + + wess_enable(); + + return(status); +} + +/* used by wess_seq_stop and wess_seq_stop_and_voiceramp functions */ +enum MuteRelease { NoMuteRelease, YesMuteRelease}; + +void __wess_seq_stop(int sequence_number, enum MuteRelease mrelease, int millisec) // 800307AC +{ + /* immediate stop of sequence */ + + char nt, na; + sequence_status *psq_stat; + track_status *ptmp; + int li, lj; + + int _sequence_number; + enum MuteRelease _mrelease; + int _millisec; + + _sequence_number = sequence_number; + _mrelease = mrelease; + _millisec = millisec; + + if (!Is_Seq_Num_Valid(_sequence_number)) + { + return; + } + + wess_disable(); + + /* search for all sequences with this number and turn them off */ + nt = wess_driver_sequences; + na = pm_stat->seqs_active; + psq_stat = pm_stat->pseqstattbl; + if (na) + { + while (nt--) + { + if (psq_stat->flags & SEQ_ACTIVE) + { + if (psq_stat->seq_num == _sequence_number) + { + psq_stat->flags = (psq_stat->flags | SEQ_STOP) & ~SEQ_PAUSE & ~SEQ_RESTART; + } + if (!--na) break; + } + psq_stat++; + } + } + + if (_mrelease) + { + queue_the_function(QUEUE_SEQ_STOP_AND_VOICERAMP); + queue_the_data(&_millisec, sizeof(int)); + } + else + { + queue_the_function(QUEUE_SEQ_STOP); + } + queue_the_data(&_sequence_number, sizeof(int)); + wess_enable(); +} + +void wess_seq_stop(int sequence_number) // 800308BC +{ + __wess_seq_stop(sequence_number, NoMuteRelease, 0); +} + +void wess_seq_stop_and_voiceramp(int sequence_number, int millisec) // 800308E0 +{ + __wess_seq_stop(sequence_number, YesMuteRelease, millisec); +} + +void queue_wess_seq_stop(int sequence_number, enum MuteRelease mrelease, int millisec); + +void run_queue_wess_seq_stop(void) // 80030904 +{ + int sequence_number; + + unqueue_the_data(&sequence_number, sizeof(int)); + queue_wess_seq_stop(sequence_number, NoMuteRelease, 0); +} + +void run_queue_wess_seq_stop_and_voiceramp(void) // 80030938 +{ + int millisec; + int sequence_number; + + unqueue_the_data(&millisec, sizeof(int)); + unqueue_the_data(&sequence_number, sizeof(int)); + queue_wess_seq_stop(sequence_number, YesMuteRelease, millisec); +} + +void queue_wess_seq_stop(int sequence_number, enum MuteRelease mrelease, int millisec) // 80030978 +{ + /* immediate stop of sequence */ + + char nt, na; + sequence_status *psq_stat; + track_status *ptmp; + char *lpdest; + int li, lj; + int get_millisec; + + int _sequence_number; + enum MuteRelease _mrelease; + int _millisec; + + _sequence_number = sequence_number; + _mrelease = mrelease; + _millisec = millisec; + + if (!Is_Seq_Num_Valid(_sequence_number)) + { + return; + } + + wess_disable(); + + /* search for all sequences with this number and turn them off */ + nt = wess_driver_sequences; + na = pm_stat->seqs_active; + psq_stat = pm_stat->pseqstattbl; + if (na) + { + if (_mrelease) + { + get_millisec = wess_get_mute_release(); + wess_set_mute_release(_millisec); + } + + while (nt--) + { + //if (psq_stat->active) + if (psq_stat->flags & SEQ_ACTIVE) + { + if (psq_stat->seq_num == _sequence_number) + { + if (psq_stat->flags & SEQ_STOP) + { + psq_stat->flags &= ~SEQ_STOP; + + li = psq_stat->tracks_active; + lj = pm_stat->max_trks_perseq; + /* *lpdest refers to an active track if not 0xFF */ + lpdest = psq_stat->ptrk_indxs; + while (lj--) + { + if (*lpdest != 0xFF) + { + ptmp = (pm_stat->ptrkstattbl + (*lpdest)); + CmdFuncArr[ptmp->patchtype][TrkOff](ptmp); + if (!--li) break; + } + lpdest++; + } + } + } + if (!--na) break; + } + psq_stat++; + } + + if (_mrelease) + { + wess_set_mute_release(get_millisec); + } + } + + wess_enable(); +} + +void __wess_seq_stopall(enum MuteRelease mrelease, int millisec) // 80030B78 +{ + /* immediate stop of all sequences */ + + char nt, na; + sequence_status *psq_stat; + track_status *ptmp; + int li, lj; + + enum MuteRelease _mrelease; + int _millisec; + + _mrelease = mrelease; + _millisec = millisec; + + if (!Is_Module_Loaded()) + { + return; + } + + wess_disable(); + + /* search for all sequences with this number and turn them off */ + nt = wess_driver_sequences; + na = pm_stat->seqs_active; + psq_stat = pm_stat->pseqstattbl; + if (na) + { + while (nt--) + { + if (psq_stat->flags & SEQ_ACTIVE) + { + psq_stat->flags = (psq_stat->flags | SEQ_STOP) & ~SEQ_PAUSE & ~SEQ_RESTART; + if (!--na) break; + } + psq_stat++; + } + } + + if (_mrelease) + { + queue_the_function(QUEUE_SEQ_STOPALL_AND_VOICERAMP); + queue_the_data(&_millisec, sizeof(int)); + } + else + { + queue_the_function(QUEUE_SEQ_STOPALL); + } + + wess_enable(); +} + +void wess_seq_stopall(void) // 80030C68 +{ + __wess_seq_stopall(NoMuteRelease, 0); +} + +void wess_seq_stopall_and_voiceramp(int millisec) // 80030C8C +{ + __wess_seq_stopall(YesMuteRelease, millisec); +} + +void queue_wess_seq_stopall(enum MuteRelease mrelease, int millisec); + +void run_queue_wess_seq_stopall(void) // 80030CB0 +{ + queue_wess_seq_stopall(NoMuteRelease, 0); +} + +void run_queue_wess_seq_stopall_and_voiceramp(void) // 80030CD4 +{ + int millisec; + + unqueue_the_data(&millisec, sizeof(int)); + queue_wess_seq_stopall(YesMuteRelease, millisec); +} + +void queue_wess_seq_stopall(enum MuteRelease mrelease, int millisec) // 80030D04 +{ + char nt, na; + sequence_status *psq_stat; + track_status *ptmp; + char *lpdest; + int li, lj; + int get_millisec; + + enum MuteRelease _mrelease; + int _millisec; + + _mrelease = mrelease; + _millisec = millisec; + + if (!Is_Module_Loaded()) + { + return; + } + + /* immediate stop of all sequences */ + wess_disable(); + + /* search for all sequences and turn them off */ + nt = wess_driver_sequences; + na = pm_stat->seqs_active; + psq_stat = pm_stat->pseqstattbl; + if (na) + { + if (_mrelease) + { + get_millisec = wess_get_mute_release(); + wess_set_mute_release(_millisec); + } + + while (nt--) + { + if (psq_stat->flags & SEQ_ACTIVE) + { + if (psq_stat->flags & SEQ_STOP) + { + psq_stat->flags &= ~SEQ_STOP; + + li = psq_stat->tracks_active; + lj = pm_stat->max_trks_perseq; + /* *lpdest refers to an active track if not 0xFF */ + lpdest = psq_stat->ptrk_indxs; + while (lj--) + { + if (*lpdest != 0xFF) + { + ptmp = (pm_stat->ptrkstattbl + (*lpdest)); + CmdFuncArr[ptmp->patchtype][TrkOff](ptmp); + if (!--li) break; + } + lpdest++; + } + } + if (!--na) break; + } + + psq_stat++; + } + + if (_mrelease) + { + wess_set_mute_release(get_millisec); + } + } + + wess_enable(); +} +#endif // 0 diff --git a/Doom 64/wessapi.h b/Doom 64/wessapi.h @@ -0,0 +1,552 @@ + /*------------------------------------------------------------------*/ + /* + The Williams Entertainment Sound System + Application Programming Interface Routines + by Scott Patterson + */ + /*------------------------------------------------------------------*/ + +#ifndef _WESSAPI_H +#define _WESSAPI_H + +#include <ultra64.h> + + /*------------------------------------------------------------------*/ + /* + Enumerated types. + */ + /*------------------------------------------------------------------*/ + +/* used by wess_seq_pause and wess_seq_pauseall functions */ +enum MuteFlag { NoMute, YesMute }; + +/* used by wess_seq_restartall function */ +enum VoiceRestartFlag { NoVoiceRestart, YesVoiceRestart }; + +/* used by wess_sequence_status function */ +enum SequenceStatus { SEQUENCE_INVALID, + SEQUENCE_INACTIVE, + SEQUENCE_STOPPED, + SEQUENCE_PLAYING }; + + /*------------------------------------------------------------------*/ + /*------------------------------------------------------------------*/ + /* + System Setup and Shutdown Functions. + */ + /*------------------------------------------------------------------*/ + /*------------------------------------------------------------------*/ + + + /* + wess_set_error_callback - set a callback for runtime audio errors + + passing NULL removes the callback + + the errstring passed to the callback is guaranteed to be less than 12 + uppercase letter characters only, thus you can print the errors + with a very simple print routine. + + the errnum1 and errnum2 ints passed to the callback may or may not + have meaning based on the errstring + */ + +typedef void (*WessErrorCallbackProc)( char *errstring, int errnum1, int errnum2 ); + +extern void wess_set_error_callback( WessErrorCallbackProc errcall ); + + /* + wess_set_decompression_callback - set a callback for runtime decompression + + passing NULL removes the callback + + If the sound system source files are compressed, this callback will happen + inside the following functions: + + wess_load_module + + wess_seq_loader_init + + wess_seq_load, wess_seq_range_load, or wess_seq_list_load + + when the callback occurs you must run the decompression type + that matches the decomp_type parameter from the source file at a given + offset into memory. + + if the decompression is not available or something goes wrong, then return + a negative number and the sound system call that issued the callback will + abort. + */ + +#define NO_DECOMPRESSION 0 /* you will never actually get this as a decomp type */ +#define MARKG_INFLATE_DECOMPRESSION 1 + +typedef int (*WessDecompCallbackProc)( unsigned char decomp_type, + char *fileref, + unsigned long file_offset, + char *ramdest, + unsigned long uncompressed_size ); + +extern void wess_set_decomp_callback( WessDecompCallbackProc decompcall ); + + /* + wess_set_tweak - set the tweak parameters for the audio engine + + If you need to change audio system parameters, wess_tweak allows this. + + If you don't know what these parameters do, don't change them! + + This call must be made before wess_init to have any effect. + + Use the mask to set particlar parameters. + */ + +#define TWEAK_DMA_BUFFERS (0x1L<< 0) +#define TWEAK_DMA_MESSAGES (0x1L<< 1) +#define TWEAK_DMA_BUFFER_LENGTH (0x1L<< 2) +#define TWEAK_EXTRA_SAMPLES (0x1L<< 3) +#define TWEAK_FRAME_LAG (0x1L<< 4) +#define TWEAK_VOICES (0x1L<< 5) +#define TWEAK_UPDATES (0x1L<< 6) +#define TWEAK_SEQUENCES (0x1L<< 7) +#define TWEAK_TRACKS (0x1L<< 8) +#define TWEAK_GATES (0x1L<< 9) +#define TWEAK_ITERS (0x1L<< 10) +#define TWEAK_CALLBACKS (0x1L<< 11) +#define TWEAK_MAX_TRKS_PER_SEQ (0x1L<< 12) +#define TWEAK_MAX_SUBS_PER_TRK (0x1L<< 13) + +typedef struct { + unsigned long mask; + unsigned long dma_buffers; /* default is 24 */ + unsigned long dma_messages; /* default is 32 */ + unsigned long dma_buffer_length; /* default is 0x800 */ + unsigned long extra_samples; /* default is 80 */ + unsigned long frame_lag; /* default is 1 */ + unsigned long voices; /* default is 24 */ + unsigned long updates; /* default is 48 */ + unsigned long sequences; /* default is 26 */ + unsigned long tracks; /* default is 25 */ + unsigned long gates; /* default is 0 */ + unsigned long iters; /* default is 0 */ + unsigned long callbacks; /* default is 0 */ + unsigned long max_trks_per_seq; /* default is 16 */ + unsigned long max_subs_per_trk; /* default is 0 */ + } WessTweakAttr; + +extern void wess_set_tweaks(WessTweakAttr *attr); + + /* + wess_get_tweak - get the tweak parameters for the audio engine + + The given WessTweakAttr structure will updated to the current parameters. + + This function simply fills the WessTweakAttr structure and sets mask = 0. + */ + +extern void wess_get_tweaks(WessTweakAttr *attr); + + + /* + wess_init - Initializes the Williams Entertainment Sound System. + + config is a pointer to the WessConfig structure that holds the + following information: + + audioframerate - the frequency (number of times per second) the + wess_work function will be called. Typically this + will be 30 (30fps) or 60 (60fps). + + outputsamplerate - this is the output sample rate of the audio data + the higher this number, the higher the possible + frequency response of the audio, but the more data + that the RSP must calculate. + + maxACMDSize - the number of commands allowed for the audio + command list sent to the RSP. If this number is + too small, memory will be trashed. Typical values + are 3072 (for 30fps) or 2048 (for 60fps) + + heap_ptr - pointer to an audio heap pointer set up with the + alHeapInit call. + + revtbl_ptr - pointer to a reverb settings table for effects initialization. + this MUST be set to zero if no effects are to be turned on. + */ + +#define WESS_REVERB_NONE 0 +#define WESS_REVERB_SMALLROOM 1 +#define WESS_REVERB_BIGROOM 2 +#define WESS_REVERB_CHORUS 3 +#define WESS_REVERB_FLANGE 4 +#define WESS_REVERB_ECHO 5 +#define WESS_REVERB_CUSTOM 6 + +typedef struct WessConfig { /* see wess_init function for more info */ + f32 audioframerate; /* the number of times per second that wesswork is called */ + u32 outputsamplerate; /* the output samplerate to calculate */ + u32 maxACMDSize; /* the size of the audio command list buffers */ + ALHeap *heap_ptr; /* audio heap pointer */ + char *wdd_location; /* cart location of wdd file */ + s32 reverb_id; /* choose from WESS_REVERB defines */ + s32 *revtbl_ptr; /* reverb table pointer (used if reverb_id == WESS_REVERB_CUSTOM */ +} WessConfig; + +extern void wess_init(WessConfig *wessconfig); + + /* + wess_rom_copy - U64 rom copy + + after wess_init has been called, you can call wess_rom_copy + + - this is a blocking rom copy + + - returns 0 and copies nothing if the request was for zero bytes or if + the wess_init call has not been made + - returns length copied if length is non zero + */ + +extern int wess_rom_copy(char *src, char *dest, int len); + + /* + wess_exit - call this to shutdown the audio system + */ + +extern void wess_exit(void); + + /* + wess_work - performs ALL CPU audio work for application + + This function must be called at a constant frequency, as set up + by the WessConfig.audioframerate parameter in the wess_init function. + It handles all audio work processing and returns a pointer to an RSP + audio task, or 0 if no RSP processing is required. + + The task returned by wess_work must be given to the RSP as quickly + as possible so that the RSP audio microcode has completed building + the audio frame buffer in time for the next call to wess_work. + Typically this requires that an in-progress RSP graphics task must + yield, and will resume when the RSP completes the audio task. + */ + +extern OSTask * wess_work(void); + + /* + wess_master_fade - Master volume fade. + + This function smoothly fades the master volume of all sound + effects and music channels from the current volume to dest_vol. + The transition will complete in millisec milliseconds. Returns the + current master volume level prior to the call. + + dest_vol should be 0 - 127 + */ + +extern int wess_master_fade(char dest_vol, int millisec); + + /* + routine: wess_load_module() + + - loads master table of sounds and sequences + - returns 0 for failure, 1 for success + - NULL for memory_pointer results in internal memory allocation + of memory_allowance bytes + - if memory_pointer!=NULL then it is assumed to be a pointer + to memory_allocation bytes of memory for use by the sound system + - enables sequencer engine + */ + +extern int wess_size_module (char *wmd_filename); + +extern int wess_load_module (char *wmd_filename, + char *memory_pointer, + int memory_allowance); + + /* + routine: wess_unload_module() + + - disables sequencer engine + - frees any allocated memory + */ + +extern void wess_unload_module (void); + + /* + routine: wess_get_wmd_start() + + - after call to wess_load_module is successful, this + gets the pointer to beginning of module block + */ + +extern char *wess_get_wmd_start (void); + + /* + routine: wess_get_wmd_end() + + - after call to wess_load_module is successful, this + gets the pointer past end of module block + */ + +extern char *wess_get_wmd_end (void); + + /*------------------------------------------------------------------*/ + /*------------------------------------------------------------------*/ + /* + Sequencer calls. + */ + /*------------------------------------------------------------------*/ + /*------------------------------------------------------------------*/ + + /* + routine: wess_seq_trigger() + + - a sequence is everything from a single sound to a music sequence. + - multiple sequences can be called simultaneously + - dynamic sequence, track, and voice allocation is managed + by the sequencer + - tracks have priorty assignments and voices triggered by a + track inheirit its priority + - you can trigger multiple instances of a sequence with multiple + trigger calls + */ + +#define TRIGGER_VOLUME (0x1L<< 0) +#define TRIGGER_PAN (0x1L<< 1) +#define TRIGGER_PATCH (0x1L<< 2) +#define TRIGGER_PITCH (0x1L<< 3) +#define TRIGGER_MUTEMODE (0x1L<< 4) +#define TRIGGER_TEMPO (0x1L<< 5) +#define TRIGGER_TIMED (0x1L<< 6) +#define TRIGGER_LOOPED (0x1L<< 7) +#define TRIGGER_REVERB (0x1L<< 8) + +typedef struct { + unsigned long mask; + unsigned char volume; /* 0-127 */ + unsigned char pan; /* 0-127, 64 center */ + short patch; /* 0-32767 */ + short pitch; /* -8192 to 8191 */ + unsigned char mutemode; /* 0-7 */ + unsigned char reverb; + unsigned short tempo; + unsigned long timeppq; + } TriggerPlayAttr; + + /* the basic sequence trigger call */ + +extern void wess_seq_trigger (int seq_num); + + /* override masked sequence parameters */ + +extern void wess_seq_trigger_special (int seq_num, + TriggerPlayAttr *attr); + + /* set your own type number to the sequence */ + +extern void wess_seq_trigger_type (int seq_num, + unsigned long seq_type); + + /* set your own type number to the sequence and + override masked sequence parameters */ + +extern void wess_seq_trigger_type_special (int seq_num, + unsigned long seq_type, + TriggerPlayAttr *attr); + +extern void wess_seq_update_type_special (unsigned long seq_type, + TriggerPlayAttr *attr); + + /* + routine: wess_seq_status() + + - find out status of any instances of sequences_number + - returns SEQUENCE_INVALID for no such sequence + SEQUENCE_INACTIVE for is not being processed + SEQUENCE_STOPPED for sequence is stopped + SEQUENCE_PLAYING for sequence is playing + */ + +extern int wess_seq_status (int sequence_number); + + /* + routine: wess_seq_type_status() + + - find out status of any instances of sequence_type + - returns SEQUENCE_INACTIVE for no sequence of this type is being processed + SEQUENCE_STOPPED for a sequence of this type is stopped + SEQUENCE_PLAYING for a sequence is this type is playing + */ + +extern int wess_seq_type_status (unsigned long sequence_type); + + /* + routine: wess_seq_stop() + + - stops all instances of a specified sequence + */ + +extern void wess_seq_stop (int sequence_number); + +extern void wess_seq_stop_and_voiceramp (int sequence_number,int millisec); + + /* + routine: wess_seq_stoptype() + + - immediate stop of all sequences that were registered as a certain + type by wess_seq_trigger_type + */ + +extern void wess_seq_stoptype (unsigned long sequence_type); + +extern void wess_seq_stoptype_and_voiceramp (unsigned long sequence_type,int millisec); + + /* + routine: wess_seq_stopall() + + - immediate stop of all sequences + */ + +extern void wess_seq_stopall (void); + +extern void wess_seq_stopall_and_voiceramp (int millisec); + + /* + routine: wess_seq_pause() + + - immediately pause a sequence + - if MuteFlag is YesMute, all playing voices are muted + - if MuteFlag is NoMute, all playing voices do note decay + */ + +extern void wess_seq_pause (int sequence_number, + enum MuteFlag mflag); + + /* + routine: wess_seq_restart() + + - restarts a paused sequence + */ + +extern void wess_seq_restart (int sequence_number); + + /* + routine: wess_seq_stopall() + + - immediate pause of all sequences + - if mflag is YesMute, all playing voices are muted + - if mflag is NoMute, all playing voices remain on + - if remember bits are set then corrosponding voices + will restore when wess_seq_restartall is called + */ + +#define REMEMBER_MUSIC (0x1L<< 0) +#define REMEMBER_SNDFX (0x1L<< 1) + +extern void wess_seq_pauseall (enum MuteFlag mflag, int remember); + + /* + routine: wess_seq_restartall() + + - restart all paused sequences + - if restart_remembered voices is YesVoiceRestart, all the + voices remembered at pauseall time will restart + */ + +extern void wess_seq_restartall (enum VoiceRestartFlag restart_remembered_voices); + + /* + routine: wess_register_callback() + + - callbacks are useful for video and program flow synchronization + with audio. + - callbacks are called when any track of a playing sequence + encounters a StatusMark with a registered marker_ID + - the first parameter of the callback is the marker_ID encountered + - the second parameter is the StatusMark's data field + */ + +extern void wess_register_callback (char marker_ID, + void (*function_pointer)(char,short)); + + /* + routine: wess_delete_callback() + + - stop any callbacks from a particular marker_ID + */ + +extern void wess_delete_callback (char marker_ID); + + /*------------------------------------------------------------------*/ + /*------------------------------------------------------------------*/ + /* + Master functions get and set global sound parameters. + */ + /*------------------------------------------------------------------*/ + /*------------------------------------------------------------------*/ + + /* + routine: wess_master_sfx_volume_get() + routine: wess_master_mus_volume_get() + + - gets the master volume + */ + +extern char wess_master_sfx_volume_get (void); +extern char wess_master_mus_volume_get (void); + + /* + routine: wess_master_sfx_vol_set() + routine: wess_master_mus_vol_set() + + - sets the master volume + */ + +extern void wess_master_sfx_vol_set (char volume); +extern void wess_master_mus_vol_set (char volume); + + /* + routine: wess_pan_mode_get() + + - gets the pan mode where 0=off, 1=normal, 2=switchLR + */ + +extern char wess_pan_mode_get (void); + + /* + routine: wess_pan_mode_set() + + - sets the pan mode where 0=off, 1=normal, 2=switchLR + */ + +extern void wess_pan_mode_set (char mode); + + /* + routine: wess_set_mute_release(millisec) + + - sets the stop/mute release time given milliseconds + */ + +extern void wess_set_mute_release(int millisec); + + /* + routine: wess_get_mute_release(millisec) + + - gets the stop/mute release time given milliseconds + */ + +extern int wess_get_mute_release(void); + + /* + routine: wess_master_status() + + - this returns a pointer to low level data structures + - some function calls need this pointer + */ + +extern void * wess_get_master_status (void); + +#endif + + + + diff --git a/Doom 64/wessapic.c b/Doom 64/wessapic.c @@ -0,0 +1,96 @@ + +/* WESS API INCLUDES */ +#include "wessapi.h" // audio stuff... +#include "seqload.h" +#include "soundhw.h" +#include "wessarc.h" +#include "wessseq.h" + +#include "funqueue.h" + +#include "graph.h" // debug + +#ifndef NOUSEWESSCODE +extern pmasterstat *pm_stat; //0x800B41CC + +void wess_register_callback(char marker_ID, void(*function_pointer)(char, short)) // 80030EF0 +{ + static char si, sn; //800B41D0, 800B41D1 + static callback_status *cbs; //800B41D4 + + char _marker_ID; + void(*_function_pointer)(char, short); + + _marker_ID = marker_ID; + _function_pointer = function_pointer; + + if (!Is_Module_Loaded()) + { + return; + } + + wess_disable(); + + sn = pm_stat->callbacks_active; + si = wess_driver_callbacks; + if (sn != si) /* check if we are full of callbacks */ + { + cbs = pm_stat->pcalltable; + while (si--) + { + if (!cbs->active) + { + cbs->curval = 0; + cbs->type = _marker_ID; + cbs->callfunc = _function_pointer; + pm_stat->callbacks_active++; + break; + } + cbs++; + } + } + + wess_enable(); +} + +void wess_delete_callback(char marker_ID) // 80030FF0 +{ + static char si, sn; //800B41D8, 800B41D9 + static callback_status *cbs; //800B41DC + + char _marker_ID; + + _marker_ID = marker_ID; + + if (!Is_Module_Loaded()) + { + return; + } + + wess_disable(); + + sn = pm_stat->callbacks_active; + if (sn) + { + cbs = pm_stat->pcalltable; + si = wess_driver_callbacks; + while (si--) + { + if (cbs->active) + { + if (cbs->type == _marker_ID) + { + cbs->active = 0; + --pm_stat->callbacks_active; + break; + } + if (!--sn) break; + } + cbs++; + } + } + + wess_enable(); +} + +#endif diff --git a/Doom 64/wessapim.c b/Doom 64/wessapim.c @@ -0,0 +1,244 @@ + +/* WESS API INCLUDES */ +#include "wessapi.h" // audio stuff... +#include "seqload.h" +#include "soundhw.h" +#include "wessarc.h" +#include "wessseq.h" + +#include "funqueue.h" + +#include "graph.h" // debug + +#ifndef NOUSEWESSCODE + +unsigned char master_sfx_volume = 0x7F; // 80075834 +unsigned char master_mus_volume = 0x7F; // 80075835 +unsigned char pan_status = 1; // 80075836 +int enabledecay = 0; // 8005D980 + +extern pmasterstat *pm_stat; //0x800B41CC + +char wess_master_sfx_volume_get(void) // 80031120 +{ + if (!Is_Module_Loaded()) + { + return 0; + } + + return (master_sfx_volume); +} + +char wess_master_mus_volume_get(void) // 80031158 +{ + if (!Is_Module_Loaded()) + { + return 0; + } + + return (master_mus_volume); +} + +void wess_master_sfx_vol_set(char volume) // 80031190 +{ + char _volume; + + _volume = volume; + + wess_disable(); + queue_the_function(QUEUE_MASTER_SFX_VOL_SET); + queue_the_data(&_volume, sizeof(char)); + wess_enable(); +} + +void queue_wess_master_sfx_vol_set(char volume); + +void run_queue_wess_master_sfx_vol_set(void) // 800311CC +{ + char volume; + + unqueue_the_data(&volume, sizeof(char)); + queue_wess_master_sfx_vol_set(volume); +} + +void queue_wess_master_sfx_vol_set(char volume) // 800311FC +{ + char nt, na; + sequence_status *psq_stat; + track_status *ptmp; + char *lpdest; + char *ppos; + int li, lj; + char tmpppos[16]; + + char _volume; + + _volume = volume; + + if (!Is_Module_Loaded()) + { + return; + } + + master_sfx_volume = _volume; + + wess_disable(); + + /* search for all sequences with this number and turn them off */ + nt = wess_driver_sequences; + na = pm_stat->seqs_active; + psq_stat = pm_stat->pseqstattbl; + + if (na) + { + while (nt--) + { + if (psq_stat->flags & SEQ_ACTIVE) + { + li = psq_stat->tracks_active; + lj = pm_stat->max_trks_perseq; + /* *lpdest refers to an active track if not 0xFF */ + lpdest = psq_stat->ptrk_indxs; + while (lj--) + { + if (*lpdest != 0xFF) + { + ptmp = (pm_stat->ptrkstattbl + (*lpdest)); + + if (ptmp->sndclass == SNDFX_CLASS) + { + //save + ppos = ptmp->ppos; + + // set tmp buffer ppos + ptmp->ppos = tmpppos; + ptmp->ppos[0] = VolumeMod; + ptmp->ppos[1] = ptmp->volume_cntrl; + ptmp->volume_cntrl = 0; + + CmdFuncArr[ptmp->patchtype][VolumeMod](ptmp); + + //restore + ptmp->ppos = ppos; + } + if (!--li) break; + } + lpdest++; + } + + if (!--na) break; + } + psq_stat++; + } + } + + wess_enable(); +} + +void wess_master_mus_vol_set(char volume) // 800313DC +{ + char _volume; + + _volume = volume; + + wess_disable(); + queue_the_function(QUEUE_MASTER_MUS_VOL_SET); + queue_the_data(&_volume, sizeof(char)); + wess_enable(); +} + + +void queue_wess_master_mus_vol_set(char volume); + +void run_queue_wess_master_mus_vol_set(void) // 80031418 +{ + char volume; + + unqueue_the_data(&volume, sizeof(char)); + queue_wess_master_mus_vol_set(volume); +} + +void queue_wess_master_mus_vol_set(char volume) // 80031448 +{ + char nt, na; + sequence_status *psq_stat; + track_status *ptmp; + char *lpdest; + char *ppos; + int li, lj; + char tmpppos[16]; + + char _volume; + + _volume = volume; + + if (!Is_Module_Loaded()) + { + return; + } + + master_mus_volume = _volume; + + wess_disable(); + + /* search for all sequences with this number and turn them off */ + nt = wess_driver_sequences; + na = pm_stat->seqs_active; + psq_stat = pm_stat->pseqstattbl; + + if (na) + { + while (nt--) + { + if (psq_stat->flags & SEQ_ACTIVE) + { + li = psq_stat->tracks_active; + lj = pm_stat->max_trks_perseq; + /* *lpdest refers to an active track if not 0xFF */ + lpdest = psq_stat->ptrk_indxs; + while (lj--) + { + if (*lpdest != 0xFF) + { + ptmp = (pm_stat->ptrkstattbl + (*lpdest)); + + if (ptmp->sndclass == MUSIC_CLASS) + { + //save + ppos = ptmp->ppos; + + // set tmp buffer ppos + ptmp->ppos = tmpppos; + ptmp->ppos[0] = VolumeMod; + ptmp->ppos[1] = ptmp->volume_cntrl; + ptmp->volume_cntrl = 0; + + CmdFuncArr[ptmp->patchtype][VolumeMod](ptmp); + + //restore + ptmp->ppos = ppos; + } + if (!--li) break; + } + lpdest++; + } + + if (!--na) break; + } + psq_stat++; + } + } + + wess_enable(); +} + +char wess_pan_mode_get(void) // 80031624 +{ + return pan_status; +} + +void wess_pan_mode_set(char mode) // 80031634 +{ + pan_status = mode; +} +#endif diff --git a/Doom 64/wessapip.c b/Doom 64/wessapip.c @@ -0,0 +1,535 @@ + +/* WESS API INCLUDES */ +#include "wessapi.h" // audio stuff... +#include "seqload.h" +#include "soundhw.h" +#include "wessarc.h" +#include "wessseq.h" + +#include "funqueue.h" + +#include "graph.h" // debug +#ifndef NOUSEWESSCODE +extern pmasterstat *pm_stat; //0x800B41CC + +void trackstart(track_status *ptmp, sequence_status *psq_stat) // 80031650 +{ + if (ptmp->flags & TRK_STOPPED) + { + ptmp->flags &= ~(TRK_MUTE|TRK_STOPPED); + if (++psq_stat->tracks_playing) + { + psq_stat->playmode = SEQ_STATE_PLAYING; + } + } +} + +void trackstop(track_status *ptmp, sequence_status *psq_stat) // 800316A0 +{ + if (!(ptmp->flags & TRK_STOPPED)) + { + ptmp->flags |= (TRK_MUTE|TRK_STOPPED); + if (!--psq_stat->tracks_playing) + { + psq_stat->playmode = SEQ_STATE_STOPPED; + } + } +} + +void wess_seq_pause(int sequence_number, enum MuteFlag mflag) // 800316F0 +{ + char nt, na; + sequence_status *psq_stat; + track_status *ptmp; + char *lpdest; + int li, lj; + + int _sequence_number; + enum MuteFlag _mflag; + + _sequence_number = sequence_number; + _mflag = mflag; + + if (!Is_Seq_Num_Valid(_sequence_number)) + { + return; + } + + /* immediate pause of sequence */ + wess_disable(); + + /* search for all sequences with this number and turn them off */ + nt = wess_driver_sequences; + na = pm_stat->seqs_active; + psq_stat = pm_stat->pseqstattbl; + if (na) + { + while (nt--) + { + if (psq_stat->flags & SEQ_ACTIVE) + { + if (psq_stat->seq_num == _sequence_number) + { + psq_stat->flags |= SEQ_PAUSE; + } + if (!--na) break; + } + psq_stat++; + } + } + + queue_the_function(QUEUE_SEQ_PAUSE); + queue_the_data(&_sequence_number, sizeof(int)); + queue_the_data(&_mflag, sizeof(int)); + + wess_enable(); +} + +void queue_wess_seq_pause(int sequence_number, enum MuteFlag mflag); + +void run_queue_wess_seq_pause(void) // 800317B8 +{ + enum MuteFlag mflag; + int sequence_number; + + unqueue_the_data(&sequence_number, sizeof(int)); + unqueue_the_data(&mflag, sizeof(int)); + queue_wess_seq_pause(sequence_number, mflag); +} + +void queue_wess_seq_pause(int sequence_number, enum MuteFlag mflag) // 800317F8 +{ + char nt, na; + sequence_status *psq_stat; + track_status *ptmp; + char *lpdest; + int li, lj; + + int _sequence_number; + enum MuteFlag _mflag; + + _sequence_number = sequence_number; + _mflag = mflag; + + if (!Is_Seq_Num_Valid(_sequence_number)) + { + return; + } + + /* immediate pause of sequence */ + wess_disable(); + + /* search for all sequences with this number and turn them off */ + nt = wess_driver_sequences; + na = pm_stat->seqs_active; + psq_stat = pm_stat->pseqstattbl; + if (na) + { + while (nt--) + { + if (psq_stat->flags & SEQ_ACTIVE) + { + if (psq_stat->seq_num == _sequence_number) + { + if (psq_stat->flags & SEQ_PAUSE) + { + psq_stat->flags &= ~SEQ_PAUSE; + + li = psq_stat->tracks_active; + lj = pm_stat->max_trks_perseq; + /* *lpdest refers to an active track if not 0xFF */ + lpdest = psq_stat->ptrk_indxs; + while (lj--) + { + if (*lpdest != 0xFF) + { + ptmp = (pm_stat->ptrkstattbl + (*lpdest)); + trackstop(ptmp, psq_stat); + if (_mflag == YesMute) + { + CmdFuncArr[ptmp->patchtype][TrkMute](ptmp); + } + if (!--li) break; + } + lpdest++; + } + } + } + if (!--na) break; + } + psq_stat++; + } + } + + wess_enable(); +} + +void wess_seq_restart(int sequence_number) // 800319C4 +{ + char nt, na; + sequence_status *psq_stat; + track_status *ptmp; + char *lpdest; + int li, lj; + + int _sequence_number; + + _sequence_number = sequence_number; + + if (!Is_Seq_Num_Valid(_sequence_number)) + { + return; + } + + /* immediate restart of sequence */ + wess_disable(); + + /* search for all sequences with this number and turn them off */ + nt = wess_driver_sequences; + na = pm_stat->seqs_active; + psq_stat = pm_stat->pseqstattbl; + if (na) + { + while (nt--) + { + if (psq_stat->flags & SEQ_ACTIVE) + { + if (psq_stat->seq_num == _sequence_number) + { + psq_stat->flags |= SEQ_RESTART; + } + if (!--na) break; + } + psq_stat++; + } + } + + queue_the_function(QUEUE_SEQ_RESTART); + queue_the_data(&_sequence_number, sizeof(int)); + + wess_enable(); +} + +void queue_wess_seq_restart(int sequence_number); + +void run_queue_wess_seq_restart(void) // 80031A7C +{ + int sequence_number; + + unqueue_the_data(&sequence_number, sizeof(int)); + queue_wess_seq_restart(sequence_number); +} + +void queue_wess_seq_restart(int sequence_number) // 80031AAC +{ + char nt, na; + sequence_status *psq_stat; + track_status *ptmp; + char *lpdest; + int li, lj; + + int _sequence_number; + + _sequence_number = sequence_number; + + if (!Is_Seq_Num_Valid(_sequence_number)) + { + return; + } + + /* immediate restart of sequence */ + wess_disable(); + + /* search for all sequences with this number and turn them off */ + nt = wess_driver_sequences; + na = pm_stat->seqs_active; + psq_stat = pm_stat->pseqstattbl; + if (na) + { + while (nt--) + { + if (psq_stat->flags & SEQ_ACTIVE) + { + if (psq_stat->seq_num == _sequence_number) + { + if (psq_stat->flags & SEQ_RESTART) + { + psq_stat->flags &= ~SEQ_RESTART; + li = psq_stat->tracks_active; + lj = pm_stat->max_trks_perseq; + /* *lpdest refers to an active track if not 0xFF */ + lpdest = psq_stat->ptrk_indxs; + while (lj--) + { + if (*lpdest != 0xFF) + { + ptmp = (pm_stat->ptrkstattbl + (*lpdest)); + trackstart(ptmp, psq_stat); + if (!--li) break; + } + lpdest++; + } + } + } + if (!--na) break; + } + psq_stat++; + } + } + + wess_enable(); +} + +void wess_seq_pauseall(enum MuteFlag mflag, int remember) // 80031C14 +{ + char nt, na; + sequence_status *psq_stat; + track_status *ptmp; + char *lpdest; + int li, lj; + + enum MuteFlag _mflag; + int _remember; + + _mflag = mflag; + _remember = remember; + + if (!Is_Module_Loaded()) + { + return; + } + + /* immediate pause of all sequences */ + wess_disable(); + + /* search for all sequences with this number and turn them off */ + nt = wess_driver_sequences; + na = pm_stat->seqs_active; + psq_stat = pm_stat->pseqstattbl; + if (na) + { + while (nt--) + { + if (psq_stat->flags & SEQ_ACTIVE) + { + psq_stat->flags |= SEQ_PAUSE; + if (!--na) break; + } + psq_stat++; + } + } + + queue_the_function(QUEUE_SEQ_PAUSEALL); + queue_the_data(&_mflag, sizeof(int)); + queue_the_data(&_remember, sizeof(int)); + + wess_enable(); +} + +void queue_wess_seq_pauseall(enum MuteFlag mflag, int remember); + +void run_queue_wess_seq_pauseall(void) // 80031CCC +{ + enum MuteFlag mflag; + int remember; + + unqueue_the_data(&mflag, sizeof(int)); + unqueue_the_data(&remember, sizeof(int)); + queue_wess_seq_pauseall(mflag, remember); +} + +void queue_wess_seq_pauseall(enum MuteFlag mflag, int remember) // 80031D0C +{ + char nt, na; + sequence_status *psq_stat; + track_status *ptmp; + char *lpdest; + int li, lj; + + enum MuteFlag _mflag; + int _remember; + + _mflag = mflag; + _remember = remember; + + if (!Is_Module_Loaded()) + { + return; + } + + /* immediate pause of all sequences */ + wess_disable(); + + if (_mflag == YesMute) + { + start_record_music_mute(_remember); + } + + /* search for all sequences with this number and turn them off */ + nt = wess_driver_sequences; + na = pm_stat->seqs_active; + psq_stat = pm_stat->pseqstattbl; + if (na) + { + while (nt--) + { + if (psq_stat->flags & SEQ_ACTIVE) + { + if (psq_stat->flags & SEQ_PAUSE) + { + psq_stat->flags &= ~SEQ_PAUSE; + + li = psq_stat->tracks_active; + lj = pm_stat->max_trks_perseq; + /* *lpdest refers to an active track if not 0xFF */ + lpdest = psq_stat->ptrk_indxs; + while (lj--) + { + if (*lpdest != 0xFF) + { + ptmp = (pm_stat->ptrkstattbl + (*lpdest)); + trackstop(ptmp, psq_stat); + if (_mflag == YesMute) + { + CmdFuncArr[ptmp->patchtype][TrkMute](ptmp); + } + if (!--li) break; + } + lpdest++; + } + + if (!--na) break; + } + } + psq_stat++; + } + } + + if (_mflag == YesMute) + { + end_record_music_mute(); + } + + wess_enable(); +} + +void wess_seq_restartall(enum VoiceRestartFlag restart_remembered_voices) // 80031EF4 +{ + char nt, na; + sequence_status *psq_stat; + track_status *ptmp; + char *lpdest; + int li, lj, ncnt, nc; + + enum VoiceRestartFlag _restart_remembered_voices; + + _restart_remembered_voices = restart_remembered_voices; + + if (!Is_Module_Loaded()) + { + return; + } + + /* immediate restart of all sequences */ + wess_disable(); + + /* search for all sequences with this number and turn them off */ + nt = wess_driver_sequences; + na = pm_stat->seqs_active; + psq_stat = pm_stat->pseqstattbl; + if (na) + { + while (nt--) + { + if (psq_stat->flags & SEQ_ACTIVE) + { + psq_stat->flags |= SEQ_RESTART; + if (!--na) break; + } + psq_stat++; + } + } + + queue_the_function(QUEUE_SEQ_RESTARTALL); + queue_the_data(&_restart_remembered_voices, sizeof(int)); + + wess_enable(); +} + +void queue_wess_seq_restartall(enum VoiceRestartFlag restart_remembered_voices); + +void run_queue_wess_seq_restartall(void) // 80031F9C +{ + enum VoiceRestartFlag restart_remembered_voices; + + unqueue_the_data(&restart_remembered_voices, sizeof(int)); + queue_wess_seq_restartall(restart_remembered_voices); +} + +extern void do_record_music_unmute(int seq_num, int track, track_status *ptk_stat); + +void queue_wess_seq_restartall(enum VoiceRestartFlag restart_remembered_voices) // 80031FCC +{ + char nt, na; + sequence_status *psq_stat; + track_status *ptmp; + char *lpdest; + int li, lj, ncnt, nc; + + enum VoiceRestartFlag _restart_remembered_voices; + + _restart_remembered_voices = restart_remembered_voices; + + if (!Is_Module_Loaded()) + { + return; + } + + /* immediate restart of all sequences */ + wess_disable(); + + /* search for all sequences with this number and turn them off */ + nt = wess_driver_sequences; + na = pm_stat->seqs_active; + psq_stat = pm_stat->pseqstattbl; + if (na) + { + while (nt--) + { + if (psq_stat->flags & SEQ_ACTIVE) + { + if (psq_stat->flags & SEQ_RESTART) + { + psq_stat->flags &= ~SEQ_RESTART; + + li = psq_stat->tracks_active; + lj = pm_stat->max_trks_perseq; + /* *lpdest refers to an active track if not 0xFF */ + lpdest = psq_stat->ptrk_indxs; + while (lj--) + { + if (*lpdest != 0xFF) + { + ptmp = (pm_stat->ptrkstattbl + (*lpdest)); + trackstart(ptmp, psq_stat); + + if (_restart_remembered_voices) + { + do_record_music_unmute(psq_stat->seq_num, *lpdest, ptmp); + } + + if (!--li) break; + } + lpdest++; + } + + if (!--na) break; + } + } + psq_stat++; + } + } + + wess_enable(); +} +#endif diff --git a/Doom 64/wessapit.c b/Doom 64/wessapit.c @@ -0,0 +1,649 @@ + +/* WESS API INCLUDES */ +#include "wessapi.h" // audio stuff... +#include "seqload.h" +#include "soundhw.h" +#include "wessarc.h" +#include "wessseq.h" + +#include "funqueue.h" + +#include "graph.h" // debug +#ifndef NOUSEWESSCODE +extern pmasterstat *pm_stat; //0x800B41CC + +/* used by wess trigger functions */ +enum HandleFlag { NoHandle, YesHandle }; + +/* used by wess_seq_stop and wess_seq_stop_and_voiceramp functions */ +enum MuteRelease { NoMuteRelease, YesMuteRelease}; + +void wess_seq_trigger_type(int seq_num, unsigned long seq_type) // 80032160 +{ + sequence_data *psq_info; + + psq_info = pm_stat->pmod_info->pseq_info + seq_num; /* pointer math */ + + wess_seq_structrig(psq_info, seq_num, seq_type, NoHandle, NULL); +} + +void wess_seq_trigger_type_special(int seq_num, unsigned long seq_type, TriggerPlayAttr *attr) // 800321A8 +{ + sequence_data *psq_info; + + psq_info = pm_stat->pmod_info->pseq_info + seq_num; /* pointer math */ + + wess_seq_structrig(psq_info, seq_num, seq_type, NoHandle, attr); +} + +void updatetrackstat(track_status *ptk_stat, TriggerPlayAttr *attr) // 800321FC +{ + int tempmask; + char *temp; + char tmpppos[4]; + + if ((attr == NULL) || (!attr->mask)) + return; + + tempmask = attr->mask; + + if (tempmask & TRIGGER_VOLUME) //0x01 + { + temp = ptk_stat->ppos; //copy + + // set tmp buffer ppos + ptk_stat->ppos = tmpppos; + ptk_stat->ppos[0] = VolumeMod; + ptk_stat->ppos[1] = attr->volume; + + CmdFuncArr[ptk_stat->patchtype][VolumeMod](ptk_stat); + ptk_stat->ppos = temp; //restore + } + + if (tempmask & TRIGGER_PAN) + { + temp = ptk_stat->ppos; //copy + + // set tmp buffer ppos + ptk_stat->ppos = tmpppos; + ptk_stat->ppos[0] = PanMod; + ptk_stat->ppos[1] = attr->pan; + + CmdFuncArr[ptk_stat->patchtype][PanMod](ptk_stat); + ptk_stat->ppos = temp; //restore + } + + if (tempmask & TRIGGER_PATCH) //0x04 + { + ptk_stat->patchnum = attr->patch; + } + + if (tempmask & TRIGGER_PITCH) //0x08 + { + temp = ptk_stat->ppos; //copy + + // set tmp buffer ppos + ptk_stat->ppos = tmpppos; + ptk_stat->ppos[0] = PitchMod; + ptk_stat->ppos[1] = (char)(attr->pitch & 0xff); + ptk_stat->ppos[2] = (char)(attr->pitch >> 8); + + CmdFuncArr[ptk_stat->patchtype][PitchMod](ptk_stat); + ptk_stat->ppos = temp; //restore + } + + if (tempmask & TRIGGER_MUTEMODE) //0x10 + { + if (ptk_stat->mutemask & (1 << attr->mutemode)) + { + ptk_stat->flags |= TRK_MUTE; + } + else { + ptk_stat->flags &= ~TRK_MUTE; + } + } + + if (tempmask & TRIGGER_TEMPO) //0x20 + { + ptk_stat->qpm = attr->tempo; + ptk_stat->ppi = CalcPartsPerInt(GetIntsPerSec(), ptk_stat->ppq, ptk_stat->qpm); + } + + if (tempmask & TRIGGER_TIMED) //0x40 + { + ptk_stat->endppi = ptk_stat->totppi + attr->timeppq; + ptk_stat->flags |= TRK_TIMED; + } + + if (tempmask&TRIGGER_LOOPED) //0x80 + { + ptk_stat->flags |= TRK_LOOPED; + } +} + +void wess_seq_update_type_special(unsigned long seq_type, TriggerPlayAttr *attr) // 80032460 +{ + unsigned long _seq_type; + TriggerPlayAttr *_attr; + + _seq_type = seq_type; + _attr = attr; + + wess_disable(); + + queue_the_function(QUEUE_SEQ_UPDATE_TYPE_SPECIAL); + queue_the_data(&_seq_type, sizeof(unsigned long)); + queue_the_data(&_attr, sizeof(TriggerPlayAttr)); + + wess_enable(); +} + +void queue_wess_seq_update_type_special(unsigned long seq_type, TriggerPlayAttr *attr); + +void run_queue_wess_seq_update_type_special(void) // 800324AC +{ + unsigned long seq_type; + TriggerPlayAttr attr; + + unqueue_the_data(&seq_type, sizeof(unsigned long)); + unqueue_the_data(&attr, sizeof(TriggerPlayAttr)); + queue_wess_seq_update_type_special(seq_type, &attr); +} + +void queue_wess_seq_update_type_special(unsigned long seq_type, TriggerPlayAttr *attr) // 800324E8 +{ + /* immediate stop of sequence */ + char nt, na; + sequence_status *psq_stat; + track_status *ptmp; + char *lpdest; + int li, lj; + + unsigned long _seq_type; + TriggerPlayAttr *_attr; + + _seq_type = seq_type; + _attr = attr; + + if (!Is_Module_Loaded()) + { + return; + } + + wess_disable(); + + /* search for all sequences with this number and turn them off */ + nt = wess_driver_sequences; + na = pm_stat->seqs_active; + psq_stat = pm_stat->pseqstattbl; + if (na) + { + while (nt--) + { + if (psq_stat->flags & SEQ_ACTIVE) + { + if (psq_stat->seq_type == _seq_type) + { + li = psq_stat->tracks_active; + lj = pm_stat->max_trks_perseq; + /* *lpdest refers to an active track if not 0xFF */ + lpdest = psq_stat->ptrk_indxs; + while (lj--) + { + if (*lpdest != 0xFF) + { + ptmp = (pm_stat->ptrkstattbl + (*lpdest)); + if (_attr != 0) + { + updatetrackstat(ptmp, _attr); + } + if (!--li) break; + } + lpdest++; + } + } + if (!--na) break; + } + psq_stat++; + } + } + + wess_enable(); +} + +int wess_seq_type_status(unsigned long sequence_type) // 8003266C +{ + char nt, na; + sequence_status *psq_stat; + int status; + + unsigned long _sequence_type; + + _sequence_type = sequence_type; + + if (!Is_Module_Loaded()) + { + return(SEQUENCE_INACTIVE); + } + + wess_disable(); + + status = SEQUENCE_INACTIVE; + + /* search for all sequences with this number and turn them off */ + nt = wess_driver_sequences; + na = pm_stat->seqs_active; + psq_stat = pm_stat->pseqstattbl; + if (na) + { + while (nt--) + { + if (psq_stat->flags & SEQ_ACTIVE) + { + if (psq_stat->seq_type == _sequence_type) + { + if (psq_stat->playmode == SEQ_STATE_STOPPED) + { + status = SEQUENCE_STOPPED; + } + else if (psq_stat->playmode == SEQ_STATE_PLAYING) { + status = SEQUENCE_PLAYING; + } + } + + if (!--na) break; + } + psq_stat++; + } + } + + wess_enable(); + + return(status); +} + +void __wess_seq_stoptype(unsigned long sequence_type, enum MuteRelease mrelease, int millisec) // 80032758 +{ + char nt, na; + sequence_status *psq_stat; + + unsigned long _sequence_type; + enum MuteRelease _mrelease; + int _millisec; + + _sequence_type = sequence_type; + _mrelease = mrelease; + _millisec = millisec; + + if (!Is_Module_Loaded()) + { + return; + } + + + wess_disable(); + + + /* search for all sequences with this number and turn them off */ + nt = wess_driver_sequences; + na = pm_stat->seqs_active; + psq_stat = pm_stat->pseqstattbl; + if (na) + { + while (nt--) + { + if (psq_stat->flags & SEQ_ACTIVE) + { + if (psq_stat->seq_type == _sequence_type) + { + psq_stat->flags = (psq_stat->flags | SEQ_STOP) & ~(SEQ_PAUSE|SEQ_RESTART); + } + + if (!--na) break; + } + psq_stat++; + } + } + + if (_mrelease) + { + queue_the_function(QUEUE_SEQ_STOPTYPE_AND_VOICERAMP); + queue_the_data(&_millisec, sizeof(int)); + } + else + { + queue_the_function(QUEUE_SEQ_STOPTYPE); + } + queue_the_data(&_sequence_type, sizeof(int)); + wess_enable(); +} + +void wess_seq_stoptype(unsigned long sequence_type) // 80032868 +{ + __wess_seq_stoptype(sequence_type, NoMuteRelease, 0); +} + +void wess_seq_stoptype_and_voiceramp(unsigned long sequence_type, int millisec) // 8003288C +{ + __wess_seq_stoptype(sequence_type, YesMuteRelease, millisec); +} + +void queue_wess_seq_stoptype(unsigned long sequence_type, enum MuteRelease mrelease, int millisec); + +void run_queue_wess_seq_stoptype(void) // 800328B0 +{ + unsigned long sequence_type; + + unqueue_the_data(&sequence_type, sizeof(unsigned long)); + queue_wess_seq_stoptype(sequence_type, NoMuteRelease, 0); +} + +void run_queue_wess_seq_stoptype_and_voiceramp(void) // 800328E4 +{ + int millisec; + unsigned long sequence_type; + + unqueue_the_data(&millisec, sizeof(int)); + unqueue_the_data(&sequence_type, sizeof(unsigned long)); + queue_wess_seq_stoptype(sequence_type, YesMuteRelease, millisec); +} + +void queue_wess_seq_stoptype(unsigned long sequence_type, enum MuteRelease mrelease, int millisec) // 80032924 +{ + char nt, na; + sequence_status *psq_stat; + track_status *ptmp; + char *lpdest; + int li, lj; + int get_millisec; + + unsigned long _sequence_type; + enum MuteRelease _mrelease; + int _millisec; + + _sequence_type = sequence_type; + _mrelease = mrelease; + _millisec = millisec; + + if (!Is_Module_Loaded()) + { + return; + } + + wess_disable(); + + + /* search for all sequences with this number and turn them off */ + nt = wess_driver_sequences; + na = pm_stat->seqs_active; + psq_stat = pm_stat->pseqstattbl; + if (na) + { + if (_mrelease) + { + get_millisec = wess_get_mute_release(); + wess_set_mute_release(_millisec); + } + + while (nt--) + { + if (psq_stat->flags & SEQ_ACTIVE) + { + if (psq_stat->seq_type == _sequence_type) + { + if (psq_stat->flags & SEQ_STOP) + { + psq_stat->flags &= ~SEQ_STOP; + + li = psq_stat->tracks_active; + lj = pm_stat->max_trks_perseq; + /* *lpdest refers to an active track if not 0xFF */ + lpdest = psq_stat->ptrk_indxs; + while (lj--) + { + if (*lpdest != 0xFF) + { + ptmp = (pm_stat->ptrkstattbl + (*lpdest)); + CmdFuncArr[ptmp->patchtype][TrkOff](ptmp); + + if (!--li) break; + } + lpdest++; + } + } + } + + if (!--na) break; + } + psq_stat++; + } + } + + if (_mrelease) + { + wess_set_mute_release(get_millisec); + } + + wess_enable(); +} + +int wess_get_seq_num_active(int seq_num) // 80032B24 +{ + char nt, na; + sequence_status *psq_stat; + int seq_count; + + int _seq_num; + + _seq_num = seq_num; + + if (!Is_Seq_Num_Valid(_seq_num)) + { + return(0); + } + + seq_count = 0; + + wess_disable(); + + /* search for all sequences with this number and turn them off */ + nt = wess_driver_sequences; + na = pm_stat->seqs_active; + psq_stat = pm_stat->pseqstattbl; + if (na) + { + while (nt--) + { + if (psq_stat->flags & SEQ_ACTIVE) + { + if (psq_stat->seq_num == _seq_num) + { + seq_count++; + } + + if (!--na) break; + } + psq_stat++; + } + } + + wess_enable(); + + return (seq_count); +} + +int wess_copy_all_seq_num_active(int *seq_num_list) // 80032BE8 +{ + char nt, na; + sequence_status *psq_stat; + int i, seq_count, sikip_set_seq; + int *list_temp; + + int *_seq_num_list; + + _seq_num_list = seq_num_list; + + if (!Is_Module_Loaded()) + { + return(0); + } + + seq_count = 0; + + wess_disable(); + + /* search for all sequences with this number and turn them off */ + nt = wess_driver_sequences; + na = pm_stat->seqs_active; + psq_stat = pm_stat->pseqstattbl; + if (na) + { + while (nt--) + { + sikip_set_seq = 0; + if (psq_stat->flags & SEQ_ACTIVE) + { + i = 0; + if(seq_count > 0) + { + list_temp = _seq_num_list; + do + { + if (psq_stat->seq_num == *list_temp) + { + sikip_set_seq = 1; + break; + } + list_temp++; + i++; + }while (i != seq_count); + } + + if (!sikip_set_seq) + { + list_temp = (_seq_num_list + seq_count); + *list_temp = psq_stat->seq_num; + seq_count++; + } + + if (!--na) break; + } + psq_stat++; + } + } + + wess_enable(); + + return (seq_count); +} + +int wess_get_seq_type_active(int seq_type) // 80032CD4 +{ + char nt, na; + sequence_status *psq_stat; + int seq_count; + + int _seq_type; + + _seq_type = seq_type; + + if (!Is_Module_Loaded()) + { + return(0); + } + + seq_count = 0; + + wess_disable(); + + /* search for all sequences with this number and turn them off */ + nt = wess_driver_sequences; + na = pm_stat->seqs_active; + psq_stat = pm_stat->pseqstattbl; + if (na) + { + while (nt--) + { + if (psq_stat->flags & SEQ_ACTIVE) + { + if (psq_stat->seq_type == _seq_type) + { + seq_count++; + } + + if (!--na) break; + } + psq_stat++; + } + } + + wess_enable(); + + return (seq_count); +} + +int wess_copy_all_seq_type_active(int *seq_type_list) // 80032D8C +{ + char nt, na; + sequence_status *psq_stat; + int i, seq_count, sikip_set_seq; + int *list_temp; + + int *_seq_type_list; + + _seq_type_list = seq_type_list; + + if (!Is_Module_Loaded()) + { + return(0); + } + + wess_disable(); + + seq_count = 0; + + /* search for all sequences with this number and turn them off */ + nt = wess_driver_sequences; + na = pm_stat->seqs_active; + psq_stat = pm_stat->pseqstattbl; + if (na) + { + while (nt--) + { + sikip_set_seq = 0; + if (psq_stat->flags & SEQ_ACTIVE) + { + i = 0; + if (seq_count > 0) + { + list_temp = _seq_type_list; + do + { + if (psq_stat->seq_type == *list_temp) + { + sikip_set_seq = 1; + break; + } + list_temp++; + i++; + } while (i != seq_count); + } + + if (!sikip_set_seq) + { + list_temp = (_seq_type_list + seq_count); + *list_temp = psq_stat->seq_type; + seq_count++; + } + + if (!--na) break; + } + psq_stat++; + } + } + + wess_enable(); + + return (seq_count); +} +#endif diff --git a/Doom 64/wessarc.c b/Doom 64/wessarc.c @@ -0,0 +1,530 @@ + +#include "wessapi.h" +#include "wessarc.h" +#include "wessint_s.h" +#ifndef NOUSEWESSCODE +extern void(*DrvFunctions[36])(track_status *); +extern void(*drv_cmds[19])(track_status *); + +void (**CmdFuncArr[10])(track_status *) = { + DrvFunctions, + drv_cmds, + DrvFunctions, + DrvFunctions, + DrvFunctions, + DrvFunctions, + DrvFunctions, + DrvFunctions, + DrvFunctions, + DrvFunctions + }; + +int wess_driver_num_dma_buffers = 24; // 8005D948 +int wess_driver_num_dma_messages = 32; // 8005D94C +int wess_driver_dma_buffer_length = 0x800; // 8005D950 +int wess_driver_extra_samples = 80; // 8005D954 +int wess_driver_frame_lag = 1; // 8005D958 +int wess_driver_voices = 24; // 8005D95C +int wess_driver_updates = 48; // 8005D960 +int wess_driver_sequences = 26; // 8005D964 +int wess_driver_tracks = 25; // 8005D968 +int wess_driver_gates = 0; // 8005D96C +int wess_driver_iters = 0; // 8005D970 +int wess_driver_callbacks = 0; // 8005D974 +int wess_driver_max_trks_per_seq = 16; // 8005D978 load_sequence_data:80039868(R), +int wess_driver_max_subs_per_trk = 0; // 8005D97C + + +int WessTimerActive = 0; // 8005D984 +int T2counter = 0; // 8005D988 +unsigned long millicount = 0; // 8005D98C +int SeqOn = 0; // 8005D990 +unsigned long accmpi = 0; // 8005D994 +int disabledeep = 0; // 8005D998 + +WessErrorCallbackProc wesserr; // 800B4210 +WessDecompCallbackProc wessdecomp; // 800B4214 +long imask; // 800B4218 + +void wess_set_error_callback(WessErrorCallbackProc errcall) // 80035290 +{ + wesserr = errcall; +} + +void wess_error_callback(char *errstring, int errnum1, int errnum2) // 8003529C +{ + if (wesserr) + { + wesserr(errstring, errnum1, errnum2); + } +} + +void wess_set_decomp_callback(WessDecompCallbackProc decompcall) // 800352C8 +{ + wessdecomp = decompcall; +} + +int wess_decomp(unsigned char decomp_type, + char *fileref, + unsigned long file_offset, + char *ramdest, + unsigned long uncompressed_size) // 800352D4 +{ + if (wessdecomp != 0) + { + return wessdecomp(decomp_type, fileref, file_offset, ramdest, uncompressed_size); + } + + return(-1); +} + +void wess_low_level_init(void) // 8003531C +{ + //Nothing +} + +void wess_low_level_exit(void) // 80035324 +{ + //Nothing +} + +char *wess_malloc(char *mem) // 8003532C +{ + return NULL; +} + +void wess_free(char *mem) // 80035338 +{ + //Nothing +} + +void wess_engine_off(void) // 80035340 +{ + SeqOn = 0; +} + +void wess_engine_on(void) // 8003534C +{ + SeqOn = 1; +} + +void wess_disable(void) // 8003535C +{ + if (disabledeep == 0) + { + imask = wesssys_disable_ints(); + } + disabledeep += 1; +} + +void wess_enable(void) // 8003539C +{ + disabledeep += -1; + if (disabledeep == 0) + { + wesssys_restore_ints(imask); + } +} + +short GetIntsPerSec(void) // 800353DC +{ + return(120); +} + + +unsigned long CalcPartsPerInt(short ips, short ppq, short qpm) // 800353E4 +{ + register unsigned long arg0; + register unsigned long ppi; + + __ll_mul((s32) qpm >> 31, qpm, 0, (1<<16)); + asm("move %0,$2":"=r"(arg0) : ); + asm("move %0,$3":"=r"(ppi) : ); + __ll_mul(arg0, (u32) ppi, (s32) ppq >> 31, ppq); + asm("move %0,$2":"=r"(arg0) : ); + asm("move %0,$3":"=r"(ppi) : ); + __ull_div(arg0, (u32) ppi, 0, 60); + asm("move %0,$2":"=r"(arg0) : ); + asm("move %0,$3":"=r"(ppi) : ); + __ull_div(arg0, (u32) ppi, (s32) ips >> 31, ips); + asm("move %0,$2":"=r"(arg0) : ); + asm("move %0,$3":"=r"(ppi) : ); + return (u32) ppi; +} + +long WessInterruptHandler(void) // 80035458 +{ + accmpi += 0x85555; + millicount += (accmpi >> 16); + accmpi &= 65535; + + T2counter++; + if (SeqOn) + { + process_function_queue(); + SeqEngine(); + } + return(0); +} + +void init_WessTimer(void) // 800354DC +{ + SeqOn = 0; + WessTimerActive = 1; +} + +void exit_WessTimer(void) // 800354F4 +{ + WessTimerActive = 0; +} + +int Wess_init_for_LoadFileData(char *filename) // 80035500 +{ + return(1); +} + +char alignbuf[28]; // 800B41E4 unused +Wess_File_IO_Struct module_fileref; // 800B4200 +Wess_Data_IO_Struct data_fileref; // 800B4208 + +Wess_File_IO_Struct *module_open(char *filename) // 8003550C +{ + module_fileref.start = filename; + module_fileref.src = filename; + return &module_fileref; +} + +int module_read(void *destptr, int readbytes, Wess_File_IO_Struct *fileptr) // 80035520 +{ + wess_rom_copy(fileptr->src, (char *)destptr, readbytes); + fileptr->src += readbytes; + return readbytes; +} + +int module_seek(Wess_File_IO_Struct *fileptr, int seekpos, int seekmode) // 80035574 +{ + if (seekmode == SEEK_SET) + { + fileptr->src = fileptr->start + seekpos; + } + else if (seekmode == SEEK_CUR) + { + fileptr->src += seekpos; + } + return 0; +} + +unsigned long module_tell(Wess_File_IO_Struct *fileptr) // 800355B0 +{ + return (unsigned long)fileptr->src; +} + +void module_close(Wess_File_IO_Struct *fileptr) // 800355BC +{ + return; +} + +int get_num_Wess_Sound_Drivers(int **settings_tag_lists) // 800355C4 +{ + return(1); +} + +Wess_File_IO_Struct *data_open(char *filename) // 800355D0 +{ + return &data_fileref; +} + +int data_read(Wess_Data_IO_Struct *fileptr, void *destptr, int readbytes, int filepos) //800355E0 +{ + return 0; +} + +void data_close(Wess_Data_IO_Struct *fileptr) // 800355F8 +{ + return; +} + +static unsigned char sequence_table[128]; // 800B4220 + +char *get_sequence_table(void) // 80035600 +{ + master_status_structure *pm_stat_ptr; + int sequences; + int i; + + pm_stat_ptr = (master_status_structure *)wess_get_master_status(); + + sequences = wess_driver_sequences; + if (sequences > 127) + sequences = 127; + + if (pm_stat_ptr) + { + i = 0; + if (sequences > 0) + { + if (sequences & 3) + { + do + { + if ((pm_stat_ptr->pseqstattbl + i)->flags & SEQ_ACTIVE) + sequence_table[i] = '1'; + else + sequence_table[i] = '0'; + + i++; + } while (sequences & 3 != i); + } + } + + if (i != sequences) + { + do + { + if ((pm_stat_ptr->pseqstattbl + i)->flags & SEQ_ACTIVE) + sequence_table[i] = '1'; + else + sequence_table[i] = '0'; + + if ((pm_stat_ptr->pseqstattbl + (i + 1))->flags & SEQ_ACTIVE) + sequence_table[i + 1] = '1'; + else + sequence_table[i + 1] = '0'; + + if ((pm_stat_ptr->pseqstattbl + (i + 2))->flags & SEQ_ACTIVE) + sequence_table[i + 2] = '1'; + else + sequence_table[i + 2] = '0'; + + if ((pm_stat_ptr->pseqstattbl + (i + 3))->flags & SEQ_ACTIVE) + sequence_table[i + 3] = '1'; + else + sequence_table[i + 3] = '0'; + + i += 4; + } while (sequences != i); + } + + sequence_table[sequences] = '\0'; + } + + return (char *)&sequence_table; +} + +static unsigned char tracks_table[128]; // 800B42A0 + +char *get_tracks_table(void) // 800357A0 +{ + master_status_structure *pm_stat_ptr; + int tracks; + int i; + + pm_stat_ptr = (master_status_structure *)wess_get_master_status(); + + tracks = wess_driver_tracks; + if (tracks > 127) + tracks = 127; + + if (pm_stat_ptr) + { + i = 0; + if (tracks > 0) + { + if (tracks & 3) + { + do + { + if ((pm_stat_ptr->ptrkstattbl + i)->flags & TRK_ACTIVE) + tracks_table[i] = '1'; + else + tracks_table[i] = '0'; + + i++; + } while (tracks & 3 != i); + } + } + + if (i != tracks) + { + do + { + if ((pm_stat_ptr->ptrkstattbl + i)->flags & TRK_ACTIVE) + tracks_table[i] = '1'; + else + tracks_table[i] = '0'; + + if ((pm_stat_ptr->ptrkstattbl + (i + 1))->flags & TRK_ACTIVE) + tracks_table[i + 1] = '1'; + else + tracks_table[i + 1] = '0'; + + if ((pm_stat_ptr->ptrkstattbl + (i + 2))->flags & TRK_ACTIVE) + tracks_table[i + 2] = '1'; + else + tracks_table[i + 2] = '0'; + + if ((pm_stat_ptr->ptrkstattbl + (i + 3))->flags & TRK_ACTIVE) + tracks_table[i + 3] = '1'; + else + tracks_table[i + 3] = '0'; + + i += 4; + } while (tracks != i); + } + + tracks_table[tracks] = '\0'; + } + + return (char *)&tracks_table; +} + +int get_track_volume_cntrl(int track) // 8003593C +{ + master_status_structure *pm_stat_ptr; + + pm_stat_ptr = (master_status_structure *)wess_get_master_status(); + + if (pm_stat_ptr) + { + return (pm_stat_ptr->ptrkstattbl + track)->volume_cntrl; + } + + return -1; +} + +static unsigned char voices_active_table[128]; // 800B4320 + +char *get_voices_active_table(void) // L80035988 +{ + master_status_structure *pm_stat_ptr; + int voices; + int i; + + pm_stat_ptr = (master_status_structure *)wess_get_master_status(); + + voices = wess_driver_voices; + + if (!(voices < 128)) + voices = 127; + + if (pm_stat_ptr) + { + i = 0; + if (voices > 0) + { + if (voices & 3) + { + do + { + if ((pm_stat_ptr->pvoicestattbl + i)->flags & VOICE_ACTIVE) + voices_active_table[i] = '1'; + else + voices_active_table[i] = '0'; + + i++; + } while (voices & 3 != i); + } + } + + if (i != voices) + { + do + { + if ((pm_stat_ptr->pvoicestattbl + i)->flags & VOICE_ACTIVE) + voices_active_table[i] = '1'; + else + voices_active_table[i] = '0'; + + if ((pm_stat_ptr->pvoicestattbl + (i + 1))->flags & VOICE_ACTIVE) + voices_active_table[i + 1] = '1'; + else + voices_active_table[i + 1] = '0'; + + if ((pm_stat_ptr->pvoicestattbl + (i + 2))->flags & VOICE_ACTIVE) + voices_active_table[i + 2] = '1'; + else + voices_active_table[i + 2] = '0'; + + if ((pm_stat_ptr->pvoicestattbl + (i + 3))->flags & VOICE_ACTIVE) + voices_active_table[i + 3] = '1'; + else + voices_active_table[i + 3] = '0'; + + i += 4; + } while (voices != i); + } + + voices_active_table[voices] = '\0'; + } + + return (char *)&voices_active_table; +} + +static unsigned char voices_handle_table[128]; // 800B43A0 + +char *get_voices_handle_table(void) // 80035B24 +{ + master_status_structure *pm_stat_ptr; + int voices; + int i; + + pm_stat_ptr = (master_status_structure *)wess_get_master_status(); + + voices = wess_driver_voices; + + if (!(voices < 128)) + voices = 127; + + if (pm_stat_ptr) + { + i = 0; + if (voices > 0) + { + if (voices & 3) + { + do + { + if ((pm_stat_ptr->pvoicestattbl + i)->flags & VOICE_RELEASE) + voices_handle_table[i] = '1'; + else + voices_handle_table[i] = '0'; + + i++; + } while (voices & 3 != i); + } + } + + if (i != voices) + { + do + { + if ((pm_stat_ptr->pvoicestattbl + i)->flags & VOICE_RELEASE) + voices_handle_table[i] = '1'; + else + voices_handle_table[i] = '0'; + + if ((pm_stat_ptr->pvoicestattbl + (i + 1))->flags & VOICE_RELEASE) + voices_handle_table[i + 1] = '1'; + else + voices_handle_table[i + 1] = '0'; + + if ((pm_stat_ptr->pvoicestattbl + (i + 2))->flags & VOICE_RELEASE) + voices_handle_table[i + 2] = '1'; + else + voices_handle_table[i + 2] = '0'; + + if ((pm_stat_ptr->pvoicestattbl + (i + 3))->flags & VOICE_RELEASE) + voices_handle_table[i + 3] = '1'; + else + voices_handle_table[i + 3] = '0'; + + i += 4; + } while (voices != i); + } + + voices_handle_table[voices] = '\0'; + } + + return (char *)&voices_handle_table; +} +#endif diff --git a/Doom 64/wessarc.h b/Doom 64/wessarc.h @@ -0,0 +1,465 @@ +#ifndef _WESSARC_H +#define _WESSARC_H + +#include <ultra64.h> +#include <libaudio.h> + +//#define NOUSEWESSCODE + +enum Wess_Error { + + wess_NO_ERROR, + wess_FOPEN, + wess_FREAD, + wess_FSEEK +}; + +//LCD FILE Structs +typedef struct +{ + unsigned char patchmap_cnt; //r* + unsigned char pad1; //r*1 + unsigned short patchmap_idx; //r*2 +}patches_header; + +typedef struct +{ + unsigned char priority; //*0 + unsigned char volume; //*1----*2 + unsigned char pan; //*2----*3 + unsigned char reverb; //*3----*1 + unsigned char root_key; //*4----*4 + unsigned char fine_adj; //*5----*5 + unsigned char note_min; //*6----*6 + unsigned char note_max; //*7----*7 + unsigned char pitchstep_min; //*8----*8 + unsigned char pitchstep_max; //*9----*9 + unsigned short sample_id; //*10 swap + unsigned short attack_time; //*12 swap + unsigned short decay_time; //*14 swap + unsigned short release_time; //*16 swap + unsigned char attack_level; //*18 + unsigned char decay_level; //*19 +}patchmaps_header; + +typedef struct { + s32 order; + s32 npredictors; + s16 book[128]; /* Actually variable size. Must be 8-byte aligned */ +} ALADPCMBook2; + +typedef struct { + u32 start; + u32 end; + u32 count; + ADPCM_STATE state; + u32 pad; +} ALADPCMloop2; + +typedef struct { + u32 start; + u32 end; + u32 count; + u32 pad; +} ALRawLoop2; + +typedef struct { + ALADPCMloop2 *loop; + ALADPCMBook2 *book; +} ALADPCMWaveInfo2; + +typedef struct +{ + u8 *base; /* ptr to start of wave data */ //r*0 + s32 len; /* length of data in bytes */ //r*4 + u8 type; /* compression type */ //r*8 + u8 flags; /* offset/address flags */ //r*9 + void *loop; //r*12 + void *book; //r*14 +} ALWaveTable2; + +typedef struct +{ + //u8 *base; /* ptr to start of wave data */ //r*0 + //s32 len; /* length of data in bytes */ //r*4 + //u8 type; /* compression type */ //r*8 + //u8 flags; /* offset/address flags */ //r*9 + //union { + // ALADPCMWaveInfo2 adpcmWave;//12 + // ALRAWWaveInfo rawWave;//12 + //} waveInfo;//12 + + ALWaveTable2 wave; + s32 pitch;//20 +} patchinfo_header; //ALWaveTable custom + +typedef struct +{ + unsigned short nsfx1; //0 sfx count (124) + unsigned short rawcount; //2 + unsigned short adpcmcount; //4 loop data count (23) + unsigned short nsfx2; //6 sfx count again?? (124) +} loopinfo_header; + +//******************************* + +typedef struct +{ + int module_id_text; //* + unsigned int module_version; //*4 + unsigned int pad1; //*8 + unsigned short pad2; //*12 + unsigned short sequences; //*14 + unsigned char decomp_type; //*16 + unsigned char pad3; //*17 + unsigned char pad4; //*18 + unsigned char pad5; //*19 + unsigned int compress_size; //*20 + unsigned int data_size; //*24 + unsigned int pad6; //*28 +}module_header;//32 + +typedef struct +{ + unsigned char voices_type; //* + unsigned char reverb; //*1 + unsigned short initpatchnum; //*2 + unsigned short initpitch_cntrl; //*4 + unsigned char initvolume_cntrl; //*6 + unsigned char initpan_cntrl; //*7 + unsigned char substack_count; //*8 + unsigned char mutebits; //*9 + unsigned short initppq; //*10 + unsigned short initqpm; //*12 + unsigned short labellist_count; //*14 + unsigned int data_size; //*16 +}track_header;//size 20 bytes + +typedef struct +{ + track_header *trk_hdr;//* + unsigned long *plabellist;//*4 + char *ptrk_data;//*8 +}track_data; + +typedef struct +{ + unsigned short tracks; //* + unsigned short decomp_type; //*2 + unsigned int trkinfolength; //*4 + unsigned int fileposition; //*8 +}seq_header; + +typedef struct +{ + seq_header seq_hdr; //* + track_data *ptrk_info; //*12 +}sequence_data; + +typedef struct +{ + module_header mod_hdr; //* + sequence_data *pseq_info; //*32 +}module_data; + +typedef void (*callfunc_t)(char, short); +typedef struct +{ + unsigned char active; //* + unsigned char type; //*1 + unsigned short curval; //*2 + callfunc_t callfunc; //*4 +}callback_status; + +typedef struct +{ + unsigned int load_flags; //* + unsigned short patches; //*4 + unsigned short patch_size; //*6 + unsigned short patchmaps; //*8 + unsigned short patchmap_size; //*10 + unsigned short patchinfo; //*12 + unsigned short patchinfo_size; //*14 + unsigned short drummaps; //*16 + unsigned short drummap_size; //*18 + unsigned int extra_data_size; //*20 +}patch_group_header; + +typedef struct +{ + int hardware_ID;//76 + int flags_load;//80 +}hardware_table_list; + +typedef struct +{ + patch_group_header pat_grp_hdr; //* + char *ppat_data; //*24 +}patch_group_data;//size 84 bytes + +#define DriverInit 0 +#define DriverExit 1 +#define DriverEntry1 2 +#define DriverEntry2 3 +#define DriverEntry3 4 +#define TrkOff 5 +#define TrkMute 6 +#define PatchChg 7 +#define PatchMod 8 +#define PitchMod 9 +#define ZeroMod 10 +#define ModuMod 11 +#define VolumeMod 12 +#define PanMod 13 +#define PedalMod 14 +#define ReverbMod 15 +#define ChorusMod 16 +#define NoteOn 17 +#define NoteOff 18 + +// Engine Only +#define StatusMark 19 +#define GateJump 20 +#define IterJump 21 +#define ResetGates 22 +#define ResetIters 23 +#define WriteIterBox 24 +#define SeqTempo 25 +#define SeqGosub 26 +#define SeqJump 27 +#define SeqRet 28 +#define SeqEnd 29 +#define TrkTempo 30 +#define TrkGosub 31 +#define TrkJump 32 +#define TrkRet 33 +#define TrkEnd 34 +#define NullEvent 35 + +#define SEQ_STATE_STOPPED 0 +#define SEQ_STATE_PLAYING 1 + +//(val << 0 < 0) 128 +//(val << 1 < 0) 64 +//(val << 2 < 0) 32 +//(val << 3 < 0) 16 +//(val << 4 < 0) 8 +//(val << 5 < 0) 4 +//(val << 6 < 0) 2 +//(val << 7 < 0) 1 + +//New track +#define TRK_OFF 1 +#define TRK_SKIP 2 +#define TRK_LOOPED 4 +#define TRK_TIMED 8 +#define TRK_STOPPED 16 +#define TRK_HANDLED 32 +#define TRK_MUTE 64 +#define TRK_ACTIVE 128 + +//New seq +#define SEQ_STOP 8 +#define SEQ_RESTART 16 +#define SEQ_PAUSE 32 +#define SEQ_HANDLE 64 +#define SEQ_ACTIVE 128 + +//New voice +#define VOICE_DECAY 32 +#define VOICE_RELEASE 64 +#define VOICE_ACTIVE 128 + +typedef struct +{ + unsigned char flags; //* + unsigned char playmode; //*1 + unsigned short seq_num; //*2 + unsigned char tracks_active; //*4 + unsigned char tracks_playing; //*5 + unsigned char volume; //*6 + unsigned char pan; //*7 + unsigned int seq_type; //*8 + char *ptrk_indxs; //*12--- + char *pgates; //*16--- + char *piters; //*20 +}sequence_status; + +typedef struct +{ + unsigned char flags; //* + unsigned char refindx; //*1 + unsigned char seq_owner; //*2 + unsigned char sndclass; //*3 + unsigned short patchnum; //*4 + short pitch_cntrl; //*6 + unsigned int deltatime; //*8 + unsigned char reverb; //*12 + unsigned char volume_cntrl; //*13 + unsigned char pan_cntrl; //*14 + unsigned char mutemask; //*15 + unsigned char patchtype; //*16 + unsigned char voices_active; //*17 + unsigned char voices_max; //*18 + unsigned char priority; //*19 + unsigned short ppq; //*20 + unsigned short qpm; //*22 + unsigned short labellist_count;//*24 + unsigned short labellist_max; //*26 + unsigned long ppi; //*28 + unsigned long starppi; //*32 + unsigned int accppi; //*36 + unsigned int totppi; //*40 + unsigned int endppi; //*44 + unsigned char *pstart; //*48 + unsigned char *ppos; //*52 + unsigned long *plabellist; //*56 + unsigned long *psubstack; //*60 + unsigned char *psp; //*64 + unsigned long *pstackend; //*68 + unsigned int data_size; //*72 + unsigned int data_space; //*76 +}track_status; + +typedef struct +{ + unsigned char flags; //* + unsigned char patchtype; //*1 + unsigned char refindx; //*2 + unsigned char track; //*3 + unsigned char priority; //*4 + unsigned char keynum; //*5 + unsigned char velnum; //*6 + unsigned char sndtype; //*7 + patchmaps_header *patchmaps; //*8 + patchinfo_header *patchinfo; //*12 /* offset to wavetable struct */ + unsigned long pabstime; //*16 +}voice_status;//size 24 bytes + +typedef struct +{ + unsigned long *pabstime; //*--- + unsigned char seqs_active; //*4 + unsigned char trks_active; //*5 + unsigned char voices_active; //*6 + unsigned char voices_total; //*7 + unsigned char patch_types_loaded; //*8 + unsigned char callbacks_active; //*9 + unsigned char max_trks_perseq; //*10 + unsigned char max_substack_pertrk; //*11---- + module_data *pmod_info; //*12--- + callback_status *pcalltable; //*16--- + patch_group_data *ppat_info; //*20----- + sequence_status *pseqstattbl; //*24----- + track_status *ptrkstattbl; //*28----- + voice_status *pvoicestattbl; //*32----- +}master_status_structure; + +typedef master_status_structure pmasterstat; + +#define WESS_SSSP_TEXT 0x534E3634//'SN64' +#define WESS_CORE_VERSION 0x02 + +#define SNDFX_CLASS 0 +#define MUSIC_CLASS 1 +#define DRUMS_CLASS 2 +#define SFXDRUMS_CLASS 3 + +#define TAG_SOUND_EFFECTS 1 +#define TAG_MUSIC 2 +#define TAG_DRUMS 4 + +#define LOAD_PATCHES 1 +#define LOAD_PATCHMAPS 2 +#define LOAD_PATCHINFO 4 +#define LOAD_DRUMMAPS 8 +#define LOAD_EXTRADATA 16 + +///---------------------------------- +extern void (**CmdFuncArr[10])(track_status *); + +extern int wess_driver_num_dma_buffers; +extern int wess_driver_num_dma_messages; +extern int wess_driver_dma_buffer_length; +extern int wess_driver_extra_samples; +extern int wess_driver_frame_lag; +extern int wess_driver_voices; +extern int wess_driver_updates; +extern int wess_driver_sequences; +extern int wess_driver_tracks; +extern int wess_driver_gates; +extern int wess_driver_iters; +extern int wess_driver_callbacks; +extern int wess_driver_max_trks_per_seq; +extern int wess_driver_max_subs_per_trk; +extern int enabledecay; + +extern int SeqOn; +extern unsigned long millicount; +extern int WessTimerActive; + + +#define SEEK_SET 0 +#define SEEK_CUR 1 +#define SEEK_END 2 + +typedef struct +{ + char *start; //L800B4200 + char *src; //L800B4204 +} N64_File_IO_Struct; + +typedef N64_File_IO_Struct Wess_File_IO_Struct; +typedef N64_File_IO_Struct Wess_Data_IO_Struct; + +extern Wess_File_IO_Struct module_fileref;//800B4200 +extern Wess_Data_IO_Struct data_fileref;//L800B4208 + +extern void wess_engine_off(void);//L80035340() +extern void wess_engine_on(void);//L8003534C() + +extern void wess_low_level_init(void);//L8003531C() +extern void wess_low_level_exit(void);//L80035324() + +extern short GetIntsPerSec(void); +extern unsigned long CalcPartsPerInt(short ips,short ppq,short qpm); + +extern void init_WessTimer(void); +extern void exit_WessTimer(void); + +extern void wess_low_level_exit(void); +extern char *wess_malloc(char *mem); +extern void wess_free(char *mem); + +extern Wess_File_IO_Struct *module_open(char *filename); +extern int module_read(void *destptr, int readbytes, Wess_File_IO_Struct *fileptr); +extern int module_seek(Wess_File_IO_Struct *fileptr, int seekpos, int seekmode); +extern unsigned long module_tell(Wess_File_IO_Struct *fileptr); +extern void module_close(Wess_File_IO_Struct *fileptr); + +extern int wess_decomp(unsigned char decomp_type, char *fileref, unsigned long file_offset, char *ramdest, unsigned long uncompressed_size); +extern void wess_enable(void); +extern void wess_disable(void); + + +extern long WessInterruptHandler(void); + +typedef void(*WessAction)(track_status *ptmp, int value); + +#define QUEUE_SEQ_STOPALL 0 +#define QUEUE_SEQ_STOP 1 +#define QUEUE_MASTER_SFX_VOL_SET 2 +#define QUEUE_MASTER_MUS_VOL_SET 3 +#define QUEUE_HANDLE_PARM_MOD 4 +#define QUEUE_HANDLE_NOTEON 5 +#define QUEUE_SEQ_PAUSE 6 +#define QUEUE_SEQ_RESTART 7 +#define QUEUE_SEQ_PAUSEALL 8 +#define QUEUE_SEQ_RESTARTALL 9 +#define QUEUE_SEQ_STOPTYPE 10 +#define QUEUE_SEQ_UPDATE_TYPE_SPECIAL 11 +#define QUEUE_SEQ_STOPALL_AND_VOICERAMP 12 +#define QUEUE_SEQ_STOP_AND_VOICERAMP 13 +#define QUEUE_SEQ_STOPTYPE_AND_VOICERAMP 14 + +#endif // _WESSARC_H diff --git a/Doom 64/wessedit.c b/Doom 64/wessedit.c @@ -0,0 +1,219 @@ + +/* ULTRA64 LIBRARIES */ +#include <ultra64.h> +#include "ultratypes.h" +#include <libaudio.h> + +/* WESS API INCLUDES */ +#include "wessapi.h" // audio stuff... +#include "seqload.h" +#include "soundhw.h" +#include "wessarc.h" +#include "wessseq.h" + +#include "funqueue.h" + +#include "wessedit.h" +#ifndef NOUSEWESSCODE +extern pmasterstat *pm_stat; //0x800B41CC + +static int max_edit_labels = 2; //0x8005D900 +static int soundfx_edit_tracks = 8; //0x8005D904 +static int music_edit_tracks = 15; //0x8005D908 +static int drums_edit_tracks = 1; //0x8005D90C +static int edt_mem_is_mine = 0;//0x8005D910 +static char *edt_mem = 0;//0x8005D914 +static int edt_size = 0;//0x8005D918 + +void wess_handle_free_edit_space(void) // 80034D20 +{ + if (edt_mem_is_mine) + { + if (edt_mem) + { + wess_free(edt_mem); + edt_mem = 0; + } + edt_mem_is_mine = 0; + } +} + +char *wess_get_edt_start(void) // 80034D70 +{ + return(edt_mem); +} + +int wess_get_edt_size(void) // 80034D80 +{ + return(edt_size); +} + +void wess_handle_set_edit_tracks(int labels, int soundfx, int music, int drums) // 80034D90 +{ + max_edit_labels = labels; + soundfx_edit_tracks = soundfx; + music_edit_tracks = music; + drums_edit_tracks = drums; +} + +int wess_handle_create_edit_space(char *memory_pointer, int data_size, int memory_allowance) // 80034DB4 +{ + int i, j, k, soundfx_cnt, music_cnt, drums_cnt; + sequence_status *psq_stat; + track_status *ptk_stat; + char *pdest; + char *pmem; + int ptrk_indxs_pos; + int set_psq_stat; + + char *_memory_pointer; + int _data_size; + int _memory_allowance; + + _memory_pointer = memory_pointer; + _data_size = data_size; + _memory_allowance = memory_allowance; + + if (!Is_Module_Loaded()) + return(0); + + soundfx_cnt = 0; + music_cnt = 0; + drums_cnt = 0; + + set_psq_stat = 0; + + if (_memory_pointer == NULL) + { + edt_mem_is_mine = 1; + edt_mem = wess_malloc((char *)_memory_allowance); + if (edt_mem == NULL) + { + return(0); + } + } + else + { + edt_mem_is_mine = 0; + edt_mem = _memory_pointer; + } + + edt_size = _memory_allowance; + + wess_disable(); + + for (i = 0; i < wess_driver_tracks; i++) + { + if (!((pm_stat->pseqstattbl + i)->flags & SEQ_ACTIVE)) + break; + } + + if (wess_driver_tracks == i) + { + wess_enable(); + return 0; + } + + psq_stat = (pm_stat->pseqstattbl + i); + pdest = psq_stat->ptrk_indxs; + for (j = 0; j < wess_driver_tracks; j++) + { + ptk_stat = (pm_stat->ptrkstattbl + i); + + if (!(ptk_stat->flags & TRK_ACTIVE)) + { + if (soundfx_cnt < soundfx_edit_tracks) + { + ptk_stat->sndclass = SNDFX_CLASS; + ptk_stat->patchtype = 1; + ptk_stat->data_space = _data_size - (max_edit_labels << 2); + ptrk_indxs_pos = soundfx_cnt; + soundfx_cnt++; + } + else if (music_cnt < music_edit_tracks) + { + ptk_stat->sndclass = MUSIC_CLASS; + ptk_stat->patchtype = 1; + ptk_stat->data_space = _data_size - (max_edit_labels << 2); + ptrk_indxs_pos = (music_cnt + soundfx_edit_tracks); + music_cnt++; + } + else if (drums_cnt < drums_edit_tracks) + { + ptk_stat->sndclass = DRUMS_CLASS; + ptk_stat->patchtype = 1; + ptk_stat->data_space = (_memory_allowance - (soundfx_edit_tracks + music_edit_tracks) * _data_size) - (max_edit_labels << 2); + ptrk_indxs_pos = (drums_cnt + soundfx_edit_tracks + music_edit_tracks); + drums_cnt++; + } + else + { + break; + } + + //---------------------- + set_psq_stat = 1; + + *(pdest + ptrk_indxs_pos) = j; /* update ptrk_indxs for the sequence */ + + ptk_stat->seq_owner = i; + ptk_stat->patchnum = 0; + ptk_stat->volume_cntrl = 0x7f; + ptk_stat->pitch_cntrl = 0; + ptk_stat->pan_cntrl = 0x40; + ptk_stat->voices_active = 0; + ptk_stat->ppq = 120; + ptk_stat->qpm = 120; + ptk_stat->ppi = CalcPartsPerInt(GetIntsPerSec(), ptk_stat->ppq, ptk_stat->qpm); + ptk_stat->starppi = 0; + ptk_stat->totppi = 0; + ptk_stat->labellist_count = 0; + ptk_stat->data_size = 2; + ptk_stat->psp = (unsigned char*)ptk_stat->psubstack; + ptk_stat->labellist_max = max_edit_labels; + + //---------------------- + pmem = (edt_mem + (ptrk_indxs_pos * _data_size)); + ptk_stat->plabellist = (unsigned long *)pmem; + + for (k = 0; k < ptk_stat->labellist_max; k++) + { + *pmem++ = 0; + } + + //---------------------- + pmem = (edt_mem + (max_edit_labels << 2) + (ptrk_indxs_pos * _data_size)); + ptk_stat->pstart = (char *)pmem; + pmem[0] = 0; + pmem[1] = TrkEnd; + + ptk_stat->flags = (ptk_stat->flags|TRK_ACTIVE|TRK_STOPPED|TRK_HANDLED|TRK_OFF) & ~(TRK_MUTE|TRK_TIMED|TRK_LOOPED|TRK_SKIP); + ptk_stat->ppos = Read_Vlq(ptk_stat->pstart, &ptk_stat->deltatime); + ptk_stat->mutemask = 0; + + psq_stat->tracks_active++; + pm_stat->trks_active++; + } + } + + if (set_psq_stat) + { + psq_stat->flags |= (SEQ_HANDLE|SEQ_ACTIVE); + psq_stat->seq_num = -1; + psq_stat->seq_type = 0; + psq_stat->playmode = 0; + psq_stat->volume = 0x7f; + psq_stat->pan = 0x40; + pm_stat->seqs_active++; + } + + wess_enable(); + + if (set_psq_stat) + { + return (i + 1); + } + + return 0; +} +#endif diff --git a/Doom 64/wessedit.h b/Doom 64/wessedit.h @@ -0,0 +1,12 @@ +#ifndef _WESSEDIT_H +#define _WESSEDIT_H + +#include "wessarc.h" + +extern void wess_handle_free_edit_space(void); // 80034D20 +extern char *wess_get_edt_start(void); // 80034D70 +extern int wess_get_edt_size(void); // 80034D80 +extern void wess_handle_set_edit_tracks(int labels, int soundfx, int music, int drums); // 80034D90 +extern int wess_handle_create_edit_space(char *memory_pointer, int data_size, int memory_allowance); // 80034DB4 + +#endif diff --git a/Doom 64/wessfade.c b/Doom 64/wessfade.c @@ -0,0 +1,39 @@ + +/* ULTRA64 LIBRARIES */ +#include <ultra64.h> +#include "ultratypes.h" +#include <libaudio.h> + +/* WESS API INCLUDES */ +#include "wessapi.h" // audio stuff... +#include "seqload.h" +#include "soundhw.h" +#include "wessarc.h" +#include "wessseq.h" + +#include "funqueue.h" + +#include "wessfade.h" +#ifndef NOUSEWESSCODE + +int wess_seq_fade(int seq_num) // 80035F00 +{ + return Is_Seq_Num_Valid(seq_num); +} + +int wess_seq_fadeall(int seq_num) // 80035F24 +{ + return Is_Module_Loaded(); +} + +int wess_seq_segue(int seq_num, int seq_num2) // 80035F48 +{ + int val; + + val = Is_Seq_Num_Valid(seq_num); + if (val) + val = Is_Seq_Num_Valid(seq_num2); + + return (val); +} +#endif diff --git a/Doom 64/wessfade.h b/Doom 64/wessfade.h @@ -0,0 +1,8 @@ +#ifndef _WESSFADE_H +#define _WESSFADE_H + +extern int wess_seq_fade(int seq_num); // 80035EFC +extern int wess_seq_fadeall(int seq_num); // 80035F24 +extern int wess_seq_segue(int seq_num, int seq_num2); // 80035F48 + +#endif diff --git a/Doom 64/wesshand.h b/Doom 64/wesshand.h @@ -0,0 +1,32 @@ +#ifndef _WESSTRAK_H +#define _WESSTRAK_H + +#include "wessapi.h" +#include "wessarc.h" + +extern sequence_status *gethandleseq(int handle); // 80032E80 +extern sequence_status *gethandleseq(int handle); // 80032E80 +extern int wess_handle_get(int seq_num); // 80032F80 +extern int wess_handle_status(int handle); // 80032FD8 +extern void wess_handle_return(int handle); // 80033048 +extern void wess_handle_play_special(int handle, TriggerPlayAttr *attr); // 80033180 +extern void wess_handle_play(int handle); // 80033298() +extern void wess_handle_play_track_special(int handle, int track, TriggerPlayAttr *attr); // 800332B8 +extern void wess_handle_play_track(int handle, int track); // 80033344 +extern void wess_handle_get_special(int handle, TriggerPlayAttr *attr); // 80033364 +extern void wess_handle_set_special(int handle, TriggerPlayAttr *attr); // 80033454 +extern void wess_handle_stop(int handle); // 80033544 +extern void wess_handle_fastsettempo(int handle, short tempo); // 80033658 +extern int wess_handle_fade(void); // 80033788 +extern void wess_handle_resetposition(int handle); // 800337B0 +extern int wess_track_gotoposition(track_status *ptmp, int position, char *ppos); // 800338F0 +extern int wess_track_setposition(track_status *ptmp, int position, char *ppos); // 80033B24 +extern int wess_handle_setposition(int handle, int position); // 80033EB8 +extern int wess_handle_getposition(int handle); // 80034010 +extern void patch_chg_action(track_status *ptmp, short patch_num); // 800340E0 +extern void pitch_mod_action(track_status *ptmp, int pitch_cntr); // 80034144 +extern void volume_mod_action(track_status *ptmp, int volume_cntr); // 800341A8 +extern void pan_mod_action(track_status *ptmp, int pan_cntr); // 80034200 +extern void wess_track_parm_mod(track_status *ptmp, int value, WessAction funcion); // 80034258 + +#endif diff --git a/Doom 64/wessint_s.h b/Doom 64/wessint_s.h @@ -0,0 +1,10 @@ + +#ifndef _WESSINT_S_H +#define _WESSINT_S_H + +#include <ultra64.h> + +extern unsigned long wesssys_disable_ints(void); +extern void wesssys_restore_ints(unsigned long state); + +#endif diff --git a/Doom 64/wessint_s.s b/Doom 64/wessint_s.s @@ -0,0 +1,82 @@ +#include <asm.h> +#include <PR/R4300.h> +#include <PR/ultratypes.h> + +#define zero $0 +#define at $1 +#define v0 $2 +#define v1 $3 +#define a0 $4 +#define a1 $5 +#define a2 $6 +#define a3 $7 +#define t0 $8 +#define t1 $9 +#define t2 $10 +#define t3 $11 +#define t4 $12 +#define t5 $13 +#define t6 $14 +#define t7 $15 +#define s0 $16 +#define s1 $17 +#define s2 $18 +#define s3 $19 +#define s4 $20 +#define s5 $21 +#define s6 $22 +#define s7 $23 +#define t8 $24 +#define t9 $25 +#define k0 $26 +#define k1 $27 +#define gp $28 +#define sp $29 +#define fp $30 +#define ra $31 +#define return s7 + + .text + .set noreorder + .option pic0 + +/* Original Code From Mortal Kombat Trilogy N64 */ + +/*------------------------------------------*/ +/* unsigned long wesssys_disable_ints(void) */ +/*------------------------------------------*/ + +.globl wesssys_disable_ints +.ent wesssys_disable_ints + +wesssys_disable_ints: /* 8003A3E0 */ + + mfc0 $8, $12 /* t0 = special register with IE bit */ + and $9, $8, ~1 /* t1 = same register with IE bit cleared */ + mtc0 $9, $12 /* disable R4300 CPU interrupts */ + andi $2, $8, 1 /* return the prior state of just the IE bit */ + nop + jr $31 + nop + +.end wesssys_disable_ints + +/*------------------------------------------------*/ +/* void wesssys_restore_ints(unsigned long state) */ +/*------------------------------------------------*/ + +.globl wesssys_restore_ints +.ent wesssys_restore_ints + +wesssys_restore_ints: /* 8003A400 */ + + mfc0 $8,$12 /* t0 = special register with IE bit */ + nop + or $8, $4 /* restore IE bit from passed-in parameter */ + mtc0 $8, $12 /* restore R4300 CPU interrupts */ + nop + nop + j $31 /* return nothing */ + nop + +.end wesssys_restore_ints diff --git a/Doom 64/wessseq.h b/Doom 64/wessseq.h @@ -0,0 +1,32 @@ +#ifndef _WESSSEQ_H +#define _WESSSEQ_H + +#include <ultra64.h> +#include <libaudio.h> +#include "wessapi.h" +#include "wessarc.h" + +extern unsigned char master_sfx_volume; +extern unsigned char master_mus_volume; +extern unsigned char pan_status; +extern int enabledecay; + +extern char *Read_Vlq(char *pstart, void *deltatime); +extern char *Write_Vlq(char *dest, unsigned int value); +extern int Len_Vlq(unsigned int value); + +extern int SeqOn; +extern void(*drv_cmds[19])(track_status *); + +extern void add_music_mute_note(track_status *ptk_stat, + unsigned short seq_num, unsigned short track, + unsigned char keynum, unsigned char velnum, + patchmaps_header *patchmap, + patchinfo_header *patchinfo); + +extern void Eng_TrkOff (track_status *ptk_stat); + +extern void(*DrvFunctions[36])(track_status *); +extern void SeqEngine(void); + +#endif // _WESSSEQ_H diff --git a/Doom 64/wessshell.h b/Doom 64/wessshell.h @@ -0,0 +1,10 @@ +#ifndef _FUNQUEUE_H +#define _FUNQUEUE_H + +extern ALPlayer wessnode; // 800B4140 +extern ALPlayer *wessstate; // 800B4154 + +extern void SSP_SeqpNew(void); // 8002F100 +extern ALMicroTime __wessVoiceHandler(void *node); // 8002F154 + +#endif diff --git a/Doom 64/wesstrak.h b/Doom 64/wesstrak.h @@ -0,0 +1,29 @@ +#ifndef _WESSTRAK_H +#define _WESSTRAK_H + +#include "wessarc.h" + +extern void wess_handle_patchchg(int handle, int track, short patchnum); // 80034664 +extern void wess_handle_noteon(int handle, int track, char keynum, char velnum); // 8003469C +extern void run_queue_wess_handle_noteon(void); // 80034708 +extern void run_queue_wess_handle_noteon(void); // 80034708 +extern void noteoff_action(track_status *ptmp, int keynum); // 8003483C +extern void wess_handle_noteoff(int handle, int track, char keynum); // 80034894 +extern void wess_handle_noteoff(int handle, int track, char keynum); // 80034894 +extern void zero_mod_action(track_status *ptmp, int value); // 800348F0 +extern void wess_handle_zeromod(int handle, int track, char value); // 80034948 +extern void wess_handle_zeromod(int handle, int track, char value); // 80034948 +extern void wess_handle_zeromod(int handle, int track, char value); // 80034948 +extern void wess_handle_zeromod(int handle, int track, char value); // 80034948 +extern void wess_handle_panmod(int handle, int track, char pan_cntr); // 80034A24 +extern void pedal_mod_action(track_status *ptmp, int value); // 80034A50 +extern void wess_handle_pedalmod(int handle, int track, char value); // 80034AA8 +extern void wess_handle_pedalmod(int handle, int track, char value); // 80034AA8 +extern void wess_handle_reverbmod(int handle, int track, char reverb); // 80034B2C +extern void chorus_mod_action(track_status *ptmp, int chorus); // 80034B58 +extern void wess_handle_chorusmod(int handle, int track, char chorus); // 80034BB0 +extern void wess_handle_chorusmod(int handle, int track, char chorus); // 80034BB0 +extern void run_queue_wess_handle_parm_mod(void); // 80034C48 +extern void run_queue_wess_handle_parm_mod(void); // 80034C48 + +#endif