From 07ad92c380bdd6b3fd89c2fc159351908ec10f37 Mon Sep 17 00:00:00 2001 From: Treeki Date: Mon, 8 Apr 2013 00:34:00 +0200 Subject: add Credits Manager sprite --- src/creditsMgr.S | 60 ++++ src/creditsMgr.cpp | 895 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/levelspecial.cpp | 4 + src/randomcrap.S | 9 + 4 files changed, 968 insertions(+) create mode 100644 src/creditsMgr.S create mode 100644 src/creditsMgr.cpp (limited to 'src') diff --git a/src/creditsMgr.S b/src/creditsMgr.S new file mode 100644 index 0000000..cf5e809 --- /dev/null +++ b/src/creditsMgr.S @@ -0,0 +1,60 @@ +.text +.extern StaffCreditsAddCoin +.extern CreditsModeActive +.extern continueAddToCoinCount +.global StaffCreditsAddAllCoins +StaffCreditsAddAllCoins: + lis r4, CreditsModeActive@h + ori r4, r4, CreditsModeActive@l + lbz r4, 0(r4) + cmpwi r4, 1 + beq isCredits + stwu r1, -0x40(r1) + b continueAddToCoinCount +isCredits: + b StaffCreditsAddCoin + + +.extern continueAddToScore +.global StaffCreditsNoScore +StaffCreditsNoScore: + lis r9, CreditsModeActive@h + ori r9, r9, CreditsModeActive@l + lbz r9, 0(r9) + cmpwi r9, 1 + beqlr + cmpwi r5, -1 + b continueAddToScore + + +.global AutoScrollInjector +.extern BG_GM_ptr +AutoScrollInjector: + lis r3, CameraLockEnabled@h + ori r3, r3, CameraLockEnabled@l + lbz r3, 0(r3) + cmpwi r3, 1 + bnelr + + lis r3, BG_GM_ptr@h + ori r3, r3, BG_GM_ptr@l + lwz r3, 0(r3) + + lis r4, CameraLockPosition@h + ori r4, r4, CameraLockPosition@l + + addis r3, r3, 9 + lfs f1, 0(r4) + stfs f1, -0x178(r3) + lfs f1, 4(r4) + stfs f1, -0x174(r3) + blr + + + +.data +.global CameraLockEnabled +.global CameraLockPosition +CameraLockEnabled: .byte 0 +.align 4 +CameraLockPosition: .float 0.0, 0.0 \ No newline at end of file diff --git a/src/creditsMgr.cpp b/src/creditsMgr.cpp new file mode 100644 index 0000000..216b78b --- /dev/null +++ b/src/creditsMgr.cpp @@ -0,0 +1,895 @@ +#include +#include +#include +#include +#include +#define GEKKO +#include "rvl/mtx.h" +#include "rvl/GXEnum.h" +#include "rvl/GXStruct.h" +#include "rvl/GXTransform.h" +#include "rvl/GXGeometry.h" +#include "rvl/GXDispList.h" +#include "rvl/GXLighting.h" +#include "rvl/GXTev.h" +#include "rvl/GXTexture.h" +#include "rvl/GXCull.h" +#include "rvl/GXPixel.h" +#include "rvl/GXBump.h" +#include "rvl/GXVert.h" +#include "rvl/vifuncs.h" +#include +#include +#include +void *EGG__Heap__alloc(unsigned long size, int unk, void *heap); +void EGG__Heap__free(void *ptr, void *heap); + +extern char CameraLockEnabled; +extern VEC2 CameraLockPosition; + +mTexture_c efbTexture; +bool getNextEFB = false; +int thing = 0; + +const char *CreditsFileList[] = {"CreditsBG", 0}; + +extern "C" void GXPixModeSync(); +extern "C" void *MakeMarioEnterDemoMode(); +extern "C" void *MakeMarioExitDemoMode(); + +extern void *SoundRelatedClass; + +class dFlipbookRenderer_c : public m3d::proc_c { + public: + dFlipbookRenderer_c(); + ~dFlipbookRenderer_c(); + + mAllocator_c allocator; + void drawOpa(); + void drawXlu(); + void execute(); + + bool isEnabled; + int flipFrame; + + int scheduledBG; + + char *tplBuffer[2]; + u32 tplBufferSize[2]; + GXTexObj bgTexObj[2]; + + void loadNewBG(int bgID, bool isBackface); +}; + +class dCreditsMgr_c : public dActorState_c { + public: + int onCreate(); + int onDelete(); + int onExecute(); + int onDraw(); + + int currentPathID; + + bool isOutOfView() { return false; } + Vec2 _vf70(); + + dDvdLoader_c scriptLoader; + const u8 *scriptPos; + + dFlipbookRenderer_c renderer; + + bool loadLayout(); + bool loadTitleLayout(); + bool layoutLoaded; + bool titleLayoutLoaded; + m2d::EmbedLayout_c layout; + m2d::EmbedLayout_c titleLayout; + + bool titleLayoutVisible; + + int countdown; + + bool fireworks; + int fireworksCountdown; + + int fauxScrollFrame; + float fauxScrollMinX, fauxScrollMaxX, fauxScrollY; + + nw4r::lyt::TextBox + *Title, *TitleS, + *Name, *NameS, + *LeftName, *LeftNameS, + *RightName, *RightNameS; + nw4r::lyt::Pane + *TitleContainer, *NamesContainer, + *OneNameC, *TwoNamesC, *N_proportionC_00; + + void doAutoscroll(int pathID); + void positionPlayers(); + + void animComplete(); + + void enableZoom(); + void disableZoom(); + void playerWinAnim(); + void playerLookUp(); + void theEnd(); + void exitStage(); + + bool endingMode; + +// USING_STATES(dCreditsMgr_c); +// DECLARE_STATE(Wait); +// DECLARE_STATE(PlayLayoutAnim); +// DECLARE_STATE(Flipping); + + static dCreditsMgr_c *build(); + static dCreditsMgr_c *instance; +}; +// CREATE_STATE(dCreditsMgr_c, Wait); +// CREATE_STATE(dCreditsMgr_c, PlayLayoutAnim); +// CREATE_STATE(dCreditsMgr_c, Flipping); + +dCreditsMgr_c *dCreditsMgr_c::instance = 0; + +dCreditsMgr_c *dCreditsMgr_c::build() { + void *buf = AllocFromGameHeap1(sizeof(dCreditsMgr_c)); + return new(buf) dCreditsMgr_c; +} + + +int dCreditsMgr_c::onCreate() { + instance = this; + + if (!loadLayout()) + return false; + if (!loadTitleLayout()) + return false; + + if (!scriptLoader.load("/NewerRes/NewerStaffRoll.bin")) + return false; + + scriptPos = (const u8*)scriptLoader.buffer; + + getNextEFB = true; // make sure we have a texture + + renderer.allocator.setup(GameHeaps[0], 0x20); + bool result = renderer.setup(&renderer.allocator); + + renderer.loadNewBG(0, false); + + //acState.setState(&StateID_Wait); + + return true; +} + +int dCreditsMgr_c::onDelete() { + scriptLoader.unload(); + return layout.free(); +} +extern "C" bool SpawnEffect(const char*, int, Vec*, S16Vec*, Vec*); +int dCreditsMgr_c::onExecute() { + char *autoscrInfo = ((char*)dBgGm_c::instance) + 0x900AC; + + fauxScrollFrame++; + if (fauxScrollFrame > 60) + fauxScrollFrame = 60; + float fsMult = (1.0f / 60.0f) * float(fauxScrollFrame); + float interp = float(fauxScrollMinX) + ((fauxScrollMaxX - fauxScrollMinX) * fsMult); + CameraLockPosition.x = interp; + CameraLockPosition.y = fauxScrollY; + + if (endingMode) { + for (int i = 0; i < 4; i++) { + dAcPy_c *player; + if ((player = dAcPy_c::findByID(i))) { + if (!player->testFlag(0x24)) { + player->setAnimePlayWithAnimID(0); + } + player->setFlag(0x24); + player->rot.y = 0; + } + } + } + + if (fireworks) { + fireworksCountdown--; + if (fireworksCountdown <= 0) { + fireworksCountdown = MakeRandomNumber(40); + + static const char *fw[7] = { + "Wm_ob_fireworks_y", + "Wm_ob_fireworks_b", + "Wm_ob_fireworks_g", + "Wm_ob_fireworks_p", + "Wm_ob_fireworks_k", + "Wm_ob_fireworks_1up", + "Wm_ob_fireworks_star", + }; + + int fwID = MakeRandomNumber(7); + int xOffs = MakeRandomNumber(464); + int yOffs = MakeRandomNumber(80); + + VEC3 efPos = {10208.0f + xOffs, -304.0f - yOffs, pos.z + 200.0f}; + + SpawnEffect(fw[fwID], 0, &efPos, 0, 0); + } + } + + if (countdown > 0) { + countdown--; + } else if (!renderer.isEnabled) { + // Execute commands if we can + bool exitInterpreter = false; + while (scriptPos && !exitInterpreter) { + int u16_top, u16_bottom; + int whatAnim; + u8 *staffCreditScore; + + const u8 *read = scriptPos; + int cmdSize = *(read++); + int cmdType = *(read++); + + scriptPos += cmdSize; + + switch (cmdType) { + case 0: // Stop running script + scriptPos = 0; + exitInterpreter = true; + break; + + case 1: // Delay + u16_top = *(read++); + u16_bottom = *(read++); + countdown = (u16_top << 8) | u16_bottom; + exitInterpreter = true; + break; + + case 2: // Switch scene + doAutoscroll(*(read++)); + break; + + case 3: // Switch scene and wait + doAutoscroll(*(read++)); + exitInterpreter = true; + break; + + case 4: // Show scores + staffCreditScore = GetStaffCreditScore(); + staffCreditScore[0x279] = 1; + OSReport("Staff Credit Score object is at %p, going to show it\n", staffCreditScore); + break; + + case 5: // Show text + layout.enableNonLoopAnim(0); + break; + case 6: // Hide text + layout.enableNonLoopAnim(1); + break; + + case 7: { // Set names. FUN! + int titleLength = *(read++); + int nameCount = *(read++); + + WriteAsciiToTextBox(Title, (const char*)read); + WriteAsciiToTextBox(TitleS, (const char*)read); + + read += titleLength; + + WriteAsciiToTextBox(Name, (const char*)read); + WriteAsciiToTextBox(NameS, (const char*)read); + + float calcHeight = 29.0f * nameCount; + TitleContainer->trans.y = (calcHeight * 0.5f) + 3.0f; + + OneNameC->SetVisible(true); + TwoNamesC->SetVisible(false); + + } break; + + case 8: + titleLayoutVisible = true; + break; + case 9: + titleLayoutVisible = false; + break; + case 10: + whatAnim = *(read++); + titleLayout.enableNonLoopAnim(whatAnim); + break; + + case 11: + endingMode = true; + break; + case 12: + enableZoom(); + break; + case 13: + playerWinAnim(); + break; + case 14: + disableZoom(); + break; + case 15: + playerLookUp(); + break; + case 16: + theEnd(); + break; + case 17: + exitStage(); + exitInterpreter = true; + break; + case 18: + GetTheEnd()->willHide = true; + break; + } + } + } + + layout.execAnimations(); + layout.update(); + + titleLayout.execAnimations(); + titleLayout.update(); + + //acState.execute(); + renderer.execute(); + + return true; +} + +int dCreditsMgr_c::onDraw() { + renderer.scheduleForDrawing(); + layout.scheduleForDrawing(); + if (titleLayoutVisible) + titleLayout.scheduleForDrawing(); + return true; +} + + +bool dCreditsMgr_c::loadLayout() { + if (!layoutLoaded) { + if (!layout.loadArc("StaffRoll.arc", false)) + return false; + + layout.build("StaffRoll.brlyt"); + + static const char *brlanNames[] = { + "StaffRoll_show.brlan", + "StaffRoll_hide.brlan", + }; + static const char *groupNames[] = { + "TheOnlyGroup", "TheOnlyGroup" + }; + + layout.loadAnimations(brlanNames, 2); + layout.loadGroups(groupNames, (int[2]){0, 1}, 2); + layout.disableAllAnimations(); + layout.resetAnim(0); + + static const char *tbNames[] = { + "Title", "TitleS", + "Name", "NameS", + "LeftName", "LeftNameS", + "RightName", "RightNameS" + }; + static const char *paneNames[] = { + "TitleContainer", "NamesContainer", + "OneNameC", "TwoNamesC", + }; + + layout.getTextBoxes(tbNames, &Title, 8); + layout.getPanes(paneNames, &TitleContainer, 4); + + layoutLoaded = true; + } + return layoutLoaded; +} + +bool dCreditsMgr_c::loadTitleLayout() { + if (!titleLayoutLoaded) { + if (!titleLayout.loadArc("StaffRollTitle.arc", false)) + return false; + + titleLayout.build("StaffRollTitle.brlyt"); + + static const char *brlanNames[] = { + "StaffRollTitle_appear1.brlan", + "StaffRollTitle_appear2.brlan", + }; + static const char *groupNames[] = { + "TheOnlyGroup", "TheOnlyGroup" + }; + + titleLayout.loadAnimations(brlanNames, 2); + titleLayout.loadGroups(groupNames, (int[2]){0, 1}, 2); + titleLayout.disableAllAnimations(); + titleLayout.resetAnim(1); + + float propScale = 1.3f; + if (!IsWideScreen()) + propScale *= 0.85f; + + N_proportionC_00 = titleLayout.findPaneByName("N_proportionC_00"); + N_proportionC_00->trans.y = -130.0f; + N_proportionC_00->scale.x = propScale; + N_proportionC_00->scale.y = propScale; + + titleLayoutLoaded = true; + } + return titleLayoutLoaded; +} + +extern "C" dCourse_c::rail_s *GetRail(int id); + +void dCreditsMgr_c::doAutoscroll(int pathID) { + OSReport("Activating Autoscroll with path %d\n", pathID); + + getNextEFB = true; + renderer.isEnabled = true; + renderer.flipFrame = 0; + renderer.scheduledBG = pathID; + MakeMarioEnterDemoMode(); + + char *autoscrInfo = ((char*)dBgGm_c::instance) + 0x900AC; + *((u8*)(autoscrInfo + 0x14)) = pathID; + *((u8*)(autoscrInfo + 0x15)) = 1; // unk11 + *((u8*)(autoscrInfo + 0x16)) = 0; // atEnd Related + *((u8*)(autoscrInfo + 0x17)) = 2; // atEnd + *((u8*)(autoscrInfo + 0x18)) = 0; // mode + *((u8*)(autoscrInfo + 0x1A)) = 1; // isAutoscrolling + *((u32*)(((char*)dBgGm_c::instance) + 0x900EC)) = 0; // node ID + *((u32*)(((char*)dBgGm_c::instance) + 0x900F0)) = 0; // ? + + currentPathID = pathID; + + dCourse_c::rail_s *rail = GetRail(pathID); + dCourse_c *course = dCourseFull_c::instance->get(GetAreaNum()); + + dCourse_c::railNode_s *firstNode = &course->railNode[rail->startNode]; + dCourse_c::railNode_s *secondNode = &course->railNode[rail->startNode+1]; + + fauxScrollFrame = 0; + fauxScrollMinX = firstNode->xPos; + fauxScrollMaxX = secondNode->xPos; + fauxScrollY = -firstNode->yPos; + + CameraLockEnabled = 1; +} + +void dCreditsMgr_c::animComplete() { + positionPlayers(); +} + + +void dCreditsMgr_c::positionPlayers() { + dCourse_c *course = dCourseFull_c::instance->get(GetAreaNum()); + dCourse_c::nextGoto_s *entrance = course->getNextGotoByID(currentPathID); + + float diff = endingMode ? 48.0f : 24.0f; + float playerPositions[4]; + playerPositions[0] = entrance->xPos; + playerPositions[1] = playerPositions[0] - diff; + playerPositions[2] = playerPositions[0] + diff; + playerPositions[3] = playerPositions[0] + diff + diff; + + int whichPos = 0; + for (int i = 0; i < 4; i++) { + dAcPy_c *player; + if ((player = dAcPy_c::findByID(i))) { + player->pos.x = playerPositions[whichPos]; + player->pos.y = -(entrance->yPos + 16); + player->direction = 0; + player->rot.y = 0x3000; + dPlayerModelHandler_c *pmh = (dPlayerModelHandler_c*)(((u32)player) + 0x2A60); + pmh->mdlClass->startAnimation(0, 1.0f, 0.0f, 0.0f); + whichPos++; + } + } +} + + +void dCreditsMgr_c::enableZoom() { + BgGmBase::manualZoomEntry_s &zoom = dBgGm_c::instance->manualZooms[0]; + zoom.x1 = 10218.0f; + zoom.x2 = 11000.0f; + zoom.y1 = -200.0f; + zoom.y2 = -600.0f; + + zoom.x1 = 1100.0f; + zoom.x2 = 1300.0f; + zoom.y1 = -400.0f; + zoom.y2 = -550.0f; + zoom.zoomLevel = 7; + zoom.unkValue6 = 0; + zoom.firstFlag = 0; +} +void dCreditsMgr_c::disableZoom() { + BgGmBase::manualZoomEntry_s &zoom = dBgGm_c::instance->manualZooms[0]; + zoom.unkValue6 = 100; +} +void dCreditsMgr_c::playerWinAnim() { + // who won? + // First, get the amounts + u8 *amountsU8 = GetStaffCreditScore() + 0x288; + int *playerAmounts = (int*)(amountsU8); + int maxSoFar = 0; + + for (int i = 0; i < 4; i++) { + if (playerAmounts[i] > maxSoFar) + maxSoFar = playerAmounts[i]; + } + + if (maxSoFar == 0) + return; + + // did anyone win? + for (int i = 0; i < 4; i++) { + if (playerAmounts[i] == maxSoFar) { + dAcPy_c *player = dAcPy_c::findByID(i); + if (!player) + continue; + + player->setAnimePlayWithAnimID(goal_puton_capA); + player->setFlag(0x24); + + static const int vocs[4] = { + SE_VOC_MA_CLEAR_NORMAL, + SE_VOC_LU_CLEAR_NORMAL, + SE_VOC_KO_CLEAR_NORMAL, + SE_VOC_KO2_CLEAR_NORMAL + }; + dPlayerModelHandler_c *pmh = (dPlayerModelHandler_c*)(((u32)player) + 0x2A60); + int voc = vocs[pmh->mdlClass->player_id_1]; + nw4r::snd::SoundHandle handle; + PlaySoundWithFunctionB4(SoundRelatedClass, &handle, voc, 1); + + int powerup = *((u32*)( 0x1090 + ((u8*)player) )); + handle.SetPitch(powerup == 3 ? 1.5f : 1.0f); + } + } +} + +void dCreditsMgr_c::playerLookUp() { + _120 |= 8; + lookAtMode = 2; // Higher maximum distance +} +void dCreditsMgr_c::theEnd() { + fireworks = true; + fireworksCountdown = 25; + + GetTheEnd()->willShow = true; +} +void dCreditsMgr_c::exitStage() { + ExitStage(WORLD_MAP, 0, BEAT_LEVEL, CIRCLE_WIPE); +} + +Vec2 dCreditsMgr_c::_vf70() { + // HACK OF THE MILLENIUM + // DON'T TRY THIS AT HOME. + Vec2 *v = (Vec2*)this; + v->x = 10454.0f; + v->y = -320.0f; + return (const Vec2){12345.0f, 67890.f}; +} + + + +void EFBMagic2() { + if (getNextEFB) { + getNextEFB = false; + + GXRenderModeObj *ro = nw4r::g3d::G3DState::GetRenderModeObj(); + efbTexture.format = GX_TF_RGB565; + efbTexture.width = ro->fbWidth; + efbTexture.height = ro->efbHeight; + efbTexture.wrapS = GX_CLAMP; + efbTexture.wrapT = GX_CLAMP; + + if (efbTexture.getBuffer() == 0) + efbTexture.allocateBuffer(GameHeaps[2]); + + GXSetTexCopySrc(0, 0, efbTexture.width, efbTexture.height); + GXSetTexCopyDst(efbTexture.width, efbTexture.height, (GXTexFmt)efbTexture.format, GX_FALSE); + GXSetCopyFilter(GX_FALSE, 0, GX_FALSE, 0); + GXCopyTex(efbTexture.getBuffer(), GX_FALSE); + + GXPixModeSync(); + GXInvalidateTexAll(); + } +} + +void dFlipbookRenderer_c::execute() { + if (flipFrame == 7) { + loadNewBG(scheduledBG, true); + } + + if (isEnabled) { + flipFrame += 7; + + ClassWithCameraInfo *cwci = ClassWithCameraInfo::instance; + if (flipFrame > int(cwci->screenWidth)) { + loadNewBG(scheduledBG, false); + dCreditsMgr_c::instance->animComplete(); + + if (!dCreditsMgr_c::instance->endingMode) + MakeMarioExitDemoMode(); + isEnabled = false; + OSReport("DONE!\n"); + } + } +} + + +static void setupGXForDrawingCrap() { + GXSetNumChans(0); + GXSetChanCtrl(GX_COLOR0A0, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_NONE, GX_AF_NONE); + GXSetChanAmbColor(GX_COLOR0A0, (GXColor){255,255,255,255}); + GXSetChanMatColor(GX_COLOR0A0, (GXColor){255,255,255,255}); + GXSetNumTexGens(1); + GXSetTexCoordGen2(GX_TEXCOORD0, GX_TG_MTX3x4, GX_TG_NRM, GX_IDENTITY, GX_FALSE, GX_PTIDENTITY); + + GXSetNumTevStages(1); + GXSetNumIndStages(0); + for (int i = 0; i < 0x10; i++) + GXSetTevDirect((GXTevStageID)i); + + GXSetTevOp(GX_TEVSTAGE0, GX_REPLACE); + GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); + + GXSetTevSwapModeTable(GX_TEV_SWAP0, GX_CH_RED, GX_CH_GREEN, GX_CH_BLUE, GX_CH_ALPHA); + + GXSetZCompLoc(GX_FALSE); + GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_SET); + //GXSetBlendMode(GX_BM_NONE, GX_BL_ZERO, GX_BL_ZERO, GX_LO_SET); + GXSetZMode(GX_TRUE, GX_ALWAYS, GX_FALSE); + GXSetAlphaCompare(GX_ALWAYS, 0, GX_AOP_OR, GX_ALWAYS, 0); + + GXSetFog(GX_FOG_NONE, 0, 0, 0, 0, (GXColor){0,0,0,0}); + GXSetFogRangeAdj(GX_FALSE, 0, 0); + + GXSetAlphaUpdate(GX_TRUE); + + GXSetCullMode(GX_CULL_NONE); + + GXSetDither(GX_TRUE); + + GXSetTevColor(GX_TEVREG0, (GXColor){255,255,255,255}); + GXSetTevColor(GX_TEVREG1, (GXColor){255,255,255,255}); + GXSetTevColor(GX_TEVREG2, (GXColor){255,255,255,255}); + + GXSetZMode(GX_TRUE, GX_LEQUAL, GX_TRUE); + + nw4r::g3d::Camera cam(GetCameraByID(GetCurrentCameraID())); + Mtx matrix; + cam.GetCameraMtx(&matrix); + GXLoadPosMtxImm(matrix, 0); + GXSetCurrentMtx(0); + + GXClearVtxDesc(); + + GXSetVtxDesc(GX_VA_POS, GX_DIRECT); + GXSetVtxDesc(GX_VA_NRM, GX_DIRECT); + + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_F32, 0); +} + +void dFlipbookRenderer_c::drawXlu() { + if (!isEnabled || flipFrame < 2) + return; + + setupGXForDrawingCrap(); + + ClassWithCameraInfo *cwci = ClassWithCameraInfo::instance; + + float screenTop = cwci->screenTop + Stage80::instance->screenYOffset; + float left = cwci->screenLeft + Stage80::instance->screenXOffset; + float right = left + cwci->screenWidth; + + float halfWidth = (cwci->screenWidth * 0.5f); + float midpoint = left + halfWidth; + + float value = (flipFrame / cwci->screenWidth); + float sinThing = 50.0f * sin(3.14159f * value); + + bool drawBackside = (flipFrame > halfWidth); + + float xformedFlipEdge = right - flipFrame; + + // EFB SPECIFIC VERTICAL VARIABLES + float efbEffectiveHeight = cwci->screenHeight; + if (!IsWideScreen()) + efbEffectiveHeight *= 1.295f; + + float efbHalfHeight = (efbEffectiveHeight * 0.5f); + + float efbYCentre = screenTop - (cwci->screenHeight * 0.5f); + if (!IsWideScreen()) + efbYCentre += 1.0f; + float efbTop = efbYCentre + efbHalfHeight; + float efbBottom = efbYCentre - efbHalfHeight; + + float efbExCoord = (efbEffectiveHeight + sinThing + sinThing) * 0.5f; + // TPL SPECIFIC VERTICAL VARIABLES + float tplHalfHeight = cwci->screenHeight * 0.5f; + float tplTop = screenTop; + float tplBottom = screenTop - cwci->screenHeight; + + float tplExCoord = (cwci->screenHeight + sinThing + sinThing) * 0.5f; + + + // EFB Left + efbTexture.load(GX_TEXMAP0); + + GXBegin(GX_QUADS, GX_VTXFMT0, 4); + { + // Bottom Right + GXPosition3f32(midpoint, efbBottom, 9990.0f); + GXNormal3f32(0.5f, 1.0f, 1.0f); + // Top Right + GXPosition3f32(midpoint, efbTop, 9990.0f); + GXNormal3f32(0.5f, 0.0f, 1.0f); + // Top Left + GXPosition3f32(left, efbTop, 9990.0f); + GXNormal3f32(0.0f, 0.0f, 1.0f); + // Bottom Left + GXPosition3f32(left, efbBottom, 9990.0f); + GXNormal3f32(0.0f, 1.0f, 1.0f); + } + GXEnd(); + + // TPL Right + GXLoadTexObj(&bgTexObj[1], GX_TEXMAP0); + + GXBegin(GX_QUADS, GX_VTXFMT0, 4); + { + // Bottom Right + GXPosition3f32(right, tplBottom, 9990.0f); + GXNormal3f32(1.0f, 1.0f, 1.0f); + // Top Right + GXPosition3f32(right, tplTop, 9990.0f); + GXNormal3f32(1.0f, 0.0f, 1.0f); + // Top Left + GXPosition3f32(midpoint, tplTop, 9990.0f); + GXNormal3f32(0.5f, 0.0f, 1.0f); + // Bottom Left + GXPosition3f32(midpoint, tplBottom, 9990.0f); + GXNormal3f32(0.5f, 1.0f, 1.0f); + + } + GXEnd(); + + + if (!drawBackside) { + // Flipping right side: EFB + + efbTexture.load(GX_TEXMAP0); + + GXBegin(GX_QUADS, GX_VTXFMT0, 4); + + // EFB Right (Flipped) + // Bottom Left + GXPosition3f32(midpoint, efbBottom, 9990.0f); + GXNormal3f32(efbHalfHeight * 0.5f, efbHalfHeight, efbHalfHeight); + // Top Left + GXPosition3f32(midpoint, efbTop, 9990.0f); + GXNormal3f32(efbHalfHeight * 0.5f, 0.0f, efbHalfHeight); + // Top Right + GXPosition3f32(xformedFlipEdge, efbTop + sinThing, 9990.0f); + GXNormal3f32(efbExCoord, 0.0f, efbExCoord); + // Bottom Right + GXPosition3f32(xformedFlipEdge, efbBottom - sinThing, 9990.0f); + GXNormal3f32(efbExCoord, efbExCoord, efbExCoord); + + GXEnd(); + + } else { + // Flipping left side + + GXLoadTexObj(&bgTexObj[1], GX_TEXMAP0); + + GXBegin(GX_QUADS, GX_VTXFMT0, 4); + + // TPL Left (Flipped)) + // Bottom Left + GXPosition3f32(xformedFlipEdge, tplBottom - sinThing, 9990.0f); + GXNormal3f32(0.0f, tplExCoord, tplExCoord); + // Top Left + GXPosition3f32(xformedFlipEdge, tplTop + sinThing, 9990.0f); + GXNormal3f32(0.0f, 0.0f, tplExCoord); + // Top Right + GXPosition3f32(midpoint, tplTop, 9990.0f); + GXNormal3f32(tplHalfHeight * 0.5f, 0.0f, tplHalfHeight); + // Bottom Right + GXPosition3f32(midpoint, tplBottom, 9990.0f); + GXNormal3f32(tplHalfHeight * 0.5f, tplHalfHeight, tplHalfHeight); + + GXEnd(); + } +} + + +void dFlipbookRenderer_c::drawOpa() { + setupGXForDrawingCrap(); + + GXLoadTexObj(&bgTexObj[0], GX_TEXMAP0); + + ClassWithCameraInfo *cwci = ClassWithCameraInfo::instance; + float left = cwci->screenLeft + Stage80::instance->screenXOffset; + float right = left + cwci->screenWidth; + float top = cwci->screenTop + Stage80::instance->screenYOffset; + float bottom = top - cwci->screenHeight; + + GXBegin(GX_QUADS, GX_VTXFMT0, 4); + GXPosition3f32(right, bottom, -4000.0f); + GXNormal3f32(1.0f, 1.0f, 1.0f); + GXPosition3f32(right, top, -4000.0f); + GXNormal3f32(1.0f, 0.0f, 1.0f); + GXPosition3f32(left, top, -4000.0f); + GXNormal3f32(0.0f, 0.0f, 1.0f); + GXPosition3f32(left, bottom, -4000.0f); + GXNormal3f32(0.0f, 1.0f, 1.0f); + GXEnd(); +} + +#include + +void dFlipbookRenderer_c::loadNewBG(int bgID, bool isBackface) { + OSReport("Will load BG: %d\n", bgID); + + int setID = isBackface ? 1 : 0; + + char bgName[32]; + sprintf(bgName, isBackface ? "/Back%d.tpl.LZ" : "/BG%d.tpl.LZ", bgID); + OSReport("Getting %s\n", bgName); + + u8 *sourceBuf = getResource("CreditsBG", bgName); + u32 bufSize = CXGetUncompressedSize(sourceBuf); + + if (tplBuffer[setID] && (tplBufferSize[setID] != bufSize)) { + OSReport("Current TPL buffer (%p) is size %d (0x%x), freeing\n", tplBuffer[setID], tplBufferSize[setID], tplBufferSize[setID]); + EGG__Heap__free(tplBuffer[setID], GameHeaps[2]); + tplBuffer[setID] = 0; + } + + if (!tplBuffer[setID]) { + OSReport("Allocating TPL buffer of size %d (0x%x)\n", bufSize, bufSize); + tplBuffer[setID] = (char*)EGG__Heap__alloc(bufSize, 0x20, GameHeaps[2]); + tplBufferSize[setID] = bufSize; + } + + //CXUncompContextLH context; + //CXInitUncompContextLH(&context, tplBuffer); + //int result = CXReadUncompLH(&context, sourceBuf, 0x1000000); + //OSReport("Source buf: %p / Dest buf: %p / Dest size: %d (0x%x)\n", sourceBuf, tplBuffer, bufSize, bufSize); + //OSReport("CXReadUncompLH result: %d\n", result); + CXUncompressLZ(sourceBuf, tplBuffer[setID]); + OSReport("Butts. Decompressing %p to %p.\n", sourceBuf, tplBuffer[setID]); + + TPLBind((TPLPalettePtr)tplBuffer[setID]); + TPLDescriptorPtr desc = TPLGet((TPLPalettePtr)tplBuffer[setID], 0); + TPLHeaderPtr tex = desc->textureHeader; + OSReport("Received TPLHeader %p; Data: %p; Size: %d x %d; Format; %d\n", tex, tex->data, tex->width, tex->height, tex->format); + + GXInitTexObj(&bgTexObj[setID], tex->data, tex->width, tex->height, + (GXTexFmt)tex->format, tex->wrapS, tex->wrapT, GX_FALSE); +} + +dFlipbookRenderer_c::dFlipbookRenderer_c() { + scheduledBG = -1; +} + +dFlipbookRenderer_c::~dFlipbookRenderer_c() { + for (int setID = 0; setID < 2; setID++) { + if (tplBuffer[setID]) { + EGG__Heap__free(tplBuffer[setID], GameHeaps[2]); + tplBuffer[setID] = 0; + } + } +} + + + diff --git a/src/levelspecial.cpp b/src/levelspecial.cpp index 962b87f..002a6a1 100644 --- a/src/levelspecial.cpp +++ b/src/levelspecial.cpp @@ -45,6 +45,9 @@ extern char BGScaleEnabled; extern u32 GameTimer; +extern char CameraLockEnabled; +extern VEC2 CameraLockPosition; + #define time *(u32*)((GameTimer) + 0x4) @@ -91,6 +94,7 @@ bool ResetAfterLevel(bool didItWork) { for (int i = 0; i < 4; i++) Player_Flags[i] &= ~4; BGScaleEnabled = 0; + CameraLockEnabled = 0; return didItWork; } diff --git a/src/randomcrap.S b/src/randomcrap.S index a5f6751..3502ad2 100644 --- a/src/randomcrap.S +++ b/src/randomcrap.S @@ -315,6 +315,15 @@ BigMetSlidingFix: mtlr r0 addi r1, r1, 0x10 blr + +.global EFB_Crap +.extern EFBMagic2__Fv +.extern ContinueFromEFBMagic2 +EFB_Crap: + bl EFBMagic2__Fv + lwz r3, 4(r30) + b ContinueFromEFBMagic2 + .data .global BGScaleFront, BGScaleBack, BGScaleEnabled BGScale: -- cgit v1.2.3