void async_GUI_Mentat_ShowOpen() { Sprites_UnloadTiles(); GUI_Mentat_Display(asyncMentatShow.wsaFilename, g_playerHouseID); GFX_Screen_SetActive(2); Widget_SetAndPaintCurrentWidget(8); if (asyncMentatShow.wsaFilename != NULL) { void *wsa; wsa = WSA_LoadFile(asyncMentatShow.wsaFilename, GFX_Screen_Get_ByIndex(5), GFX_Screen_GetSize_ByIndex(5), false); WSA_DisplayFrame(wsa, 0, g_curWidgetXBase * 8, g_curWidgetYBase, 2); WSA_Unload(wsa); } GUI_DrawSprite(2, g_sprites[397 + g_playerHouseID * 15], g_shoulderLeft, g_shoulderTop, 0, 0); GFX_Screen_SetActive(0); GUI_Mouse_Hide_Safe(); GUI_Screen_Copy(0, 0, 0, 0, SCREEN_WIDTH / 8, SCREEN_HEIGHT, 2, 0); GUI_Mouse_Show_Safe(); GUI_SetPaletteAnimated(g_palette1, 15); Async_GUI_Mentat_Loop(asyncMentatShow.wsaFilename, NULL, asyncMentatShow.stringBuffer, true, NULL); Async_Storage_uint16(&asyncMentatShow.ret); }
/** * Display a mentat. * @param houseFilename Filename of the house. * @param houseID ID of the house. */ void GUI_Mentat_Display(const char *wsaFilename, uint8 houseID) { char textBuffer[16]; Screen oldScreenID; int i; snprintf(textBuffer, sizeof(textBuffer), "MENTAT%c.CPS", g_table_houseInfo[houseID].name[0]); Sprites_LoadImage(textBuffer, SCREEN_1, g_palette_998A); oldScreenID = GFX_Screen_SetActive(SCREEN_1); if (houseID == HOUSE_MERCENARY) { File_ReadBlockFile("BENE.PAL", g_palette1, 256 * 3); } memset(s_mentatSprites, 0, sizeof(s_mentatSprites)); s_eyesLeft = s_eyesRight = s_unknownHouseData[houseID][0]; s_eyesTop = s_eyesBottom = s_unknownHouseData[houseID][1]; for (i = 0; i < 5; i++) { s_mentatSprites[0][i] = g_sprites[387 + houseID * 15 + i]; } s_eyesRight += Sprite_GetWidth(s_mentatSprites[0][0]); s_eyesBottom += Sprite_GetHeight(s_mentatSprites[0][0]); s_mouthLeft = s_mouthRight = s_unknownHouseData[houseID][2]; s_mouthTop = s_mouthBottom = s_unknownHouseData[houseID][3]; for (i = 0; i < 5; i++) { s_mentatSprites[1][i] = g_sprites[392 + houseID * 15 + i]; } s_mouthRight += Sprite_GetWidth(s_mentatSprites[1][0]); s_mouthBottom += Sprite_GetHeight(s_mentatSprites[1][0]); s_otherLeft = s_unknownHouseData[houseID][4]; s_otherTop = s_unknownHouseData[houseID][5]; for (i = 0; i < 4; i++) { s_mentatSprites[2][i] = g_sprites[398 + houseID * 15 + i]; } g_shoulderLeft = s_unknownHouseData[houseID][6]; g_shoulderTop = s_unknownHouseData[houseID][7]; Widget_SetAndPaintCurrentWidget(8); if (wsaFilename != NULL) { void *wsa; wsa = WSA_LoadFile(wsaFilename, GFX_Screen_Get_ByIndex(SCREEN_2), GFX_Screen_GetSize_ByIndex(SCREEN_2), false); WSA_DisplayFrame(wsa, 0, g_curWidgetXBase * 8, g_curWidgetYBase, SCREEN_1); WSA_Unload(wsa); } GUI_DrawSprite(SCREEN_1, g_sprites[397 + houseID * 15], g_shoulderLeft, g_shoulderTop, 0, 0); GFX_Screen_SetActive(oldScreenID); }
/** * Show the Mentat screen. * @param spriteBuffer The buffer of the strings. * @param wsaFilename The WSA to show. * @param w The widgets to handle. Can be NULL for no widgets. * @param unknown A boolean. * @return Return value of GUI_Widget_HandleEvents() or f__B4DA_0AB8_002A_AAB2() (latter when no widgets). */ uint16 GUI_Mentat_Show(char *stringBuffer, const char *wsaFilename, Widget *w, bool unknown) { uint16 ret; Sprites_UnloadTiles(); GUI_Mentat_Display(wsaFilename, g_playerHouseID); GFX_Screen_SetActive(SCREEN_1); Widget_SetAndPaintCurrentWidget(8); if (wsaFilename != NULL) { void *wsa; wsa = WSA_LoadFile(wsaFilename, GFX_Screen_Get_ByIndex(SCREEN_2), GFX_Screen_GetSize_ByIndex(SCREEN_2), false); WSA_DisplayFrame(wsa, 0, g_curWidgetXBase * 8, g_curWidgetYBase, SCREEN_1); WSA_Unload(wsa); } GUI_DrawSprite(SCREEN_1, g_sprites[397 + g_playerHouseID * 15], g_shoulderLeft, g_shoulderTop, 0, 0); GFX_Screen_SetActive(SCREEN_0); GUI_Mouse_Hide_Safe(); GUI_Screen_Copy(0, 0, 0, 0, SCREEN_WIDTH / 8, SCREEN_HEIGHT, SCREEN_1, SCREEN_0); GUI_Mouse_Show_Safe(); GUI_SetPaletteAnimated(g_palette1, 15); ret = GUI_Mentat_Loop(wsaFilename, NULL, stringBuffer, true, NULL); if (w != NULL) { do { GUI_Widget_DrawAll(w); ret = GUI_Widget_HandleEvents(w); GUI_PaletteAnimate(); GUI_Mentat_Animation(0); sleepIdle(); } while ((ret & 0x8000) == 0); } Input_History_Clear(); if (unknown) { Load_Palette_Mercenaries(); Sprites_LoadTiles(); } return ret; }
void async_GUI_Mentat_LoopClose() { if (asyncMentatLoop.wsa != NULL) WSA_Unload(asyncMentatLoop.wsa); GFX_Screen_SetActive(4); GUI_DrawSprite(4, g_sprites[397 + g_playerHouseID * 15], g_shoulderLeft, g_shoulderTop, 0, 0); GUI_Mouse_Hide_InWidget(g_curWidgetIndex); GUI_Screen_Copy(g_curWidgetXBase, g_curWidgetYBase, g_curWidgetXBase, g_curWidgetYBase, g_curWidgetWidth, g_curWidgetHeight, 4, 0); GUI_Mouse_Show_InWidget(); Widget_SetCurrentWidget(asyncMentatLoop.old07AE); GFX_Screen_SetActive(asyncMentatLoop.oldScreenID); Input_History_Clear(); Async_StorageSet_uint16(asyncMentatLoop.result); }
/** * Draw sprites and handle mouse in a mentat screen. * @param speakingMode If \c 1, the mentat is speaking. */ void GUI_Mentat_Animation(uint16 speakingMode) { static uint32 movingEyesTimer = 0; /* Timer when to change the eyes sprite. */ static uint16 movingEyesSprite = 0; /* Index in _mentatSprites of the displayed moving eyes. */ static uint16 movingEyesNextSprite = 0; /* If not 0, it decides the movingEyesNextSprite */ static uint32 movingMouthTimer = 0; static uint16 movingMouthSprite = 0; static uint32 movingOtherTimer = 0; static int16 otherSprite = 0; bool partNeedsRedraw; uint16 i; if (movingOtherTimer < g_timerGUI && !g_disableOtherMovement) { if (movingOtherTimer != 0) { uint8 *sprite; if (s_mentatSprites[2][1 + abs(otherSprite)] == NULL) { otherSprite = 1 - otherSprite; } else { otherSprite++; } sprite = s_mentatSprites[2][abs(otherSprite)]; GUI_Mouse_Hide_InRegion(s_otherLeft, s_otherTop, s_otherLeft + Sprite_GetWidth(sprite), s_otherTop + Sprite_GetHeight(sprite)); GUI_DrawSprite(SCREEN_0, sprite, s_otherLeft, s_otherTop, 0, 0); GUI_Mouse_Show_InRegion(); } switch (g_playerHouseID) { case HOUSE_HARKONNEN: movingOtherTimer = g_timerGUI + 300 * 60; break; case HOUSE_ATREIDES: movingOtherTimer = g_timerGUI + 60 * Tools_RandomLCG_Range(1,3); break; case HOUSE_ORDOS: if (otherSprite != 0) { movingOtherTimer = g_timerGUI + 6; } else { movingOtherTimer = g_timerGUI + 60 * Tools_RandomLCG_Range(10, 19); } break; default: break; } } if (speakingMode == 1) { if (movingMouthTimer < g_timerGUI) { uint8 *sprite; movingMouthSprite = Tools_RandomLCG_Range(0, 4); sprite = s_mentatSprites[1][movingMouthSprite]; GUI_Mouse_Hide_InRegion(s_mouthLeft, s_mouthTop, s_mouthLeft + Sprite_GetWidth(sprite), s_mouthTop + Sprite_GetHeight(sprite)); GUI_DrawSprite(SCREEN_0, sprite, s_mouthLeft, s_mouthTop, 0, 0); GUI_Mouse_Show_InRegion(); switch (movingMouthSprite) { case 0: movingMouthTimer = g_timerGUI + Tools_RandomLCG_Range(7, 30); break; case 1: case 2: case 3: movingMouthTimer = g_timerGUI + Tools_RandomLCG_Range(6, 10); break; case 4: movingMouthTimer = g_timerGUI + Tools_RandomLCG_Range(5, 6); break; default: break; } } } else { partNeedsRedraw = false; if (Input_Test(0x41) == 0 && Input_Test(0x42) == 0) { if (movingMouthSprite != 0) { movingMouthSprite = 0; movingMouthTimer = 0; partNeedsRedraw = true; } } else if (Mouse_InsideRegion(s_mouthLeft, s_mouthTop, s_mouthRight, s_mouthBottom) != 0) { if (movingMouthTimer != 0xFFFFFFFF) { movingMouthTimer = 0xFFFFFFFF; movingMouthSprite = Tools_RandomLCG_Range(1, 4); partNeedsRedraw = true; } } else { if (movingMouthSprite != 0) { movingMouthSprite = 0; movingMouthTimer = 0; partNeedsRedraw = true; } } if (partNeedsRedraw) { uint8 *sprite; sprite = s_mentatSprites[1][movingMouthSprite]; GUI_Mouse_Hide_InRegion(s_mouthLeft, s_mouthTop, s_mouthLeft + Sprite_GetWidth(sprite), s_mouthTop + Sprite_GetHeight(sprite)); GUI_DrawSprite(SCREEN_0, sprite, s_mouthLeft, s_mouthTop, 0, 0); GUI_Mouse_Show_InRegion(); } } partNeedsRedraw = false; if (Input_Test(0x41) != 0 || Input_Test(0x42) != 0) { if (Mouse_InsideRegion(s_eyesLeft, s_eyesTop, s_eyesRight, s_eyesBottom) != 0) { if (movingEyesSprite != 0x4) { partNeedsRedraw = true; movingEyesSprite = (movingEyesSprite == 3) ? 4 : 3; movingEyesNextSprite = 0; movingEyesTimer = 0; } if (partNeedsRedraw) { uint8 *sprite; sprite = s_mentatSprites[0][movingEyesSprite]; GUI_Mouse_Hide_InRegion(s_eyesLeft, s_eyesTop, s_eyesLeft + Sprite_GetWidth(sprite), s_eyesTop + Sprite_GetHeight(sprite)); GUI_DrawSprite(SCREEN_0, sprite, s_eyesLeft, s_eyesTop, 0, 0); GUI_Mouse_Show_InRegion(); } return; } } if (Mouse_InsideRegion((int16)s_eyesLeft - 16, (int16)s_eyesTop - 8, s_eyesRight + 16, s_eyesBottom + 24) != 0) { if (Mouse_InsideRegion((int16)s_eyesLeft - 8, s_eyesBottom, s_eyesRight + 8, SCREEN_HEIGHT - 1) != 0) { i = 3; } else { if (Mouse_InsideRegion(s_eyesRight, (int16)s_eyesTop - 8, s_eyesRight + 16, s_eyesBottom + 8) != 0) { i = 2; } else { i = (Mouse_InsideRegion((int16)s_eyesLeft - 16, (int16)s_eyesTop - 8, s_eyesLeft, s_eyesBottom + 8) == 0) ? 0 : 1; } } if (i != movingEyesSprite) { partNeedsRedraw = true; movingEyesSprite = i; movingEyesNextSprite = 0; movingEyesTimer = g_timerGUI; } } else { if (movingEyesTimer >= g_timerGUI) return; partNeedsRedraw = true; if (movingEyesNextSprite != 0) { movingEyesSprite = movingEyesNextSprite; movingEyesNextSprite = 0; if (movingEyesSprite != 4) { movingEyesTimer = g_timerGUI + Tools_RandomLCG_Range(20, 180); } else { movingEyesTimer = g_timerGUI + Tools_RandomLCG_Range(12, 30); } } else { i = 0; switch (speakingMode) { case 0: i = Tools_RandomLCG_Range(0, 7); if (i > 5) { i = 1; } else { if (i == 5) { i = 4; } } break; case 1: if (movingEyesSprite != ((!g_interrogation) ? 0 : 3)) { i = 0; } else { i = Tools_RandomLCG_Range(0, 17); if (i > 9) { i = 0; } else { if (i >= 5) { i = 4; } } } break; default: i = Tools_RandomLCG_Range(0, 15); if (i > 10) { i = 2; } else { if (i >= 5) { i = 4; } } break; } if ((i == 2 && movingEyesSprite == 1) || (i == 1 && movingEyesSprite == 2)) { movingEyesNextSprite = i; movingEyesSprite = 0; movingEyesTimer = g_timerGUI + Tools_RandomLCG_Range(1, 5); } else { if (i != movingEyesSprite && (i == 4 || movingEyesSprite == 4)) { movingEyesNextSprite = i; movingEyesSprite = 3; movingEyesTimer = g_timerGUI; } else { movingEyesSprite = i; if (i != 4) { movingEyesTimer = g_timerGUI + Tools_RandomLCG_Range(15, 180); } else { movingEyesTimer = g_timerGUI + Tools_RandomLCG_Range(6, 60); } } } if (g_interrogation && movingEyesSprite == 0) movingEyesSprite = 3; } } if (partNeedsRedraw) { uint8 *sprite; sprite = s_mentatSprites[0][movingEyesSprite]; GUI_Mouse_Hide_InRegion(s_eyesLeft, s_eyesTop, s_eyesLeft + Sprite_GetWidth(sprite), s_eyesTop + Sprite_GetHeight(sprite)); GUI_DrawSprite(SCREEN_0, sprite, s_eyesLeft, s_eyesTop, 0, 0); GUI_Mouse_Show_InRegion(); } }
static void GUI_Mentat_Draw(bool force) { static uint16 displayedHelpSubject = 0; Screen oldScreenID; Widget *line; Widget *w = g_widgetMentatTail; uint8 *helpSubjects = s_helpSubjects; uint16 i; if (!force && s_topHelpList == displayedHelpSubject) return; displayedHelpSubject = s_topHelpList; oldScreenID = GFX_Screen_SetActive(SCREEN_1); Widget_SetAndPaintCurrentWidget(8); GUI_DrawSprite(SCREEN_1, g_sprites[397 + g_playerHouseID * 15], g_shoulderLeft, g_shoulderTop, 0, 0); GUI_DrawText_Wrapper(String_Get_ByIndex(STR_SELECT_SUBJECT), (g_curWidgetXBase << 3) + 16, g_curWidgetYBase + 2, 12, 0, 0x12); GUI_DrawText_Wrapper(NULL, 0, 0, 0, 0, 0x11); line = GUI_Widget_Get_ByIndex(w, 3); for (i = 0; i < 11; i++) { line->drawParameterDown.text = (char *)helpSubjects + 7; line->drawParameterSelected.text = (char *)helpSubjects + 7; line->drawParameterNormal.text = (char *)helpSubjects + 7; if (helpSubjects[6] == '0') { line->offsetX = 16; line->fgColourSelected = 11; line->fgColourDown = 11; line->fgColourNormal = 11; line->stringID = 0x30; } else { uint8 colour = (i == s_selectedHelpSubject) ? 8 : 15; line->offsetX = 24; line->fgColourSelected = colour; line->fgColourDown = colour; line->fgColourNormal = colour; line->stringID = 0x31; } GUI_Widget_MakeNormal(line, false); GUI_Widget_Draw(line); line = GUI_Widget_GetNext(line); helpSubjects = String_NextString(helpSubjects); } GUI_Widget_Scrollbar_Init(GUI_Widget_Get_ByIndex(w, 15), s_numberHelpSubjects, 11, s_topHelpList); GUI_Widget_Draw(GUI_Widget_Get_ByIndex(w, 16)); GUI_Widget_Draw(GUI_Widget_Get_ByIndex(w, 17)); GUI_Mouse_Hide_Safe(); GUI_Screen_Copy(g_curWidgetXBase, g_curWidgetYBase, g_curWidgetXBase, g_curWidgetYBase, g_curWidgetWidth, g_curWidgetHeight, SCREEN_1, SCREEN_0); GUI_Mouse_Show_Safe(); GFX_Screen_SetActive(oldScreenID); }
uint16 GUI_Mentat_Loop(const char *wsaFilename, char *pictureDetails, char *text, bool arg12, Widget *w) { Screen oldScreenID; uint16 old07AE; void *wsa; uint16 descLines; bool dirty; bool done; bool textDone; uint16 frame; uint32 descTick; uint16 mentatSpeakingMode; uint16 result; uint32 textTick; uint32 textDelay; uint16 lines; uint16 textLines; uint16 step; dirty = false; textTick = 0; textDelay = 0; old07AE = Widget_SetCurrentWidget(8); oldScreenID = GFX_Screen_SetActive(SCREEN_2); wsa = NULL; if (wsaFilename != NULL) { wsa = WSA_LoadFile(wsaFilename, GFX_Screen_Get_ByIndex(SCREEN_1), GFX_Screen_GetSize_ByIndex(SCREEN_1), false); } step = 0; if (wsa == NULL) { Widget_PaintCurrentWidget(); step = 1; } GUI_DrawText_Wrapper(NULL, 0, 0, 0, 0, 0x31); descLines = GUI_SplitText(pictureDetails, (g_curWidgetWidth << 3) + 10, '\0'); GUI_DrawText_Wrapper(NULL, 0, 0, 0, 0, 0x32); textLines = GUI_Mentat_SplitText(text, 304); mentatSpeakingMode = 2; lines = 0; frame = 0; g_timerTimeout = 0; descTick = g_timerGUI + 30; Input_History_Clear(); textDone = false; result = 0; for (done = false; !done; sleepIdle()) { uint16 key; GFX_Screen_SetActive(SCREEN_0); key = GUI_Widget_HandleEvents(w); GUI_PaletteAnimate(); if (key != 0) { if ((key & 0x800) == 0) { if (w != NULL) { if ((key & 0x8000) != 0 && result == 0) result = key; } else { if (textDone) result = key; } } else { key = 0; } } switch (step) { case 0: if (key == 0) break; step = 1; /* FALL-THROUGH */ case 1: if (key != 0) { if (result != 0) { step = 5; break; } lines = descLines; dirty = true; } else { if (g_timerGUI > descTick) { descTick = g_timerGUI + 15; lines++; dirty = true; } } if (lines < descLines && lines <= 12) break; step = (text != NULL) ? 2 : 4; lines = descLines; break; case 2: GUI_Mouse_Hide_InRegion(0, 0, SCREEN_WIDTH, 40); GUI_Screen_Copy(0, 0, 0, 160, SCREEN_WIDTH / 8, 40, SCREEN_0, SCREEN_2); GUI_Mouse_Show_InRegion(); step = 3; key = 1; /* FALL-THROUGH */ case 3: if (mentatSpeakingMode == 2 && textTick < g_timerGUI) key = 1; if ((key != 0 && textDone) || result != 0) { GUI_Mouse_Hide_InRegion(0, 0, SCREEN_WIDTH, 40); GUI_Screen_Copy(0, 160, 0, 0, SCREEN_WIDTH / 8, 40, SCREEN_2, SCREEN_0); GUI_Mouse_Show_InRegion(); step = 4; mentatSpeakingMode = 0; break; } if (key != 0) { GUI_Screen_Copy(0, 160, 0, 0, SCREEN_WIDTH / 8, 40, SCREEN_2, SCREEN_2); if (textLines-- != 0) { GFX_Screen_SetActive(SCREEN_2); GUI_DrawText_Wrapper(text, 4, 1, g_curWidgetFGColourBlink, 0, 0x32); mentatSpeakingMode = 1; textDelay = (uint32)strlen(text) * 4; textTick = g_timerGUI + textDelay; if (textLines != 0) { while (*text++ != '\0') {} } else { textDone = true; } GFX_Screen_SetActive(SCREEN_0); } GUI_Mouse_Hide_InRegion(0, 0, SCREEN_WIDTH, 40); GUI_Screen_Copy(0, 0, 0, 0, SCREEN_WIDTH / 8, 40, SCREEN_2, SCREEN_0); GUI_Mouse_Show_InRegion(); break; } if (mentatSpeakingMode == 0 || textTick > g_timerGUI) break; mentatSpeakingMode = 2; textTick += textDelay + textDelay / 2; break; case 4: if (result != 0 || w == NULL) step = 5; break; case 5: dirty = true; done = true; break; default: break; } GUI_Mentat_Animation(mentatSpeakingMode); if (wsa != NULL && g_timerTimeout == 0) { g_timerTimeout = 7; do { if (step == 0 && frame > 4) step = 1; if (!WSA_DisplayFrame(wsa, frame++, g_curWidgetXBase << 3, g_curWidgetYBase, SCREEN_2)) { if (step == 0) step = 1; if (arg12 != 0) { frame = 0; } else { WSA_Unload(wsa); wsa = NULL; } } } while (frame == 0); dirty = true; } if (!dirty) continue; GUI_Mentat_DrawInfo(pictureDetails, (g_curWidgetXBase << 3) + 5, g_curWidgetYBase + 3, 8, 0, lines, 0x31); GUI_DrawSprite(SCREEN_2, g_sprites[397 + g_playerHouseID * 15], g_shoulderLeft, g_shoulderTop, 0, 0); GUI_Mouse_Hide_InWidget(g_curWidgetIndex); GUI_Screen_Copy(g_curWidgetXBase, g_curWidgetYBase, g_curWidgetXBase, g_curWidgetYBase, g_curWidgetWidth, g_curWidgetHeight, SCREEN_2, SCREEN_0); GUI_Mouse_Show_InWidget(); dirty = false; } if (wsa != NULL) WSA_Unload(wsa); GFX_Screen_SetActive(SCREEN_2); GUI_DrawSprite(SCREEN_2, g_sprites[397 + g_playerHouseID * 15], g_shoulderLeft, g_shoulderTop, 0, 0); GUI_Mouse_Hide_InWidget(g_curWidgetIndex); GUI_Screen_Copy(g_curWidgetXBase, g_curWidgetYBase, g_curWidgetXBase, g_curWidgetYBase, g_curWidgetWidth, g_curWidgetHeight, SCREEN_2, SCREEN_0); GUI_Mouse_Show_InWidget(); Widget_SetCurrentWidget(old07AE); GFX_Screen_SetActive(oldScreenID); Input_History_Clear(); return result; }
void async_GUI_Mentat_Loop() { uint16 key; GFX_Screen_SetActive(0); key = GUI_Widget_HandleEvents(asyncMentatLoop.w); GUI_PaletteAnimate(); if (key != 0) { if ((key & 0x800) == 0) { if (asyncMentatLoop.w != NULL) { if ((key & 0x8000) != 0 && asyncMentatLoop.result == 0) asyncMentatLoop.result = key; } else { if (asyncMentatLoop.textDone) asyncMentatLoop.result = key; } } else { key = 0; } } switch (asyncMentatLoop.step) { case 0: if (key == 0) break; asyncMentatLoop.step = 1; /* FALL-THROUGH */ case 1: if (key != 0) { if (asyncMentatLoop.result != 0) { asyncMentatLoop.step = 5; break; } asyncMentatLoop.lines = asyncMentatLoop.descLines; asyncMentatLoop.dirty = true; } else { if (g_timerGUI > asyncMentatLoop.descTick) { asyncMentatLoop.descTick = g_timerGUI + 15; asyncMentatLoop.lines++; asyncMentatLoop.dirty = true; } } if (asyncMentatLoop.lines < asyncMentatLoop.descLines && asyncMentatLoop.lines <= 12) break; asyncMentatLoop.step = (asyncMentatLoop.text != NULL) ? 2 : 4; asyncMentatLoop.lines = asyncMentatLoop.descLines; break; case 2: GUI_Mouse_Hide_InRegion(0, 0, SCREEN_WIDTH, 40); GUI_Screen_Copy(0, 0, 0, 160, SCREEN_WIDTH / 8, 40, 0, 4); GUI_Mouse_Show_InRegion(); asyncMentatLoop.step = 3; key = 1; /* FALL-THROUGH */ case 3: if (asyncMentatLoop.mentatSpeakingMode == 2 && asyncMentatLoop.textTick < g_timerGUI) key = 1; if ((key != 0 && asyncMentatLoop.textDone) || asyncMentatLoop.result != 0) { GUI_Mouse_Hide_InRegion(0, 0, SCREEN_WIDTH, 40); GUI_Screen_Copy(0, 160, 0, 0, SCREEN_WIDTH / 8, 40, 4, 0); GUI_Mouse_Show_InRegion(); asyncMentatLoop.step = 4; asyncMentatLoop.mentatSpeakingMode = 0; break; } if (key != 0) { GUI_Screen_Copy(0, 160, 0, 0, SCREEN_WIDTH / 8, 40, 4, 4); if (asyncMentatLoop.textLines-- != 0) { GFX_Screen_SetActive(4); GUI_DrawText_Wrapper(asyncMentatLoop.text, 4, 1, g_curWidgetFGColourBlink, 0, 0x32); asyncMentatLoop.mentatSpeakingMode = 1; asyncMentatLoop.textDelay = strlen(asyncMentatLoop.text) * 4; asyncMentatLoop.textTick = g_timerGUI + asyncMentatLoop.textDelay; if (asyncMentatLoop.textLines != 0) { while (*asyncMentatLoop.text++ != '\0') {} } else { asyncMentatLoop.textDone = true; } GFX_Screen_SetActive(0); } GUI_Mouse_Hide_InRegion(0, 0, SCREEN_WIDTH, 40); GUI_Screen_Copy(0, 0, 0, 0, SCREEN_WIDTH / 8, 40, 4, 0); GUI_Mouse_Show_InRegion(); break; } if (asyncMentatLoop.mentatSpeakingMode == 0 || asyncMentatLoop.textTick > g_timerGUI) break; asyncMentatLoop.mentatSpeakingMode = 2; asyncMentatLoop.textTick += asyncMentatLoop.textDelay + asyncMentatLoop.textDelay / 2; break; case 4: if (asyncMentatLoop.result != 0 || asyncMentatLoop.w == NULL) asyncMentatLoop.step = 5; break; case 5: asyncMentatLoop.dirty = true; asyncMentatLoop.done = true; break; default: break; } GUI_Mentat_Animation(asyncMentatLoop.mentatSpeakingMode); if (asyncMentatLoop.wsa != NULL && g_timerTimeout == 0) { g_timerTimeout = 7; do { if (asyncMentatLoop.step == 0 && asyncMentatLoop.frame > 4) asyncMentatLoop.step = 1; if (!WSA_DisplayFrame(asyncMentatLoop.wsa, asyncMentatLoop.frame++, g_curWidgetXBase << 3, g_curWidgetYBase, 4)) { if (asyncMentatLoop.step == 0) asyncMentatLoop.step = 1; if (asyncMentatLoop.arg12 != 0) { asyncMentatLoop.frame = 0; } else { WSA_Unload(asyncMentatLoop.wsa); asyncMentatLoop.wsa = NULL; } } } while (asyncMentatLoop.frame == 0); asyncMentatLoop.dirty = true; } if (!asyncMentatLoop.dirty) { sleepIdle(); return; } GUI_Mentat_DrawInfo(asyncMentatLoop.pictureDetails, (g_curWidgetXBase << 3) + 5, g_curWidgetYBase + 3, 8, 0, asyncMentatLoop.lines, 0x31); GUI_DrawSprite(4, g_sprites[397 + g_playerHouseID * 15], g_shoulderLeft, g_shoulderTop, 0, 0); GUI_Mouse_Hide_InWidget(g_curWidgetIndex); GUI_Screen_Copy(g_curWidgetXBase, g_curWidgetYBase, g_curWidgetXBase, g_curWidgetYBase, g_curWidgetWidth, g_curWidgetHeight, 4, 0); GUI_Mouse_Show_InWidget(); asyncMentatLoop.dirty = false; sleepIdle(); }
/** * Ask the security question to the user. Give him 3 times. If he fails, * return false, otherwise true. * @return True if and only if the user answered one of the three questions * correct. */ bool GUI_Security_Show(void) { const char *wsaHouseFilename; uint16 questionsCount; uint16 oldCurrentWidget; Screen oldScreenID; uint16 i; bool valid; g_disableOtherMovement = true; g_interrogation = true; wsaHouseFilename = House_GetWSAHouseFilename(g_playerHouseID); if (wsaHouseFilename == NULL) return true; GUI_SetPaletteAnimated(g_palette2, 15); GUI_Mentat_Display(wsaHouseFilename, g_playerHouseID); GUI_Mouse_Hide_Safe(); GUI_Screen_Copy(0, 0, 0, 0, SCREEN_WIDTH / 8, SCREEN_HEIGHT, SCREEN_1, SCREEN_0); GUI_Mouse_Show_Safe(); GUI_SetPaletteAnimated(g_palette1, 15); strncpy(g_readBuffer, String_Get_ByIndex(STR_SECURITY_TEXT_HARKONNEN + g_playerHouseID * 3), g_readBufferSize); GUI_Mentat_Loop(wsaHouseFilename, NULL, g_readBuffer, true, NULL); questionsCount = atoi(String_Get_ByIndex(STR_SECURITY_COUNT)); oldCurrentWidget = Widget_SetCurrentWidget(8); oldScreenID = GFX_Screen_SetActive(SCREEN_2); for (i = 0, valid = false; i < 3 && !valid; i++) { void *wsa; uint16 questionIndex; uint32 tickWaitTill; char buffer[81]; questionIndex = Tools_RandomLCG_Range(0, questionsCount - 1) * 3 + STR_SECURITY_QUESTIONS; Widget_SetCurrentWidget(8); wsa = WSA_LoadFile(String_Get_ByIndex(questionIndex + 1), GFX_Screen_Get_ByIndex(SCREEN_1), GFX_Screen_GetSize_ByIndex(SCREEN_1), false); WSA_DisplayFrame(wsa, 0, g_curWidgetXBase << 3, g_curWidgetYBase, SCREEN_2); WSA_Unload(wsa); GUI_DrawSprite(SCREEN_2, g_sprites[397 + g_playerHouseID * 15], g_shoulderLeft, g_shoulderTop, 0, 0); GUI_Mouse_Hide_InWidget(g_curWidgetIndex); GUI_Screen_Copy(g_curWidgetXBase, g_curWidgetYBase, g_curWidgetXBase, g_curWidgetYBase, g_curWidgetWidth, g_curWidgetHeight, SCREEN_2, SCREEN_0); GUI_Mouse_Show_InWidget(); strncpy(g_readBuffer, String_Get_ByIndex(questionIndex), g_readBufferSize); GUI_Security_DrawText(g_readBuffer); g_interrogationTimer = g_timerGUI + (uint32)strlen(g_readBuffer) * 4; Widget_SetCurrentWidget(9); GUI_Mouse_Hide_Safe(); GUI_Screen_Copy(g_curWidgetXBase - 1, g_curWidgetYBase - 8, 0, 0, g_curWidgetWidth + 2, g_curWidgetHeight + 16, SCREEN_0, SCREEN_2); GUI_Mouse_Show_Safe(); GFX_Screen_SetActive(SCREEN_0); GUI_Mouse_Hide_Safe(); GUI_DrawBorder((g_curWidgetXBase << 3) - 6, g_curWidgetYBase - 6, (g_curWidgetWidth << 3) + 12, g_curWidgetHeight + 12, 1, true); GUI_DrawBorder((g_curWidgetXBase << 3) - 2, g_curWidgetYBase - 2, (g_curWidgetWidth << 3) + 4, g_curWidgetHeight + 4, 2, false); GUI_Mouse_Show_Safe(); Input_History_Clear(); buffer[0] = 0; GUI_DrawText_Wrapper(NULL, 0, 0, 0, 0, 0x22); GUI_EditBox(buffer, sizeof(buffer) - 1, 9, NULL, &GUI_Mentat_Tick, 0); GUI_Security_UndrawText(); GUI_Mouse_Hide_Safe(); GUI_Screen_Copy(0, 0, g_curWidgetXBase - 1, g_curWidgetYBase - 8, g_curWidgetWidth + 2, g_curWidgetHeight + 16, SCREEN_2, SCREEN_0); GUI_Mouse_Show_Safe(); GUI_Security_NormaliseText(buffer); strncpy(g_readBuffer, String_Get_ByIndex(questionIndex + 2), g_readBufferSize); GUI_Security_NormaliseText(g_readBuffer); if (strcasecmp(g_readBuffer, buffer) != 0) { strncpy(g_readBuffer, String_Get_ByIndex(STR_SECURITY_WRONG_HARKONNEN + g_playerHouseID * 3), g_readBufferSize); } else { strncpy(g_readBuffer, String_Get_ByIndex(STR_SECURITY_CORRECT_HARKONNEN + g_playerHouseID * 3), g_readBufferSize); valid = true; } GUI_Security_DrawText(g_readBuffer); tickWaitTill = g_timerGUI + (uint32)strlen(g_readBuffer) * 4; Input_History_Clear(); /* ENHANCEMENT -- In Dune2, the + 120 is on the other side, causing the 'You are wrong! / Well done.' screen to appear very short (close to invisible, so to say) */ while (g_timerGUI + (g_dune2_enhanced ? 0 : 120) < tickWaitTill + (g_dune2_enhanced ? 120 : 0)) { if (Input_Keyboard_NextKey() != 0) break; if (g_timerGUI < tickWaitTill) { GUI_Mentat_Animation(1); } else { GUI_Mentat_Animation(0); } } GUI_Security_UndrawText(); } Widget_SetCurrentWidget(oldCurrentWidget); GFX_Screen_SetActive(oldScreenID); Input_History_Clear(); Load_Palette_Mercenaries(); g_disableOtherMovement = false; g_interrogation = false; return valid; }
/** * Draw a single tile on the screen. * * @param packed The tile to draw. */ void GUI_Widget_Viewport_DrawTile(uint16 packed) { uint16 x; uint16 y; uint16 colour; uint16 spriteID; Tile *t; uint16 mapScale; colour = 12; spriteID = 0xFFFF; if (Tile_IsOutOfMap(packed) || !Map_IsValidPosition(packed)) return; x = Tile_GetPackedX(packed); y = Tile_GetPackedY(packed); mapScale = g_scenario.mapScale + 1; if (mapScale == 0 || BitArray_Test(g_displayedMinimap, packed)) return; t = &g_map[packed]; if ((t->isUnveiled && g_playerHouse->flags.radarActivated) || g_debugScenario) { uint16 type = Map_GetLandscapeType(packed); Unit *u; if (mapScale > 1) { spriteID = g_scenario.mapScale + g_table_landscapeInfo[type].spriteID - 1; } else { colour = g_table_landscapeInfo[type].radarColour; } if (g_table_landscapeInfo[type].radarColour == 0xFFFF) { if (mapScale > 1) { spriteID = mapScale + t->houseID * 2 + 29; } else { colour = g_table_houseInfo[t->houseID].minimapColor; } } u = Unit_Get_ByPackedTile(packed); if (u != NULL) { if (mapScale > 1) { if (u->o.type == UNIT_SANDWORM) { spriteID = mapScale + 53; } else { spriteID = mapScale + Unit_GetHouseID(u) * 2 + 29; } } else { if (u->o.type == UNIT_SANDWORM) { colour = 255; } else { colour = g_table_houseInfo[Unit_GetHouseID(u)].minimapColor; } } } } else { Structure *s; s = Structure_Get_ByPackedTile(packed); if (s != NULL && s->o.houseID == g_playerHouseID) { if (mapScale > 1) { spriteID = mapScale + s->o.houseID * 2 + 29; } else { colour = g_table_houseInfo[s->o.houseID].minimapColor; } } else { if (mapScale > 1) { spriteID = g_scenario.mapScale + g_table_landscapeInfo[LST_ENTIRELY_MOUNTAIN].spriteID - 1; } else { colour = 12; } } } x -= g_mapInfos[g_scenario.mapScale].minX; y -= g_mapInfos[g_scenario.mapScale].minY; if (spriteID != 0xFFFF) { x *= g_scenario.mapScale + 1; y *= g_scenario.mapScale + 1; GUI_DrawSprite(g_screenActiveID, g_sprites[spriteID], x, y, 3, 0x4000); } else { GFX_PutPixel(x + 256, y + 136, colour & 0xFF); } }
/** * Redraw parts of the viewport that require redrawing. * * @param forceRedraw If true, dirty flags are ignored, and everything is drawn. * @param arg08 ?? * @param drawToMainScreen True if and only if we are drawing to the main screen and not some buffer screen. */ void GUI_Widget_Viewport_Draw(bool forceRedraw, bool arg08, bool drawToMainScreen) { static const uint16 values_32A4[8][2] = { {0, 0}, {1, 0}, {2, 0}, {3, 0}, {4, 0}, {3, 1}, {2, 1}, {1, 1} }; uint16 x; uint16 y; uint16 i; uint16 curPos; bool updateDisplay; Screen oldScreenID; uint16 oldValue_07AE_0000; int16 minX[10]; int16 maxX[10]; PoolFindStruct find; updateDisplay = forceRedraw; memset(minX, 0xF, sizeof(minX)); memset(maxX, 0, sizeof(minX)); oldScreenID = GFX_Screen_SetActive(SCREEN_1); oldValue_07AE_0000 = Widget_SetCurrentWidget(2); if (g_dirtyViewportCount != 0 || forceRedraw) { for (y = 0; y < 10; y++) { uint16 top = (y << 4) + 0x28; for (x = 0; x < (drawToMainScreen ? 15 : 16); x++) { Tile *t; uint16 left; curPos = g_viewportPosition + Tile_PackXY(x, y); if (x < 15 && !forceRedraw && BitArray_Test(g_dirtyViewport, curPos)) { if (maxX[y] < x) maxX[y] = x; if (minX[y] > x) minX[y] = x; updateDisplay = true; } if (!BitArray_Test(g_dirtyMinimap, curPos) && !forceRedraw) continue; BitArray_Set(g_dirtyViewport, curPos); if (x < 15) { updateDisplay = true; if (maxX[y] < x) maxX[y] = x; if (minX[y] > x) minX[y] = x; } t = &g_map[curPos]; left = x << 4; if (!g_debugScenario && g_veiledSpriteID == t->overlaySpriteID) { GUI_DrawFilledRectangle(left, top, left + 15, top + 15, 12); continue; } GFX_DrawSprite(t->groundSpriteID, left, top, t->houseID); if (t->overlaySpriteID == 0 || g_debugScenario) continue; GFX_DrawSprite(t->overlaySpriteID, left, top, t->houseID); } } g_dirtyViewportCount = 0; } find.type = UNIT_SANDWORM; find.index = 0xFFFF; find.houseID = HOUSE_INVALID; while (true) { Unit *u; uint8 *sprite; u = Unit_Find(&find); if (u == NULL) break; if (!u->o.flags.s.isDirty && !forceRedraw) continue; u->o.flags.s.isDirty = false; if (!g_map[Tile_PackTile(u->o.position)].isUnveiled && !g_debugScenario) continue; sprite = GUI_Widget_Viewport_Draw_GetSprite(g_table_unitInfo[u->o.type].groundSpriteID, Unit_GetHouseID(u)); s_spriteFlags = 0x200; if (Map_IsPositionInViewport(u->o.position, &x, &y)) GUI_DrawSprite(g_screenActiveID, sprite, x, y, 2, s_spriteFlags | 0xC000); if (Map_IsPositionInViewport(u->targetLast, &x, &y)) GUI_DrawSprite(g_screenActiveID, sprite, x, y, 2, s_spriteFlags | 0xC000); if (Map_IsPositionInViewport(u->targetPreLast, &x, &y)) GUI_DrawSprite(g_screenActiveID, sprite, x, y, 2, s_spriteFlags | 0xC000); if (u != g_unitSelected) continue; if (!Map_IsPositionInViewport(u->o.position, &x, &y)) continue; GUI_DrawSprite(g_screenActiveID, g_sprites[6], x, y, 2, 0xC000); } if (g_unitSelected == NULL && (g_var_3A08 != 0 || arg08) && (Structure_Get_ByPackedTile(g_selectionRectanglePosition) != NULL || g_selectionType == SELECTIONTYPE_PLACE || g_debugScenario)) { uint16 x1 = (Tile_GetPackedX(g_selectionRectanglePosition) - Tile_GetPackedX(g_minimapPosition)) << 4; uint16 y1 = ((Tile_GetPackedY(g_selectionRectanglePosition) - Tile_GetPackedY(g_minimapPosition)) << 4) + 0x28; uint16 x2 = x1 + (g_selectionWidth << 4) - 1; uint16 y2 = y1 + (g_selectionHeight << 4) - 1; GUI_SetClippingArea(0, 40, 239, SCREEN_HEIGHT - 1); GUI_DrawWiredRectangle(x1, y1, x2, y2, 0xFF); if (g_selectionState == 0 && g_selectionType == SELECTIONTYPE_PLACE) { GUI_DrawLine(x1, y1, x2, y2, 0xFF); GUI_DrawLine(x2, y1, x1, y2, 0xFF); } GUI_SetClippingArea(0, 0, SCREEN_WIDTH - 1, SCREEN_HEIGHT - 1); g_var_3A08 = 0; } if (g_dirtyUnitCount != 0 || forceRedraw || updateDisplay) { find.type = 0xFFFF; find.index = 0xFFFF; find.houseID = HOUSE_INVALID; while (true) { Unit *u; UnitInfo *ui; uint16 packed; uint8 orientation; uint16 index; u = Unit_Find(&find); if (u == NULL) break; if (u->o.index < 20 || u->o.index > 101) continue; packed = Tile_PackTile(u->o.position); if ((!u->o.flags.s.isDirty || u->o.flags.s.isNotOnMap) && !forceRedraw && !BitArray_Test(g_dirtyViewport, packed)) continue; u->o.flags.s.isDirty = false; if (!g_map[packed].isUnveiled && !g_debugScenario) continue; ui = &g_table_unitInfo[u->o.type]; if (!Map_IsPositionInViewport(u->o.position, &x, &y)) continue; x += g_table_tilediff[0][u->wobbleIndex].x; y += g_table_tilediff[0][u->wobbleIndex].y; orientation = Orientation_Orientation256ToOrientation8(u->orientation[0].current); if (u->spriteOffset >= 0 || ui->destroyedSpriteID == 0) { static const uint16 values_32C4[8][2] = { {0, 0}, {1, 0}, {1, 0}, {1, 0}, {2, 0}, {1, 1}, {1, 1}, {1, 1} }; index = ui->groundSpriteID; switch (ui->displayMode) { case DISPLAYMODE_UNIT: case DISPLAYMODE_ROCKET: if (ui->movementType == MOVEMENT_SLITHER) break; index += values_32A4[orientation][0]; s_spriteFlags = values_32A4[orientation][1]; break; case DISPLAYMODE_INFANTRY_3_FRAMES: { static const uint16 values_334A[4] = {0, 1, 0, 2}; index += values_32C4[orientation][0] * 3; index += values_334A[u->spriteOffset & 3]; s_spriteFlags = values_32C4[orientation][1]; } break; case DISPLAYMODE_INFANTRY_4_FRAMES: index += values_32C4[orientation][0] * 4; index += u->spriteOffset & 3; s_spriteFlags = values_32C4[orientation][1]; break; default: s_spriteFlags = 0; break; } } else { index = ui->destroyedSpriteID - u->spriteOffset - 1; s_spriteFlags = 0; } if (u->o.type != UNIT_SANDWORM && u->o.flags.s.isHighlighted) s_spriteFlags |= 0x100; if (ui->o.flags.blurTile) s_spriteFlags |= 0x200; GUI_DrawSprite(g_screenActiveID, GUI_Widget_Viewport_Draw_GetSprite(index, (u->deviated != 0) ? u->deviatedHouse : Unit_GetHouseID(u)), x, y, 2, s_spriteFlags | 0xE000, s_paletteHouse, g_paletteMapping2, 1); if (u->o.type == UNIT_HARVESTER && u->actionID == ACTION_HARVEST && u->spriteOffset >= 0 && (u->actionID == ACTION_HARVEST || u->actionID == ACTION_MOVE)) { uint16 type = Map_GetLandscapeType(packed); if (type == LST_SPICE || type == LST_THICK_SPICE) { static const int16 values_334E[8][2] = { {0, 7}, {-7, 6}, {-14, 1}, {-9, -6}, {0, -9}, { 9, -6}, { 14, 1}, { 7, 6} }; GUI_DrawSprite(g_screenActiveID, GUI_Widget_Viewport_Draw_GetSprite((u->spriteOffset % 3) + 0xDF + (values_32A4[orientation][0] * 3), Unit_GetHouseID(u)), x + values_334E[orientation][0], y + values_334E[orientation][1], 2, values_32A4[orientation][1] | 0xC000); } } if (u->spriteOffset >= 0 && ui->turretSpriteID != 0xFFFF) { int16 offsetX = 0; int16 offsetY = 0; uint16 spriteID = ui->turretSpriteID; orientation = Orientation_Orientation256ToOrientation8(u->orientation[ui->o.flags.hasTurret ? 1 : 0].current); switch (ui->turretSpriteID) { case 0x8D: /* sonic tank */ offsetY = -2; break; case 0x92: /* rocket launcher */ offsetY = -3; break; case 0x7E: { /* siege tank */ static const int16 values_336E[8][2] = { { 0, -5}, { 0, -5}, { 2, -3}, { 2, -1}, {-1, -3}, {-2, -1}, {-2, -3}, {-1, -5} }; offsetX = values_336E[orientation][0]; offsetY = values_336E[orientation][1]; } break; case 0x88: { /* devastator */ static const int16 values_338E[8][2] = { { 0, -4}, {-1, -3}, { 2, -4}, {0, -3}, {-1, -3}, { 0, -3}, {-2, -4}, {1, -3} }; offsetX = values_338E[orientation][0]; offsetY = values_338E[orientation][1]; } break; default: break; } s_spriteFlags = values_32A4[orientation][1]; spriteID += values_32A4[orientation][0]; GUI_DrawSprite(g_screenActiveID, GUI_Widget_Viewport_Draw_GetSprite(spriteID, Unit_GetHouseID(u)), x + offsetX, y + offsetY, 2, s_spriteFlags | 0xE000, s_paletteHouse); } if (u->o.flags.s.isSmoking) { uint16 spriteID = 180 + (u->spriteOffset & 3); if (spriteID == 183) spriteID = 181; GUI_DrawSprite(g_screenActiveID, g_sprites[spriteID], x, y - 14, 2, 0xC000); } if (u != g_unitSelected) continue; GUI_DrawSprite(g_screenActiveID, g_sprites[6], x, y, 2, 0xC000); } g_dirtyUnitCount = 0; } for (i = 0; i < EXPLOSION_MAX; i++) { Explosion *e = Explosion_Get_ByIndex(i); curPos = Tile_PackTile(e->position); if (BitArray_Test(g_dirtyViewport, curPos)) e->isDirty = true; if (e->commands == NULL) continue; if (!e->isDirty && !forceRedraw) continue; if (e->spriteID == 0) continue; e->isDirty = false; if (!g_map[curPos].isUnveiled && !g_debugScenario) continue; if (!Map_IsPositionInViewport(e->position, &x, &y)) continue; s_spriteFlags = 0xC000; GUI_DrawSprite(g_screenActiveID, GUI_Widget_Viewport_Draw_GetSprite(e->spriteID, e->houseID), x, y, 2, s_spriteFlags, s_paletteHouse); } if (g_dirtyAirUnitCount != 0 || forceRedraw || updateDisplay) { find.type = 0xFFFF; find.index = 0xFFFF; find.houseID = HOUSE_INVALID; while (true) { static const uint16 values_32E4[8][2] = { {0, 0}, {1, 0}, {2, 0}, {1, 2}, {0, 2}, {1, 3}, {2, 1}, {1, 1} }; Unit *u; UnitInfo *ui; uint8 orientation; uint8 *sprite; uint16 index; u = Unit_Find(&find); if (u == NULL) break; if (u->o.index > 15) continue; curPos = Tile_PackTile(u->o.position); if ((!u->o.flags.s.isDirty || u->o.flags.s.isNotOnMap) && !forceRedraw && !BitArray_Test(g_dirtyViewport, curPos)) continue; u->o.flags.s.isDirty = false; if (!g_map[curPos].isUnveiled && !g_debugScenario) continue; ui = &g_table_unitInfo[u->o.type]; if (!Map_IsPositionInViewport(u->o.position, &x, &y)) continue; index = ui->groundSpriteID; orientation = u->orientation[0].current; s_spriteFlags = 0xC000; switch (ui->displayMode) { case DISPLAYMODE_SINGLE_FRAME: if (u->o.flags.s.bulletIsBig) index++; break; case DISPLAYMODE_UNIT: orientation = Orientation_Orientation256ToOrientation8(orientation); index += values_32E4[orientation][0]; s_spriteFlags |= values_32E4[orientation][1]; break; case DISPLAYMODE_ROCKET: { static const uint16 values_3304[16][2] = { {0, 0}, {1, 0}, {2, 0}, {3, 0}, {4, 0}, {3, 2}, {2, 2}, {1, 2}, {0, 2}, {3, 3}, {2, 3}, {3, 3}, {4, 1}, {3, 1}, {2, 1}, {1, 1} }; orientation = Orientation_Orientation256ToOrientation16(orientation); index += values_3304[orientation][0]; s_spriteFlags |= values_3304[orientation][1]; } break; case DISPLAYMODE_ORNITHOPTER: { static const uint16 values_33AE[4] = {2, 1, 0, 1}; orientation = Orientation_Orientation256ToOrientation8(orientation); index += (values_32E4[orientation][0] * 3) + values_33AE[u->spriteOffset & 3]; s_spriteFlags |= values_32E4[orientation][1]; } break; default: s_spriteFlags = 0x0; break; } if (ui->flags.hasAnimationSet && u->o.flags.s.animationFlip) index += 5; if (u->o.type == UNIT_CARRYALL && u->o.flags.s.inTransport) index += 3; sprite = GUI_Widget_Viewport_Draw_GetSprite(index, Unit_GetHouseID(u)); if (ui->o.flags.hasShadow) GUI_DrawSprite(g_screenActiveID, sprite, x + 1, y + 3, 2, (s_spriteFlags & 0xDFFF) | 0x300, g_paletteMapping1, 1); if (ui->o.flags.blurTile) s_spriteFlags |= 0x200; GUI_DrawSprite(g_screenActiveID, sprite, x, y, 2, s_spriteFlags | 0x2000, s_paletteHouse); } g_dirtyAirUnitCount = 0; } if (updateDisplay) { memset(g_dirtyMinimap, 0, sizeof(g_dirtyMinimap)); memset(g_dirtyViewport, 0, sizeof(g_dirtyViewport)); } if (g_changedTilesCount != 0) { bool init = false; bool update = false; Screen oldScreenID2 = SCREEN_1; for (i = 0; i < g_changedTilesCount; i++) { curPos = g_changedTiles[i]; BitArray_Clear(g_changedTilesMap, curPos); if (!init) { init = true; oldScreenID2 = GFX_Screen_SetActive(SCREEN_1); GUI_Mouse_Hide_InWidget(3); } GUI_Widget_Viewport_DrawTile(curPos); if (!update && BitArray_Test(g_displayedMinimap, curPos)) update = true; } if (update) Map_UpdateMinimapPosition(g_minimapPosition, true); if (init) { GUI_Screen_Copy(32, 136, 32, 136, 8, 64, g_screenActiveID, SCREEN_0); GFX_Screen_SetActive(oldScreenID2); GUI_Mouse_Show_InWidget(); } if (g_changedTilesCount == lengthof(g_changedTiles)) { g_changedTilesCount = 0; for (i = 0; i < 4096; i++) { if (!BitArray_Test(g_changedTilesMap, i)) continue; g_changedTiles[g_changedTilesCount++] = i; if (g_changedTilesCount == lengthof(g_changedTiles)) break; } } else { g_changedTilesCount = 0; } } if ((g_viewportMessageCounter & 1) != 0 && g_viewportMessageText != NULL && (minX[6] <= 14 || maxX[6] >= 0 || arg08 || forceRedraw)) { GUI_DrawText_Wrapper(g_viewportMessageText, 112, 139, 15, 0, 0x132); minX[6] = -1; maxX[6] = 14; } if (updateDisplay && !drawToMainScreen) { if (g_viewport_fadein) { GUI_Mouse_Hide_InWidget(g_curWidgetIndex); /* ENHANCEMENT -- When fading in the game on start, you don't see the fade as it is against the already drawn screen. */ if (g_dune2_enhanced) { Screen oldScreenID2 = g_screenActiveID; GFX_Screen_SetActive(SCREEN_0); GUI_DrawFilledRectangle(g_curWidgetXBase << 3, g_curWidgetYBase, (g_curWidgetXBase + g_curWidgetWidth) << 3, g_curWidgetYBase + g_curWidgetHeight, 0); GFX_Screen_SetActive(oldScreenID2); } GUI_Screen_FadeIn(g_curWidgetXBase, g_curWidgetYBase, g_curWidgetXBase, g_curWidgetYBase, g_curWidgetWidth, g_curWidgetHeight, g_screenActiveID, SCREEN_0); GUI_Mouse_Show_InWidget(); g_viewport_fadein = false; } else { bool init = false; for (i = 0; i < 10; i++) { uint16 width; uint16 height; if (arg08) { minX[i] = 0; maxX[i] = 14; } if (maxX[i] < minX[i]) continue; x = minX[i] * 2; y = (i << 4) + 0x28; width = (maxX[i] - minX[i] + 1) * 2; height = 16; if (!init) { GUI_Mouse_Hide_InWidget(g_curWidgetIndex); init = true; } GUI_Screen_Copy(x, y, x, y, width, height, g_screenActiveID, SCREEN_0); } if (init) GUI_Mouse_Show_InWidget(); } } GFX_Screen_SetActive(oldScreenID); Widget_SetCurrentWidget(oldValue_07AE_0000); }
static void GameCredits_Play(char *data, uint16 windowID, Screen memory, Screen screenID, uint16 delay) { uint16 loc02; uint16 stringCount = 0; uint32 loc0C; uint16 spriteID = 514; bool loc10 = false; uint16 spriteX; uint16 spriteY; uint16 spritePos = 0; struct { uint16 x; int16 y; char *text; uint8 separator; uint8 charHeight; uint8 type; } strings[33]; struct { uint16 x; uint16 y; } positions[6]; uint16 stage = 4; uint16 counter = 60; Widget_SetCurrentWidget(windowID); spriteX = (g_curWidgetWidth << 3) - Sprite_GetWidth(g_sprites[spriteID]); spriteY = g_curWidgetHeight - Sprite_GetHeight(g_sprites[spriteID]); positions[0].x = spriteX; positions[0].y = 0; positions[1].x = 0; positions[1].y = spriteY / 2; positions[2].x = spriteX; positions[2].y = spriteY; positions[3].x = 0; positions[3].y = 0; positions[4].x = spriteX; positions[4].y = spriteY / 2; positions[5].x = 0; positions[5].y = spriteY; GUI_Screen_Copy(0, 0, 0, 0, SCREEN_WIDTH / 8, SCREEN_HEIGHT, SCREEN_0, memory); GUI_Screen_Copy(0, 0, 0, 0, SCREEN_WIDTH / 8, SCREEN_HEIGHT, memory, screenID); GameCredits_SwapScreen(g_curWidgetYBase, g_curWidgetHeight, memory, s_buffer_182E); GFX_Screen_SetActive(SCREEN_0); loc0C = g_timerSleep; Input_History_Clear(); while (true) { while (loc0C > g_timerSleep) sleepIdle(); loc0C = g_timerSleep + delay; while ((g_curWidgetHeight / 6) + 2 > stringCount && *data != 0) { char *text = data; uint16 y; if (stringCount != 0) { y = strings[stringCount - 1].y; if (strings[stringCount - 1].separator != 5) y += strings[stringCount - 1].charHeight + strings[stringCount - 1].charHeight / 8; } else { y = g_curWidgetHeight; } text = data; data = strpbrk(data, "\x05\r"); if (data == NULL) data = strchr(text, '\0'); strings[stringCount].separator = *data; *data = '\0'; if (strings[stringCount].separator != 0) data++; strings[stringCount].type = 0; if (*text == 3 || *text == 4) strings[stringCount].type = *text++; if (*text == 1) { text++; Font_Select(g_fontNew6p); } else if (*text == 2) { text++; Font_Select(g_fontNew8p); } strings[stringCount].charHeight = g_fontCurrent->height; switch (strings[stringCount].type) { case 3: strings[stringCount].x = 157 - Font_GetStringWidth(text); break; case 4: strings[stringCount].x = 161; break; default: strings[stringCount].x = 1 + (SCREEN_WIDTH - Font_GetStringWidth(text)) / 2; break; } strings[stringCount].y = y; strings[stringCount].text = text; stringCount++; } switch (stage) { case 0: GUI_ClearScreen(memory); if (spriteID == 514) GUI_ClearScreen(screenID); stage++; counter = 2; break; case 1: case 4: if (counter-- == 0) { counter = 0; stage++; } break; case 2: if (spriteID == 525) spriteID = 514; GUI_DrawSprite(memory, g_sprites[spriteID], positions[spritePos].x, positions[spritePos].y, windowID, 0x4000); counter = 8; stage++; spriteID++; if (++spritePos > 5) spritePos = 0;; break; case 3: if (counter < 8) GFX_SetPalette(g_palette1 + 256 * 3 * counter); if (counter-- == 0) { stage++; counter = 20; } break; case 5: if (counter > 0) GFX_SetPalette(g_palette1 + 256 * 3 * counter); if (counter++ >= 8) stage = 0; break; default: break; } GUI_Screen_Copy(g_curWidgetXBase, g_curWidgetYBase, g_curWidgetXBase, g_curWidgetYBase, g_curWidgetWidth, g_curWidgetHeight, memory, screenID); for (loc02 = 0; loc02 < stringCount; loc02++) { if ((int16)strings[loc02].y < g_curWidgetHeight) { GFX_Screen_SetActive(screenID); Font_Select(g_fontNew8p); if (strings[loc02].charHeight != g_fontCurrent->height) Font_Select(g_fontNew6p); GUI_DrawText(strings[loc02].text, strings[loc02].x, strings[loc02].y + g_curWidgetYBase, 255, 0); GFX_Screen_SetActive(SCREEN_0); } strings[loc02].y--; } GameCredits_SwapScreen(g_curWidgetYBase, g_curWidgetHeight, screenID, s_buffer_182E); if ((int16)strings[0].y < -10) { strings[0].text += strlen(strings[0].text); *strings[0].text = strings[0].separator; stringCount--; memcpy(&strings[0], &strings[1], stringCount * sizeof(*strings)); } if ((g_curWidgetHeight / 6 + 2) > stringCount) { if (strings[stringCount - 1].y + strings[stringCount - 1].charHeight < g_curWidgetYBase + g_curWidgetHeight) loc10 = true; } if (loc10 && stage == 0) break; if (Input_Keyboard_NextKey() != 0) break; } GUI_SetPaletteAnimated(g_palette2, 120); GUI_ClearScreen(SCREEN_0); GUI_ClearScreen(memory); GUI_ClearScreen(screenID); }