[Reverse-engineering] [th02/th04/th05] Pellet rendering

… which allows a split into first rendering the top part of every
pellet, then the bottom part. This way, the game only needs two
grcg_setcolor() calls for any number of pellets.

Part of P0085, funded by -Tom-.
This commit is contained in:
nmlgc 2020-03-27 22:12:18 +01:00
parent 4843d17aae
commit 65816a43db
11 changed files with 290 additions and 443 deletions

2
th02/bullet/bullet.hpp Normal file
View File

@ -0,0 +1,2 @@
// Renders a pellet at the given position.
void pascal near pellet_render(int left, int top);

25
th02/bullet/pellet_r.cpp Normal file
View File

@ -0,0 +1,25 @@
#include "th02/sprites/pellet.h"
void pascal near pellet_render(int left, int top)
{
_ES = SEG_PLANE_B;
_BX = _BX; // Keeps any parameters from being put into BX
_AX = (left >> 3);
_DX = top;
_DX <<= 6;
_AX += _DX;
_DX >>= 2;
_DI = _AX + _DX;
_SI = reinterpret_cast<uint16_t>(sPELLET[left & 7]);
_CX = 8;
put_loop: {
asm movsw
_DI += (ROW_SIZE - sizeof(dots16_t));
if(static_cast<int16_t>(_DI) >= PLANE_SIZE) {
_DI -= PLANE_SIZE;
}
}
asm loop put_loop;
}

View File

@ -4,11 +4,11 @@
*/
extern "C" {
#include <stdlib.h>
#include "platform.h"
#include "ReC98.h"
#include "th02/math/randring.h"
#define RANDRING_INSTANCE 2
#include "th02/math/randring.cpp"
#include "th02/bullet/pellet_r.cpp"
}

View File

@ -9416,53 +9416,8 @@ main_03__TEXT segment byte public 'CODE' use16
RANDRING2_NEXT8_AND procdesc pascal near \
mask:byte
RANDRING2_NEXT16 procdesc pascal near
; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame
sub_FAFC proc near
arg_0 = word ptr 4
arg_2 = word ptr 6
push bp
mov bp, sp
push si
push di
mov ax, 0A800h
mov es, ax
assume es:nothing
mov ax, [bp+arg_2]
sar ax, 3
mov dx, [bp+arg_0]
shl dx, 6
add ax, dx
shr dx, 2
add ax, dx
mov di, ax
mov ax, [bp+arg_2]
and ax, 7
shl ax, 4
add ax, offset _sPELLET
mov si, ax
mov cx, 8
loc_FB2C:
movsw
add di, 4Eh ; 'N'
cmp di, 7D00h
jl short loc_FB3A
sub di, 7D00h
loc_FB3A:
loop loc_FB2C
pop di
pop si
pop bp
retn 4
sub_FAFC endp
PELLET_RENDER procdesc pascal near \
left:word, top:word
; =============== S U B R O U T I N E =======================================
@ -11499,17 +11454,17 @@ loc_10C37:
mov bx, word_2174E
mov ax, [bx]
sar ax, 4
mov word_21740, ax
mov _bullet_left, ax
mov bx, word_21750
mov ax, [bx]
sar ax, 4
mov word_21742, ax
mov di, word_21742
cmp word_21740, 14h
cmp _bullet_left, 20
jle short loc_10C6C
cmp word_21740, 1A0h
cmp _bullet_left, PLAYFIELD_RIGHT
jge short loc_10C6C
cmp di, 180h
cmp di, PLAYFIELD_BOTTOM
jge short loc_10C6C
or di, di
jg short loc_10C72
@ -11526,11 +11481,11 @@ loc_10C72:
jnz short loc_10CA9
mov ax, point_205F6.x
add ax, 7
cmp ax, word_21740
cmp ax, _bullet_left
jg short loc_10CDC
mov ax, point_205F6.x
add ax, 17
cmp ax, word_21740
cmp ax, _bullet_left
jle short loc_10CDC
mov ax, point_205F6.y
add ax, 12
@ -11546,11 +11501,11 @@ loc_10C72:
loc_10CA9:
mov ax, point_205F6.x
add ax, -3
cmp ax, word_21740
cmp ax, _bullet_left
jg short loc_10CDC
mov ax, point_205F6.x
add ax, 19
cmp ax, word_21740
cmp ax, _bullet_left
jle short loc_10CDC
mov ax, point_205F6.y
add ax, 4
@ -11583,15 +11538,13 @@ loc_10CEA:
mov [bp+var_4], 0
loc_10D09:
push word_21740
push di
call sub_FAFC
call pellet_render pascal, _bullet_left, di
jmp short loc_10D2D
; ---------------------------------------------------------------------------
loc_10D13:
call grcg_off
push word_21740
push _bullet_left
push di
mov al, [si+0Eh]
mov ah, 0
@ -34970,7 +34923,8 @@ byte_20672 db ?
dword_20682 dd ?
word_20686 dw ?
db 4280 dup(?)
word_21740 dw ?
public _bullet_left
_bullet_left dw ?
word_21742 dw ?
word_21744 dw ?
word_21746 dw ?

