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