diff --git a/Makefile b/Makefile index 07752f3..c9979de 100644 --- a/Makefile +++ b/Makefile @@ -17,18 +17,20 @@ IPU_OBJ = $(addprefix build/ipu_obj/, \ p_setup.gp \ p_setup_codelets.gp \ p_tick.gp \ + p_mobj.gp \ r_bsp.gp \ r_codelets.gp \ r_main.gp \ tables.gp \ v_video.gp \ + doomstat.gp \ ) CPU_FLAGS = -I src -I /usr/local/include/SDL2 -I/usr/include/libpng16 -I/opt/poplar/include \ -D_REENTRANT -lSDL2 -lSDL2_mixer -lSDL2_net -lpng16 -lz -lpoplar \ -Wall -Werror \ - -O2 + -O2 # -m32 IPU_FLAGS = -I src/ipu \ -Wall -Werror -Wno-unused-variable \ diff --git a/README.md b/README.md index bef584f..cb7f5c9 100644 --- a/README.md +++ b/README.md @@ -4,9 +4,10 @@ A WIP to put Doom 1993 on the IPU. -``` +```bash # Install dependencies -sudo apt update; sudo apt-get install -y libsdl2-dev libsdl2-image-dev libsdl2-mixer-dev libsdl2-net-dev libpng-dev g++-7 +sudo apt update +sudo apt-get install -y libsdl2-dev libsdl2-image-dev libsdl2-mixer-dev libsdl2-net-dev libpng-dev g++-7 # Build binary make # Download shareware resource pack diff --git a/src/ipu/am_map.c b/src/ipu/am_map.c index 3a8f54b..ccb2f27 100644 --- a/src/ipu/am_map.c +++ b/src/ipu/am_map.c @@ -226,7 +226,7 @@ static fixed_t scale_ftom; // player object // May need mechanism for sending plr->message to rendering tile... LATER // static player_t *plr; // the player represented by an arrow -IPUPlayerPos_t am_playerpos; +IPUTransfer_playerstate_t am_playerpos; patch_t *marknums[10]; // numbers used for marking by the automap unsigned char markbuf[IPUAMMARKBUFSIZE]; // JOSEF: static mark patch storage, avoiding disk diff --git a/src/ipu/doomstat.c b/src/ipu/doomstat.c new file mode 100644 index 0000000..6617475 --- /dev/null +++ b/src/ipu/doomstat.c @@ -0,0 +1,29 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// DESCRIPTION: +// Put all global tate variables here. +// + +#include "doomstat.h" + +// Game Mode - identify IWAD as shareware, retail etc. +GameMode_t gamemode = indetermined; +GameMission_t gamemission = doom; +GameVersion_t gameversion = exe_final2; +GameVariant_t gamevariant = vanilla; +char *gamedescription; + +// Set if homebrew PWAD stuff has been added. +boolean modifiedgame; diff --git a/src/ipu/ipu_interface.h b/src/ipu/ipu_interface.h index 22f2b83..239a660 100644 --- a/src/ipu/ipu_interface.h +++ b/src/ipu/ipu_interface.h @@ -6,6 +6,7 @@ extern "C" { #include "d_event.h" #include "d_player.h" +#include "d_mode.h" #include "doomdef.h" #include "doomtype.h" #include "m_fixed.h" @@ -24,16 +25,24 @@ typedef struct { int gameepisode; int gamemap; int lumpnum; + GameMode_t gamemode; + int deathmatch; + boolean playeringame[MAXPLAYERS]; } G_LoadLevel_MiscValues_t; typedef struct { fixed_t x, y, z; angle_t angle; -} IPUPlayerPos_t; + int extralight; + fixed_t viewz; + int fixedcolormap; +} IPUTransfer_playerstate_t; typedef struct { + int consoleplayer; gamestate_t gamestate; - IPUPlayerPos_t player_mobj; + IPUTransfer_playerstate_t player; + int mappedline_updates[IPUMAPPEDLINEUPDATES]; } G_Ticker_MiscValues_t; @@ -45,9 +54,8 @@ typedef struct { } G_Responder_MiscValues_t; typedef struct { - int displayplayer; - player_t players_displayplayer; - mobj_t displayplayer_mo; + // nothing + int dummy; // just so struct is not empty } R_RenderPlayerView_MiscValues_t; diff --git a/src/ipu/ipu_transfer.c b/src/ipu/ipu_transfer.c index ff761df..fe9ca64 100644 --- a/src/ipu/ipu_transfer.c +++ b/src/ipu/ipu_transfer.c @@ -5,30 +5,46 @@ #include "ipu_interface.h" #include "ipu_transfer.h" -#include "ipu_print.h" +#include "print.h" int gamelumpnum; -int requestedlumpnum; void IPU_G_LoadLevel_UnpackMiscValues(G_LoadLevel_MiscValues_t* pack) { gameepisode = pack->gameepisode; gamemap = pack->gamemap; gamelumpnum = pack->lumpnum; + gamemode = pack->gamemode; + deathmatch = pack->deathmatch; + for (int i = 0; i < MAXPLAYERS; ++i) { + playeringame[i] = pack->playeringame[i]; + } } void IPU_G_Ticker_UnpackMiscValues(G_Ticker_MiscValues_t* pack) { gamestate = pack->gamestate; if (gamestate != GS_LEVEL) return; - am_playerpos.x = pack->player_mobj.x; - am_playerpos.y = pack->player_mobj.y; - am_playerpos.z = pack->player_mobj.z; - am_playerpos.angle = pack->player_mobj.angle; + + consoleplayer = displayplayer = pack->consoleplayer; // Asserted true on host + players[consoleplayer].mo->x = pack->player.x; + players[consoleplayer].mo->y = pack->player.y; + players[consoleplayer].mo->z = pack->player.z; + players[consoleplayer].mo->angle = pack->player.angle; + players[consoleplayer].extralight = pack->player.extralight; + players[consoleplayer].viewz = pack->player.viewz; + players[consoleplayer].fixedcolormap = pack->player.fixedcolormap; + + am_playerpos.x = pack->player.x; + am_playerpos.y = pack->player.y; + am_playerpos.z = pack->player.z; + am_playerpos.angle = pack->player.angle; for (int i = 0; i < IPUMAPPEDLINEUPDATES; ++i) { int update = pack->mappedline_updates[i]; if (update == -1) break; lines[update].flags |= ML_MAPPED; } + + } void IPU_Setup_UnpackMarkNums(const unsigned char* buf) { @@ -42,7 +58,5 @@ void IPU_Setup_UnpackMarkNums(const unsigned char* buf) { void IPU_R_RenderPlayerView_UnpackMiscValues(R_RenderPlayerView_MiscValues_t* pack) { - displayplayer = pack->displayplayer; - players[displayplayer] = pack->players_displayplayer; - // TODO: pack->displaypayer_mo + // Nothing to unpack } \ No newline at end of file diff --git a/src/ipu/ipu_transfer.h b/src/ipu/ipu_transfer.h index a32a29d..a145e64 100644 --- a/src/ipu/ipu_transfer.h +++ b/src/ipu/ipu_transfer.h @@ -9,8 +9,7 @@ extern "C" { extern int gamelumpnum; -extern int requestedlumpnum; -extern IPUPlayerPos_t am_playerpos; +extern IPUTransfer_playerstate_t am_playerpos; extern patch_t* marknums[10]; extern unsigned char markbuf[IPUAMMARKBUFSIZE]; diff --git a/src/ipu/p_mobj.c b/src/ipu/p_mobj.c new file mode 100644 index 0000000..f3a8e07 --- /dev/null +++ b/src/ipu/p_mobj.c @@ -0,0 +1,941 @@ +// +// Copyright(C) 1993-1996 Id Software, Inc. +// Copyright(C) 2005-2014 Simon Howard +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License +// as published by the Free Software Foundation; either version 2 +// of the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// DESCRIPTION: +// Moving object handling. Spawn functions. +// + +// #include // JOSEF +// #include + +#include "d_mode.h" +#include "d_player.h" +#include "doomdef.h" +#include "doomstat.h" +#include "doomtype.h" +#include "m_fixed.h" +#include "p_local.h" +#include "p_mobj.h" + +#include +#include "ipu_malloc.h" +/* +#include "doomdata.h" +#include "d_think.h" +#include "d_ticcmd.h" +#include "hu_stuff.h" +#include "i_system.h" +#include "i_timer.h" +#include "info.h" +#include "m_random.h" +#include "r_defs.h" +#include "r_main.h" +#include "s_sound.h" +#include "sounds.h" +#include "st_stuff.h" +#include "tables.h" +#include "z_zone.h" + +void G_PlayerReborn(int player); +void P_SpawnMapThing(mapthing_t *mthing); + +// +// P_SetMobjState +// Returns true if the mobj is still present. +// +int test; + +// Use a heuristic approach to detect infinite state cycles: Count the number +// of times the loop in P_SetMobjState() executes and exit with an error once +// an arbitrary very large limit is reached. + +#define MOBJ_CYCLE_LIMIT 1000000 + +boolean P_SetMobjState(mobj_t *mobj, statenum_t state) { + state_t *st; + int cycle_counter = 0; + + do { + if (state == S_NULL) { + mobj->state = (state_t *)S_NULL; + P_RemoveMobj(mobj); + return false; + } + + st = &states[state]; + mobj->state = st; + mobj->tics = st->tics; + mobj->sprite = st->sprite; + mobj->frame = st->frame; + + // Modified handling. + // Call action functions when the state is set + if (st->action.acp1) + st->action.acp1(mobj); + + state = st->nextstate; + + if (cycle_counter++ > MOBJ_CYCLE_LIMIT) { + I_Error("P_SetMobjState: Infinite state cycle detected!"); + } + } while (!mobj->tics); + + return true; +} + +// +// P_ExplodeMissile +// +void P_ExplodeMissile(mobj_t *mo) { + mo->momx = mo->momy = mo->momz = 0; + + P_SetMobjState(mo, mobjinfo[mo->type].deathstate); + + mo->tics -= P_Random() & 3; + + if (mo->tics < 1) + mo->tics = 1; + + mo->flags &= ~MF_MISSILE; + + if (mo->info->deathsound) + S_StartSound(mo, mo->info->deathsound); +} + +// +// P_XYMovement +// +#define STOPSPEED 0x1000 +#define FRICTION 0xe800 + +void P_XYMovement(mobj_t *mo) { + fixed_t ptryx; + fixed_t ptryy; + player_t *player; + fixed_t xmove; + fixed_t ymove; + + if (!mo->momx && !mo->momy) { + if (mo->flags & MF_SKULLFLY) { + // the skull slammed into something + mo->flags &= ~MF_SKULLFLY; + mo->momx = mo->momy = mo->momz = 0; + + P_SetMobjState(mo, mo->info->spawnstate); + } + return; + } + + player = mo->player; + + if (mo->momx > MAXMOVE) + mo->momx = MAXMOVE; + else if (mo->momx < -MAXMOVE) + mo->momx = -MAXMOVE; + + if (mo->momy > MAXMOVE) + mo->momy = MAXMOVE; + else if (mo->momy < -MAXMOVE) + mo->momy = -MAXMOVE; + + xmove = mo->momx; + ymove = mo->momy; + + do { + if (xmove > MAXMOVE / 2 || ymove > MAXMOVE / 2) { + ptryx = mo->x + xmove / 2; + ptryy = mo->y + ymove / 2; + xmove >>= 1; + ymove >>= 1; + } else { + ptryx = mo->x + xmove; + ptryy = mo->y + ymove; + xmove = ymove = 0; + } + + if (!P_TryMove(mo, ptryx, ptryy)) { + // blocked move + if (mo->player) { // try to slide along it + P_SlideMove(mo); + } else if (mo->flags & MF_MISSILE) { + // explode a missile + if (ceilingline && ceilingline->backsector && + ceilingline->backsector->ceilingpic == skyflatnum) { + // Hack to prevent missiles exploding + // against the sky. + // Does not handle sky floors. + P_RemoveMobj(mo); + return; + } + P_ExplodeMissile(mo); + } else + mo->momx = mo->momy = 0; + } + } while (xmove || ymove); + + // slow down + if (player && player->cheats & CF_NOMOMENTUM) { + // debug option for no sliding at all + mo->momx = mo->momy = 0; + return; + } + + 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) { + // do not stop sliding + // if halfway off a step with some momentum + if (mo->momx > FRACUNIT / 4 || mo->momx < -FRACUNIT / 4 || + mo->momy > FRACUNIT / 4 || mo->momy < -FRACUNIT / 4) { + if (mo->floorz != mo->subsector->sector->floorheight) + return; + } + } + + if (mo->momx > -STOPSPEED && mo->momx < STOPSPEED && mo->momy > -STOPSPEED && + mo->momy < STOPSPEED && (!player || (player->cmd.forwardmove == 0 && + player->cmd.sidemove == 0))) { + // if in a walking frame, stop moving + if (player && (unsigned)((player->mo->state - states) - S_PLAY_RUN1) < 4) + P_SetMobjState(player->mo, S_PLAY); + + mo->momx = 0; + mo->momy = 0; + } else { + mo->momx = FixedMul(mo->momx, FRICTION); + mo->momy = FixedMul(mo->momy, FRICTION); + } +} + +// +// P_ZMovement +// +void P_ZMovement(mobj_t *mo) { + fixed_t dist; + fixed_t delta; + + // check for smooth step up + if (mo->player && mo->z < mo->floorz) { + mo->player->viewheight -= mo->floorz - mo->z; + + mo->player->deltaviewheight = (VIEWHEIGHT - mo->player->viewheight) >> 3; + } + + // adjust height + mo->z += mo->momz; + + if (mo->flags & MF_FLOAT && mo->target) { + // float down towards target if too close + if (!(mo->flags & MF_SKULLFLY) && !(mo->flags & MF_INFLOAT)) { + dist = P_AproxDistance(mo->x - mo->target->x, mo->y - mo->target->y); + + delta = (mo->target->z + (mo->height >> 1)) - mo->z; + + if (delta < 0 && dist < -(delta * 3)) + mo->z -= FLOATSPEED; + else if (delta > 0 && dist < (delta * 3)) + mo->z += FLOATSPEED; + } + } + + // clip movement + if (mo->z <= mo->floorz) { + // hit the floor + + // Note (id): + // somebody left this after the setting momz to 0, + // kinda useless there. + // + // cph - This was the a bug in the linuxdoom-1.10 source which + // caused it not to sync Doom 2 v1.9 demos. Someone + // added the above comment and moved up the following code. So + // demos would desync in close lost soul fights. + // Note that this only applies to original Doom 1 or Doom2 demos - not + // Final Doom and Ultimate Doom. So we test demo_compatibility *and* + // gamemission. (Note we assume that Doom1 is always Ult Doom, which + // seems to hold for most published demos.) + // + // fraggle - cph got the logic here slightly wrong. There are three + // versions of Doom 1.9: + // + // * The version used in registered doom 1.9 + doom2 - no bounce + // * The version used in ultimate doom - has bounce + // * The version used in final doom - has bounce + // + // So we need to check that this is either retail or commercial + // (but not doom2) + + int correct_lost_soul_bounce = gameversion >= exe_ultimate; + + if (correct_lost_soul_bounce && mo->flags & MF_SKULLFLY) { + // the skull slammed into something + mo->momz = -mo->momz; + } + + if (mo->momz < 0) { + if (mo->player && mo->momz < -GRAVITY * 8) { + // Squat down. + // Decrease viewheight for a moment + // after hitting the ground (hard), + // and utter appropriate sound. + mo->player->deltaviewheight = mo->momz >> 3; + S_StartSound(mo, sfx_oof); + } + mo->momz = 0; + } + mo->z = mo->floorz; + + // cph 2001/05/26 - + // See lost soul bouncing comment above. We need this here for bug + // compatibility with original Doom2 v1.9 - if a soul is charging and + // hit by a raising floor this incorrectly reverses its Y momentum. + // + + if (!correct_lost_soul_bounce && mo->flags & MF_SKULLFLY) + mo->momz = -mo->momz; + + if ((mo->flags & MF_MISSILE) && !(mo->flags & MF_NOCLIP)) { + P_ExplodeMissile(mo); + return; + } + } else if (!(mo->flags & MF_NOGRAVITY)) { + if (mo->momz == 0) + mo->momz = -GRAVITY * 2; + else + mo->momz -= GRAVITY; + } + + 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_SKULLFLY) { // the skull slammed into something + mo->momz = -mo->momz; + } + + if ((mo->flags & MF_MISSILE) && !(mo->flags & MF_NOCLIP)) { + P_ExplodeMissile(mo); + return; + } + } +} + +// +// P_NightmareRespawn +// +void P_NightmareRespawn(mobj_t *mobj) { + fixed_t x; + fixed_t y; + fixed_t z; + subsector_t *ss; + mobj_t *mo; + mapthing_t *mthing; + + x = mobj->spawnpoint.x << FRACBITS; + y = mobj->spawnpoint.y << FRACBITS; + + // somthing is occupying it's position? + if (!P_CheckPosition(mobj, x, y)) + return; // no respwan + + // spawn a teleport fog at old spot + // because of removal of the body? + mo = P_SpawnMobj(mobj->x, mobj->y, mobj->subsector->sector->floorheight, + MT_TFOG); + // initiate teleport sound + S_StartSound(mo, sfx_telept); + + // spawn a teleport fog at the new spot + ss = R_PointInSubsector(x, y); + + mo = P_SpawnMobj(x, y, ss->sector->floorheight, MT_TFOG); + + S_StartSound(mo, sfx_telept); + + // spawn the new monster + mthing = &mobj->spawnpoint; + + // spawn it + if (mobj->info->flags & MF_SPAWNCEILING) + z = ONCEILINGZ; + else + z = ONFLOORZ; + + // inherit attributes from deceased one + mo = P_SpawnMobj(x, y, z, mobj->type); + mo->spawnpoint = mobj->spawnpoint; + mo->angle = ANG45 * (mthing->angle / 45); + + if (mthing->options & MTF_AMBUSH) + mo->flags |= MF_AMBUSH; + + mo->reactiontime = 18; + + // remove the old monster, + P_RemoveMobj(mobj); +} + +// +// P_MobjThinker +// +void P_MobjThinker(mobj_t *mobj) { + // momentum movement + if (mobj->momx || mobj->momy || (mobj->flags & MF_SKULLFLY)) { + P_XYMovement(mobj); + + // FIXME: decent NOP/NULL/Nil function pointer please. + if (mobj->thinker.function.acv == (actionf_v)(-1)) + return; // mobj was removed + } + if ((mobj->z != mobj->floorz) || mobj->momz) { + P_ZMovement(mobj); + + // FIXME: decent NOP/NULL/Nil function pointer please. + if (mobj->thinker.function.acv == (actionf_v)(-1)) + return; // mobj was removed + } + + // cycle through states, + // calling action functions at transitions + if (mobj->tics != -1) { + mobj->tics--; + + // you can cycle through multiple states in a tic + if (!mobj->tics) + if (!P_SetMobjState(mobj, mobj->state->nextstate)) + return; // freed itself + } else { + // check for nightmare respawn + if (!(mobj->flags & MF_COUNTKILL)) + return; + + if (!respawnmonsters) + return; + + mobj->movecount++; + + if (mobj->movecount < 12 * TICRATE) + return; + + if (leveltime & 31) + return; + + if (P_Random() > 4) + return; + + P_NightmareRespawn(mobj); + } +} +*/ + +// +// P_SpawnMobj +// +mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) { + mobj_t *mobj; + state_t *st; + mobjinfo_t *info; + + mobj = IPU_level_malloc(sizeof(*mobj)); + memset(mobj, 0, sizeof(*mobj)); + + // JOSEF: Just allocate the mem for now + /* LATER: Complete the rest of this function + + 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; + + if (gameskill != sk_nightmare) + mobj->reactiontime = info->reactiontime; + + mobj->lastlook = P_Random() % MAXPLAYERS; + // do not set the state with P_SetMobjState, + // because action routines can not 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; + + mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker; + + P_AddThinker(&mobj->thinker); + */ + + return mobj; +} + +/* +// +// P_RemoveMobj +// +mapthing_t itemrespawnque[ITEMQUESIZE]; +int itemrespawntime[ITEMQUESIZE]; +int iquehead; +int iquetail; + +void P_RemoveMobj(mobj_t *mobj) { + if ((mobj->flags & MF_SPECIAL) && !(mobj->flags & MF_DROPPED) && + (mobj->type != MT_INV) && (mobj->type != MT_INS)) { + itemrespawnque[iquehead] = mobj->spawnpoint; + itemrespawntime[iquehead] = leveltime; + iquehead = (iquehead + 1) & (ITEMQUESIZE - 1); + + // lose one off the end? + if (iquehead == iquetail) + iquetail = (iquetail + 1) & (ITEMQUESIZE - 1); + } + + // unlink from sector and block lists + P_UnsetThingPosition(mobj); + + // stop any playing sound + S_StopSound(mobj); + + // free block + P_RemoveThinker((thinker_t *)mobj); +} + +// +// P_RespawnSpecials +// +void P_RespawnSpecials(void) { + fixed_t x; + fixed_t y; + fixed_t z; + + subsector_t *ss; + mobj_t *mo; + mapthing_t *mthing; + + int i; + + // only respawn items in deathmatch + if (deathmatch != 2) + return; // + + // nothing left to respawn? + if (iquehead == iquetail) + return; + + // wait at least 30 seconds + if (leveltime - itemrespawntime[iquetail] < 30 * TICRATE) + return; + + mthing = &itemrespawnque[iquetail]; + + x = mthing->x << FRACBITS; + y = mthing->y << FRACBITS; + + // spawn a teleport fog at the new spot + ss = R_PointInSubsector(x, y); + mo = P_SpawnMobj(x, y, ss->sector->floorheight, MT_IFOG); + S_StartSound(mo, sfx_itmbk); + + // find which type to spawn + for (i = 0; i < NUMMOBJTYPES; i++) { + if (mthing->type == mobjinfo[i].doomednum) + break; + } + + // spawn it + if (mobjinfo[i].flags & MF_SPAWNCEILING) + z = ONCEILINGZ; + else + z = ONFLOORZ; + + mo = P_SpawnMobj(x, y, z, i); + mo->spawnpoint = *mthing; + mo->angle = ANG45 * (mthing->angle / 45); + + // pull it from the que + iquetail = (iquetail + 1) & (ITEMQUESIZE - 1); +} +*/ + +// +// 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) { + player_t *p; + fixed_t x; + fixed_t y; + fixed_t z; + + mobj_t *mobj; + + int i; + + if (mthing->type == 0) { + return; + } + + // not playing? + if (!playeringame[mthing->type - 1]) + return; + + p = &players[mthing->type - 1]; + + if (p->playerstate == PST_REBORN) { + // G_PlayerReborn(mthing->type - 1); LATER + printf("###\nG_PlayerReborn NOT IMPLEMENTED\n###"); + } + + x = mthing->x << FRACBITS; + y = mthing->y << FRACBITS; + z = ONFLOORZ; + mobj = P_SpawnMobj(x, y, z, MT_PLAYER); + + // set color translations for player sprites + if (mthing->type > 1) + mobj->flags |= (mthing->type - 1) << MF_TRANSSHIFT; + + mobj->angle = ANG45 * (mthing->angle / 45); + mobj->player = p; + mobj->health = p->health; + + p->mo = mobj; + p->playerstate = PST_LIVE; + p->refire = 0; + p->message = NULL; + p->damagecount = 0; + p->bonuscount = 0; + p->extralight = 0; + p->fixedcolormap = 0; + p->viewheight = VIEWHEIGHT; + + // setup gun psprite + // P_SetupPsprites(p); // LATER + + // give all cards in death match mode + if (deathmatch) + for (i = 0; i < NUMCARDS; i++) + p->cards[i] = true; + + // LATER + // if (mthing->type - 1 == consoleplayer) { + // // wake up the status bar + // ST_Start(); + // // wake up the heads up text + // HU_Start(); + // } +} + +// +// P_SpawnMapThing +// The fields of the mapthing should +// already be in host byte order. +// +void P_SpawnMapThing(mapthing_t *mthing) { + int i; + int bit; + mobj_t *mobj; + fixed_t x; + fixed_t y; + fixed_t z; + + // count deathmatch start positions + if (mthing->type == 11) { + // JOSEF: LATER + // if (deathmatch_p < &deathmatchstarts[10]) { + // memcpy(deathmatch_p, mthing, sizeof(*mthing)); + // deathmatch_p++; + // } + return; + } + + if (mthing->type <= 0) { + // Thing type 0 is actually "player -1 start". + // For some reason, Vanilla Doom accepts/ignores this. + + return; + } + + // check for players specially + if (mthing->type <= 4) { + // save spots for respawning in network games + playerstarts[mthing->type - 1] = *mthing; + if (!deathmatch) { + P_SpawnPlayer(mthing); + } + + return; + } + + /* LATER + // check for apropriate skill level + if (!netgame && (mthing->options & 16)) + return; + + if (gameskill == sk_baby) + bit = 1; + else if (gameskill == sk_nightmare) + bit = 4; + else + bit = 1 << (gameskill - 1); + + if (!(mthing->options & bit)) + return; + + // 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 %i at (%i, %i)", mthing->type, + mthing->x, mthing->y); + + // don't spawn keycards and players in deathmatch + if (deathmatch && mobjinfo[i].flags & MF_NOTDMATCH) + return; + + // don't spawn any monsters if -nomonsters + if (nomonsters && (i == MT_SKULL || (mobjinfo[i].flags & MF_COUNTKILL))) { + return; + } + + // 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->spawnpoint = *mthing; + + if (mobj->tics > 0) + mobj->tics = 1 + (P_Random() % mobj->tics); + if (mobj->flags & MF_COUNTKILL) + totalkills++; + if (mobj->flags & MF_COUNTITEM) + totalitems++; + + mobj->angle = ANG45 * (mthing->angle / 45); + if (mthing->options & MTF_AMBUSH) + mobj->flags |= MF_AMBUSH; + + */ +} + +/* +// +// GAME SPAWN FUNCTIONS +// + +// +// P_SpawnPuff +// +extern fixed_t attackrange; + +void P_SpawnPuff(fixed_t x, fixed_t y, fixed_t z) { + mobj_t *th; + + z += (P_SubRandom() << 10); + + th = P_SpawnMobj(x, y, z, MT_PUFF); + th->momz = FRACUNIT; + th->tics -= P_Random() & 3; + + if (th->tics < 1) + th->tics = 1; + + // don't make punches spark on the wall + if (attackrange == MELEERANGE) + P_SetMobjState(th, S_PUFF3); +} + +// +// P_SpawnBlood +// +void P_SpawnBlood(fixed_t x, fixed_t y, fixed_t z, int damage) { + mobj_t *th; + + z += (P_SubRandom() << 10); + th = P_SpawnMobj(x, y, z, MT_BLOOD); + th->momz = FRACUNIT * 2; + th->tics -= P_Random() & 3; + + if (th->tics < 1) + th->tics = 1; + + if (damage <= 12 && damage >= 9) + P_SetMobjState(th, S_BLOOD2); + else if (damage < 9) + P_SetMobjState(th, S_BLOOD3); +} + +// +// P_CheckMissileSpawn +// Moves the missile forward a bit +// and possibly explodes it right there. +// +void P_CheckMissileSpawn(mobj_t *th) { + th->tics -= P_Random() & 3; + if (th->tics < 1) + th->tics = 1; + + // move a little forward so an angle can + // be computed if it immediately explodes + th->x += (th->momx >> 1); + th->y += (th->momy >> 1); + th->z += (th->momz >> 1); + + if (!P_TryMove(th, th->x, th->y)) + P_ExplodeMissile(th); +} + +// Certain functions assume that a mobj_t pointer is non-NULL, +// causing a crash in some situations where it is NULL. Vanilla +// Doom did not crash because of the lack of proper memory +// protection. This function substitutes NULL pointers for +// pointers to a dummy mobj, to avoid a crash. + +mobj_t *P_SubstNullMobj(mobj_t *mobj) { + if (mobj == NULL) { + static mobj_t dummy_mobj; + + dummy_mobj.x = 0; + dummy_mobj.y = 0; + dummy_mobj.z = 0; + dummy_mobj.flags = 0; + + mobj = &dummy_mobj; + } + + return mobj; +} + +// +// P_SpawnMissile +// +mobj_t *P_SpawnMissile(mobj_t *source, mobj_t *dest, mobjtype_t type) { + mobj_t *th; + angle_t an; + int dist; + + th = P_SpawnMobj(source->x, source->y, source->z + 4 * 8 * FRACUNIT, type); + + if (th->info->seesound) + S_StartSound(th, th->info->seesound); + + th->target = source; // where it came from + an = R_PointToAngle2(source->x, source->y, dest->x, dest->y); + + // fuzzy player + if (dest->flags & MF_SHADOW) + an += P_SubRandom() << 20; + + th->angle = an; + an >>= ANGLETOFINESHIFT; + th->momx = FixedMul(th->info->speed, finecosine[an]); + th->momy = FixedMul(th->info->speed, finesine[an]); + + dist = P_AproxDistance(dest->x - source->x, dest->y - source->y); + dist = dist / th->info->speed; + + if (dist < 1) + dist = 1; + + th->momz = (dest->z - source->z) / dist; + P_CheckMissileSpawn(th); + + return th; +} + +// +// P_SpawnPlayerMissile +// Tries to aim at a nearby monster +// +void P_SpawnPlayerMissile(mobj_t *source, mobjtype_t type) { + mobj_t *th; + angle_t an; + + fixed_t x; + fixed_t y; + fixed_t z; + fixed_t slope; + + // see which target is to be aimed at + an = source->angle; + slope = P_AimLineAttack(source, an, 16 * 64 * FRACUNIT); + + if (!linetarget) { + an += 1 << 26; + slope = P_AimLineAttack(source, an, 16 * 64 * FRACUNIT); + + if (!linetarget) { + an -= 2 << 26; + slope = P_AimLineAttack(source, an, 16 * 64 * FRACUNIT); + } + + if (!linetarget) { + an = source->angle; + slope = 0; + } + } + + x = source->x; + y = source->y; + z = source->z + 4 * 8 * FRACUNIT; + + th = P_SpawnMobj(x, y, z, type); + + if (th->info->seesound) + S_StartSound(th, th->info->seesound); + + th->target = source; + th->angle = an; + th->momx = FixedMul(th->info->speed, finecosine[an >> ANGLETOFINESHIFT]); + th->momy = FixedMul(th->info->speed, finesine[an >> ANGLETOFINESHIFT]); + th->momz = FixedMul(th->info->speed, slope); + + P_CheckMissileSpawn(th); +} + +*/ \ No newline at end of file diff --git a/src/ipu/p_setup.c b/src/ipu/p_setup.c index b2c64c8..4e7724c 100644 --- a/src/ipu/p_setup.c +++ b/src/ipu/p_setup.c @@ -12,6 +12,8 @@ #include "print.h" +void P_SpawnMapThing(mapthing_t *mthing); + // // MAP related Lookup tables. // Store VERTEXES, LINEDEFS, SIDEDEFS, etc. @@ -104,11 +106,6 @@ void P_LoadVertexes(const unsigned char *buf) { li->x = ml->x << FRACBITS; li->y = ml->y << FRACBITS; } - - // Free buffer memory. - // JOSEF: W_ReleaseLumpNum(lump); - - requestedlumpnum = gamelumpnum + ML_SECTORS; } // @@ -137,8 +134,6 @@ void P_LoadSectors(const unsigned char *buf) { ss->tag = SHORT(ms->tag); ss->thinglist = NULL; } - - requestedlumpnum = gamelumpnum + ML_SIDEDEFS; } @@ -221,7 +216,7 @@ void P_LoadThings(const unsigned char *buf) { spawnthing.type = SHORT(mt->type); spawnthing.options = SHORT(mt->options); - // P_SpawnMapThing(&spawnthing); // TODO + P_SpawnMapThing(&spawnthing); // TODO } } @@ -252,8 +247,6 @@ void P_LoadSideDefs(const unsigned char *buf) { */ sd->sector = §ors[SHORT(msd->sector)]; } - - requestedlumpnum = gamelumpnum + ML_LINEDEFS; // JOSEF: Get rid of this } // @@ -324,7 +317,6 @@ void P_LoadLineDefs(const unsigned char *buf) { else ld->backsector = 0; } - requestedlumpnum = gamelumpnum + ML_SSECTORS; } // @@ -349,7 +341,6 @@ void P_LoadSubsectors(const unsigned char *buf) { ss->firstline = SHORT(ms->firstseg); } - requestedlumpnum = gamelumpnum + ML_NODES; } // @@ -396,10 +387,8 @@ void P_SetupLevel_pt0(const unsigned char unused) { leveltime = 0; reset_ipuprint(); - ipuprint("Map starts at lump "); ipuprintnum(gamelumpnum); ipuprint("\n"); + // ipuprint("Map starts at lump "); ipuprintnum(gamelumpnum); ipuprint("\n"); - // JOSEF: Lumpnum for P_LoadBlockMap - requestedlumpnum = gamelumpnum + ML_BLOCKMAP; return; // note: most of this ordering is important @@ -478,7 +467,4 @@ void P_LoadBlockMap(const unsigned char *buf) { count = sizeof(*blocklinks) * bmapwidth * bmapheight; blocklinks = IPU_level_malloc(count); memset(blocklinks, 0, count); - - // JOSEF: next lump to load - requestedlumpnum = gamelumpnum + ML_VERTEXES; } \ No newline at end of file diff --git a/src/ipu/r_bsp.c b/src/ipu/r_bsp.c index 961ed4a..0c22c1d 100644 --- a/src/ipu/r_bsp.c +++ b/src/ipu/r_bsp.c @@ -75,6 +75,8 @@ typedef struct { cliprange_t *newend; cliprange_t solidsegs[MAXSEGS]; + +/* // // R_ClipSolidWallSegment // Does handle solid walls, @@ -207,7 +209,9 @@ void R_ClearClipSegs(void) { solidsegs[1].last = 0x7fffffff; newend = solidsegs + 2; } +*/ +/* // // R_AddLine // Clips the given segment @@ -495,3 +499,4 @@ void R_RenderBSPNode(int bspnum) { if (R_CheckBBox(bsp->bbox[side ^ 1])) R_RenderBSPNode(bsp->children[side ^ 1]); } +*/ diff --git a/src/ipu/r_codelets.cpp b/src/ipu/r_codelets.cpp index 24856fe..469a1cf 100644 --- a/src/ipu/r_codelets.cpp +++ b/src/ipu/r_codelets.cpp @@ -2,13 +2,13 @@ #include -// #include "doomdata.h" +#include "doomstat.h" #include "ipu_transfer.h" extern "C" { - // void P_SetupLevel_pt0(const unsigned char *buf); + void R_RenderPlayerView(player_t *player); }; @@ -19,15 +19,14 @@ struct R_RenderPlayerView_Vertex : public poplar::Vertex { poplar::InOut> frame; void compute() { - // printf("Running R_RenderPlayerView_Vertex\n"); - // AM_Drawer(&frame[0]); - for (int i = 0; i < 100; ++i){ - frame[i + 320 * i ] = 1; - frame[i + 320 * i + 1] = 1; - } + // for (int i = 0; i < 100; ++i){ + // frame[i + 320 * i ] = 1; + // frame[i + 320 * i + 1] = 1; + // } IPU_R_RenderPlayerView_UnpackMiscValues( (R_RenderPlayerView_MiscValues_t*) &miscValues[0] ); + R_RenderPlayerView(&players[displayplayer]); return ; } }; diff --git a/src/ipu/r_main.c b/src/ipu/r_main.c index 71e3f7f..cfced9d 100644 --- a/src/ipu/r_main.c +++ b/src/ipu/r_main.c @@ -43,6 +43,8 @@ #include "r_things.h" #include "tables.h" +#include "print.h" + // JOSEF: added inline int abs(int x) { return (x < 0) ? -x : x; @@ -51,7 +53,7 @@ inline int abs(int x) { // Fineangles in the SCREENWIDTH wide window. #define FIELDOFVIEW 2048 -int viewangleoffset; +int viewangleoffset = 0; // increment every time a check is made int validcount = 1; @@ -712,6 +714,7 @@ void R_SetupFrame(player_t *player) { sscount = 0; + /* Later if (player->fixedcolormap) { fixedcolormap = colormaps + player->fixedcolormap * 256; @@ -721,6 +724,7 @@ void R_SetupFrame(player_t *player) { scalelightfixed[i] = fixedcolormap; } else fixedcolormap = 0; + */ framecount++; validcount++; diff --git a/src/ipu_transfer.c b/src/ipu_transfer.c index 0568eca..0fb8872 100644 --- a/src/ipu_transfer.c +++ b/src/ipu_transfer.c @@ -22,7 +22,11 @@ void IPU_G_LoadLevel_PackMiscValues(void* buf) { G_LoadLevel_MiscValues_t pack; pack.gameepisode = gameepisode; - pack.gamemap = gamemap; + pack.gamemap = gamemap; + pack.gamemode = gamemode; + pack.deathmatch = deathmatch; + for (int i = 0; i < MAXPLAYERS; ++i) + pack.playeringame[i] = playeringame[i]; char lumpname[9]; lumpname[0] = 'E'; @@ -63,10 +67,17 @@ void IPU_G_Ticker_PackMiscValues(void* buf) { pack->gamestate = gamestate; if (gamestate != GS_LEVEL) return; - pack->player_mobj.x = players[consoleplayer].mo->x; - pack->player_mobj.y = players[consoleplayer].mo->y; - pack->player_mobj.z = players[consoleplayer].mo->z; - pack->player_mobj.angle = players[consoleplayer].mo->angle; + + assert(consoleplayer == displayplayer); + pack->consoleplayer = consoleplayer; + pack->player.x = players[consoleplayer].mo->x; + pack->player.y = players[consoleplayer].mo->y; + pack->player.z = players[consoleplayer].mo->z; + pack->player.angle = players[consoleplayer].mo->angle; + pack->player.extralight = players[consoleplayer].extralight; + pack->player.viewz = players[consoleplayer].viewz; + pack->player.fixedcolormap = players[consoleplayer].fixedcolormap; + for (int i = 0; i < IPUMAPPEDLINEUPDATES; ++i) { if (!mapped_line_count) { pack->mappedline_updates[i] = -1; @@ -82,10 +93,8 @@ void IPU_G_Responder_PackMiscValues(void* src_buf, void* dst_buf) { } void IPU_R_RenderPlayerView_PackMiscValues(void* buf) { - R_RenderPlayerView_MiscValues_t* pack = (R_RenderPlayerView_MiscValues_t*) buf; - pack->displayplayer = displayplayer; - pack->players_displayplayer = players[displayplayer]; - pack->displayplayer_mo = *players[displayplayer].mo; + // R_RenderPlayerView_MiscValues_t* pack = (R_RenderPlayerView_MiscValues_t*) buf; + // Nothing to pack } void IPU_Setup_PackMarkNums(void* buf) {