[Decompilation] [th01] Pellets: Manager class constructor

Note how Turbo C++ auto-generates that call to `operator new`, which
you don't see in the decompilation anymore. So yeah, as soon as you add
a constructor, Turbo C++ enforces heap allocation for any instance of
that class, even function-local ones that would otherwise be
stack-allocated.

That's where the bad reputation of C++ comes from, I guess?

Part of P0102, funded by Yanga.
This commit is contained in:
nmlgc 2020-07-04 13:52:53 +02:00
parent c11a95666b
commit edb70162e0
8 changed files with 89 additions and 114 deletions

View File

@ -59,7 +59,7 @@ bin\th01\op.exe: bin\piloadc.obj bin\th01\op.obj th01\op_01.cpp th01\op_02.c th0
$**
|
bin\th01\reiiden.exe: bin\piloadc.obj bin\th01\reiiden.obj th01\main_01.cpp th01\main_01_.cpp th01\main_02.c th01\main_03.c th01\main_04.c th01\main_05.c th01\main_06.cpp th01\main_07.cpp th01\main_08.cpp th01\main_09.cpp th01\main_12.c th01\main_13.cpp th01\main_13_.cpp th01\main_14.cpp th01\main_16.c th01\main_19.cpp th01\main_25.cpp th01\main_27.cpp th01\main_38.cpp th01\main_38_.cpp
bin\th01\reiiden.exe: bin\piloadc.obj bin\th01\reiiden.obj th01\main_01.cpp th01\main_01_.cpp th01\main_02.c th01\main_03.c th01\main_04.c th01\main_05.c th01\main_06.cpp th01\main_07.cpp th01\main_08.cpp th01\main_09.cpp th01\main_12.c th01\main_13.cpp th01\main_13_.cpp th01\main_14.cpp th01\main_16.c th01\main_19.cpp th01\main_25.cpp th01\main_27.cpp th01\main_38.cpp
$(CC) $(CFLAGS) -ml -3 -DGAME=1 -DBINARY='M' -nbin\th01\ -eREIIDEN.EXE @&&|
$**
|

View File

@ -269,6 +269,50 @@ Examples:
**Certainty**: Maybe Borland (not Turbo) C++ has an optimization option
against it?
### Boilerplate for constructors defined outside the class declaration
```c++
struct MyClass {
// Members…
MyClass();
};
MyClass::MyClass() {
// Initialization…
}
```
Resulting ASM:
```asm
; MyClass::MyClass(MyClass* this)
; Exact instructions differ depending on the memory model. Model-independent
; ASM instructions are in UPPERCASE.
@MyClass@$bctr$qv proc
PUSH BP
MOV BP, SP
; (saving SI and DI, if used in constructor code)
; (if this, 0)
JNZ @@ctor_code
PUSH sizeof(MyClass)
CALL @$bnew$qui ; operator new(uint)
POP CX
; (this = value_returned_from_new)
; (if this)
JZ @@ret
@@ctor_code:
; Initialization…
@@ret:
; (retval = this)
; (restoring DI and SI, if used in constructor code)
POP BP
RET
@MyClass@$bctr$qv endp
```
## Limits of decompilability
### `MOV BX, SP`-style functions, or others with no standard stack frame

View File

@ -1,12 +1,3 @@
#include "th01/math/subpixel.hpp"
#include "th01/math/vector.hpp"
#include "th01/main/vars.hpp"
#include "th01/main/bullet/pellet.hpp"
#include "th01/main/playfld.hpp"
#include "th01/main/player/orb.hpp"
#include "th01/main/player/player.hpp"
#include "th01/main/player/shots.hpp"
/// Constants
/// ---------
// Can't declare these as `static const` variables, because that would break
@ -25,6 +16,24 @@ static const unsigned int PELLET_DESTROY_SCORE = 10;
pellet_t near *pellet_cur;
/// -------
CPellets::CPellets(void)
{
int i;
#define p pellet_cur
p = iteration_start();
for(i = 0; i < PELLET_COUNT; i++, p++) {
p->moving = false;
p->not_rendered = false;
}
#undef p
alive_count = 0;
for(i = 0; i < sizeof(unknown_zero) / sizeof(unknown_zero[0]); i++) {
unknown_zero[i] = 0;
}
}
void vector2_to_player_from(
int x, int y, int &ret_x, int &ret_y, int length, unsigned char plus_angle
)

View File

@ -168,6 +168,8 @@ protected:
bool16 visible_after_hittests_for_cur(int pellet_left, int pellet_top);
public:
CPellets(void);
// Spawns a number of bullets according to the given [pattern], with their
// corresponding velocities, at (left, top). [speed_base] is tuned
// according to the currently played difficulty and the resident

View File

@ -1,11 +1,3 @@
#include "th01/snd/mdrv2.h"
#include "th01/formats/ptn.hpp"
#include "th01/hardware/egc.h"
#include "th01/main/playfld.hpp"
#include "th01/main/player/player.hpp"
#include "th01/main/player/orb.hpp"
#include "th01/main/player/shots.hpp"
static const int SHOT_SPRITE_MARGIN = 2;
static const int SHOT_DECAY_FRAMES = 7;

View File

