Files
2026-02-02 04:50:13 +01:00

957 lines
21 KiB
C++

/* ScummVM - Graphic Adventure Engine
*
* ScummVM is the legal property of its developers, whose names
* are too numerous to list here. Please refer to the COPYRIGHT
* file distributed with this source distribution.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
#include "m4/adv_r/conv.h"
#include "m4/adv_r/adv_control.h"
#include "m4/adv_r/chunk_ops.h"
#include "m4/core/errors.h"
#include "m4/core/imath.h"
#include "m4/gui/gui_univ.h"
#include "m4/gui/gui_vmng.h"
#include "m4/vars.h"
#include "m4/m4.h"
namespace M4 {
// ---------------
// Set entry stats,
// Get next node pointer
// Process declarations
// Get message text
static void conv_exec_entry(int32 offset, Conv *c) {
int32 i = offset;
int32 tag, next;
goto_chunk *go;
c_goto_chunk *c_goto;
decl_chunk *decl;
assign_chunk *asgn;
c_assign_chunk *c_asgn;
misc_chunk *misc;
c_misc_chunk *c_misc;
int32 l_op;
int32 r_op;
entry_chunk *entry = get_entry(c, i);
const int32 entry_count = entry->size;
entry->status = conv_toggle_flags(entry);
i += sizeof(entry_chunk);
while (i < offset + entry_count) {
conv_ops_get_entry(i, &next, &tag, c);
switch (tag) {
case TEXT_CHUNK:
case MESSAGE_CHUNK:
case ENTRY_CHUNK:
case FALL_CHUNK:
break;
case C_ASGN_CHUNK:
c_asgn = get_c_asgn(c, i);
decl = get_decl(c, c_asgn->c_op_l);
l_op = conv_get_decl_val(c, decl);
if (conv_ops_cond_successful(l_op, c_asgn->c_op, c_asgn->c_op_r)) {
decl = get_decl(c, c_asgn->index);
conv_set_decl_val(c, decl, conv_ops_process_asgn(conv_get_decl_val(c, decl), c_asgn->op, c_asgn->opnd1));
}
break;
case ASGN_CHUNK:
asgn = get_asgn(c, i);
decl = get_decl(c, asgn->index);
conv_set_decl_val(c, decl, conv_ops_process_asgn(conv_get_decl_val(c, decl), asgn->op, asgn->opnd1));
break;
case HIDE_CHUNK:
misc = get_misc(c, i);
entry = get_hash_entry(c, misc->index);
if (!(entry->status & DESTROYED))
entry->status |= HIDDEN;
break;
case CHDE_CHUNK:
c_misc = get_c_misc(c, i);
entry = get_hash_entry(c, c_misc->index);
decl = get_decl(c, c_misc->c_op_l);
l_op = conv_get_decl_val(c, decl);
if (conv_ops_cond_successful(l_op, c_misc->c_op, c_misc->c_op_r)) {
if (!(entry->status & DESTROYED))
entry->status |= HIDDEN;
}
break;
case UHID_CHUNK:
misc = get_misc(c, i);
entry = get_hash_entry(c, misc->index);
if (!(entry->status & DESTROYED)) {
entry->status &= 0xfffffffb; // Mask HIDDEN bit
entry->status |= 0x00000001;
}
break;
case CUHD_CHUNK:
c_misc = get_c_misc(c, i);
entry = get_hash_entry(c, c_misc->index);
decl = get_decl(c, c_misc->c_op_l);
l_op = conv_get_decl_val(c, decl);
if (conv_ops_cond_successful(l_op, c_misc->c_op, c_misc->c_op_r)) {
if (!(entry->status & DESTROYED)) {
entry->status &= 0xfffffffb;
entry->status |= 0x00000001;
}
}
break;
case DSTR_CHUNK:
misc = get_misc(c, i);
entry = get_hash_entry(c, misc->index);
entry->status |= DESTROYED;
break;
case CDST_CHUNK:
c_misc = get_c_misc(c, i);
entry = get_hash_entry(c, c_misc->index);
decl = get_decl(c, c_misc->c_op_l);
l_op = conv_get_decl_val(c, decl);
if (conv_ops_cond_successful(l_op, c_misc->c_op, c_misc->c_op_r))
entry->status |= DESTROYED;
break;
case COND_GOTO_CHUNK:
c_goto = get_c_goto(c, i);
decl = get_decl(c, c_goto->opnd1);
l_op = conv_get_decl_val(c, decl);
r_op = c_goto->opnd2; //val
if (conv_ops_cond_successful(l_op, c_goto->op, r_op)) {
c->myCNode = c_goto->index;
return;
}
break;
case COND_EXIT_GOTO_CHUNK:
c_goto = get_c_goto(c, i);
decl = get_decl(c, c_goto->opnd1);
l_op = conv_get_decl_val(c, decl);
r_op = c_goto->opnd2; //val
if (conv_ops_cond_successful(l_op, c_goto->op, r_op)) {
if (c_goto->index != CONV_QUIT) { //was go->index
c->myCNode = c_goto->index; //was go->index
c->exit_now = CONV_BAIL;
} else {
c->exit_now = CONV_QUIT;
c->myCNode = CONV_QUIT;
}
return;
}
break;
case EXIT_GOTO_CHUNK:
go = get_goto(c, i);
if (go->index != CONV_QUIT) {
c->myCNode = go->index;
c->exit_now = CONV_BAIL;
} else {
c->exit_now = CONV_QUIT;
c->myCNode = CONV_QUIT;
}
return;
case GOTO_CHUNK:
go = get_goto(c, i);
c->myCNode = go->index;
return;
// Replies are non-player responses
case REPLY_CHUNK:
case COND_REPLY_CHUNK:
case WEIGHT_REPLY_CHUNK:
case WEIGHT_PREPLY_CHUNK:
break;
default:
conv_ops_unknown_chunk(tag, "conv_exec_entry");
break;
}
i = next;
}
}
static int conv_get_mesg(int32 offset, int32 is_valid, Conv *c) {
int32 i = offset;
int32 x, y, s_offset = 0, cSize;
int32 tag, next;
int32 text_len;
int sum, result = 0;
decl_chunk *decl;
reply_chunk *reply;
c_reply_chunk *c_reply;
w_reply_chunk *w_reply;
w_entry_chunk *w_entry;
int32 l_op;
int32 r_op;
entry_chunk *entry = get_entry(c, i);
const int32 entry_count = entry->size;
i += sizeof(entry_chunk);
while (i < offset + entry_count) {
conv_ops_get_entry(i, &next, &tag, c);
switch (tag) {
case TEXT_CHUNK:
case MESSAGE_CHUNK:
case ENTRY_CHUNK:
case FALL_CHUNK:
case C_ASGN_CHUNK:
case ASGN_CHUNK:
case HIDE_CHUNK:
case CHDE_CHUNK:
case UHID_CHUNK:
case CUHD_CHUNK:
case DSTR_CHUNK:
case CDST_CHUNK:
case COND_GOTO_CHUNK:
case COND_EXIT_GOTO_CHUNK:
case EXIT_GOTO_CHUNK:
case GOTO_CHUNK:
break;
case REPLY_CHUNK:
reply = get_reply(c, i);
if (is_valid) {
result = 1;
_G(cdd).player_non_player = 0;
if (!strcmp(_G(cdd).mesg, "")) {
text_len = conv_ops_text_strlen(get_string(c, reply->index + sizeof(mesg_chunk)));
Common::strcpy_s(_G(cdd).mesg, get_string(c, reply->index + sizeof(mesg_chunk) + text_len));
_G(cdd).mesg_snd_file = get_string(c, reply->index + sizeof(mesg_chunk));
} else {
Common::strcat_s(_G(cdd).mesg, " ");
text_len = conv_ops_text_strlen(get_string(c, reply->index + sizeof(mesg_chunk)));
Common::strcat_s(_G(cdd).mesg, get_string(c, reply->index + sizeof(mesg_chunk) + text_len));
_G(cdd).mesg_snd_file = get_string(c, reply->index + sizeof(mesg_chunk));
}
}
break;
case COND_REPLY_CHUNK:
c_reply = get_c_reply(c, i);
decl = get_decl(c, c_reply->op_l);
l_op = conv_get_decl_val(c, decl);
r_op = c_reply->op_r; //val
if (is_valid && conv_ops_cond_successful(l_op, c_reply->op, r_op)) {
result = 1;
_G(cdd).player_non_player = 0;
if (!strcmp(_G(cdd).mesg, "")) {
text_len = conv_ops_text_strlen(get_string(c, c_reply->index + sizeof(mesg_chunk)));
Common::strcpy_s(_G(cdd).mesg, get_string(c, c_reply->index + sizeof(mesg_chunk) + text_len));
_G(cdd).mesg_snd_file = get_string(c, c_reply->index + sizeof(mesg_chunk));
} else {
Common::strcat_s(_G(cdd).mesg, " ");
text_len = conv_ops_text_strlen(get_string(c, c_reply->index + sizeof(mesg_chunk)));
Common::strcat_s(_G(cdd).mesg, get_string(c, c_reply->index + sizeof(mesg_chunk) + text_len));
_G(cdd).mesg_snd_file = get_string(c, c_reply->index + sizeof(mesg_chunk));
}
}
break;
case WEIGHT_REPLY_CHUNK:
cSize = i;
w_reply = get_w_reply(c, i);
cSize += sizeof(w_reply_chunk);
sum = 0;
for (x = 0; x < w_reply->num_replies; x++) {
w_entry = get_w_entry(c, cSize);
sum += w_entry->weight;
cSize += sizeof(w_entry_chunk);
}
y = g_engine->getRandomNumber(sum - 1) + 1;
cSize = i;
w_reply = get_w_reply(c, i);
cSize += sizeof(w_reply_chunk);
sum = 0;
for (x = 0; (x < w_reply->num_replies) && (sum < y); x++) {
w_entry = get_w_entry(c, cSize);
s_offset = w_entry->index;
sum += w_entry->weight;
cSize += sizeof(w_entry_chunk);
}
if (is_valid) {
result = 1;
_G(cdd).player_non_player = 0;
if (!strcmp(_G(cdd).mesg, "")) {
text_len = conv_ops_text_strlen(get_string(c, s_offset + sizeof(mesg_chunk)));
Common::strcpy_s(_G(cdd).mesg, get_string(c, s_offset + sizeof(mesg_chunk) + text_len));
_G(cdd).mesg_snd_file = get_string(c, s_offset + sizeof(mesg_chunk));
} else {
Common::strcat_s(_G(cdd).mesg, " ");
text_len = conv_ops_text_strlen(get_string(c, s_offset + sizeof(mesg_chunk)));
Common::strcat_s(_G(cdd).mesg, get_string(c, s_offset + sizeof(mesg_chunk) + text_len));
_G(cdd).mesg_snd_file = get_string(c, s_offset + sizeof(mesg_chunk));
}
}
break;
case WEIGHT_PREPLY_CHUNK:
cSize = i;
w_reply = get_w_reply(c, i);
cSize += sizeof(w_reply_chunk);
sum = 0;
for (x = 0; x < w_reply->num_replies; x++) {
w_entry = get_w_entry(c, cSize);
sum += w_entry->weight;
cSize += sizeof(w_entry_chunk);
}
y = g_engine->getRandomNumber(sum - 1) + 1;
cSize = i;
w_reply = get_w_reply(c, i);
cSize += sizeof(w_reply_chunk);
sum = 0;
for (x = 0; (x < w_reply->num_replies) && (sum < y); x++) {
w_entry = get_w_entry(c, cSize);
s_offset = w_entry->index;
sum += w_entry->weight;
cSize += sizeof(w_entry_chunk);
}
if (is_valid) {
result = 1;
_G(cdd).player_non_player = 1;
if (!strcmp(_G(cdd).mesg, "")) {
text_len = conv_ops_text_strlen(get_string(c, s_offset + sizeof(mesg_chunk)));
Common::strcpy_s(_G(cdd).mesg, get_string(c, s_offset + sizeof(mesg_chunk) + text_len));
_G(cdd).mesg_snd_file = get_string(c, s_offset + sizeof(mesg_chunk));
} else {
Common::strcat_s(_G(cdd).mesg, " ");
text_len = conv_ops_text_strlen(get_string(c, s_offset + sizeof(mesg_chunk)));
Common::strcat_s(_G(cdd).mesg, get_string(c, s_offset + sizeof(mesg_chunk) + text_len));
_G(cdd).mesg_snd_file = get_string(c, s_offset + sizeof(mesg_chunk));
}
}
break;
default:
conv_ops_unknown_chunk(tag, "conv_get_mesg");
break;
}
i = next;
}
return result;
}
static void find_true_ent(int entry_num, Conv *c) {
int32 ent = 0, n = 0;
int32 next = 0, tag = 0, num_ents = 0;
int i;
// Start by getting the current NODE or LNODE
node_chunk *node;
lnode_chunk *lnode;
conv_ops_get_entry(ent, &next, &tag, c);
switch (tag) {
case LNODE_CHUNK:
lnode = get_lnode(c, ent);
ent += sizeof(lnode_chunk);
num_ents = lnode->num_entries;
entry_num = lnode->entry_num;
c->node_hash = lnode->hash;
break;
case NODE_CHUNK:
node = get_node(c, ent);
ent += sizeof(node_chunk);
num_ents = node->num_entries;
c->node_hash = node->hash;
break;
default:
break;
}
// ent will now be pointing at an ENTRY or FALLTHROUGH
const int32 sub_ent = next;
conv_ops_get_entry(sub_ent, &next, &tag, c);
if (tag == FALL_CHUNK) {
// We either want to jump to a new node
// or skip to the first offset.
fall_chunk *fall = get_fall(c, sub_ent);
assert(fall);
//do this to skip the fall chunk and all will be fine.
ent += sizeof(int32); //was get_long, sizeof( fall_chunk )
}
_GC(ent) = 0;
// Not only i<entry_num, check to see entry->num_entries
for (i = 0, n = 0; n < num_ents; n++) {
const int32 offset = get_long(c, ent);
entry_chunk *entry = get_entry(c, ent + offset);
if (i == entry_num)
break;
if ((entry->status & 0x00000003) && ok_status(entry)) //was 1
i++;
_GC(ent)++;
ent += sizeof(int32);
}
}
// Simplify me now that all changes have been made.
static int conv_get_node_text(Conv *c) {
lnode_chunk *lnode = nullptr;
node_chunk *node;
entry_chunk *entry = nullptr;
fall_chunk *fall = nullptr;
int32 ent = 0, offset = 0, tag, next, num_ents = 0;
int i = 0, num_vis = 0, result = 0;
_G(cdd).num_txt_ents = 0;
_GC(width) = 0; _GC(height) = 0;
// conv _get_node_text will either get a NODE or LNODE
conv_ops_get_entry(offset, &next, &tag, c);
offset = 0; //not needed.?
_GC(n_t_e) = 0;
switch (tag) {
case LNODE_CHUNK:
lnode = get_lnode(c, offset);
offset += sizeof(lnode_chunk);
num_ents = lnode->num_entries;
c->node_hash = lnode->hash;
break;
case NODE_CHUNK:
node = get_node(c, offset);
offset += sizeof(node_chunk);
num_ents = node->num_entries;
c->node_hash = node->hash;
break;
default:
// handle error.
break;
}
switch (tag) {
case LNODE_CHUNK:
// was in bounds.
// lnode->entry_num starts at 0. in the chunk.
if (lnode->entry_num >= lnode->num_entries)
lnode->entry_num = 0;
for (i = 0; (i <= lnode->entry_num) && (i < num_ents); i++) {
ent = get_long(c, offset);
entry = get_entry(c, offset + ent);
offset += sizeof(int32);
}
offset -= sizeof(int32);
// Set sound file name instead.?
if ((entry->status != 0) && (num_ents != 0) && ok_status(entry)) {
//here here here.
if (conv_get_text(offset + ent, entry->size, c)) {
result = 1;
_G(cdd).num_txt_ents = 0;
_G(cdd).mesg_snd_file = _G(cdd).snd_files[0];
_G(cdd).text[0] = nullptr;
_G(cdd).snd_files[0] = nullptr;
_G(cdd).player_non_player = 1;
c->c_entry_num = lnode->entry_num;
}
num_vis++;
}
lnode->entry_num++;
_GC(ent) = lnode->entry_num;
break;
case NODE_CHUNK:
for (i = 0; i < num_ents; i++) {
ent = get_long(c, offset);
entry = get_entry(c, offset + ent);
if (entry->tag != FALL_CHUNK) {
if ((entry->status != 0) && ok_status(entry)) {
if (conv_get_text(offset + ent, entry->size, c)) {
result = 1;
_G(cdd).player_non_player = 1;
}
num_vis++;
_GC(n_t_e)++;
}
} else {
fall = get_fall(c, offset + ent);
}
offset += sizeof(int32);
}
if (fall) {
if (num_vis <= fall->val) {
_GC(n_t_e) = 0;
c->myCNode = fall->index;
c->mode = CONV_GET_TEXT_MODE;
result = 0;
}
}
break;
default:
break;
}
return result;
}
void conv_shutdown() {
if (conv_get_handle())
conv_unload(conv_get_handle());
if (_GC(myTextScrn))
TextScrn_Destroy(_GC(myTextScrn));
_GC(myTextScrn) = nullptr;
}
static void conv_start(Conv *c) {
int32 ok = 1, ent = 0, tag = 0, next;
decl_chunk *decl;
switch (c->exit_now) {
case CONV_OK:
// Potential prob. when entering while loop.
break;
// Goto_exit encountered.
// a conversation state.
case CONV_BAIL:
return;
// Goodbye forever.
case CONV_QUIT:
return;
//new conv. no restore file on hard disk.
case CONV_NEW:
c->exit_now = CONV_OK;
c->myCNode = 0;
break;
default:
break;
}
while ((ent < c->chunkSize) && ok) {
conv_ops_get_entry(ent, &next, &tag, c); //ok if c->myCNode = 0
switch (tag) {
case LNODE_CHUNK:
case NODE_CHUNK:
ok = 0;
break;
case DECL_CHUNK:
decl = get_decl(c, ent);
assert(decl);
break;
default:
break;
}
if (ok)
ent = next;
}
c->myCNode = ent;
// if we exit, the current node is set, the next node is null
}
static int conv_next_node(Conv *c) {
if (c->myCNode == -1)
return 0;
switch (c->exit_now) {
case CONV_OK:
return 1;
case CONV_QUIT:
case CONV_BAIL:
return 0;
case CONV_NEW:
conv_start(c); // Should go in conv_load.
return 1;
default:
break;
}
return 1;
}
static int conv_process_entry(int entry_num, Conv *c, int mode) {
node_chunk *node;
lnode_chunk *lnode;
int32 offset = 0, ent = 0, is_valid = 0, n = 0;
int32 next = 0, tag = 0, num_ents = 0;
int i = 0;
int result = 1;
// Start by getting the current NODE or LNODE
conv_ops_get_entry(ent, &next, &tag, c);
switch (tag) {
case LNODE_CHUNK:
lnode = get_lnode(c, ent);
ent += sizeof(lnode_chunk);
num_ents = lnode->num_entries;
entry_num = lnode->entry_num;
c->node_hash = lnode->hash;
break;
case NODE_CHUNK:
node = get_node(c, ent);
ent += sizeof(node_chunk);
num_ents = node->num_entries;
c->node_hash = node->hash;
break;
default:
break;
}
// ent will now be pointing at an ENTRY or FALLTHROUGH
const int32 sub_ent = next;
conv_ops_get_entry(sub_ent, &next, &tag, c);
if (tag == FALL_CHUNK) {
// We either want to jump to a new node
// or skip to the first offset.
fall_chunk *fall = get_fall(c, sub_ent);
assert(fall);
// Do this to skip the fall chunk and all will be fine.
ent += sizeof(int32); //was get_long, sizeof( fall_chunk )
n++; //don't increment i.
}
// Not only i<entry_num, check to see entry->num_entries
while ((i < entry_num) && (n < num_ents)) {
offset = get_long(c, ent);
entry_chunk *entry = get_entry(c, ent + offset);
if ((entry->status != 0) && ok_status(entry)) {
i++;
is_valid = 1;
}
ent += sizeof(int32);
n++;
}
ent -= sizeof(int32);
if (is_valid) {
switch (mode) {
case CONV_GET_MESG_MODE:
result = conv_get_mesg(ent + offset, is_valid, c);
break;
case CONV_UPDATE_MODE:
conv_exec_entry(ent + offset, c);
break;
default:
break;
}
}
return result;
}
static void textBoxInit();
static int conv_run(Conv *c) {
if (!c)
return 0;
int ok = 1;
if (conv_next_node(c)) {
switch (c->exit_now) {
case CONV_NEW:
case CONV_QUIT:
case CONV_BAIL:
break;
case CONV_OK:
while (ok && conv_next_node(c)) {
switch (c->mode) {
case CONV_GET_TEXT_MODE:
cdd_init();
c->mode = CONV_GET_MESG_MODE;
if (conv_get_node_text(c)) {
ok = 0;
if (_G(cdd).num_txt_ents) { //node
mouse_unlock_sprite();
mouse_lock_sprite(0);
textBoxInit();
} else { //linear node.
conv_set_event(-1);
Common::strcpy_s(_G(player).verb, _GC(conv_name)); // was verb.
c->c_entry_num = 1;
}
}
break;
case CONV_GET_MESG_MODE:
cdd_init();
if (conv_process_entry(c->c_entry_num, c, CONV_GET_MESG_MODE)) {
mouse_unlock_sprite();
mouse_lock_sprite(5);
conv_set_event(-1);
Common::strcpy_s(_G(player).verb, _GC(conv_name));
ok = 0;
}
c->mode = CONV_UPDATE_MODE;
break;
case CONV_UPDATE_MODE:
conv_process_entry(c->c_entry_num, c, CONV_UPDATE_MODE);
c->mode = CONV_GET_TEXT_MODE;
break;
default:
break;
}
}
break;
default:
break;
}
}
if (!conv_next_node(c))
conv_unload(c);
return 0;
}
static void convtestCallback(void *a, void *) {
mouse_unlock_sprite();
mouse_lock_sprite(5);
player_set_commands_allowed(false);
TextItem *i = (TextItem *)a;
Conv *c = conv_get_handle();
if (!c)
return;
c->c_entry_num = i->tag;
c->mode = CONV_GET_MESG_MODE;
TextScrn_Destroy(_GC(myTextScrn));
_GC(myTextScrn) = nullptr;
find_true_ent(c->c_entry_num, c);
_G(cdd).mesg_snd_file = _G(cdd).snd_files[c->c_entry_num - 1];
_G(cdd).player_non_player = 1;
Common::strcpy_s(_G(player).verb, _GC(conv_name));
_G(player).command_ready = true;
conv_set_event(-1); // Must have or conv freezes.
}
void set_dlg_rect() {
int32 status;
ScreenContext *game_buff_ptr = vmng_screen_find(_G(gameDrawBuff), &status);
if (!game_buff_ptr)
error_show(FL, 'BUF!');
const int32 screen_x_center = VIDEO_W / 2;
const int32 screen_y_center = (game_buff_ptr->y2 - game_buff_ptr->y1) / 2;
const int32 screen_x_size = VIDEO_W;
const int32 screen_y_size = (game_buff_ptr->y2 - game_buff_ptr->y1);
_GC(height) = gr_font_get_height() + _GC(conv_font_spacing_v); // Must have....
_GC(width) += 2 * _GC(conv_font_spacing_h);
const int32 sizeX = _GC(width);
const int32 sizeY = _G(cdd).num_txt_ents * (_GC(height)) + _GC(conv_font_spacing_v);
switch (_GC(glob_x)) {
case DLG_CENTER_H:
_GC(r_x1) = screen_x_center - (sizeX / 2);
break;
case DLG_FLUSH_LEFT:
_GC(r_x1) = 0;
break;
case DLG_FLUSH_RIGHT:
_GC(r_x1) = screen_x_size - sizeX;
break;
default:
_GC(r_x1) = _GC(glob_x);
_GC(r_x1) += game_buff_ptr->x1;
break;
}
switch (_GC(glob_y)) {
case DLG_CENTER_V:
_GC(r_y1) = screen_y_center - (sizeY / 2);
break;
case DLG_FLUSH_TOP:
_GC(r_y1) = 0;
break;
case DLG_FLUSH_BOTTOM:
_GC(r_y1) = screen_y_size - sizeY + game_buff_ptr->y1 - 10;
break;
default:
_GC(r_y1) = _GC(glob_y);
_GC(r_y1) += game_buff_ptr->y1;
break;
}
if (_GC(r_x1) < 0)
_GC(r_x1) = 0;
if (_GC(r_y1) < 0)
_GC(r_y1) = 0;
_GC(r_y2) = _GC(r_y1) + sizeY - 1;
_GC(r_x2) = _GC(r_x1) + sizeX - 1;
_GC(r_x2) = imath_min(VIDEO_W, _GC(r_x2));
_GC(r_y2) = imath_min(VIDEO_H, _GC(r_y2));
}
static void textBoxInit() {
player_set_commands_allowed(true);
mouse_set_sprite(0);
gr_font_set(_G(font_conv));
conv_get_node_text(conv_get_handle());
set_dlg_rect();
_GC(myTextScrn) = TextScrn_Create(_GC(r_x1), _GC(r_y1), _GC(r_x2), _GC(r_y2), _GC(conv_shading),
6 | SF_GET_MOUSE | SF_IMMOVABLE | SF_BLOCK_MOUSE,
_GC(conv_normal_colour), _GC(conv_hilite_colour), _GC(conv_normal_colour_alt1),
_GC(conv_hilite_colour_alt1), _GC(conv_normal_colour_alt2),
_GC(conv_hilite_colour_alt2));
for (int32 i = 0; i < _G(cdd).num_txt_ents; i++) {
TextScrn_Add_TextItem(_GC(myTextScrn), _GC(conv_font_spacing_h),
(i * _GC(height)) + _GC(conv_font_spacing_v), i + 1, TS_GIVEN,
_G(cdd).text[i], convtestCallback);
}
TextScrn_Activate(_GC(myTextScrn));
}
void conv_get_dlg_coords(int32 *x1, int32 *y1, int32 *x2, int32 *y2) {
*x1 = _GC(r_x1);
*y1 = _GC(r_y1);
*x2 = _GC(r_x2);
*y2 = _GC(r_y2);
}
void conv_set_dlg_coords(int32 x1, int32 y1, int32 x2, int32 y2) {
_GC(r_x1) = x1;
_GC(r_y1) = y1;
_GC(r_x2) = x2;
_GC(r_y2) = y2;
}
void conv_go(Conv *c) {
conv_run(c);
}
} // End of namespace M4