Skip to content

Commit

Permalink
First attempt at adding support for directional sound.
Browse files Browse the repository at this point in the history
Also fixed a small issue in CMakeLists.txt.
  • Loading branch information
Falcury committed Jan 20, 2020
1 parent 4acfe46 commit b2fac76
Show file tree
Hide file tree
Showing 10 changed files with 230 additions and 5 deletions.
3 changes: 3 additions & 0 deletions SDLPoP.ini
Expand Up @@ -25,6 +25,9 @@ enable_copyprot = false
; Enable music.
enable_music = true

; Enable directional sound.
enable_directional_sound = false

; Enable or disable fading.
enable_fade = true

Expand Down
2 changes: 1 addition & 1 deletion src/CMakeLists.txt
Expand Up @@ -115,7 +115,7 @@ endif()

if(WIN32)
target_link_libraries(prince mingw32 SDL2main SDL2 SDL2_image)
elif(APPLE)
elseif(APPLE)
target_link_libraries(prince SDL2main SDL2 SDL2_image m)
else() # Linux, *BSD, etc.
target_link_libraries(prince SDL2 SDL2_image m)
Expand Down
9 changes: 9 additions & 0 deletions src/data.h
Expand Up @@ -673,6 +673,14 @@ extern word justblocked; // name from Apple II source
// data:5F84
extern word last_loose_sound;

extern short want_directional_sound;
extern short next_sound_is_directional;
extern short current_sound_is_directional;
extern float current_sound_dir_x;
extern float current_sound_distance;
extern float sound_distance_loss;
room_offset_type room_offsets[24];

