diff --git a/.gitignore b/.gitignore index 896b0f2..ce7cad6 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ build/ debugger +gfxvalidator assets_working/ vpk/ portal_pak_dir/ diff --git a/Makefile b/Makefile index 9238fa9..53c6245 100644 --- a/Makefile +++ b/Makefile @@ -16,7 +16,7 @@ SFZ2N64:=sfz2n64 $(SKELATOOL64): make -C skelatool64 -OPTIMIZER := -O0 +OPTIMIZER := -O2 LCDEFS := -DDEBUG -g -Isrc/ -I/usr/include/n64/nustd -Werror -Wall N64LIB := -lultra_rom -lnustd @@ -35,6 +35,11 @@ ASMOBJECTS = $(patsubst %.s, build/%.o, $(ASMFILES)) CODEFILES = $(shell find src/ -type f -name '*.c') +ifeq ($(WITH_GFX_VALIDATOR),1) +LCDEFS += -DWITH_GFX_VALIDATOR +CODEFILES += gfxvalidator/validator.c gfxvalidator/error_printer.c gfxvalidator/command_printer.c +endif + CODESEGMENT = build/codesegment BOOT = /usr/lib/n64/PR/bootcode/boot.6102 diff --git a/README.md b/README.md index 84d145a..a418a7d 100644 --- a/README.md +++ b/README.md @@ -95,3 +95,4 @@ Where `/home/james/Blender/blender-2.93.1-linux-x64` is the folder where Blender - [x] Implement "Emancipation grid" - [x] Cut holes in portal walls - [x] Get an optimized build working +- [x] Portal animations diff --git a/src/graphics/graphics.c b/src/graphics/graphics.c index 1b8de2c..45e8976 100644 --- a/src/graphics/graphics.c +++ b/src/graphics/graphics.c @@ -7,6 +7,14 @@ struct GraphicsTask gGraphicsTasks[2]; extern OSMesgQueue gfxFrameMsgQ; extern OSMesgQueue *schedulerCommandQueue; +#if WITH_GFX_VALIDATOR +#include "../../gfxvalidator/validator.h" +#endif + +#if WITH_DEBUGGER +#include "../../debugger/debugger.h" +#endif + #define RDP_OUTPUT_SIZE 0x4000 u64* rdpOutput; @@ -67,8 +75,6 @@ void graphicsCreateTask(struct GraphicsTask* targetTask, GraphicsCallback callba renderStateFlushCache(renderState); - - OSScTask *scTask = &targetTask->task; OSTask_t *task = &scTask->list.t; @@ -100,5 +106,19 @@ void graphicsCreateTask(struct GraphicsTask* targetTask, GraphicsCallback callba scTask->next = 0; scTask->state = 0; +#if WITH_GFX_VALIDATOR + struct GFXValidationResult validationResult; + zeroMemory(&validationResult, sizeof(struct GFXValidationResult)); + + if (!gfxValidate(&scTask->list, MAX_DL_LENGTH, &validationResult)) { +#if WITH_DEBUGGER + gdbBreak(); +#else + zeroMemory(&validationResult, sizeof(struct GFXValidationResult)); + return; +#endif // WITH_DEBUGGER + } +#endif // WITH_GFX_VALIDATOR + osSendMesg(schedulerCommandQueue, (OSMesg)scTask, OS_MESG_BLOCK); } \ No newline at end of file diff --git a/src/graphics/screen_clipper.c b/src/graphics/screen_clipper.c index c36fa7c..9bf12b3 100644 --- a/src/graphics/screen_clipper.c +++ b/src/graphics/screen_clipper.c @@ -52,6 +52,10 @@ void screenClipperIncludePoint(struct Vector4* point, struct Box2D* output) { } unsigned screenClipperClipBoundary(struct ScreenClipper* clipper, struct Vector4* input, struct Vector4* output, unsigned pointCount, int axis, int direction, int oppositeSide) { + if (pointCount == 0) { + return 0; + } + unsigned outputPointCount = 0; struct Vector4* previous = &input[pointCount - 1]; diff --git a/src/player/player.c b/src/player/player.c index 0aa9545..410d8d4 100644 --- a/src/player/player.c +++ b/src/player/player.c @@ -243,8 +243,6 @@ void playerUpdate(struct Player* player, struct Transform* cameraTransform) { player->body.velocity.y = JUMP_IMPULSE; } - OSContPad* controllerInput = controllersGetControllerData(0); - struct Vector3 targetVelocity = gZeroVec; if (controllerGetButton(0, L_CBUTTONS | L_JPAD)) { @@ -313,6 +311,19 @@ void playerUpdate(struct Player* player, struct Transform* cameraTransform) { player->flags |= PlayerFlagsGrounded; } else { player->flags &= ~PlayerFlagsGrounded; + + struct ContactManifold* manifold = contactSolverNextManifold(&gContactSolver, &player->collisionObject, NULL); + + while (manifold) { + for (int contact = 0; contact < manifold->contactCount; ++contact) { + if (manifold->contacts[contact].id == 0xFFFF) { + manifold->contactCount = 0; + break; + } + } + + manifold = contactSolverNextManifold(&gContactSolver, &player->collisionObject, manifold); + } } playerHandleCollision(player); @@ -330,8 +341,7 @@ void playerUpdate(struct Player* player, struct Transform* cameraTransform) { soundPlayerPlay(soundsPortalExit[2 - didPassThroughPortal], 0.75f, 1.0f, NULL); } - - + OSContPad* controllerInput = controllersGetControllerData(0); float targetYaw = -playerCleanupStickInput(controllerInput->stick_x) * ROTATE_RATE; float targetPitch = playerCleanupStickInput(controllerInput->stick_y) * ROTATE_RATE; diff --git a/src/scene/portal_surface.c b/src/scene/portal_surface.c index 9270f46..8d0ce6d 100644 --- a/src/scene/portal_surface.c +++ b/src/scene/portal_surface.c @@ -62,6 +62,10 @@ int portalSurfaceShouldSwapOrder(int portalToMove) { } void portalSurfaceReplacementRevert(struct PortalSurfaceReplacement* replacement) { + if (!(replacement->flags & PortalSurfaceReplacementFlagsIsEnabled)) { + return; + } + gCurrentLevel->staticContent[replacement->staticIndex].displayList = replacement->previousSurface.triangles; portalSurfaceCleanup(&gCurrentLevel->portalSurfaces[replacement->portalSurfaceIndex]); gCurrentLevel->portalSurfaces[replacement->portalSurfaceIndex] = replacement->previousSurface; diff --git a/src/scene/portal_surface_generator.c b/src/scene/portal_surface_generator.c index af51748..c292a3a 100644 --- a/src/scene/portal_surface_generator.c +++ b/src/scene/portal_surface_generator.c @@ -46,6 +46,10 @@ int portalSurfaceFindEnclosingFace(struct PortalSurface* surface, struct Vector2 vector2Sub(&b, &a, &edgeOffset); vector2Sub(&aroundPointF, &a, &pointOffset); + if (edgeOffset.x == 0.0f && edgeOffset.y == 0.0f) { + continue; + } + float lerp = vector2Dot(&edgeOffset, &pointOffset) / vector2MagSqr(&edgeOffset); if (lerp < 0.0f) { diff --git a/tools/dump_rcp_state.py b/tools/dump_rcp_state.py new file mode 100644 index 0000000..a7c330f --- /dev/null +++ b/tools/dump_rcp_state.py @@ -0,0 +1,37 @@ +import gdb +import traceback + +def dump_hex_integer(output, number): + output.write(format((number >> 24) & 255, "02X")) + output.write(" ") + output.write(format((number >> 16) & 255, "02X")) + output.write(" ") + output.write(format((number >> 8) & 255, "02X")) + output.write(" ") + output.write(format((number >> 0) & 255, "02X")) + +try: + dmem_ptr = gdb.parse_and_eval("(int*)0xA4000000") + + with open("rcp_dump.txt", "w") as output: + for i in range(0, 4096, 16): + index_offset = i >> 2 + + output.write(format(i, "03X")) + + output.write(" ") + + dump_hex_integer(output, int(dmem_ptr[index_offset + 0])) + output.write(" ") + dump_hex_integer(output, int(dmem_ptr[index_offset + 1])) + output.write(" ") + dump_hex_integer(output, int(dmem_ptr[index_offset + 2])) + output.write(" ") + dump_hex_integer(output, int(dmem_ptr[index_offset + 3])) + + output.write(" \n") + +except: + print("An error happened") + print(traceback.format_exc()) + \ No newline at end of file