[Decompilation] [th02] Dialog: Displaying individual lines

And we're finally polyfilling std::array to avoid writing these hack
structures over and over.
Unfortunately, we can't ever polyfill it *exactly* because Turbo C++
4.0J neither supports namespaces nor template classes nested inside
non-template classes to simulate namespaces. Might as well go for a
PascalCased class name in accordance with the existing coding style
then – no need to add an exception just to have a class name like
`std_array` or something.

Part of P0260, funded by Yanga.
This commit is contained in:
nmlgc 2023-10-26 15:22:59 +02:00
parent c4622992b5
commit d38f2a675d
3 changed files with 77 additions and 105 deletions

35
platform/array.hpp Normal file
View File

@ -0,0 +1,35 @@
// std::array polyfill
// -------------------
#if (__cplusplus >= 201103L)
#include <array>
template <class T, size_t N> using Array = std::array<T, N>;
#else
template <class T, int N> struct Array {
typedef int size_type;
private:
T v[N];
public:
size_type count() const {
return N;
}
T* data() {
return v;
}
const T* data() const {
return v;
}
T& operator [](size_type pos) {
return v[pos];
}
const T& operator [](size_type pos) const {
return v[pos];
}
};
#endif

View File

@ -5,6 +5,7 @@
#include "planar.h"
#include "shiftjis.hpp"
#include "master.hpp"
#include "platform/array.hpp"
extern "C" {
#include "th02/hardware/frmdelay.h"
}
@ -43,6 +44,12 @@ static const pixel_t BOX_SLIDE_SPEED = (PLAYFIELD_W / 24);
static const screen_x_t FACE_LEFT = (BOX_LEFT + 8);
static const screen_y_t FACE_TOP = (BOX_TOP + 8);
static const tram_x_t TEXT_TRAM_LEFT = (
(BOX_LEFT + DIALOG_BOX_LEFT_W - (DIALOG_BOX_PART_W / 2)) / GLYPH_HALF_W
);
static const tram_x_t TEXT_TRAM_TOP = (
(BOX_TOP + (BOX_H / 2) - ((DIALOG_BOX_LINES * GLYPH_H) / 2)) / GLYPH_H
);
// -----------
// State
@ -309,3 +316,19 @@ void pascal near dialog_face_put(
mpn_put_8((FACE_LEFT + (1 * TILE_W)), top3, face_tile_id(topleft_id, 1, 2));
mpn_put_8((FACE_LEFT + (2 * TILE_W)), top3, face_tile_id(topleft_id, 2, 2));
}
void pascal near dialog_text_put(
tram_cell_amount_t line, const shiftjis_t* str, uint16_t atrb, int n
)
{
// ZUN landmine: master.lib has text_putnsa() for this purpose, which works
// without copying the string and risking a buffer overflow in the process,
// or wasting 40 bytes of conventional RAM on \0 bytes.
extern const Array<shiftjis_t, DIALOG_LINE_SIZE> clear_bytes;
Array<shiftjis_t, DIALOG_LINE_SIZE> buf = clear_bytes;
for(int i = 0; i < n; i++) {
buf[i] = str[i];
}
text_putsa(TEXT_TRAM_LEFT, (TEXT_TRAM_TOP + line), buf.data(), atrb);
}

View File

@ -12394,67 +12394,19 @@ sub_12B9E endp
@dialog_post$qv procdesc near
@DIALOG_FACE_PUT$QI procdesc pascal near \
topleft_id:word
@DIALOG_TEXT_PUT$QINXUCUII procdesc pascal near \
line:word, str:dword, atrb:word, n:word
DIALOG_TEXT ends
main_03__TEXT segment byte public 'CODE' use16
; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame
sub_1300F proc near
var_28 = byte ptr -28h
arg_0 = word ptr 4
arg_2 = word ptr 6
arg_4 = dword ptr 8
arg_8 = word ptr 0Ch
enter 28h, 0
push si
lea ax, [bp+var_28]
push ss
push ax
push ds
push offset unk_1EB98
mov cx, 28h ; '('
call SCOPY@
xor si, si
jmp short loc_13035
; ---------------------------------------------------------------------------
loc_13029:
les bx, [bp+arg_4]
add bx, si
mov al, es:[bx]
mov [bp+si+var_28], al
inc si
loc_13035:
cmp si, [bp+arg_0]
jl short loc_13029
push 14
mov ax, [bp+arg_8]
add ax, 21
push ax
push ss
lea ax, [bp+var_28]
push ax
push [bp+arg_2]
call text_putsa
pop si
leave
retn 0Ah
sub_1300F endp
; =============== S U B R O U T I N E =======================================
; Attributes: bp-based frame
sub_13055 proc near
var_4 = word ptr -4
@@box = word ptr -4
var_2 = word ptr -2
@@topleft_id = word ptr 4
@ -12467,7 +12419,7 @@ var_2 = word ptr -2
xor di, di
mov al, _dialog_box_cur
mov ah, 0
mov [bp+var_4], ax
mov [bp+@@box], ax
jmp short loc_130F7
; ---------------------------------------------------------------------------
@ -12476,32 +12428,32 @@ loc_13090:
call @dialog_face_put$qi pascal, [bp+@@topleft_id]
cmp si, 24h ; '$'
jg short loc_130B3
push 0
push ds
mov ax, [bp+var_4]
push 0 ; line
push ds ; str (segment)
mov ax, [bp+@@box]
imul ax, (DIALOG_BOX_LINES * DIALOG_LINE_SIZE)
add ax, offset (_dialog_text + (0 * DIALOG_LINE_SIZE))
push ax
push TX_WHITE
push si
push ax ; str (offset)
push TX_WHITE ; atrb
push si ; n
jmp short loc_130CC
; ---------------------------------------------------------------------------
loc_130B3:
cmp si, 48h ; 'H'
jg short loc_130CF
push 1
push ds
mov ax, [bp+var_4]
push 1 ; line
push ds ; str (segment)
mov ax, [bp+@@box]
imul ax, (DIALOG_BOX_LINES * DIALOG_LINE_SIZE)
add ax, offset (_dialog_text + (1 * DIALOG_LINE_SIZE))
push ax
push TX_WHITE
lea ax, [si-24h]
push ax ; str (offset)
push TX_WHITE ; atrb
lea ax, [si-36] ; n
push ax
loc_130CC:
call sub_1300F
call @dialog_text_put$qinxucuii
loc_130CF:
inc di
@ -30628,46 +30580,8 @@ byte_1EB88 db 1
aStage_dt1 db 'STAGE .DT1',0
db 0
word_1EB96 dw 12D6h
unk_1EB98 db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
db 0
public _clear_bytes
_clear_bytes db DIALOG_LINE_SIZE dup(0)
db 10h
db 8
db 16h