/** * Destroy a structure and spawn soldiers around the place. * * Stack: *none* * * @param script The script engine to operate on. * @return Always 0. */ uint16 Script_Structure_Destroy(ScriptEngine *script) { Structure *s; uint16 position; uint16 layout; uint16 i; VARIABLE_NOT_USED(script); s = g_scriptCurrentStructure; layout = g_table_structureInfo[s->o.type].layout; position = Tile_PackTile(s->o.position); Structure_Remove(s); for (i = 0; i < g_table_structure_layoutTileCount[layout]; i++) { tile32 tile; Unit *u; tile = Tile_UnpackTile(position + g_table_structure_layoutTiles[layout][i]); if (g_table_structureInfo[s->o.type].o.spawnChance < Tools_Random_256()) continue; u = Unit_Create(UNIT_INDEX_INVALID, UNIT_SOLDIER, s->o.houseID, tile, Tools_Random_256()); if (u == NULL) continue; u->o.hitpoints = g_table_unitInfo[UNIT_SOLDIER].o.hitpoints * (Tools_Random_256() & 3) / 256; if (s->o.houseID != g_playerHouseID) { Unit_SetAction(u, ACTION_ATTACK); continue; } Unit_SetAction(u, ACTION_MOVE); tile = Tile_MoveByRandom(u->o.position, 32, true); u->targetMove = Tools_Index_Encode(Tile_PackTile(tile), IT_TILE); } if (g_debugScenario) return 0; if (s->o.houseID != g_playerHouseID) return 0; if (g_config.language == LANGUAGE_FRENCH) { GUI_DisplayText("%s %s %s", 0, String_Get_ByIndex(g_table_structureInfo[s->o.type].o.stringID_full), g_table_houseInfo[s->o.houseID].name, String_Get_ByIndex(0x85)); } else { GUI_DisplayText("%s %s %s", 0, g_table_houseInfo[s->o.houseID].name, String_Get_ByIndex(g_table_structureInfo[s->o.type].o.stringID_full), String_Get_ByIndex(0x85)); } return 0; }
/********************************************************************************* * Description : 固件版本界面 * * Arguments : * * Returns : * * Notes : * *********************************************************************************/ INT32 SET_FirmwareSetting(void) { UINT32 key; INT8 buf[20]; BOOL need_draw = TRUE; while(1) { if(need_draw) { // INT8 *p; // UINT8 ch1,ch2,ch3,ch4; GUI_ClearScreen(NULL); //show barcode GUI_ResShowPic(GUI_IMG_FWBCODE, 10, 0); sprintf(buf, "APP:%d.%d", AP_GetVersion() >> 8, AP_GetVersion() & 0xff); GUI_DisplayText(0, 16, buf); sprintf(buf, "Date: %08d", AP_GetBuildDate()); GUI_DisplayText(0, 32, buf); sprintf(buf, "HW:%d.%d r%d", GetPlatformVersion() >> 8, GetPlatformVersion() & 0xff, GetPlatformRevision()); GUI_DisplayText(0, 48, buf); GUI_UpdateScreen(NULL); need_draw = FALSE; }//need_draw key = MESSAGE_Wait(); switch( key ) { case AP_MSG_WAIT_TIMEOUT: //子菜单界面在8秒后返回系统功能菜单 case AP_KEY_MODE | AP_KEY_UP: case AP_KEY_PLAY | AP_KEY_UP: return 0; default: key = MESSAGE_HandleHotkey(key); if(key == RESULT_REDRAW) { need_draw = TRUE; } else if(key != 0) { return key; } } }//while(1) }
/** * Transform an MCV into Construction Yard. * * Stack: *none*. * * @param script The script engine to operate on. * @return 1 if and only if the transformation succeeded. */ uint16 Script_Unit_MCVDeploy(ScriptEngine *script) { Unit *u; Structure *s = NULL; uint16 i; VARIABLE_NOT_USED(script); u = g_scriptCurrentUnit; Unit_UpdateMap(0, u); uint houseID = Unit_GetHouseID(u); uint tile = Tile_PackTile(u->o.position); for (i = 0; i < 4; i++) { static int8 offsets[4] = { 0, -1, -64, -65 }; s = Structure_Create(STRUCTURE_INDEX_INVALID, STRUCTURE_CONSTRUCTION_YARD, houseID, tile + offsets[i]); if (s != NULL) { Unit_Remove(u); return 1; } } if (houseID == g_playerHouseID) { GUI_DisplayText(String_Get_ByIndex(STR_UNIT_IS_UNABLE_TO_DEPLOY_HERE), 0); } Unit_UpdateMap(1, u); return 0; }
/** * Initialize a game, by setting most variables to zero, cleaning the map, etc * etc. */ void Game_Init() { Unit_Init(); Structure_Init(); UnitAI_ClearSquads(); Team_Init(); House_Init(); Animation_Init(); Explosion_Init(); memset(g_map, 0, 64 * 64 * sizeof(Tile)); Map_ResetFogOfWar(); memset(g_mapSpriteID, 0, 64 * 64 * sizeof(uint16)); memset(g_starportAvailable, 0, sizeof(g_starportAvailable)); Audio_PlayVoice(VOICE_STOP); g_playerCreditsNoSilo = 0; g_houseMissileCountdown = 0; g_selectionState = 0; /* Invalid. */ g_structureActivePosition = 0; g_unitHouseMissile = NULL; g_unitActive = NULL; g_structureActive = NULL; g_activeAction = 0xFFFF; g_structureActiveType = 0xFFFF; GUI_DisplayText(NULL, -1); }
/** * Calculate the power usage and production, and the credits storage. * * @param h The house to calculate the numbers for. */ void House_CalculatePowerAndCredit(House *h) { PoolFindStruct find; if (h == NULL) return; h->powerUsage = 0; h->powerProduction = 0; h->creditsStorage = 0; find.houseID = h->index; find.index = 0xFFFF; find.type = 0xFFFF; while (true) { const StructureInfo *si; Structure *s; s = Structure_Find(&find); if (s == NULL) break; /* ENHANCEMENT -- Only count structures that are placed on the map, not ones we are building. */ if (g_dune2_enhanced && s->o.flags.s.isNotOnMap) continue; si = &g_table_structureInfo[s->o.type]; h->creditsStorage += si->creditsStorage; /* Positive values means usage */ if (si->powerUsage >= 0) { h->powerUsage += si->powerUsage; continue; } /* Negative value and full health means everything goes to production */ if (s->o.hitpoints >= si->o.hitpoints) { h->powerProduction += -si->powerUsage; continue; } /* Negative value and partial health, calculate how much should go to production (capped at 50%) */ /* ENHANCEMENT -- The 50% cap of Dune2 is silly and disagress with the GUI. If your hp is 10%, so should the production. */ if (!g_dune2_enhanced && s->o.hitpoints <= si->o.hitpoints / 2) { h->powerProduction += (-si->powerUsage) / 2; continue; } h->powerProduction += (-si->powerUsage) * s->o.hitpoints / si->o.hitpoints; } /* Check if we are low on power */ if (h->index == g_playerHouseID && h->powerUsage > h->powerProduction) { GUI_DisplayText(String_Get_ByIndex(STR_INSUFFICIENT_POWER_WINDTRAP_IS_NEEDED), 1); } /* If there are no buildings left, you lose your right on 'credits without storage' */ if (h->index == g_playerHouseID && h->structuresBuilt == 0 && g_validateStrictIfZero == 0) { g_playerCreditsNoSilo = 0; } }
/** * Displays the "XXX XXX destroyed." message for the current unit. * * Stack: *none*. * * @param script The script engine to operate on. * @return The value 0. Always. */ uint16 Script_Unit_DisplayDestroyedText(ScriptEngine *script) { const UnitInfo *ui; Unit *u; VARIABLE_NOT_USED(script); u = g_scriptCurrentUnit; ui = &g_table_unitInfo[u->o.type]; if (g_config.language == LANGUAGE_FRENCH) { GUI_DisplayText(String_Get_ByIndex(STR_S_S_DESTROYED), 0, String_Get_ByIndex(ui->o.stringID_abbrev), g_table_houseInfo[Unit_GetHouseID(u)].name); } else { GUI_DisplayText(String_Get_ByIndex(STR_S_S_DESTROYED), 0, g_table_houseInfo[Unit_GetHouseID(u)].name, String_Get_ByIndex(ui->o.stringID_abbrev)); } return 0; }
/** * Draws a string. * * Stack: 1 - The index of the string to draw. * 2-4 - The arguments for the string. * * @param script The script engine to operate on. * @return The value 0. Always. */ uint16 Script_Team_DisplayText(ScriptEngine *script) { Team *t; char *text; uint16 offset; t = g_scriptCurrentTeam; if (t->houseID == g_playerHouseID) return 0; offset = BETOH16(*(script->scriptInfo->text + STACK_PEEK(1))); text = (char *)script->scriptInfo->text + offset; GUI_DisplayText(text, 0, STACK_PEEK(2), STACK_PEEK(3), STACK_PEEK(4)); return 0; }
/** * Gives a harvester to the given house if it has a refinery and no harvesters. * * @param houseID The index of the house to give a harvester to. */ void House_EnsureHarvesterAvailable(uint8 houseID) { PoolFindStruct find; Structure *s; find.houseID = houseID; find.type = 0xFFFF; find.index = 0xFFFF; while (true) { s = Structure_Find(&find); if (s == NULL) break; /* ENHANCEMENT -- Dune2 checked the wrong type to skip. LinkedID is a structure for a Construction Yard */ if (!g_dune2_enhanced && s->o.type == STRUCTURE_HEAVY_VEHICLE) continue; if (g_dune2_enhanced && s->o.type == STRUCTURE_CONSTRUCTION_YARD) continue; if (s->o.linkedID == UNIT_INVALID) continue; if (Unit_Get_ByIndex(s->o.linkedID)->o.type == UNIT_HARVESTER) return; } find.houseID = houseID; find.type = UNIT_CARRYALL; find.index = 0xFFFF; while (true) { Unit *u; u = Unit_Find(&find); if (u == NULL) break; if (u->o.linkedID == UNIT_INVALID) continue; if (Unit_Get_ByIndex(u->o.linkedID)->o.type == UNIT_HARVESTER) return; } if (Unit_IsTypeOnMap(houseID, UNIT_HARVESTER)) return; find.houseID = houseID; find.type = STRUCTURE_REFINERY; find.index = 0xFFFF; s = Structure_Find(&find); if (s == NULL) return; if (Unit_CreateWrapper(houseID, UNIT_HARVESTER, Tools_Index_Encode(s->o.index, IT_STRUCTURE)) == NULL) return; if (houseID != g_playerHouseID) return; GUI_DisplayText(String_Get_ByIndex(STR_HARVESTER_IS_HEADING_TO_REFINERY), 0); }
/** * Initialize a game, by setting most variables to zero, cleaning the map, etc * etc. */ void Game_Init(void) { Unit_Init(); Structure_Init(); Team_Init(); House_Init(); Animation_Init(); Explosion_Init(); memset(g_map, 0, 64 * 64 * sizeof(Tile)); memset(g_displayedViewport, 0, sizeof(g_displayedViewport)); memset(g_displayedMinimap, 0, sizeof(g_displayedMinimap)); memset(g_changedTilesMap, 0, sizeof(g_changedTilesMap)); memset(g_dirtyViewport, 0, sizeof(g_dirtyViewport)); memset(g_dirtyMinimap, 0, sizeof(g_dirtyMinimap)); memset(g_mapSpriteID, 0, 64 * 64 * sizeof(uint16)); memset(g_starportAvailable, 0, sizeof(g_starportAvailable)); Sound_Output_Feedback(0xFFFE); g_playerCreditsNoSilo = 0; g_houseMissileCountdown = 0; g_selectionState = 0; /* Invalid. */ g_structureActivePosition = 0; g_unitHouseMissile = NULL; g_unitActive = NULL; g_structureActive = NULL; g_activeAction = 0xFFFF; g_structureActiveType = 0xFFFF; GUI_DisplayText(NULL, -1); }
/** * Loop over all houses, preforming various of tasks. */ void GameLoop_House(void) { PoolFindStruct find; House *h = NULL; bool tickHouse = false; bool tickPowerMaintenance = false; bool tickStarport = false; bool tickReinforcement = false; bool tickMissileCountdown = false; bool tickStarportAvailability = false; if (g_debugScenario) return; if (s_tickHouseHouse <= g_timerGame) { tickHouse = true; s_tickHouseHouse = g_timerGame + 900; } if (g_tickHousePowerMaintenance <= g_timerGame) { tickPowerMaintenance = true; g_tickHousePowerMaintenance = g_timerGame + 10800; } if (s_tickHouseStarport <= g_timerGame) { tickStarport = true; s_tickHouseStarport = g_timerGame + 180; } if (s_tickHouseReinforcement <= g_timerGame) { tickReinforcement = true; s_tickHouseReinforcement = g_timerGame + (g_debugGame ? 60 : 600); } if (s_tickHouseMissileCountdown <= g_timerGame) { tickMissileCountdown = true; s_tickHouseMissileCountdown = g_timerGame + 60; } if (s_tickHouseStarportAvailability <= g_timerGame) { tickStarportAvailability = true; s_tickHouseStarportAvailability = g_timerGame + 1800; } if (tickMissileCountdown && g_houseMissileCountdown != 0) { g_houseMissileCountdown--; Sound_Output_Feedback(g_houseMissileCountdown + 41); if (g_houseMissileCountdown == 0) Unit_LaunchHouseMissile(Map_FindLocationTile(4, g_playerHouseID)); } if (tickStarportAvailability) { uint16 type; /* Pick a random unit to increase starport availability */ type = Tools_RandomLCG_Range(0, UNIT_MAX - 1); /* Increase how many of this unit is available via starport by one */ if (g_starportAvailable[type] != 0 && g_starportAvailable[type] < 10) { if (g_starportAvailable[type] == -1) { g_starportAvailable[type] = 1; } else { g_starportAvailable[type]++; } } } if (tickReinforcement) { Unit *nu = NULL; int i; for (i = 0; i < 16; i++) { uint16 locationID; bool deployed; Unit *u; if (g_scenario.reinforcement[i].unitID == UNIT_INDEX_INVALID) continue; if (g_scenario.reinforcement[i].timeLeft == 0) continue; if (--g_scenario.reinforcement[i].timeLeft != 0) continue; u = Unit_Get_ByIndex(g_scenario.reinforcement[i].unitID); locationID = g_scenario.reinforcement[i].locationID; deployed = false; if (locationID >= 4) { if (nu == NULL) { nu = Unit_Create(UNIT_INDEX_INVALID, UNIT_CARRYALL, u->o.houseID, Tile_UnpackTile(Map_FindLocationTile(Tools_Random_256() & 3, u->o.houseID)), 100); if (nu != NULL) { nu->o.flags.s.byScenario = true; Unit_SetDestination(nu, Tools_Index_Encode(Map_FindLocationTile(locationID, u->o.houseID), IT_TILE)); } } if (nu != NULL) { u->o.linkedID = nu->o.linkedID; nu->o.linkedID = (uint8)u->o.index; nu->o.flags.s.inTransport = true; g_scenario.reinforcement[i].unitID = UNIT_INDEX_INVALID; deployed = true; } else { /* Failed to create carry-all, try again in a short moment */ g_scenario.reinforcement[i].timeLeft = 1; } } else { deployed = Unit_SetPosition(u, Tile_UnpackTile(Map_FindLocationTile(locationID, u->o.houseID))); } if (deployed && g_scenario.reinforcement[i].repeat != 0) { tile32 tile; tile.x = 0xFFFF; tile.y = 0xFFFF; g_validateStrictIfZero++; u = Unit_Create(UNIT_INDEX_INVALID, u->o.type, u->o.houseID, tile, 0); g_validateStrictIfZero--; if (u != NULL) { g_scenario.reinforcement[i].unitID = u->o.index; g_scenario.reinforcement[i].timeLeft = g_scenario.reinforcement[i].timeBetween; } } } } find.houseID = HOUSE_INVALID; find.index = 0xFFFF; find.type = 0xFFFF; while (true) { h = House_Find(&find); if (h == NULL) break; if (tickHouse) { /* ENHANCEMENT -- Originally this code was outside the house loop, which seems very odd. * This problem is considered to be so bad, that the original code has been removed. */ if (h->index != g_playerHouseID) { if (h->creditsStorage < h->credits) { h->credits = h->creditsStorage; } } else { uint16 maxCredits = max(h->creditsStorage, g_playerCreditsNoSilo); if (h->credits > maxCredits) { h->credits = maxCredits; GUI_DisplayText(String_Get_ByIndex(STR_INSUFFICIENT_SPICE_STORAGE_AVAILABLE_SPICE_IS_LOST), 1); } } if (h->index == g_playerHouseID) { if (h->creditsStorage > g_playerCreditsNoSilo) { g_playerCreditsNoSilo = 0; } if (g_playerCreditsNoSilo == 0 && g_campaignID > 1 && h->credits != 0) { if (h->creditsStorage != 0 && ((h->credits * 256 / h->creditsStorage) > 200)) { GUI_DisplayText(String_Get_ByIndex(STR_SPICE_STORAGE_CAPACITY_LOW_BUILD_SILOS), 0); } } if (h->credits < 100 && g_playerCreditsNoSilo != 0) { GUI_DisplayText(String_Get_ByIndex(STR_CREDITS_ARE_LOW_HARVEST_SPICE_FOR_MORE_CREDITS), 0); } } } if (tickHouse) House_EnsureHarvesterAvailable((uint8)h->index); if (tickStarport && h->starportLinkedID != UNIT_INDEX_INVALID) { Unit *u = NULL; h->starportTimeLeft--; if ((int16)h->starportTimeLeft < 0) h->starportTimeLeft = 0; if (h->starportTimeLeft == 0) { Structure *s; s = Structure_Get_ByIndex(g_structureIndex); if (s->o.type == STRUCTURE_STARPORT && s->o.houseID == h->index) { u = Unit_CreateWrapper((uint8)h->index, UNIT_FRIGATE, Tools_Index_Encode(s->o.index, IT_STRUCTURE)); } else { PoolFindStruct find2; find2.houseID = h->index; find2.index = 0xFFFF; find2.type = STRUCTURE_STARPORT; while (true) { s = Structure_Find(&find2); if (s == NULL) break; if (s->o.linkedID != 0xFF) continue; u = Unit_CreateWrapper((uint8)h->index, UNIT_FRIGATE, Tools_Index_Encode(s->o.index, IT_STRUCTURE)); break; } } if (u != NULL) { u->o.linkedID = (uint8)h->starportLinkedID; h->starportLinkedID = UNIT_INDEX_INVALID; u->o.flags.s.inTransport = true; Sound_Output_Feedback(38); } h->starportTimeLeft = (u != NULL) ? g_table_houseInfo[h->index].starportDeliveryTime : 1; } } if (tickHouse) { House_CalculatePowerAndCredit(h); Structure_CalculateHitpointsMax(h); if (h->timerUnitAttack != 0) h->timerUnitAttack--; if (h->timerSandwormAttack != 0) h->timerSandwormAttack--; if (h->timerStructureAttack != 0) h->timerStructureAttack--; if (h->harvestersIncoming > 0 && Unit_CreateWrapper((uint8)h->index, UNIT_HARVESTER, 0) != NULL) h->harvestersIncoming--; } if (tickPowerMaintenance) { uint16 powerMaintenanceCost = (h->powerUsage / 32) + 1; h->credits -= min(h->credits, powerMaintenanceCost); } } }
/** * Main game loop. */ static void GameLoop_Main(void) { static uint32 l_timerNext = 0; static uint32 l_timerUnitStatus = 0; static int16 l_selectionState = -2; uint16 key; String_Init(); Sprites_Init(); Input_Flags_SetBits(INPUT_FLAG_KEY_REPEAT | INPUT_FLAG_UNKNOWN_0010 | INPUT_FLAG_UNKNOWN_0200 | INPUT_FLAG_UNKNOWN_2000); Input_Flags_ClearBits(INPUT_FLAG_KEY_RELEASE | INPUT_FLAG_UNKNOWN_0400 | INPUT_FLAG_UNKNOWN_0100 | INPUT_FLAG_UNKNOWN_0080 | INPUT_FLAG_UNKNOWN_0040 | INPUT_FLAG_UNKNOWN_0020 | INPUT_FLAG_UNKNOWN_0008 | INPUT_FLAG_UNKNOWN_0004 | INPUT_FLAG_NO_TRANSLATE); Timer_SetTimer(TIMER_GAME, true); Timer_SetTimer(TIMER_GUI, true); g_campaignID = 0; g_scenarioID = 1; g_playerHouseID = HOUSE_INVALID; g_debugScenario = false; g_selectionType = SELECTIONTYPE_MENTAT; g_selectionTypeNew = SELECTIONTYPE_MENTAT; g_palette1 = calloc(1, 256 * 3); g_palette2 = calloc(1, 256 * 3); g_readBufferSize = 12000; g_readBuffer = calloc(1, g_readBufferSize); ReadProfileIni("PROFILE.INI"); free(g_readBuffer); g_readBuffer = NULL; File_ReadBlockFile("IBM.PAL", g_palette_998A, 256 * 3); memmove(g_palette1, g_palette_998A, 256 * 3); GUI_ClearScreen(SCREEN_0); Video_SetPalette(g_palette1, 0, 256); GFX_SetPalette(g_palette1); GFX_SetPalette(g_palette2); g_paletteMapping1 = malloc(256); g_paletteMapping2 = malloc(256); GUI_Palette_CreateMapping(g_palette1, g_paletteMapping1, 0xC, 0x55); g_paletteMapping1[0xFF] = 0xFF; g_paletteMapping1[0xDF] = 0xDF; g_paletteMapping1[0xEF] = 0xEF; GUI_Palette_CreateMapping(g_palette1, g_paletteMapping2, 0xF, 0x55); g_paletteMapping2[0xFF] = 0xFF; g_paletteMapping2[0xDF] = 0xDF; g_paletteMapping2[0xEF] = 0xEF; Script_LoadFromFile("TEAM.EMC", g_scriptTeam, g_scriptFunctionsTeam, NULL); Script_LoadFromFile("BUILD.EMC", g_scriptStructure, g_scriptFunctionsStructure, NULL); GUI_Palette_CreateRemap(HOUSE_MERCENARY); g_cursorSpriteID = 0; Sprites_SetMouseSprite(0, 0, g_sprites[0]); while (g_mouseHiddenDepth > 1) { GUI_Mouse_Show_Safe(); } Window_WidgetClick_Create(); GameOptions_Load(); Unit_Init(); Team_Init(); House_Init(); Structure_Init(); GUI_Mouse_Show_Safe(); if (g_debugSkipDialogs) { Music_Play(0); free(g_readBuffer); g_readBufferSize = (g_enableVoices == 0) ? 12000 : 20000; g_readBuffer = calloc(1, g_readBufferSize); g_gameMode = GM_NORMAL; } for (;; sleepIdle()) { if (g_gameMode == GM_MENU) { GameLoop_GameIntroAnimationMenu(); if (!g_running) break; if (g_gameMode == GM_MENU) continue; GUI_Mouse_Hide_Safe(); g_canSkipIntro = false; GUI_DrawFilledRectangle(g_curWidgetXBase << 3, g_curWidgetYBase, (g_curWidgetXBase + g_curWidgetWidth) << 3, g_curWidgetYBase + g_curWidgetHeight, 12); Input_History_Clear(); if (s_enableLog != 0) Mouse_SetMouseMode((uint8)s_enableLog, "DUNE.LOG"); GFX_SetPalette(g_palette1); GUI_Mouse_Show_Safe(); } if (g_gameMode == GM_PICKHOUSE) { Music_Play(28); g_playerHouseID = HOUSE_MERCENARY; g_playerHouseID = GUI_PickHouse(); GUI_Mouse_Hide_Safe(); GFX_ClearBlock(SCREEN_0); Sprites_LoadTiles(); GUI_Palette_CreateRemap(g_playerHouseID); Voice_LoadVoices(g_playerHouseID); GUI_Mouse_Show_Safe(); g_gameMode = GM_RESTART; g_scenarioID = 1; g_campaignID = 0; g_strategicRegionBits = 0; } if (g_selectionTypeNew != g_selectionType) { GUI_ChangeSelectionType(g_selectionTypeNew); } GUI_PaletteAnimate(); if (g_gameMode == GM_RESTART) { GUI_ChangeSelectionType(SELECTIONTYPE_MENTAT); Game_LoadScenario(g_playerHouseID, g_scenarioID); if (!g_debugScenario && !g_debugSkipDialogs) GUI_Mentat_ShowBriefing(); g_gameMode = GM_NORMAL; GUI_ChangeSelectionType(g_debugScenario ? SELECTIONTYPE_DEBUG : SELECTIONTYPE_STRUCTURE); Music_Play(Tools_RandomLCG_Range(0, 8) + 8); l_timerNext = g_timerGUI + 300; } if (l_selectionState != g_selectionState) { Map_SetSelectionObjectPosition(0xFFFF); Map_SetSelectionObjectPosition(g_selectionRectanglePosition); l_selectionState = g_selectionState; } if (!Driver_Voice_IsPlaying() && !Sound_StartSpeech()) { if (g_gameConfig.music == 0) { Music_Play(2); g_musicInBattle = 0; } else if (g_musicInBattle > 0) { Music_Play(Tools_RandomLCG_Range(0, 5) + 17); l_timerNext = g_timerGUI + 300; g_musicInBattle = -1; } else { g_musicInBattle = 0; if (g_enableSoundMusic != 0 && g_timerGUI > l_timerNext) { if (!Driver_Music_IsPlaying()) { Music_Play(Tools_RandomLCG_Range(0, 8) + 8); l_timerNext = g_timerGUI + 300; } } } } GFX_Screen_SetActive(SCREEN_0); key = GUI_Widget_HandleEvents(g_widgetLinkedListHead); if (g_selectionType == SELECTIONTYPE_TARGET || g_selectionType == SELECTIONTYPE_PLACE || g_selectionType == SELECTIONTYPE_UNIT || g_selectionType == SELECTIONTYPE_STRUCTURE) { if (g_unitSelected != NULL) { if (l_timerUnitStatus < g_timerGame) { Unit_DisplayStatusText(g_unitSelected); l_timerUnitStatus = g_timerGame + 300; } if (g_selectionType != SELECTIONTYPE_TARGET) { g_selectionPosition = Tile_PackTile(Tile_Center(g_unitSelected->o.position)); } } GUI_Widget_ActionPanel_Draw(false); InGame_Numpad_Move(key); GUI_DrawCredits(g_playerHouseID, 0); GameLoop_Team(); GameLoop_Unit(); GameLoop_Structure(); GameLoop_House(); GUI_DrawScreen(SCREEN_0); } GUI_DisplayText(NULL, 0); if (g_running && !g_debugScenario) { GameLoop_LevelEnd(); } if (!g_running) break; } GUI_Mouse_Hide_Safe(); if (s_enableLog != 0) Mouse_SetMouseMode(INPUT_MOUSE_MODE_NORMAL, "DUNE.LOG"); GUI_Mouse_Hide_Safe(); Widget_SetCurrentWidget(0); GFX_Screen_SetActive(SCREEN_1); GFX_ClearScreen(); GUI_Screen_FadeIn(g_curWidgetXBase, g_curWidgetYBase, g_curWidgetXBase, g_curWidgetYBase, g_curWidgetWidth, g_curWidgetHeight, SCREEN_1, SCREEN_0); }
/** * Handles the Click events for the Viewport widget. * * @param w The widget. */ bool GUI_Widget_Viewport_Click(Widget *w) { uint16 direction; uint16 x, y; uint16 spriteID; uint16 packed; bool click, drag; spriteID = g_cursorSpriteID; switch (w->index) { default: break; case 39: spriteID = 1; break; case 40: spriteID = 2; break; case 41: spriteID = 4; break; case 42: spriteID = 3; break; case 43: spriteID = g_cursorDefaultSpriteID; break; case 44: spriteID = g_cursorDefaultSpriteID; break; case 45: spriteID = 0; break; } if (spriteID != g_cursorSpriteID) { /* HotSpots for different cursor types. */ static const XYPosition cursorHotSpots[6] = {{0, 0}, {5, 0}, {8, 5}, {5, 8}, {0, 5}, {8, 8}}; s_tickCursor = g_timerGame; Sprites_SetMouseSprite(cursorHotSpots[spriteID].x, cursorHotSpots[spriteID].y, g_sprites[spriteID]); g_cursorSpriteID = spriteID; } if (w->index == 45) return true; click = false; drag = false; if ((w->state.buttonState & 0x11) != 0) { click = true; g_var_37B8 = false; } else if ((w->state.buttonState & 0x22) != 0 && !g_var_37B8) { drag = true; } /* ENHANCEMENT -- Dune2 depends on slow CPUs to limit the rate mouse clicks are handled. */ if (g_dune2_enhanced && (click || drag)) { if (s_tickClick + 2 >= g_timerGame) return true; s_tickClick = g_timerGame; } direction = 0xFFFF; switch (w->index) { default: break; case 39: direction = 0; break; case 40: direction = 2; break; case 41: direction = 6; break; case 42: direction = 4; break; } if (direction != 0xFFFF) { /* Always scroll if we have a click or a drag */ if (!click && !drag) { /* Wait for either one of the timers */ if (s_tickMapScroll + 10 >= g_timerGame || s_tickCursor + 20 >= g_timerGame) return true; /* Don't scroll if we have a structure/unit selected and don't want to autoscroll */ if (g_gameConfig.autoScroll == 0 && (g_selectionType == SELECTIONTYPE_STRUCTURE || g_selectionType == SELECTIONTYPE_UNIT)) return true; } s_tickMapScroll = g_timerGame; Map_MoveDirection(direction); return true; } if (click) { x = g_mouseClickX; y = g_mouseClickY; } else { x = g_mouseX; y = g_mouseY; } if (w->index == 43) { x = x / 16 + Tile_GetPackedX(g_minimapPosition); y = (y - 40) / 16 + Tile_GetPackedY(g_minimapPosition); } else if (w->index == 44) { uint16 mapScale; const MapInfo *mapInfo; mapScale = g_scenario.mapScale; mapInfo = &g_mapInfos[mapScale]; x = min((max(x, 256) - 256) / (mapScale + 1), mapInfo->sizeX - 1) + mapInfo->minX; y = min((max(y, 136) - 136) / (mapScale + 1), mapInfo->sizeY - 1) + mapInfo->minY; } packed = Tile_PackXY(x, y); if (click && g_selectionType == SELECTIONTYPE_TARGET) { Unit *u; ActionType action; uint16 encoded; GUI_DisplayText(NULL, -1); if (g_unitHouseMissile != NULL) { Unit_LaunchHouseMissile(packed); return true; } u = g_unitActive; action = g_activeAction; Object_Script_Variable4_Clear(&u->o); u->targetAttack = 0; u->targetMove = 0; u->route[0] = 0xFF; if (action != ACTION_MOVE && action != ACTION_HARVEST) { encoded = Tools_Index_Encode(Unit_FindTargetAround(packed), IT_TILE); } else { encoded = Tools_Index_Encode(packed, IT_TILE); } Unit_SetAction(u, action); if (action == ACTION_MOVE) { Unit_SetDestination(u, encoded); } else if (action == ACTION_HARVEST) { u->targetMove = encoded; } else { Unit *target; Unit_SetTarget(u, encoded); target = Tools_Index_GetUnit(u->targetAttack); if (target != NULL) target->blinkCounter = 8; } if (g_enableVoices == 0) { Driver_Sound_Play(36, 0xFF); } else if (g_table_unitInfo[u->o.type].movementType == MOVEMENT_FOOT) { Sound_StartSound(g_table_actionInfo[action].soundID); } else { Sound_StartSound(((Tools_Random_256() & 0x1) == 0) ? 20 : 17); } g_unitActive = NULL; g_activeAction = 0xFFFF; GUI_ChangeSelectionType(SELECTIONTYPE_UNIT); return true; } if (click && g_selectionType == SELECTIONTYPE_PLACE) { const StructureInfo *si; Structure *s; House *h; s = g_structureActive; si = &g_table_structureInfo[g_structureActiveType]; h = g_playerHouse; if (Structure_Place(s, g_selectionPosition)) { Voice_Play(20); if (s->o.type == STRUCTURE_PALACE) House_Get_ByIndex(s->o.houseID)->palacePosition = s->o.position; if (g_structureActiveType == STRUCTURE_REFINERY && g_validateStrictIfZero == 0) { Unit *u; g_validateStrictIfZero++; u = Unit_CreateWrapper(g_playerHouseID, UNIT_HARVESTER, Tools_Index_Encode(s->o.index, IT_STRUCTURE)); g_validateStrictIfZero--; if (u == NULL) { h->harvestersIncoming++; } else { u->originEncoded = Tools_Index_Encode(s->o.index, IT_STRUCTURE); } } GUI_ChangeSelectionType(SELECTIONTYPE_STRUCTURE); s = Structure_Get_ByPackedTile(g_structureActivePosition); if (s != NULL) { if ((Structure_GetBuildable(s) & (1 << s->objectType)) == 0) Structure_BuildObject(s, 0xFFFE); } g_structureActiveType = 0xFFFF; g_structureActive = NULL; g_selectionState = 0; /* Invalid. */ GUI_DisplayHint(si->o.hintStringID, si->o.spriteID); House_UpdateRadarState(h); if (h->powerProduction < h->powerUsage) { if ((h->structuresBuilt & (1 << STRUCTURE_OUTPOST)) != 0) { GUI_DisplayText(String_Get_ByIndex(STR_NOT_ENOUGH_POWER_FOR_RADAR_BUILD_WINDTRAPS), 3); } } return true; } Voice_Play(47); if (g_structureActiveType == STRUCTURE_SLAB_1x1 || g_structureActiveType == STRUCTURE_SLAB_2x2) { GUI_DisplayText(String_Get_ByIndex(STR_CAN_NOT_PLACE_FOUNDATION_HERE), 2); } else { GUI_DisplayHint(STR_STRUCTURES_MUST_BE_PLACED_ON_CLEAR_ROCK_OR_CONCRETE_AND_ADJACENT_TO_ANOTHER_FRIENDLY_STRUCTURE, 0xFFFF); GUI_DisplayText(String_Get_ByIndex(STR_CAN_NOT_PLACE_S_HERE), 2, String_Get_ByIndex(si->o.stringID_abbrev)); } return true; } if (click && w->index == 43) { uint16 position; if (g_debugScenario) { position = packed; } else { position = Unit_FindTargetAround(packed); } if (g_map[position].overlaySpriteID != g_veiledSpriteID || g_debugScenario) { if (Object_GetByPackedTile(position) != NULL || g_debugScenario) { Map_SetSelection(position); Unit_DisplayStatusText(g_unitSelected); } } if ((w->state.buttonState & 0x10) != 0) Map_SetViewportPosition(packed); return true; } if ((click || drag) && w->index == 44) { Map_SetViewportPosition(packed); return true; } if (g_selectionType == SELECTIONTYPE_TARGET) { Map_SetSelection(Unit_FindTargetAround(packed)); } else if (g_selectionType == SELECTIONTYPE_PLACE) { Map_SetSelection(packed); } return true; }
/********************************************************************************* * Description : 显示系统开机动画 * * Arguments : wait_key_up, 是否要等待按键 * * Returns : TRUE, 正常 FALSE, enter testmode * * Notes : * *********************************************************************************/ BOOL APP_DisplaySysLogo(BOOL wait_key_up) { INT32 i, j; BOOL keydown = FALSE; UINT32 key; UINT32 prekey = 0; hal_HstSendEvent(SYS_EVENT, 0x19884501); hal_HstSendEvent(SYS_EVENT, g_displayconfig.log_image_time); hal_HstSendEvent(SYS_EVENT, g_displayconfig.log_image_count); if(g_displayconfig.log_image_count == 0 && g_displayconfig.log_image_time == 0) { for(i = 0; i < 1; i++) for(j = 0; j < 1;) { key = MESSAGE_Wait(); //app_trace(APP_MAIN_TRC, "Display Log receive event 0x%x,prekey=0x%x, keydown=%d", key, prekey, keydown); switch(key) { case AP_MSG_RTC: case AP_MSG_CHARGING: j++; break; default: if((key & 0xffff) == AP_KEY_DOWN) { if(prekey != 0 || key != (AP_KEY_DOWN | AP_KEY_POWER)) { keydown = TRUE; } prekey = key; } if(keydown && (key & 0xffff) == AP_KEY_UP) { return TRUE; } key = MESSAGE_HandleHotkey(key);//handle unusual usb/t-card/line-in pluging event if(key != 0) { event_detected_displaying_log = key; hal_HstSendEvent(SYS_EVENT, 0x13063002); hal_HstSendEvent(SYS_EVENT, key); } break; } } } for(i = 0; i < g_displayconfig.log_image_count; i++) { #if APP_SUPPORT_RGBLCD==1 if(AP_Support_LCD()) { GUI_ClearScreen(NULL);//清全屏幕 GUI_ResShowImage(GUI_IMG_LOGO, i, 0, 40); //g_displayconfig.log_x, g_displayconfig.log_y);/*BootLogo*/ GUI_UpdateScreen(NULL); } #elif APP_SUPPORT_LCD==1 if(AP_Support_LCD()) { GUI_ClearScreen(NULL);//清全屏幕 GUI_ResShowImage(GUI_IMG_LOGO, i, 0, 8); //g_displayconfig.log_x, g_displayconfig.log_y);/*BootLogo*/ GUI_UpdateScreen(NULL); } #elif APP_SUPPORT_LED8S==1 GUI_ClearScreen(NULL); GUI_ResShowPic(0xffff, 0, 0); GUI_DisplayText(0, 0, "8888"); GUI_UpdateScreen(NULL); #endif hal_HstSendEvent(SYS_EVENT, 0x19884500); hal_HstSendEvent(SYS_EVENT, g_displayconfig.log_image_time); for(j = 0; j < g_displayconfig.log_image_time; ) { key = MESSAGE_Wait(); //app_trace(APP_MAIN_TRC, "Display Log receive event 0x%x,prekey=0x%x, keydown=%d", key, prekey, keydown); switch(key) { case AP_MSG_RTC: case AP_MSG_CHARGING: j++; break; default: if((key & 0xffff) == AP_KEY_DOWN) { if(prekey != 0 || key != (AP_KEY_DOWN | AP_KEY_POWER)) { keydown = TRUE; } prekey = key; } if(keydown && (key & 0xffff) == AP_KEY_UP) { return TRUE; } break; } } } return TRUE; }
void APP_Test_Mode(void) { UINT32 key; g_test_mode = TRUE; // test leds MESSAGE_Sleep(1); LED_SetPattern(GUI_LED_TEST_PATTERN1, 1); MESSAGE_Sleep(1); LED_SetPattern(GUI_LED_TEST_PATTERN2, 1); SetPAVolume(0); hal_HstSendEvent(BOOT_EVENT, 0x7e570100); // 10% // test lcd #if APP_SUPPORT_RGBLCD==1 if(AP_Support_LCD()) { GUI_ClearScreen(NULL); GUI_InvertRegion(NULL); GUI_UpdateScreen(NULL); MESSAGE_Sleep(1); GUI_InvertRegion(NULL); GUI_UpdateScreen(NULL); MESSAGE_Sleep(1); } #elif APP_SUPPORT_LCD==1 if(AP_Support_LCD()) { GUI_ClearScreen(NULL); GUI_InvertRegion(NULL); GUI_UpdateScreen(NULL); MESSAGE_Sleep(1); GUI_InvertRegion(NULL); GUI_UpdateScreen(NULL); MESSAGE_Sleep(1); } #elif APP_SUPPORT_LED8S==1 GUI_ClearScreen(NULL); GUI_ResShowPic(0xffff, 0, 0); GUI_UpdateScreen(NULL); COS_Sleep(200); GUI_DisplayText(0, 0, "8"); GUI_UpdateScreen(NULL); COS_Sleep(200); GUI_DisplayText(1, 0, "8"); GUI_UpdateScreen(NULL); COS_Sleep(200); GUI_DisplayText(2, 0, "8"); GUI_UpdateScreen(NULL); COS_Sleep(200); GUI_DisplayText(3, 0, "8"); GUI_UpdateScreen(NULL); COS_Sleep(200); #endif hal_HstSendEvent(BOOT_EVENT, 0x7e570300); // 30% // test fm #if APP_SUPPORT_FM hal_HstSendEvent(SYS_EVENT, 0x11220010); { extern FM_play_status_t *FMStatus; FMStatus = (FM_play_status_t*)NVRAMGetData(VM_AP_RADIO, sizeof(FM_play_status_t)); FM_SendCommand(MC_OPEN, 0); FMStatus->freq = AP_TEST_FM_FREQ1; FM_SendCommand(MC_PLAY, 0); if(!fmd_ValidStop(FMStatus->freq)) { FMStatus->freq = AP_TEST_FM_FREQ2; if(!fmd_ValidStop(FMStatus->freq)) { FMStatus->freq = AP_TEST_FM_FREQ3; if(!fmd_ValidStop(FMStatus->freq)) { goto test_fail; } } } SetPAVolume(0); FM_SendCommand(MC_CLOSE, 0); } #endif hal_HstSendEvent(BOOT_EVENT, 0x7e570500); // 50% // test bluetooth #if APP_SUPPORT_BLUETOOTH==1 hal_HstSendEvent(SYS_EVENT, 0x11220020); { extern bt_vars_t *g_pBT_vars; extern INT8 g_bt_cur_device; g_bt_cur_device = -1; g_pBT_vars = (bt_vars_t*)NVRAMGetData(VM_AP_BLUETOOTH, sizeof(bt_vars_t)); if(BT_Active_Bluetooth() != 0) { goto test_fail; // test_fail } } #endif hal_HstSendEvent(BOOT_EVENT, 0x7e570800); // 80% // test audio #if APP_SUPPORT_MUSIC==1 { hal_HstSendEvent(SYS_EVENT, 0x11220030); if(!MountDisk(FS_DEV_TYPE_TFLASH)) { goto test_fail; // test_fail } hal_HstSendEvent(SYS_EVENT, 0x11220040); if(!fselInit(FSEL_TYPE_MUSIC, FSEL_ALL_SEQUENCE, FSEL_TYPE_COMMONDIR, FS_DEV_TYPE_TFLASH)) { goto test_fail; // test_fail } if(!fselGetNextFile(&g_testfile_entry)) { goto test_fail; // test_fail } hal_HstSendEvent(SYS_EVENT, 0x11220042); hal_HstSendEvent(SYS_EVENT, g_testfile_entry); g_current_fd = FS_OpenDirect(g_testfile_entry, FS_O_RDONLY, 0); hal_HstSendEvent(SYS_EVENT, g_current_fd); if(g_current_fd < 0) { goto test_fail; // test_fail } hal_HstSendEvent(SYS_EVENT, 0x11220050); if(MCI_ERR_NO != MCI_AudioPlay(0, g_current_fd, MCI_TYPE_DAF, play_finished, 0)) { goto test_fail; } SetPAVolume(0); play_end = FALSE; GUI_DisplayMessage(0, 0, "Test Sucess!", GUI_MSG_FLAG_DISPLAY); hal_HstSendEvent(SYS_EVENT, 0x11220060); hal_HstSendEvent(BOOT_EVENT, 0x7e570a00); // 100% hal_HstSendEvent(BOOT_EVENT, 0x7e5752cc); // test success LED_SetPattern(GUI_LED_TEST_SUCESS, LED_LOOP_INFINITE); while(1) { key = MESSAGE_Wait(); if(play_end) { play_end = FALSE; MCI_AudioStop(); MCI_AudioPlay(0, g_current_fd, MCI_TYPE_DAF, play_finished, 0); } #if 1//warkey //按任意键打开音量播放音乐,MODE键退出并重启 if(key == (AP_KEY_MODE | AP_KEY_DOWN)) { MCI_AudioStop(); FS_Close(g_current_fd); RestartSystem(); } else if(((key >> 16) > 0) && ((key >> 16) < MAX_KEYS)) { if((key & 0xffff) == AP_KEY_DOWN) { SetPAVolume(7); } else if((key & 0xffff) == AP_KEY_UP) { SetPAVolume(0); g_test_mode = FALSE; } } #else//原始 if(key == (AP_KEY_PLAY | AP_KEY_DOWN)) { SetPAVolume(7); } else if(key == (AP_KEY_PLAY | AP_KEY_UP)) { SetPAVolume(0); hal_HstSendEvent(BOOT_EVENT, 0x7e5752cc); // test success g_test_mode = FALSE; } else if(key == (AP_KEY_MODE | AP_KEY_DOWN)) { MCI_AudioStop(); FS_Close(g_current_fd); RestartSystem(); } #endif }; } #else hal_HstSendEvent(BOOT_EVENT, 0x7e570a00); // 100% LED_SetPattern(GUI_LED_TEST_SUCESS, LED_LOOP_INFINITE); hal_HstSendEvent(BOOT_EVENT, 0x7e5752cc); // test success g_test_mode = FALSE; while(1) { key = MESSAGE_Wait(); if(key == (AP_KEY_MODE | AP_KEY_DOWN)) { RestartSystem(); } if(key == (AP_KEY_POWER | AP_KEY_DOWN)) { DM_DeviceSwithOff(); } }; #endif test_fail: GUI_DisplayMessage(0, 0, "Test Fail!", GUI_MSG_FLAG_DISPLAY); LED_SetPattern(GUI_LED_TEST_FAIL, LED_LOOP_INFINITE); hal_HstSendEvent(BOOT_EVENT, 0x7e57fa11); // test fail g_test_mode = FALSE; while(1) { key = MESSAGE_Wait(); if(key == (AP_KEY_MODE | AP_KEY_DOWN)) { RestartSystem(); } if(key == (AP_KEY_POWER | AP_KEY_DOWN)) { DM_DeviceSwithOff(); } } }