ReC98/th03/formats/script.hpp

154 lines
4.5 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/// Common code for plaintext script formats
/// ----------------------------------------
// ZUN bloat: At 257 bytes of static data, [_ctype] might be a rather heavy
// dependency for three digit and control character checks. For digits, it's
// also *technically* wrong, as the <ctype.h> functions are affected by the
// current locale (see section 7.4.2 of the C standard), whereas the subsequent
// conversion is hardcoded as a single subtraction from an ASCII '0'.
//
// In the original binary, "control character" refers to every ASCII codepoint
// < 0x20.
#include <ctype.h>
// Code generation… PORTERS: Remove.
#if defined(__TURBOC__) && defined(__MSDOS__)
#undef _IS_DIG
#undef _IS_CTL
static const unsigned char _IS_DIG = 2;
static const unsigned char _IS_CTL = 32;
#endif
enum script_ret_t {
CONTINUE = 0,
STOP = -1,
};
extern int script_param_number_default;
#define str_sep_control_or_space(c) \
(iscntrl(c) || (c == ' '))
#ifdef script_p
// Reads up to 3 ASCII number digits from [script_p] and writes the
// resulting 3-digit number to [ret]. If [script_p] does not point to any
// digit, [script_param_number_default] is written to [ret] instead.
void pascal near script_param_read_number_first(int& ret)
{
unsigned char c0 = *script_p; script_p++;
unsigned char c1 = *script_p; script_p++;
unsigned char c2 = *script_p; script_p++;
if(!isdigit(c0)) {
ret = script_param_number_default;
script_p -= 3;
} else if(!isdigit(c1)) {
ret = (c0 - '0');
script_p -= 2;
} else if(!isdigit(c2)) {
ret = (((c0 - '0') * 10) + c1 - '0');
script_p -= 1;
} else {
ret = (((c0 - '0') * 100) + ((c1 - '0') * 10) + (c2 - '0'));
}
}
inline void script_param_read_number_first(int& ret, int default_value) {
script_param_number_default = default_value;
script_param_read_number_first(ret);
}
void pascal near script_param_read_number_second(int& ret)
{
if(*script_p == ',') {
script_p++;
script_param_read_number_first(ret);
} else {
ret = script_param_number_default;
}
}
// Reads a filename parameter into [ret] i.e., as many characters from
// [script_p] until either
// • encountering a control or ' ' character (leaving [script_p] pointing to
// the character after this sentinel one),
// • or until up to a maximum of (PF_FN_LEN - 1) characters have beed read
// (leaving [script_p] pointing to the character after the last one read).
// The resulting string is \0-terminated, and [temp_len] receives the
// amount of characters before the \0 terminator.
#define script_param_read_fn(ret, temp_len, temp_c) { \
for(temp_len = 0; temp_len < (PF_FN_LEN - 1); temp_len++) { \
temp_c = *script_p; \
script_p++; \
if(str_sep_control_or_space(temp_c)) { \
break; \
} \
ret[temp_len] = temp_c; \
} \
ret[temp_len] = '\0'; \
}
// Commands shared between the cutscene and dialog systems
// -------------------------------------------------------
// The ternary trick in script_op_bgm() is innovative enough, we *really*
// don't want to also work around the resulting warning now. Besides,
// [fast_forward] is an rvalue in the TH04/TH05 dialog code and an lvalue
// in the TH03/TH04/TH05 cutscene code.
#if defined(__TURBOC__) && defined(__MSDOS__)
#pragma warn -rch
#pragma warn -ccc
#endif
#define script_op_bgm(stop_before_load, temp_c, temp_fn, temp_len) { \
c = *script_p; \
if(c == '$') { \
script_p++; \
snd_kaja_func(KAJA_SONG_STOP, 0); \
if(stop_before_load) { /* ZUN bloat */ \
return CONTINUE; \
} \
} else if(c == '*') { \
script_p++; \
snd_kaja_func(KAJA_SONG_PLAY, 0); \
if(stop_before_load) { /* ZUN bloat */ \
return CONTINUE; \
} \
} else if(c == ',') { \
script_p++; \
script_param_read_fn(fn, p1, c); \
(stop_before_load \
? snd_kaja_func(KAJA_SONG_STOP, 0) \
: optimization_barrier() \
); \
snd_load(fn, SND_LOAD_SONG); \
snd_kaja_func(KAJA_SONG_PLAY, 0); \
} \
}
#define script_op_fade(c, func_in, func_out, temp_p1) { \
script_p++; \
script_param_read_number_first(temp_p1, 1); \
if(c == 'i') { \
func_in(p1); \
} else { \
func_out(p1); \
} \
}
#define script_op_shake(fast_forward, temp_i, temp_p1) { \
script_param_read_number_first(temp_p1, 8); \
for(temp_i = 0; temp_i <= temp_p1; temp_i++) { \
if(temp_i & 1) { \
graph_scrollup(4); \
} else { \
graph_scrollup(RES_Y - 4); \
} \
if(!fast_forward) { \
frame_delay(1); \
} \
} \
graph_scrollup(0); \
}
// -------------------------------------------------------
#endif