[Decompilation] [th03] Shot update and render functions

Meh, can't overload arithmetic operators that take a Subpixel without
generating a needless load and store, even with -Z. But heck, slightly
uglifying subpixel/subpixel arithmetic is exactly the right trade-off.

Completes P0061, funded by Touhou Patch Center.
This commit is contained in:
nmlgc 2019-12-03 22:45:08 +01:00
parent 8b01c60f44
commit 5f4f5d87dc
6 changed files with 81 additions and 111 deletions

View File

@ -81,8 +81,8 @@ bin\th03\op.exe: bin\th03\op.obj th03\op_02.c
$**
|
bin\th03\main.exe: bin\th03\main.obj th03\sprite16.cpp
$(CC) $(CFLAGS) -ml -DGAME=3 -nbin\th03\ -eMAIN.EXE @&&|
bin\th03\main.exe: bin\th03\main.obj th03\main_01.cpp th03\sprite16.cpp
$(CC) $(CFLAGS) -ml -Z -DGAME=3 -nbin\th03\ -eMAIN.EXE @&&|
$**
|

View File

@ -2,10 +2,10 @@
| | |
|-|-|
| `DX` | First 8-bit variable declared *if no other function is called* |
| `DX` | First 8-bit variable declared *if no other function is called*<br />Second 16-bit variable declared *if no other function is called* |
| `[bp-1]` | First 8-bit variable declared *otherwise* |
| `SI` | First 16-bit variable declared |
| `DI` | Second 16-bit variable declared |
| `DI` | Second 16-bit variable declared *if other functions are called* |
Example:
@ -64,10 +64,16 @@ inline optimally though:
## C++
* Every class method that returns `void` inlines to the ideal representation.
* Every class method that returns `*this` inlines to the ideal representation
*only at the first nesting level*. Example: A class method calling an
overloaded operator returning `*this` will generate (needless) instructions
Class methods inline to their ideal representation if all of these are true:
* returns `void` || (returns `*this` && is at the first nesting level of
inlining)
* takes no parameters || takes only built-in, scalar-type parameters
Examples:
* A class method (first nesting level) calling an overloaded operator (second
nesting level) returning `*this` will generate (needless) instructions
equivalent to `MOV AX, *this`. Thus, any overloaded `=`, `+=`, `-=`, etc.
operator should always return `void`.
@ -75,8 +81,8 @@ inline optimally though:
custom types with overloaded assignment operators, with the resulting code
generation being indistinguishable from equivalent C preprocessor macros.
* Returning *anything else* will first store that result in `AX`, leading any
branches at the call site to then refer to `AX`.
* Returning *anything else* but `void` or `*this` will first store that result
in `AX`, leading any branches at the call site to then refer to `AX`.
**Certainty**: Maybe Borland (not Turbo) C++ has an optimization option
against it?

54
th03/main_01.cpp Normal file
View File

@ -0,0 +1,54 @@
/* ReC98
* -----
* Code segment #1 of TH03's MAIN.EXE
*/
extern "C"
{
#include "pc98.h"
#include "th03/sprite16.hpp"
#include "th03/playfld.hpp"
#include "th03/shots.hpp"
void pascal near shots_update(void)
{
shotpair_t near *shotpair = shotpairs;
for(int i = 0; i < SHOTPAIR_COUNT; i++, shotpair++) {
if(shotpair->flag) {
shotpair->topleft.y.v += shotpair->velocity_y.v;
if(shotpair->topleft.y.v <= to_sp(-1.0f)) {
shotpair->flag = 0;
}
}
}
}
void pascal near shots_render(void)
{
shotpair_t near *shotpair = shotpairs;
sprite16_put_w = SHOT_W;
sprite16_put_h = SHOT_H;
sprite16_clip_left = 0;
sprite16_clip_right = RES_X - 1;
for(int i = 0; i < SHOTPAIR_COUNT; i++, shotpair++) {
if(shotpair->flag) {
int so = shotpair->so_anim + shotpair->so_pid;
int left = playfield_fg_x_to_screen(
shotpair->topleft.x, shotpair->pid
);
int top = shotpair->topleft.y.to_screen() + PLAYFIELD_Y;
sprite16_put(left + 0, top, so);
sprite16_put(left + SHOTPAIR_DISTANCE, top, so);
shotpair->so_anim += SHOT_VRAM_W;
if(shotpair->so_anim >= (SHOT_VRAM_W * SHOT_SPRITE_COUNT)) {
shotpair->so_anim = 0;
}
}
}
}
}

