Compare commits

..
175 changed files with 4642 additions and 17161 deletions
+6 -115
View File
@@ -25,9 +25,6 @@ if(MSVC)
endif()
option(FALLOUT_VENDORED "Use vendored third-party libraries" ON)
option(FALLOUT_AUDIO_OGG "Enable OGG decoding with stb_vorbis when available" ON)
set(FALLOUT_STB_VORBIS_DIR "" CACHE PATH "Directory containing stb_vorbis.c")
if(ANDROID)
add_library(${EXECUTABLE_NAME} SHARED)
@@ -38,9 +35,7 @@ endif()
# Git Info
include("cmake/gitver.cmake")
# Shared engine sources — used by both game and mapper targets.
# Excludes main.cc/main.h (game-only entry logic).
set(FALLOUT_ENGINE_SOURCES
target_sources(${EXECUTABLE_NAME} PUBLIC
"src/actions.cc"
"src/actions.h"
"src/animation.cc"
@@ -156,11 +151,15 @@ set(FALLOUT_ENGINE_SOURCES
"src/lips.h"
"src/loadsave.cc"
"src/loadsave.h"
"src/main.cc"
"src/main.h"
"src/mainmenu.cc"
"src/mainmenu.h"
"src/map_defs.h"
"src/map.cc"
"src/map.h"
"src/map_edge.cc"
"src/map_edge.h"
"src/memory_defs.h"
"src/memory_manager.cc"
"src/memory_manager.h"
@@ -183,8 +182,6 @@ set(FALLOUT_ENGINE_SOURCES
"src/obj_types.h"
"src/object.cc"
"src/object.h"
"src/ogg_decoder.cc"
"src/ogg_decoder.h"
"src/opcode_context.cc"
"src/opcode_context.h"
"src/options.cc"
@@ -205,8 +202,6 @@ set(FALLOUT_ENGINE_SOURCES
"src/proto_types.h"
"src/proto.cc"
"src/proto.h"
"src/prototype_options.cc"
"src/prototype_options.h"
"src/queue.cc"
"src/queue.h"
"src/random.cc"
@@ -270,7 +265,7 @@ set(FALLOUT_ENGINE_SOURCES
"src/xfile.h"
)
set(FALLOUT_PLATFORM_SOURCES
target_sources(${EXECUTABLE_NAME} PUBLIC
"src/audio_engine.cc"
"src/audio_engine.h"
"src/delay.cc"
@@ -304,8 +299,6 @@ set(FALLOUT_PLATFORM_SOURCES
"src/sfall_opcodes.cc"
"src/sfall_opcodes.h"
"src/sfall_script_hooks.cc"
"src/script_sound.cc"
"src/script_sound.h"
"src/sfall_arrays.cc"
"src/sfall_arrays.h"
"src/sfall_animation.cc"
@@ -318,43 +311,8 @@ set(FALLOUT_PLATFORM_SOURCES
"third_party/lodepng/lodepng.cpp"
)
target_sources(${EXECUTABLE_NAME} PUBLIC
${FALLOUT_ENGINE_SOURCES}
"src/main.cc"
"src/main.h"
)
target_sources(${EXECUTABLE_NAME} PUBLIC ${FALLOUT_PLATFORM_SOURCES})
target_include_directories(${EXECUTABLE_NAME} PUBLIC "third_party/lodepng")
set(FALLOUT_HAVE_STB_VORBIS OFF)
if(FALLOUT_AUDIO_OGG)
if(EXISTS "${CMAKE_SOURCE_DIR}/third_party/stb_vorbis/stb_vorbis.c")
set(_fallout_stb_vorbis_dir "${CMAKE_SOURCE_DIR}/third_party/stb_vorbis")
else()
set(_fallout_stb_vorbis_dir "${FALLOUT_STB_VORBIS_DIR}")
if(NOT _fallout_stb_vorbis_dir)
find_path(_fallout_stb_vorbis_dir
NAMES "stb_vorbis.c"
DOC "Directory containing stb_vorbis.c")
endif()
endif()
if(_fallout_stb_vorbis_dir AND EXISTS "${_fallout_stb_vorbis_dir}/stb_vorbis.c")
set(FALLOUT_HAVE_STB_VORBIS ON)
target_include_directories(${EXECUTABLE_NAME} PRIVATE "${_fallout_stb_vorbis_dir}")
else()
message(STATUS "OGG support disabled: stb_vorbis.c not found")
endif()
endif()
if(FALLOUT_HAVE_STB_VORBIS)
target_compile_definitions(${EXECUTABLE_NAME} PRIVATE HAVE_STB_VORBIS=1)
else()
target_compile_definitions(${EXECUTABLE_NAME} PRIVATE HAVE_STB_VORBIS=0)
endif()
if(IOS)
target_sources(${EXECUTABLE_NAME} PUBLIC
"src/platform/ios/paths.h"
@@ -571,73 +529,6 @@ if((NOT ANDROID) AND (NOT IOS) AND (NOT CMAKE_SYSTEM_NAME MATCHES "Emscripten"))
endif()
endif()
if((NOT ANDROID) AND (NOT IOS) AND (NOT CMAKE_SYSTEM_NAME MATCHES "Emscripten"))
if(WIN32)
add_executable(mapper-ce WIN32)
else()
add_executable(mapper-ce)
endif()
target_sources(mapper-ce PUBLIC
${FALLOUT_ENGINE_SOURCES}
${FALLOUT_PLATFORM_SOURCES}
"src/mapper/map_func.cc"
"src/mapper/map_func.h"
"src/mapper/mapper.cc"
"src/mapper/mapper.h"
"src/mapper/mp_instance.cc"
"src/mapper/mp_instance.h"
"src/mapper/mp_proto.cc"
"src/mapper/mp_proto.h"
"src/mapper/mp_scrpt.cc"
"src/mapper/mp_scrpt.h"
"src/mapper/mp_targt.cc"
"src/mapper/mp_targt.h"
"src/mapper/mp_text.cc"
"src/mapper/mp_text.h"
)
target_compile_definitions(mapper-ce PUBLIC FALLOUT_MAPPER)
if(WIN32)
target_compile_definitions(mapper-ce PUBLIC
_CRT_SECURE_NO_WARNINGS
_CRT_NONSTDC_NO_WARNINGS
NOMINMAX
WIN32_LEAN_AND_MEAN
_STATIC_CPPLIB
)
target_link_libraries(mapper-ce
winmm
debug libcpmtd
optimized libcpmt
)
target_sources(mapper-ce PUBLIC
"os/windows/fallout2-ce.rc"
)
endif()
if(APPLE)
target_link_libraries(mapper-ce "-framework CoreFoundation")
set_target_properties(mapper-ce PROPERTIES
XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "NO"
XCODE_ATTRIBUTE_CODE_SIGNING_REQUIRED "NO"
)
endif()
target_include_directories(mapper-ce PUBLIC "third_party/lodepng")
target_include_directories(mapper-ce PRIVATE "src")
target_include_directories(mapper-ce PRIVATE ${ZLIB_INCLUDE_DIRS})
target_include_directories(mapper-ce PRIVATE ${SDL2_INCLUDE_DIRS})
target_link_libraries(mapper-ce
fpattern::fpattern
fpattern_windows::fpattern_windows
${ZLIB_LIBRARIES}
${SDL2_LIBRARIES}
)
endif()
if(APPLE)
if(IOS)
install(TARGETS ${EXECUTABLE_NAME} DESTINATION "Payload")
+6 -6
View File
@@ -43,7 +43,7 @@ See [`https://sfall-team.github.io/sfall/`](https://sfall-team.github.io/sfall/)
| Combat / Knockback | set_weapon_knockback<br>set_target_knockback<br>set_attacker_knockback<br>remove_weapon_knockback<br>remove_target_knockback<br>remove_attacker_knockback | not implemented | - |
| Maps and encounters | in_world_map<br>force_encounter<br>force_encounter_with_flags<br>set_map_time_multi<br>get/set_map_enter_position<br>exec_map_update_scripts<br>get/set_terrain_name<br>set_town_title<br>get/set_can_rest_on_map<br>set_rest_heal_time<br>set_rest_mode<br>set_worldmap_heal_time | implemented: in_world_map, force_encounter, force_encounter_with_flags, set_map_time_multi | - |
| Maps and encounters / Worldmap | get_world_map_x/y_pos<br>set_world_map_pos | âś… | - |
| Audio | play_sfall_sound<br>stop_sfall_sound | âś… | `play_sfall_sound` currently supports `.acm`, `.wav`, `.ogg` formats, and can load from `.dat` archives. `.mp3` is not yet supported. |
| Audio | eax_available<br>set_eax_environment<br>play_sfall_sound<br>stop_sfall_sound | not implemented | *eax* opcodes will not be implemented |
| Combat / Weapons and ammo | get/set_weapon_ammo_pid<br>get/set_weapon_ammo_count | âś… | - |
| Sfall / Version | sfall_ver_major<br>sfall_ver_minor<br>sfall_ver_build | âś… | CE currently reports `4.3.4` |
| Utility / Math | log, exponent, round, sqrt, abs, sin, cos, tan, arctan, ceil, ^, floor2, div | âś… | - |
@@ -72,7 +72,7 @@ See [`https://sfall-team.github.io/sfall/`](https://sfall-team.github.io/sfall/)
| INI settings | get_ini_setting<br>get_ini_string<br>get_ini_section<br>get_ini_sections<br>get_ini_config<br>get_ini_config_db<br>set_ini_setting | âś… except get_ini_config, get_ini_config_db | `modified_ini` is intentionally omitted as deprecated. |
| Objects and scripts | set_self<br>set_dude_obj<br>real_dude_obj<br>remove_script<br>get/set_script<br>obj_is_carrying_obj<br>loot_obj<br>dialog_obj<br>obj_under_cursor<br>get/set_object_data<br>get/set_flags<br>set_unique_id<br>set_scr_name<br>obj_is_openable<br>get/set_proto_data<br>get_object_ai_data | implemented: set_self, get/set/remove_script, obj_is_carrying_obj, loot_obj, dialog_obj, obj_under_cursor, get_object_data, get_flags, set_flags, obj_is_openable, get_proto_data, set_proto_data | - |
| Other / Game management | set_movie_path<br>stop/resume_game<br>mark_movie_played<br>game_loaded<br>get_game_mode<br>get_uptime<br>signal_close_game | implemented: game_loaded, get_game_mode, get_uptime, signal_close_game | - |
| Gameplay tweaks | set_pickpocket_max<br>set_hit_chance_max<br>set_xp_mod<br>set_critter_hit_chance_mod<br>set_base_hit_chance_mod<br>set_hp_per_level_mod<br>gdialog_get_barter_mod<br>get/set_unspent_ap_bonus<br>get/set_unspent_ap_perk_bonus<br>set_base_pickpocket_mod<br>set_critter_pickpocket_mod<br>get/set_inven_ap_cost<br>set_drugs_data<br>get_kill_counter<br>mod_kill_counter<br>set_pipboy_available | implemented: gdialog_get_barter_mod, get/set_unspent_ap{_perk}_bonus, get/set_inven_ap_cost | - |
| Gameplay tweaks | set_pickpocket_max<br>set_hit_chance_max<br>set_xp_mod<br>set_critter_hit_chance_mod<br>set_base_hit_chance_mod<br>set_hp_per_level_mod<br>gdialog_get_barter_mod<br>get/set_unspent_ap_bonus<br>get/<br>set_base_pickpocket_mod<br>set_critter_pickpocket_mod<br>get/set_inven_ap_cost<br>set_drugs_data<br>get_kill_counter<br>mod_kill_counter<br>set_pipboy_available | implemented: gdialog_get_barter_mod | - |
| NPCs | inc_npc_level<br>get_npc_level<br>npc_engine_level_up | not implemented | - |
| Other | get_year<br>set_dm/df_model<br>active_hand<br>toggle_active_hand<br>get/set_viewport_x/y<br>hero_select_win<br>get_light_level<br>message_str_game<br>sneak_success<br>create_spatial<br>unwield_slot<br>add_g_timer_event<br>add_extra_msg_file<br>get_metarule_table<br>metarule_exist<br>remove_timer_event<br>spatial_radius | implemented: get_year, active_hand, toggle_active_hand, get_light_level, message_str_game, add_extra_msg_file, metarule_exist | `input_funcs_available`, `nb_create_char` are deprecated in sfall and intentionally absent in CE. `add_extra_msg_file` does not support the explicit `fileNumber` form in CE. |
@@ -98,11 +98,11 @@ See [`https://sfall-team.github.io/sfall/`](https://sfall-team.github.io/sfall/)
| KeyPress | `HOOK_KEYPRESS` | âś… | Third hook arg is currently `0`; CE doesn't use VK codes. |
| MouseClick | `HOOK_MOUSECLICK` | âś… | - |
| UseSkill | `HOOK_USESKILL` | đźš« | - |
| Steal | `HOOK_STEAL` | âś… | - |
| Steal | `HOOK_STEAL` | đźš« | Et tu |
| WithinPerception | `HOOK_WITHINPERCEPTION` | âś… | - |
| InventoryMove | `HOOK_INVENTORYMOVE` | âś… | - |
| InvenWield | `HOOK_INVENWIELD` | âś… | - |
| AdjustFID | `HOOK_ADJUSTFID` | âś… | Second hook arg currently matches the first because CE has no internal FID modifiers like Hero Appearance. |
| InvenWield | `HOOK_INVENWIELD` | đźš« | - |
| AdjustFID | `HOOK_ADJUSTFID` | đźš« | - |
| CombatTurn | `HOOK_COMBATTURN` | âś… | - |
| StdProcedure | `HOOK_STDPROCEDURE` | âś… | - |
| StdProcedureEnd | `HOOK_STDPROCEDURE_END` | âś… | - |
@@ -124,5 +124,5 @@ See [`https://sfall-team.github.io/sfall/`](https://sfall-team.github.io/sfall/)
| AdjustRads | `HOOK_ADJUSTRADS` | đźš« | (maybe) |
| RollCheck | `HOOK_ROLLCHECK` | đźš« | - |
| BestWeapon | `HOOK_BESTWEAPON` | đźš« | - |
| CanUseWeapon | `HOOK_CANUSEWEAPON` | âś… | - |
| CanUseWeapon | `HOOK_CANUSEWEAPON` | đźš« | - |
| BuildSfxWeapon | `HOOK_BUILDSFXWEAPON` | đźš« | - |
Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.
Binary file not shown.

Before

Width:  |  Height:  |  Size: 70 KiB

-8
View File
@@ -22,10 +22,6 @@ save_text_maps=0
show_pid_numbers=0
sort_script_list=0
use_art_not_protos=0
; Allows to load a certain map right away after loading the mapper.
map=denbus2
; Allows to disable grid item picker and use a simpler list-based picker.
use_grid_item_picker=1
[preferences]
brightness=1.000000
@@ -98,8 +94,6 @@ auto_quick_save=3
display_bonus_damage=1
;Set to 1 to get notification of karma changes in the notification window
display_karma_changes=0
;Set to 1 to use the hi-res dialog border/background at resolutions above 640x480. Requires art\intrface\HR_ALLTLK.FRM (for example from f2_res.dat)
dialog_border=1
;Set to one to hide areas outside map bounds when using higher than 640x480 resolution, and to zero to disable
enable_high_resolution_stencil=1
;Set to 1 to extend the action points bar to show up to 16 AP instead of 10 (requires iface_apbar_e.frm)
@@ -126,5 +120,3 @@ inventory_columns=2
auto_open_doors=0
; Overrides distance at which walk animation is used when using an object.
use_walk_distance=5
; Allow switching to companions' inventories in loot screens (and barter, in the future)
party_loot_and_barter=1
+3 -3
View File
@@ -4,7 +4,7 @@
#define ARRAY_MAX_STRING (1024)
#define ARRAY_MAX_STRING (255)
#define ARRAY_MAX_SIZE (100000)
procedure array_test_suite begin
@@ -82,8 +82,8 @@ procedure array_test_suite begin
call assertEquals("string_split", get_array(string_split("this+is+good", "+"), 2), "good");
call assertEquals("string_split 2", len_array(string_split("advice", "")), 6);
s := "";
for (i := 0; i < ARRAY_MAX_STRING+1; i+=100) begin
s += "Verbosity.Verbosity.Verbosity.Verbosity.Verbosity.Verbosity.Verbosity.Verbosity.Verbosity.Verbosity.";
for (i := 0; i < ARRAY_MAX_STRING+30; i+=10) begin
s += "Verbosity.";
end
arr[0] := s;
call assertEquals("array max string", strlen(arr[0]), ARRAY_MAX_STRING-1);
-78
View File
@@ -1,78 +0,0 @@
#include "sfall.h"
#include "dik.h"
variable loop_sound_id := 0;
variable quiet_loop_sound_id := 0;
variable music_sound_id := 0;
procedure stop_if_active(variable sound_id, variable label) begin
if (sound_id != 0) then begin
stop_sfall_sound(sound_id);
display_msg(label + " stopped");
end else begin
display_msg(label + " is not active");
end
end
procedure keypress_handler begin
variable pressed := get_sfall_arg_at(0);
variable key := get_sfall_arg_at(1);
variable ignored;
if (not pressed) then return;
if (key == DIK_K) then begin
display_msg("play_sfall_sound mode 0 one-shot: sound\\sfx\\pistol.ACM");
ignored := play_sfall_sound("sound\\sfx\\pistol.ACM", 0);
end else if (key == DIK_N) then begin
if (loop_sound_id != 0) then begin
display_msg(string_format1("loop already active id=%d", loop_sound_id));
return;
end
loop_sound_id := play_sfall_sound("sound\\music\\20CAR.ACM", 1);
display_msg(string_format1("mode 1 loop id=%d", loop_sound_id));
end else if (key == DIK_M) then begin
call stop_if_active(loop_sound_id, "mode 1 loop");
loop_sound_id := 0;
end else if (key == DIK_C) then begin
if (quiet_loop_sound_id != 0) then begin
display_msg(string_format1("quiet loop already active id=%d", quiet_loop_sound_id));
return;
end
quiet_loop_sound_id := play_sfall_sound("sound\\music\\20CAR.ACM", 0x30000001);
display_msg(string_format1("quiet mode 1 loop id=%d", quiet_loop_sound_id));
end else if (key == DIK_X) then begin
call stop_if_active(quiet_loop_sound_id, "quiet mode 1 loop");
quiet_loop_sound_id := 0;
end else if (key == DIK_G) then begin
if (music_sound_id != 0) then begin
display_msg(string_format1("mode 2 music replacement already active id=%d", music_sound_id));
return;
end
music_sound_id := play_sfall_sound("sound\\music\\20CAR.ACM", 2);
display_msg(string_format1("mode 2 music replacement id=%d", music_sound_id));
end else if (key == DIK_H) then begin
call stop_if_active(music_sound_id, "mode 2 music replacement");
music_sound_id := 0;
end else if (key == DIK_V) then begin
display_msg("play_sfall_sound mode 3 speech-volume one-shot: sound\\sfx\\pistol.ACM");
ignored := play_sfall_sound("sound\\sfx\\pistol.ACM", 3);
end else if (key == DIK_B) then begin
display_msg("play_sfall_sound mode 0 one-shot wav: smw_1-up.wav"); // needs a wav file in the game dir
ignored := play_sfall_sound("smw_1-up.wav", 0);
end
end
procedure start begin
if (not game_loaded) then return;
display_msg("sfall_sound manual test ready");
display_msg("One-shots use master.dat SFX and loose-file wav; loops/replacement use music");
display_msg("K one-shot ACM mode0, B one-shot WAV mode0, N start loop mode1, M stop loop");
display_msg("C start quiet loop mode1, X stop quiet loop");
display_msg("G start mode2 music replacement, H stop mode2 replacement, V mode3 one-shot");
register_hook_proc(HOOK_KEYPRESS, keypress_handler);
end
-83
View File
@@ -1,83 +0,0 @@
#include "sfall.h"
#include "dik.h"
#include "lib.arrays.h"
variable steal_mode := 0;
procedure steal_mode_name(variable mode) begin
if (mode == 1) then return "force_success";
if (mode == 2) then return "caught_fail";
if (mode == 3) then return "silent_fail";
if (mode == 4) then return "xp_override";
return "vanilla";
end
procedure steal_handler begin
variable
args := get_sfall_args,
thief := args[0],
target := args[1],
item := args[2],
is_planting := args[3],
quantity := args[4],
thief_name := "<null>",
target_name := "<null>",
item_name := "<null>";
if (thief) then thief_name := obj_name(thief);
if (target) then target_name := obj_name(target);
if (item) then item_name := obj_name(item);
display_msg(string_format6("steal mode=%s thief=%s target=%s item=%s planting=%d qty=%d",
steal_mode_name(steal_mode),
thief_name,
target_name,
item_name,
is_planting,
quantity));
display_msg(string_format1("steal args=%s", debug_array_str(args)));
if (thief != dude_obj) then return;
if (steal_mode == 1) then begin
display_msg("steal forcing success");
display_msg(sprintf(mstr_skill(571 + is_planting * 2), item_name));
set_sfall_return(1);
end else if (steal_mode == 2) then begin
display_msg("steal forcing caught failure");
display_msg(sprintf(mstr_skill(570 + is_planting * 2), item_name));
set_sfall_return(0);
end else if (steal_mode == 3) then begin
display_msg("steal forcing silent failure");
set_sfall_return(2);
end else if (steal_mode == 4) then begin
display_msg("steal forcing success with xp override 77");
display_msg(sprintf(mstr_skill(571 + is_planting * 2), item_name));
set_sfall_return(1);
set_sfall_return(77);
end
end
procedure keypress_handler begin
variable
pressed := get_sfall_arg_at(0),
key := get_sfall_arg_at(1);
if (not pressed) then return;
if (key != DIK_X) then return;
steal_mode += 1;
if (steal_mode > 4) then steal_mode := 0;
display_msg(string_format1("steal mode -> %s", steal_mode_name(steal_mode)));
end
procedure start begin
if (not game_loaded) then return;
display_msg("steal manual test ready: press X to cycle vanilla / force_success / caught_fail / silent_fail / xp_override");
display_msg("open a steal screen and move an item in either direction; mode 4 should award 77 XP for a successful action");
register_hook_proc(HOOK_KEYPRESS, keypress_handler);
register_hook_proc(HOOK_STEAL, steal_handler);
end
+5 -5
View File
@@ -46,13 +46,13 @@ typedef enum ScienceRepairTargetType {
SCIENCE_REPAIR_TARGET_TYPE_ANYONE,
} ScienceRepairTargetType;
// 0x5106D0 action_in_explode
// 0x5106D0
static bool _action_in_explode = false;
// 0x5106D4 rotation
// 0x5106D4
int rotation;
// 0x5106E0 death_2
// 0x5106E0
static const int gNormalDeathAnimations[DAMAGE_TYPE_COUNT] = {
ANIM_DANCING_AUTOFIRE,
ANIM_SLICED_IN_HALF,
@@ -63,7 +63,7 @@ static const int gNormalDeathAnimations[DAMAGE_TYPE_COUNT] = {
ANIM_BIG_HOLE,
};
// 0x5106FC death_3
// 0x5106FC
static const int gMaximumBloodDeathAnimations[DAMAGE_TYPE_COUNT] = {
ANIM_CHUNKS_OF_FLESH,
ANIM_SLICED_IN_HALF,
@@ -519,7 +519,7 @@ int _show_death(Object* obj, int anim)
// Animates damage to extras in a given attack (secondary targets).
//
// 0x410FEC show_damage_extras
// 0x410FEC _show_damage_extras
int showDamageToExtras(Attack* attack)
{
for (int index = 0; index < attack->extrasLength; index++) {
+11 -11
View File
@@ -309,39 +309,39 @@ static unsigned int animationComputeTicksPerFrame(Object* object, int fid);
static void reportOverloaded(Object* critter);
// 0x510718 curr_sad
// 0x510718
static int gAnimationCurrentSad = 0;
// 0x51071C curr_anim_set
// 0x51071C
static int gAnimationSequenceCurrentIndex = -1;
// 0x510720 anim_in_init
// 0x510720
static bool gAnimationInInit = false;
// 0x510724 anim_in_anim_stop
// 0x510724
static bool gAnimationInStop = false;
// 0x510728 anim_in_bk
// 0x510728
static bool _anim_in_bk = false;
// 0x530014 sad
// 0x530014
static AnimationSad gAnimationSads[ANIMATION_SAD_LIST_CAPACITY];
#define PATH_NODE_CAPACITY 10000
// 0x542FD4 dad
// 0x542FD4
static PathNode gClosedPathNodeList[PATH_NODE_CAPACITY];
// 0x54CC14 anim_set
// 0x54CC14
static AnimationSequence gAnimationSequences[32];
// 0x561814 seen_tile
// 0x561814
static unsigned char gPathfinderProcessedTiles[5000];
// 0x562B9C child_path
// 0x562B9C
static PathNode gOpenPathNodeList[PATH_NODE_CAPACITY];
// 0x56C7DC curr_anim_counter
// 0x56C7DC
static int gAnimationDescriptionCurrentIndex;
// anim_init
+26 -220
View File
@@ -1,9 +1,6 @@
#include "art.h"
#include <lodepng.h>
#include <assert.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -47,19 +44,19 @@ static int artReadHeader(Art* art, File* stream);
static int artGetDataSize(const Art* art);
static int paddingForSize(int size);
// 0x5002D8 str2
// 0x5002D8
static char gDefaultJumpsuitMaleFileName[] = "hmjmps";
// 0x05002E0 aHfjmps
// 0x05002E0
static char gDefaultJumpsuitFemaleFileName[] = "hfjmps";
// 0x5002E8 aHmwarr
// 0x5002E8
static char gDefaultTribalMaleFileName[] = "hmwarr";
// 0x5002F0 aHfprim
// 0x5002F0
static char gDefaultTribalFemaleFileName[] = "hfprim";
// 0x510738 art
// 0x510738
static ArtListDescription gArtListDescriptions[OBJ_TYPE_COUNT] = {
{ 0, "items", nullptr, nullptr, 0 },
{ 0, "critters", nullptr, nullptr, 0 },
@@ -77,18 +74,18 @@ static ArtListDescription gArtListDescriptions[OBJ_TYPE_COUNT] = {
// This flag denotes that localized arts should be looked up first. Used
// together with [gArtLanguage].
//
// 0x510898 darn_foreigners
// 0x510898
static bool gArtLanguageInitialized = false;
// 0x51089C head1
// 0x51089C
static const char* _head1 = "gggnnnbbbgnb";
// 0x5108A0 head2
// 0x5108A0
static const char* _head2 = "vfngfbnfvppp";
// Current native look base fid.
//
// 0x5108A4 art_vault_guy_num
// 0x5108A4
int _art_vault_guy_num = 0;
// Base fids for unarmored dude.
@@ -102,42 +99,41 @@ int _art_vault_guy_num = 0;
// been accessed differently in 0x49F984, which clearly uses look type as an
// index, not gender.
//
// 0x5108A8 art_vault_person_nums
// 0x5108A8
int _art_vault_person_nums[DUDE_NATIVE_LOOK_COUNT][GENDER_COUNT];
// Index of "grid001.frm" in tiles.lst.
//
// 0x5108B8 art_mapper_blank_tile
// 0x5108B8
static int _art_mapper_blank_tile = 1;
// Non-english language name.
//
// This value is used as a directory name to display localized arts.
//
// 0x56C970 darn_foreign_sub_path
// 0x56C970
static char gArtLanguage[32];
// 0x56C990 art_cache
// 0x56C990
Cache gArtCache;
// 0x56C9E4 art_name
// 0x56C9E4
static char _art_name[COMPAT_MAX_PATH];
// head_info
// 0x56CAE8 head_info
// 0x56CAE8
static HeadDescription* gHeadDescriptions;
// anon_alias
// 0x56CAEC anon_alias
// 0x56CAEC
static int* _anon_alias;
// artCritterFidShouldRunData
// 0x56CAF0 artCritterFidShouldRunData
// 0x56CAF0
static int* gArtCritterFidShoudRunData;
static std::unordered_map<std::string, std::shared_ptr<NamedCacheEntry>> gNamedArtCache;
constexpr int kNamedCacheMaxBytes = 32 * 1024 * 1024; // 32MB soft limit
constexpr size_t kMaxNamedPngPixels = 16 * 1024 * 1024;
static unsigned int gNamedArtCacheMruCounter = 0;
static int gNamedArtCacheCurrentBytes = 0;
@@ -359,14 +355,6 @@ int artIsObjectTypeHidden(int objectType)
return objectType >= OBJ_TYPE_ITEM && objectType < OBJ_TYPE_COUNT ? gArtListDescriptions[objectType].flags & 1 : 0;
}
// 0x409DF0
void artToggleObjectTypeHidden(int objectType)
{
if (objectType >= 0 && objectType < OBJ_TYPE_COUNT) {
gArtListDescriptions[objectType].flags ^= 1;
}
}
// 0x418F7C
int artGetFidgetCount(int headFid)
{
@@ -456,40 +444,6 @@ int art_list_str(int fid, char* name)
return -1;
}
int artListIndex(int objectType, const char* name)
{
if (objectType < 0 || objectType >= OBJ_TYPE_COUNT) return -1;
if (gArtListDescriptions[objectType].fileNames == nullptr) return -1;
char upperName[13] = { 0 };
strncpy(upperName, name, 12);
upperName[12] = '\0';
compat_strupr(upperName);
int length = gArtListDescriptions[objectType].fileNamesLength;
const char* fileNames = gArtListDescriptions[objectType].fileNames;
for (int index = 0; index < length; index++) {
const char* entry = fileNames + index * 13;
char upperEntry[13];
strncpy(upperEntry, entry, 12);
upperEntry[12] = '\0';
compat_strupr(upperEntry);
char* p = upperEntry;
while (*p && ((*p >= 'A' && *p <= 'Z') || (*p >= '0' && *p <= '9') || *p == '_'))
p++;
*p = '\0';
if (strcmp(upperEntry, upperName) == 0) {
return index;
}
}
return -1;
}
// 0x419160
Art* artLock(int fid, CacheEntry** handlePtr)
{
@@ -1120,7 +1074,7 @@ static int artReadFrameData(unsigned char* data, File* stream, int count, int* p
// 0x419E1C
static int artReadHeader(Art* art, File* stream)
{
if (fileReadInt32(stream, &(art->version)) == -1) return -1;
if (fileReadInt32(stream, &(art->field_0)) == -1) return -1;
if (fileReadInt16(stream, &(art->framesPerSecond)) == -1) return -1;
if (fileReadInt16(stream, &(art->actionFrame)) == -1) return -1;
if (fileReadInt16(stream, &(art->frameCount)) == -1) return -1;
@@ -1137,137 +1091,13 @@ static int artReadHeader(Art* art, File* stream)
return 0;
}
static bool artPathHasExtension(const char* path, const char* extension)
{
size_t pathLength = strlen(path);
size_t extensionLength = strlen(extension);
if (pathLength < extensionLength) {
return false;
}
return compat_stricmp(path + pathLength - extensionLength, extension) == 0;
}
static bool artReadFile(const char* path, std::vector<unsigned char>& data)
{
int size = 0;
if (dbGetFileSize(path, &size) != 0 || size <= 0) {
return false;
}
data.resize(size);
return dbGetFileContents(path, data.data()) == 0;
}
static bool artUnpackIndexedPngPixels(const std::vector<unsigned char>& indexedData, unsigned width, unsigned height, unsigned bitdepth, unsigned char* output)
{
size_t pixelCount = static_cast<size_t>(width) * static_cast<size_t>(height);
if (bitdepth == 8) {
if (indexedData.size() < pixelCount) {
return false;
}
memcpy(output, indexedData.data(), pixelCount);
return true;
}
unsigned char mask = static_cast<unsigned char>((1 << bitdepth) - 1);
size_t neededBytes = (pixelCount * bitdepth + 7) / 8;
if (indexedData.size() < neededBytes) {
return false;
}
for (size_t index = 0; index < pixelCount; index++) {
size_t bitOffset = index * bitdepth;
unsigned char byte = indexedData[bitOffset / 8];
unsigned shift = 8 - bitdepth - static_cast<unsigned>(bitOffset % 8);
output[index] = (byte >> shift) & mask;
}
return true;
}
static Art* artLoadIndexedPng(const char* path)
{
std::vector<unsigned char> encoded;
if (!artReadFile(path, encoded)) {
return nullptr;
}
lodepng::State state;
state.decoder.color_convert = 0;
std::vector<unsigned char> indexedData;
unsigned width = 0;
unsigned height = 0;
unsigned error = lodepng::decode(indexedData, width, height, state, encoded);
if (error != 0) {
debugPrint("ART: failed to decode indexed PNG %s: %s\n", path, lodepng_error_text(error));
return nullptr;
}
if (state.info_png.color.colortype != LCT_PALETTE) {
debugPrint("ART: PNG is not palette-indexed: %s\n", path);
return nullptr;
}
if (lodepng_has_palette_alpha(&state.info_png.color)) {
debugPrint("ART: indexed PNG transparency is unsupported, reserve palette index 0 instead: %s\n", path);
return nullptr;
}
size_t pixelCount = static_cast<size_t>(width) * static_cast<size_t>(height);
if (width == 0 || height == 0 || width > SHRT_MAX || height > SHRT_MAX) {
debugPrint("ART: invalid indexed PNG dimensions for %s: %ux%u\n", path, width, height);
return nullptr;
}
if (pixelCount > kMaxNamedPngPixels || pixelCount > INT_MAX) {
debugPrint("ART: indexed PNG is too large: %s\n", path);
return nullptr;
}
Art header = {};
header.version = 4;
header.framesPerSecond = 10;
header.actionFrame = 0;
header.frameCount = 1;
header.dataSize = sizeof(ArtFrame) + static_cast<int>(pixelCount);
int currentPadding = paddingForSize(sizeof(Art));
for (int rotation = 0; rotation < ROTATION_COUNT; rotation++) {
header.dataOffsets[rotation] = 0;
header.padding[rotation] = currentPadding;
}
int dataSize = artGetDataSize(&header);
unsigned char* data = reinterpret_cast<unsigned char*>(internal_malloc(dataSize));
if (data == nullptr) {
return nullptr;
}
memset(data, 0, dataSize);
Art* art = reinterpret_cast<Art*>(data);
*art = header;
ArtFrame* frame = reinterpret_cast<ArtFrame*>(data + sizeof(Art) + art->padding[0]);
frame->width = static_cast<short>(width);
frame->height = static_cast<short>(height);
frame->size = static_cast<int>(pixelCount);
frame->x = 0;
frame->y = 0;
if (!artUnpackIndexedPngPixels(indexedData, width, height, state.info_png.color.bitdepth, reinterpret_cast<unsigned char*>(frame) + sizeof(ArtFrame))) {
debugPrint("ART: failed to read indexed PNG pixels: %s\n", path);
internal_free(data);
return nullptr;
}
return art;
}
static Art* artLoadFrm(const char* path)
// NOTE: Original function was slightly different, but never used. Basically
// it's a memory allocating variant of `artRead` (which reads data into given
// buffer). This function is useful to load custom `frm` files since `Art` now
// needs more memory then it's on-disk size (due to memory padding).
//
// 0x419EC0
Art* artLoad(const char* path)
{
File* stream = fileOpen(path, "rb");
if (stream == nullptr) {
@@ -1295,30 +1125,6 @@ static Art* artLoadFrm(const char* path)
return reinterpret_cast<Art*>(data);
}
// NOTE: Original function was slightly different, but never used. Basically
// it's a memory allocating variant of `artRead` (which reads data into given
// buffer). This function is useful to load custom `frm` files since `Art` now
// needs more memory then it's on-disk size (due to memory padding).
//
// 0x419EC0
Art* artLoad(const char* path)
{
if (path == nullptr) {
return nullptr;
}
if (artPathHasExtension(path, ".png")) {
return artLoadIndexedPng(path);
}
Art* art = artLoadFrm(path);
if (art != nullptr) {
return art;
}
return nullptr;
}
static Art* artLoadLocalized(const char* path)
{
const char* localizedPath;
@@ -1391,7 +1197,7 @@ int artWriteFrameData(unsigned char* data, File* stream, int count)
// 0x41A138
int artWriteHeader(Art* art, File* stream)
{
if (fileWriteInt32(stream, art->version) == -1) return -1;
if (fileWriteInt32(stream, art->field_0) == -1) return -1;
if (fileWriteInt16(stream, art->framesPerSecond) == -1) return -1;
if (fileWriteInt16(stream, art->actionFrame) == -1) return -1;
if (fileWriteInt16(stream, art->frameCount) == -1) return -1;
+1 -3
View File
@@ -69,7 +69,7 @@ typedef enum Background {
} Background;
typedef struct Art {
int version;
int field_0;
short framesPerSecond;
short actionFrame;
short frameCount;
@@ -122,7 +122,6 @@ void artReset();
void artExit();
char* artGetObjectTypeName(int objectType);
int artIsObjectTypeHidden(int objectType);
void artToggleObjectTypeHidden(int objectType);
int artGetFidgetCount(int headFid);
void artRender(int fid, unsigned char* dest, int width, int height, int pitch);
int art_list_str(int fid, char* name);
@@ -151,7 +150,6 @@ int _art_alias_num(int index);
int artCritterFidShouldRun(int fid);
int artAliasFid(int fid);
int buildFid(int objectType, int frmId, int animType, int weaponCode, int rotation);
int artListIndex(int objectType, const char* name);
Art* artLoad(const char* path);
int artRead(const char* path, unsigned char* data);
int artWrite(const char* path, unsigned char* data);
+14 -214
View File
@@ -4,13 +4,9 @@
#include <stdio.h>
#include <string.h>
#include <SDL.h>
#include "db.h"
#include "debug.h"
#include "memory_manager.h"
#include "ogg_decoder.h"
#include "platform_compat.h"
#include "sound.h"
#include "sound_decoder.h"
@@ -19,41 +15,28 @@ namespace fallout {
typedef enum AudioFlags {
AUDIO_IN_USE = 0x01,
AUDIO_COMPRESSED = 0x02,
// CE: Decoded formats like WAV/OGG are fully loaded into memory up front.
AUDIO_MEMORY = 0x04,
} AudioFileFlags;
typedef struct Audio {
int flags;
File* stream;
SoundDecoder* soundDecoder;
unsigned char* data;
int fileSize;
int sampleRate;
int channels;
int bitsPerSample;
int position;
} Audio;
typedef enum AudioOpenMode {
AUDIO_OPEN_MODE_RAW = 0,
AUDIO_OPEN_MODE_COMPRESSED = 1, // ACM
AUDIO_OPEN_MODE_WAV = 2,
AUDIO_OPEN_MODE_OGG = 3,
} AudioOpenMode;
static bool defaultCompressionFunc(char* filePath);
static int audioSoundDecoderReadHandler(void* data, void* buf, unsigned int size);
static bool audioIsWavePath(const char* filePath);
static bool audioDecodeWave(File* stream, AudioFileInfo* info, unsigned char** dataPtr, int* sizePtr);
// 0x5108BC queryCompressedFunc
// 0x5108BC
static AudioQueryCompressedFunc* queryCompressedFunc = defaultCompressionFunc;
// 0x56CB00 numAudio
// 0x56CB00
static int gAudioListLength;
// 0x56CB04 audio
// 0x56CB04
static Audio* gAudioList;
// 0x41A2B0
@@ -73,128 +56,18 @@ static int audioSoundDecoderReadHandler(void* data, void* buffer, unsigned int s
return fileRead(buffer, 1, size, reinterpret_cast<File*>(data));
}
static bool audioIsWavePath(const char* filePath)
{
const char* dot = strrchr(filePath, '.');
return dot != nullptr && compat_stricmp(dot + 1, "wav") == 0;
}
static bool audioDecodeWave(File* stream, AudioFileInfo* info, unsigned char** dataPtr, int* sizePtr)
{
bool success = false;
unsigned char* fileData = nullptr;
Uint8* loadedData = nullptr;
Uint8* convertedData = nullptr;
SDL_RWops* rw = nullptr;
SDL_AudioSpec spec = {};
Uint32 loadedLength = 0;
int channels = 0;
SDL_AudioCVT cvt;
memset(&cvt, 0, sizeof(cvt));
int convertedLength = 0;
bool convertedDataNeedsFree = false;
bool loadedDataNeedsFree = false;
int fileSize = fileGetSize(stream);
if (fileSize <= 0) {
return false;
}
fileData = reinterpret_cast<unsigned char*>(internal_malloc_safe(fileSize, __FILE__, __LINE__));
if (fileRead(fileData, 1, fileSize, stream) != fileSize) {
goto done;
}
rw = SDL_RWFromConstMem(fileData, fileSize);
if (rw == nullptr) {
goto done;
}
if (SDL_LoadWAV_RW(rw, 1, &spec, &loadedData, &loadedLength) == nullptr) {
rw = nullptr;
goto done;
}
rw = nullptr;
loadedDataNeedsFree = true;
channels = spec.channels == 1 ? 1 : 2;
if (SDL_BuildAudioCVT(&cvt, spec.format, spec.channels, spec.freq, AUDIO_S16SYS, channels, spec.freq) < 0) {
goto done;
}
convertedLength = static_cast<int>(loadedLength);
if (cvt.needed != 0) {
cvt.len = static_cast<int>(loadedLength);
cvt.buf = reinterpret_cast<Uint8*>(SDL_malloc(cvt.len * cvt.len_mult));
if (cvt.buf == nullptr) {
goto done;
}
memcpy(cvt.buf, loadedData, loadedLength);
if (SDL_ConvertAudio(&cvt) != 0) {
SDL_free(cvt.buf);
goto done;
}
convertedData = cvt.buf;
convertedLength = cvt.len_cvt;
convertedDataNeedsFree = true;
} else {
convertedData = loadedData;
}
if (info != nullptr) {
info->channels = channels;
info->sampleRate = spec.freq;
info->bitsPerSample = 16;
}
if (dataPtr != nullptr && sizePtr != nullptr) {
*dataPtr = reinterpret_cast<unsigned char*>(internal_malloc_safe(convertedLength, __FILE__, __LINE__));
memcpy(*dataPtr, convertedData, convertedLength);
*sizePtr = convertedLength;
}
success = true;
done:
if (rw != nullptr) {
SDL_RWclose(rw);
}
if (convertedData != nullptr) {
if (convertedDataNeedsFree) {
SDL_free(convertedData);
}
}
if (loadedDataNeedsFree && loadedData != nullptr) {
SDL_FreeWAV(loadedData);
}
if (fileData != nullptr) {
internal_free_safe(fileData, __FILE__, __LINE__);
}
return success;
}
// AudioOpen
// 0x41A2EC
int audioOpen(const char* fname, AudioFileInfo* info, bool* isMemoryBackedPtr)
int audioOpen(const char* fname, int* sampleRate)
{
char path[COMPAT_MAX_PATH];
char path[80];
snprintf(path, sizeof(path), "%s", fname);
AudioOpenMode openMode;
if (audioIsWavePath(path)) {
openMode = AUDIO_OPEN_MODE_WAV;
} else if (oggDecoderIsFilePath(path)) {
openMode = AUDIO_OPEN_MODE_OGG;
} else if (queryCompressedFunc(path)) {
openMode = AUDIO_OPEN_MODE_COMPRESSED;
int compression;
if (queryCompressedFunc(path)) {
compression = 2;
} else {
openMode = AUDIO_OPEN_MODE_RAW;
compression = 0;
}
File* stream = fileOpen(path, "rb");
@@ -220,64 +93,17 @@ int audioOpen(const char* fname, AudioFileInfo* info, bool* isMemoryBackedPtr)
}
Audio* audioFile = &(gAudioList[index]);
memset(audioFile, 0, sizeof(*audioFile));
audioFile->flags = AUDIO_IN_USE;
audioFile->stream = stream;
if (openMode == AUDIO_OPEN_MODE_WAV || openMode == AUDIO_OPEN_MODE_OGG) {
AudioFileInfo decodedInfo = {};
audioFile->flags |= AUDIO_MEMORY;
bool decoded = false;
if (openMode == AUDIO_OPEN_MODE_WAV) {
decoded = audioDecodeWave(stream, &decodedInfo, &(audioFile->data), &(audioFile->fileSize));
} else {
AudioFileInfo audioFileInfo = {};
decoded = oggDecoderDecode(stream, &audioFileInfo, &(audioFile->data), &(audioFile->fileSize));
decodedInfo.sampleRate = audioFileInfo.sampleRate;
decodedInfo.channels = audioFileInfo.channels;
decodedInfo.bitsPerSample = audioFileInfo.bitsPerSample;
}
if (!decoded) {
fileClose(stream);
memset(audioFile, 0, sizeof(*audioFile));
debugPrint("AudioOpen: Couldn't decode %s\n", path);
return -1;
}
fileClose(stream);
audioFile->stream = nullptr;
audioFile->sampleRate = decodedInfo.sampleRate;
audioFile->channels = decodedInfo.channels;
audioFile->bitsPerSample = decodedInfo.bitsPerSample;
if (info != nullptr) {
*info = decodedInfo;
}
if (isMemoryBackedPtr != nullptr) {
*isMemoryBackedPtr = true;
}
} else if (openMode == AUDIO_OPEN_MODE_COMPRESSED) {
if (compression == 2) {
audioFile->flags |= AUDIO_COMPRESSED;
audioFile->soundDecoder = soundDecoderInit(audioSoundDecoderReadHandler, audioFile->stream, &(audioFile->channels), &(audioFile->sampleRate), &(audioFile->fileSize));
audioFile->fileSize *= 2;
audioFile->bitsPerSample = 16;
if (info != nullptr) {
info->sampleRate = audioFile->sampleRate;
info->bitsPerSample = audioFile->bitsPerSample;
}
if (isMemoryBackedPtr != nullptr) {
*isMemoryBackedPtr = false;
}
*sampleRate = audioFile->sampleRate;
} else {
audioFile->fileSize = fileGetSize(stream);
audioFile->bitsPerSample = 8;
if (info != nullptr) {
info->bitsPerSample = audioFile->bitsPerSample;
}
if (isMemoryBackedPtr != nullptr) {
*isMemoryBackedPtr = false;
}
}
audioFile->position = 0;
@@ -289,13 +115,7 @@ int audioOpen(const char* fname, AudioFileInfo* info, bool* isMemoryBackedPtr)
int audioClose(int handle)
{
Audio* audioFile = &(gAudioList[handle - 1]);
if ((audioFile->flags & AUDIO_MEMORY) != 0) {
if (audioFile->data != nullptr) {
internal_free_safe(audioFile->data, __FILE__, __LINE__);
}
} else if (audioFile->stream != nullptr) {
fileClose(audioFile->stream);
}
fileClose(audioFile->stream);
if ((audioFile->flags & AUDIO_COMPRESSED) != 0) {
soundDecoderFree(audioFile->soundDecoder);
@@ -312,16 +132,7 @@ int audioRead(int handle, void* buffer, unsigned int size)
Audio* audioFile = &(gAudioList[handle - 1]);
int bytesRead;
if ((audioFile->flags & AUDIO_MEMORY) != 0) {
bytesRead = audioFile->fileSize - audioFile->position;
if (bytesRead > static_cast<int>(size)) {
bytesRead = size;
}
if (bytesRead > 0) {
memcpy(buffer, audioFile->data + audioFile->position, bytesRead);
}
} else if ((audioFile->flags & AUDIO_COMPRESSED) != 0) {
if ((audioFile->flags & AUDIO_COMPRESSED) != 0) {
bytesRead = soundDecoderDecode(audioFile->soundDecoder, buffer, size);
} else {
bytesRead = fileRead(buffer, 1, size, audioFile->stream);
@@ -355,18 +166,7 @@ long audioSeek(int handle, long offset, int origin)
assert(false && "Should be unreachable");
}
if ((audioFile->flags & AUDIO_MEMORY) != 0) {
if (pos < 0) {
pos = 0;
}
if (pos > audioFile->fileSize) {
pos = audioFile->fileSize;
}
audioFile->position = pos;
return audioFile->position;
} else if ((audioFile->flags & AUDIO_COMPRESSED) != 0) {
if ((audioFile->flags & AUDIO_COMPRESSED) != 0) {
if (pos < audioFile->position) {
soundDecoderFree(audioFile->soundDecoder);
fileSeek(audioFile->stream, 0, SEEK_SET);
+1 -3
View File
@@ -1,13 +1,11 @@
#ifndef AUDIO_H
#define AUDIO_H
#include "sound.h"
namespace fallout {
typedef bool(AudioQueryCompressedFunc)(char* filePath);
int audioOpen(const char* fname, AudioFileInfo* info, bool* isMemoryBackedPtr);
int audioOpen(const char* fname, int* sampleRate);
int audioClose(int handle);
int audioRead(int handle, void* buffer, unsigned int size);
long audioSeek(int handle, long offset, int origin);
+6 -17
View File
@@ -30,13 +30,13 @@ typedef struct AudioFile {
static bool defaultCompressionFunc(char* filePath);
static int audioFileSoundDecoderReadHandler(void* data, void* buffer, unsigned int size);
// 0x5108C0 queryCompressedFunc_2
// 0x5108C0
static AudioFileQueryCompressedFunc* queryCompressedFunc = defaultCompressionFunc;
// 0x56CB10 audiof
// 0x56CB10
static AudioFile* gAudioFileList;
// 0x56CB14 numAudiof
// 0x56CB14
static int gAudioFileListLength;
// 0x41A850
@@ -57,7 +57,7 @@ static int audioFileSoundDecoderReadHandler(void* data, void* buffer, unsigned i
}
// 0x41A88C
int audioFileOpen(const char* fname, AudioFileInfo* info, bool* isMemoryBackedPtr)
int audioFileOpen(const char* fname, int* sampleRate)
{
char path[COMPAT_MAX_PATH];
strcpy(path, fname);
@@ -98,21 +98,10 @@ int audioFileOpen(const char* fname, AudioFileInfo* info, bool* isMemoryBackedPt
audioFile->flags |= AUDIO_FILE_COMPRESSED;
audioFile->soundDecoder = soundDecoderInit(audioFileSoundDecoderReadHandler, audioFile->stream, &(audioFile->channels), &(audioFile->sampleRate), &(audioFile->fileSize));
audioFile->fileSize *= 2;
if (info != nullptr) {
info->sampleRate = audioFile->sampleRate;
info->bitsPerSample = 16;
}
if (isMemoryBackedPtr != nullptr) {
*isMemoryBackedPtr = false;
}
*sampleRate = audioFile->sampleRate;
} else {
audioFile->fileSize = getFileSize(stream);
if (info != nullptr) {
info->bitsPerSample = 8;
}
if (isMemoryBackedPtr != nullptr) {
*isMemoryBackedPtr = false;
}
}
audioFile->position = 0;
+1 -3
View File
@@ -1,13 +1,11 @@
#ifndef AUDIO_FILE_H
#define AUDIO_FILE_H
#include "sound.h"
namespace fallout {
typedef bool(AudioFileQueryCompressedFunc)(char* filePath);
int audioFileOpen(const char* fname, AudioFileInfo* info, bool* isMemoryBackedPtr);
int audioFileOpen(const char* fname, int* sampleRate);
int audioFileClose(int handle);
int audioFileRead(int handle, void* buf, unsigned int size);
long audioFileSeek(int handle, long offset, int origin);
+23 -23
View File
@@ -62,14 +62,14 @@ typedef struct AutomapEntry {
unsigned char* data;
} AutomapEntry;
// 0x41ADE0 defam
// 0x41ADE0
static const int _defam[AUTOMAP_MAP_COUNT][ELEVATION_COUNT] = {
{ -1, -1, -1 },
{ -1, -1, -1 },
{ -1, -1, -1 },
};
// 0x41B560 displayMapList
// 0x41B560
static int _displayMapList[AUTOMAP_MAP_COUNT] = {
-1,
-1,
@@ -242,17 +242,17 @@ static const int gAutomapFrmIds[AUTOMAP_FRM_COUNT] = {
173, // autodwn.frm - switch down
};
// 0x5108C4 autoflags
// 0x5108C4
static int gAutomapFlags = 0;
// 0x56CB18 amdbhead
// 0x56CB18
static AutomapHeader gAutomapHeader;
// 0x56D2A0 amdbsubhead
// 0x56D2A0
static AutomapEntry gAutomapEntry;
// automap_init
// 0x41B7F4 automap_init
// 0x41B7F4
int automapInit()
{
gAutomapFlags = 0;
@@ -260,7 +260,7 @@ int automapInit()
return 0;
}
// 0x41B808 automap_reset
// 0x41B808
int automapReset()
{
gAutomapFlags = 0;
@@ -268,7 +268,7 @@ int automapReset()
return 0;
}
// 0x41B81C automap_exit
// 0x41B81C
void automapExit()
{
char path[COMPAT_MAX_PATH];
@@ -276,25 +276,25 @@ void automapExit()
compat_remove(path);
}
// 0x41B87C automap_load
// 0x41B87C
int automapLoad(File* stream)
{
return fileReadInt32(stream, &gAutomapFlags);
}
// 0x41B898 automap_save
// 0x41B898
int automapSave(File* stream)
{
return fileWriteInt32(stream, gAutomapFlags);
}
// 0x41B8B4 automapDisplayMap
// 0x41B8B4
int _automapDisplayMap(int map)
{
return _displayMapList[map];
}
// 0x41B8BC automap
// 0x41B8BC
void automapShow(bool isInGame, bool isUsingScanner)
{
ScopedGameMode gm(GameMode::kAutomap);
@@ -499,7 +499,7 @@ void automapShow(bool isInGame, bool isUsingScanner)
// Renders automap in Map window.
//
// 0x41BD1C draw_top_down_map
// 0x41BD1C
static void automapRenderInMapWindow(int window, int elevation, unsigned char* backgroundData, int flags)
{
int color;
@@ -620,7 +620,7 @@ static void automapRenderInMapWindow(int window, int elevation, unsigned char* b
// Renders automap in Pipboy window.
//
// 0x41C004 draw_top_down_map_pipboy
// 0x41C004
int automapRenderInPipboyWindow(int window, int map, int elevation)
{
unsigned char* windowBuffer = windowGetBuffer(window) + 640 * AUTOMAP_PIPBOY_VIEW_Y + AUTOMAP_PIPBOY_VIEW_X;
@@ -682,7 +682,7 @@ int automapRenderInPipboyWindow(int window, int map, int elevation)
}
// automap_pip_save
// 0x41C0F0 automap_pip_save
// 0x41C0F0
int automapSaveCurrent()
{
int map = mapGetCurrentMap();
@@ -896,7 +896,7 @@ int automapSaveCurrent()
// Saves automap entry into stream.
//
// 0x41C844 WriteAM_Entry
// 0x41C844
static int automapSaveEntry(File* stream)
{
unsigned char* buffer;
@@ -928,7 +928,7 @@ err:
return -1;
}
// 0x41C8CC AM_ReadEntry
// 0x41C8CC
static int automapLoadEntry(int map, int elevation)
{
gAutomapEntry.compressedData = nullptr;
@@ -1015,7 +1015,7 @@ out:
// Saves automap.db header.
//
// 0x41CAD8 WriteAM_Header
// 0x41CAD8
static int automapSaveHeader(File* stream)
{
fileRewind(stream);
@@ -1045,7 +1045,7 @@ err:
// Loads automap.db header.
//
// 0x41CB50 AM_ReadMainHeader
// 0x41CB50
static int automapLoadHeader(File* stream)
{
@@ -1068,7 +1068,7 @@ static int automapLoadHeader(File* stream)
return 0;
}
// 0x41CBA4 decode_map_data
// 0x41CBA4
static void _decode_map_data(int elevation)
{
memset(gAutomapEntry.data, 0, SQUARE_GRID_SIZE);
@@ -1101,7 +1101,7 @@ static void _decode_map_data(int elevation)
}
}
// 0x41CC98 am_pip_init
// 0x41CC98
static int automapCreate()
{
gAutomapHeader.version = 1;
@@ -1128,7 +1128,7 @@ static int automapCreate()
// Copy data from stream1 to stream2.
//
// 0x41CD6C copy_file_data
// 0x41CD6C
static int _copy_file_data(File* stream1, File* stream2, int length)
{
void* buffer = internal_malloc(0xFFFF);
@@ -1160,7 +1160,7 @@ static int _copy_file_data(File* stream1, File* stream2, int length)
return 0;
}
// 0x41CE74 ReadAMList
// 0x41CE74
int automapGetHeader(AutomapHeader** automapHeaderPtr)
{
char path[COMPAT_MAX_PATH];
+3 -3
View File
@@ -5,13 +5,13 @@
#endif
#ifdef _WIN32
// 0x530010 autorun_mutex
// 0x530010
static HANDLE gInterplayGenericAutorunMutex;
#endif
namespace fallout {
// 0x4139C0 autorun_mutex_create
// 0x4139C0
bool autorunMutexCreate()
{
#ifdef _WIN32
@@ -25,7 +25,7 @@ bool autorunMutexCreate()
return true;
}
// 0x413A00 autorun_mutex_destroy
// 0x413A00
void autorunMutexClose()
{
#ifdef _WIN32

Some files were not shown because too many files have changed in this diff Show More