From 18e755d99bb69f7c88da430d38db624085029615 Mon Sep 17 00:00:00 2001 From: nmlgc Date: Sun, 27 Jun 2021 15:28:58 +0200 Subject: [PATCH] [Decompilation] [th04] Bullets: Regular spawn function Part of P0150, funded by Blue Bolt. --- Research/Borland C++ decompilation.md | 3 + th01/math/subpixel.hpp | 10 +- th04/main/bullet/add.cpp | 99 ++++++++++++++++++ th04/main/bullet/bullet.hpp | 7 ++ th04/main/bullet/bullet.inc | 1 + th04/main/gather.hpp | 1 + th04/main/gather[bss].asm | 1 + th04/main032.cpp | 2 + th04_main.asm | 139 -------------------------- 9 files changed, 123 insertions(+), 140 deletions(-) diff --git a/Research/Borland C++ decompilation.md b/Research/Borland C++ decompilation.md index 8ebc0953..2ae7f62d 100644 --- a/Research/Borland C++ decompilation.md +++ b/Research/Borland C++ decompilation.md @@ -15,6 +15,9 @@ Example: | `[bp-1]` | `char var_2;` | | `[bp-2]` | `char var_3;` | +* Local `enum` variables with underlying 1-byte types are always word-aligned, + regardless of the value of `-a`. + ### Grouping Any structures or classes that contain more than a single scalar-type member diff --git a/th01/math/subpixel.hpp b/th01/math/subpixel.hpp index 9c37e44f..c0363cbd 100644 --- a/th01/math/subpixel.hpp +++ b/th01/math/subpixel.hpp @@ -87,7 +87,15 @@ template struct SPPointBase { // 16-bit (Q12.4) typedef SubpixelBase Subpixel; -typedef SPPointBase SPPoint; + +struct SPPoint : public SPPointBase { + void set_long(subpixel_t subpixel_x, subpixel_t subpixel_y) { + reinterpret_cast(x) = ( + subpixel_x | (static_cast(subpixel_y) << 16) + ); + } +}; + // 8-bit (Q4.4) typedef SubpixelBase SubpixelLength8; typedef SubpixelBase Subpixel8; diff --git a/th04/main/bullet/add.cpp b/th04/main/bullet/add.cpp index f4ca6448..ede10da3 100644 --- a/th04/main/bullet/add.cpp +++ b/th04/main/bullet/add.cpp @@ -458,3 +458,102 @@ bool near bullet_template_clip(void) } return false; } + +#define bullet_set_spawn_vars(ptr, available, spawn_state, spawn_type) \ + spawn_state = BSS_GRAZEABLE; \ + switch(spawn_type) { \ + case BST_PELLET: \ + ptr = &pellets[PELLET_COUNT - 1]; \ + available = PELLET_COUNT; \ + break; \ + case BST_BULLET16_CLOUD_BACKWARDS: \ + spawn_state = BSS_CLOUD_BACKWARDS; \ + goto bullet16; \ + case BST_BULLET16_CLOUD_FORWARDS: \ + spawn_state = BSS_CLOUD_FORWARDS; \ + goto bullet16; \ + default: \ + bullet16: \ + ptr = &bullets16[BULLET16_COUNT - 1]; \ + available = BULLET16_COUNT; \ + break; \ + } + +#define bullet_init_from_template(bullet, group_done, group_i, spawn_state) \ + bullet->age = 0; \ + bullet->pos.cur = bullet_template.origin; \ + bullet->from_group = bullet_template.group; \ + bullet->patnum = bullet_template.patnum; \ + bullet->spawn_state = static_cast(spawn_state); \ + \ + group_done = bullet_velocity_and_angle_set(group_i); \ + \ + if(bullet_template.patnum >= PAT_BULLET16_D) { \ + bullet->patnum += bullet_patnum_for_angle(group_i_absolute_angle); \ + } \ + \ + bullet->pos.velocity = bullet_template.velocity; \ + bullet->angle = group_i_absolute_angle; \ + bullet->speed_final = bullet_template.speed; \ + bullet->speed_cur = bullet_template.speed; \ + +void pascal near bullets_add_regular_raw(void) +{ + bullet_t near *bullet; + int group_i; + int bullets_available; + unsigned char move_state; + bool group_done; + unsigned char spawn_state; // MODDERS: Should be bullet_spawn_state_t + + if(bullet_template.spawn_type == BST_GATHER_PELLET) { + gather_template.center = bullet_template.origin; + gather_template.velocity.set_long(0.0f, 0.0f); + gather_template.radius.set(GATHER_RADIUS_START); + gather_template.angle_delta = 0x02; + gather_template.col = 9; + gather_template.ring_points = 8; + bullet_template.spawn_type = BST_PELLET; + gather_add_bullets(); + return; + } + if(bullet_template_clip()) { + return; + } + + bullet_set_spawn_vars( + bullet, bullets_available, spawn_state, bullet_template.spawn_type + ); + + move_state = BMS_REGULAR; + if( + (bullet_template.speed < to_sp8(BMS_SLOWDOWN_THRESHOLD)) || + bullet_clear_time + ) { + if( + (bullet_template.group != BG_STACK) && + (bullet_template.group != BG_STACK_AIMED) + ) { + move_state = BMS_SLOWDOWN; + } + } + + group_i = 0; + while(bullets_available > 0) { + if(bullet->flag == 0) { + bullet->flag = 1; + bullet->move_state = static_cast(move_state); + bullet->ax.slowdown_time = BMS_SLOWDOWN_FRAMES; + bullet->dx.slowdown_speed_delta = ( + to_sp8(BMS_SLOWDOWN_BASE_SPEED) - bullet_template.speed + ); + bullet_init_from_template(bullet, group_done, group_i, spawn_state); + if(group_done) { + break; + } + group_i++; + } + bullets_available--; + bullet--; + } +} diff --git a/th04/main/bullet/bullet.hpp b/th04/main/bullet/bullet.hpp index 503f0498..bfbda2e8 100644 --- a/th04/main/bullet/bullet.hpp +++ b/th04/main/bullet/bullet.hpp @@ -15,7 +15,14 @@ /// bullet.hpp! #define BSS_CLOUD_FRAMES (BULLET_CLOUD_CELS * 4) #define BMS_DECAY_FRAMES (BULLET_DECAY_CELS * 4) + +// Regular bullets with a given speed below BMS_SLOWDOWN_THRESHOLD are set to +// BMS_SLOWDOWN. This fires them at BMS_SLOWDOWN_BASE_SPEED instead, and then +// gradually slows them down to their given speed over the next +// BMS_SLOWDOWN_FRAMES. +// • In TH04, this is not done for stacks. #define BMS_SLOWDOWN_BASE_SPEED 4.5f +#define BMS_SLOWDOWN_THRESHOLD (BMS_SLOWDOWN_BASE_SPEED - 0.5f) #define BMS_SLOWDOWN_FRAMES 32 enum bullet_spawn_state_t { diff --git a/th04/main/bullet/bullet.inc b/th04/main/bullet/bullet.inc index ee541687..ef13e1a0 100644 --- a/th04/main/bullet/bullet.inc +++ b/th04/main/bullet/bullet.inc @@ -6,6 +6,7 @@ BSS_CLOUD_FRAMES = 16 BMS_DECAY_FRAMES = 16 BMS_SLOWDOWN_BASE_SPEED = (4 shl 4) + 8 +BMS_SLOWDOWN_THRESHOLD = (BMS_SLOWDOWN_BASE_SPEED - 8) BMS_SLOWDOWN_FRAMES = 32 ; bullet_spawn_state_t diff --git a/th04/main/gather.hpp b/th04/main/gather.hpp index d5336da3..80ee938b 100644 --- a/th04/main/gather.hpp +++ b/th04/main/gather.hpp @@ -34,6 +34,7 @@ struct gather_template_t { #define GATHER_POINT_W 8 #define GATHER_POINT_H 8 #define GATHER_FRAMES 32 +#define GATHER_RADIUS_START 64.0f #define GATHER_RADIUS_END 2.0f #define GATHER_COUNT 16 diff --git a/th04/main/gather[bss].asm b/th04/main/gather[bss].asm index a1035a42..93066fc3 100644 --- a/th04/main/gather[bss].asm +++ b/th04/main/gather[bss].asm @@ -28,6 +28,7 @@ gather_template_t ends GATHER_POINT_W = 8 GATHER_POINT_H = 8 GATHER_FRAMES = 32 +GATHER_RADIUS_START = (64 shl 4) GATHER_RADIUS_END = (2 shl 4) GATHER_COUNT = 16 diff --git a/th04/main032.cpp b/th04/main032.cpp index 01c5f3e0..a494d5c3 100644 --- a/th04/main032.cpp +++ b/th04/main032.cpp @@ -15,10 +15,12 @@ extern "C" { #include "th04/math/motion.hpp" #include "th04/math/randring.h" #include "th04/math/vector.hpp" +#include "th04/sprites/main_pat.h" #include "th04/main/playfld.hpp" #include "th04/main/playperf.hpp" #include "th04/main/player/player.hpp" #include "th04/main/bullet/bullet.hpp" +#include "th04/main/gather.hpp" #pragma option -a2 #include "th04/main/bullet/add.cpp" diff --git a/th04_main.asm b/th04_main.asm index 3cf774c7..3ed775e5 100644 --- a/th04_main.asm +++ b/th04_main.asm @@ -28232,145 +28232,6 @@ main_033_TEXT segment byte public 'CODE' use16 angle:byte _bullet_template_clip procdesc near -; =============== S U B R O U T I N E ======================================= - -; Attributes: bp-based frame -public BULLETS_ADD_REGULAR_RAW -bullets_add_regular_raw proc near - -@@spawn_state = byte ptr -5 -@@done = byte ptr -4 -@@move_state = byte ptr -3 -@@i = word ptr -2 - - push bp - mov bp, sp - sub sp, 6 - push si - push di - cmp _bullet_template.spawn_type, BST_GATHER_PELLET - jnz short loc_1D2D5 - mov eax, _bullet_template.BT_origin - mov _gather_template.GT_center, eax - mov _gather_template.GT_velocity, 0 - mov _gather_template.GT_radius, (64 shl 4) - mov _gather_template.GT_angle_delta, 2 - mov _gather_template.GT_col, 9 - mov _gather_template.GT_ring_points, 8 - mov _bullet_template.spawn_type, BST_PELLET - call _gather_add_bullets - jmp loc_1D3BB -; --------------------------------------------------------------------------- - -loc_1D2D5: - call _bullet_template_clip - or al, al - jnz loc_1D3BB - mov [bp+@@spawn_state], BSS_GRAZEABLE - mov al, _bullet_template.spawn_type - mov ah, 0 - cmp ax, BST_PELLET - jz short @@pellet - cmp ax, BST_BULLET16_CLOUD_FORWARDS - jz short @@cloud_forwards - cmp ax, BST_BULLET16_CLOUD_BACKWARDS - jz short @@cloud_backwards - jmp short loc_1D30C -; --------------------------------------------------------------------------- - -@@pellet: - mov si, offset _pellets[(PELLET_COUNT - 1) * size bullet_t] - mov [bp+@@i], PELLET_COUNT - jmp short loc_1D314 -; --------------------------------------------------------------------------- - -@@cloud_backwards: - mov [bp+@@spawn_state], BSS_CLOUD_BACKWARDS - jmp short loc_1D30C -; --------------------------------------------------------------------------- - -@@cloud_forwards: - mov [bp+@@spawn_state], BSS_CLOUD_FORWARDS - -loc_1D30C: - mov si, offset _bullets16[(BULLET16_COUNT - 1) * size bullet_t] - mov [bp+@@i], BULLET16_COUNT - -loc_1D314: - mov [bp+@@move_state], BMS_REGULAR - cmp _bullet_template.speed, (4 shl 4) - jb short loc_1D326 - cmp _bullet_clear_time, 0 - jz short loc_1D338 - -loc_1D326: - cmp _bullet_template.BT_group, BG_STACK - jz short loc_1D338 - cmp _bullet_template.BT_group, BG_STACK_AIMED - jz short loc_1D338 - mov [bp+@@move_state], BMS_SLOWDOWN - -loc_1D338: - xor di, di - jmp short loc_1D3B5 -; --------------------------------------------------------------------------- - -loc_1D33C: - cmp [si+bullet_t.flag], 0 - jnz short loc_1D3AF - mov [si+bullet_t.flag], 1 - mov al, [bp+@@move_state] - mov [si+bullet_t.move_state], al - mov [si+bullet_t.slowdown_time], BMS_SLOWDOWN_FRAMES - mov al, BMS_SLOWDOWN_BASE_SPEED - sub al, _bullet_template.speed - mov [si+bullet_t.slowdown_speed_delta], al - mov [si+bullet_t.age], 0 - mov eax, _bullet_template.BT_origin - mov dword ptr [si+bullet_t.pos.cur], eax - mov al, _bullet_template.BT_group - mov [si+bullet_t.from_group], al - mov al, _bullet_template.patnum - mov ah, 0 - mov [si+bullet_t.BULLET_patnum], ax - mov al, [bp+@@spawn_state] - mov [si+bullet_t.spawn_state], al - call BULLET_VELOCITY_AND_ANGLE_SET pascal, di - mov [bp+@@done], al - cmp _bullet_template.patnum, PAT_BULLET16_D - jb short loc_1D391 - call bullet_patnum_for_angle pascal, word ptr _group_i_absolute_angle - mov ah, 0 - add [si+bullet_t.BULLET_patnum], ax - -loc_1D391: - mov eax, _bullet_template.BT_velocity - mov dword ptr [si+bullet_t.pos.velocity], eax - mov al, _group_i_absolute_angle - mov [si+bullet_t.BULLET_angle], al - mov al, _bullet_template.speed - mov [si+bullet_t.speed_final], al - mov [si+bullet_t.speed_cur], al - cmp [bp+@@done], 0 - jnz short loc_1D3BB - inc di - -loc_1D3AF: - dec [bp+@@i] - sub si, size bullet_t - -loc_1D3B5: - cmp [bp+@@i], 0 - jg short loc_1D33C - -loc_1D3BB: - pop di - pop si - leave - retn -bullets_add_regular_raw endp - - ; =============== S U B R O U T I N E ======================================= ; Attributes: bp-based frame