extern int last_key_scancode;
extern font_type hc_font INIT(= {0x01,0xFF, 7,2,1,1, NULL});
extern textstate_type textstate INIT(= {0,0,0,15,&hc_font});
Expand Down Expand Up @@ -707,6 +715,7 @@ extern bool skip_normal_data_files;
extern byte use_fixes_and_enhancements INIT(= 0);
extern byte enable_copyprot INIT(= 0);
extern byte enable_music INIT(= 1);
extern byte enable_directional_sound INIT(= 0);
extern byte enable_fade INIT(= 1);
extern byte enable_flash INIT(= 1);
extern byte enable_text INIT(= 1);
Expand Down
7 changes: 7 additions & 0 deletions src/menu.c
Expand Up @@ -142,6 +142,7 @@ enum setting_ids {
SETTING_ENABLE_INFO_SCREEN,
SETTING_ENABLE_SOUND,
SETTING_ENABLE_MUSIC,
SETTING_ENABLE_DIRECTIONAL_SOUND,
SETTING_ENABLE_CONTROLLER_RUMBLE,
SETTING_JOYSTICK_THRESHOLD,
SETTING_JOYSTICK_ONLY_HORIZONTAL,
Expand Down Expand Up @@ -302,6 +303,11 @@ setting_type general_settings[] = {
{.id = SETTING_ENABLE_MUSIC, .style = SETTING_STYLE_TOGGLE, .linked = &enable_music,
.text = "Enable music",
.explanation = "Turn music on or off."},
{.id = SETTING_ENABLE_DIRECTIONAL_SOUND, .style = SETTING_STYLE_TOGGLE, .linked = &enable_directional_sound,
.text = "Enable directional sound",
.explanation = "Turn directional sound on or off.\n"
"Works best with headphones.\n"
"Distant sounds will also be softer.\n"},
{.id = SETTING_ENABLE_CONTROLLER_RUMBLE, .style = SETTING_STYLE_TOGGLE, .linked = &enable_controller_rumble,
.text = "Enable controller rumble",
.explanation = "If using a controller with a rumble motor, provide haptic feedback when the kid is hurt."},
Expand Down Expand Up @@ -1994,6 +2000,7 @@ void process_ingame_settings_user_managed(SDL_RWops* rw, rw_process_func_type pr
process(enable_fade);
process(enable_flash);
process(enable_lighting);
process(enable_directional_sound);
}

void process_ingame_settings_mod_managed(SDL_RWops* rw, rw_process_func_type process_func) {
Expand Down
2 changes: 2 additions & 0 deletions src/options.c
Expand Up @@ -175,6 +175,7 @@ static int global_ini_callback(const char *section, const char *name, const char
#endif
process_boolean("enable_copyprot", &enable_copyprot);
process_boolean("enable_music", &enable_music);
process_boolean("enable_directional_sound", &enable_directional_sound);
process_boolean("enable_fade", &enable_fade);
process_boolean("enable_flash", &enable_flash);
process_boolean("enable_text", &enable_text);
Expand Down Expand Up @@ -413,6 +414,7 @@ void set_options_to_default() {
#endif
enable_copyprot = 0;
enable_music = 1;
enable_directional_sound = 0;
enable_fade = 1;
enable_flash = 1;
enable_text = 1;
Expand Down
2 changes: 2 additions & 0 deletions src/proto.h
Expand Up @@ -34,6 +34,7 @@ void __pascal far load_level();
void reset_level_unused_fields(bool loading_clean_level);
int __pascal far play_kid_frame();
void __pascal far play_guard_frame();
void find_all_rooms_from(byte starting_room);
void __pascal far check_the_end();
void __pascal far check_fall_flo();
void __pascal far read_joyst_control();
Expand All @@ -44,6 +45,7 @@ void __pascal far set_health_life();
void __pascal far draw_hp();
void __pascal far do_delta_hp();
void __pascal far play_sound(int sound_id);
void set_sound_room(int room);
void __pascal far play_next_sound();
void __pascal far check_sword_vs_sword();
void __pascal far load_chtab_from_file(int chtab_id,int resource,const char near *filename,int palette_bits);
Expand Down
87 changes: 87 additions & 0 deletions src/seg000.c
Expand Up @@ -387,6 +387,7 @@ void restore_room_after_quick_load() {
text_time_total = text_time_remaining = 0;
//next_sound = current_sound = -1;
exit_room_timer = 0;
find_all_rooms_from(drawn_room);
}

int quick_load() {
Expand Down Expand Up @@ -1180,6 +1181,68 @@ void __pascal far play_guard_frame() {
}
}

void dijkstra_visit_room(byte room) {
if (!(room > 0 && room <= 24)) return;
room_offset_type* current_node = &room_offsets[room - 1];
current_node->visited = 1;

byte next_distance = current_node->distance + 1;
sbyte curr_offset_x = current_node->dx;
sbyte curr_offset_y = current_node->dy;
link_type links = level.roomlinks[room-1];
room_offset_type* left = (links.left > 0 && links.left <= 24) ? &room_offsets[links.left-1] : NULL;
room_offset_type* right = (links.right > 0 && links.right <= 24) ? &room_offsets[links.right-1] : NULL;
room_offset_type* up = (links.up > 0 && links.up <= 24) ? &room_offsets[links.up-1] : NULL;
room_offset_type* down = (links.down > 0 && links.down <= 24) ? &room_offsets[links.down-1] : NULL;
if (left != NULL && next_distance < left->distance) {
left->distance = next_distance;
left->dx = curr_offset_x - 1;
left->dy = curr_offset_y;
}
if (right != NULL && next_distance < right->distance) {
right->distance = next_distance;
right->dx = curr_offset_x + 1;
right->dy = curr_offset_y;
}
if (up != NULL && next_distance < up->distance) {
up->distance = next_distance;
up->dx = curr_offset_x;
up->dy = curr_offset_y - 1;
}
if (down != NULL && next_distance < down->distance) {
down->distance = next_distance;
down->dx = curr_offset_x;
down->dy = curr_offset_y + 1;
}
}

// Find where all reachable rooms are located relative to the current room, using Dijkstra's algorithm.
// https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm
void find_all_rooms_from(byte starting_room) {
memset(room_offsets, 0, sizeof(room_offsets));
for (int i = 0; i < COUNT(room_offsets); ++i) {
room_offsets[i].distance = 255;
}
room_offsets[starting_room-1].distance = 0; // The starting node is at distance=0 by definition.
room_offsets[starting_room-1].visited = false;

int current_node = drawn_room;
for (int i = 1; i <= 24; ++i) {
dijkstra_visit_room(current_node);
// Find the unvisited node with the lowest distance to the starting node, and repeat.
current_node = 0;
int closest_distance = 255;
for (int j = 1; j <= 24; ++j) {
room_offset_type* node = &room_offsets[j-1];
if (!node->visited && node->distance < closest_distance) {
closest_distance = node->distance;
current_node = j;
}
}
if (current_node > 0) continue; else break; // All nodes visited.
}
}

// seg000:0FBD
void __pascal far check_the_end() {
if (next_room != 0 && next_room != drawn_room) {
Expand All @@ -1199,6 +1262,7 @@ void __pascal far check_the_end() {
start_chompers();
check_fall_flo();
check_shadow();
find_all_rooms_from(drawn_room);
}
}

Expand Down Expand Up @@ -1533,6 +1597,28 @@ void __pascal far play_sound(int sound_id) {
if (NULL == sound_pointers[sound_id]) return;
if (sound_pcspeaker_exists[sound_id] != 0 || sound_pointers[sound_id]->type != sound_speaker) {
next_sound = sound_id;
next_sound_is_directional = want_directional_sound;
}
}
want_directional_sound = false;
}

void set_sound_room(int room) {
room_offset_type room_offset = room_offsets[room-1];
if (room_offset.visited) {
float distance_x = (float) ABS(room_offset.dx);
float distance_y = (float) ABS(room_offset.dy);

if (room_offset.dx != 0 || room_offset.dy != 0) {
want_directional_sound = true;
current_sound_distance = sqrtf(distance_x*distance_x + distance_y*distance_y); // Assumes rooms are square...
sound_distance_loss = 1.0f / MAX(1.0f, log2f(current_sound_distance + 1.0f) * 4.0f); // could be tweaked
float angle = atan2f((float) room_offset.dy, (float) room_offset.dx);
current_sound_dir_x = cosf(angle);
} else {
want_directional_sound = false;
current_sound_distance = 0.0f;
sound_distance_loss = 1.0f;
}
}
}
Expand All @@ -1544,6 +1630,7 @@ void __pascal far play_next_sound() {
(sound_interruptible[current_sound] != 0 && sound_prio_table[next_sound] <= sound_prio_table[current_sound])
) {
current_sound = next_sound;
current_sound_is_directional = next_sound_is_directional;
play_sound_from_buffer(sound_pointers[current_sound]);
}
}
Expand Down
30 changes: 30 additions & 0 deletions src/seg007.c
Expand Up @@ -359,6 +359,10 @@ Possible values of anim_type:
//if ((curr_modifier -= gate_close_speeds[anim_type]) < 0) {
curr_modifier = 0;
trob.type = -1;
if (enable_directional_sound) {
byte sound_room = trob.tilepos % 10 == 9 ? level.roomlinks[trob.room-1].right : trob.room;
set_sound_room(sound_room);
}
play_sound(sound_6_gate_closing_fast); // gate closing fast
}
} else {
Expand All @@ -370,6 +374,10 @@ Possible values of anim_type:
if (curr_modifier != 0) {
if (curr_modifier < 188) {
if ((curr_modifier & 3) == 3) {
if (enable_directional_sound) {
byte sound_room = trob.tilepos % 10 == 9 ? level.roomlinks[trob.room-1].right : trob.room;
set_sound_room(sound_room);
}
play_door_sound_if_visible(sound_4_gate_closing); // gate closing
}
}
Expand All @@ -380,6 +388,10 @@ Possible values of anim_type:
// opening
if (curr_modifier < 188) {
if ((curr_modifier & 7) == 0) {
if (enable_directional_sound) {
byte sound_room = trob.tilepos % 10 == 9 ? level.roomlinks[trob.room-1].right : trob.room;
set_sound_room(sound_room);
}
play_sound(sound_5_gate_opening); // gate opening
}
} else {
Expand All @@ -388,6 +400,10 @@ Possible values of anim_type:
// after regular open
curr_modifier = 238;
trob.type = 0; // closing
if (enable_directional_sound) {
byte sound_room = trob.tilepos % 10 == 9 ? level.roomlinks[trob.room-1].right : trob.room;
set_sound_room(sound_room);
}
play_sound(sound_7_gate_stop); // gate stop (after opening)
} else {
// after permanent open
Expand All @@ -407,6 +423,10 @@ Possible values of anim_type:
// seg007:05E3
void __pascal far gate_stop() {
trob.type = -1;
if (enable_directional_sound) {
byte sound_room = trob.tilepos % 10 == 9 ? level.roomlinks[trob.room-1].right : trob.room;
set_sound_room(sound_room);
}
play_door_sound_if_visible(sound_7_gate_stop); // gate stop (after closing)
}

Expand Down Expand Up @@ -459,6 +479,9 @@ Possible values of trob_type:
}
} else {
sound_interruptible[sound_15_leveldoor_sliding] = 0;
if (enable_directional_sound) {
set_sound_room(trob.room);
}
play_sound(sound_15_leveldoor_sliding); // level door sliding (opening)
}
}
Expand Down Expand Up @@ -873,6 +896,9 @@ void __pascal far loose_shake(int arg_0) {
// random sample rate (10500..11500)
//sound_pointers[sound_id]->samplerate = prandom(1000) + 10500;
}
if (enable_directional_sound) {
set_sound_room(trob.room);
}
play_sound(sound_id);
}
}
Expand Down Expand Up @@ -1025,6 +1051,9 @@ void __pascal far move_loose() {
mob_down_a_row();
return;
}
if (enable_directional_sound) {
set_sound_room(curmob.room);
}
play_sound(sound_2_tile_crashing); // tile crashing
do_knock(curmob.room, curmob.row);
curmob.y = y_something[curmob.row + 1];
Expand Down Expand Up @@ -1257,4 +1286,5 @@ void __pascal far play_door_sound_if_visible(int sound_id) {
if (has_sound) {
play_sound(sound_id);
}
want_directional_sound = false;
}

0 comments on commit b2fac76

Please sign in to comment.