@ -1,15 +1,26 @@
/* ReC98
* -----
* 1st part of code segment #38 of TH01's REIIDEN.EXE
* Code segment #38 of TH01's REIIDEN.EXE
*/
#pragma option -Z
extern "C" {
#include "platform.h"
#include "pc98.h"
#include "planar.h"
#include "th01/th01.h"
#include "th01/ranks.h"
#include "th01/snd/mdrv2.h"
#include "th01/formats/ptn.hpp"
#include "th01/hardware/egc.h"
#include "th01/math/subpixel.hpp"
#include "th01/math/vector.hpp"
#include "th01/main/vars.hpp"
#include "th01/main/playfld.hpp"
#include "th01/main/player/player.hpp"
#include "th01/main/player/orb.hpp"
#include "th01/main/bullet/pellet.hpp"
#include "th01/main/player/shots.hpp"
#include "th01/main/player/shots.cpp"
#include "th01/main/bullet/pellet.cpp"
}

View File

@ -1,15 +0,0 @@
/* ReC98
* -----
* 2nd part of code segment #38 of TH01's REIIDEN.EXE
*/
#pragma codeseg main_38__TEXT main_38
#pragma option -Z
extern "C" {
#include "th01/th01.h"
#include "th01/ranks.h"
#include "th01/main/bullet/pellet.cpp"
}

View File

@ -73,7 +73,7 @@ main_13 group main_13_TEXT, main_13__TEXT
main_19 group main_19_TEXT, main_19__TEXT
main_25 group main_25_TEXT, main_25__TEXT
main_27 group main_27_TEXT, main_27__TEXT
main_38 group main_38_TEXT, main_38__TEXT, main_38___TEXT
main_38 group main_38_TEXT, main_38__TEXT
; ===========================================================================
@ -4483,7 +4483,7 @@ word_E309 dw 4, 9, 0Eh, 13h
sub_E319 proc far
push bp
mov bp, sp
call sub_30047 c, offset _Pellets, ds
call @CPellets@$bctr$qv c, offset _Pellets, ds
mov _Shots.SHOT_unknown[0 * word], 50h
mov _Shots.SHOT_unknown[1 * word], 60h
mov _Shots.SHOT_unknown[2 * word], 70h
@ -53930,90 +53930,22 @@ main_37_TEXT ends
; Segment type: Pure code
main_38_TEXT segment byte public 'CODE' use16
main_38_TEXT ends
main_38__TEXT segment byte public 'CODE' use16
assume cs:main_38
;org 4
assume es:nothing, ss:nothing, ds:_DATA, fs:nothing, gs:nothing
extern @CShots@add$qii:proc
extern @CShots@unput_and_reset_all$qv:proc
extern @CShots@unput_update_render$qv:proc
extern @CShots@hittest_pellet$qii:proc
extern @CShots@hittest_boss$qiiii:proc
; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame
sub_30047 proc far
@@CPellets = dword ptr 6
push bp
mov bp, sp
push si
cmp [bp+@@CPellets], 0
jnz short loc_30065
push size CPellets
call @$bnew$qui ; operator new(uint)
pop cx
mov word ptr [bp+@@CPellets+2], dx
mov word ptr [bp+@@CPellets], ax
or ax, dx
jz short loc_300AA
loc_30065:
mov ax, word ptr [bp+@@CPellets]
mov _pellet_cur, ax
xor si, si
jmp short loc_30081
; ---------------------------------------------------------------------------
loc_3006F:
mov bx, _pellet_cur
mov byte ptr [bx], 0
mov word ptr [bx+18h], 0
inc si
add _pellet_cur, size pellet_t
loc_30081:
cmp si, PELLET_COUNT
jl short loc_3006F
les bx, [bp+@@CPellets]
mov es:[bx+CPellets.PELLET_alive_count], 0
xor si, si
jmp short loc_300A5
; ---------------------------------------------------------------------------
loc_30094:
mov ax, si
add ax, ax
les bx, [bp+@@CPellets]
add bx, ax
mov es:[bx+PELLET_unknown_zero], 0
inc si
loc_300A5:
cmp si, 10
jl short loc_30094
loc_300AA:
mov dx, word ptr [bp+@@CPellets+2]
mov ax, word ptr [bp+@@CPellets]
pop si
pop bp
retf
sub_30047 endp
main_38__TEXT ends
main_38___TEXT segment byte public 'CODE' use16
extern @CPellets@$bctr$qv:proc
extern @CPellets@add_pattern$qii16pellet_pattern_ti:proc
extern @CPellets@add_single$qiiii15pellet_motion_tiii:proc
extern @CPellets@motion_type_apply_for_cur$qv:proc
extern @CPellets@visible_after_hittests_for_cur$qii:proc
extern _pellet_render:proc
main_38_TEXT ends
main_38__TEXT segment byte public 'CODE' use16
assume cs:main_38
assume es:nothing, ss:nothing, ds:_DATA, fs:nothing, gs:nothing
; =============== S U B R O U T I N E =======================================
@ -54609,7 +54541,7 @@ sub_30F70 endp
; ---------------------------------------------------------------------------
dw 0
main_38___TEXT ends
main_38__TEXT ends
.data