View File

@ -26,6 +26,10 @@ public:
void operator =(float screen_v) {
v = static_cast<T>(to_sp(screen_v));
}
T to_screen() const {
return v >> 4;
}
};
template <class T> struct SPPointBase {

View File

@ -23,3 +23,6 @@ struct shotpair_t {
#define SHOTPAIR_COUNT 32
extern shotpair_t shotpairs[SHOTPAIR_COUNT];
void pascal near shots_update(void);
void pascal near shots_render(void);

View File

@ -289,7 +289,7 @@ loc_977E:
call p2_1F332
call p2_205D2
call sub_B7E5
call sub_E83F
call shots_update
mov byte ptr word_1FE88, 0
mov byte ptr word_23AF0, 0
call p1_2028C
@ -350,7 +350,7 @@ loc_986C:
mov byte ptr word_1FE88, 1
mov byte ptr word_23AF0, 28h ; '('
call p2_1F33A
call sub_E86A
call shots_render
call sub_164DA
call sub_1837C
call sub_B80B
@ -9078,105 +9078,8 @@ loc_E83B:
retn
sub_E737 endp
; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame
sub_E83F proc near
push bp
mov bp, sp
push si
mov si, offset _shotpairs
xor dx, dx
jmp short loc_E862
; ---------------------------------------------------------------------------
loc_E84A:
cmp [si+shotpair_t.flag], 0
jz short loc_E85E
mov ax, [si+shotpair_t.velocity_y]
add [si+shotpair_t.topleft.y], ax
cmp [si+shotpair_t.topleft.y], -16
jg short loc_E85E
mov [si+shotpair_t.flag], 0
loc_E85E:
inc dx
add si, size shotpair_t
loc_E862:
cmp dx, SHOTPAIR_COUNT
jl short loc_E84A
pop si
pop bp
retn
sub_E83F endp
; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame
sub_E86A proc near
@@top = word ptr -6
@@left = word ptr -4
@@sprite_offset = word ptr -2
enter 6, 0
push si
push di
mov si, offset _shotpairs
mov _sprite16_put_w, (SHOT_W / 16)
mov _sprite16_put_h, SHOT_VRAM_H
mov _sprite16_clip_left, PLAYFIELD1_CLIP_LEFT
mov _sprite16_clip_right, PLAYFIELD2_CLIP_RIGHT
xor di, di
jmp short loc_E8EF
; ---------------------------------------------------------------------------
loc_E88E:
cmp [si+shotpair_t.flag], 0
jz short loc_E8EB
mov al, [si+shotpair_t.so_anim]
mov ah, 0
add ax, [si+shotpair_t.so_pid]
mov [bp+@@sprite_offset], ax
push [si+shotpair_t.topleft.x]
mov al, [si+shotpair_t.pid]
mov ah, 0
push ax
nopcall playfield_fg_x_to_screen
mov [bp+@@left], ax
mov ax, [si+shotpair_t.topleft.y]
sar ax, 4
add ax, PLAYFIELD_Y
mov [bp+@@top], ax
call sprite16_put pascal, [bp+@@left], ax, [bp+@@sprite_offset]
mov ax, [bp+@@left]
add ax, SHOTPAIR_DISTANCE
call sprite16_put pascal, ax, [bp+@@top], [bp+@@sprite_offset]
mov al, [si+shotpair_t.so_anim]
add al, SHOT_VRAM_W
mov [si+shotpair_t.so_anim], al
cmp [si+shotpair_t.so_anim], SHOT_SPRITE_COUNT * SHOT_VRAM_W
jb short loc_E8EB
mov [si+shotpair_t.so_anim], 0
loc_E8EB:
inc di
add si, size shotpair_t
loc_E8EF:
cmp di, SHOTPAIR_COUNT
jl short loc_E88E
pop di
pop si
leave
retn
sub_E86A endp
SHOTS_UPDATE procdesc pascal near
SHOTS_RENDER procdesc pascal near
main_01_TEXT ends
; ===========================================================================