From ee95cefdff1e371c6435f0dca91f7fa555326f9f Mon Sep 17 00:00:00 2001 From: doyle Date: Fri, 1 Dec 2023 16:46:58 +1100 Subject: [PATCH] fp: Update build script for new tely --- External/tely | 2 +- feely_pona.cpp | 140 ++-- feely_pona_build.cpp | 1227 +++++++++++++++------------------- feely_pona_game.cpp | 12 +- feely_pona_game.h | 4 +- feely_pona_sprite_packer.cpp | 2 + feely_pona_unity.h | 2 +- 7 files changed, 613 insertions(+), 776 deletions(-) diff --git a/External/tely b/External/tely index f23fa22..17b352f 160000 --- a/External/tely +++ b/External/tely @@ -1 +1 @@ -Subproject commit f23fa227c3880beeaf389cf3b14d30e70c6369b5 +Subproject commit 17b352f0b86c538f6e197f7e3428b4c4e321f651 diff --git a/feely_pona.cpp b/feely_pona.cpp index d248d3d..b8ecb41 100644 --- a/feely_pona.cpp +++ b/feely_pona.cpp @@ -127,18 +127,18 @@ static TELY_AssetSpriteSheet FP_LoadSpriteSheetFromSpec(TELY_OS *os, TELY_Assets static void FP_SetDefaultGamepadBindings(FP_GameControls *controls) { // NOTE: Note up/down/left/right uses analog sticks, non-negotiable. - controls->attack.gamepad_key = TELY_OSInputGamepadKey_X; - controls->range_attack.gamepad_key = TELY_OSInputGamepadKey_Y; - controls->build_mode.gamepad_key = TELY_OSInputGamepadKey_L3; - controls->strafe.gamepad_key = TELY_OSInputGamepadKey_B; - controls->dash.gamepad_key = TELY_OSInputGamepadKey_A; - controls->buy_building.gamepad_key = TELY_OSInputGamepadKey_LeftBumper; - controls->buy_upgrade.gamepad_key = TELY_OSInputGamepadKey_RightBumper; - controls->move_building_ui_cursor_left.gamepad_key = TELY_OSInputGamepadKey_DLeft; - controls->move_building_ui_cursor_right.gamepad_key = TELY_OSInputGamepadKey_DRight; + controls->attack.gamepad_key = TELY_InputGamepadKey_X; + controls->range_attack.gamepad_key = TELY_InputGamepadKey_Y; + controls->build_mode.gamepad_key = TELY_InputGamepadKey_L3; + controls->strafe.gamepad_key = TELY_InputGamepadKey_B; + controls->dash.gamepad_key = TELY_InputGamepadKey_A; + controls->buy_building.gamepad_key = TELY_InputGamepadKey_LeftBumper; + controls->buy_upgrade.gamepad_key = TELY_InputGamepadKey_RightBumper; + controls->move_building_ui_cursor_left.gamepad_key = TELY_InputGamepadKey_DLeft; + controls->move_building_ui_cursor_right.gamepad_key = TELY_InputGamepadKey_DRight; } -static FP_ListenForNewPlayerResult FP_ListenForNewPlayer(TELY_OSInput *input, FP_Game *game, bool tutorial_is_allowed) +static FP_ListenForNewPlayerResult FP_ListenForNewPlayer(TELY_Input *input, FP_Game *game, bool tutorial_is_allowed) { FP_ListenForNewPlayerResult result = {}; if (game->play.players.size == 2) @@ -159,16 +159,16 @@ static FP_ListenForNewPlayerResult FP_ListenForNewPlayer(TELY_OSInput *input, FP } } - bool keyboard_pressed = !keyboard_already_allocated && TELY_OSInput_ScanKeyIsPressed(input, TELY_OSInputScanKey_B); - bool gamepad_pressed = TELY_OSInput_GamepadKeyIsPressed(input, gamepad_index, TELY_OSInputGamepadKey_Start); + bool keyboard_pressed = !keyboard_already_allocated && TELY_Input_ScanKeyIsPressed(input, TELY_InputScanKey_B); + bool gamepad_pressed = TELY_Input_GamepadKeyIsPressed(input, gamepad_index, TELY_InputGamepadKey_Start); if (tutorial_is_allowed) { - if (!keyboard_already_allocated && TELY_OSInput_ScanKeyIsPressed(input, TELY_OSInputScanKey_T)) { + if (!keyboard_already_allocated && TELY_Input_ScanKeyIsPressed(input, TELY_InputScanKey_T)) { keyboard_pressed = true; result.tutorial_requested = true; } - if (TELY_OSInput_GamepadKeyIsPressed(input, gamepad_index, TELY_OSInputGamepadKey_Select)) { + if (TELY_Input_GamepadKeyIsPressed(input, gamepad_index, TELY_InputGamepadKey_Select)) { gamepad_pressed = true; result.tutorial_requested = true; } @@ -190,19 +190,19 @@ static FP_ListenForNewPlayerResult FP_ListenForNewPlayer(TELY_OSInput *input, FP FP_GameControls *controls = &terry->controls; if (keyboard_pressed) { controls->mode = FP_GameControlMode_Keyboard; - controls->up.scan_key = TELY_OSInputScanKey_W; - controls->down.scan_key = TELY_OSInputScanKey_S; - controls->left.scan_key = TELY_OSInputScanKey_A; - controls->right.scan_key = TELY_OSInputScanKey_D; - controls->attack.scan_key = TELY_OSInputScanKey_J; - controls->range_attack.scan_key = TELY_OSInputScanKey_K; - controls->build_mode.scan_key = TELY_OSInputScanKey_H; - controls->strafe.scan_key = TELY_OSInputScanKey_L; - controls->dash.scan_key = TELY_OSInputScanKey_N; - controls->buy_building.scan_key = TELY_OSInputScanKey_U; - controls->buy_upgrade.scan_key = TELY_OSInputScanKey_I; - controls->move_building_ui_cursor_left.scan_key = TELY_OSInputScanKey_Q; - controls->move_building_ui_cursor_right.scan_key = TELY_OSInputScanKey_E; + controls->up.scan_key = TELY_InputScanKey_W; + controls->down.scan_key = TELY_InputScanKey_S; + controls->left.scan_key = TELY_InputScanKey_A; + controls->right.scan_key = TELY_InputScanKey_D; + controls->attack.scan_key = TELY_InputScanKey_J; + controls->range_attack.scan_key = TELY_InputScanKey_K; + controls->build_mode.scan_key = TELY_InputScanKey_H; + controls->strafe.scan_key = TELY_InputScanKey_L; + controls->dash.scan_key = TELY_InputScanKey_N; + controls->buy_building.scan_key = TELY_InputScanKey_U; + controls->buy_upgrade.scan_key = TELY_InputScanKey_I; + controls->move_building_ui_cursor_left.scan_key = TELY_InputScanKey_Q; + controls->move_building_ui_cursor_right.scan_key = TELY_InputScanKey_E; } else { controls->mode = FP_GameControlMode_Gamepad; controls->gamepad_index = gamepad_index; @@ -524,7 +524,7 @@ static void FP_AppendMobSpawnerWaypoints(FP_Game *game, FP_GameEntityHandle src_ } } -static void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_OSInput *input, FP_GameEntity *entity, Dqn_V2 *acceleration_meters_per_s) +static void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_Input *input, FP_GameEntity *entity, Dqn_V2 *acceleration_meters_per_s) { TELY_AssetSpriteSheet *sheet = &game->atlas_sprite_sheet; FP_GameEntityAction *action = &entity->action; @@ -1300,7 +1300,7 @@ static void FP_EntityActionStateMachine(FP_Game *game, TELY_Audio *audio, TELY_O } } -static void FP_Update(TELY_OS *os, FP_Game *game, TELY_OSInput *input, TELY_Audio *audio) +static void FP_Update(TELY_OS *os, FP_Game *game, TELY_Input *input, TELY_Audio *audio) { Dqn_Profiler_ZoneScopeWithIndex("FP_Update", FP_ProfileZone_FPUpdate); if (game->play.state == FP_GameState_Pause) @@ -1314,16 +1314,16 @@ static void FP_Update(TELY_OS *os, FP_Game *game, TELY_OSInput *input, TELY_Audi DQN_MSVC_WARNING_PUSH DQN_MSVC_WARNING_DISABLE(4127) // Conditional expression is constant 'FP_DEVELOPER_MODE' - if (FP_DEVELOPER_MODE && TELY_OSInput_KeyIsReleased(input->mouse_left)) + if (FP_DEVELOPER_MODE && TELY_Input_KeyIsReleased(input->mouse_keys[TELY_InputMouseKey_Left])) game->play.clicked_entity = game->play.prev_active_entity; - if (TELY_OSInput_ScanKeyIsPressed(input, TELY_OSInputScanKey_Escape)) { + if (TELY_Input_ScanKeyIsPressed(input, TELY_InputScanKey_Escape)) { game->play.state = FP_GameState_Pause; return; } if (FP_DEVELOPER_MODE && game->play.clicked_entity.id) { - if (TELY_OSInput_ScanKeyIsPressed(input, TELY_OSInputScanKey_Delete)) + if (TELY_Input_ScanKeyIsPressed(input, TELY_InputScanKey_Delete)) FP_Game_DeleteEntity(game, game->play.clicked_entity); } DQN_MSVC_WARNING_POP @@ -1351,7 +1351,7 @@ static void FP_Update(TELY_OS *os, FP_Game *game, TELY_OSInput *input, TELY_Audi // NOTE: Gamepad movement input if (controls->mode == FP_GameControlMode_Gamepad) { - TELY_OSInputGamepad *gamepad = input->gamepads + controls->gamepad_index; + TELY_InputGamepad *gamepad = input->gamepads + controls->gamepad_index; dir_vector += gamepad->left_stick; } @@ -2438,27 +2438,27 @@ static void FP_Update(TELY_OS *os, FP_Game *game, TELY_OSInput *input, TELY_Audi Dqn_Profiler_EndZone(update_zone); } -static Dqn_Str8 FP_ScanKeyToLabel(Dqn_Arena *arena, TELY_OSInputScanKey scan_key) +static Dqn_Str8 FP_ScanKeyToLabel(Dqn_Arena *arena, TELY_InputScanKey scan_key) { Dqn_Str8 result = {}; Dqn_Allocator allocator = Dqn_Arena_Allocator(arena); - if (scan_key >= TELY_OSInputScanKey_A && scan_key <= TELY_OSInputScanKey_Z) { - char scan_key_ch = DQN_CAST(char)('A' + (scan_key - TELY_OSInputScanKey_A)); + if (scan_key >= TELY_InputScanKey_A && scan_key <= TELY_InputScanKey_Z) { + char scan_key_ch = DQN_CAST(char)('A' + (scan_key - TELY_InputScanKey_A)); result = Dqn_Str8_InitF(allocator, "[%c]", scan_key_ch); } else { - if (scan_key == TELY_OSInputScanKey_Up) { + if (scan_key == TELY_InputScanKey_Up) { result = Dqn_Str8_InitF(allocator, "[Up]"); - } else if (scan_key == TELY_OSInputScanKey_Down) { + } else if (scan_key == TELY_InputScanKey_Down) { result = Dqn_Str8_InitF(allocator, "[Down]"); - } else if (scan_key == TELY_OSInputScanKey_Left) { + } else if (scan_key == TELY_InputScanKey_Left) { result = Dqn_Str8_InitF(allocator, "[Left]"); - } else if (scan_key == TELY_OSInputScanKey_Right) { + } else if (scan_key == TELY_InputScanKey_Right) { result = Dqn_Str8_InitF(allocator, "[Right]"); - } else if (scan_key == TELY_OSInputScanKey_Semicolon) { + } else if (scan_key == TELY_InputScanKey_Semicolon) { result = Dqn_Str8_InitF(allocator, "[;]"); - } else if (scan_key == TELY_OSInputScanKey_Apostrophe) { + } else if (scan_key == TELY_InputScanKey_Apostrophe) { result = Dqn_Str8_InitF(allocator, "[']"); - } else if (scan_key == TELY_OSInputScanKey_Backslash) { + } else if (scan_key == TELY_InputScanKey_Backslash) { result = Dqn_Str8_InitF(allocator, "[/]"); } } @@ -2481,13 +2481,13 @@ static void FP_DrawBillboardKeyBindHint(TELY_Renderer *renderer, if (mode == FP_GameControlMode_Gamepad) { Dqn_Str8 tex_name = {}; - if (key_bind.gamepad_key == TELY_OSInputGamepadKey_A) + if (key_bind.gamepad_key == TELY_InputGamepadKey_A) tex_name = g_anim_names.merchant_button_a; - else if (key_bind.gamepad_key == TELY_OSInputGamepadKey_B) + else if (key_bind.gamepad_key == TELY_InputGamepadKey_B) tex_name = g_anim_names.merchant_button_b; - else if (key_bind.gamepad_key == TELY_OSInputGamepadKey_X) + else if (key_bind.gamepad_key == TELY_InputGamepadKey_X) tex_name = g_anim_names.merchant_button_x; - else if (key_bind.gamepad_key == TELY_OSInputGamepadKey_Y) + else if (key_bind.gamepad_key == TELY_InputGamepadKey_Y) tex_name = g_anim_names.merchant_button_y; if (tex_name.size) { @@ -2518,7 +2518,7 @@ static void FP_DrawBillboardKeyBindHint(TELY_Renderer *renderer, static void FP_Render(FP_Game *game, TELY_OS *os, TELY_Renderer *renderer, TELY_Audio *audio) { Dqn_Profiler_ZoneScopeWithIndex("FP_Render", FP_ProfileZone_FPRender); - TELY_OSInput *input = &os->input; + TELY_Input *input = &os->input; TELY_RFui *rfui = &game->rfui; TELY_Assets *assets = &os->assets; @@ -3320,13 +3320,13 @@ static void FP_Render(FP_Game *game, TELY_OS *os, TELY_Renderer *renderer, TELY_ bool trigger_buy_anim = false; if (have_enough_coins) { - if (TELY_OSInput_ScanKeyIsPressed(input, key_bind.scan_key)) { + if (TELY_Input_ScanKeyIsPressed(input, key_bind.scan_key)) { game->play.player_trigger_purchase_building_timestamp = game->play.clock_ms + buy_duration_ms; - } else if (TELY_OSInput_ScanKeyIsDown(input, key_bind.scan_key)) { + } else if (TELY_Input_ScanKeyIsDown(input, key_bind.scan_key)) { trigger_buy_anim = true; if (game->play.clock_ms > game->play.player_trigger_purchase_building_timestamp) game->play.player_trigger_purchase_building_timestamp = game->play.clock_ms; - } else if (TELY_OSInput_ScanKeyIsReleased(input, key_bind.scan_key)) { + } else if (TELY_Input_ScanKeyIsReleased(input, key_bind.scan_key)) { if (game->play.clock_ms > game->play.player_trigger_purchase_building_timestamp) { if (mapping.inventory_count) { player->coins -= *mapping.building_base_price; @@ -3452,13 +3452,13 @@ static void FP_Render(FP_Game *game, TELY_OS *os, TELY_Renderer *renderer, TELY_ bool trigger_buy_anim = false; if (have_enough_coins) { - if (TELY_OSInput_ScanKeyIsPressed(input, key_bind.scan_key)) { + if (TELY_Input_ScanKeyIsPressed(input, key_bind.scan_key)) { game->play.player_trigger_purchase_upgrade_timestamp = game->play.clock_ms + buy_duration_ms; - } else if (TELY_OSInput_ScanKeyIsDown(input, key_bind.scan_key)) { + } else if (TELY_Input_ScanKeyIsDown(input, key_bind.scan_key)) { trigger_buy_anim = true; if (game->play.clock_ms > game->play.player_trigger_purchase_upgrade_timestamp) game->play.player_trigger_purchase_upgrade_timestamp = game->play.clock_ms; - } else if (TELY_OSInput_ScanKeyIsReleased(input, key_bind.scan_key)) { + } else if (TELY_Input_ScanKeyIsReleased(input, key_bind.scan_key)) { if (game->play.clock_ms > game->play.player_trigger_purchase_upgrade_timestamp) { player->coins -= *mapping.upgrade_base_price; *mapping.upgrade_base_price *= 1; @@ -3996,7 +3996,7 @@ static void FP_Render(FP_Game *game, TELY_OS *os, TELY_Renderer *renderer, TELY_ TELY_Render_PopFont(renderer); TELY_Render_PopColourV4(renderer); - if (TELY_OSInput_ScanKeyIsPressed(input, TELY_OSInputScanKey_Return)) + if (TELY_Input_ScanKeyIsPressed(input, TELY_InputScanKey_Return)) game->play.state = FP_GameState_Play; } @@ -4160,7 +4160,7 @@ static void FP_Render(FP_Game *game, TELY_OS *os, TELY_Renderer *renderer, TELY_ TELY_Render_PopFont(renderer); TELY_Render_PopColourV4(renderer); - if (TELY_OSInput_ScanKeyIsPressed(input, TELY_OSInputScanKey_Return)) + if (TELY_Input_ScanKeyIsPressed(input, TELY_InputScanKey_Return)) FP_PlayReset(game, os); } @@ -4208,7 +4208,7 @@ static void FP_Render(FP_Game *game, TELY_OS *os, TELY_Renderer *renderer, TELY_ // NOTE: Debug UI ============================================================================== - if (TELY_OSInput_ScanKeyIsPressed(input, TELY_OSInputScanKey_F1)) + if (TELY_Input_ScanKeyIsPressed(input, TELY_InputScanKey_F1)) game->play.debug_ui = !game->play.debug_ui; DQN_MSVC_WARNING_PUSH @@ -4289,23 +4289,23 @@ static void FP_Render(FP_Game *game, TELY_OS *os, TELY_Renderer *renderer, TELY_ if (TELY_RFui_ButtonF(rfui, "F1 Debug info").clicked) game->play.debug_ui = !game->play.debug_ui; - if (TELY_RFui_ButtonF(rfui, "F2 Add coins x10,000").clicked || TELY_OSInput_ScanKeyIsPressed(input, TELY_OSInputScanKey_F2)) { + if (TELY_RFui_ButtonF(rfui, "F2 Add coins x10,000").clicked || TELY_Input_ScanKeyIsPressed(input, TELY_InputScanKey_F2)) { for (FP_GameEntityHandle player_handle : game->play.players) { FP_GameEntity *player = FP_Game_GetEntity(game, player_handle); player->coins += 10'000; } } - if (TELY_RFui_ButtonF(rfui, "F3 Win game").clicked || TELY_OSInput_ScanKeyIsPressed(input, TELY_OSInputScanKey_F3)) + if (TELY_RFui_ButtonF(rfui, "F3 Win game").clicked || TELY_Input_ScanKeyIsPressed(input, TELY_InputScanKey_F3)) game->play.state = FP_GameState_WinGame; - if (TELY_RFui_ButtonF(rfui, "F4 Lose game").clicked || TELY_OSInput_ScanKeyIsPressed(input, TELY_OSInputScanKey_F4)) + if (TELY_RFui_ButtonF(rfui, "F4 Lose game").clicked || TELY_Input_ScanKeyIsPressed(input, TELY_InputScanKey_F4)) game->play.state = FP_GameState_LoseGame; - if (TELY_RFui_ButtonF(rfui, "F5 Reset game").clicked || TELY_OSInput_ScanKeyIsPressed(input, TELY_OSInputScanKey_F5)) + if (TELY_RFui_ButtonF(rfui, "F5 Reset game").clicked || TELY_Input_ScanKeyIsPressed(input, TELY_InputScanKey_F5)) FP_PlayReset(game, os); - if (TELY_RFui_ButtonF(rfui, "F6 Increase health").clicked || TELY_OSInput_ScanKeyIsPressed(input, TELY_OSInputScanKey_F6)) { + if (TELY_RFui_ButtonF(rfui, "F6 Increase health").clicked || TELY_Input_ScanKeyIsPressed(input, TELY_InputScanKey_F6)) { for (FP_GameEntityHandle player_handle : game->play.players) { FP_GameEntity *player = FP_Game_GetEntity(game, player_handle); player->hp_cap += FP_DEFAULT_DAMAGE; @@ -4313,7 +4313,7 @@ static void FP_Render(FP_Game *game, TELY_OS *os, TELY_Renderer *renderer, TELY_ } } - if (TELY_RFui_ButtonF(rfui, "F7 Increase stamina").clicked || TELY_OSInput_ScanKeyIsPressed(input, TELY_OSInputScanKey_F7)) { + if (TELY_RFui_ButtonF(rfui, "F7 Increase stamina").clicked || TELY_Input_ScanKeyIsPressed(input, TELY_InputScanKey_F7)) { for (FP_GameEntityHandle player_handle : game->play.players) { FP_GameEntity *player = FP_Game_GetEntity(game, player_handle); player->stamina_cap += DQN_CAST(uint16_t)(FP_TERRY_DASH_STAMINA_COST * .5f); @@ -4321,7 +4321,7 @@ static void FP_Render(FP_Game *game, TELY_OS *os, TELY_Renderer *renderer, TELY_ } } - if (TELY_RFui_ButtonF(rfui, "F8 Increase mobile data").clicked || TELY_OSInput_ScanKeyIsPressed(input, TELY_OSInputScanKey_F8)) { + if (TELY_RFui_ButtonF(rfui, "F8 Increase mobile data").clicked || TELY_Input_ScanKeyIsPressed(input, TELY_InputScanKey_F8)) { for (FP_GameEntityHandle player_handle : game->play.players) { FP_GameEntity *player = FP_Game_GetEntity(game, player_handle); player->terry_mobile_data_plan_cap += DQN_KILOBYTES(1); @@ -4329,10 +4329,10 @@ static void FP_Render(FP_Game *game, TELY_OS *os, TELY_Renderer *renderer, TELY_ } } - if (TELY_RFui_ButtonF(rfui, "F9 %s god mode", game->play.god_mode ? "Disable" : "Enable").clicked || TELY_OSInput_ScanKeyIsPressed(input, TELY_OSInputScanKey_F9)) + if (TELY_RFui_ButtonF(rfui, "F9 %s god mode", game->play.god_mode ? "Disable" : "Enable").clicked || TELY_Input_ScanKeyIsPressed(input, TELY_InputScanKey_F9)) game->play.god_mode = !game->play.god_mode; - if (TELY_RFui_ButtonF(rfui, "F11 Building inventory +1").clicked || TELY_OSInput_ScanKeyIsPressed(input, TELY_OSInputScanKey_F11)) { + if (TELY_RFui_ButtonF(rfui, "F11 Building inventory +1").clicked || TELY_Input_ScanKeyIsPressed(input, TELY_InputScanKey_F11)) { for (FP_GameEntityHandle player_handle : game->play.players) { FP_GameEntity *player = FP_Game_GetEntity(game, player_handle); player->inventory.clubs += 1; @@ -4342,7 +4342,7 @@ static void FP_Render(FP_Game *game, TELY_OS *os, TELY_Renderer *renderer, TELY_ } } - if (TELY_RFui_ButtonF(rfui, "1 %s HUD", game->play.debug_hide_hud ? "Show" : "Hide").clicked || TELY_OSInput_ScanKeyIsPressed(input, TELY_OSInputScanKey_1)) + if (TELY_RFui_ButtonF(rfui, "1 %s HUD", game->play.debug_hide_hud ? "Show" : "Hide").clicked || TELY_Input_ScanKeyIsPressed(input, TELY_InputScanKey_1)) game->play.debug_hide_hud = !game->play.debug_hide_hud; if (TELY_RFui_ButtonF(rfui, "%s bounding rects", game->play.debug_hide_bounding_rectangles ? "Show" : "Hide").clicked) @@ -4449,7 +4449,7 @@ static void FP_Render(FP_Game *game, TELY_OS *os, TELY_Renderer *renderer, TELY_ TELY_OS_DLL_FUNCTION void TELY_OS_DLLFrameUpdate(TELY_OS *os) { - TELY_OSInput *input = &os->input; + TELY_Input *input = &os->input; TELY_Renderer *renderer = &os->renderer; FP_Game *game = DQN_CAST(FP_Game *) os->user_data; @@ -4466,7 +4466,7 @@ void TELY_OS_DLLFrameUpdate(TELY_OS *os) // ============================================================================================= if (game->play.state == FP_GameState_Play || game->play.state == FP_GameState_Tutorial) { - if (TELY_OSInput_KeyWasDown(input->mouse_left) && TELY_OSInput_KeyIsDown(input->mouse_left)) { + if (TELY_Input_KeyWasDown(input->mouse_keys[TELY_InputMouseKey_Left]) && TELY_Input_KeyIsDown(input->mouse_keys[TELY_InputMouseKey_Left])) { if (game->play.prev_active_entity.id) game->play.active_entity = game->play.prev_active_entity; } else { @@ -4486,7 +4486,7 @@ void TELY_OS_DLLFrameUpdate(TELY_OS *os) continue; game->play.hot_entity = entity->handle; - if (TELY_OSInput_KeyIsPressed(input->mouse_left)) { + if (TELY_Input_KeyIsPressed(input->mouse_keys[TELY_InputMouseKey_Left])) { game->play.active_entity = entity->handle; game->play.clicked_entity = entity->handle; } diff --git a/feely_pona_build.cpp b/feely_pona_build.cpp index 8be7221..6857b74 100644 --- a/feely_pona_build.cpp +++ b/feely_pona_build.cpp @@ -1,115 +1,32 @@ -// #include - -#include - #define DQN_IMPLEMENTATION #include "External/tely/External/dqn/dqn.h" #define DQN_CPP_BUILD_IMPLEMENTATION #include "External/tely/External/dqn/dqn_cppbuild.h" -#if 0 -void RebuildProgramIfRequired(int argc, char const **argv) +struct BuildTime { - Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr); - Dqn_Str8 const exe_dir = Dqn_OS_EXEDir(scratch.arena); - Dqn_Str8 build_program_path = Dqn_OS_EXEPath(scratch.arena); - Dqn_FsInfo build_program_info = Dqn_Fs_GetInfo(build_program_path); - Dqn_FsInfo source_path = Dqn_Fs_GetInfo(Dqn_Str8_InitCStr8(__FILE__)); + Dqn_Str8 name; + uint64_t timestamps[2]; +}; - if (!build_program_info.exists) { - Dqn_WinError error = Dqn_Win_LastError(scratch.arena); - Dqn_Log_WarningF("Failed to get the last write time of the build program '%.*s', skipping rebuild (%d): %.*s", - DQN_STR_FMT(build_program_path), error.code, DQN_STR_FMT(error.msg)); - return; - } - - if (!source_path.exists) { - Dqn_WinError error = Dqn_Win_LastError(scratch.arena); - Dqn_Log_WarningF( - "Failed to get the last write time of the build program's source code '%s', skipping rebuild (%d): %.*s", - __FILE__, error.code, DQN_STR_FMT(error.msg)); - return; - } - - // NOTE: The build program is newer than the source path, no rebuild required - if (source_path.last_write_time_in_s < build_program_info.last_write_time_in_s) { - return; - } - - Dqn_Log_InfoF("Build program source code has changed, rebuilding the program (timestamps changed source was %I64u, build program was %I64u)", - source_path.last_write_time_in_s, - build_program_info.last_write_time_in_s); - - Dqn_Str8 temp_build_program_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s.old", DQN_STR_FMT(build_program_path)); - if (!Dqn_Fs_Move(build_program_path, temp_build_program_path, true)) { - Dqn_WinError error = Dqn_Win_LastError(scratch.arena); - Dqn_Log_WarningF("Failed to backup the build program for rebuilding, skipping rebuild (%d): %.*s", error.code, DQN_STR_FMT(error.msg)); - return; - } - - // NOTE: Rebuild the build program because a change was detected =============== - Dqn_Str8 rebuild_cmd = Dqn_Str8_InitF(scratch.allocator, "cl -Z7 -W4 -nologo %s /incremental:no /link", __FILE__); - Dqn_OSExecResult rebuild_result = Dqn_OS_Exec(rebuild_cmd, exe_dir /*working_dir*/); - if (rebuild_result.os_error_code) { - Dqn_WinError error = Dqn_Win_LastError(scratch.arena); - Dqn_Log_ErrorF("Detected change in the build program's source code '%s' but the OS failed to rebuild the program, skipping rebuild (%d): %.*s", __FILE__, error.code, DQN_STR_FMT(error.msg)); - return; - } - - if (rebuild_result.exit_code) { - Dqn_Fs_Move(temp_build_program_path, build_program_path, true); - exit(rebuild_result.exit_code); - } - - Dqn_Str8Builder builder = {}; - builder.allocator = scratch.allocator; - DQN_FOR_UINDEX (arg_index, argc) - Dqn_Str8Builder_AppendF(&builder, "%s%s", arg_index ? " " : "", argv[arg_index]); - - Dqn_Str8 rebootstrap_cmd = Dqn_Str8Builder_Build(&builder, scratch.allocator); - Dqn_OSExecResult exec_result = Dqn_OS_Exec(rebootstrap_cmd, exe_dir /*working_dir*/); - if (exec_result.os_error_code) { - Dqn_WinError error = Dqn_Win_LastError(scratch.arena); - Dqn_Log_ErrorF("Detected change in the build program's source code '%s' but the OS failed to rebuild the program, skipping rebuild (%d): %.*s", __FILE__, error.code, DQN_STR_FMT(error.msg)); - Dqn_Fs_Move(temp_build_program_path, build_program_path, true); - return; - } - - exit(exec_result.exit_code); -} -#endif +enum Compiler +{ + Compiler_MSVC, + Compiler_GCC, + Compiler_EMCC, + Compiler_Count, +}; #define PRINT_HELP Dqn_Print_StdLnF(Dqn_PrintStd_Out, "USAGE: feely_pona_build [--help|--dry-run|--web|--fast-dev-build|--msvc|--gcc]") int main(int argc, char const **argv) { + // NOTE: Preamble ============================================================================== Dqn_Library_Init(Dqn_LibraryOnInit_Nil); - - bool dry_run = false; - bool target_web = false; - bool dev_fast_build = false; - bool msvc_build = false; - bool gcc_build = false; - for (Dqn_isize arg_index = 1; arg_index < argc; arg_index++) { - Dqn_Str8 arg = Dqn_Str8_InitCStr8(argv[arg_index]); - if (arg == DQN_STR8("--help")) { - PRINT_HELP; - return 0; - } else if (arg == DQN_STR8("--dry-run")) { - dry_run = true; - } else if (arg == DQN_STR8("--web")) { - target_web = true; - } else if (arg == DQN_STR8("--fast-dev-build")) { - dev_fast_build = true; - } else if (arg == DQN_STR8("--gcc")) { - gcc_build = true; - } else if (arg == DQN_STR8("--msvc")) { - msvc_build = true; - } else { - PRINT_HELP; - return 0; - } - } + Dqn_FArray32 build_timings = {}; + BuildTime *global_build_timings = Dqn_FArray_Make(&build_timings, Dqn_ZeroMem_Yes); + global_build_timings->name = DQN_STR8("Dqn_CPPBuild Summary (Total)"); + global_build_timings->timestamps[0] = Dqn_OS_PerfCounterNow(); #if 0 RebuildProgramIfRequired(argc, argv); @@ -117,661 +34,579 @@ int main(int argc, char const **argv) Dqn_Print_StdLnF(Dqn_PrintStd_Out, "-- Dqn_CPPBuild v0"); #endif - if (msvc_build && gcc_build) { - Dqn_Print_StdLnF(Dqn_PrintStd_Out, - "Both '--msvc' and '--gcc' were specified but only one is supported at a time for this build program."); - return -1; - } + bool build_using_compiler[Compiler_Count] = {}; - if (!msvc_build && !gcc_build) { - #if defined(DQN_OS_WIN32) - msvc_build = true; - #else - gcc_build = true; - #endif - } - - Dqn_Print_StdLnF(Dqn_PrintStd_Out, "Building for %s", msvc_build ? "Windows" : "Linux"); - - uint64_t build_timings[2] = {}; - build_timings[0] = Dqn_OS_PerfCounterNow(); - Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr); - Dqn_Str8 const exe_dir = Dqn_OS_EXEDir(scratch.arena); - Dqn_Str8 const code_dir = exe_dir; - Dqn_Str8 const build_dir = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Build", DQN_STR_FMT(exe_dir)); - Dqn_Str8 const tely_dir = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/External/tely", DQN_STR_FMT(exe_dir)); - Dqn_CPPBuildFlagsStyle flags_style = msvc_build ? Dqn_CPPBuildFlagsStyle_MSVC : Dqn_CPPBuildFlagsStyle_GCC; - - Dqn_FArray32 common_compile_flags = {}; - Dqn_FArray32 common_link_flags = {}; - if (msvc_build) { - Dqn_FArray_AddAssert(&common_compile_flags, DQN_STR8("cl")); - Dqn_FArray_AddAssert(&common_compile_flags, DQN_STR8("-W4")); - Dqn_FArray_AddAssert(&common_compile_flags, DQN_STR8("-Z7")); - Dqn_FArray_AddAssert(&common_compile_flags, DQN_STR8("-MT")); - Dqn_FArray_AddAssert(&common_compile_flags, DQN_STR8("-EHsc")); - Dqn_FArray_AddAssert(&common_compile_flags, DQN_STR8("-nologo")); - - Dqn_FArray_AddAssert(&common_link_flags, DQN_STR8("-link")); - Dqn_FArray_AddAssert(&common_link_flags, DQN_STR8("-incremental:no")); - } else { - Dqn_FArray_AddAssert(&common_compile_flags, DQN_STR8("g++")); - Dqn_FArray_AddAssert(&common_compile_flags, DQN_STR8("-Wall")); - Dqn_FArray_AddAssert(&common_compile_flags, DQN_STR8("-g")); - - Dqn_FArray_AddAssert(&common_link_flags, DQN_STR8("-lm")); - } - - // NOTE: Assets ================================================================================ - uint64_t robocopy_timings[2] = {}; - { - robocopy_timings[0] = Dqn_OS_PerfCounterNow(); - DQN_DEFER { robocopy_timings[1] = Dqn_OS_PerfCounterNow(); }; - - Dqn_FArray8 common_copy_cmd_args = {}; - if (msvc_build) { - Dqn_FArray_AddCArrayAssert(&common_copy_cmd_args, { - DQN_STR8("robocopy"), - DQN_STR8("/NJH"), - DQN_STR8("/NJS"), - DQN_STR8("/NDL"), - DQN_STR8("/NP"), - }); + // NOTE: Parse arguments ======================================================================= + bool dry_run = false; + bool fast_dev_build = false; + for (Dqn_isize arg_index = 1; arg_index < argc; arg_index++) { + Dqn_Str8 arg = Dqn_Str8_InitCStr8(argv[arg_index]); + if (arg == DQN_STR8("--help")) { + PRINT_HELP; + return 0; + } else if (arg == DQN_STR8("--dry-run")) { + dry_run = true; + } else if (arg == DQN_STR8("--fast-dev-build")) { + fast_dev_build = true; + } else if (arg == DQN_STR8("--gcc")) { + build_using_compiler[Compiler_GCC] = true; + } else if (arg == DQN_STR8("--msvc")) { + build_using_compiler[Compiler_MSVC] = true; + } else if (arg == DQN_STR8("--web")) { + build_using_compiler[Compiler_EMCC] = true; } else { - Dqn_FArray_AddCArrayAssert(&common_copy_cmd_args, { - DQN_STR8("cp"), - DQN_STR8("--recursive"), - }); - } - - Dqn_Str8 textures_dest = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Data/Textures", DQN_STR_FMT(build_dir)); - DQN_HARD_ASSERT(Dqn_Fs_MakeDir(textures_dest)); - - Dqn_FArray8> copy_cmd_list = {}; - if (msvc_build) { - Dqn_FArray8 copy_atlas = common_copy_cmd_args; - Dqn_FArray_AddCArrayAssert(©_atlas, { - Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Data/Textures", DQN_STR_FMT(exe_dir)), - Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Data/Textures atlas.*", DQN_STR_FMT(build_dir)), - }); - Dqn_FArray_Add(©_cmd_list, copy_atlas); - } else { - Dqn_FArray8 copy_atlas_txt = common_copy_cmd_args; - Dqn_FArray_AddCArrayAssert(©_atlas_txt, { - Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Data/Textures/atlas.txt", DQN_STR_FMT(exe_dir)), - textures_dest, - }); - Dqn_FArray_Add(©_cmd_list, copy_atlas_txt); - - Dqn_FArray8 copy_atlas_png = common_copy_cmd_args; - Dqn_FArray_AddCArrayAssert(©_atlas_png, { - Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Data/Textures/atlas.png", DQN_STR_FMT(exe_dir)), - textures_dest, - }); - Dqn_FArray_Add(©_cmd_list, copy_atlas_png); - } - - Dqn_FArray8 copy_fonts_cmd = common_copy_cmd_args; - Dqn_FArray_AddCArrayAssert(©_fonts_cmd, { - Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Data/Fonts", DQN_STR_FMT(exe_dir)), - Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Data/Fonts", DQN_STR_FMT(build_dir)), - }); - Dqn_FArray_Add(©_cmd_list, copy_fonts_cmd); - - Dqn_FArray8 copy_audio_cmd = common_copy_cmd_args; - Dqn_FArray_AddCArrayAssert(©_audio_cmd, { - Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Data/Audio", DQN_STR_FMT(exe_dir)), - Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Data/Audio", DQN_STR_FMT(build_dir)), - }); - Dqn_FArray_Add(©_cmd_list, copy_audio_cmd); - - for (Dqn_FArray8 const ©_cmd : copy_cmd_list) { - Dqn_Slice copy_cmd_slice = Dqn_FArray_Slice(©_cmd); - Dqn_Str8 rendered_line = Dqn_Slice_Str8Render(scratch.arena, copy_cmd_slice, DQN_STR8(" ")); - Dqn_Print_StdLnF(Dqn_PrintStd_Out, "[BUILD] Executing '%.*s'", DQN_STR_FMT(rendered_line)); - if (!dry_run) { - if (msvc_build) { - // NOTE: Robocopy returns 1 on success so we don't use the ExecOrAbort function - Dqn_OS_Exec(copy_cmd_slice, /*working_dir*/ {}); - } else { - Dqn_OS_ExecOrAbort(copy_cmd_slice, /*working_dir*/ {}); - } - } + PRINT_HELP; + return 0; } } - // NOTE: Raylib ================================================================================ - Dqn_Str8 const raylib_dir = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/External/tely/External/raylib", DQN_STR_FMT(exe_dir)); - Dqn_Slice const raylib_base_files = Dqn_Slice_InitCArray(scratch.arena, { - Dqn_FsPath_ConvertF(scratch.arena, "%.*s/rcore.c", DQN_STR_FMT(raylib_dir)), - Dqn_FsPath_ConvertF(scratch.arena, "%.*s/utils.c", DQN_STR_FMT(raylib_dir)), - Dqn_FsPath_ConvertF(scratch.arena, "%.*s/raudio.c", DQN_STR_FMT(raylib_dir)), - Dqn_FsPath_ConvertF(scratch.arena, "%.*s/rmodels.c", DQN_STR_FMT(raylib_dir)), - Dqn_FsPath_ConvertF(scratch.arena, "%.*s/rtext.c", DQN_STR_FMT(raylib_dir)), - Dqn_FsPath_ConvertF(scratch.arena, "%.*s/rtextures.c", DQN_STR_FMT(raylib_dir)), - Dqn_FsPath_ConvertF(scratch.arena, "%.*s/rshapes.c", DQN_STR_FMT(raylib_dir)), - }); - - Dqn_FArray32 raylib_pc_output_files = {}; - uint64_t raylib_pc_timings[2] = {}; + // NOTE: Add a default compiler target if none were specified { - raylib_pc_timings[0] = Dqn_OS_PerfCounterNow(); - DQN_DEFER { raylib_pc_timings[1] = Dqn_OS_PerfCounterNow(); }; + size_t total_compiler_targets = 0; + for (bool is_set : build_using_compiler) + total_compiler_targets += DQN_CAST(size_t)is_set; - // NOTE: Setup raylib build context ======================================================== - Dqn_FArray32 compile_flags = {}; - Dqn_CPPBuildContext build_context = {}; - { - build_context.include_dirs = Dqn_Slice_InitCArray(scratch.arena, { - Dqn_FsPath_ConvertF(scratch.arena, "%.*s", DQN_STR_FMT(raylib_dir)), - Dqn_FsPath_ConvertF(scratch.arena, "%.*s/external/glfw/include", DQN_STR_FMT(raylib_dir)), - Dqn_FsPath_ConvertF(scratch.arena, "%.*s/glfw/deps/mingw", DQN_STR_FMT(raylib_dir)), - }); - - if (msvc_build) { - Dqn_FArray_AddCArrayAssert(&compile_flags, { - DQN_STR8("cl"), - DQN_STR8("-w"), - DQN_STR8("-Z7"), - DQN_STR8("-MT"), - DQN_STR8("-EHsc"), - DQN_STR8("-nologo"), - }); - } else { - Dqn_FArray_AddCArrayAssert(&compile_flags, { - DQN_STR8("gcc"), - DQN_STR8("-g"), - }); - } - - Dqn_FArray_AddCArrayAssert(&compile_flags, { - DQN_STR8("-c"), // Compile object files only - DQN_STR8("-D"), DQN_STR8("_DEFAULT_SOURCE"), - DQN_STR8("-D"), DQN_STR8("PLATFORM_DESKTOP"), - }); - - build_context.build_dir = build_dir; - build_context.compile_flags = Dqn_FArray_Slice(&compile_flags); - build_context.flags_style = flags_style; - } - - // NOTE: Compile each file separately with a custom output name ============================ - for (Dqn_Str8 base_file : raylib_base_files) { - Dqn_Str8 file_stem = Dqn_Str8_FileNameNoExtension(base_file); - - Dqn_CPPBuildCompileFile build_file = {}; - build_file.input_file_path = base_file; - build_file.output_file_path = Dqn_Str8_InitF(scratch.allocator, "raylib_%.*s.%s", DQN_STR_FMT(file_stem), msvc_build ? "obj" : "o"); - build_context.compile_files = Dqn_Slice_Init(&build_file, 1); - Dqn_FArray_AddAssert(&raylib_pc_output_files, build_file.output_file_path); - - Dqn_Str8 cmd = Dqn_CPPBuild_ToCommandLineStr8(build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.arena); - Dqn_Print_StdLnF(Dqn_PrintStd_Out, "[BUILD] Executing '%.*s'", DQN_STR_FMT(cmd)); - if (!dry_run) - Dqn_CPPBuild_ExecOrAbort(build_context, Dqn_CPPBuildMode_CacheBuild); - } - - // NOTE: Build rlgfw ======================================================================= - { - Dqn_CPPBuildCompileFile build_file = {}; - build_file.input_file_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/rglfw.c", DQN_STR_FMT(raylib_dir)); - build_file.output_file_path = Dqn_Str8_InitF(scratch.allocator, "raylib_rglfw.%s", msvc_build ? "obj" : "o"); - build_context.compile_files = Dqn_Slice_InitCArray(scratch.arena, {build_file}); - Dqn_FArray_AddAssert(&raylib_pc_output_files, build_file.output_file_path); - - Dqn_Str8 cmd = Dqn_CPPBuild_ToCommandLineStr8(build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.arena); - Dqn_Print_StdLnF(Dqn_PrintStd_Out, "[BUILD] Executing '%.*s'", DQN_STR_FMT(cmd)); - if (!dry_run) - Dqn_CPPBuild_ExecOrAbort(build_context, Dqn_CPPBuildMode_CacheBuild); - } - } - - // NOTE: sokol_audio ================================================================================ - Dqn_Str8 sokol_audio_source_code_file = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/External/sokol/sokol_audio.c", DQN_STR_FMT(tely_dir)); - uint64_t sokol_audio_pc_timings[2] = {}; - Dqn_FArray32 sokol_audio_pc_output_files = {}; - { - sokol_audio_pc_timings[0] = Dqn_OS_PerfCounterNow(); - DQN_DEFER { sokol_audio_pc_timings[1] = Dqn_OS_PerfCounterNow(); }; - - - Dqn_Str8 output_file = Dqn_Str8_InitF(scratch.allocator, "sokol_audio.%s", msvc_build ? "obj" : "o"); - Dqn_CPPBuildContext build_context = {}; - build_context.flags_style = flags_style; - build_context.compile_files = Dqn_Slice_InitCArray(scratch.arena, { - Dqn_CPPBuildCompileFile{ - {}, // Prefix flags - {}, // Suffix flags - sokol_audio_source_code_file, - output_file, - }, - }); - - Dqn_FArray_AddAssert(&sokol_audio_pc_output_files, output_file); - - Dqn_FArray32 compile_flags = common_compile_flags; - Dqn_FArray_AddAssert(&compile_flags, DQN_STR8("-c")); - - build_context.compile_flags = Dqn_FArray_Slice(&compile_flags); - build_context.build_dir = build_dir; - - Dqn_Str8 cmd = Dqn_CPPBuild_ToCommandLineStr8(build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.arena); - Dqn_Print_StdLnF(Dqn_PrintStd_Out, "[BUILD] Executing '%.*s'", DQN_STR_FMT(cmd)); - if (!dry_run) - Dqn_CPPBuild_ExecOrAbort(build_context, Dqn_CPPBuildMode_CacheBuild); - } - - // NOTE: Feely Pona Sprite Packer ============================================================== - uint64_t feely_pona_sprite_packer_timings[2] = {}; - if (msvc_build) { - feely_pona_sprite_packer_timings[0] = Dqn_OS_PerfCounterNow(); - DQN_DEFER { feely_pona_sprite_packer_timings[1] = Dqn_OS_PerfCounterNow(); }; - - Dqn_CPPBuildContext build_context = {}; - build_context.flags_style = flags_style; - build_context.compile_files = Dqn_Slice_InitCArray(scratch.arena, { - Dqn_CPPBuildCompileFile{{} /*Prefix flags*/, {} /*Suffix flags*/, Dqn_FsPath_ConvertF(scratch.arena, "%.*s/feely_pona_sprite_packer.cpp", DQN_STR_FMT(code_dir)) }, - }); - - build_context.compile_flags = Dqn_FArray_Slice(&common_compile_flags); - build_context.link_flags = Dqn_FArray_Slice(&common_link_flags); - build_context.build_dir = build_dir; - - Dqn_Str8 cmd = Dqn_CPPBuild_ToCommandLineStr8(build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.arena); - Dqn_Print_StdLnF(Dqn_PrintStd_Out, "[BUILD] Executing '%.*s'", DQN_STR_FMT(cmd)); - if (!dry_run) - Dqn_CPPBuild_ExecOrAbort(build_context, Dqn_CPPBuildMode_CacheBuild); - } - - // NOTE: Feely Pona Link Flags ================================================================= - Dqn_FArray32 feely_pona_platform_link_flags = common_link_flags; - { - // NOTE: Link to raylib object files and windows libs ====================================== - Dqn_FArray_AddArrayAssert(&feely_pona_platform_link_flags, raylib_pc_output_files.data, raylib_pc_output_files.size); - Dqn_FArray_AddArrayAssert(&feely_pona_platform_link_flags, sokol_audio_pc_output_files.data, sokol_audio_pc_output_files.size); - if (msvc_build) { - Dqn_FArray_AddCArrayAssert(&feely_pona_platform_link_flags, { - DQN_STR8("gdi32.lib"), // raylib - DQN_STR8("opengl32.lib"), // raylib - DQN_STR8("winmm.lib"), // raylib - DQN_STR8("user32.lib"), - DQN_STR8("shell32.lib"), - }); - } else { - Dqn_FArray_AddCArrayAssert(&feely_pona_platform_link_flags, { - DQN_STR8("-lpthread"), - }); - - #if defined(DQN_OS_UNIX) - Dqn_FArray_AddCArrayAssert(&feely_pona_platform_link_flags, { - DQN_STR8("-ldl"), - DQN_STR8("-lasound"), - }); + if (total_compiler_targets == 0) { + #if defined(DQN_OS_WIN32) + build_using_compiler[Compiler_MSVC] = true; #else - Dqn_FArray_AddCArrayAssert(&feely_pona_platform_link_flags, { - DQN_STR8("-lgdi32"), // raylib - DQN_STR8("-lopengl32"), // raylib - DQN_STR8("-lwinmm"), // raylib - DQN_STR8("-lole32"), // sokol_audio - DQN_STR8("-lbcrypt"), // dqn - DQN_STR8("-lwininet"), // dqn - DQN_STR8("-ldbghelp"), // dqn - }); + compiler_targets[Compiler_GCC] = true; #endif } } - // NOTE: Feely Pona No DLL ===================================================================== - uint64_t feely_pona_no_dll_timings[2] = {}; - if (!dev_fast_build) { - feely_pona_no_dll_timings[0] = Dqn_OS_PerfCounterNow(); - DQN_DEFER { feely_pona_no_dll_timings[1] = Dqn_OS_PerfCounterNow(); }; + // NOTE: Setup build =========================================================================== + Dqn_ThreadScratch scratch = Dqn_Thread_GetScratch(nullptr); + Dqn_Str8 const exe_dir = Dqn_OS_EXEDir(scratch.arena); + Dqn_Str8 const code_dir = exe_dir; + Dqn_Str8 const build_dir = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Build", DQN_STR_FMT(exe_dir)); + Dqn_Str8 const tely_dir = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/External/tely", DQN_STR_FMT(exe_dir)); - Dqn_CPPBuildCompileFile build_file = {}; - build_file.input_file_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/feely_pona_unity.h", DQN_STR_FMT(code_dir)); - build_file.output_file_path = Dqn_FsPath_ConvertF(scratch.arena, "terry_cherry"); - if (msvc_build) { - build_file.prefix_flags = Dqn_Slice_InitCArray(scratch.arena, {DQN_STR8("-Tp")}); + #define RecordScopeTime(...) \ + BuildTime *build_time_ = Dqn_FArray_Make(&build_timings, Dqn_ZeroMem_Yes); \ + build_time_->name = Dqn_Str8_InitF(scratch.allocator, ##__VA_ARGS__); \ + build_time_->timestamps[0] = Dqn_OS_PerfCounterNow(); \ + DQN_DEFER { build_time_->timestamps[1] = Dqn_OS_PerfCounterNow(); } + + bool assets_copied = false; + for (Dqn_usize compiler_index = 0; compiler_index < Compiler_Count; compiler_index++) { + if (!build_using_compiler[compiler_index]) + continue; + + Compiler compiler = DQN_CAST(Compiler) compiler_index; + Dqn_Str8 obj_file_extension = compiler == Compiler_MSVC ? DQN_STR8("obj") : DQN_STR8("o"); + Dqn_Str8 compiler_label = {}; + switch (compiler) { + case Compiler_MSVC: compiler_label = DQN_STR8("msvc"); break; + case Compiler_GCC: compiler_label = DQN_STR8("gcc"); break; + case Compiler_EMCC: compiler_label = DQN_STR8("emcc"); break; + case Compiler_Count: break; + } + + // NOTE: Compile flags ========================================================================= + Dqn_FArray32 common_compile_flags_no_warnings = {}; + if (compiler == Compiler_MSVC) { + Dqn_FArray_AddCArrayAssert(&common_compile_flags_no_warnings, { + DQN_STR8("cl"), + DQN_STR8("-Z7"), + DQN_STR8("-MT"), + DQN_STR8("-EHsc"), + DQN_STR8("-nologo"), + }); + } else if (compiler == Compiler_GCC) { + Dqn_FArray_AddCArrayAssert(&common_compile_flags_no_warnings, { + DQN_STR8("g++"), + DQN_STR8("-g"), + }); } else { - build_file.prefix_flags = Dqn_Slice_InitCArray(scratch.arena, {DQN_STR8("-xc++")}); - build_file.suffix_flags = Dqn_Slice_InitCArray(scratch.arena, {DQN_STR8("-xnone")}); + DQN_ASSERT(compiler == Compiler_EMCC); + #if defined(DQN_OS_WIN32) + Dqn_FArray_AddCArrayAssert(&common_compile_flags_no_warnings, { + DQN_STR8("cmd"), + DQN_STR8("/c"), + DQN_STR8("emcc.bat"), + }); + #else + Dqn_FArray_AddCArrayAssert(&common_compile_flags_no_warnings, { + DQN_STR8("emcc"), + DQN_STR8("-Os"), // Optimise for size + }); + #endif } - Dqn_FArray32 compile_flags = common_compile_flags; - Dqn_FArray_AddCArrayAssert(&compile_flags, { - DQN_STR8("-D"), DQN_STR8("TELY_WITH_PLATFORM"), - DQN_STR8("-D"), DQN_STR8("FEELY_PONA_IMPLEMENTATION"), - }); - - Dqn_CPPBuildContext feely_pona_no_dll_build_context = {}; - feely_pona_no_dll_build_context.flags_style = flags_style; - feely_pona_no_dll_build_context.compile_files = Dqn_Slice_Init(&build_file, 1); - feely_pona_no_dll_build_context.include_dirs = Dqn_Slice_Init(DQN_CAST(Dqn_Str8 *)&raylib_dir, 1); - feely_pona_no_dll_build_context.compile_flags = Dqn_FArray_Slice(&compile_flags); - feely_pona_no_dll_build_context.build_dir = build_dir; - feely_pona_no_dll_build_context.link_flags = Dqn_FArray_Slice(&feely_pona_platform_link_flags); - - Dqn_Str8 cmd = Dqn_CPPBuild_ToCommandLineStr8(feely_pona_no_dll_build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.arena); - Dqn_Print_StdLnF(Dqn_PrintStd_Out, "[BUILD] Executing '%.*s'", DQN_STR_FMT(cmd)); - if (!dry_run) - Dqn_CPPBuild_ExecOrAbort(feely_pona_no_dll_build_context, Dqn_CPPBuildMode_AlwaysRebuild); - } - - // NOTE: Feely Pona DLL ======================================================================== - uint64_t feely_pona_dll_timings[2] = {}; - if (msvc_build) { - feely_pona_dll_timings[0] = Dqn_OS_PerfCounterNow(); - DQN_DEFER { feely_pona_dll_timings[1] = Dqn_OS_PerfCounterNow(); }; - - Dqn_CPPBuildCompileFile build_file = {}; - build_file.input_file_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/feely_pona_unity.h", DQN_STR_FMT(code_dir)); - build_file.output_file_path = Dqn_FsPath_ConvertF(scratch.arena, "terry_cherry_dev_dll"); - build_file.prefix_flags = Dqn_Slice_InitCArray(scratch.arena, {DQN_STR8("-Tp")}); - - Dqn_FArray32 compile_flags = common_compile_flags; - Dqn_FArray_AddAssert(&compile_flags, DQN_STR8("-LD")); - Dqn_FArray_AddAssert(&compile_flags, DQN_STR8("-D FEELY_PONA_IMPLEMENTATION")); - if (!dev_fast_build) - Dqn_FArray_AddAssert(&compile_flags, DQN_STR8("-analyze")); - - Dqn_CPPBuildContext build_context = {}; - build_context.flags_style = flags_style; - build_context.compile_files = Dqn_Slice_Init(&build_file, 1); - build_context.compile_flags = Dqn_FArray_Slice(&compile_flags); - build_context.link_flags = {}; - build_context.build_dir = build_dir; - - Dqn_Str8 cmd = Dqn_CPPBuild_ToCommandLineStr8(build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.arena); - Dqn_Print_StdLnF(Dqn_PrintStd_Out, "[BUILD] Executing '%.*s'", DQN_STR_FMT(cmd)); - if (!dry_run) - Dqn_CPPBuild_ExecOrAbort(build_context, Dqn_CPPBuildMode_AlwaysRebuild); - } - - // NOTE: Feely Pona platform =================================================================== - uint64_t feely_pona_platform_timings[2] = {}; - if (msvc_build) { - feely_pona_platform_timings[0] = Dqn_OS_PerfCounterNow(); - DQN_DEFER { feely_pona_platform_timings[1] = Dqn_OS_PerfCounterNow(); }; - - Dqn_CPPBuildCompileFile build_file = {}; - build_file.input_file_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/feely_pona_unity.h", DQN_STR_FMT(code_dir)); - build_file.output_file_path = Dqn_FsPath_ConvertF(scratch.arena, "terry_cherry_dev", DQN_STR_FMT(code_dir)); - build_file.prefix_flags = Dqn_Slice_InitCArray(scratch.arena, {DQN_STR8("-Tp")}); - - Dqn_FArray32 compile_flags = common_compile_flags; - Dqn_FArray_AddCArrayAssert(&compile_flags, { - DQN_STR8("-D"), DQN_STR8("TELY_WITH_PLATFORM"), - DQN_STR8("-D"), DQN_STR8("TELY_WITH_PLATFORM_DLL"), - }); - - Dqn_CPPBuildContext build_context = {}; - build_context.flags_style = flags_style; - build_context.compile_files = Dqn_Slice_Init(&build_file, 1); - build_context.compile_flags = Dqn_FArray_Slice(&compile_flags); - build_context.link_flags = Dqn_FArray_Slice(&feely_pona_platform_link_flags); - build_context.build_dir = build_dir; - build_context.include_dirs = Dqn_Slice_InitCArray(scratch.arena, {raylib_dir}); - - Dqn_Str8 cmd = Dqn_CPPBuild_ToCommandLineStr8(build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.arena); - Dqn_Print_StdLnF(Dqn_PrintStd_Out, "[BUILD] Executing '%.*s'", DQN_STR_FMT(cmd)); - if (!dry_run) { - Dqn_Str8 exe_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/terry_cherry_dev.exe", DQN_STR_FMT(build_dir)); - bool exe_is_locked = false; - if (Dqn_Fs_Exists(exe_path)) { - Dqn_FsFile exe_file = Dqn_Fs_OpenFile(exe_path, Dqn_FsFileOpen_OpenIfExist, Dqn_FsFileAccess_Read | Dqn_FsFileAccess_Write); - exe_is_locked = exe_file.error_size; - Dqn_Fs_CloseFile(&exe_file); - } - - if (!exe_is_locked) { - Dqn_CPPBuild_ExecOrAbort(build_context, Dqn_CPPBuildMode_AlwaysRebuild); - } - } - } - - // NOTE: raylib emscripten ===================================================================== - uint64_t raylib_emscripten_timings[2] = {}; - uint64_t feely_pona_emscripten_timings[2] = {}; - if (msvc_build && target_web) { - Dqn_Str8 const raylib_emscripten_lib_name = DQN_STR8("raylib_emscripten.a"); - bool debug_build = false; - - Dqn_FArray32 build_specific_compile_flags = {}; - if (debug_build) { - Dqn_FArray_AddCArrayAssert(&build_specific_compile_flags, {DQN_STR8("-s"), DQN_STR8("ASSERTIONS=2")}); - Dqn_FArray_AddCArrayAssert(&build_specific_compile_flags, {DQN_STR8("-s"), DQN_STR8("SAFE_HEAP=0")}); - Dqn_FArray_AddCArrayAssert(&build_specific_compile_flags, {DQN_STR8("-s"), DQN_STR8("STACK_OVERFLOW_CHECK=2")}); - Dqn_FArray_AddCArrayAssert(&build_specific_compile_flags, {DQN_STR8("--profiling-funcs")}); // Expose function names in stack trace - Dqn_FArray_AddCArrayAssert(&build_specific_compile_flags, {DQN_STR8("-g")}); // Debug symbols + Dqn_FArray32 common_link_flags = {}; + Dqn_FArray32 common_compile_flags = common_compile_flags_no_warnings; + Dqn_FArray_AddCArrayAssert(&common_compile_flags_no_warnings, {DQN_STR8("-w")}); + if (compiler == Compiler_MSVC) { + Dqn_FArray_AddCArrayAssert(&common_compile_flags, {DQN_STR8("-W4")}); + Dqn_FArray_AddCArrayAssert(&common_link_flags, { + DQN_STR8("-link"), + DQN_STR8("-incremental:no"), + }); } else { - Dqn_FArray_AddCArrayAssert(&build_specific_compile_flags, {DQN_STR8("-Os")}); // Optimise for size + Dqn_FArray_AddCArrayAssert(&common_compile_flags, { + DQN_STR8("-Wall"), + }); + Dqn_FArray_AddCArrayAssert(&common_link_flags, { + DQN_STR8("-lm"), + }); } - // NOTE: Compile each raylib file separately with emcc ===================================== - { - raylib_emscripten_timings[0] = Dqn_OS_PerfCounterNow(); - DQN_DEFER { raylib_emscripten_timings[1] = Dqn_OS_PerfCounterNow(); }; + // NOTE: Link flags ============================================================================ + // NOTE: Build context ========================================================================= + Dqn_CPPBuildContext common_build_context = {}; + common_build_context.build_dir = build_dir; + common_build_context.flags_style = compiler == Compiler_MSVC ? Dqn_CPPBuildFlagsStyle_MSVC : Dqn_CPPBuildFlagsStyle_GCC; - // NOTE: Setup build context =========================================================== - Dqn_FArray32 emscripten_obj_files = {}; - Dqn_CPPBuildContext raylib_emscripten_build_context = {}; - raylib_emscripten_build_context.flags_style = Dqn_CPPBuildFlagsStyle_GCC; + // NOTE: Build program ========================================================================= + // NOTE: Copy assets =========================================================================== + if (!assets_copied) { + RecordScopeTime("Copy assets"); + assets_copied = true; - for (Dqn_Str8 base_file : raylib_base_files) { - Dqn_Str8 file_stem = Dqn_Str8_FileNameNoExtension(base_file); + Dqn_FArray32 cmd_array = {}; + #if defined(DQN_OS_WIN32) + Dqn_FArray_AddCArray(&cmd_array, { + DQN_STR8("robocopy"), + DQN_STR8("/MIR"), // Mirror + DQN_STR8("/NJH"), // No job header + DQN_STR8("/NJS"), // No job summary + DQN_STR8("/NDL"), + DQN_STR8("/NP"), // No progress + }); + #else + cmd_array = Dqn_FArray_AddCArray(&cmd_array, { + DQN_STR8("cp"), + DQN_STR8("--recursive"), + DQN_STR8("--force"), + }); + #endif - // NOTE: Append "emscripten" suffix to the object files - Dqn_CPPBuildCompileFile build_file = {}; - build_file.input_file_path = base_file; - build_file.output_file_path = Dqn_Str8_InitF(scratch.allocator, "raylib_%.*s_emscripten.o", DQN_STR_FMT(file_stem)); - - Dqn_FArray32 compile_flags = {}; - Dqn_FArray_AddCArrayAssert(&compile_flags, { - DQN_STR8("cmd"), - DQN_STR8("/C"), - DQN_STR8("emcc.bat"), - DQN_STR8("-c"), // Compile and assemble, but do not link - DQN_STR8("-Wall"), - DQN_STR8("-Os"), // Optimize for size - DQN_STR8("-D PLATFORM_WEB"), - DQN_STR8("-D GRAPHICS_API_OPENGL_ES2"), - }); - Dqn_FArray_AddArrayAssert(&compile_flags, build_specific_compile_flags.data, build_specific_compile_flags.size); - - raylib_emscripten_build_context.compile_files = Dqn_Slice_Init(&build_file, 1); - raylib_emscripten_build_context.compile_flags = Dqn_FArray_Slice(&compile_flags); - raylib_emscripten_build_context.build_dir = build_dir; - Dqn_FArray_AddAssert(&emscripten_obj_files, build_file.output_file_path); - - Dqn_Str8 cmd = Dqn_CPPBuild_ToCommandLineStr8(raylib_emscripten_build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.arena); - Dqn_Print_StdLnF(Dqn_PrintStd_Out, "[BUILD] Executing '%.*s'", DQN_STR_FMT(cmd)); - if (!dry_run) - Dqn_CPPBuild_ExecOrAbort(raylib_emscripten_build_context, Dqn_CPPBuildMode_CacheBuild); - } + DQN_MSVC_WARNING_PUSH + DQN_MSVC_WARNING_DISABLE(6063) + DQN_MSVC_WARNING_DISABLE(6064) + // TODO(doyle): The stringify macro in AddCArrayAssert triggers MSVC's code '-analyze' + // flag because it forwards the '%.*s' into Dqn_Log_TypeFCallSite which takes in a + // format string. + // + // warning C6064: Missing integer argument to 'Dqn_Log_TypeFCallSite' that corresponds to conversion specifier '1'. + // warning C6063: Missing string argument to 'Dqn_Log_TypeFCallSite' that corresponds to conversion specifier '2'. + // warning C6064: Missing integer argument to 'Dqn_Log_TypeFCallSite' that corresponds to conversion specifier '3'. + // warning C6063: Missing string argument to 'Dqn_Log_TypeFCallSite' that corresponds to conversion specifier '4'. + // NOTE: Copy the fonts { - Dqn_Str8 base_file = sokol_audio_source_code_file; - - // NOTE: Append "emscripten" suffix to the object files - Dqn_CPPBuildCompileFile build_file = {}; - build_file.input_file_path = base_file; - build_file.output_file_path = Dqn_Str8_InitF(scratch.allocator, "sokol_audio_emscripten.o"); - - Dqn_FArray32 compile_flags = Dqn_FArray_InitCArray({ - DQN_STR8("cmd"), - DQN_STR8("/C"), - DQN_STR8("emcc.bat"), - DQN_STR8("-c"), // Compile and assemble, but do not link - DQN_STR8("-Wall"), - DQN_STR8("-Os"), // Optimize for size - }); - Dqn_FArray_AddArrayAssert(&compile_flags, build_specific_compile_flags.data, build_specific_compile_flags.size); - - raylib_emscripten_build_context.compile_files = Dqn_Slice_Init(&build_file, 1); - raylib_emscripten_build_context.compile_flags = Dqn_FArray_Slice(&compile_flags); - raylib_emscripten_build_context.build_dir = build_dir; - Dqn_FArray_AddAssert(&emscripten_obj_files, build_file.output_file_path); - - Dqn_Str8 cmd = Dqn_CPPBuild_ToCommandLineStr8(raylib_emscripten_build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.arena); - Dqn_Print_StdLnF(Dqn_PrintStd_Out, "[BUILD] Executing '%.*s'", DQN_STR_FMT(cmd)); - if (!dry_run) - Dqn_CPPBuild_ExecOrAbort(raylib_emscripten_build_context, Dqn_CPPBuildMode_CacheBuild); - } - - // NOTE: Build the wasm raylib+sokol_audio library ===================================== - { - Dqn_FArray32 cmd_args = Dqn_FArray_InitCArray({ - DQN_STR8("cmd"), - DQN_STR8("/C"), - DQN_STR8("emar.bat"), - DQN_STR8("rcs"), - raylib_emscripten_lib_name, + Dqn_FArray32 font_cmd_array = cmd_array; + Dqn_FArray_AddCArrayAssert(&font_cmd_array, { + Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Data/Fonts", DQN_STR_FMT(exe_dir)), // Source + Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Data/Fonts", DQN_STR_FMT(build_dir)), // Dest }); - Dqn_FArray_AddArrayAssert(&cmd_args, emscripten_obj_files.data, emscripten_obj_files.size); - Dqn_Slice cmd_slice = Dqn_FArray_Slice(&cmd_args); - - Dqn_Str8 cmd = Dqn_Slice_Str8Render(scratch.arena, cmd_slice, DQN_STR8(" ") /*separator*/); - Dqn_Print_StdLnF(Dqn_PrintStd_Out, "[BUILD] Executing '%.*s'", DQN_STR_FMT(cmd)); + Dqn_Slice cmd_slice = Dqn_FArray_Slice(&font_cmd_array); + Dqn_Print_StdLnF(Dqn_PrintStd_Out, "[BUILD] Executing '%s'", Dqn_Slice_Str8RenderSpaceSeparated(scratch.arena, cmd_slice).data); if (!dry_run) - Dqn_OS_ExecOrAbort(cmd_slice, build_dir); + Dqn_OS_Exec(cmd_slice, /*working_dir*/ {}); } - } - // NOTE: feely pona emscripten ============================================================= - { - feely_pona_emscripten_timings[0] = Dqn_OS_PerfCounterNow(); - DQN_DEFER { feely_pona_emscripten_timings[1] = Dqn_OS_PerfCounterNow(); }; - - // NOTE: feely pona emscripten shell ======================================================= - Dqn_Str8 html_shell_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/feely_pona_emscripten_shell.html", DQN_STR_FMT(build_dir)); + // NOTE: Copy the audio { - Dqn_Str8 html_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/feely_pona_emscripten_shell.html", DQN_STR_FMT(code_dir)); - Dqn_Str8 html_buffer = Dqn_Fs_Read(html_path, scratch.allocator); - if (!DQN_CHECKF(html_buffer.size, - "Failed to read Emscripten HTML shell file. The file at\n\n '%.*s'\n\ndoes not exist or is not readable", - DQN_STR_FMT(html_path))) - return -1; + Dqn_FArray32 audio_cmd_array = cmd_array; + Dqn_FArray_AddCArrayAssert(&audio_cmd_array, { + Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Data/Audio", DQN_STR_FMT(exe_dir)), // Source + Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Data/Audio", DQN_STR_FMT(build_dir)), // Dest + }); - Dqn_Str8 version_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/feely_pona_version.txt", DQN_STR_FMT(code_dir)); - Dqn_Str8 version_buffer = Dqn_Fs_Read(version_path, scratch.allocator); - Dqn_Str8SplitAllocResult version_parts = Dqn_Str8_SplitAlloc(scratch.allocator, version_buffer, DQN_STR8("\n")); + Dqn_Slice cmd_slice = Dqn_FArray_Slice(&audio_cmd_array); + Dqn_Print_StdLnF(Dqn_PrintStd_Out, "[BUILD] Executing '%s'", Dqn_Slice_Str8RenderSpaceSeparated(scratch.arena, cmd_slice).data); + if (!dry_run) + Dqn_OS_Exec(cmd_slice, /*working_dir*/ {}); + } - if (!DQN_CHECKF(version_parts.size == 3, - "Version file '%.*s' must have 3 lines containing, date, commit hash and number of commits. The buffer we tried extracting information from was\n\n%.*s\n\n", - DQN_STR_FMT(version_path), - DQN_STR_FMT(version_buffer))) { + // NOTE: Copy the texture atlas + { + Dqn_Str8 atlas_dest_dir = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Data/Textures", DQN_STR_FMT(build_dir)); + Dqn_Fs_MakeDir(atlas_dest_dir); + + Dqn_Str8 atlas_txt_src = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Data/Textures/atlas.txt", DQN_STR_FMT(exe_dir)); + Dqn_Str8 atlas_txt_dest = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Data/Textures/atlas.txt", DQN_STR_FMT(build_dir)); + + Dqn_Str8 atlas_png_src = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Data/Textures/atlas.png", DQN_STR_FMT(exe_dir)); + Dqn_Str8 atlas_png_dest = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Data/Textures/atlas.png", DQN_STR_FMT(build_dir)); + + if (!Dqn_Fs_Copy(atlas_txt_src, atlas_txt_dest, true /*overwrite*/)) { + Dqn_Print_StdLnF(Dqn_PrintStd_Out, "[BUILD] Failed to copy file from '%.*s' to '%.*s'", DQN_STR_FMT(atlas_txt_src), DQN_STR_FMT(atlas_txt_dest)); return -1; } - Dqn_Str8 date = Dqn_Str8_TrimWhitespaceAround(version_parts.data[0]); - Dqn_Str8 commit_hash = Dqn_Str8_TrimWhitespaceAround(version_parts.data[1]); - Dqn_Str8 commit_count = Dqn_Str8_TrimWhitespaceAround(version_parts.data[2]); - Dqn_Str8 version_text = Dqn_Str8_InitF(scratch.allocator, - "%.*s edition rev. %.*s-%.*s", - DQN_STR_FMT(date), - DQN_STR_FMT(commit_count), - DQN_STR_FMT(commit_hash)); - - Dqn_Str8 html_buffer_processed = Dqn_Str8_Replace(html_buffer, - DQN_STR8("@version@"), - version_text, - 0 /*start_index*/, - scratch.allocator); - if (!DQN_CHECKF(Dqn_Fs_Write(html_shell_path, - html_buffer_processed), - "Failed to write Emscripten HTML shell with the project version inserted into it. We were unable to write to the target location\n\n '%.*s'\n", - DQN_STR_FMT(html_shell_path))) + if (!Dqn_Fs_Copy(atlas_png_src, atlas_png_dest, true /*overwrite*/)) { + Dqn_Print_StdLnF(Dqn_PrintStd_Out, "[BUILD] Failed to copy file from '%.*s' to '%.*s'", DQN_STR_FMT(atlas_png_src), DQN_STR_FMT(atlas_png_dest)); return -1; + } + } + DQN_MSVC_WARNING_POP + + } + + // NOTE: Raylib ============================================================================ + Dqn_Str8 raylib_dir = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/External/raylib", DQN_STR_FMT(tely_dir)); + Dqn_FArray32 raylib_obj_files = {}; + { + RecordScopeTime("%.*s Raylib ", DQN_STR_FMT(compiler_label)); + + Dqn_FArray32 base_files = Dqn_FArray_InitCArray({ + Dqn_FsPath_ConvertF(scratch.arena, "%.*s/rcore.c", DQN_STR_FMT(raylib_dir)), + Dqn_FsPath_ConvertF(scratch.arena, "%.*s/utils.c", DQN_STR_FMT(raylib_dir)), + Dqn_FsPath_ConvertF(scratch.arena, "%.*s/raudio.c", DQN_STR_FMT(raylib_dir)), + Dqn_FsPath_ConvertF(scratch.arena, "%.*s/rmodels.c", DQN_STR_FMT(raylib_dir)), + Dqn_FsPath_ConvertF(scratch.arena, "%.*s/rtext.c", DQN_STR_FMT(raylib_dir)), + Dqn_FsPath_ConvertF(scratch.arena, "%.*s/rtextures.c", DQN_STR_FMT(raylib_dir)), + Dqn_FsPath_ConvertF(scratch.arena, "%.*s/rshapes.c", DQN_STR_FMT(raylib_dir)), + }); + if (compiler != Compiler_EMCC) { + Dqn_FArray_AddCArrayAssert(&base_files, { + Dqn_FsPath_ConvertF(scratch.arena, "%.*s/rglfw.c", DQN_STR_FMT(raylib_dir)) + }); } - // NOTE: Compile with emcc ============================================================= - Dqn_Str8 output_name = DQN_STR8("Terry_Cherry"); - Dqn_CPPBuildCompileFile build_file = {}; - build_file.prefix_flags = Dqn_Slice_InitCArray(scratch.arena, {DQN_STR8("-xc++")}); - build_file.suffix_flags = Dqn_Slice_InitCArray(scratch.arena, {DQN_STR8("-xnone")}); - build_file.input_file_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/feely_pona_unity.cpp", DQN_STR_FMT(code_dir)); - build_file.output_file_path = Dqn_Str8_InitF(scratch.allocator, "%.*s.html", DQN_STR_FMT(output_name)); + Dqn_FArray32 compile_flags = common_compile_flags_no_warnings; + Dqn_FArray_AddCArrayAssert(&compile_flags, {DQN_STR8("-c")}); + if (compiler == Compiler_EMCC) { + Dqn_FArray_AddCArrayAssert(&compile_flags, { + DQN_STR8("-Os"), + DQN_STR8("-D"), DQN_STR8("PLATFORM_WEB"), + DQN_STR8("-D"), DQN_STR8("GRAPHICS_API_OPENGL_ES2"), + }); + } else { + if (compiler == Compiler_GCC) { + DQN_ASSERT(compile_flags.data[0] == DQN_STR8("g++")); + compile_flags.data[0] = DQN_STR8("gcc"); + } - Dqn_CPPBuildContext build_context = {}; - build_context.flags_style = Dqn_CPPBuildFlagsStyle_GCC; - build_context.compile_file_obj_suffix = DQN_CPP_BUILD_OBJ_SUFFIX_O; - build_context.compile_files = Dqn_Slice_Init(&build_file, 1); + Dqn_FArray_AddCArrayAssert(&compile_flags, { + DQN_STR8("-D"), DQN_STR8("PLATFORM_DESKTOP"), + }); + } - Dqn_FArray32 compile_flags = Dqn_FArray_InitCArray({ - DQN_STR8("cmd"), DQN_STR8("/C"), DQN_STR8("emcc.bat"), - DQN_STR8("-Wall"), - DQN_STR8("--shell-file"), html_shell_path, - Dqn_FsPath_ConvertF(scratch.arena, "%.*s/%.*s", DQN_STR_FMT(build_dir), DQN_STR_FMT(raylib_emscripten_lib_name)), - DQN_STR8("-s"), DQN_STR8("USE_GLFW=3"), - DQN_STR8("-s"), DQN_STR8("TOTAL_MEMORY=512MB"), - DQN_STR8("-s"), DQN_STR8("TOTAL_STACK=32MB"), - DQN_STR8("-s"), DQN_STR8("ALLOW_MEMORY_GROWTH"), - DQN_STR8("--preload-file"), DQN_STR8("Data"), - DQN_STR8("-msimd128"), - DQN_STR8("-msse2"), - DQN_STR8("-D"), DQN_STR8("TELY_WITH_PLATFORM"), - DQN_STR8("-D"), DQN_STR8("FEELY_PONA_IMPLEMENTATION"), + Dqn_CPPBuildContext build_context = common_build_context; + build_context.compile_flags = Dqn_FArray_Slice(&compile_flags); + build_context.include_dirs = Dqn_Slice_InitCArray(scratch.arena, { + Dqn_FsPath_ConvertF(scratch.arena, "%.*s", DQN_STR_FMT(raylib_dir)), + Dqn_FsPath_ConvertF(scratch.arena, "%.*s/external/glfw/include", DQN_STR_FMT(raylib_dir)), + Dqn_FsPath_ConvertF(scratch.arena, "%.*s/glfw/deps/mingw", DQN_STR_FMT(raylib_dir)), }); - Dqn_FArray_AddArrayAssert(&compile_flags, build_specific_compile_flags.data, build_specific_compile_flags.size); - build_context.compile_flags = Dqn_FArray_Slice(&compile_flags); + for (Dqn_Str8 base_file : base_files) { + Dqn_Str8 file_stem = Dqn_Str8_FileNameNoExtension(base_file); + Dqn_CPPBuildCompileFile build_file = {}; + build_file.input_file_path = base_file; + build_file.output_file_path = Dqn_Str8_InitF(scratch.allocator, "%.*s_%.*s.%.*s", DQN_STR_FMT(compiler_label), DQN_STR_FMT(file_stem), DQN_STR_FMT(obj_file_extension)); + Dqn_FArray_AddAssert(&raylib_obj_files, build_file.output_file_path); + + build_context.compile_files = Dqn_Slice_Init(&build_file, 1); + Dqn_Str8 cmd = Dqn_CPPBuild_ToCommandLineStr8(build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.arena); + Dqn_Print_StdLnF(Dqn_PrintStd_Out, "[BUILD] Executing '%.*s'", DQN_STR_FMT(cmd)); + if (!dry_run) + Dqn_CPPBuild_ExecOrAbort(build_context, Dqn_CPPBuildMode_CacheBuild); + } + } + + // NOTE: Sokol ============================================================================= + Dqn_Str8 sokol_dir = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/External/sokol", DQN_STR_FMT(tely_dir)); + Dqn_FArray32 sokol_obj_files = {}; + { + RecordScopeTime("%.*s Sokol", DQN_STR_FMT(compiler_label)); + + Dqn_CPPBuildCompileFile build_file = {}; + build_file.input_file_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/External/sokol/sokol_audio.c", DQN_STR_FMT(tely_dir)); + build_file.output_file_path = Dqn_Str8_InitF(scratch.allocator, "%.*s_sokol.%.*s", DQN_STR_FMT(compiler_label), DQN_STR_FMT(obj_file_extension)); + + Dqn_FArray32 compile_flags = common_compile_flags_no_warnings; + Dqn_FArray_AddCArrayAssert(&compile_flags, { + DQN_STR8("-c"), + }); + if (compiler == Compiler_EMCC) + Dqn_FArray_AddCArrayAssert(&compile_flags, {DQN_STR8("-Os")}); + + Dqn_CPPBuildContext build_context = common_build_context; + build_context.compile_flags = Dqn_FArray_Slice(&compile_flags); + build_context.compile_files = Dqn_Slice_Init(&build_file, 1); + Dqn_FArray_AddAssert(&sokol_obj_files, build_file.output_file_path); + + Dqn_Str8 cmd = Dqn_CPPBuild_ToCommandLineStr8(build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.arena); + Dqn_Print_StdLnF(Dqn_PrintStd_Out, "[BUILD] Executing '%.*s'", DQN_STR_FMT(cmd)); + if (!dry_run) + Dqn_CPPBuild_ExecOrAbort(build_context, Dqn_CPPBuildMode_CacheBuild); + } + + // NOTE: Feely Pona Sprite Packer ============================================================== + if (compiler == Compiler_MSVC) { + RecordScopeTime("Sprite Packer"); + + Dqn_CPPBuildContext build_context = common_build_context; + + Dqn_CPPBuildCompileFile build_file = {}; + build_file.input_file_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/feely_pona_sprite_packer.cpp", DQN_STR_FMT(code_dir)); + build_file.output_file_path = Dqn_Str8_InitF(scratch.allocator, "%.*s_feely_pona_sprite_packer.%.*s", DQN_STR_FMT(compiler_label), DQN_STR_FMT(obj_file_extension)); + if (compiler == Compiler_MSVC) { + build_file.prefix_flags = Dqn_Slice_InitCArray(scratch.arena, {DQN_STR8("/Tp")}); + } else { + build_file.prefix_flags = Dqn_Slice_InitCArray(scratch.arena, {DQN_STR8("-xc++")}); + build_file.suffix_flags = Dqn_Slice_InitCArray(scratch.arena, {DQN_STR8("-xnone")}); + } + + build_context.compile_flags = Dqn_FArray_Slice(&common_compile_flags); + build_context.link_flags = Dqn_FArray_Slice(&common_link_flags); build_context.build_dir = build_dir; Dqn_Str8 cmd = Dqn_CPPBuild_ToCommandLineStr8(build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.arena); Dqn_Print_StdLnF(Dqn_PrintStd_Out, "[BUILD] Executing '%.*s'", DQN_STR_FMT(cmd)); if (!dry_run) Dqn_CPPBuild_ExecOrAbort(build_context, Dqn_CPPBuildMode_CacheBuild); + } - // NOTE: Move the files to a directory - Dqn_Str8 folder_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/%.*s", DQN_STR_FMT(build_dir), DQN_STR_FMT(output_name)); - if (!Dqn_Fs_DirExists(folder_path)) { - Dqn_FArray32 mkdir_cmd = {}; - Dqn_FArray_AddAssert(&mkdir_cmd, DQN_STR8("mkdir")); - Dqn_FArray_AddAssert(&mkdir_cmd, folder_path); - Dqn_OS_ExecOrAbort(Dqn_FArray_Slice(&mkdir_cmd), {}); + // NOTE: Feely Pona Link Flags ============================================================= + Dqn_FArray32 feely_pona_raylib_backend_link_flags = {}; + { + Dqn_FArray_AddArrayAssert(&feely_pona_raylib_backend_link_flags, sokol_obj_files.data, sokol_obj_files.size); + Dqn_FArray_AddArrayAssert(&feely_pona_raylib_backend_link_flags, raylib_obj_files.data, raylib_obj_files.size); + if (compiler == Compiler_MSVC) { + Dqn_FArray_AddCArrayAssert(&feely_pona_raylib_backend_link_flags, { + DQN_STR8("gdi32.lib"), // raylib + DQN_STR8("opengl32.lib"), // raylib + DQN_STR8("winmm.lib"), // raylib + DQN_STR8("user32.lib"), + DQN_STR8("shell32.lib"), + }); + } else if (compiler == Compiler_GCC) { + Dqn_FArray_AddCArrayAssert(&feely_pona_raylib_backend_link_flags, { + DQN_STR8("-lpthread"), + }); + + #if defined(DQN_OS_UNIX) + Dqn_FArray_AddCArrayAssert(&csight_raylib_backend_link_flags, { + DQN_STR8("-ldl"), + DQN_STR8("-lasound"), + }); + #else + Dqn_FArray_AddCArrayAssert(&feely_pona_raylib_backend_link_flags, { + DQN_STR8("-lgdi32"), // raylib + DQN_STR8("-lopengl32"), // raylib + DQN_STR8("-lwinmm"), // raylib + DQN_STR8("-lole32"), // sokol audio + DQN_STR8("-lbcrypt"), // dqn + DQN_STR8("-lwininet"), // dqn + DQN_STR8("-ldbghelp"), // dqn + }); + #endif + } + } + + Dqn_FArray32 feely_pona_backend_include_dirs = Dqn_FArray_InitCArray({ + sokol_dir, + raylib_dir, + }); + + // NOTE: Feely Pona No DLL ================================================================= + if (!fast_dev_build || compiler == Compiler_EMCC) { + RecordScopeTime("%.*s Feely Pona", DQN_STR_FMT(compiler_label)); + + Dqn_CPPBuildCompileFile build_file = {}; + build_file.input_file_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/feely_pona_unity.cpp", DQN_STR_FMT(code_dir)); + if (compiler == Compiler_EMCC) + build_file.output_file_path = Dqn_FsPath_ConvertF(scratch.arena, "Terry_Cherry.html"); + else + build_file.output_file_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s_terry_cherry", DQN_STR_FMT(compiler_label)); + + Dqn_FArray32 compile_flags = common_compile_flags; + Dqn_FArray_AddCArrayAssert(&compile_flags, { + DQN_STR8("-D"), DQN_STR8("TELY_WITH_PLATFORM"), + DQN_STR8("-D"), DQN_STR8("FEELY_PONA_IMPLEMENTATION"), + }); + + if (compiler == Compiler_EMCC) { + // NOTE: Write Feely Pona version into Emscripten HTML Shell + Dqn_Str8 html_shell_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/feely_pona_emscripten_shell.html", DQN_STR_FMT(build_dir)); + { + Dqn_Str8 html_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/feely_pona_emscripten_shell.html", DQN_STR_FMT(code_dir)); + Dqn_Str8 html_buffer = Dqn_Fs_Read(html_path, scratch.allocator); + if (!DQN_CHECKF(html_buffer.size, + "Failed to read Emscripten HTML shell file. The file at\n\n '%.*s'\n\ndoes not exist or is not readable", + DQN_STR_FMT(html_path))) + return -1; + + Dqn_Str8 version_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/feely_pona_version.txt", DQN_STR_FMT(code_dir)); + Dqn_Str8 version_buffer = Dqn_Fs_Read(version_path, scratch.allocator); + Dqn_Str8SplitAllocResult version_parts = Dqn_Str8_SplitAlloc(scratch.allocator, version_buffer, DQN_STR8("\n")); + + if (!DQN_CHECKF(version_parts.size == 3, + "Version file '%.*s' must have 3 lines containing, date, commit hash and number of commits. The buffer we tried extracting information from was\n\n%.*s\n\n", + DQN_STR_FMT(version_path), + DQN_STR_FMT(version_buffer))) { + return -1; + } + + Dqn_Str8 date = Dqn_Str8_TrimWhitespaceAround(version_parts.data[0]); + Dqn_Str8 commit_hash = Dqn_Str8_TrimWhitespaceAround(version_parts.data[1]); + Dqn_Str8 commit_count = Dqn_Str8_TrimWhitespaceAround(version_parts.data[2]); + Dqn_Str8 version_text = Dqn_Str8_InitF(scratch.allocator, + "%.*s edition rev. %.*s-%.*s", + DQN_STR_FMT(date), + DQN_STR_FMT(commit_count), + DQN_STR_FMT(commit_hash)); + + Dqn_Str8 html_buffer_processed = Dqn_Str8_Replace(html_buffer, + DQN_STR8("@version@"), + version_text, + 0 /*start_index*/, + scratch.allocator); + if (!DQN_CHECKF(Dqn_Fs_Write(html_shell_path, + html_buffer_processed), + "Failed to write Emscripten HTML shell with the project version inserted into it. We were unable to write to the target location\n\n '%.*s'\n", + DQN_STR_FMT(html_shell_path))) + return -1; + } + + Dqn_FArray_AddCArrayAssert(&compile_flags, { + DQN_STR8("-Wall"), + DQN_STR8("-s"), DQN_STR8("USE_GLFW=3"), + DQN_STR8("-s"), DQN_STR8("TOTAL_MEMORY=512MB"), + DQN_STR8("-s"), DQN_STR8("TOTAL_STACK=32MB"), + DQN_STR8("-s"), DQN_STR8("ALLOW_MEMORY_GROWTH"), + DQN_STR8("--shell-file"), html_shell_path, + DQN_STR8("--preload-file"), DQN_STR8("Data"), + DQN_STR8("-msimd128"), + DQN_STR8("-msse2"), + }); + + bool debug_build = false; + if (debug_build) { + Dqn_FArray_AddCArrayAssert(&compile_flags, { + DQN_STR8("-s"), DQN_STR8("ASSERTIONS=2"), + DQN_STR8("-s"), DQN_STR8("SAFE_HEAP=0"), + DQN_STR8("-s"), DQN_STR8("STACK_OVERFLOW_CHECK=2"), + DQN_STR8("--profiling-funcs"), // Expose function names in stack trace + DQN_STR8("-g") // Debug symbols + }); + } else { + Dqn_FArray_AddCArrayAssert(&compile_flags, { + DQN_STR8("-Os"), + }); + } } - Dqn_Str8 const generated_file_extension[] = { - DQN_STR8("data"), - DQN_STR8("html"), - DQN_STR8("js"), - DQN_STR8("wasm"), - }; + Dqn_CPPBuildContext build_context = common_build_context; + build_context.compile_files = Dqn_Slice_Init(&build_file, 1); + build_context.include_dirs = Dqn_FArray_Slice(&feely_pona_backend_include_dirs); + build_context.compile_flags = Dqn_FArray_Slice(&compile_flags); + build_context.link_flags = Dqn_FArray_Slice(&feely_pona_raylib_backend_link_flags); - for (Dqn_Str8 file_ext : generated_file_extension) { - Dqn_Str8 src_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/%.*s.%.*s", DQN_STR_FMT(build_dir), DQN_STR_FMT(output_name), DQN_STR_FMT(file_ext)); - Dqn_Str8 dest_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/%.*s.%.*s", DQN_STR_FMT(folder_path), DQN_STR_FMT(output_name), DQN_STR_FMT(file_ext)); + Dqn_Str8 cmd = Dqn_CPPBuild_ToCommandLineStr8(build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.arena); + Dqn_Print_StdLnF(Dqn_PrintStd_Out, "[BUILD] Executing '%.*s'", DQN_STR_FMT(cmd)); + if (!dry_run) + Dqn_CPPBuild_ExecOrAbort(build_context, Dqn_CPPBuildMode_AlwaysRebuild); - Dqn_FArray32 cmd_args = {}; - Dqn_FArray_AddAssert(&cmd_args, DQN_STR8("cmd")); - Dqn_FArray_AddAssert(&cmd_args, DQN_STR8("/C")); - Dqn_FArray_AddAssert(&cmd_args, DQN_STR8("move")); - Dqn_FArray_AddAssert(&cmd_args, DQN_STR8("/Y")); - Dqn_FArray_AddAssert(&cmd_args, src_path); - Dqn_FArray_AddAssert(&cmd_args, dest_path); + // NOTE: Copy generated files for web target to directory + if (compiler == Compiler_EMCC) { + Dqn_Str8 folder_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Terry_Cherry", DQN_STR_FMT(build_dir)); + if (!Dqn_Fs_DirExists(folder_path)) { + if (!Dqn_Fs_MakeDir(folder_path)) { + Dqn_Print_StdLnF(Dqn_PrintStd_Out, "Failed to make directory '%.*s'", DQN_STR_FMT(folder_path)); + return -1; + } + } - Dqn_Slice cmd_slice = Dqn_FArray_Slice(&cmd_args); - Dqn_Str8 cmd_rendered = Dqn_Slice_Str8Render(scratch.arena, cmd_slice, DQN_STR8(" ")); - Dqn_Print_StdLnF(Dqn_PrintStd_Out, "[BUILD] Executing '%.*s'", DQN_STR_FMT(cmd_rendered)); - if (!dry_run) - Dqn_OS_ExecOrAbort(cmd_slice, build_dir); + Dqn_Str8 const generated_file_extension[] = { + DQN_STR8("data"), + DQN_STR8("html"), + DQN_STR8("js"), + DQN_STR8("wasm"), + }; + + for (Dqn_Str8 file_ext : generated_file_extension) { + Dqn_Str8 src_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Terry_Cherry.%.*s", DQN_STR_FMT(build_dir), DQN_STR_FMT(file_ext)); + Dqn_Str8 dest_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/Terry_Cherry.%.*s", DQN_STR_FMT(folder_path), DQN_STR_FMT(file_ext)); + Dqn_Print_StdLnF(Dqn_PrintStd_Out, "[BUILD] Moving '%.*s' to '%.*s'\n", DQN_STR_FMT(src_path), DQN_STR_FMT(dest_path)); + if (!dry_run && !Dqn_Fs_Move(src_path, dest_path, true /*overwrite*/)) { + Dqn_Print_StdLnF(Dqn_PrintStd_Out, "Failed to copy file from '%.*s' to '%.*s'", DQN_STR_FMT(src_path), DQN_STR_FMT(dest_path)); + return -1; + } + } + } + } + + // NOTE: Feely Pona Dev DLL ================================================================ + if (compiler == Compiler_MSVC) { + RecordScopeTime("%.*s Feely Pona Dev DLL", DQN_STR_FMT(compiler_label)); + Dqn_CPPBuildCompileFile build_file = {}; + build_file.input_file_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/feely_pona_unity.h", DQN_STR_FMT(code_dir)); + build_file.output_file_path = Dqn_FsPath_ConvertF(scratch.arena, "terry_cherry_dev_dll", DQN_STR_FMT(compiler_label)); + build_file.prefix_flags = Dqn_Slice_InitCArray(scratch.arena, {DQN_STR8("/Tp")}); + + Dqn_FArray32 compile_flags = common_compile_flags; + Dqn_FArray_AddAssert(&compile_flags, DQN_STR8("-LD")); + Dqn_FArray_AddAssert(&compile_flags, DQN_STR8("-D FEELY_PONA_IMPLEMENTATION")); + if (!fast_dev_build) + Dqn_FArray_AddAssert(&compile_flags, DQN_STR8("-analyze")); + + Dqn_CPPBuildContext build_context = common_build_context; + build_context.compile_files = Dqn_Slice_Init(&build_file, 1); + build_context.compile_flags = Dqn_FArray_Slice(&compile_flags); + + Dqn_Str8 cmd = Dqn_CPPBuild_ToCommandLineStr8(build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.arena); + Dqn_Print_StdLnF(Dqn_PrintStd_Out, "[BUILD] Executing '%.*s'", DQN_STR_FMT(cmd)); + if (!dry_run) + Dqn_CPPBuild_ExecOrAbort(build_context, Dqn_CPPBuildMode_AlwaysRebuild); + } + + // NOTE: Feely Pona Dev ==================================================================== + if (compiler == Compiler_MSVC) { + RecordScopeTime("%.*s Feely Pona Dev", DQN_STR_FMT(compiler_label)); + Dqn_CPPBuildCompileFile build_file = {}; + build_file.input_file_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/feely_pona_unity.h", DQN_STR_FMT(code_dir)); + build_file.output_file_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s_terry_cherry_dev", DQN_STR_FMT(compiler_label)); + build_file.prefix_flags = Dqn_Slice_InitCArray(scratch.arena, {DQN_STR8("/Tp")}); + + Dqn_FArray32 compile_flags = common_compile_flags; + Dqn_FArray_AddCArrayAssert(&compile_flags, { + DQN_STR8("-D"), DQN_STR8("TELY_WITH_PLATFORM"), + DQN_STR8("-D"), DQN_STR8("TELY_WITH_PLATFORM_DLL"), + }); + + Dqn_CPPBuildContext build_context = common_build_context; + build_context.compile_files = Dqn_Slice_Init(&build_file, 1); + build_context.compile_flags = Dqn_FArray_Slice(&compile_flags); + build_context.link_flags = Dqn_FArray_Slice(&feely_pona_raylib_backend_link_flags); + build_context.include_dirs = Dqn_FArray_Slice(&feely_pona_backend_include_dirs); + + Dqn_Str8 cmd = Dqn_CPPBuild_ToCommandLineStr8(build_context, Dqn_CPPBuildMode_AlwaysRebuild, scratch.arena); + Dqn_Print_StdLnF(Dqn_PrintStd_Out, "[BUILD] Executing '%.*s'", DQN_STR_FMT(cmd)); + if (!dry_run) { + Dqn_Str8 exe_path = Dqn_FsPath_ConvertF(scratch.arena, "%.*s/%.*s_feely_pona_dev.exe", DQN_STR_FMT(build_dir), DQN_STR_FMT(compiler_label)); + bool exe_is_locked = false; + if (Dqn_Fs_Exists(exe_path)) { + Dqn_FsFile exe_file = Dqn_Fs_OpenFile(exe_path, Dqn_FsFileOpen_OpenIfExist, Dqn_FsFileAccess_Read | Dqn_FsFileAccess_Write); + exe_is_locked = exe_file.error_size; + Dqn_Fs_CloseFile(&exe_file); + } + + if (!exe_is_locked) { + Dqn_CPPBuild_ExecOrAbort(build_context, Dqn_CPPBuildMode_AlwaysRebuild); + } } } } + global_build_timings->timestamps[1] = Dqn_OS_PerfCounterNow(); - build_timings[1] = Dqn_OS_PerfCounterNow(); - Dqn_Print_StdLnF(Dqn_PrintStd_Out, "\n-- Dqn_CPPBuild Timings (%.2fms)", Dqn_OS_PerfCounterMs(build_timings[0], build_timings[1])); - Dqn_Print_StdLnF(Dqn_PrintStd_Out, " robocopy: %.2fms", Dqn_OS_PerfCounterMs(robocopy_timings[0], robocopy_timings[1])); - Dqn_Print_StdLnF(Dqn_PrintStd_Out, " raylib: %.2fms", Dqn_OS_PerfCounterMs(raylib_pc_timings[0], raylib_pc_timings[1])); - Dqn_Print_StdLnF(Dqn_PrintStd_Out, " sokol_audio: %.2fms", Dqn_OS_PerfCounterMs(sokol_audio_pc_timings[0], sokol_audio_pc_timings[1])); - Dqn_Print_StdLnF(Dqn_PrintStd_Out, " feely pona sprite packer: %.2fms", Dqn_OS_PerfCounterMs(feely_pona_sprite_packer_timings[0], feely_pona_sprite_packer_timings[1])); - Dqn_Print_StdLnF(Dqn_PrintStd_Out, " feely pona (no dll): %.2fms", Dqn_OS_PerfCounterMs(feely_pona_no_dll_timings[0], feely_pona_no_dll_timings[1])); - Dqn_Print_StdLnF(Dqn_PrintStd_Out, " feely pona (dll): %.2fms", Dqn_OS_PerfCounterMs(feely_pona_dll_timings[0], feely_pona_dll_timings[1])); - Dqn_Print_StdLnF(Dqn_PrintStd_Out, " feely pona (platform-raylib): %.2fms", Dqn_OS_PerfCounterMs(feely_pona_platform_timings[0], feely_pona_platform_timings[1])); - if (target_web) { - Dqn_Print_StdLnF(Dqn_PrintStd_Out, " raylib (emscripten): %.2fms", Dqn_OS_PerfCounterMs(raylib_emscripten_timings[0], raylib_emscripten_timings[1])); - Dqn_Print_StdLnF(Dqn_PrintStd_Out, " feely pona (emscripten): %.2fms", Dqn_OS_PerfCounterMs(feely_pona_emscripten_timings[0], feely_pona_emscripten_timings[1])); + Dqn_usize longest_name = 0; + for (BuildTime build_time : build_timings) + longest_name = DQN_MAX(longest_name, build_time.name.size + 1); + + for (Dqn_usize build_index = 0; build_index < build_timings.size; build_index++) { + BuildTime build_time = build_timings.data[build_index]; + Dqn_Print_StdF(Dqn_PrintStd_Out, "%.*s:", DQN_STR_FMT(build_time.name)); + if (build_time.name.size < longest_name) + Dqn_Print_StdF(Dqn_PrintStd_Out, "%*s", DQN_CAST(int)(longest_name - build_time.name.size), ""); + Dqn_Print_StdLnF(Dqn_PrintStd_Out, "%.2fms", Dqn_OS_PerfCounterMs(build_time.timestamps[0], build_time.timestamps[1])); } return 0; } diff --git a/feely_pona_game.cpp b/feely_pona_game.cpp index 997a3be..503ff7f 100644 --- a/feely_pona_game.cpp +++ b/feely_pona_game.cpp @@ -3,24 +3,24 @@ #include "feely_pona_unity.h" #endif -static bool FP_Game_KeyBindIsPressed(TELY_OSInput const *input, FP_GameControls const *controls, FP_GameKeyBind key_bind) +static bool FP_Game_KeyBindIsPressed(TELY_Input const *input, FP_GameControls const *controls, FP_GameKeyBind key_bind) { bool result = false; if (controls->mode == FP_GameControlMode_Keyboard) { - result = TELY_OSInput_ScanKeyIsPressed(input, key_bind.scan_key); + result = TELY_Input_ScanKeyIsPressed(input, key_bind.scan_key); } else { - result = TELY_OSInput_GamepadKeyIsPressed(input, controls->gamepad_index, key_bind.gamepad_key); + result = TELY_Input_GamepadKeyIsPressed(input, controls->gamepad_index, key_bind.gamepad_key); } return result; } -static bool FP_Game_KeyBindIsDown(TELY_OSInput const *input, FP_GameControls const *controls, FP_GameKeyBind key_bind) +static bool FP_Game_KeyBindIsDown(TELY_Input const *input, FP_GameControls const *controls, FP_GameKeyBind key_bind) { bool result = false; if (controls->mode == FP_GameControlMode_Keyboard) { - result = TELY_OSInput_ScanKeyIsDown(input, key_bind.scan_key); + result = TELY_Input_ScanKeyIsDown(input, key_bind.scan_key); } else { - result = TELY_OSInput_GamepadKeyIsDown(input, controls->gamepad_index, key_bind.gamepad_key); + result = TELY_Input_GamepadKeyIsDown(input, controls->gamepad_index, key_bind.gamepad_key); } return result; } diff --git a/feely_pona_game.h b/feely_pona_game.h index 591cb8a..681a720 100644 --- a/feely_pona_game.h +++ b/feely_pona_game.h @@ -168,8 +168,8 @@ enum FP_GameInGameMenu struct FP_GameKeyBind { - TELY_OSInputScanKey scan_key; - TELY_OSInputGamepadKey gamepad_key; + TELY_InputScanKey scan_key; + TELY_InputGamepadKey gamepad_key; }; enum FP_GameControlMode diff --git a/feely_pona_sprite_packer.cpp b/feely_pona_sprite_packer.cpp index fdcf9f1..09eace0 100644 --- a/feely_pona_sprite_packer.cpp +++ b/feely_pona_sprite_packer.cpp @@ -8,6 +8,8 @@ #define DQN_ONLY_DSMAP #define DQN_ONLY_LIST #define DQN_ONLY_FS +#define DQN_ONLY_SEMAPHORE +#define DQN_ONLY_THREAD #define _CRT_SECURE_NO_WARNINGS #define DQN_IMPLEMENTATION #include "External/tely/External/dqn/dqn.h" diff --git a/feely_pona_unity.h b/feely_pona_unity.h index 6310468..430d897 100644 --- a/feely_pona_unity.h +++ b/feely_pona_unity.h @@ -2,7 +2,7 @@ // Unity build header to compile the entire application as a single translation unit #define TELY_PLATFORM_DLL_FILE_NAME "terry_cherry_dev_dll" -#include "External/tely/tely_os_raylib_unity.h" +#include "External/tely/tely_backend_raylib_unity.h" // NOTE: feely_pona ================================================================================ #if defined(_CLANGD) || defined(FEELY_PONA_IMPLEMENTATION)