View File

@ -115,6 +115,31 @@ extern bullet_t bullets[BULLET_COUNT];
#define pellets (&bullets[0])
#define bullets16 (&bullets[PELLET_COUNT])
/// Rendering
/// ---------
union pellet_render_t {
struct {
int left;
int top;
} top;
struct {
uint16_t vram_offset;
uint16_t sprite_offset;
} bottom;
};
extern int pellets_alive;
extern pellet_render_t pellets_render[PELLET_COUNT];
// Renders the top and bottom part of all pellets, as per [pellets_render] and
// [pellets_alive]. Assumptions:
// • ES is already be set to the beginning of a VRAM segment
// • The GRCG is active, and set to the intended color
// • pellets_render_top() is called before pellets_render_bottom()
void near pellets_render_top();
void near pellets_render_bottom();
/// ---------
struct bullet_template_t {
uint8_t spawn_type;
unsigned char patnum; // TH05: 0 = pellet

View File

@ -45,6 +45,15 @@ bullet_t struc
endif
bullet_t ends
pellet_render_t struc
PRT_left label word
PRB_vram_offset label word
dw ?
PRT_top label word
PRB_sprite_offset label word
dw ?
pellet_render_t ends
PELLET_W = 8
PELLET_H = 8
BULLET16_W = 16
@ -60,7 +69,8 @@ endif
BULLET_COUNT = (PELLET_COUNT + BULLET16_COUNT)
public _bullets, _pellets, _bullets16
public _bullets, _pellets, _bullets16, _pellets_render
_bullets label bullet_t
_pellets bullet_t PELLET_COUNT dup(<?>)
_bullets16 bullet_t BULLET16_COUNT dup(<?>)
_pellets_render pellet_render_t PELLET_COUNT dup(<?>)

175
th04/bullet/pellet_r.asm Normal file
View File

@ -0,0 +1,175 @@
PELLET_TOP_H = 6
PELLET_BOTTOM_Y = (PELLET_H - PELLET_BOTTOM_H)
public _pellets_render_top
_pellets_render_top proc near
mov ax, _pellets_alive
or ax, ax
jnz short @@at_least_one_alive
retn
; ---------------------------------------------------------------------------
@@at_least_one_alive:
push bp
push si
push di
mov bp, ax
mov bx, offset _pellets_render
@@pellet_loop:
mov di, [bx+pellet_render_t.PRT_left]
mov ax, di
sar di, 3
mov cx, [bx+pellet_render_t.PRT_top]
shl cx, 6
add di, cx
shr cx, 2
add di, cx
and ax, 7
mov si, ax
shl si, 4
add si, offset _sPELLET
shl ax, 3
mov cx, PELLET_TOP_H
or ax, ax
jz short @@BYTEALIGNED
cmp di, ((RES_Y - PELLET_TOP_H + 1) * ROW_SIZE)
jb short @@SHIFTED_YLOOP2
@@SHIFTED_YLOOP1:
movsw
add di, (ROW_SIZE - word)
dec cx
cmp di, PLANE_SIZE
jb short @@SHIFTED_YLOOP1
sub di, PLANE_SIZE
@@SHIFTED_YLOOP2:
movsw
add di, (ROW_SIZE - word)
loop @@SHIFTED_YLOOP2
jmp short @@pellet_next
; ---------------------------------------------------------------------------
even
@@BYTEALIGNED:
cmp di, ((RES_Y - PELLET_TOP_H + 1) * ROW_SIZE)
jb short @@BYTEALIGNED_YLOOP2
@@BYTEALIGNED_YLOOP1:
movsb
inc si
add di, (ROW_SIZE - byte)
dec cx
cmp di, PLANE_SIZE
jb short @@BYTEALIGNED_YLOOP1
sub di, PLANE_SIZE
@@BYTEALIGNED_YLOOP2:
movsb
inc si
add di, (ROW_SIZE - byte)
loop @@BYTEALIGNED_YLOOP2
@@pellet_next:
sub di, (((PELLET_TOP_H + 1) - PELLET_BOTTOM_Y) * ROW_SIZE)
jns short @@set_bottom_data
add di, PLANE_SIZE
@@set_bottom_data:
add ax, offset _sPELLET_BOTTOM
mov [bx+pellet_render_t.PRB_vram_offset], di
mov [bx+pellet_render_t.PRB_sprite_offset], ax
add bx, size pellet_render_t
dec bp
jnz short @@pellet_loop
pop di
pop si
pop bp
retn
_pellets_render_top endp
even
public _pellets_render_bottom
_pellets_render_bottom proc near
@@rows_after_roll equ <dx>
mov ax, _pellets_alive
or ax, ax
jnz short @@at_least_one_alive
retn
; ---------------------------------------------------------------------------
@@at_least_one_alive:
push bp
push si
push di
mov bp, ax
mov bx, offset _pellets_render
@@pellet_loop:
mov di, [bx+pellet_render_t.PRB_vram_offset]
mov si, [bx+pellet_render_t.PRB_sprite_offset]
xor @@rows_after_roll, @@rows_after_roll
cmp di, ((RES_Y - PELLET_BOTTOM_H - 1) * ROW_SIZE)
jnb short @@roll_needed
even
mov cx, (PELLET_BOTTOM_H + 1)
jmp short @@no_roll
; ---------------------------------------------------------------------------
@@roll_needed:
mov ax, (PLANE_SIZE + (ROW_SIZE - 1))
sub ax, di
mov cx, ROW_SIZE
div cx
mov cx, ax
mov @@rows_after_roll, (PELLET_BOTTOM_H + 1)
sub @@rows_after_roll, cx
@@no_roll:
mov ax, [si] ; lol, it's also just a LODSW?
jmp short @@put
; ---------------------------------------------------------------------------
@@row_loop:
lodsw
@@put:
or al, al
jz short @@only_byte_2
or ah, ah
jz short @@only_byte_1
mov es:[di], ax
jmp short @@row_next
; ---------------------------------------------------------------------------
@@only_byte_1:
mov es:[di], al
jmp short @@row_next
; ---------------------------------------------------------------------------
@@only_byte_2:
mov es:[di+1], ah
@@row_next:
add di, ROW_SIZE
loop @@row_loop
or @@rows_after_roll, @@rows_after_roll
jz short @@pellet_next
sub di, PLANE_SIZE
xchg cx, @@rows_after_roll
jmp short @@row_loop
; ---------------------------------------------------------------------------
@@pellet_next:
add bx, size pellet_render_t
dec bp
jnz short @@pellet_loop
pop di
pop si
pop bp
retn
_pellets_render_bottom endp

View File

@ -0,0 +1,2 @@
public _pellets_alive
_pellets_alive dw ?

View File

@ -1,3 +1,5 @@
PELLET_BOTTOM_H = 4
public _sPELLET_BOTTOM
label _sPELLET_BOTTOM byte
; x + 0

View File

@ -2710,182 +2710,7 @@ midbossx_render endp
; ---------------------------------------------------------------------------
db 0
; =============== S U B R O U T I N E =======================================
sub_C99C proc near
mov ax, word_2D006
or ax, ax
jnz short loc_C9A4
retn
; ---------------------------------------------------------------------------
loc_C9A4:
push bp
push si
push di
mov bp, ax
mov bx, 86D2h
loc_C9AC:
mov di, [bx]
mov ax, di
sar di, 3
mov cx, [bx+2]
shl cx, 6
add di, cx
shr cx, 2
add di, cx
and ax, 7
mov si, ax
shl si, 4
add si, offset _sPELLET
shl ax, 3
mov cx, 6
or ax, ax
jz short loc_C9F4
cmp di, 7B70h
jb short loc_C9EB
loc_C9DC:
movsw
add di, 4Eh ; 'N'
dec cx
cmp di, 7D00h
jb short loc_C9DC
sub di, 7D00h
loc_C9EB:
movsw
add di, 4Eh ; 'N'
loop loc_C9EB
jmp short loc_CA11
; ---------------------------------------------------------------------------
nop
loc_C9F4:
cmp di, 7B70h
jb short loc_CA0A
loc_C9FA:
movsb
inc si
add di, 4Fh ; 'O'
dec cx
cmp di, 7D00h
jb short loc_C9FA
sub di, 7D00h
loc_CA0A:
movsb
inc si
add di, 4Fh ; 'O'
loop loc_CA0A
loc_CA11:
sub di, 0F0h
jns short loc_CA1B
add di, 7D00h
loc_CA1B:
add ax, offset _sPELLET_BOTTOM
mov [bx], di
mov [bx+2], ax
add bx, 4
dec bp
jnz short loc_C9AC
pop di
pop si
pop bp
retn
sub_C99C endp
; ---------------------------------------------------------------------------
nop
; =============== S U B R O U T I N E =======================================
sub_CA2E proc near
mov ax, word_2D006
or ax, ax
jnz short loc_CA36
retn
; ---------------------------------------------------------------------------
loc_CA36:
push bp
push si
push di
mov bp, ax
mov bx, 86D2h
loc_CA3E:
mov di, [bx]
mov si, [bx+2]
xor dx, dx
cmp di, 7B70h
jnb short loc_CA51
nop
mov cx, 5
jmp short loc_CA62
; ---------------------------------------------------------------------------
loc_CA51:
mov ax, 7D4Fh
sub ax, di
mov cx, 50h ; 'P'
div cx
mov cx, ax
mov dx, 5
sub dx, cx
loc_CA62:
mov ax, [si]
jmp short loc_CA67
; ---------------------------------------------------------------------------
loc_CA66:
lodsw
loc_CA67:
or al, al
jz short loc_CA79
or ah, ah
jz short loc_CA74
mov es:[di], ax
jmp short loc_CA7D
; ---------------------------------------------------------------------------
loc_CA74:
mov es:[di], al
jmp short loc_CA7D
; ---------------------------------------------------------------------------
loc_CA79:
mov es:[di+1], ah
loc_CA7D:
add di, 50h ; 'P'
loop loc_CA66
or dx, dx
jz short loc_CA8E
sub di, 7D00h
xchg cx, dx
jmp short loc_CA66
; ---------------------------------------------------------------------------
loc_CA8E:
add bx, 4
dec bp
jnz short loc_CA3E
pop di
pop si
pop bp
retn
sub_CA2E endp
include th04/bullet/pellet_r.asm
; =============== S U B R O U T I N E =======================================
@ -14055,10 +13880,10 @@ loc_12D6D:
jnz short loc_12DBE
mov ah, 0Fh
call main_01:grcg_setcolor_direct_noint_1
call main_01:sub_C99C
call main_01:_pellets_render_top
mov ah, GC_RG
call main_01:grcg_setcolor_direct_noint_1
call main_01:sub_CA2E
call main_01:_pellets_render_bottom
jmp short @@ret
; ---------------------------------------------------------------------------
@ -30896,7 +30721,7 @@ var_2 = word ptr -2
push si
push di
mov [bp+var_2], 0
mov word_2D006, 0
mov _pellets_alive, 0
mov si, offset _bullets[(BULLET_COUNT - 1) * size bullet_t]
cmp _bullet_clear_trigger, 0
jnz loc_1CB44
@ -31113,17 +30938,17 @@ loc_1CAC5:
jl short loc_1CAF8
mov ax, [si+bullet_t.pos.cur.x]
sar ax, 4
add ax, 28
mov bx, word_2D006
add ax, (PLAYFIELD_X - (PELLET_W / 2))
mov bx, _pellets_alive
shl bx, 2
mov [bx-792Eh], ax
mov _pellets_render[bx].PRT_left, ax
mov ax, [si+bullet_t.pos.cur.y]
add ax, (12 shl 4)
add ax, ((PLAYFIELD_Y - (PELLET_H / 2)) shl 4)
call scroll_subpixel_y_to_vram_seg3 pascal, ax
mov bx, word_2D006
mov bx, _pellets_alive
shl bx, 2
mov [bx-792Ch], ax
inc word_2D006
mov _pellets_render[bx].PRT_top, ax
inc _pellets_alive
loc_1CAF8:
inc di
@ -38968,7 +38793,7 @@ include th04/midboss/vars[bss].asm
include th04/boss/vars[bss].asm
include th04/sparks[bss].asm
include th04/bullet/bullets[bss].asm
db 1884 dup(?)
db 924 dup(?)
byte_2A16E db ?
db 1879 dup(?)
point_2A8C6 Point <?>
@ -39010,7 +38835,7 @@ score_2CFFE dw ?
fp_2D000 dw ?
fp_2D002 dw ?
fp_2D004 dw ?
word_2D006 dw ?
include th04/bullet/pellet_r[bss].asm
angle_2D008 db ?
evendata
byte_2D00A db ?

View File

@ -904,7 +904,7 @@ loc_B3C5:
loc_B3CA:
nopcall sub_BF27
mov grcgcolor_2CC8E, GC_RG
mov _pellet_bottom_col, GC_RG
mov al, stage_id
mov ah, 0
mov bx, ax
@ -1964,181 +1964,7 @@ nullsub_1 proc far
nullsub_1 endp
nop
; =============== S U B R O U T I N E =======================================
sub_C054 proc near
mov ax, word_2C97E
or ax, ax
jnz short loc_C05C
retn
; ---------------------------------------------------------------------------
loc_C05C:
push bp
push si
push di
mov bp, ax
mov bx, 8FC6h
loc_C064:
mov di, [bx]
mov ax, di
sar di, 3
mov cx, [bx+2]
shl cx, 6
add di, cx
shr cx, 2
add di, cx
and ax, 7
mov si, ax
shl si, 4
add si, offset _sPELLET
shl ax, 3
mov cx, 6
or ax, ax
jz short loc_C0AC
cmp di, 7B70h
jb short loc_C0A3
loc_C094:
movsw
add di, 4Eh ; 'N'
dec cx
cmp di, 7D00h
jb short loc_C094
sub di, 7D00h
loc_C0A3:
movsw
add di, 4Eh ; 'N'
loop loc_C0A3
jmp short loc_C0C9
; ---------------------------------------------------------------------------
nop
loc_C0AC:
cmp di, 7B70h
jb short loc_C0C2
loc_C0B2:
movsb
inc si
add di, 4Fh ; 'O'
dec cx
cmp di, 7D00h
jb short loc_C0B2
sub di, 7D00h
loc_C0C2:
movsb
inc si
add di, 4Fh ; 'O'
loop loc_C0C2
loc_C0C9:
sub di, 0F0h
jns short loc_C0D3
add di, 7D00h
loc_C0D3:
add ax, offset _sPELLET_BOTTOM
mov [bx], di
mov [bx+2], ax
add bx, 4
dec bp
jnz short loc_C064
pop di
pop si
pop bp
retn
sub_C054 endp
; ---------------------------------------------------------------------------
nop
; =============== S U B R O U T I N E =======================================
sub_C0E6 proc near
mov ax, word_2C97E
or ax, ax
jnz short loc_C0EE
retn
; ---------------------------------------------------------------------------
loc_C0EE:
push bp
push si
push di
mov bp, ax
mov bx, 8FC6h
loc_C0F6:
mov di, [bx]
mov si, [bx+2]
xor dx, dx
cmp di, 7B70h
jnb short loc_C109
nop
mov cx, 5
jmp short loc_C11A
; ---------------------------------------------------------------------------
loc_C109:
mov ax, 7D4Fh
sub ax, di
mov cx, 50h ; 'P'
div cx
mov cx, ax
mov dx, 5
sub dx, cx
loc_C11A:
mov ax, [si]
jmp short loc_C11F
; ---------------------------------------------------------------------------
loc_C11E:
lodsw
loc_C11F:
or al, al
jz short loc_C131
or ah, ah
jz short loc_C12C
mov es:[di], ax
jmp short loc_C135
; ---------------------------------------------------------------------------
loc_C12C:
mov es:[di], al
jmp short loc_C135
; ---------------------------------------------------------------------------
loc_C131:
mov es:[di+1], ah
loc_C135:
add di, 50h ; 'P'
loop loc_C11E
or dx, dx
jz short loc_C146
sub di, 7D00h
xchg cx, dx
jmp short loc_C11E
; ---------------------------------------------------------------------------
loc_C146:
add bx, 4
dec bp
jnz short loc_C0F6
pop di
pop si
pop bp
retn
sub_C0E6 endp
include th04/bullet/pellet_r.asm
include th04/spark_render.asm
include th04/sparks.asm
include th04/item/splash_dot_render.asm
@ -8334,10 +8160,10 @@ loc_101BD:
jnz short loc_1018A
mov ah, 0Fh
call grcg_setcolor_direct_noint_1
call sub_C054
mov ah, byte ptr grcgcolor_2CC8E
call _pellets_render_top
mov ah, byte ptr _pellet_bottom_col
call grcg_setcolor_direct_noint_1
call sub_C0E6
call _pellets_render_bottom
jmp short @@ret
; ---------------------------------------------------------------------------
@ -17170,7 +16996,7 @@ var_2 = word ptr -2
push di
mov [bp+var_2], 0
mov word_2CDF8, 0
mov word_2C97E, 0
mov _pellets_alive, 0
mov si, offset _bullets[(BULLET_COUNT - 1) * size bullet_t]
cmp _bullet_clear_trigger, 0
jnz loc_17EC3
@ -17412,17 +17238,17 @@ loc_17E41:
jl short loc_17E74
mov ax, [si+bullet_t.pos.cur.x]
sar ax, 4
add ax, 28
mov bx, word_2C97E
add ax, (PLAYFIELD_X - (PELLET_W / 2))
mov bx, _pellets_alive
shl bx, 2
mov [bx-703Ah], ax
mov _pellets_render[bx].PRT_left, ax
mov ax, [si+bullet_t.pos.cur.y]
add ax, (12 shl 4)
add ax, ((PLAYFIELD_Y - (PELLET_H / 2)) shl 4)
call scroll_subpixel_y_to_vram_seg3 pascal, ax
mov bx, word_2C97E
mov bx, _pellets_alive
shl bx, 2
mov [bx-7038h], ax
inc word_2C97E
mov _pellets_render[bx].PRT_top, ax
inc _pellets_alive
loc_17E74:
inc di
@ -28815,7 +28641,7 @@ sub_1EA14 proc near
jnz short loc_1EA2E
mov byte_2D084, 40h
mov byte_2D083, 0
mov grcgcolor_2CC8E, GC_I
mov _pellet_bottom_col, GC_I
loc_1EA2E:
mov ax, _boss_phase_frame
@ -29999,7 +29825,7 @@ loc_1F51A:
call sub_1F23B
loc_1F523:
mov grcgcolor_2CC8E, GC_RG
mov _pellet_bottom_col, GC_RG
mov patnum_2CE64, 200
inc byte_2D07F
jmp loc_1F666
@ -31729,7 +31555,7 @@ include th04/boss/vars[bss].asm
include th05/boss/vars2[bss].asm
include th04/sparks[bss].asm
include th04/bullet/bullets[bss].asm
db 3452 dup(?)
db 2732 dup(?)
point_2A722 Point <?>
dword_2A726 dd ?
word_2A72A dw ?
@ -31766,7 +31592,7 @@ include th04/bullet_clear[bss].asm
public _stage_graze
_stage_graze dw ?
score_2C97C dw ?
word_2C97E dw ?
include th04/bullet/pellet_r[bss].asm
db 6 dup(?)
word_2C986 dw ?
word_2C988 dw ?
@ -31778,7 +31604,8 @@ byte_2C99C db ?
include th05/lasers_render[bss].asm
include th05/bullet/curve[bss].asm
include th04/item/splashes[bss].asm
grcgcolor_2CC8E dw ?
public _pellet_bottom_col
_pellet_bottom_col dw ?
db 360 dup(?)
word_2CDF8 dw ?
include th04/scroll[bss].asm